ab95509f93c87b578ae3276a2f36987a6f780802
[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 GST_START_TEST (test_client_multicast_transport_specific)
730 {
731   GstRTSPClient *client;
732   GstRTSPMessage request = { 0, };
733   gchar *str;
734   GstRTSPSessionPool *session_pool;
735   GstRTSPContext ctx = { NULL };
736
737   client = setup_multicast_client ();
738
739   ctx.client = client;
740   ctx.auth = gst_rtsp_auth_new ();
741   ctx.token =
742       gst_rtsp_token_new (GST_RTSP_TOKEN_TRANSPORT_CLIENT_SETTINGS,
743       G_TYPE_BOOLEAN, TRUE, GST_RTSP_TOKEN_MEDIA_FACTORY_ROLE, G_TYPE_STRING,
744       "user", NULL);
745   gst_rtsp_context_push_current (&ctx);
746
747   expected_transport = "RTP/AVP;multicast;destination=233.252.0.1;"
748       "ttl=1;port=5000-5001;mode=\"PLAY\"";
749
750   /* simple SETUP with a valid URI */
751   fail_unless (gst_rtsp_message_init_request (&request, GST_RTSP_SETUP,
752           "rtsp://localhost/test/stream=0") == GST_RTSP_OK);
753   str = g_strdup_printf ("%d", cseq);
754   gst_rtsp_message_take_header (&request, GST_RTSP_HDR_CSEQ, str);
755   gst_rtsp_message_add_header (&request, GST_RTSP_HDR_TRANSPORT,
756       expected_transport);
757
758   gst_rtsp_client_set_send_func (client, test_setup_response_200_multicast,
759       NULL, NULL);
760   fail_unless (gst_rtsp_client_handle_message (client,
761           &request) == GST_RTSP_OK);
762   gst_rtsp_message_unset (&request);
763   expected_transport = NULL;
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_teardown (client);
773
774   teardown_client (client);
775   g_object_unref (ctx.auth);
776   gst_rtsp_token_unref (ctx.token);
777   gst_rtsp_context_pop_current (&ctx);
778 }
779
780 GST_END_TEST;
781
782 static gboolean
783 test_response_sdp (GstRTSPClient * client, GstRTSPMessage * response,
784     gboolean close, gpointer user_data)
785 {
786   guint8 *data;
787   guint size;
788   GstSDPMessage *sdp_msg;
789   const GstSDPMedia *sdp_media;
790   const GstSDPBandwidth *bw;
791   gint bandwidth_val = GPOINTER_TO_INT (user_data);
792
793   fail_unless (gst_rtsp_message_get_body (response, &data, &size)
794       == GST_RTSP_OK);
795   gst_sdp_message_new (&sdp_msg);
796   fail_unless (gst_sdp_message_parse_buffer (data, size, sdp_msg)
797       == GST_SDP_OK);
798
799   /* session description */
800   /* v= */
801   fail_unless (gst_sdp_message_get_version (sdp_msg) != NULL);
802   /* o= */
803   fail_unless (gst_sdp_message_get_origin (sdp_msg) != NULL);
804   /* s= */
805   fail_unless (gst_sdp_message_get_session_name (sdp_msg) != NULL);
806   /* t=0 0 */
807   fail_unless (gst_sdp_message_times_len (sdp_msg) == 0);
808
809   /* verify number of medias */
810   fail_unless (gst_sdp_message_medias_len (sdp_msg) == 1);
811
812   /* media description */
813   sdp_media = gst_sdp_message_get_media (sdp_msg, 0);
814   fail_unless (sdp_media != NULL);
815
816   /* m= */
817   fail_unless (gst_sdp_media_get_media (sdp_media) != NULL);
818
819   /* media bandwidth */
820   if (bandwidth_val) {
821     fail_unless (gst_sdp_media_bandwidths_len (sdp_media) == 1);
822     bw = gst_sdp_media_get_bandwidth (sdp_media, 0);
823     fail_unless (bw != NULL);
824     fail_unless (g_strcmp0 (bw->bwtype, "AS") == 0);
825     fail_unless (bw->bandwidth == bandwidth_val);
826   } else {
827     fail_unless (gst_sdp_media_bandwidths_len (sdp_media) == 0);
828   }
829
830   gst_sdp_message_free (sdp_msg);
831
832   return TRUE;
833 }
834
835 static void
836 test_client_sdp (const gchar * launch_line, guint * bandwidth_val)
837 {
838   GstRTSPClient *client;
839   GstRTSPMessage request = { 0, };
840   gchar *str;
841
842   /* simple DESCRIBE for an existing url */
843   client = setup_client (launch_line);
844   fail_unless (gst_rtsp_message_init_request (&request, GST_RTSP_DESCRIBE,
845           "rtsp://localhost/test") == GST_RTSP_OK);
846   str = g_strdup_printf ("%d", cseq);
847   gst_rtsp_message_add_header (&request, GST_RTSP_HDR_CSEQ, str);
848   g_free (str);
849
850   gst_rtsp_client_set_send_func (client, test_response_sdp,
851       (gpointer) bandwidth_val, NULL);
852   fail_unless (gst_rtsp_client_handle_message (client,
853           &request) == GST_RTSP_OK);
854   gst_rtsp_message_unset (&request);
855
856   teardown_client (client);
857 }
858
859 GST_START_TEST (test_client_sdp_with_max_bitrate_tag)
860 {
861   test_client_sdp ("videotestsrc "
862       "! taginject tags=\"maximum-bitrate=(uint)50000000\" "
863       "! video/x-raw,width=352,height=288 ! rtpgstpay name=pay0 pt=96",
864       GUINT_TO_POINTER (50000));
865
866
867   /* max-bitrate=0: no bandwidth line */
868   test_client_sdp ("videotestsrc "
869       "! taginject tags=\"maximum-bitrate=(uint)0\" "
870       "! video/x-raw,width=352,height=288 ! rtpgstpay name=pay0 pt=96",
871       GUINT_TO_POINTER (0));
872 }
873
874 GST_END_TEST;
875
876 GST_START_TEST (test_client_sdp_with_bitrate_tag)
877 {
878   test_client_sdp ("videotestsrc "
879       "! taginject tags=\"bitrate=(uint)7000000\" "
880       "! video/x-raw,width=352,height=288 ! rtpgstpay name=pay0 pt=96",
881       GUINT_TO_POINTER (7000));
882
883   /* bitrate=0: no bandwdith line */
884   test_client_sdp ("videotestsrc "
885       "! taginject tags=\"bitrate=(uint)0\" "
886       "! video/x-raw,width=352,height=288 ! rtpgstpay name=pay0 pt=96",
887       GUINT_TO_POINTER (0));
888 }
889
890 GST_END_TEST;
891
892 GST_START_TEST (test_client_sdp_with_max_bitrate_and_bitrate_tags)
893 {
894   test_client_sdp ("videotestsrc "
895       "! taginject tags=\"bitrate=(uint)7000000,maximum-bitrate=(uint)50000000\" "
896       "! video/x-raw,width=352,height=288 ! rtpgstpay name=pay0 pt=96",
897       GUINT_TO_POINTER (50000));
898
899   /* max-bitrate is zero: fallback to bitrate */
900   test_client_sdp ("videotestsrc "
901       "! taginject tags=\"bitrate=(uint)7000000,maximum-bitrate=(uint)0\" "
902       "! video/x-raw,width=352,height=288 ! rtpgstpay name=pay0 pt=96",
903       GUINT_TO_POINTER (7000));
904
905   /* max-bitrate=bitrate=0o: no bandwidth line */
906   test_client_sdp ("videotestsrc "
907       "! taginject tags=\"bitrate=(uint)0,maximum-bitrate=(uint)0\" "
908       "! video/x-raw,width=352,height=288 ! rtpgstpay name=pay0 pt=96",
909       GUINT_TO_POINTER (0));
910 }
911
912 GST_END_TEST;
913
914 GST_START_TEST (test_client_sdp_with_no_bitrate_tags)
915 {
916   test_client_sdp ("videotestsrc "
917       "! video/x-raw,width=352,height=288 ! rtpgstpay name=pay0 pt=96", NULL);
918 }
919
920 GST_END_TEST;
921
922 static void
923 mcast_transport_specific_two_clients (gboolean shared)
924 {
925   GstRTSPClient *client, *client2;
926   GstRTSPMessage request = { 0, };
927   gchar *str;
928   GstRTSPSessionPool *session_pool;
929   GstRTSPContext ctx = { NULL };
930   GstRTSPContext ctx2 = { NULL };
931   GstRTSPMountPoints *mount_points;
932   GstRTSPMediaFactory *factory;
933   GstRTSPAddressPool *address_pool;
934   GstRTSPThreadPool *thread_pool;
935   gchar *session_id1;
936
937   mount_points = gst_rtsp_mount_points_new ();
938   factory = gst_rtsp_media_factory_new ();
939   if (shared)
940     gst_rtsp_media_factory_set_shared (factory, TRUE);
941   gst_rtsp_media_factory_set_max_mcast_ttl (factory, 5);
942   gst_rtsp_media_factory_set_launch (factory,
943       "audiotestsrc ! audio/x-raw,rate=44100 ! audioconvert ! rtpL16pay name=pay0");
944   address_pool = gst_rtsp_address_pool_new ();
945   fail_unless (gst_rtsp_address_pool_add_range (address_pool,
946           "233.252.0.1", "233.252.0.1", 5000, 5001, 1));
947   gst_rtsp_media_factory_set_address_pool (factory, address_pool);
948   gst_rtsp_media_factory_add_role (factory, "user",
949       "media.factory.access", G_TYPE_BOOLEAN, TRUE,
950       "media.factory.construct", G_TYPE_BOOLEAN, TRUE, NULL);
951   gst_rtsp_mount_points_add_factory (mount_points, "/test", factory);
952   session_pool = gst_rtsp_session_pool_new ();
953   thread_pool = gst_rtsp_thread_pool_new ();
954
955   /* first multicast client with transport specific request */
956   client = gst_rtsp_client_new ();
957   gst_rtsp_client_set_session_pool (client, session_pool);
958   gst_rtsp_client_set_mount_points (client, mount_points);
959   gst_rtsp_client_set_thread_pool (client, thread_pool);
960
961   ctx.client = client;
962   ctx.auth = gst_rtsp_auth_new ();
963   ctx.token =
964       gst_rtsp_token_new (GST_RTSP_TOKEN_TRANSPORT_CLIENT_SETTINGS,
965       G_TYPE_BOOLEAN, TRUE, GST_RTSP_TOKEN_MEDIA_FACTORY_ROLE, G_TYPE_STRING,
966       "user", NULL);
967   gst_rtsp_context_push_current (&ctx);
968
969   expected_transport = "RTP/AVP;multicast;destination=233.252.0.1;"
970       "ttl=1;port=5000-5001;mode=\"PLAY\"";
971
972   /* send SETUP request */
973   fail_unless (gst_rtsp_message_init_request (&request, GST_RTSP_SETUP,
974           "rtsp://localhost/test/stream=0") == GST_RTSP_OK);
975   str = g_strdup_printf ("%d", cseq);
976   gst_rtsp_message_take_header (&request, GST_RTSP_HDR_CSEQ, str);
977   gst_rtsp_message_add_header (&request, GST_RTSP_HDR_TRANSPORT,
978       expected_transport);
979
980   gst_rtsp_client_set_send_func (client, test_setup_response_200_multicast,
981       NULL, NULL);
982   fail_unless (gst_rtsp_client_handle_message (client,
983           &request) == GST_RTSP_OK);
984   gst_rtsp_message_unset (&request);
985   expected_transport = NULL;
986
987   /* send PLAY request */
988   fail_unless (gst_rtsp_message_init_request (&request, GST_RTSP_PLAY,
989           "rtsp://localhost/test") == GST_RTSP_OK);
990   str = g_strdup_printf ("%d", cseq);
991   gst_rtsp_message_take_header (&request, GST_RTSP_HDR_CSEQ, str);
992   gst_rtsp_message_add_header (&request, GST_RTSP_HDR_SESSION, session_id);
993   gst_rtsp_client_set_send_func (client, test_response_200, NULL, NULL);
994   fail_unless (gst_rtsp_client_handle_message (client,
995           &request) == GST_RTSP_OK);
996   gst_rtsp_message_unset (&request);
997   gst_rtsp_context_pop_current (&ctx);
998   session_id1 = session_id;
999
1000   /* second multicast client with transport specific request */
1001   cseq = 0;
1002   client2 = gst_rtsp_client_new ();
1003   gst_rtsp_client_set_session_pool (client2, session_pool);
1004   gst_rtsp_client_set_mount_points (client2, mount_points);
1005   gst_rtsp_client_set_thread_pool (client2, thread_pool);
1006
1007   ctx2.client = client2;
1008   ctx2.auth = gst_rtsp_auth_new ();
1009   ctx2.token =
1010       gst_rtsp_token_new (GST_RTSP_TOKEN_TRANSPORT_CLIENT_SETTINGS,
1011       G_TYPE_BOOLEAN, TRUE, GST_RTSP_TOKEN_MEDIA_FACTORY_ROLE, G_TYPE_STRING,
1012       "user", NULL);
1013   gst_rtsp_context_push_current (&ctx2);
1014
1015   expected_transport = "RTP/AVP;multicast;destination=233.252.0.2;"
1016       "ttl=1;port=5002-5003;mode=\"PLAY\"";
1017
1018   /* send SETUP request */
1019   fail_unless (gst_rtsp_message_init_request (&request, GST_RTSP_SETUP,
1020           "rtsp://localhost/test/stream=0") == GST_RTSP_OK);
1021   str = g_strdup_printf ("%d", cseq);
1022   gst_rtsp_message_take_header (&request, GST_RTSP_HDR_CSEQ, str);
1023   gst_rtsp_message_add_header (&request, GST_RTSP_HDR_TRANSPORT,
1024       expected_transport);
1025
1026   gst_rtsp_client_set_send_func (client2, test_setup_response_200_multicast,
1027       NULL, NULL);
1028   fail_unless (gst_rtsp_client_handle_message (client2,
1029           &request) == GST_RTSP_OK);
1030   gst_rtsp_message_unset (&request);
1031   expected_transport = NULL;
1032
1033   /* send PLAY request */
1034   fail_unless (gst_rtsp_message_init_request (&request, GST_RTSP_PLAY,
1035           "rtsp://localhost/test") == GST_RTSP_OK);
1036   str = g_strdup_printf ("%d", cseq);
1037   gst_rtsp_message_take_header (&request, GST_RTSP_HDR_CSEQ, str);
1038   gst_rtsp_message_add_header (&request, GST_RTSP_HDR_SESSION, session_id);
1039   gst_rtsp_client_set_send_func (client2, test_response_200, NULL, NULL);
1040   fail_unless (gst_rtsp_client_handle_message (client2,
1041           &request) == GST_RTSP_OK);
1042   gst_rtsp_message_unset (&request);
1043
1044   send_teardown (client2);
1045   gst_rtsp_context_pop_current (&ctx2);
1046
1047   gst_rtsp_context_push_current (&ctx);
1048   session_id = session_id1;
1049   send_teardown (client);
1050   gst_rtsp_context_pop_current (&ctx);
1051
1052   teardown_client (client);
1053   teardown_client (client2);
1054   g_object_unref (ctx.auth);
1055   g_object_unref (ctx2.auth);
1056   gst_rtsp_token_unref (ctx.token);
1057   gst_rtsp_token_unref (ctx2.token);
1058   g_object_unref (mount_points);
1059   g_object_unref (session_pool);
1060   g_object_unref (address_pool);
1061   g_object_unref (thread_pool);
1062 }
1063
1064 /* test if two multicast clients can choose different transport settings */
1065 GST_START_TEST
1066     (test_client_multicast_transport_specific_two_clients_shared_media) {
1067   mcast_transport_specific_two_clients (TRUE);
1068 }
1069
1070 GST_END_TEST;
1071
1072 static Suite *
1073 rtspclient_suite (void)
1074 {
1075   Suite *s = suite_create ("rtspclient");
1076   TCase *tc = tcase_create ("general");
1077
1078   suite_add_tcase (s, tc);
1079   tcase_set_timeout (tc, 20);
1080   tcase_add_test (tc, test_require);
1081   tcase_add_test (tc, test_request);
1082   tcase_add_test (tc, test_options);
1083   tcase_add_test (tc, test_describe);
1084   tcase_add_test (tc, test_client_multicast_transport_404);
1085   tcase_add_test (tc, test_client_multicast_transport);
1086   tcase_add_test (tc, test_client_multicast_ignore_transport_specific);
1087   tcase_add_test (tc, test_client_multicast_transport_specific);
1088   tcase_add_test (tc, test_client_sdp_with_max_bitrate_tag);
1089   tcase_add_test (tc, test_client_sdp_with_bitrate_tag);
1090   tcase_add_test (tc, test_client_sdp_with_max_bitrate_and_bitrate_tags);
1091   tcase_add_test (tc, test_client_sdp_with_no_bitrate_tags);
1092   tcase_add_test (tc,
1093       test_client_multicast_transport_specific_two_clients_shared_media);
1094
1095   return s;
1096 }
1097
1098 GST_CHECK_MAIN (rtspclient);