Exemplo n.º 1
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())
Exemplo n.º 2
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())))
        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.5))
        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))
Exemplo n.º 3
0
    async def test_handle_rtcp_rr(self):
        async with dummy_dtls_transport_pair() as (local_transport, _):
            sender = RTCRtpSender(VideoStreamTrack(), local_transport)
            self.assertEqual(sender.kind, "video")

            await sender.send(RTCRtpParameters(codecs=[VP8_CODEC]))

            # receive RTCP RR
            packet = RtcpRrPacket(
                ssrc=1234,
                reports=[
                    RtcpReceiverInfo(
                        ssrc=sender._ssrc,
                        fraction_lost=0,
                        packets_lost=0,
                        highest_sequence=630,
                        jitter=1906,
                        lsr=0,
                        dlsr=0,
                    )
                ],
            )
            await sender._handle_rtcp_packet(packet)

            # check stats
            report = await sender.getStats()
            self.assertTrue(isinstance(report, RTCStatsReport))
            self.assertEqual(
                sorted([s.type for s in report.values()]),
                ["outbound-rtp", "remote-inbound-rtp", "transport"],
            )

            # clean shutdown
            await sender.stop()
Exemplo n.º 4
0
    async def test_handle_rtcp_remb(self):
        async with dummy_dtls_transport_pair() as (local_transport, _):
            sender = RTCRtpSender(VideoStreamTrack(), local_transport)
            self.assertEqual(sender.kind, "video")

            await sender.send(RTCRtpParameters(codecs=[VP8_CODEC]))

            # receive RTCP feedback REMB
            packet = RtcpPsfbPacket(
                fmt=RTCP_PSFB_APP,
                ssrc=1234,
                media_ssrc=0,
                fci=pack_remb_fci(4160000, [sender._ssrc]),
            )
            await sender._handle_rtcp_packet(packet)

            # receive RTCP feedback REMB (malformed)
            packet = RtcpPsfbPacket(fmt=RTCP_PSFB_APP,
                                    ssrc=1234,
                                    media_ssrc=0,
                                    fci=b"JUNK")
            await sender._handle_rtcp_packet(packet)

            # clean shutdown
            await sender.stop()
Exemplo n.º 5
0
    def test_rtp_and_rtcp(self):
        transport, remote = dummy_dtls_transport_pair()

        receiver = RTCRtpReceiver('audio', transport)
        self.assertEqual(receiver.transport, transport)

        receiver._track = RemoteStreamTrack(kind='audio')
        run(receiver.receive(RTCRtpParameters(codecs=[PCMU_CODEC])))

        # receive RTP
        run(remote.send(load('rtp.bin')))

        # receive RTCP
        run(remote.send(load('rtcp_sr.bin')))

        # receive truncated RTCP
        run(remote.send(b'\x81\xca\x00'))

        # receive garbage
        run(remote.send(b'garbage'))

        # check remote track
        frame = run(receiver._track.recv())
        self.assertTrue(isinstance(frame, AudioFrame))

        # shutdown
        run(asyncio.sleep(0.1))
        receiver.stop()
        run(asyncio.sleep(0))
Exemplo n.º 6
0
    def test_rtp_and_rtcp(self):
        transport, remote = dummy_dtls_transport_pair()

        receiver = RTCRtpReceiver('audio', transport)
        self.assertEqual(receiver.transport, transport)

        receiver._track = RemoteStreamTrack(kind='audio')
        run(receiver.receive(RTCRtpParameters(codecs=[PCMU_CODEC])))

        # receive RTP
        packet = RtpPacket.parse(load('rtp.bin'))
        run(receiver._handle_rtp_packet(packet))

        # receive RTCP
        for packet in RtcpPacket.parse(load('rtcp_sr.bin')):
            run(receiver._handle_rtcp_packet(packet))
        self.assertEqual(sorted(receiver._stats.keys()),
                         ['remote-inbound-rtp', 'remote-outbound-rtp'])

        # check remote track
        frame = run(receiver._track.recv())
        self.assertTrue(isinstance(frame, AudioFrame))

        # shutdown
        run(receiver.stop())
        run(asyncio.sleep(0))
