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