Пример #1
0
    def new_question(self):
        # forward question index
        self.question_idx += 1
        if self.question_idx >= len(self.questions):
            if self.loop:
                random.shuffle(self.questions)
                self.question_idx = 0
            else:
                self.end_of_game()
                return

        self.question = self.questions[self.question_idx]
        self.qid = self.question['qid']
        self.question_text = self.question['text'].split()
        self.question_length = len(self.question_text)
        self.position = 0
        self.start_streamer()

        def callback(x):
            self.new_question_1()

        def errback(x):
            logger.warning('[new question] streamer timed out')

        condition = partial(self._check_streamer, 'qid', self.qid)
        if condition():
            callback(None)
        else:
            deferred = Deferred()
            deferred.addTimeout(3, reactor)
            deferred.addCallbacks(callback, errback)
            self._deferreds.append((deferred, condition, 'streamer check'))
Пример #2
0
class ReceiverBase(object):
    response_handlers: List[Tuple[Pattern, "Control"]]
    cached_values: MutableMapping[str, Any]
    protocol: Optional[ReceiverProtocol] = None
    connected: Optional[Deferred] = None
    pending_writes: List[str]
    deferred_writer: Optional[Deferred] = None
    timeout: int

    def __init__(self, host: str, timeout: int = 1):
        self.cached_values = {}
        self.pending_writes = []
        self.timeout = timeout

        self.connected = self.connect(host)
        self.connected.addCallback(self._connected)
        self.connected.addCallback(self._write_next)

    def connect(self, host: str) -> Deferred:
        endpoint = TCP4ClientEndpoint(reactor, host, 23)
        protocol = ReceiverProtocol(self)
        return connectProtocol(endpoint, protocol)

    def write(self, command: str) -> None:
        self.pending_writes.append(command)

        if self.deferred_writer is None:
            self._write_next(None)

    def _write_next(self, _):
        if self.protocol is None:
            return
        if not self.pending_writes:
            return

        command = self.pending_writes.pop(0)
        self.protocol.sendLine(command.encode("ascii"))

        if self.timeout > 0:
            self.deferred_writer = Deferred()
            self.deferred_writer.addTimeout(self.timeout, reactor)
            self.deferred_writer.addCallback(self._write_next)
            self.deferred_writer.addErrback(self._write_next)

    def _connected(self, protocol):
        self.protocol = protocol
        self.connected = None

    def parse(self, line):
        handled = False
        for pattern, control in self.response_handlers:
            match = pattern.match(line)
            if match:
                control.parse(self, match)
                handled = True
        if not handled:
            print(f"Unhandled response: {line}", file=sys.stderr)
        if self.deferred_writer:
            self.deferred_writer, d = None, self.deferred_writer
            d.callback(None)
Пример #3
0
    def do_request(self,
                   message: Message,
                   timeout: Optional[int] = None) -> None:
        """
        Send request message to the client.
        Before sending additional message preparing required.
        """
        deferred = Deferred()
        timeout = timeout or self.request_timeout

        def on_timeout(failure, timeout_):
            logger.error(
                'Request timed out, no response was received '
                'in {timeout} sec',
                timeout=timeout_)
            del self._pending_requests[self._hop_by_hop]

        # noinspection PyTypeChecker
        deferred.addTimeout(timeout, reactor, on_timeout)

        message.hdr.hopbyhop = self._hop_by_hop
        self._hop_by_hop += 1

        request = message.create_request()
        self.transport.write(request)

        self._pending_requests[self._hop_by_hop] = PendingRequest(
            message, deferred)
