[kdbus] KDBUS_ITEM_PAYLOAD_OFF items are (once again) relative to msg header
[platform/upstream/glib.git] / gio / gsocketlistener.c
index 8bb5748..7185745 100644 (file)
@@ -15,9 +15,7 @@
  * Lesser General Public License for more details.
  *
  * You should have received a copy of the GNU Lesser General
- * Public License along with this library; if not, write to the
- * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
- * Boston, MA 02111-1307, USA.
+ * Public License along with this library; if not, see <http://www.gnu.org/licenses/>.
  *
  * Authors: Christian Kellner <gicmo@gnome.org>
  *          Samuel Cormier-Iijima <sciyoshi@gmail.com>
@@ -28,7 +26,7 @@
 #include "config.h"
 #include "gsocketlistener.h"
 
-#include <gio/gsimpleasyncresult.h>
+#include <gio/gtask.h>
 #include <gio/gcancellable.h>
 #include <gio/gsocketaddress.h>
 #include <gio/ginetaddress.h>
 
 
 /**
- * SECTION: gsocketlistener
+ * SECTION:gsocketlistener
  * @title: GSocketListener
  * @short_description: Helper for accepting network client connections
+ * @include: gio/gio.h
  * @see_also: #GThreadedSocketService, #GSocketService.
  *
  * A #GSocketListener is an object that keeps track of a set
@@ -56,8 +55,6 @@
  * Since: 2.22
  */
 
-G_DEFINE_TYPE (GSocketListener, g_socket_listener, G_TYPE_OBJECT);
-
 enum
 {
   PROP_0,
@@ -75,6 +72,8 @@ struct _GSocketListenerPrivate
   guint               closed : 1;
 };
 
