rtsp-stream: Don't require address pool in the transport specific case
[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 static gchar *session_id;
25 static gint cseq;
26 static guint expected_session_timeout = 60;
27 static const gchar *expected_unsupported_header;
28
29 static gboolean
30 test_response_200 (GstRTSPClient * client, GstRTSPMessage * response,
31     gboolean close, gpointer user_data)
32 {
33   GstRTSPStatusCode code;
34   const gchar *reason;
35   GstRTSPVersion version;
36
37   fail_unless (gst_rtsp_message_get_type (response) ==
38       GST_RTSP_MESSAGE_RESPONSE);
39
40   fail_unless (gst_rtsp_message_parse_response (response, &code, &reason,
41           &version)
42       == GST_RTSP_OK);
43   fail_unless (code == GST_RTSP_STS_OK);
44   fail_unless (g_str_equal (reason, "OK"));
45   fail_unless (version == GST_RTSP_VERSION_1_0);
46
47   return TRUE;
48 }
49
50 static gboolean
51 test_response_400 (GstRTSPClient * client, GstRTSPMessage * response,
52     gboolean close, gpointer user_data)
53 {
54   GstRTSPStatusCode code;
55   const gchar *reason;
56   GstRTSPVersion version;
57
58   fail_unless (gst_rtsp_message_get_type (response) ==
59       GST_RTSP_MESSAGE_RESPONSE);
60
61   fail_unless (gst_rtsp_message_parse_response (response, &code, &reason,
62           &version)
63       == GST_RTSP_OK);
64   fail_unless (code == GST_RTSP_STS_BAD_REQUEST);
65   fail_unless (g_str_equal (reason, "Bad Request"));
66   fail_unless (version == GST_RTSP_VERSION_1_0);
67
68   return TRUE;
69 }
70
71 static gboolean
72 test_response_404 (GstRTSPClient * client, GstRTSPMessage * response,
73     gboolean close, gpointer user_data)
74 {
75   GstRTSPStatusCode code;
76   const gchar *reason;
77   GstRTSPVersion version;
78
79   fail_unless (gst_rtsp_message_get_type (response) ==
80       GST_RTSP_MESSAGE_RESPONSE);
81
82   fail_unless (gst_rtsp_message_parse_response (response, &code, &reason,
83           &version)
84       == GST_RTSP_OK);
85   fail_unless (code == GST_RTSP_STS_NOT_FOUND);
86   fail_unless (g_str_equal (reason, "Not Found"));
87   fail_unless (version == GST_RTSP_VERSION_1_0);
88
89   return TRUE;
90 }
91
92 static gboolean
93 test_response_454 (GstRTSPClient * client, GstRTSPMessage * response,
94     gboolean close, gpointer user_data)
95 {
96   GstRTSPStatusCode code;
97   const gchar *reason;
98   GstRTSPVersion version;
99
100   fail_unless (gst_rtsp_message_get_type (response) ==
101       GST_RTSP_MESSAGE_RESPONSE);
102
103   fail_unless (gst_rtsp_message_parse_response (response, &code, &reason,
104           &version)
105       == GST_RTSP_OK);
106   fail_unless (code == GST_RTSP_STS_SESSION_NOT_FOUND);
107   fail_unless (g_str_equal (reason, "Session Not Found"));
108   fail_unless (version == GST_RTSP_VERSION_1_0);
109
110   return TRUE;
111 }
112
113 static gboolean
114 test_response_551 (GstRTSPClient * client, GstRTSPMessage * response,
115     gboolean close, gpointer user_data)
116 {
117   GstRTSPStatusCode code;
118   const gchar *reason;
119   GstRTSPVersion version;
120   gchar *options;
121
122   fail_unless (gst_rtsp_message_get_type (response) ==
123       GST_RTSP_MESSAGE_RESPONSE);
124
125   fail_unless (gst_rtsp_message_parse_response (response, &code, &reason,
126           &version)
127       == GST_RTSP_OK);
128   fail_unless (code == GST_RTSP_STS_OPTION_NOT_SUPPORTED);
129   fail_unless (g_str_equal (reason, "Option not supported"));
130   fail_unless (gst_rtsp_message_get_header (response, GST_RTSP_HDR_UNSUPPORTED,
131           &options, 0) == GST_RTSP_OK);
132   fail_unless (!g_strcmp0 (expected_unsupported_header, options));
133   fail_unless (version == GST_RTSP_VERSION_1_0);
134
135   return TRUE;
136 }
137
138 static GstRTSPClient *
139 setup_client (const gchar * launch_line)
140 {
141   GstRTSPClient *client;
142   GstRTSPSessionPool *session_pool;
143   GstRTSPMountPoints *mount_points;
144   GstRTSPMediaFactory *factory;
145   GstRTSPThreadPool *thread_pool;
146
147   client = gst_rtsp_client_new ();
148
149   session_pool = gst_rtsp_session_pool_new ();
150   gst_rtsp_client_set_session_pool (client, session_pool);
151
152   mount_points = gst_rtsp_mount_points_new ();
153   factory = gst_rtsp_media_factory_new ();
154   if (launch_line == NULL)
155     gst_rtsp_media_factory_set_launch (factory,
156         "videotestsrc ! video/x-raw,width=352,height=288 ! rtpgstpay name=pay0 pt=96");
157   else
158     gst_rtsp_media_factory_set_launch (factory, launch_line);
159
160   gst_rtsp_mount_points_add_factory (mount_points, "/test", factory);
161   gst_rtsp_client_set_mount_points (client, mount_points);
162
163   thread_pool = gst_rtsp_thread_pool_new ();
164   gst_rtsp_client_set_thread_pool (client, thread_pool);
165
166   g_object_unref (mount_points);
167   g_object_unref (session_pool);
168   g_object_unref (thread_pool);
169
170   return client;
171 }
172
173 static void
174 teardown_client (GstRTSPClient * client)
175 {
176   gst_rtsp_client_set_thread_pool (client, NULL);
177   g_object_unref (client);
178 }
179
180 static gchar *
181 check_requirements_cb (GstRTSPClient * client, GstRTSPContext * ctx,
182     gchar ** req, gpointer user_data)
183 {
184   int index = 0;
185   GString *result = g_string_new ("");
186
187   while (req[index] != NULL) {
188     if (g_strcmp0 (req[index], "test-requirements")) {
189       if (result->len > 0)
190         g_string_append (result, ", ");
191       g_string_append (result, req[index]);
192     }
193     index++;
194   }
195
196   return g_string_free (result, FALSE);
197 }
198
199 GST_START_TEST (test_require)
200 {
201   GstRTSPClient *client;
202   GstRTSPMessage request = { 0, };
203   gchar *str;
204
205   client = gst_rtsp_client_new ();
206
207   /* require header without handler */
208   fail_unless (gst_rtsp_message_init_request (&request, GST_RTSP_OPTIONS,
209           "rtsp://localhost/test") == GST_RTSP_OK);
210   str = g_strdup_printf ("test-not-supported1");
211   gst_rtsp_message_add_header (&request, GST_RTSP_HDR_REQUIRE, str);
212   g_free (str);
213
214   expected_unsupported_header = "test-not-supported1";
215   gst_rtsp_client_set_send_func (client, test_response_551, NULL, NULL);
216   fail_unless (gst_rtsp_client_handle_message (client,
217           &request) == GST_RTSP_OK);
218   gst_rtsp_message_unset (&request);
219
220   g_signal_connect (G_OBJECT (client), "check-requirements",
221       G_CALLBACK (check_requirements_cb), NULL);
222
223   /* one supported option */
224   fail_unless (gst_rtsp_message_init_request (&request, GST_RTSP_OPTIONS,
225           "rtsp://localhost/test") == GST_RTSP_OK);
226   str = g_strdup_printf ("test-requirements");
227   gst_rtsp_message_add_header (&request, GST_RTSP_HDR_REQUIRE, str);
228   g_free (str);
229
230   gst_rtsp_client_set_send_func (client, test_response_200, NULL, NULL);
231   fail_unless (gst_rtsp_client_handle_message (client,
232           &request) == GST_RTSP_OK);
233   gst_rtsp_message_unset (&request);
234
235   /* unsupported option */
236   fail_unless (gst_rtsp_message_init_request (&request, GST_RTSP_OPTIONS,
237           "rtsp://localhost/test") == GST_RTSP_OK);
238   str = g_strdup_printf ("test-not-supported1");
239   gst_rtsp_message_add_header (&request, GST_RTSP_HDR_REQUIRE, str);
240   g_free (str);
241
242   expected_unsupported_header = "test-not-supported1";
243   gst_rtsp_client_set_send_func (client, test_response_551, NULL, NULL);
244   fail_unless (gst_rtsp_client_handle_message (client,
245           &request) == GST_RTSP_OK);
246   gst_rtsp_message_unset (&request);
247
248   /* more than one unsupported options */
249   fail_unless (gst_rtsp_message_init_request (&request, GST_RTSP_OPTIONS,
250           "rtsp://localhost/test") == GST_RTSP_OK);
251   str = g_strdup_printf ("test-not-supported1");
252   gst_rtsp_message_add_header (&request, GST_RTSP_HDR_REQUIRE, str);
253   g_free (str);
254   str = g_strdup_printf ("test-not-supported2");
255   gst_rtsp_message_add_header (&request, GST_RTSP_HDR_REQUIRE, str);
256   g_free (str);
257
258   expected_unsupported_header = "test-not-supported1, test-not-supported2";
259   gst_rtsp_client_set_send_func (client, test_response_551, NULL, NULL);
260   fail_unless (gst_rtsp_client_handle_message (client,
261           &request) == GST_RTSP_OK);
262   gst_rtsp_message_unset (&request);
263
264   /* supported and unsupported together */
265   fail_unless (gst_rtsp_message_init_request (&request, GST_RTSP_OPTIONS,
266           "rtsp://localhost/test") == GST_RTSP_OK);
267   str = g_strdup_printf ("test-not-supported1");
268   gst_rtsp_message_add_header (&request, GST_RTSP_HDR_REQUIRE, str);
269   g_free (str);
270   str = g_strdup_printf ("test-requirements");
271   gst_rtsp_message_add_header (&request, GST_RTSP_HDR_REQUIRE, str);
272   g_free (str);
273   str = g_strdup_printf ("test-not-supported2");
274   gst_rtsp_message_add_header (&request, GST_RTSP_HDR_REQUIRE, str);
275   g_free (str);
276
277   expected_unsupported_header = "test-not-supported1, test-not-supported2";
278   gst_rtsp_client_set_send_func (client, test_response_551, NULL, NULL);
279   fail_unless (gst_rtsp_client_handle_message (client,
280           &request) == GST_RTSP_OK);
281   gst_rtsp_message_unset (&request);
282
283   g_object_unref (client);
284 }
285
286 GST_END_TEST;
287
288 GST_START_TEST (test_request)
289 {
290   GstRTSPClient *client;
291   GstRTSPMessage request = { 0, };
292   gchar *str;
293   GstRTSPConnection *conn;
294   GSocket *sock;
295   GError *error = NULL;
296
297   client = gst_rtsp_client_new ();
298
299   /* OPTIONS with invalid url */
300   fail_unless (gst_rtsp_message_init_request (&request, GST_RTSP_OPTIONS,
301           "foopy://padoop/") == GST_RTSP_OK);
302   str = g_strdup_printf ("%d", cseq);
303   gst_rtsp_message_add_header (&request, GST_RTSP_HDR_CSEQ, str);
304   g_free (str);
305
306   gst_rtsp_client_set_send_func (client, test_response_400, NULL, NULL);
307   fail_unless (gst_rtsp_client_handle_message (client,
308           &request) == GST_RTSP_OK);
309
310   gst_rtsp_message_unset (&request);
311
312   /* OPTIONS with unknown session id */
313   fail_unless (gst_rtsp_message_init_request (&request, GST_RTSP_OPTIONS,
314           "rtsp://localhost/test") == GST_RTSP_OK);
315   str = g_strdup_printf ("%d", cseq);
316   gst_rtsp_message_add_header (&request, GST_RTSP_HDR_CSEQ, str);
317   g_free (str);
318   gst_rtsp_message_add_header (&request, GST_RTSP_HDR_SESSION, "foobar");
319
320   gst_rtsp_client_set_send_func (client, test_response_454, NULL, NULL);
321   fail_unless (gst_rtsp_client_handle_message (client,
322           &request) == GST_RTSP_OK);
323
324   gst_rtsp_message_unset (&request);
325
326   /* OPTIONS with an absolute path instead of an absolute url */
327   /* set host information */
328   sock = g_socket_new (G_SOCKET_FAMILY_IPV4, G_SOCKET_TYPE_STREAM,
329       G_SOCKET_PROTOCOL_TCP, &error);
330   g_assert_no_error (error);
331   gst_rtsp_connection_create_from_socket (sock, "localhost", 444, NULL, &conn);
332   fail_unless (gst_rtsp_client_set_connection (client, conn));
333   g_object_unref (sock);
334
335   fail_unless (gst_rtsp_message_init_request (&request, GST_RTSP_OPTIONS,
336           "/test") == GST_RTSP_OK);
337   str = g_strdup_printf ("%d", cseq);
338   gst_rtsp_message_add_header (&request, GST_RTSP_HDR_CSEQ, str);
339   g_free (str);
340
341   gst_rtsp_client_set_send_func (client, test_response_200, NULL, NULL);
342   fail_unless (gst_rtsp_client_handle_message (client,
343           &request) == GST_RTSP_OK);
344   gst_rtsp_message_unset (&request);
345
346   /* OPTIONS with an absolute path instead of an absolute url with invalid
347    * host information */
348   g_object_unref (client);
349   client = gst_rtsp_client_new ();
350   fail_unless (gst_rtsp_message_init_request (&request, GST_RTSP_OPTIONS,
351           "/test") == GST_RTSP_OK);
352   str = g_strdup_printf ("%d", cseq);
353   gst_rtsp_message_add_header (&request, GST_RTSP_HDR_CSEQ, str);
354   g_free (str);
355
356   gst_rtsp_client_set_send_func (client, test_response_400, NULL, NULL);
357   fail_unless (gst_rtsp_client_handle_message (client,
358           &request) == GST_RTSP_OK);
359   gst_rtsp_message_unset (&request);
360
361   g_object_unref (client);
362 }
363
364 GST_END_TEST;
365
366 static gboolean
367 test_option_response_200 (GstRTSPClient * client, GstRTSPMessage * response,
368     gboolean close, gpointer user_data)
369 {
370   GstRTSPStatusCode code;
371   const gchar *reason;
372   GstRTSPVersion version;
373   gchar *str;
374   GstRTSPMethod methods;
375
376   fail_unless (gst_rtsp_message_get_type (response) ==
377       GST_RTSP_MESSAGE_RESPONSE);
378
379   fail_unless (gst_rtsp_message_parse_response (response, &code, &reason,
380           &version)
381       == GST_RTSP_OK);
382   fail_unless (code == GST_RTSP_STS_OK);
383   fail_unless (g_str_equal (reason, "OK"));
384   fail_unless (version == GST_RTSP_VERSION_1_0);
385
386   fail_unless (gst_rtsp_message_get_header (response, GST_RTSP_HDR_CSEQ, &str,
387           0) == GST_RTSP_OK);
388   fail_unless (atoi (str) == cseq++);
389
390   fail_unless (gst_rtsp_message_get_header (response, GST_RTSP_HDR_PUBLIC, &str,
391           0) == GST_RTSP_OK);
392
393   methods = gst_rtsp_options_from_text (str);
394   fail_if (methods == 0);
395   fail_unless (methods == (GST_RTSP_DESCRIBE |
396           GST_RTSP_ANNOUNCE |
397           GST_RTSP_OPTIONS |
398           GST_RTSP_PAUSE |
399           GST_RTSP_PLAY |
400           GST_RTSP_RECORD |
401           GST_RTSP_SETUP |
402           GST_RTSP_GET_PARAMETER | GST_RTSP_SET_PARAMETER | GST_RTSP_TEARDOWN));
403
404   return TRUE;
405 }
406
407 GST_START_TEST (test_options)
408 {
409   GstRTSPClient *client;
410   GstRTSPMessage request = { 0, };
411   gchar *str;
412
413   client = gst_rtsp_client_new ();
414
415   /* simple OPTIONS */
416   fail_unless (gst_rtsp_message_init_request (&request, GST_RTSP_OPTIONS,
417           "rtsp://localhost/test") == GST_RTSP_OK);
418   str = g_strdup_printf ("%d", cseq);
419   gst_rtsp_message_add_header (&request, GST_RTSP_HDR_CSEQ, str);
420   g_free (str);
421
422   gst_rtsp_client_set_send_func (client, test_option_response_200, NULL, NULL);
423   fail_unless (gst_rtsp_client_handle_message (client,
424           &request) == GST_RTSP_OK);
425   gst_rtsp_message_unset (&request);
426
427   g_object_unref (client);
428 }
429
430 GST_END_TEST;
431
432 GST_START_TEST (test_describe)
433 {
434   GstRTSPClient *client;
435   GstRTSPMessage request = { 0, };
436   gchar *str;
437
438   client = gst_rtsp_client_new ();
439
440   /* simple DESCRIBE for non-existing url */
441   fail_unless (gst_rtsp_message_init_request (&request, GST_RTSP_DESCRIBE,
442           "rtsp://localhost/test") == GST_RTSP_OK);
443   str = g_strdup_printf ("%d", cseq);
444   gst_rtsp_message_add_header (&request, GST_RTSP_HDR_CSEQ, str);
445   g_free (str);
446
447   gst_rtsp_client_set_send_func (client, test_response_404, NULL, NULL);
448   fail_unless (gst_rtsp_client_handle_message (client,
449           &request) == GST_RTSP_OK);
450   gst_rtsp_message_unset (&request);
451
452   g_object_unref (client);
453
454   /* simple DESCRIBE for an existing url */
455   client = setup_client (NULL);
456   fail_unless (gst_rtsp_message_init_request (&request, GST_RTSP_DESCRIBE,
457           "rtsp://localhost/test") == GST_RTSP_OK);
458   str = g_strdup_printf ("%d", cseq);
459   gst_rtsp_message_add_header (&request, GST_RTSP_HDR_CSEQ, str);
460   g_free (str);
461
462   gst_rtsp_client_set_send_func (client, test_response_200, NULL, NULL);
463   fail_unless (gst_rtsp_client_handle_message (client,
464           &request) == GST_RTSP_OK);
465   gst_rtsp_message_unset (&request);
466
467   teardown_client (client);
468 }
469
470 GST_END_TEST;
471
472 static const gchar *expected_transport = NULL;
473
474 static gboolean
475 test_setup_response_200_multicast (GstRTSPClient * client,
476     GstRTSPMessage * response, gboolean close, gpointer user_data)
477 {
478   GstRTSPStatusCode code;
479   const gchar *reason;
480   GstRTSPVersion version;
481   gchar *str;
482   GstRTSPSessionPool *session_pool;
483   GstRTSPSession *session;
484   gchar **session_hdr_params;
485
486   fail_unless (expected_transport != NULL);
487
488   fail_unless_equals_int (gst_rtsp_message_get_type (response),
489       GST_RTSP_MESSAGE_RESPONSE);
490
491   fail_unless (gst_rtsp_message_parse_response (response, &code, &reason,
492           &version)
493       == GST_RTSP_OK);
494   fail_unless_equals_int (code, GST_RTSP_STS_OK);
495   fail_unless_equals_string (reason, "OK");
496   fail_unless_equals_int (version, GST_RTSP_VERSION_1_0);
497
498   fail_unless (gst_rtsp_message_get_header (response, GST_RTSP_HDR_CSEQ, &str,
499           0) == GST_RTSP_OK);
500   fail_unless (atoi (str) == cseq++);
501
502   fail_unless (gst_rtsp_message_get_header (response, GST_RTSP_HDR_TRANSPORT,
503           &str, 0) == GST_RTSP_OK);
504
505   fail_unless_equals_string (str, expected_transport);
506
507   fail_unless (gst_rtsp_message_get_header (response, GST_RTSP_HDR_SESSION,
508           &str, 0) == GST_RTSP_OK);
509   session_hdr_params = g_strsplit (str, ";", -1);
510
511   /* session-id value */
512   fail_unless (session_hdr_params[0] != NULL);
513
514   if (expected_session_timeout != 60) {
515     /* session timeout param */
516     gchar *timeout_str = g_strdup_printf ("timeout=%u",
517         expected_session_timeout);
518
519     fail_unless (session_hdr_params[1] != NULL);
520     g_strstrip (session_hdr_params[1]);
521     fail_unless (g_strcmp0 (session_hdr_params[1], timeout_str) == 0);
522     g_free (timeout_str);
523   }
524
525   session_pool = gst_rtsp_client_get_session_pool (client);
526   fail_unless (session_pool != NULL);
527
528   session = gst_rtsp_session_pool_find (session_pool, session_hdr_params[0]);
529   g_strfreev (session_hdr_params);
530
531   /* remember session id to be able to send teardown */
532   session_id = g_strdup (gst_rtsp_session_get_sessionid (session));
533   fail_unless (session_id != NULL);
534
535   fail_unless (session != NULL);
536   g_object_unref (session);
537
538   g_object_unref (session_pool);
539
540
541   return TRUE;
542 }
543
544 static gboolean
545 test_teardown_response_200 (GstRTSPClient * client,
546     GstRTSPMessage * response, gboolean close, gpointer user_data)
547 {
548   GstRTSPStatusCode code;
549   const gchar *reason;
550   GstRTSPVersion version;
551
552   fail_unless (gst_rtsp_message_get_type (response) ==
553       GST_RTSP_MESSAGE_RESPONSE);
554
555   fail_unless (gst_rtsp_message_parse_response (response, &code, &reason,
556           &version)
557       == GST_RTSP_OK);
558   fail_unless (code == GST_RTSP_STS_OK);
559   fail_unless (g_str_equal (reason, "OK"));
560   fail_unless (version == GST_RTSP_VERSION_1_0);
561
562   return TRUE;
563 }
564
565 static void
566 send_teardown (GstRTSPClient * client)
567 {
568   GstRTSPMessage request = { 0, };
569   gchar *str;
570
571   fail_unless (session_id != NULL);
572   fail_unless (gst_rtsp_message_init_request (&request, GST_RTSP_TEARDOWN,
573           "rtsp://localhost/test") == GST_RTSP_OK);
574   str = g_strdup_printf ("%d", cseq);
575   gst_rtsp_message_take_header (&request, GST_RTSP_HDR_CSEQ, str);
576   gst_rtsp_message_add_header (&request, GST_RTSP_HDR_SESSION, session_id);
577   gst_rtsp_client_set_send_func (client, test_teardown_response_200,
578       NULL, NULL);
579   fail_unless (gst_rtsp_client_handle_message (client,
580           &request) == GST_RTSP_OK);
581   gst_rtsp_message_unset (&request);
582   g_free (session_id);
583   session_id = NULL;
584 }
585
586 static GstRTSPClient *
587 setup_multicast_client (void)
588 {
589   GstRTSPClient *client;
590   GstRTSPSessionPool *session_pool;
591   GstRTSPMountPoints *mount_points;
592   GstRTSPMediaFactory *factory;
593   GstRTSPAddressPool *address_pool;
594   GstRTSPThreadPool *thread_pool;
595
596   client = gst_rtsp_client_new ();
597
598   session_pool = gst_rtsp_session_pool_new ();
599   gst_rtsp_client_set_session_pool (client, session_pool);
600
601   mount_points = gst_rtsp_mount_points_new ();
602   factory = gst_rtsp_media_factory_new ();
603   gst_rtsp_media_factory_set_launch (factory,
604       "audiotestsrc ! audio/x-raw,rate=44100 ! audioconvert ! rtpL16pay name=pay0");
605   address_pool = gst_rtsp_address_pool_new ();
606   fail_unless (gst_rtsp_address_pool_add_range (address_pool,
607           "233.252.0.1", "233.252.0.1", 5000, 5010, 1));
608   gst_rtsp_media_factory_set_address_pool (factory, address_pool);
609   gst_rtsp_media_factory_add_role (factory, "user",
610       "media.factory.access", G_TYPE_BOOLEAN, TRUE,
611       "media.factory.construct", G_TYPE_BOOLEAN, TRUE, NULL);
612   gst_rtsp_mount_points_add_factory (mount_points, "/test", factory);
613   gst_rtsp_client_set_mount_points (client, mount_points);
614
615   thread_pool = gst_rtsp_thread_pool_new ();
616   gst_rtsp_client_set_thread_pool (client, thread_pool);
617
618   g_object_unref (mount_points);
619   g_object_unref (session_pool);
620   g_object_unref (address_pool);
621   g_object_unref (thread_pool);
622
623   return client;
624 }
625
626 GST_START_TEST (test_client_multicast_transport_404)
627 {
628   GstRTSPClient *client;
629   GstRTSPMessage request = { 0, };
630   gchar *str;
631
632   client = setup_multicast_client ();
633
634   /* simple SETUP for non-existing url */
635   fail_unless (gst_rtsp_message_init_request (&request, GST_RTSP_SETUP,
636           "rtsp://localhost/test2/stream=0") == GST_RTSP_OK);
637   str = g_strdup_printf ("%d", cseq);
638   gst_rtsp_message_take_header (&request, GST_RTSP_HDR_CSEQ, str);
639   gst_rtsp_message_add_header (&request, GST_RTSP_HDR_TRANSPORT,
640       "RTP/AVP;multicast");
641
642   gst_rtsp_client_set_send_func (client, test_response_404, NULL, NULL);
643   fail_unless (gst_rtsp_client_handle_message (client,
644           &request) == GST_RTSP_OK);
645   gst_rtsp_message_unset (&request);
646
647   teardown_client (client);
648 }
649
650 GST_END_TEST;
651
652 static void
653 new_session_cb (GObject * client, GstRTSPSession * session, gpointer user_data)
654 {
655   GST_DEBUG ("%p: new session %p", client, session);
656   gst_rtsp_session_set_timeout (session, expected_session_timeout);
657 }
658
659 GST_START_TEST (test_client_multicast_transport)
660 {
661   GstRTSPClient *client;
662   GstRTSPMessage request = { 0, };
663   gchar *str;
664
665   client = setup_multicast_client ();
666
667   expected_session_timeout = 20;
668   g_signal_connect (G_OBJECT (client), "new-session",
669       G_CALLBACK (new_session_cb), NULL);
670
671   /* simple SETUP with a valid URI and multicast */
672   fail_unless (gst_rtsp_message_init_request (&request, GST_RTSP_SETUP,
673           "rtsp://localhost/test/stream=0") == GST_RTSP_OK);
674   str = g_strdup_printf ("%d", cseq);
675   gst_rtsp_message_take_header (&request, GST_RTSP_HDR_CSEQ, str);
676   gst_rtsp_message_add_header (&request, GST_RTSP_HDR_TRANSPORT,
677       "RTP/AVP;multicast");
678
679   expected_transport = "RTP/AVP;multicast;destination=233.252.0.1;"
680       "ttl=1;port=5000-5001;mode=\"PLAY\"";
681   gst_rtsp_client_set_send_func (client, test_setup_response_200_multicast,
682       NULL, NULL);
683   fail_unless (gst_rtsp_client_handle_message (client,
684           &request) == GST_RTSP_OK);
685   gst_rtsp_message_unset (&request);
686   expected_transport = NULL;
687   expected_session_timeout = 60;
688
689   send_teardown (client);
690
691   teardown_client (client);
692 }
693
694 GST_END_TEST;
695
696 GST_START_TEST (test_client_multicast_ignore_transport_specific)
697 {
698   GstRTSPClient *client;
699   GstRTSPMessage request = { 0, };
700   gchar *str;
701
702   client = setup_multicast_client ();
703
704   /* simple SETUP with a valid URI and multicast and a specific dest,
705    * but ignore it  */
706   fail_unless (gst_rtsp_message_init_request (&request, GST_RTSP_SETUP,
707           "rtsp://localhost/test/stream=0") == GST_RTSP_OK);
708   str = g_strdup_printf ("%d", cseq);
709   gst_rtsp_message_take_header (&request, GST_RTSP_HDR_CSEQ, str);
710   gst_rtsp_message_add_header (&request, GST_RTSP_HDR_TRANSPORT,
711       "RTP/AVP;multicast;destination=233.252.0.2;ttl=2;port=5001-5006;");
712
713   expected_transport = "RTP/AVP;multicast;destination=233.252.0.1;"
714       "ttl=1;port=5000-5001;mode=\"PLAY\"";
715   gst_rtsp_client_set_send_func (client, test_setup_response_200_multicast,
716       NULL, NULL);
717   fail_unless (gst_rtsp_client_handle_message (client,
718           &request) == GST_RTSP_OK);
719   gst_rtsp_message_unset (&request);
720   expected_transport = NULL;
721
722   send_teardown (client);
723
724   teardown_client (client);
725 }
726
727 GST_END_TEST;
728
729 static void
730 multicast_transport_specific (void)
731 {
732   GstRTSPClient *client;
733   GstRTSPMessage request = { 0, };
734   gchar *str;
735   GstRTSPSessionPool *session_pool;
736   GstRTSPContext ctx = { NULL };
737
738   client = setup_multicast_client ();
739
740   ctx.client = client;
741   ctx.auth = gst_rtsp_auth_new ();
742   ctx.token =
743       gst_rtsp_token_new (GST_RTSP_TOKEN_TRANSPORT_CLIENT_SETTINGS,
744       G_TYPE_BOOLEAN, TRUE, GST_RTSP_TOKEN_MEDIA_FACTORY_ROLE, G_TYPE_STRING,
745       "user", NULL);
746   gst_rtsp_context_push_current (&ctx);
747
748   expected_transport = "RTP/AVP;multicast;destination=233.252.0.1;"
749       "ttl=1;port=5000-5001;mode=\"PLAY\"";
750
751   /* simple SETUP with a valid URI */
752   fail_unless (gst_rtsp_message_init_request (&request, GST_RTSP_SETUP,
753           "rtsp://localhost/test/stream=0") == GST_RTSP_OK);
754   str = g_strdup_printf ("%d", cseq);
755   gst_rtsp_message_take_header (&request, GST_RTSP_HDR_CSEQ, str);
756   gst_rtsp_message_add_header (&request, GST_RTSP_HDR_TRANSPORT,
757       expected_transport);
758
759   gst_rtsp_client_set_send_func (client, test_setup_response_200_multicast,
760       NULL, NULL);
761   fail_unless (gst_rtsp_client_handle_message (client,
762           &request) == GST_RTSP_OK);
763   gst_rtsp_message_unset (&request);
764
765   gst_rtsp_client_set_send_func (client, test_setup_response_200_multicast,
766       NULL, NULL);
767   session_pool = gst_rtsp_client_get_session_pool (client);
768   fail_unless (session_pool != NULL);
769   fail_unless (gst_rtsp_session_pool_get_n_sessions (session_pool) == 1);
770   g_object_unref (session_pool);
771
772   /* send PLAY request */
773   fail_unless (gst_rtsp_message_init_request (&request, GST_RTSP_PLAY,
774           "rtsp://localhost/test") == GST_RTSP_OK);
775   str = g_strdup_printf ("%d", cseq);
776   gst_rtsp_message_take_header (&request, GST_RTSP_HDR_CSEQ, str);
777   gst_rtsp_message_add_header (&request, GST_RTSP_HDR_SESSION, session_id);
778   gst_rtsp_client_set_send_func (client, test_response_200, NULL, NULL);
779   fail_unless (gst_rtsp_client_handle_message (client,
780           &request) == GST_RTSP_OK);
781   gst_rtsp_message_unset (&request);
782
783   send_teardown (client);
784   teardown_client (client);
785   g_object_unref (ctx.auth);
786   gst_rtsp_token_unref (ctx.token);
787   gst_rtsp_context_pop_current (&ctx);
788 }
789
790 /* CASE: multicast address requested by the client exists in the address pool */
791 GST_START_TEST (test_client_multicast_transport_specific)
792 {
793   expected_transport = "RTP/AVP;multicast;destination=233.252.0.1;"
794       "ttl=1;port=5000-5001;mode=\"PLAY\"";
795   multicast_transport_specific ();
796   expected_transport = NULL;
797 }
798
799 GST_END_TEST;
800
801 /* CASE: multicast address requested by the client does not exist in the address pool */
802 GST_START_TEST (test_client_multicast_transport_specific_no_address_in_pool)
803 {
804   expected_transport = "RTP/AVP;multicast;destination=234.252.0.3;"
805       "ttl=1;port=6000-6001;mode=\"PLAY\"";
806   multicast_transport_specific ();
807   expected_transport = NULL;
808 }
809
810 GST_END_TEST;
811
812 static gboolean
813 test_response_sdp (GstRTSPClient * client, GstRTSPMessage * response,
814     gboolean close, gpointer user_data)
815 {
816   guint8 *data;
817   guint size;
818   GstSDPMessage *sdp_msg;
819   const GstSDPMedia *sdp_media;
820   const GstSDPBandwidth *bw;
821   gint bandwidth_val = GPOINTER_TO_INT (user_data);
822
823   fail_unless (gst_rtsp_message_get_body (response, &data, &size)
824       == GST_RTSP_OK);
825   gst_sdp_message_new (&sdp_msg);
826   fail_unless (gst_sdp_message_parse_buffer (data, size, sdp_msg)
827       == GST_SDP_OK);
828
829   /* session description */
830   /* v= */
831   fail_unless (gst_sdp_message_get_version (sdp_msg) != NULL);
832   /* o= */
833   fail_unless (gst_sdp_message_get_origin (sdp_msg) != NULL);
834   /* s= */
835   fail_unless (gst_sdp_message_get_session_name (sdp_msg) != NULL);
836   /* t=0 0 */
837   fail_unless (gst_sdp_message_times_len (sdp_msg) == 0);
838
839   /* verify number of medias */
840   fail_unless (gst_sdp_message_medias_len (sdp_msg) == 1);
841
842   /* media description */
843   sdp_media = gst_sdp_message_get_media (sdp_msg, 0);
844   fail_unless (sdp_media != NULL);
845
846   /* m= */
847   fail_unless (gst_sdp_media_get_media (sdp_media) != NULL);
848
849   /* media bandwidth */
850   if (bandwidth_val) {
851     fail_unless (gst_sdp_media_bandwidths_len (sdp_media) == 1);
852     bw = gst_sdp_media_get_bandwidth (sdp_media, 0);
853     fail_unless (bw != NULL);
854     fail_unless (g_strcmp0 (bw->bwtype, "AS") == 0);
855     fail_unless (bw->bandwidth == bandwidth_val);
856   } else {
857     fail_unless (gst_sdp_media_bandwidths_len (sdp_media) == 0);
858   }
859
860   gst_sdp_message_free (sdp_msg);
861
862   return TRUE;
863 }
864
865 static void
866 test_client_sdp (const gchar * launch_line, guint * bandwidth_val)
867 {
868   GstRTSPClient *client;
869   GstRTSPMessage request = { 0, };
870   gchar *str;
871
872   /* simple DESCRIBE for an existing url */
873   client = setup_client (launch_line);
874   fail_unless (gst_rtsp_message_init_request (&request, GST_RTSP_DESCRIBE,
875           "rtsp://localhost/test") == GST_RTSP_OK);
876   str = g_strdup_printf ("%d", cseq);
877   gst_rtsp_message_add_header (&request, GST_RTSP_HDR_CSEQ, str);
878   g_free (str);
879
880   gst_rtsp_client_set_send_func (client, test_response_sdp,
881       (gpointer) bandwidth_val, NULL);
882   fail_unless (gst_rtsp_client_handle_message (client,
883           &request) == GST_RTSP_OK);
884   gst_rtsp_message_unset (&request);
885
886   teardown_client (client);
887 }
888
889 GST_START_TEST (test_client_sdp_with_max_bitrate_tag)
890 {
891   test_client_sdp ("videotestsrc "
892       "! taginject tags=\"maximum-bitrate=(uint)50000000\" "
893       "! video/x-raw,width=352,height=288 ! rtpgstpay name=pay0 pt=96",
894       GUINT_TO_POINTER (50000));
895
896
897   /* max-bitrate=0: no bandwidth line */
898   test_client_sdp ("videotestsrc "
899       "! taginject tags=\"maximum-bitrate=(uint)0\" "
900       "! video/x-raw,width=352,height=288 ! rtpgstpay name=pay0 pt=96",
901       GUINT_TO_POINTER (0));
902 }
903
904 GST_END_TEST;
905
906 GST_START_TEST (test_client_sdp_with_bitrate_tag)
907 {
908   test_client_sdp ("videotestsrc "
909       "! taginject tags=\"bitrate=(uint)7000000\" "
910       "! video/x-raw,width=352,height=288 ! rtpgstpay name=pay0 pt=96",
911       GUINT_TO_POINTER (7000));
912
913   /* bitrate=0: no bandwdith line */
914   test_client_sdp ("videotestsrc "
915       "! taginject tags=\"bitrate=(uint)0\" "
916       "! video/x-raw,width=352,height=288 ! rtpgstpay name=pay0 pt=96",
917       GUINT_TO_POINTER (0));
918 }
919
920 GST_END_TEST;
921
922 GST_START_TEST (test_client_sdp_with_max_bitrate_and_bitrate_tags)
923 {
924   test_client_sdp ("videotestsrc "
925       "! taginject tags=\"bitrate=(uint)7000000,maximum-bitrate=(uint)50000000\" "
926       "! video/x-raw,width=352,height=288 ! rtpgstpay name=pay0 pt=96",
927       GUINT_TO_POINTER (50000));
928
929   /* max-bitrate is zero: fallback to bitrate */
930   test_client_sdp ("videotestsrc "
931       "! taginject tags=\"bitrate=(uint)7000000,maximum-bitrate=(uint)0\" "
932       "! video/x-raw,width=352,height=288 ! rtpgstpay name=pay0 pt=96",
933       GUINT_TO_POINTER (7000));
934
935   /* max-bitrate=bitrate=0o: no bandwidth line */
936   test_client_sdp ("videotestsrc "
937       "! taginject tags=\"bitrate=(uint)0,maximum-bitrate=(uint)0\" "
938       "! video/x-raw,width=352,height=288 ! rtpgstpay name=pay0 pt=96",
939       GUINT_TO_POINTER (0));
940 }
941
942 GST_END_TEST;
943
944 GST_START_TEST (test_client_sdp_with_no_bitrate_tags)
945 {
946   test_client_sdp ("videotestsrc "
947       "! video/x-raw,width=352,height=288 ! rtpgstpay name=pay0 pt=96", NULL);
948 }
949
950 GST_END_TEST;
951
952 static void
953 mcast_transport_specific_two_clients (gboolean shared)
954 {
955   GstRTSPClient *client, *client2;
956   GstRTSPMessage request = { 0, };
957   gchar *str;
958   GstRTSPSessionPool *session_pool;
959   GstRTSPContext ctx = { NULL };
960   GstRTSPContext ctx2 = { NULL };
961   GstRTSPMountPoints *mount_points;
962   GstRTSPMediaFactory *factory;
963   GstRTSPAddressPool *address_pool;
964   GstRTSPThreadPool *thread_pool;
965   gchar *session_id1;
966
967   mount_points = gst_rtsp_mount_points_new ();
968   factory = gst_rtsp_media_factory_new ();
969   if (shared)
970     gst_rtsp_media_factory_set_shared (factory, TRUE);
971   gst_rtsp_media_factory_set_max_mcast_ttl (factory, 5);
972   gst_rtsp_media_factory_set_launch (factory,
973       "audiotestsrc ! audio/x-raw,rate=44100 ! audioconvert ! rtpL16pay name=pay0");
974   address_pool = gst_rtsp_address_pool_new ();
975   fail_unless (gst_rtsp_address_pool_add_range (address_pool,
976           "233.252.0.1", "233.252.0.1", 5000, 5001, 1));
977   gst_rtsp_media_factory_set_address_pool (factory, address_pool);
978   gst_rtsp_media_factory_add_role (factory, "user",
979       "media.factory.access", G_TYPE_BOOLEAN, TRUE,
980       "media.factory.construct", G_TYPE_BOOLEAN, TRUE, NULL);
981   gst_rtsp_mount_points_add_factory (mount_points, "/test", factory);
982   session_pool = gst_rtsp_session_pool_new ();
983   thread_pool = gst_rtsp_thread_pool_new ();
984
985   /* first multicast client with transport specific request */
986   client = gst_rtsp_client_new ();
987   gst_rtsp_client_set_session_pool (client, session_pool);
988   gst_rtsp_client_set_mount_points (client, mount_points);
989   gst_rtsp_client_set_thread_pool (client, thread_pool);
990
991   ctx.client = client;
992   ctx.auth = gst_rtsp_auth_new ();
993   ctx.token =
994       gst_rtsp_token_new (GST_RTSP_TOKEN_TRANSPORT_CLIENT_SETTINGS,
995       G_TYPE_BOOLEAN, TRUE, GST_RTSP_TOKEN_MEDIA_FACTORY_ROLE, G_TYPE_STRING,
996       "user", NULL);
997   gst_rtsp_context_push_current (&ctx);
998
999   expected_transport = "RTP/AVP;multicast;destination=233.252.0.1;"
1000       "ttl=1;port=5000-5001;mode=\"PLAY\"";
1001
1002   /* send SETUP request */
1003   fail_unless (gst_rtsp_message_init_request (&request, GST_RTSP_SETUP,
1004           "rtsp://localhost/test/stream=0") == GST_RTSP_OK);
1005   str = g_strdup_printf ("%d", cseq);
1006   gst_rtsp_message_take_header (&request, GST_RTSP_HDR_CSEQ, str);
1007   gst_rtsp_message_add_header (&request, GST_RTSP_HDR_TRANSPORT,
1008       expected_transport);
1009
1010   gst_rtsp_client_set_send_func (client, test_setup_response_200_multicast,
1011       NULL, NULL);
1012   fail_unless (gst_rtsp_client_handle_message (client,
1013           &request) == GST_RTSP_OK);
1014   gst_rtsp_message_unset (&request);
1015   expected_transport = NULL;
1016
1017   /* send PLAY request */
1018   fail_unless (gst_rtsp_message_init_request (&request, GST_RTSP_PLAY,
1019           "rtsp://localhost/test") == GST_RTSP_OK);
1020   str = g_strdup_printf ("%d", cseq);
1021   gst_rtsp_message_take_header (&request, GST_RTSP_HDR_CSEQ, str);
1022   gst_rtsp_message_add_header (&request, GST_RTSP_HDR_SESSION, session_id);
1023   gst_rtsp_client_set_send_func (client, test_response_200, NULL, NULL);
1024   fail_unless (gst_rtsp_client_handle_message (client,
1025           &request) == GST_RTSP_OK);
1026   gst_rtsp_message_unset (&request);
1027   gst_rtsp_context_pop_current (&ctx);
1028   session_id1 = session_id;
1029
1030   /* second multicast client with transport specific request */
1031   cseq = 0;
1032   client2 = gst_rtsp_client_new ();
1033   gst_rtsp_client_set_session_pool (client2, session_pool);
1034   gst_rtsp_client_set_mount_points (client2, mount_points);
1035   gst_rtsp_client_set_thread_pool (client2, thread_pool);
1036
1037   ctx2.client = client2;
1038   ctx2.auth = gst_rtsp_auth_new ();
1039   ctx2.token =
1040       gst_rtsp_token_new (GST_RTSP_TOKEN_TRANSPORT_CLIENT_SETTINGS,
1041       G_TYPE_BOOLEAN, TRUE, GST_RTSP_TOKEN_MEDIA_FACTORY_ROLE, G_TYPE_STRING,
1042       "user", NULL);
1043   gst_rtsp_context_push_current (&ctx2);
1044
1045   expected_transport = "RTP/AVP;multicast;destination=233.252.0.2;"
1046       "ttl=1;port=5002-5003;mode=\"PLAY\"";
1047
1048   /* send SETUP request */
1049   fail_unless (gst_rtsp_message_init_request (&request, GST_RTSP_SETUP,
1050           "rtsp://localhost/test/stream=0") == GST_RTSP_OK);
1051   str = g_strdup_printf ("%d", cseq);
1052   gst_rtsp_message_take_header (&request, GST_RTSP_HDR_CSEQ, str);
1053   gst_rtsp_message_add_header (&request, GST_RTSP_HDR_TRANSPORT,
1054       expected_transport);
1055
1056   gst_rtsp_client_set_send_func (client2, test_setup_response_200_multicast,
1057       NULL, NULL);
1058   fail_unless (gst_rtsp_client_handle_message (client2,
1059           &request) == GST_RTSP_OK);
1060   gst_rtsp_message_unset (&request);
1061   expected_transport = NULL;
1062
1063   /* send PLAY request */
1064   fail_unless (gst_rtsp_message_init_request (&request, GST_RTSP_PLAY,
1065           "rtsp://localhost/test") == GST_RTSP_OK);
1066   str = g_strdup_printf ("%d", cseq);
1067   gst_rtsp_message_take_header (&request, GST_RTSP_HDR_CSEQ, str);
1068   gst_rtsp_message_add_header (&request, GST_RTSP_HDR_SESSION, session_id);
1069   gst_rtsp_client_set_send_func (client2, test_response_200, NULL, NULL);
1070   fail_unless (gst_rtsp_client_handle_message (client2,
1071           &request) == GST_RTSP_OK);
1072   gst_rtsp_message_unset (&request);
1073
1074   send_teardown (client2);
1075   gst_rtsp_context_pop_current (&ctx2);
1076
1077   gst_rtsp_context_push_current (&ctx);
1078   session_id = session_id1;
1079   send_teardown (client);
1080   gst_rtsp_context_pop_current (&ctx);
1081
1082   teardown_client (client);
1083   teardown_client (client2);
1084   g_object_unref (ctx.auth);
1085   g_object_unref (ctx2.auth);
1086   gst_rtsp_token_unref (ctx.token);
1087   gst_rtsp_token_unref (ctx2.token);
1088   g_object_unref (mount_points);
1089   g_object_unref (session_pool);
1090   g_object_unref (address_pool);
1091   g_object_unref (thread_pool);
1092 }
1093
1094 /* test if two multicast clients can choose different transport settings
1095  * CASE: media is shared */
1096 GST_START_TEST
1097     (test_client_multicast_transport_specific_two_clients_shared_media) {
1098   mcast_transport_specific_two_clients (TRUE);
1099 }
1100
1101 GST_END_TEST;
1102
1103 /* test if two multicast clients can choose different transport settings
1104  * CASE: media is not shared */
1105 GST_START_TEST (test_client_multicast_transport_specific_two_clients)
1106 {
1107   mcast_transport_specific_two_clients (FALSE);
1108 }
1109
1110 GST_END_TEST;
1111
1112 static Suite *
1113 rtspclient_suite (void)
1114 {
1115   Suite *s = suite_create ("rtspclient");
1116   TCase *tc = tcase_create ("general");
1117
1118   suite_add_tcase (s, tc);
1119   tcase_set_timeout (tc, 20);
1120   tcase_add_test (tc, test_require);
1121   tcase_add_test (tc, test_request);
1122   tcase_add_test (tc, test_options);
1123   tcase_add_test (tc, test_describe);
1124   tcase_add_test (tc, test_client_multicast_transport_404);
1125   tcase_add_test (tc, test_client_multicast_transport);
1126   tcase_add_test (tc, test_client_multicast_ignore_transport_specific);
1127   tcase_add_test (tc, test_client_multicast_transport_specific);
1128   tcase_add_test (tc, test_client_sdp_with_max_bitrate_tag);
1129   tcase_add_test (tc, test_client_sdp_with_bitrate_tag);
1130   tcase_add_test (tc, test_client_sdp_with_max_bitrate_and_bitrate_tags);
1131   tcase_add_test (tc, test_client_sdp_with_no_bitrate_tags);
1132   tcase_add_test (tc,
1133       test_client_multicast_transport_specific_two_clients_shared_media);
1134   tcase_add_test (tc, test_client_multicast_transport_specific_two_clients);
1135   tcase_add_test (tc,
1136       test_client_multicast_transport_specific_no_address_in_pool);
1137
1138   return s;
1139 }
1140
1141 GST_CHECK_MAIN (rtspclient);