Exemplo n.º 7
0
    async def test_send_keyframe(self):
        """
        Ask for a keyframe.
        """
        queue = asyncio.Queue()

        async def mock_send_rtp(data):
            if not is_rtcp(data):
                await queue.put(RtpPacket.parse(data))

        async with dummy_dtls_transport_pair() as (local_transport, _):
            local_transport._send_rtp = mock_send_rtp

            sender = RTCRtpSender(VideoStreamTrack(), local_transport)
            self.assertEqual(sender.kind, "video")

            await sender.send(RTCRtpParameters(codecs=[VP8_CODEC]))

            # wait for one packet to be transmitted, and ask for keyframe
            await queue.get()
            sender._send_keyframe()

            # wait for packet to be transmitted, then shutdown
            await asyncio.sleep(0.1)
            await sender.stop()
Exemplo n.º 8
0
    def test_handle_rtcp_rr(self):
        transport, remote = dummy_dtls_transport_pair()

        sender = RTCRtpSender(VideoStreamTrack(), transport)
        self.assertEqual(sender.kind, 'video')
        self.assertEqual(sender.transport, transport)

        run(
            sender.send(
                RTCRtpParameters(codecs=[
                    RTCRtpCodecParameters(
                        name='VP8', clockRate=90000, payloadType=100),
                ])))

        # receive RTCP RR
        for packet in RtcpPacket.parse(load('rtcp_rr.bin')):
            run(sender._handle_rtcp_packet(packet))

        # check stats
        report = run(sender.getStats())
        self.assertTrue(isinstance(report, RTCStatsReport))
        self.assertEqual(sorted([s.type for s in report.values()]),
                         ['outbound-rtp', 'remote-inbound-rtp', 'transport'])

        # clean shutdown
        run(sender.stop())
Exemplo n.º 9
0
    def test_rtp_and_rtcp(self):
        transport, remote = dummy_dtls_transport_pair()

        receiver = RTCRtpReceiver('audio', transport)
        self.assertEqual(receiver.transport, transport)

        receiver._track = RemoteStreamTrack(kind='audio')
        self.assertEqual(receiver._track.readyState, 'live')
        run(receiver.receive(RTCRtpParameters(codecs=[PCMU_CODEC])))

        # receive RTP
        packet = RtpPacket.parse(load('rtp.bin'))
        run(receiver._handle_rtp_packet(packet, arrival_time_ms=0))

        # receive RTCP SR
        for packet in RtcpPacket.parse(load('rtcp_sr.bin')):
            run(receiver._handle_rtcp_packet(packet))

        # check stats
        report = run(receiver.getStats())
        self.assertTrue(isinstance(report, RTCStatsReport))
        self.assertEqual(sorted(report.keys()), ['inbound-rtp', 'remote-outbound-rtp'])

        # check remote track
        frame = run(receiver._track.recv())
        self.assertTrue(isinstance(frame, AudioFrame))

        # shutdown
        run(receiver.stop())
        self.assertEqual(receiver._track.readyState, 'ended')
Exemplo n.º 10
0
    def test_handle_rtcp_remb(self):
        sender = RTCRtpSender(VideoStreamTrack(), self.local_transport)
        self.assertEqual(sender.kind, 'video')

        run(
            sender.send(
                RTCRtpParameters(codecs=[
                    RTCRtpCodecParameters(
                        name='VP8', clockRate=90000, payloadType=100),
                ])))

        # receive RTCP feedback REMB
        packet = RtcpPsfbPacket(fmt=RTCP_PSFB_APP,
                                ssrc=1234,
                                media_ssrc=0,
                                fci=b'REMB\x01\x13\xf7\xa0\x96\xbe\x96\xcf')
        run(sender._handle_rtcp_packet(packet))

        # receive RTCP feedback REMB (malformed)
        packet = RtcpPsfbPacket(fmt=RTCP_PSFB_APP,
                                ssrc=1234,
                                media_ssrc=0,
                                fci=b'JUNK')
        run(sender._handle_rtcp_packet(packet))

        # clean shutdown
        run(sender.stop())
