LCOV - code coverage report
Current view: top level - glib/gio - gsocketclient.c (source / functions) Hit Total Coverage
Test: unnamed Lines: 530 694 76.4 %
Date: 2024-04-23 05:16:05 Functions: 56 67 83.6 %
Branches: 202 312 64.7 %

           Branch data     Line data    Source code
       1                 :            : /*  GIO - GLib Input, Output and Streaming Library
       2                 :            :  *
       3                 :            :  * Copyright © 2008, 2009 codethink
       4                 :            :  * Copyright © 2009 Red Hat, Inc
       5                 :            :  * Copyright © 2018 Igalia S.L.
       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: Ryan Lortie <desrt@desrt.ca>
      23                 :            :  *          Alexander Larsson <alexl@redhat.com>
      24                 :            :  */
      25                 :            : 
      26                 :            : #include "config.h"
      27                 :            : #include "gsocketclient.h"
      28                 :            : 
      29                 :            : #ifndef G_OS_WIN32
      30                 :            : #include <netinet/in.h>
      31                 :            : #endif
      32                 :            : 
      33                 :            : #include <stdlib.h>
      34                 :            : #include <string.h>
      35                 :            : 
      36                 :            : #include <gio/gioenumtypes.h>
      37                 :            : #include <gio/gsocketaddressenumerator.h>
      38                 :            : #include <gio/gsocketconnectable.h>
      39                 :            : #include <gio/gsocketconnection.h>
      40                 :            : #include <gio/gioprivate.h>
      41                 :            : #include <gio/gproxyaddressenumerator.h>
      42                 :            : #include <gio/gproxyaddress.h>
      43                 :            : #include <gio/gtask.h>
      44                 :            : #include <gio/gcancellable.h>
      45                 :            : #include <gio/gioerror.h>
      46                 :            : #include <gio/gsocket.h>
      47                 :            : #include <gio/gnetworkaddress.h>
      48                 :            : #include <gio/gnetworking.h>
      49                 :            : #include <gio/gnetworkservice.h>
      50                 :            : #include <gio/gproxy.h>
      51                 :            : #include <gio/gproxyresolver.h>
      52                 :            : #include <gio/gsocketaddress.h>
      53                 :            : #include <gio/gtcpconnection.h>
      54                 :            : #include <gio/gtcpwrapperconnection.h>
      55                 :            : #include <gio/gtlscertificate.h>
      56                 :            : #include <gio/gtlsclientconnection.h>
      57                 :            : #include <gio/ginetaddress.h>
      58                 :            : #include "glibintl.h"
      59                 :            : #include "gmarshal-internal.h"
      60                 :            : 
      61                 :            : /* As recommended by RFC 8305 this is the time it waits
      62                 :            :  * on a connection before starting another concurrent attempt.
      63                 :            :  *
      64                 :            :  * See https://datatracker.ietf.org/doc/html/rfc8305#section-8
      65                 :            :  */
      66                 :            : #define HAPPY_EYEBALLS_CONNECTION_ATTEMPT_DELAY_MS 250
      67                 :            : 
      68                 :            : /**
      69                 :            :  * GSocketClient:
      70                 :            :  *
      71                 :            :  * `GSocketClient` is a lightweight high-level utility class for connecting to
      72                 :            :  * a network host using a connection oriented socket type.
      73                 :            :  *
      74                 :            :  * You create a `GSocketClient` object, set any options you want, and then
      75                 :            :  * call a sync or async connect operation, which returns a
      76                 :            :  * [class@Gio.SocketConnection] subclass on success.
      77                 :            :  *
      78                 :            :  * The type of the [class@Gio.SocketConnection] object returned depends on the
      79                 :            :  * type of the underlying socket that is in use. For instance, for a TCP/IP
      80                 :            :  * connection it will be a [class@Gio.TcpConnection].
      81                 :            :  *
      82                 :            :  * As `GSocketClient` is a lightweight object, you don't need to cache it. You
      83                 :            :  * can just create a new one any time you need one.
      84                 :            :  *
      85                 :            :  * Since: 2.22
      86                 :            :  */
      87                 :            : 
      88                 :            : 
      89                 :            : enum
      90                 :            : {
      91                 :            :   EVENT,
      92                 :            :   LAST_SIGNAL
      93                 :            : };
      94                 :            : 
      95                 :            : static guint signals[LAST_SIGNAL] = { 0 };
      96                 :            : 
      97                 :            : enum
      98                 :            : {
      99                 :            :   PROP_NONE,
     100                 :            :   PROP_FAMILY,
     101                 :            :   PROP_TYPE,
     102                 :            :   PROP_PROTOCOL,
     103                 :            :   PROP_LOCAL_ADDRESS,
     104                 :            :   PROP_TIMEOUT,
     105                 :            :   PROP_ENABLE_PROXY,
     106                 :            :   PROP_TLS,
     107                 :            :   PROP_TLS_VALIDATION_FLAGS,
     108                 :            :   PROP_PROXY_RESOLVER
     109                 :            : };
     110                 :            : 
     111                 :            : struct _GSocketClientPrivate
     112                 :            : {
     113                 :            :   GSocketFamily family;
     114                 :            :   GSocketType type;
     115                 :            :   GSocketProtocol protocol;
     116                 :            :   GSocketAddress *local_address;
     117                 :            :   guint timeout;
     118                 :            :   gboolean enable_proxy;
     119                 :            :   GHashTable *app_proxies;
     120                 :            :   gboolean tls;
     121                 :            :   GTlsCertificateFlags tls_validation_flags;
     122                 :            :   GProxyResolver *proxy_resolver;
     123                 :            : };
     124                 :            : 
     125   [ +  +  +  -  :      15511 : G_DEFINE_TYPE_WITH_PRIVATE (GSocketClient, g_socket_client, G_TYPE_OBJECT)
                   +  + ]
     126                 :            : 
     127                 :            : static GSocket *
     128                 :       1266 : create_socket (GSocketClient  *client,
     129                 :            :                GSocketAddress *dest_address,
     130                 :            :                GError        **error)
     131                 :            : {
     132                 :            :   GSocketFamily family;
     133                 :            :   GSocket *socket;
     134                 :            : 
     135                 :       1266 :   family = client->priv->family;
     136         [ +  - ]:       1266 :   if (family == G_SOCKET_FAMILY_INVALID &&
     137         [ -  + ]:       1266 :       client->priv->local_address != NULL)
     138                 :          0 :     family = g_socket_address_get_family (client->priv->local_address);
     139         [ +  - ]:       1266 :   if (family == G_SOCKET_FAMILY_INVALID)
     140                 :       1266 :     family = g_socket_address_get_family (dest_address);
     141                 :            : 
     142                 :       1266 :   socket = g_socket_new (family,
     143                 :       1266 :                          client->priv->type,
     144                 :       1266 :                          client->priv->protocol,
     145                 :            :                          error);
     146         [ -  + ]:       1266 :   if (socket == NULL)
     147                 :          0 :     return NULL;
     148                 :            : 
     149         [ -  + ]:       1266 :   if (client->priv->local_address)
     150                 :            :     {
     151                 :            : #ifdef IP_BIND_ADDRESS_NO_PORT
     152                 :          0 :       g_socket_set_option (socket, IPPROTO_IP, IP_BIND_ADDRESS_NO_PORT, 1, NULL);
     153                 :            : #endif
     154                 :            : 
     155         [ #  # ]:          0 :       if (!g_socket_bind (socket,
     156                 :          0 :                           client->priv->local_address,
     157                 :            :                           FALSE,
     158                 :            :                           error))
     159                 :            :         {
     160                 :          0 :           g_object_unref (socket);
     161                 :          0 :           return NULL;
     162                 :            :         }
     163                 :            :     }
     164                 :            : 
     165         [ -  + ]:       1266 :   if (client->priv->timeout)
     166                 :          0 :     g_socket_set_timeout (socket, client->priv->timeout);
     167                 :            : 
     168                 :       1266 :   return socket;
     169                 :            : }
     170                 :            : 
     171                 :            : static gboolean
     172                 :       1271 : can_use_proxy (GSocketClient *client)
     173                 :            : {
     174                 :       1271 :   GSocketClientPrivate *priv = client->priv;
     175                 :            : 
     176                 :       1271 :   return priv->enable_proxy
     177   [ +  +  +  - ]:       1271 :           && priv->type == G_SOCKET_TYPE_STREAM;
     178                 :            : }
     179                 :            : 
     180                 :            : static void
     181                 :         26 : clarify_connect_error (GError             *error,
     182                 :            :                        GSocketConnectable *connectable,
     183                 :            :                        GSocketAddress     *address)
     184                 :            : {
     185                 :            :   const char *name;
     186                 :         26 :   char *tmp_name = NULL;
     187                 :            : 
     188   [ -  +  +  -  :         26 :   if (G_IS_PROXY_ADDRESS (address))
             -  +  -  + ]
     189                 :            :     {
     190                 :          0 :       name = tmp_name = g_inet_address_to_string (g_inet_socket_address_get_address (G_INET_SOCKET_ADDRESS (address)));
     191                 :            : 
     192                 :          0 :       g_prefix_error (&error, _("Could not connect to proxy server %s: "), name);
     193                 :            :     }
     194                 :            :   else
     195                 :            :     {
     196   [ -  +  +  -  :         26 :       if (G_IS_NETWORK_ADDRESS (connectable))
             -  +  -  + ]
     197                 :          0 :         name = g_network_address_get_hostname (G_NETWORK_ADDRESS (connectable));
     198   [ -  +  +  -  :         26 :       else if (G_IS_NETWORK_SERVICE (connectable))
             -  +  -  + ]
     199                 :          0 :         name = g_network_service_get_domain (G_NETWORK_SERVICE (connectable));
     200   [ -  +  +  -  :         26 :       else if (G_IS_INET_SOCKET_ADDRESS (connectable))
             -  +  -  + ]
     201                 :          0 :         name = tmp_name = g_inet_address_to_string (g_inet_socket_address_get_address (G_INET_SOCKET_ADDRESS (connectable)));
     202                 :            :       else
     203                 :         26 :         name = NULL;
     204                 :            : 
     205         [ -  + ]:         26 :       if (name)
     206                 :          0 :         g_prefix_error (&error, _("Could not connect to %s: "), name);
     207                 :            :       else
     208                 :         26 :         g_prefix_error (&error, _("Could not connect: "));
     209                 :            :     }
     210                 :            : 
     211                 :         26 :   g_free (tmp_name);
     212                 :         26 : }
     213                 :            : 
     214                 :            : static void
     215                 :       1253 : g_socket_client_init (GSocketClient *client)
     216                 :            : {
     217                 :       1253 :   client->priv = g_socket_client_get_instance_private (client);
     218                 :       1253 :   client->priv->type = G_SOCKET_TYPE_STREAM;
     219                 :       1253 :   client->priv->app_proxies = g_hash_table_new_full (g_str_hash,
     220                 :            :                                                      g_str_equal,
     221                 :            :                                                      g_free,
     222                 :            :                                                      NULL);
     223                 :       1253 : }
     224                 :            : 
     225                 :            : /**
     226                 :            :  * g_socket_client_new:
     227                 :            :  *
     228                 :            :  * Creates a new #GSocketClient with the default options.
     229                 :            :  *
     230                 :            :  * Returns: a #GSocketClient.
     231                 :            :  *     Free the returned object with g_object_unref().
     232                 :            :  *
     233                 :            :  * Since: 2.22
     234                 :            :  */
     235                 :            : GSocketClient *
     236                 :       1252 : g_socket_client_new (void)
     237                 :            : {
     238                 :       1252 :   return g_object_new (G_TYPE_SOCKET_CLIENT, NULL);
     239                 :            : }
     240                 :            : 
     241                 :            : static void
     242                 :       1252 : g_socket_client_finalize (GObject *object)
     243                 :            : {
     244                 :       1252 :   GSocketClient *client = G_SOCKET_CLIENT (object);
     245                 :            : 
     246                 :       1252 :   g_clear_object (&client->priv->local_address);
     247                 :       1252 :   g_clear_object (&client->priv->proxy_resolver);
     248                 :            : 
     249                 :       1252 :   G_OBJECT_CLASS (g_socket_client_parent_class)->finalize (object);
     250                 :            : 
     251                 :       1252 :   g_hash_table_unref (client->priv->app_proxies);
     252                 :       1252 : }
     253                 :            : 
     254                 :            : static void
     255                 :         37 : g_socket_client_get_property (GObject    *object,
     256                 :            :                               guint       prop_id,
     257                 :            :                               GValue     *value,
     258                 :            :                               GParamSpec *pspec)
     259                 :            : {
     260                 :         37 :   GSocketClient *client = G_SOCKET_CLIENT (object);
     261                 :            : 
     262   [ +  +  +  +  :         37 :   switch (prop_id)
          +  +  +  +  -  
                      - ]
     263                 :            :     {
     264                 :          1 :       case PROP_FAMILY:
     265                 :          1 :         g_value_set_enum (value, client->priv->family);
     266                 :          1 :         break;
     267                 :            : 
     268                 :          8 :       case PROP_TYPE:
     269                 :          8 :         g_value_set_enum (value, client->priv->type);
     270                 :          8 :         break;
     271                 :            : 
     272                 :          1 :       case PROP_PROTOCOL:
     273                 :          1 :         g_value_set_enum (value, client->priv->protocol);
     274                 :          1 :         break;
     275                 :            : 
     276                 :          1 :       case PROP_LOCAL_ADDRESS:
     277                 :          1 :         g_value_set_object (value, client->priv->local_address);
     278                 :          1 :         break;
     279                 :            : 
     280                 :          1 :       case PROP_TIMEOUT:
     281                 :          1 :         g_value_set_uint (value, client->priv->timeout);
     282                 :          1 :         break;
     283                 :            : 
     284                 :         12 :       case PROP_ENABLE_PROXY:
     285                 :         12 :         g_value_set_boolean (value, client->priv->enable_proxy);
     286                 :         12 :         break;
     287                 :            : 
     288                 :         12 :       case PROP_TLS:
     289                 :         12 :         g_value_set_boolean (value, g_socket_client_get_tls (client));
     290                 :         12 :         break;
     291                 :            : 
     292                 :          1 :       case PROP_TLS_VALIDATION_FLAGS:
     293                 :            : G_GNUC_BEGIN_IGNORE_DEPRECATIONS
     294                 :          1 :         g_value_set_flags (value, g_socket_client_get_tls_validation_flags (client));
     295                 :            : G_GNUC_END_IGNORE_DEPRECATIONS
     296                 :          1 :         break;
     297                 :            : 
     298                 :          0 :       case PROP_PROXY_RESOLVER:
     299                 :          0 :         g_value_set_object (value, g_socket_client_get_proxy_resolver (client));
     300                 :          0 :         break;
     301                 :            : 
     302                 :          0 :       default:
     303                 :          0 :         G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
     304                 :            :     }
     305                 :         37 : }
     306                 :            : 
     307                 :            : static void
     308                 :      11285 : g_socket_client_set_property (GObject      *object,
     309                 :            :                               guint         prop_id,
     310                 :            :                               const GValue *value,
     311                 :            :                               GParamSpec   *pspec)
     312                 :            : {
     313                 :      11285 :   GSocketClient *client = G_SOCKET_CLIENT (object);
     314                 :            : 
     315   [ +  +  +  +  :      11285 :   switch (prop_id)
          +  +  +  +  +  
                      - ]
     316                 :            :     {
     317                 :       1253 :     case PROP_FAMILY:
     318                 :       1253 :       g_socket_client_set_family (client, g_value_get_enum (value));
     319                 :       1253 :       break;
     320                 :            : 
     321                 :       1255 :     case PROP_TYPE:
     322                 :       1255 :       g_socket_client_set_socket_type (client, g_value_get_enum (value));
     323                 :       1255 :       break;
     324                 :            : 
     325                 :       1253 :     case PROP_PROTOCOL:
     326                 :       1253 :       g_socket_client_set_protocol (client, g_value_get_enum (value));
     327                 :       1253 :       break;
     328                 :            : 
     329                 :       1253 :     case PROP_LOCAL_ADDRESS:
     330                 :       1253 :       g_socket_client_set_local_address (client, g_value_get_object (value));
     331                 :       1253 :       break;
     332                 :            : 
     333                 :       1253 :     case PROP_TIMEOUT:
     334                 :       1253 :       g_socket_client_set_timeout (client, g_value_get_uint (value));
     335                 :       1253 :       break;
     336                 :            : 
     337                 :       1256 :     case PROP_ENABLE_PROXY:
     338                 :       1256 :       g_socket_client_set_enable_proxy (client, g_value_get_boolean (value));
     339                 :       1256 :       break;
     340                 :            : 
     341                 :       1256 :     case PROP_TLS:
     342                 :       1256 :       g_socket_client_set_tls (client, g_value_get_boolean (value));
     343                 :       1256 :       break;
     344                 :            : 
     345                 :       1253 :     case PROP_TLS_VALIDATION_FLAGS:
     346                 :            : G_GNUC_BEGIN_IGNORE_DEPRECATIONS
     347                 :       1253 :       g_socket_client_set_tls_validation_flags (client, g_value_get_flags (value));
     348                 :            : G_GNUC_END_IGNORE_DEPRECATIONS
     349                 :       1253 :       break;
     350                 :            : 
     351                 :       1253 :     case PROP_PROXY_RESOLVER:
     352                 :       1253 :       g_socket_client_set_proxy_resolver (client, g_value_get_object (value));
     353                 :       1253 :       break;
     354                 :            : 
     355                 :          0 :     default:
     356                 :          0 :       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
     357                 :            :     }
     358                 :      11285 : }
     359                 :            : 
     360                 :            : /**
     361                 :            :  * g_socket_client_get_family:
     362                 :            :  * @client: a #GSocketClient.
     363                 :            :  *
     364                 :            :  * Gets the socket family of the socket client.
     365                 :            :  *
     366                 :            :  * See g_socket_client_set_family() for details.
     367                 :            :  *
     368                 :            :  * Returns: a #GSocketFamily
     369                 :            :  *
     370                 :            :  * Since: 2.22
     371                 :            :  */
     372                 :            : GSocketFamily
     373                 :          0 : g_socket_client_get_family (GSocketClient *client)
     374                 :            : {
     375                 :          0 :   return client->priv->family;
     376                 :            : }
     377                 :            : 
     378                 :            : /**
     379                 :            :  * g_socket_client_set_family:
     380                 :            :  * @client: a #GSocketClient.
     381                 :            :  * @family: a #GSocketFamily
     382                 :            :  *
     383                 :            :  * Sets the socket family of the socket client.
     384                 :            :  * If this is set to something other than %G_SOCKET_FAMILY_INVALID
     385                 :            :  * then the sockets created by this object will be of the specified
     386                 :            :  * family.
     387                 :            :  *
     388                 :            :  * This might be useful for instance if you want to force the local
     389                 :            :  * connection to be an ipv4 socket, even though the address might
     390                 :            :  * be an ipv6 mapped to ipv4 address.
     391                 :            :  *
     392                 :            :  * Since: 2.22
     393                 :            :  */
     394                 :            : void
     395                 :       1253 : g_socket_client_set_family (GSocketClient *client,
     396                 :            :                             GSocketFamily  family)
     397                 :            : {
     398         [ +  - ]:       1253 :   if (client->priv->family == family)
     399                 :       1253 :     return;
     400                 :            : 
     401                 :          0 :   client->priv->family = family;
     402                 :          0 :   g_object_notify (G_OBJECT (client), "family");
     403                 :            : }
     404                 :            : 
     405                 :            : /**
     406                 :            :  * g_socket_client_get_socket_type:
     407                 :            :  * @client: a #GSocketClient.
     408                 :            :  *
     409                 :            :  * Gets the socket type of the socket client.
     410                 :            :  *
     411                 :            :  * See g_socket_client_set_socket_type() for details.
     412                 :            :  *
     413                 :            :  * Returns: a #GSocketFamily
     414                 :            :  *
     415                 :            :  * Since: 2.22
     416                 :            :  */
     417                 :            : GSocketType
     418                 :          2 : g_socket_client_get_socket_type (GSocketClient *client)
     419                 :            : {
     420                 :          2 :   return client->priv->type;
     421                 :            : }
     422                 :            : 
     423                 :            : /**
     424                 :            :  * g_socket_client_set_socket_type:
     425                 :            :  * @client: a #GSocketClient.
     426                 :            :  * @type: a #GSocketType
     427                 :            :  *
     428                 :            :  * Sets the socket type of the socket client.
     429                 :            :  * The sockets created by this object will be of the specified
     430                 :            :  * type.
     431                 :            :  *
     432                 :            :  * It doesn't make sense to specify a type of %G_SOCKET_TYPE_DATAGRAM,
     433                 :            :  * as GSocketClient is used for connection oriented services.
     434                 :            :  *
     435                 :            :  * Since: 2.22
     436                 :            :  */
     437                 :            : void
     438                 :       1256 : g_socket_client_set_socket_type (GSocketClient *client,
     439                 :            :                                  GSocketType    type)
     440                 :            : {
     441         [ +  + ]:       1256 :   if (client->priv->type == type)
     442                 :       1253 :     return;
     443                 :            : 
     444                 :          3 :   client->priv->type = type;
     445                 :          3 :   g_object_notify (G_OBJECT (client), "type");
     446                 :            : }
     447                 :            : 
     448                 :            : /**
     449                 :            :  * g_socket_client_get_protocol:
     450                 :            :  * @client: a #GSocketClient
     451                 :            :  *
     452                 :            :  * Gets the protocol name type of the socket client.
     453                 :            :  *
     454                 :            :  * See g_socket_client_set_protocol() for details.
     455                 :            :  *
     456                 :            :  * Returns: a #GSocketProtocol
     457                 :            :  *
     458                 :            :  * Since: 2.22
     459                 :            :  */
     460                 :            : GSocketProtocol
     461                 :          0 : g_socket_client_get_protocol (GSocketClient *client)
     462                 :            : {
     463                 :          0 :   return client->priv->protocol;
     464                 :            : }
     465                 :            : 
     466                 :            : /**
     467                 :            :  * g_socket_client_set_protocol:
     468                 :            :  * @client: a #GSocketClient.
     469                 :            :  * @protocol: a #GSocketProtocol
     470                 :            :  *
     471                 :            :  * Sets the protocol of the socket client.
     472                 :            :  * The sockets created by this object will use of the specified
     473                 :            :  * protocol.
     474                 :            :  *
     475                 :            :  * If @protocol is %G_SOCKET_PROTOCOL_DEFAULT that means to use the default
     476                 :            :  * protocol for the socket family and type.
     477                 :            :  *
     478                 :            :  * Since: 2.22
     479                 :            :  */
     480                 :            : void
     481                 :       1253 : g_socket_client_set_protocol (GSocketClient   *client,
     482                 :            :                               GSocketProtocol  protocol)
     483                 :            : {
     484         [ +  - ]:       1253 :   if (client->priv->protocol == protocol)
     485                 :       1253 :     return;
     486                 :            : 
     487                 :          0 :   client->priv->protocol = protocol;
     488                 :          0 :   g_object_notify (G_OBJECT (client), "protocol");
     489                 :            : }
     490                 :            : 
     491                 :            : /**
     492                 :            :  * g_socket_client_get_local_address:
     493                 :            :  * @client: a #GSocketClient.
     494                 :            :  *
     495                 :            :  * Gets the local address of the socket client.
     496                 :            :  *
     497                 :            :  * See g_socket_client_set_local_address() for details.
     498                 :            :  *
     499                 :            :  * Returns: (nullable) (transfer none): a #GSocketAddress or %NULL. Do not free.
     500                 :            :  *
     501                 :            :  * Since: 2.22
     502                 :            :  */
     503                 :            : GSocketAddress *
     504                 :          0 : g_socket_client_get_local_address (GSocketClient *client)
     505                 :            : {
     506                 :          0 :   return client->priv->local_address;
     507                 :            : }
     508                 :            : 
     509                 :            : /**
     510                 :            :  * g_socket_client_set_local_address:
     511                 :            :  * @client: a #GSocketClient.
     512                 :            :  * @address: (nullable): a #GSocketAddress, or %NULL
     513                 :            :  *
     514                 :            :  * Sets the local address of the socket client.
     515                 :            :  * The sockets created by this object will bound to the
     516                 :            :  * specified address (if not %NULL) before connecting.
     517                 :            :  *
     518                 :            :  * This is useful if you want to ensure that the local
     519                 :            :  * side of the connection is on a specific port, or on
     520                 :            :  * a specific interface.
     521                 :            :  *
     522                 :            :  * Since: 2.22
     523                 :            :  */
     524                 :            : void
     525                 :       1253 : g_socket_client_set_local_address (GSocketClient  *client,
     526                 :            :                                    GSocketAddress *address)
     527                 :            : {
     528         [ -  + ]:       1253 :   if (address)
     529                 :          0 :     g_object_ref (address);
     530                 :            : 
     531         [ -  + ]:       1253 :   if (client->priv->local_address)
     532                 :            :     {
     533                 :          0 :       g_object_unref (client->priv->local_address);
     534                 :            :     }
     535                 :       1253 :   client->priv->local_address = address;
     536                 :       1253 :   g_object_notify (G_OBJECT (client), "local-address");
     537                 :       1253 : }
     538                 :            : 
     539                 :            : /**
     540                 :            :  * g_socket_client_get_timeout:
     541                 :            :  * @client: a #GSocketClient
     542                 :            :  *
     543                 :            :  * Gets the I/O timeout time for sockets created by @client.
     544                 :            :  *
     545                 :            :  * See g_socket_client_set_timeout() for details.
     546                 :            :  *
     547                 :            :  * Returns: the timeout in seconds
     548                 :            :  *
     549                 :            :  * Since: 2.26
     550                 :            :  */
     551                 :            : guint
     552                 :          0 : g_socket_client_get_timeout (GSocketClient *client)
     553                 :            : {
     554                 :          0 :   return client->priv->timeout;
     555                 :            : }
     556                 :            : 
     557                 :            : 
     558                 :            : /**
     559                 :            :  * g_socket_client_set_timeout:
     560                 :            :  * @client: a #GSocketClient.
     561                 :            :  * @timeout: the timeout
     562                 :            :  *
     563                 :            :  * Sets the I/O timeout for sockets created by @client. @timeout is a
     564                 :            :  * time in seconds, or 0 for no timeout (the default).
     565                 :            :  *
     566                 :            :  * The timeout value affects the initial connection attempt as well,
     567                 :            :  * so setting this may cause calls to g_socket_client_connect(), etc,
     568                 :            :  * to fail with %G_IO_ERROR_TIMED_OUT.
     569                 :            :  *
     570                 :            :  * Since: 2.26
     571                 :            :  */
     572                 :            : void
     573                 :       1253 : g_socket_client_set_timeout (GSocketClient *client,
     574                 :            :                              guint          timeout)
     575                 :            : {
     576         [ +  - ]:       1253 :   if (client->priv->timeout == timeout)
     577                 :       1253 :     return;
     578                 :            : 
     579                 :          0 :   client->priv->timeout = timeout;
     580                 :          0 :   g_object_notify (G_OBJECT (client), "timeout");
     581                 :            : }
     582                 :            : 
     583                 :            : /**
     584                 :            :  * g_socket_client_get_enable_proxy:
     585                 :            :  * @client: a #GSocketClient.
     586                 :            :  *
     587                 :            :  * Gets the proxy enable state; see g_socket_client_set_enable_proxy()
     588                 :            :  *
     589                 :            :  * Returns: whether proxying is enabled
     590                 :            :  *
     591                 :            :  * Since: 2.26
     592                 :            :  */
     593                 :            : gboolean
     594                 :          4 : g_socket_client_get_enable_proxy (GSocketClient *client)
     595                 :            : {
     596                 :          4 :   return client->priv->enable_proxy;
     597                 :            : }
     598                 :            : 
     599                 :            : /**
     600                 :            :  * g_socket_client_set_enable_proxy:
     601                 :            :  * @client: a #GSocketClient.
     602                 :            :  * @enable: whether to enable proxies
     603                 :            :  *
     604                 :            :  * Sets whether or not @client attempts to make connections via a
     605                 :            :  * proxy server. When enabled (the default), #GSocketClient will use a
     606                 :            :  * #GProxyResolver to determine if a proxy protocol such as SOCKS is
     607                 :            :  * needed, and automatically do the necessary proxy negotiation.
     608                 :            :  *
     609                 :            :  * See also g_socket_client_set_proxy_resolver().
     610                 :            :  *
     611                 :            :  * Since: 2.26
     612                 :            :  */
     613                 :            : void
     614                 :       2487 : g_socket_client_set_enable_proxy (GSocketClient *client,
     615                 :            :                                   gboolean       enable)
     616                 :            : {
     617                 :       2487 :   enable = !!enable;
     618         [ -  + ]:       2487 :   if (client->priv->enable_proxy == enable)
     619                 :          0 :     return;
     620                 :            : 
     621                 :       2487 :   client->priv->enable_proxy = enable;
     622                 :       2487 :   g_object_notify (G_OBJECT (client), "enable-proxy");
     623                 :            : }
     624                 :            : 
     625                 :            : /**
     626                 :            :  * g_socket_client_get_tls:
     627                 :            :  * @client: a #GSocketClient.
     628                 :            :  *
     629                 :            :  * Gets whether @client creates TLS connections. See
     630                 :            :  * g_socket_client_set_tls() for details.
     631                 :            :  *
     632                 :            :  * Returns: whether @client uses TLS
     633                 :            :  *
     634                 :            :  * Since: 2.28
     635                 :            :  */
     636                 :            : gboolean
     637                 :         15 : g_socket_client_get_tls (GSocketClient *client)
     638                 :            : {
     639                 :         15 :   return client->priv->tls;
     640                 :            : }
     641                 :            : 
     642                 :            : /**
     643                 :            :  * g_socket_client_set_tls:
     644                 :            :  * @client: a #GSocketClient.
     645                 :            :  * @tls: whether to use TLS
     646                 :            :  *
     647                 :            :  * Sets whether @client creates TLS (aka SSL) connections. If @tls is
     648                 :            :  * %TRUE, @client will wrap its connections in a #GTlsClientConnection
     649                 :            :  * and perform a TLS handshake when connecting.
     650                 :            :  *
     651                 :            :  * Note that since #GSocketClient must return a #GSocketConnection,
     652                 :            :  * but #GTlsClientConnection is not a #GSocketConnection, this
     653                 :            :  * actually wraps the resulting #GTlsClientConnection in a
     654                 :            :  * #GTcpWrapperConnection when returning it. You can use
     655                 :            :  * g_tcp_wrapper_connection_get_base_io_stream() on the return value
     656                 :            :  * to extract the #GTlsClientConnection.
     657                 :            :  *
     658                 :            :  * If you need to modify the behavior of the TLS handshake (eg, by
     659                 :            :  * setting a client-side certificate to use, or connecting to the
     660                 :            :  * #GTlsConnection::accept-certificate signal), you can connect to
     661                 :            :  * @client's #GSocketClient::event signal and wait for it to be
     662                 :            :  * emitted with %G_SOCKET_CLIENT_TLS_HANDSHAKING, which will give you
     663                 :            :  * a chance to see the #GTlsClientConnection before the handshake
     664                 :            :  * starts.
     665                 :            :  *
     666                 :            :  * Since: 2.28
     667                 :            :  */
     668                 :            : void
     669                 :       1257 : g_socket_client_set_tls (GSocketClient *client,
     670                 :            :                          gboolean       tls)
     671                 :            : {
     672                 :       1257 :   tls = !!tls;
     673         [ +  + ]:       1257 :   if (tls == client->priv->tls)
     674                 :       1253 :     return;
     675                 :            : 
     676                 :          4 :   client->priv->tls = tls;
     677                 :          4 :   g_object_notify (G_OBJECT (client), "tls");
     678                 :            : }
     679                 :            : 
     680                 :            : /**
     681                 :            :  * g_socket_client_get_tls_validation_flags:
     682                 :            :  * @client: a #GSocketClient.
     683                 :            :  *
     684                 :            :  * Gets the TLS validation flags used creating TLS connections via
     685                 :            :  * @client.
     686                 :            :  *
     687                 :            :  * This function does not work as originally designed and is impossible
     688                 :            :  * to use correctly. See #GSocketClient:tls-validation-flags for more
     689                 :            :  * information.
     690                 :            :  *
     691                 :            :  * Returns: the TLS validation flags
     692                 :            :  *
     693                 :            :  * Since: 2.28
     694                 :            :  *
     695                 :            :  * Deprecated: 2.72: Do not attempt to ignore validation errors.
     696                 :            :  */
     697                 :            : GTlsCertificateFlags
     698                 :          1 : g_socket_client_get_tls_validation_flags (GSocketClient *client)
     699                 :            : {
     700                 :          1 :   return client->priv->tls_validation_flags;
     701                 :            : }
     702                 :            : 
     703                 :            : /**
     704                 :            :  * g_socket_client_set_tls_validation_flags:
     705                 :            :  * @client: a #GSocketClient.
     706                 :            :  * @flags: the validation flags
     707                 :            :  *
     708                 :            :  * Sets the TLS validation flags used when creating TLS connections
     709                 :            :  * via @client. The default value is %G_TLS_CERTIFICATE_VALIDATE_ALL.
     710                 :            :  *
     711                 :            :  * This function does not work as originally designed and is impossible
     712                 :            :  * to use correctly. See #GSocketClient:tls-validation-flags for more
     713                 :            :  * information.
     714                 :            :  *
     715                 :            :  * Since: 2.28
     716                 :            :  *
     717                 :            :  * Deprecated: 2.72: Do not attempt to ignore validation errors.
     718                 :            :  */
     719                 :            : void
     720                 :       1253 : g_socket_client_set_tls_validation_flags (GSocketClient        *client,
     721                 :            :                                           GTlsCertificateFlags  flags)
     722                 :            : {
     723         [ +  - ]:       1253 :   if (client->priv->tls_validation_flags != flags)
     724                 :            :     {
     725                 :       1253 :       client->priv->tls_validation_flags = flags;
     726                 :       1253 :       g_object_notify (G_OBJECT (client), "tls-validation-flags");
     727                 :            :     }
     728                 :       1253 : }
     729                 :            : 
     730                 :            : /**
     731                 :            :  * g_socket_client_get_proxy_resolver:
     732                 :            :  * @client: a #GSocketClient.
     733                 :            :  *
     734                 :            :  * Gets the #GProxyResolver being used by @client. Normally, this will
     735                 :            :  * be the resolver returned by g_proxy_resolver_get_default(), but you
     736                 :            :  * can override it with g_socket_client_set_proxy_resolver().
     737                 :            :  *
     738                 :            :  * Returns: (transfer none): The #GProxyResolver being used by
     739                 :            :  *   @client.
     740                 :            :  *
     741                 :            :  * Since: 2.36
     742                 :            :  */
     743                 :            : GProxyResolver *
     744                 :          4 : g_socket_client_get_proxy_resolver (GSocketClient *client)
     745                 :            : {
     746         [ +  + ]:          4 :   if (client->priv->proxy_resolver)
     747                 :          2 :     return client->priv->proxy_resolver;
     748                 :            :   else
     749                 :          2 :     return g_proxy_resolver_get_default ();
     750                 :            : }
     751                 :            : 
     752                 :            : /**
     753                 :            :  * g_socket_client_set_proxy_resolver:
     754                 :            :  * @client: a #GSocketClient.
     755                 :            :  * @proxy_resolver: (nullable): a #GProxyResolver, or %NULL for the
     756                 :            :  *   default.
     757                 :            :  *
     758                 :            :  * Overrides the #GProxyResolver used by @client. You can call this if
     759                 :            :  * you want to use specific proxies, rather than using the system
     760                 :            :  * default proxy settings.
     761                 :            :  *
     762                 :            :  * Note that whether or not the proxy resolver is actually used
     763                 :            :  * depends on the setting of #GSocketClient:enable-proxy, which is not
     764                 :            :  * changed by this function (but which is %TRUE by default)
     765                 :            :  *
     766                 :            :  * Since: 2.36
     767                 :            :  */
     768                 :            : void
     769                 :       1255 : g_socket_client_set_proxy_resolver (GSocketClient  *client,
     770                 :            :                                     GProxyResolver *proxy_resolver)
     771                 :            : {
     772                 :            :   /* We have to be careful to avoid calling
     773                 :            :    * g_proxy_resolver_get_default() until we're sure we need it,
     774                 :            :    * because trying to load the default proxy resolver module will
     775                 :            :    * break some test programs that aren't expecting it (eg,
     776                 :            :    * tests/gsettings).
     777                 :            :    */
     778                 :            : 
     779         [ +  + ]:       1255 :   if (client->priv->proxy_resolver)
     780                 :          1 :     g_object_unref (client->priv->proxy_resolver);
     781                 :            : 
     782                 :       1255 :   client->priv->proxy_resolver = proxy_resolver;
     783                 :            : 
     784         [ +  + ]:       1255 :   if (client->priv->proxy_resolver)
     785                 :          1 :     g_object_ref (client->priv->proxy_resolver);
     786                 :       1255 : }
     787                 :            : 
     788                 :            : static void
     789                 :        123 : g_socket_client_class_init (GSocketClientClass *class)
     790                 :            : {
     791                 :        123 :   GObjectClass *gobject_class = G_OBJECT_CLASS (class);
     792                 :            : 
     793                 :        123 :   gobject_class->finalize = g_socket_client_finalize;
     794                 :        123 :   gobject_class->set_property = g_socket_client_set_property;
     795                 :        123 :   gobject_class->get_property = g_socket_client_get_property;
     796                 :            : 
     797                 :            :   /**
     798                 :            :    * GSocketClient::event:
     799                 :            :    * @client: the #GSocketClient
     800                 :            :    * @event: the event that is occurring
     801                 :            :    * @connectable: the #GSocketConnectable that @event is occurring on
     802                 :            :    * @connection: (nullable): the current representation of the connection
     803                 :            :    *
     804                 :            :    * Emitted when @client's activity on @connectable changes state.
     805                 :            :    * Among other things, this can be used to provide progress
     806                 :            :    * information about a network connection in the UI. The meanings of
     807                 :            :    * the different @event values are as follows:
     808                 :            :    *
     809                 :            :    * - %G_SOCKET_CLIENT_RESOLVING: @client is about to look up @connectable
     810                 :            :    *   in DNS. @connection will be %NULL.
     811                 :            :    *
     812                 :            :    * - %G_SOCKET_CLIENT_RESOLVED:  @client has successfully resolved
     813                 :            :    *   @connectable in DNS. @connection will be %NULL.
     814                 :            :    *
     815                 :            :    * - %G_SOCKET_CLIENT_CONNECTING: @client is about to make a connection
     816                 :            :    *   to a remote host; either a proxy server or the destination server
     817                 :            :    *   itself. @connection is the #GSocketConnection, which is not yet
     818                 :            :    *   connected.  Since GLib 2.40, you can access the remote
     819                 :            :    *   address via g_socket_connection_get_remote_address().
     820                 :            :    *
     821                 :            :    * - %G_SOCKET_CLIENT_CONNECTED: @client has successfully connected
     822                 :            :    *   to a remote host. @connection is the connected #GSocketConnection.
     823                 :            :    *
     824                 :            :    * - %G_SOCKET_CLIENT_PROXY_NEGOTIATING: @client is about to negotiate
     825                 :            :    *   with a proxy to get it to connect to @connectable. @connection is
     826                 :            :    *   the #GSocketConnection to the proxy server.
     827                 :            :    *
     828                 :            :    * - %G_SOCKET_CLIENT_PROXY_NEGOTIATED: @client has negotiated a
     829                 :            :    *   connection to @connectable through a proxy server. @connection is
     830                 :            :    *   the stream returned from g_proxy_connect(), which may or may not
     831                 :            :    *   be a #GSocketConnection.
     832                 :            :    *
     833                 :            :    * - %G_SOCKET_CLIENT_TLS_HANDSHAKING: @client is about to begin a TLS
     834                 :            :    *   handshake. @connection is a #GTlsClientConnection.
     835                 :            :    *
     836                 :            :    * - %G_SOCKET_CLIENT_TLS_HANDSHAKED: @client has successfully completed
     837                 :            :    *   the TLS handshake. @connection is a #GTlsClientConnection.
     838                 :            :    *
     839                 :            :    * - %G_SOCKET_CLIENT_COMPLETE: @client has either successfully connected
     840                 :            :    *   to @connectable (in which case @connection is the #GSocketConnection
     841                 :            :    *   that it will be returning to the caller) or has failed (in which
     842                 :            :    *   case @connection is %NULL and the client is about to return an error).
     843                 :            :    *
     844                 :            :    * Each event except %G_SOCKET_CLIENT_COMPLETE may be emitted
     845                 :            :    * multiple times (or not at all) for a given connectable (in
     846                 :            :    * particular, if @client ends up attempting to connect to more than
     847                 :            :    * one address). However, if @client emits the #GSocketClient::event
     848                 :            :    * signal at all for a given connectable, then it will always emit
     849                 :            :    * it with %G_SOCKET_CLIENT_COMPLETE when it is done.
     850                 :            :    *
     851                 :            :    * Note that there may be additional #GSocketClientEvent values in
     852                 :            :    * the future; unrecognized @event values should be ignored.
     853                 :            :    *
     854                 :            :    * Since: 2.32
     855                 :            :    */
     856                 :        123 :   signals[EVENT] =
     857                 :        123 :     g_signal_new (I_("event"),
     858                 :            :                   G_TYPE_FROM_CLASS (gobject_class),
     859                 :            :                   G_SIGNAL_RUN_LAST,
     860                 :            :                   G_STRUCT_OFFSET (GSocketClientClass, event),
     861                 :            :                   NULL, NULL,
     862                 :            :                   _g_cclosure_marshal_VOID__ENUM_OBJECT_OBJECT,
     863                 :            :                   G_TYPE_NONE, 3,
     864                 :            :                   G_TYPE_SOCKET_CLIENT_EVENT,
     865                 :            :                   G_TYPE_SOCKET_CONNECTABLE,
     866                 :            :                   G_TYPE_IO_STREAM);
     867                 :        123 :   g_signal_set_va_marshaller (signals[EVENT],
     868                 :            :                               G_TYPE_FROM_CLASS (class),
     869                 :            :                               _g_cclosure_marshal_VOID__ENUM_OBJECT_OBJECTv);
     870                 :            : 
     871                 :            :   /**
     872                 :            :    * GSocketClient:family:
     873                 :            :    *
     874                 :            :    * The address family to use for socket construction.
     875                 :            :    *
     876                 :            :    * Since: 2.22
     877                 :            :    */
     878                 :        123 :   g_object_class_install_property (gobject_class, PROP_FAMILY,
     879                 :            :                                    g_param_spec_enum ("family", NULL, NULL,
     880                 :            :                                                       G_TYPE_SOCKET_FAMILY,
     881                 :            :                                                       G_SOCKET_FAMILY_INVALID,
     882                 :            :                                                       G_PARAM_CONSTRUCT |
     883                 :            :                                                       G_PARAM_READWRITE |
     884                 :            :                                                       G_PARAM_STATIC_STRINGS));
     885                 :            : 
     886                 :            :   /**
     887                 :            :    * GSocketClient:type:
     888                 :            :    *
     889                 :            :    * The type to use for socket construction.
     890                 :            :    *
     891                 :            :    * Since: 2.22
     892                 :            :    */
     893                 :        123 :   g_object_class_install_property (gobject_class, PROP_TYPE,
     894                 :            :                                    g_param_spec_enum ("type", NULL, NULL,
     895                 :            :                                                       G_TYPE_SOCKET_TYPE,
     896                 :            :                                                       G_SOCKET_TYPE_STREAM,
     897                 :            :                                                       G_PARAM_CONSTRUCT |
     898                 :            :                                                       G_PARAM_READWRITE |
     899                 :            :                                                       G_PARAM_STATIC_STRINGS));
     900                 :            : 
     901                 :            :   /**
     902                 :            :    * GSocketClient:protocol:
     903                 :            :    *
     904                 :            :    * The protocol to use for socket construction, or `0` for default.
     905                 :            :    *
     906                 :            :    * Since: 2.22
     907                 :            :    */
     908                 :        123 :   g_object_class_install_property (gobject_class, PROP_PROTOCOL,
     909                 :            :                                    g_param_spec_enum ("protocol", NULL, NULL,
     910                 :            :                                                       G_TYPE_SOCKET_PROTOCOL,
     911                 :            :                                                       G_SOCKET_PROTOCOL_DEFAULT,
     912                 :            :                                                       G_PARAM_CONSTRUCT |
     913                 :            :                                                       G_PARAM_READWRITE |
     914                 :            :                                                       G_PARAM_STATIC_STRINGS));
     915                 :            : 
     916                 :            :   /**
     917                 :            :    * GSocketClient:local-address:
     918                 :            :    *
     919                 :            :    * The local address constructed sockets will be bound to.
     920                 :            :    *
     921                 :            :    * Since: 2.22
     922                 :            :    */
     923                 :        123 :   g_object_class_install_property (gobject_class, PROP_LOCAL_ADDRESS,
     924                 :            :                                    g_param_spec_object ("local-address", NULL, NULL,
     925                 :            :                                                         G_TYPE_SOCKET_ADDRESS,
     926                 :            :                                                         G_PARAM_CONSTRUCT |
     927                 :            :                                                         G_PARAM_READWRITE |
     928                 :            :                                                         G_PARAM_STATIC_STRINGS));
     929                 :            : 
     930                 :            :   /**
     931                 :            :    * GSocketClient:timeout:
     932                 :            :    *
     933                 :            :    * The I/O timeout for sockets, in seconds, or `0` for none.
     934                 :            :    *
     935                 :            :    * Since: 2.22
     936                 :            :    */
     937                 :        123 :   g_object_class_install_property (gobject_class, PROP_TIMEOUT,
     938                 :            :                                    g_param_spec_uint ("timeout", NULL, NULL,
     939                 :            :                                                       0, G_MAXUINT, 0,
     940                 :            :                                                       G_PARAM_CONSTRUCT |
     941                 :            :                                                       G_PARAM_READWRITE |
     942                 :            :                                                       G_PARAM_STATIC_STRINGS));
     943                 :            : 
     944                 :            :   /**
     945                 :            :    * GSocketClient:enable-proxy:
     946                 :            :    *
     947                 :            :    * Enable proxy support.
     948                 :            :    *
     949                 :            :    * Since: 2.22
     950                 :            :    */
     951                 :        123 :    g_object_class_install_property (gobject_class, PROP_ENABLE_PROXY,
     952                 :            :                                     g_param_spec_boolean ("enable-proxy", NULL, NULL,
     953                 :            :                                                           TRUE,
     954                 :            :                                                           G_PARAM_CONSTRUCT |
     955                 :            :                                                           G_PARAM_READWRITE |
     956                 :            :                                                           G_PARAM_STATIC_STRINGS));
     957                 :            : 
     958                 :            :   /**
     959                 :            :    * GSocketClient:tls:
     960                 :            :    *
     961                 :            :    * Whether to create TLS connections.
     962                 :            :    *
     963                 :            :    * Since: 2.22
     964                 :            :    */
     965                 :        123 :   g_object_class_install_property (gobject_class, PROP_TLS,
     966                 :            :                                    g_param_spec_boolean ("tls", NULL, NULL,
     967                 :            :                                                          FALSE,
     968                 :            :                                                          G_PARAM_CONSTRUCT |
     969                 :            :                                                          G_PARAM_READWRITE |
     970                 :            :                                                          G_PARAM_STATIC_STRINGS));
     971                 :            : 
     972                 :            :   /**
     973                 :            :    * GSocketClient:tls-validation-flags:
     974                 :            :    *
     975                 :            :    * The TLS validation flags used when creating TLS connections. The
     976                 :            :    * default value is %G_TLS_CERTIFICATE_VALIDATE_ALL.
     977                 :            :    *
     978                 :            :    * GLib guarantees that if certificate verification fails, at least one
     979                 :            :    * flag will be set, but it does not guarantee that all possible flags
     980                 :            :    * will be set. Accordingly, you may not safely decide to ignore any
     981                 :            :    * particular type of error. For example, it would be incorrect to mask
     982                 :            :    * %G_TLS_CERTIFICATE_EXPIRED if you want to allow expired certificates,
     983                 :            :    * because this could potentially be the only error flag set even if
     984                 :            :    * other problems exist with the certificate. Therefore, there is no
     985                 :            :    * safe way to use this property. This is not a horrible problem,
     986                 :            :    * though, because you should not be attempting to ignore validation
     987                 :            :    * errors anyway. If you really must ignore TLS certificate errors,
     988                 :            :    * connect to the #GSocketClient::event signal, wait for it to be
     989                 :            :    * emitted with %G_SOCKET_CLIENT_TLS_HANDSHAKING, and use that to
     990                 :            :    * connect to #GTlsConnection::accept-certificate.
     991                 :            :    *
     992                 :            :    * Deprecated: 2.72: Do not attempt to ignore validation errors.
     993                 :            :    */
     994                 :        123 :   g_object_class_install_property (gobject_class, PROP_TLS_VALIDATION_FLAGS,
     995                 :            :                                    g_param_spec_flags ("tls-validation-flags", NULL, NULL,
     996                 :            :                                                        G_TYPE_TLS_CERTIFICATE_FLAGS,
     997                 :            :                                                        G_TLS_CERTIFICATE_VALIDATE_ALL,
     998                 :            :                                                        G_PARAM_CONSTRUCT |
     999                 :            :                                                        G_PARAM_READWRITE |
    1000                 :            :                                                        G_PARAM_STATIC_STRINGS |
    1001                 :            :                                                        G_PARAM_DEPRECATED));
    1002                 :            : 
    1003                 :            :   /**
    1004                 :            :    * GSocketClient:proxy-resolver:
    1005                 :            :    *
    1006                 :            :    * The proxy resolver to use
    1007                 :            :    *
    1008                 :            :    * Since: 2.36
    1009                 :            :    */
    1010                 :        123 :   g_object_class_install_property (gobject_class, PROP_PROXY_RESOLVER,
    1011                 :            :                                    g_param_spec_object ("proxy-resolver", NULL, NULL,
    1012                 :            :                                                         G_TYPE_PROXY_RESOLVER,
    1013                 :            :                                                         G_PARAM_CONSTRUCT |
    1014                 :            :                                                         G_PARAM_READWRITE |
    1015                 :            :                                                         G_PARAM_STATIC_STRINGS));
    1016                 :        123 : }
    1017                 :            : 
    1018                 :            : static void
    1019                 :       6339 : g_socket_client_emit_event (GSocketClient       *client,
    1020                 :            :                             GSocketClientEvent   event,
    1021                 :            :                             GSocketConnectable  *connectable,
    1022                 :            :                             GIOStream           *connection)
    1023                 :            : {
    1024                 :       6339 :   g_signal_emit (client, signals[EVENT], 0,
    1025                 :            :                  event, connectable, connection);
    1026                 :       6339 : }
    1027                 :            : 
    1028                 :            : /* Originally, GSocketClient returned whatever error occurred last. Turns
    1029                 :            :  * out this doesn't work well in practice. Consider the following case:
    1030                 :            :  * DNS returns an IPv4 and IPv6 address. First we'll connect() to the
    1031                 :            :  * IPv4 address, and say that succeeds, but TLS is enabled and the TLS
    1032                 :            :  * handshake fails. Then we try the IPv6 address and receive ENETUNREACH
    1033                 :            :  * because IPv6 isn't supported. We wind up returning NETWORK_UNREACHABLE
    1034                 :            :  * even though the address can be pinged and a TLS error would be more
    1035                 :            :  * appropriate. So instead, we now try to return the error corresponding
    1036                 :            :  * to the latest attempted GSocketClientEvent in the connection process.
    1037                 :            :  * TLS errors take precedence over proxy errors, which take precedence
    1038                 :            :  * over connect() errors, which take precedence over DNS errors.
    1039                 :            :  *
    1040                 :            :  * Note that the example above considers a sync codepath, but this is an
    1041                 :            :  * issue for the async codepath too, where events and errors may occur
    1042                 :            :  * in confusing orders.
    1043                 :            :  */
    1044                 :            : typedef struct
    1045                 :            : {
    1046                 :            :   GError *tmp_error;
    1047                 :            :   GError *best_error;
    1048                 :            :   GSocketClientEvent best_error_event;
    1049                 :            : } SocketClientErrorInfo;
    1050                 :            : 
    1051                 :            : static SocketClientErrorInfo *
    1052                 :       1271 : socket_client_error_info_new (void)
    1053                 :            : {
    1054                 :       1271 :   return g_new0 (SocketClientErrorInfo, 1);
    1055                 :            : }
    1056                 :            : 
    1057                 :            : static void
    1058                 :       1270 : socket_client_error_info_free (SocketClientErrorInfo *info)
    1059                 :            : {
    1060                 :       1270 :   g_assert (info->tmp_error == NULL);
    1061                 :       1270 :   g_clear_error (&info->best_error);
    1062                 :       1270 :   g_free (info);
    1063                 :       1270 : }
    1064                 :            : 
    1065                 :            : static void
    1066                 :       2570 : consider_tmp_error (SocketClientErrorInfo *info,
    1067                 :            :                     GSocketClientEvent     event)
    1068                 :            : {
    1069         [ +  + ]:       2570 :   if (info->tmp_error == NULL)
    1070                 :       2530 :     return;
    1071                 :            : 
    1072                 :            :   /* If we ever add more GSocketClientEvents in the future, then we'll
    1073                 :            :    * no longer be able to use >= for this comparison, because future
    1074                 :            :    * events will compare greater than G_SOCKET_CLIENT_COMPLETE. Until
    1075                 :            :    * then, this is convenient. Note G_SOCKET_CLIENT_RESOLVING is 0 so we
    1076                 :            :    * need to use >= here or those errors would never be set. That means
    1077                 :            :    * if we get two errors on the same GSocketClientEvent, we wind up
    1078                 :            :    * preferring the last one, which is fine.
    1079                 :            :    */
    1080                 :         40 :   g_assert (event <= G_SOCKET_CLIENT_COMPLETE);
    1081         [ +  - ]:         40 :   if (event >= info->best_error_event)
    1082                 :            :     {
    1083                 :         40 :       g_clear_error (&info->best_error);
    1084                 :         40 :       info->best_error = info->tmp_error;
    1085                 :         40 :       info->tmp_error = NULL;
    1086                 :         40 :       info->best_error_event = event;
    1087                 :            :     }
    1088                 :            :   else
    1089                 :            :     {
    1090                 :          0 :       g_clear_error (&info->tmp_error);
    1091                 :            :     }
    1092                 :            : }
    1093                 :            : 
    1094                 :            : /**
    1095                 :            :  * g_socket_client_connect:
    1096                 :            :  * @client: a #GSocketClient.
    1097                 :            :  * @connectable: a #GSocketConnectable specifying the remote address.
    1098                 :            :  * @cancellable: (nullable): optional #GCancellable object, %NULL to ignore.
    1099                 :            :  * @error: #GError for error reporting, or %NULL to ignore.
    1100                 :            :  *
    1101                 :            :  * Tries to resolve the @connectable and make a network connection to it.
    1102                 :            :  *
    1103                 :            :  * Upon a successful connection, a new #GSocketConnection is constructed
    1104                 :            :  * and returned.  The caller owns this new object and must drop their
    1105                 :            :  * reference to it when finished with it.
    1106                 :            :  *
    1107                 :            :  * The type of the #GSocketConnection object returned depends on the type of
    1108                 :            :  * the underlying socket that is used. For instance, for a TCP/IP connection
    1109                 :            :  * it will be a #GTcpConnection.
    1110                 :            :  *
    1111                 :            :  * The socket created will be the same family as the address that the
    1112                 :            :  * @connectable resolves to, unless family is set with g_socket_client_set_family()
    1113                 :            :  * or indirectly via g_socket_client_set_local_address(). The socket type
    1114                 :            :  * defaults to %G_SOCKET_TYPE_STREAM but can be set with
    1115                 :            :  * g_socket_client_set_socket_type().
    1116                 :            :  *
    1117                 :            :  * If a local address is specified with g_socket_client_set_local_address() the
    1118                 :            :  * socket will be bound to this address before connecting.
    1119                 :            :  *
    1120                 :            :  * Returns: (transfer full): a #GSocketConnection on success, %NULL on error.
    1121                 :            :  *
    1122                 :            :  * Since: 2.22
    1123                 :            :  */
    1124                 :            : GSocketConnection *
    1125                 :       1249 : g_socket_client_connect (GSocketClient       *client,
    1126                 :            :                          GSocketConnectable  *connectable,
    1127                 :            :                          GCancellable        *cancellable,
    1128                 :            :                          GError             **error)
    1129                 :            : {
    1130                 :       1249 :   GIOStream *connection = NULL;
    1131                 :       1249 :   GSocketAddressEnumerator *enumerator = NULL;
    1132                 :            :   SocketClientErrorInfo *error_info;
    1133                 :       1249 :   gboolean ever_resolved = FALSE;
    1134                 :            : 
    1135                 :       1249 :   error_info = socket_client_error_info_new ();
    1136                 :            : 
    1137         [ +  + ]:       1249 :   if (can_use_proxy (client))
    1138                 :            :     {
    1139                 :         19 :       enumerator = g_socket_connectable_proxy_enumerate (connectable);
    1140         [ +  + ]:         19 :       if (client->priv->proxy_resolver &&
    1141   [ -  +  +  -  :          3 :           G_IS_PROXY_ADDRESS_ENUMERATOR (enumerator))
             +  -  +  - ]
    1142                 :            :         {
    1143                 :          3 :           g_object_set (G_OBJECT (enumerator),
    1144                 :          3 :                         "proxy-resolver", client->priv->proxy_resolver,
    1145                 :            :                         NULL);
    1146                 :            :         }
    1147                 :            :     }
    1148                 :            :   else
    1149                 :       1230 :     enumerator = g_socket_connectable_enumerate (connectable);
    1150                 :            : 
    1151         [ +  + ]:       2496 :   while (connection == NULL)
    1152                 :            :     {
    1153                 :       1279 :       GSocketAddress *address = NULL;
    1154                 :       1279 :       gboolean application_proxy = FALSE;
    1155                 :            :       GSocket *socket;
    1156                 :            :       gboolean using_proxy;
    1157                 :            : 
    1158         [ -  + ]:       1279 :       if (g_cancellable_is_cancelled (cancellable))
    1159                 :            :         {
    1160                 :          0 :           g_clear_error (&error_info->best_error);
    1161                 :          0 :           g_cancellable_set_error_if_cancelled (cancellable, &error_info->best_error);
    1162                 :          0 :           break;
    1163                 :            :         }
    1164                 :            : 
    1165         [ +  + ]:       1279 :       if (!ever_resolved)
    1166                 :            :         {
    1167                 :       1249 :           g_socket_client_emit_event (client, G_SOCKET_CLIENT_RESOLVING,
    1168                 :            :                                       connectable, NULL);
    1169                 :            :         }
    1170                 :       1279 :       address = g_socket_address_enumerator_next (enumerator, cancellable,
    1171                 :            :                                                   &error_info->tmp_error);
    1172                 :       1279 :       consider_tmp_error (error_info, G_SOCKET_CLIENT_RESOLVING);
    1173         [ +  + ]:       1279 :       if (!ever_resolved)
    1174                 :            :         {
    1175                 :       1249 :           g_socket_client_emit_event (client, G_SOCKET_CLIENT_RESOLVED,
    1176                 :            :                                       connectable, NULL);
    1177                 :       1249 :           ever_resolved = TRUE;
    1178                 :            :         }
    1179                 :            : 
    1180         [ +  + ]:       1279 :       if (address == NULL)
    1181                 :            :         {
    1182                 :            :           /* Enumeration is finished. */
    1183                 :         32 :           g_assert (&error_info->best_error != NULL);
    1184                 :         32 :           break;
    1185                 :            :         }
    1186                 :            : 
    1187   [ -  +  +  -  :       1255 :       using_proxy = (G_IS_PROXY_ADDRESS (address) &&
             +  +  +  + ]
    1188         [ +  - ]:          8 :                      client->priv->enable_proxy);
    1189                 :            : 
    1190                 :       1247 :       socket = create_socket (client, address, &error_info->tmp_error);
    1191                 :       1247 :       consider_tmp_error (error_info, G_SOCKET_CLIENT_CONNECTING);
    1192         [ -  + ]:       1247 :       if (socket == NULL)
    1193                 :            :         {
    1194                 :          0 :           g_object_unref (address);
    1195                 :          0 :           continue;
    1196                 :            :         }
    1197                 :            : 
    1198                 :       1247 :       connection = (GIOStream *)g_socket_connection_factory_create_connection (socket);
    1199                 :       1247 :       g_socket_connection_set_cached_remote_address ((GSocketConnection*)connection, address);
    1200                 :       1247 :       g_socket_client_emit_event (client, G_SOCKET_CLIENT_CONNECTING, connectable, connection);
    1201                 :            : 
    1202         [ +  + ]:       1247 :       if (g_socket_connection_connect (G_SOCKET_CONNECTION (connection),
    1203                 :            :                                        address, cancellable, &error_info->tmp_error))
    1204                 :            :         {
    1205                 :       1221 :           g_socket_connection_set_cached_remote_address ((GSocketConnection*)connection, NULL);
    1206                 :       1221 :           g_socket_client_emit_event (client, G_SOCKET_CLIENT_CONNECTED, connectable, connection);
    1207                 :            :         }
    1208                 :            :       else
    1209                 :            :         {
    1210                 :         26 :           clarify_connect_error (error_info->tmp_error, connectable, address);
    1211                 :         26 :           consider_tmp_error (error_info, G_SOCKET_CLIENT_CONNECTING);
    1212                 :         26 :           g_object_unref (connection);
    1213                 :         26 :           connection = NULL;
    1214                 :            :         }
    1215                 :            : 
    1216   [ +  +  +  + ]:       1247 :       if (connection && using_proxy)
    1217                 :            :         {
    1218                 :          8 :           GProxyAddress *proxy_addr = G_PROXY_ADDRESS (address);
    1219                 :            :           const gchar *protocol;
    1220                 :            :           GProxy *proxy;
    1221                 :            : 
    1222                 :          8 :           protocol = g_proxy_address_get_protocol (proxy_addr);
    1223                 :            : 
    1224                 :            :           /* The connection should not be anything else then TCP Connection,
    1225                 :            :            * but let's put a safety guard in case
    1226                 :            :            */
    1227   [ -  +  +  -  :          8 :           if (!G_IS_TCP_CONNECTION (connection))
             +  -  -  + ]
    1228                 :            :             {
    1229                 :          0 :               g_critical ("Trying to proxy over non-TCP connection, this is "
    1230                 :            :                           "most likely a bug in GLib IO library.");
    1231                 :            : 
    1232                 :          0 :               g_set_error_literal (&error_info->tmp_error,
    1233                 :            :                   G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
    1234                 :            :                   _("Proxying over a non-TCP connection is not supported."));
    1235                 :          0 :               consider_tmp_error (error_info, G_SOCKET_CLIENT_PROXY_NEGOTIATING);
    1236                 :            : 
    1237                 :          0 :               g_object_unref (connection);
    1238                 :          0 :               connection = NULL;
    1239                 :            :             }
    1240         [ -  + ]:          8 :           else if (g_hash_table_contains (client->priv->app_proxies, protocol))
    1241                 :            :             {
    1242                 :          0 :               application_proxy = TRUE;
    1243                 :            :             }
    1244         [ +  - ]:          8 :           else if ((proxy = g_proxy_get_default_for_protocol (protocol)))
    1245                 :            :             {
    1246                 :            :               GIOStream *proxy_connection;
    1247                 :            : 
    1248                 :          8 :               g_socket_client_emit_event (client, G_SOCKET_CLIENT_PROXY_NEGOTIATING, connectable, connection);
    1249                 :          8 :               proxy_connection = g_proxy_connect (proxy,
    1250                 :            :                                                   connection,
    1251                 :            :                                                   proxy_addr,
    1252                 :            :                                                   cancellable,
    1253                 :            :                                                   &error_info->tmp_error);
    1254                 :          8 :               consider_tmp_error (error_info, G_SOCKET_CLIENT_PROXY_NEGOTIATING);
    1255                 :            : 
    1256                 :          8 :               g_object_unref (connection);
    1257                 :          8 :               connection = proxy_connection;
    1258                 :          8 :               g_object_unref (proxy);
    1259                 :            : 
    1260         [ +  + ]:          8 :               if (connection)
    1261                 :          4 :                 g_socket_client_emit_event (client, G_SOCKET_CLIENT_PROXY_NEGOTIATED, connectable, connection);
    1262                 :            :             }
    1263                 :            :           else
    1264                 :            :             {
    1265                 :          0 :               g_set_error (&error_info->tmp_error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
    1266                 :            :                            _("Proxy protocol “%s” is not supported."),
    1267                 :            :                            protocol);
    1268                 :          0 :               consider_tmp_error (error_info, G_SOCKET_CLIENT_PROXY_NEGOTIATING);
    1269                 :          0 :               g_object_unref (connection);
    1270                 :          0 :               connection = NULL;
    1271                 :            :             }
    1272                 :            :         }
    1273                 :            : 
    1274   [ +  -  +  +  :       1247 :       if (!application_proxy && connection && client->priv->tls)
                   -  + ]
    1275                 :            :         {
    1276                 :            :           GIOStream *tlsconn;
    1277                 :            : 
    1278                 :          0 :           tlsconn = g_tls_client_connection_new (connection, connectable, &error_info->tmp_error);
    1279                 :          0 :           g_object_unref (connection);
    1280                 :          0 :           connection = tlsconn;
    1281                 :            : 
    1282         [ #  # ]:          0 :           if (tlsconn)
    1283                 :            :             {
    1284                 :            : G_GNUC_BEGIN_IGNORE_DEPRECATIONS
    1285                 :          0 :               g_tls_client_connection_set_validation_flags (G_TLS_CLIENT_CONNECTION (tlsconn),
    1286                 :          0 :                                                             client->priv->tls_validation_flags);
    1287                 :            : G_GNUC_END_IGNORE_DEPRECATIONS
    1288                 :          0 :               g_socket_client_emit_event (client, G_SOCKET_CLIENT_TLS_HANDSHAKING, connectable, connection);
    1289         [ #  # ]:          0 :               if (g_tls_connection_handshake (G_TLS_CONNECTION (tlsconn),
    1290                 :            :                                               cancellable, &error_info->tmp_error))
    1291                 :            :                 {
    1292                 :          0 :                   g_socket_client_emit_event (client, G_SOCKET_CLIENT_TLS_HANDSHAKED, connectable, connection);
    1293                 :            :                 }
    1294                 :            :               else
    1295                 :            :                 {
    1296                 :          0 :                   consider_tmp_error (error_info, G_SOCKET_CLIENT_TLS_HANDSHAKING);
    1297                 :          0 :                   g_object_unref (tlsconn);
    1298                 :          0 :                   connection = NULL;
    1299                 :            :                 }
    1300                 :            :             }
    1301                 :            :           else
    1302                 :            :             {
    1303                 :          0 :               consider_tmp_error (error_info, G_SOCKET_CLIENT_TLS_HANDSHAKING);
    1304                 :            :             }
    1305                 :            :         }
    1306                 :            : 
    1307   [ +  +  -  +  :       1247 :       if (connection && !G_IS_SOCKET_CONNECTION (connection))
          +  -  -  +  -  
                      + ]
    1308                 :            :         {
    1309                 :            :           GSocketConnection *wrapper_connection;
    1310                 :            : 
    1311                 :          0 :           wrapper_connection = g_tcp_wrapper_connection_new (connection, socket);
    1312                 :          0 :           g_object_unref (connection);
    1313                 :          0 :           connection = (GIOStream *)wrapper_connection;
    1314                 :            :         }
    1315                 :            : 
    1316                 :       1247 :       g_object_unref (socket);
    1317                 :       1247 :       g_object_unref (address);
    1318                 :            :     }
    1319                 :       1249 :   g_object_unref (enumerator);
    1320                 :            : 
    1321         [ +  + ]:       1249 :   if (!connection)
    1322                 :         32 :     g_propagate_error (error, g_steal_pointer (&error_info->best_error));
    1323                 :       1249 :   socket_client_error_info_free (error_info);
    1324                 :            : 
    1325                 :       1249 :   g_socket_client_emit_event (client, G_SOCKET_CLIENT_COMPLETE, connectable, connection);
    1326                 :       1249 :   return G_SOCKET_CONNECTION (connection);
    1327                 :            : }
    1328                 :            : 
    1329                 :            : /**
    1330                 :            :  * g_socket_client_connect_to_host:
    1331                 :            :  * @client: a #GSocketClient
    1332                 :            :  * @host_and_port: the name and optionally port of the host to connect to
    1333                 :            :  * @default_port: the default port to connect to
    1334                 :            :  * @cancellable: (nullable): a #GCancellable, or %NULL
    1335                 :            :  * @error: a pointer to a #GError, or %NULL
    1336                 :            :  *
    1337                 :            :  * This is a helper function for g_socket_client_connect().
    1338                 :            :  *
    1339                 :            :  * Attempts to create a TCP connection to the named host.
    1340                 :            :  *
    1341                 :            :  * @host_and_port may be in any of a number of recognized formats; an IPv6
    1342                 :            :  * address, an IPv4 address, or a domain name (in which case a DNS
    1343                 :            :  * lookup is performed).  Quoting with [] is supported for all address
    1344                 :            :  * types.  A port override may be specified in the usual way with a
    1345                 :            :  * colon.  Ports may be given as decimal numbers or symbolic names (in
    1346                 :            :  * which case an /etc/services lookup is performed).
    1347                 :            :  *
    1348                 :            :  * If no port override is given in @host_and_port then @default_port will be
    1349                 :            :  * used as the port number to connect to.
    1350                 :            :  *
    1351                 :            :  * In general, @host_and_port is expected to be provided by the user (allowing
    1352                 :            :  * them to give the hostname, and a port override if necessary) and
    1353                 :            :  * @default_port is expected to be provided by the application.
    1354                 :            :  *
    1355                 :            :  * In the case that an IP address is given, a single connection
    1356                 :            :  * attempt is made.  In the case that a name is given, multiple
    1357                 :            :  * connection attempts may be made, in turn and according to the
    1358                 :            :  * number of address records in DNS, until a connection succeeds.
    1359                 :            :  *
    1360                 :            :  * Upon a successful connection, a new #GSocketConnection is constructed
    1361                 :            :  * and returned.  The caller owns this new object and must drop their
    1362                 :            :  * reference to it when finished with it.
    1363                 :            :  *
    1364                 :            :  * In the event of any failure (DNS error, service not found, no hosts
    1365                 :            :  * connectable) %NULL is returned and @error (if non-%NULL) is set
    1366                 :            :  * accordingly.
    1367                 :            :  *
    1368                 :            :  * Returns: (transfer full): a #GSocketConnection on success, %NULL on error.
    1369                 :            :  *
    1370                 :            :  * Since: 2.22
    1371                 :            :  */
    1372                 :            : GSocketConnection *
    1373                 :          0 : g_socket_client_connect_to_host (GSocketClient  *client,
    1374                 :            :                                  const gchar    *host_and_port,
    1375                 :            :                                  guint16         default_port,
    1376                 :            :                                  GCancellable   *cancellable,
    1377                 :            :                                  GError        **error)
    1378                 :            : {
    1379                 :            :   GSocketConnectable *connectable;
    1380                 :            :   GSocketConnection *connection;
    1381                 :            : 
    1382                 :          0 :   connectable = g_network_address_parse (host_and_port, default_port, error);
    1383         [ #  # ]:          0 :   if (connectable == NULL)
    1384                 :          0 :     return NULL;
    1385                 :            : 
    1386                 :          0 :   connection = g_socket_client_connect (client, connectable,
    1387                 :            :                                         cancellable, error);
    1388                 :          0 :   g_object_unref (connectable);
    1389                 :            : 
    1390                 :          0 :   return connection;
    1391                 :            : }
    1392                 :            : 
    1393                 :            : /**
    1394                 :            :  * g_socket_client_connect_to_service:
    1395                 :            :  * @client: a #GSocketConnection
    1396                 :            :  * @domain: a domain name
    1397                 :            :  * @service: the name of the service to connect to
    1398                 :            :  * @cancellable: (nullable): a #GCancellable, or %NULL
    1399                 :            :  * @error: a pointer to a #GError, or %NULL
    1400                 :            :  *
    1401                 :            :  * Attempts to create a TCP connection to a service.
    1402                 :            :  *
    1403                 :            :  * This call looks up the SRV record for @service at @domain for the
    1404                 :            :  * "tcp" protocol.  It then attempts to connect, in turn, to each of
    1405                 :            :  * the hosts providing the service until either a connection succeeds
    1406                 :            :  * or there are no hosts remaining.
    1407                 :            :  *
    1408                 :            :  * Upon a successful connection, a new #GSocketConnection is constructed
    1409                 :            :  * and returned.  The caller owns this new object and must drop their
    1410                 :            :  * reference to it when finished with it.
    1411                 :            :  *
    1412                 :            :  * In the event of any failure (DNS error, service not found, no hosts
    1413                 :            :  * connectable) %NULL is returned and @error (if non-%NULL) is set
    1414                 :            :  * accordingly.
    1415                 :            :  *
    1416                 :            :  * Returns: (transfer full): a #GSocketConnection if successful, or %NULL on error
    1417                 :            :  */
    1418                 :            : GSocketConnection *
    1419                 :          0 : g_socket_client_connect_to_service (GSocketClient  *client,
    1420                 :            :                                     const gchar    *domain,
    1421                 :            :                                     const gchar    *service,
    1422                 :            :                                     GCancellable   *cancellable,
    1423                 :            :                                     GError        **error)
    1424                 :            : {
    1425                 :            :   GSocketConnectable *connectable;
    1426                 :            :   GSocketConnection *connection;
    1427                 :            : 
    1428                 :          0 :   connectable = g_network_service_new (service, "tcp", domain);
    1429                 :          0 :   connection = g_socket_client_connect (client, connectable,
    1430                 :            :                                         cancellable, error);
    1431                 :          0 :   g_object_unref (connectable);
    1432                 :            : 
    1433                 :          0 :   return connection;
    1434                 :            : }
    1435                 :            : 
    1436                 :            : /**
    1437                 :            :  * g_socket_client_connect_to_uri:
    1438                 :            :  * @client: a #GSocketClient
    1439                 :            :  * @uri: A network URI
    1440                 :            :  * @default_port: the default port to connect to
    1441                 :            :  * @cancellable: (nullable): a #GCancellable, or %NULL
    1442                 :            :  * @error: a pointer to a #GError, or %NULL
    1443                 :            :  *
    1444                 :            :  * This is a helper function for g_socket_client_connect().
    1445                 :            :  *
    1446                 :            :  * Attempts to create a TCP connection with a network URI.
    1447                 :            :  *
    1448                 :            :  * @uri may be any valid URI containing an "authority" (hostname/port)
    1449                 :            :  * component. If a port is not specified in the URI, @default_port
    1450                 :            :  * will be used. TLS will be negotiated if #GSocketClient:tls is %TRUE.
    1451                 :            :  * (#GSocketClient does not know to automatically assume TLS for
    1452                 :            :  * certain URI schemes.)
    1453                 :            :  *
    1454                 :            :  * Using this rather than g_socket_client_connect() or
    1455                 :            :  * g_socket_client_connect_to_host() allows #GSocketClient to
    1456                 :            :  * determine when to use application-specific proxy protocols.
    1457                 :            :  *
    1458                 :            :  * Upon a successful connection, a new #GSocketConnection is constructed
    1459                 :            :  * and returned.  The caller owns this new object and must drop their
    1460                 :            :  * reference to it when finished with it.
    1461                 :            :  *
    1462                 :            :  * In the event of any failure (DNS error, service not found, no hosts
    1463                 :            :  * connectable) %NULL is returned and @error (if non-%NULL) is set
    1464                 :            :  * accordingly.
    1465                 :            :  *
    1466                 :            :  * Returns: (transfer full): a #GSocketConnection on success, %NULL on error.
    1467                 :            :  *
    1468                 :            :  * Since: 2.26
    1469                 :            :  */
    1470                 :            : GSocketConnection *
    1471                 :         14 : g_socket_client_connect_to_uri (GSocketClient  *client,
    1472                 :            :                                 const gchar    *uri,
    1473                 :            :                                 guint16         default_port,
    1474                 :            :                                 GCancellable   *cancellable,
    1475                 :            :                                 GError        **error)
    1476                 :            : {
    1477                 :            :   GSocketConnectable *connectable;
    1478                 :            :   GSocketConnection *connection;
    1479                 :            : 
    1480                 :         14 :   connectable = g_network_address_parse_uri (uri, default_port, error);
    1481         [ +  + ]:         14 :   if (connectable == NULL)
    1482                 :          1 :     return NULL;
    1483                 :            : 
    1484                 :         13 :   connection = g_socket_client_connect (client, connectable,
    1485                 :            :                                         cancellable, error);
    1486                 :         13 :   g_object_unref (connectable);
    1487                 :            : 
    1488                 :         13 :   return connection;
    1489                 :            : }
    1490                 :            : 
    1491                 :            : typedef struct
    1492                 :            : {
    1493                 :            :   GTask *task; /* unowned */
    1494                 :            :   GSocketClient *client;
    1495                 :            : 
    1496                 :            :   GSocketConnectable *connectable;
    1497                 :            :   GSocketAddressEnumerator *enumerator;
    1498                 :            :   GCancellable *enumeration_cancellable;
    1499                 :            :   GCancellable *enumeration_parent_cancellable;  /* (nullable) (owned) */
    1500                 :            :   gulong enumeration_cancelled_id;
    1501                 :            : 
    1502                 :            :   GSList *connection_attempts;  /* (element-type ConnectionAttempt) (owned) */
    1503                 :            :   GSList *successful_connections;
    1504                 :            :   SocketClientErrorInfo *error_info;
    1505                 :            : 
    1506                 :            :   /* Number of times g_socket_address_enumerator_next_async() has successfully
    1507                 :            :    * returned an address. */
    1508                 :            :   guint n_addresses_enumerated;
    1509                 :            : 
    1510                 :            :   gboolean enumeration_completed;
    1511                 :            :   gboolean connection_in_progress;
    1512                 :            :   gboolean completed;
    1513                 :            : } GSocketClientAsyncConnectData;
    1514                 :            : 
    1515                 :            : static void connection_attempt_unref (gpointer attempt);
    1516                 :            : 
    1517                 :            : static void
    1518                 :         21 : g_socket_client_async_connect_data_free (GSocketClientAsyncConnectData *data)
    1519                 :            : {
    1520                 :         21 :   data->task = NULL;
    1521                 :         21 :   g_clear_object (&data->connectable);
    1522                 :         21 :   g_clear_object (&data->enumerator);
    1523                 :            : 
    1524                 :         21 :   g_cancellable_disconnect (data->enumeration_parent_cancellable, data->enumeration_cancelled_id);
    1525                 :         21 :   g_clear_object (&data->enumeration_parent_cancellable);
    1526                 :         21 :   data->enumeration_cancelled_id = 0;
    1527                 :         21 :   g_clear_object (&data->enumeration_cancellable);
    1528                 :            : 
    1529                 :         21 :   g_slist_free_full (data->connection_attempts, connection_attempt_unref);
    1530                 :         21 :   g_slist_free_full (data->successful_connections, connection_attempt_unref);
    1531                 :            : 
    1532                 :         21 :   g_clear_pointer (&data->error_info, socket_client_error_info_free);
    1533                 :            : 
    1534                 :         21 :   g_slice_free (GSocketClientAsyncConnectData, data);
    1535                 :         21 : }
    1536                 :            : 
    1537                 :            : typedef struct
    1538                 :            : {
    1539                 :            :   GSocketAddress *address;
    1540                 :            :   GSocket *socket;
    1541                 :            :   GIOStream *connection;
    1542                 :            :   GProxyAddress *proxy_addr;
    1543                 :            :   GSocketClientAsyncConnectData *data; /* unowned */
    1544                 :            :   GSource *delay_timeout_source;  /* (owned) */
    1545                 :            :   gboolean delay_reached;
    1546                 :            :   GCancellable *cancellable;
    1547                 :            :   GCancellable *task_cancellable;  /* (owned); this is equal to g_task_get_cancellable (ConnectionAttempt.data->task), but with a longer lifetime */
    1548                 :            :   gulong cancelled_id;
    1549                 :            :   grefcount ref;
    1550                 :            : } ConnectionAttempt;
    1551                 :            : 
    1552                 :            : static ConnectionAttempt *
    1553                 :         19 : connection_attempt_new (void)
    1554                 :            : {
    1555                 :         19 :   ConnectionAttempt *attempt = g_new0 (ConnectionAttempt, 1);
    1556                 :         19 :   g_ref_count_init (&attempt->ref);
    1557                 :         19 :   return attempt;
    1558                 :            : }
    1559                 :            : 
    1560                 :            : static ConnectionAttempt *
    1561                 :         19 : connection_attempt_ref (ConnectionAttempt *attempt)
    1562                 :            : {
    1563                 :         19 :   g_ref_count_inc (&attempt->ref);
    1564                 :         19 :   return attempt;
    1565                 :            : }
    1566                 :            : 
    1567                 :            : static void
    1568                 :         38 : connection_attempt_unref (gpointer pointer)
    1569                 :            : {
    1570                 :         38 :   ConnectionAttempt *attempt = pointer;
    1571         [ +  + ]:         38 :   if (g_ref_count_dec (&attempt->ref))
    1572                 :            :     {
    1573                 :         19 :       g_clear_object (&attempt->address);
    1574                 :         19 :       g_clear_object (&attempt->socket);
    1575                 :         19 :       g_clear_object (&attempt->connection);
    1576                 :         19 :       g_cancellable_disconnect (attempt->task_cancellable, attempt->cancelled_id);
    1577                 :         19 :       g_clear_object (&attempt->task_cancellable);
    1578                 :         19 :       attempt->cancelled_id = 0;
    1579                 :         19 :       g_clear_object (&attempt->cancellable);
    1580                 :         19 :       g_clear_object (&attempt->proxy_addr);
    1581         [ -  + ]:         19 :       if (attempt->delay_timeout_source)
    1582                 :            :         {
    1583                 :          0 :           g_source_destroy (attempt->delay_timeout_source);
    1584                 :          0 :           g_source_unref (attempt->delay_timeout_source);
    1585                 :            :         }
    1586                 :         19 :       g_free (attempt);
    1587                 :            :     }
    1588                 :         38 : }
    1589                 :            : 
    1590                 :            : static void
    1591                 :         19 : connection_attempt_remove (ConnectionAttempt *attempt)
    1592                 :            : {
    1593                 :         19 :   GSList *attempt_link = g_slist_find (attempt->data->connection_attempts, attempt);
    1594         [ +  - ]:         19 :   if (attempt_link != NULL)
    1595                 :            :     {
    1596                 :         19 :       attempt->data->connection_attempts = g_slist_delete_link (attempt->data->connection_attempts, attempt_link);
    1597                 :         19 :       connection_attempt_unref (attempt);
    1598                 :            :     }
    1599                 :         19 : }
    1600                 :            : 
    1601                 :            : static void
    1602                 :         22 : cancel_all_attempts (GSocketClientAsyncConnectData *data)
    1603                 :            : {
    1604                 :            :   GSList *l;
    1605                 :            : 
    1606   [ -  -  -  + ]:         22 :   for (l = data->connection_attempts; l; l = g_slist_next (l))
    1607                 :            :     {
    1608                 :          0 :       ConnectionAttempt *attempt_entry = l->data;
    1609                 :          0 :       g_cancellable_cancel (attempt_entry->cancellable);
    1610                 :          0 :       connection_attempt_unref (attempt_entry);
    1611                 :            :     }
    1612                 :         22 :   g_slist_free (data->connection_attempts);
    1613                 :         22 :   data->connection_attempts = NULL;
    1614                 :            : 
    1615                 :         22 :   g_slist_free_full (data->successful_connections, connection_attempt_unref);
    1616                 :         22 :   data->successful_connections = NULL;
    1617                 :            : 
    1618                 :         22 :   g_cancellable_cancel (data->enumeration_cancellable);
    1619                 :         22 : }
    1620                 :            : 
    1621                 :            : static void
    1622                 :         15 : g_socket_client_async_connect_complete (ConnectionAttempt *attempt)
    1623                 :            : {
    1624                 :         15 :   GSocketClientAsyncConnectData *data = attempt->data;
    1625                 :         15 :   GError *error = NULL;
    1626                 :         15 :   g_assert (attempt->connection);
    1627                 :         15 :   g_assert (!data->completed);
    1628                 :            : 
    1629   [ -  +  +  -  :         15 :   if (!G_IS_SOCKET_CONNECTION (attempt->connection))
             -  +  -  + ]
    1630                 :            :     {
    1631                 :            :       GSocketConnection *wrapper_connection;
    1632                 :            : 
    1633                 :          0 :       wrapper_connection = g_tcp_wrapper_connection_new (attempt->connection, attempt->socket);
    1634                 :          0 :       g_object_unref (attempt->connection);
    1635                 :          0 :       attempt->connection = (GIOStream *)wrapper_connection;
    1636                 :            :     }
    1637                 :            : 
    1638                 :         15 :   data->completed = TRUE;
    1639                 :         15 :   cancel_all_attempts (data);
    1640                 :            : 
    1641         [ +  + ]:         15 :   if (g_cancellable_set_error_if_cancelled (g_task_get_cancellable (data->task), &error))
    1642                 :            :     {
    1643                 :          1 :       g_debug ("GSocketClient: Connection cancelled!");
    1644                 :          1 :       g_socket_client_emit_event (data->client, G_SOCKET_CLIENT_COMPLETE, data->connectable, NULL);
    1645                 :          1 :       g_task_return_error (data->task, g_steal_pointer (&error));
    1646                 :            :     }
    1647                 :            :   else
    1648                 :            :     {
    1649                 :         14 :       g_debug ("GSocketClient: Connection successful!");
    1650                 :         14 :       g_socket_client_emit_event (data->client, G_SOCKET_CLIENT_COMPLETE, data->connectable, attempt->connection);
    1651                 :         14 :       g_task_return_pointer (data->task, g_steal_pointer (&attempt->connection), g_object_unref);
    1652                 :            :     }
    1653                 :            : 
    1654                 :         15 :   connection_attempt_unref (attempt);
    1655                 :         15 :   g_object_unref (data->task);
    1656                 :         15 : }
    1657                 :            : 
    1658                 :            : 
    1659                 :            : static void
    1660                 :            : g_socket_client_enumerator_callback (GObject      *object,
    1661                 :            :                                      GAsyncResult *result,
    1662                 :            :                                      gpointer      user_data);
    1663                 :            : 
    1664                 :            : static void
    1665                 :         28 : enumerator_next_async (GSocketClientAsyncConnectData *data,
    1666                 :            :                        gboolean                       add_task_ref)
    1667                 :            : {
    1668                 :            :   /* Each enumeration takes a ref. This arg just avoids repeated unrefs when
    1669                 :            :      an enumeration starts another enumeration */
    1670         [ +  + ]:         28 :   if (add_task_ref)
    1671                 :          2 :     g_object_ref (data->task);
    1672                 :            : 
    1673         [ +  + ]:         28 :   if (data->n_addresses_enumerated == 0)
    1674                 :         22 :     g_socket_client_emit_event (data->client, G_SOCKET_CLIENT_RESOLVING, data->connectable, NULL);
    1675                 :         28 :   g_debug ("GSocketClient: Starting new address enumeration");
    1676                 :         28 :   g_socket_address_enumerator_next_async (data->enumerator,
    1677                 :            :                                           data->enumeration_cancellable,
    1678                 :            :                                           g_socket_client_enumerator_callback,
    1679                 :            :                                           data);
    1680                 :         28 : }
    1681                 :            : 
    1682                 :            : static void try_next_connection_or_finish (GSocketClientAsyncConnectData *, gboolean);
    1683                 :            : 
    1684                 :            : static void
    1685                 :          0 : g_socket_client_tls_handshake_callback (GObject      *object,
    1686                 :            :                                         GAsyncResult *result,
    1687                 :            :                                         gpointer      user_data)
    1688                 :            : {
    1689                 :          0 :   ConnectionAttempt *attempt = user_data;
    1690                 :          0 :   GSocketClientAsyncConnectData *data = attempt->data;
    1691                 :            : 
    1692         [ #  # ]:          0 :   if (g_tls_connection_handshake_finish (G_TLS_CONNECTION (object),
    1693                 :            :                                          result,
    1694                 :          0 :                                          &data->error_info->tmp_error))
    1695                 :            :     {
    1696                 :          0 :       g_object_unref (attempt->connection);
    1697                 :          0 :       attempt->connection = G_IO_STREAM (object);
    1698                 :            : 
    1699                 :          0 :       g_debug ("GSocketClient: TLS handshake succeeded");
    1700                 :          0 :       g_socket_client_emit_event (data->client, G_SOCKET_CLIENT_TLS_HANDSHAKED, data->connectable, attempt->connection);
    1701                 :          0 :       g_socket_client_async_connect_complete (attempt);
    1702                 :            :     }
    1703                 :            :   else
    1704                 :            :     {
    1705                 :          0 :       g_object_unref (object);
    1706                 :          0 :       connection_attempt_unref (attempt);
    1707                 :            : 
    1708                 :          0 :       g_debug ("GSocketClient: TLS handshake failed: %s", data->error_info->tmp_error->message);
    1709                 :          0 :       consider_tmp_error (data->error_info, G_SOCKET_CLIENT_TLS_HANDSHAKING);
    1710                 :          0 :       try_next_connection_or_finish (data, TRUE);
    1711                 :            :     }
    1712                 :          0 : }
    1713                 :            : 
    1714                 :            : static void
    1715                 :         15 : g_socket_client_tls_handshake (ConnectionAttempt *attempt)
    1716                 :            : {
    1717                 :         15 :   GSocketClientAsyncConnectData *data = attempt->data;
    1718                 :            :   GIOStream *tlsconn;
    1719                 :            : 
    1720         [ +  - ]:         15 :   if (!data->client->priv->tls)
    1721                 :            :     {
    1722                 :         15 :       g_socket_client_async_connect_complete (attempt);
    1723                 :         15 :       return;
    1724                 :            :     }
    1725                 :            : 
    1726                 :          0 :   g_debug ("GSocketClient: Starting TLS handshake");
    1727                 :          0 :   tlsconn = g_tls_client_connection_new (attempt->connection,
    1728                 :            :                                          data->connectable,
    1729                 :          0 :                                          &data->error_info->tmp_error);
    1730         [ #  # ]:          0 :   if (tlsconn)
    1731                 :            :     {
    1732                 :            : G_GNUC_BEGIN_IGNORE_DEPRECATIONS
    1733                 :          0 :       g_tls_client_connection_set_validation_flags (G_TLS_CLIENT_CONNECTION (tlsconn),
    1734                 :          0 :                                                     data->client->priv->tls_validation_flags);
    1735                 :            : G_GNUC_END_IGNORE_DEPRECATIONS
    1736                 :          0 :       g_socket_client_emit_event (data->client, G_SOCKET_CLIENT_TLS_HANDSHAKING, data->connectable, G_IO_STREAM (tlsconn));
    1737                 :            : 
    1738                 :            :       /* This operation will time out if the underlying #GSocket times out on
    1739                 :            :        * any part of the TLS handshake. It does not have a higher-level
    1740                 :            :        * timeout. */
    1741                 :          0 :       g_tls_connection_handshake_async (G_TLS_CONNECTION (tlsconn),
    1742                 :            :                                         G_PRIORITY_DEFAULT,
    1743                 :            :                                         g_task_get_cancellable (data->task),
    1744                 :            :                                         g_socket_client_tls_handshake_callback,
    1745                 :            :                                         attempt);
    1746                 :            :     }
    1747                 :            :   else
    1748                 :            :     {
    1749                 :          0 :       connection_attempt_unref (attempt);
    1750                 :            : 
    1751                 :          0 :       consider_tmp_error (data->error_info, G_SOCKET_CLIENT_TLS_HANDSHAKING);
    1752                 :          0 :       try_next_connection_or_finish (data, TRUE);
    1753                 :            :     }
    1754                 :            : }
    1755                 :            : 
    1756                 :            : static void
    1757                 :          8 : g_socket_client_proxy_connect_callback (GObject      *object,
    1758                 :            :                                         GAsyncResult *result,
    1759                 :            :                                         gpointer      user_data)
    1760                 :            : {
    1761                 :          8 :   ConnectionAttempt *attempt = user_data;
    1762                 :          8 :   GSocketClientAsyncConnectData *data = attempt->data;
    1763                 :            : 
    1764                 :          8 :   g_object_unref (attempt->connection);
    1765                 :          8 :   attempt->connection = g_proxy_connect_finish (G_PROXY (object),
    1766                 :            :                                                 result,
    1767                 :          8 :                                                 &data->error_info->tmp_error);
    1768         [ +  + ]:          8 :   if (attempt->connection)
    1769                 :            :     {
    1770                 :          4 :       g_socket_client_emit_event (data->client, G_SOCKET_CLIENT_PROXY_NEGOTIATED, data->connectable, attempt->connection);
    1771                 :          4 :       g_socket_client_tls_handshake (attempt);
    1772                 :            :     }
    1773                 :            :   else
    1774                 :            :     {
    1775                 :          4 :       connection_attempt_unref (attempt);
    1776                 :            : 
    1777                 :          4 :       consider_tmp_error (data->error_info, G_SOCKET_CLIENT_PROXY_NEGOTIATING);
    1778                 :          4 :       try_next_connection_or_finish (data, TRUE);
    1779                 :            :     }
    1780                 :          8 : }
    1781                 :            : 
    1782                 :            : static void
    1783                 :          7 : complete_connection_with_error (GSocketClientAsyncConnectData *data,
    1784                 :            :                                 GError                        *error)
    1785                 :            : {
    1786                 :          7 :   g_debug ("GSocketClient: Connection failed: %s", error->message);
    1787                 :          7 :   g_assert (!data->completed);
    1788                 :            : 
    1789                 :          7 :   g_socket_client_emit_event (data->client, G_SOCKET_CLIENT_COMPLETE, data->connectable, NULL);
    1790                 :          7 :   data->completed = TRUE;
    1791                 :          7 :   cancel_all_attempts (data);
    1792                 :          7 :   g_task_return_error (data->task, error);
    1793                 :          7 : }
    1794                 :            : 
    1795                 :            : static gboolean
    1796                 :         46 : task_completed_or_cancelled (GSocketClientAsyncConnectData *data)
    1797                 :            : {
    1798                 :         46 :   GTask *task = data->task;
    1799                 :         46 :   GCancellable *cancellable = g_task_get_cancellable (task);
    1800                 :         46 :   GError *error = NULL;
    1801                 :            : 
    1802         [ +  + ]:         46 :   if (data->completed)
    1803                 :          1 :     return TRUE;
    1804         [ +  + ]:         45 :   else if (g_cancellable_set_error_if_cancelled (cancellable, &error))
    1805                 :            :     {
    1806                 :          1 :       complete_connection_with_error (data, g_steal_pointer (&error));
    1807                 :          1 :       return TRUE;
    1808                 :            :     }
    1809                 :            :   else
    1810                 :         44 :     return FALSE;
    1811                 :            : }
    1812                 :            : 
    1813                 :            : /* Returns %TRUE if it’s popped a connection of data->successful_connections and
    1814                 :            :  * successfully started the next ongoing async operation for that connection. */
    1815                 :            : static gboolean
    1816                 :         19 : try_next_successful_connection (GSocketClientAsyncConnectData *data)
    1817                 :            : {
    1818                 :            :   ConnectionAttempt *attempt;
    1819                 :            :   const gchar *protocol;
    1820                 :            :   GProxy *proxy;
    1821                 :            : 
    1822         [ -  + ]:         19 :   if (data->connection_in_progress)
    1823                 :          0 :     return FALSE;
    1824                 :            : 
    1825                 :         19 :   g_assert (data->successful_connections != NULL);
    1826                 :         19 :   attempt = data->successful_connections->data;
    1827                 :         19 :   g_assert (attempt != NULL);
    1828                 :         19 :   data->successful_connections = g_slist_remove (data->successful_connections, attempt);
    1829                 :         19 :   data->connection_in_progress = TRUE;
    1830                 :            : 
    1831                 :         19 :   g_debug ("GSocketClient: Starting application layer connection");
    1832                 :            : 
    1833         [ +  + ]:         19 :   if (!attempt->proxy_addr)
    1834                 :            :     {
    1835                 :         11 :       g_socket_client_tls_handshake (g_steal_pointer (&attempt));
    1836                 :         11 :       return TRUE;
    1837                 :            :     }
    1838                 :            : 
    1839                 :          8 :   protocol = g_proxy_address_get_protocol (attempt->proxy_addr);
    1840                 :            : 
    1841                 :            :   /* The connection should not be anything other than TCP,
    1842                 :            :    * but let's put a safety guard in case
    1843                 :            :    */
    1844   [ -  +  +  -  :          8 :   if (!G_IS_TCP_CONNECTION (attempt->connection))
             +  -  -  + ]
    1845                 :            :     {
    1846                 :          0 :       g_critical ("Trying to proxy over non-TCP connection, this is "
    1847                 :            :           "most likely a bug in GLib IO library.");
    1848                 :            : 
    1849                 :          0 :       g_set_error_literal (&data->error_info->tmp_error,
    1850                 :            :           G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
    1851                 :            :           _("Proxying over a non-TCP connection is not supported."));
    1852                 :          0 :       consider_tmp_error (data->error_info, G_SOCKET_CLIENT_PROXY_NEGOTIATING);
    1853                 :            :     }
    1854         [ -  + ]:          8 :   else if (g_hash_table_contains (data->client->priv->app_proxies, protocol))
    1855                 :            :     {
    1856                 :            :       /* Simply complete the connection, we don't want to do TLS handshake
    1857                 :            :        * as the application proxy handling may need proxy handshake first */
    1858                 :          0 :       g_socket_client_async_connect_complete (g_steal_pointer (&attempt));
    1859                 :          0 :       return TRUE;
    1860                 :            :     }
    1861         [ +  - ]:          8 :   else if ((proxy = g_proxy_get_default_for_protocol (protocol)))
    1862                 :            :     {
    1863                 :          8 :       GIOStream *connection = attempt->connection;
    1864                 :          8 :       GProxyAddress *proxy_addr = attempt->proxy_addr;
    1865                 :            : 
    1866                 :          8 :       g_socket_client_emit_event (data->client, G_SOCKET_CLIENT_PROXY_NEGOTIATING, data->connectable, attempt->connection);
    1867                 :          8 :       g_debug ("GSocketClient: Starting proxy connection");
    1868                 :            : 
    1869                 :            :       /* FIXME: The #GProxy implementations do not have well-defined timeout
    1870                 :            :        * behaviour, so this operation may theoretically never complete or time
    1871                 :            :        * out. In practice, all #GProxy implementations use a #GSocket and a
    1872                 :            :        * default timeout on that will eventually be hit. But there is no
    1873                 :            :        * higher-level timeout. */
    1874                 :          8 :       g_proxy_connect_async (proxy,
    1875                 :            :                              connection,
    1876                 :            :                              proxy_addr,
    1877                 :            :                              g_task_get_cancellable (data->task),
    1878                 :            :                              g_socket_client_proxy_connect_callback,
    1879                 :            :                              g_steal_pointer (&attempt));
    1880                 :          8 :       g_object_unref (proxy);
    1881                 :          8 :       return TRUE;
    1882                 :            :     }
    1883                 :            :   else
    1884                 :            :     {
    1885                 :          0 :       g_set_error (&data->error_info->tmp_error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
    1886                 :            :           _("Proxy protocol “%s” is not supported."),
    1887                 :            :           protocol);
    1888                 :          0 :       consider_tmp_error (data->error_info, G_SOCKET_CLIENT_PROXY_NEGOTIATING);
    1889                 :            :     }
    1890                 :            : 
    1891                 :          0 :   data->connection_in_progress = FALSE;
    1892                 :          0 :   g_clear_pointer (&attempt, connection_attempt_unref);
    1893                 :          0 :   return FALSE; /* All non-return paths are failures */
    1894                 :            : }
    1895                 :            : 
    1896                 :            : static void
    1897                 :         23 : try_next_connection_or_finish (GSocketClientAsyncConnectData *data,
    1898                 :            :                                gboolean                       end_current_connection)
    1899                 :            : {
    1900         [ +  + ]:         23 :   if (end_current_connection)
    1901                 :          4 :     data->connection_in_progress = FALSE;
    1902                 :            : 
    1903         [ -  + ]:         23 :   if (data->connection_in_progress)
    1904                 :          0 :     return;
    1905                 :            : 
    1906                 :            :   /* Try to pop and make progress on the next successful_connection. */
    1907         [ +  + ]:         23 :   while (data->successful_connections)
    1908                 :            :     {
    1909         [ +  - ]:         19 :       if (try_next_successful_connection (data))
    1910                 :         19 :         return;
    1911                 :            :     }
    1912                 :            : 
    1913                 :            :   /* If there are no more successful_connections which we can make progress on,
    1914                 :            :    * try the next address enumeration. */
    1915         [ +  - ]:          4 :   if (!data->enumeration_completed)
    1916                 :            :     {
    1917                 :          4 :       enumerator_next_async (data, FALSE);
    1918                 :          4 :       return;
    1919                 :            :     }
    1920                 :            : 
    1921                 :          0 :   complete_connection_with_error (data, g_steal_pointer (&data->error_info->best_error));
    1922                 :            : }
    1923                 :            : 
    1924                 :            : static void
    1925                 :         19 : g_socket_client_connected_callback (GObject      *source,
    1926                 :            :                                     GAsyncResult *result,
    1927                 :            :                                     gpointer      user_data)
    1928                 :            : {
    1929                 :         19 :   ConnectionAttempt *attempt = g_steal_pointer (&user_data);
    1930                 :         19 :   GSocketClientAsyncConnectData *data = attempt->data;
    1931                 :            : 
    1932   [ +  -  -  + ]:         19 :   if (task_completed_or_cancelled (data) || g_cancellable_is_cancelled (attempt->cancellable))
    1933                 :            :     {
    1934                 :          0 :       connection_attempt_remove (attempt);
    1935                 :          0 :       connection_attempt_unref (attempt);
    1936                 :          0 :       g_object_unref (data->task);
    1937                 :          0 :       return;
    1938                 :            :     }
    1939                 :            : 
    1940         [ +  + ]:         19 :   if (attempt->delay_timeout_source)
    1941                 :            :     {
    1942                 :         17 :       g_source_destroy (attempt->delay_timeout_source);
    1943                 :         17 :       g_clear_pointer (&attempt->delay_timeout_source, g_source_unref);
    1944                 :            :     }
    1945                 :            : 
    1946         [ -  + ]:         19 :   if (!g_socket_connection_connect_finish (G_SOCKET_CONNECTION (source),
    1947                 :         19 :                                            result, &data->error_info->tmp_error))
    1948                 :            :     {
    1949         [ #  # ]:          0 :       if (!g_cancellable_is_cancelled (attempt->cancellable))
    1950                 :            :         {
    1951                 :          0 :           g_debug ("GSocketClient: Connection attempt failed: %s", data->error_info->tmp_error->message);
    1952                 :          0 :           clarify_connect_error (data->error_info->tmp_error, data->connectable, attempt->address);
    1953                 :          0 :           consider_tmp_error (data->error_info, G_SOCKET_CLIENT_CONNECTING);
    1954                 :          0 :           connection_attempt_remove (attempt);
    1955                 :          0 :           connection_attempt_unref (attempt);
    1956                 :          0 :           try_next_connection_or_finish (data, FALSE);
    1957                 :            :         }
    1958                 :            :       else /* Silently ignore cancelled attempts */
    1959                 :            :         {
    1960                 :          0 :           g_clear_error (&data->error_info->tmp_error);
    1961                 :          0 :           g_object_unref (data->task);
    1962                 :          0 :           connection_attempt_unref (attempt);
    1963                 :            :         }
    1964                 :            : 
    1965                 :          0 :       return;
    1966                 :            :     }
    1967                 :            : 
    1968                 :         19 :   g_socket_connection_set_cached_remote_address ((GSocketConnection*)attempt->connection, NULL);
    1969                 :         19 :   g_debug ("GSocketClient: TCP connection successful");
    1970                 :         19 :   g_socket_client_emit_event (data->client, G_SOCKET_CLIENT_CONNECTED, data->connectable, attempt->connection);
    1971                 :            : 
    1972                 :            :   /* wrong, but backward compatible */
    1973                 :         19 :   g_socket_set_blocking (attempt->socket, TRUE);
    1974                 :            : 
    1975                 :            :   /* This ends the parallel "happy eyeballs" portion of connecting.
    1976                 :            :      Now that we have a successful tcp connection we will attempt to connect
    1977                 :            :      at the TLS/Proxy layer. If those layers fail we will move on to the next
    1978                 :            :      connection.
    1979                 :            :    */
    1980                 :         19 :   connection_attempt_remove (attempt);
    1981                 :         19 :   data->successful_connections = g_slist_append (data->successful_connections, g_steal_pointer (&attempt));
    1982                 :         19 :   try_next_connection_or_finish (data, FALSE);
    1983                 :            : }
    1984                 :            : 
    1985                 :            : static gboolean
    1986                 :          2 : on_connection_attempt_delay_reached (gpointer data)
    1987                 :            : {
    1988                 :          2 :   ConnectionAttempt *attempt = data;
    1989                 :            : 
    1990                 :          2 :   g_assert (!attempt->delay_reached);
    1991                 :          2 :   attempt->delay_reached = TRUE;
    1992                 :            : 
    1993         [ +  - ]:          2 :   if (!attempt->data->enumeration_completed)
    1994                 :            :     {
    1995                 :          2 :       g_debug ("GSocketClient: Connection attempt delay reached, trying another enumeration");
    1996                 :          2 :       enumerator_next_async (attempt->data, TRUE);
    1997                 :            :     }
    1998                 :            : 
    1999                 :          2 :   g_clear_pointer (&attempt->delay_timeout_source, g_source_unref);
    2000                 :          2 :   return G_SOURCE_REMOVE;
    2001                 :            : }
    2002                 :            : 
    2003                 :            : static void
    2004                 :          3 : on_connection_cancelled (GCancellable *cancellable,
    2005                 :            :                          gpointer      data)
    2006                 :            : {
    2007                 :          3 :   GCancellable *linked_cancellable = G_CANCELLABLE (data);
    2008                 :            : 
    2009                 :          3 :   g_cancellable_cancel (linked_cancellable);
    2010                 :          3 : }
    2011                 :            : 
    2012                 :            : static void
    2013                 :         27 : g_socket_client_enumerator_callback (GObject      *object,
    2014                 :            :                                      GAsyncResult *result,
    2015                 :            :                                      gpointer      user_data)
    2016                 :            : {
    2017                 :         27 :   GSocketClientAsyncConnectData *data = user_data;
    2018                 :         27 :   GSocketAddress *address = NULL;
    2019                 :            :   GSocket *socket;
    2020                 :            :   ConnectionAttempt *attempt;
    2021                 :            : 
    2022         [ +  + ]:         27 :   if (task_completed_or_cancelled (data))
    2023                 :            :     {
    2024                 :          2 :       g_object_unref (data->task);
    2025                 :          2 :       return;
    2026                 :            :     }
    2027                 :            : 
    2028                 :         25 :   address = g_socket_address_enumerator_next_finish (data->enumerator,
    2029                 :         25 :                                                      result, &data->error_info->tmp_error);
    2030         [ +  + ]:         25 :   if (address == NULL)
    2031                 :            :     {
    2032         [ -  + ]:          6 :       if (G_UNLIKELY (data->enumeration_completed))
    2033                 :          0 :         return;
    2034                 :            : 
    2035                 :          6 :       data->enumeration_completed = TRUE;
    2036                 :          6 :       g_debug ("GSocketClient: Address enumeration completed (out of addresses)");
    2037                 :            : 
    2038                 :            :       /* As per API docs: We only care about error if it's the first call,
    2039                 :            :          after that the enumerator is done.
    2040                 :            : 
    2041                 :            :          Note that we don't care about cancellation errors because
    2042                 :            :          task_completed_or_cancelled() above should handle that.
    2043                 :            : 
    2044                 :            :          If this fails and nothing is in progress then we will complete task here.
    2045                 :            :        */
    2046   [ +  +  +  -  :          6 :       if ((data->n_addresses_enumerated > 0 && !data->connection_attempts && !data->connection_in_progress) ||
                   -  + ]
    2047         [ +  - ]:          3 :           data->n_addresses_enumerated == 0)
    2048                 :            :         {
    2049         [ +  + ]:          6 :           g_debug ("GSocketClient: Address enumeration failed: %s",
    2050                 :            :                    data->error_info->tmp_error ? data->error_info->tmp_error->message : NULL);
    2051                 :          6 :           consider_tmp_error (data->error_info, G_SOCKET_CLIENT_RESOLVING);
    2052                 :          6 :           g_assert (data->error_info->best_error);
    2053                 :          6 :           complete_connection_with_error (data, g_steal_pointer (&data->error_info->best_error));
    2054                 :            :         }
    2055                 :            : 
    2056                 :            :       /* Enumeration should never trigger again, drop our ref */
    2057                 :          6 :       g_object_unref (data->task);
    2058                 :          6 :       return;
    2059                 :            :     }
    2060                 :            : 
    2061                 :         19 :   g_debug ("GSocketClient: Address enumeration succeeded");
    2062         [ +  + ]:         19 :   if (data->n_addresses_enumerated == 0)
    2063                 :         18 :     g_socket_client_emit_event (data->client, G_SOCKET_CLIENT_RESOLVED,
    2064                 :            :                                 data->connectable, NULL);
    2065                 :            : 
    2066                 :         19 :   data->n_addresses_enumerated++;
    2067                 :            : 
    2068                 :         19 :   socket = create_socket (data->client, address, &data->error_info->tmp_error);
    2069         [ -  + ]:         19 :   if (socket == NULL)
    2070                 :            :     {
    2071                 :          0 :       g_object_unref (address);
    2072                 :          0 :       consider_tmp_error (data->error_info, G_SOCKET_CLIENT_CONNECTING);
    2073                 :          0 :       enumerator_next_async (data, FALSE);
    2074                 :          0 :       return;
    2075                 :            :     }
    2076                 :            : 
    2077                 :         19 :   attempt = connection_attempt_new ();
    2078                 :         19 :   attempt->data = data;
    2079                 :         19 :   attempt->socket = socket;
    2080                 :         19 :   attempt->address = address;
    2081                 :         19 :   attempt->cancellable = g_cancellable_new ();
    2082                 :         19 :   attempt->connection = (GIOStream *)g_socket_connection_factory_create_connection (socket);
    2083                 :         19 :   attempt->delay_timeout_source = g_timeout_source_new (HAPPY_EYEBALLS_CONNECTION_ATTEMPT_DELAY_MS);
    2084                 :            : 
    2085                 :         19 :   g_debug ("%s: starting connection attempt %p for GSocketClientAsyncConnectData %p",
    2086                 :            :            G_STRFUNC, attempt, data);
    2087                 :            : 
    2088   [ -  +  +  -  :         19 :   if (G_IS_PROXY_ADDRESS (address) && data->client->priv->enable_proxy)
          +  +  +  +  +  
                      - ]
    2089                 :          8 :     attempt->proxy_addr = g_object_ref (G_PROXY_ADDRESS (address));
    2090                 :            : 
    2091                 :         19 :   g_source_set_callback (attempt->delay_timeout_source, on_connection_attempt_delay_reached, attempt, NULL);
    2092                 :         19 :   g_source_attach (attempt->delay_timeout_source, g_task_get_context (data->task));
    2093                 :         19 :   data->connection_attempts = g_slist_append (data->connection_attempts, connection_attempt_ref (attempt));
    2094                 :            : 
    2095         [ +  + ]:         19 :   if (g_task_get_cancellable (data->task))
    2096                 :            :     {
    2097                 :          1 :       attempt->task_cancellable = g_object_ref (g_task_get_cancellable (data->task));
    2098                 :          1 :       attempt->cancelled_id =
    2099                 :          1 :           g_cancellable_connect (attempt->task_cancellable, G_CALLBACK (on_connection_cancelled),
    2100                 :          1 :                                  g_object_ref (attempt->cancellable), g_object_unref);
    2101                 :            :     }
    2102                 :            : 
    2103                 :         19 :   g_socket_connection_set_cached_remote_address ((GSocketConnection *)attempt->connection, address);
    2104                 :         19 :   g_debug ("GSocketClient: Starting TCP connection attempt");
    2105                 :         19 :   g_socket_client_emit_event (data->client, G_SOCKET_CLIENT_CONNECTING, data->connectable, attempt->connection);
    2106                 :            : 
    2107                 :            :   /* If client->priv->timeout is set, this async operation will time out after
    2108                 :            :    * then. Otherwise it will continue until the kernel timeouts for a
    2109                 :            :    * non-blocking connect() call (if any) are hit. */
    2110                 :         19 :   g_socket_connection_connect_async (G_SOCKET_CONNECTION (attempt->connection),
    2111                 :            :                                      address,
    2112                 :            :                                      attempt->cancellable,
    2113                 :            :                                      g_socket_client_connected_callback, attempt  /* transfer full */);
    2114                 :            : }
    2115                 :            : 
    2116                 :            : /**
    2117                 :            :  * g_socket_client_connect_async:
    2118                 :            :  * @client: a #GSocketClient
    2119                 :            :  * @connectable: a #GSocketConnectable specifying the remote address.
    2120                 :            :  * @cancellable: (nullable): a #GCancellable, or %NULL
    2121                 :            :  * @callback: (scope async): a #GAsyncReadyCallback
    2122                 :            :  * @user_data: user data for the callback
    2123                 :            :  *
    2124                 :            :  * This is the asynchronous version of g_socket_client_connect().
    2125                 :            :  *
    2126                 :            :  * You may wish to prefer the asynchronous version even in synchronous
    2127                 :            :  * command line programs because, since 2.60, it implements
    2128                 :            :  * [RFC 8305](https://tools.ietf.org/html/rfc8305) "Happy Eyeballs"
    2129                 :            :  * recommendations to work around long connection timeouts in networks
    2130                 :            :  * where IPv6 is broken by performing an IPv4 connection simultaneously
    2131                 :            :  * without waiting for IPv6 to time out, which is not supported by the
    2132                 :            :  * synchronous call. (This is not an API guarantee, and may change in
    2133                 :            :  * the future.)
    2134                 :            :  *
    2135                 :            :  * When the operation is finished @callback will be
    2136                 :            :  * called. You can then call g_socket_client_connect_finish() to get
    2137                 :            :  * the result of the operation.
    2138                 :            :  *
    2139                 :            :  * Since: 2.22
    2140                 :            :  */
    2141                 :            : void
    2142                 :         22 : g_socket_client_connect_async (GSocketClient       *client,
    2143                 :            :                                GSocketConnectable  *connectable,
    2144                 :            :                                GCancellable        *cancellable,
    2145                 :            :                                GAsyncReadyCallback  callback,
    2146                 :            :                                gpointer             user_data)
    2147                 :            : {
    2148                 :            :   GSocketClientAsyncConnectData *data;
    2149                 :            : 
    2150                 :         22 :   g_return_if_fail (G_IS_SOCKET_CLIENT (client));
    2151                 :            : 
    2152                 :         22 :   data = g_slice_new0 (GSocketClientAsyncConnectData);
    2153                 :         22 :   data->client = client;
    2154                 :         22 :   data->connectable = g_object_ref (connectable);
    2155                 :         22 :   data->error_info = socket_client_error_info_new ();
    2156                 :            : 
    2157         [ +  - ]:         22 :   if (can_use_proxy (client))
    2158                 :            :     {
    2159                 :         22 :       data->enumerator = g_socket_connectable_proxy_enumerate (connectable);
    2160         [ +  + ]:         22 :       if (client->priv->proxy_resolver &&
    2161   [ -  +  +  -  :          3 :           G_IS_PROXY_ADDRESS_ENUMERATOR (data->enumerator))
             +  -  +  - ]
    2162                 :            :         {
    2163                 :          3 :           g_object_set (G_OBJECT (data->enumerator),
    2164                 :          3 :                         "proxy-resolver", client->priv->proxy_resolver,
    2165                 :            :                         NULL);
    2166                 :            :         }
    2167                 :            :     }
    2168                 :            :   else
    2169                 :          0 :     data->enumerator = g_socket_connectable_enumerate (connectable);
    2170                 :            : 
    2171                 :            :   /* This function tries to match the behavior of g_socket_client_connect ()
    2172                 :            :      which is simple enough but much of it is done in parallel to be as responsive
    2173                 :            :      as possible as per Happy Eyeballs (RFC 8305). This complicates flow quite a
    2174                 :            :      bit but we can describe it in 3 sections:
    2175                 :            : 
    2176                 :            :      Firstly we have address enumeration (DNS):
    2177                 :            :        - This may be triggered multiple times by enumerator_next_async().
    2178                 :            :        - It also has its own cancellable (data->enumeration_cancellable).
    2179                 :            :        - Enumeration is done lazily because GNetworkAddressAddressEnumerator
    2180                 :            :          also does work in parallel and may lazily add new addresses.
    2181                 :            :        - If the first enumeration errors then the task errors. Otherwise all enumerations
    2182                 :            :          will potentially be used (until task or enumeration is cancelled).
    2183                 :            : 
    2184                 :            :       Then we start attempting connections (TCP):
    2185                 :            :         - Each connection is independent and kept in a ConnectionAttempt object.
    2186                 :            :           - They each hold a ref on the main task and have their own cancellable.
    2187                 :            :         - Multiple attempts may happen in parallel as per Happy Eyeballs.
    2188                 :            :         - Upon failure or attempt delays being reached more connection attempts are made.
    2189                 :            :           - If no connections succeed the task errors.
    2190                 :            :         - Upon success they are kept in a list of successful connections.
    2191                 :            : 
    2192                 :            :       Lastly we connect at the application layer (TLS, Proxies):
    2193                 :            :         - These are done in serial.
    2194                 :            :           - The reasoning here is that Happy Eyeballs is about making bad connections responsive
    2195                 :            :             at the IP/TCP layers. Issues at the application layer are generally not due to
    2196                 :            :             connectivity issues but rather misconfiguration.
    2197                 :            :         - Upon failure it will try the next TCP connection until it runs out and
    2198                 :            :           the task errors.
    2199                 :            :         - Upon success it cancels everything remaining (enumeration and connections)
    2200                 :            :           and returns the connection.
    2201                 :            :   */
    2202                 :            : 
    2203                 :         22 :   data->task = g_task_new (client, cancellable, callback, user_data);
    2204                 :         22 :   g_task_set_check_cancellable (data->task, FALSE); /* We handle this manually */
    2205         [ +  - ]:         22 :   g_task_set_source_tag (data->task, g_socket_client_connect_async);
    2206                 :         22 :   g_task_set_task_data (data->task, data, (GDestroyNotify)g_socket_client_async_connect_data_free);
    2207                 :            : 
    2208                 :         22 :   data->enumeration_cancellable = g_cancellable_new ();
    2209         [ +  + ]:         22 :   if (cancellable)
    2210                 :            :     {
    2211                 :          2 :       data->enumeration_parent_cancellable = g_object_ref (cancellable);
    2212                 :          2 :       data->enumeration_cancelled_id =
    2213                 :          2 :           g_cancellable_connect (cancellable, G_CALLBACK (on_connection_cancelled),
    2214                 :          2 :                                  g_object_ref (data->enumeration_cancellable), g_object_unref);
    2215                 :            :     }
    2216                 :            : 
    2217                 :         22 :   g_debug ("%s: starting new g_socket_client_connect_async() with GTask %p "
    2218                 :            :            "and GSocketClientAsyncConnectData %p",
    2219                 :            :            G_STRFUNC, data->task, data);
    2220                 :            : 
    2221                 :         22 :   enumerator_next_async (data, FALSE);
    2222                 :            : }
    2223                 :            : 
    2224                 :            : /**
    2225                 :            :  * g_socket_client_connect_to_host_async:
    2226                 :            :  * @client: a #GSocketClient
    2227                 :            :  * @host_and_port: the name and optionally the port of the host to connect to
    2228                 :            :  * @default_port: the default port to connect to
    2229                 :            :  * @cancellable: (nullable): a #GCancellable, or %NULL
    2230                 :            :  * @callback: (scope async): a #GAsyncReadyCallback
    2231                 :            :  * @user_data: user data for the callback
    2232                 :            :  *
    2233                 :            :  * This is the asynchronous version of g_socket_client_connect_to_host().
    2234                 :            :  *
    2235                 :            :  * When the operation is finished @callback will be
    2236                 :            :  * called. You can then call g_socket_client_connect_to_host_finish() to get
    2237                 :            :  * the result of the operation.
    2238                 :            :  *
    2239                 :            :  * Since: 2.22
    2240                 :            :  */
    2241                 :            : void
    2242                 :          3 : g_socket_client_connect_to_host_async (GSocketClient        *client,
    2243                 :            :                                        const gchar          *host_and_port,
    2244                 :            :                                        guint16               default_port,
    2245                 :            :                                        GCancellable         *cancellable,
    2246                 :            :                                        GAsyncReadyCallback   callback,
    2247                 :            :                                        gpointer              user_data)
    2248                 :            : {
    2249                 :            :   GSocketConnectable *connectable;
    2250                 :            :   GError *error;
    2251                 :            : 
    2252                 :          3 :   error = NULL;
    2253                 :          3 :   connectable = g_network_address_parse (host_and_port, default_port,
    2254                 :            :                                          &error);
    2255         [ -  + ]:          3 :   if (connectable == NULL)
    2256                 :            :     {
    2257                 :          0 :       g_task_report_error (client, callback, user_data,
    2258                 :            :                            g_socket_client_connect_to_host_async,
    2259                 :            :                            error);
    2260                 :            :     }
    2261                 :            :   else
    2262                 :            :     {
    2263                 :          3 :       g_socket_client_connect_async (client,
    2264                 :            :                                      connectable, cancellable,
    2265                 :            :                                      callback, user_data);
    2266                 :          3 :       g_object_unref (connectable);
    2267                 :            :     }
    2268                 :          3 : }
    2269                 :            : 
    2270                 :            : /**
    2271                 :            :  * g_socket_client_connect_to_service_async:
    2272                 :            :  * @client: a #GSocketClient
    2273                 :            :  * @domain: a domain name
    2274                 :            :  * @service: the name of the service to connect to
    2275                 :            :  * @cancellable: (nullable): a #GCancellable, or %NULL
    2276                 :            :  * @callback: (scope async): a #GAsyncReadyCallback
    2277                 :            :  * @user_data: user data for the callback
    2278                 :            :  *
    2279                 :            :  * This is the asynchronous version of
    2280                 :            :  * g_socket_client_connect_to_service().
    2281                 :            :  *
    2282                 :            :  * Since: 2.22
    2283                 :            :  */
    2284                 :            : void
    2285                 :          0 : g_socket_client_connect_to_service_async (GSocketClient       *client,
    2286                 :            :                                           const gchar         *domain,
    2287                 :            :                                           const gchar         *service,
    2288                 :            :                                           GCancellable        *cancellable,
    2289                 :            :                                           GAsyncReadyCallback  callback,
    2290                 :            :                                           gpointer             user_data)
    2291                 :            : {
    2292                 :            :   GSocketConnectable *connectable;
    2293                 :            : 
    2294                 :          0 :   connectable = g_network_service_new (service, "tcp", domain);
    2295                 :          0 :   g_socket_client_connect_async (client,
    2296                 :            :                                  connectable, cancellable,
    2297                 :            :                                  callback, user_data);
    2298                 :          0 :   g_object_unref (connectable);
    2299                 :          0 : }
    2300                 :            : 
    2301                 :            : /**
    2302                 :            :  * g_socket_client_connect_to_uri_async:
    2303                 :            :  * @client: a #GSocketClient
    2304                 :            :  * @uri: a network uri
    2305                 :            :  * @default_port: the default port to connect to
    2306                 :            :  * @cancellable: (nullable): a #GCancellable, or %NULL
    2307                 :            :  * @callback: (scope async): a #GAsyncReadyCallback
    2308                 :            :  * @user_data: user data for the callback
    2309                 :            :  *
    2310                 :            :  * This is the asynchronous version of g_socket_client_connect_to_uri().
    2311                 :            :  *
    2312                 :            :  * When the operation is finished @callback will be
    2313                 :            :  * called. You can then call g_socket_client_connect_to_uri_finish() to get
    2314                 :            :  * the result of the operation.
    2315                 :            :  *
    2316                 :            :  * Since: 2.26
    2317                 :            :  */
    2318                 :            : void
    2319                 :         14 : g_socket_client_connect_to_uri_async (GSocketClient        *client,
    2320                 :            :                                       const gchar          *uri,
    2321                 :            :                                       guint16               default_port,
    2322                 :            :                                       GCancellable         *cancellable,
    2323                 :            :                                       GAsyncReadyCallback   callback,
    2324                 :            :                                       gpointer              user_data)
    2325                 :            : {
    2326                 :            :   GSocketConnectable *connectable;
    2327                 :            :   GError *error;
    2328                 :            : 
    2329                 :         14 :   error = NULL;
    2330                 :         14 :   connectable = g_network_address_parse_uri (uri, default_port, &error);
    2331         [ +  + ]:         14 :   if (connectable == NULL)
    2332                 :            :     {
    2333                 :          1 :       g_task_report_error (client, callback, user_data,
    2334                 :            :                            g_socket_client_connect_to_uri_async,
    2335                 :            :                            error);
    2336                 :            :     }
    2337                 :            :   else
    2338                 :            :     {
    2339                 :         13 :       g_debug("g_socket_client_connect_to_uri_async");
    2340                 :         13 :       g_socket_client_connect_async (client,
    2341                 :            :                                      connectable, cancellable,
    2342                 :            :                                      callback, user_data);
    2343                 :         13 :       g_object_unref (connectable);
    2344                 :            :     }
    2345                 :         14 : }
    2346                 :            : 
    2347                 :            : 
    2348                 :            : /**
    2349                 :            :  * g_socket_client_connect_finish:
    2350                 :            :  * @client: a #GSocketClient.
    2351                 :            :  * @result: a #GAsyncResult.
    2352                 :            :  * @error: a #GError location to store the error occurring, or %NULL to
    2353                 :            :  * ignore.
    2354                 :            :  *
    2355                 :            :  * Finishes an async connect operation. See g_socket_client_connect_async()
    2356                 :            :  *
    2357                 :            :  * Returns: (transfer full): a #GSocketConnection on success, %NULL on error.
    2358                 :            :  *
    2359                 :            :  * Since: 2.22
    2360                 :            :  */
    2361                 :            : GSocketConnection *
    2362                 :         23 : g_socket_client_connect_finish (GSocketClient  *client,
    2363                 :            :                                 GAsyncResult   *result,
    2364                 :            :                                 GError        **error)
    2365                 :            : {
    2366                 :         23 :   g_return_val_if_fail (g_task_is_valid (result, client), NULL);
    2367                 :            : 
    2368                 :         23 :   return g_task_propagate_pointer (G_TASK (result), error);
    2369                 :            : }
    2370                 :            : 
    2371                 :            : /**
    2372                 :            :  * g_socket_client_connect_to_host_finish:
    2373                 :            :  * @client: a #GSocketClient.
    2374                 :            :  * @result: a #GAsyncResult.
    2375                 :            :  * @error: a #GError location to store the error occurring, or %NULL to
    2376                 :            :  * ignore.
    2377                 :            :  *
    2378                 :            :  * Finishes an async connect operation. See g_socket_client_connect_to_host_async()
    2379                 :            :  *
    2380                 :            :  * Returns: (transfer full): a #GSocketConnection on success, %NULL on error.
    2381                 :            :  *
    2382                 :            :  * Since: 2.22
    2383                 :            :  */
    2384                 :            : GSocketConnection *
    2385                 :          0 : g_socket_client_connect_to_host_finish (GSocketClient  *client,
    2386                 :            :                                         GAsyncResult   *result,
    2387                 :            :                                         GError        **error)
    2388                 :            : {
    2389                 :          0 :   return g_socket_client_connect_finish (client, result, error);
    2390                 :            : }
    2391                 :            : 
    2392                 :            : /**
    2393                 :            :  * g_socket_client_connect_to_service_finish:
    2394                 :            :  * @client: a #GSocketClient.
    2395                 :            :  * @result: a #GAsyncResult.
    2396                 :            :  * @error: a #GError location to store the error occurring, or %NULL to
    2397                 :            :  * ignore.
    2398                 :            :  *
    2399                 :            :  * Finishes an async connect operation. See g_socket_client_connect_to_service_async()
    2400                 :            :  *
    2401                 :            :  * Returns: (transfer full): a #GSocketConnection on success, %NULL on error.
    2402                 :            :  *
    2403                 :            :  * Since: 2.22
    2404                 :            :  */
    2405                 :            : GSocketConnection *
    2406                 :          0 : g_socket_client_connect_to_service_finish (GSocketClient  *client,
    2407                 :            :                                            GAsyncResult   *result,
    2408                 :            :                                            GError        **error)
    2409                 :            : {
    2410                 :          0 :   return g_socket_client_connect_finish (client, result, error);
    2411                 :            : }
    2412                 :            : 
    2413                 :            : /**
    2414                 :            :  * g_socket_client_connect_to_uri_finish:
    2415                 :            :  * @client: a #GSocketClient.
    2416                 :            :  * @result: a #GAsyncResult.
    2417                 :            :  * @error: a #GError location to store the error occurring, or %NULL to
    2418                 :            :  * ignore.
    2419                 :            :  *
    2420                 :            :  * Finishes an async connect operation. See g_socket_client_connect_to_uri_async()
    2421                 :            :  *
    2422                 :            :  * Returns: (transfer full): a #GSocketConnection on success, %NULL on error.
    2423                 :            :  *
    2424                 :            :  * Since: 2.26
    2425                 :            :  */
    2426                 :            : GSocketConnection *
    2427                 :          3 : g_socket_client_connect_to_uri_finish (GSocketClient  *client,
    2428                 :            :                                        GAsyncResult   *result,
    2429                 :            :                                        GError        **error)
    2430                 :            : {
    2431                 :          3 :   return g_socket_client_connect_finish (client, result, error);
    2432                 :            : }
    2433                 :            : 
    2434                 :            : /**
    2435                 :            :  * g_socket_client_add_application_proxy:
    2436                 :            :  * @client: a #GSocketClient
    2437                 :            :  * @protocol: The proxy protocol
    2438                 :            :  *
    2439                 :            :  * Enable proxy protocols to be handled by the application. When the
    2440                 :            :  * indicated proxy protocol is returned by the #GProxyResolver,
    2441                 :            :  * #GSocketClient will consider this protocol as supported but will
    2442                 :            :  * not try to find a #GProxy instance to handle handshaking. The
    2443                 :            :  * application must check for this case by calling
    2444                 :            :  * g_socket_connection_get_remote_address() on the returned
    2445                 :            :  * #GSocketConnection, and seeing if it's a #GProxyAddress of the
    2446                 :            :  * appropriate type, to determine whether or not it needs to handle
    2447                 :            :  * the proxy handshaking itself.
    2448                 :            :  *
    2449                 :            :  * This should be used for proxy protocols that are dialects of
    2450                 :            :  * another protocol such as HTTP proxy. It also allows cohabitation of
    2451                 :            :  * proxy protocols that are reused between protocols. A good example
    2452                 :            :  * is HTTP. It can be used to proxy HTTP, FTP and Gopher and can also
    2453                 :            :  * be use as generic socket proxy through the HTTP CONNECT method.
    2454                 :            :  *
    2455                 :            :  * When the proxy is detected as being an application proxy, TLS handshake
    2456                 :            :  * will be skipped. This is required to let the application do the proxy
    2457                 :            :  * specific handshake.
    2458                 :            :  */
    2459                 :            : void
    2460                 :          0 : g_socket_client_add_application_proxy (GSocketClient *client,
    2461                 :            :                                        const gchar   *protocol)
    2462                 :            : {
    2463                 :          0 :   g_hash_table_add (client->priv->app_proxies, g_strdup (protocol));
    2464                 :          0 : }

Generated by: LCOV version 1.14