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
This commit is contained in:
Stian Selnes 2016-12-13 10:13:52 +01:00 committed by Tim-Philipp Müller
parent adc315978c
commit 457fdf95c4
2 changed files with 56 additions and 0 deletions

View file

@ -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

View file

@ -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);