示例#1
0
class Client(object, LineOnlyReceiver):
    state = None
    fields = ()

    def __init__(self, app):
        self.app = app

    def connectionMade(self):
        self.logger = TerminalLogger(self.app)
        self.sendLine('REGISTER {}'.format(self.__class__.__name__.lower()))

    def connectionLost(self, reason=ConnectionDone):
        if reason != ConnectionDone:
            self.logger.error('Connection lost!')

        del self.app.port
        del self.app.factory
        self.app.state = AppState.offline

        if hasattr(self.app, 'loop'):
            self.app.loop.stop()
            del self.app.loop

    def lineReceived(self, line):
        self.logger.log(line)
        args = line.split()

        if not self.state:
            if args[0] == 'REGISTERACK':
                self.handle_REGISTERACK(args)

                self.app.loop = LoopingCall(self.loop)
                self.app.loop.start(1)
            else:
                self.handle_unknown(line)
        else:
            if args[0] in ('GIVEN', 'TAKEN', 'SET'):
                getattr(self, 'handle_' + args[0])(args)
            else:
                self.handle_unknown(line)

    def handle_REGISTERACK(self, args):
        raise NotImplementedError

    def handle_GIVEN(self, args):
        raise NotImplementedError

    def handle_TAKEN(self, args):
        raise NotImplementedError

    def handle_SET(self, args):
        if args[1] in self.fields:
            setattr(self, args[1], type(getattr(self, args[1]))(args[2]))
        else:
            self.logger.error('Field \'{}\' not found!', args[1])

    def handle_unknown(self, line):
        self.logger.warning('Received unhandled message: {}', line)

    def loop(self):
        self.sendLine('STATUS {} {}'.format(
            self.state.name,
            ' '.join([str(getattr(self, field)) for field in self.fields])
        ))
示例#2
0
class Server(LineOnlyReceiver):
    state = None
    pending = False
    marks = ['!', 'X', '^', '>', 'v']

    def __init__(self, app):
        self.app = app

    def connectionMade(self):
        self.logger = TerminalLogger(self.app)

    def connectionLost(self, reason=ConnectionDone):
        self.logger.log('Client disconnected! {}', reason)

        if self in self.app.clients:
            self.app.clients.remove(self)

    def lineReceived(self, line):
        args = line.split()

        if not self.state:
            if args[0] == 'REGISTER':
                self.handle_REGISTER(args)
            else:
                self.handle_unknown(line)
        else:
            if args[0] == 'STATUS':
                self.handle_STATUS(args)
            else:
                self.handle_unknown(line)

    def handle_REGISTER(self, args):
        if args[1] in ConnectCommand.client_types:
            self.type = ConnectCommand.client_types[args[1]]
            self.state = ClientState.registered
            self.app.clients.append(self)

            self.sendLine('REGISTERACK OK')

            self.logger.log('New {} client!', self.type.__class__.__name__)
        else:
            self.sendLine('REGISTERACK UNKNOWN_CLIENT_TYPE')
            self.logger.error('Unknown client type {}!', args[1])
            self.transport.loseConnection()

    def handle_STATUS(self, args):
        self.state = ClientState[args[1]]
        self.pending = False

        for key, field in enumerate(self.type.fields, start=2):
            setattr(self, field, type(getattr(self.type, field))(args[key]))

    def handle_unknown(self, line):
        self.logger.warning('Received unhandled message: {}', line)

    @staticmethod
    def loop(app, user_data):
        clients = ['[{}][{}]{}:{} {}'.format(
            i, Server.marks[client.state.value], client.type.__name__, client.state.name,
            ' '.join(['{}:{}'.format(field, str(getattr(client, field))) for field in client.type.fields])
        ) for i, client in enumerate(app.clients)]
        app.header.set_text('\n'.join(clients) if app.clients else '[-][-]No clients')

        for client_curr, client_next in pairwise(app.clients):
            if (client_curr.state == ClientState.ready_give) and not client_curr.pending:
                if client_next:
                    if (client_next.state == ClientState.ready_take) and not client_next.pending:
                        client_curr.sendLine('TAKEN')
                        client_next.sendLine('GIVEN')
                        client_curr.pending = True
                        client_next.pending = True
                else:
                    client_curr.sendLine('TAKEN')
                    client_curr.pending = True

        app.loop = app.set_alarm_in(1, Server.loop)