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
This commit is contained in:
David Svensson Fors 2018-08-17 09:54:27 +02:00 committed by Sebastian Dröge
parent 990d5dde86
commit a2e182c3b4
2 changed files with 74 additions and 2 deletions

View file

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

View file

@ -21,6 +21,13 @@
#include <rtsp-client.h>
#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);