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)
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()
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, )
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")
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)
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)
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
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())
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
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
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
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()
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())
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')
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)
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)
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))
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))
async def handle(self, connection: ConnectionAPI, cmd: Ping) -> None: connection.get_base_protocol().send(Pong(None))
async def handle(self, connection: ConnectionAPI, cmd: Disconnect) -> None: self.disconnect_reason = cmd.payload if connection.is_operational: connection.cancel_nowait()
async def apply(self, connection: ConnectionAPI) -> AsyncIterator[None]: self.connection = connection with connection.add_command_handler(self.command_type, cast(HandlerFn, self.handle)): yield
async def handle(self, connection: ConnectionAPI, msg: Payload) -> None: connection.get_base_protocol().send_pong()
def applies_to(self, connection: ConnectionAPI) -> bool: return any( protocol.supports_command(self.cmd_type) for protocol in connection.get_multiplexer().get_protocols())
def __call__(self, connection: ConnectionAPI, logic: LogicAPI) -> bool: return connection.has_protocol(self._protocol_type)
def __call__(self, connection: ConnectionAPI, logic: LogicAPI) -> bool: return any( protocol.supports_command(self._command_type) for protocol in connection.get_protocols())