Пример #1
0
    def test_handshake_error(
        self, mock_err_get_error, mock_ssl_get_error, mock_do_handshake
    ):
        mock_err_get_error.side_effect = [0x2006D080, 0, 0]
        mock_ssl_get_error.return_value = 1
        mock_do_handshake.return_value = -1

        transport1, transport2 = dummy_ice_transport_pair()

        certificate1 = RTCCertificate.generateCertificate()
        session1 = RTCDtlsTransport(transport1, [certificate1])

        certificate2 = RTCCertificate.generateCertificate()
        session2 = RTCDtlsTransport(transport2, [certificate2])

        run(
            asyncio.gather(
                session1.start(session2.getLocalParameters()),
                session2.start(session1.getLocalParameters()),
            )
        )
        self.assertEqual(session1.state, "failed")
        self.assertEqual(session2.state, "failed")

        run(session1.stop())
        run(session2.stop())
Пример #2
0
    def test_abrupt_disconnect(self):
        transport1, transport2 = dummy_ice_transport_pair()

        certificate1 = RTCCertificate.generateCertificate()
        session1 = RTCDtlsTransport(transport1, [certificate1])

        certificate2 = RTCCertificate.generateCertificate()
        session2 = RTCDtlsTransport(transport2, [certificate2])

        run(
            asyncio.gather(
                session1.start(session2.getLocalParameters()),
                session2.start(session1.getLocalParameters()),
            )
        )

        # break connections -> tasks exits
        run(transport1.stop())
        run(transport2.stop())

        # close DTLS
        run(session1.stop())
        run(session2.stop())

        # check outcome
        self.assertEqual(session1.state, "closed")
        self.assertEqual(session2.state, "closed")
Пример #3
0
    def test_abrupt_disconnect_during_recv(self):
        transport1, transport2 = dummy_ice_transport_pair()

        certificate1 = RTCCertificate.generateCertificate()
        session1 = RTCDtlsTransport(transport1, [certificate1])

        certificate2 = RTCCertificate.generateCertificate()
        session2 = RTCDtlsTransport(transport2, [certificate2])

        run(
            asyncio.gather(session1.start(session2.getLocalParameters()),
                           session2.start(session1.getLocalParameters())))

        # break one connection
        with self.assertRaises(ConnectionError):
            run(asyncio.gather(session1.data.recv(), transport1.stop()))
        self.assertEqual(session1.state, 'closed')

        # break other connection
        with self.assertRaises(ConnectionError):
            run(asyncio.gather(session2.data.recv(), transport2.stop()))
        self.assertEqual(session2.state, 'closed')

        # try closing again
        run(session1.stop())
        run(session2.stop())
Пример #4
0
    def test_bad_client_fingerprint(self):
        transport1, transport2 = dummy_ice_transport_pair()

        certificate1 = RTCCertificate.generateCertificate()
        session1 = RTCDtlsTransport(transport1, [certificate1])

        certificate2 = RTCCertificate.generateCertificate()
        session2 = RTCDtlsTransport(transport2, [certificate2])

        bogus_parameters = RTCDtlsParameters(
            fingerprints=[
                RTCDtlsFingerprint(algorithm="sha-256", value="bogus_fingerprint")
            ]
        )
        run(
            asyncio.gather(
                session1.start(bogus_parameters),
                session2.start(session1.getLocalParameters()),
            )
        )
        self.assertEqual(session1.state, "failed")
        self.assertEqual(session2.state, "connected")

        run(session1.stop())
        run(session2.stop())
Пример #5
0
    async def test_abrupt_disconnect_2(self):
        transport1, transport2 = dummy_ice_transport_pair()

        certificate1 = RTCCertificate.generateCertificate()
        session1 = RTCDtlsTransport(transport1, [certificate1])

        certificate2 = RTCCertificate.generateCertificate()
        session2 = RTCDtlsTransport(transport2, [certificate2])

        await asyncio.gather(
            session1.start(session2.getLocalParameters()),
            session2.start(session1.getLocalParameters()),
        )

        def fake_write_ssl():
            raise ConnectionError

        session1._write_ssl = fake_write_ssl

        # close DTLS -> ConnectionError
        await session1.stop()
        await session2.stop()
        await asyncio.sleep(0.1)

        # check outcome
        self.assertEqual(session1.state, "closed")
        self.assertEqual(session2.state, "closed")
