b2e0dd3847f0881a425056a4eb9b425e5dfbbcf1
[platform/upstream/gstreamer.git] / tests / check / gst / client.c
1 /* GStreamer
2  * Copyright (C) 2012 Wim Taymans <wim.taymans@gmail.com>
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Library General Public
6  * License as published by the Free Software Foundation; either
7  * version 2 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Library General Public License for more details.
13  *
14  * You should have received a copy of the GNU Library General Public
15  * License along with this library; if not, write to the
16  * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
17  * Boston, MA 02110-1301, USA.
18  */
19
20 #include <gst/check/gstcheck.h>
21
22 #include <rtsp-client.h>
23
24 #define VIDEO_PIPELINE "videotestsrc ! " \
25   "video/x-raw,width=352,height=288 ! " \
26   "rtpgstpay name=pay0 pt=96"
27 #define AUDIO_PIPELINE "audiotestsrc ! " \
28   "audio/x-raw,rate=8000 ! " \
29   "rtpgstpay name=pay1 pt=97"
30
31 static gchar *session_id;
32 static gint cseq;
33 static guint expected_session_timeout = 60;
34 static const gchar *expected_unsupported_header;
35
36 static gboolean
37 test_response_200 (GstRTSPClient * client, GstRTSPMessage * response,
38     gboolean close, gpointer user_data)
39 {
40   GstRTSPStatusCode code;
41   const gchar *reason;
42   GstRTSPVersion version;
43
44   fail_unless (gst_rtsp_message_get_type (response) ==
45       GST_RTSP_MESSAGE_RESPONSE);
46
47   fail_unless (gst_rtsp_message_parse_response (response, &code, &reason,
48           &version)
49       == GST_RTSP_OK);
50   fail_unless (code == GST_RTSP_STS_OK);
51   fail_unless (g_str_equal (reason, "OK"));
52   fail_unless (version == GST_RTSP_VERSION_1_0);
53
54   return TRUE;
55 }
56
57 static gboolean
58 test_response_400 (GstRTSPClient * client, GstRTSPMessage * response,
59     gboolean close, gpointer user_data)
60 {
61   GstRTSPStatusCode code;
62   const gchar *reason;
63   GstRTSPVersion version;
64
65   fail_unless (gst_rtsp_message_get_type (response) ==
66       GST_RTSP_MESSAGE_RESPONSE);
67
68   fail_unless (gst_rtsp_message_parse_response (response, &code, &reason,
69           &version)
70       == GST_RTSP_OK);
71   fail_unless (code == GST_RTSP_STS_BAD_REQUEST);
72   fail_unless (g_str_equal (reason, "Bad Request"));
73   fail_unless (version == GST_RTSP_VERSION_1_0);
74
75   return TRUE;
76 }
77
78 static gboolean
79 test_response_404 (GstRTSPClient * client, GstRTSPMessage * response,
80     gboolean close, gpointer user_data)
81 {
82   GstRTSPStatusCode code;
83   const gchar *reason;
84   GstRTSPVersion version;
85
86   fail_unless (gst_rtsp_message_get_type (response) ==
87       GST_RTSP_MESSAGE_RESPONSE);
88
89   fail_unless (gst_rtsp_message_parse_response (response, &code, &reason,
90           &version)
91       == GST_RTSP_OK);
92   fail_unless (code == GST_RTSP_STS_NOT_FOUND);
93   fail_unless (g_str_equal (reason, "Not Found"));
94   fail_unless (version == GST_RTSP_VERSION_1_0);
95
96   return TRUE;
97 }
98
99 static gboolean
100 test_response_454 (GstRTSPClient * client, GstRTSPMessage * response,
101     gboolean close, gpointer user_data)
102 {
103   GstRTSPStatusCode code;
104   const gchar *reason;
105   GstRTSPVersion version;
106
107   fail_unless (gst_rtsp_message_get_type (response) ==
108       GST_RTSP_MESSAGE_RESPONSE);
109
110   fail_unless (gst_rtsp_message_parse_response (response, &code, &reason,
111           &version)
112       == GST_RTSP_OK);
113   fail_unless (code == GST_RTSP_STS_SESSION_NOT_FOUND);
114   fail_unless (g_str_equal (reason, "Session Not Found"));
115   fail_unless (version == GST_RTSP_VERSION_1_0);
116
117   return TRUE;
118 }
119
120 static gboolean
121 test_response_551 (GstRTSPClient * client, GstRTSPMessage * response,
122     gboolean close, gpointer user_data)
123 {
124   GstRTSPStatusCode code;
125   const gchar *reason;
126   GstRTSPVersion version;
127   gchar *options;
128
129   fail_unless (gst_rtsp_message_get_type (response) ==
130       GST_RTSP_MESSAGE_RESPONSE);
131
132   fail_unless (gst_rtsp_message_parse_response (response, &code, &reason,
133           &version)
134       == GST_RTSP_OK);
135   fail_unless (code == GST_RTSP_STS_OPTION_NOT_SUPPORTED);
136   fail_unless (g_str_equal (reason, "Option not supported"));
137   fail_unless (gst_rtsp_message_get_header (response, GST_RTSP_HDR_UNSUPPORTED,
138           &options, 0) == GST_RTSP_OK);
139   fail_unless (!g_strcmp0 (expected_unsupported_header, options));
140   fail_unless (version == GST_RTSP_VERSION_1_0);
141
142   return TRUE;
143 }
144
145 static void
146 create_connection (GstRTSPConnection ** conn)
147 {
148   GSocket *sock;
149   GError *error = NULL;
150
151   sock = g_socket_new (G_SOCKET_FAMILY_IPV4, G_SOCKET_TYPE_STREAM,
152       G_SOCKET_PROTOCOL_TCP, &error);
153   g_assert_no_error (error);
154   fail_unless (gst_rtsp_connection_create_from_socket (sock, "127.0.0.1", 444,
155           NULL, conn) == GST_RTSP_OK);
156   g_object_unref (sock);
157 }
158
159 static GstRTSPClient *
160 setup_client (const gchar * launch_line)
161 {
162   GstRTSPClient *client;
163   GstRTSPSessionPool *session_pool;
164   GstRTSPMountPoints *mount_points;
165   GstRTSPMediaFactory *factory;
166   GstRTSPThreadPool *thread_pool;
167
168   client = gst_rtsp_client_new ();
169
170   session_pool = gst_rtsp_session_pool_new ();
171   gst_rtsp_client_set_session_pool (client, session_pool);
172
173   mount_points = gst_rtsp_mount_points_new ();
174   factory = gst_rtsp_media_factory_new ();
175   if (launch_line == NULL)
176     gst_rtsp_media_factory_set_launch (factory,
177         "( " VIDEO_PIPELINE "  " AUDIO_PIPELINE " )");
178   else
179     gst_rtsp_media_factory_set_launch (factory, launch_line);
180
181   gst_rtsp_mount_points_add_factory (mount_points, "/test", factory);
182   gst_rtsp_client_set_mount_points (client, mount_points);
183
184   thread_pool = gst_rtsp_thread_pool_new ();
185   gst_rtsp_client_set_thread_pool (client, thread_pool);
186
187   g_object_unref (mount_points);
188   g_object_unref (session_pool);
189   g_object_unref (thread_pool);
190
191   return client;
192 }
193
194 static void
195 teardown_client (GstRTSPClient * client)
196 {
197   gst_rtsp_client_set_thread_pool (client, NULL);
198   g_object_unref (client);
199 }
200
201 static gchar *
202 check_requirements_cb (GstRTSPClient * client, GstRTSPContext * ctx,
203     gchar ** req, gpointer user_data)
204 {
205   int index = 0;
206   GString *result = g_string_new ("");
207
208   while (req[index] != NULL) {
209     if (g_strcmp0 (req[index], "test-requirements")) {
210       if (result->len > 0)
211         g_string_append (result, ", ");
212       g_string_append (result, req[index]);
213     }
214     index++;
215   }
216
217   return g_string_free (result, FALSE);
218 }
219
220 GST_START_TEST (test_require)
221 {
222   GstRTSPClient *client;
223   GstRTSPMessage request = { 0, };
224   gchar *str;
225
226   client = gst_rtsp_client_new ();
227
228   /* require header without handler */
229   fail_unless (gst_rtsp_message_init_request (&request, GST_RTSP_OPTIONS,
230           "rtsp://localhost/test") == GST_RTSP_OK);
231   str = g_strdup_printf ("test-not-supported1");
232   gst_rtsp_message_add_header (&request, GST_RTSP_HDR_REQUIRE, str);
233   g_free (str);
234
235   expected_unsupported_header = "test-not-supported1";
236   gst_rtsp_client_set_send_func (client, test_response_551, NULL, NULL);
237   fail_unless (gst_rtsp_client_handle_message (client,
238           &request) == GST_RTSP_OK);
239   gst_rtsp_message_unset (&request);
240
241   g_signal_connect (G_OBJECT (client), "check-requirements",
242       G_CALLBACK (check_requirements_cb), NULL);
243
244   /* one supported option */
245   fail_unless (gst_rtsp_message_init_request (&request, GST_RTSP_OPTIONS,
246           "rtsp://localhost/test") == GST_RTSP_OK);
247   str = g_strdup_printf ("test-requirements");
248   gst_rtsp_message_add_header (&request, GST_RTSP_HDR_REQUIRE, str);
249   g_free (str);
250
251   gst_rtsp_client_set_send_func (client, test_response_200, NULL, NULL);
252   fail_unless (gst_rtsp_client_handle_message (client,
253           &request) == GST_RTSP_OK);
254   gst_rtsp_message_unset (&request);
255
256   /* unsupported option */
257   fail_unless (gst_rtsp_message_init_request (&request, GST_RTSP_OPTIONS,
258           "rtsp://localhost/test") == GST_RTSP_OK);
259   str = g_strdup_printf ("test-not-supported1");
260   gst_rtsp_message_add_header (&request, GST_RTSP_HDR_REQUIRE, str);
261   g_free (str);
262
263   expected_unsupported_header = "test-not-supported1";
264   gst_rtsp_client_set_send_func (client, test_response_551, NULL, NULL);
265   fail_unless (gst_rtsp_client_handle_message (client,
266           &request) == GST_RTSP_OK);
267   gst_rtsp_message_unset (&request);
268
269   /* more than one unsupported options */
270   fail_unless (gst_rtsp_message_init_request (&request, GST_RTSP_OPTIONS,
271           "rtsp://localhost/test") == GST_RTSP_OK);
272   str = g_strdup_printf ("test-not-supported1");
273   gst_rtsp_message_add_header (&request, GST_RTSP_HDR_REQUIRE, str);
274   g_free (str);
275   str = g_strdup_printf ("test-not-supported2");
276   gst_rtsp_message_add_header (&request, GST_RTSP_HDR_REQUIRE, str);
277   g_free (str);
278
279   expected_unsupported_header = "test-not-supported1, test-not-supported2";
280   gst_rtsp_client_set_send_func (client, test_response_551, NULL, NULL);
281   fail_unless (gst_rtsp_client_handle_message (client,
282           &request) == GST_RTSP_OK);
283   gst_rtsp_message_unset (&request);
284
285   /* supported and unsupported together */
286   fail_unless (gst_rtsp_message_init_request (&request, GST_RTSP_OPTIONS,
287           "rtsp://localhost/test") == GST_RTSP_OK);
288   str = g_strdup_printf ("test-not-supported1");
289   gst_rtsp_message_add_header (&request, GST_RTSP_HDR_REQUIRE, str);
290   g_free (str);
291   str = g_strdup_printf ("test-requirements");
292   gst_rtsp_message_add_header (&request, GST_RTSP_HDR_REQUIRE, str);
293   g_free (str);
294   str = g_strdup_printf ("test-not-supported2");
295   gst_rtsp_message_add_header (&request, GST_RTSP_HDR_REQUIRE, str);
296   g_free (str);
297
298   expected_unsupported_header = "test-not-supported1, test-not-supported2";
299   gst_rtsp_client_set_send_func (client, test_response_551, NULL, NULL);
300   fail_unless (gst_rtsp_client_handle_message (client,
301           &request) == GST_RTSP_OK);
302   gst_rtsp_message_unset (&request);
303
304   g_object_unref (client);
305 }
306
307 GST_END_TEST;
308
309 GST_START_TEST (test_request)
310 {
311   GstRTSPClient *client;
312   GstRTSPMessage request = { 0, };
313   gchar *str;
314   GstRTSPConnection *conn;
315
316   client = gst_rtsp_client_new ();
317
318   /* OPTIONS with invalid url */
319   fail_unless (gst_rtsp_message_init_request (&request, GST_RTSP_OPTIONS,
320           "foopy://padoop/") == GST_RTSP_OK);
321   str = g_strdup_printf ("%d", cseq);
322   gst_rtsp_message_add_header (&request, GST_RTSP_HDR_CSEQ, str);
323   g_free (str);
324
325   gst_rtsp_client_set_send_func (client, test_response_400, NULL, NULL);
326   fail_unless (gst_rtsp_client_handle_message (client,
327           &request) == GST_RTSP_OK);
328
329   gst_rtsp_message_unset (&request);
330
331   /* OPTIONS with unknown session id */
332   fail_unless (gst_rtsp_message_init_request (&request, GST_RTSP_OPTIONS,
333           "rtsp://localhost/test") == GST_RTSP_OK);
334   str = g_strdup_printf ("%d", cseq);
335   gst_rtsp_message_add_header (&request, GST_RTSP_HDR_CSEQ, str);
336   g_free (str);
337   gst_rtsp_message_add_header (&request, GST_RTSP_HDR_SESSION, "foobar");
338
339   gst_rtsp_client_set_send_func (client, test_response_454, NULL, NULL);
340   fail_unless (gst_rtsp_client_handle_message (client,
341           &request) == GST_RTSP_OK);
342
343   gst_rtsp_message_unset (&request);
344
345   /* OPTIONS with an absolute path instead of an absolute url */
346   /* set host information */
347   create_connection (&conn);
348   fail_unless (gst_rtsp_client_set_connection (client, conn));
349   fail_unless (gst_rtsp_message_init_request (&request, GST_RTSP_OPTIONS,
350           "/test") == GST_RTSP_OK);
351   str = g_strdup_printf ("%d", cseq);
352   gst_rtsp_message_add_header (&request, GST_RTSP_HDR_CSEQ, str);
353   g_free (str);
354
355   gst_rtsp_client_set_send_func (client, test_response_200, NULL, NULL);
356   fail_unless (gst_rtsp_client_handle_message (client,
357           &request) == GST_RTSP_OK);
358   gst_rtsp_message_unset (&request);
359
360   /* OPTIONS with an absolute path instead of an absolute url with invalid
361    * host information */
362   g_object_unref (client);
363   client = gst_rtsp_client_new ();
364   fail_unless (gst_rtsp_message_init_request (&request, GST_RTSP_OPTIONS,
365           "/test") == GST_RTSP_OK);
366   str = g_strdup_printf ("%d", cseq);
367   gst_rtsp_message_add_header (&request, GST_RTSP_HDR_CSEQ, str);
368   g_free (str);
369
370   gst_rtsp_client_set_send_func (client, test_response_400, NULL, NULL);
371   fail_unless (gst_rtsp_client_handle_message (client,
372           &request) == GST_RTSP_OK);
373   gst_rtsp_message_unset (&request);
374
375   g_object_unref (client);
376 }
377
378 GST_END_TEST;
379
380 static gboolean
381 test_option_response_200 (GstRTSPClient * client, GstRTSPMessage * response,
382     gboolean close, gpointer user_data)
383 {
384   GstRTSPStatusCode code;
385   const gchar *reason;
386   GstRTSPVersion version;
387   gchar *str;
388   GstRTSPMethod methods;
389
390   fail_unless (gst_rtsp_message_get_type (response) ==
391       GST_RTSP_MESSAGE_RESPONSE);
392
393   fail_unless (gst_rtsp_message_parse_response (response, &code, &reason,
394           &version)
395       == GST_RTSP_OK);
396   fail_unless (code == GST_RTSP_STS_OK);
397   fail_unless (g_str_equal (reason, "OK"));
398   fail_unless (version == GST_RTSP_VERSION_1_0);
399
400   fail_unless (gst_rtsp_message_get_header (response, GST_RTSP_HDR_CSEQ, &str,
401           0) == GST_RTSP_OK);
402   fail_unless (atoi (str) == cseq++);
403
404   fail_unless (gst_rtsp_message_get_header (response, GST_RTSP_HDR_PUBLIC, &str,
405           0) == GST_RTSP_OK);
406
407   methods = gst_rtsp_options_from_text (str);
408   fail_if (methods == 0);
409   fail_unless (methods == (GST_RTSP_DESCRIBE |
410           GST_RTSP_ANNOUNCE |
411           GST_RTSP_OPTIONS |
412           GST_RTSP_PAUSE |
413           GST_RTSP_PLAY |
414           GST_RTSP_RECORD |
415           GST_RTSP_SETUP |
416           GST_RTSP_GET_PARAMETER | GST_RTSP_SET_PARAMETER | GST_RTSP_TEARDOWN));
417
418   return TRUE;
419 }
420
421 GST_START_TEST (test_options)
422 {
423   GstRTSPClient *client;
424   GstRTSPMessage request = { 0, };
425   gchar *str;
426
427   client = gst_rtsp_client_new ();
428
429   /* simple OPTIONS */
430   fail_unless (gst_rtsp_message_init_request (&request, GST_RTSP_OPTIONS,
431           "rtsp://localhost/test") == GST_RTSP_OK);
432   str = g_strdup_printf ("%d", cseq);
433   gst_rtsp_message_add_header (&request, GST_RTSP_HDR_CSEQ, str);
434   g_free (str);
435
436   gst_rtsp_client_set_send_func (client, test_option_response_200, NULL, NULL);
437   fail_unless (gst_rtsp_client_handle_message (client,
438           &request) == GST_RTSP_OK);
439   gst_rtsp_message_unset (&request);
440
441   g_object_unref (client);
442 }
443
444 GST_END_TEST;
445
446 GST_START_TEST (test_describe)
447 {
448   GstRTSPClient *client;
449   GstRTSPMessage request = { 0, };
450   gchar *str;
451
452   client = gst_rtsp_client_new ();
453
454   /* simple DESCRIBE for non-existing url */
455   fail_unless (gst_rtsp_message_init_request (&request, GST_RTSP_DESCRIBE,
456           "rtsp://localhost/test") == GST_RTSP_OK);
457   str = g_strdup_printf ("%d", cseq);
458   gst_rtsp_message_add_header (&request, GST_RTSP_HDR_CSEQ, str);
459   g_free (str);
460
461   gst_rtsp_client_set_send_func (client, test_response_404, NULL, NULL);
462   fail_unless (gst_rtsp_client_handle_message (client,
463           &request) == GST_RTSP_OK);
464   gst_rtsp_message_unset (&request);
465
466   g_object_unref (client);
467
468   /* simple DESCRIBE for an existing url */
469   client = setup_client (NULL);
470   fail_unless (gst_rtsp_message_init_request (&request, GST_RTSP_DESCRIBE,
471           "rtsp://localhost/test") == GST_RTSP_OK);
472   str = g_strdup_printf ("%d", cseq);
473   gst_rtsp_message_add_header (&request, GST_RTSP_HDR_CSEQ, str);
474   g_free (str);
475
476   gst_rtsp_client_set_send_func (client, test_response_200, NULL, NULL);
477   fail_unless (gst_rtsp_client_handle_message (client,
478           &request) == GST_RTSP_OK);
479   gst_rtsp_message_unset (&request);
480
481   teardown_client (client);
482 }
483
484 GST_END_TEST;
485
486 static const gchar *expected_transport = NULL;
487
488 static gboolean
489 test_setup_response_200 (GstRTSPClient * client, GstRTSPMessage * response,
490     gboolean close, gpointer user_data)
491 {
492   GstRTSPStatusCode code;
493   const gchar *reason;
494   GstRTSPVersion version;
495   gchar *str;
496   gchar *pattern;
497   GstRTSPSessionPool *session_pool;
498   GstRTSPSession *session;
499   gchar **session_hdr_params;
500
501   fail_unless (expected_transport != NULL);
502
503   fail_unless_equals_int (gst_rtsp_message_get_type (response),
504       GST_RTSP_MESSAGE_RESPONSE);
505
506   fail_unless (gst_rtsp_message_parse_response (response, &code, &reason,
507           &version)
508       == GST_RTSP_OK);
509   fail_unless_equals_int (code, GST_RTSP_STS_OK);
510   fail_unless_equals_string (reason, "OK");
511   fail_unless_equals_int (version, GST_RTSP_VERSION_1_0);
512
513   fail_unless (gst_rtsp_message_get_header (response, GST_RTSP_HDR_CSEQ, &str,
514           0) == GST_RTSP_OK);
515   fail_unless (atoi (str) == cseq++);
516
517   fail_unless (gst_rtsp_message_get_header (response, GST_RTSP_HDR_TRANSPORT,
518           &str, 0) == GST_RTSP_OK);
519
520   pattern = g_strdup_printf ("^%s$", expected_transport);
521   fail_unless (g_regex_match_simple (pattern, str, 0, 0),
522       "Transport '%s' doesn't match pattern '%s'", str, pattern);
523   g_free (pattern);
524
525   fail_unless (gst_rtsp_message_get_header (response, GST_RTSP_HDR_SESSION,
526           &str, 0) == GST_RTSP_OK);
527   session_hdr_params = g_strsplit (str, ";", -1);
528
529   /* session-id value */
530   fail_unless (session_hdr_params[0] != NULL);
531
532   if (expected_session_timeout != 60) {
533     /* session timeout param */
534     gchar *timeout_str = g_strdup_printf ("timeout=%u",
535         expected_session_timeout);
536
537     fail_unless (session_hdr_params[1] != NULL);
538     g_strstrip (session_hdr_params[1]);
539     fail_unless (g_strcmp0 (session_hdr_params[1], timeout_str) == 0);
540     g_free (timeout_str);
541   }
542
543   session_pool = gst_rtsp_client_get_session_pool (client);
544   fail_unless (session_pool != NULL);
545
546   session = gst_rtsp_session_pool_find (session_pool, session_hdr_params[0]);
547   g_strfreev (session_hdr_params);
548
549   /* remember session id to be able to send teardown */
550   if (session_id)
551     g_free (session_id);
552   session_id = g_strdup (gst_rtsp_session_get_sessionid (session));
553   fail_unless (session_id != NULL);
554
555   fail_unless (session != NULL);
556   g_object_unref (session);
557
558   g_object_unref (session_pool);
559
560
561   return TRUE;
562 }
563
564 static gboolean
565 test_setup_response_461 (GstRTSPClient * client,
566     GstRTSPMessage * response, gboolean close, gpointer user_data)
567 {
568   GstRTSPStatusCode code;
569   const gchar *reason;
570   GstRTSPVersion version;
571   gchar *str;
572
573   fail_unless (expected_transport == NULL);
574
575   fail_unless (gst_rtsp_message_get_type (response) ==
576       GST_RTSP_MESSAGE_RESPONSE);
577
578   fail_unless (gst_rtsp_message_parse_response (response, &code, &reason,
579           &version)
580       == GST_RTSP_OK);
581   fail_unless (code == GST_RTSP_STS_UNSUPPORTED_TRANSPORT);
582   fail_unless (g_str_equal (reason, "Unsupported transport"));
583   fail_unless (version == GST_RTSP_VERSION_1_0);
584
585   fail_unless (gst_rtsp_message_get_header (response, GST_RTSP_HDR_CSEQ, &str,
586           0) == GST_RTSP_OK);
587   fail_unless (atoi (str) == cseq++);
588
589
590   return TRUE;
591 }
592
593 static gboolean
594 test_teardown_response_200 (GstRTSPClient * client,
595     GstRTSPMessage * response, gboolean close, gpointer user_data)
596 {
597   GstRTSPStatusCode code;
598   const gchar *reason;
599   GstRTSPVersion version;
600
601   fail_unless (gst_rtsp_message_get_type (response) ==
602       GST_RTSP_MESSAGE_RESPONSE);
603
604   fail_unless (gst_rtsp_message_parse_response (response, &code, &reason,
605           &version)
606       == GST_RTSP_OK);
607   fail_unless (code == GST_RTSP_STS_OK);
608   fail_unless (g_str_equal (reason, "OK"));
609   fail_unless (version == GST_RTSP_VERSION_1_0);
610
611   return TRUE;
612 }
613
614 static void
615 send_teardown (GstRTSPClient * client)
616 {
617   GstRTSPMessage request = { 0, };
618   gchar *str;
619
620   fail_unless (session_id != NULL);
621   fail_unless (gst_rtsp_message_init_request (&request, GST_RTSP_TEARDOWN,
622           "rtsp://localhost/test") == GST_RTSP_OK);
623   str = g_strdup_printf ("%d", cseq);
624   gst_rtsp_message_take_header (&request, GST_RTSP_HDR_CSEQ, str);
625   gst_rtsp_message_add_header (&request, GST_RTSP_HDR_SESSION, session_id);
626   gst_rtsp_client_set_send_func (client, test_teardown_response_200,
627       NULL, NULL);
628   fail_unless (gst_rtsp_client_handle_message (client,
629           &request) == GST_RTSP_OK);
630   gst_rtsp_message_unset (&request);
631   g_free (session_id);
632   session_id = NULL;
633 }
634
635 GST_START_TEST (test_setup_tcp)
636 {
637   GstRTSPClient *client;
638   GstRTSPConnection *conn;
639   GstRTSPMessage request = { 0, };
640   gchar *str;
641
642   client = setup_client (NULL);
643   create_connection (&conn);
644   fail_unless (gst_rtsp_client_set_connection (client, conn));
645
646   fail_unless (gst_rtsp_message_init_request (&request, GST_RTSP_SETUP,
647           "rtsp://localhost/test/stream=0") == GST_RTSP_OK);
648   str = g_strdup_printf ("%d", cseq);
649   gst_rtsp_message_add_header (&request, GST_RTSP_HDR_CSEQ, str);
650   g_free (str);
651   gst_rtsp_message_add_header (&request, GST_RTSP_HDR_TRANSPORT,
652       "RTP/AVP/TCP;unicast");
653
654   gst_rtsp_client_set_send_func (client, test_setup_response_200, NULL, NULL);
655   expected_transport =
656       "RTP/AVP/TCP;unicast;interleaved=0-1;ssrc=.*;mode=\"PLAY\"";
657   fail_unless (gst_rtsp_client_handle_message (client,
658           &request) == GST_RTSP_OK);
659
660   gst_rtsp_message_unset (&request);
661
662   send_teardown (client);
663   teardown_client (client);
664 }
665
666 GST_END_TEST;
667
668 GST_START_TEST (test_setup_tcp_two_streams_same_channels)
669 {
670   GstRTSPClient *client;
671   GstRTSPConnection *conn;
672   GstRTSPMessage request = { 0, };
673   gchar *str;
674
675   client = setup_client (NULL);
676   create_connection (&conn);
677   fail_unless (gst_rtsp_client_set_connection (client, conn));
678
679   /* test SETUP of a video stream with 0-1 as interleaved channels */
680   fail_unless (gst_rtsp_message_init_request (&request, GST_RTSP_SETUP,
681           "rtsp://localhost/test/stream=0") == GST_RTSP_OK);
682   str = g_strdup_printf ("%d", cseq);
683   gst_rtsp_message_add_header (&request, GST_RTSP_HDR_CSEQ, str);
684   g_free (str);
685   gst_rtsp_message_add_header (&request, GST_RTSP_HDR_TRANSPORT,
686       "RTP/AVP/TCP;unicast;interleaved=0-1");
687   gst_rtsp_client_set_send_func (client, test_setup_response_200, NULL, NULL);
688   expected_transport =
689       "RTP/AVP/TCP;unicast;interleaved=0-1;ssrc=.*;mode=\"PLAY\"";
690   fail_unless (gst_rtsp_client_handle_message (client,
691           &request) == GST_RTSP_OK);
692   gst_rtsp_message_unset (&request);
693
694   /* test SETUP of an audio stream with *the same* interleaved channels.
695    * we expect the server to allocate new channel numbers */
696   fail_unless (gst_rtsp_message_init_request (&request, GST_RTSP_SETUP,
697           "rtsp://localhost/test/stream=1") == GST_RTSP_OK);
698   str = g_strdup_printf ("%d", cseq);
699   gst_rtsp_message_add_header (&request, GST_RTSP_HDR_CSEQ, str);
700   g_free (str);
701   gst_rtsp_message_add_header (&request, GST_RTSP_HDR_TRANSPORT,
702       "RTP/AVP/TCP;unicast;interleaved=0-1");
703   gst_rtsp_message_add_header (&request, GST_RTSP_HDR_SESSION, session_id);
704   gst_rtsp_client_set_send_func (client, test_setup_response_200, NULL, NULL);
705   expected_transport =
706       "RTP/AVP/TCP;unicast;interleaved=2-3;ssrc=.*;mode=\"PLAY\"";
707   fail_unless (gst_rtsp_client_handle_message (client,
708           &request) == GST_RTSP_OK);
709   gst_rtsp_message_unset (&request);
710
711   send_teardown (client);
712   teardown_client (client);
713 }
714
715 GST_END_TEST;
716
717 static GstRTSPClient *
718 setup_multicast_client (guint max_ttl)
719 {
720   GstRTSPClient *client;
721   GstRTSPSessionPool *session_pool;
722   GstRTSPMountPoints *mount_points;
723   GstRTSPMediaFactory *factory;
724   GstRTSPAddressPool *address_pool;
725   GstRTSPThreadPool *thread_pool;
726
727   client = gst_rtsp_client_new ();
728
729   session_pool = gst_rtsp_session_pool_new ();
730   gst_rtsp_client_set_session_pool (client, session_pool);
731
732   mount_points = gst_rtsp_mount_points_new ();
733   factory = gst_rtsp_media_factory_new ();
734   gst_rtsp_media_factory_set_launch (factory,
735       "audiotestsrc ! audio/x-raw,rate=44100 ! audioconvert ! rtpL16pay name=pay0");
736   address_pool = gst_rtsp_address_pool_new ();
737   fail_unless (gst_rtsp_address_pool_add_range (address_pool,
738           "233.252.0.1", "233.252.0.1", 5000, 5010, 1));
739   gst_rtsp_media_factory_set_address_pool (factory, address_pool);
740   gst_rtsp_media_factory_add_role (factory, "user",
741       "media.factory.access", G_TYPE_BOOLEAN, TRUE,
742       "media.factory.construct", G_TYPE_BOOLEAN, TRUE, NULL);
743   gst_rtsp_mount_points_add_factory (mount_points, "/test", factory);
744   gst_rtsp_client_set_mount_points (client, mount_points);
745   gst_rtsp_media_factory_set_max_mcast_ttl (factory, max_ttl);
746
747   thread_pool = gst_rtsp_thread_pool_new ();
748   gst_rtsp_client_set_thread_pool (client, thread_pool);
749
750   g_object_unref (mount_points);
751   g_object_unref (session_pool);
752   g_object_unref (address_pool);
753   g_object_unref (thread_pool);
754
755   return client;
756 }
757
758 GST_START_TEST (test_client_multicast_transport_404)
759 {
760   GstRTSPClient *client;
761   GstRTSPMessage request = { 0, };
762   gchar *str;
763
764   client = setup_multicast_client (1);
765
766   /* simple SETUP for non-existing url */
767   fail_unless (gst_rtsp_message_init_request (&request, GST_RTSP_SETUP,
768           "rtsp://localhost/test2/stream=0") == GST_RTSP_OK);
769   str = g_strdup_printf ("%d", cseq);
770   gst_rtsp_message_take_header (&request, GST_RTSP_HDR_CSEQ, str);
771   gst_rtsp_message_add_header (&request, GST_RTSP_HDR_TRANSPORT,
772       "RTP/AVP;multicast");
773
774   gst_rtsp_client_set_send_func (client, test_response_404, NULL, NULL);
775   fail_unless (gst_rtsp_client_handle_message (client,
776           &request) == GST_RTSP_OK);
777   gst_rtsp_message_unset (&request);
778
779   teardown_client (client);
780 }
781
782 GST_END_TEST;
783
784 static void
785 new_session_cb (GObject * client, GstRTSPSession * session, gpointer user_data)
786 {
787   GST_DEBUG ("%p: new session %p", client, session);
788   gst_rtsp_session_set_timeout (session, expected_session_timeout);
789 }
790
791 GST_START_TEST (test_client_multicast_transport)
792 {
793   GstRTSPClient *client;
794   GstRTSPMessage request = { 0, };
795   gchar *str;
796
797   client = setup_multicast_client (1);
798
799   expected_session_timeout = 20;
800   g_signal_connect (G_OBJECT (client), "new-session",
801       G_CALLBACK (new_session_cb), NULL);
802
803   /* simple SETUP with a valid URI and multicast */
804   fail_unless (gst_rtsp_message_init_request (&request, GST_RTSP_SETUP,
805           "rtsp://localhost/test/stream=0") == GST_RTSP_OK);
806   str = g_strdup_printf ("%d", cseq);
807   gst_rtsp_message_take_header (&request, GST_RTSP_HDR_CSEQ, str);
808   gst_rtsp_message_add_header (&request, GST_RTSP_HDR_TRANSPORT,
809       "RTP/AVP;multicast");
810
811   expected_transport = "RTP/AVP;multicast;destination=233.252.0.1;"
812       "ttl=1;port=5000-5001;mode=\"PLAY\"";
813   gst_rtsp_client_set_send_func (client, test_setup_response_200, NULL, NULL);
814   fail_unless (gst_rtsp_client_handle_message (client,
815           &request) == GST_RTSP_OK);
816   gst_rtsp_message_unset (&request);
817   expected_transport = NULL;
818   expected_session_timeout = 60;
819
820   send_teardown (client);
821
822   teardown_client (client);
823 }
824
825 GST_END_TEST;
826
827 GST_START_TEST (test_client_multicast_ignore_transport_specific)
828 {
829   GstRTSPClient *client;
830   GstRTSPMessage request = { 0, };
831   gchar *str;
832
833   client = setup_multicast_client (1);
834
835   /* simple SETUP with a valid URI and multicast and a specific dest,
836    * but ignore it  */
837   fail_unless (gst_rtsp_message_init_request (&request, GST_RTSP_SETUP,
838           "rtsp://localhost/test/stream=0") == GST_RTSP_OK);
839   str = g_strdup_printf ("%d", cseq);
840   gst_rtsp_message_take_header (&request, GST_RTSP_HDR_CSEQ, str);
841   gst_rtsp_message_add_header (&request, GST_RTSP_HDR_TRANSPORT,
842       "RTP/AVP;multicast;destination=233.252.0.2;ttl=2;port=5001-5006;");
843
844   expected_transport = "RTP/AVP;multicast;destination=233.252.0.1;"
845       "ttl=1;port=5000-5001;mode=\"PLAY\"";
846   gst_rtsp_client_set_send_func (client, test_setup_response_200, NULL, NULL);
847   fail_unless (gst_rtsp_client_handle_message (client,
848           &request) == GST_RTSP_OK);
849   gst_rtsp_message_unset (&request);
850   expected_transport = NULL;
851
852   send_teardown (client);
853
854   teardown_client (client);
855 }
856
857 GST_END_TEST;
858
859 static void
860 multicast_transport_specific (void)
861 {
862   GstRTSPClient *client;
863   GstRTSPMessage request = { 0, };
864   gchar *str;
865   GstRTSPSessionPool *session_pool;
866   GstRTSPContext ctx = { NULL };
867
868   client = setup_multicast_client (1);
869
870   ctx.client = client;
871   ctx.auth = gst_rtsp_auth_new ();
872   ctx.token =
873       gst_rtsp_token_new (GST_RTSP_TOKEN_TRANSPORT_CLIENT_SETTINGS,
874       G_TYPE_BOOLEAN, TRUE, GST_RTSP_TOKEN_MEDIA_FACTORY_ROLE, G_TYPE_STRING,
875       "user", NULL);
876   gst_rtsp_context_push_current (&ctx);
877
878   /* simple SETUP with a valid URI */
879   fail_unless (gst_rtsp_message_init_request (&request, GST_RTSP_SETUP,
880           "rtsp://localhost/test/stream=0") == GST_RTSP_OK);
881   str = g_strdup_printf ("%d", cseq);
882   gst_rtsp_message_take_header (&request, GST_RTSP_HDR_CSEQ, str);
883   gst_rtsp_message_add_header (&request, GST_RTSP_HDR_TRANSPORT,
884       expected_transport);
885
886   gst_rtsp_client_set_send_func (client, test_setup_response_200, NULL, NULL);
887   fail_unless (gst_rtsp_client_handle_message (client,
888           &request) == GST_RTSP_OK);
889   gst_rtsp_message_unset (&request);
890
891   gst_rtsp_client_set_send_func (client, test_setup_response_200, NULL, NULL);
892   session_pool = gst_rtsp_client_get_session_pool (client);
893   fail_unless (session_pool != NULL);
894   fail_unless (gst_rtsp_session_pool_get_n_sessions (session_pool) == 1);
895   g_object_unref (session_pool);
896
897   /* send PLAY request */
898   fail_unless (gst_rtsp_message_init_request (&request, GST_RTSP_PLAY,
899           "rtsp://localhost/test") == GST_RTSP_OK);
900   str = g_strdup_printf ("%d", cseq);
901   gst_rtsp_message_take_header (&request, GST_RTSP_HDR_CSEQ, str);
902   gst_rtsp_message_add_header (&request, GST_RTSP_HDR_SESSION, session_id);
903   gst_rtsp_client_set_send_func (client, test_response_200, NULL, NULL);
904   fail_unless (gst_rtsp_client_handle_message (client,
905           &request) == GST_RTSP_OK);
906   gst_rtsp_message_unset (&request);
907
908   send_teardown (client);
909   teardown_client (client);
910   g_object_unref (ctx.auth);
911   gst_rtsp_token_unref (ctx.token);
912   gst_rtsp_context_pop_current (&ctx);
913 }
914
915 /* CASE: multicast address requested by the client exists in the address pool */
916 GST_START_TEST (test_client_multicast_transport_specific)
917 {
918   expected_transport = "RTP/AVP;multicast;destination=233.252.0.1;"
919       "ttl=1;port=5000-5001;mode=\"PLAY\"";
920   multicast_transport_specific ();
921   expected_transport = NULL;
922 }
923
924 GST_END_TEST;
925
926 /* CASE: multicast address requested by the client does not exist in the address pool */
927 GST_START_TEST (test_client_multicast_transport_specific_no_address_in_pool)
928 {
929   expected_transport = "RTP/AVP;multicast;destination=234.252.0.3;"
930       "ttl=1;port=6000-6001;mode=\"PLAY\"";
931   multicast_transport_specific ();
932   expected_transport = NULL;
933 }
934
935 GST_END_TEST;
936
937 static gboolean
938 test_response_sdp (GstRTSPClient * client, GstRTSPMessage * response,
939     gboolean close, gpointer user_data)
940 {
941   guint8 *data;
942   guint size;
943   GstSDPMessage *sdp_msg;
944   const GstSDPMedia *sdp_media;
945   const GstSDPBandwidth *bw;
946   gint bandwidth_val = GPOINTER_TO_INT (user_data);
947
948   fail_unless (gst_rtsp_message_get_body (response, &data, &size)
949       == GST_RTSP_OK);
950   gst_sdp_message_new (&sdp_msg);
951   fail_unless (gst_sdp_message_parse_buffer (data, size, sdp_msg)
952       == GST_SDP_OK);
953
954   /* session description */
955   /* v= */
956   fail_unless (gst_sdp_message_get_version (sdp_msg) != NULL);
957   /* o= */
958   fail_unless (gst_sdp_message_get_origin (sdp_msg) != NULL);
959   /* s= */
960   fail_unless (gst_sdp_message_get_session_name (sdp_msg) != NULL);
961   /* t=0 0 */
962   fail_unless (gst_sdp_message_times_len (sdp_msg) == 0);
963
964   /* verify number of medias */
965   fail_unless (gst_sdp_message_medias_len (sdp_msg) == 1);
966
967   /* media description */
968   sdp_media = gst_sdp_message_get_media (sdp_msg, 0);
969   fail_unless (sdp_media != NULL);
970
971   /* m= */
972   fail_unless (gst_sdp_media_get_media (sdp_media) != NULL);
973
974   /* media bandwidth */
975   if (bandwidth_val) {
976     fail_unless (gst_sdp_media_bandwidths_len (sdp_media) == 1);
977     bw = gst_sdp_media_get_bandwidth (sdp_media, 0);
978     fail_unless (bw != NULL);
979     fail_unless (g_strcmp0 (bw->bwtype, "AS") == 0);
980     fail_unless (bw->bandwidth == bandwidth_val);
981   } else {
982     fail_unless (gst_sdp_media_bandwidths_len (sdp_media) == 0);
983   }
984
985   gst_sdp_message_free (sdp_msg);
986
987   return TRUE;
988 }
989
990 static void
991 test_client_sdp (const gchar * launch_line, guint * bandwidth_val)
992 {
993   GstRTSPClient *client;
994   GstRTSPMessage request = { 0, };
995   gchar *str;
996
997   /* simple DESCRIBE for an existing url */
998   client = setup_client (launch_line);
999   fail_unless (gst_rtsp_message_init_request (&request, GST_RTSP_DESCRIBE,
1000           "rtsp://localhost/test") == GST_RTSP_OK);
1001   str = g_strdup_printf ("%d", cseq);
1002   gst_rtsp_message_add_header (&request, GST_RTSP_HDR_CSEQ, str);
1003   g_free (str);
1004
1005   gst_rtsp_client_set_send_func (client, test_response_sdp,
1006       (gpointer) bandwidth_val, NULL);
1007   fail_unless (gst_rtsp_client_handle_message (client,
1008           &request) == GST_RTSP_OK);
1009   gst_rtsp_message_unset (&request);
1010
1011   teardown_client (client);
1012 }
1013
1014 GST_START_TEST (test_client_sdp_with_max_bitrate_tag)
1015 {
1016   test_client_sdp ("videotestsrc "
1017       "! taginject tags=\"maximum-bitrate=(uint)50000000\" "
1018       "! video/x-raw,width=352,height=288 ! rtpgstpay name=pay0 pt=96",
1019       GUINT_TO_POINTER (50000));
1020
1021
1022   /* max-bitrate=0: no bandwidth line */
1023   test_client_sdp ("videotestsrc "
1024       "! taginject tags=\"maximum-bitrate=(uint)0\" "
1025       "! video/x-raw,width=352,height=288 ! rtpgstpay name=pay0 pt=96",
1026       GUINT_TO_POINTER (0));
1027 }
1028
1029 GST_END_TEST;
1030
1031 GST_START_TEST (test_client_sdp_with_bitrate_tag)
1032 {
1033   test_client_sdp ("videotestsrc "
1034       "! taginject tags=\"bitrate=(uint)7000000\" "
1035       "! video/x-raw,width=352,height=288 ! rtpgstpay name=pay0 pt=96",
1036       GUINT_TO_POINTER (7000));
1037
1038   /* bitrate=0: no bandwdith line */
1039   test_client_sdp ("videotestsrc "
1040       "! taginject tags=\"bitrate=(uint)0\" "
1041       "! video/x-raw,width=352,height=288 ! rtpgstpay name=pay0 pt=96",
1042       GUINT_TO_POINTER (0));
1043 }
1044
1045 GST_END_TEST;
1046
1047 GST_START_TEST (test_client_sdp_with_max_bitrate_and_bitrate_tags)
1048 {
1049   test_client_sdp ("videotestsrc "
1050       "! taginject tags=\"bitrate=(uint)7000000,maximum-bitrate=(uint)50000000\" "
1051       "! video/x-raw,width=352,height=288 ! rtpgstpay name=pay0 pt=96",
1052       GUINT_TO_POINTER (50000));
1053
1054   /* max-bitrate is zero: fallback to bitrate */
1055   test_client_sdp ("videotestsrc "
1056       "! taginject tags=\"bitrate=(uint)7000000,maximum-bitrate=(uint)0\" "
1057       "! video/x-raw,width=352,height=288 ! rtpgstpay name=pay0 pt=96",
1058       GUINT_TO_POINTER (7000));
1059
1060   /* max-bitrate=bitrate=0o: no bandwidth line */
1061   test_client_sdp ("videotestsrc "
1062       "! taginject tags=\"bitrate=(uint)0,maximum-bitrate=(uint)0\" "
1063       "! video/x-raw,width=352,height=288 ! rtpgstpay name=pay0 pt=96",
1064       GUINT_TO_POINTER (0));
1065 }
1066
1067 GST_END_TEST;
1068
1069 GST_START_TEST (test_client_sdp_with_no_bitrate_tags)
1070 {
1071   test_client_sdp ("videotestsrc "
1072       "! video/x-raw,width=352,height=288 ! rtpgstpay name=pay0 pt=96", NULL);
1073 }
1074
1075 GST_END_TEST;
1076
1077 static void
1078 mcast_transport_two_clients (gboolean shared, const gchar * transport1,
1079     const gchar * expected_transport1, const gchar * addr1,
1080     const gchar * transport2, const gchar * expected_transport2,
1081     const gchar * addr2, gboolean bind_mcast_address)
1082 {
1083   GstRTSPClient *client1, *client2;
1084   GstRTSPMessage request = { 0, };
1085   gchar *str;
1086   GstRTSPSessionPool *session_pool;
1087   GstRTSPContext ctx = { NULL };
1088   GstRTSPContext ctx2 = { NULL };
1089   GstRTSPMountPoints *mount_points;
1090   GstRTSPMediaFactory *factory;
1091   GstRTSPAddressPool *address_pool;
1092   GstRTSPThreadPool *thread_pool;
1093   gchar *session_id1;
1094   gchar *client_addr = NULL;
1095
1096   mount_points = gst_rtsp_mount_points_new ();
1097   factory = gst_rtsp_media_factory_new ();
1098   if (shared)
1099     gst_rtsp_media_factory_set_shared (factory, TRUE);
1100   gst_rtsp_media_factory_set_max_mcast_ttl (factory, 5);
1101   gst_rtsp_media_factory_set_bind_mcast_address (factory, bind_mcast_address);
1102   gst_rtsp_media_factory_set_launch (factory,
1103       "audiotestsrc ! audio/x-raw,rate=44100 ! audioconvert ! rtpL16pay name=pay0");
1104   address_pool = gst_rtsp_address_pool_new ();
1105   fail_unless (gst_rtsp_address_pool_add_range (address_pool,
1106           "233.252.0.1", "233.252.0.1", 5000, 5001, 1));
1107   gst_rtsp_media_factory_set_address_pool (factory, address_pool);
1108   gst_rtsp_media_factory_add_role (factory, "user",
1109       "media.factory.access", G_TYPE_BOOLEAN, TRUE,
1110       "media.factory.construct", G_TYPE_BOOLEAN, TRUE, NULL);
1111   gst_rtsp_mount_points_add_factory (mount_points, "/test", factory);
1112   session_pool = gst_rtsp_session_pool_new ();
1113   thread_pool = gst_rtsp_thread_pool_new ();
1114
1115   /* first multicast client with transport specific request */
1116   client1 = gst_rtsp_client_new ();
1117   gst_rtsp_client_set_session_pool (client1, session_pool);
1118   gst_rtsp_client_set_mount_points (client1, mount_points);
1119   gst_rtsp_client_set_thread_pool (client1, thread_pool);
1120
1121   ctx.client = client1;
1122   ctx.auth = gst_rtsp_auth_new ();
1123   ctx.token =
1124       gst_rtsp_token_new (GST_RTSP_TOKEN_TRANSPORT_CLIENT_SETTINGS,
1125       G_TYPE_BOOLEAN, TRUE, GST_RTSP_TOKEN_MEDIA_FACTORY_ROLE, G_TYPE_STRING,
1126       "user", NULL);
1127   gst_rtsp_context_push_current (&ctx);
1128
1129   expected_transport = expected_transport1;
1130
1131   /* send SETUP request */
1132   fail_unless (gst_rtsp_message_init_request (&request, GST_RTSP_SETUP,
1133           "rtsp://localhost/test/stream=0") == GST_RTSP_OK);
1134   str = g_strdup_printf ("%d", cseq);
1135   gst_rtsp_message_take_header (&request, GST_RTSP_HDR_CSEQ, str);
1136   gst_rtsp_message_add_header (&request, GST_RTSP_HDR_TRANSPORT, transport1);
1137
1138   gst_rtsp_client_set_send_func (client1, test_setup_response_200, NULL, NULL);
1139   fail_unless (gst_rtsp_client_handle_message (client1,
1140           &request) == GST_RTSP_OK);
1141   gst_rtsp_message_unset (&request);
1142   expected_transport = NULL;
1143
1144   /* send PLAY request */
1145   fail_unless (gst_rtsp_message_init_request (&request, GST_RTSP_PLAY,
1146           "rtsp://localhost/test") == GST_RTSP_OK);
1147   str = g_strdup_printf ("%d", cseq);
1148   gst_rtsp_message_take_header (&request, GST_RTSP_HDR_CSEQ, str);
1149   gst_rtsp_message_add_header (&request, GST_RTSP_HDR_SESSION, session_id);
1150   gst_rtsp_client_set_send_func (client1, test_response_200, NULL, NULL);
1151   fail_unless (gst_rtsp_client_handle_message (client1,
1152           &request) == GST_RTSP_OK);
1153   gst_rtsp_message_unset (&request);
1154
1155   /* check address */
1156   client_addr = gst_rtsp_stream_get_multicast_client_addresses (ctx.stream);
1157   fail_if (client_addr == NULL);
1158   fail_unless (g_str_equal (client_addr, addr1));
1159   g_free (client_addr);
1160
1161   gst_rtsp_context_pop_current (&ctx);
1162   session_id1 = g_strdup (session_id);
1163
1164   /* second multicast client with transport specific request */
1165   cseq = 0;
1166   client2 = gst_rtsp_client_new ();
1167   gst_rtsp_client_set_session_pool (client2, session_pool);
1168   gst_rtsp_client_set_mount_points (client2, mount_points);
1169   gst_rtsp_client_set_thread_pool (client2, thread_pool);
1170
1171   ctx2.client = client2;
1172   ctx2.auth = gst_rtsp_auth_new ();
1173   ctx2.token =
1174       gst_rtsp_token_new (GST_RTSP_TOKEN_TRANSPORT_CLIENT_SETTINGS,
1175       G_TYPE_BOOLEAN, TRUE, GST_RTSP_TOKEN_MEDIA_FACTORY_ROLE, G_TYPE_STRING,
1176       "user", NULL);
1177   gst_rtsp_context_push_current (&ctx2);
1178
1179   expected_transport = expected_transport2;
1180
1181   /* send SETUP request */
1182   fail_unless (gst_rtsp_message_init_request (&request, GST_RTSP_SETUP,
1183           "rtsp://localhost/test/stream=0") == GST_RTSP_OK);
1184   str = g_strdup_printf ("%d", cseq);
1185   gst_rtsp_message_take_header (&request, GST_RTSP_HDR_CSEQ, str);
1186   gst_rtsp_message_add_header (&request, GST_RTSP_HDR_TRANSPORT, transport2);
1187
1188   gst_rtsp_client_set_send_func (client2, test_setup_response_200, NULL, NULL);
1189   fail_unless (gst_rtsp_client_handle_message (client2,
1190           &request) == GST_RTSP_OK);
1191   gst_rtsp_message_unset (&request);
1192   expected_transport = NULL;
1193
1194   /* send PLAY request */
1195   fail_unless (gst_rtsp_message_init_request (&request, GST_RTSP_PLAY,
1196           "rtsp://localhost/test") == GST_RTSP_OK);
1197   str = g_strdup_printf ("%d", cseq);
1198   gst_rtsp_message_take_header (&request, GST_RTSP_HDR_CSEQ, str);
1199   gst_rtsp_message_add_header (&request, GST_RTSP_HDR_SESSION, session_id);
1200   gst_rtsp_client_set_send_func (client2, test_response_200, NULL, NULL);
1201   fail_unless (gst_rtsp_client_handle_message (client2,
1202           &request) == GST_RTSP_OK);
1203   gst_rtsp_message_unset (&request);
1204
1205   /* check addresses */
1206   client_addr = gst_rtsp_stream_get_multicast_client_addresses (ctx2.stream);
1207   fail_if (client_addr == NULL);
1208   if (shared) {
1209     if (g_str_equal (addr1, addr2)) {
1210       fail_unless (g_str_equal (client_addr, addr1));
1211     } else {
1212       gchar *addr_str = g_strdup_printf ("%s,%s", addr2, addr1);
1213       fail_unless (g_str_equal (client_addr, addr_str));
1214       g_free (addr_str);
1215     }
1216   } else {
1217     fail_unless (g_str_equal (client_addr, addr2));
1218   }
1219   g_free (client_addr);
1220
1221   send_teardown (client2);
1222   gst_rtsp_context_pop_current (&ctx2);
1223
1224   gst_rtsp_context_push_current (&ctx);
1225   session_id = session_id1;
1226   send_teardown (client1);
1227   gst_rtsp_context_pop_current (&ctx);
1228
1229   teardown_client (client1);
1230   teardown_client (client2);
1231   g_object_unref (ctx.auth);
1232   g_object_unref (ctx2.auth);
1233   gst_rtsp_token_unref (ctx.token);
1234   gst_rtsp_token_unref (ctx2.token);
1235   g_object_unref (mount_points);
1236   g_object_unref (session_pool);
1237   g_object_unref (address_pool);
1238   g_object_unref (thread_pool);
1239 }
1240
1241 /* test if two multicast clients can choose different transport settings
1242  * CASE: media is shared */
1243 GST_START_TEST
1244     (test_client_multicast_transport_specific_two_clients_shared_media) {
1245   const gchar *transport_client_1 = "RTP/AVP;multicast;destination=233.252.0.1;"
1246       "ttl=1;port=5000-5001;mode=\"PLAY\"";
1247   const gchar *expected_transport_1 = transport_client_1;
1248   const gchar *addr_client_1 = "233.252.0.1:5000";
1249
1250   const gchar *transport_client_2 = "RTP/AVP;multicast;destination=233.252.0.2;"
1251       "ttl=1;port=5002-5003;mode=\"PLAY\"";
1252   const gchar *expected_transport_2 = transport_client_2;
1253   const gchar *addr_client_2 = "233.252.0.2:5002";
1254
1255   mcast_transport_two_clients (TRUE, transport_client_1,
1256       expected_transport_1, addr_client_1, transport_client_2,
1257       expected_transport_2, addr_client_2, FALSE);
1258 }
1259
1260 GST_END_TEST;
1261
1262 /* test if two multicast clients can choose different transport settings
1263  * CASE: media is not shared */
1264 GST_START_TEST (test_client_multicast_transport_specific_two_clients)
1265 {
1266   const gchar *transport_client_1 = "RTP/AVP;multicast;destination=233.252.0.1;"
1267       "ttl=1;port=5000-5001;mode=\"PLAY\"";
1268   const gchar *expected_transport_1 = transport_client_1;
1269   const gchar *addr_client_1 = "233.252.0.1:5000";
1270
1271   const gchar *transport_client_2 = "RTP/AVP;multicast;destination=233.252.0.2;"
1272       "ttl=1;port=5002-5003;mode=\"PLAY\"";
1273   const gchar *expected_transport_2 = transport_client_2;
1274   const gchar *addr_client_2 = "233.252.0.2:5002";
1275
1276   mcast_transport_two_clients (FALSE, transport_client_1,
1277       expected_transport_1, addr_client_1, transport_client_2,
1278       expected_transport_2, addr_client_2, FALSE);
1279 }
1280
1281 GST_END_TEST;
1282
1283 /* test if two multicast clients can choose the same ports but different
1284  * multicast destinations
1285  * CASE: media is not shared */
1286 GST_START_TEST (test_client_multicast_transport_specific_two_clients_same_ports)
1287 {
1288   const gchar *transport_client_1 = "RTP/AVP;multicast;destination=233.252.0.1;"
1289       "ttl=1;port=9000-9001;mode=\"PLAY\"";
1290   const gchar *expected_transport_1 = transport_client_1;
1291   const gchar *addr_client_1 = "233.252.0.1:9000";
1292
1293   const gchar *transport_client_2 = "RTP/AVP;multicast;destination=233.252.0.2;"
1294       "ttl=1;port=9000-9001;mode=\"PLAY\"";
1295   const gchar *expected_transport_2 = transport_client_2;
1296   const gchar *addr_client_2 = "233.252.0.2:9000";
1297
1298   /* configure the multicast socket to be bound to the requested multicast address instead of INADDR_ANY.
1299    * The clients request the same rtp/rtcp borts and having the socket that are bound to ANY would result
1300    * in bind() failure */
1301   gboolean allow_bind_mcast_address = TRUE;
1302
1303   mcast_transport_two_clients (FALSE, transport_client_1,
1304       expected_transport_1, addr_client_1, transport_client_2,
1305       expected_transport_2, addr_client_2, allow_bind_mcast_address);
1306 }
1307
1308 GST_END_TEST;
1309
1310 /* test if two multicast clients can choose the same multicast destination but different
1311  * ports
1312  * CASE: media is not shared */
1313 GST_START_TEST
1314     (test_client_multicast_transport_specific_two_clients_same_destination) {
1315   const gchar *transport_client_1 = "RTP/AVP;multicast;destination=233.252.0.2;"
1316       "ttl=1;port=9002-9003;mode=\"PLAY\"";
1317   const gchar *expected_transport_1 = transport_client_1;
1318   const gchar *addr_client_1 = "233.252.0.2:9002";
1319
1320   const gchar *transport_client_2 = "RTP/AVP;multicast;destination=233.252.0.2;"
1321       "ttl=1;port=9004-9005;mode=\"PLAY\"";
1322   const gchar *expected_transport_2 = transport_client_2;
1323   const gchar *addr_client_2 = "233.252.0.2:9004";
1324
1325   mcast_transport_two_clients (FALSE, transport_client_1,
1326       expected_transport_1, addr_client_1, transport_client_2,
1327       expected_transport_2, addr_client_2, FALSE);
1328 }
1329
1330 GST_END_TEST;
1331 /* test if two multicast clients can choose the same transport settings.
1332  * CASE: media is shared */
1333 GST_START_TEST
1334     (test_client_multicast_transport_specific_two_clients_shared_media_same_transport)
1335 {
1336
1337   const gchar *transport_client_1 = "RTP/AVP;multicast;destination=233.252.0.1;"
1338       "ttl=1;port=5000-5001;mode=\"PLAY\"";
1339   const gchar *expected_transport_1 = transport_client_1;
1340   const gchar *addr_client_1 = "233.252.0.1:5000";
1341
1342   const gchar *transport_client_2 = transport_client_1;
1343   const gchar *expected_transport_2 = expected_transport_1;
1344   const gchar *addr_client_2 = addr_client_1;
1345
1346   mcast_transport_two_clients (TRUE, transport_client_1,
1347       expected_transport_1, addr_client_1, transport_client_2,
1348       expected_transport_2, addr_client_2, FALSE);
1349 }
1350
1351 GST_END_TEST;
1352
1353 /* test if two multicast clients get the same transport settings without
1354  * requesting specific transport.
1355  * CASE: media is shared */
1356 GST_START_TEST (test_client_multicast_two_clients_shared_media)
1357 {
1358   const gchar *transport_client_1 = "RTP/AVP;multicast;mode=\"PLAY\"";
1359   const gchar *expected_transport_1 =
1360       "RTP/AVP;multicast;destination=233.252.0.1;"
1361       "ttl=1;port=5000-5001;mode=\"PLAY\"";
1362   const gchar *addr_client_1 = "233.252.0.1:5000";
1363
1364   const gchar *transport_client_2 = transport_client_1;
1365   const gchar *expected_transport_2 = expected_transport_1;
1366   const gchar *addr_client_2 = addr_client_1;
1367
1368   mcast_transport_two_clients (TRUE, transport_client_1,
1369       expected_transport_1, addr_client_1, transport_client_2,
1370       expected_transport_2, addr_client_2, FALSE);
1371 }
1372
1373 GST_END_TEST;
1374
1375 /* test if two multicast clients get the different transport settings: the first client 
1376  * requests the specific transport configuration while the second client lets
1377  * the server select the multicast address and the ports.
1378  * CASE: media is shared */
1379 GST_START_TEST
1380     (test_client_multicast_two_clients_first_specific_transport_shared_media) {
1381   const gchar *transport_client_1 = "RTP/AVP;multicast;destination=233.252.0.1;"
1382       "ttl=1;port=5000-5001;mode=\"PLAY\"";
1383   const gchar *expected_transport_1 = transport_client_1;
1384   const gchar *addr_client_1 = "233.252.0.1:5000";
1385
1386   const gchar *transport_client_2 = "RTP/AVP;multicast;mode=\"PLAY\"";
1387   const gchar *expected_transport_2 = expected_transport_1;
1388   const gchar *addr_client_2 = addr_client_1;
1389
1390   mcast_transport_two_clients (TRUE, transport_client_1,
1391       expected_transport_1, addr_client_1, transport_client_2,
1392       expected_transport_2, addr_client_2, FALSE);
1393 }
1394
1395 GST_END_TEST;
1396 /* test if two multicast clients get the different transport settings: the first client lets
1397  * the server select the multicast address and the ports while the second client requests 
1398  * the specific transport configuration.
1399  * CASE: media is shared */
1400 GST_START_TEST
1401     (test_client_multicast_two_clients_second_specific_transport_shared_media) {
1402   const gchar *transport_client_1 = "RTP/AVP;multicast;mode=\"PLAY\"";
1403   const gchar *expected_transport_1 =
1404       "RTP/AVP;multicast;destination=233.252.0.1;"
1405       "ttl=1;port=5000-5001;mode=\"PLAY\"";
1406   const gchar *addr_client_1 = "233.252.0.1:5000";
1407
1408   const gchar *transport_client_2 = "RTP/AVP;multicast;destination=233.252.0.2;"
1409       "ttl=2;port=5004-5005;mode=\"PLAY\"";
1410   const gchar *expected_transport_2 = transport_client_2;
1411   const gchar *addr_client_2 = "233.252.0.2:5004";
1412
1413   mcast_transport_two_clients (TRUE, transport_client_1,
1414       expected_transport_1, addr_client_1, transport_client_2,
1415       expected_transport_2, addr_client_2, FALSE);
1416 }
1417
1418 GST_END_TEST;
1419
1420 /* test if the maximum ttl multicast value is chosen by the server
1421  * CASE: the first client provides the highest ttl value */
1422 GST_START_TEST (test_client_multicast_max_ttl_first_client)
1423 {
1424   const gchar *transport_client_1 = "RTP/AVP;multicast;destination=233.252.0.1;"
1425       "ttl=3;port=5000-5001;mode=\"PLAY\"";
1426   const gchar *expected_transport_1 = transport_client_1;
1427   const gchar *addr_client_1 = "233.252.0.1:5000";
1428
1429   const gchar *transport_client_2 = "RTP/AVP;multicast;destination=233.252.0.2;"
1430       "ttl=1;port=5002-5003;mode=\"PLAY\"";
1431   const gchar *expected_transport_2 =
1432       "RTP/AVP;multicast;destination=233.252.0.2;"
1433       "ttl=3;port=5002-5003;mode=\"PLAY\"";
1434   const gchar *addr_client_2 = "233.252.0.2:5002";
1435
1436   mcast_transport_two_clients (TRUE, transport_client_1,
1437       expected_transport_1, addr_client_1, transport_client_2,
1438       expected_transport_2, addr_client_2, FALSE);
1439 }
1440
1441 GST_END_TEST;
1442
1443 /* test if the maximum ttl multicast value is chosen by the server
1444  * CASE: the second client provides the highest ttl value */
1445 GST_START_TEST (test_client_multicast_max_ttl_second_client)
1446 {
1447   const gchar *transport_client_1 = "RTP/AVP;multicast;destination=233.252.0.1;"
1448       "ttl=2;port=5000-5001;mode=\"PLAY\"";
1449   const gchar *expected_transport_1 = transport_client_1;
1450   const gchar *addr_client_1 = "233.252.0.1:5000";
1451
1452   const gchar *transport_client_2 = "RTP/AVP;multicast;destination=233.252.0.2;"
1453       "ttl=4;port=5002-5003;mode=\"PLAY\"";
1454   const gchar *expected_transport_2 = transport_client_2;
1455   const gchar *addr_client_2 = "233.252.0.2:5002";
1456
1457   mcast_transport_two_clients (TRUE, transport_client_1,
1458       expected_transport_1, addr_client_1, transport_client_2,
1459       expected_transport_2, addr_client_2, FALSE);
1460 }
1461
1462 GST_END_TEST;
1463 GST_START_TEST (test_client_multicast_invalid_ttl)
1464 {
1465   GstRTSPClient *client;
1466   GstRTSPMessage request = { 0, };
1467   gchar *str;
1468   GstRTSPSessionPool *session_pool;
1469   GstRTSPContext ctx = { NULL };
1470
1471   client = setup_multicast_client (3);
1472
1473   ctx.client = client;
1474   ctx.auth = gst_rtsp_auth_new ();
1475   ctx.token =
1476       gst_rtsp_token_new (GST_RTSP_TOKEN_TRANSPORT_CLIENT_SETTINGS,
1477       G_TYPE_BOOLEAN, TRUE, GST_RTSP_TOKEN_MEDIA_FACTORY_ROLE, G_TYPE_STRING,
1478       "user", NULL);
1479   gst_rtsp_context_push_current (&ctx);
1480
1481   /* simple SETUP with an invalid ttl=0 */
1482   fail_unless (gst_rtsp_message_init_request (&request, GST_RTSP_SETUP,
1483           "rtsp://localhost/test/stream=0") == GST_RTSP_OK);
1484   str = g_strdup_printf ("%d", cseq);
1485   gst_rtsp_message_take_header (&request, GST_RTSP_HDR_CSEQ, str);
1486   gst_rtsp_message_add_header (&request, GST_RTSP_HDR_TRANSPORT,
1487       "RTP/AVP;multicast;destination=233.252.0.1;ttl=0;port=5000-5001;");
1488
1489   gst_rtsp_client_set_send_func (client, test_setup_response_461, NULL, NULL);
1490   fail_unless (gst_rtsp_client_handle_message (client,
1491           &request) == GST_RTSP_OK);
1492   gst_rtsp_message_unset (&request);
1493
1494   session_pool = gst_rtsp_client_get_session_pool (client);
1495   fail_unless (session_pool != NULL);
1496   fail_unless (gst_rtsp_session_pool_get_n_sessions (session_pool) == 0);
1497   g_object_unref (session_pool);
1498
1499   teardown_client (client);
1500   g_object_unref (ctx.auth);
1501   gst_rtsp_token_unref (ctx.token);
1502   gst_rtsp_context_pop_current (&ctx);
1503 }
1504
1505 GST_END_TEST;
1506
1507 static Suite *
1508 rtspclient_suite (void)
1509 {
1510   Suite *s = suite_create ("rtspclient");
1511   TCase *tc = tcase_create ("general");
1512
1513   suite_add_tcase (s, tc);
1514   tcase_set_timeout (tc, 20);
1515   tcase_add_test (tc, test_require);
1516   tcase_add_test (tc, test_request);
1517   tcase_add_test (tc, test_options);
1518   tcase_add_test (tc, test_describe);
1519   tcase_add_test (tc, test_setup_tcp);
1520   tcase_add_test (tc, test_setup_tcp_two_streams_same_channels);
1521   tcase_add_test (tc, test_client_multicast_transport_404);
1522   tcase_add_test (tc, test_client_multicast_transport);
1523   tcase_add_test (tc, test_client_multicast_ignore_transport_specific);
1524   tcase_add_test (tc, test_client_multicast_transport_specific);
1525   tcase_add_test (tc, test_client_sdp_with_max_bitrate_tag);
1526   tcase_add_test (tc, test_client_sdp_with_bitrate_tag);
1527   tcase_add_test (tc, test_client_sdp_with_max_bitrate_and_bitrate_tags);
1528   tcase_add_test (tc, test_client_sdp_with_no_bitrate_tags);
1529   tcase_add_test (tc,
1530       test_client_multicast_transport_specific_two_clients_shared_media);
1531   tcase_add_test (tc, test_client_multicast_transport_specific_two_clients);
1532 #ifndef G_OS_WIN32
1533   tcase_add_test (tc,
1534       test_client_multicast_transport_specific_two_clients_same_ports);
1535 #else
1536   /* skip the test on windows as the test restricts the multicast sockets to multicast traffic only,
1537    * by specifying the multicast IP as the bind address and this currently doesn't work on Windows */
1538   tcase_skip_broken_test (tc,
1539       test_client_multicast_transport_specific_two_clients_same_ports);
1540 #endif
1541   tcase_add_test (tc,
1542       test_client_multicast_transport_specific_two_clients_same_destination);
1543   tcase_add_test (tc,
1544       test_client_multicast_transport_specific_two_clients_shared_media_same_transport);
1545   tcase_add_test (tc, test_client_multicast_two_clients_shared_media);
1546   tcase_add_test (tc,
1547       test_client_multicast_two_clients_first_specific_transport_shared_media);
1548   tcase_add_test (tc,
1549       test_client_multicast_two_clients_second_specific_transport_shared_media);
1550   tcase_add_test (tc,
1551       test_client_multicast_transport_specific_no_address_in_pool);
1552   tcase_add_test (tc, test_client_multicast_max_ttl_first_client);
1553   tcase_add_test (tc, test_client_multicast_max_ttl_second_client);
1554   tcase_add_test (tc, test_client_multicast_invalid_ttl);
1555
1556   return s;
1557 }
1558
1559 GST_CHECK_MAIN (rtspclient);