def _receive_event(self, timeout=SERVER_TIMEOUT): """Receives next event of type NONE or RECEIVE.""" if self.server_peer is None: raise network.NotConnected() try: event = self.host.service(timeout) if event.type == enet.EVENT_TYPE_NONE: return None elif event.type == enet.EVENT_TYPE_DISCONNECT: self._reset() self.log.warning("Unexpected disconnect from %s", event.peer.address) raise network.CommandError( "Unexpected disconnect from {}".format(event.peer.address)) elif event.type == enet.EVENT_TYPE_CONNECT: self._reset() self.log.warning("Unexpected connection from %s", event.peer.address) raise network.CommandError( "Unexpected connection from {}".format(event.peer.address)) return event except IOError as e: raise network.FatalError(e)
def server_recv_event(self, timeout=SERVER_TIMEOUT): if self.serverpeer is None: raise network.NotConnected() event = self.host.service(timeout) if event.type == enet.EVENT_TYPE_NONE: return None elif event.type == enet.EVENT_TYPE_DISCONNECT: self.reset() self.log.warning("Unexpected disconnect from %s" % (event.peer.address)) raise network.CommandError("Unexpected disconnect from %s" % (event.peer.address)) elif event.type == enet.EVENT_TYPE_CONNECT: # ignore connect events during holepunching if self.game is not None: for player in self.game.players: if player.address == event.peer.address: self.log.debug("[HOLEPUNCH CONNECTION] %s" % (event.peer.address)) event.peer.disconnect() event.peer.reset() return None self.reset() self.log.warning("Unexpected connection from %s" % (event.peer.address)) raise network.CommandError("Unexpected connection from %s" % (event.peer.address)) return event
def listgames(self, mapname = None, maxplayers = None, onlyThisVersion = False): if self.mode is not ClientMode.Server: raise network.NotInServerMode("We are not connected to any server") self.log.debug("[LIST]") self.send(packets.client.cmd_listgames(self.version if onlyThisVersion else -1, mapname, maxplayers)) packet = self.recv_packet([packets.cmd_error, packets.server.data_gameslist]) if packet is None: raise network.CommandError("No reply from server") elif isinstance(packet[1], packets.cmd_error): raise network.CommandError(packet[1].errorstr) elif not isinstance(packet[1], packets.server.data_gameslist): raise network.CommandError("Unexpected packet") return packet[1].games
def creategame(self, mapname, maxplayers): if self.mode is not ClientMode.Server: raise network.NotInServerMode("We are not connected to any server") self.log.debug("[CREATE] mapname=%s maxplayers=%d" % (mapname, maxplayers)) self.send(packets.client.cmd_creategame(self.version, mapname, maxplayers, self.name)) packet = self.recv_packet([packets.cmd_error, packets.server.data_gamestate]) if packet is None: raise network.CommandError("No reply from server") elif isinstance(packet[1], packets.cmd_error): raise network.CommandError(packet[1].errorstr) elif not isinstance(packet[1], packets.server.data_gamestate): raise network.CommandError("Unexpected packet") self.game = packet[1].game return self.game
def _recv_event(self, timeout=SERVER_TIMEOUT): if self.serverpeer is None: raise network.NotConnected() event = self.host.service(timeout) if event.type == enet.EVENT_TYPE_NONE: return None elif event.type == enet.EVENT_TYPE_DISCONNECT: self.reset() self.log.warning("Unexpected disconnect from %s" % (event.peer.address)) raise network.CommandError("Unexpected disconnect from %s" % (event.peer.address)) elif event.type == enet.EVENT_TYPE_CONNECT: self.reset() self.log.warning("Unexpected connection from %s" % (event.peer.address)) raise network.CommandError("Unexpected connection from %s" % (event.peer.address)) return event
def leavegame(self): if self.mode is not ClientMode.Server: raise network.NotInServerMode("We are not connected to any server") if self.game is None: raise network.NotInGameLobby("We are not in a game lobby") self.log.debug("[LEAVE]") self.send(packets.client.cmd_leavegame()) packet = self.recv_packet([packets.cmd_error, packets.cmd_ok]) if packet is None: raise network.CommandError("No reply from server") elif isinstance(packet[1], packets.cmd_error): raise network.CommandError(packet[1].errorstr) elif not isinstance(packet[1], packets.cmd_ok): raise network.CommandError("Unexpected packet") self.game = None return True
def joingame(self, uuid): if self.mode is not ClientMode.Server: raise network.NotInServerMode("We are not connected to any server") if not isinstance(uuid, UUID): uuid = UUID(uuid) self.log.debug("[JOIN] %s" % (uuid)) self.send(packets.client.cmd_joingame(uuid, self.version, self.name)) packet = self.recv_packet([packets.cmd_error, packets.server.data_gamestate]) if packet is None: raise network.CommandError("No reply from server") elif isinstance(packet[1], packets.cmd_error): raise network.CommandError(packet[1].errorstr) elif not isinstance(packet[1], packets.server.data_gamestate): raise network.CommandError("Unexpected packet") self.game = packet[1].game return self.game
def _receive(self, timeout=SERVER_TIMEOUT): """Receive event and return unpacked packet.""" try: event = self._receive_event(timeout) if event is None or event.type != enet.EVENT_TYPE_RECEIVE: return None packet = packets.unserialize(event.packet.data) except Exception as e: try: event except NameError: pass else: self.log.error("Unknown packet from %s!", event.peer.address) errstr = "Pickle/Security: {}".format(e) print("[FATAL] {}".format( errstr)) # print that even when no logger is enabled! self.log.error("[FATAL] %s", errstr) self.disconnect() raise network.FatalError(errstr) if isinstance(packet, packets.cmd_error): # handle special errors here # the game got terminated by the client raise network.CommandError(packet.errorstr, cmd_type=packet.type) elif isinstance(packet, packets.cmd_fatalerror): self.log.error("[FATAL] Network message: %s", packet.errorstr) self.disconnect(server_may_disconnect=True) raise network.FatalError(packet.errorstr) return [event.peer, packet]
def recv(self, timeout=SERVER_TIMEOUT): event = self._recv_event(timeout) if event is None: return None elif event.type == enet.EVENT_TYPE_RECEIVE: packet = None try: packet = packets.unserialize(event.packet.data) except Exception as e: self.log.error("Unknown packet from %s!" % (event.peer.address)) errstr = "Pickle/Security: %s" % (e) print "[FATAL] %s" % (errstr) # print that even when no logger is enabled! self.log.error("[FATAL] %s" % (errstr)) self.disconnect() raise network.FatalError(errstr) if isinstance(packet, packets.cmd_error): # handle special errors here # FIXME: it's better to pass that to the interface, # but our ui error handler currently can't handle that # the game got terminated by the client if packet.type == ErrorType.TerminateGame: game = self.game # this will destroy self.game self.leavegame(stealth=True) self.call_callbacks("lobbygame_terminate", game, packet.errorstr) return None raise network.CommandError(packet.errorstr) elif isinstance(packet, packets.cmd_fatalerror): self.log.error("[FATAL] Network message: %s" % (packet.errorstr)) self.disconnect(True) raise network.FatalError(packet.errorstr) return [event.peer, packet]
def assert_type(packet): if packet_type is None: return packet if packet is None: raise network.FatalError("No reply from server") elif not isinstance(packet[1], packet_type): raise network.CommandError("Unexpected packet") return packet
def p2p_recv_event(self, timeout = SERVER_TIMEOUT): event = self.host.service(timeout) if event.type == enet.EVENT_TYPE_NONE: return None elif event.type == enet.EVENT_TYPE_DISCONNECT: # ignore disconnect from server if self.serverpeer is not None and Address(self.serverpeer.address) == event.peer.address: self.log.debug("[DISCONNECT] done") self.serverpeer = None return None self.reset() self.log.warning("Unexpected disconnect from %s" % (event.peer.address)) raise network.CommandError("Unexpected disconnect from %s" % (event.peer.address)) elif event.type == enet.EVENT_TYPE_CONNECT: event.peer.disconnect() event.peer.reset() self.log.warning("Unexpected connection from %s" % (event.peer.address)) raise network.CommandError("Unexpected connection from %s" % (event.peer.address)) return event
def setprops(self, lang): if self.mode is None: raise network.NotConnected() if self.mode is not ClientMode.Server: raise network.NotInServerMode("We are not in server mode") self.log.debug("[SETPROPS]") self.send(packets.client.cmd_sessionprops(lang)) packet = self.recv_packet([packets.cmd_ok]) if packet is None: raise network.FatalError("No reply from server") elif not isinstance(packet[1], packets.cmd_ok): raise network.CommandError("Unexpected packet") return True
def leavegame(self, stealth=False): if self.mode is None: raise network.NotConnected() if self.mode is not ClientMode.Server: raise network.NotInServerMode("We are not in server mode") if self.game is None: raise network.NotInGameLobby("We are not in a game lobby") self.log.debug("[LEAVE]") if stealth: self.game = None return self.send(packets.client.cmd_leavegame()) packet = self.recv_packet([packets.cmd_ok]) if packet is None: raise network.FatalError("No reply from server") elif not isinstance(packet[1], packets.cmd_ok): raise network.CommandError("Unexpected packet") self.game = None return True
def joingame(self, uuid, password="", fetch=False): if self.mode is None: raise network.NotConnected() if self.mode is not ClientMode.Server: raise network.NotInServerMode("We are not in server mode") self.log.debug("[JOIN] %s" % (uuid)) self.send(packets.client.cmd_joingame( uuid = uuid, clientver = self.version, clientid = self.clientid, playername = self.name, playercolor = self.color, password = password, fetch = fetch)) packet = self.recv_packet([packets.server.data_gamestate]) if packet is None: raise network.FatalError("No reply from server") elif not isinstance(packet[1], packets.server.data_gamestate): raise network.CommandError("Unexpected packet") self.game = packet[1].game return self.game
def creategame(self, mapname, maxplayers, gamename, maphash="", password=""): if self.mode is None: raise network.NotConnected() if self.mode is not ClientMode.Server: raise network.NotInServerMode("We are not in server mode") self.log.debug("[CREATE] mapname=%s maxplayers=%d" % (mapname, maxplayers)) self.send(packets.client.cmd_creategame( clientver = self.version, clientid = self.clientid, playername = self.name, playercolor = self.color, gamename = gamename, mapname = mapname, maxplayers = maxplayers, maphash = maphash, password = password)) packet = self.recv_packet([packets.server.data_gamestate]) if packet is None: raise network.FatalError("No reply from server") elif not isinstance(packet[1], packets.server.data_gamestate): raise network.CommandError("Unexpected packet") self.game = packet[1].game return self.game
def connect(self): if self.serverpeer is not None: raise network.AlreadyConnected("We are already connected to a server") self.log.debug("[CONNECT] to server %s" % (self.serveraddress)) try: self.serverpeer = self.host.connect(enet.Address(self.serveraddress.host, self.serveraddress.port), 1, SERVER_PROTOCOL) except (IOError, MemoryError): raise network.NetworkException("Unable to connect to server. Maybe invalid or irresolvable server address.") self.mode = ClientMode.Server event = self.host.service(SERVER_TIMEOUT) if event.type != enet.EVENT_TYPE_CONNECT: self.reset() raise network.UnableToConnect("Unable to connect to server") # wait for session id packet = self.recv_packet([packets.server.cmd_session]) if packet is None: raise network.FatalError("No reply from server") elif not isinstance(packet[1], packets.server.cmd_session): raise network.CommandError("Unexpected packet") self.sid = packet[1].sid self.capabilities = packet[1].capabilities self.log.debug("[CONNECT] done (session=%s)" % (self.sid))