Пример #6
0
    def test_rtp_malformed(self):
        transport1, transport2 = dummy_ice_transport_pair()

        certificate1 = RTCCertificate.generateCertificate()
        session1 = RTCDtlsTransport(transport1, [certificate1])

        # receive truncated RTP
        run(session1._handle_rtp_data(RTP[0:8], 0))

        # receive truncated RTCP
        run(session1._handle_rtcp_data(RTCP[0:8]))
Пример #7
0
    def test_lossy_channel(self):
        transport1, transport2 = dummy_ice_transport_pair(loss=0.3)

        certificate1 = RTCCertificate.generateCertificate()
        session1 = RTCDtlsTransport(transport1, [certificate1])

        certificate2 = RTCCertificate.generateCertificate()
        session2 = RTCDtlsTransport(transport2, [certificate2])

        run(
            asyncio.gather(session1.start(session2.getLocalParameters()),
                           session2.start(session1.getLocalParameters())))

        run(session1.stop())
        run(session2.stop())
Пример #8
0
def dummy_dtls_transport_pair():
    ice_a, ice_b = dummy_ice_transport_pair()
    dtls_a = RTCDtlsTransport(ice_a, [RTCCertificate.generateCertificate()])
    dtls_b = RTCDtlsTransport(ice_b, [RTCCertificate.generateCertificate()])
    run(
        asyncio.gather(dtls_b.start(dtls_a.getLocalParameters()),
                       dtls_a.start(dtls_b.getLocalParameters())))
    return (dtls_a, dtls_b)
Пример #9
0
    def test_broken_ssl(self, mock_use_certificate):
        mock_use_certificate.return_value = 0

        transport1, transport2 = dummy_ice_transport_pair()

        certificate = RTCCertificate.generateCertificate()
        with self.assertRaises(DtlsError):
            RTCDtlsTransport(transport1, [certificate])
Пример #10
0
    def test_lossy_channel(self):
        """
        Transport with 25% loss eventually connects.
        """
        transport1, transport2 = dummy_ice_transport_pair(loss=[True, False, False, False])

        certificate1 = RTCCertificate.generateCertificate()
        session1 = RTCDtlsTransport(transport1, [certificate1])

        certificate2 = RTCCertificate.generateCertificate()
        session2 = RTCDtlsTransport(transport2, [certificate2])

        run(asyncio.gather(
            session1.start(session2.getLocalParameters()),
            session2.start(session1.getLocalParameters())))

        run(session1.stop())
        run(session2.stop())
Пример #11
0
async def dummy_dtls_transport_pair():
    ice_a, ice_b = dummy_ice_transport_pair()
    dtls_a = RTCDtlsTransport(ice_a, [RTCCertificate.generateCertificate()])
    dtls_b = RTCDtlsTransport(ice_b, [RTCCertificate.generateCertificate()])
    await asyncio.gather(
        dtls_b.start(dtls_a.getLocalParameters()),
        dtls_a.start(dtls_b.getLocalParameters()),
    )

    try:
        yield (dtls_a, dtls_b)
    finally:
        await dtls_a.stop()
        await dtls_b.stop()
Пример #12
0
    def test_handshake_error(self, mock_get_error, mock_do_handshake):
        mock_get_error.return_value = 1
        mock_do_handshake.return_value = -1

        transport1, transport2 = dummy_ice_transport_pair()

        certificate1 = RTCCertificate.generateCertificate()
        session1 = RTCDtlsTransport(transport1, [certificate1])

        certificate2 = RTCCertificate.generateCertificate()
        session2 = RTCDtlsTransport(transport2, [certificate2])

        with self.assertRaises(DtlsError) as cm:
            run(
                asyncio.gather(session1.start(session2.getLocalParameters()),
                               session2.start(session1.getLocalParameters())))
        self.assertEqual(str(cm.exception), 'DTLS handshake failed (error 1)')
        self.assertEqual(session1.state, 'failed')
        self.assertEqual(session2.state, 'failed')

        run(session1.stop())
        run(session2.stop())
Пример #13
0
    def test_bad_client_fingerprint(self):
        transport1, transport2 = dummy_ice_transport_pair()

        certificate1 = RTCCertificate.generateCertificate()
        session1 = RTCDtlsTransport(transport1, [certificate1])

        certificate2 = RTCCertificate.generateCertificate()
        session2 = RTCDtlsTransport(transport2, [certificate2])

        bogus_parameters = RTCDtlsParameters(
            fingerprints=[RTCDtlsFingerprint(algorithm='sha-256', value='bogus_fingerprint')])
        with self.assertRaises(DtlsError) as cm:
            run(asyncio.gather(
                session1.start(bogus_parameters),
                session2.start(session1.getLocalParameters())))
        self.assertEqual(str(cm.exception), 'DTLS fingerprint does not match')
        self.assertEqual(session1.state, 'failed')
        self.assertEqual(session2.state, 'connecting')

        run(session1.stop())
        run(session2.stop())
