From: David Svensson Fors Date: Fri, 17 Aug 2018 07:54:27 +0000 (+0200) Subject: rtsp-client: Avoid reuse of channel numbers for interleaved X-Git-Tag: 1.19.3~495^2~226 X-Git-Url: http://review.tizen.org/git/?p=platform%2Fupstream%2Fgstreamer.git;a=commitdiff_plain;h=a2e182c3b41cf7a149d099d65e32ac512dd60dc3 rtsp-client: Avoid reuse of channel numbers for interleaved If a (strange) client would reuse interleaved channel numbers in multiple SETUP requests, we should not accept them. The channel numbers are used for looking up stream transports in the priv->transports hash table, and transports disappear from the table if channel numbers are reused. RFC 7826 (RTSP 2.0), Section 18.54, clarifies that it is OK for the server to change the channel numbers suggested by the client. https://bugzilla.gnome.org/show_bug.cgi?id=796988 --- diff --git a/gst/rtsp-server/rtsp-client.c b/gst/rtsp-server/rtsp-client.c index d4c5211..2e124f8 100644 --- a/gst/rtsp-server/rtsp-client.c +++ b/gst/rtsp-server/rtsp-client.c @@ -2084,6 +2084,16 @@ default_configure_client_transport (GstRTSPClient * client, gst_rtsp_session_media_alloc_channels (ctx->sessmedia, &ct->interleaved); } + /* alloc new channels if they are already taken */ + while (g_hash_table_contains (priv->transports, + GINT_TO_POINTER (ct->interleaved.min)) + || g_hash_table_contains (priv->transports, + GINT_TO_POINTER (ct->interleaved.max))) { + gst_rtsp_session_media_alloc_channels (ctx->sessmedia, + &ct->interleaved); + if (ct->interleaved.max > 255) + goto error_allocating_channels; + } } } return TRUE; @@ -2115,6 +2125,11 @@ error_mcast_transport: GST_ERROR_OBJECT (client, "Failed to add multicast client transport"); return FALSE; } +error_allocating_channels: + { + GST_ERROR_OBJECT (client, "Failed to allocate interleaved channels"); + return FALSE; + } } static GstRTSPTransport * diff --git a/tests/check/gst/client.c b/tests/check/gst/client.c index 6368c15..aa7893c 100644 --- a/tests/check/gst/client.c +++ b/tests/check/gst/client.c @@ -21,6 +21,13 @@ #include +#define VIDEO_PIPELINE "videotestsrc ! " \ + "video/x-raw,width=352,height=288 ! " \ + "rtpgstpay name=pay0 pt=96" +#define AUDIO_PIPELINE "audiotestsrc ! " \ + "audio/x-raw,rate=8000 ! " \ + "rtpgstpay name=pay1 pt=97" + static gchar *session_id; static gint cseq; static guint expected_session_timeout = 60; @@ -167,7 +174,7 @@ setup_client (const gchar * launch_line) factory = gst_rtsp_media_factory_new (); if (launch_line == NULL) gst_rtsp_media_factory_set_launch (factory, - "videotestsrc ! video/x-raw,width=352,height=288 ! rtpgstpay name=pay0 pt=96"); + "( " VIDEO_PIPELINE " " AUDIO_PIPELINE " )"); else gst_rtsp_media_factory_set_launch (factory, launch_line); @@ -637,7 +644,7 @@ GST_START_TEST (test_setup_tcp) fail_unless (gst_rtsp_client_set_connection (client, conn)); fail_unless (gst_rtsp_message_init_request (&request, GST_RTSP_SETUP, - "rtsp://localhost/test") == GST_RTSP_OK); + "rtsp://localhost/test/stream=0") == GST_RTSP_OK); str = g_strdup_printf ("%d", cseq); gst_rtsp_message_add_header (&request, GST_RTSP_HDR_CSEQ, str); g_free (str); @@ -658,6 +665,55 @@ GST_START_TEST (test_setup_tcp) GST_END_TEST; +GST_START_TEST (test_setup_tcp_two_streams_same_channels) +{ + GstRTSPClient *client; + GstRTSPConnection *conn; + GstRTSPMessage request = { 0, }; + gchar *str; + + client = setup_client (NULL); + create_connection (&conn); + fail_unless (gst_rtsp_client_set_connection (client, conn)); + + /* test SETUP of a video stream with 0-1 as interleaved channels */ + fail_unless (gst_rtsp_message_init_request (&request, GST_RTSP_SETUP, + "rtsp://localhost/test/stream=0") == GST_RTSP_OK); + str = g_strdup_printf ("%d", cseq); + gst_rtsp_message_add_header (&request, GST_RTSP_HDR_CSEQ, str); + g_free (str); + gst_rtsp_message_add_header (&request, GST_RTSP_HDR_TRANSPORT, + "RTP/AVP/TCP;unicast;interleaved=0-1"); + gst_rtsp_client_set_send_func (client, test_setup_response_200, NULL, NULL); + expected_transport = + "RTP/AVP/TCP;unicast;interleaved=0-1;ssrc=.*;mode=\"PLAY\""; + fail_unless (gst_rtsp_client_handle_message (client, + &request) == GST_RTSP_OK); + gst_rtsp_message_unset (&request); + + /* test SETUP of an audio stream with *the same* interleaved channels. + * we expect the server to allocate new channel numbers */ + fail_unless (gst_rtsp_message_init_request (&request, GST_RTSP_SETUP, + "rtsp://localhost/test/stream=1") == GST_RTSP_OK); + str = g_strdup_printf ("%d", cseq); + gst_rtsp_message_add_header (&request, GST_RTSP_HDR_CSEQ, str); + g_free (str); + gst_rtsp_message_add_header (&request, GST_RTSP_HDR_TRANSPORT, + "RTP/AVP/TCP;unicast;interleaved=0-1"); + gst_rtsp_message_add_header (&request, GST_RTSP_HDR_SESSION, session_id); + gst_rtsp_client_set_send_func (client, test_setup_response_200, NULL, NULL); + expected_transport = + "RTP/AVP/TCP;unicast;interleaved=2-3;ssrc=.*;mode=\"PLAY\""; + fail_unless (gst_rtsp_client_handle_message (client, + &request) == GST_RTSP_OK); + gst_rtsp_message_unset (&request); + + send_teardown (client); + teardown_client (client); +} + +GST_END_TEST; + static GstRTSPClient * setup_multicast_client (guint max_ttl) { @@ -1415,6 +1471,7 @@ rtspclient_suite (void) tcase_add_test (tc, test_options); tcase_add_test (tc, test_describe); tcase_add_test (tc, test_setup_tcp); + tcase_add_test (tc, test_setup_tcp_two_streams_same_channels); tcase_add_test (tc, test_client_multicast_transport_404); tcase_add_test (tc, test_client_multicast_transport); tcase_add_test (tc, test_client_multicast_ignore_transport_specific);