async def handle(self, connection: ConnectionAPI, cmd: Ping) -> None:
     connection.logger.debug2("Received ping on %s, replying with pong",
                              connection)
     try:
         connection.get_base_protocol().send(Pong(None))
     except PeerConnectionLost:
         connection.logger.debug2("%s disconnected while sending pong",
                                  connection)
Esempio n. 2
0
    async def handle(self, connection: ConnectionAPI, msg: Payload) -> None:
        msg = cast(Dict[str, Any], msg)
        try:
            reason = DisconnectReason(msg['reason'])
        except TypeError:
            self.logger.debug('Got unknown disconnect reason reason: %s', msg)
        else:
            self.disconnect_reason = reason

        if connection.is_operational:
            connection.cancel_nowait()
Esempio n. 3
0
    def __init__(self,
                 connection: ConnectionAPI,
                 context: BasePeerContext,
                 event_bus: EndpointAPI = None,
                 ) -> None:
        super().__init__(token=connection.cancel_token, loop=connection.cancel_token.loop)

        # Peer context object
        self.context = context

        # Connection instance
        self.connection = connection
        self.multiplexer = connection.get_multiplexer()

        self.base_protocol = self.connection.get_base_protocol()

        # TODO: need to remove this property but for now it is here to support
        # backwards compat
        for protocol_class in self.supported_sub_protocols:
            try:
                self.sub_proto = self.multiplexer.get_protocol_by_type(protocol_class)
            except UnknownProtocol:
                pass
            else:
                break
        else:
            raise ValidationError("No supported subprotocols found in multiplexer")

        # The self-identifying string that the remote names itself.
        self.client_version_string = self.connection.safe_client_version_string

        # Optional event bus handle
        self._event_bus = event_bus

        # Flag indicating whether the connection this peer represents was
        # established from a dial-out or dial-in (True: dial-in, False:
        # dial-out)
        # TODO: rename to `dial_in` and have a computed property for `dial_out`
        self.inbound = connection.is_dial_in
        self._subscribers: List[PeerSubscriber] = []

        # A counter of the number of messages this peer has received for each
        # message type.
        self.received_msgs: Dict[CommandAPI, int] = collections.defaultdict(int)

        # Manages the boot process
        self.boot_manager = self.get_boot_manager()
        self.connection_tracker = self.setup_connection_tracker()

        self.process_handshake_receipts(
            connection.get_p2p_receipt(),
            connection.protocol_receipts,
        )
Esempio n. 4
0
def choose_eth_or_les_api(connection: ConnectionAPI) -> AnyETHLESAPI:

    if connection.has_protocol(ETHProtocolV65):
        return connection.get_logic(ETHV65API.name, ETHV65API)
    elif connection.has_protocol(ETHProtocolV64):
        return connection.get_logic(ETHV64API.name, ETHV64API)
    elif connection.has_protocol(ETHProtocolV63):
        return connection.get_logic(ETHV63API.name, ETHV63API)
    elif connection.has_protocol(LESProtocolV2):
        return connection.get_logic(LESV2API.name, LESV2API)
    elif connection.has_protocol(LESProtocolV1):
        return connection.get_logic(LESV1API.name, LESV1API)
    else:
        raise Exception("Unreachable code path")
Esempio n. 5
0
    def __init__(self, connection: ConnectionAPI) -> None:
        self._connection = connection

        for attr, exchange_cls in self._exchange_config.items():
            if hasattr(self, attr):
                raise AttributeError(
                    f"Unable to set manager on attribute `{attr}` which is already "
                    f"present on the class: {getattr(self, attr)}")

            protocol = connection.get_protocol_for_command_type(
                exchange_cls.get_request_cmd_type())

            if not protocol.supports_command(
                    exchange_cls.get_response_cmd_type()):
                raise ValidationError(
                    f"Could not determine appropriate protocol: "
                    f"The response command type "
                    f"{exchange_cls.get_response_cmd_type()} is not supported by the "
                    f"protocol that matched the request command type: "
                    f"{protocol}")

            manager: ExchangeManager[Any, Any, Any]
            manager = ExchangeManager(
                connection=self._connection,
                requesting_on=protocol,
                listening_for=exchange_cls.get_response_cmd_type(),
            )
            exchange = exchange_cls(manager)
            setattr(self, attr, exchange)