Пример #14
0
    async def test_lossy_channel(self):
        """
        Transport with 25% loss eventually connects.
        """
        transport1, transport2 = dummy_ice_transport_pair()
        loss_pattern = [True, False, False, False]
        transport1._connection.loss_pattern = loss_pattern
        transport2._connection.loss_pattern = loss_pattern

        certificate1 = RTCCertificate.generateCertificate()
        session1 = RTCDtlsTransport(transport1, [certificate1])

        certificate2 = RTCCertificate.generateCertificate()
        session2 = RTCDtlsTransport(transport2, [certificate2])

        await asyncio.gather(
            session1.start(session2.getLocalParameters()),
            session2.start(session1.getLocalParameters()),
        )

        await session1.stop()
        await session2.stop()
Пример #15
0
    def test_data(self):
        transport1, transport2 = dummy_ice_transport_pair()

        certificate1 = RTCCertificate.generateCertificate()
        session1 = RTCDtlsTransport(transport1, [certificate1])

        certificate2 = RTCCertificate.generateCertificate()
        session2 = RTCDtlsTransport(transport2, [certificate2])

        run(
            asyncio.gather(session1.start(session2.getLocalParameters()),
                           session2.start(session1.getLocalParameters())))

        # send encypted data
        run(session1.data.send(b'ping'))
        data = run(session2.data.recv())
        self.assertEqual(data, b'ping')

        run(session2.data.send(b'pong'))
        data = run(session1.data.recv())
        self.assertEqual(data, b'pong')

        # shutdown
        run(session1.stop())
        run(asyncio.sleep(0.5))
        self.assertEqual(session1.state, 'closed')
        self.assertEqual(session2.state, 'closed')

        # try closing again
        run(session1.stop())
        run(session2.stop())

        # try receving after close
        with self.assertRaises(ConnectionError):
            run(session1.data.recv())

        # try sending after close
        with self.assertRaises(ConnectionError):
            run(session1.data.send(b'foo'))
Пример #16
0
 def test_broken_ssl(self, mock_use_certificate):
     mock_use_certificate.return_value = 0
     certificate = RTCCertificate.generateCertificate()
     with self.assertRaises(DtlsError):
         RTCDtlsTransport(None, [certificate])
Пример #17
0
    def test_srtp_unprotect_error(self):
        transport1, transport2 = dummy_ice_transport_pair()

        certificate1 = RTCCertificate.generateCertificate()
        session1 = RTCDtlsTransport(transport1, [certificate1])
        receiver1 = DummyRtpReceiver()
        session1._register_rtp_receiver(
            receiver1,
            RTCRtpParameters(rtcp=RTCRtcpParameters(ssrc=1831097322)))

        certificate2 = RTCCertificate.generateCertificate()
        session2 = RTCDtlsTransport(transport2, [certificate2])
        receiver2 = DummyRtpReceiver()
        session2._register_rtp_receiver(
            receiver2,
            RTCRtpParameters(rtcp=RTCRtcpParameters(ssrc=4028317929)))

        run(
            asyncio.gather(session1.start(session2.getLocalParameters()),
                           session2.start(session1.getLocalParameters())))

        # send same RTP twice, to trigger error on the receiver side:
        # "replay check failed (bad index)"
        run(session1._send_rtp(RTP))
        run(session1._send_rtp(RTP))
        run(asyncio.sleep(0.5))
        self.assertEqual(len(receiver2.rtcp_packets), 0)
        self.assertEqual(len(receiver2.rtp_packets), 1)

        # shutdown
        run(session1.stop())
        run(session2.stop())
