def get_protocol_command_for(self, msg: bytes) -> protocol.Command: """Return the Command corresponding to the cmd_id encoded in the given msg.""" cmd_id = get_devp2p_cmd_id(msg) self.logger.trace("Got msg with cmd_id: %s", cmd_id) if cmd_id < self.base_protocol.cmd_length: return self.base_protocol.cmd_by_id[cmd_id] elif cmd_id < self.sub_proto.cmd_id_offset + self.sub_proto.cmd_length: return self.sub_proto.cmd_by_id[cmd_id] else: raise UnknownProtocolCommand(f"No protocol found for cmd_id {cmd_id}")
def get_protocol_command_for(self, msg: bytes) -> protocol.Command: """Return the Command corresponding to the cmd_id encoded in the given msg.""" cmd_id = get_devp2p_cmd_id(msg) self.logger.debug("Got msg with cmd_id: %s", cmd_id) if cmd_id < self.base_protocol.cmd_length: proto = self.base_protocol elif cmd_id < self.sub_proto.cmd_id_offset + self.sub_proto.cmd_length: proto = self.sub_proto # type: ignore else: raise UnknownProtocolCommand("No protocol found for cmd_id {}".format(cmd_id)) return proto.cmd_by_id[cmd_id]
async def stream_transport_messages(transport: TransportAPI, base_protocol: BaseP2PProtocol, *protocols: ProtocolAPI, ) -> AsyncIterator[Tuple[ProtocolAPI, CommandAPI[Any]]]: """ Streams 2-tuples of (Protocol, Command) over the provided `Transport` """ # A cache for looking up the proper protocol instance for a given command # id. command_id_cache: Dict[int, ProtocolAPI] = {} while not transport.is_closing: try: msg = await transport.recv() except PeerConnectionLost: return command_id = msg.command_id if msg.command_id not in command_id_cache: if command_id < base_protocol.command_length: command_id_cache[command_id] = base_protocol else: for protocol in protocols: if command_id < protocol.command_id_offset + protocol.command_length: command_id_cache[command_id] = protocol break else: protocol_infos = ' '.join(tuple( ( f"{proto.name}@{proto.version}" f"[offset={proto.command_id_offset}," f"command_length={proto.command_length}]" ) for proto in cons(base_protocol, protocols) )) raise UnknownProtocolCommand( f"No protocol found for command_id {command_id}: Available " f"protocol/offsets are: {protocol_infos}" ) msg_proto = command_id_cache[command_id] command_type = msg_proto.get_command_type_for_command_id(command_id) try: cmd = command_type.decode(msg, msg_proto.snappy_support) except (rlp.exceptions.DeserializationError, snappy_CompressedLengthError) as err: raise MalformedMessage(f"Failed to decode {msg} for {command_type}") from err yield msg_proto, cmd # yield to the event loop for a moment to allow `transport.is_closing` # a chance to update. await asyncio.sleep(0)
def add_command_handler( self, command_type: Type[CommandAPI[Any]], handler_fn: HandlerFn, ) -> SubscriptionAPI: for protocol in self._multiplexer.get_protocols(): if protocol.supports_command(command_type): self._command_handlers[command_type].add(handler_fn) cancel_fn = functools.partial( self._command_handlers[command_type].remove, handler_fn, ) return Subscription(cancel_fn) else: raise UnknownProtocolCommand( f"Command {command_type} was not found in the connected " f"protocols: {self._multiplexer.get_protocols()}")
async def stream_transport_messages(transport: TransportAPI, base_protocol: BaseP2PProtocol, *protocols: ProtocolAPI, token: CancelToken = None, ) -> AsyncIterator[Tuple[ProtocolAPI, CommandAPI, Payload]]: """ Streams 3-tuples of (Protocol, Command, Payload) over the provided `Transport` """ # A cache for looking up the proper protocol instance for a given command # id. cmd_id_cache: Dict[int, ProtocolAPI] = {} while not transport.is_closing: raw_msg = await transport.recv(token) cmd_id = get_devp2p_cmd_id(raw_msg) if cmd_id not in cmd_id_cache: if cmd_id < base_protocol.cmd_length: cmd_id_cache[cmd_id] = base_protocol else: for protocol in protocols: if cmd_id < protocol.cmd_id_offset + protocol.cmd_length: cmd_id_cache[cmd_id] = protocol break else: protocol_infos = ' '.join(tuple( f"{proto.name}@{proto.version}[offset={proto.cmd_id_offset},cmd_length={proto.cmd_length}]" # noqa: E501 for proto in cons(base_protocol, protocols) )) raise UnknownProtocolCommand( f"No protocol found for cmd_id {cmd_id}: Available " f"protocol/offsets are: {protocol_infos}" ) msg_proto = cmd_id_cache[cmd_id] cmd = msg_proto.cmd_by_id[cmd_id] msg = cmd.decode(raw_msg) yield msg_proto, cmd, msg # yield to the event loop for a moment to allow `transport.is_closing` # a chance to update. await asyncio.sleep(0)
async def stream_transport_messages( transport: TransportAPI, base_protocol: BaseP2PProtocol, *protocols: ProtocolAPI, token: CancelToken = None, ) -> AsyncIterator[Tuple[ProtocolAPI, CommandAPI[Any]]]: """ Streams 2-tuples of (Protocol, Command) over the provided `Transport` """ # A cache for looking up the proper protocol instance for a given command # id. command_id_cache: Dict[int, ProtocolAPI] = {} while not transport.is_closing: msg = await transport.recv(token) command_id = msg.command_id if msg.command_id not in command_id_cache: if command_id < base_protocol.command_length: command_id_cache[command_id] = base_protocol else: for protocol in protocols: if command_id < protocol.command_id_offset + protocol.command_length: command_id_cache[command_id] = protocol break else: protocol_infos = ' '.join( tuple((f"{proto.name}@{proto.version}" f"[offset={proto.command_id_offset}," f"command_length={proto.command_length}]") for proto in cons(base_protocol, protocols))) raise UnknownProtocolCommand( f"No protocol found for command_id {command_id}: Available " f"protocol/offsets are: {protocol_infos}") msg_proto = command_id_cache[command_id] command_type = msg_proto.get_command_type_for_command_id(command_id) cmd = command_type.decode(msg, msg_proto.snappy_support) yield msg_proto, cmd # yield to the event loop for a moment to allow `transport.is_closing` # a chance to update. await asyncio.sleep(0)
async def stream_transport_messages(transport: TransportAPI, base_protocol: BaseP2PProtocol, *protocols: ProtocolAPI, ) -> AsyncIterator[Tuple[ProtocolAPI, CommandAPI[Any]]]: """ Streams 2-tuples of (Protocol, Command) over the provided `Transport` Raises a TimeoutError if nothing is received in constants.CONN_IDLE_TIMEOUT seconds. """ # A cache for looking up the proper protocol instance for a given command # id. command_id_cache: Dict[int, ProtocolAPI] = {} loop = asyncio.get_event_loop() while not transport.is_closing: try: msg = await transport.recv() except PeerConnectionLost: transport.logger.debug( "Lost connection to %s, leaving stream_transport_messages()", transport.remote) return command_id = msg.command_id if msg.command_id not in command_id_cache: if command_id < base_protocol.command_length: command_id_cache[command_id] = base_protocol else: for protocol in protocols: if command_id < protocol.command_id_offset + protocol.command_length: command_id_cache[command_id] = protocol break else: protocol_infos = ' '.join(tuple( ( f"{proto.name}@{proto.version}" f"[offset={proto.command_id_offset}," f"command_length={proto.command_length}]" ) for proto in cons(base_protocol, protocols) )) raise UnknownProtocolCommand( f"No protocol found for command_id {command_id}: Available " f"protocol/offsets are: {protocol_infos}" ) msg_proto = command_id_cache[command_id] command_type = msg_proto.get_command_type_for_command_id(command_id) try: if len(msg.body) > MAX_IN_LOOP_DECODE_SIZE: cmd = await loop.run_in_executor( None, command_type.decode, msg, msg_proto.snappy_support, ) else: cmd = command_type.decode(msg, msg_proto.snappy_support) except (rlp.exceptions.DeserializationError, snappy_CompressedLengthError) as err: raise MalformedMessage(f"Failed to decode {msg} for {command_type}") from err yield msg_proto, cmd # yield to the event loop for a moment to allow `transport.is_closing` # a chance to update. await asyncio.sleep(0)