Exemplo n.º 11
0
    def test_retransmit(self):
        """
        Ask for an RTP packet retransmission.
        """
        transport = FakeDtlsTransport()

        sender = RTCRtpSender(VideoStreamTrack(), transport)
        self.assertEqual(sender.kind, 'video')
        self.assertEqual(sender.transport, transport)

        run(
            sender.send(
                RTCRtpParameters(codecs=[
                    RTCRtpCodecParameters(
                        name='VP8', clockRate=90000, payloadType=100),
                ])))

        # wait for one packet to be transmitted, and ask to retransmit
        packet = run(transport.queue.get())
        run(sender._retransmit(packet.sequence_number))

        # wait for packet to be retransmitted, then shutdown
        run(asyncio.sleep(0.5))
        run(sender.stop())

        # check packet was retransmitted
        found_rtx = False
        while not transport.queue.empty():
            queue_packet = transport.queue.get_nowait()
            if queue_packet.sequence_number == packet.sequence_number:
                found_rtx = True
        self.assertTrue(found_rtx)
Exemplo n.º 12
0
    def test_send_keyframe(self):
        """
        Ask for a keyframe.
        """
        queue = asyncio.Queue()

        async def mock_send_rtp(data):
            if not is_rtcp(data):
                await queue.put(RtpPacket.parse(data))

        self.local_transport._send_rtp = mock_send_rtp

        sender = RTCRtpSender(VideoStreamTrack(), self.local_transport)
        self.assertEqual(sender.kind, 'video')

        run(
            sender.send(
                RTCRtpParameters(codecs=[
                    RTCRtpCodecParameters(
                        name='VP8', clockRate=90000, payloadType=100),
                ])))

        # wait for one packet to be transmitted, and ask for keyframe
        run(queue.get())
        sender._send_keyframe()

        # wait for packet to be transmitted, then shutdown
        run(asyncio.sleep(0.1))
        run(sender.stop())
Exemplo n.º 13
0
    def test_padding_only_with_header_extensions(self):
        extensions_map = rtp.HeaderExtensionsMap()
        extensions_map.configure(
            RTCRtpParameters(headerExtensions=[
                RTCRtpHeaderExtensionParameters(
                    id=2,
                    uri=
                    "http://www.webrtc.org/experiments/rtp-hdrext/abs-send-time",
                )
            ]))

        data = load("rtp_only_padding_with_header_extensions.bin")
        packet = RtpPacket.parse(data, extensions_map)
        self.assertEqual(packet.version, 2)
        self.assertEqual(packet.marker, 0)
        self.assertEqual(packet.payload_type, 98)
        self.assertEqual(packet.sequence_number, 22138)
        self.assertEqual(packet.timestamp, 3171065731)
        self.assertEqual(packet.csrc, [])
        self.assertEqual(packet.extensions,
                         rtp.HeaderExtensions(abs_send_time=15846540))
        self.assertEqual(len(packet.payload), 0)
        self.assertEqual(packet.padding_size, 224)

        serialized = packet.serialize(extensions_map)
        self.assertEqual(len(serialized), len(data))
        self.assertEqual(serialized[0:20], data[0:20])
        self.assertEqual(serialized[-1], data[-1])
Exemplo n.º 14
0
    def test_retransmit(self):
        """
        Ask for an RTP packet retransmission.
        """
        transport = FakeDtlsTransport()

        sender = RTCRtpSender(VideoStreamTrack(), transport)
        self.assertEqual(sender.kind, 'video')
        self.assertEqual(sender.transport, transport)

        run(
            sender.send(
                RTCRtpParameters(codecs=[
                    RTCRtpCodecParameters(
                        name='VP8', clockRate=90000, payloadType=100),
                ])))

        # wait for one packet to be transmitted, and ask to retransmit
        packet = run(transport.queue.get())
        run(sender._retransmit(packet.sequence_number))

        # wait for packet to be transmitted
        rtx_packet = run(transport.queue.get())
        self.assertEqual(rtx_packet.sequence_number, packet.sequence_number)

        # clean shutdown
        run(sender.stop())
