def test_conn_build_packet_multi_v1(self):
        """
        build a packet with one new message and one old message
        """

        current_time = 0

        def clock():
            nonlocal current_time
            current_time += 1
            return current_time

        conn = ConnectionBase(False, None)
        conn.clock = clock
        conn.bitfield_pkt.current_seqnum = SeqNum(1234)
        conn.bitfield_pkt.bits = 0xAAAAAAAA
        conn.status = ConnectionStatus.CONNECTED
        conn.session_key_bytes = b"0" * 16

        payload1 = b"hello world1"
        conn.send(payload1)

        #_ = conn._build_packet()

        payload2 = b"hello world2"
        conn.send(payload2)

        pkt = conn._build_packet()

        self.assertEqual(PacketType.APP, pkt.hdr.pkt_type, pkt.hdr.pkt_type)
        self.assertEqual(2, pkt.hdr.count)
        self.assertEqual(
            Packet.overhead(2) + len(payload1) + len(payload2), pkt.hdr.length)
    def test_conn_build_packet_keep_alive(self):
        """
        build a keepalive packet if there is nothing else to send
        """

        conn = ConnectionBase(False, None)
        conn.status = ConnectionStatus.CONNECTED
        conn.bitfield_pkt.current_seqnum = SeqNum(1234)
        conn.bitfield_pkt.bits = 0xAAAAAAAA

        pkt = conn._build_packet()

        self.assertEqual(PacketType.KEEP_ALIVE, pkt.hdr.pkt_type)
    def test_conn_handle_first(self):
        """
        two packets are received in the correct sequential order
        """

        conn = ConnectionBase(False, None)
        conn.bitfield_pkt.insert(SeqNum(1))

        self.assertEqual(SeqNum(1), conn.bitfield_pkt.current_seqnum)
        self.assertEqual("0x0", hex(conn.bitfield_pkt.bits))
    def test_conn_handle_duplicate_acked(self):
        """
        a previously acked packet is received again
        """

        conn = ConnectionBase(False, None)
        conn.bitfield_pkt.current_seqnum = SeqNum(1234)
        conn.bitfield_pkt.bits = 0x8AAAAAAA
        with self.assertRaises(DuplicationError) as e:
            conn.bitfield_pkt.insert(SeqNum(1233))
    def test_conn_handle_duplicate_last(self):
        """
        the most recent packet is duplicated
        """

        conn = ConnectionBase(False, None)
        conn.bitfield_pkt.current_seqnum = SeqNum(1234)
        conn.bitfield_pkt.bits = 0x8AAAAAAA
        with self.assertRaises(DuplicationError) as e:
            conn.bitfield_pkt.insert(SeqNum(1234))
    def test_conn_receive_datagram_1(self):

        key = b"0" * 16
        hdr = PacketHeader.create(True, 0, PacketType.APP, SeqNum(1),
                                  SeqNum(1), 0)
        msgs = [
            PendingMessage(SeqNum(1), PacketType.APP, b"hello world1", None, 0)
        ]

        pkt = Packet.create(hdr, msgs)

        datagram = pkt.to_bytes(key)

        conn = ConnectionBase(False, None)
        conn.session_key_bytes = key

        conn._recv_datagram(PacketHeader.from_bytes(False, datagram), datagram)
        self.assertEqual(SeqNum(1), conn.bitfield_pkt.current_seqnum)
        self.assertEqual(1, len(conn.incoming_messages))
        self.assertEqual(msgs[0].payload, conn.incoming_messages[0][1])
    def test_conn_handle_seq_revered_order_2(self):
        """
        two packets are received in reversed order
        """

        conn = ConnectionBase(False, None)
        conn.bitfield_pkt.current_seqnum = SeqNum(1234)
        conn.bitfield_pkt.bits = 0x0AAAAAAA
        conn.bitfield_pkt.insert(SeqNum(1232))

        self.assertEqual(SeqNum(1234), conn.bitfield_pkt.current_seqnum)
        self.assertEqual("0x4aaaaaaa", hex(conn.bitfield_pkt.bits))
    def test_conn_handle_seq_sequential_32(self):
        """
        two packets are received in the correct sequential order
        """

        conn = ConnectionBase(False, None)
        conn.bitfield_pkt.current_seqnum = SeqNum(1233)
        conn.bitfield_pkt.bits = 0xAAAAAAAA
        conn.bitfield_pkt.insert(SeqNum(1265))

        self.assertEqual(SeqNum(1265), conn.bitfield_pkt.current_seqnum)
        self.assertEqual("0x1", hex(conn.bitfield_pkt.bits))
    def test_conn_handle_seq_out_of_order_33(self):
        """
        two packets are received out of order with more
        than 32 sequence numbers in between
        """

        conn = ConnectionBase(False, None)
        conn.bitfield_pkt.current_seqnum = SeqNum(1234)
        conn.bitfield_pkt.bits = 0x8AAAAAAA
        conn.bitfield_pkt.insert(SeqNum(1201))

        self.assertEqual(SeqNum(1234), conn.bitfield_pkt.current_seqnum)
        self.assertEqual("0x8aaaaaaa", hex(conn.bitfield_pkt.bits))
    def test_conn_build_packet_single(self):
        """
        build a packet with a single message
        """

        conn = ConnectionBase(False, None)
        conn.bitfield_pkt.current_seqnum = SeqNum(1234)
        conn.bitfield_pkt.bits = 0xAAAAAAAA
        conn.status = ConnectionStatus.CONNECTED
        conn.session_key_bytes = b"0" * 16

        payload = b"hello world"
        conn.send(payload)

        pkt = conn._build_packet()

        self.assertEqual(PacketType.APP, pkt.hdr.pkt_type)
        self.assertEqual(1, pkt.hdr.count)
        self.assertEqual(Packet.overhead(1) + len(payload), pkt.hdr.length)
        self.assertEqual(payload, pkt.msg[2:])
    def test_conn_send_datagram_simple(self):
        """
        """
        payload = b"hello world"
        conn = ConnectionBase(False, None)
        conn._send_type(PacketType.CLIENT_HELLO, payload, RetryMode.NONE, None)

        pkt = conn._build_packet()
        datagram = conn._encode_packet(pkt)

        self.assertEqual(
            PacketHeader.SIZE + PacketHeader.CRC_SIZE + Packet.overhead(1) +
            len(payload), len(datagram))

        hdr = PacketHeader.from_bytes(True, datagram)
        pkt = Packet.from_bytes(hdr, None, datagram)
        self.assertEqual(pkt.msg[2:], payload)
    def test_conn_send_retry_timeout(self):
        """
        """
        key = b"0" * 16
        payload = b"test"
        ctime = 0.0
        retry_delay = .150

        client = ConnectionBase(False, None)
        client.session_key_bytes = key
        client.status = ConnectionStatus.CONNECTED

        client.send(payload, retry=1)

        pkt1 = client._build_packet_impl(ctime, False, retry_delay)

        ctime += retry_delay + 1 / 60

        pkt2 = client._build_packet_impl(ctime, False, retry_delay)

        self.assertEqual(pkt1.msg, pkt2.msg)
        self.assertNotEqual(pkt1.hdr.seq, pkt2.hdr.seq)

        self.assertEqual(len(client.pending_retry), 2)

        client._handle_timeout(pkt1.hdr.seq)
        self.assertEqual(len(client.pending_retry), 1)

        client._handle_ack(pkt2.hdr.seq)
        self.assertEqual(len(client.pending_retry), 0)
    def test_conn_sendrecv_datagram_encrypted(self):
        """
        """
        key = b"0" * 16

        payload = b"hello world"
        client = ConnectionBase(False, None)
        client.session_key_bytes = key
        client.status = ConnectionStatus.CONNECTED

        server = ConnectionBase(True, None)
        server.session_key_bytes = key

        client.send(payload)

        pkt = client._build_packet()
        datagram = client._encode_packet(pkt)

        hdr = PacketHeader.from_bytes(True, datagram)
        server._recv_datagram(hdr, datagram)

        self.assertEqual(1, len(server.incoming_messages))
        self.assertEqual(payload, server.incoming_messages[0][1])