LCOV - code coverage report
Current view: top level - gio - gsocketaddress.c (source / functions) Coverage Total Hit
Test: unnamed Lines: 87.5 % 112 98
Test Date: 2024-11-26 05:23:01 Functions: 100.0 % 20 20
Branches: - 0 0

             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                 :      290847 : 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                 :        1698 : g_socket_address_get_family (GSocketAddress *address)
      82                 :             : {
      83                 :        1698 :   g_return_val_if_fail (G_IS_SOCKET_ADDRESS (address), 0);
      84                 :             : 
      85                 :        1698 :   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                 :         137 : g_socket_address_class_init (GSocketAddressClass *klass)
     107                 :             : {
     108                 :         137 :   GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
     109                 :             : 
     110                 :         137 :   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                 :         137 :   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                 :         137 : }
     126                 :             : 
     127                 :             : static void
     128                 :         137 : g_socket_address_connectable_iface_init (GSocketConnectableIface *connectable_iface)
     129                 :             : {
     130                 :         137 :   connectable_iface->enumerate  = g_socket_address_connectable_enumerate;
     131                 :         137 :   connectable_iface->proxy_enumerate  = g_socket_address_connectable_proxy_enumerate;
     132                 :             :   /* to_string() is implemented by subclasses */
     133                 :         137 : }
     134                 :             : 
     135                 :             : static void
     136                 :        2202 : g_socket_address_init (GSocketAddress *address)
     137                 :             : {
     138                 :             : 
     139                 :        2202 : }
     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                 :        1783 : g_socket_address_get_native_size (GSocketAddress *address)
     156                 :             : {
     157                 :        1783 :   g_return_val_if_fail (G_IS_SOCKET_ADDRESS (address), -1);
     158                 :             : 
     159                 :        1783 :   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                 :        1868 : g_socket_address_to_native (GSocketAddress  *address,
     184                 :             :                             gpointer         dest,
     185                 :             :                             gsize            destlen,
     186                 :             :                             GError         **error)
     187                 :             : {
     188                 :        1868 :   g_return_val_if_fail (G_IS_SOCKET_ADDRESS (address), FALSE);
     189                 :             : 
     190                 :        1868 :   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                 :         114 : g_socket_address_new_from_native (gpointer native,
     208                 :             :                                   gsize    len)
     209                 :             : {
     210                 :             :   gshort family;
     211                 :             : 
     212                 :         114 :   if (len < sizeof (gshort))
     213                 :           0 :     return NULL;
     214                 :             : 
     215                 :         114 :   family = ((struct sockaddr *) native)->sa_family;
     216                 :             : 
     217                 :         114 :   if (family == AF_UNSPEC)
     218                 :           0 :     return NULL;
     219                 :             : 
     220                 :         114 :   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                 :          72 :   if (family == AF_INET6)
     236                 :             :     {
     237                 :          29 :       struct sockaddr_in6 *addr = (struct sockaddr_in6 *) native;
     238                 :             :       GInetAddress *iaddr;
     239                 :             :       GSocketAddress *sockaddr;
     240                 :             : 
     241                 :          29 :       if (len < sizeof (*addr))
     242                 :           0 :         return NULL;
     243                 :             : 
     244                 :          29 :       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                 :          27 :           iaddr = g_inet_address_new_from_bytes ((guint8 *) &(addr->sin6_addr), AF_INET6);
     256                 :             :         }
     257                 :             : 
     258                 :          29 :       sockaddr = g_object_new (G_TYPE_INET_SOCKET_ADDRESS,
     259                 :             :                                "address", iaddr,
     260                 :          29 :                                "port", g_ntohs (addr->sin6_port),
     261                 :             :                                "flowinfo", addr->sin6_flowinfo,
     262                 :             :                                "scope_id", addr->sin6_scope_id,
     263                 :             :                                NULL);
     264                 :          29 :       g_object_unref (iaddr);
     265                 :          29 :       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                 :        6557 : G_DEFINE_TYPE (GSocketAddressAddressEnumerator, _g_socket_address_address_enumerator, G_TYPE_SOCKET_ADDRESS_ENUMERATOR)
     322                 :             : 
     323                 :             : static void
     324                 :        2047 : g_socket_address_address_enumerator_finalize (GObject *object)
     325                 :             : {
     326                 :             :   GSocketAddressAddressEnumerator *sockaddr_enum =
     327                 :        2047 :     G_SOCKET_ADDRESS_ADDRESS_ENUMERATOR (object);
     328                 :             : 
     329                 :        2047 :   if (sockaddr_enum->sockaddr)
     330                 :           0 :     g_object_unref (sockaddr_enum->sockaddr);
     331                 :             : 
     332                 :        2047 :   G_OBJECT_CLASS (_g_socket_address_address_enumerator_parent_class)->finalize (object);
     333                 :        2047 : }
     334                 :             : 
     335                 :             : static GSocketAddress *
     336                 :        2225 : g_socket_address_address_enumerator_next (GSocketAddressEnumerator  *enumerator,
     337                 :             :                                           GCancellable              *cancellable,
     338                 :             :                                           GError                   **error)
     339                 :             : {
     340                 :             :   GSocketAddressAddressEnumerator *sockaddr_enum =
     341                 :        2225 :     G_SOCKET_ADDRESS_ADDRESS_ENUMERATOR (enumerator);
     342                 :             : 
     343                 :        2225 :   if (sockaddr_enum->sockaddr)
     344                 :             :     {
     345                 :        2047 :       GSocketAddress *ret = sockaddr_enum->sockaddr;
     346                 :             : 
     347                 :        2047 :       sockaddr_enum->sockaddr = NULL;
     348                 :        2047 :       return ret;
     349                 :             :     }
     350                 :             :   else
     351                 :         178 :     return NULL;
     352                 :             : }
     353                 :             : 
     354                 :             : static void
     355                 :        2047 : _g_socket_address_address_enumerator_init (GSocketAddressAddressEnumerator *enumerator)
     356                 :             : {
     357                 :        2047 : }
     358                 :             : 
     359                 :             : static void
     360                 :         119 : _g_socket_address_address_enumerator_class_init (GSocketAddressAddressEnumeratorClass *sockaddrenum_class)
     361                 :             : {
     362                 :         119 :   GObjectClass *object_class = G_OBJECT_CLASS (sockaddrenum_class);
     363                 :             :   GSocketAddressEnumeratorClass *enumerator_class =
     364                 :         119 :     G_SOCKET_ADDRESS_ENUMERATOR_CLASS (sockaddrenum_class);
     365                 :             : 
     366                 :         119 :   enumerator_class->next = g_socket_address_address_enumerator_next;
     367                 :         119 :   object_class->finalize = g_socket_address_address_enumerator_finalize;
     368                 :         119 : }
     369                 :             : 
     370                 :             : static GSocketAddressEnumerator *
     371                 :        2047 : g_socket_address_connectable_enumerate (GSocketConnectable *connectable)
     372                 :             : {
     373                 :             :   GSocketAddressAddressEnumerator *sockaddr_enum;
     374                 :             : 
     375                 :        2047 :   sockaddr_enum = g_object_new (G_TYPE_SOCKET_ADDRESS_ADDRESS_ENUMERATOR, NULL);
     376                 :        2047 :   sockaddr_enum->sockaddr = g_object_ref (G_SOCKET_ADDRESS (connectable));
     377                 :             : 
     378                 :        2047 :   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 2.0-1