#include <rtsp-client.h>
+static gchar *session_id;
static gint cseq;
+static guint expected_session_timeout = 60;
+static const gchar *expected_unsupported_header;
static gboolean
-test_option_response_200 (GstRTSPClient * client, GstRTSPMessage * response,
+test_response_200 (GstRTSPClient * client, GstRTSPMessage * response,
gboolean close, gpointer user_data)
{
GstRTSPStatusCode code;
const gchar *reason;
GstRTSPVersion version;
- gchar *str;
- GstRTSPMethod methods;
fail_unless (gst_rtsp_message_get_type (response) ==
GST_RTSP_MESSAGE_RESPONSE);
- gst_rtsp_message_dump (response);
fail_unless (gst_rtsp_message_parse_response (response, &code, &reason,
&version)
== GST_RTSP_OK);
fail_unless (g_str_equal (reason, "OK"));
fail_unless (version == GST_RTSP_VERSION_1_0);
- fail_unless (gst_rtsp_message_get_header (response, GST_RTSP_HDR_CSEQ, &str,
- 0) == GST_RTSP_OK);
- fail_unless (atoi (str) == cseq++);
+ return TRUE;
+}
- fail_unless (gst_rtsp_message_get_header (response, GST_RTSP_HDR_PUBLIC, &str,
- 0) == GST_RTSP_OK);
+static gboolean
+test_response_400 (GstRTSPClient * client, GstRTSPMessage * response,
+ gboolean close, gpointer user_data)
+{
+ GstRTSPStatusCode code;
+ const gchar *reason;
+ GstRTSPVersion version;
- methods = gst_rtsp_options_from_text (str);
- fail_if (methods == 0);
- fail_unless (methods == (GST_RTSP_DESCRIBE |
- GST_RTSP_OPTIONS |
- GST_RTSP_PAUSE |
- GST_RTSP_PLAY |
- GST_RTSP_SETUP |
- GST_RTSP_GET_PARAMETER | GST_RTSP_SET_PARAMETER | GST_RTSP_TEARDOWN));
+ fail_unless (gst_rtsp_message_get_type (response) ==
+ GST_RTSP_MESSAGE_RESPONSE);
+
+ fail_unless (gst_rtsp_message_parse_response (response, &code, &reason,
+ &version)
+ == GST_RTSP_OK);
+ fail_unless (code == GST_RTSP_STS_BAD_REQUEST);
+ fail_unless (g_str_equal (reason, "Bad Request"));
+ fail_unless (version == GST_RTSP_VERSION_1_0);
+
+ return TRUE;
+}
+
+static gboolean
+test_response_404 (GstRTSPClient * client, GstRTSPMessage * response,
+ gboolean close, gpointer user_data)
+{
+ GstRTSPStatusCode code;
+ const gchar *reason;
+ GstRTSPVersion version;
+
+ fail_unless (gst_rtsp_message_get_type (response) ==
+ GST_RTSP_MESSAGE_RESPONSE);
+
+ fail_unless (gst_rtsp_message_parse_response (response, &code, &reason,
+ &version)
+ == GST_RTSP_OK);
+ fail_unless (code == GST_RTSP_STS_NOT_FOUND);
+ fail_unless (g_str_equal (reason, "Not Found"));
+ fail_unless (version == GST_RTSP_VERSION_1_0);
return TRUE;
}
static gboolean
-test_option_response_454 (GstRTSPClient * client, GstRTSPMessage * response,
+test_response_454 (GstRTSPClient * client, GstRTSPMessage * response,
gboolean close, gpointer user_data)
{
GstRTSPStatusCode code;
fail_unless (gst_rtsp_message_get_type (response) ==
GST_RTSP_MESSAGE_RESPONSE);
- gst_rtsp_message_dump (response);
fail_unless (gst_rtsp_message_parse_response (response, &code, &reason,
&version)
return TRUE;
}
-GST_START_TEST (test_options)
+static gboolean
+test_response_551 (GstRTSPClient * client, GstRTSPMessage * response,
+ gboolean close, gpointer user_data)
+{
+ GstRTSPStatusCode code;
+ const gchar *reason;
+ GstRTSPVersion version;
+ gchar *options;
+
+ fail_unless (gst_rtsp_message_get_type (response) ==
+ GST_RTSP_MESSAGE_RESPONSE);
+
+ fail_unless (gst_rtsp_message_parse_response (response, &code, &reason,
+ &version)
+ == GST_RTSP_OK);
+ fail_unless (code == GST_RTSP_STS_OPTION_NOT_SUPPORTED);
+ fail_unless (g_str_equal (reason, "Option not supported"));
+ fail_unless (gst_rtsp_message_get_header (response, GST_RTSP_HDR_UNSUPPORTED,
+ &options, 0) == GST_RTSP_OK);
+ fail_unless (!g_strcmp0 (expected_unsupported_header, options));
+ fail_unless (version == GST_RTSP_VERSION_1_0);
+
+ return TRUE;
+}
+
+static void
+create_connection (GstRTSPConnection ** conn)
+{
+ GSocket *sock;
+ GError *error = NULL;
+
+ sock = g_socket_new (G_SOCKET_FAMILY_IPV4, G_SOCKET_TYPE_STREAM,
+ G_SOCKET_PROTOCOL_TCP, &error);
+ g_assert_no_error (error);
+ fail_unless (gst_rtsp_connection_create_from_socket (sock, "127.0.0.1", 444,
+ NULL, conn) == GST_RTSP_OK);
+ g_object_unref (sock);
+}
+
+static GstRTSPClient *
+setup_client (const gchar * launch_line)
+{
+ GstRTSPClient *client;
+ GstRTSPSessionPool *session_pool;
+ GstRTSPMountPoints *mount_points;
+ GstRTSPMediaFactory *factory;
+ GstRTSPThreadPool *thread_pool;
+
+ client = gst_rtsp_client_new ();
+
+ session_pool = gst_rtsp_session_pool_new ();
+ gst_rtsp_client_set_session_pool (client, session_pool);
+
+ mount_points = gst_rtsp_mount_points_new ();
+ 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");
+ else
+ gst_rtsp_media_factory_set_launch (factory, launch_line);
+
+ gst_rtsp_mount_points_add_factory (mount_points, "/test", factory);
+ gst_rtsp_client_set_mount_points (client, mount_points);
+
+ thread_pool = gst_rtsp_thread_pool_new ();
+ gst_rtsp_client_set_thread_pool (client, thread_pool);
+
+ g_object_unref (mount_points);
+ g_object_unref (session_pool);
+ g_object_unref (thread_pool);
+
+ return client;
+}
+
+static void
+teardown_client (GstRTSPClient * client)
+{
+ gst_rtsp_client_set_thread_pool (client, NULL);
+ g_object_unref (client);
+}
+
+static gchar *
+check_requirements_cb (GstRTSPClient * client, GstRTSPContext * ctx,
+ gchar ** req, gpointer user_data)
+{
+ int index = 0;
+ GString *result = g_string_new ("");
+
+ while (req[index] != NULL) {
+ if (g_strcmp0 (req[index], "test-requirements")) {
+ if (result->len > 0)
+ g_string_append (result, ", ");
+ g_string_append (result, req[index]);
+ }
+ index++;
+ }
+
+ return g_string_free (result, FALSE);
+}
+
+GST_START_TEST (test_require)
{
GstRTSPClient *client;
GstRTSPMessage request = { 0, };
client = gst_rtsp_client_new ();
- /* simple OPTIONS */
+ /* require header without handler */
+ fail_unless (gst_rtsp_message_init_request (&request, GST_RTSP_OPTIONS,
+ "rtsp://localhost/test") == GST_RTSP_OK);
+ str = g_strdup_printf ("test-not-supported1");
+ gst_rtsp_message_add_header (&request, GST_RTSP_HDR_REQUIRE, str);
+ g_free (str);
+
+ expected_unsupported_header = "test-not-supported1";
+ gst_rtsp_client_set_send_func (client, test_response_551, NULL, NULL);
+ fail_unless (gst_rtsp_client_handle_message (client,
+ &request) == GST_RTSP_OK);
+ gst_rtsp_message_unset (&request);
+
+ g_signal_connect (G_OBJECT (client), "check-requirements",
+ G_CALLBACK (check_requirements_cb), NULL);
+
+ /* one supported option */
+ fail_unless (gst_rtsp_message_init_request (&request, GST_RTSP_OPTIONS,
+ "rtsp://localhost/test") == GST_RTSP_OK);
+ str = g_strdup_printf ("test-requirements");
+ gst_rtsp_message_add_header (&request, GST_RTSP_HDR_REQUIRE, str);
+ g_free (str);
+
+ gst_rtsp_client_set_send_func (client, test_response_200, NULL, NULL);
+ fail_unless (gst_rtsp_client_handle_message (client,
+ &request) == GST_RTSP_OK);
+ gst_rtsp_message_unset (&request);
+
+ /* unsupported option */
+ fail_unless (gst_rtsp_message_init_request (&request, GST_RTSP_OPTIONS,
+ "rtsp://localhost/test") == GST_RTSP_OK);
+ str = g_strdup_printf ("test-not-supported1");
+ gst_rtsp_message_add_header (&request, GST_RTSP_HDR_REQUIRE, str);
+ g_free (str);
+
+ expected_unsupported_header = "test-not-supported1";
+ gst_rtsp_client_set_send_func (client, test_response_551, NULL, NULL);
+ fail_unless (gst_rtsp_client_handle_message (client,
+ &request) == GST_RTSP_OK);
+ gst_rtsp_message_unset (&request);
+
+ /* more than one unsupported options */
+ fail_unless (gst_rtsp_message_init_request (&request, GST_RTSP_OPTIONS,
+ "rtsp://localhost/test") == GST_RTSP_OK);
+ str = g_strdup_printf ("test-not-supported1");
+ gst_rtsp_message_add_header (&request, GST_RTSP_HDR_REQUIRE, str);
+ g_free (str);
+ str = g_strdup_printf ("test-not-supported2");
+ gst_rtsp_message_add_header (&request, GST_RTSP_HDR_REQUIRE, str);
+ g_free (str);
+
+ expected_unsupported_header = "test-not-supported1, test-not-supported2";
+ gst_rtsp_client_set_send_func (client, test_response_551, NULL, NULL);
+ fail_unless (gst_rtsp_client_handle_message (client,
+ &request) == GST_RTSP_OK);
+ gst_rtsp_message_unset (&request);
+
+ /* supported and unsupported together */
fail_unless (gst_rtsp_message_init_request (&request, GST_RTSP_OPTIONS,
"rtsp://localhost/test") == GST_RTSP_OK);
+ str = g_strdup_printf ("test-not-supported1");
+ gst_rtsp_message_add_header (&request, GST_RTSP_HDR_REQUIRE, str);
+ g_free (str);
+ str = g_strdup_printf ("test-requirements");
+ gst_rtsp_message_add_header (&request, GST_RTSP_HDR_REQUIRE, str);
+ g_free (str);
+ str = g_strdup_printf ("test-not-supported2");
+ gst_rtsp_message_add_header (&request, GST_RTSP_HDR_REQUIRE, str);
+ g_free (str);
+
+ expected_unsupported_header = "test-not-supported1, test-not-supported2";
+ gst_rtsp_client_set_send_func (client, test_response_551, NULL, NULL);
+ fail_unless (gst_rtsp_client_handle_message (client,
+ &request) == GST_RTSP_OK);
+ gst_rtsp_message_unset (&request);
+
+ g_object_unref (client);
+}
+
+GST_END_TEST;
+
+GST_START_TEST (test_request)
+{
+ GstRTSPClient *client;
+ GstRTSPMessage request = { 0, };
+ gchar *str;
+ GstRTSPConnection *conn;
+
+ client = gst_rtsp_client_new ();
+
+ /* OPTIONS with invalid url */
+ fail_unless (gst_rtsp_message_init_request (&request, GST_RTSP_OPTIONS,
+ "foopy://padoop/") == 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_client_set_send_func (client, test_option_response_200, NULL, NULL);
- gst_rtsp_message_dump (&request);
+ gst_rtsp_client_set_send_func (client, test_response_400, NULL, NULL);
fail_unless (gst_rtsp_client_handle_message (client,
&request) == GST_RTSP_OK);
+
gst_rtsp_message_unset (&request);
/* OPTIONS with unknown session id */
g_free (str);
gst_rtsp_message_add_header (&request, GST_RTSP_HDR_SESSION, "foobar");
- gst_rtsp_client_set_send_func (client, test_option_response_454, NULL, NULL);
- gst_rtsp_message_dump (&request);
+ gst_rtsp_client_set_send_func (client, test_response_454, NULL, NULL);
+ fail_unless (gst_rtsp_client_handle_message (client,
+ &request) == GST_RTSP_OK);
+
+ gst_rtsp_message_unset (&request);
+
+ /* OPTIONS with an absolute path instead of an absolute url */
+ /* set host information */
+ create_connection (&conn);
+ fail_unless (gst_rtsp_client_set_connection (client, conn));
+ fail_unless (gst_rtsp_message_init_request (&request, GST_RTSP_OPTIONS,
+ "/test") == 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_client_set_send_func (client, test_response_200, NULL, NULL);
+ fail_unless (gst_rtsp_client_handle_message (client,
+ &request) == GST_RTSP_OK);
+ gst_rtsp_message_unset (&request);
+
+ /* OPTIONS with an absolute path instead of an absolute url with invalid
+ * host information */
+ g_object_unref (client);
+ client = gst_rtsp_client_new ();
+ fail_unless (gst_rtsp_message_init_request (&request, GST_RTSP_OPTIONS,
+ "/test") == 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_client_set_send_func (client, test_response_400, NULL, NULL);
+ fail_unless (gst_rtsp_client_handle_message (client,
+ &request) == GST_RTSP_OK);
+ gst_rtsp_message_unset (&request);
+
+ g_object_unref (client);
+}
+
+GST_END_TEST;
+
+static gboolean
+test_option_response_200 (GstRTSPClient * client, GstRTSPMessage * response,
+ gboolean close, gpointer user_data)
+{
+ GstRTSPStatusCode code;
+ const gchar *reason;
+ GstRTSPVersion version;
+ gchar *str;
+ GstRTSPMethod methods;
+
+ fail_unless (gst_rtsp_message_get_type (response) ==
+ GST_RTSP_MESSAGE_RESPONSE);
+
+ fail_unless (gst_rtsp_message_parse_response (response, &code, &reason,
+ &version)
+ == GST_RTSP_OK);
+ fail_unless (code == GST_RTSP_STS_OK);
+ fail_unless (g_str_equal (reason, "OK"));
+ fail_unless (version == GST_RTSP_VERSION_1_0);
+
+ fail_unless (gst_rtsp_message_get_header (response, GST_RTSP_HDR_CSEQ, &str,
+ 0) == GST_RTSP_OK);
+ fail_unless (atoi (str) == cseq++);
+
+ fail_unless (gst_rtsp_message_get_header (response, GST_RTSP_HDR_PUBLIC, &str,
+ 0) == GST_RTSP_OK);
+
+ methods = gst_rtsp_options_from_text (str);
+ fail_if (methods == 0);
+ fail_unless (methods == (GST_RTSP_DESCRIBE |
+ GST_RTSP_ANNOUNCE |
+ GST_RTSP_OPTIONS |
+ GST_RTSP_PAUSE |
+ GST_RTSP_PLAY |
+ GST_RTSP_RECORD |
+ GST_RTSP_SETUP |
+ GST_RTSP_GET_PARAMETER | GST_RTSP_SET_PARAMETER | GST_RTSP_TEARDOWN));
+
+ return TRUE;
+}
+
+GST_START_TEST (test_options)
+{
+ GstRTSPClient *client;
+ GstRTSPMessage request = { 0, };
+ gchar *str;
+
+ client = gst_rtsp_client_new ();
+
+ /* simple OPTIONS */
+ fail_unless (gst_rtsp_message_init_request (&request, GST_RTSP_OPTIONS,
+ "rtsp://localhost/test") == 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_client_set_send_func (client, test_option_response_200, NULL, NULL);
fail_unless (gst_rtsp_client_handle_message (client,
&request) == GST_RTSP_OK);
+ gst_rtsp_message_unset (&request);
+
+ g_object_unref (client);
+}
+GST_END_TEST;
+
+GST_START_TEST (test_describe)
+{
+ GstRTSPClient *client;
+ GstRTSPMessage request = { 0, };
+ gchar *str;
+
+ client = gst_rtsp_client_new ();
+
+ /* simple DESCRIBE for non-existing url */
+ fail_unless (gst_rtsp_message_init_request (&request, GST_RTSP_DESCRIBE,
+ "rtsp://localhost/test") == 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_client_set_send_func (client, test_response_404, NULL, NULL);
+ fail_unless (gst_rtsp_client_handle_message (client,
+ &request) == GST_RTSP_OK);
gst_rtsp_message_unset (&request);
g_object_unref (client);
+
+ /* simple DESCRIBE for an existing url */
+ client = setup_client (NULL);
+ fail_unless (gst_rtsp_message_init_request (&request, GST_RTSP_DESCRIBE,
+ "rtsp://localhost/test") == 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_client_set_send_func (client, test_response_200, NULL, NULL);
+ fail_unless (gst_rtsp_client_handle_message (client,
+ &request) == GST_RTSP_OK);
+ gst_rtsp_message_unset (&request);
+
+ teardown_client (client);
+}
+
+GST_END_TEST;
+
+static const gchar *expected_transport = NULL;
+
+static gboolean
+test_setup_response_200 (GstRTSPClient * client, GstRTSPMessage * response,
+ gboolean close, gpointer user_data)
+{
+ GstRTSPStatusCode code;
+ const gchar *reason;
+ GstRTSPVersion version;
+ gchar *str;
+ gchar *pattern;
+ GstRTSPSessionPool *session_pool;
+ GstRTSPSession *session;
+ gchar **session_hdr_params;
+
+ fail_unless (expected_transport != NULL);
+
+ fail_unless_equals_int (gst_rtsp_message_get_type (response),
+ GST_RTSP_MESSAGE_RESPONSE);
+
+ fail_unless (gst_rtsp_message_parse_response (response, &code, &reason,
+ &version)
+ == GST_RTSP_OK);
+ fail_unless_equals_int (code, GST_RTSP_STS_OK);
+ fail_unless_equals_string (reason, "OK");
+ fail_unless_equals_int (version, GST_RTSP_VERSION_1_0);
+
+ fail_unless (gst_rtsp_message_get_header (response, GST_RTSP_HDR_CSEQ, &str,
+ 0) == GST_RTSP_OK);
+ fail_unless (atoi (str) == cseq++);
+
+ fail_unless (gst_rtsp_message_get_header (response, GST_RTSP_HDR_TRANSPORT,
+ &str, 0) == GST_RTSP_OK);
+
+ pattern = g_strdup_printf ("^%s$", expected_transport);
+ fail_unless (g_regex_match_simple (pattern, str, 0, 0),
+ "Transport '%s' doesn't match pattern '%s'", str, pattern);
+ g_free (pattern);
+
+ fail_unless (gst_rtsp_message_get_header (response, GST_RTSP_HDR_SESSION,
+ &str, 0) == GST_RTSP_OK);
+ session_hdr_params = g_strsplit (str, ";", -1);
+
+ /* session-id value */
+ fail_unless (session_hdr_params[0] != NULL);
+
+ if (expected_session_timeout != 60) {
+ /* session timeout param */
+ gchar *timeout_str = g_strdup_printf ("timeout=%u",
+ expected_session_timeout);
+
+ fail_unless (session_hdr_params[1] != NULL);
+ g_strstrip (session_hdr_params[1]);
+ fail_unless (g_strcmp0 (session_hdr_params[1], timeout_str) == 0);
+ g_free (timeout_str);
+ }
+
+ session_pool = gst_rtsp_client_get_session_pool (client);
+ fail_unless (session_pool != NULL);
+
+ session = gst_rtsp_session_pool_find (session_pool, session_hdr_params[0]);
+ g_strfreev (session_hdr_params);
+
+ /* remember session id to be able to send teardown */
+ if (session_id)
+ g_free (session_id);
+ session_id = g_strdup (gst_rtsp_session_get_sessionid (session));
+ fail_unless (session_id != NULL);
+
+ fail_unless (session != NULL);
+ g_object_unref (session);
+
+ g_object_unref (session_pool);
+
+
+ return TRUE;
+}
+
+static gboolean
+test_setup_response_461 (GstRTSPClient * client,
+ GstRTSPMessage * response, gboolean close, gpointer user_data)
+{
+ GstRTSPStatusCode code;
+ const gchar *reason;
+ GstRTSPVersion version;
+ gchar *str;
+
+ fail_unless (expected_transport == NULL);
+
+ fail_unless (gst_rtsp_message_get_type (response) ==
+ GST_RTSP_MESSAGE_RESPONSE);
+
+ fail_unless (gst_rtsp_message_parse_response (response, &code, &reason,
+ &version)
+ == GST_RTSP_OK);
+ fail_unless (code == GST_RTSP_STS_UNSUPPORTED_TRANSPORT);
+ fail_unless (g_str_equal (reason, "Unsupported transport"));
+ fail_unless (version == GST_RTSP_VERSION_1_0);
+
+ fail_unless (gst_rtsp_message_get_header (response, GST_RTSP_HDR_CSEQ, &str,
+ 0) == GST_RTSP_OK);
+ fail_unless (atoi (str) == cseq++);
+
+
+ return TRUE;
+}
+
+static gboolean
+test_teardown_response_200 (GstRTSPClient * client,
+ GstRTSPMessage * response, gboolean close, gpointer user_data)
+{
+ GstRTSPStatusCode code;
+ const gchar *reason;
+ GstRTSPVersion version;
+
+ fail_unless (gst_rtsp_message_get_type (response) ==
+ GST_RTSP_MESSAGE_RESPONSE);
+
+ fail_unless (gst_rtsp_message_parse_response (response, &code, &reason,
+ &version)
+ == GST_RTSP_OK);
+ fail_unless (code == GST_RTSP_STS_OK);
+ fail_unless (g_str_equal (reason, "OK"));
+ fail_unless (version == GST_RTSP_VERSION_1_0);
+
+ return TRUE;
+}
+
+static void
+send_teardown (GstRTSPClient * client)
+{
+ GstRTSPMessage request = { 0, };
+ gchar *str;
+
+ fail_unless (session_id != NULL);
+ fail_unless (gst_rtsp_message_init_request (&request, GST_RTSP_TEARDOWN,
+ "rtsp://localhost/test") == GST_RTSP_OK);
+ str = g_strdup_printf ("%d", cseq);
+ gst_rtsp_message_take_header (&request, GST_RTSP_HDR_CSEQ, str);
+ gst_rtsp_message_add_header (&request, GST_RTSP_HDR_SESSION, session_id);
+ gst_rtsp_client_set_send_func (client, test_teardown_response_200,
+ NULL, NULL);
+ fail_unless (gst_rtsp_client_handle_message (client,
+ &request) == GST_RTSP_OK);
+ gst_rtsp_message_unset (&request);
+ g_free (session_id);
+ session_id = NULL;
+}
+
+GST_START_TEST (test_setup_tcp)
+{
+ 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));
+
+ fail_unless (gst_rtsp_message_init_request (&request, GST_RTSP_SETUP,
+ "rtsp://localhost/test") == 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");
+
+ 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);
+
+ send_teardown (client);
+ teardown_client (client);
+}
+
+GST_END_TEST;
+
+static GstRTSPClient *
+setup_multicast_client (guint max_ttl)
+{
+ GstRTSPClient *client;
+ GstRTSPSessionPool *session_pool;
+ GstRTSPMountPoints *mount_points;
+ GstRTSPMediaFactory *factory;
+ GstRTSPAddressPool *address_pool;
+ GstRTSPThreadPool *thread_pool;
+
+ client = gst_rtsp_client_new ();
+
+ session_pool = gst_rtsp_session_pool_new ();
+ gst_rtsp_client_set_session_pool (client, session_pool);
+
+ mount_points = gst_rtsp_mount_points_new ();
+ factory = gst_rtsp_media_factory_new ();
+ gst_rtsp_media_factory_set_launch (factory,
+ "audiotestsrc ! audio/x-raw,rate=44100 ! audioconvert ! rtpL16pay name=pay0");
+ address_pool = gst_rtsp_address_pool_new ();
+ fail_unless (gst_rtsp_address_pool_add_range (address_pool,
+ "233.252.0.1", "233.252.0.1", 5000, 5010, 1));
+ gst_rtsp_media_factory_set_address_pool (factory, address_pool);
+ gst_rtsp_media_factory_add_role (factory, "user",
+ "media.factory.access", G_TYPE_BOOLEAN, TRUE,
+ "media.factory.construct", G_TYPE_BOOLEAN, TRUE, NULL);
+ gst_rtsp_mount_points_add_factory (mount_points, "/test", factory);
+ gst_rtsp_client_set_mount_points (client, mount_points);
+ gst_rtsp_media_factory_set_max_mcast_ttl (factory, max_ttl);
+
+ thread_pool = gst_rtsp_thread_pool_new ();
+ gst_rtsp_client_set_thread_pool (client, thread_pool);
+
+ g_object_unref (mount_points);
+ g_object_unref (session_pool);
+ g_object_unref (address_pool);
+ g_object_unref (thread_pool);
+
+ return client;
+}
+
+GST_START_TEST (test_client_multicast_transport_404)
+{
+ GstRTSPClient *client;
+ GstRTSPMessage request = { 0, };
+ gchar *str;
+
+ client = setup_multicast_client (1);
+
+ /* simple SETUP for non-existing url */
+ fail_unless (gst_rtsp_message_init_request (&request, GST_RTSP_SETUP,
+ "rtsp://localhost/test2/stream=0") == GST_RTSP_OK);
+ str = g_strdup_printf ("%d", cseq);
+ gst_rtsp_message_take_header (&request, GST_RTSP_HDR_CSEQ, str);
+ gst_rtsp_message_add_header (&request, GST_RTSP_HDR_TRANSPORT,
+ "RTP/AVP;multicast");
+
+ gst_rtsp_client_set_send_func (client, test_response_404, NULL, NULL);
+ fail_unless (gst_rtsp_client_handle_message (client,
+ &request) == GST_RTSP_OK);
+ gst_rtsp_message_unset (&request);
+
+ teardown_client (client);
+}
+
+GST_END_TEST;
+
+static void
+new_session_cb (GObject * client, GstRTSPSession * session, gpointer user_data)
+{
+ GST_DEBUG ("%p: new session %p", client, session);
+ gst_rtsp_session_set_timeout (session, expected_session_timeout);
+}
+
+GST_START_TEST (test_client_multicast_transport)
+{
+ GstRTSPClient *client;
+ GstRTSPMessage request = { 0, };
+ gchar *str;
+
+ client = setup_multicast_client (1);
+
+ expected_session_timeout = 20;
+ g_signal_connect (G_OBJECT (client), "new-session",
+ G_CALLBACK (new_session_cb), NULL);
+
+ /* simple SETUP with a valid URI and multicast */
+ 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_take_header (&request, GST_RTSP_HDR_CSEQ, str);
+ gst_rtsp_message_add_header (&request, GST_RTSP_HDR_TRANSPORT,
+ "RTP/AVP;multicast");
+
+ expected_transport = "RTP/AVP;multicast;destination=233.252.0.1;"
+ "ttl=1;port=5000-5001;mode=\"PLAY\"";
+ gst_rtsp_client_set_send_func (client, test_setup_response_200, NULL, NULL);
+ fail_unless (gst_rtsp_client_handle_message (client,
+ &request) == GST_RTSP_OK);
+ gst_rtsp_message_unset (&request);
+ expected_transport = NULL;
+ expected_session_timeout = 60;
+
+ send_teardown (client);
+
+ teardown_client (client);
+}
+
+GST_END_TEST;
+
+GST_START_TEST (test_client_multicast_ignore_transport_specific)
+{
+ GstRTSPClient *client;
+ GstRTSPMessage request = { 0, };
+ gchar *str;
+
+ client = setup_multicast_client (1);
+
+ /* simple SETUP with a valid URI and multicast and a specific dest,
+ * but ignore it */
+ 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_take_header (&request, GST_RTSP_HDR_CSEQ, str);
+ gst_rtsp_message_add_header (&request, GST_RTSP_HDR_TRANSPORT,
+ "RTP/AVP;multicast;destination=233.252.0.2;ttl=2;port=5001-5006;");
+
+ expected_transport = "RTP/AVP;multicast;destination=233.252.0.1;"
+ "ttl=1;port=5000-5001;mode=\"PLAY\"";
+ gst_rtsp_client_set_send_func (client, test_setup_response_200, NULL, NULL);
+ fail_unless (gst_rtsp_client_handle_message (client,
+ &request) == GST_RTSP_OK);
+ gst_rtsp_message_unset (&request);
+ expected_transport = NULL;
+
+ send_teardown (client);
+
+ teardown_client (client);
+}
+
+GST_END_TEST;
+
+static void
+multicast_transport_specific (void)
+{
+ GstRTSPClient *client;
+ GstRTSPMessage request = { 0, };
+ gchar *str;
+ GstRTSPSessionPool *session_pool;
+ GstRTSPContext ctx = { NULL };
+
+ client = setup_multicast_client (1);
+
+ ctx.client = client;
+ ctx.auth = gst_rtsp_auth_new ();
+ ctx.token =
+ gst_rtsp_token_new (GST_RTSP_TOKEN_TRANSPORT_CLIENT_SETTINGS,
+ G_TYPE_BOOLEAN, TRUE, GST_RTSP_TOKEN_MEDIA_FACTORY_ROLE, G_TYPE_STRING,
+ "user", NULL);
+ gst_rtsp_context_push_current (&ctx);
+
+ expected_transport = "RTP/AVP;multicast;destination=233.252.0.1;"
+ "ttl=1;port=5000-5001;mode=\"PLAY\"";
+
+ /* simple SETUP with a valid URI */
+ 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_take_header (&request, GST_RTSP_HDR_CSEQ, str);
+ gst_rtsp_message_add_header (&request, GST_RTSP_HDR_TRANSPORT,
+ expected_transport);
+
+ gst_rtsp_client_set_send_func (client, test_setup_response_200, NULL, NULL);
+ fail_unless (gst_rtsp_client_handle_message (client,
+ &request) == GST_RTSP_OK);
+ gst_rtsp_message_unset (&request);
+
+ gst_rtsp_client_set_send_func (client, test_setup_response_200, NULL, NULL);
+ session_pool = gst_rtsp_client_get_session_pool (client);
+ fail_unless (session_pool != NULL);
+ fail_unless (gst_rtsp_session_pool_get_n_sessions (session_pool) == 1);
+ g_object_unref (session_pool);
+
+ /* send PLAY request */
+ fail_unless (gst_rtsp_message_init_request (&request, GST_RTSP_PLAY,
+ "rtsp://localhost/test") == GST_RTSP_OK);
+ str = g_strdup_printf ("%d", cseq);
+ gst_rtsp_message_take_header (&request, GST_RTSP_HDR_CSEQ, str);
+ gst_rtsp_message_add_header (&request, GST_RTSP_HDR_SESSION, session_id);
+ gst_rtsp_client_set_send_func (client, test_response_200, NULL, NULL);
+ fail_unless (gst_rtsp_client_handle_message (client,
+ &request) == GST_RTSP_OK);
+ gst_rtsp_message_unset (&request);
+
+ send_teardown (client);
+ teardown_client (client);
+ g_object_unref (ctx.auth);
+ gst_rtsp_token_unref (ctx.token);
+ gst_rtsp_context_pop_current (&ctx);
+}
+
+/* CASE: multicast address requested by the client exists in the address pool */
+GST_START_TEST (test_client_multicast_transport_specific)
+{
+ expected_transport = "RTP/AVP;multicast;destination=233.252.0.1;"
+ "ttl=1;port=5000-5001;mode=\"PLAY\"";
+ multicast_transport_specific ();
+ expected_transport = NULL;
+}
+
+GST_END_TEST;
+
+/* CASE: multicast address requested by the client does not exist in the address pool */
+GST_START_TEST (test_client_multicast_transport_specific_no_address_in_pool)
+{
+ expected_transport = "RTP/AVP;multicast;destination=234.252.0.3;"
+ "ttl=1;port=6000-6001;mode=\"PLAY\"";
+ multicast_transport_specific ();
+ expected_transport = NULL;
+}
+
+GST_END_TEST;
+
+static gboolean
+test_response_sdp (GstRTSPClient * client, GstRTSPMessage * response,
+ gboolean close, gpointer user_data)
+{
+ guint8 *data;
+ guint size;
+ GstSDPMessage *sdp_msg;
+ const GstSDPMedia *sdp_media;
+ const GstSDPBandwidth *bw;
+ gint bandwidth_val = GPOINTER_TO_INT (user_data);
+
+ fail_unless (gst_rtsp_message_get_body (response, &data, &size)
+ == GST_RTSP_OK);
+ gst_sdp_message_new (&sdp_msg);
+ fail_unless (gst_sdp_message_parse_buffer (data, size, sdp_msg)
+ == GST_SDP_OK);
+
+ /* session description */
+ /* v= */
+ fail_unless (gst_sdp_message_get_version (sdp_msg) != NULL);
+ /* o= */
+ fail_unless (gst_sdp_message_get_origin (sdp_msg) != NULL);
+ /* s= */
+ fail_unless (gst_sdp_message_get_session_name (sdp_msg) != NULL);
+ /* t=0 0 */
+ fail_unless (gst_sdp_message_times_len (sdp_msg) == 0);
+
+ /* verify number of medias */
+ fail_unless (gst_sdp_message_medias_len (sdp_msg) == 1);
+
+ /* media description */
+ sdp_media = gst_sdp_message_get_media (sdp_msg, 0);
+ fail_unless (sdp_media != NULL);
+
+ /* m= */
+ fail_unless (gst_sdp_media_get_media (sdp_media) != NULL);
+
+ /* media bandwidth */
+ if (bandwidth_val) {
+ fail_unless (gst_sdp_media_bandwidths_len (sdp_media) == 1);
+ bw = gst_sdp_media_get_bandwidth (sdp_media, 0);
+ fail_unless (bw != NULL);
+ fail_unless (g_strcmp0 (bw->bwtype, "AS") == 0);
+ fail_unless (bw->bandwidth == bandwidth_val);
+ } else {
+ fail_unless (gst_sdp_media_bandwidths_len (sdp_media) == 0);
+ }
+
+ gst_sdp_message_free (sdp_msg);
+
+ return TRUE;
+}
+
+static void
+test_client_sdp (const gchar * launch_line, guint * bandwidth_val)
+{
+ GstRTSPClient *client;
+ GstRTSPMessage request = { 0, };
+ gchar *str;
+
+ /* simple DESCRIBE for an existing url */
+ client = setup_client (launch_line);
+ fail_unless (gst_rtsp_message_init_request (&request, GST_RTSP_DESCRIBE,
+ "rtsp://localhost/test") == 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_client_set_send_func (client, test_response_sdp,
+ (gpointer) bandwidth_val, NULL);
+ fail_unless (gst_rtsp_client_handle_message (client,
+ &request) == GST_RTSP_OK);
+ gst_rtsp_message_unset (&request);
+
+ teardown_client (client);
+}
+
+GST_START_TEST (test_client_sdp_with_max_bitrate_tag)
+{
+ test_client_sdp ("videotestsrc "
+ "! taginject tags=\"maximum-bitrate=(uint)50000000\" "
+ "! video/x-raw,width=352,height=288 ! rtpgstpay name=pay0 pt=96",
+ GUINT_TO_POINTER (50000));
+
+
+ /* max-bitrate=0: no bandwidth line */
+ test_client_sdp ("videotestsrc "
+ "! taginject tags=\"maximum-bitrate=(uint)0\" "
+ "! video/x-raw,width=352,height=288 ! rtpgstpay name=pay0 pt=96",
+ GUINT_TO_POINTER (0));
+}
+
+GST_END_TEST;
+
+GST_START_TEST (test_client_sdp_with_bitrate_tag)
+{
+ test_client_sdp ("videotestsrc "
+ "! taginject tags=\"bitrate=(uint)7000000\" "
+ "! video/x-raw,width=352,height=288 ! rtpgstpay name=pay0 pt=96",
+ GUINT_TO_POINTER (7000));
+
+ /* bitrate=0: no bandwdith line */
+ test_client_sdp ("videotestsrc "
+ "! taginject tags=\"bitrate=(uint)0\" "
+ "! video/x-raw,width=352,height=288 ! rtpgstpay name=pay0 pt=96",
+ GUINT_TO_POINTER (0));
+}
+
+GST_END_TEST;
+
+GST_START_TEST (test_client_sdp_with_max_bitrate_and_bitrate_tags)
+{
+ test_client_sdp ("videotestsrc "
+ "! taginject tags=\"bitrate=(uint)7000000,maximum-bitrate=(uint)50000000\" "
+ "! video/x-raw,width=352,height=288 ! rtpgstpay name=pay0 pt=96",
+ GUINT_TO_POINTER (50000));
+
+ /* max-bitrate is zero: fallback to bitrate */
+ test_client_sdp ("videotestsrc "
+ "! taginject tags=\"bitrate=(uint)7000000,maximum-bitrate=(uint)0\" "
+ "! video/x-raw,width=352,height=288 ! rtpgstpay name=pay0 pt=96",
+ GUINT_TO_POINTER (7000));
+
+ /* max-bitrate=bitrate=0o: no bandwidth line */
+ test_client_sdp ("videotestsrc "
+ "! taginject tags=\"bitrate=(uint)0,maximum-bitrate=(uint)0\" "
+ "! video/x-raw,width=352,height=288 ! rtpgstpay name=pay0 pt=96",
+ GUINT_TO_POINTER (0));
+}
+
+GST_END_TEST;
+
+GST_START_TEST (test_client_sdp_with_no_bitrate_tags)
+{
+ test_client_sdp ("videotestsrc "
+ "! video/x-raw,width=352,height=288 ! rtpgstpay name=pay0 pt=96", NULL);
+}
+
+GST_END_TEST;
+
+static void
+mcast_transport_two_clients (gboolean shared, const gchar * transport1,
+ const gchar * expected_transport1, const gchar * addr1,
+ const gchar * transport2, const gchar * expected_transport2,
+ const gchar * addr2)
+{
+ GstRTSPClient *client1, *client2;
+ GstRTSPMessage request = { 0, };
+ gchar *str;
+ GstRTSPSessionPool *session_pool;
+ GstRTSPContext ctx = { NULL };
+ GstRTSPContext ctx2 = { NULL };
+ GstRTSPMountPoints *mount_points;
+ GstRTSPMediaFactory *factory;
+ GstRTSPAddressPool *address_pool;
+ GstRTSPThreadPool *thread_pool;
+ gchar *session_id1;
+ gchar *client_addr = NULL;
+
+ mount_points = gst_rtsp_mount_points_new ();
+ factory = gst_rtsp_media_factory_new ();
+ if (shared)
+ gst_rtsp_media_factory_set_shared (factory, TRUE);
+ gst_rtsp_media_factory_set_max_mcast_ttl (factory, 5);
+ gst_rtsp_media_factory_set_launch (factory,
+ "audiotestsrc ! audio/x-raw,rate=44100 ! audioconvert ! rtpL16pay name=pay0");
+ address_pool = gst_rtsp_address_pool_new ();
+ fail_unless (gst_rtsp_address_pool_add_range (address_pool,
+ "233.252.0.1", "233.252.0.1", 5000, 5001, 1));
+ gst_rtsp_media_factory_set_address_pool (factory, address_pool);
+ gst_rtsp_media_factory_add_role (factory, "user",
+ "media.factory.access", G_TYPE_BOOLEAN, TRUE,
+ "media.factory.construct", G_TYPE_BOOLEAN, TRUE, NULL);
+ gst_rtsp_mount_points_add_factory (mount_points, "/test", factory);
+ session_pool = gst_rtsp_session_pool_new ();
+ thread_pool = gst_rtsp_thread_pool_new ();
+
+ /* first multicast client with transport specific request */
+ client1 = gst_rtsp_client_new ();
+ gst_rtsp_client_set_session_pool (client1, session_pool);
+ gst_rtsp_client_set_mount_points (client1, mount_points);
+ gst_rtsp_client_set_thread_pool (client1, thread_pool);
+
+ ctx.client = client1;
+ ctx.auth = gst_rtsp_auth_new ();
+ ctx.token =
+ gst_rtsp_token_new (GST_RTSP_TOKEN_TRANSPORT_CLIENT_SETTINGS,
+ G_TYPE_BOOLEAN, TRUE, GST_RTSP_TOKEN_MEDIA_FACTORY_ROLE, G_TYPE_STRING,
+ "user", NULL);
+ gst_rtsp_context_push_current (&ctx);
+
+ expected_transport = expected_transport1;
+
+ /* send SETUP request */
+ 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_take_header (&request, GST_RTSP_HDR_CSEQ, str);
+ gst_rtsp_message_add_header (&request, GST_RTSP_HDR_TRANSPORT, transport1);
+
+ gst_rtsp_client_set_send_func (client1, test_setup_response_200, NULL, NULL);
+ fail_unless (gst_rtsp_client_handle_message (client1,
+ &request) == GST_RTSP_OK);
+ gst_rtsp_message_unset (&request);
+ expected_transport = NULL;
+
+ /* send PLAY request */
+ fail_unless (gst_rtsp_message_init_request (&request, GST_RTSP_PLAY,
+ "rtsp://localhost/test") == GST_RTSP_OK);
+ str = g_strdup_printf ("%d", cseq);
+ gst_rtsp_message_take_header (&request, GST_RTSP_HDR_CSEQ, str);
+ gst_rtsp_message_add_header (&request, GST_RTSP_HDR_SESSION, session_id);
+ gst_rtsp_client_set_send_func (client1, test_response_200, NULL, NULL);
+ fail_unless (gst_rtsp_client_handle_message (client1,
+ &request) == GST_RTSP_OK);
+ gst_rtsp_message_unset (&request);
+
+ /* check address */
+ client_addr = gst_rtsp_stream_get_multicast_client_addresses (ctx.stream);
+ fail_if (client_addr == NULL);
+ fail_unless (g_str_equal (client_addr, addr1));
+ g_free (client_addr);
+
+ gst_rtsp_context_pop_current (&ctx);
+ session_id1 = g_strdup (session_id);
+
+ /* second multicast client with transport specific request */
+ cseq = 0;
+ client2 = gst_rtsp_client_new ();
+ gst_rtsp_client_set_session_pool (client2, session_pool);
+ gst_rtsp_client_set_mount_points (client2, mount_points);
+ gst_rtsp_client_set_thread_pool (client2, thread_pool);
+
+ ctx2.client = client2;
+ ctx2.auth = gst_rtsp_auth_new ();
+ ctx2.token =
+ gst_rtsp_token_new (GST_RTSP_TOKEN_TRANSPORT_CLIENT_SETTINGS,
+ G_TYPE_BOOLEAN, TRUE, GST_RTSP_TOKEN_MEDIA_FACTORY_ROLE, G_TYPE_STRING,
+ "user", NULL);
+ gst_rtsp_context_push_current (&ctx2);
+
+ expected_transport = expected_transport2;
+
+ /* send SETUP request */
+ 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_take_header (&request, GST_RTSP_HDR_CSEQ, str);
+ gst_rtsp_message_add_header (&request, GST_RTSP_HDR_TRANSPORT, transport2);
+
+ gst_rtsp_client_set_send_func (client2, test_setup_response_200, NULL, NULL);
+ fail_unless (gst_rtsp_client_handle_message (client2,
+ &request) == GST_RTSP_OK);
+ gst_rtsp_message_unset (&request);
+ expected_transport = NULL;
+
+ /* send PLAY request */
+ fail_unless (gst_rtsp_message_init_request (&request, GST_RTSP_PLAY,
+ "rtsp://localhost/test") == GST_RTSP_OK);
+ str = g_strdup_printf ("%d", cseq);
+ gst_rtsp_message_take_header (&request, GST_RTSP_HDR_CSEQ, str);
+ gst_rtsp_message_add_header (&request, GST_RTSP_HDR_SESSION, session_id);
+ gst_rtsp_client_set_send_func (client2, test_response_200, NULL, NULL);
+ fail_unless (gst_rtsp_client_handle_message (client2,
+ &request) == GST_RTSP_OK);
+ gst_rtsp_message_unset (&request);
+
+ /* check addresses */
+ client_addr = gst_rtsp_stream_get_multicast_client_addresses (ctx2.stream);
+ fail_if (client_addr == NULL);
+ if (shared) {
+ if (g_str_equal (addr1, addr2)) {
+ fail_unless (g_str_equal (client_addr, addr1));
+ } else {
+ gchar *addr_str = g_strdup_printf ("%s,%s", addr2, addr1);
+ fail_unless (g_str_equal (client_addr, addr_str));
+ g_free (addr_str);
+ }
+ } else {
+ fail_unless (g_str_equal (client_addr, addr2));
+ }
+ g_free (client_addr);
+
+ send_teardown (client2);
+ gst_rtsp_context_pop_current (&ctx2);
+
+ gst_rtsp_context_push_current (&ctx);
+ session_id = session_id1;
+ send_teardown (client1);
+ gst_rtsp_context_pop_current (&ctx);
+
+ teardown_client (client1);
+ teardown_client (client2);
+ g_object_unref (ctx.auth);
+ g_object_unref (ctx2.auth);
+ gst_rtsp_token_unref (ctx.token);
+ gst_rtsp_token_unref (ctx2.token);
+ g_object_unref (mount_points);
+ g_object_unref (session_pool);
+ g_object_unref (address_pool);
+ g_object_unref (thread_pool);
+}
+
+/* test if two multicast clients can choose different transport settings
+ * CASE: media is shared */
+GST_START_TEST
+ (test_client_multicast_transport_specific_two_clients_shared_media) {
+ const gchar *transport_client_1 = "RTP/AVP;multicast;destination=233.252.0.1;"
+ "ttl=1;port=5000-5001;mode=\"PLAY\"";
+ const gchar *expected_transport_1 = transport_client_1;
+ const gchar *addr_client_1 = "233.252.0.1:5000";
+
+ const gchar *transport_client_2 = "RTP/AVP;multicast;destination=233.252.0.2;"
+ "ttl=1;port=5002-5003;mode=\"PLAY\"";
+ const gchar *expected_transport_2 = transport_client_2;
+ const gchar *addr_client_2 = "233.252.0.2:5002";
+
+ mcast_transport_two_clients (TRUE, transport_client_1,
+ expected_transport_1, addr_client_1, transport_client_2,
+ expected_transport_2, addr_client_2);
+}
+
+GST_END_TEST;
+
+/* test if two multicast clients can choose different transport settings
+ * CASE: media is not shared */
+GST_START_TEST (test_client_multicast_transport_specific_two_clients)
+{
+ const gchar *transport_client_1 = "RTP/AVP;multicast;destination=233.252.0.1;"
+ "ttl=1;port=5000-5001;mode=\"PLAY\"";
+ const gchar *expected_transport_1 = transport_client_1;
+ const gchar *addr_client_1 = "233.252.0.1:5000";
+
+ const gchar *transport_client_2 = "RTP/AVP;multicast;destination=233.252.0.2;"
+ "ttl=1;port=5002-5003;mode=\"PLAY\"";
+ const gchar *expected_transport_2 = transport_client_2;
+ const gchar *addr_client_2 = "233.252.0.2:5002";
+
+ mcast_transport_two_clients (FALSE, transport_client_1,
+ expected_transport_1, addr_client_1, transport_client_2,
+ expected_transport_2, addr_client_2);
+}
+
+GST_END_TEST;
+
+/* test if two multicast clients can choose the same transport settings.
+ * CASE: media is shared */
+GST_START_TEST
+ (test_client_multicast_transport_specific_two_clients_shared_media_same_transport)
+{
+
+ const gchar *transport_client_1 = "RTP/AVP;multicast;destination=233.252.0.1;"
+ "ttl=1;port=5000-5001;mode=\"PLAY\"";
+ const gchar *expected_transport_1 = transport_client_1;
+ const gchar *addr_client_1 = "233.252.0.1:5000";
+
+ const gchar *transport_client_2 = transport_client_1;
+ const gchar *expected_transport_2 = expected_transport_1;
+ const gchar *addr_client_2 = addr_client_1;
+
+ mcast_transport_two_clients (TRUE, transport_client_1,
+ expected_transport_1, addr_client_1, transport_client_2,
+ expected_transport_2, addr_client_2);
+}
+
+GST_END_TEST;
+
+/* test if two multicast clients get the same transport settings without
+ * requesting specific transport.
+ * CASE: media is shared */
+GST_START_TEST (test_client_multicast_two_clients_shared_media)
+{
+ const gchar *transport_client_1 = "RTP/AVP;multicast;mode=\"PLAY\"";
+ const gchar *expected_transport_1 =
+ "RTP/AVP;multicast;destination=233.252.0.1;"
+ "ttl=1;port=5000-5001;mode=\"PLAY\"";
+ const gchar *addr_client_1 = "233.252.0.1:5000";
+
+ const gchar *transport_client_2 = transport_client_1;
+ const gchar *expected_transport_2 = expected_transport_1;
+ const gchar *addr_client_2 = addr_client_1;
+
+ mcast_transport_two_clients (TRUE, transport_client_1,
+ expected_transport_1, addr_client_1, transport_client_2,
+ expected_transport_2, addr_client_2);
+}
+
+GST_END_TEST;
+
+/* test if two multicast clients get the different transport settings: the first client
+ * requests the specific transport configuration while the second client lets
+ * the server select the multicast address and the ports.
+ * CASE: media is shared */
+GST_START_TEST
+ (test_client_multicast_two_clients_first_specific_transport_shared_media) {
+ const gchar *transport_client_1 = "RTP/AVP;multicast;destination=233.252.0.1;"
+ "ttl=1;port=5000-5001;mode=\"PLAY\"";
+ const gchar *expected_transport_1 = transport_client_1;
+ const gchar *addr_client_1 = "233.252.0.1:5000";
+
+ const gchar *transport_client_2 = "RTP/AVP;multicast;mode=\"PLAY\"";
+ const gchar *expected_transport_2 = expected_transport_1;
+ const gchar *addr_client_2 = addr_client_1;
+
+ mcast_transport_two_clients (TRUE, transport_client_1,
+ expected_transport_1, addr_client_1, transport_client_2,
+ expected_transport_2, addr_client_2);
+}
+
+GST_END_TEST;
+/* test if two multicast clients get the different transport settings: the first client lets
+ * the server select the multicast address and the ports while the second client requests
+ * the specific transport configuration.
+ * CASE: media is shared */
+GST_START_TEST
+ (test_client_multicast_two_clients_second_specific_transport_shared_media) {
+ const gchar *transport_client_1 = "RTP/AVP;multicast;mode=\"PLAY\"";
+ const gchar *expected_transport_1 =
+ "RTP/AVP;multicast;destination=233.252.0.1;"
+ "ttl=1;port=5000-5001;mode=\"PLAY\"";
+ const gchar *addr_client_1 = "233.252.0.1:5000";
+
+ const gchar *transport_client_2 = "RTP/AVP;multicast;destination=233.252.0.2;"
+ "ttl=2;port=5004-5005;mode=\"PLAY\"";
+ const gchar *expected_transport_2 = transport_client_2;
+ const gchar *addr_client_2 = "233.252.0.2:5004";
+
+ mcast_transport_two_clients (TRUE, transport_client_1,
+ expected_transport_1, addr_client_1, transport_client_2,
+ expected_transport_2, addr_client_2);
+}
+
+GST_END_TEST;
+
+/* test if the maximum ttl multicast value is chosen by the server
+ * CASE: the first client provides the highest ttl value */
+GST_START_TEST (test_client_multicast_max_ttl_first_client)
+{
+ const gchar *transport_client_1 = "RTP/AVP;multicast;destination=233.252.0.1;"
+ "ttl=3;port=5000-5001;mode=\"PLAY\"";
+ const gchar *expected_transport_1 = transport_client_1;
+ const gchar *addr_client_1 = "233.252.0.1:5000";
+
+ const gchar *transport_client_2 = "RTP/AVP;multicast;destination=233.252.0.2;"
+ "ttl=1;port=5002-5003;mode=\"PLAY\"";
+ const gchar *expected_transport_2 =
+ "RTP/AVP;multicast;destination=233.252.0.2;"
+ "ttl=3;port=5002-5003;mode=\"PLAY\"";
+ const gchar *addr_client_2 = "233.252.0.2:5002";
+
+ mcast_transport_two_clients (TRUE, transport_client_1,
+ expected_transport_1, addr_client_1, transport_client_2,
+ expected_transport_2, addr_client_2);
+}
+
+GST_END_TEST;
+
+/* test if the maximum ttl multicast value is chosen by the server
+ * CASE: the second client provides the highest ttl value */
+GST_START_TEST (test_client_multicast_max_ttl_second_client)
+{
+ const gchar *transport_client_1 = "RTP/AVP;multicast;destination=233.252.0.1;"
+ "ttl=2;port=5000-5001;mode=\"PLAY\"";
+ const gchar *expected_transport_1 = transport_client_1;
+ const gchar *addr_client_1 = "233.252.0.1:5000";
+
+ const gchar *transport_client_2 = "RTP/AVP;multicast;destination=233.252.0.2;"
+ "ttl=4;port=5002-5003;mode=\"PLAY\"";
+ const gchar *expected_transport_2 = transport_client_2;
+ const gchar *addr_client_2 = "233.252.0.2:5002";
+
+ mcast_transport_two_clients (TRUE, transport_client_1,
+ expected_transport_1, addr_client_1, transport_client_2,
+ expected_transport_2, addr_client_2);
+}
+
+GST_END_TEST;
+GST_START_TEST (test_client_multicast_invalid_ttl)
+{
+ GstRTSPClient *client;
+ GstRTSPMessage request = { 0, };
+ gchar *str;
+ GstRTSPSessionPool *session_pool;
+ GstRTSPContext ctx = { NULL };
+
+ client = setup_multicast_client (3);
+
+ ctx.client = client;
+ ctx.auth = gst_rtsp_auth_new ();
+ ctx.token =
+ gst_rtsp_token_new (GST_RTSP_TOKEN_TRANSPORT_CLIENT_SETTINGS,
+ G_TYPE_BOOLEAN, TRUE, GST_RTSP_TOKEN_MEDIA_FACTORY_ROLE, G_TYPE_STRING,
+ "user", NULL);
+ gst_rtsp_context_push_current (&ctx);
+
+ /* simple SETUP with an invalid ttl=0 */
+ 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_take_header (&request, GST_RTSP_HDR_CSEQ, str);
+ gst_rtsp_message_add_header (&request, GST_RTSP_HDR_TRANSPORT,
+ "RTP/AVP;multicast;destination=233.252.0.1;ttl=0;port=5000-5001;");
+
+ gst_rtsp_client_set_send_func (client, test_setup_response_461, NULL, NULL);
+ fail_unless (gst_rtsp_client_handle_message (client,
+ &request) == GST_RTSP_OK);
+ gst_rtsp_message_unset (&request);
+
+ session_pool = gst_rtsp_client_get_session_pool (client);
+ fail_unless (session_pool != NULL);
+ fail_unless (gst_rtsp_session_pool_get_n_sessions (session_pool) == 0);
+ g_object_unref (session_pool);
+
+ teardown_client (client);
+ g_object_unref (ctx.auth);
+ gst_rtsp_token_unref (ctx.token);
+ gst_rtsp_context_pop_current (&ctx);
}
GST_END_TEST;
suite_add_tcase (s, tc);
tcase_set_timeout (tc, 20);
+ tcase_add_test (tc, test_require);
+ tcase_add_test (tc, test_request);
tcase_add_test (tc, test_options);
+ tcase_add_test (tc, test_describe);
+ tcase_add_test (tc, test_setup_tcp);
+ 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);
+ tcase_add_test (tc, test_client_multicast_transport_specific);
+ tcase_add_test (tc, test_client_sdp_with_max_bitrate_tag);
+ tcase_add_test (tc, test_client_sdp_with_bitrate_tag);
+ tcase_add_test (tc, test_client_sdp_with_max_bitrate_and_bitrate_tags);
+ tcase_add_test (tc, test_client_sdp_with_no_bitrate_tags);
+ tcase_add_test (tc,
+ test_client_multicast_transport_specific_two_clients_shared_media);
+ tcase_add_test (tc, test_client_multicast_transport_specific_two_clients);
+ tcase_add_test (tc,
+ test_client_multicast_transport_specific_two_clients_shared_media_same_transport);
+ tcase_add_test (tc, test_client_multicast_two_clients_shared_media);
+ tcase_add_test (tc,
+ test_client_multicast_two_clients_first_specific_transport_shared_media);
+ tcase_add_test (tc,
+ test_client_multicast_two_clients_second_specific_transport_shared_media);
+ tcase_add_test (tc,
+ test_client_multicast_transport_specific_no_address_in_pool);
+ tcase_add_test (tc, test_client_multicast_max_ttl_first_client);
+ tcase_add_test (tc, test_client_multicast_max_ttl_second_client);
+ tcase_add_test (tc, test_client_multicast_invalid_ttl);
return s;
}