Пример #4
0
    def handle_buzzing(self, end_of_question=False):
        buzzing_inds = []
        for i, user in enumerate(self.users):
            if self.buzzed[user.peer]:
                continue
            if end_of_question:
                buzzing_inds.append(i)
                continue
            if user.peer in self.user_responses and \
                    'type' in self.user_responses[user.peer]:
                rsp_type = self.user_responses[user.peer]['type']
                if rsp_type == MSG_TYPE_BUZZING_REQUEST:
                    buzzing_inds.append(i)

        if len(buzzing_inds) == 0:
            if end_of_question:
                self.end_of_question()
            return

        random.shuffle(buzzing_inds)
        buzzing_idx = buzzing_inds[0]

        logger.info('[buzzing] Player {} answering'.format(buzzing_idx))

        red_msg = {
            'type': MSG_TYPE_BUZZING_RED,
            'qid': self.qid,
            'uid': buzzing_idx,
            'length': 8
        }
        red_users = self.users[:buzzing_idx] + self.users[buzzing_idx + 1:]
        self.broadcast(red_users, red_msg)

        green_msg = {
            'type': MSG_TYPE_BUZZING_GREEN,
            'qid': self.qid,
            'length': 8
        }
        green_user = self.users[buzzing_idx]
        green_user.sendMessage(json.dumps(green_msg).encode('utf-8'))

        self.buzzed[green_user.peer] = True

        condition = partial(self._check_user, green_user.peer, 'type',
                            MSG_TYPE_BUZZING_ANSWER)
        callback = partial(self.handle_buzzing_ok, buzzing_idx,
                           end_of_question)
        errback = partial(self.handle_buzzing_timeout, buzzing_idx,
                          end_of_question)

        if condition():
            callback(None)
        else:
            deferred = Deferred()
            deferred.addTimeout(ANSWER_TIME_OUT, reactor)
            deferred.addCallbacks(callback, errback)
            self._deferreds.append(
                (deferred, condition, 'wait for user answer'))
Пример #5
0
 def newDeferredResponse(self):
     """Make a lifetime limited response and save it in a FIFO queue
     
     Responses are associated to requests based only in the order
     assuming the server send reponses in the same order as it receive requests
     """
     d = Deferred()
     d.addTimeout(self.timeout, reactor)
     d.addErrback(self.cleanupOnTimeout, d)
     self.deferredResponses.append(d)
     return d
Пример #6
0
    def _render_POST_stratum(self, tx: Transaction, request: Request) -> None:
        """ Resolves the request using stratum
            Create a deferred and send it and the tx to be mined to stratum
            WHen the proof of work is completed in stratum, the callback is called
        """
        # When using stratum to solve pow, we already set timestamp and parents
        stratum_deferred = Deferred()
        stratum_deferred.addCallback(self._stratum_deferred_resolve, request)

        fn_timeout = partial(self._stratum_timeout, request=request, tx=tx)
        stratum_deferred.addTimeout(TIMEOUT_STRATUM_RESOLVE_POW, self.manager.reactor, onTimeoutCancel=fn_timeout)

        self.manager.stratum_factory.mine_transaction(tx, stratum_deferred)
Пример #7
0
    def _buzzing(self, buzzing_ids, end_of_question):
        random.shuffle(buzzing_ids)
        buzzing_id = buzzing_ids[0]
        green_player = self.players[buzzing_id]
        logger.info('[buzzing] player {} answering'.format(green_player.name))

        self.info_text += NEW_LINE + BADGE_BUZZ
        self.info_text += ' {}: '.format(bodify(green_player.name))
        self.bell_positions.append(self.position_map[self.position])

        msg = {'qid': self.qid, 
                'length': ANSWER_TIME_OUT,
                'info_text': self.info_text}

        msg['type'] = MSG_TYPE_BUZZING_GREEN
        green_player.sendMessage(msg)
        green_player.buzzed = True
        green_player.position_buzz = self.position

        msg['type'] = MSG_TYPE_BUZZING_RED
        for player in self.players.values():
            if player.uid != buzzing_id:
                player.sendMessage(msg)

        self.latest_buzzing_msg = msg

        condition = partial(self.check_player_response, 
                green_player, 'type', MSG_TYPE_BUZZING_ANSWER)

        def callback(x):
            self._buzzing_after(buzzing_id, end_of_question, timed_out=False)

        def errback(x):
            logger.info('[buzzing] player {} answer time out'.format(
                green_player.name))
            self._buzzing_after(buzzing_id, end_of_question, timed_out=True)

        if condition():
            callback(None)
        else:
            deferred = Deferred()
            deferred.addTimeout(ANSWER_TIME_OUT, reactor)
            deferred.addCallbacks(callback, errback)
            self.deferreds.append((deferred, condition))
