Example #1
0
    def test_t3_expired(self):
        async def mock_send_chunk(chunk):
            pass

        async def mock_transmit():
            pass

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

        # 1 chunk
        run(client._send(123, 456, b'M' * USERDATA_MAX_LENGTH))
        self.assertIsNotNone(client._t3_handle)
        self.assertEqual(len(client._outbound_queue), 1)
        self.assertEqual(client._outbound_queue_pos, 1)

        # t3 expires
        client._transmit = mock_transmit
        client._t3_expired()
        self.assertIsNone(client._t3_handle)
        self.assertEqual(len(client._outbound_queue), 1)
        self.assertEqual(client._outbound_queue_pos, 0)

        # let async code complete
        run(asyncio.sleep(0))
Example #2
0
    def test_send_data(self):
        async def mock_send_chunk(chunk):
            pass

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

        # no data
        run(client._transmit())
        self.assertIsNone(client._t3_handle)
        self.assertEqual(client._outbound_queue_pos, 0)

        # 1 chunk
        run(client._send(123, 456, b'M' * USERDATA_MAX_LENGTH))
        self.assertIsNotNone(client._t3_handle)
        self.assertEqual(len(client._outbound_queue), 1)
        self.assertEqual(client._outbound_queue_pos, 1)
Example #3
0
    def test_connect_lossy_transport(self):
        """
        Transport with 25% loss eventually connects.
        """
        client_transport, server_transport = dummy_dtls_transport_pair(
            loss=[True, False, False, False])

        client = RTCSctpTransport(client_transport)
        client._rto = 0.1
        self.assertFalse(client.is_server)
        server = RTCSctpTransport(server_transport)
        server._rto = 0.1
        self.assertTrue(server.is_server)

        # connect
        server.start(client.getCapabilities(), client.port)
        client.start(server.getCapabilities(), server.port)

        # check outcome
        run(wait_for_outcome(client, server))
        self.assertEqual(client.state, RTCSctpTransport.State.ESTABLISHED)
        self.assertEqual(server.state, RTCSctpTransport.State.ESTABLISHED)

        # transmit data
        server_queue = asyncio.Queue()

        async def server_fake_receive(*args):
            await server_queue.put(args)

        server._receive = server_fake_receive

        for i in range(20):
            message = (123, i, b'ping')
            run(client._send(*message))
            received = run(server_queue.get())
            self.assertEqual(received, message)

        # shutdown
        run(client.stop())
        run(server.stop())
        self.assertEqual(client.state, RTCSctpTransport.State.CLOSED)
        self.assertEqual(server.state, RTCSctpTransport.State.CLOSED)
Example #4
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)