def __init__(self, sock, addr): Endpoint.__init__(self, sock, addr) Greenlet.__init__(self) self.observers = BatchList() self.gamedata = Gamedata() self.cmd_listeners = defaultdict(WeakSet) self.current_game = None
class Server(Endpoint, Greenlet): ''' Used at client side, to represent server ''' def __init__(self, sock, addr): Endpoint.__init__(self, sock, addr) Greenlet.__init__(self) self.ctlcmds = Channel() self.userid = 0 self.gamedata = Gamedata(recording=True) def _run(self): while True: cmd, data = self.read() if cmd == 'gamedata': self.gamedata.feed(data) else: self.ctlcmds.put([cmd, data]) def gexpect(self, tag, blocking=True): return self.gamedata.gexpect(tag, blocking) def gbreak(self): return self.gamedata.gbreak() def gclear(self): self.gamedata = Gamedata(recording=True) def gwrite(self, tag, data): log.debug('GAME_WRITE: %s', repr([tag, data])) encoded = self.encode(['gamedata', [tag, data]]) self.raw_write(encoded) def wait_till_live(self): self.gamedata.wait_empty() def gamedata_piled(self): return len(self.gamedata.gdqueue) > 60 def shutdown(self): self.kill() self.join() self.ctlcmds.put(['shutdown', None]) self.close()
class Client(Endpoint, Greenlet): def __init__(self, sock, addr): Endpoint.__init__(self, sock, addr) Greenlet.__init__(self) self.observers = BatchList() self.gamedata = Gamedata() self.cmd_listeners = defaultdict(WeakSet) self.current_game = None @log_failure(log) def _run(self): self.account = None # ----- Banner ----- from settings import VERSION self.write(['thbattle_greeting', (options.node, VERSION)]) # ------------------ self.state = 'connected' while True: try: hasdata = False with Timeout(90, False): cmd, data = self.read() hasdata = True if not hasdata: self.close() # client should send heartbeat periodically raise EndpointDied if cmd == 'gamedata': self.gamedata.feed(data) else: self.handle_command(cmd, data) except EndpointDied: self.gbreak() break except Exception: log.exception("Error occurred when handling client command") # client died, do clean ups self.handle_drop() def close(self): Endpoint.close(self) self.kill(EndpointDied) def __repr__(self): acc = self.account if not acc: return Endpoint.__repr__(self) return '%s:%s:%s' % ( self.__class__.__name__, self.address[0], acc.username.encode('utf-8'), ) def __data__(self): return dict( account=self.account, state=self.state, ) def __eq__(self, other): return self.account is other.account def listen_command(self, *cmds): listeners_set = self.cmd_listeners q = Queue(100) for cmd in cmds: listeners_set[cmd].add(q) return q def handle_command(self, cmd, data): f = getattr(self, 'command_' + str(cmd), None) if not f: listeners = self.cmd_listeners[cmd] if listeners: [l.put(data) for l in listeners] return log.debug('No command %s', cmd) self.write(['invalid_command', [cmd, data]]) return for_state = getattr(f, 'for_state', None) if for_state and self.state not in for_state: log.debug('Command %s is for state %s, called in %s', cmd, for_state, self.state) self.write(['invalid_command', [cmd, data]]) return if not isinstance(data, (list, tuple)): log.error('Malformed command: %s %s', cmd, data) return n = f.__code__.co_argcount - 1 if n != len(data): log.error( 'Command "%s" argcount mismatch, expect %s, got %s', cmd, n, len(data) ) else: f(*data) def handle_drop(self): if self.state not in ('connected', 'hang'): lobby.exit_game(self, is_drop=True) if self.state != 'connected': lobby.user_leave(self) def gexpect(self, tag, blocking=True): tag, data = self.gamedata.gexpect(tag, blocking) if tag: manager = GameManager.get_by_user(self) manager.record_user_gamedata(self, tag, data) return tag, data def gwrite(self, tag, data): log.debug('GAME_WRITE: %s -> %s', self.account.username, repr([tag, data])) manager = GameManager.get_by_user(self) manager.record_gamedata(self, tag, data) encoded = self.encode(['gamedata', [tag, data]]) self.raw_write(encoded) self.observers and self.observers.raw_write(encoded) def gbreak(self): return self.gamedata.gbreak() def gclear(self): self.gamedata = Gamedata() def for_state(*state): def register(f): f.for_state = state return f return register # --------- Handlers --------- @for_state('connected') def command_auth(self, login, password): if self.account: self.write(['invalid_command', ['auth', '']]) return acc = Account.authenticate(login, password) if acc: self.account = acc if not acc.available(): self.write(['auth_result', 'not_available']) self.close() else: self.write(['auth_result', 'success']) self.account = acc lobby.user_join(self) else: self.write(['auth_result', 'invalid_credential']) @for_state('hang') def command_create_game(self, _type, name, invite_only): manager = lobby.create_game(self, _type, name, invite_only) manager.add_invited(self) manager and lobby.join_game(self, manager.gameid) @for_state('hang') def command_quick_start_game(self): lobby.quick_start_game(self) @for_state('hang') def command_join_game(self, gameid): lobby.join_game(self, gameid) def command_get_lobbyinfo(self): lobby.send_lobbyinfo([self]) @for_state('hang') def command_observe_user(self, uid): lobby.observe_user(self, uid) @for_state('hang') def command_query_gameinfo(self, gid): lobby.send_gameinfo(self, gid) @for_state('inroomwait') def command_get_ready(self): lobby.get_ready(self) @for_state('inroomwait') def command_set_game_param(self, key, value): lobby.set_game_param(self, key, value) @for_state('inroomwait', 'ready', 'ingame', 'observing') def command_exit_game(self): lobby.exit_game(self) @for_state('inroomwait', 'ready') def command_kick_user(self, uid): lobby.kick_user(self, uid) @for_state('inroomwait', 'ready') def command_invite_user(self, uid): lobby.invite_user(self, uid) @for_state('inroomwait', 'ready', 'ingame') def command_kick_observer(self, uid): lobby.kick_observer(self, uid) @for_state('inroomwait', 'observing') def command_change_location(self, loc): lobby.change_location(self, loc) @for_state('ready') def command_cancel_ready(self): lobby.cancel_ready(self) def command_heartbeat(self): pass @for_state('hang', 'inroomwait', 'ready', 'ingame', 'observing') def command_chat(self, text): lobby.chat(self, text) @for_state('hang', 'inroomwait', 'ready', 'ingame', 'observing') def command_speaker(self, text): lobby.speaker(self, text) del for_state
def gclear(self): self.gamedata = Gamedata()
def gclear(self): self.gamedata = Gamedata(recording=True)
def __init__(self, sock, addr): Endpoint.__init__(self, sock, addr) Greenlet.__init__(self) self.ctlcmds = Channel() self.userid = 0 self.gamedata = Gamedata(recording=True)