Пример #18
0
    def test_rtp(self):
        transport1, transport2 = dummy_ice_transport_pair()

        certificate1 = RTCCertificate.generateCertificate()
        session1 = RTCDtlsTransport(transport1, [certificate1])
        receiver1 = DummyRtpReceiver()
        session1._register_rtp_receiver(
            receiver1,
            RTCRtpParameters(rtcp=RTCRtcpParameters(ssrc=1831097322)))

        certificate2 = RTCCertificate.generateCertificate()
        session2 = RTCDtlsTransport(transport2, [certificate2])
        receiver2 = DummyRtpReceiver()
        session2._register_rtp_receiver(
            receiver2,
            RTCRtpParameters(rtcp=RTCRtcpParameters(ssrc=4028317929)))

        run(
            asyncio.gather(session1.start(session2.getLocalParameters()),
                           session2.start(session1.getLocalParameters())))

        # send RTP
        run(session1._send_rtp(RTP))
        run(asyncio.sleep(0.1))
        self.assertEqual(len(receiver2.rtcp_packets), 0)
        self.assertEqual(len(receiver2.rtp_packets), 1)

        # send RTCP
        run(session2._send_rtp(RTCP))
        run(asyncio.sleep(0.1))
        self.assertEqual(len(receiver1.rtcp_packets), 1)
        self.assertEqual(len(receiver1.rtp_packets), 0)

        # shutdown
        run(session1.stop())
        run(asyncio.sleep(0.5))
        self.assertEqual(session1.state, 'closed')
        self.assertEqual(session2.state, 'closed')

        # try closing again
        run(session1.stop())
        run(session2.stop())

        # try sending after close
        with self.assertRaises(ConnectionError):
            run(session1._send_rtp(RTP))
Пример #19
0
    def test_data(self):
        transport1, transport2 = dummy_ice_transport_pair()

        certificate1 = RTCCertificate.generateCertificate()
        session1 = RTCDtlsTransport(transport1, [certificate1])
        receiver1 = DummyDataReceiver()
        session1._register_data_receiver(receiver1)

        certificate2 = RTCCertificate.generateCertificate()
        session2 = RTCDtlsTransport(transport2, [certificate2])
        receiver2 = DummyDataReceiver()
        session2._register_data_receiver(receiver2)

        run(
            asyncio.gather(session1.start(session2.getLocalParameters()),
                           session2.start(session1.getLocalParameters())))

        # send encypted data
        run(session1._send_data(b'ping'))
        run(asyncio.sleep(0.1))
        self.assertEqual(receiver2.data, [b'ping'])

        run(session2._send_data(b'pong'))
        run(asyncio.sleep(0.1))
        self.assertEqual(receiver1.data, [b'pong'])

        # shutdown
        run(session1.stop())
        run(asyncio.sleep(0.5))
        self.assertEqual(session1.state, 'closed')
        self.assertEqual(session2.state, 'closed')

        # try closing again
        run(session1.stop())
        run(session2.stop())

        # try sending after close
        with self.assertRaises(ConnectionError):
            run(session1._send_data(b'foo'))
Пример #20
0
    def test_srtp_unprotect_error(self):
        transport1, transport2 = dummy_ice_transport_pair()

        certificate1 = RTCCertificate.generateCertificate()
        session1 = RTCDtlsTransport(transport1, [certificate1])
        receiver1 = DummyRtpReceiver()
        session1._register_rtp_receiver(
            receiver1,
            RTCRtpReceiveParameters(
                codecs=[
                    RTCRtpCodecParameters(
                        mimeType="audio/PCMU", clockRate=8000, payloadType=0
                    )
                ],
                encodings=[RTCRtpDecodingParameters(ssrc=1831097322, payloadType=0)],
            ),
        )

        certificate2 = RTCCertificate.generateCertificate()
        session2 = RTCDtlsTransport(transport2, [certificate2])
        receiver2 = DummyRtpReceiver()
        session2._register_rtp_receiver(
            receiver2,
            RTCRtpReceiveParameters(
                codecs=[
                    RTCRtpCodecParameters(
                        mimeType="audio/PCMU", clockRate=8000, payloadType=0
                    )
                ],
                encodings=[RTCRtpDecodingParameters(ssrc=4028317929, payloadType=0)],
            ),
        )

        run(
            asyncio.gather(
                session1.start(session2.getLocalParameters()),
                session2.start(session1.getLocalParameters()),
            )
        )

        # send same RTP twice, to trigger error on the receiver side:
        # "replay check failed (bad index)"
        run(session1._send_rtp(RTP))
        run(session1._send_rtp(RTP))
        run(asyncio.sleep(0.1))
        self.assertEqual(len(receiver2.rtcp_packets), 0)
        self.assertEqual(len(receiver2.rtp_packets), 1)

        # shutdown
        run(session1.stop())
        run(session2.stop())
