Use a packet structure to wrap raw data
Signed-off-by: Yohann D'ANELLO <ynerant@crans.org>
This commit is contained in:
		@@ -48,10 +48,79 @@ class Squinnondation:
 | 
			
		||||
 | 
			
		||||
        while True:
 | 
			
		||||
            data, addr = squirrel.receive_raw_data()
 | 
			
		||||
            print("received message: %s" % data)
 | 
			
		||||
            pkt = Packet.unmarshal(data)
 | 
			
		||||
            print("received message: %d %d %d %s" % (pkt.magic, pkt.version, pkt.body_length, pkt.body.raw_data))
 | 
			
		||||
            print(str(pkt.marshal()))
 | 
			
		||||
            # squirrel.send_raw_data(hazelnut, b"Hello squirrel!")
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class TLV:
 | 
			
		||||
    """
 | 
			
		||||
    The Tag-Length-Value contains the different type of data that can be sent.
 | 
			
		||||
    TODO: add subclasses for each type of TLV
 | 
			
		||||
    """
 | 
			
		||||
    type: int
 | 
			
		||||
    raw_data: bytes
 | 
			
		||||
 | 
			
		||||
    def validate_data(self) -> bool:
 | 
			
		||||
        """
 | 
			
		||||
        Ensure that the TLV is well-formed.
 | 
			
		||||
        Raises a ValueError if it is not the case.
 | 
			
		||||
        TODO: Make some tests
 | 
			
		||||
        """
 | 
			
		||||
        return True
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class Packet:
 | 
			
		||||
    """
 | 
			
		||||
    A Packet is a wrapper around the
 | 
			
		||||
    """
 | 
			
		||||
    magic: int
 | 
			
		||||
    version: int
 | 
			
		||||
    body_length: int
 | 
			
		||||
    body: TLV
 | 
			
		||||
 | 
			
		||||
    def validate_data(self) -> bool:
 | 
			
		||||
        """
 | 
			
		||||
        Ensure that the packet is well-formed.
 | 
			
		||||
        Raises a ValueError if the packet contains bad data.
 | 
			
		||||
        """
 | 
			
		||||
        if self.magic != 95:
 | 
			
		||||
            raise ValueError("The magic code of the packet must be 95, found: {:d}".format(self.magic))
 | 
			
		||||
        if self.version != 0:
 | 
			
		||||
            raise ValueError("The version of the packet is not supported: {:d}".format(self.version))
 | 
			
		||||
        if not (0 <= self.body_length <= 120):
 | 
			
		||||
            raise ValueError("The body length of the packet is negative or too high. It must be between 0 and 1020,"
 | 
			
		||||
                             "found: {:d}".format(self.body_length))
 | 
			
		||||
        return self.body.validate_data()
 | 
			
		||||
 | 
			
		||||
    @staticmethod
 | 
			
		||||
    def unmarshal(data: bytes) -> "Packet":
 | 
			
		||||
        """
 | 
			
		||||
        Read raw data and build the packet wrapper.
 | 
			
		||||
        Raises a ValueError whenever the data is invalid.
 | 
			
		||||
        """
 | 
			
		||||
        pkt = Packet()
 | 
			
		||||
        pkt.magic = data[0]
 | 
			
		||||
        pkt.version = data[1]
 | 
			
		||||
        pkt.body_length = int.from_bytes(data[2:4], byteorder="big")
 | 
			
		||||
        pkt.body = TLV()
 | 
			
		||||
        pkt.body.raw_data = data[4:4+pkt.body_length]
 | 
			
		||||
 | 
			
		||||
        pkt.validate_data()
 | 
			
		||||
 | 
			
		||||
        return pkt
 | 
			
		||||
 | 
			
		||||
    def marshal(self) -> bytes:
 | 
			
		||||
        """
 | 
			
		||||
        Compute the byte array data associated to the packet.
 | 
			
		||||
        """
 | 
			
		||||
        data = bytes([self.magic, self.version])
 | 
			
		||||
        data += self.body_length.to_bytes(2, "big")
 | 
			
		||||
        data += self.body.raw_data
 | 
			
		||||
        return data
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class Hazelnut:
 | 
			
		||||
    """
 | 
			
		||||
    A hazelnut is a connected client, with its socket.
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user