rtsp-client: allow application to decide what requirements are supported
[platform/upstream/gst-rtsp-server.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_OPTIONS |
397           GST_RTSP_PAUSE |
398           GST_RTSP_PLAY |
399           GST_RTSP_SETUP |
400           GST_RTSP_GET_PARAMETER | GST_RTSP_SET_PARAMETER | GST_RTSP_TEARDOWN));
401
402   return TRUE;
403 }
404
405 GST_START_TEST (test_options)
406 {
407   GstRTSPClient *client;
408   GstRTSPMessage request = { 0, };
409   gchar *str;
410
411   client = gst_rtsp_client_new ();
412
413   /* simple OPTIONS */
414   fail_unless (gst_rtsp_message_init_request (&request, GST_RTSP_OPTIONS,
415           "rtsp://localhost/test") == GST_RTSP_OK);
416   str = g_strdup_printf ("%d", cseq);
417   gst_rtsp_message_add_header (&request, GST_RTSP_HDR_CSEQ, str);
418   g_free (str);
419
420   gst_rtsp_client_set_send_func (client, test_option_response_200, NULL, NULL);
421   fail_unless (gst_rtsp_client_handle_message (client,
422           &request) == GST_RTSP_OK);
423   gst_rtsp_message_unset (&request);
424
425   g_object_unref (client);
426 }
427
428 GST_END_TEST;
429
430 GST_START_TEST (test_describe)
431 {
432   GstRTSPClient *client;
433   GstRTSPMessage request = { 0, };
434   gchar *str;
435
436   client = gst_rtsp_client_new ();
437
438   /* simple DESCRIBE for non-existing url */
439   fail_unless (gst_rtsp_message_init_request (&request, GST_RTSP_DESCRIBE,
440           "rtsp://localhost/test") == GST_RTSP_OK);
441   str = g_strdup_printf ("%d", cseq);
442   gst_rtsp_message_add_header (&request, GST_RTSP_HDR_CSEQ, str);
443   g_free (str);
444
445   gst_rtsp_client_set_send_func (client, test_response_404, NULL, NULL);
446   fail_unless (gst_rtsp_client_handle_message (client,
447           &request) == GST_RTSP_OK);
448   gst_rtsp_message_unset (&request);
449
450   g_object_unref (client);
451
452   /* simple DESCRIBE for an existing url */
453   client = setup_client (NULL);
454   fail_unless (gst_rtsp_message_init_request (&request, GST_RTSP_DESCRIBE,
455           "rtsp://localhost/test") == GST_RTSP_OK);
456   str = g_strdup_printf ("%d", cseq);
457   gst_rtsp_message_add_header (&request, GST_RTSP_HDR_CSEQ, str);
458   g_free (str);
459
460   gst_rtsp_client_set_send_func (client, test_response_200, NULL, NULL);
461   fail_unless (gst_rtsp_client_handle_message (client,
462           &request) == GST_RTSP_OK);
463   gst_rtsp_message_unset (&request);
464
465   teardown_client (client);
466 }
467
468 GST_END_TEST;
469
470 static const gchar *expected_transport = NULL;
471
472 static gboolean
473 test_setup_response_200_multicast (GstRTSPClient * client,
474     GstRTSPMessage * response, gboolean close, gpointer user_data)
475 {
476   GstRTSPStatusCode code;
477   const gchar *reason;
478   GstRTSPVersion version;
479   gchar *str;
480   GstRTSPSessionPool *session_pool;
481   GstRTSPSession *session;
482   gchar **session_hdr_params;
483
484   fail_unless (expected_transport != NULL);
485
486   fail_unless (gst_rtsp_message_get_type (response) ==
487       GST_RTSP_MESSAGE_RESPONSE);
488
489   fail_unless (gst_rtsp_message_parse_response (response, &code, &reason,
490           &version)
491       == GST_RTSP_OK);
492   fail_unless (code == GST_RTSP_STS_OK);
493   fail_unless (g_str_equal (reason, "OK"));
494   fail_unless (version == GST_RTSP_VERSION_1_0);
495
496   fail_unless (gst_rtsp_message_get_header (response, GST_RTSP_HDR_CSEQ, &str,
497           0) == GST_RTSP_OK);
498   fail_unless (atoi (str) == cseq++);
499
500   fail_unless (gst_rtsp_message_get_header (response, GST_RTSP_HDR_TRANSPORT,
501           &str, 0) == GST_RTSP_OK);
502
503   fail_unless (!strcmp (str, expected_transport));
504
505   fail_unless (gst_rtsp_message_get_header (response, GST_RTSP_HDR_SESSION,
506           &str, 0) == GST_RTSP_OK);
507   session_hdr_params = g_strsplit (str, ";", -1);
508
509   /* session-id value */
510   fail_unless (session_hdr_params[0] != NULL);
511
512   if (expected_session_timeout != 60) {
513     /* session timeout param */
514     gchar *timeout_str = g_strdup_printf ("timeout=%u",
515         expected_session_timeout);
516
517     fail_unless (session_hdr_params[1] != NULL);
518     g_strstrip (session_hdr_params[1]);
519     fail_unless (g_strcmp0 (session_hdr_params[1], timeout_str) == 0);
520     g_free (timeout_str);
521   }
522
523   session_pool = gst_rtsp_client_get_session_pool (client);
524   fail_unless (session_pool != NULL);
525
526   fail_unless (gst_rtsp_session_pool_get_n_sessions (session_pool) == 1);
527   session = gst_rtsp_session_pool_find (session_pool, session_hdr_params[0]);
528   g_strfreev (session_hdr_params);
529
530   /* remember session id to be able to send teardown */
531   session_id = g_strdup (gst_rtsp_session_get_sessionid (session));
532   fail_unless (session_id != NULL);
533
534   fail_unless (session != NULL);
535   g_object_unref (session);
536
537   g_object_unref (session_pool);
538
539
540   return TRUE;
541 }
542
543 static gboolean
544 test_teardown_response_200 (GstRTSPClient * client,
545     GstRTSPMessage * response, gboolean close, gpointer user_data)
546 {
547   GstRTSPStatusCode code;
548   const gchar *reason;
549   GstRTSPVersion version;
550
551   fail_unless (gst_rtsp_message_get_type (response) ==
552       GST_RTSP_MESSAGE_RESPONSE);
553
554   fail_unless (gst_rtsp_message_parse_response (response, &code, &reason,
555           &version)
556       == GST_RTSP_OK);
557   fail_unless (code == GST_RTSP_STS_OK);
558   fail_unless (g_str_equal (reason, "OK"));
559   fail_unless (version == GST_RTSP_VERSION_1_0);
560
561   return TRUE;
562 }
563
564 static void
565 send_teardown (GstRTSPClient * client)
566 {
567   GstRTSPMessage request = { 0, };
568   gchar *str;
569
570   fail_unless (session_id != NULL);
571   fail_unless (gst_rtsp_message_init_request (&request, GST_RTSP_TEARDOWN,
572           "rtsp://localhost/test") == GST_RTSP_OK);
573   str = g_strdup_printf ("%d", cseq);
574   gst_rtsp_message_take_header (&request, GST_RTSP_HDR_CSEQ, str);
575   gst_rtsp_message_add_header (&request, GST_RTSP_HDR_SESSION,
576       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 gboolean
730 test_setup_response_461 (GstRTSPClient * client,
731     GstRTSPMessage * response, gboolean close, gpointer user_data)
732 {
733   GstRTSPStatusCode code;
734   const gchar *reason;
735   GstRTSPVersion version;
736   gchar *str;
737
738   fail_unless (expected_transport == NULL);
739
740   fail_unless (gst_rtsp_message_get_type (response) ==
741       GST_RTSP_MESSAGE_RESPONSE);
742
743   fail_unless (gst_rtsp_message_parse_response (response, &code, &reason,
744           &version)
745       == GST_RTSP_OK);
746   fail_unless (code == GST_RTSP_STS_UNSUPPORTED_TRANSPORT);
747   fail_unless (g_str_equal (reason, "Unsupported transport"));
748   fail_unless (version == GST_RTSP_VERSION_1_0);
749
750   fail_unless (gst_rtsp_message_get_header (response, GST_RTSP_HDR_CSEQ, &str,
751           0) == GST_RTSP_OK);
752   fail_unless (atoi (str) == cseq++);
753
754
755   return TRUE;
756 }
757
758 GST_START_TEST (test_client_multicast_invalid_transport_specific)
759 {
760   GstRTSPClient *client;
761   GstRTSPMessage request = { 0, };
762   gchar *str;
763   GstRTSPSessionPool *session_pool;
764   GstRTSPContext ctx = { NULL };
765
766   client = setup_multicast_client ();
767
768   ctx.client = client;
769   ctx.auth = gst_rtsp_auth_new ();
770   ctx.token =
771       gst_rtsp_token_new (GST_RTSP_TOKEN_TRANSPORT_CLIENT_SETTINGS,
772       G_TYPE_BOOLEAN, TRUE, GST_RTSP_TOKEN_MEDIA_FACTORY_ROLE, G_TYPE_STRING,
773       "user", NULL);
774   gst_rtsp_context_push_current (&ctx);
775
776   /* simple SETUP with a valid URI and multicast, but an invalid ip */
777   fail_unless (gst_rtsp_message_init_request (&request, GST_RTSP_SETUP,
778           "rtsp://localhost/test/stream=0") == GST_RTSP_OK);
779   str = g_strdup_printf ("%d", cseq);
780   gst_rtsp_message_take_header (&request, GST_RTSP_HDR_CSEQ, str);
781   gst_rtsp_message_add_header (&request, GST_RTSP_HDR_TRANSPORT,
782       "RTP/AVP;multicast;destination=233.252.0.2;ttl=1;port=5000-5001;");
783
784   gst_rtsp_client_set_send_func (client, test_setup_response_461, NULL, NULL);
785   fail_unless (gst_rtsp_client_handle_message (client,
786           &request) == GST_RTSP_OK);
787   gst_rtsp_message_unset (&request);
788
789   session_pool = gst_rtsp_client_get_session_pool (client);
790   fail_unless (session_pool != NULL);
791   fail_unless (gst_rtsp_session_pool_get_n_sessions (session_pool) == 0);
792   g_object_unref (session_pool);
793
794
795
796   /* simple SETUP with a valid URI and multicast, but an invalid prt */
797   fail_unless (gst_rtsp_message_init_request (&request, GST_RTSP_SETUP,
798           "rtsp://localhost/test/stream=0") == GST_RTSP_OK);
799   str = g_strdup_printf ("%d", cseq);
800   gst_rtsp_message_take_header (&request, GST_RTSP_HDR_CSEQ, str);
801   gst_rtsp_message_add_header (&request, GST_RTSP_HDR_TRANSPORT,
802       "RTP/AVP;multicast;destination=233.252.0.1;ttl=1;port=6000-6001;");
803
804   gst_rtsp_client_set_send_func (client, test_setup_response_461, NULL, NULL);
805   fail_unless (gst_rtsp_client_handle_message (client,
806           &request) == GST_RTSP_OK);
807   gst_rtsp_message_unset (&request);
808
809   session_pool = gst_rtsp_client_get_session_pool (client);
810   fail_unless (session_pool != NULL);
811   fail_unless (gst_rtsp_session_pool_get_n_sessions (session_pool) == 0);
812   g_object_unref (session_pool);
813
814
815
816   /* simple SETUP with a valid URI and multicast, but an invalid ttl */
817   fail_unless (gst_rtsp_message_init_request (&request, GST_RTSP_SETUP,
818           "rtsp://localhost/test/stream=0") == GST_RTSP_OK);
819   str = g_strdup_printf ("%d", cseq);
820   gst_rtsp_message_take_header (&request, GST_RTSP_HDR_CSEQ, str);
821   gst_rtsp_message_add_header (&request, GST_RTSP_HDR_TRANSPORT,
822       "RTP/AVP;multicast;destination=233.252.0.1;ttl=2;port=5000-5001;");
823
824   gst_rtsp_client_set_send_func (client, test_setup_response_461, NULL, NULL);
825   fail_unless (gst_rtsp_client_handle_message (client,
826           &request) == GST_RTSP_OK);
827   gst_rtsp_message_unset (&request);
828
829   session_pool = gst_rtsp_client_get_session_pool (client);
830   fail_unless (session_pool != NULL);
831   fail_unless (gst_rtsp_session_pool_get_n_sessions (session_pool) == 0);
832   g_object_unref (session_pool);
833
834
835   teardown_client (client);
836   g_object_unref (ctx.auth);
837   gst_rtsp_token_unref (ctx.token);
838   gst_rtsp_context_pop_current (&ctx);
839 }
840
841 GST_END_TEST;
842
843 GST_START_TEST (test_client_multicast_transport_specific)
844 {
845   GstRTSPClient *client;
846   GstRTSPMessage request = { 0, };
847   gchar *str;
848   GstRTSPSessionPool *session_pool;
849   GstRTSPContext ctx = { NULL };
850
851   client = setup_multicast_client ();
852
853   ctx.client = client;
854   ctx.auth = gst_rtsp_auth_new ();
855   ctx.token =
856       gst_rtsp_token_new (GST_RTSP_TOKEN_TRANSPORT_CLIENT_SETTINGS,
857       G_TYPE_BOOLEAN, TRUE, GST_RTSP_TOKEN_MEDIA_FACTORY_ROLE, G_TYPE_STRING,
858       "user", NULL);
859   gst_rtsp_context_push_current (&ctx);
860
861   expected_transport = "RTP/AVP;multicast;destination=233.252.0.1;"
862       "ttl=1;port=5000-5001;mode=\"PLAY\"";
863
864   /* simple SETUP with a valid URI and multicast, but an invalid ip */
865   fail_unless (gst_rtsp_message_init_request (&request, GST_RTSP_SETUP,
866           "rtsp://localhost/test/stream=0") == GST_RTSP_OK);
867   str = g_strdup_printf ("%d", cseq);
868   gst_rtsp_message_take_header (&request, GST_RTSP_HDR_CSEQ, str);
869   gst_rtsp_message_add_header (&request, GST_RTSP_HDR_TRANSPORT,
870       expected_transport);
871
872   gst_rtsp_client_set_send_func (client, test_setup_response_200_multicast,
873       NULL, NULL);
874   fail_unless (gst_rtsp_client_handle_message (client,
875           &request) == GST_RTSP_OK);
876   gst_rtsp_message_unset (&request);
877   expected_transport = NULL;
878
879   gst_rtsp_client_set_send_func (client, test_setup_response_200_multicast,
880       NULL, NULL);
881   session_pool = gst_rtsp_client_get_session_pool (client);
882   fail_unless (session_pool != NULL);
883   fail_unless (gst_rtsp_session_pool_get_n_sessions (session_pool) == 1);
884   g_object_unref (session_pool);
885
886   send_teardown (client);
887
888   teardown_client (client);
889   g_object_unref (ctx.auth);
890   gst_rtsp_token_unref (ctx.token);
891   gst_rtsp_context_pop_current (&ctx);
892 }
893
894 GST_END_TEST;
895
896 static gboolean
897 test_response_sdp (GstRTSPClient * client, GstRTSPMessage * response,
898     gboolean close, gpointer user_data)
899 {
900   guint8 *data;
901   guint size;
902   GstSDPMessage *sdp_msg;
903   const GstSDPMedia *sdp_media;
904   const GstSDPBandwidth *bw;
905   gint bandwidth_val = GPOINTER_TO_INT (user_data);
906
907   fail_unless (gst_rtsp_message_get_body (response, &data, &size)
908       == GST_RTSP_OK);
909   gst_sdp_message_new (&sdp_msg);
910   fail_unless (gst_sdp_message_parse_buffer (data, size, sdp_msg)
911       == GST_SDP_OK);
912
913   /* session description */
914   /* v= */
915   fail_unless (gst_sdp_message_get_version (sdp_msg) != NULL);
916   /* o= */
917   fail_unless (gst_sdp_message_get_origin (sdp_msg) != NULL);
918   /* s= */
919   fail_unless (gst_sdp_message_get_session_name (sdp_msg) != NULL);
920   /* t=0 0 */
921   fail_unless (gst_sdp_message_times_len (sdp_msg) == 0);
922
923   /* verify number of medias */
924   fail_unless (gst_sdp_message_medias_len (sdp_msg) == 1);
925
926   /* media description */
927   sdp_media = gst_sdp_message_get_media (sdp_msg, 0);
928   fail_unless (sdp_media != NULL);
929
930   /* m= */
931   fail_unless (gst_sdp_media_get_media (sdp_media) != NULL);
932
933   /* media bandwidth */
934   if (bandwidth_val) {
935     fail_unless (gst_sdp_media_bandwidths_len (sdp_media) == 1);
936     bw = gst_sdp_media_get_bandwidth (sdp_media, 0);
937     fail_unless (bw != NULL);
938     fail_unless (g_strcmp0 (bw->bwtype, "AS") == 0);
939     fail_unless (bw->bandwidth == bandwidth_val);
940   } else {
941     fail_unless (gst_sdp_media_bandwidths_len (sdp_media) == 0);
942   }
943
944   gst_sdp_message_free (sdp_msg);
945
946   return TRUE;
947 }
948
949 static void
950 test_client_sdp (const gchar * launch_line, guint * bandwidth_val)
951 {
952   GstRTSPClient *client;
953   GstRTSPMessage request = { 0, };
954   gchar *str;
955
956   /* simple DESCRIBE for an existing url */
957   client = setup_client (launch_line);
958   fail_unless (gst_rtsp_message_init_request (&request, GST_RTSP_DESCRIBE,
959           "rtsp://localhost/test") == GST_RTSP_OK);
960   str = g_strdup_printf ("%d", cseq);
961   gst_rtsp_message_add_header (&request, GST_RTSP_HDR_CSEQ, str);
962   g_free (str);
963
964   gst_rtsp_client_set_send_func (client, test_response_sdp,
965       (gpointer) bandwidth_val, NULL);
966   fail_unless (gst_rtsp_client_handle_message (client,
967           &request) == GST_RTSP_OK);
968   gst_rtsp_message_unset (&request);
969
970   teardown_client (client);
971 }
972
973 GST_START_TEST (test_client_sdp_with_max_bitrate_tag)
974 {
975   test_client_sdp ("videotestsrc "
976       "! taginject tags=\"maximum-bitrate=(uint)50000000\" "
977       "! video/x-raw,width=352,height=288 ! rtpgstpay name=pay0 pt=96",
978       GUINT_TO_POINTER (50000));
979
980
981   /* max-bitrate=0: no bandwidth line */
982   test_client_sdp ("videotestsrc "
983       "! taginject tags=\"maximum-bitrate=(uint)0\" "
984       "! video/x-raw,width=352,height=288 ! rtpgstpay name=pay0 pt=96",
985       GUINT_TO_POINTER (0));
986 }
987
988 GST_END_TEST;
989
990 GST_START_TEST (test_client_sdp_with_bitrate_tag)
991 {
992   test_client_sdp ("videotestsrc "
993       "! taginject tags=\"bitrate=(uint)7000000\" "
994       "! video/x-raw,width=352,height=288 ! rtpgstpay name=pay0 pt=96",
995       GUINT_TO_POINTER (7000));
996
997   /* bitrate=0: no bandwdith line */
998   test_client_sdp ("videotestsrc "
999       "! taginject tags=\"bitrate=(uint)0\" "
1000       "! video/x-raw,width=352,height=288 ! rtpgstpay name=pay0 pt=96",
1001       GUINT_TO_POINTER (0));
1002 }
1003
1004 GST_END_TEST;
1005
1006 GST_START_TEST (test_client_sdp_with_max_bitrate_and_bitrate_tags)
1007 {
1008   test_client_sdp ("videotestsrc "
1009       "! taginject tags=\"bitrate=(uint)7000000,maximum-bitrate=(uint)50000000\" "
1010       "! video/x-raw,width=352,height=288 ! rtpgstpay name=pay0 pt=96",
1011       GUINT_TO_POINTER (50000));
1012
1013   /* max-bitrate is zero: fallback to bitrate */
1014   test_client_sdp ("videotestsrc "
1015       "! taginject tags=\"bitrate=(uint)7000000,maximum-bitrate=(uint)0\" "
1016       "! video/x-raw,width=352,height=288 ! rtpgstpay name=pay0 pt=96",
1017       GUINT_TO_POINTER (7000));
1018
1019   /* max-bitrate=bitrate=0o: no bandwidth line */
1020   test_client_sdp ("videotestsrc "
1021       "! taginject tags=\"bitrate=(uint)0,maximum-bitrate=(uint)0\" "
1022       "! video/x-raw,width=352,height=288 ! rtpgstpay name=pay0 pt=96",
1023       GUINT_TO_POINTER (0));
1024 }
1025
1026 GST_END_TEST;
1027
1028 GST_START_TEST (test_client_sdp_with_no_bitrate_tags)
1029 {
1030   test_client_sdp ("videotestsrc "
1031       "! video/x-raw,width=352,height=288 ! rtpgstpay name=pay0 pt=96", NULL);
1032 }
1033
1034 GST_END_TEST;
1035
1036 static Suite *
1037 rtspclient_suite (void)
1038 {
1039   Suite *s = suite_create ("rtspclient");
1040   TCase *tc = tcase_create ("general");
1041
1042   suite_add_tcase (s, tc);
1043   tcase_set_timeout (tc, 20);
1044   tcase_add_test (tc, test_require);
1045   tcase_add_test (tc, test_request);
1046   tcase_add_test (tc, test_options);
1047   tcase_add_test (tc, test_describe);
1048   tcase_add_test (tc, test_client_multicast_transport_404);
1049   tcase_add_test (tc, test_client_multicast_transport);
1050   tcase_add_test (tc, test_client_multicast_ignore_transport_specific);
1051   tcase_add_test (tc, test_client_multicast_invalid_transport_specific);
1052   tcase_add_test (tc, test_client_multicast_transport_specific);
1053   tcase_add_test (tc, test_client_sdp_with_max_bitrate_tag);
1054   tcase_add_test (tc, test_client_sdp_with_bitrate_tag);
1055   tcase_add_test (tc, test_client_sdp_with_max_bitrate_and_bitrate_tags);
1056   tcase_add_test (tc, test_client_sdp_with_no_bitrate_tags);
1057
1058   return s;
1059 }
1060
1061 GST_CHECK_MAIN (rtspclient);