gkdbus: Fix underflow and unreachable code bug
[platform/upstream/glib.git] / gio / gsocketconnection.c
index d60f198..67e8f3d 100644 (file)
@@ -4,10 +4,12 @@
  *           © 2008 codethink
  * Copyright © 2009 Red Hat, Inc
  *
+ * SPDX-License-Identifier: LGPL-2.1-or-later
+ *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
  * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
+ * version 2.1 of the License, or (at your option) any later version.
  *
  * This library is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -15,9 +17,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>
@@ -31,6 +31,7 @@
 
 #include "gsocketoutputstream.h"
 #include "gsocketinputstream.h"
+#include "gioprivate.h"
 #include <gio/giostream.h>
 #include <gio/gtask.h>
 #include "gunixconnection.h"
  * custom socket connection types for specific combination of socket
  * family/type/protocol using g_socket_connection_factory_register_type().
  *
+ * To close a #GSocketConnection, use g_io_stream_close(). Closing both
+ * substreams of the #GIOStream separately will not close the underlying
+ * #GSocket.
+ *
  * Since: 2.22
  */
 
-G_DEFINE_TYPE (GSocketConnection, g_socket_connection, G_TYPE_IO_STREAM);
-
 enum
 {
   PROP_NONE,
@@ -74,6 +77,8 @@ struct _GSocketConnectionPrivate
   GInputStream  *input_stream;
   GOutputStream *output_stream;
 
+  GSocketAddress *cached_remote_address;
+
   gboolean       in_dispose;
 };
 
@@ -89,6 +94,8 @@ static gboolean g_socket_connection_close_finish  (GIOStream            *stream,
                                                   GAsyncResult         *result,
                                                   GError              **error);
 
