예제 #1
0
    def test_bad_cookie(self):
        client_transport, server_transport = dummy_dtls_transport_pair()
        client = RTCSctpTransport(client_transport)
        server = RTCSctpTransport(server_transport)

        # corrupt cookie
        real_send_chunk = client._send_chunk

        async def mock_send_chunk(chunk):
            if isinstance(chunk, CookieEchoChunk):
                chunk.body = b'garbage'
            return await real_send_chunk(chunk)

        client._send_chunk = mock_send_chunk

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

        # check outcome
        run(asyncio.sleep(0.5))
        self.assertEqual(client.state, RTCSctpTransport.State.COOKIE_ECHOED)
        self.assertEqual(server.state, RTCSctpTransport.State.CLOSED)

        # shutdown
        run(client.stop())
        run(server.stop())
        self.assertEqual(client.state, RTCSctpTransport.State.CLOSED)
        self.assertEqual(server.state, RTCSctpTransport.State.CLOSED)
예제 #2
0
    def test_t2_expired_when_shutdown_sent(self):
        async def mock_send_chunk(chunk):
            pass

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

        chunk = ShutdownChunk()

        # fails once
        client.state = RTCSctpTransport.State.SHUTDOWN_SENT
        client._t2_start(chunk)
        client._t2_expired()
        self.assertEqual(client._t2_failures, 1)
        self.assertIsNotNone(client._t2_handle)
        self.assertEqual(client.state, RTCSctpTransport.State.SHUTDOWN_SENT)

        # fails 10 times
        client._t2_failures = 9
        client._t2_expired()
        self.assertEqual(client._t2_failures, 10)
        self.assertIsNotNone(client._t2_handle)
        self.assertEqual(client.state, RTCSctpTransport.State.SHUTDOWN_SENT)

        # fails 11 times
        client._t2_expired()
        self.assertEqual(client._t2_failures, 11)
        self.assertIsNone(client._t2_handle)
        self.assertEqual(client.state, RTCSctpTransport.State.CLOSED)
예제 #3
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))
예제 #4
0
    def test_send_sack(self):
        sack = None

        async def mock_send_chunk(c):
            nonlocal sack
            sack = c

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

        run(client._send_sack())
        self.assertIsNotNone(sack)
        self.assertEqual(sack.duplicates, [])
        self.assertEqual(sack.gaps, [])
        self.assertEqual(sack.cumulative_tsn, 123)
예제 #5
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)
예제 #6
0
    def test_send_sack_with_gaps(self):
        sack = None

        async def mock_send_chunk(c):
            nonlocal sack
            sack = c

        client_transport = DummyDtlsTransport()
        client = RTCSctpTransport(client_transport)
        client._last_received_tsn = 12
        client._sack_misordered = [14, 15, 17]
        client._send_chunk = mock_send_chunk

        run(client._send_sack())
        self.assertIsNotNone(sack)
        self.assertEqual(sack.duplicates, [])
        self.assertEqual(sack.gaps, [(2, 3), (5, 5)])
        self.assertEqual(sack.cumulative_tsn, 12)
예제 #7
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)
예제 #8
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)