Example #1
0
 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
Example #2
0
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()
Example #3
0
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
Example #4
0
 def gclear(self):
     self.gamedata = Gamedata()
Example #5
0
 def gclear(self):
     self.gamedata = Gamedata(recording=True)
Example #6
0
 def __init__(self, sock, addr):
     Endpoint.__init__(self, sock, addr)
     Greenlet.__init__(self)
     self.ctlcmds = Channel()
     self.userid = 0
     self.gamedata = Gamedata(recording=True)