LCOV - code coverage report
Current view: top level - gio - gproxyaddressenumerator.c (source / functions) Coverage Total Hit
Test: unnamed Lines: 94.1 % 306 288
Test Date: 2024-11-26 05:23:01 Functions: 100.0 % 21 21
Branches: - 0 0

             Branch data     Line data    Source code
       1                 :             : /* GIO - GLib Input, Output and Streaming Library
       2                 :             :  *
       3                 :             :  * Copyright (C) 2010 Collabora, Ltd.
       4                 :             :  *
       5                 :             :  * SPDX-License-Identifier: LGPL-2.1-or-later
       6                 :             :  *
       7                 :             :  * This library is free software; you can redistribute it and/or
       8                 :             :  * modify it under the terms of the GNU Lesser General Public
       9                 :             :  * License as published by the Free Software Foundation; either
      10                 :             :  * version 2.1 of the License, or (at your option) any later version.
      11                 :             :  *
      12                 :             :  * This library is distributed in the hope that it will be useful,
      13                 :             :  * but WITHOUT ANY WARRANTY; without even the implied warranty of
      14                 :             :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      15                 :             :  * Lesser General Public License for more details.
      16                 :             :  *
      17                 :             :  * You should have received a copy of the GNU Lesser General
      18                 :             :  * Public License along with this library; if not, see <http://www.gnu.org/licenses/>.
      19                 :             :  *
      20                 :             :  * Author: Nicolas Dufresne <nicolas.dufresne@collabora.co.uk>
      21                 :             :  */
      22                 :             : 
      23                 :             : #include "config.h"
      24                 :             : #include "gproxyaddressenumerator.h"
      25                 :             : 
      26                 :             : #include <string.h>
      27                 :             : 
      28                 :             : #include "gasyncresult.h"
      29                 :             : #include "ginetaddress.h"
      30                 :             : #include "gioerror.h"
      31                 :             : #include "glibintl.h"
      32                 :             : #include "glib-private.h"
      33                 :             : #include "gnetworkaddress.h"
      34                 :             : #include "gnetworkingprivate.h"
      35                 :             : #include "gproxy.h"
      36                 :             : #include "gproxyaddress.h"
      37                 :             : #include "gproxyresolver.h"
      38                 :             : #include "gtask.h"
      39                 :             : #include "gresolver.h"
      40                 :             : #include "gsocketaddress.h"
      41                 :             : #include "gsocketaddressenumerator.h"
      42                 :             : #include "gsocketconnectable.h"
      43                 :             : 
      44                 :             : /**
      45                 :             :  * GProxyAddressEnumerator:
      46                 :             :  *
      47                 :             :  * `GProxyAddressEnumerator` is a wrapper around
      48                 :             :  * [class@Gio.SocketAddressEnumerator] which takes the [class@Gio.SocketAddress]
      49                 :             :  * instances returned by the [class@Gio.SocketAddressEnumerator]
      50                 :             :  * and wraps them in [class@Gio.ProxyAddress] instances, using the given
      51                 :             :  * [property@Gio.ProxyAddressEnumerator:proxy-resolver].
      52                 :             :  *
      53                 :             :  * This enumerator will be returned (for example, by
      54                 :             :  * [method@Gio.SocketConnectable.enumerate]) as appropriate when a proxy is
      55                 :             :  * configured; there should be no need to manually wrap a
      56                 :             :  * [class@Gio.SocketAddressEnumerator] instance with one.
      57                 :             :  */
      58                 :             : 
      59                 :             : #define GET_PRIVATE(o) (G_PROXY_ADDRESS_ENUMERATOR (o)->priv)
      60                 :             : 
      61                 :             : enum
      62                 :             : {
      63                 :             :   PROP_0,
      64                 :             :   PROP_URI,
      65                 :             :   PROP_DEFAULT_PORT,
      66                 :             :   PROP_CONNECTABLE,
      67                 :             :   PROP_PROXY_RESOLVER
      68                 :             : };
      69                 :             : 
      70                 :             : struct _GProxyAddressEnumeratorPrivate
      71                 :             : {
      72                 :             :   /* Destination address */
      73                 :             :   GSocketConnectable *connectable;
      74                 :             :   gchar              *dest_uri;
      75                 :             :   guint16             default_port;
      76                 :             :   gchar              *dest_hostname;
      77                 :             :   guint16             dest_port;
      78                 :             :   GList              *dest_ips;
      79                 :             : 
      80                 :             :   /* Proxy enumeration */
      81                 :             :   GProxyResolver           *proxy_resolver;
      82                 :             :   gchar                   **proxies;
      83                 :             :   gchar                   **next_proxy;
      84                 :             :   GSocketAddressEnumerator *addr_enum;
      85                 :             :   GSocketAddress           *proxy_address;
      86                 :             :   const gchar              *proxy_uri;
      87                 :             :   gchar                    *proxy_type;
      88                 :             :   gchar                    *proxy_username;
      89                 :             :   gchar                    *proxy_password;
      90                 :             :   gboolean                  supports_hostname;
      91                 :             :   GList                    *next_dest_ip;
      92                 :             :   GError                   *last_error;
      93                 :             : 
      94                 :             :   /* ever_enumerated is TRUE after we've returned a result for the first time
      95                 :             :    * via g_proxy_address_enumerator_next() or _next_async(). If FALSE, we have
      96                 :             :    * never returned yet, and should return an error if returning NULL because
      97                 :             :    * it does not make sense for a proxy resolver to return NULL except on error.
      98                 :             :    * (Whereas a DNS resolver would return NULL with no error to indicate "no
      99                 :             :    * results", a proxy resolver would want to return "direct://" instead, so
     100                 :             :    * NULL without error does not make sense for us.)
     101                 :             :    *
     102                 :             :    * But if ever_enumerated is TRUE, then we must not report any further errors
     103                 :             :    * (except for G_IO_ERROR_CANCELLED), because this is an API contract of
     104                 :             :    * GSocketAddressEnumerator.
     105                 :             :    */
     106                 :             :   gboolean                  ever_enumerated;
     107                 :             : };
     108                 :             : 
     109                 :        4479 : G_DEFINE_TYPE_WITH_PRIVATE (GProxyAddressEnumerator, g_proxy_address_enumerator, G_TYPE_SOCKET_ADDRESS_ENUMERATOR)
     110                 :             : 
     111                 :             : static void
     112                 :          28 : save_userinfo (GProxyAddressEnumeratorPrivate *priv,
     113                 :             :                const gchar *proxy)
     114                 :             : {
     115                 :          28 :   g_clear_pointer (&priv->proxy_username, g_free);
     116                 :          28 :   g_clear_pointer (&priv->proxy_password, g_free);
     117                 :             : 
     118                 :          28 :   g_uri_split_with_user (proxy, G_URI_FLAGS_HAS_PASSWORD, NULL,
     119                 :             :                          &priv->proxy_username, &priv->proxy_password,
     120                 :             :                          NULL, NULL, NULL, NULL, NULL, NULL, NULL);
     121                 :          28 : }
     122                 :             : 
     123                 :             : static void
     124                 :         557 : next_enumerator (GProxyAddressEnumeratorPrivate *priv)
     125                 :             : {
     126                 :         557 :   if (priv->proxy_address)
     127                 :           0 :     return;
     128                 :             : 
     129                 :        1026 :   while (priv->addr_enum == NULL && *priv->next_proxy)
     130                 :             :     {
     131                 :         469 :       GSocketConnectable *connectable = NULL;
     132                 :             :       GProxy *proxy;
     133                 :             : 
     134                 :         469 :       priv->proxy_uri = *priv->next_proxy++;
     135                 :         469 :       g_free (priv->proxy_type);
     136                 :         469 :       priv->proxy_type = g_uri_parse_scheme (priv->proxy_uri);
     137                 :             : 
     138                 :         469 :       if (priv->proxy_type == NULL)
     139                 :           6 :         continue;
     140                 :             : 
     141                 :             :       /* Assumes hostnames are supported for unknown protocols */
     142                 :         463 :       priv->supports_hostname = TRUE;
     143                 :         463 :       proxy = g_proxy_get_default_for_protocol (priv->proxy_type);
     144                 :         463 :       if (proxy)
     145                 :             :         {
     146                 :          28 :           priv->supports_hostname = g_proxy_supports_hostname (proxy);
     147                 :          28 :           g_object_unref (proxy);
     148                 :             :         }
     149                 :             : 
     150                 :         463 :       if (strcmp ("direct", priv->proxy_type) == 0)
     151                 :             :         {
     152                 :         435 :           if (priv->connectable)
     153                 :         435 :             connectable = g_object_ref (priv->connectable);
     154                 :             :           else
     155                 :           0 :             connectable = g_network_address_new (priv->dest_hostname,
     156                 :           0 :                                                  priv->dest_port);
     157                 :             :         }
     158                 :             :       else
     159                 :             :         {
     160                 :          28 :           GError *error = NULL;
     161                 :             :           int default_port;
     162                 :             : 
     163                 :          28 :           default_port = GLIB_PRIVATE_CALL (g_uri_get_default_scheme_port) (priv->proxy_type);
     164                 :          28 :           if (default_port == -1)
     165                 :          28 :             default_port = 0;
     166                 :             : 
     167                 :          28 :           connectable = g_network_address_parse_uri (priv->proxy_uri, default_port, &error);
     168                 :          28 :           if (error)
     169                 :             :             {
     170                 :           0 :               g_warning ("Invalid proxy URI '%s': %s",
     171                 :             :                          priv->proxy_uri, error->message);
     172                 :           0 :               g_error_free (error);
     173                 :             :             }
     174                 :             : 
     175                 :          28 :           save_userinfo (priv, priv->proxy_uri);
     176                 :             :         }
     177                 :             : 
     178                 :         463 :       if (connectable)
     179                 :             :         {
     180                 :         463 :           priv->addr_enum = g_socket_connectable_enumerate (connectable);
     181                 :         463 :           g_object_unref (connectable);
     182                 :             :         }
     183                 :             :     }
     184                 :             : }
     185                 :             : 
     186                 :             : static GSocketAddress *
     187                 :         314 : g_proxy_address_enumerator_next (GSocketAddressEnumerator  *enumerator,
     188                 :             :                                  GCancellable              *cancellable,
     189                 :             :                                  GError                   **error)
     190                 :             : {
     191                 :         314 :   GProxyAddressEnumeratorPrivate *priv = GET_PRIVATE (enumerator);
     192                 :         314 :   GSocketAddress *result = NULL;
     193                 :         314 :   GError *first_error = NULL;
     194                 :             : 
     195                 :         314 :   if (!priv->ever_enumerated)
     196                 :             :     {
     197                 :         226 :       g_assert (priv->proxies == NULL);
     198                 :         452 :       priv->proxies = g_proxy_resolver_lookup (priv->proxy_resolver,
     199                 :         226 :                                                priv->dest_uri,
     200                 :             :                                                cancellable,
     201                 :             :                                                error);
     202                 :         226 :       priv->next_proxy = priv->proxies;
     203                 :             : 
     204                 :         226 :       if (priv->proxies == NULL)
     205                 :             :         {
     206                 :           0 :           priv->ever_enumerated = TRUE;
     207                 :           0 :           return NULL;
     208                 :             :         }
     209                 :             :     }
     210                 :             : 
     211                 :         637 :   while (result == NULL && (*priv->next_proxy || priv->addr_enum))
     212                 :             :     {
     213                 :             :       gchar *dest_hostname;
     214                 :             :       gchar *dest_protocol;
     215                 :             :       GInetSocketAddress *inetsaddr;
     216                 :             :       GInetAddress *inetaddr;
     217                 :             :       guint16 port;
     218                 :             : 
     219                 :         323 :       next_enumerator (priv);
     220                 :             : 
     221                 :         323 :       if (!priv->addr_enum)
     222                 :           2 :         continue;
     223                 :             : 
     224                 :         321 :       if (priv->proxy_address == NULL)
     225                 :             :         {
     226                 :         321 :           priv->proxy_address = g_socket_address_enumerator_next (
     227                 :             :                                     priv->addr_enum,
     228                 :             :                                     cancellable,
     229                 :         321 :                                     first_error ? NULL : &first_error);
     230                 :             :         }
     231                 :             : 
     232                 :         321 :       if (priv->proxy_address == NULL)
     233                 :             :         {
     234                 :          91 :           g_object_unref (priv->addr_enum);
     235                 :          91 :           priv->addr_enum = NULL;
     236                 :             : 
     237                 :          91 :           if (priv->dest_ips)
     238                 :             :             {
     239                 :           7 :               g_resolver_free_addresses (priv->dest_ips);
     240                 :           7 :               priv->dest_ips = NULL;
     241                 :             :             }
     242                 :             : 
     243                 :          91 :           continue;
     244                 :             :         }
     245                 :             : 
     246                 :         230 :       if (strcmp ("direct", priv->proxy_type) == 0)
     247                 :             :         {
     248                 :         212 :           result = priv->proxy_address;
     249                 :         212 :           priv->proxy_address = NULL;
     250                 :         212 :           continue;
     251                 :             :         }
     252                 :             : 
     253                 :          18 :       if (!priv->supports_hostname)
     254                 :             :         {
     255                 :             :           GInetAddress *dest_ip;
     256                 :             : 
     257                 :          11 :           if (!priv->dest_ips)
     258                 :             :             {
     259                 :             :               GResolver *resolver;
     260                 :             : 
     261                 :          11 :               resolver = g_resolver_get_default();
     262                 :          11 :               priv->dest_ips = g_resolver_lookup_by_name (resolver,
     263                 :          11 :                                                           priv->dest_hostname,
     264                 :             :                                                           cancellable,
     265                 :          11 :                                                           first_error ? NULL : &first_error);
     266                 :          11 :               g_object_unref (resolver);
     267                 :             : 
     268                 :          11 :               if (!priv->dest_ips)
     269                 :             :                 {
     270                 :           2 :                   g_object_unref (priv->proxy_address);
     271                 :           2 :                   priv->proxy_address = NULL;
     272                 :           2 :                   continue;
     273                 :             :                 }
     274                 :             :             }
     275                 :             : 
     276                 :           9 :           if (!priv->next_dest_ip)
     277                 :           9 :             priv->next_dest_ip = priv->dest_ips;
     278                 :             :         
     279                 :           9 :           dest_ip = G_INET_ADDRESS (priv->next_dest_ip->data);
     280                 :           9 :           dest_hostname = g_inet_address_to_string (dest_ip);
     281                 :             : 
     282                 :           9 :           priv->next_dest_ip = g_list_next (priv->next_dest_ip);
     283                 :             :         }
     284                 :             :       else
     285                 :             :         {
     286                 :          14 :           dest_hostname = g_strdup (priv->dest_hostname);
     287                 :             :         }
     288                 :             : 
     289                 :          16 :       g_assert (G_IS_INET_SOCKET_ADDRESS (priv->proxy_address));
     290                 :             : 
     291                 :          16 :       dest_protocol = g_uri_parse_scheme (priv->dest_uri);
     292                 :             : 
     293                 :          16 :       inetsaddr = G_INET_SOCKET_ADDRESS (priv->proxy_address);
     294                 :          16 :       inetaddr = g_inet_socket_address_get_address (inetsaddr);
     295                 :          16 :       port = g_inet_socket_address_get_port (inetsaddr);
     296                 :             : 
     297                 :          16 :       result = g_object_new (G_TYPE_PROXY_ADDRESS,
     298                 :             :                              "address", inetaddr,
     299                 :             :                              "port", port,
     300                 :             :                              "protocol", priv->proxy_type,
     301                 :             :                              "destination-protocol", dest_protocol,
     302                 :             :                              "destination-hostname", dest_hostname,
     303                 :          16 :                              "destination-port", priv->dest_port,
     304                 :             :                              "username", priv->proxy_username,
     305                 :             :                              "password", priv->proxy_password,
     306                 :             :                              "uri", priv->proxy_uri,
     307                 :             :                              NULL);
     308                 :          16 :       g_free (dest_hostname);
     309                 :          16 :       g_free (dest_protocol);
     310                 :             : 
     311                 :          16 :       if (priv->supports_hostname || priv->next_dest_ip == NULL)
     312                 :             :         {
     313                 :          16 :           g_object_unref (priv->proxy_address);
     314                 :          16 :           priv->proxy_address = NULL;
     315                 :             :         }
     316                 :             :     }
     317                 :             : 
     318                 :         314 :   if (result == NULL && first_error && (!priv->ever_enumerated || g_error_matches (first_error, G_IO_ERROR, G_IO_ERROR_CANCELLED)))
     319                 :           1 :     g_propagate_error (error, first_error);
     320                 :         313 :   else if (first_error)
     321                 :           2 :     g_error_free (first_error);
     322                 :             : 
     323                 :         314 :   if (result == NULL && error != NULL && *error == NULL && !priv->ever_enumerated)
     324                 :           2 :     g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_FAILED, _("Unspecified proxy lookup failure"));
     325                 :             : 
     326                 :         314 :   priv->ever_enumerated = TRUE;
     327                 :             : 
     328                 :         314 :   return result;
     329                 :             : }
     330                 :             : 
     331                 :             : static void
     332                 :          86 : complete_async (GTask *task)
     333                 :             : {
     334                 :          86 :   GProxyAddressEnumeratorPrivate *priv = g_task_get_task_data (task);
     335                 :             : 
     336                 :          86 :   if (priv->last_error && (!priv->ever_enumerated || g_error_matches (priv->last_error, G_IO_ERROR, G_IO_ERROR_CANCELLED)))
     337                 :             :     {
     338                 :           4 :       g_task_return_error (task, priv->last_error);
     339                 :           4 :       priv->last_error = NULL;
     340                 :             :     }
     341                 :          82 :   else if (!priv->ever_enumerated)
     342                 :             :     {
     343                 :           2 :       g_task_return_new_error_literal (task, G_IO_ERROR, G_IO_ERROR_FAILED,
     344                 :           2 :                                        _("Unspecified proxy lookup failure"));
     345                 :             :     }
     346                 :             :   else
     347                 :             :     {
     348                 :          80 :       g_task_return_pointer (task, NULL, NULL);
     349                 :             :     }
     350                 :             : 
     351                 :          86 :   priv->ever_enumerated = TRUE;
     352                 :             : 
     353                 :          86 :   g_clear_error (&priv->last_error);
     354                 :          86 :   g_object_unref (task);
     355                 :          86 : }
     356                 :             : 
     357                 :             : static void
     358                 :         230 : return_result (GTask *task)
     359                 :             : {
     360                 :         230 :   GProxyAddressEnumeratorPrivate *priv = g_task_get_task_data (task);
     361                 :             :   GSocketAddress *result;
     362                 :             : 
     363                 :         230 :   if (strcmp ("direct", priv->proxy_type) == 0)
     364                 :             :     {
     365                 :         222 :       result = priv->proxy_address;
     366                 :         222 :       priv->proxy_address = NULL;
     367                 :             :     }
     368                 :             :   else
     369                 :             :     {
     370                 :             :       gchar *dest_hostname, *dest_protocol;
     371                 :             :       GInetSocketAddress *inetsaddr;
     372                 :             :       GInetAddress *inetaddr;
     373                 :             :       guint16 port;
     374                 :             : 
     375                 :           8 :       if (!priv->supports_hostname)
     376                 :             :         {
     377                 :             :           GInetAddress *dest_ip;
     378                 :             : 
     379                 :           5 :           if (!priv->next_dest_ip)
     380                 :           5 :             priv->next_dest_ip = priv->dest_ips;
     381                 :             : 
     382                 :           5 :           dest_ip = G_INET_ADDRESS (priv->next_dest_ip->data);
     383                 :           5 :           dest_hostname = g_inet_address_to_string (dest_ip);
     384                 :             : 
     385                 :           5 :           priv->next_dest_ip = g_list_next (priv->next_dest_ip);
     386                 :             :         }
     387                 :             :       else
     388                 :             :         {
     389                 :           6 :           dest_hostname = g_strdup (priv->dest_hostname);
     390                 :             :         }
     391                 :           8 :       dest_protocol = g_uri_parse_scheme (priv->dest_uri);
     392                 :             : 
     393                 :           8 :       g_assert (G_IS_INET_SOCKET_ADDRESS (priv->proxy_address));
     394                 :             : 
     395                 :           8 :       inetsaddr = G_INET_SOCKET_ADDRESS (priv->proxy_address);
     396                 :           8 :       inetaddr = g_inet_socket_address_get_address (inetsaddr);
     397                 :           8 :       port = g_inet_socket_address_get_port (inetsaddr);
     398                 :             : 
     399                 :           8 :       result = g_object_new (G_TYPE_PROXY_ADDRESS,
     400                 :             :                              "address", inetaddr,
     401                 :             :                              "port", port,
     402                 :             :                              "protocol", priv->proxy_type,
     403                 :             :                              "destination-protocol", dest_protocol,
     404                 :             :                              "destination-hostname", dest_hostname,
     405                 :           8 :                              "destination-port", priv->dest_port,
     406                 :             :                              "username", priv->proxy_username,
     407                 :             :                              "password", priv->proxy_password,
     408                 :             :                              "uri", priv->proxy_uri,
     409                 :             :                              NULL);
     410                 :           8 :       g_free (dest_hostname);
     411                 :           8 :       g_free (dest_protocol);
     412                 :             : 
     413                 :           8 :       if (priv->supports_hostname || priv->next_dest_ip == NULL)
     414                 :             :         {
     415                 :           8 :           g_object_unref (priv->proxy_address);
     416                 :           8 :           priv->proxy_address = NULL;
     417                 :             :         }
     418                 :             :     }
     419                 :             : 
     420                 :         230 :   priv->ever_enumerated = TRUE;
     421                 :         230 :   g_task_return_pointer (task, result, g_object_unref);
     422                 :         230 :   g_object_unref (task);
     423                 :         230 : }
     424                 :             : 
     425                 :             : static void address_enumerate_cb (GObject      *object,
     426                 :             :                                   GAsyncResult *result,
     427                 :             :                                   gpointer      user_data);
     428                 :             : 
     429                 :             : static void
     430                 :          86 : next_proxy (GTask *task)
     431                 :             : {
     432                 :          86 :   GProxyAddressEnumeratorPrivate *priv = g_task_get_task_data (task);
     433                 :             : 
     434                 :          86 :   if (*priv->next_proxy)
     435                 :             :     {
     436                 :           3 :       g_object_unref (priv->addr_enum);
     437                 :           3 :       priv->addr_enum = NULL;
     438                 :             : 
     439                 :           3 :       if (priv->dest_ips)
     440                 :             :         {
     441                 :           1 :           g_resolver_free_addresses (priv->dest_ips);
     442                 :           1 :           priv->dest_ips = NULL;
     443                 :             :         }
     444                 :             : 
     445                 :           3 :       next_enumerator (priv);
     446                 :             : 
     447                 :           3 :       if (priv->addr_enum)
     448                 :             :         {
     449                 :           3 :           g_socket_address_enumerator_next_async (priv->addr_enum,
     450                 :             :                                                   g_task_get_cancellable (task),
     451                 :             :                                                   address_enumerate_cb,
     452                 :             :                                                   task);
     453                 :           3 :           return;
     454                 :             :         }
     455                 :             :     }
     456                 :             : 
     457                 :          83 :   complete_async (task);
     458                 :             : }
     459                 :             : 
     460                 :             : static void
     461                 :           7 : dest_hostname_lookup_cb (GObject           *object,
     462                 :             :                          GAsyncResult      *result,
     463                 :             :                          gpointer           user_data)
     464                 :             : {
     465                 :           7 :   GTask *task = user_data;
     466                 :           7 :   GProxyAddressEnumeratorPrivate *priv = g_task_get_task_data (task);
     467                 :             : 
     468                 :           7 :   g_clear_error (&priv->last_error);
     469                 :           7 :   priv->dest_ips = g_resolver_lookup_by_name_finish (G_RESOLVER (object),
     470                 :             :                                                      result,
     471                 :             :                                                      &priv->last_error);
     472                 :           7 :   if (priv->dest_ips)
     473                 :           5 :     return_result (task);
     474                 :             :   else
     475                 :             :     {
     476                 :           2 :       g_clear_object (&priv->proxy_address);
     477                 :           2 :       next_proxy (task);
     478                 :             :     }
     479                 :           7 : }
     480                 :             : 
     481                 :             : static void
     482                 :         316 : address_enumerate_cb (GObject      *object,
     483                 :             :                       GAsyncResult *result,
     484                 :             :                       gpointer      user_data)
     485                 :             : {
     486                 :         316 :   GTask *task = user_data;
     487                 :         316 :   GProxyAddressEnumeratorPrivate *priv = g_task_get_task_data (task);
     488                 :             : 
     489                 :         316 :   g_clear_error (&priv->last_error);
     490                 :         316 :   priv->proxy_address =
     491                 :         316 :     g_socket_address_enumerator_next_finish (priv->addr_enum,
     492                 :             :                                              result,
     493                 :             :                                              &priv->last_error);
     494                 :         316 :   if (priv->proxy_address)
     495                 :             :     {
     496                 :         232 :       if (!priv->supports_hostname && !priv->dest_ips)
     497                 :             :         {
     498                 :             :           GResolver *resolver;
     499                 :           7 :           resolver = g_resolver_get_default();
     500                 :           7 :           g_resolver_lookup_by_name_async (resolver,
     501                 :           7 :                                            priv->dest_hostname,
     502                 :             :                                            g_task_get_cancellable (task),
     503                 :             :                                            dest_hostname_lookup_cb,
     504                 :             :                                            task);
     505                 :           7 :           g_object_unref (resolver);
     506                 :           7 :           return;
     507                 :             :         }
     508                 :             : 
     509                 :         225 :       return_result (task);
     510                 :             :     }
     511                 :             :   else
     512                 :          84 :     next_proxy (task);
     513                 :             : }
     514                 :             : 
     515                 :             : static void
     516                 :         232 : proxy_lookup_cb (GObject      *object,
     517                 :             :                  GAsyncResult *result,
     518                 :             :                  gpointer      user_data)
     519                 :             : {
     520                 :         232 :   GTask *task = user_data;
     521                 :         232 :   GProxyAddressEnumeratorPrivate *priv = g_task_get_task_data (task);
     522                 :             : 
     523                 :         232 :   g_clear_error (&priv->last_error);
     524                 :         232 :   priv->proxies = g_proxy_resolver_lookup_finish (G_PROXY_RESOLVER (object),
     525                 :             :                                                   result,
     526                 :             :                                                   &priv->last_error);
     527                 :         232 :   priv->next_proxy = priv->proxies;
     528                 :             : 
     529                 :         232 :   if (priv->last_error)
     530                 :             :     {
     531                 :           1 :       complete_async (task);
     532                 :           1 :       return;
     533                 :             :     }
     534                 :             :   else
     535                 :             :     {
     536                 :         231 :       next_enumerator (priv);
     537                 :         231 :       if (priv->addr_enum)
     538                 :             :         {
     539                 :         229 :           g_socket_address_enumerator_next_async (priv->addr_enum,
     540                 :             :                                                   g_task_get_cancellable (task),
     541                 :             :                                                   address_enumerate_cb,
     542                 :             :                                                   task);
     543                 :         229 :           return;
     544                 :             :         }
     545                 :             :     }
     546                 :             : 
     547                 :           2 :   complete_async (task);
     548                 :             : }
     549                 :             : 
     550                 :             : static void
     551                 :         316 : g_proxy_address_enumerator_next_async (GSocketAddressEnumerator *enumerator,
     552                 :             :                                        GCancellable             *cancellable,
     553                 :             :                                        GAsyncReadyCallback       callback,
     554                 :             :                                        gpointer                  user_data)
     555                 :             : {
     556                 :         316 :   GProxyAddressEnumeratorPrivate *priv = GET_PRIVATE (enumerator);
     557                 :             :   GTask *task;
     558                 :             : 
     559                 :         316 :   task = g_task_new (enumerator, cancellable, callback, user_data);
     560                 :         316 :   g_task_set_source_tag (task, g_proxy_address_enumerator_next_async);
     561                 :         316 :   g_task_set_task_data (task, priv, NULL);
     562                 :             : 
     563                 :         316 :   if (priv->proxies == NULL)
     564                 :             :     {
     565                 :         232 :       g_proxy_resolver_lookup_async (priv->proxy_resolver,
     566                 :         232 :                                      priv->dest_uri,
     567                 :             :                                      cancellable,
     568                 :             :                                      proxy_lookup_cb,
     569                 :             :                                      task);
     570                 :         232 :       return;
     571                 :             :     }
     572                 :             : 
     573                 :          84 :   if (priv->addr_enum)
     574                 :             :     {
     575                 :          84 :       if (priv->proxy_address)
     576                 :             :         {
     577                 :           0 :           return_result (task);
     578                 :           0 :           return;
     579                 :             :         }
     580                 :             :       else
     581                 :             :         {
     582                 :          84 :           g_socket_address_enumerator_next_async (priv->addr_enum,
     583                 :             :                                                   cancellable,
     584                 :             :                                                   address_enumerate_cb,
     585                 :             :                                                   task);
     586                 :          84 :           return;
     587                 :             :         }
     588                 :             :     }
     589                 :             : 
     590                 :           0 :   complete_async (task);
     591                 :             : }
     592                 :             : 
     593                 :             : static GSocketAddress *
     594                 :         313 : g_proxy_address_enumerator_next_finish (GSocketAddressEnumerator  *enumerator,
     595                 :             :                                         GAsyncResult              *result,
     596                 :             :                                         GError                   **error)
     597                 :             : {
     598                 :         313 :   g_return_val_if_fail (g_task_is_valid (result, enumerator), NULL);
     599                 :             : 
     600                 :         313 :   return g_task_propagate_pointer (G_TASK (result), error);
     601                 :             : }
     602                 :             : 
     603                 :             : static void
     604                 :         459 : g_proxy_address_enumerator_constructed (GObject *object)
     605                 :             : {
     606                 :         459 :   GProxyAddressEnumeratorPrivate *priv = GET_PRIVATE (object);
     607                 :             :   GSocketConnectable *conn;
     608                 :             :   guint port;
     609                 :             : 
     610                 :         459 :   if (priv->dest_uri)
     611                 :             :     {
     612                 :         458 :       conn = g_network_address_parse_uri (priv->dest_uri, priv->default_port, NULL);
     613                 :         458 :       if (conn)
     614                 :             :         {
     615                 :         458 :           g_object_get (conn,
     616                 :             :                         "hostname", &priv->dest_hostname,
     617                 :             :                         "port", &port,
     618                 :             :                         NULL);
     619                 :         458 :           priv->dest_port = port;
     620                 :             : 
     621                 :         458 :           g_object_unref (conn);
     622                 :             :         }
     623                 :             :       else
     624                 :           0 :         g_warning ("Invalid URI '%s'", priv->dest_uri);
     625                 :             :     }
     626                 :             : 
     627                 :         459 :   G_OBJECT_CLASS (g_proxy_address_enumerator_parent_class)->constructed (object);
     628                 :         459 : }
     629                 :             : 
     630                 :             : static void
     631                 :           3 : g_proxy_address_enumerator_get_property (GObject        *object,
     632                 :             :                                          guint           property_id,
     633                 :             :                                          GValue         *value,
     634                 :             :                                          GParamSpec     *pspec)
     635                 :             : {
     636                 :           3 :   GProxyAddressEnumeratorPrivate *priv = GET_PRIVATE (object);
     637                 :           3 :   switch (property_id)
     638                 :             :     {
     639                 :           1 :     case PROP_URI:
     640                 :           1 :       g_value_set_string (value, priv->dest_uri);
     641                 :           1 :       break;
     642                 :             : 
     643                 :           1 :     case PROP_DEFAULT_PORT:
     644                 :           1 :       g_value_set_uint (value, priv->default_port);
     645                 :           1 :       break;
     646                 :             : 
     647                 :           1 :     case PROP_CONNECTABLE:
     648                 :           1 :       g_value_set_object (value, priv->connectable);
     649                 :           1 :       break;
     650                 :             : 
     651                 :           0 :     case PROP_PROXY_RESOLVER:
     652                 :           0 :       g_value_set_object (value, priv->proxy_resolver);
     653                 :           0 :       break;
     654                 :             : 
     655                 :           0 :     default:
     656                 :           0 :       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
     657                 :             :     }
     658                 :           3 : }
     659                 :             : 
     660                 :             : static void
     661                 :        1842 : g_proxy_address_enumerator_set_property (GObject        *object,
     662                 :             :                                          guint           property_id,
     663                 :             :                                          const GValue   *value,
     664                 :             :                                          GParamSpec     *pspec)
     665                 :             : {
     666                 :        1842 :   GProxyAddressEnumeratorPrivate *priv = GET_PRIVATE (object);
     667                 :        1842 :   switch (property_id)
     668                 :             :     {
     669                 :         459 :     case PROP_URI:
     670                 :         459 :       priv->dest_uri = g_value_dup_string (value);
     671                 :         459 :       break;
     672                 :             : 
     673                 :         459 :     case PROP_DEFAULT_PORT:
     674                 :         459 :       priv->default_port = g_value_get_uint (value);
     675                 :         459 :       break;
     676                 :             : 
     677                 :         459 :     case PROP_CONNECTABLE:
     678                 :         459 :       priv->connectable = g_value_dup_object (value);
     679                 :         459 :       break;
     680                 :             : 
     681                 :         465 :     case PROP_PROXY_RESOLVER:
     682                 :         465 :       if (priv->proxy_resolver)
     683                 :           6 :         g_object_unref (priv->proxy_resolver);
     684                 :         465 :       priv->proxy_resolver = g_value_get_object (value);
     685                 :         465 :       if (!priv->proxy_resolver)
     686                 :         459 :         priv->proxy_resolver = g_proxy_resolver_get_default ();
     687                 :         465 :       g_object_ref (priv->proxy_resolver);
     688                 :         465 :       break;
     689                 :             : 
     690                 :           0 :     default:
     691                 :           0 :       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
     692                 :             :     }
     693                 :        1842 : }
     694                 :             : 
     695                 :             : static void
     696                 :         458 : g_proxy_address_enumerator_finalize (GObject *object)
     697                 :             : {
     698                 :         458 :   GProxyAddressEnumeratorPrivate *priv = GET_PRIVATE (object);
     699                 :             : 
     700                 :         458 :   if (priv->connectable)
     701                 :         453 :     g_object_unref (priv->connectable);
     702                 :             : 
     703                 :         458 :   if (priv->proxy_resolver)
     704                 :         458 :     g_object_unref (priv->proxy_resolver);
     705                 :             : 
     706                 :         458 :   g_free (priv->dest_uri);
     707                 :         458 :   g_free (priv->dest_hostname);
     708                 :             : 
     709                 :         458 :   if (priv->dest_ips)
     710                 :           6 :     g_resolver_free_addresses (priv->dest_ips);
     711                 :             : 
     712                 :         458 :   g_strfreev (priv->proxies);
     713                 :             : 
     714                 :         458 :   if (priv->addr_enum)
     715                 :         368 :     g_object_unref (priv->addr_enum);
     716                 :             : 
     717                 :         458 :   g_free (priv->proxy_type);
     718                 :         458 :   g_free (priv->proxy_username);
     719                 :         458 :   g_free (priv->proxy_password);
     720                 :             : 
     721                 :         458 :   g_clear_error (&priv->last_error);
     722                 :             : 
     723                 :         458 :   G_OBJECT_CLASS (g_proxy_address_enumerator_parent_class)->finalize (object);
     724                 :         458 : }
     725                 :             : 
     726                 :             : static void
     727                 :         459 : g_proxy_address_enumerator_init (GProxyAddressEnumerator *self)
     728                 :             : {
     729                 :         459 :   self->priv = g_proxy_address_enumerator_get_instance_private (self);
     730                 :         459 : }
     731                 :             : 
     732                 :             : static void
     733                 :           8 : g_proxy_address_enumerator_class_init (GProxyAddressEnumeratorClass *proxy_enumerator_class)
     734                 :             : {
     735                 :           8 :   GObjectClass *object_class = G_OBJECT_CLASS (proxy_enumerator_class);
     736                 :           8 :   GSocketAddressEnumeratorClass *enumerator_class = G_SOCKET_ADDRESS_ENUMERATOR_CLASS (proxy_enumerator_class);
     737                 :             : 
     738                 :           8 :   object_class->constructed = g_proxy_address_enumerator_constructed;
     739                 :           8 :   object_class->set_property = g_proxy_address_enumerator_set_property;
     740                 :           8 :   object_class->get_property = g_proxy_address_enumerator_get_property;
     741                 :           8 :   object_class->finalize = g_proxy_address_enumerator_finalize;
     742                 :             : 
     743                 :           8 :   enumerator_class->next = g_proxy_address_enumerator_next;
     744                 :           8 :   enumerator_class->next_async = g_proxy_address_enumerator_next_async;
     745                 :           8 :   enumerator_class->next_finish = g_proxy_address_enumerator_next_finish;
     746                 :             : 
     747                 :             :   /**
     748                 :             :    * GProxyAddressEnumerator:uri:
     749                 :             :    *
     750                 :             :    * The destination URI. Use `none://` for a generic socket.
     751                 :             :    */
     752                 :           8 :   g_object_class_install_property (object_class,
     753                 :             :                                    PROP_URI,
     754                 :             :                                    g_param_spec_string ("uri", NULL, NULL,
     755                 :             :                                                         NULL,
     756                 :             :                                                         G_PARAM_READWRITE |
     757                 :             :                                                         G_PARAM_CONSTRUCT_ONLY |
     758                 :             :                                                         G_PARAM_STATIC_STRINGS));
     759                 :             : 
     760                 :             :   /**
     761                 :             :    * GProxyAddressEnumerator:default-port:
     762                 :             :    *
     763                 :             :    * The default port to use if #GProxyAddressEnumerator:uri does not
     764                 :             :    * specify one.
     765                 :             :    *
     766                 :             :    * Since: 2.38
     767                 :             :    */
     768                 :           8 :   g_object_class_install_property (object_class,
     769                 :             :                                    PROP_DEFAULT_PORT,
     770                 :             :                                    g_param_spec_uint ("default-port", NULL, NULL,
     771                 :             :                                                       0, 65535, 0,
     772                 :             :                                                       G_PARAM_READWRITE |
     773                 :             :                                                       G_PARAM_CONSTRUCT_ONLY |
     774                 :             :                                                       G_PARAM_STATIC_STRINGS));
     775                 :             : 
     776                 :             :   /**
     777                 :             :    * GProxyAddressEnumerator:connectable:
     778                 :             :    *
     779                 :             :    * The connectable being enumerated.
     780                 :             :    */
     781                 :           8 :   g_object_class_install_property (object_class,
     782                 :             :                                    PROP_CONNECTABLE,
     783                 :             :                                    g_param_spec_object ("connectable", NULL, NULL,
     784                 :             :                                                         G_TYPE_SOCKET_CONNECTABLE,
     785                 :             :                                                         G_PARAM_READWRITE |
     786                 :             :                                                         G_PARAM_CONSTRUCT_ONLY |
     787                 :             :                                                         G_PARAM_STATIC_STRINGS));
     788                 :             : 
     789                 :             :   /**
     790                 :             :    * GProxyAddressEnumerator:proxy-resolver:
     791                 :             :    *
     792                 :             :    * The proxy resolver to use.
     793                 :             :    *
     794                 :             :    * Since: 2.36
     795                 :             :    */
     796                 :           8 :   g_object_class_install_property (object_class,
     797                 :             :                                    PROP_PROXY_RESOLVER,
     798                 :             :                                    g_param_spec_object ("proxy-resolver", NULL, NULL,
     799                 :             :                                                         G_TYPE_PROXY_RESOLVER,
     800                 :             :                                                         G_PARAM_READWRITE |
     801                 :             :                                                         G_PARAM_CONSTRUCT |
     802                 :             :                                                         G_PARAM_STATIC_STRINGS));
     803                 :           8 : }
        

Generated by: LCOV version 2.0-1