def test_stale_cookie(self): def mock_timestamp(): mock_timestamp.calls += 1 if mock_timestamp.calls == 1: return 0 else: return 61 mock_timestamp.calls = 0 client_transport, server_transport = dummy_dtls_transport_pair() client = RTCSctpTransport(client_transport) server = RTCSctpTransport(server_transport) server._get_timestamp = mock_timestamp 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.CLOSED) 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)
def test_abrupt_disconnect(self): """ Abrupt disconnect causes the __run() loop to exit. """ client_transport, server_transport = dummy_dtls_transport_pair() client = RTCSctpTransport(client_transport) server = RTCSctpTransport(server_transport) # 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) # break one connection run(client_transport.close()) run(asyncio.sleep(0.1)) self.assertEqual(client.state, RTCSctpTransport.State.CLOSED) # break other connection run(server_transport.close()) run(asyncio.sleep(0.1)) self.assertEqual(server.state, RTCSctpTransport.State.CLOSED) # try closing again run(client.stop()) run(server.stop())
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)
def test_abrupt_disconnect_2(self): """ Abrupt disconnect causes sending ABORT chunk to fail. """ client_transport, server_transport = dummy_dtls_transport_pair() client = RTCSctpTransport(client_transport) server = RTCSctpTransport(server_transport) # 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) # break connection run(client_transport.close()) run(server_transport.close()) # stop run(client.stop()) run(server.stop())
def test_connect_server_limits_streams(self): client_transport, server_transport = dummy_dtls_transport_pair() client = RTCSctpTransport(client_transport) self.assertFalse(client.is_server) server = RTCSctpTransport(server_transport) server.inbound_streams_max = 2048 server.outbound_streams = 256 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(client.inbound_streams, 256) self.assertEqual(client.outbound_streams, 2048) self.assertEqual(client._remote_extensions, [130]) self.assertEqual(server.state, RTCSctpTransport.State.ESTABLISHED) self.assertEqual(server.inbound_streams, 2048) self.assertEqual(server.outbound_streams, 256) self.assertEqual(server._remote_extensions, [130]) run(asyncio.sleep(0.5)) # shutdown run(client.stop()) run(server.stop()) self.assertEqual(client.state, RTCSctpTransport.State.CLOSED) self.assertEqual(server.state, RTCSctpTransport.State.CLOSED)
def test_connect_broken_transport(self): """ Transport with 100% loss never connects. """ client_transport, server_transport = dummy_dtls_transport_pair( loss=[True]) 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.CLOSED) 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)
def test_connect_then_server_creates_data_channel(self): client_transport, server_transport = dummy_dtls_transport_pair() client = RTCSctpTransport(client_transport) self.assertFalse(client.is_server) server = RTCSctpTransport(server_transport) self.assertTrue(server.is_server) client_channels = track_channels(client) server_channels = track_channels(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) # create data channel channel = RTCDataChannel(server, RTCDataChannelParameters(label='chat')) self.assertEqual(channel.id, None) self.assertEqual(channel.label, 'chat') run(asyncio.sleep(0.5)) self.assertEqual(len(client_channels), 1) self.assertEqual(client_channels[0].id, 0) self.assertEqual(client_channels[0].label, 'chat') self.assertEqual(len(server_channels), 0) # shutdown run(client.stop()) run(server.stop()) self.assertEqual(client.state, RTCSctpTransport.State.CLOSED) self.assertEqual(server.state, RTCSctpTransport.State.CLOSED)
def test_abort(self): client_transport, server_transport = dummy_dtls_transport_pair() client = RTCSctpTransport(client_transport) server = RTCSctpTransport(server_transport) # 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) # shutdown run(client._abort()) run(asyncio.sleep(0.5)) self.assertEqual(client.state, RTCSctpTransport.State.CLOSED) self.assertEqual(server.state, RTCSctpTransport.State.CLOSED)
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)
def test_connect_client_limits_streams(self): client_transport, server_transport = dummy_dtls_transport_pair() client = RTCSctpTransport(client_transport) client.inbound_streams_max = 2048 client.outbound_streams = 256 self.assertFalse(client.is_server) server = RTCSctpTransport(server_transport) 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(client.inbound_streams, 2048) self.assertEqual(client.outbound_streams, 256) self.assertEqual(client._remote_extensions, [130]) self.assertEqual(server.state, RTCSctpTransport.State.ESTABLISHED) self.assertEqual(server.inbound_streams, 256) self.assertEqual(server.outbound_streams, 2048) self.assertEqual(server._remote_extensions, [130]) # client requests additional outbound streams param = StreamAddOutgoingParam( request_sequence=client._reconfig_request_seq, new_streams=16) run(client._send_reconfig_param(param)) run(asyncio.sleep(0.5)) self.assertEqual(server.inbound_streams, 272) self.assertEqual(server.outbound_streams, 2048) # shutdown run(client.stop()) run(server.stop()) self.assertEqual(client.state, RTCSctpTransport.State.CLOSED) self.assertEqual(server.state, RTCSctpTransport.State.CLOSED)