+G_DEFINE_TYPE_WITH_PRIVATE (GSocketListener, g_socket_listener, G_TYPE_OBJECT)
+
 static void
 g_socket_listener_finalize (GObject *object)
 {
@@ -83,9 +82,11 @@ g_socket_listener_finalize (GObject *object)
   if (listener->priv->main_context)
     g_main_context_unref (listener->priv->main_context);
 
-  if (!listener->priv->closed)
-    g_socket_listener_close (listener);
-
+  /* Do not explicitly close the sockets. Instead, let them close themselves if
+   * their final reference is dropped, but keep them open if a reference is
+   * held externally to the GSocketListener (which is possible if
+   * g_socket_listener_add_socket() was used).
+   */
   g_ptr_array_free (listener->priv->sockets, TRUE);
 
   G_OBJECT_CLASS (g_socket_listener_parent_class)
@@ -136,8 +137,6 @@ g_socket_listener_class_init (GSocketListenerClass *klass)
 {
   GObjectClass *gobject_class G_GNUC_UNUSED = G_OBJECT_CLASS (klass);
 
-  g_type_class_add_private (klass, sizeof (GSocketListenerPrivate));
-
   gobject_class->finalize = g_socket_listener_finalize;
   gobject_class->set_property = g_socket_listener_set_property;
   gobject_class->get_property = g_socket_listener_get_property;
@@ -156,9 +155,7 @@ g_socket_listener_class_init (GSocketListenerClass *klass)
 static void
 g_socket_listener_init (GSocketListener *listener)
 {
-  listener->priv = G_TYPE_INSTANCE_GET_PRIVATE (listener,
-                                               G_TYPE_SOCKET_LISTENER,
-                                               GSocketListenerPrivate);
+  listener->priv = g_socket_listener_get_instance_private (listener);
   listener->priv->sockets =
     g_ptr_array_new_with_free_func ((GDestroyNotify) g_object_unref);
   listener->priv->listen_backlog = 10;
@@ -199,7 +196,7 @@ check_listener (GSocketListener *listener,
  * g_socket_listener_add_socket:
  * @listener: a #GSocketListener
  * @socket: a listening #GSocket
- * @source_object: Optional #GObject identifying this source
+ * @source_object: (allow-none): Optional #GObject identifying this source
  * @error: #GError for error reporting, or %NULL to ignore.
  *
  * Adds @socket to the set of sockets that we try to accept
@@ -211,6 +208,11 @@ check_listener (GSocketListener *listener,
  * useful if you're listening on multiple addresses and do
  * different things depending on what address is connected to.
  *
+ * The @socket will not be automatically closed when the @listener is finalized
+ * unless the listener held the final reference to the socket. Before GLib 2.42,
+ * the @socket was automatically closed on finalization of the @listener, even
+ * if references to it were held elsewhere.
+ *
  * Returns: %TRUE on success, %FALSE on error.
  *
  * Since: 2.22
@@ -253,7 +255,7 @@ g_socket_listener_add_socket (GSocketListener  *listener,
  * @address: a #GSocketAddress
  * @type: a #GSocketType
  * @protocol: a #GSocketProtocol
- * @source_object: Optional #GObject identifying this source
+ * @source_object: (allow-none): Optional #GObject identifying this source
  * @effective_address: (out) (allow-none): location to store the address that was bound to, or %NULL.
  * @error: #GError for error reporting, or %NULL to ignore.
  *
@@ -263,7 +265,7 @@ g_socket_listener_add_socket (GSocketListener  *listener,
  *
  * Note that adding an IPv6 address, depending on the platform,
  * may or may not result in a listener that also accepts IPv4
- * connections.  For more determinstic behaviour, see
+ * connections.  For more deterministic behavior, see
  * g_socket_listener_add_inet_port().
  *
  * @source_object will be passed out in the various calls
@@ -272,7 +274,7 @@ g_socket_listener_add_socket (GSocketListener  *listener,
  * different things depending on what address is connected to.
  *
  * If successful and @effective_address is non-%NULL then it will
- * be set to the address that the binding actually occured at.  This
+ * be set to the address that the binding actually occurred at.  This
  * is helpful for determining the port number that was used for when
  * requesting a binding to port 0 (ie: "any port").  This address, if
  * requested, belongs to the caller and must be freed.
@@ -344,7 +346,7 @@ g_socket_listener_add_address (GSocketListener  *listener,
  * g_socket_listener_add_inet_port:
  * @listener: a #GSocketListener
  * @port: an IP port number (non-zero)
- * @source_object: Optional #GObject identifying this source
+ * @source_object: (allow-none): Optional #GObject identifying this source
  * @error: #GError for error reporting, or %NULL to ignore.
  *
  * Helper function for g_socket_listener_add_address() that
@@ -563,7 +565,7 @@ accept_callback (GSocket      *socket,
  * g_socket_listener_accept_socket:
  * @listener: a #GSocketListener
  * @source_object: (out) (transfer none) (allow-none): location where #GObject pointer will be stored, or %NULL.
- * @cancellable: optional #GCancellable object, %NULL to ignore.
+ * @cancellable: (allow-none): optional #GCancellable object, %NULL to ignore.
  * @error: #GError for error reporting, or %NULL to ignore.
  *
  * Blocks waiting for a client to connect to any of the sockets added
@@ -640,7 +642,7 @@ g_socket_listener_accept_socket (GSocketListener  *listener,
  * g_socket_listener_accept:
  * @listener: a #GSocketListener
  * @source_object: (out) (transfer none) (allow-none): location where #GObject pointer will be stored, or %NULL
- * @cancellable: optional #GCancellable object, %NULL to ignore.
+ * @cancellable: (allow-none): optional #GCancellable object, %NULL to ignore.
  * @error: #GError for error reporting, or %NULL to ignore.
  *
  * Blocks waiting for a client to connect to any of the sockets added
@@ -681,53 +683,41 @@ g_socket_listener_accept (GSocketListener  *listener,
   return connection;
 }
 
-struct AcceptAsyncData {
-  GSimpleAsyncResult *simple;
-  GCancellable *cancellable;
-  GList *sources;
-};
-
 static gboolean
 accept_ready (GSocket      *accept_socket,
              GIOCondition  condition,
-             gpointer      _data)
+             gpointer      user_data)
 {
-  struct AcceptAsyncData *data = _data;
+  GTask *task = user_data;
   GError *error = NULL;
   GSocket *socket;
   GObject *source_object;
 
-  socket = g_socket_accept (accept_socket, data->cancellable, &error);
+  socket = g_socket_accept (accept_socket, g_task_get_cancellable (task), &error);
   if (socket)
     {
-      g_simple_async_result_set_op_res_gpointer (data->simple, socket,
-                                                g_object_unref);
       source_object = g_object_get_qdata (G_OBJECT (accept_socket), source_quark);
       if (source_object)
-       g_object_set_qdata_full (G_OBJECT (data->simple),
+       g_object_set_qdata_full (G_OBJECT (task),
                                 source_quark,
                                 g_object_ref (source_object), g_object_unref);
+      g_task_return_pointer (task, socket, g_object_unref);
     }
   else
     {
-      g_simple_async_result_set_from_error (data->simple, error);
-      g_error_free (error);
+      g_task_return_error (task, error);
     }
 
-  g_simple_async_result_complete_in_idle (data->simple);
-  g_object_unref (data->simple);
-  free_sources (data->sources);
-  g_free (data);
-
+  g_object_unref (task);
   return FALSE;
 }
 
 /**
  * g_socket_listener_accept_socket_async:
  * @listener: a #GSocketListener
- * @cancellable: a #GCancellable, or %NULL
- * @callback: a #GAsyncReadyCallback
- * @user_data: user data for the callback
+ * @cancellable: (allow-none): a #GCancellable, or %NULL
+ * @callback: (scope async): a #GAsyncReadyCallback
+ * @user_data: (closure): user data for the callback
  *
  * This is the asynchronous version of g_socket_listener_accept_socket().
  *
@@ -743,36 +733,33 @@ g_socket_listener_accept_socket_async (GSocketListener     *listener,
                                       GAsyncReadyCallback  callback,
                                       gpointer             user_data)
 {
-  struct AcceptAsyncData *data;
+  GTask *task;
+  GList *sources;
   GError *error = NULL;
 
+  task = g_task_new (listener, cancellable, callback, user_data);
+
   if (!check_listener (listener, &error))
     {
-      g_simple_async_report_gerror_in_idle (G_OBJECT (listener),
-                                           callback, user_data,
-                                           error);
-      g_error_free (error);
+      g_task_return_error (task, error);
+      g_object_unref (task);
       return;
     }
 
-  data = g_new0 (struct AcceptAsyncData, 1);
-  data->simple = g_simple_async_result_new (G_OBJECT (listener),
-                                           callback, user_data,
-                                           g_socket_listener_accept_socket_async);
-  data->cancellable = cancellable;
-  data->sources = add_sources (listener,
-                              accept_ready,
-                              data,
-                              cancellable,
-                              g_main_context_get_thread_default ());
+  sources = add_sources (listener,
+                        accept_ready,
+                        task,
+                        cancellable,
+                        g_main_context_get_thread_default ());
+  g_task_set_task_data (task, sources, (GDestroyNotify) free_sources);
 }
 
 /**
  * g_socket_listener_accept_socket_finish:
  * @listener: a #GSocketListener
  * @result: a #GAsyncResult.
- * @source_object: Optional #GObject identifying this source
- * @error: a #GError location to store the error occuring, or %NULL to
+ * @source_object: (out) (transfer none) (allow-none): Optional #GObject identifying this source
+ * @error: a #GError location to store the error occurring, or %NULL to
  * ignore.
  *
  * Finishes an async accept operation. See g_socket_listener_accept_socket_async()
@@ -787,32 +774,21 @@ g_socket_listener_accept_socket_finish (GSocketListener  *listener,
                                        GObject         **source_object,
                                        GError          **error)
 {
-  GSocket *socket;
-  GSimpleAsyncResult *simple;
-
   g_return_val_if_fail (G_IS_SOCKET_LISTENER (listener), NULL);
-
-  simple = G_SIMPLE_ASYNC_RESULT (result);
-
-  if (g_simple_async_result_propagate_error (simple, error))
-    return NULL;
-
-  g_warn_if_fail (g_simple_async_result_get_source_tag (simple) == g_socket_listener_accept_socket_async);
-
-  socket = g_simple_async_result_get_op_res_gpointer (simple);
+  g_return_val_if_fail (g_task_is_valid (result, listener), NULL);
 
   if (source_object)
     *source_object = g_object_get_qdata (G_OBJECT (result), source_quark);
 
-  return g_object_ref (socket);
+  return g_task_propagate_pointer (G_TASK (result), error);
 }
 
 /**
  * g_socket_listener_accept_async:
  * @listener: a #GSocketListener
- * @cancellable: a #GCancellable, or %NULL
- * @callback: a #GAsyncReadyCallback
- * @user_data: user data for the callback
+ * @cancellable: (allow-none): a #GCancellable, or %NULL
+ * @callback: (scope async): a #GAsyncReadyCallback
+ * @user_data: (closure): user data for the callback
  *
  * This is the asynchronous version of g_socket_listener_accept().
  *
@@ -838,8 +814,8 @@ g_socket_listener_accept_async (GSocketListener     *listener,
  * g_socket_listener_accept_finish:
  * @listener: a #GSocketListener
  * @result: a #GAsyncResult.
- * @source_object: Optional #GObject identifying this source
- * @error: a #GError location to store the error occuring, or %NULL to
+ * @source_object: (out) (transfer none) (allow-none): Optional #GObject identifying this source
+ * @error: a #GError location to store the error occurring, or %NULL to
  * ignore.
  *
  * Finishes an async accept operation. See g_socket_listener_accept_async()
@@ -929,12 +905,12 @@ g_socket_listener_close (GSocketListener *listener)
 /**
  * g_socket_listener_add_any_inet_port:
  * @listener: a #GSocketListener
- * @source_object: Optional #GObject identifying this source
- * @error: a #GError location to store the error occuring, or %NULL to
+ * @source_object: (allow-none): Optional #GObject identifying this source
+ * @error: a #GError location to store the error occurring, or %NULL to
  * ignore.
  *
  * Listens for TCP connections on any available port number for both
- * IPv6 and IPv4 (if each are available).
+ * IPv6 and IPv4 (if each is available).
  *
  * This is useful if you need to have a socket for incoming connections
  * but don't care about the specific port number.