Exemplo n.º 1
0
    def test_encode_decode_fragment(self):
        msg = "Hello, World!".encode("utf-8")
        datagram1 = DatagramHeader(source=100,
                                   destination=100,
                                   length=len(msg),
                                   checksum=crc_b(msg))

        fragment1 = FragmentHeader(Protocol.DATAGRAM, FragmentFlags.NONE, 0,
                                   99)

        header1 = NetworkHeader(version=0,
                                protocol=Protocol.FRAGMENT,
                                qos=QoS.Default,
                                ttl=4,
                                identity=42,
                                length=fragment1.size() + datagram1.size() +
                                len(msg),
                                source=MeshAddress(1),
                                destination=MeshAddress(2))

        stream = BytesIO()
        header1.encode(stream)
        fragment1.encode(stream)
        datagram1.encode(stream)
        stream.write(msg)
        stream.seek(0)

        header2 = NetworkHeader.decode(stream)
        fragment = FragmentHeader.decode(stream)
        datagram = DatagramHeader.decode(stream)
        msg2 = stream.read()
        self.assertEqual(header1, header2)
        self.assertEqual(datagram1, datagram)
        self.assertEqual(msg2, msg)
Exemplo n.º 2
0
    def handle_l4(self, network_header: NetworkHeader, stream: BytesIO):
        fragment_header = FragmentHeader.decode(stream)
        fragment = Fragment(network_header, fragment_header, stream.read())

        source = fragment.network_header.source
        dest = fragment.network_header.destination
        protocol = fragment.fragment_header.protocol

        # Only Datagram allowed inside fragments (for now)
        if protocol != Protocol.DATAGRAM:
            self.warning(
                f"Dropping fragment for unsupport protocol {protocol}")

        # The sequence minus fragment is same for all fragments in a given PDU
        base_seq = (
            MeshProtocol.WindowSize + fragment.fragment_header.sequence -
            fragment.fragment_header.fragment) % MeshProtocol.WindowSize

        # Buffer the incoming frame and see if it completes a whole segment
        self.buffer[source][base_seq].append(fragment)

        fragments = self.buffer[source][base_seq]
        sorted_fragments = sorted(
            fragments, key=operator.attrgetter("fragment_header.fragment"))
        has_more = sorted_fragments[
            -1].fragment_header.flags & FragmentFlags.FRAGMENT
        have_all = len(
            fragments) == sorted_fragments[-1].fragment_header.fragment + 1
        if not has_more and have_all:
            del self.buffer[source][base_seq]
            joined = BytesIO()
            for fragment in sorted_fragments:
                if fragment.network_header.source == source and \
                        fragment.network_header.destination == dest and \
                        fragment.fragment_header.protocol == protocol:
                    joined.write(fragment.payload)
                else:
                    # Fragment consistency error
                    raise RuntimeError(
                        "Fragment consistency error, header fields do not match"
                    )
            joined.seek(0)
            datagram_header = DatagramHeader.decode(joined)
            payload = joined.read()
            self.datagram_manager.handle_datagram(
                Datagram(fragment.network_header, datagram_header, payload))
Exemplo n.º 3
0
    def test_encode_decode_datagram(self):
        msg = "Hello, World!".encode("utf-8")
        datagram_header_1 = DatagramHeader(source=100,
                                           destination=100,
                                           length=len(msg),
                                           checksum=crc_b(msg))

        header1 = NetworkHeader(version=0,
                                protocol=Protocol.DATAGRAM,
                                qos=QoS.Default,
                                ttl=4,
                                identity=42,
                                length=datagram_header_1.size() + len(msg),
                                source=MeshAddress(1),
                                destination=MeshAddress(2))

        data = encode_packet(header1, [datagram_header_1], msg)
        stream = BytesIO(data)
        header2 = NetworkHeader.decode(stream)
        datagram2 = DatagramHeader.decode(stream)
        self.assertEqual(header1, header2)
        self.assertEqual(datagram_header_1, datagram2)
 def handle_l4(self, network_header: NetworkHeader,
               stream: BytesIO):
     nonlocal captured
     DatagramHeader.decode(stream)
     captured = stream.read()
Exemplo n.º 5
0
 def handle_l4(self, network_header: NetworkHeader, stream: BytesIO):
     datagram_header = DatagramHeader.decode(stream)
     self.datagram_manager.handle_datagram(
         Datagram(network_header, datagram_header, stream.read()))