ddde369a7ae1befda604b187d4c7133df396a2ad
[platform/upstream/gstreamer.git] / subprojects / gst-rtsp-server / gst / rtsp-server / rtsp-server.c
1 /* GStreamer
2  * Copyright (C) 2008 Wim Taymans <wim.taymans at 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  * SECTION:rtsp-server
21  * @short_description: The main server object
22  * @see_also: #GstRTSPClient, #GstRTSPThreadPool
23  *
24  * The server object is the object listening for connections on a port and
25  * creating #GstRTSPClient objects to handle those connections.
26  *
27  * The server will listen on the address set with gst_rtsp_server_set_address()
28  * and the port or service configured with gst_rtsp_server_set_service().
29  * Use gst_rtsp_server_set_backlog() to configure the amount of pending requests
30  * that the server will keep. By default the server listens on the current
31  * network (0.0.0.0) and port 8554.
32  *
33  * The server will require an SSL connection when a TLS certificate has been
34  * set in the auth object with gst_rtsp_auth_set_tls_certificate().
35  *
36  * To start the server, use gst_rtsp_server_attach() to attach it to a
37  * #GMainContext. For more control, gst_rtsp_server_create_source() and
38  * gst_rtsp_server_create_socket() can be used to get a #GSource and #GSocket
39  * respectively.
40  *
41  * gst_rtsp_server_transfer_connection() can be used to transfer an existing
42  * socket to the RTSP server, for example from an HTTP server.
43  *
44  * Once the server socket is attached to a mainloop, it will start accepting
45  * connections. When a new connection is received, a new #GstRTSPClient object
46  * is created to handle the connection. The new client will be configured with
47  * the server #GstRTSPAuth, #GstRTSPMountPoints, #GstRTSPSessionPool and
48  * #GstRTSPThreadPool.
49  *
50  * The server uses the configured #GstRTSPThreadPool object to handle the
51  * remainder of the communication with this client.
52  *
53  * Last reviewed on 2013-07-11 (1.0.0)
54  */
55 #ifdef HAVE_CONFIG_H
56 #include "config.h"
57 #endif
58
59 #include <stdlib.h>
60 #include <string.h>
61
62 #include "rtsp-context.h"
63 #include "rtsp-server-object.h"
64 #include "rtsp-client.h"
65
66 #define GST_RTSP_SERVER_GET_LOCK(server)  (&(GST_RTSP_SERVER_CAST(server)->priv->lock))
67 #define GST_RTSP_SERVER_LOCK(server)      (g_mutex_lock(GST_RTSP_SERVER_GET_LOCK(server)))
68 #define GST_RTSP_SERVER_UNLOCK(server)    (g_mutex_unlock(GST_RTSP_SERVER_GET_LOCK(server)))
69
70 struct _GstRTSPServerPrivate
71 {
72   GMutex lock;                  /* protects everything in this struct */
73
74   /* server information */
75   gchar *address;
76   gchar *service;
77   gint backlog;
78
79   GSocket *socket;
80
81   /* sessions on this server */
82   GstRTSPSessionPool *session_pool;
83
84   /* mount points for this server */
85   GstRTSPMountPoints *mount_points;
86
87   /* request size limit */
88   guint content_length_limit;
89
90   /* authentication manager */
91   GstRTSPAuth *auth;
92
93   /* resource manager */
94   GstRTSPThreadPool *thread_pool;
95
96   /* the clients that are connected */
97   GList *clients;
98   guint clients_cookie;
99 };
100
101 #define DEFAULT_ADDRESS         "0.0.0.0"
102 #define DEFAULT_BOUND_PORT      -1
103 /* #define DEFAULT_ADDRESS         "::0" */
104 #define DEFAULT_SERVICE         "8554"
105 #define DEFAULT_BACKLOG         5
106
107 /* Define to use the SO_LINGER option so that the server sockets can be resused
108  * sooner. Disabled for now because it is not very well implemented by various
109  * OSes and it causes clients to fail to read the TEARDOWN response. */
110 #undef USE_SOLINGER
111
112 enum
113 {
114   PROP_0,
115   PROP_ADDRESS,
116   PROP_SERVICE,
117   PROP_BOUND_PORT,
118   PROP_BACKLOG,
119
120   PROP_SESSION_POOL,
121   PROP_MOUNT_POINTS,
122   PROP_CONTENT_LENGTH_LIMIT,
123   PROP_LAST
124 };
125
126 enum
127 {
128   SIGNAL_CLIENT_CONNECTED,
129   SIGNAL_LAST
130 };
131
132 G_DEFINE_TYPE_WITH_PRIVATE (GstRTSPServer, gst_rtsp_server, G_TYPE_OBJECT);
133
134 GST_DEBUG_CATEGORY_STATIC (rtsp_server_debug);
135 #define GST_CAT_DEFAULT rtsp_server_debug
136
137 typedef struct _ClientContext ClientContext;
138
139 static guint gst_rtsp_server_signals[SIGNAL_LAST] = { 0 };
140
141 static void gst_rtsp_server_get_property (GObject * object, guint propid,
142     GValue * value, GParamSpec * pspec);
143 static void gst_rtsp_server_set_property (GObject * object, guint propid,
144     const GValue * value, GParamSpec * pspec);
145 static void gst_rtsp_server_finalize (GObject * object);
146
147 static GstRTSPClient *default_create_client (GstRTSPServer * server);
148
149 static void
150 gst_rtsp_server_class_init (GstRTSPServerClass * klass)
151 {
152   GObjectClass *gobject_class;
153
154   gobject_class = G_OBJECT_CLASS (klass);
155
156   gobject_class->get_property = gst_rtsp_server_get_property;
157   gobject_class->set_property = gst_rtsp_server_set_property;
158   gobject_class->finalize = gst_rtsp_server_finalize;
159
160   /**
161    * GstRTSPServer::address:
162    *
163    * The address of the server. This is the address where the server will
164    * listen on.
165    */
166   g_object_class_install_property (gobject_class, PROP_ADDRESS,
167       g_param_spec_string ("address", "Address",
168           "The address the server uses to listen on", DEFAULT_ADDRESS,
169           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
170   /**
171    * GstRTSPServer::service:
172    *
173    * The service of the server. This is either a string with the service name or
174    * a port number (as a string) the server will listen on.
175    */
176   g_object_class_install_property (gobject_class, PROP_SERVICE,
177       g_param_spec_string ("service", "Service",
178           "The service or port number the server uses to listen on",
179           DEFAULT_SERVICE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
180   /**
181    * GstRTSPServer::bound-port:
182    *
183    * The actual port the server is listening on. Can be used to retrieve the
184    * port number when the server is started on port 0, which means bind to a
185    * random port. Set to -1 if the server has not been bound yet.
186    */
187   g_object_class_install_property (gobject_class, PROP_BOUND_PORT,
188       g_param_spec_int ("bound-port", "Bound port",
189           "The port number the server is listening on",
190           -1, G_MAXUINT16, DEFAULT_BOUND_PORT,
191           G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
192   /**
193    * GstRTSPServer::backlog:
194    *
195    * The backlog argument defines the maximum length to which the queue of
196    * pending connections for the server may grow. If a connection request arrives
197    * when the queue is full, the client may receive an error with an indication of
198    * ECONNREFUSED or, if the underlying protocol supports retransmission, the
199    * request may be ignored so that a later reattempt at connection succeeds.
200    */
201   g_object_class_install_property (gobject_class, PROP_BACKLOG,
202       g_param_spec_int ("backlog", "Backlog",
203           "The maximum length to which the queue "
204           "of pending connections may grow", 0, G_MAXINT, DEFAULT_BACKLOG,
205           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
206   /**
207    * GstRTSPServer::session-pool:
208    *
209    * The session pool of the server. By default each server has a separate
210    * session pool but sessions can be shared between servers by setting the same
211    * session pool on multiple servers.
212    */
213   g_object_class_install_property (gobject_class, PROP_SESSION_POOL,
214       g_param_spec_object ("session-pool", "Session Pool",
215           "The session pool to use for client session",
216           GST_TYPE_RTSP_SESSION_POOL,
217           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
218   /**
219    * GstRTSPServer::mount-points:
220    *
221    * The mount points to use for this server. By default the server has no
222    * mount points and thus cannot map urls to media streams.
223    */
224   g_object_class_install_property (gobject_class, PROP_MOUNT_POINTS,
225       g_param_spec_object ("mount-points", "Mount Points",
226           "The mount points to use for client session",
227           GST_TYPE_RTSP_MOUNT_POINTS,
228           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
229
230   /**
231    * RTSPServer::content-length-limit:
232    *
233    * Define an appropriate request size limit and reject requests exceeding the
234    * limit.
235    *
236    * Since: 1.18
237    */
238   g_object_class_install_property (gobject_class, PROP_CONTENT_LENGTH_LIMIT,
239       g_param_spec_uint ("content-length-limit", "Limitation of Content-Length",
240           "Limitation of Content-Length",
241           0, G_MAXUINT, G_MAXUINT, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
242
243   gst_rtsp_server_signals[SIGNAL_CLIENT_CONNECTED] =
244       g_signal_new ("client-connected", G_TYPE_FROM_CLASS (gobject_class),
245       G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstRTSPServerClass, client_connected),
246       NULL, NULL, NULL, G_TYPE_NONE, 1, GST_TYPE_RTSP_CLIENT);
247
248   klass->create_client = default_create_client;
249
250   GST_DEBUG_CATEGORY_INIT (rtsp_server_debug, "rtspserver", 0, "GstRTSPServer");
251 }
252
253 static void
254 gst_rtsp_server_init (GstRTSPServer * server)
255 {
256   GstRTSPServerPrivate *priv = gst_rtsp_server_get_instance_private (server);
257
258   server->priv = priv;
259
260   g_mutex_init (&priv->lock);
261   priv->address = g_strdup (DEFAULT_ADDRESS);
262   priv->service = g_strdup (DEFAULT_SERVICE);
263   priv->socket = NULL;
264   priv->backlog = DEFAULT_BACKLOG;
265   priv->session_pool = gst_rtsp_session_pool_new ();
266   priv->mount_points = gst_rtsp_mount_points_new ();
267   priv->content_length_limit = G_MAXUINT;
268   priv->thread_pool = gst_rtsp_thread_pool_new ();
269 }
270
271 static void
272 gst_rtsp_server_finalize (GObject * object)
273 {
274   GstRTSPServer *server = GST_RTSP_SERVER (object);
275   GstRTSPServerPrivate *priv = server->priv;
276
277   GST_DEBUG_OBJECT (server, "finalize server");
278
279   g_free (priv->address);
280   g_free (priv->service);
281
282   if (priv->socket)
283     g_object_unref (priv->socket);
284
285   if (priv->session_pool)
286     g_object_unref (priv->session_pool);
287   if (priv->mount_points)
288     g_object_unref (priv->mount_points);
289   if (priv->thread_pool)
290     g_object_unref (priv->thread_pool);
291
292   if (priv->auth)
293     g_object_unref (priv->auth);
294
295   g_mutex_clear (&priv->lock);
296
297   G_OBJECT_CLASS (gst_rtsp_server_parent_class)->finalize (object);
298 }
299
300 /**
301  * gst_rtsp_server_new:
302  *
303  * Create a new #GstRTSPServer instance.
304  *
305  * Returns: (transfer full): a new #GstRTSPServer
306  */
307 GstRTSPServer *
308 gst_rtsp_server_new (void)
309 {
310   GstRTSPServer *result;
311
312   result = g_object_new (GST_TYPE_RTSP_SERVER, NULL);
313
314   return result;
315 }
316
317 /**
318  * gst_rtsp_server_set_address:
319  * @server: a #GstRTSPServer
320  * @address: the address
321  *
322  * Configure @server to accept connections on the given address.
323  *
324  * This function must be called before the server is bound.
325  */
326 void
327 gst_rtsp_server_set_address (GstRTSPServer * server, const gchar * address)
328 {
329   GstRTSPServerPrivate *priv;
330
331   g_return_if_fail (GST_IS_RTSP_SERVER (server));
332   g_return_if_fail (address != NULL);
333
334   priv = server->priv;
335
336   GST_RTSP_SERVER_LOCK (server);
337   g_free (priv->address);
338   priv->address = g_strdup (address);
339   GST_RTSP_SERVER_UNLOCK (server);
340 }
341
342 /**
343  * gst_rtsp_server_get_address:
344  * @server: a #GstRTSPServer
345  *
346  * Get the address on which the server will accept connections.
347  *
348  * Returns: (transfer full) (nullable): the server address. g_free() after usage.
349  */
350 gchar *
351 gst_rtsp_server_get_address (GstRTSPServer * server)
352 {
353   GstRTSPServerPrivate *priv;
354   gchar *result;
355
356   g_return_val_if_fail (GST_IS_RTSP_SERVER (server), NULL);
357
358   priv = server->priv;
359
360   GST_RTSP_SERVER_LOCK (server);
361   result = g_strdup (priv->address);
362   GST_RTSP_SERVER_UNLOCK (server);
363
364   return result;
365 }
366
367 /**
368  * gst_rtsp_server_get_bound_port:
369  * @server: a #GstRTSPServer
370  *
371  * Get the port number where the server was bound to.
372  *
373  * Returns: the port number
374  */
375 int
376 gst_rtsp_server_get_bound_port (GstRTSPServer * server)
377 {
378   GstRTSPServerPrivate *priv;
379   GSocketAddress *address;
380   int result = -1;
381
382   g_return_val_if_fail (GST_IS_RTSP_SERVER (server), result);
383
384   priv = server->priv;
385
386   GST_RTSP_SERVER_LOCK (server);
387   if (priv->socket == NULL)
388     goto out;
389
390   address = g_socket_get_local_address (priv->socket, NULL);
391   result = g_inet_socket_address_get_port (G_INET_SOCKET_ADDRESS (address));
392   g_object_unref (address);
393
394 out:
395   GST_RTSP_SERVER_UNLOCK (server);
396
397   return result;
398 }
399
400 /**
401  * gst_rtsp_server_set_service:
402  * @server: a #GstRTSPServer
403  * @service: the service
404  *
405  * Configure @server to accept connections on the given service.
406  * @service should be a string containing the service name (see services(5)) or
407  * a string containing a port number between 1 and 65535.
408  *
409  * When @service is set to "0", the server will listen on a random free
410  * port. The actual used port can be retrieved with
411  * gst_rtsp_server_get_bound_port().
412  *
413  * This function must be called before the server is bound.
414  */
415 void
416 gst_rtsp_server_set_service (GstRTSPServer * server, const gchar * service)
417 {
418   GstRTSPServerPrivate *priv;
419
420   g_return_if_fail (GST_IS_RTSP_SERVER (server));
421   g_return_if_fail (service != NULL);
422
423   priv = server->priv;
424
425   GST_RTSP_SERVER_LOCK (server);
426   g_free (priv->service);
427   priv->service = g_strdup (service);
428   GST_RTSP_SERVER_UNLOCK (server);
429 }
430
431 /**
432  * gst_rtsp_server_get_service:
433  * @server: a #GstRTSPServer
434  *
435  * Get the service on which the server will accept connections.
436  *
437  * Returns: (transfer full) (nullable): the service. use g_free() after usage.
438  */
439 gchar *
440 gst_rtsp_server_get_service (GstRTSPServer * server)
441 {
442   GstRTSPServerPrivate *priv;
443   gchar *result;
444
445   g_return_val_if_fail (GST_IS_RTSP_SERVER (server), NULL);
446
447   priv = server->priv;
448
449   GST_RTSP_SERVER_LOCK (server);
450   result = g_strdup (priv->service);
451   GST_RTSP_SERVER_UNLOCK (server);
452
453   return result;
454 }
455
456 /**
457  * gst_rtsp_server_set_backlog:
458  * @server: a #GstRTSPServer
459  * @backlog: the backlog
460  *
461  * configure the maximum amount of requests that may be queued for the
462  * server.
463  *
464  * This function must be called before the server is bound.
465  */
466 void
467 gst_rtsp_server_set_backlog (GstRTSPServer * server, gint backlog)
468 {
469   GstRTSPServerPrivate *priv;
470
471   g_return_if_fail (GST_IS_RTSP_SERVER (server));
472
473   priv = server->priv;
474
475   GST_RTSP_SERVER_LOCK (server);
476   priv->backlog = backlog;
477   GST_RTSP_SERVER_UNLOCK (server);
478 }
479
480 /**
481  * gst_rtsp_server_get_backlog:
482  * @server: a #GstRTSPServer
483  *
484  * The maximum amount of queued requests for the server.
485  *
486  * Returns: the server backlog.
487  */
488 gint
489 gst_rtsp_server_get_backlog (GstRTSPServer * server)
490 {
491   GstRTSPServerPrivate *priv;
492   gint result;
493
494   g_return_val_if_fail (GST_IS_RTSP_SERVER (server), -1);
495
496   priv = server->priv;
497
498   GST_RTSP_SERVER_LOCK (server);
499   result = priv->backlog;
500   GST_RTSP_SERVER_UNLOCK (server);
501
502   return result;
503 }
504
505 /**
506  * gst_rtsp_server_set_session_pool:
507  * @server: a #GstRTSPServer
508  * @pool: (transfer none) (nullable): a #GstRTSPSessionPool
509  *
510  * configure @pool to be used as the session pool of @server.
511  */
512 void
513 gst_rtsp_server_set_session_pool (GstRTSPServer * server,
514     GstRTSPSessionPool * pool)
515 {
516   GstRTSPServerPrivate *priv;
517   GstRTSPSessionPool *old;
518
519   g_return_if_fail (GST_IS_RTSP_SERVER (server));
520
521   priv = server->priv;
522
523   if (pool)
524     g_object_ref (pool);
525
526   GST_RTSP_SERVER_LOCK (server);
527   old = priv->session_pool;
528   priv->session_pool = pool;
529   GST_RTSP_SERVER_UNLOCK (server);
530
531   if (old)
532     g_object_unref (old);
533 }
534
535 /**
536  * gst_rtsp_server_get_session_pool:
537  * @server: a #GstRTSPServer
538  *
539  * Get the #GstRTSPSessionPool used as the session pool of @server.
540  *
541  * Returns: (transfer full) (nullable): the #GstRTSPSessionPool used for sessions. g_object_unref() after
542  * usage.
543  */
544 GstRTSPSessionPool *
545 gst_rtsp_server_get_session_pool (GstRTSPServer * server)
546 {
547   GstRTSPServerPrivate *priv;
548   GstRTSPSessionPool *result;
549
550   g_return_val_if_fail (GST_IS_RTSP_SERVER (server), NULL);
551
552   priv = server->priv;
553
554   GST_RTSP_SERVER_LOCK (server);
555   if ((result = priv->session_pool))
556     g_object_ref (result);
557   GST_RTSP_SERVER_UNLOCK (server);
558
559   return result;
560 }
561
562 /**
563  * gst_rtsp_server_set_mount_points:
564  * @server: a #GstRTSPServer
565  * @mounts: (transfer none) (nullable): a #GstRTSPMountPoints
566  *
567  * configure @mounts to be used as the mount points of @server.
568  */
569 void
570 gst_rtsp_server_set_mount_points (GstRTSPServer * server,
571     GstRTSPMountPoints * mounts)
572 {
573   GstRTSPServerPrivate *priv;
574   GstRTSPMountPoints *old;
575
576   g_return_if_fail (GST_IS_RTSP_SERVER (server));
577
578   priv = server->priv;
579
580   if (mounts)
581     g_object_ref (mounts);
582
583   GST_RTSP_SERVER_LOCK (server);
584   old = priv->mount_points;
585   priv->mount_points = mounts;
586   GST_RTSP_SERVER_UNLOCK (server);
587
588   if (old)
589     g_object_unref (old);
590 }
591
592
593 /**
594  * gst_rtsp_server_get_mount_points:
595  * @server: a #GstRTSPServer
596  *
597  * Get the #GstRTSPMountPoints used as the mount points of @server.
598  *
599  * Returns: (transfer full) (nullable): the #GstRTSPMountPoints of @server. g_object_unref() after
600  * usage.
601  */
602 GstRTSPMountPoints *
603 gst_rtsp_server_get_mount_points (GstRTSPServer * server)
604 {
605   GstRTSPServerPrivate *priv;
606   GstRTSPMountPoints *result;
607
608   g_return_val_if_fail (GST_IS_RTSP_SERVER (server), NULL);
609
610   priv = server->priv;
611
612   GST_RTSP_SERVER_LOCK (server);
613   if ((result = priv->mount_points))
614     g_object_ref (result);
615   GST_RTSP_SERVER_UNLOCK (server);
616
617   return result;
618 }
619
620 /**
621  * gst_rtsp_server_set_content_length_limit
622  * @server: a #GstRTSPServer
623  * Configure @server to use the specified Content-Length limit.
624  *
625  * Define an appropriate request size limit and reject requests exceeding the
626  * limit.
627  *
628  * Since: 1.18
629  */
630 void
631 gst_rtsp_server_set_content_length_limit (GstRTSPServer * server, guint limit)
632 {
633   GstRTSPServerPrivate *priv;
634
635   g_return_if_fail (GST_IS_RTSP_SERVER (server));
636
637   priv = server->priv;
638
639   GST_RTSP_SERVER_LOCK (server);
640   priv->content_length_limit = limit;
641   GST_RTSP_SERVER_UNLOCK (server);
642 }
643
644 /**
645  * gst_rtsp_server_get_content_length_limit:
646  * @server: a #GstRTSPServer
647  *
648  * Get the Content-Length limit of @server.
649  *
650  * Returns: the Content-Length limit.
651  *
652  * Since: 1.18
653  */
654 guint
655 gst_rtsp_server_get_content_length_limit (GstRTSPServer * server)
656 {
657   GstRTSPServerPrivate *priv;
658   guint result;
659
660   g_return_val_if_fail (GST_IS_RTSP_SERVER (server), G_MAXUINT);
661
662   priv = server->priv;
663
664   GST_RTSP_SERVER_LOCK (server);
665   result = priv->content_length_limit;
666   GST_RTSP_SERVER_UNLOCK (server);
667
668   return result;
669 }
670
671 /**
672  * gst_rtsp_server_set_auth:
673  * @server: a #GstRTSPServer
674  * @auth: (transfer none) (nullable): a #GstRTSPAuth
675  *
676  * configure @auth to be used as the authentication manager of @server.
677  */
678 void
679 gst_rtsp_server_set_auth (GstRTSPServer * server, GstRTSPAuth * auth)
680 {
681   GstRTSPServerPrivate *priv;
682   GstRTSPAuth *old;
683
684   g_return_if_fail (GST_IS_RTSP_SERVER (server));
685
686   priv = server->priv;
687
688   if (auth)
689     g_object_ref (auth);
690
691   GST_RTSP_SERVER_LOCK (server);
692   old = priv->auth;
693   priv->auth = auth;
694   GST_RTSP_SERVER_UNLOCK (server);
695
696   if (old)
697     g_object_unref (old);
698 }
699
700
701 /**
702  * gst_rtsp_server_get_auth:
703  * @server: a #GstRTSPServer
704  *
705  * Get the #GstRTSPAuth used as the authentication manager of @server.
706  *
707  * Returns: (transfer full) (nullable): the #GstRTSPAuth of @server. g_object_unref() after
708  * usage.
709  */
710 GstRTSPAuth *
711 gst_rtsp_server_get_auth (GstRTSPServer * server)
712 {
713   GstRTSPServerPrivate *priv;
714   GstRTSPAuth *result;
715
716   g_return_val_if_fail (GST_IS_RTSP_SERVER (server), NULL);
717
718   priv = server->priv;
719
720   GST_RTSP_SERVER_LOCK (server);
721   if ((result = priv->auth))
722     g_object_ref (result);
723   GST_RTSP_SERVER_UNLOCK (server);
724
725   return result;
726 }
727
728 /**
729  * gst_rtsp_server_set_thread_pool:
730  * @server: a #GstRTSPServer
731  * @pool: (transfer none) (nullable): a #GstRTSPThreadPool
732  *
733  * configure @pool to be used as the thread pool of @server.
734  */
735 void
736 gst_rtsp_server_set_thread_pool (GstRTSPServer * server,
737     GstRTSPThreadPool * pool)
738 {
739   GstRTSPServerPrivate *priv;
740   GstRTSPThreadPool *old;
741
742   g_return_if_fail (GST_IS_RTSP_SERVER (server));
743
744   priv = server->priv;
745
746   if (pool)
747     g_object_ref (pool);
748
749   GST_RTSP_SERVER_LOCK (server);
750   old = priv->thread_pool;
751   priv->thread_pool = pool;
752   GST_RTSP_SERVER_UNLOCK (server);
753
754   if (old)
755     g_object_unref (old);
756 }
757
758 /**
759  * gst_rtsp_server_get_thread_pool:
760  * @server: a #GstRTSPServer
761  *
762  * Get the #GstRTSPThreadPool used as the thread pool of @server.
763  *
764  * Returns: (transfer full) (nullable): the #GstRTSPThreadPool of @server. g_object_unref() after
765  * usage.
766  */
767 GstRTSPThreadPool *
768 gst_rtsp_server_get_thread_pool (GstRTSPServer * server)
769 {
770   GstRTSPServerPrivate *priv;
771   GstRTSPThreadPool *result;
772
773   g_return_val_if_fail (GST_IS_RTSP_SERVER (server), NULL);
774
775   priv = server->priv;
776
777   GST_RTSP_SERVER_LOCK (server);
778   if ((result = priv->thread_pool))
779     g_object_ref (result);
780   GST_RTSP_SERVER_UNLOCK (server);
781
782   return result;
783 }
784
785 static void
786 gst_rtsp_server_get_property (GObject * object, guint propid,
787     GValue * value, GParamSpec * pspec)
788 {
789   GstRTSPServer *server = GST_RTSP_SERVER (object);
790
791   switch (propid) {
792     case PROP_ADDRESS:
793       g_value_take_string (value, gst_rtsp_server_get_address (server));
794       break;
795     case PROP_SERVICE:
796       g_value_take_string (value, gst_rtsp_server_get_service (server));
797       break;
798     case PROP_BOUND_PORT:
799       g_value_set_int (value, gst_rtsp_server_get_bound_port (server));
800       break;
801     case PROP_BACKLOG:
802       g_value_set_int (value, gst_rtsp_server_get_backlog (server));
803       break;
804     case PROP_SESSION_POOL:
805       g_value_take_object (value, gst_rtsp_server_get_session_pool (server));
806       break;
807     case PROP_MOUNT_POINTS:
808       g_value_take_object (value, gst_rtsp_server_get_mount_points (server));
809       break;
810     case PROP_CONTENT_LENGTH_LIMIT:
811       g_value_set_uint (value,
812           gst_rtsp_server_get_content_length_limit (server));
813       break;
814     default:
815       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, propid, pspec);
816   }
817 }
818
819 static void
820 gst_rtsp_server_set_property (GObject * object, guint propid,
821     const GValue * value, GParamSpec * pspec)
822 {
823   GstRTSPServer *server = GST_RTSP_SERVER (object);
824
825   switch (propid) {
826     case PROP_ADDRESS:
827       gst_rtsp_server_set_address (server, g_value_get_string (value));
828       break;
829     case PROP_SERVICE:
830       gst_rtsp_server_set_service (server, g_value_get_string (value));
831       break;
832     case PROP_BACKLOG:
833       gst_rtsp_server_set_backlog (server, g_value_get_int (value));
834       break;
835     case PROP_SESSION_POOL:
836       gst_rtsp_server_set_session_pool (server, g_value_get_object (value));
837       break;
838     case PROP_MOUNT_POINTS:
839       gst_rtsp_server_set_mount_points (server, g_value_get_object (value));
840       break;
841     case PROP_CONTENT_LENGTH_LIMIT:
842       gst_rtsp_server_set_content_length_limit (server,
843           g_value_get_uint (value));
844       break;
845     default:
846       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, propid, pspec);
847   }
848 }
849
850 /**
851  * gst_rtsp_server_create_socket:
852  * @server: a #GstRTSPServer
853  * @cancellable: (allow-none): a #GCancellable
854  * @error: (out): a #GError
855  *
856  * Create a #GSocket for @server. The socket will listen on the
857  * configured service.
858  *
859  * Returns: (transfer full): the #GSocket for @server or %NULL when an error
860  * occurred.
861  */
862 GSocket *
863 gst_rtsp_server_create_socket (GstRTSPServer * server,
864     GCancellable * cancellable, GError ** error)
865 {
866   GstRTSPServerPrivate *priv;
867   GSocketConnectable *conn;
868   GSocketAddressEnumerator *enumerator;
869   GSocket *socket = NULL;
870 #ifdef USE_SOLINGER
871   struct linger linger;
872 #endif
873   GError *sock_error = NULL;
874   GError *bind_error = NULL;
875   guint16 port;
876
877   g_return_val_if_fail (GST_IS_RTSP_SERVER (server), NULL);
878
879   priv = server->priv;
880
881   GST_RTSP_SERVER_LOCK (server);
882   GST_DEBUG_OBJECT (server, "getting address info of %s/%s", priv->address,
883       priv->service);
884
885   /* resolve the server IP address */
886   port = atoi (priv->service);
887   if (port != 0 || !strcmp (priv->service, "0"))
888     conn = g_network_address_new (priv->address, port);
889   else
890     conn = g_network_service_new (priv->service, "tcp", priv->address);
891
892   enumerator = g_socket_connectable_enumerate (conn);
893   g_object_unref (conn);
894
895   /* create server socket, we loop through all the addresses until we manage to
896    * create a socket and bind. */
897   while (TRUE) {
898     GSocketAddress *sockaddr;
899
900     sockaddr =
901         g_socket_address_enumerator_next (enumerator, cancellable, error);
902     if (!sockaddr) {
903       if (!*error)
904         GST_DEBUG_OBJECT (server, "no more addresses %s",
905             *error ? (*error)->message : "");
906       else
907         GST_DEBUG_OBJECT (server, "failed to retrieve next address %s",
908             (*error)->message);
909       break;
910     }
911
912     /* only keep the first error */
913     socket = g_socket_new (g_socket_address_get_family (sockaddr),
914         G_SOCKET_TYPE_STREAM, G_SOCKET_PROTOCOL_TCP,
915         sock_error ? NULL : &sock_error);
916
917     if (socket == NULL) {
918       GST_DEBUG_OBJECT (server, "failed to make socket (%s), try next",
919           sock_error->message);
920       g_object_unref (sockaddr);
921       continue;
922     }
923
924     if (g_socket_bind (socket, sockaddr, TRUE, bind_error ? NULL : &bind_error)) {
925       /* ask what port the socket has been bound to */
926       if (port == 0 || !strcmp (priv->service, "0")) {
927         GError *addr_error = NULL;
928
929         g_object_unref (sockaddr);
930         sockaddr = g_socket_get_local_address (socket, &addr_error);
931
932         if (addr_error != NULL) {
933           GST_DEBUG_OBJECT (server,
934               "failed to get the local address of a bound socket %s",
935               addr_error->message);
936           g_clear_error (&addr_error);
937           break;
938         }
939         port =
940             g_inet_socket_address_get_port (G_INET_SOCKET_ADDRESS (sockaddr));
941
942         if (port != 0) {
943           g_free (priv->service);
944           priv->service = g_strdup_printf ("%d", port);
945         } else {
946           GST_DEBUG_OBJECT (server, "failed to get the port of a bound socket");
947         }
948       }
949       g_object_unref (sockaddr);
950       break;
951     }
952
953     GST_DEBUG_OBJECT (server, "failed to bind socket (%s), try next",
954         bind_error->message);
955     g_object_unref (sockaddr);
956     g_object_unref (socket);
957     socket = NULL;
958   }
959   g_object_unref (enumerator);
960
961   if (socket == NULL)
962     goto no_socket;
963
964   g_clear_error (&sock_error);
965   g_clear_error (&bind_error);
966
967   GST_DEBUG_OBJECT (server, "opened sending server socket");
968
969   /* keep connection alive; avoids SIGPIPE during write */
970   g_socket_set_keepalive (socket, TRUE);
971
972 #if 0
973 #ifdef USE_SOLINGER
974   /* make sure socket is reset 5 seconds after close. This ensure that we can
975    * reuse the socket quickly while still having a chance to send data to the
976    * client. */
977   linger.l_onoff = 1;
978   linger.l_linger = 5;
979   if (setsockopt (sockfd, SOL_SOCKET, SO_LINGER,
980           (void *) &linger, sizeof (linger)) < 0)
981     goto linger_failed;
982 #endif
983 #endif
984
985   /* set the server socket to nonblocking */
986   g_socket_set_blocking (socket, FALSE);
987
988   /* set listen backlog */
989   g_socket_set_listen_backlog (socket, priv->backlog);
990
991   if (!g_socket_listen (socket, error))
992     goto listen_failed;
993
994   GST_DEBUG_OBJECT (server, "listening on server socket %p with queue of %d",
995       socket, priv->backlog);
996
997   GST_RTSP_SERVER_UNLOCK (server);
998
999   return socket;
1000
1001   /* ERRORS */
1002 no_socket:
1003   {
1004     GST_ERROR_OBJECT (server, "failed to create socket");
1005     goto close_error;
1006   }
1007 #if 0
1008 #ifdef USE_SOLINGER
1009 linger_failed:
1010   {
1011     GST_ERROR_OBJECT (server, "failed to no linger socket: %s",
1012         g_strerror (errno));
1013     goto close_error;
1014   }
1015 #endif
1016 #endif
1017 listen_failed:
1018   {
1019     GST_ERROR_OBJECT (server, "failed to listen on socket: %s",
1020         (*error)->message);
1021     goto close_error;
1022   }
1023 close_error:
1024   {
1025     if (socket)
1026       g_object_unref (socket);
1027
1028     if (sock_error) {
1029       if (error == NULL)
1030         g_propagate_error (error, sock_error);
1031       else
1032         g_error_free (sock_error);
1033     }
1034     if (bind_error) {
1035       if ((error == NULL) || (*error == NULL))
1036         g_propagate_error (error, bind_error);
1037       else
1038         g_error_free (bind_error);
1039     }
1040     GST_RTSP_SERVER_UNLOCK (server);
1041     return NULL;
1042   }
1043 }
1044
1045 struct _ClientContext
1046 {
1047   GstRTSPServer *server;
1048   GstRTSPThread *thread;
1049   GstRTSPClient *client;
1050 };
1051
1052 static gboolean
1053 free_client_context (ClientContext * ctx)
1054 {
1055   GST_DEBUG ("free context %p", ctx);
1056
1057   GST_RTSP_SERVER_LOCK (ctx->server);
1058   if (ctx->thread)
1059     gst_rtsp_thread_stop (ctx->thread);
1060   GST_RTSP_SERVER_UNLOCK (ctx->server);
1061
1062   g_object_unref (ctx->client);
1063   g_object_unref (ctx->server);
1064   g_slice_free (ClientContext, ctx);
1065
1066   return G_SOURCE_REMOVE;
1067 }
1068
1069 static void
1070 unmanage_client (GstRTSPClient * client, ClientContext * ctx)
1071 {
1072   GstRTSPServer *server = ctx->server;
1073   GstRTSPServerPrivate *priv = server->priv;
1074
1075   GST_DEBUG_OBJECT (server, "unmanage client %p", client);
1076
1077   GST_RTSP_SERVER_LOCK (server);
1078   priv->clients = g_list_remove (priv->clients, ctx);
1079   priv->clients_cookie++;
1080   GST_RTSP_SERVER_UNLOCK (server);
1081
1082   if (ctx->thread) {
1083     GSource *src;
1084
1085     src = g_idle_source_new ();
1086     g_source_set_callback (src, (GSourceFunc) free_client_context, ctx, NULL);
1087     g_source_attach (src, ctx->thread->context);
1088     g_source_unref (src);
1089   } else {
1090     free_client_context (ctx);
1091   }
1092 }
1093
1094 /* add the client context to the active list of clients, takes ownership
1095  * of client */
1096 static void
1097 manage_client (GstRTSPServer * server, GstRTSPClient * client)
1098 {
1099   ClientContext *cctx;
1100   GstRTSPServerPrivate *priv = server->priv;
1101   GMainContext *mainctx = NULL;
1102   GstRTSPContext ctx = { NULL };
1103
1104   GST_DEBUG_OBJECT (server, "manage client %p", client);
1105
1106   g_signal_emit (server, gst_rtsp_server_signals[SIGNAL_CLIENT_CONNECTED], 0,
1107       client);
1108
1109   cctx = g_slice_new0 (ClientContext);
1110   cctx->server = g_object_ref (server);
1111   cctx->client = client;
1112
1113   GST_RTSP_SERVER_LOCK (server);
1114
1115   ctx.server = server;
1116   ctx.client = client;
1117
1118   cctx->thread = gst_rtsp_thread_pool_get_thread (priv->thread_pool,
1119       GST_RTSP_THREAD_TYPE_CLIENT, &ctx);
1120   if (cctx->thread)
1121     mainctx = cctx->thread->context;
1122   else {
1123     GSource *source;
1124     /* find the context to add the watch */
1125     if ((source = g_main_current_source ()))
1126       mainctx = g_source_get_context (source);
1127   }
1128
1129   g_signal_connect (client, "closed", (GCallback) unmanage_client, cctx);
1130   priv->clients = g_list_prepend (priv->clients, cctx);
1131   priv->clients_cookie++;
1132
1133   gst_rtsp_client_attach (client, mainctx);
1134
1135   GST_RTSP_SERVER_UNLOCK (server);
1136 }
1137
1138 static GstRTSPClient *
1139 default_create_client (GstRTSPServer * server)
1140 {
1141   GstRTSPClient *client;
1142   GstRTSPServerPrivate *priv = server->priv;
1143
1144   /* a new client connected, create a session to handle the client. */
1145   client = gst_rtsp_client_new ();
1146
1147   /* set the session pool that this client should use */
1148   GST_RTSP_SERVER_LOCK (server);
1149   gst_rtsp_client_set_session_pool (client, priv->session_pool);
1150   /* set the mount points that this client should use */
1151   gst_rtsp_client_set_mount_points (client, priv->mount_points);
1152   /* Set content-length limit */
1153   gst_rtsp_client_set_content_length_limit (GST_RTSP_CLIENT (client),
1154       priv->content_length_limit);
1155   /* set authentication manager */
1156   gst_rtsp_client_set_auth (client, priv->auth);
1157   /* set threadpool */
1158   gst_rtsp_client_set_thread_pool (client, priv->thread_pool);
1159   GST_RTSP_SERVER_UNLOCK (server);
1160
1161   return client;
1162 }
1163
1164 /**
1165  * gst_rtsp_server_transfer_connection:
1166  * @server: a #GstRTSPServer
1167  * @socket: (transfer full): a network socket
1168  * @ip: the IP address of the remote client
1169  * @port: the port used by the other end
1170  * @initial_buffer: (nullable): any initial data that was already read from the socket
1171  *
1172  * Take an existing network socket and use it for an RTSP connection. This
1173  * is used when transferring a socket from an HTTP server which should be used
1174  * as an RTSP over HTTP tunnel. The @initial_buffer contains any remaining data
1175  * that the HTTP server read from the socket while parsing the HTTP header.
1176  *
1177  * Returns: TRUE if all was ok, FALSE if an error occurred.
1178  */
1179 gboolean
1180 gst_rtsp_server_transfer_connection (GstRTSPServer * server, GSocket * socket,
1181     const gchar * ip, gint port, const gchar * initial_buffer)
1182 {
1183   GstRTSPClient *client = NULL;
1184   GstRTSPServerClass *klass;
1185   GstRTSPConnection *conn;
1186   GstRTSPResult res;
1187
1188   klass = GST_RTSP_SERVER_GET_CLASS (server);
1189
1190   if (klass->create_client)
1191     client = klass->create_client (server);
1192   if (client == NULL)
1193     goto client_failed;
1194
1195   GST_RTSP_CHECK (gst_rtsp_connection_create_from_socket (socket, ip, port,
1196           initial_buffer, &conn), no_connection);
1197   g_object_unref (socket);
1198
1199   /* set connection on the client now */
1200   gst_rtsp_client_set_connection (client, conn);
1201
1202   /* manage the client connection */
1203   manage_client (server, client);
1204
1205   return TRUE;
1206
1207   /* ERRORS */
1208 client_failed:
1209   {
1210     GST_ERROR_OBJECT (server, "failed to create a client");
1211     g_object_unref (socket);
1212     return FALSE;
1213   }
1214 no_connection:
1215   {
1216     gchar *str = gst_rtsp_strresult (res);
1217     GST_ERROR ("could not create connection from socket %p: %s", socket, str);
1218     g_free (str);
1219     g_object_unref (socket);
1220     g_object_unref (client);
1221     return FALSE;
1222   }
1223 }
1224
1225 /**
1226  * gst_rtsp_server_io_func:
1227  * @socket: a #GSocket
1228  * @condition: the condition on @source
1229  * @server: (transfer none): a #GstRTSPServer
1230  *
1231  * A default #GSocketSourceFunc that creates a new #GstRTSPClient to accept and handle a
1232  * new connection on @socket or @server.
1233  *
1234  * Returns: TRUE if the source could be connected, FALSE if an error occurred.
1235  */
1236 gboolean
1237 gst_rtsp_server_io_func (GSocket * socket, GIOCondition condition,
1238     GstRTSPServer * server)
1239 {
1240   GstRTSPServerPrivate *priv = server->priv;
1241   GstRTSPClient *client = NULL;
1242   GstRTSPServerClass *klass;
1243   GstRTSPResult res;
1244   GstRTSPConnection *conn = NULL;
1245   GstRTSPContext ctx = { NULL };
1246
1247   if (condition & G_IO_IN) {
1248     /* a new client connected. */
1249     GST_RTSP_CHECK (gst_rtsp_connection_accept (socket, &conn, NULL),
1250         accept_failed);
1251
1252     ctx.server = server;
1253     ctx.conn = conn;
1254     ctx.auth = priv->auth;
1255     gst_rtsp_context_push_current (&ctx);
1256
1257     if (!gst_rtsp_auth_check (GST_RTSP_AUTH_CHECK_CONNECT))
1258       goto connection_refused;
1259
1260     klass = GST_RTSP_SERVER_GET_CLASS (server);
1261     /* a new client connected, create a client object to handle the client. */
1262     if (klass->create_client)
1263       client = klass->create_client (server);
1264     if (client == NULL)
1265       goto client_failed;
1266
1267     /* set connection on the client now */
1268     gst_rtsp_client_set_connection (client, conn);
1269
1270     /* manage the client connection */
1271     manage_client (server, client);
1272   } else {
1273     GST_WARNING_OBJECT (server, "received unknown event %08x", condition);
1274     goto exit_no_ctx;
1275   }
1276 exit:
1277   gst_rtsp_context_pop_current (&ctx);
1278 exit_no_ctx:
1279
1280   return G_SOURCE_CONTINUE;
1281
1282   /* ERRORS */
1283 accept_failed:
1284   {
1285     gchar *str = gst_rtsp_strresult (res);
1286     GST_ERROR_OBJECT (server, "Could not accept client on socket %p: %s",
1287         socket, str);
1288     g_free (str);
1289     /* We haven't pushed the context yet, so just return */
1290     goto exit_no_ctx;
1291   }
1292 connection_refused:
1293   {
1294     GST_ERROR_OBJECT (server, "connection refused");
1295     gst_rtsp_connection_free (conn);
1296     goto exit;
1297   }
1298 client_failed:
1299   {
1300     GST_ERROR_OBJECT (server, "failed to create a client");
1301     gst_rtsp_connection_free (conn);
1302     goto exit;
1303   }
1304 }
1305
1306 static void
1307 watch_destroyed (GstRTSPServer * server)
1308 {
1309   GstRTSPServerPrivate *priv = server->priv;
1310
1311   GST_DEBUG_OBJECT (server, "source destroyed");
1312
1313   g_object_unref (priv->socket);
1314   priv->socket = NULL;
1315   g_object_unref (server);
1316 }
1317
1318 /**
1319  * gst_rtsp_server_create_source:
1320  * @server: a #GstRTSPServer
1321  * @cancellable: (allow-none): a #GCancellable or %NULL.
1322  * @error: (out): a #GError
1323  *
1324  * Create a #GSource for @server. The new source will have a default
1325  * #GSocketSourceFunc of gst_rtsp_server_io_func().
1326  *
1327  * @cancellable if not %NULL can be used to cancel the source, which will cause
1328  * the source to trigger, reporting the current condition (which is likely 0
1329  * unless cancellation happened at the same time as a condition change). You can
1330  * check for this in the callback using g_cancellable_is_cancelled().
1331  *
1332  * This takes a reference on @server until @source is destroyed.
1333  *
1334  * Returns: (transfer full): the #GSource for @server or %NULL when an error
1335  * occurred. Free with g_source_unref ()
1336  */
1337 GSource *
1338 gst_rtsp_server_create_source (GstRTSPServer * server,
1339     GCancellable * cancellable, GError ** error)
1340 {
1341   GstRTSPServerPrivate *priv;
1342   GSocket *socket, *old;
1343   GSource *source;
1344
1345   g_return_val_if_fail (GST_IS_RTSP_SERVER (server), NULL);
1346
1347   priv = server->priv;
1348
1349   socket = gst_rtsp_server_create_socket (server, NULL, error);
1350   if (socket == NULL)
1351     goto no_socket;
1352
1353   GST_RTSP_SERVER_LOCK (server);
1354   old = priv->socket;
1355   priv->socket = g_object_ref (socket);
1356   GST_RTSP_SERVER_UNLOCK (server);
1357
1358   if (old)
1359     g_object_unref (old);
1360
1361   /* create a watch for reads (new connections) and possible errors */
1362   source = g_socket_create_source (socket, G_IO_IN |
1363       G_IO_ERR | G_IO_HUP | G_IO_NVAL, cancellable);
1364   g_object_unref (socket);
1365
1366   /* configure the callback */
1367   g_source_set_callback (source,
1368       (GSourceFunc) gst_rtsp_server_io_func, g_object_ref (server),
1369       (GDestroyNotify) watch_destroyed);
1370
1371   return source;
1372
1373 no_socket:
1374   {
1375     GST_ERROR_OBJECT (server, "failed to create socket");
1376     return NULL;
1377   }
1378 }
1379
1380 /**
1381  * gst_rtsp_server_attach:
1382  * @server: a #GstRTSPServer
1383  * @context: (allow-none): a #GMainContext
1384  *
1385  * Attaches @server to @context. When the mainloop for @context is run, the
1386  * server will be dispatched. When @context is %NULL, the default context will be
1387  * used).
1388  *
1389  * This function should be called when the server properties and urls are fully
1390  * configured and the server is ready to start.
1391  *
1392  * This takes a reference on @server until the source is destroyed. Note that
1393  * if @context is not the default main context as returned by
1394  * g_main_context_default() (or %NULL), g_source_remove() cannot be used to
1395  * destroy the source. In that case it is recommended to use
1396  * gst_rtsp_server_create_source() and attach it to @context manually.
1397  *
1398  * Returns: the ID (greater than 0) for the source within the GMainContext.
1399  */
1400 guint
1401 gst_rtsp_server_attach (GstRTSPServer * server, GMainContext * context)
1402 {
1403   guint res;
1404   GSource *source;
1405   GError *error = NULL;
1406
1407   g_return_val_if_fail (GST_IS_RTSP_SERVER (server), 0);
1408
1409   source = gst_rtsp_server_create_source (server, NULL, &error);
1410   if (source == NULL)
1411     goto no_source;
1412
1413   res = g_source_attach (source, context);
1414   g_source_unref (source);
1415
1416   return res;
1417
1418   /* ERRORS */
1419 no_source:
1420   {
1421     GST_ERROR_OBJECT (server, "failed to create watch: %s", error->message);
1422     g_error_free (error);
1423     return 0;
1424   }
1425 }
1426
1427 /**
1428  * gst_rtsp_server_client_filter:
1429  * @server: a #GstRTSPServer
1430  * @func: (scope call) (allow-none): a callback
1431  * @user_data: user data passed to @func
1432  *
1433  * Call @func for each client managed by @server. The result value of @func
1434  * determines what happens to the client. @func will be called with @server
1435  * locked so no further actions on @server can be performed from @func.
1436  *
1437  * If @func returns #GST_RTSP_FILTER_REMOVE, the client will be removed from
1438  * @server.
1439  *
1440  * If @func returns #GST_RTSP_FILTER_KEEP, the client will remain in @server.
1441  *
1442  * If @func returns #GST_RTSP_FILTER_REF, the client will remain in @server but
1443  * will also be added with an additional ref to the result #GList of this
1444  * function..
1445  *
1446  * When @func is %NULL, #GST_RTSP_FILTER_REF will be assumed for each client.
1447  *
1448  * Returns: (element-type GstRTSPClient) (transfer full): a #GList with all
1449  * clients for which @func returned #GST_RTSP_FILTER_REF. After usage, each
1450  * element in the #GList should be unreffed before the list is freed.
1451  */
1452 GList *
1453 gst_rtsp_server_client_filter (GstRTSPServer * server,
1454     GstRTSPServerClientFilterFunc func, gpointer user_data)
1455 {
1456   GstRTSPServerPrivate *priv;
1457   GList *result, *walk, *next;
1458   GHashTable *visited;
1459   guint cookie;
1460
1461   g_return_val_if_fail (GST_IS_RTSP_SERVER (server), NULL);
1462
1463   priv = server->priv;
1464
1465   result = NULL;
1466   if (func)
1467     visited = g_hash_table_new_full (NULL, NULL, g_object_unref, NULL);
1468
1469   GST_RTSP_SERVER_LOCK (server);
1470 restart:
1471   cookie = priv->clients_cookie;
1472   for (walk = priv->clients; walk; walk = next) {
1473     ClientContext *cctx = walk->data;
1474     GstRTSPClient *client = cctx->client;
1475     GstRTSPFilterResult res;
1476     gboolean changed;
1477
1478     next = g_list_next (walk);
1479
1480     if (func) {
1481       /* only visit each media once */
1482       if (g_hash_table_contains (visited, client))
1483         continue;
1484
1485       g_hash_table_add (visited, g_object_ref (client));
1486       GST_RTSP_SERVER_UNLOCK (server);
1487
1488       res = func (server, client, user_data);
1489
1490       GST_RTSP_SERVER_LOCK (server);
1491     } else
1492       res = GST_RTSP_FILTER_REF;
1493
1494     changed = (cookie != priv->clients_cookie);
1495
1496     switch (res) {
1497       case GST_RTSP_FILTER_REMOVE:
1498         GST_RTSP_SERVER_UNLOCK (server);
1499
1500         gst_rtsp_client_close (client);
1501
1502         GST_RTSP_SERVER_LOCK (server);
1503         changed |= (cookie != priv->clients_cookie);
1504         break;
1505       case GST_RTSP_FILTER_REF:
1506         result = g_list_prepend (result, g_object_ref (client));
1507         break;
1508       case GST_RTSP_FILTER_KEEP:
1509       default:
1510         break;
1511     }
1512     if (changed)
1513       goto restart;
1514   }
1515   GST_RTSP_SERVER_UNLOCK (server);
1516
1517   if (func)
1518     g_hash_table_unref (visited);
1519
1520   return result;
1521 }