Branch data Line data Source code
1 : : /* GIO - GLib Input, Output and Streaming Library
2 : : *
3 : : * Copyright © 2008 Christian Kellner, Samuel Cormier-Iijima
4 : : * Copyright © 2009 codethink
5 : : * Copyright © 2009 Red Hat, Inc
6 : : *
7 : : * SPDX-License-Identifier: LGPL-2.1-or-later
8 : : *
9 : : * This library is free software; you can redistribute it and/or
10 : : * modify it under the terms of the GNU Lesser General Public
11 : : * License as published by the Free Software Foundation; either
12 : : * version 2.1 of the License, or (at your option) any later version.
13 : : *
14 : : * This library is distributed in the hope that it will be useful,
15 : : * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 : : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 : : * Lesser General Public License for more details.
18 : : *
19 : : * You should have received a copy of the GNU Lesser General
20 : : * Public License along with this library; if not, see <http://www.gnu.org/licenses/>.
21 : : *
22 : : * Authors: Christian Kellner <gicmo@gnome.org>
23 : : * Samuel Cormier-Iijima <sciyoshi@gmail.com>
24 : : * Ryan Lortie <desrt@desrt.ca>
25 : : * Alexander Larsson <alexl@redhat.com>
26 : : */
27 : :
28 : : #include "config.h"
29 : : #include "gsocketlistener.h"
30 : :
31 : : #include <gio/gioenumtypes.h>
32 : : #include <gio/gtask.h>
33 : : #include <gio/gcancellable.h>
34 : : #include <gio/gsocketaddress.h>
35 : : #include <gio/ginetaddress.h>
36 : : #include <gio/gioerror.h>
37 : : #include <gio/gsocket.h>
38 : : #include <gio/gsocketconnection.h>
39 : : #include <gio/ginetsocketaddress.h>
40 : : #include "glibintl.h"
41 : : #include "gmarshal-internal.h"
42 : :
43 : :
44 : : /**
45 : : * GSocketListener:
46 : : *
47 : : * A `GSocketListener` is an object that keeps track of a set
48 : : * of server sockets and helps you accept sockets from any of the
49 : : * socket, either sync or async.
50 : : *
51 : : * Add addresses and ports to listen on using
52 : : * [method@Gio.SocketListener.add_address] and
53 : : * [method@Gio.SocketListener.add_inet_port]. These will be listened on until
54 : : * [method@Gio.SocketListener.close] is called. Dropping your final reference to
55 : : * the `GSocketListener` will not cause [method@Gio.SocketListener.close] to be
56 : : * called implicitly, as some references to the `GSocketListener` may be held
57 : : * internally.
58 : : *
59 : : * If you want to implement a network server, also look at
60 : : * [class@Gio.SocketService] and [class@Gio.ThreadedSocketService] which are
61 : : * subclasses of `GSocketListener` that make this even easier.
62 : : *
63 : : * Since: 2.22
64 : : */
65 : :
66 : : enum
67 : : {
68 : : PROP_0,
69 : : PROP_LISTEN_BACKLOG
70 : : };
71 : :
72 : : enum
73 : : {
74 : : EVENT,
75 : : LAST_SIGNAL
76 : : };
77 : :
78 : : static guint signals[LAST_SIGNAL] = { 0 };
79 : :
80 : : static GQuark source_quark = 0;
81 : :
82 : : struct _GSocketListenerPrivate
83 : : {
84 : : GPtrArray *sockets;
85 : : GMainContext *main_context;
86 : : int listen_backlog;
87 : : guint closed : 1;
88 : : };
89 : :
90 : 931 : G_DEFINE_TYPE_WITH_PRIVATE (GSocketListener, g_socket_listener, G_TYPE_OBJECT)
91 : :
92 : : static void
93 : 24 : g_socket_listener_finalize (GObject *object)
94 : : {
95 : 24 : GSocketListener *listener = G_SOCKET_LISTENER (object);
96 : :
97 : 24 : if (listener->priv->main_context)
98 : 0 : g_main_context_unref (listener->priv->main_context);
99 : :
100 : : /* Do not explicitly close the sockets. Instead, let them close themselves if
101 : : * their final reference is dropped, but keep them open if a reference is
102 : : * held externally to the GSocketListener (which is possible if
103 : : * g_socket_listener_add_socket() was used).
104 : : */
105 : 24 : g_ptr_array_free (listener->priv->sockets, TRUE);
106 : :
107 : 24 : G_OBJECT_CLASS (g_socket_listener_parent_class)
108 : 24 : ->finalize (object);
109 : 24 : }
110 : :
111 : : static void
112 : 1 : g_socket_listener_get_property (GObject *object,
113 : : guint prop_id,
114 : : GValue *value,
115 : : GParamSpec *pspec)
116 : : {
117 : 1 : GSocketListener *listener = G_SOCKET_LISTENER (object);
118 : :
119 : 1 : switch (prop_id)
120 : : {
121 : 1 : case PROP_LISTEN_BACKLOG:
122 : 1 : g_value_set_int (value, listener->priv->listen_backlog);
123 : 1 : break;
124 : :
125 : 0 : default:
126 : 0 : G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
127 : : }
128 : 1 : }
129 : :
130 : : static void
131 : 38 : g_socket_listener_set_property (GObject *object,
132 : : guint prop_id,
133 : : const GValue *value,
134 : : GParamSpec *pspec)
135 : : {
136 : 38 : GSocketListener *listener = G_SOCKET_LISTENER (object);
137 : :
138 : 38 : switch (prop_id)
139 : : {
140 : 38 : case PROP_LISTEN_BACKLOG:
141 : 38 : g_socket_listener_set_backlog (listener, g_value_get_int (value));
142 : 38 : break;
143 : :
144 : 0 : default:
145 : 0 : G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
146 : : }
147 : 38 : }
148 : :
149 : : static void
150 : 12 : g_socket_listener_class_init (GSocketListenerClass *klass)
151 : : {
152 : 12 : GObjectClass *gobject_class G_GNUC_UNUSED = G_OBJECT_CLASS (klass);
153 : :
154 : 12 : gobject_class->finalize = g_socket_listener_finalize;
155 : 12 : gobject_class->set_property = g_socket_listener_set_property;
156 : 12 : gobject_class->get_property = g_socket_listener_get_property;
157 : :
158 : : /**
159 : : * GSocketListener:listen-backlog:
160 : : *
161 : : * The number of outstanding connections in the listen queue.
162 : : *
163 : : * Since: 2.22
164 : : */
165 : 12 : g_object_class_install_property (gobject_class, PROP_LISTEN_BACKLOG,
166 : : g_param_spec_int ("listen-backlog", NULL, NULL,
167 : : 0,
168 : : 2000,
169 : : 10,
170 : : G_PARAM_CONSTRUCT | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
171 : :
172 : : /**
173 : : * GSocketListener::event:
174 : : * @listener: the #GSocketListener
175 : : * @event: the event that is occurring
176 : : * @socket: the #GSocket the event is occurring on
177 : : *
178 : : * Emitted when @listener's activity on @socket changes state.
179 : : * Note that when @listener is used to listen on both IPv4 and
180 : : * IPv6, a separate set of signals will be emitted for each, and
181 : : * the order they happen in is undefined.
182 : : *
183 : : * Since: 2.46
184 : : */
185 : 12 : signals[EVENT] =
186 : 12 : g_signal_new (I_("event"),
187 : : G_TYPE_FROM_CLASS (gobject_class),
188 : : G_SIGNAL_RUN_LAST,
189 : : G_STRUCT_OFFSET (GSocketListenerClass, event),
190 : : NULL, NULL,
191 : : _g_cclosure_marshal_VOID__ENUM_OBJECT,
192 : : G_TYPE_NONE, 2,
193 : : G_TYPE_SOCKET_LISTENER_EVENT,
194 : : G_TYPE_SOCKET);
195 : 12 : g_signal_set_va_marshaller (signals[EVENT],
196 : : G_TYPE_FROM_CLASS (gobject_class),
197 : : _g_cclosure_marshal_VOID__ENUM_OBJECTv);
198 : :
199 : 12 : source_quark = g_quark_from_static_string ("g-socket-listener-source");
200 : 12 : }
201 : :
202 : : static void
203 : 38 : g_socket_listener_init (GSocketListener *listener)
204 : : {
205 : 38 : listener->priv = g_socket_listener_get_instance_private (listener);
206 : 76 : listener->priv->sockets =
207 : 38 : g_ptr_array_new_with_free_func ((GDestroyNotify) g_object_unref);
208 : 38 : listener->priv->listen_backlog = 10;
209 : 38 : }
210 : :
211 : : /**
212 : : * g_socket_listener_new:
213 : : *
214 : : * Creates a new #GSocketListener with no sockets to listen for.
215 : : * New listeners can be added with e.g. g_socket_listener_add_address()
216 : : * or g_socket_listener_add_inet_port().
217 : : *
218 : : * Returns: a new #GSocketListener.
219 : : *
220 : : * Since: 2.22
221 : : */
222 : : GSocketListener *
223 : 3 : g_socket_listener_new (void)
224 : : {
225 : 3 : return g_object_new (G_TYPE_SOCKET_LISTENER, NULL);
226 : : }
227 : :
228 : : static gboolean
229 : 323 : check_listener (GSocketListener *listener,
230 : : GError **error)
231 : : {
232 : 323 : if (listener->priv->closed)
233 : : {
234 : 0 : g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_CLOSED,
235 : : _("Listener is already closed"));
236 : 0 : return FALSE;
237 : : }
238 : :
239 : 323 : return TRUE;
240 : : }
241 : :
242 : : /**
243 : : * g_socket_listener_add_socket:
244 : : * @listener: a #GSocketListener
245 : : * @socket: a listening #GSocket
246 : : * @source_object: (nullable): Optional #GObject identifying this source
247 : : * @error: #GError for error reporting, or %NULL to ignore.
248 : : *
249 : : * Adds @socket to the set of sockets that we try to accept
250 : : * new clients from. The socket must be bound to a local
251 : : * address and listened to.
252 : : *
253 : : * @source_object will be passed out in the various calls
254 : : * to accept to identify this particular source, which is
255 : : * useful if you're listening on multiple addresses and do
256 : : * different things depending on what address is connected to.
257 : : *
258 : : * The @socket will not be automatically closed when the @listener is finalized
259 : : * unless the listener held the final reference to the socket. Before GLib 2.42,
260 : : * the @socket was automatically closed on finalization of the @listener, even
261 : : * if references to it were held elsewhere.
262 : : *
263 : : * Returns: %TRUE on success, %FALSE on error.
264 : : *
265 : : * Since: 2.22
266 : : */
267 : : gboolean
268 : 32 : g_socket_listener_add_socket (GSocketListener *listener,
269 : : GSocket *socket,
270 : : GObject *source_object,
271 : : GError **error)
272 : : {
273 : 32 : if (!check_listener (listener, error))
274 : 0 : return FALSE;
275 : :
276 : : /* TODO: Check that socket it is bound & not closed? */
277 : :
278 : 32 : if (g_socket_is_closed (socket))
279 : : {
280 : 0 : g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_FAILED,
281 : : _("Added socket is closed"));
282 : 0 : return FALSE;
283 : : }
284 : :
285 : 32 : g_object_ref (socket);
286 : 32 : g_ptr_array_add (listener->priv->sockets, socket);
287 : :
288 : 32 : if (source_object)
289 : 0 : g_object_set_qdata_full (G_OBJECT (socket), source_quark,
290 : : g_object_ref (source_object), g_object_unref);
291 : :
292 : :
293 : 32 : if (G_SOCKET_LISTENER_GET_CLASS (listener)->changed)
294 : 29 : G_SOCKET_LISTENER_GET_CLASS (listener)->changed (listener);
295 : :
296 : 32 : return TRUE;
297 : : }
298 : :
299 : : /**
300 : : * g_socket_listener_add_address:
301 : : * @listener: a #GSocketListener
302 : : * @address: a #GSocketAddress
303 : : * @type: a #GSocketType
304 : : * @protocol: a #GSocketProtocol
305 : : * @source_object: (nullable): Optional #GObject identifying this source
306 : : * @effective_address: (out) (optional): location to store the address that was bound to, or %NULL.
307 : : * @error: #GError for error reporting, or %NULL to ignore.
308 : : *
309 : : * Creates a socket of type @type and protocol @protocol, binds
310 : : * it to @address and adds it to the set of sockets we're accepting
311 : : * sockets from.
312 : : *
313 : : * Note that adding an IPv6 address, depending on the platform,
314 : : * may or may not result in a listener that also accepts IPv4
315 : : * connections. For more deterministic behavior, see
316 : : * g_socket_listener_add_inet_port().
317 : : *
318 : : * @source_object will be passed out in the various calls
319 : : * to accept to identify this particular source, which is
320 : : * useful if you're listening on multiple addresses and do
321 : : * different things depending on what address is connected to.
322 : : *
323 : : * If successful and @effective_address is non-%NULL then it will
324 : : * be set to the address that the binding actually occurred at. This
325 : : * is helpful for determining the port number that was used for when
326 : : * requesting a binding to port 0 (ie: "any port"). This address, if
327 : : * requested, belongs to the caller and must be freed.
328 : : *
329 : : * Call g_socket_listener_close() to stop listening on @address; this will not
330 : : * be done automatically when you drop your final reference to @listener, as
331 : : * references may be held internally.
332 : : *
333 : : * Returns: %TRUE on success, %FALSE on error.
334 : : *
335 : : * Since: 2.22
336 : : */
337 : : gboolean
338 : 32 : g_socket_listener_add_address (GSocketListener *listener,
339 : : GSocketAddress *address,
340 : : GSocketType type,
341 : : GSocketProtocol protocol,
342 : : GObject *source_object,
343 : : GSocketAddress **effective_address,
344 : : GError **error)
345 : : {
346 : : GSocketAddress *local_address;
347 : : GSocketFamily family;
348 : : GSocket *socket;
349 : :
350 : 32 : if (!check_listener (listener, error))
351 : 0 : return FALSE;
352 : :
353 : 32 : family = g_socket_address_get_family (address);
354 : 32 : socket = g_socket_new (family, type, protocol, error);
355 : 32 : if (socket == NULL)
356 : 0 : return FALSE;
357 : :
358 : 32 : g_socket_set_listen_backlog (socket, listener->priv->listen_backlog);
359 : :
360 : 32 : g_signal_emit (listener, signals[EVENT], 0,
361 : : G_SOCKET_LISTENER_BINDING, socket);
362 : :
363 : 32 : if (!g_socket_bind (socket, address, TRUE, error))
364 : : {
365 : 0 : g_object_unref (socket);
366 : 0 : return FALSE;
367 : : }
368 : :
369 : 32 : g_signal_emit (listener, signals[EVENT], 0,
370 : : G_SOCKET_LISTENER_BOUND, socket);
371 : 32 : g_signal_emit (listener, signals[EVENT], 0,
372 : : G_SOCKET_LISTENER_LISTENING, socket);
373 : :
374 : 32 : if (!g_socket_listen (socket, error))
375 : : {
376 : 0 : g_object_unref (socket);
377 : 0 : return FALSE;
378 : : }
379 : :
380 : 32 : g_signal_emit (listener, signals[EVENT], 0,
381 : : G_SOCKET_LISTENER_LISTENED, socket);
382 : :
383 : 32 : local_address = NULL;
384 : 32 : if (effective_address)
385 : : {
386 : 11 : local_address = g_socket_get_local_address (socket, error);
387 : 11 : if (local_address == NULL)
388 : : {
389 : 0 : g_object_unref (socket);
390 : 0 : return FALSE;
391 : : }
392 : : }
393 : :
394 : 32 : if (!g_socket_listener_add_socket (listener, socket,
395 : : source_object,
396 : : error))
397 : : {
398 : 0 : if (local_address)
399 : 0 : g_object_unref (local_address);
400 : 0 : g_object_unref (socket);
401 : 0 : return FALSE;
402 : : }
403 : :
404 : 32 : if (effective_address)
405 : 11 : *effective_address = local_address;
406 : :
407 : 32 : g_object_unref (socket); /* add_socket refs this */
408 : :
409 : 32 : return TRUE;
410 : : }
411 : :
412 : : /**
413 : : * g_socket_listener_add_inet_port:
414 : : * @listener: a #GSocketListener
415 : : * @port: an IP port number (non-zero)
416 : : * @source_object: (nullable): Optional #GObject identifying this source
417 : : * @error: #GError for error reporting, or %NULL to ignore.
418 : : *
419 : : * Helper function for g_socket_listener_add_address() that
420 : : * creates a TCP/IP socket listening on IPv4 and IPv6 (if
421 : : * supported) on the specified port on all interfaces.
422 : : *
423 : : * @source_object will be passed out in the various calls
424 : : * to accept to identify this particular source, which is
425 : : * useful if you're listening on multiple addresses and do
426 : : * different things depending on what address is connected to.
427 : : *
428 : : * Call g_socket_listener_close() to stop listening on @port; this will not
429 : : * be done automatically when you drop your final reference to @listener, as
430 : : * references may be held internally.
431 : : *
432 : : * Returns: %TRUE on success, %FALSE on error.
433 : : *
434 : : * Since: 2.22
435 : : */
436 : : gboolean
437 : 0 : g_socket_listener_add_inet_port (GSocketListener *listener,
438 : : guint16 port,
439 : : GObject *source_object,
440 : : GError **error)
441 : : {
442 : 0 : gboolean need_ipv4_socket = TRUE;
443 : 0 : GSocket *socket4 = NULL;
444 : : GSocket *socket6;
445 : :
446 : 0 : g_return_val_if_fail (listener != NULL, FALSE);
447 : 0 : g_return_val_if_fail (port != 0, FALSE);
448 : :
449 : 0 : if (!check_listener (listener, error))
450 : 0 : return FALSE;
451 : :
452 : : /* first try to create an IPv6 socket */
453 : 0 : socket6 = g_socket_new (G_SOCKET_FAMILY_IPV6,
454 : : G_SOCKET_TYPE_STREAM,
455 : : G_SOCKET_PROTOCOL_DEFAULT,
456 : : NULL);
457 : :
458 : 0 : if (socket6 != NULL)
459 : : /* IPv6 is supported on this platform, so if we fail now it is
460 : : * a result of being unable to bind to our port. Don't fail
461 : : * silently as a result of this!
462 : : */
463 : : {
464 : : GInetAddress *inet_address;
465 : : GSocketAddress *address;
466 : :
467 : 0 : inet_address = g_inet_address_new_any (G_SOCKET_FAMILY_IPV6);
468 : 0 : address = g_inet_socket_address_new (inet_address, port);
469 : 0 : g_object_unref (inet_address);
470 : :
471 : 0 : g_socket_set_listen_backlog (socket6, listener->priv->listen_backlog);
472 : :
473 : 0 : g_signal_emit (listener, signals[EVENT], 0,
474 : : G_SOCKET_LISTENER_BINDING, socket6);
475 : :
476 : 0 : if (!g_socket_bind (socket6, address, TRUE, error))
477 : : {
478 : 0 : g_object_unref (address);
479 : 0 : g_object_unref (socket6);
480 : 0 : return FALSE;
481 : : }
482 : :
483 : 0 : g_object_unref (address);
484 : :
485 : 0 : g_signal_emit (listener, signals[EVENT], 0,
486 : : G_SOCKET_LISTENER_BOUND, socket6);
487 : 0 : g_signal_emit (listener, signals[EVENT], 0,
488 : : G_SOCKET_LISTENER_LISTENING, socket6);
489 : :
490 : 0 : if (!g_socket_listen (socket6, error))
491 : : {
492 : 0 : g_object_unref (socket6);
493 : 0 : return FALSE;
494 : : }
495 : :
496 : 0 : g_signal_emit (listener, signals[EVENT], 0,
497 : : G_SOCKET_LISTENER_LISTENED, socket6);
498 : :
499 : 0 : if (source_object)
500 : 0 : g_object_set_qdata_full (G_OBJECT (socket6), source_quark,
501 : : g_object_ref (source_object),
502 : : g_object_unref);
503 : :
504 : : /* If this socket already speaks IPv4 then we are done. */
505 : 0 : if (g_socket_speaks_ipv4 (socket6))
506 : 0 : need_ipv4_socket = FALSE;
507 : : }
508 : :
509 : 0 : if (need_ipv4_socket)
510 : : /* We are here for exactly one of the following reasons:
511 : : *
512 : : * - our platform doesn't support IPv6
513 : : * - we successfully created an IPv6 socket but it's V6ONLY
514 : : *
515 : : * In either case, we need to go ahead and create an IPv4 socket
516 : : * and fail the call if we can't bind to it.
517 : : */
518 : : {
519 : 0 : socket4 = g_socket_new (G_SOCKET_FAMILY_IPV4,
520 : : G_SOCKET_TYPE_STREAM,
521 : : G_SOCKET_PROTOCOL_DEFAULT,
522 : : error);
523 : :
524 : 0 : if (socket4 != NULL)
525 : : /* IPv4 is supported on this platform, so if we fail now it is
526 : : * a result of being unable to bind to our port. Don't fail
527 : : * silently as a result of this!
528 : : */
529 : : {
530 : : GInetAddress *inet_address;
531 : : GSocketAddress *address;
532 : :
533 : 0 : inet_address = g_inet_address_new_any (G_SOCKET_FAMILY_IPV4);
534 : 0 : address = g_inet_socket_address_new (inet_address, port);
535 : 0 : g_object_unref (inet_address);
536 : :
537 : 0 : g_socket_set_listen_backlog (socket4,
538 : 0 : listener->priv->listen_backlog);
539 : :
540 : 0 : g_signal_emit (listener, signals[EVENT], 0,
541 : : G_SOCKET_LISTENER_BINDING, socket4);
542 : :
543 : 0 : if (!g_socket_bind (socket4, address, TRUE, error))
544 : : {
545 : 0 : g_object_unref (address);
546 : 0 : g_object_unref (socket4);
547 : 0 : if (socket6 != NULL)
548 : 0 : g_object_unref (socket6);
549 : :
550 : 0 : return FALSE;
551 : : }
552 : :
553 : 0 : g_object_unref (address);
554 : :
555 : 0 : g_signal_emit (listener, signals[EVENT], 0,
556 : : G_SOCKET_LISTENER_BOUND, socket4);
557 : 0 : g_signal_emit (listener, signals[EVENT], 0,
558 : : G_SOCKET_LISTENER_LISTENING, socket4);
559 : :
560 : 0 : if (!g_socket_listen (socket4, error))
561 : : {
562 : 0 : g_object_unref (socket4);
563 : 0 : if (socket6 != NULL)
564 : 0 : g_object_unref (socket6);
565 : :
566 : 0 : return FALSE;
567 : : }
568 : :
569 : 0 : g_signal_emit (listener, signals[EVENT], 0,
570 : : G_SOCKET_LISTENER_LISTENED, socket4);
571 : :
572 : 0 : if (source_object)
573 : 0 : g_object_set_qdata_full (G_OBJECT (socket4), source_quark,
574 : : g_object_ref (source_object),
575 : : g_object_unref);
576 : : }
577 : : else
578 : : /* Ok. So IPv4 is not supported on this platform. If we
579 : : * succeeded at creating an IPv6 socket then that's OK, but
580 : : * otherwise we need to tell the user we failed.
581 : : */
582 : : {
583 : 0 : if (socket6 != NULL)
584 : 0 : g_clear_error (error);
585 : : else
586 : 0 : return FALSE;
587 : : }
588 : : }
589 : :
590 : 0 : g_assert (socket6 != NULL || socket4 != NULL);
591 : :
592 : 0 : if (socket6 != NULL)
593 : 0 : g_ptr_array_add (listener->priv->sockets, socket6);
594 : :
595 : 0 : if (socket4 != NULL)
596 : 0 : g_ptr_array_add (listener->priv->sockets, socket4);
597 : :
598 : 0 : if (G_SOCKET_LISTENER_GET_CLASS (listener)->changed)
599 : 0 : G_SOCKET_LISTENER_GET_CLASS (listener)->changed (listener);
600 : :
601 : 0 : return TRUE;
602 : : }
603 : :
604 : : static GList *
605 : 259 : add_sources (GSocketListener *listener,
606 : : GSocketSourceFunc callback,
607 : : gpointer callback_data,
608 : : GCancellable *cancellable,
609 : : GMainContext *context)
610 : : {
611 : : GSocket *socket;
612 : : GSource *source;
613 : : GList *sources;
614 : : guint i;
615 : :
616 : 259 : sources = NULL;
617 : 518 : for (i = 0; i < listener->priv->sockets->len; i++)
618 : : {
619 : 259 : socket = listener->priv->sockets->pdata[i];
620 : :
621 : 259 : source = g_socket_create_source (socket, G_IO_IN, cancellable);
622 : 259 : g_source_set_callback (source,
623 : : (GSourceFunc) callback,
624 : : callback_data, NULL);
625 : 259 : g_source_attach (source, context);
626 : :
627 : 259 : sources = g_list_prepend (sources, source);
628 : : }
629 : :
630 : 259 : return sources;
631 : : }
632 : :
633 : : static void
634 : 245 : free_sources (GList *sources)
635 : : {
636 : : GSource *source;
637 : 490 : while (sources != NULL)
638 : : {
639 : 245 : source = sources->data;
640 : 245 : sources = g_list_delete_link (sources, sources);
641 : 245 : g_source_destroy (source);
642 : 245 : g_source_unref (source);
643 : : }
644 : 245 : }
645 : :
646 : : struct AcceptData {
647 : : GMainLoop *loop;
648 : : GSocket *socket;
649 : : };
650 : :
651 : : static gboolean
652 : 0 : accept_callback (GSocket *socket,
653 : : GIOCondition condition,
654 : : gpointer user_data)
655 : : {
656 : 0 : struct AcceptData *data = user_data;
657 : :
658 : 0 : data->socket = socket;
659 : 0 : g_main_loop_quit (data->loop);
660 : :
661 : 0 : return TRUE;
662 : : }
663 : :
664 : : /**
665 : : * g_socket_listener_accept_socket:
666 : : * @listener: a #GSocketListener
667 : : * @source_object: (out) (transfer none) (optional) (nullable): location where #GObject pointer will be stored, or %NULL.
668 : : * @cancellable: (nullable): optional #GCancellable object, %NULL to ignore.
669 : : * @error: #GError for error reporting, or %NULL to ignore.
670 : : *
671 : : * Blocks waiting for a client to connect to any of the sockets added
672 : : * to the listener. Returns the #GSocket that was accepted.
673 : : *
674 : : * If you want to accept the high-level #GSocketConnection, not a #GSocket,
675 : : * which is often the case, then you should use g_socket_listener_accept()
676 : : * instead.
677 : : *
678 : : * If @source_object is not %NULL it will be filled out with the source
679 : : * object specified when the corresponding socket or address was added
680 : : * to the listener.
681 : : *
682 : : * If @cancellable is not %NULL, then the operation can be cancelled by
683 : : * triggering the cancellable object from another thread. If the operation
684 : : * was cancelled, the error %G_IO_ERROR_CANCELLED will be returned.
685 : : *
686 : : * Returns: (transfer full): a #GSocket on success, %NULL on error.
687 : : *
688 : : * Since: 2.22
689 : : */
690 : : GSocket *
691 : 0 : g_socket_listener_accept_socket (GSocketListener *listener,
692 : : GObject **source_object,
693 : : GCancellable *cancellable,
694 : : GError **error)
695 : : {
696 : : GSocket *accept_socket, *socket;
697 : :
698 : 0 : g_return_val_if_fail (G_IS_SOCKET_LISTENER (listener), NULL);
699 : :
700 : 0 : if (!check_listener (listener, error))
701 : 0 : return NULL;
702 : :
703 : 0 : if (listener->priv->sockets->len == 1)
704 : : {
705 : 0 : accept_socket = listener->priv->sockets->pdata[0];
706 : 0 : if (!g_socket_condition_wait (accept_socket, G_IO_IN,
707 : : cancellable, error))
708 : 0 : return NULL;
709 : : }
710 : : else
711 : : {
712 : : GList *sources;
713 : : struct AcceptData data;
714 : : GMainLoop *loop;
715 : :
716 : 0 : if (listener->priv->main_context == NULL)
717 : 0 : listener->priv->main_context = g_main_context_new ();
718 : :
719 : 0 : loop = g_main_loop_new (listener->priv->main_context, FALSE);
720 : 0 : data.loop = loop;
721 : 0 : sources = add_sources (listener,
722 : : accept_callback,
723 : : &data,
724 : : cancellable,
725 : 0 : listener->priv->main_context);
726 : 0 : g_main_loop_run (loop);
727 : 0 : accept_socket = data.socket;
728 : 0 : free_sources (sources);
729 : 0 : g_main_loop_unref (loop);
730 : : }
731 : :
732 : 0 : if (!(socket = g_socket_accept (accept_socket, cancellable, error)))
733 : 0 : return NULL;
734 : :
735 : 0 : if (source_object)
736 : 0 : *source_object = g_object_get_qdata (G_OBJECT (accept_socket), source_quark);
737 : :
738 : 0 : return socket;
739 : : }
740 : :
741 : : /**
742 : : * g_socket_listener_accept:
743 : : * @listener: a #GSocketListener
744 : : * @source_object: (out) (transfer none) (optional) (nullable): location where #GObject pointer will be stored, or %NULL
745 : : * @cancellable: (nullable): optional #GCancellable object, %NULL to ignore.
746 : : * @error: #GError for error reporting, or %NULL to ignore.
747 : : *
748 : : * Blocks waiting for a client to connect to any of the sockets added
749 : : * to the listener. Returns a #GSocketConnection for the socket that was
750 : : * accepted.
751 : : *
752 : : * If @source_object is not %NULL it will be filled out with the source
753 : : * object specified when the corresponding socket or address was added
754 : : * to the listener.
755 : : *
756 : : * If @cancellable is not %NULL, then the operation can be cancelled by
757 : : * triggering the cancellable object from another thread. If the operation
758 : : * was cancelled, the error %G_IO_ERROR_CANCELLED will be returned.
759 : : *
760 : : * Returns: (transfer full): a #GSocketConnection on success, %NULL on error.
761 : : *
762 : : * Since: 2.22
763 : : */
764 : : GSocketConnection *
765 : 0 : g_socket_listener_accept (GSocketListener *listener,
766 : : GObject **source_object,
767 : : GCancellable *cancellable,
768 : : GError **error)
769 : : {
770 : : GSocketConnection *connection;
771 : : GSocket *socket;
772 : :
773 : 0 : socket = g_socket_listener_accept_socket (listener,
774 : : source_object,
775 : : cancellable,
776 : : error);
777 : 0 : if (socket == NULL)
778 : 0 : return NULL;
779 : :
780 : 0 : connection = g_socket_connection_factory_create_connection (socket);
781 : 0 : g_object_unref (socket);
782 : :
783 : 0 : return connection;
784 : : }
785 : :
786 : : typedef struct
787 : : {
788 : : GList *sources; /* (element-type GSource) */
789 : : gboolean returned_yet;
790 : : } AcceptSocketAsyncData;
791 : :
792 : : static void
793 : 245 : accept_socket_async_data_free (AcceptSocketAsyncData *data)
794 : : {
795 : 245 : free_sources (data->sources);
796 : 245 : g_free (data);
797 : 245 : }
798 : :
799 : : static gboolean
800 : 250 : accept_ready (GSocket *accept_socket,
801 : : GIOCondition condition,
802 : : gpointer user_data)
803 : : {
804 : 250 : GTask *task = user_data;
805 : 250 : GError *error = NULL;
806 : : GSocket *socket;
807 : : GObject *source_object;
808 : 250 : AcceptSocketAsyncData *data = g_task_get_task_data (task);
809 : :
810 : : /* Don’t call g_task_return_*() multiple times if we have multiple incoming
811 : : * connections in the same #GMainContext iteration. */
812 : 250 : if (data->returned_yet)
813 : 0 : return G_SOURCE_REMOVE;
814 : :
815 : 250 : socket = g_socket_accept (accept_socket, g_task_get_cancellable (task), &error);
816 : 250 : if (socket)
817 : : {
818 : 228 : source_object = g_object_get_qdata (G_OBJECT (accept_socket), source_quark);
819 : 228 : if (source_object)
820 : 0 : g_object_set_qdata_full (G_OBJECT (task),
821 : : source_quark,
822 : : g_object_ref (source_object), g_object_unref);
823 : 228 : g_task_return_pointer (task, socket, g_object_unref);
824 : : }
825 : : else
826 : : {
827 : 22 : g_task_return_error (task, error);
828 : : }
829 : :
830 : 250 : data->returned_yet = TRUE;
831 : 250 : g_object_unref (task);
832 : :
833 : 250 : return G_SOURCE_REMOVE;
834 : : }
835 : :
836 : : /**
837 : : * g_socket_listener_accept_socket_async:
838 : : * @listener: a #GSocketListener
839 : : * @cancellable: (nullable): a #GCancellable, or %NULL
840 : : * @callback: (scope async): a #GAsyncReadyCallback
841 : : * @user_data: user data for the callback
842 : : *
843 : : * This is the asynchronous version of g_socket_listener_accept_socket().
844 : : *
845 : : * When the operation is finished @callback will be
846 : : * called. You can then call g_socket_listener_accept_socket_finish()
847 : : * to get the result of the operation.
848 : : *
849 : : * Since: 2.22
850 : : */
851 : : void
852 : 259 : g_socket_listener_accept_socket_async (GSocketListener *listener,
853 : : GCancellable *cancellable,
854 : : GAsyncReadyCallback callback,
855 : : gpointer user_data)
856 : : {
857 : : GTask *task;
858 : 259 : GError *error = NULL;
859 : 259 : AcceptSocketAsyncData *data = NULL;
860 : :
861 : 259 : task = g_task_new (listener, cancellable, callback, user_data);
862 : 259 : g_task_set_source_tag (task, g_socket_listener_accept_socket_async);
863 : :
864 : 259 : if (!check_listener (listener, &error))
865 : : {
866 : 0 : g_task_return_error (task, error);
867 : 0 : g_object_unref (task);
868 : 0 : return;
869 : : }
870 : :
871 : 259 : data = g_new0 (AcceptSocketAsyncData, 1);
872 : 259 : data->returned_yet = FALSE;
873 : 259 : data->sources = add_sources (listener,
874 : : accept_ready,
875 : : task,
876 : : cancellable,
877 : : g_main_context_get_thread_default ());
878 : 259 : g_task_set_task_data (task, g_steal_pointer (&data),
879 : : (GDestroyNotify) accept_socket_async_data_free);
880 : : }
881 : :
882 : : /**
883 : : * g_socket_listener_accept_socket_finish:
884 : : * @listener: a #GSocketListener
885 : : * @result: a #GAsyncResult.
886 : : * @source_object: (out) (transfer none) (optional) (nullable): Optional #GObject identifying this source
887 : : * @error: a #GError location to store the error occurring, or %NULL to
888 : : * ignore.
889 : : *
890 : : * Finishes an async accept operation. See g_socket_listener_accept_socket_async()
891 : : *
892 : : * Returns: (transfer full): a #GSocket on success, %NULL on error.
893 : : *
894 : : * Since: 2.22
895 : : */
896 : : GSocket *
897 : 245 : g_socket_listener_accept_socket_finish (GSocketListener *listener,
898 : : GAsyncResult *result,
899 : : GObject **source_object,
900 : : GError **error)
901 : : {
902 : 245 : g_return_val_if_fail (G_IS_SOCKET_LISTENER (listener), NULL);
903 : 245 : g_return_val_if_fail (g_task_is_valid (result, listener), NULL);
904 : :
905 : 245 : if (source_object)
906 : 243 : *source_object = g_object_get_qdata (G_OBJECT (result), source_quark);
907 : :
908 : 245 : return g_task_propagate_pointer (G_TASK (result), error);
909 : : }
910 : :
911 : : /**
912 : : * g_socket_listener_accept_async:
913 : : * @listener: a #GSocketListener
914 : : * @cancellable: (nullable): a #GCancellable, or %NULL
915 : : * @callback: (scope async): a #GAsyncReadyCallback
916 : : * @user_data: user data for the callback
917 : : *
918 : : * This is the asynchronous version of g_socket_listener_accept().
919 : : *
920 : : * When the operation is finished @callback will be
921 : : * called. You can then call g_socket_listener_accept_finish()
922 : : * to get the result of the operation.
923 : : *
924 : : * Since: 2.22
925 : : */
926 : : void
927 : 259 : g_socket_listener_accept_async (GSocketListener *listener,
928 : : GCancellable *cancellable,
929 : : GAsyncReadyCallback callback,
930 : : gpointer user_data)
931 : : {
932 : 259 : g_socket_listener_accept_socket_async (listener,
933 : : cancellable,
934 : : callback,
935 : : user_data);
936 : 259 : }
937 : :
938 : : /**
939 : : * g_socket_listener_accept_finish:
940 : : * @listener: a #GSocketListener
941 : : * @result: a #GAsyncResult.
942 : : * @source_object: (out) (transfer none) (optional) (nullable): Optional #GObject identifying this source
943 : : * @error: a #GError location to store the error occurring, or %NULL to
944 : : * ignore.
945 : : *
946 : : * Finishes an async accept operation. See g_socket_listener_accept_async()
947 : : *
948 : : * Returns: (transfer full): a #GSocketConnection on success, %NULL on error.
949 : : *
950 : : * Since: 2.22
951 : : */
952 : : GSocketConnection *
953 : 245 : g_socket_listener_accept_finish (GSocketListener *listener,
954 : : GAsyncResult *result,
955 : : GObject **source_object,
956 : : GError **error)
957 : : {
958 : : GSocket *socket;
959 : : GSocketConnection *connection;
960 : :
961 : 245 : socket = g_socket_listener_accept_socket_finish (listener,
962 : : result,
963 : : source_object,
964 : : error);
965 : 245 : if (socket == NULL)
966 : 18 : return NULL;
967 : :
968 : 227 : connection = g_socket_connection_factory_create_connection (socket);
969 : 227 : g_object_unref (socket);
970 : 227 : return connection;
971 : : }
972 : :
973 : : /**
974 : : * g_socket_listener_set_backlog:
975 : : * @listener: a #GSocketListener
976 : : * @listen_backlog: an integer
977 : : *
978 : : * Sets the listen backlog on the sockets in the listener. This must be called
979 : : * before adding any sockets, addresses or ports to the #GSocketListener (for
980 : : * example, by calling g_socket_listener_add_inet_port()) to be effective.
981 : : *
982 : : * See g_socket_set_listen_backlog() for details
983 : : *
984 : : * Since: 2.22
985 : : */
986 : : void
987 : 38 : g_socket_listener_set_backlog (GSocketListener *listener,
988 : : int listen_backlog)
989 : : {
990 : : GSocket *socket;
991 : : guint i;
992 : :
993 : 38 : if (listener->priv->closed)
994 : 0 : return;
995 : :
996 : 38 : listener->priv->listen_backlog = listen_backlog;
997 : :
998 : 38 : for (i = 0; i < listener->priv->sockets->len; i++)
999 : : {
1000 : 0 : socket = listener->priv->sockets->pdata[i];
1001 : 0 : g_socket_set_listen_backlog (socket, listen_backlog);
1002 : : }
1003 : : }
1004 : :
1005 : : /**
1006 : : * g_socket_listener_close:
1007 : : * @listener: a #GSocketListener
1008 : : *
1009 : : * Closes all the sockets in the listener.
1010 : : *
1011 : : * Since: 2.22
1012 : : */
1013 : : void
1014 : 0 : g_socket_listener_close (GSocketListener *listener)
1015 : : {
1016 : : GSocket *socket;
1017 : : guint i;
1018 : :
1019 : 0 : g_return_if_fail (G_IS_SOCKET_LISTENER (listener));
1020 : :
1021 : 0 : if (listener->priv->closed)
1022 : 0 : return;
1023 : :
1024 : 0 : for (i = 0; i < listener->priv->sockets->len; i++)
1025 : : {
1026 : 0 : socket = listener->priv->sockets->pdata[i];
1027 : 0 : g_socket_close (socket, NULL);
1028 : : }
1029 : 0 : listener->priv->closed = TRUE;
1030 : : }
1031 : :
1032 : : /**
1033 : : * g_socket_listener_add_any_inet_port:
1034 : : * @listener: a #GSocketListener
1035 : : * @source_object: (nullable): Optional #GObject identifying this source
1036 : : * @error: a #GError location to store the error occurring, or %NULL to
1037 : : * ignore.
1038 : : *
1039 : : * Listens for TCP connections on any available port number for both
1040 : : * IPv6 and IPv4 (if each is available).
1041 : : *
1042 : : * This is useful if you need to have a socket for incoming connections
1043 : : * but don't care about the specific port number.
1044 : : *
1045 : : * @source_object will be passed out in the various calls
1046 : : * to accept to identify this particular source, which is
1047 : : * useful if you're listening on multiple addresses and do
1048 : : * different things depending on what address is connected to.
1049 : : *
1050 : : * Returns: the port number, or 0 in case of failure.
1051 : : *
1052 : : * Since: 2.24
1053 : : **/
1054 : : guint16
1055 : 3 : g_socket_listener_add_any_inet_port (GSocketListener *listener,
1056 : : GObject *source_object,
1057 : : GError **error)
1058 : : {
1059 : 3 : GSList *sockets_to_close = NULL;
1060 : 3 : guint16 candidate_port = 0;
1061 : 3 : GSocket *socket6 = NULL;
1062 : 3 : GSocket *socket4 = NULL;
1063 : 3 : gint attempts = 37;
1064 : :
1065 : : /*
1066 : : * multi-step process:
1067 : : * - first, create an IPv6 socket.
1068 : : * - if that fails, create an IPv4 socket and bind it to port 0 and
1069 : : * that's it. no retries if that fails (why would it?).
1070 : : * - if our IPv6 socket also speaks IPv4 then we are done.
1071 : : * - if not, then we need to create a IPv4 socket with the same port
1072 : : * number. this might fail, of course. so we try this a bunch of
1073 : : * times -- leaving the old IPv6 sockets open so that we get a
1074 : : * different port number to try each time.
1075 : : * - if all that fails then just give up.
1076 : : */
1077 : :
1078 : 3 : while (attempts--)
1079 : : {
1080 : : GInetAddress *inet_address;
1081 : : GSocketAddress *address;
1082 : : gboolean result;
1083 : :
1084 : 3 : g_assert (socket6 == NULL);
1085 : 3 : socket6 = g_socket_new (G_SOCKET_FAMILY_IPV6,
1086 : : G_SOCKET_TYPE_STREAM,
1087 : : G_SOCKET_PROTOCOL_DEFAULT,
1088 : : NULL);
1089 : :
1090 : 3 : if (socket6 != NULL)
1091 : : {
1092 : 3 : inet_address = g_inet_address_new_any (G_SOCKET_FAMILY_IPV6);
1093 : 3 : address = g_inet_socket_address_new (inet_address, 0);
1094 : 3 : g_object_unref (inet_address);
1095 : :
1096 : 3 : g_signal_emit (listener, signals[EVENT], 0,
1097 : : G_SOCKET_LISTENER_BINDING, socket6);
1098 : :
1099 : 3 : result = g_socket_bind (socket6, address, TRUE, error);
1100 : 3 : g_object_unref (address);
1101 : :
1102 : 6 : if (!result ||
1103 : 3 : !(address = g_socket_get_local_address (socket6, error)))
1104 : : {
1105 : 0 : g_object_unref (socket6);
1106 : 0 : socket6 = NULL;
1107 : 0 : break;
1108 : : }
1109 : :
1110 : 3 : g_signal_emit (listener, signals[EVENT], 0,
1111 : : G_SOCKET_LISTENER_BOUND, socket6);
1112 : :
1113 : 3 : g_assert (G_IS_INET_SOCKET_ADDRESS (address));
1114 : : candidate_port =
1115 : 3 : g_inet_socket_address_get_port (G_INET_SOCKET_ADDRESS (address));
1116 : 3 : g_assert (candidate_port != 0);
1117 : 3 : g_object_unref (address);
1118 : :
1119 : 3 : if (g_socket_speaks_ipv4 (socket6))
1120 : 3 : break;
1121 : : }
1122 : :
1123 : 0 : g_assert (socket4 == NULL);
1124 : 0 : socket4 = g_socket_new (G_SOCKET_FAMILY_IPV4,
1125 : : G_SOCKET_TYPE_STREAM,
1126 : : G_SOCKET_PROTOCOL_DEFAULT,
1127 : : socket6 ? NULL : error);
1128 : :
1129 : 0 : if (socket4 == NULL)
1130 : : /* IPv4 not supported.
1131 : : * if IPv6 is supported then candidate_port will be non-zero
1132 : : * (and the error parameter above will have been NULL)
1133 : : * if IPv6 is unsupported then candidate_port will be zero
1134 : : * (and error will have been set by the above call)
1135 : : */
1136 : 0 : break;
1137 : :
1138 : 0 : inet_address = g_inet_address_new_any (G_SOCKET_FAMILY_IPV4);
1139 : 0 : address = g_inet_socket_address_new (inet_address, candidate_port);
1140 : 0 : g_object_unref (inet_address);
1141 : :
1142 : 0 : g_signal_emit (listener, signals[EVENT], 0,
1143 : : G_SOCKET_LISTENER_BINDING, socket4);
1144 : :
1145 : : /* a note on the 'error' clause below:
1146 : : *
1147 : : * if candidate_port is 0 then we report the error right away
1148 : : * since it is strange that this binding would fail at all.
1149 : : * otherwise, we ignore the error message (ie: NULL).
1150 : : *
1151 : : * the exception to this rule is the last time through the loop
1152 : : * (ie: attempts == 0) in which case we want to set the error
1153 : : * because failure here means that the entire call will fail and
1154 : : * we need something to show to the user.
1155 : : *
1156 : : * an english summary of the situation: "if we gave a candidate
1157 : : * port number AND we have more attempts to try, then ignore the
1158 : : * error for now".
1159 : : */
1160 : 0 : result = g_socket_bind (socket4, address, TRUE,
1161 : 0 : (candidate_port && attempts) ? NULL : error);
1162 : 0 : g_object_unref (address);
1163 : :
1164 : 0 : if (candidate_port)
1165 : : {
1166 : 0 : g_assert (socket6 != NULL);
1167 : :
1168 : 0 : if (result)
1169 : : /* got our candidate port successfully */
1170 : : {
1171 : 0 : g_signal_emit (listener, signals[EVENT], 0,
1172 : : G_SOCKET_LISTENER_BOUND, socket4);
1173 : 0 : break;
1174 : : }
1175 : : else
1176 : : /* we failed to bind to the specified port. try again. */
1177 : : {
1178 : 0 : g_object_unref (socket4);
1179 : 0 : socket4 = NULL;
1180 : :
1181 : : /* keep this open so we get a different port number */
1182 : 0 : sockets_to_close = g_slist_prepend (sockets_to_close,
1183 : : socket6);
1184 : 0 : candidate_port = 0;
1185 : 0 : socket6 = NULL;
1186 : : }
1187 : : }
1188 : : else
1189 : : /* we didn't tell it a port. this means two things.
1190 : : * - if we failed, then something really bad happened.
1191 : : * - if we succeeded, then we need to find out the port number.
1192 : : */
1193 : : {
1194 : 0 : g_assert (socket6 == NULL);
1195 : :
1196 : 0 : if (!result ||
1197 : 0 : !(address = g_socket_get_local_address (socket4, error)))
1198 : : {
1199 : 0 : g_object_unref (socket4);
1200 : 0 : socket4 = NULL;
1201 : 0 : break;
1202 : : }
1203 : :
1204 : 0 : g_signal_emit (listener, signals[EVENT], 0,
1205 : : G_SOCKET_LISTENER_BOUND, socket4);
1206 : :
1207 : 0 : g_assert (G_IS_INET_SOCKET_ADDRESS (address));
1208 : : candidate_port =
1209 : 0 : g_inet_socket_address_get_port (G_INET_SOCKET_ADDRESS (address));
1210 : 0 : g_assert (candidate_port != 0);
1211 : 0 : g_object_unref (address);
1212 : 0 : break;
1213 : : }
1214 : : }
1215 : :
1216 : : /* should only be non-zero if we have a socket */
1217 : 3 : g_assert ((candidate_port != 0) == (socket4 || socket6));
1218 : :
1219 : 3 : while (sockets_to_close)
1220 : : {
1221 : 0 : g_object_unref (sockets_to_close->data);
1222 : 0 : sockets_to_close = g_slist_delete_link (sockets_to_close,
1223 : : sockets_to_close);
1224 : : }
1225 : :
1226 : : /* now we actually listen() the sockets and add them to the listener */
1227 : 3 : if (socket6 != NULL)
1228 : : {
1229 : 3 : g_socket_set_listen_backlog (socket6, listener->priv->listen_backlog);
1230 : :
1231 : 3 : g_signal_emit (listener, signals[EVENT], 0,
1232 : : G_SOCKET_LISTENER_LISTENING, socket6);
1233 : :
1234 : 3 : if (!g_socket_listen (socket6, error))
1235 : : {
1236 : 0 : g_object_unref (socket6);
1237 : 0 : if (socket4)
1238 : 0 : g_object_unref (socket4);
1239 : :
1240 : 0 : return 0;
1241 : : }
1242 : :
1243 : 3 : g_signal_emit (listener, signals[EVENT], 0,
1244 : : G_SOCKET_LISTENER_LISTENED, socket6);
1245 : :
1246 : 3 : if (source_object)
1247 : 0 : g_object_set_qdata_full (G_OBJECT (socket6), source_quark,
1248 : : g_object_ref (source_object),
1249 : : g_object_unref);
1250 : :
1251 : 3 : g_ptr_array_add (listener->priv->sockets, socket6);
1252 : : }
1253 : :
1254 : 3 : if (socket4 != NULL)
1255 : : {
1256 : 0 : g_socket_set_listen_backlog (socket4, listener->priv->listen_backlog);
1257 : :
1258 : 0 : g_signal_emit (listener, signals[EVENT], 0,
1259 : : G_SOCKET_LISTENER_LISTENING, socket4);
1260 : :
1261 : 0 : if (!g_socket_listen (socket4, error))
1262 : : {
1263 : 0 : g_object_unref (socket4);
1264 : 0 : if (socket6)
1265 : 0 : g_object_unref (socket6);
1266 : :
1267 : 0 : return 0;
1268 : : }
1269 : :
1270 : 0 : g_signal_emit (listener, signals[EVENT], 0,
1271 : : G_SOCKET_LISTENER_LISTENED, socket4);
1272 : :
1273 : 0 : if (source_object)
1274 : 0 : g_object_set_qdata_full (G_OBJECT (socket4), source_quark,
1275 : : g_object_ref (source_object),
1276 : : g_object_unref);
1277 : :
1278 : 0 : g_ptr_array_add (listener->priv->sockets, socket4);
1279 : : }
1280 : :
1281 : 3 : if ((socket4 != NULL || socket6 != NULL) &&
1282 : 3 : G_SOCKET_LISTENER_GET_CLASS (listener)->changed)
1283 : 3 : G_SOCKET_LISTENER_GET_CLASS (listener)->changed (listener);
1284 : :
1285 : 3 : return candidate_port;
1286 : : }
|