rtsp-client: Report RECORD and ANNOUNCE as supported in the OPTIONS
[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 (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 (code == GST_RTSP_STS_OK);
495   fail_unless (g_str_equal (reason, "OK"));
496   fail_unless (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 (!strcmp (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   fail_unless (gst_rtsp_session_pool_get_n_sessions (session_pool) == 1);
529   session = gst_rtsp_session_pool_find (session_pool, session_hdr_params[0]);
530   g_strfreev (session_hdr_params);
531
532   /* remember session id to be able to send teardown */
533   session_id = g_strdup (gst_rtsp_session_get_sessionid (session));
534   fail_unless (session_id != NULL);
535
536   fail_unless (session != NULL);
537   g_object_unref (session);
538
539   g_object_unref (session_pool);
540
541
542   return TRUE;
543 }
544
545 static gboolean
546 test_teardown_response_200 (GstRTSPClient * client,
547     GstRTSPMessage * response, gboolean close, gpointer user_data)
548 {
549   GstRTSPStatusCode code;
550   const gchar *reason;
551   GstRTSPVersion version;
552
553   fail_unless (gst_rtsp_message_get_type (response) ==
554       GST_RTSP_MESSAGE_RESPONSE);
555
556   fail_unless (gst_rtsp_message_parse_response (response, &code, &reason,
557           &version)
558       == GST_RTSP_OK);
559   fail_unless (code == GST_RTSP_STS_OK);
560   fail_unless (g_str_equal (reason, "OK"));
561   fail_unless (version == GST_RTSP_VERSION_1_0);
562
563   return TRUE;
564 }
565
566 static void
567 send_teardown (GstRTSPClient * client)
568 {
569   GstRTSPMessage request = { 0, };
570   gchar *str;
571
572   fail_unless (session_id != NULL);
573   fail_unless (gst_rtsp_message_init_request (&request, GST_RTSP_TEARDOWN,
574           "rtsp://localhost/test") == GST_RTSP_OK);
575   str = g_strdup_printf ("%d", cseq);
576   gst_rtsp_message_take_header (&request, GST_RTSP_HDR_CSEQ, str);
577   gst_rtsp_message_add_header (&request, GST_RTSP_HDR_SESSION, session_id);
578   gst_rtsp_client_set_send_func (client, test_teardown_response_200,
579       NULL, NULL);
580   fail_unless (gst_rtsp_client_handle_message (client,
581           &request) == GST_RTSP_OK);
582   gst_rtsp_message_unset (&request);
583   g_free (session_id);
584   session_id = NULL;
585 }
586
587 static GstRTSPClient *
588 setup_multicast_client (void)
589 {
590   GstRTSPClient *client;
591   GstRTSPSessionPool *session_pool;
592   GstRTSPMountPoints *mount_points;
593   GstRTSPMediaFactory *factory;
594   GstRTSPAddressPool *address_pool;
595   GstRTSPThreadPool *thread_pool;
596
597   client = gst_rtsp_client_new ();
598
599   session_pool = gst_rtsp_session_pool_new ();
600   gst_rtsp_client_set_session_pool (client, session_pool);
601
602   mount_points = gst_rtsp_mount_points_new ();
603   factory = gst_rtsp_media_factory_new ();
604   gst_rtsp_media_factory_set_launch (factory,
605       "audiotestsrc ! audio/x-raw,rate=44100 ! audioconvert ! rtpL16pay name=pay0");
606   address_pool = gst_rtsp_address_pool_new ();
607   fail_unless (gst_rtsp_address_pool_add_range (address_pool,
608           "233.252.0.1", "233.252.0.1", 5000, 5010, 1));
609   gst_rtsp_media_factory_set_address_pool (factory, address_pool);
610   gst_rtsp_media_factory_add_role (factory, "user",
611       "media.factory.access", G_TYPE_BOOLEAN, TRUE,
612       "media.factory.construct", G_TYPE_BOOLEAN, TRUE, NULL);
613   gst_rtsp_mount_points_add_factory (mount_points, "/test", factory);
614   gst_rtsp_client_set_mount_points (client, mount_points);
615
616   thread_pool = gst_rtsp_thread_pool_new ();
617   gst_rtsp_client_set_thread_pool (client, thread_pool);
618
619   g_object_unref (mount_points);
620   g_object_unref (session_pool);
621   g_object_unref (address_pool);
622   g_object_unref (thread_pool);
623
624   return client;
625 }
626
627 GST_START_TEST (test_client_multicast_transport_404)
628 {
629   GstRTSPClient *client;
630   GstRTSPMessage request = { 0, };
631   gchar *str;
632
633   client = setup_multicast_client ();
634
635   /* simple SETUP for non-existing url */
636   fail_unless (gst_rtsp_message_init_request (&request, GST_RTSP_SETUP,
637           "rtsp://localhost/test2/stream=0") == GST_RTSP_OK);
638   str = g_strdup_printf ("%d", cseq);
639   gst_rtsp_message_take_header (&request, GST_RTSP_HDR_CSEQ, str);
640   gst_rtsp_message_add_header (&request, GST_RTSP_HDR_TRANSPORT,
641       "RTP/AVP;multicast");
642
643   gst_rtsp_client_set_send_func (client, test_response_404, NULL, NULL);
644   fail_unless (gst_rtsp_client_handle_message (client,
645           &request) == GST_RTSP_OK);
646   gst_rtsp_message_unset (&request);
647
648   teardown_client (client);
649 }
650
651 GST_END_TEST;
652
653 static void
654 new_session_cb (GObject * client, GstRTSPSession * session, gpointer user_data)
655 {
656   GST_DEBUG ("%p: new session %p", client, session);
657   gst_rtsp_session_set_timeout (session, expected_session_timeout);
658 }
659
660 GST_START_TEST (test_client_multicast_transport)
661 {
662   GstRTSPClient *client;
663   GstRTSPMessage request = { 0, };
664   gchar *str;
665
666   client = setup_multicast_client ();
667
668   expected_session_timeout = 20;
669   g_signal_connect (G_OBJECT (client), "new-session",
670       G_CALLBACK (new_session_cb), NULL);
671
672   /* simple SETUP with a valid URI and multicast */
673   fail_unless (gst_rtsp_message_init_request (&request, GST_RTSP_SETUP,
674           "rtsp://localhost/test/stream=0") == GST_RTSP_OK);
675   str = g_strdup_printf ("%d", cseq);
676   gst_rtsp_message_take_header (&request, GST_RTSP_HDR_CSEQ, str);
677   gst_rtsp_message_add_header (&request, GST_RTSP_HDR_TRANSPORT,
678       "RTP/AVP;multicast");
679
680   expected_transport = "RTP/AVP;multicast;destination=233.252.0.1;"
681       "ttl=1;port=5000-5001;mode=\"PLAY\"";
682   gst_rtsp_client_set_send_func (client, test_setup_response_200_multicast,
683       NULL, NULL);
684   fail_unless (gst_rtsp_client_handle_message (client,
685           &request) == GST_RTSP_OK);
686   gst_rtsp_message_unset (&request);
687   expected_transport = NULL;
688   expected_session_timeout = 60;
689
690   send_teardown (client);
691
692   teardown_client (client);
693 }
694
695 GST_END_TEST;
696
697 GST_START_TEST (test_client_multicast_ignore_transport_specific)
698 {
699   GstRTSPClient *client;
700   GstRTSPMessage request = { 0, };
701   gchar *str;
702
703   client = setup_multicast_client ();
704
705   /* simple SETUP with a valid URI and multicast and a specific dest,
706    * but ignore it  */
707   fail_unless (gst_rtsp_message_init_request (&request, GST_RTSP_SETUP,
708           "rtsp://localhost/test/stream=0") == GST_RTSP_OK);
709   str = g_strdup_printf ("%d", cseq);
710   gst_rtsp_message_take_header (&request, GST_RTSP_HDR_CSEQ, str);
711   gst_rtsp_message_add_header (&request, GST_RTSP_HDR_TRANSPORT,
712       "RTP/AVP;multicast;destination=233.252.0.2;ttl=2;port=5001-5006;");
713
714   expected_transport = "RTP/AVP;multicast;destination=233.252.0.1;"
715       "ttl=1;port=5000-5001;mode=\"PLAY\"";
716   gst_rtsp_client_set_send_func (client, test_setup_response_200_multicast,
717       NULL, NULL);
718   fail_unless (gst_rtsp_client_handle_message (client,
719           &request) == GST_RTSP_OK);
720   gst_rtsp_message_unset (&request);
721   expected_transport = NULL;
722
723   send_teardown (client);
724
725   teardown_client (client);
726 }
727
728 GST_END_TEST;
729
730 static gboolean
731 test_setup_response_461 (GstRTSPClient * client,
732     GstRTSPMessage * response, gboolean close, gpointer user_data)
733 {
734   GstRTSPStatusCode code;
735   const gchar *reason;
736   GstRTSPVersion version;
737   gchar *str;
738
739   fail_unless (expected_transport == NULL);
740
741   fail_unless (gst_rtsp_message_get_type (response) ==
742       GST_RTSP_MESSAGE_RESPONSE);
743
744   fail_unless (gst_rtsp_message_parse_response (response, &code, &reason,
745           &version)
746       == GST_RTSP_OK);
747   fail_unless (code == GST_RTSP_STS_UNSUPPORTED_TRANSPORT);
748   fail_unless (g_str_equal (reason, "Unsupported transport"));
749   fail_unless (version == GST_RTSP_VERSION_1_0);
750
751   fail_unless (gst_rtsp_message_get_header (response, GST_RTSP_HDR_CSEQ, &str,
752           0) == GST_RTSP_OK);
753   fail_unless (atoi (str) == cseq++);
754
755
756   return TRUE;
757 }
758
759 GST_START_TEST (test_client_multicast_invalid_transport_specific)
760 {
761   GstRTSPClient *client;
762   GstRTSPMessage request = { 0, };
763   gchar *str;
764   GstRTSPSessionPool *session_pool;
765   GstRTSPContext ctx = { NULL };
766
767   client = setup_multicast_client ();
768
769   ctx.client = client;
770   ctx.auth = gst_rtsp_auth_new ();
771   ctx.token =
772       gst_rtsp_token_new (GST_RTSP_TOKEN_TRANSPORT_CLIENT_SETTINGS,
773       G_TYPE_BOOLEAN, TRUE, GST_RTSP_TOKEN_MEDIA_FACTORY_ROLE, G_TYPE_STRING,
774       "user", NULL);
775   gst_rtsp_context_push_current (&ctx);
776
777   /* simple SETUP with a valid URI and multicast, but an invalid ip */
778   fail_unless (gst_rtsp_message_init_request (&request, GST_RTSP_SETUP,
779           "rtsp://localhost/test/stream=0") == GST_RTSP_OK);
780   str = g_strdup_printf ("%d", cseq);
781   gst_rtsp_message_take_header (&request, GST_RTSP_HDR_CSEQ, str);
782   gst_rtsp_message_add_header (&request, GST_RTSP_HDR_TRANSPORT,
783       "RTP/AVP;multicast;destination=233.252.0.2;ttl=1;port=5000-5001;");
784
785   gst_rtsp_client_set_send_func (client, test_setup_response_461, NULL, NULL);
786   fail_unless (gst_rtsp_client_handle_message (client,
787           &request) == GST_RTSP_OK);
788   gst_rtsp_message_unset (&request);
789
790   session_pool = gst_rtsp_client_get_session_pool (client);
791   fail_unless (session_pool != NULL);
792   fail_unless (gst_rtsp_session_pool_get_n_sessions (session_pool) == 0);
793   g_object_unref (session_pool);
794
795
796
797   /* simple SETUP with a valid URI and multicast, but an invalid prt */
798   fail_unless (gst_rtsp_message_init_request (&request, GST_RTSP_SETUP,
799           "rtsp://localhost/test/stream=0") == GST_RTSP_OK);
800   str = g_strdup_printf ("%d", cseq);
801   gst_rtsp_message_take_header (&request, GST_RTSP_HDR_CSEQ, str);
802   gst_rtsp_message_add_header (&request, GST_RTSP_HDR_TRANSPORT,
803       "RTP/AVP;multicast;destination=233.252.0.1;ttl=1;port=6000-6001;");
804
805   gst_rtsp_client_set_send_func (client, test_setup_response_461, NULL, NULL);
806   fail_unless (gst_rtsp_client_handle_message (client,
807           &request) == GST_RTSP_OK);
808   gst_rtsp_message_unset (&request);
809
810   session_pool = gst_rtsp_client_get_session_pool (client);
811   fail_unless (session_pool != NULL);
812   fail_unless (gst_rtsp_session_pool_get_n_sessions (session_pool) == 0);
813   g_object_unref (session_pool);
814
815
816
817   /* simple SETUP with a valid URI and multicast, but an invalid ttl */
818   fail_unless (gst_rtsp_message_init_request (&request, GST_RTSP_SETUP,
819           "rtsp://localhost/test/stream=0") == GST_RTSP_OK);
820   str = g_strdup_printf ("%d", cseq);
821   gst_rtsp_message_take_header (&request, GST_RTSP_HDR_CSEQ, str);
822   gst_rtsp_message_add_header (&request, GST_RTSP_HDR_TRANSPORT,
823       "RTP/AVP;multicast;destination=233.252.0.1;ttl=2;port=5000-5001;");
824
825   gst_rtsp_client_set_send_func (client, test_setup_response_461, NULL, NULL);
826   fail_unless (gst_rtsp_client_handle_message (client,
827           &request) == GST_RTSP_OK);
828   gst_rtsp_message_unset (&request);
829
830   session_pool = gst_rtsp_client_get_session_pool (client);
831   fail_unless (session_pool != NULL);
832   fail_unless (gst_rtsp_session_pool_get_n_sessions (session_pool) == 0);
833   g_object_unref (session_pool);
834
835
836   teardown_client (client);
837   g_object_unref (ctx.auth);
838   gst_rtsp_token_unref (ctx.token);
839   gst_rtsp_context_pop_current (&ctx);
840 }
841
842 GST_END_TEST;
843
844 GST_START_TEST (test_client_multicast_transport_specific)
845 {
846   GstRTSPClient *client;
847   GstRTSPMessage request = { 0, };
848   gchar *str;
849   GstRTSPSessionPool *session_pool;
850   GstRTSPContext ctx = { NULL };
851
852   client = setup_multicast_client ();
853
854   ctx.client = client;
855   ctx.auth = gst_rtsp_auth_new ();
856   ctx.token =
857       gst_rtsp_token_new (GST_RTSP_TOKEN_TRANSPORT_CLIENT_SETTINGS,
858       G_TYPE_BOOLEAN, TRUE, GST_RTSP_TOKEN_MEDIA_FACTORY_ROLE, G_TYPE_STRING,
859       "user", NULL);
860   gst_rtsp_context_push_current (&ctx);
861
862   expected_transport = "RTP/AVP;multicast;destination=233.252.0.1;"
863       "ttl=1;port=5000-5001;mode=\"PLAY\"";
864
865   /* simple SETUP with a valid URI and multicast, but an invalid ip */
866   fail_unless (gst_rtsp_message_init_request (&request, GST_RTSP_SETUP,
867           "rtsp://localhost/test/stream=0") == GST_RTSP_OK);
868   str = g_strdup_printf ("%d", cseq);
869   gst_rtsp_message_take_header (&request, GST_RTSP_HDR_CSEQ, str);
870   gst_rtsp_message_add_header (&request, GST_RTSP_HDR_TRANSPORT,
871       expected_transport);
872
873   gst_rtsp_client_set_send_func (client, test_setup_response_200_multicast,
874       NULL, NULL);
875   fail_unless (gst_rtsp_client_handle_message (client,
876           &request) == GST_RTSP_OK);
877   gst_rtsp_message_unset (&request);
878   expected_transport = NULL;
879
880   gst_rtsp_client_set_send_func (client, test_setup_response_200_multicast,
881       NULL, NULL);
882   session_pool = gst_rtsp_client_get_session_pool (client);
883   fail_unless (session_pool != NULL);
884   fail_unless (gst_rtsp_session_pool_get_n_sessions (session_pool) == 1);
885   g_object_unref (session_pool);
886
887   send_teardown (client);
888
889   teardown_client (client);
890   g_object_unref (ctx.auth);
891   gst_rtsp_token_unref (ctx.token);
892   gst_rtsp_context_pop_current (&ctx);
893 }
894
895 GST_END_TEST;
896
897 static gboolean
898 test_response_sdp (GstRTSPClient * client, GstRTSPMessage * response,
899     gboolean close, gpointer user_data)
900 {
901   guint8 *data;
902   guint size;
903   GstSDPMessage *sdp_msg;
904   const GstSDPMedia *sdp_media;
905   const GstSDPBandwidth *bw;
906   gint bandwidth_val = GPOINTER_TO_INT (user_data);
907
908   fail_unless (gst_rtsp_message_get_body (response, &data, &size)
909       == GST_RTSP_OK);
910   gst_sdp_message_new (&sdp_msg);
911   fail_unless (gst_sdp_message_parse_buffer (data, size, sdp_msg)
912       == GST_SDP_OK);
913
914   /* session description */
915   /* v= */
916   fail_unless (gst_sdp_message_get_version (sdp_msg) != NULL);
917   /* o= */
918   fail_unless (gst_sdp_message_get_origin (sdp_msg) != NULL);
919   /* s= */
920   fail_unless (gst_sdp_message_get_session_name (sdp_msg) != NULL);
921   /* t=0 0 */
922   fail_unless (gst_sdp_message_times_len (sdp_msg) == 0);
923
924   /* verify number of medias */
925   fail_unless (gst_sdp_message_medias_len (sdp_msg) == 1);
926
927   /* media description */
928   sdp_media = gst_sdp_message_get_media (sdp_msg, 0);
929   fail_unless (sdp_media != NULL);
930
931   /* m= */
932   fail_unless (gst_sdp_media_get_media (sdp_media) != NULL);
933
934   /* media bandwidth */
935   if (bandwidth_val) {
936     fail_unless (gst_sdp_media_bandwidths_len (sdp_media) == 1);
937     bw = gst_sdp_media_get_bandwidth (sdp_media, 0);
938     fail_unless (bw != NULL);
939     fail_unless (g_strcmp0 (bw->bwtype, "AS") == 0);
940     fail_unless (bw->bandwidth == bandwidth_val);
941   } else {
942     fail_unless (gst_sdp_media_bandwidths_len (sdp_media) == 0);
943   }
944
945   gst_sdp_message_free (sdp_msg);
946
947   return TRUE;
948 }
949
950 static void
951 test_client_sdp (const gchar * launch_line, guint * bandwidth_val)
952 {
953   GstRTSPClient *client;
954   GstRTSPMessage request = { 0, };
955   gchar *str;
956
957   /* simple DESCRIBE for an existing url */
958   client = setup_client (launch_line);
959   fail_unless (gst_rtsp_message_init_request (&request, GST_RTSP_DESCRIBE,
960           "rtsp://localhost/test") == GST_RTSP_OK);
961   str = g_strdup_printf ("%d", cseq);
962   gst_rtsp_message_add_header (&request, GST_RTSP_HDR_CSEQ, str);
963   g_free (str);
964
965   gst_rtsp_client_set_send_func (client, test_response_sdp,
966       (gpointer) bandwidth_val, NULL);
967   fail_unless (gst_rtsp_client_handle_message (client,
968           &request) == GST_RTSP_OK);
969   gst_rtsp_message_unset (&request);
970
971   teardown_client (client);
972 }
973
974 GST_START_TEST (test_client_sdp_with_max_bitrate_tag)
975 {
976   test_client_sdp ("videotestsrc "
977       "! taginject tags=\"maximum-bitrate=(uint)50000000\" "
978       "! video/x-raw,width=352,height=288 ! rtpgstpay name=pay0 pt=96",
979       GUINT_TO_POINTER (50000));
980
981
982   /* max-bitrate=0: no bandwidth line */
983   test_client_sdp ("videotestsrc "
984       "! taginject tags=\"maximum-bitrate=(uint)0\" "
985       "! video/x-raw,width=352,height=288 ! rtpgstpay name=pay0 pt=96",
986       GUINT_TO_POINTER (0));
987 }
988
989 GST_END_TEST;
990
991 GST_START_TEST (test_client_sdp_with_bitrate_tag)
992 {
993   test_client_sdp ("videotestsrc "
994       "! taginject tags=\"bitrate=(uint)7000000\" "
995       "! video/x-raw,width=352,height=288 ! rtpgstpay name=pay0 pt=96",
996       GUINT_TO_POINTER (7000));
997
998   /* bitrate=0: no bandwdith line */
999   test_client_sdp ("videotestsrc "
1000       "! taginject tags=\"bitrate=(uint)0\" "
1001       "! video/x-raw,width=352,height=288 ! rtpgstpay name=pay0 pt=96",
1002       GUINT_TO_POINTER (0));
1003 }
1004
1005 GST_END_TEST;
1006
1007 GST_START_TEST (test_client_sdp_with_max_bitrate_and_bitrate_tags)
1008 {
1009   test_client_sdp ("videotestsrc "
1010       "! taginject tags=\"bitrate=(uint)7000000,maximum-bitrate=(uint)50000000\" "
1011       "! video/x-raw,width=352,height=288 ! rtpgstpay name=pay0 pt=96",
1012       GUINT_TO_POINTER (50000));
1013
1014   /* max-bitrate is zero: fallback to bitrate */
1015   test_client_sdp ("videotestsrc "
1016       "! taginject tags=\"bitrate=(uint)7000000,maximum-bitrate=(uint)0\" "
1017       "! video/x-raw,width=352,height=288 ! rtpgstpay name=pay0 pt=96",
1018       GUINT_TO_POINTER (7000));
1019
1020   /* max-bitrate=bitrate=0o: no bandwidth line */
1021   test_client_sdp ("videotestsrc "
1022       "! taginject tags=\"bitrate=(uint)0,maximum-bitrate=(uint)0\" "
1023       "! video/x-raw,width=352,height=288 ! rtpgstpay name=pay0 pt=96",
1024       GUINT_TO_POINTER (0));
1025 }
1026
1027 GST_END_TEST;
1028
1029 GST_START_TEST (test_client_sdp_with_no_bitrate_tags)
1030 {
1031   test_client_sdp ("videotestsrc "
1032       "! video/x-raw,width=352,height=288 ! rtpgstpay name=pay0 pt=96", NULL);
1033 }
1034
1035 GST_END_TEST;
1036
1037 static Suite *
1038 rtspclient_suite (void)
1039 {
1040   Suite *s = suite_create ("rtspclient");
1041   TCase *tc = tcase_create ("general");
1042
1043   suite_add_tcase (s, tc);
1044   tcase_set_timeout (tc, 20);
1045   tcase_add_test (tc, test_require);
1046   tcase_add_test (tc, test_request);
1047   tcase_add_test (tc, test_options);
1048   tcase_add_test (tc, test_describe);
1049   tcase_add_test (tc, test_client_multicast_transport_404);
1050   tcase_add_test (tc, test_client_multicast_transport);
1051   tcase_add_test (tc, test_client_multicast_ignore_transport_specific);
1052   tcase_add_test (tc, test_client_multicast_invalid_transport_specific);
1053   tcase_add_test (tc, test_client_multicast_transport_specific);
1054   tcase_add_test (tc, test_client_sdp_with_max_bitrate_tag);
1055   tcase_add_test (tc, test_client_sdp_with_bitrate_tag);
1056   tcase_add_test (tc, test_client_sdp_with_max_bitrate_and_bitrate_tags);
1057   tcase_add_test (tc, test_client_sdp_with_no_bitrate_tags);
1058
1059   return s;
1060 }
1061
1062 GST_CHECK_MAIN (rtspclient);