(root)/
glib-2.79.0/
gio/
gnativesocketaddress.c
       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 "gnativesocketaddress.h"
      29  #include "gnetworkingprivate.h"
      30  #include "gioerror.h"
      31  #include "glibintl.h"
      32  
      33  
      34  /**
      35   * GNativeSocketAddress:
      36   *
      37   * A socket address of some unknown native type.
      38   *
      39   * This corresponds to a general `struct sockaddr` of a type not otherwise
      40   * handled by GLib.
      41   *
      42   * Since: 2.46
      43   */
      44  
      45  struct _GNativeSocketAddressPrivate
      46  {
      47    struct sockaddr *sockaddr;
      48    union {
      49      struct sockaddr_storage storage;
      50      struct sockaddr sa;
      51    } storage;
      52    gsize sockaddr_len;
      53  };
      54  
      55  G_DEFINE_TYPE_WITH_PRIVATE (GNativeSocketAddress, g_native_socket_address, G_TYPE_SOCKET_ADDRESS)
      56  
      57  static void
      58  g_native_socket_address_dispose (GObject *object)
      59  {
      60    GNativeSocketAddress *address = G_NATIVE_SOCKET_ADDRESS (object);
      61  
      62    if (address->priv->sockaddr != &address->priv->storage.sa)
      63      g_free (address->priv->sockaddr);
      64  
      65    G_OBJECT_CLASS (g_native_socket_address_parent_class)->dispose (object);
      66  }
      67  
      68  static GSocketFamily
      69  g_native_socket_address_get_family (GSocketAddress *address)
      70  {
      71    GNativeSocketAddress *addr;
      72  
      73    g_return_val_if_fail (G_IS_NATIVE_SOCKET_ADDRESS (address), 0);
      74  
      75    addr = G_NATIVE_SOCKET_ADDRESS (address);
      76  
      77    return addr->priv->sockaddr->sa_family;
      78  }
      79  
      80  static gssize
      81  g_native_socket_address_get_native_size (GSocketAddress *address)
      82  {
      83    GNativeSocketAddress *addr;
      84  
      85    g_return_val_if_fail (G_IS_NATIVE_SOCKET_ADDRESS (address), 0);
      86  
      87    addr = G_NATIVE_SOCKET_ADDRESS (address);
      88  
      89    return addr->priv->sockaddr_len;
      90  }
      91  
      92  static gboolean
      93  g_native_socket_address_to_native (GSocketAddress  *address,
      94                                     gpointer         dest,
      95                                     gsize            destlen,
      96                                     GError         **error)
      97  {
      98    GNativeSocketAddress *addr;
      99  
     100    g_return_val_if_fail (G_IS_NATIVE_SOCKET_ADDRESS (address), FALSE);
     101  
     102    addr = G_NATIVE_SOCKET_ADDRESS (address);
     103  
     104    if (destlen < addr->priv->sockaddr_len)
     105      {
     106        g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_NO_SPACE,
     107                             _("Not enough space for socket address"));
     108        return FALSE;
     109      }
     110  
     111    memcpy (dest, addr->priv->sockaddr, addr->priv->sockaddr_len);
     112    return TRUE;
     113  }
     114  
     115  static void
     116  g_native_socket_address_class_init (GNativeSocketAddressClass *klass)
     117  {
     118    GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
     119    GSocketAddressClass *gsocketaddress_class = G_SOCKET_ADDRESS_CLASS (klass);
     120  
     121    gobject_class->dispose = g_native_socket_address_dispose;
     122  
     123    gsocketaddress_class->get_family = g_native_socket_address_get_family;
     124    gsocketaddress_class->to_native = g_native_socket_address_to_native;
     125    gsocketaddress_class->get_native_size = g_native_socket_address_get_native_size;
     126  }
     127  
     128  static void
     129  g_native_socket_address_init (GNativeSocketAddress *address)
     130  {
     131    address->priv = g_native_socket_address_get_instance_private (address);
     132  }
     133  
     134  /**
     135   * g_native_socket_address_new:
     136   * @native: a native address object
     137   * @len: the length of @native, in bytes
     138   *
     139   * Creates a new #GNativeSocketAddress for @native and @len.
     140   *
     141   * Returns: a new #GNativeSocketAddress
     142   *
     143   * Since: 2.46
     144   */
     145  GSocketAddress *
     146  g_native_socket_address_new (gpointer        native,
     147                               gsize           len)
     148  {
     149    GNativeSocketAddress *addr;
     150  
     151    addr = g_object_new (G_TYPE_NATIVE_SOCKET_ADDRESS, NULL);
     152  
     153    if (len <= sizeof(addr->priv->storage))
     154      addr->priv->sockaddr = &addr->priv->storage.sa;
     155    else
     156      addr->priv->sockaddr = g_malloc (len);
     157  
     158    memcpy (addr->priv->sockaddr, native, len);
     159    addr->priv->sockaddr_len = len;
     160    return G_SOCKET_ADDRESS (addr);
     161  }