예제 #1
0
    def test_receive_data_out_of_order(self):
        client_transport, _ = dummy_dtls_transport_pair()
        client = RTCSctpTransport(client_transport)
        client._last_received_tsn = 0

        # build chunks
        chunks = []

        chunk = DataChunk(flags=SCTP_DATA_FIRST_FRAG)
        chunk.user_data = b'foo'
        chunk.tsn = 1
        chunks.append(chunk)

        chunk = DataChunk()
        chunk.user_data = b'bar'
        chunk.tsn = 2
        chunks.append(chunk)

        chunk = DataChunk(flags=SCTP_DATA_LAST_FRAG)
        chunk.user_data = b'baz'
        chunk.tsn = 3
        chunks.append(chunk)

        # receive first chunk
        run(client._receive_chunk(chunks[0]))
        self.assertEqual(client._sack_needed, True)
        self.assertEqual(client._sack_duplicates, [])
        self.assertEqual(client._sack_misordered, set())
        self.assertEqual(client._last_received_tsn, 1)
        client._sack_needed = False

        # receive last chunk
        run(client._receive_chunk(chunks[2]))
        self.assertEqual(client._sack_needed, True)
        self.assertEqual(client._sack_duplicates, [])
        self.assertEqual(client._sack_misordered, set([3]))
        self.assertEqual(client._last_received_tsn, 1)
        client._sack_needed = False

        # receive middle chunk
        run(client._receive_chunk(chunks[1]))
        self.assertEqual(client._sack_needed, True)
        self.assertEqual(client._sack_duplicates, [])
        self.assertEqual(client._sack_misordered, set([]))
        self.assertEqual(client._last_received_tsn, 3)
        client._sack_needed = False

        # receive last chunk again
        run(client._receive_chunk(chunks[2]))
        self.assertEqual(client._sack_needed, True)
        self.assertEqual(client._sack_duplicates, [3])
        self.assertEqual(client._sack_misordered, set([]))
        self.assertEqual(client._last_received_tsn, 3)
        client._sack_needed = False
예제 #2
0
    def test_send_data_over_cwnd(self):
        async def mock_send_chunk(chunk):
            pass

        client_transport = DummyDtlsTransport()
        client = RTCSctpTransport(client_transport)
        client._send_chunk = mock_send_chunk
        client._ssthresh = 131072

        # STEP 1 - queue 4 chunks, but cwnd only allows 3
        run(client._send(123, 456, b'M' * USERDATA_MAX_LENGTH * 4))

        # T3 timer was started
        self.assertIsNotNone(client._t3_handle)

        self.assertEqual(len(client._outbound_queue), 4)
        self.assertEqual(client._outbound_queue_pos, 3)

        # STEP 2 - sack comes in acknowledging 2 chunks
        previous_timer = client._t3_handle
        sack = SackChunk()
        sack.cumulative_tsn = client._outbound_queue[1].tsn
        run(client._receive_chunk(sack))

        # T3 timer was restarted
        self.assertIsNotNone(client._t3_handle)
        self.assertNotEqual(client._t3_handle, previous_timer)

        self.assertEqual(len(client._outbound_queue), 2)
        self.assertEqual(client._outbound_queue_pos, 2)

        # STEP 3 - sack comes in acknowledging 2 more chunks
        sack = SackChunk()
        sack.cumulative_tsn = client._outbound_queue[1].tsn
        run(client._receive_chunk(sack))

        # T3 timer was stopped
        self.assertIsNone(client._t3_handle)

        self.assertEqual(len(client._outbound_queue), 0)
        self.assertEqual(client._outbound_queue_pos, 0)
예제 #3
0
    def test_receive_data(self):
        client_transport, _ = dummy_dtls_transport_pair()
        client = RTCSctpTransport(client_transport)
        client._last_received_tsn = 0

        # receive chunk
        chunk = DataChunk(flags=(SCTP_DATA_FIRST_FRAG | SCTP_DATA_LAST_FRAG))
        chunk.user_data = b'foo'
        chunk.tsn = 1
        run(client._receive_chunk(chunk))

        self.assertEqual(client._sack_needed, True)
        self.assertEqual(client._sack_duplicates, [])
        self.assertEqual(client._last_received_tsn, 1)
        client._sack_needed = False

        # receive chunk again
        run(client._receive_chunk(chunk))
        self.assertEqual(client._sack_needed, True)
        self.assertEqual(client._sack_duplicates, [1])
        self.assertEqual(client._last_received_tsn, 1)
예제 #4
0
    def test_receive_shutdown(self):
        async def mock_send_chunk(chunk):
            pass

        client_transport, _ = dummy_dtls_transport_pair()
        client = RTCSctpTransport(client_transport)
        client._last_received_tsn = 0
        client._send_chunk = mock_send_chunk
        client.state = RTCSctpTransport.State.ESTABLISHED

        # receive shutdown
        chunk = ShutdownChunk()
        chunk.cumulative_tsn = tsn_minus_one(client._last_sacked_tsn)
        run(client._receive_chunk(chunk))
        self.assertEqual(client.state,
                         RTCSctpTransport.State.SHUTDOWN_ACK_SENT)

        # receive shutdown complete
        chunk = ShutdownCompleteChunk()
        run(client._receive_chunk(chunk))
        self.assertEqual(client.state, RTCSctpTransport.State.CLOSED)
예제 #5
0
    def test_receive_sack_discard(self):
        client_transport, _ = dummy_dtls_transport_pair()
        client = RTCSctpTransport(client_transport)
        client._last_received_tsn = 0

        # receive sack
        sack_point = client._last_sacked_tsn
        chunk = SackChunk()
        chunk.cumulative_tsn = tsn_minus_one(sack_point)
        run(client._receive_chunk(chunk))

        # sack point must not changed
        self.assertEqual(client._last_sacked_tsn, sack_point)
예제 #6
0
    def test_receive_heartbeat(self):
        client_transport, server_transport = dummy_dtls_transport_pair()
        client = RTCSctpTransport(client_transport)
        client._last_received_tsn = 0
        client._remote_port = 5000

        # receive heartbeat
        chunk = HeartbeatChunk()
        chunk.params.append((1, b'\x01\x02\x03\x04'))
        chunk.tsn = 1
        run(client._receive_chunk(chunk))

        # check response
        data = run(server_transport.recv())
        packet = Packet.parse(data)
        self.assertEqual(len(packet.chunks), 1)
        self.assertTrue(isinstance(packet.chunks[0], HeartbeatAckChunk))
        self.assertEqual(packet.chunks[0].params, [(1, b'\x01\x02\x03\x04')])