Ejemplo 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)
Ejemplo n.º 2
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)
Ejemplo n.º 3
0
    def check_acks(self):
        with self.not_empty:
            while len(self.sent) == 0:
                self.not_empty.wait()

            item = self.sent[0]
            item.attempt += 1
            if item.attempt > ReliableManager.MaxResend:
                self.info(f"Expiring {item}")
                self.sent.remove(item)
                self.network.failed_send(item.header.destination)
                self.not_full.notify()
            else:
                self.info(f"Resending {item}")
                stream = BytesIO(item.buffer)
                network_header = NetworkHeader.decode(stream)
                network_header = dataclasses.replace(
                    network_header, identity=self.network.next_sequence())
                stream.seek(0)
                network_header.encode(stream)
                stream.seek(0)
                self.network.send(network_header, stream.read())
                # TODO backoff
            self.timer.reset()
Ejemplo n.º 4
0
    def process_incoming(self, payload: L2Payload):
        stream = BytesIO(payload.l3_data)

        try:
            network_header = NetworkHeader.decode(stream)
        except Exception as e:
            self.error(f"Could not decode network packet from {payload}.", e)
            return

        # Handle L3 protocols first
        if network_header.destination == self.our_address and network_header.protocol == Protocol.CONTROL:
            ctrl = ControlHeader.decode(stream)
            self.info(f"Got {ctrl} from {network_header.source}")
            if ctrl.control_type == ControlType.PING:
                self.ping_protocol.handle_ping(network_header, ctrl)
            else:
                self.warning(
                    f"Ignoring unsupported control packet: {ctrl.control_type}"
                )
            return

        if network_header.protocol == Protocol.HELLO:
            self.handle_hello(payload.link_id, network_header,
                              HelloHeader.decode(stream))
            return

        if network_header.protocol == Protocol.LINK_STATE:
            self.handle_advertisement(
                payload.link_id, network_header,
                LinkStateAdvertisementHeader.decode(stream))
            return

        if network_header.protocol == Protocol.LINK_STATE_QUERY:
            self.handle_query(payload.link_id, network_header,
                              LinkStateQueryHeader.decode(stream))
            return

        # Now decide if we should handle or drop
        if self.header_cache.contains(hash(network_header)):
            self.debug(f"Dropping duplicate {network_header}")
            return

        # If the packet is addressed to us, handle it
        if network_header.destination == self.our_address:
            self.debug(f"Handling {network_header}")
            self.l4_handlers.handle_l4(network_header, network_header.protocol,
                                       stream)
            return

        if network_header.destination == self.BroadcastAddress:
            self.debug(f"Handling broadcast {network_header}")
            self.l4_handlers.handle_l4(network_header, network_header.protocol,
                                       stream)
            if network_header.ttl > 1:
                # Decrease the TTL and re-broadcast on all links except where we heard it
                header_copy = dataclasses.replace(network_header,
                                                  ttl=network_header.ttl - 1)
                stream.seek(0)
                header_copy.encode(stream)
                stream.seek(0)
                self.send(header_copy,
                          stream.read(),
                          exclude_link_id=payload.link_id)
            else:
                self.debug("Not re-broadcasting due to TTL")
        else:
            header_copy = dataclasses.replace(network_header,
                                              ttl=network_header.ttl - 1)
            stream.seek(0)
            header_copy.encode(stream)
            stream.seek(0)
            self.send(header_copy,
                      stream.read(),
                      exclude_link_id=payload.link_id)