class KeepAliveMessageV4(MessageV4): """ BloXroute Version message that contains a message nonce to be used in the response. nonce: long, to be provided and managed by the connection """ KEEP_ALIVE_MESSAGE_BLOCK = PayloadBlock(AbstractBloxrouteMessage.HEADER_LENGTH, "ResponseMessage", PROTOCOL_VERSION, PayloadElement(name="nonce", structure="<Q", decode=lambda x: x or None), ) KEEP_ALIVE_MESSAGE_LENGTH = KEEP_ALIVE_MESSAGE_BLOCK.size def __init__(self, msg_type, nonce=None, buf=None): self.timestamp = datetime.utcnow() if buf is None: buf = bytearray(BX_HDR_COMMON_OFF + self.KEEP_ALIVE_MESSAGE_LENGTH) buf = self.KEEP_ALIVE_MESSAGE_BLOCK.build(buf, nonce=nonce) self.buf = buf self._nonce = None self._network_num = None self._memoryview = memoryview(buf) super(KeepAliveMessageV4, self).__init__(msg_type, self.KEEP_ALIVE_MESSAGE_LENGTH, buf) def __unpack(self): contents = self.KEEP_ALIVE_MESSAGE_BLOCK.read(self._memoryview) self._nonce = contents.get("nonce") def nonce(self): if self._nonce is None: self.__unpack() return self._nonce
class PongMessage(KeepAliveMessage): MESSAGE_TYPE = BloxrouteMessageType.PONG PONG_MESSAGE_BLOCK = PayloadBlock( AbstractBloxrouteMessage.HEADER_LENGTH, "ResponseMessage", PROTOCOL_VERSION, PayloadElement(name="nonce", structure="<Q", decode=lambda x: x or None), PayloadElement(name="timestamp", structure="<Q", decode=lambda x: x or None), ) PONG_MESSAGE_LENGTH = PONG_MESSAGE_BLOCK.size + constants.CONTROL_FLAGS_LEN def __init__(self, nonce: Optional[int] = None, timestamp: Optional[int] = None, buf: Optional[bytearray] = None) -> None: if buf is None: buf = bytearray(self.HEADER_LENGTH + self.PONG_MESSAGE_LENGTH) buf = self.PONG_MESSAGE_BLOCK.build(buf, timestamp=timestamp) self._timestamp: Optional[int] = None super(PongMessage, self).__init__(msg_type=self.MESSAGE_TYPE, nonce=nonce, buf=buf, payload_length=self.PONG_MESSAGE_LENGTH) def __unpack(self) -> None: contents = self.PONG_MESSAGE_BLOCK.read(self._memoryview) self._nonce = contents.get("nonce") self._timestamp = contents.get("timestamp") def timestamp(self) -> Optional[int]: if self._timestamp is None: self.__unpack() return self._timestamp def __repr__(self) -> str: return "PongMessage<nonce: {},timestamp: {}>".format( self.nonce(), self.timestamp())
class VersionMessage(AbstractBloxrouteMessage): """ Bloxroute message that contains version info. """ BASE_LENGTH = (constants.STARTING_SEQUENCE_BYTES_LEN + constants.BX_HDR_COMMON_OFF + constants.VERSION_NUM_LEN + constants.NETWORK_NUM_LEN) VERSION_MESSAGE_BLOCK = PayloadBlock( AbstractBloxrouteMessage.HEADER_LENGTH, "VersionMessage", 0, PayloadElement(structure="<L", name="protocol_version"), PayloadElement(structure="<L", name="network_num")) VERSION_MESSAGE_LENGTH = VERSION_MESSAGE_BLOCK.size + constants.CONTROL_FLAGS_LEN def __init__(self, msg_type, payload_len, protocol_version, network_num, buf) -> None: if protocol_version is not None and network_num is not None: if len(buf) < self.BASE_LENGTH: raise ValueError("Version message is not long enough.") buf = self.VERSION_MESSAGE_BLOCK.build( buf, protocol_version=protocol_version, network_num=network_num) self._protocol_version = None self._network_num = None super(VersionMessage, self).__init__(msg_type, payload_len, buf) def __unpack(self): contents = self.VERSION_MESSAGE_BLOCK.read(self._memoryview) self._protocol_version = contents.get("protocol_version") self._network_num = contents.get("network_num") def protocol_version(self): if self._protocol_version is None: self.__unpack() return self._protocol_version def network_num(self): if self._network_num is None: self.__unpack() return self._network_num
def setUp(self): self.MESSAGE_BLOCK_HDR = PayloadBlock(0, "HDR", 0, PayloadElement(name="msg_type", structure="<12s",), PayloadElement(name="payload_len", structure="<L",) ) self.MESSAGE_BLOCK_VERSION = PayloadBlock(0, "VersionMessage", 0, self.MESSAGE_BLOCK_HDR, PayloadElement(structure="<L", name="protocol_version"), PayloadElement(structure="<L", name="network_num") ) self.MESSAGE_BLOCK_HELLO = PayloadBlock(0, "HelloMessage", 3, self.MESSAGE_BLOCK_VERSION, PayloadElement(name="node_id", structure="<16s", encode=lambda x: uuid_pack.to_bytes(x), decode=lambda x: uuid_pack.from_bytes(x)) ) self.kwargs = { "node_id": "31f93bcc-ad56-431f-9c14-28ffb0e8e41a", "msg_type": b"HelloMessage", "protocol_version": 3, "network_num": 12345 }
class HelloMessage(VersionMessage): """ BloXroute relay hello message type. node_id: the id of the node """ MESSAGE_TYPE = BloxrouteMessageType.HELLO HELLO_MESSAGE_BLOCK = PayloadBlock( VersionMessage.BASE_LENGTH, "HelloMessage", PROTOCOL_VERSION, PayloadElement( name="node_id", structure="%ss" % constants.NODE_ID_SIZE_IN_BYTES, encode=uuid_pack.to_bytes, decode=uuid_pack.from_bytes ) ) HELLO_MESSAGE_LENGTH = ( VersionMessage.VERSION_MESSAGE_BLOCK.size + HELLO_MESSAGE_BLOCK.size + constants.CONTROL_FLAGS_LEN ) # pyre-fixme[9]: node_id has type `str`; used as `None`. def __init__(self, protocol_version: Optional[int] = None, network_num: Optional[int] = None, node_id: str = None, # pyre-fixme[9]: buf has type `bytearray`; used as `None`. buf: bytearray = None): if buf is None: buf = bytearray(self.HEADER_LENGTH + self.HELLO_MESSAGE_LENGTH) buf = self.HELLO_MESSAGE_BLOCK.build(buf, node_id=node_id) self.buf = buf self._node_id = None self._network_num = None self._memoryview = memoryview(buf) super(HelloMessage, self).__init__(self.MESSAGE_TYPE, self.HELLO_MESSAGE_LENGTH, protocol_version, network_num, buf) def __unpack(self): contents = self.HELLO_MESSAGE_BLOCK.read(self._memoryview) self._node_id = contents.get("node_id") def node_id(self): if self._node_id is None: self.__unpack() return self._node_id
class KeepAliveMessage(AbstractBloxrouteMessage): """ BloXroute Version message that contains a message nonce to be used in the response. nonce: long, to be provided and managed by the connection """ KEEP_ALIVE_MESSAGE_BLOCK = PayloadBlock( AbstractBloxrouteMessage.HEADER_LENGTH, "ResponseMessage", PROTOCOL_VERSION, PayloadElement(name="nonce", structure="<Q", decode=lambda x: x or None), ) KEEP_ALIVE_MESSAGE_LENGTH = KEEP_ALIVE_MESSAGE_BLOCK.size + constants.CONTROL_FLAGS_LEN def __init__(self, msg_type: bytes, nonce: Optional[int] = None, buf: Optional[bytearray] = None, payload_length: Optional[int] = None) -> None: if payload_length is None: payload_length = self.KEEP_ALIVE_MESSAGE_LENGTH if buf is None: buf = bytearray(self.HEADER_LENGTH + payload_length) buf = self.KEEP_ALIVE_MESSAGE_BLOCK.build(buf, nonce=nonce) self.buf = buf self._nonce: Optional[int] = None self._network_num: Optional[int] = None self._memoryview = memoryview(buf) super(KeepAliveMessage, self).__init__(msg_type, payload_length, buf) def __unpack(self) -> None: contents = self.KEEP_ALIVE_MESSAGE_BLOCK.read(self._memoryview) self._nonce = contents.get("nonce") def nonce(self) -> int: if self._nonce is None: self.__unpack() nonce = self._nonce if nonce is None: return 0 return nonce
class HelloMessageV4(VersionMessageV4): """ BloXroute relay hello message type. node_id: the id of the node """ MESSAGE_TYPE = BloxrouteMessageType.HELLO HELLO_MESSAGE_BLOCK = PayloadBlock( VersionMessage.BASE_LENGTH, "HelloMessage", PROTOCOL_VERSION, PayloadElement(name="node_id", structure="%ss" % NODE_ID_SIZE_IN_BYTES, encode=lambda x: uuid_pack.to_bytes(x), decode=lambda x: uuid_pack.from_bytes(x))) HELLO_MESSAGE_LENGTH = VersionMessage.VERSION_MESSAGE_BLOCK.size + HELLO_MESSAGE_BLOCK.size def __init__(self, protocol_version=None, network_num=None, buf=None, node_id=None): if buf is None: buf = bytearray(BX_HDR_COMMON_OFF + self.HELLO_MESSAGE_LENGTH) buf = self.HELLO_MESSAGE_BLOCK.build(buf, node_id=node_id) self.buf = buf self._node_id = None self._network_num = None self._memoryview = memoryview(buf) super(HelloMessageV4, self).__init__(self.MESSAGE_TYPE, self.HELLO_MESSAGE_LENGTH, protocol_version, network_num, buf) def __unpack(self): contents = self.HELLO_MESSAGE_BLOCK.read(self._memoryview) self._node_id = contents.get("node_id") def node_id(self): if self._node_id is None: self.__unpack() return self._node_id