Esempio n. 6
0
    async def apply(
            self,
            connection: ConnectionAPI) -> AsyncIterator[asyncio.Task[Any]]:
        """
        See LogicAPI.apply()

        The future returned here will be done when the first of the futures obtained from applying
        all behaviors of this application is done.
        """
        self.connection = connection

        async with contextlib.AsyncExitStack() as stack:
            futures: List[asyncio.Task[Any]] = []
            # First apply all the child behaviors
            for behavior in self._behaviors:
                if behavior.should_apply_to(connection):
                    fut = await stack.enter_async_context(
                        behavior.apply(connection))
                    futures.append(fut)

            # If none of our behaviors were applied, use a never-ending task so that callsites
            # can wait on it like when behaviors are applied.
            if not futures:
                futures.append(
                    create_task(_never_ending_coro(),
                                f'Application/{self.name}/no-behaviors-fut'))

            # Now register ourselves with the connection.
            with connection.add_logic(self.name, self):
                name = f'Application/{self.name}/apply/{connection.remote}'
                yield create_task(wait_first(futures), name=name)
Esempio n. 7
0
    async def apply(self, connection: ConnectionAPI) -> AsyncIterator[None]:
        if self.cmd_type is None:
            raise TypeError(f"No cmd_type specified for {self}")

        with connection.add_command_handler(self.cmd_type, self.handle):
            self.on_apply(connection)
            yield
Esempio n. 8
0
 def qualifier(self, connection: ConnectionAPI, logic: LogicAPI) -> bool:
     try:
         protocol = connection.get_protocol_for_command_type(
             self.exchange.get_request_cmd_type())
     except UnknownProtocol:
         return False
     else:
         return protocol.supports_command(
             self.exchange.get_response_cmd_type())
Esempio n. 9
0
    async def apply(self, connection: ConnectionAPI) -> AsyncIterator[None]:
        self.connection = connection

        async with contextlib.AsyncExitStack() as stack:
            # First apply all the child behaviors
            for behavior in self._behaviors:
                if behavior.should_apply_to(connection):
                    await stack.enter_async_context(behavior.apply(connection))

            # Now register ourselves with the connection.
            with connection.add_logic(self.name, self):
                yield
Esempio n. 10
0
    async def apply(self, connection: ConnectionAPI) -> AsyncIterator[None]:
        if hasattr(self, '_connection') is True:
            raise Exception("Reentrance!")

        self._connection = connection

        async with AsyncExitStack() as stack:
            for behavior in self.get_behaviors():
                if behavior.applies_to(connection):
                    await stack.enter_async_context(behavior.apply(connection))

            with connection.add_behavior(self.name, self):
                self.on_apply(connection)
                yield
Esempio n. 11
0
    async def run_exchange(self, connection: ConnectionAPI) -> AsyncIterator[None]:
        protocol = connection.get_protocol_for_command_type(self.get_request_cmd_type())

        response_stream: ResponseCandidateStream[TRequestCommand, TResponseCommand] = ResponseCandidateStream(  # noqa: E501
            connection,
            protocol,
            self.get_response_cmd_type(),
        )
        self._manager = ExchangeManager(
            connection,
            response_stream,
        )
        async with run_service(response_stream):
            yield
Esempio n. 12
0
    async def apply(
            self,
            connection: ConnectionAPI) -> AsyncIterator[asyncio.Future[None]]:
        """
        See LogicAPI.apply()

        The future returned here will never be done as a CommandHandler doesn't run a background
        task.
        """
        self.connection = connection

        with connection.add_command_handler(self.command_type,
                                            cast(HandlerFn, self.handle)):
            yield asyncio.Future()
Esempio n. 13
0
    async def run_exchange(
            self, connection: ConnectionAPI) -> AsyncIterator[asyncio.Future[None]]:
        protocol = connection.get_protocol_for_command_type(self.get_request_cmd_type())

        response_stream: ResponseCandidateStream[TRequestCommand, TResponseCommand] = ResponseCandidateStream(  # noqa: E501
            connection,
            protocol,
            self.get_response_cmd_type(),
        )
        async with background_asyncio_service(response_stream) as response_stream_manager:
            self._manager = ExchangeManager(
                connection,
                response_stream,
            )
            yield asyncio.create_task(response_stream_manager.wait_finished())
