def __init__(self, sock, addr, greenlet): Endpoint.__init__(self, sock, addr) self.observers = BatchList() self.gamedata = Gamedata() self.cmd_listeners = defaultdict(WeakSet) self.current_game = None self.greenlet = greenlet self.account = 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.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): def __init__(self, sock, addr, greenlet): Endpoint.__init__(self, sock, addr) self.observers = BatchList() self.gamedata = Gamedata() self.cmd_listeners = defaultdict(WeakSet) self.current_game = None self.greenlet = greenlet self.account = None @classmethod def serve(cls, sock, addr): c = getcurrent() cli = cls(sock, addr, c) c.gr_name = repr(cli) cli._serve() @log_failure(log) def _serve(self): # ----- 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 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) gr = self.greenlet self.greenlet = None gr and gr.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): if cmd == 'gamedata': self.gamedata.feed(data) return 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 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'): Subsystem.lobby.exit_game(self, is_drop=True) if self.state != 'connected': Subsystem.lobby.user_leave(self) def gexpect(self, tag, blocking=True): tag, data = self.gamedata.gexpect(tag, blocking) tag and _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])) _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() # --------- Handlers --------- def command_auth(self, login, password): if self.state != 'connected' or 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 Subsystem.lobby.user_join(self) else: self.write(['auth_result', 'invalid_credential']) def command_lobby(self, cmd, args): Subsystem.lobby.process_command(self, cmd, args) def command_item(self, cmd, args): Subsystem.item.process_command(self, cmd, args) def command_heartbeat(self): pass
def gclear(self): self.gamedata = Gamedata()
class Client(Endpoint): def __init__(self, sock, addr, greenlet): Endpoint.__init__(self, sock, addr) self.observers = BatchList() self.gamedata = Gamedata() self.cmd_listeners = defaultdict(WeakSet) self.current_game = None self.greenlet = greenlet self.account = None @classmethod def serve(cls, sock, addr): c = getcurrent() cli = cls(sock, addr, c) c.gr_name = repr(cli) cli._serve() @log_failure(log) def _serve(self): # ----- 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 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) gr = self.greenlet self.greenlet = None gr and gr.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): if cmd == 'gamedata': self.gamedata.feed(data) return 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 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'): Subsystem.lobby.exit_game(self, is_drop=True) if self.state != 'connected': Subsystem.lobby.user_leave(self) def gexpect(self, tag, blocking=True): tag, data = self.gamedata.gexpect(tag, blocking) tag and _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])) _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() # --------- Handlers --------- def command_auth(self, login, password): if self.state != 'connected' or 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 Subsystem.lobby.user_join(self) else: self.write(['auth_result', 'invalid_credential']) def command_lobby(self, cmd, args): Subsystem.lobby.process_command(self, cmd, args) def command_item(self, cmd, args): Subsystem.item.process_command(self, cmd, args) def command_heartbeat(self): pass
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.gamedata = Gamedata(recording=True)