Exemplo n.º 15
0
    def test_rtx(self):
        extensions_map = rtp.HeaderExtensionsMap()
        extensions_map.configure(
            RTCRtpParameters(headerExtensions=[
                RTCRtpHeaderExtensionParameters(
                    id=9, uri="urn:ietf:params:rtp-hdrext:sdes:mid")
            ]))

        data = load("rtp_with_sdes_mid.bin")
        packet = RtpPacket.parse(data, extensions_map)

        # wrap / unwrap RTX
        rtx = wrap_rtx(packet,
                       payload_type=112,
                       sequence_number=12345,
                       ssrc=1234)
        recovered = unwrap_rtx(rtx, payload_type=111, ssrc=4084547440)

        # check roundtrip
        self.assertEqual(recovered.version, packet.version)
        self.assertEqual(recovered.marker, packet.marker)
        self.assertEqual(recovered.payload_type, packet.payload_type)
        self.assertEqual(recovered.sequence_number, packet.sequence_number)
        self.assertEqual(recovered.timestamp, packet.timestamp)
        self.assertEqual(recovered.ssrc, packet.ssrc)
        self.assertEqual(recovered.csrc, packet.csrc)
        self.assertEqual(recovered.extensions, packet.extensions)
        self.assertEqual(recovered.payload, packet.payload)
Exemplo n.º 16
0
    def test_connection_error(self):
        """
        Close the underlying transport before the receiver.
        """
        transport, _ = dummy_dtls_transport_pair()

        receiver = RTCRtpReceiver('audio', transport)
        self.assertEqual(receiver.transport, transport)

        receiver._track = RemoteStreamTrack(kind='audio')
        receiver._ssrc = 1234
        run(receiver.receive(RTCRtpParameters(codecs=[PCMU_CODEC])))

        # receive a packet to prime RTCP
        packet = RtpPacket.parse(load('rtp.bin'))
        run(receiver._handle_rtp_packet(packet, arrival_time_ms=0))

        # break connection
        run(transport.stop())

        # give RTCP time to send a report
        run(asyncio.sleep(2))

        # shutdown
        run(receiver.stop())
Exemplo n.º 17
0
    def test_track_ended(self):
        track = AudioStreamTrack()
        sender = RTCRtpSender(track, self.local_transport)
        run(sender.send(RTCRtpParameters(codecs=[PCMU_CODEC])))

        track.stop()
        run(asyncio.sleep(0.5))
Exemplo n.º 18
0
    def test_handle_rtcp_rr(self):
        sender = RTCRtpSender(VideoStreamTrack(), self.local_transport)
        self.assertEqual(sender.kind, 'video')

        run(sender.send(RTCRtpParameters(codecs=[VP8_CODEC])))

        # receive RTCP RR
        packet = RtcpRrPacket(ssrc=1234,
                              reports=[
                                  RtcpReceiverInfo(ssrc=sender._ssrc,
                                                   fraction_lost=0,
                                                   packets_lost=0,
                                                   highest_sequence=630,
                                                   jitter=1906,
                                                   lsr=0,
                                                   dlsr=0)
                              ])
        run(sender._handle_rtcp_packet(packet))

        # check stats
        report = run(sender.getStats())
        self.assertTrue(isinstance(report, RTCStatsReport))
        self.assertEqual(sorted([s.type for s in report.values()]),
                         ['outbound-rtp', 'remote-inbound-rtp', 'transport'])

        # clean shutdown
        run(sender.stop())
Exemplo n.º 19
0
    def test_track_ended(self):
        track = AudioStreamTrack()
        sender = RTCRtpSender(track, self.local_transport)
        run(sender.send(RTCRtpParameters(codecs=[PCMU_CODEC])))

        # stop track and wait for RTP loop to exit
        track.stop()
        run(asyncio.sleep(0.1))
Exemplo n.º 20
0
    def test_stop_on_exception(self):
        sender = RTCRtpSender(BuggyStreamTrack(), self.local_transport)
        self.assertEqual(sender.kind, "audio")

        run(sender.send(RTCRtpParameters(codecs=[PCMU_CODEC])))

        # clean shutdown
        run(sender.stop())
