tests: Add test for client disconnection
[platform/upstream/gstreamer.git] / tests / check / gst / rtspserver.c
1 /* GStreamer
2  *
3  * unit test for GstRTSPServer
4  *
5  * Copyright (C) 2012 Axis Communications <dev-gstreamer at axis dot com>
6  * @author David Svensson Fors <davidsf at axis dot com>
7  *
8  * This library is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU Library General Public
10  * License as published by the Free Software Foundation; either
11  * version 2 of the License, or (at your option) any later version.
12  *
13  * This library is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16  * Library General Public License for more details.
17  *
18  * You should have received a copy of the GNU Library General Public
19  * License along with this library; if not, write to the
20  * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
21  * Boston, MA 02110-1301, USA.
22  */
23
24 #include <gst/check/gstcheck.h>
25 #include <gst/sdp/gstsdpmessage.h>
26
27 #include <stdio.h>
28 #include <netinet/in.h>
29
30 #include "rtsp-server.h"
31
32 #define VIDEO_PIPELINE "videotestsrc ! " \
33   "video/x-raw,width=352,height=288 ! " \
34   "rtpgstpay name=pay0 pt=96"
35 #define AUDIO_PIPELINE "audiotestsrc ! " \
36   "audio/x-raw,rate=8000 ! " \
37   "rtpgstpay name=pay1 pt=97"
38
39 #define TEST_MOUNT_POINT  "/test"
40 #define TEST_PROTO        "RTP/AVP"
41 #define TEST_ENCODING     "X-GST"
42 #define TEST_CLOCK_RATE   "90000"
43
44 /* tested rtsp server */
45 static GstRTSPServer *server = NULL;
46
47 /* tcp port that the test server listens for rtsp requests on */
48 static gint test_port = 0;
49
50 /* id of the server's source within the GMainContext */
51 static guint source_id;
52
53 /* iterate the default main loop until there are no events to dispatch */
54 static void
55 iterate (void)
56 {
57   while (g_main_context_iteration (NULL, FALSE)) {
58     GST_DEBUG ("iteration");
59   }
60 }
61
62 /* returns an unused port that can be used by the test */
63 static int
64 get_unused_port (gint type)
65 {
66   int sock;
67   struct sockaddr_in addr;
68   socklen_t addr_len;
69   gint port;
70
71   /* create socket */
72   fail_unless ((sock = socket (AF_INET, type, 0)) > 0);
73
74   /* pass port 0 to bind, which will bind to any free port */
75   memset (&addr, 0, sizeof addr);
76   addr.sin_family = AF_INET;
77   addr.sin_addr.s_addr = INADDR_ANY;
78   addr.sin_port = htons (0);
79   fail_unless (bind (sock, (struct sockaddr *) &addr, sizeof addr) == 0);
80
81   /* ask what port was bound using getsockname */
82   addr_len = sizeof addr;
83   memset (&addr, 0, addr_len);
84   fail_unless (getsockname (sock, (struct sockaddr *) &addr, &addr_len) == 0);
85   port = ntohs (addr.sin_port);
86
87   /* close the socket so the port gets unbound again (and can be used by the
88    * test) */
89   close (sock);
90
91   return port;
92 }
93
94 /* returns TRUE if the given port is not currently bound */
95 static gboolean
96 port_is_unused (gint port, gint type)
97 {
98   int sock;
99   struct sockaddr_in addr;
100   gboolean is_bound;
101
102   /* create socket */
103   fail_unless ((sock = socket (AF_INET, type, 0)) > 0);
104
105   /* check if the port is already bound by trying to bind to it (again) */
106   memset (&addr, 0, sizeof addr);
107   addr.sin_family = AF_INET;
108   addr.sin_addr.s_addr = INADDR_ANY;
109   addr.sin_port = htons (port);
110   is_bound = (bind (sock, (struct sockaddr *) &addr, sizeof addr) != 0);
111
112   /* close the socket, which will unbind if bound by our call to bind */
113   close (sock);
114
115   return !is_bound;
116 }
117
118 /* get a free rtp/rtcp client port pair */
119 static void
120 get_client_ports (GstRTSPRange * range)
121 {
122   gint rtp_port;
123   gint rtcp_port;
124
125   /* get a pair of unused ports, where the rtp port is even */
126   do {
127     rtp_port = get_unused_port (SOCK_DGRAM);
128     rtcp_port = rtp_port + 1;
129   } while (rtp_port % 2 != 0 || !port_is_unused (rtcp_port, SOCK_DGRAM));
130   range->min = rtp_port;
131   range->max = rtcp_port;
132   GST_DEBUG ("client_port=%d-%d", range->min, range->max);
133 }
134
135 /* start the tested rtsp server */
136 static void
137 start_server ()
138 {
139   GstRTSPMountPoints *mounts;
140   gchar *service;
141   GstRTSPMediaFactory *factory;
142
143   mounts = gst_rtsp_server_get_mount_points (server);
144
145   factory = gst_rtsp_media_factory_new ();
146
147   gst_rtsp_media_factory_set_launch (factory,
148       "( " VIDEO_PIPELINE "  " AUDIO_PIPELINE " )");
149
150   gst_rtsp_mount_points_add_factory (mounts, TEST_MOUNT_POINT, factory);
151   g_object_unref (mounts);
152
153   /* set port */
154   test_port = get_unused_port (SOCK_STREAM);
155   service = g_strdup_printf ("%d", test_port);
156   gst_rtsp_server_set_service (server, service);
157   g_free (service);
158
159   /* attach to default main context */
160   source_id = gst_rtsp_server_attach (server, NULL);
161   fail_if (source_id == 0);
162
163   GST_DEBUG ("rtsp server listening on port %d", test_port);
164 }
165
166 /* stop the tested rtsp server */
167 static void
168 stop_server ()
169 {
170   g_source_remove (source_id);
171   source_id = 0;
172
173   GST_DEBUG ("rtsp server stopped");
174 }
175
176 /* create an rtsp connection to the server on test_port */
177 static GstRTSPConnection *
178 connect_to_server (gint port, const gchar * mount_point)
179 {
180   GstRTSPConnection *conn = NULL;
181   gchar *address;
182   gchar *uri_string;
183   GstRTSPUrl *url = NULL;
184
185   address = gst_rtsp_server_get_address (server);
186   uri_string = g_strdup_printf ("rtsp://%s:%d%s", address, port, mount_point);
187   g_free (address);
188   gst_rtsp_url_parse (uri_string, &url);
189   g_free (uri_string);
190
191   fail_unless (gst_rtsp_connection_create (url, &conn) == GST_RTSP_OK);
192   gst_rtsp_url_free (url);
193
194   fail_unless (gst_rtsp_connection_connect (conn, NULL) == GST_RTSP_OK);
195
196   return conn;
197 }
198
199 /* create an rtsp request */
200 static GstRTSPMessage *
201 create_request (GstRTSPConnection * conn, GstRTSPMethod method,
202     const gchar * control)
203 {
204   GstRTSPMessage *request = NULL;
205   gchar *base_uri;
206   gchar *full_uri;
207
208   base_uri = gst_rtsp_url_get_request_uri (gst_rtsp_connection_get_url (conn));
209   full_uri = g_strdup_printf ("%s/%s", base_uri, control ? control : "");
210   g_free (base_uri);
211   if (gst_rtsp_message_new_request (&request, method, full_uri) != GST_RTSP_OK) {
212     GST_DEBUG ("failed to create request object");
213     g_free (full_uri);
214     return NULL;
215   }
216   g_free (full_uri);
217   return request;
218 }
219
220 /* send an rtsp request */
221 static gboolean
222 send_request (GstRTSPConnection * conn, GstRTSPMessage * request)
223 {
224   if (gst_rtsp_connection_send (conn, request, NULL) != GST_RTSP_OK) {
225     GST_DEBUG ("failed to send request");
226     return FALSE;
227   }
228   return TRUE;
229 }
230
231 /* read rtsp response. response must be freed by the caller */
232 static GstRTSPMessage *
233 read_response (GstRTSPConnection * conn)
234 {
235   GstRTSPMessage *response = NULL;
236
237   if (gst_rtsp_message_new (&response) != GST_RTSP_OK) {
238     GST_DEBUG ("failed to create response object");
239     return NULL;
240   }
241   if (gst_rtsp_connection_receive (conn, response, NULL) != GST_RTSP_OK) {
242     GST_DEBUG ("failed to read response");
243     gst_rtsp_message_free (response);
244     return NULL;
245   }
246   fail_unless (gst_rtsp_message_get_type (response) ==
247       GST_RTSP_MESSAGE_RESPONSE);
248   return response;
249 }
250
251 /* send an rtsp request and receive response. gchar** parameters are out
252  * parameters that have to be freed by the caller */
253 static GstRTSPStatusCode
254 do_request (GstRTSPConnection * conn, GstRTSPMethod method,
255     const gchar * control, const gchar * session_in, const gchar * transport_in,
256     gchar ** content_type, gchar ** content_base, gchar ** body,
257     gchar ** session_out, gchar ** transport_out)
258 {
259   GstRTSPMessage *request;
260   GstRTSPMessage *response;
261   GstRTSPStatusCode code;
262   gchar *value;
263
264   /* create request */
265   request = create_request (conn, method, control);
266
267   /* add headers */
268   if (session_in) {
269     gst_rtsp_message_add_header (request, GST_RTSP_HDR_SESSION, session_in);
270   }
271   if (transport_in) {
272     gst_rtsp_message_add_header (request, GST_RTSP_HDR_TRANSPORT, transport_in);
273   }
274
275   /* send request */
276   fail_unless (send_request (conn, request));
277   gst_rtsp_message_free (request);
278
279   iterate ();
280
281   /* read response */
282   response = read_response (conn);
283
284   /* check status line */
285   gst_rtsp_message_parse_response (response, &code, NULL, NULL);
286   if (code != GST_RTSP_STS_OK) {
287     gst_rtsp_message_free (response);
288     return code;
289   }
290
291   /* get information from response */
292   if (content_type) {
293     gst_rtsp_message_get_header (response, GST_RTSP_HDR_CONTENT_TYPE,
294         &value, 0);
295     *content_type = g_strdup (value);
296   }
297   if (content_base) {
298     gst_rtsp_message_get_header (response, GST_RTSP_HDR_CONTENT_BASE,
299         &value, 0);
300     *content_base = g_strdup (value);
301   }
302   if (body) {
303     *body = g_malloc (response->body_size + 1);
304     strncpy (*body, (gchar *) response->body, response->body_size);
305   }
306   if (session_out) {
307     gst_rtsp_message_get_header (response, GST_RTSP_HDR_SESSION, &value, 0);
308
309     value = g_strdup (value);
310
311     /* Remove the timeout */
312     if (value) {
313       char *pos = strchr (value, ';');
314       if (pos)
315         *pos = 0;
316     }
317     if (session_in) {
318       /* check that we got the same session back */
319       fail_unless (!g_strcmp0 (value, session_in));
320     }
321     *session_out = value;
322   }
323   if (transport_out) {
324     gst_rtsp_message_get_header (response, GST_RTSP_HDR_TRANSPORT, &value, 0);
325     *transport_out = g_strdup (value);
326   }
327
328   gst_rtsp_message_free (response);
329   return code;
330 }
331
332 /* send an rtsp request with a method and a session, and receive response */
333 static GstRTSPStatusCode
334 do_simple_request (GstRTSPConnection * conn, GstRTSPMethod method,
335     const gchar * session)
336 {
337   return do_request (conn, method, NULL, session, NULL, NULL, NULL,
338       NULL, NULL, NULL);
339 }
340
341 /* send a DESCRIBE request and receive response. returns a received
342  * GstSDPMessage that must be freed by the caller */
343 static GstSDPMessage *
344 do_describe (GstRTSPConnection * conn, const gchar * mount_point)
345 {
346   GstSDPMessage *sdp_message;
347   gchar *content_type;
348   gchar *content_base;
349   gchar *body;
350   gchar *address;
351   gchar *expected_content_base;
352
353   /* send DESCRIBE request */
354   fail_unless (do_request (conn, GST_RTSP_DESCRIBE, NULL, NULL, NULL,
355           &content_type, &content_base, &body, NULL, NULL) == GST_RTSP_STS_OK);
356
357   /* check response values */
358   fail_unless (!g_strcmp0 (content_type, "application/sdp"));
359   address = gst_rtsp_server_get_address (server);
360   expected_content_base =
361       g_strdup_printf ("rtsp://%s:%d%s/", address, test_port, mount_point);
362   fail_unless (!g_strcmp0 (content_base, expected_content_base));
363
364   /* create sdp message */
365   fail_unless (gst_sdp_message_new (&sdp_message) == GST_SDP_OK);
366   fail_unless (gst_sdp_message_parse_buffer ((guint8 *) body,
367           strlen (body), sdp_message) == GST_SDP_OK);
368
369   /* clean up */
370   g_free (content_type);
371   g_free (content_base);
372   g_free (body);
373   g_free (address);
374   g_free (expected_content_base);
375
376   return sdp_message;
377 }
378
379 /* send a SETUP request and receive response. if *session is not NULL,
380  * it is used in the request. otherwise, *session is set to a returned
381  * session string that must be freed by the caller. the returned
382  * transport must be freed by the caller. */
383 static GstRTSPStatusCode
384 do_setup (GstRTSPConnection * conn, const gchar * control,
385     const GstRTSPRange * client_ports, gchar ** session,
386     GstRTSPTransport ** transport)
387 {
388   GstRTSPStatusCode code;
389   gchar *session_in = NULL;
390   gchar *transport_string_in = NULL;
391   gchar **session_out = NULL;
392   gchar *transport_string_out = NULL;
393
394   /* prepare and send SETUP request */
395   if (session) {
396     if (*session) {
397       session_in = *session;
398     } else {
399       session_out = session;
400     }
401   }
402   transport_string_in =
403       g_strdup_printf (TEST_PROTO ";unicast;client_port=%d-%d",
404       client_ports->min, client_ports->max);
405   code =
406       do_request (conn, GST_RTSP_SETUP, control, session_in,
407       transport_string_in, NULL, NULL, NULL, session_out,
408       &transport_string_out);
409   g_free (transport_string_in);
410
411   if (transport_string_out) {
412     /* create transport */
413     fail_unless (gst_rtsp_transport_new (transport) == GST_RTSP_OK);
414     fail_unless (gst_rtsp_transport_parse (transport_string_out,
415             *transport) == GST_RTSP_OK);
416     g_free (transport_string_out);
417   }
418
419   return code;
420 }
421
422 /* fixture setup function */
423 static void
424 setup (void)
425 {
426   server = gst_rtsp_server_new ();
427 }
428
429 /* fixture clean-up function */
430 static void
431 teardown (void)
432 {
433   if (server) {
434     g_object_unref (server);
435     server = NULL;
436   }
437   test_port = 0;
438 }
439
440 GST_START_TEST (test_connect)
441 {
442   GstRTSPConnection *conn;
443
444   start_server ();
445
446   /* connect to server */
447   conn = connect_to_server (test_port, TEST_MOUNT_POINT);
448
449   /* clean up */
450   gst_rtsp_connection_free (conn);
451   stop_server ();
452
453   /* iterate so the clean-up can finish */
454   iterate ();
455 }
456
457 GST_END_TEST;
458
459 GST_START_TEST (test_describe)
460 {
461   GstRTSPConnection *conn;
462   GstSDPMessage *sdp_message = NULL;
463   const GstSDPMedia *sdp_media;
464   gint32 format;
465   gchar *expected_rtpmap;
466   const gchar *rtpmap;
467   const gchar *control_video;
468   const gchar *control_audio;
469
470   start_server ();
471
472   conn = connect_to_server (test_port, TEST_MOUNT_POINT);
473
474   /* send DESCRIBE request */
475   sdp_message = do_describe (conn, TEST_MOUNT_POINT);
476
477   fail_unless (gst_sdp_message_medias_len (sdp_message) == 2);
478
479   /* check video sdp */
480   sdp_media = gst_sdp_message_get_media (sdp_message, 0);
481   fail_unless (!g_strcmp0 (gst_sdp_media_get_proto (sdp_media), TEST_PROTO));
482   fail_unless (gst_sdp_media_formats_len (sdp_media) == 1);
483   sscanf (gst_sdp_media_get_format (sdp_media, 0), "%" G_GINT32_FORMAT,
484       &format);
485   expected_rtpmap =
486       g_strdup_printf ("%d " TEST_ENCODING "/" TEST_CLOCK_RATE, format);
487   rtpmap = gst_sdp_media_get_attribute_val (sdp_media, "rtpmap");
488   fail_unless (!g_strcmp0 (rtpmap, expected_rtpmap));
489   g_free (expected_rtpmap);
490   control_video = gst_sdp_media_get_attribute_val (sdp_media, "control");
491   fail_unless (!g_strcmp0 (control_video, "stream=0"));
492
493   /* check audio sdp */
494   sdp_media = gst_sdp_message_get_media (sdp_message, 1);
495   fail_unless (!g_strcmp0 (gst_sdp_media_get_proto (sdp_media), TEST_PROTO));
496   fail_unless (gst_sdp_media_formats_len (sdp_media) == 1);
497   sscanf (gst_sdp_media_get_format (sdp_media, 0), "%" G_GINT32_FORMAT,
498       &format);
499   expected_rtpmap =
500       g_strdup_printf ("%d " TEST_ENCODING "/" TEST_CLOCK_RATE, format);
501   rtpmap = gst_sdp_media_get_attribute_val (sdp_media, "rtpmap");
502   fail_unless (!g_strcmp0 (rtpmap, expected_rtpmap));
503   g_free (expected_rtpmap);
504   control_audio = gst_sdp_media_get_attribute_val (sdp_media, "control");
505   fail_unless (!g_strcmp0 (control_audio, "stream=1"));
506
507   /* clean up and iterate so the clean-up can finish */
508   gst_sdp_message_free (sdp_message);
509   gst_rtsp_connection_free (conn);
510   stop_server ();
511   iterate ();
512 }
513
514 GST_END_TEST;
515
516 GST_START_TEST (test_describe_non_existing_mount_point)
517 {
518   GstRTSPConnection *conn;
519
520   start_server ();
521
522   /* send DESCRIBE request for a non-existing mount point
523    * and check that we get a 404 Not Found */
524   conn = connect_to_server (test_port, "/non-existing");
525   fail_unless (do_simple_request (conn, GST_RTSP_DESCRIBE, NULL)
526       == GST_RTSP_STS_NOT_FOUND);
527
528   /* clean up and iterate so the clean-up can finish */
529   gst_rtsp_connection_free (conn);
530   stop_server ();
531   iterate ();
532 }
533
534 GST_END_TEST;
535
536 GST_START_TEST (test_setup)
537 {
538   GstRTSPConnection *conn;
539   GstSDPMessage *sdp_message = NULL;
540   const GstSDPMedia *sdp_media;
541   const gchar *video_control;
542   const gchar *audio_control;
543   GstRTSPRange client_ports;
544   gchar *session = NULL;
545   GstRTSPTransport *video_transport = NULL;
546   GstRTSPTransport *audio_transport = NULL;
547
548   start_server ();
549
550   conn = connect_to_server (test_port, TEST_MOUNT_POINT);
551
552   sdp_message = do_describe (conn, TEST_MOUNT_POINT);
553
554   /* get control strings from DESCRIBE response */
555   fail_unless (gst_sdp_message_medias_len (sdp_message) == 2);
556   sdp_media = gst_sdp_message_get_media (sdp_message, 0);
557   video_control = gst_sdp_media_get_attribute_val (sdp_media, "control");
558   sdp_media = gst_sdp_message_get_media (sdp_message, 1);
559   audio_control = gst_sdp_media_get_attribute_val (sdp_media, "control");
560
561   get_client_ports (&client_ports);
562
563   /* send SETUP request for video */
564   fail_unless (do_setup (conn, video_control, &client_ports, &session,
565           &video_transport) == GST_RTSP_STS_OK);
566   GST_DEBUG ("set up video %s, got session '%s'", video_control, session);
567
568   /* check response from SETUP */
569   fail_unless (video_transport->trans == GST_RTSP_TRANS_RTP);
570   fail_unless (video_transport->profile == GST_RTSP_PROFILE_AVP);
571   fail_unless (video_transport->lower_transport == GST_RTSP_LOWER_TRANS_UDP);
572   fail_unless (video_transport->mode_play);
573   gst_rtsp_transport_free (video_transport);
574
575   /* send SETUP request for audio */
576   fail_unless (do_setup (conn, audio_control, &client_ports, &session,
577           &audio_transport) == GST_RTSP_STS_OK);
578   GST_DEBUG ("set up audio %s with session '%s'", audio_control, session);
579
580   /* check response from SETUP */
581   fail_unless (audio_transport->trans == GST_RTSP_TRANS_RTP);
582   fail_unless (audio_transport->profile == GST_RTSP_PROFILE_AVP);
583   fail_unless (audio_transport->lower_transport == GST_RTSP_LOWER_TRANS_UDP);
584   fail_unless (audio_transport->mode_play);
585   gst_rtsp_transport_free (audio_transport);
586
587   /* clean up and iterate so the clean-up can finish */
588   g_free (session);
589   gst_sdp_message_free (sdp_message);
590   gst_rtsp_connection_free (conn);
591   stop_server ();
592   iterate ();
593 }
594
595 GST_END_TEST;
596
597 GST_START_TEST (test_setup_non_existing_stream)
598 {
599   GstRTSPConnection *conn;
600   GstRTSPRange client_ports;
601
602   start_server ();
603
604   conn = connect_to_server (test_port, TEST_MOUNT_POINT);
605
606   get_client_ports (&client_ports);
607
608   /* send SETUP request with a non-existing stream and check that we get a
609    * 404 Not Found */
610   fail_unless (do_setup (conn, "stream=7", &client_ports, NULL,
611           NULL) == GST_RTSP_STS_NOT_FOUND);
612
613   /* clean up and iterate so the clean-up can finish */
614   gst_rtsp_connection_free (conn);
615   stop_server ();
616   iterate ();
617
618   /* need to unref the server here, otherwise threads will remain
619    * and teardown won't be run */
620   g_object_unref (server);
621   server = NULL;
622 }
623
624 GST_END_TEST;
625
626 static void
627 do_test_play (void)
628 {
629   GstRTSPConnection *conn;
630   GstSDPMessage *sdp_message = NULL;
631   const GstSDPMedia *sdp_media;
632   const gchar *video_control;
633   const gchar *audio_control;
634   GstRTSPRange client_port;
635   gchar *session = NULL;
636   GstRTSPTransport *video_transport = NULL;
637   GstRTSPTransport *audio_transport = NULL;
638
639   conn = connect_to_server (test_port, TEST_MOUNT_POINT);
640
641   sdp_message = do_describe (conn, TEST_MOUNT_POINT);
642
643   /* get control strings from DESCRIBE response */
644   fail_unless (gst_sdp_message_medias_len (sdp_message) == 2);
645   sdp_media = gst_sdp_message_get_media (sdp_message, 0);
646   video_control = gst_sdp_media_get_attribute_val (sdp_media, "control");
647   sdp_media = gst_sdp_message_get_media (sdp_message, 1);
648   audio_control = gst_sdp_media_get_attribute_val (sdp_media, "control");
649
650   get_client_ports (&client_port);
651
652   /* do SETUP for video and audio */
653   fail_unless (do_setup (conn, video_control, &client_port, &session,
654           &video_transport) == GST_RTSP_STS_OK);
655   fail_unless (do_setup (conn, audio_control, &client_port, &session,
656           &audio_transport) == GST_RTSP_STS_OK);
657
658   /* send PLAY request and check that we get 200 OK */
659   fail_unless (do_simple_request (conn, GST_RTSP_PLAY,
660           session) == GST_RTSP_STS_OK);
661
662   /* send TEARDOWN request and check that we get 200 OK */
663   fail_unless (do_simple_request (conn, GST_RTSP_TEARDOWN,
664           session) == GST_RTSP_STS_OK);
665
666   /* clean up and iterate so the clean-up can finish */
667   g_free (session);
668   gst_rtsp_transport_free (video_transport);
669   gst_rtsp_transport_free (audio_transport);
670   gst_sdp_message_free (sdp_message);
671   gst_rtsp_connection_free (conn);
672 }
673
674
675 GST_START_TEST (test_play)
676 {
677   start_server ();
678
679   do_test_play ();
680
681   stop_server ();
682   iterate ();
683 }
684
685 GST_END_TEST;
686
687 GST_START_TEST (test_play_without_session)
688 {
689   GstRTSPConnection *conn;
690
691   start_server ();
692
693   conn = connect_to_server (test_port, TEST_MOUNT_POINT);
694
695   /* send PLAY request without a session and check that we get a
696    * 454 Session Not Found */
697   fail_unless (do_simple_request (conn, GST_RTSP_PLAY,
698           NULL) == GST_RTSP_STS_SESSION_NOT_FOUND);
699
700   /* clean up and iterate so the clean-up can finish */
701   gst_rtsp_connection_free (conn);
702   stop_server ();
703   iterate ();
704 }
705
706 GST_END_TEST;
707
708 GST_START_TEST (test_bind_already_in_use)
709 {
710   GstRTSPServer *serv;
711   GSocketService *service;
712   GError *error = NULL;
713   guint16 port;
714   gchar *port_str;
715
716   serv = gst_rtsp_server_new ();
717   service = g_socket_service_new ();
718
719   /* bind service to port */
720   port =
721       g_socket_listener_add_any_inet_port (G_SOCKET_LISTENER (service), NULL,
722       &error);
723   g_assert_no_error (error);
724
725   port_str = g_strdup_printf ("%d\n", port);
726
727   /* try to bind server to the same port */
728   g_object_set (serv, "service", port_str, NULL);
729   g_free (port_str);
730
731   /* attach to default main context */
732   fail_unless (gst_rtsp_server_attach (serv, NULL) == 0);
733
734   /* cleanup */
735   g_object_unref (serv);
736   g_socket_listener_close (G_SOCKET_LISTENER (service));
737   g_object_unref (service);
738 }
739
740 GST_END_TEST;
741
742
743 GST_START_TEST (test_play_multithreaded)
744 {
745   gst_rtsp_server_set_max_threads (server, -1);
746
747   start_server ();
748
749   do_test_play ();
750
751   stop_server ();
752   iterate ();
753 }
754
755 GST_END_TEST;
756
757 enum
758 {
759   BLOCK_ME,
760   BLOCKED,
761   UNBLOCK
762 };
763
764
765 static void
766 media_constructed_block (GstRTSPMediaFactory * factory,
767     GstRTSPMedia * media, gpointer user_data)
768 {
769   gint *block_state = user_data;
770
771   g_mutex_lock (&check_mutex);
772
773   *block_state = BLOCKED;
774   g_cond_broadcast (&check_cond);
775
776   while (*block_state != UNBLOCK)
777     g_cond_wait (&check_cond, &check_mutex);
778   g_mutex_unlock (&check_mutex);
779 }
780
781
782 GST_START_TEST (test_play_multithreaded_block_in_describe)
783 {
784   GstRTSPConnection *conn;
785   GstRTSPMountPoints *mounts;
786   GstRTSPMediaFactory *factory;
787   gint block_state = BLOCK_ME;
788   GstRTSPMessage *request;
789   GstRTSPMessage *response;
790   GstRTSPStatusCode code;
791
792   gst_rtsp_server_set_max_threads (server, 1);
793
794   mounts = gst_rtsp_server_get_mount_points (server);
795   fail_unless (mounts != NULL);
796   factory = gst_rtsp_media_factory_new ();
797   gst_rtsp_media_factory_set_launch (factory,
798       "( " VIDEO_PIPELINE "  " AUDIO_PIPELINE " )");
799   g_signal_connect (factory, "media-constructed",
800       G_CALLBACK (media_constructed_block), &block_state);
801   gst_rtsp_mount_points_add_factory (mounts, TEST_MOUNT_POINT "2", factory);
802   g_object_unref (mounts);
803
804   start_server ();
805
806   conn = connect_to_server (test_port, TEST_MOUNT_POINT "2");
807   iterate ();
808
809   /* do describe, it will not return now as we've blocked it */
810   request = create_request (conn, GST_RTSP_DESCRIBE, NULL);
811   fail_unless (send_request (conn, request));
812   gst_rtsp_message_free (request);
813
814   g_mutex_lock (&check_mutex);
815   while (block_state != BLOCKED)
816     g_cond_wait (&check_cond, &check_mutex);
817   g_mutex_unlock (&check_mutex);
818
819   /* Do a second connection while the first one is blocked */
820   do_test_play ();
821
822   /* Now unblock the describe */
823   g_mutex_lock (&check_mutex);
824   block_state = UNBLOCK;
825   g_cond_broadcast (&check_cond);
826   g_mutex_unlock (&check_mutex);
827
828   response = read_response (conn);
829   gst_rtsp_message_parse_response (response, &code, NULL, NULL);
830   fail_unless (code == GST_RTSP_STS_OK);
831   gst_rtsp_message_free (response);
832
833
834   gst_rtsp_connection_free (conn);
835   stop_server ();
836   iterate ();
837
838 }
839
840 GST_END_TEST;
841
842
843 static void
844 new_session_timeout_one (GstRTSPClient * client,
845     GstRTSPSession * session, gpointer user_data)
846 {
847   gst_rtsp_session_set_timeout (session, 1);
848
849   g_signal_handlers_disconnect_by_func (client, new_session_timeout_one,
850       user_data);
851 }
852
853 static void
854 session_connected_new_session_cb (GstRTSPServer * server,
855     GstRTSPClient * client, gpointer user_data)
856 {
857
858   g_signal_connect (client, "new-session", user_data, NULL);
859 }
860
861 GST_START_TEST (test_play_multithreaded_timeout_client)
862 {
863   GstRTSPConnection *conn;
864   GstSDPMessage *sdp_message = NULL;
865   const GstSDPMedia *sdp_media;
866   const gchar *video_control;
867   const gchar *audio_control;
868   GstRTSPRange client_port;
869   gchar *session = NULL;
870   GstRTSPTransport *video_transport = NULL;
871   GstRTSPTransport *audio_transport = NULL;
872   GstRTSPSessionPool *pool;
873   GstRTSPMessage *request;
874   GstRTSPMessage *response;
875
876   gst_rtsp_server_set_max_threads (server, -1);
877   pool = gst_rtsp_server_get_session_pool (server);
878   g_signal_connect (server, "client-connected",
879       G_CALLBACK (session_connected_new_session_cb), new_session_timeout_one);
880
881   start_server ();
882
883
884   conn = connect_to_server (test_port, TEST_MOUNT_POINT);
885
886   sdp_message = do_describe (conn, TEST_MOUNT_POINT);
887
888   /* get control strings from DESCRIBE response */
889   fail_unless (gst_sdp_message_medias_len (sdp_message) == 2);
890   sdp_media = gst_sdp_message_get_media (sdp_message, 0);
891   video_control = gst_sdp_media_get_attribute_val (sdp_media, "control");
892   sdp_media = gst_sdp_message_get_media (sdp_message, 1);
893   audio_control = gst_sdp_media_get_attribute_val (sdp_media, "control");
894
895   get_client_ports (&client_port);
896
897   /* do SETUP for video and audio */
898   fail_unless (do_setup (conn, video_control, &client_port, &session,
899           &video_transport) == GST_RTSP_STS_OK);
900   fail_unless (do_setup (conn, audio_control, &client_port, &session,
901           &audio_transport) == GST_RTSP_STS_OK);
902
903   fail_unless (gst_rtsp_session_pool_get_n_sessions (pool) == 1);
904
905   /* send PLAY request and check that we get 200 OK */
906   fail_unless (do_simple_request (conn, GST_RTSP_PLAY,
907           session) == GST_RTSP_STS_OK);
908
909   sleep (7);
910
911   fail_unless (gst_rtsp_session_pool_cleanup (pool) == 1);
912
913
914   /* send TEARDOWN request and check that we get 454 Session Not found */
915   request = create_request (conn, GST_RTSP_TEARDOWN, NULL);
916   gst_rtsp_message_add_header (request, GST_RTSP_HDR_SESSION, session);
917   fail_unless (send_request (conn, request));
918   gst_rtsp_message_free (request);
919
920   fail_unless (gst_rtsp_message_new (&response) == GST_RTSP_OK);
921   fail_unless (gst_rtsp_connection_receive (conn, response, NULL) ==
922       GST_RTSP_ESYS);
923   fail_unless (errno == ECONNRESET);
924   gst_rtsp_message_free (response);
925
926   /* clean up and iterate so the clean-up can finish */
927   g_object_unref (pool);
928   g_free (session);
929   gst_rtsp_transport_free (video_transport);
930   gst_rtsp_transport_free (audio_transport);
931   gst_sdp_message_free (sdp_message);
932   gst_rtsp_connection_free (conn);
933
934   stop_server ();
935   iterate ();
936 }
937
938 GST_END_TEST;
939
940
941 GST_START_TEST (test_play_multithreaded_timeout_session)
942 {
943   GstRTSPConnection *conn;
944   GstSDPMessage *sdp_message = NULL;
945   const GstSDPMedia *sdp_media;
946   const gchar *video_control;
947   const gchar *audio_control;
948   GstRTSPRange client_port;
949   gchar *session1 = NULL;
950   gchar *session2 = NULL;
951   GstRTSPTransport *video_transport = NULL;
952   GstRTSPTransport *audio_transport = NULL;
953   GstRTSPSessionPool *pool;
954
955   gst_rtsp_server_set_max_threads (server, -1);
956   pool = gst_rtsp_server_get_session_pool (server);
957   g_signal_connect (server, "client-connected",
958       G_CALLBACK (session_connected_new_session_cb), new_session_timeout_one);
959
960   start_server ();
961
962
963   conn = connect_to_server (test_port, TEST_MOUNT_POINT);
964
965   gst_rtsp_connection_set_remember_session_id (conn, FALSE);
966
967   sdp_message = do_describe (conn, TEST_MOUNT_POINT);
968
969   /* get control strings from DESCRIBE response */
970   fail_unless (gst_sdp_message_medias_len (sdp_message) == 2);
971   sdp_media = gst_sdp_message_get_media (sdp_message, 0);
972   video_control = gst_sdp_media_get_attribute_val (sdp_media, "control");
973   sdp_media = gst_sdp_message_get_media (sdp_message, 1);
974   audio_control = gst_sdp_media_get_attribute_val (sdp_media, "control");
975
976   get_client_ports (&client_port);
977
978   /* do SETUP for video and audio */
979   fail_unless (do_setup (conn, video_control, &client_port, &session1,
980           &video_transport) == GST_RTSP_STS_OK);
981   fail_unless (do_setup (conn, audio_control, &client_port, &session2,
982           &audio_transport) == GST_RTSP_STS_OK);
983
984   fail_unless (gst_rtsp_session_pool_get_n_sessions (pool) == 2);
985
986   /* send PLAY request and check that we get 200 OK */
987   fail_unless (do_simple_request (conn, GST_RTSP_PLAY,
988           session1) == GST_RTSP_STS_OK);
989   fail_unless (do_simple_request (conn, GST_RTSP_PLAY,
990           session2) == GST_RTSP_STS_OK);
991
992   sleep (7);
993
994   fail_unless (gst_rtsp_session_pool_cleanup (pool) == 1);
995
996   /* send TEARDOWN request and check that we get 454 Session Not found */
997   fail_unless (do_simple_request (conn, GST_RTSP_TEARDOWN,
998           session1) == GST_RTSP_STS_SESSION_NOT_FOUND);
999
1000   fail_unless (do_simple_request (conn, GST_RTSP_TEARDOWN,
1001           session2) == GST_RTSP_STS_OK);
1002
1003   /* clean up and iterate so the clean-up can finish */
1004   g_object_unref (pool);
1005   g_free (session1);
1006   g_free (session2);
1007   gst_rtsp_transport_free (video_transport);
1008   gst_rtsp_transport_free (audio_transport);
1009   gst_sdp_message_free (sdp_message);
1010   gst_rtsp_connection_free (conn);
1011
1012   stop_server ();
1013   iterate ();
1014 }
1015
1016 GST_END_TEST;
1017
1018
1019
1020 GST_START_TEST (test_play_disconnect)
1021 {
1022   GstRTSPConnection *conn;
1023   GstSDPMessage *sdp_message = NULL;
1024   const GstSDPMedia *sdp_media;
1025   const gchar *video_control;
1026   const gchar *audio_control;
1027   GstRTSPRange client_port;
1028   gchar *session = NULL;
1029   GstRTSPTransport *video_transport = NULL;
1030   GstRTSPTransport *audio_transport = NULL;
1031   GstRTSPSessionPool *pool;
1032
1033   pool = gst_rtsp_server_get_session_pool (server);
1034   g_signal_connect (server, "client-connected",
1035       G_CALLBACK (session_connected_new_session_cb), new_session_timeout_one);
1036
1037   start_server ();
1038
1039   conn = connect_to_server (test_port, TEST_MOUNT_POINT);
1040
1041   sdp_message = do_describe (conn, TEST_MOUNT_POINT);
1042
1043   /* get control strings from DESCRIBE response */
1044   fail_unless (gst_sdp_message_medias_len (sdp_message) == 2);
1045   sdp_media = gst_sdp_message_get_media (sdp_message, 0);
1046   video_control = gst_sdp_media_get_attribute_val (sdp_media, "control");
1047   sdp_media = gst_sdp_message_get_media (sdp_message, 1);
1048   audio_control = gst_sdp_media_get_attribute_val (sdp_media, "control");
1049
1050   get_client_ports (&client_port);
1051
1052   /* do SETUP for video and audio */
1053   fail_unless (do_setup (conn, video_control, &client_port, &session,
1054           &video_transport) == GST_RTSP_STS_OK);
1055   fail_unless (do_setup (conn, audio_control, &client_port, &session,
1056           &audio_transport) == GST_RTSP_STS_OK);
1057
1058   fail_unless (gst_rtsp_session_pool_get_n_sessions (pool) == 1);
1059
1060   /* send PLAY request and check that we get 200 OK */
1061   fail_unless (do_simple_request (conn, GST_RTSP_PLAY,
1062           session) == GST_RTSP_STS_OK);
1063
1064   gst_rtsp_connection_free (conn);
1065
1066   sleep (7);
1067
1068   fail_unless (gst_rtsp_session_pool_get_n_sessions (pool) == 1);
1069   fail_unless (gst_rtsp_session_pool_cleanup (pool) == 1);
1070
1071
1072   /* clean up and iterate so the clean-up can finish */
1073   g_object_unref (pool);
1074   g_free (session);
1075   gst_rtsp_transport_free (video_transport);
1076   gst_rtsp_transport_free (audio_transport);
1077   gst_sdp_message_free (sdp_message);
1078
1079   stop_server ();
1080   iterate ();
1081 }
1082
1083 GST_END_TEST;
1084
1085 static Suite *
1086 rtspserver_suite (void)
1087 {
1088   Suite *s = suite_create ("rtspserver");
1089   TCase *tc = tcase_create ("general");
1090
1091   suite_add_tcase (s, tc);
1092   tcase_add_checked_fixture (tc, setup, teardown);
1093   tcase_set_timeout (tc, 20);
1094   tcase_add_test (tc, test_connect);
1095   tcase_add_test (tc, test_describe);
1096   tcase_add_test (tc, test_describe_non_existing_mount_point);
1097   tcase_add_test (tc, test_setup);
1098   tcase_add_test (tc, test_setup_non_existing_stream);
1099   tcase_add_test (tc, test_play);
1100   tcase_add_test (tc, test_play_without_session);
1101   tcase_add_test (tc, test_bind_already_in_use);
1102   tcase_add_test (tc, test_play_multithreaded);
1103   tcase_add_test (tc, test_play_multithreaded_block_in_describe);
1104   tcase_add_test (tc, test_play_multithreaded_timeout_client);
1105   tcase_add_test (tc, test_play_multithreaded_timeout_session);
1106   tcase_add_test (tc, test_play_disconnect);
1107
1108   return s;
1109 }
1110
1111 GST_CHECK_MAIN (rtspserver);