Пример #8
0
    def _chain_calls(self, *calls):
        """
        This will chain calls to the websocket server. Each method must follow this pattern:

            def method(result):
                d = Deferred()
                ...
                return d

        The last method must not return.

        If the test doesn't complete under 5 seconds, it will be aborted.

        :returns: The Deferred that will be invoked when the test succeeds or fails.
        """
        done = Deferred()
        done.addTimeout(5, reactor)
        self._call_next(None, list(calls), done)
        return done
    def _chain_calls(self, *calls):
        """
        This will chain calls to the websocket server. Each method must follow this pattern:

            def method(result):
                d = Deferred()
                ...
                return d

        The last method must not return.

        If the test doesn't complete under 5 seconds, it will be aborted.

        :returns: The Deferred that will be invoked when the test succeeds or fails.
        """
        done = Deferred()
        done.addTimeout(5, reactor)
        self._call_next(None, list(calls), done)
        return done
Пример #10
0
    def new_question_1(self):
        msg = {
            'type': MSG_TYPE_NEW,
            'qid': self.qid,
            'text': 'new question',
            'length': self.question_length
        }
        self.broadcast(self.users, msg)
        self.buzzed = defaultdict(lambda: False)

        for user in self.users:

            def callback(x):
                logger.info('[new question] User {} ready'.format(user.peer))

            def errback(x):
                logger.warning('[new question] user {} timed out'\
                        .format(user.peer))
                self.unregister(user)

            condition = partial(self._check_user, user.peer, 'qid', self.qid)

            if condition():
                callback(None)
            else:
                deferred = Deferred()
                deferred.addTimeout(3, reactor)
                deferred.addCallbacks(callback, errback)
                self._deferreds.append((deferred, condition, 'user check'))

        def callback():
            self.new_question_2()
            # if len(self._deferreds) == 0:
            #     logger.info('Starting question qid: {} (Answer: {})'\
            #             .format(self.qid, self.question['answer']))
            # else:
            #     logger.error('Cannot start game with {} deferreds'\
            #             .format(len(self._deferreds)))

        reactor.callLater(0.5, callback)
Пример #11
0
def restart(service_name, wait_timeout=None):
    """
    """
    global _StopingDeferred
    global _StartingDeferred
    restart_result = Deferred()

    def _on_started(start_result, stop_result, dependencies_results):
        lg.out(4, 'driver.restart._on_started : %s with %s, dependencies_results=%r' % (service_name, start_result, dependencies_results))
        try:
            stop_resp = {stop_result[0][1]: stop_result[0][0], }
        except:
            stop_resp = {'stopped': str(stop_result), }
        try:
            start_resp = {start_result[0][1]: start_result[0][0], }
        except:
            start_resp = {'started': str(start_result), }
        restart_result.callback([stop_resp, start_resp, ])
        return start_result

    def _on_failed(err):
        lg.err(err)
        restart_result.errback(str(err))
        return None

    def _do_start(stop_result=None, dependencies_results=None):
        lg.out(4, 'driver.restart._do_start : %s' % service_name)
        start_defer = start(services_list=[service_name, ])
        start_defer.addCallback(_on_started, stop_result, dependencies_results)
        start_defer.addErrback(_on_failed)
        return start_defer

    def _on_stopped(stop_result, dependencies_results):
        lg.out(4, 'driver.restart._on_stopped : %s with %s' % (service_name, stop_result))
        _do_start(stop_result, dependencies_results)
        return stop_result

    def _do_stop(dependencies_results=None):
        lg.out(4, 'driver.restart._do_stop : %s' % service_name)
        stop_defer = stop(services_list=[service_name, ])
        stop_defer.addCallback(_on_stopped, dependencies_results)
        stop_defer.addErrback(_on_failed)
        return stop_defer

    def _on_timeout(err):
        lg.out(4, 'driver.restart._on_timeout : %s' % service_name)
        all_states = [_svc.state for _svc in services().values()]
        if 'INFLUENCE' in all_states or 'STARTING' in all_states or 'STOPPING' in all_states:
            restart_result.errback(failure.Failure(Exception('timeout')))
            return err
        _do_stop()
        return None

    dl = []
    if _StopingDeferred:
        dl.append(_StopingDeferred)
    if _StartingDeferred:
        dl.append(_StartingDeferred)
    if wait_timeout:
        all_states = [_svc.state for _svc in services().values()]
        if 'INFLUENCE' in all_states or 'STARTING' in all_states or 'STOPPING' in all_states:
            wait_timeout_defer = Deferred()
            wait_timeout_defer.addTimeout(wait_timeout, clock=reactor)
            dl.append(wait_timeout_defer)
    if not dl:
        dl.append(succeed(True))

    lg.out(4, 'driver.restart %s' % service_name)
    dependencies = DeferredList(dl, fireOnOneErrback=True, consumeErrors=True)
    dependencies.addCallback(_do_stop)
    dependencies.addErrback(_on_timeout)
    return restart_result
