LCOV - code coverage report
Current view: top level - glib/gio - gsocketaddress.c (source / functions) Hit Total Coverage
Test: unnamed Lines: 99 112 88.4 %
Date: 2024-03-26 05:16:46 Functions: 20 20 100.0 %
Branches: 43 64 67.2 %

           Branch data     Line data    Source code
       1                 :            : /* GIO - GLib Input, Output and Streaming Library
       2                 :            :  *
       3                 :            :  * Copyright (C) 2008 Christian Kellner, Samuel Cormier-Iijima
       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                 :            :  * Authors: Christian Kellner <gicmo@gnome.org>
      21                 :            :  *          Samuel Cormier-Iijima <sciyoshi@gmail.com>
      22                 :            :  */
      23                 :            : 
      24                 :            : #include <config.h>
      25                 :            : #include <glib.h>
      26                 :            : #include <string.h>
      27                 :            : 
      28                 :            : #include "gsocketaddress.h"
      29                 :            : #include "ginetaddress.h"
      30                 :            : #include "ginetsocketaddress.h"
      31                 :            : #include "gnativesocketaddress.h"
      32                 :            : #include "gnetworkingprivate.h"
      33                 :            : #include "gproxyaddress.h"
      34                 :            : #include "gproxyaddressenumerator.h"
      35                 :            : #include "gsocketaddressenumerator.h"
      36                 :            : #include "gsocketconnectable.h"
      37                 :            : #include "glibintl.h"
      38                 :            : #include "gioenumtypes.h"
      39                 :            : 
      40                 :            : #include "gunixsocketaddress.h"
      41                 :            : 
      42                 :            : #ifdef G_OS_WIN32
      43                 :            : #include "giowin32-afunix.h"
      44                 :            : #endif
      45                 :            : 
      46                 :            : 
      47                 :            : /**
      48                 :            :  * GSocketAddress:
      49                 :            :  *
      50                 :            :  * `GSocketAddress` is the equivalent of
      51                 :            :  * [`struct sockaddr`](man:sockaddr(3type)) and its subtypes in the BSD sockets
      52                 :            :  * API. This is an abstract class; use [class@Gio.InetSocketAddress] for
      53                 :            :  * internet sockets, or [class@Gio.UnixSocketAddress] for UNIX domain sockets.
      54                 :            :  */
      55                 :            : 
      56                 :            : enum
      57                 :            : {
      58                 :            :   PROP_NONE,
      59                 :            :   PROP_FAMILY
      60                 :            : };
      61                 :            : 
      62                 :            : static void                      g_socket_address_connectable_iface_init       (GSocketConnectableIface *iface);
      63                 :            : static GSocketAddressEnumerator *g_socket_address_connectable_enumerate        (GSocketConnectable      *connectable);
      64                 :            : static GSocketAddressEnumerator *g_socket_address_connectable_proxy_enumerate  (GSocketConnectable      *connectable);
      65                 :            : 
      66   [ +  +  +  -  :     274520 : G_DEFINE_ABSTRACT_TYPE_WITH_CODE (GSocketAddress, g_socket_address, G_TYPE_OBJECT,
                   +  + ]
      67                 :            :                                   G_IMPLEMENT_INTERFACE (G_TYPE_SOCKET_CONNECTABLE,
      68                 :            :                                                          g_socket_address_connectable_iface_init))
      69                 :            : 
      70                 :            : /**
      71                 :            :  * g_socket_address_get_family:
      72                 :            :  * @address: a #GSocketAddress
      73                 :            :  *
      74                 :            :  * Gets the socket family type of @address.
      75                 :            :  *
      76                 :            :  * Returns: the socket family type of @address
      77                 :            :  *
      78                 :            :  * Since: 2.22
      79                 :            :  */
      80                 :            : GSocketFamily
      81                 :       1202 : g_socket_address_get_family (GSocketAddress *address)
      82                 :            : {
      83                 :       1202 :   g_return_val_if_fail (G_IS_SOCKET_ADDRESS (address), 0);
      84                 :            : 
      85                 :       1202 :   return G_SOCKET_ADDRESS_GET_CLASS (address)->get_family (address);
      86                 :            : }
      87                 :            : 
      88                 :            : static void
      89                 :          1 : g_socket_address_get_property (GObject *object, guint prop_id,
      90                 :            :                                GValue *value, GParamSpec *pspec)
      91                 :            : {
      92                 :          1 :   GSocketAddress *address = G_SOCKET_ADDRESS (object);
      93                 :            : 
      94         [ +  - ]:          1 :   switch (prop_id)
      95                 :            :     {
      96                 :          1 :      case PROP_FAMILY:
      97                 :          1 :       g_value_set_enum (value, g_socket_address_get_family (address));
      98                 :          1 :       break;
      99                 :            : 
     100                 :          0 :      default:
     101                 :          0 :       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
     102                 :            :     }
     103                 :          1 : }
     104                 :            : 
     105                 :            : static void
     106                 :        135 : g_socket_address_class_init (GSocketAddressClass *klass)
     107                 :            : {
     108                 :        135 :   GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
     109                 :            : 
     110                 :        135 :   gobject_class->get_property = g_socket_address_get_property;
     111                 :            : 
     112                 :            :   /**
     113                 :            :    * GSocketAddress:family:
     114                 :            :    *
     115                 :            :    * The family of the socket address.
     116                 :            :    *
     117                 :            :    * Since: 2.22
     118                 :            :    */
     119                 :        135 :   g_object_class_install_property (gobject_class, PROP_FAMILY,
     120                 :            :                                    g_param_spec_enum ("family", NULL, NULL,
     121                 :            :                                                       G_TYPE_SOCKET_FAMILY,
     122                 :            :                                                       G_SOCKET_FAMILY_INVALID,
     123                 :            :                                                       G_PARAM_READABLE |
     124                 :            :                                                       G_PARAM_STATIC_STRINGS));
     125                 :        135 : }
     126                 :            : 
     127                 :            : static void
     128                 :        135 : g_socket_address_connectable_iface_init (GSocketConnectableIface *connectable_iface)
     129                 :            : {
     130                 :        135 :   connectable_iface->enumerate  = g_socket_address_connectable_enumerate;
     131                 :        135 :   connectable_iface->proxy_enumerate  = g_socket_address_connectable_proxy_enumerate;
     132                 :            :   /* to_string() is implemented by subclasses */
     133                 :        135 : }
     134                 :            : 
     135                 :            : static void
     136                 :       1687 : g_socket_address_init (GSocketAddress *address)
     137                 :            : {
     138                 :            : 
     139                 :       1687 : }
     140                 :            : 
     141                 :            : /**
     142                 :            :  * g_socket_address_get_native_size:
     143                 :            :  * @address: a #GSocketAddress
     144                 :            :  *
     145                 :            :  * Gets the size of @address's native struct sockaddr.
     146                 :            :  * You can use this to allocate memory to pass to
     147                 :            :  * g_socket_address_to_native().
     148                 :            :  *
     149                 :            :  * Returns: the size of the native struct sockaddr that
     150                 :            :  *     @address represents
     151                 :            :  *
     152                 :            :  * Since: 2.22
     153                 :            :  */
     154                 :            : gssize
     155                 :       1286 : g_socket_address_get_native_size (GSocketAddress *address)
     156                 :            : {
     157                 :       1286 :   g_return_val_if_fail (G_IS_SOCKET_ADDRESS (address), -1);
     158                 :            : 
     159                 :       1286 :   return G_SOCKET_ADDRESS_GET_CLASS (address)->get_native_size (address);
     160                 :            : }
     161                 :            : 
     162                 :            : /**
     163                 :            :  * g_socket_address_to_native:
     164                 :            :  * @address: a #GSocketAddress
     165                 :            :  * @dest: a pointer to a memory location that will contain the native
     166                 :            :  * struct sockaddr
     167                 :            :  * @destlen: the size of @dest. Must be at least as large as
     168                 :            :  *     g_socket_address_get_native_size()
     169                 :            :  * @error: #GError for error reporting, or %NULL to ignore
     170                 :            :  *
     171                 :            :  * Converts a #GSocketAddress to a native struct sockaddr, which can
     172                 :            :  * be passed to low-level functions like connect() or bind().
     173                 :            :  *
     174                 :            :  * If not enough space is available, a %G_IO_ERROR_NO_SPACE error
     175                 :            :  * is returned. If the address type is not known on the system
     176                 :            :  * then a %G_IO_ERROR_NOT_SUPPORTED error is returned.
     177                 :            :  *
     178                 :            :  * Returns: %TRUE if @dest was filled in, %FALSE on error
     179                 :            :  *
     180                 :            :  * Since: 2.22
     181                 :            :  */
     182                 :            : gboolean
     183                 :       1413 : g_socket_address_to_native (GSocketAddress  *address,
     184                 :            :                             gpointer         dest,
     185                 :            :                             gsize            destlen,
     186                 :            :                             GError         **error)
     187                 :            : {
     188                 :       1413 :   g_return_val_if_fail (G_IS_SOCKET_ADDRESS (address), FALSE);
     189                 :            : 
     190                 :       1413 :   return G_SOCKET_ADDRESS_GET_CLASS (address)->to_native (address, dest, destlen, error);
     191                 :            : }
     192                 :            : 
     193                 :            : /**
     194                 :            :  * g_socket_address_new_from_native:
     195                 :            :  * @native: (not nullable): a pointer to a struct sockaddr
     196                 :            :  * @len: the size of the memory location pointed to by @native
     197                 :            :  *
     198                 :            :  * Creates a #GSocketAddress subclass corresponding to the native
     199                 :            :  * struct sockaddr @native.
     200                 :            :  *
     201                 :            :  * Returns: a new #GSocketAddress if @native could successfully
     202                 :            :  *     be converted, otherwise %NULL
     203                 :            :  *
     204                 :            :  * Since: 2.22
     205                 :            :  */
     206                 :            : GSocketAddress *
     207                 :        105 : g_socket_address_new_from_native (gpointer native,
     208                 :            :                                   gsize    len)
     209                 :            : {
     210                 :            :   gshort family;
     211                 :            : 
     212         [ -  + ]:        105 :   if (len < sizeof (gshort))
     213                 :          0 :     return NULL;
     214                 :            : 
     215                 :        105 :   family = ((struct sockaddr *) native)->sa_family;
     216                 :            : 
     217         [ -  + ]:        105 :   if (family == AF_UNSPEC)
     218                 :          0 :     return NULL;
     219                 :            : 
     220         [ +  + ]:        105 :   if (family == AF_INET)
     221                 :            :     {
     222                 :         42 :       struct sockaddr_in *addr = (struct sockaddr_in *) native;
     223                 :            :       GInetAddress *iaddr;
     224                 :            :       GSocketAddress *sockaddr;
     225                 :            : 
     226         [ -  + ]:         42 :       if (len < sizeof (*addr))
     227                 :          0 :         return NULL;
     228                 :            : 
     229                 :         42 :       iaddr = g_inet_address_new_from_bytes ((guint8 *) &(addr->sin_addr), AF_INET);
     230                 :         42 :       sockaddr = g_inet_socket_address_new (iaddr, g_ntohs (addr->sin_port));
     231                 :         42 :       g_object_unref (iaddr);
     232                 :         42 :       return sockaddr;
     233                 :            :     }
     234                 :            : 
     235         [ +  + ]:         63 :   if (family == AF_INET6)
     236                 :            :     {
     237                 :         20 :       struct sockaddr_in6 *addr = (struct sockaddr_in6 *) native;
     238                 :            :       GInetAddress *iaddr;
     239                 :            :       GSocketAddress *sockaddr;
     240                 :            : 
     241         [ -  + ]:         20 :       if (len < sizeof (*addr))
     242                 :          0 :         return NULL;
     243                 :            : 
     244   [ +  +  +  -  :         20 :       if (IN6_IS_ADDR_V4MAPPED (&(addr->sin6_addr)))
             +  +  +  + ]
     245                 :            :         {
     246                 :            :           struct sockaddr_in sin_addr;
     247                 :            : 
     248                 :          2 :           sin_addr.sin_family = AF_INET;
     249                 :          2 :           sin_addr.sin_port = addr->sin6_port;
     250                 :          2 :           memcpy (&(sin_addr.sin_addr.s_addr), addr->sin6_addr.s6_addr + 12, 4);
     251                 :          2 :           iaddr = g_inet_address_new_from_bytes ((guint8 *) &(sin_addr.sin_addr), AF_INET);
     252                 :            :         }
     253                 :            :       else
     254                 :            :         {
     255                 :         18 :           iaddr = g_inet_address_new_from_bytes ((guint8 *) &(addr->sin6_addr), AF_INET6);
     256                 :            :         }
     257                 :            : 
     258                 :         20 :       sockaddr = g_object_new (G_TYPE_INET_SOCKET_ADDRESS,
     259                 :            :                                "address", iaddr,
     260                 :         20 :                                "port", g_ntohs (addr->sin6_port),
     261                 :            :                                "flowinfo", addr->sin6_flowinfo,
     262                 :            :                                "scope_id", addr->sin6_scope_id,
     263                 :            :                                NULL);
     264                 :         20 :       g_object_unref (iaddr);
     265                 :         20 :       return sockaddr;
     266                 :            :     }
     267                 :            : 
     268         [ +  + ]:         43 :   if (family == AF_UNIX)
     269                 :            :     {
     270                 :          1 :       struct sockaddr_un *addr = (struct sockaddr_un *) native;
     271                 :          1 :       gint path_len = len - G_STRUCT_OFFSET (struct sockaddr_un, sun_path);
     272                 :            : 
     273         [ +  - ]:          1 :       if (path_len == 0)
     274                 :            :         {
     275                 :          1 :           return g_unix_socket_address_new_with_type ("", 0,
     276                 :            :                                                       G_UNIX_SOCKET_ADDRESS_ANONYMOUS);
     277                 :            :         }
     278         [ #  # ]:          0 :       else if (addr->sun_path[0] == 0)
     279                 :            :         {
     280         [ #  # ]:          0 :           if (!g_unix_socket_address_abstract_names_supported ())
     281                 :            :             {
     282                 :          0 :               return g_unix_socket_address_new_with_type ("", 0,
     283                 :            :                                                           G_UNIX_SOCKET_ADDRESS_ANONYMOUS);
     284                 :            :             }
     285         [ #  # ]:          0 :           else if (len < sizeof (*addr))
     286                 :            :             {
     287                 :          0 :               return g_unix_socket_address_new_with_type (addr->sun_path + 1,
     288                 :            :                                                           path_len - 1,
     289                 :            :                                                           G_UNIX_SOCKET_ADDRESS_ABSTRACT);
     290                 :            :             }
     291                 :            :           else
     292                 :            :             {
     293                 :          0 :               return g_unix_socket_address_new_with_type (addr->sun_path + 1,
     294                 :            :                                                           path_len - 1,
     295                 :            :                                                           G_UNIX_SOCKET_ADDRESS_ABSTRACT_PADDED);
     296                 :            :             }
     297                 :            :         }
     298                 :            :       else
     299                 :          0 :         return g_unix_socket_address_new (addr->sun_path);
     300                 :            :     }
     301                 :            : 
     302                 :         42 :   return g_native_socket_address_new (native, len);
     303                 :            : }
     304                 :            : 
     305                 :            : 
     306                 :            : #define G_TYPE_SOCKET_ADDRESS_ADDRESS_ENUMERATOR (_g_socket_address_address_enumerator_get_type ())
     307                 :            : #define G_SOCKET_ADDRESS_ADDRESS_ENUMERATOR(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), G_TYPE_SOCKET_ADDRESS_ADDRESS_ENUMERATOR, GSocketAddressAddressEnumerator))
     308                 :            : 
     309                 :            : typedef struct {
     310                 :            :   GSocketAddressEnumerator parent_instance;
     311                 :            : 
     312                 :            :   GSocketAddress *sockaddr;
     313                 :            : } GSocketAddressAddressEnumerator;
     314                 :            : 
     315                 :            : typedef struct {
     316                 :            :   GSocketAddressEnumeratorClass parent_class;
     317                 :            : 
     318                 :            : } GSocketAddressAddressEnumeratorClass;
     319                 :            : 
     320                 :            : static GType _g_socket_address_address_enumerator_get_type (void);
     321   [ +  +  +  -  :       5075 : G_DEFINE_TYPE (GSocketAddressAddressEnumerator, _g_socket_address_address_enumerator, G_TYPE_SOCKET_ADDRESS_ENUMERATOR)
                   +  + ]
     322                 :            : 
     323                 :            : static void
     324                 :       1554 : g_socket_address_address_enumerator_finalize (GObject *object)
     325                 :            : {
     326                 :            :   GSocketAddressAddressEnumerator *sockaddr_enum =
     327                 :       1554 :     G_SOCKET_ADDRESS_ADDRESS_ENUMERATOR (object);
     328                 :            : 
     329         [ +  + ]:       1554 :   if (sockaddr_enum->sockaddr)
     330                 :          1 :     g_object_unref (sockaddr_enum->sockaddr);
     331                 :            : 
     332                 :       1554 :   G_OBJECT_CLASS (_g_socket_address_address_enumerator_parent_class)->finalize (object);
     333                 :       1554 : }
     334                 :            : 
     335                 :            : static GSocketAddress *
     336                 :       1731 : g_socket_address_address_enumerator_next (GSocketAddressEnumerator  *enumerator,
     337                 :            :                                           GCancellable              *cancellable,
     338                 :            :                                           GError                   **error)
     339                 :            : {
     340                 :            :   GSocketAddressAddressEnumerator *sockaddr_enum =
     341                 :       1731 :     G_SOCKET_ADDRESS_ADDRESS_ENUMERATOR (enumerator);
     342                 :            : 
     343         [ +  + ]:       1731 :   if (sockaddr_enum->sockaddr)
     344                 :            :     {
     345                 :       1553 :       GSocketAddress *ret = sockaddr_enum->sockaddr;
     346                 :            : 
     347                 :       1553 :       sockaddr_enum->sockaddr = NULL;
     348                 :       1553 :       return ret;
     349                 :            :     }
     350                 :            :   else
     351                 :        178 :     return NULL;
     352                 :            : }
     353                 :            : 
     354                 :            : static void
     355                 :       1554 : _g_socket_address_address_enumerator_init (GSocketAddressAddressEnumerator *enumerator)
     356                 :            : {
     357                 :       1554 : }
     358                 :            : 
     359                 :            : static void
     360                 :        118 : _g_socket_address_address_enumerator_class_init (GSocketAddressAddressEnumeratorClass *sockaddrenum_class)
     361                 :            : {
     362                 :        118 :   GObjectClass *object_class = G_OBJECT_CLASS (sockaddrenum_class);
     363                 :            :   GSocketAddressEnumeratorClass *enumerator_class =
     364                 :        118 :     G_SOCKET_ADDRESS_ENUMERATOR_CLASS (sockaddrenum_class);
     365                 :            : 
     366                 :        118 :   enumerator_class->next = g_socket_address_address_enumerator_next;
     367                 :        118 :   object_class->finalize = g_socket_address_address_enumerator_finalize;
     368                 :        118 : }
     369                 :            : 
     370                 :            : static GSocketAddressEnumerator *
     371                 :       1554 : g_socket_address_connectable_enumerate (GSocketConnectable *connectable)
     372                 :            : {
     373                 :            :   GSocketAddressAddressEnumerator *sockaddr_enum;
     374                 :            : 
     375                 :       1554 :   sockaddr_enum = g_object_new (G_TYPE_SOCKET_ADDRESS_ADDRESS_ENUMERATOR, NULL);
     376                 :       1554 :   sockaddr_enum->sockaddr = g_object_ref (G_SOCKET_ADDRESS (connectable));
     377                 :            : 
     378                 :       1554 :   return (GSocketAddressEnumerator *)sockaddr_enum;
     379                 :            : }
     380                 :            : 
     381                 :            : static GSocketAddressEnumerator *
     382                 :        430 : g_socket_address_connectable_proxy_enumerate (GSocketConnectable *connectable)
     383                 :            : {
     384                 :        430 :   GSocketAddressEnumerator *addr_enum = NULL;
     385                 :            : 
     386                 :        430 :   g_assert (connectable != NULL);
     387                 :            : 
     388   [ -  +  +  -  :        430 :   if (G_IS_INET_SOCKET_ADDRESS (connectable) &&
             +  +  +  + ]
     389   [ -  +  +  -  :        424 :       !G_IS_PROXY_ADDRESS (connectable))
             -  +  +  - ]
     390                 :        424 :     {
     391                 :            :       GInetAddress *addr;
     392                 :            :       guint port;
     393                 :            :       gchar *uri;
     394                 :            :       gchar *ip;
     395                 :            : 
     396                 :        424 :       g_object_get (connectable, "address", &addr, "port", &port, NULL);
     397                 :            : 
     398                 :        424 :       ip = g_inet_address_to_string (addr);
     399                 :        424 :       uri = g_uri_join (G_URI_FLAGS_NONE, "none", NULL, ip, port, "", NULL, NULL);
     400                 :            : 
     401                 :        424 :       addr_enum = g_object_new (G_TYPE_PROXY_ADDRESS_ENUMERATOR,
     402                 :            :                                 "connectable", connectable,
     403                 :            :                                 "uri", uri,
     404                 :            :                                 NULL);
     405                 :            : 
     406                 :        424 :       g_object_unref (addr);
     407                 :        424 :       g_free (ip);
     408                 :        424 :       g_free (uri);
     409                 :            :     }
     410                 :            :   else
     411                 :            :     {
     412                 :          6 :       addr_enum = g_socket_address_connectable_enumerate (connectable);
     413                 :            :     }
     414                 :            : 
     415                 :        430 :   return addr_enum;
     416                 :            : }

Generated by: LCOV version 1.14