Esempio n. 14
0
    async def apply(
            self,
            connection: ConnectionAPI) -> AsyncIterator[asyncio.Task[Any]]:
        """
        See LogicAPI.apply()

        The future returned here will never be done as a CommandHandler doesn't run a background
        task.
        """
        self.connection = connection

        with connection.add_command_handler(self.command_type,
                                            cast(HandlerFn, self.handle)):
            yield create_task(
                _never_ending_coro(),
                f'CommandHandler/{self.__class__.__name__}/apply')
Esempio n. 15
0
    async def run_exchange(
            self,
            connection: ConnectionAPI) -> AsyncIterator[asyncio.Task[Any]]:
        protocol = connection.get_protocol_for_command_type(
            self.get_request_cmd_type())

        response_stream: ResponseCandidateStream[
            TRequestCommand,
            TResponseCommand] = ResponseCandidateStream(  # noqa: E501
                connection,
                protocol,
                self.get_response_cmd_type(),
            )
        async with background_asyncio_service(
                response_stream) as response_stream_manager:
            self._manager = ExchangeManager(
                connection,
                response_stream,
            )
            name = f'{self.__class__.__name__}/{connection.remote}'
            yield create_task(response_stream_manager.wait_finished(),
                              name=name)
Esempio n. 16
0
async def do_ping_pong_test(alice_connection: ConnectionAPI, bob_connection: ConnectionAPI) -> None:
    got_ping = asyncio.Event()
    got_pong = asyncio.Event()

    async def _handle_ping(connection: ConnectionAPI, msg: Any) -> None:
        got_ping.set()
        bob_connection.get_base_protocol().send_pong()

    async def _handle_pong(connection: ConnectionAPI, msg: Any) -> None:
        got_pong.set()

    alice_connection.add_command_handler(Pong, _handle_pong)
    bob_connection.add_command_handler(Ping, _handle_ping)

    alice_connection.get_base_protocol().send_ping()

    await asyncio.wait_for(got_ping.wait(), timeout=1)
    await asyncio.wait_for(got_pong.wait(), timeout=1)
Esempio n. 17
0
    async def run_exchange(self,
                           connection: ConnectionAPI) -> AsyncIterator[None]:
        protocol = connection.get_protocol_for_command_type(
            self.get_request_cmd_type())

        response_stream: ResponseCandidateStream[
            TRequestPayload,
            TResponsePayload] = ResponseCandidateStream(  # noqa: E501
                connection,
                protocol,
                self.get_response_cmd_type(),
            )

        try:
            self.tracker = self.tracker_class()
            self._manager = ExchangeManager(
                connection,
                response_stream,
            )
            async with run_service(response_stream):
                yield
        finally:
            del self._manager
            del self.tracker
def _send_ping(connection: ConnectionAPI) -> None:
    connection.get_base_protocol().send(Ping(None))
Esempio n. 19
0
 async def handle(self, connection: ConnectionAPI, cmd: Ping) -> None:
     connection.logger.debug2("Received ping on %s, replying with pong",
                              connection)
     connection.get_base_protocol().send(Pong(None))
Esempio n. 20
0
 async def handle(self, connection: ConnectionAPI, cmd: Ping) -> None:
     connection.get_base_protocol().send(Pong(None))
Esempio n. 21
0
    async def handle(self, connection: ConnectionAPI, cmd: Disconnect) -> None:
        self.disconnect_reason = cmd.payload

        if connection.is_operational:
            connection.cancel_nowait()
Esempio n. 22
0
    async def apply(self, connection: ConnectionAPI) -> AsyncIterator[None]:
        self.connection = connection

        with connection.add_command_handler(self.command_type,
                                            cast(HandlerFn, self.handle)):
            yield
Esempio n. 23
0
 async def handle(self, connection: ConnectionAPI, msg: Payload) -> None:
     connection.get_base_protocol().send_pong()
Esempio n. 24
0
 def applies_to(self, connection: ConnectionAPI) -> bool:
     return any(
         protocol.supports_command(self.cmd_type)
         for protocol in connection.get_multiplexer().get_protocols())
Esempio n. 25
0
 def __call__(self, connection: ConnectionAPI, logic: LogicAPI) -> bool:
     return connection.has_protocol(self._protocol_type)
Esempio n. 26
0
 def __call__(self, connection: ConnectionAPI, logic: LogicAPI) -> bool:
     return any(
         protocol.supports_command(self._command_type)
         for protocol in connection.get_protocols())