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 receive_packet(self, packet_type=None, timeout=SERVER_TIMEOUT): """Return the first received packet. If packet_type is given, only a packet of that type will be returned. """ if self.packetqueue: if packet_type is None: return self.packetqueue.pop(0) for p in self.packetqueue: if not isinstance(p[1], packet_type): continue self.packetqueue.remove(p) return p if packet_type is None: return self._receive(timeout) start = time.time() timeleft = timeout while timeleft > 0: packet = self._receive(timeleft) # packet type is None -> return whatever we received if packet_type is None: return packet # otherwise only process non-None packets if packet is not None: if isinstance(packet[1], packet_type): return packet if not self.process_async_packet(packet): self.packetqueue.append(packet) timeleft -= time.time() - start raise network.FatalError("No reply from server")
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 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 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 listgames(self, mapname=None, maxplayers=None, only_this_version=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("[LIST]") version = self.version if only_this_version else -1 self.send(packets.client.cmd_listgames(version, mapname, maxplayers)) packet = self.recv_packet([packets.server.data_gameslist]) if packet is None: raise network.FatalError("No reply from server") elif not isinstance(packet[1], packets.server.data_gameslist): raise network.CommandError("Unexpected packet") return packet[1].games
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 = packets.unserialize(event.packet.data) if packet is None: self.log.error("Unknown packet from %s!" % (event.peer.address)) self.disconnect() return None #elif isinstance(packet, packets.cmd_error): # raise network.CommandError(packet.errorstr) elif isinstance(packet, packets.cmd_fatalerror): self.log.error("[FATAL] Network message: %s" % (packet.errorstr)) self.disconnect() raise network.FatalError(packet.errorstr) return [event.peer, packet]
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))