Пример #12
0
def connected(wait_timeout=5):
    ret = Deferred()

    if driver.is_enabled('service_proxy_transport'):
        p2p_connector_lookup = automat.find('p2p_connector')
        if p2p_connector_lookup:
            p2p_connector_machine = automat.by_index(p2p_connector_lookup[0])
            if p2p_connector_machine and p2p_connector_machine.state == 'CONNECTED':
                proxy_receiver_lookup = automat.find('proxy_receiver')
                if proxy_receiver_lookup:
                    proxy_receiver_machine = automat.by_index(
                        proxy_receiver_lookup[0])
                    if proxy_receiver_machine and proxy_receiver_machine.state == 'LISTEN':
                        # service_proxy_transport() is enabled, proxy_receiver() is listening: all good
                        wait_timeout_defer = Deferred()
                        wait_timeout_defer.addBoth(lambda _: ret.callback({
                            'service_network':
                            'started',
                            'service_gateway':
                            'started',
                            'service_p2p_hookups':
                            'started',
                            'service_proxy_transport':
                            'started',
                            'proxy_receiver_state':
                            proxy_receiver_machine.state,
                        }))
                        if not wait_timeout:
                            wait_timeout = 0.01
                        wait_timeout_defer.addTimeout(wait_timeout,
                                                      clock=reactor)
                        return ret
                else:
                    d = driver.is_healthy('service_proxy_transport')
                    d.addCallback(on_service_proxy_transport_check_healthy,
                                  wait_timeout=wait_timeout)
                    d.addErrback(lg.errback,
                                 debug=_Debug,
                                 debug_level=_DebugLevel,
                                 method='network_service.connected',
                                 ignore=True)
                    lg.warn(
                        'disconnected, reason is proxy_receiver() not started yet'
                    )
                    ret.callback(
                        dict(
                            error='disconnected',
                            reason='proxy_receiver_not_started',
                        ))
                    return ret

    if not my_id.isLocalIdentityReady():
        lg.warn('local identity is not valid or not exist')
        ret.callback(
            dict(
                error='local identity is not valid or not exist',
                reason='identity_not_exist',
            ))
        return ret
    if not driver.is_enabled('service_network'):
        lg.warn('service_network() is disabled')
        ret.callback(
            dict(
                error='service_network() is disabled',
                reason='service_network_disabled',
            ))
        return ret
    if not driver.is_enabled('service_gateway'):
        lg.warn('service_gateway() is disabled')
        ret.callback(
            dict(
                error='service_gateway() is disabled',
                reason='service_gateway_disabled',
            ))
        return ret
    if not driver.is_enabled('service_p2p_hookups'):
        lg.warn('service_p2p_hookups() is disabled')
        ret.callback(
            dict(
                error='service_p2p_hookups() is disabled',
                reason='service_p2p_hookups_disabled',
            ))
        return ret

    do_service_test('service_network', ret, wait_timeout)
    return ret
