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
Beispiel #2
0
class PayloadBlockTests(AbstractTestCase):
    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
        }

    def test_hello_block_build_read(self):
        self.kwargs["payload_len"] = self.MESSAGE_BLOCK_HELLO.size - self.MESSAGE_BLOCK_HDR.size

        # build message
        buf = bytearray(self.MESSAGE_BLOCK_HELLO.size)
        self.MESSAGE_BLOCK_HELLO.build(buf=buf, **self.kwargs)

        # verify buffer
        msg_type, payload_len, protocol_version, network_num, node_id = struct.unpack_from("<12sLLL16s", buf)
        self.assertEqual(len(buf), self.MESSAGE_BLOCK_HELLO.size)
        self.assertEqual(msg_type, b"HelloMessage")
        self.assertEqual(payload_len, 24)
        self.assertEqual(protocol_version, 3)
        self.assertEqual(network_num, 12345)
        self.assertEqual(uuid_pack.from_bytes(node_id), "31f93bcc-ad56-431f-9c14-28ffb0e8e41a")

        # verify read
        result = self.MESSAGE_BLOCK_HELLO.read(buf)
        for item in self.MESSAGE_BLOCK_HELLO:
            self.assertEqual(result.pop(item.name), self.kwargs.pop(item.name))
        self.assertFalse(self.kwargs)  # check that all inputs were matched to the outputs
        self.assertFalse(result)  # check that all outputs were matched to the inputs
Beispiel #3
0
 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
     }
Beispiel #4
0
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
Beispiel #5
0
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
Beispiel #6
0
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())
Beispiel #7
0
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
Beispiel #8
0
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