spec: Remove kdbus-extension packages for _with_da_profile
[platform/upstream/glib.git] / gio / gsocketservice.c
1 /* GIO - GLib Input, Output and Streaming Library
2  *
3  * Copyright © 2009 Codethink Limited
4  * Copyright © 2009 Red Hat, Inc
5  *
6  * SPDX-License-Identifier: LGPL-2.1-or-later
7  *
8  * This library is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU Lesser General Public
10  * License as published by the Free Software Foundation; either
11  * version 2.1 of the License, or (at your option) any later version.
12  *
13  * This library is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16  * Lesser General Public License for more details.
17  *
18  * You should have received a copy of the GNU Lesser General
19  * Public License along with this library; if not, see <http://www.gnu.org/licenses/>.
20  *
21  * Authors: Ryan Lortie <desrt@desrt.ca>
22  *          Alexander Larsson <alexl@redhat.com>
23  */
24
25 /**
26  * GSocketService:
27  *
28  * A `GSocketService` is an object that represents a service that
29  * is provided to the network or over local sockets.  When a new
30  * connection is made to the service the [signal@Gio.SocketService::incoming]
31  * signal is emitted.
32  *
33  * A `GSocketService` is a subclass of [class@Gio.SocketListener] and you need
34  * to add the addresses you want to accept connections on with the
35  * [class@Gio.SocketListener] APIs.
36  *
37  * There are two options for implementing a network service based on
38  * `GSocketService`. The first is to create the service using
39  * [ctor@Gio.SocketService.new] and to connect to the
40  * [signal@Gio.SocketService::incoming] signal. The second is to subclass
41  * `GSocketService` and override the default signal handler implementation.
42  *
43  * In either case, the handler must immediately return, or else it
44  * will block additional incoming connections from being serviced.
45  * If you are interested in writing connection handlers that contain
46  * blocking code then see [class@Gio.ThreadedSocketService].
47  *
48  * The socket service runs on the main loop of the 
49  * thread-default context (see
50  * [method@GLib.MainContext.push_thread_default]) of the thread it is
51  * created in, and is not threadsafe in general. However, the calls to start and
52  * stop the service are thread-safe so these can be used from threads that
53  * handle incoming clients.
54  *
55  * Since: 2.22
56  */
57
58 #include "config.h"
59 #include "gsocketservice.h"
60
61 #include <gio/gio.h>
62 #include "gsocketlistener.h"
63 #include "gsocketconnection.h"
64 #include "glibintl.h"
65 #include "gmarshal-internal.h"
66
67 struct _GSocketServicePrivate
68 {
69   GCancellable *cancellable;
70   guint active : 1;
71   guint outstanding_accept : 1;
72 };
73
74 static guint g_socket_service_incoming_signal;
75
76 G_LOCK_DEFINE_STATIC(active);
77
78 G_DEFINE_TYPE_WITH_PRIVATE (GSocketService, g_socket_service, G_TYPE_SOCKET_LISTENER)
79
80 enum
81 {
82   PROP_0,
83   PROP_ACTIVE
84 };
85
86 static void g_socket_service_ready (GObject      *object,
87                                     GAsyncResult *result,
88                                     gpointer      user_data);
89
90 static gboolean
91 g_socket_service_real_incoming (GSocketService    *service,
92                                 GSocketConnection *connection,
93                                 GObject           *source_object)
94 {
95   return FALSE;
96 }
97
98 static void
99 g_socket_service_init (GSocketService *service)
100 {
101   service->priv = g_socket_service_get_instance_private (service);
102   service->priv->cancellable = g_cancellable_new ();
103   service->priv->active = TRUE;
104 }
105
106 static void
107 g_socket_service_finalize (GObject *object)
108 {
109   GSocketService *service = G_SOCKET_SERVICE (object);
110
111   g_object_unref (service->priv->cancellable);
112
113   G_OBJECT_CLASS (g_socket_service_parent_class)
114     ->finalize (object);
115 }
116
117 static void
118 do_accept (GSocketService  *service)
119 {
120   g_socket_listener_accept_async (G_SOCKET_LISTENER (service),
121                                   service->priv->cancellable,
122                                   g_socket_service_ready, NULL);
123   service->priv->outstanding_accept = TRUE;
124 }
125
126 static gboolean
127 get_active (GSocketService *service)
128 {
129   gboolean active;
130
131   G_LOCK (active);
132   active = service->priv->active;
133   G_UNLOCK (active);
134
135   return active;
136 }
137
138 static void
139 set_active (GSocketService *service, gboolean active)
140 {
141   gboolean notify = FALSE;
142
143   active = !!active;
144
145   G_LOCK (active);
146
147   if (active != service->priv->active)
148     {
149       service->priv->active = active;
150       notify = TRUE;
151
152       if (active)
153         {
154           if (service->priv->outstanding_accept)
155             g_cancellable_cancel (service->priv->cancellable);
156           else
157             do_accept (service);
158         }
159       else
160         {
161           if (service->priv->outstanding_accept)
162             g_cancellable_cancel (service->priv->cancellable);
163         }
164     }
165
166   G_UNLOCK (active);
167
168   if (notify)
169     g_object_notify (G_OBJECT (service), "active");
170 }
171
172 static void
173 g_socket_service_get_property (GObject    *object,
174                                guint       prop_id,
175                                GValue     *value,
176                                GParamSpec *pspec)
177 {
178   GSocketService *service = G_SOCKET_SERVICE (object);
179
180   switch (prop_id)
181     {
182     case PROP_ACTIVE:
183       g_value_set_boolean (value, get_active (service));
184       break;
185     default:
186       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
187       break;
188     }
189 }
190
191 static void
192 g_socket_service_set_property (GObject      *object,
193                                guint         prop_id,
194                                const GValue *value,
195                                GParamSpec   *pspec)
196 {
197   GSocketService *service = G_SOCKET_SERVICE (object);
198
199   switch (prop_id)
200     {
201     case PROP_ACTIVE:
202       set_active (service, g_value_get_boolean (value));
203       break;
204     default:
205       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
206       break;
207     }
208 }
209
210 static void
211 g_socket_service_changed (GSocketListener *listener)
212 {
213   GSocketService  *service = G_SOCKET_SERVICE (listener);
214
215   G_LOCK (active);
216
217   if (service->priv->active)
218     {
219       if (service->priv->outstanding_accept)
220         g_cancellable_cancel (service->priv->cancellable);
221       else
222         do_accept (service);
223     }
224
225   G_UNLOCK (active);
226 }
227
228 /**
229  * g_socket_service_is_active:
230  * @service: a #GSocketService
231  *
232  * Check whether the service is active or not. An active
233  * service will accept new clients that connect, while
234  * a non-active service will let connecting clients queue
235  * up until the service is started.
236  *
237  * Returns: %TRUE if the service is active, %FALSE otherwise
238  *
239  * Since: 2.22
240  */
241 gboolean
242 g_socket_service_is_active (GSocketService *service)
243 {
244   g_return_val_if_fail (G_IS_SOCKET_SERVICE (service), FALSE);
245
246   return get_active (service);
247 }
248
249 /**
250  * g_socket_service_start:
251  * @service: a #GSocketService
252  *
253  * Restarts the service, i.e. start accepting connections
254  * from the added sockets when the mainloop runs. This only needs
255  * to be called after the service has been stopped from
256  * g_socket_service_stop().
257  *
258  * This call is thread-safe, so it may be called from a thread
259  * handling an incoming client request.
260  *
261  * Since: 2.22
262  */
263 void
264 g_socket_service_start (GSocketService *service)
265 {
266   g_return_if_fail (G_IS_SOCKET_SERVICE (service));
267
268   set_active (service, TRUE);
269 }
270
271 /**
272  * g_socket_service_stop:
273  * @service: a #GSocketService
274  *
275  * Stops the service, i.e. stops accepting connections
276  * from the added sockets when the mainloop runs.
277  *
278  * This call is thread-safe, so it may be called from a thread
279  * handling an incoming client request.
280  *
281  * Note that this only stops accepting new connections; it does not
282  * close the listening sockets, and you can call
283  * g_socket_service_start() again later to begin listening again. To
284  * close the listening sockets, call g_socket_listener_close(). (This
285  * will happen automatically when the #GSocketService is finalized.)
286  *
287  * This must be called before calling g_socket_listener_close() as
288  * the socket service will start accepting connections immediately
289  * when a new socket is added.
290  *
291  * Since: 2.22
292  */
293 void
294 g_socket_service_stop (GSocketService *service)
295 {
296   g_return_if_fail (G_IS_SOCKET_SERVICE (service));
297
298   set_active (service, FALSE);
299 }
300
301 static gboolean
302 g_socket_service_incoming (GSocketService    *service,
303                            GSocketConnection *connection,
304                            GObject           *source_object)
305 {
306   gboolean result;
307
308   g_signal_emit (service, g_socket_service_incoming_signal,
309                  0, connection, source_object, &result);
310   return result;
311 }
312
313 static void
314 g_socket_service_class_init (GSocketServiceClass *class)
315 {
316   GObjectClass *gobject_class = G_OBJECT_CLASS (class);
317   GSocketListenerClass *listener_class = G_SOCKET_LISTENER_CLASS (class);
318
319   gobject_class->finalize = g_socket_service_finalize;
320   gobject_class->set_property = g_socket_service_set_property;
321   gobject_class->get_property = g_socket_service_get_property;
322   listener_class->changed = g_socket_service_changed;
323   class->incoming = g_socket_service_real_incoming;
324
325   /**
326    * GSocketService::incoming:
327    * @service: the #GSocketService
328    * @connection: a new #GSocketConnection object
329    * @source_object: (nullable): the source_object passed to
330    *     g_socket_listener_add_address()
331    *
332    * The ::incoming signal is emitted when a new incoming connection
333    * to @service needs to be handled. The handler must initiate the
334    * handling of @connection, but may not block; in essence,
335    * asynchronous operations must be used.
336    *
337    * @connection will be unreffed once the signal handler returns,
338    * so you need to ref it yourself if you are planning to use it.
339    *
340    * Returns: %TRUE to stop other handlers from being called
341    *
342    * Since: 2.22
343    */
344   g_socket_service_incoming_signal =
345     g_signal_new (I_("incoming"), G_TYPE_FROM_CLASS (class), G_SIGNAL_RUN_LAST,
346                   G_STRUCT_OFFSET (GSocketServiceClass, incoming),
347                   g_signal_accumulator_true_handled, NULL,
348                   _g_cclosure_marshal_BOOLEAN__OBJECT_OBJECT,
349                   G_TYPE_BOOLEAN,
350                   2, G_TYPE_SOCKET_CONNECTION, G_TYPE_OBJECT);
351   g_signal_set_va_marshaller (g_socket_service_incoming_signal,
352                               G_TYPE_FROM_CLASS (class),
353                               _g_cclosure_marshal_BOOLEAN__OBJECT_OBJECTv);
354
355   /**
356    * GSocketService:active:
357    *
358    * Whether the service is currently accepting connections.
359    *
360    * Since: 2.46
361    */
362   g_object_class_install_property (gobject_class, PROP_ACTIVE,
363                                    g_param_spec_boolean ("active", NULL, NULL,
364                                                          TRUE,
365                                                          G_PARAM_CONSTRUCT | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
366 }
367
368 static void
369 g_socket_service_ready (GObject      *object,
370                         GAsyncResult *result,
371                         gpointer      user_data)
372 {
373   GSocketListener *listener = G_SOCKET_LISTENER (object);
374   GSocketService *service = G_SOCKET_SERVICE (object);
375   GSocketConnection *connection;
376   GObject *source_object;
377   GError *error = NULL;
378
379   connection = g_socket_listener_accept_finish (listener, result, &source_object, &error);
380   if (error)
381     {
382       if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
383         g_warning ("fail: %s", error->message);
384       g_error_free (error);
385     }
386   else
387     {
388       g_socket_service_incoming (service, connection, source_object);
389       g_object_unref (connection);
390     }
391
392   G_LOCK (active);
393
394   g_cancellable_reset (service->priv->cancellable);
395
396   /* requeue */
397   service->priv->outstanding_accept = FALSE;
398   if (service->priv->active)
399     do_accept (service);
400
401   G_UNLOCK (active);
402 }
403
404 /**
405  * g_socket_service_new:
406  *
407  * Creates a new #GSocketService with no sockets to listen for.
408  * New listeners can be added with e.g. g_socket_listener_add_address()
409  * or g_socket_listener_add_inet_port().
410  *
411  * New services are created active, there is no need to call
412  * g_socket_service_start(), unless g_socket_service_stop() has been
413  * called before.
414  *
415  * Returns: a new #GSocketService.
416  *
417  * Since: 2.22
418  */
419 GSocketService *
420 g_socket_service_new (void)
421 {
422   return g_object_new (G_TYPE_SOCKET_SERVICE, NULL);
423 }