Пример #21
0
    async def test_data(self):
        transport1, transport2 = dummy_ice_transport_pair()

        certificate1 = RTCCertificate.generateCertificate()
        session1 = RTCDtlsTransport(transport1, [certificate1])
        receiver1 = DummyDataReceiver()
        session1._register_data_receiver(receiver1)

        certificate2 = RTCCertificate.generateCertificate()
        session2 = RTCDtlsTransport(transport2, [certificate2])
        receiver2 = DummyDataReceiver()
        session2._register_data_receiver(receiver2)

        await asyncio.gather(
            session1.start(session2.getLocalParameters()),
            session2.start(session1.getLocalParameters()),
        )

        # send encypted data
        await session1._send_data(b"ping")
        await asyncio.sleep(0.1)
        self.assertEqual(receiver2.data, [b"ping"])

        await session2._send_data(b"pong")
        await asyncio.sleep(0.1)
        self.assertEqual(receiver1.data, [b"pong"])

        # shutdown
        await session1.stop()
        await asyncio.sleep(0.1)
        self.assertEqual(session1.state, "closed")
        self.assertEqual(session2.state, "closed")

        # try closing again
        await session1.stop()
        await session2.stop()

        # try sending after close
        with self.assertRaises(ConnectionError):
            await session1._send_data(b"foo")
Пример #22
0
    def test_rtp(self):
        transport1, transport2 = dummy_ice_transport_pair()

        certificate1 = RTCCertificate.generateCertificate()
        session1 = RTCDtlsTransport(transport1, [certificate1])
        receiver1 = DummyRtpReceiver()
        session1._register_rtp_receiver(
            receiver1,
            RTCRtpReceiveParameters(
                codecs=[
                    RTCRtpCodecParameters(
                        mimeType="audio/PCMU", clockRate=8000, payloadType=0
                    )
                ],
                encodings=[RTCRtpDecodingParameters(ssrc=1831097322, payloadType=0)],
            ),
        )

        certificate2 = RTCCertificate.generateCertificate()
        session2 = RTCDtlsTransport(transport2, [certificate2])
        receiver2 = DummyRtpReceiver()
        session2._register_rtp_receiver(
            receiver2,
            RTCRtpReceiveParameters(
                codecs=[
                    RTCRtpCodecParameters(
                        mimeType="audio/PCMU", clockRate=8000, payloadType=0
                    )
                ],
                encodings=[RTCRtpDecodingParameters(ssrc=4028317929, payloadType=0)],
            ),
        )

        run(
            asyncio.gather(
                session1.start(session2.getLocalParameters()),
                session2.start(session1.getLocalParameters()),
            )
        )
        self.assertCounters(session1, session2, 2, 2)

        # send RTP
        run(session1._send_rtp(RTP))
        run(asyncio.sleep(0.1))
        self.assertCounters(session1, session2, 3, 2)
        self.assertEqual(len(receiver2.rtcp_packets), 0)
        self.assertEqual(len(receiver2.rtp_packets), 1)

        # send RTCP
        run(session2._send_rtp(RTCP))
        run(asyncio.sleep(0.1))
        self.assertCounters(session1, session2, 3, 3)
        self.assertEqual(len(receiver1.rtcp_packets), 1)
        self.assertEqual(len(receiver1.rtp_packets), 0)

        # shutdown
        run(session1.stop())
        run(asyncio.sleep(0.1))
        self.assertCounters(session1, session2, 4, 3)
        self.assertEqual(session1.state, "closed")
        self.assertEqual(session2.state, "closed")

        # try closing again
        run(session1.stop())
        run(session2.stop())

        # try sending after close
        with self.assertRaises(ConnectionError):
            run(session1._send_rtp(RTP))
Пример #23
0
    def test_data_handler_error(self):
        transport1, transport2 = dummy_ice_transport_pair()

        certificate1 = RTCCertificate.generateCertificate()
        session1 = RTCDtlsTransport(transport1, [certificate1])
        receiver1 = DummyDataReceiver()
        session1._register_data_receiver(receiver1)

        certificate2 = RTCCertificate.generateCertificate()
        session2 = RTCDtlsTransport(transport2, [certificate2])
        session2._register_data_receiver(BrokenDataReceiver())

        run(
            asyncio.gather(
                session1.start(session2.getLocalParameters()),
                session2.start(session1.getLocalParameters()),
            )
        )

        # send encypted data
        run(session1._send_data(b"ping"))
        run(asyncio.sleep(0.1))

        # shutdown
        run(session1.stop())
        run(session2.stop())