From 457fdf95c483dd07c318acf2b8017662014315ca Mon Sep 17 00:00:00 2001 From: Stian Selnes Date: Tue, 13 Dec 2016 10:13:52 +0100 Subject: [PATCH] rtpsession: Drop packet if trying to send from non-internal source If obtain_internal_source() returns a source that is not internal it means there exists a non-internal source with the same ssrc. Such an ssrc collision should be handled by sending a GstRTPCollision event upstream and choose a new ssrc, but for now we simply drop the packet. Trying to process the packet further will cause it to be pushed usptream (!) since the source is not internal (see source_push_rtp()). https://bugzilla.gnome.org/show_bug.cgi?id=795139 --- gst/rtpmanager/rtpsession.c | 13 ++++++++++ tests/check/elements/rtpsession.c | 43 +++++++++++++++++++++++++++++++ 2 files changed, 56 insertions(+) diff --git a/gst/rtpmanager/rtpsession.c b/gst/rtpmanager/rtpsession.c index 7b5aca0fff..18258c32a1 100644 --- a/gst/rtpmanager/rtpsession.c +++ b/gst/rtpmanager/rtpsession.c @@ -3019,6 +3019,10 @@ rtp_session_send_rtp (RTPSession * sess, gpointer data, gboolean is_list, if (created) on_new_sender_ssrc (sess, source); + if (!source->internal) + /* FIXME: Send GstRTPCollision upstream */ + goto collision; + prevsender = RTP_SOURCE_IS_SENDER (source); oldrate = source->bitrate; @@ -3043,6 +3047,15 @@ invalid_packet: GST_DEBUG ("invalid RTP packet received"); return GST_FLOW_OK; } +collision: + { + g_object_unref (source); + gst_mini_object_unref (GST_MINI_OBJECT_CAST (data)); + RTP_SESSION_UNLOCK (sess); + GST_WARNING ("non-internal source with same ssrc %08x, drop packet", + pinfo.ssrc); + return GST_FLOW_OK; + } } static void diff --git a/tests/check/elements/rtpsession.c b/tests/check/elements/rtpsession.c index bc02fc2b7c..b5ac097acd 100644 --- a/tests/check/elements/rtpsession.c +++ b/tests/check/elements/rtpsession.c @@ -889,6 +889,48 @@ GST_START_TEST (test_receive_pli_no_sender_ssrc) GST_END_TEST; +static void +add_rtcp_sdes_packet (GstBuffer * gstbuf, guint32 ssrc, const char *cname) +{ + GstRTCPPacket packet; + GstRTCPBuffer buffer = GST_RTCP_BUFFER_INIT; + + gst_rtcp_buffer_map (gstbuf, GST_MAP_READWRITE, &buffer); + + fail_unless (gst_rtcp_buffer_add_packet (&buffer, GST_RTCP_TYPE_SDES, + &packet) == TRUE); + fail_unless (gst_rtcp_packet_sdes_add_item (&packet, ssrc) == TRUE); + fail_unless (gst_rtcp_packet_sdes_add_entry (&packet, GST_RTCP_SDES_CNAME, + strlen (cname), (const guint8 *) cname)); + + gst_rtcp_buffer_unmap (&buffer); +} + +GST_START_TEST (test_ssrc_collision_when_sending) +{ + SessionHarness *h = session_harness_new (); + GstBuffer *buf = gst_rtcp_buffer_new (1400); + +/* Push SDES with identical SSRC as what we will use for sending RTP, + establishing this as a non-internal SSRC */ + add_rtcp_sdes_packet (buf, 0x12345678, "test@foo.bar"); + session_harness_recv_rtcp (h, buf); + + /* Push RTP buffer making our internal SSRC=0x12345678 */ + fail_unless_equals_int (GST_FLOW_OK, + session_harness_send_rtp (h, generate_test_buffer (0, 0x12345678))); + + /* Verify the packet we just sent is not being boomeranged back to us + as a received packet! */ + fail_unless_equals_int (0, gst_harness_buffers_in_queue (h->recv_rtp_h)); + + /* FIXME: verify a Collision event coming upstream! */ + + session_harness_free (h); +} + +GST_END_TEST; + GST_START_TEST (test_illegal_rtcp_fb_packet) { SessionHarness *h = session_harness_new (); @@ -1007,6 +1049,7 @@ rtpsession_suite (void) tcase_add_test (tc_chain, test_receive_rtcp_app_packet); tcase_add_test (tc_chain, test_dont_lock_on_stats); tcase_add_test (tc_chain, test_ignore_suspicious_bye); + tcase_add_test (tc_chain, test_ssrc_collision_when_sending); tcase_add_test (tc_chain, test_illegal_rtcp_fb_packet); tcase_add_test (tc_chain, test_feedback_rtcp_race); tcase_add_test (tc_chain, test_receive_regular_pli);