Пример #13
0
    def new_question(self):
        try:
            self.question_idx += 1
            if self.question_idx >= len(self.questions):
                if self.loop:
                    random.shuffle(self.questions)
                    self.question_idx = 0
                else:
                    self._end_of_game()
                    return
            
            self.question = self.questions[self.question_idx]
            self.question['answer'] = self.question['answer'].replace('_', ' ')
            self.qid = self.question['qid']
            self.question_length = len(self.question['text'].split())

            self.question_text = ''
            self.raw_text = self.question['text'].split()
            self.info_text = ''
            self.record = self.records[int(self.qid)]
            self.position_map = self.pos_maps[self.qid]
            self.bell_positions = []
            self.position = 0
            self.latest_resume_msg = None
            self.latest_buzzing_msg = None

            def make_callback(player):
                def f(x):
                    logger.info('[new question] player {} ready'.format(
                        player.name))
                return f

            def make_errback(player):
                def f(x):
                    logger.info('[new question] player {} timed out'.format(
                        player.name))
                    self.unregister(player=player)
                return f

            msg = {'type': MSG_TYPE_NEW, 'qid': self.qid, 
                    'length': self.question_length, 'position': 0,
                    'player_list': self.get_player_list(),
                    'speech_text': ' '.join(self.raw_text)}
            for player in self.players.values():
                player.sendMessage(msg)
                condition = partial(self.check_player_response,
                        player=player, key='qid', value=self.qid)
                callback = make_callback(player)
                errback = make_errback(player)
                
                if condition():
                    callback(None)
                else:
                    deferred = Deferred()
                    deferred.addTimeout(PLAYER_RESPONSE_TIME_OUT, reactor)
                    deferred.addCallbacks(callback, errback)
                    self.deferreds.append((deferred, condition))
        except:
            traceback.print_exc(file=sys.stdout)

        def calllater():
            for player in self.players.values():
                logger.info("player {} score {}".format(
                    player.name, player.score))
            self.pbar = tqdm(total=self.question_length, leave=False)
            self.stream_next()

        reactor.callLater(SECOND_PER_WORD, calllater)
Пример #14
0
    def register(self, client):
        if client.peer not in self.socket_to_player:
            new_player = Player(client)
            self.socket_to_player[client.peer] = new_player
            msg = {'type': MSG_TYPE_NEW,
                    'qid': self.qid,
                    'player_uid': new_player.uid,
                    'player_name': new_player.name}
            new_player.sendMessage(msg)

            def callback(x):
                try:
                    uid = new_player.response['player_uid']
                    name = new_player.response['player_name']
                    if uid in self.players:
                        # same uid exists
                        old_peer = self.players[uid].client.peer
                        self.socket_to_player[client.peer] = self.players[uid]
                        self.players[uid].client = client
                        self.players[uid].name = name
                        self.socket_to_player.pop(old_peer, None)
                        self.players[uid].active = True
                        logger.info("[register] old player {} ({} -> {})".format(
                            name, old_peer, client.peer))
                    else:
                        new_player.uid = uid
                        new_player.name = name
                        new_player.position_start = self.position
                        self.players[uid] = new_player
                        logger.info('add player {} to db'.format(new_player.uid))
                        self.db.add_player(new_player)
                        logger.info("[register] new player {} ({})".format(
                            name, client.peer))

                    msg = {'type': MSG_TYPE_NEW, 'qid': self.qid,
                            'player_list': self.get_player_list(),
                            'info_text': self.info_text,
                            'history_entries': self.history_entries,
                            'position': self.position,
                            'speech_text': ' '.join(self.raw_text[self.position:])}
                    self.players[uid].sendMessage(msg)
                    if self.latest_resume_msg is not None:
                        self.players[uid].sendMessage(self.latest_resume_msg)
                    if self.latest_buzzing_msg is not None:
                        self.players[uid].sendMessage(self.latest_buzzing_msg)

                    if len(self.players) == 1 and not self.started:
                        self.started = True
                        self.new_question()
                except:
                    traceback.print_exc(file=sys.stdout)

            def errback(x):
                logger.info('[register] client {} timed out'.format(client.peer))

            condition = partial(self.check_player_response,
                                player=new_player, key='qid', value=self.qid)
            if condition():
                callback(None)
            else:
                deferred = Deferred()
                deferred.addTimeout(PLAYER_RESPONSE_TIME_OUT, reactor)
                deferred.addCallbacks(callback, errback)
                self.deferreds.append((deferred, condition))