Exemplo n.º 21
0
    def test_stop(self):
        sender = RTCRtpSender(AudioStreamTrack(), self.local_transport)
        self.assertEqual(sender.kind, 'audio')

        run(sender.send(RTCRtpParameters(codecs=[PCMU_CODEC])))

        # clean shutdown
        run(sender.stop())
Exemplo n.º 22
0
    async def test_stop_on_exception(self):
        async with dummy_dtls_transport_pair() as (local_transport, _):
            sender = RTCRtpSender(BuggyStreamTrack(), local_transport)
            self.assertEqual(sender.kind, "audio")

            await sender.send(RTCRtpParameters(codecs=[PCMU_CODEC]))

            # clean shutdown
            await sender.stop()
Exemplo n.º 23
0
    async def test_log_debug(self, mock_is_enabled_for):
        mock_is_enabled_for.return_value = True

        async with dummy_dtls_transport_pair() as (local_transport, _):
            sender = RTCRtpSender(VideoStreamTrack(), local_transport)
            await sender.send(RTCRtpParameters(codecs=[VP8_CODEC]))

            # clean shutdown
            await sender.stop()
Exemplo n.º 24
0
    async def test_track_ended(self):
        async with dummy_dtls_transport_pair() as (local_transport, _):
            track = AudioStreamTrack()
            sender = RTCRtpSender(track, local_transport)

            await sender.send(RTCRtpParameters(codecs=[PCMU_CODEC]))

            # stop track and wait for RTP loop to exit
            track.stop()
            await asyncio.sleep(0.1)
Exemplo n.º 25
0
    def test_connection_error(self):
        """
        Close the underlying transport before the sender.
        """
        sender = RTCRtpSender(AudioStreamTrack(), self.local_transport)
        self.assertEqual(sender.kind, 'audio')

        run(sender.send(RTCRtpParameters(codecs=[PCMU_CODEC])))

        run(self.local_transport.stop())
Exemplo n.º 26
0
    def test_track_ended(self):
        transport, _ = dummy_dtls_transport_pair()

        track = AudioStreamTrack()
        sender = RTCRtpSender(track, transport)
        run(sender.send(RTCRtpParameters(codecs=[PCMU_CODEC])))

        track.stop()
        run(asyncio.sleep(0.5))

        run(transport.stop())
Exemplo n.º 27
0
    async def test_connection_error(self):
        """
        Close the underlying transport before the sender.
        """
        async with dummy_dtls_transport_pair() as (local_transport, _):
            sender = RTCRtpSender(AudioStreamTrack(), local_transport)
            self.assertEqual(sender.kind, "audio")

            await sender.send(RTCRtpParameters(codecs=[PCMU_CODEC]))

            await local_transport.stop()
Exemplo n.º 28
0
    def test_stop(self):
        transport, _ = dummy_dtls_transport_pair()

        sender = RTCRtpSender(AudioStreamTrack(), transport)
        self.assertEqual(sender.kind, 'audio')
        self.assertEqual(sender.transport, transport)

        run(sender.send(RTCRtpParameters(codecs=[PCMU_CODEC])))

        # clean shutdown
        run(sender.stop())
Exemplo n.º 29
0
    def test_handle_rtcp_pli(self):
        sender = RTCRtpSender(VideoStreamTrack(), self.local_transport)
        self.assertEqual(sender.kind, "video")

        run(sender.send(RTCRtpParameters(codecs=[VP8_CODEC])))

        # receive RTCP feedback NACK
        packet = RtcpPsfbPacket(fmt=RTCP_PSFB_PLI, ssrc=1234, media_ssrc=sender._ssrc)
        run(sender._handle_rtcp_packet(packet))

        # clean shutdown
        run(sender.stop())
Exemplo n.º 30
0
    def test_connection_error(self):
        """
        Close the underlying transport before the receiver.
        """
        transport, _ = dummy_dtls_transport_pair()

        receiver = RTCRtpReceiver('audio', transport)
        self.assertEqual(receiver.transport, transport)

        run(receiver.receive(RTCRtpParameters(codecs=[PCMU_CODEC])))

        run(transport.close())