+G_DEFINE_TYPE_WITH_PRIVATE (GSocketConnection, g_socket_connection, G_TYPE_IO_STREAM)
+
 static GInputStream *
 g_socket_connection_get_input_stream (GIOStream *io_stream)
 {
@@ -134,7 +141,7 @@ g_socket_connection_is_connected (GSocketConnection  *connection)
  * g_socket_connection_connect:
  * @connection: a #GSocketConnection
  * @address: a #GSocketAddress specifying the remote address.
- * @cancellable: (allow-none): a %GCancellable or %NULL
+ * @cancellable: (nullable): a %GCancellable or %NULL
  * @error: #GError for error reporting, or %NULL to ignore.
  *
  * Connect @connection to the specified remote address.
@@ -164,9 +171,9 @@ static gboolean g_socket_connection_connect_callback (GSocket      *socket,
  * g_socket_connection_connect_async:
  * @connection: a #GSocketConnection
  * @address: a #GSocketAddress specifying the remote address.
- * @cancellable: (allow-none): a %GCancellable or %NULL
+ * @cancellable: (nullable): a %GCancellable or %NULL
  * @callback: (scope async): a #GAsyncReadyCallback
- * @user_data: (closure): user data for the callback
+ * @user_data: user data for the callback
  *
  * Asynchronously connect @connection to the specified remote address.
  *
@@ -191,6 +198,7 @@ g_socket_connection_connect_async (GSocketConnection   *connection,
   g_return_if_fail (G_IS_SOCKET_ADDRESS (address));
 
   task = g_task_new (connection, cancellable, callback, user_data);
+  g_task_set_source_tag (task, g_socket_connection_connect_async);
 
   g_socket_set_blocking (connection->priv->socket, FALSE);
 
@@ -267,7 +275,7 @@ g_socket_connection_connect_finish (GSocketConnection  *connection,
  * This can be useful if you want to do something unusual on it
  * not supported by the #GSocketConnection APIs.
  *
- * Returns: (transfer none): a #GSocketAddress or %NULL on error.
+ * Returns: (transfer none): a #GSocket or %NULL on error.
  *
  * Since: 2.22
  */
@@ -305,6 +313,13 @@ g_socket_connection_get_local_address (GSocketConnection  *connection,
  *
  * Try to get the remote address of a socket connection.
  *
+ * Since GLib 2.40, when used with g_socket_client_connect() or
+ * g_socket_client_connect_async(), during emission of
+ * %G_SOCKET_CLIENT_CONNECTING, this function will return the remote
+ * address that will be used for the connection.  This allows
+ * applications to print e.g. "Connecting to example.com
+ * (10.42.77.3)...".
+ *
  * Returns: (transfer full): a #GSocketAddress or %NULL on error.
  *     Free the returned object with g_object_unref().
  *
@@ -314,9 +329,27 @@ GSocketAddress *
 g_socket_connection_get_remote_address (GSocketConnection  *connection,
                                        GError            **error)
 {
+  if (!g_socket_is_connected (connection->priv->socket))
+    {
+      return connection->priv->cached_remote_address ?
+        g_object_ref (connection->priv->cached_remote_address) : NULL;
+    }
   return g_socket_get_remote_address (connection->priv->socket, error);
 }
 
+/* Private API allowing applications to retrieve the resolved address
+ * now, before we start connecting.
+ *
+ * https://bugzilla.gnome.org/show_bug.cgi?id=712547
+ */
+void
+g_socket_connection_set_cached_remote_address (GSocketConnection *connection,
+                                               GSocketAddress    *address)
+{
+  g_clear_object (&connection->priv->cached_remote_address);
+  connection->priv->cached_remote_address = address ? g_object_ref (address) : NULL;
+}
+
 static void
 g_socket_connection_get_property (GObject    *object,
                                   guint       prop_id,
@@ -358,7 +391,9 @@ g_socket_connection_set_property (GObject      *object,
 static void
 g_socket_connection_constructed (GObject *object)
 {
+#ifndef G_DISABLE_ASSERT
   GSocketConnection *connection = G_SOCKET_CONNECTION (object);
+#endif
 
   g_assert (connection->priv->socket != NULL);
 }
@@ -370,6 +405,8 @@ g_socket_connection_dispose (GObject *object)
 
   connection->priv->in_dispose = TRUE;
 
+  g_clear_object (&connection->priv->cached_remote_address);
+
   G_OBJECT_CLASS (g_socket_connection_parent_class)
     ->dispose (object);
 
@@ -399,8 +436,6 @@ g_socket_connection_class_init (GSocketConnectionClass *klass)
   GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
   GIOStreamClass *stream_class = G_IO_STREAM_CLASS (klass);
 
-  g_type_class_add_private (klass, sizeof (GSocketConnectionPrivate));
-
   gobject_class->set_property = g_socket_connection_set_property;
   gobject_class->get_property = g_socket_connection_get_property;
   gobject_class->constructed = g_socket_connection_constructed;
@@ -427,9 +462,7 @@ g_socket_connection_class_init (GSocketConnectionClass *klass)
 static void
 g_socket_connection_init (GSocketConnection *connection)
 {
-  connection->priv = G_TYPE_INSTANCE_GET_PRIVATE (connection,
-                                                  G_TYPE_SOCKET_CONNECTION,
-                                                  GSocketConnectionPrivate);
+  connection->priv = g_socket_connection_get_instance_private (connection);
 }
 
 static gboolean
@@ -473,6 +506,7 @@ g_socket_connection_close_async (GIOStream           *stream,
   class = G_IO_STREAM_GET_CLASS (stream);
 
   task = g_task_new (stream, cancellable, callback, user_data);
+  g_task_set_source_tag (task, g_socket_connection_close_async);
 
   /* socket close is not blocked, just do it! */
   error = NULL;
@@ -583,9 +617,7 @@ g_socket_connection_factory_register_type (GType         g_type,
 static void
 init_builtin_types (void)
 {
-#ifndef G_OS_WIN32
   g_type_ensure (G_TYPE_UNIX_CONNECTION);
-#endif
   g_type_ensure (G_TYPE_TCP_CONNECTION);
 }