Add network address and socket types
authorDan Winship <danw@gnome.org>
Fri, 12 Dec 2008 18:13:55 +0000 (13:13 -0500)
committerDan Winship <danw@gnome.org>
Wed, 22 Apr 2009 12:36:10 +0000 (08:36 -0400)
Types and methods for dealing with IPv4 and IPv6 addresses (and UNIX
domain socket addresses under UNIX). This does not include code for
actual socket I/O.

Originally from "gnio". Much of the code was written by Christian
Kellner, Samuel Cormier-Iijima, and Ryan Lortie.

Part of #548466.

19 files changed:
configure.in
docs/reference/gio/gio-docs.xml
docs/reference/gio/gio-sections.txt
docs/reference/gio/gio.types
gio/Makefile.am
gio/ginetaddress.c [new file with mode: 0644]
gio/ginetaddress.h [new file with mode: 0644]
gio/ginetsocketaddress.c [new file with mode: 0644]
gio/ginetsocketaddress.h [new file with mode: 0644]
gio/gio.h
gio/gio.symbols
gio/gioenums.h
gio/giotypes.h
gio/gnetworkingprivate.h [new file with mode: 0644]
gio/gsocketaddress.c [new file with mode: 0644]
gio/gsocketaddress.h [new file with mode: 0644]
gio/gunixsocketaddress.c [new file with mode: 0644]
gio/gunixsocketaddress.h [new file with mode: 0644]
glibconfig.h.win32.in

index 514fd75..5c33ab9 100644 (file)
@@ -954,6 +954,26 @@ AC_CHECK_FUNCS(_NSGetEnviron)
 AC_FUNC_VSNPRINTF_C99
 AC_FUNC_PRINTF_UNIX98
 
+# Internet address families
+if test $glib_native_win32 = yes; then
+  glib_inet_includes=["
+#include <winsock2.h>
+  "]
+else
+  glib_inet_includes=["
+#include <sys/socket.h>
+  "]
+fi
+
+glib_failed=false
+GLIB_CHECK_VALUE(AF_INET, $glib_inet_includes, glib_failed=true)
+GLIB_CHECK_VALUE(AF_INET6, $glib_inet_includes, glib_failed=true)
+# winsock defines this even though it doesn't support it
+GLIB_CHECK_VALUE(AF_UNIX, $glib_inet_includes, glib_failed=true)
+if $glib_failed ; then
+  AC_MSG_ERROR([Could not determine values for AF_INET* constants])
+fi
+
 dnl
 dnl if statfs() takes 2 arguments (Posix) or 4 (Solaris)
 dnl
@@ -2986,6 +3006,10 @@ _______EOF
  */
 typedef $g_pid_type GPid;
 
+#define GLIB_SYSDEF_AF_UNIX $g_af_unix
+#define GLIB_SYSDEF_AF_INET $g_af_inet
+#define GLIB_SYSDEF_AF_INET6 $g_af_inet6
+
 G_END_DECLS
 
 #endif /* GLIBCONFIG_H */
@@ -3272,6 +3296,10 @@ g_pollhup=$glib_cv_value_POLLHUP
 g_pollerr=$glib_cv_value_POLLERR
 g_pollnval=$glib_cv_value_POLLNVAL
 
+g_af_unix=$glib_cv_value_AF_UNIX
+g_af_inet=$glib_cv_value_AF_INET
+g_af_inet6=$glib_cv_value_AF_INET6
+
 g_stack_grows=$glib_cv_stack_grows
 
 g_have_eilseq=$have_eilseq
index 46af7fe..8872ed7 100644 (file)
        <xi:include href="xml/gemblemedicon.xml"/>
        <xi:include href="xml/gemblem.xml"/>
     </chapter>
+    <chapter id="networking">
+       <title>Networking</title>
+        <xi:include href="xml/ginetaddress.xml"/>
+        <xi:include href="xml/gsocketaddress.xml"/>
+        <xi:include href="xml/ginetsocketaddress.xml"/>
+        <xi:include href="xml/gunixsocketaddress.xml"/>
+    </chapter>
     <chapter id="utils">   
        <title>Utilities</title>
         <xi:include href="xml/gfilenamecompleter.xml"/>
index 36e9aee..a2d19b7 100644 (file)
@@ -1312,4 +1312,95 @@ g_io_extension_point_set_required_type
 g_io_extension_ref_class
 </SECTION>
 
+<SECTION>
+<FILE>ginetaddress</FILE>
+<TITLE>GInetAddress</TITLE>
+GInetAddress
+g_inet_address_new_from_string
+g_inet_address_new_from_bytes
+g_inet_address_new_any
+g_inet_address_new_loopback
+g_inet_address_to_bytes
+g_inet_address_to_string
+g_inet_address_get_family
+g_inet_address_get_is_any
+g_inet_address_get_is_link_local
+g_inet_address_get_is_loopback
+g_inet_address_get_is_mc_global
+g_inet_address_get_is_mc_link_local
+g_inet_address_get_is_mc_node_local
+g_inet_address_get_is_mc_org_local
+g_inet_address_get_is_mc_site_local
+g_inet_address_get_is_multicast
+g_inet_address_get_is_site_local
+<SUBSECTION Standard>
+GInetAddressClass
+GInetAddressPrivate
+G_INET_ADDRESS
+G_INET_ADDRESS_CLASS
+G_INET_ADDRESS_GET_CLASS
+G_IS_INET_ADDRESS
+G_IS_INET_ADDRESS_CLASS
+G_TYPE_INET_ADDRESS
+<SUBSECTION Private>
+g_inet_address_get_type
+</SECTION>
+
+<SECTION>
+<FILE>gsocketaddress</FILE>
+<TITLE>GSocketAddress</TITLE>
+GSocketAddress
+GSocketFamily
+g_socket_address_new_from_native
+g_socket_address_get_family
+g_socket_address_to_native
+g_socket_address_get_native_size
+<SUBSECTION Standard>
+GSocketAddressClass
+G_IS_SOCKET_ADDRESS
+G_IS_SOCKET_ADDRESS_CLASS
+G_SOCKET_ADDRESS
+G_SOCKET_ADDRESS_CLASS
+G_SOCKET_ADDRESS_GET_CLASS
+G_TYPE_SOCKET_ADDRESS
+<SUBSECTION Private>
+g_socket_address_get_type
+</SECTION>
 
+<SECTION>
+<FILE>ginetsocketaddress</FILE>
+<TITLE>GInetSocketAddress</TITLE>
+GInetSocketAddress
+g_inet_socket_address_new
+g_inet_socket_address_get_address
+g_inet_socket_address_get_port
+<SUBSECTION Standard>
+GInetSocketAddressClass
+GInetSocketAddressPrivate
+G_INET_SOCKET_ADDRESS
+G_INET_SOCKET_ADDRESS_CLASS
+G_INET_SOCKET_ADDRESS_GET_CLASS
+G_IS_INET_SOCKET_ADDRESS
+G_IS_INET_SOCKET_ADDRESS_CLASS
+G_TYPE_INET_SOCKET_ADDRESS
+<SUBSECTION Private>
+g_inet_socket_address_get_type
+</SECTION>
+
+<SECTION>
+<FILE>gunixsocketaddress</FILE>
+<TITLE>GUnixSocketAddress</TITLE>
+GUnixSocketAddress
+g_unix_socket_address_new
+<SUBSECTION Standard>
+GUnixSocketAddressClass
+GUnixSocketAddressPrivate
+G_IS_UNIX_SOCKET_ADDRESS
+G_IS_UNIX_SOCKET_ADDRESS_CLASS
+G_TYPE_UNIX_SOCKET_ADDRESS
+G_UNIX_SOCKET_ADDRESS
+G_UNIX_SOCKET_ADDRESS_CLASS
+G_UNIX_SOCKET_ADDRESS_GET_CLASS
+<SUBSECTION Private>
+g_unix_socket_address_get_type
+</SECTION>
index c73282a..cedae87 100644 (file)
@@ -36,6 +36,8 @@ g_file_type_get_type
 g_filter_input_stream_get_type
 g_filter_output_stream_get_type
 g_icon_get_type
+g_inet_address_get_type
+g_inet_socket_address_get_type
 g_input_stream_get_type
 g_io_error_enum_get_type
 g_io_module_get_type
@@ -55,10 +57,12 @@ g_output_stream_splice_flags_get_type
 g_password_save_get_type
 g_seekable_get_type
 g_simple_async_result_get_type
+g_socket_address_get_type
 g_themed_icon_get_type
 g_unix_input_stream_get_type
 g_unix_mount_monitor_get_type
 g_unix_output_stream_get_type
+g_unix_socket_address_get_type
 g_vfs_get_type
 g_volume_get_type
 g_volume_monitor_get_type
index be6568f..53b30c2 100644 (file)
@@ -132,6 +132,7 @@ unix_sources = \
        gunixmount.h            \
        gunixmounts.c           \
        gunixmounts.h           \
+       gunixsocketaddress.c    \
        gunixvolume.c           \
        gunixvolume.h           \
        gunixvolumemonitor.c    \
@@ -147,12 +148,13 @@ giounixinclude_HEADERS = \
        gunixmounts.h           \
        gunixinputstream.h      \
        gunixoutputstream.h     \
+       gunixsocketaddress.h    \
        $(NULL)
 endif
 
 if OS_WIN32
 appinfo_sources += gwin32appinfo.c gwin32appinfo.h
-platform_libadd += -lshlwapi
+platform_libadd += -lshlwapi -lws2_32
 win32_sources = \
        gwin32mount.c \
        gwin32mount.h \
@@ -196,6 +198,8 @@ libgio_2_0_la_SOURCES =             \
        gfilterinputstream.c    \
        gfilteroutputstream.c   \
        gicon.c                 \
+       ginetaddress.c          \
+       ginetsocketaddress.c    \
        ginputstream.c          \
        gioenums.h              \
        gioerror.c              \
@@ -209,11 +213,13 @@ libgio_2_0_la_SOURCES =           \
        gmountoperation.c       \
        gnativevolumemonitor.c  \
        gnativevolumemonitor.h  \
+       gnetworkingprivate.h    \
        goutputstream.c         \
        gpollfilemonitor.c      \
        gpollfilemonitor.h      \
        gseekable.c             \
        gsimpleasyncresult.c    \
+       gsocketaddress.c        \
        gthemedicon.c           \
        gunionvolumemonitor.c   \
        gunionvolumemonitor.h   \
@@ -299,6 +305,8 @@ gio_headers =                       \
        gfilterinputstream.h    \
        gfilteroutputstream.h   \
        gicon.h                 \
+       ginetaddress.h          \
+       ginetsocketaddress.h    \
        ginputstream.h          \
        gio.h                   \
        giotypes.h              \
@@ -315,6 +323,7 @@ gio_headers =                       \
        goutputstream.h         \
        gseekable.h             \
        gsimpleasyncresult.h    \
+       gsocketaddress.h        \
        gthemedicon.h           \
        gvfs.h                  \
        gvolume.h               \
diff --git a/gio/ginetaddress.c b/gio/ginetaddress.c
new file mode 100644 (file)
index 0000000..cc5856b
--- /dev/null
@@ -0,0 +1,747 @@
+/* GIO - GLib Input, Output and Streaming Library
+ *
+ * Copyright (C) 2008 Christian Kellner, Samuel Cormier-Iijima
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Authors: Christian Kellner <gicmo@gnome.org>
+ *          Samuel Cormier-Iijima <sciyoshi@gmail.com>
+ */
+
+#include <config.h>
+#include <glib.h>
+
+#include "ginetaddress.h"
+#include "gioenums.h"
+#include "gioenumtypes.h"
+#include "glibintl.h"
+#include "gnetworkingprivate.h"
+
+#include "gioalias.h"
+
+/**
+ * SECTION:ginetaddress
+ * @short_description: An IPv4/IPv6 address
+ *
+ * #GInetAddress represents an IPv4 or IPv6 internet address.
+ *
+ * To actually connect to a remote host, you will need a
+ * #GInetSocketAddress (which includes a #GInetAddress as well as a
+ * port number).
+ **/
+
+/**
+ * GInetAddress:
+ *
+ * An IPv4 or IPv6 internet address.
+ **/
+
+/* Networking initialization function, called from inside the g_once of
+ * g_inet_address_get_type()
+ */
+static void
+_g_networking_init (void)
+{
+#ifdef G_OS_WIN32
+  WSADATA wsadata;
+  if (WSAStartup (MAKEWORD (2, 0), &wsadata) != 0)
+    g_error ("Windows Sockets could not be initialized");
+#endif
+}
+
+G_DEFINE_TYPE_WITH_CODE (GInetAddress, g_inet_address, G_TYPE_OBJECT,
+                        _g_networking_init ();)
+
+struct _GInetAddressPrivate
+{
+  GSocketFamily family;
+  union {
+    struct in_addr ipv4;
+    struct in6_addr ipv6;
+  } addr;
+};
+
+enum
+{
+  PROP_0,
+  PROP_FAMILY,
+  PROP_BYTES,
+  PROP_IS_ANY,
+  PROP_IS_LOOPBACK,
+  PROP_IS_LINK_LOCAL,
+  PROP_IS_SITE_LOCAL,
+  PROP_IS_MULTICAST,
+  PROP_IS_MC_GLOBAL,
+  PROP_IS_MC_LINK_LOCAL,
+  PROP_IS_MC_NODE_LOCAL,
+  PROP_IS_MC_ORG_LOCAL,
+  PROP_IS_MC_SITE_LOCAL,
+};
+
+static void
+g_inet_address_set_property (GObject      *object,
+                            guint         prop_id,
+                            const GValue *value,
+                            GParamSpec   *pspec)
+{
+  GInetAddress *address = G_INET_ADDRESS (object);
+
+  switch (prop_id) 
+    {
+    case PROP_FAMILY:
+      address->priv->family = g_value_get_enum (value);
+      break;
+
+    case PROP_BYTES:
+      memcpy (&address->priv->addr, g_value_get_pointer (value),
+             address->priv->family == AF_INET ?
+             sizeof (address->priv->addr.ipv4) :
+             sizeof (address->priv->addr.ipv6));
+      break;
+
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+      break;
+    }
+
+}
+
+static void
+g_inet_address_get_property (GObject    *object,
+                             guint       prop_id,
+                             GValue     *value,
+                             GParamSpec *pspec)
+{
+  GInetAddress *address = G_INET_ADDRESS (object);
+
+  switch (prop_id)
+    {
+    case PROP_FAMILY:
+      g_value_set_enum (value, address->priv->family);
+      break;
+
+    case PROP_BYTES:
+      g_value_set_pointer (value, &address->priv->addr);
+      break;
+
+    case PROP_IS_ANY:
+      g_value_set_boolean (value, g_inet_address_get_is_any (address));
+      break;
+
+    case PROP_IS_LOOPBACK:
+      g_value_set_boolean (value, g_inet_address_get_is_loopback (address));
+      break;
+
+    case PROP_IS_LINK_LOCAL:
+      g_value_set_boolean (value, g_inet_address_get_is_link_local (address));
+      break;
+
+    case PROP_IS_SITE_LOCAL:
+      g_value_set_boolean (value, g_inet_address_get_is_site_local (address));
+      break;
+
+    case PROP_IS_MULTICAST:
+      g_value_set_boolean (value, g_inet_address_get_is_multicast (address));
+      break;
+
+    case PROP_IS_MC_GLOBAL:
+      g_value_set_boolean (value, g_inet_address_get_is_mc_global (address));
+      break;
+
+    case PROP_IS_MC_LINK_LOCAL:
+      g_value_set_boolean (value, g_inet_address_get_is_mc_link_local (address));
+      break;
+
+    case PROP_IS_MC_NODE_LOCAL:
+      g_value_set_boolean (value, g_inet_address_get_is_mc_node_local (address));
+      break;
+
+    case PROP_IS_MC_ORG_LOCAL:
+      g_value_set_boolean (value, g_inet_address_get_is_mc_org_local (address));
+      break;
+
+    case PROP_IS_MC_SITE_LOCAL:
+      g_value_set_boolean (value, g_inet_address_get_is_mc_site_local (address));
+      break;
+
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+    }
+}
+
+static void
+g_inet_address_class_init (GInetAddressClass *klass)
+{
+  GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+
+  g_type_class_add_private (klass, sizeof (GInetAddressPrivate));
+
+  gobject_class->set_property = g_inet_address_set_property;
+  gobject_class->get_property = g_inet_address_get_property;
+
+  g_object_class_install_property (gobject_class, PROP_FAMILY,
+                                   g_param_spec_enum ("family",
+                                                     _("Address family"),
+                                                     _("The address family (IPv4 or IPv6)"),
+                                                     G_TYPE_SOCKET_FAMILY,
+                                                     G_SOCKET_FAMILY_INVALID,
+                                                     G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB | G_PARAM_STATIC_NAME));
+
+  g_object_class_install_property (gobject_class, PROP_BYTES,
+                                   g_param_spec_pointer ("bytes",
+                                                        _("Bytes"),
+                                                        _("The raw address data"),
+                                                        G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB | G_PARAM_STATIC_NAME));
+
+  g_object_class_install_property (gobject_class, PROP_IS_ANY,
+                                   g_param_spec_boolean ("is-any",
+                                                         _("Is any"),
+                                                         _("See g_inet_address_get_is_any()"),
+                                                         FALSE,
+                                                         G_PARAM_READABLE | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB | G_PARAM_STATIC_NAME));
+
+  g_object_class_install_property (gobject_class, PROP_IS_LINK_LOCAL,
+                                   g_param_spec_boolean ("is-link-local",
+                                                         _("Is link-local"),
+                                                         _("See g_inet_address_get_is_link_local()"),
+                                                         FALSE,
+                                                         G_PARAM_READABLE | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB | G_PARAM_STATIC_NAME));
+
+  g_object_class_install_property (gobject_class, PROP_IS_LOOPBACK,
+                                   g_param_spec_boolean ("is-loopback",
+                                                         _("Is loopback"),
+                                                         _("See g_inet_address_get_is_loopback()"),
+                                                         FALSE,
+                                                         G_PARAM_READABLE | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB | G_PARAM_STATIC_NAME));
+
+  g_object_class_install_property (gobject_class, PROP_IS_SITE_LOCAL,
+                                   g_param_spec_boolean ("is-site-local",
+                                                         _("Is site-local"),
+                                                         _("See g_inet_address_get_is_site_local()"),
+                                                         FALSE,
+                                                         G_PARAM_READABLE | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB | G_PARAM_STATIC_NAME));
+
+  g_object_class_install_property (gobject_class, PROP_IS_MULTICAST,
+                                   g_param_spec_boolean ("is-multicast",
+                                                         _("Is multicast"),
+                                                         _("See g_inet_address_get_is_multicast()"),
+                                                         FALSE,
+                                                         G_PARAM_READABLE | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB | G_PARAM_STATIC_NAME));
+
+  g_object_class_install_property (gobject_class, PROP_IS_MC_GLOBAL,
+                                   g_param_spec_boolean ("is-mc-global",
+                                                         _("Is multicast global"),
+                                                         _("See g_inet_address_get_is_mc_global()"),
+                                                         FALSE,
+                                                         G_PARAM_READABLE | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB | G_PARAM_STATIC_NAME));
+
+  g_object_class_install_property (gobject_class, PROP_IS_MC_LINK_LOCAL,
+                                   g_param_spec_boolean ("is-mc-link-local",
+                                                         _("Is multicast link-local"),
+                                                         _("See g_inet_address_get_is_mc_link_local()"),
+                                                         FALSE,
+                                                         G_PARAM_READABLE | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB | G_PARAM_STATIC_NAME));
+
+  g_object_class_install_property (gobject_class, PROP_IS_MC_NODE_LOCAL,
+                                   g_param_spec_boolean ("is-mc-node-local",
+                                                         _("Is multicast node-local"),
+                                                         _("See g_inet_address_get_is_mc_node_local()"),
+                                                         FALSE,
+                                                         G_PARAM_READABLE | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB | G_PARAM_STATIC_NAME));
+
+  g_object_class_install_property (gobject_class, PROP_IS_MC_ORG_LOCAL,
+                                   g_param_spec_boolean ("is-mc-org-local",
+                                                         _("Is multicast org-local"),
+                                                         _("See g_inet_address_get_is_mc_org_local()"),
+                                                         FALSE,
+                                                         G_PARAM_READABLE | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB | G_PARAM_STATIC_NAME));
+
+  g_object_class_install_property (gobject_class, PROP_IS_MC_SITE_LOCAL,
+                                   g_param_spec_boolean ("is-mc-site-local",
+                                                         _("Is multicast site-local"),
+                                                         _("See g_inet_address_get_is_mc_site_local()"),
+                                                         FALSE,
+                                                         G_PARAM_READABLE | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB | G_PARAM_STATIC_NAME));
+}
+
+static void
+g_inet_address_init (GInetAddress *address)
+{
+  address->priv = G_TYPE_INSTANCE_GET_PRIVATE (address,
+                                               G_TYPE_INET_ADDRESS,
+                                               GInetAddressPrivate);
+}
+
+/**
+ * g_inet_address_new_from_string:
+ * @string: a string representation of an IP address
+ *
+ * Parses @string as an IP address and creates a new #GInetAddress.
+ *
+ * Returns: a new #GInetAddress corresponding to @string, or %NULL if
+ * @string could not be parsed.
+ *
+ * Since: 2.22
+ */
+GInetAddress *
+g_inet_address_new_from_string (const gchar *string)
+{
+#ifdef G_OS_WIN32
+  struct sockaddr_storage sa;
+  struct sockaddr_in *sin = (struct sockaddr_in *)&sa;
+  struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)&sa;
+  gint len;
+#else /* !G_OS_WIN32 */
+  struct in_addr in_addr;
+  struct in6_addr in6_addr;
+#endif
+
+  /* Make sure _g_networking_init() has been called */
+  (void) g_inet_address_get_type ();
+
+#ifdef G_OS_WIN32
+  memset (&sa, 0, sizeof (sa));
+  len = sizeof (sa);
+  if (WSAStringToAddress ((LPTSTR) string, AF_INET, NULL, (LPSOCKADDR) &sa, &len) == 0)
+    return g_inet_address_new_from_bytes ((guint8 *)&sin->sin_addr, AF_INET);
+  else if (WSAStringToAddress ((LPTSTR) string, AF_INET6, NULL, (LPSOCKADDR) &sa, &len) == 0)
+    return g_inet_address_new_from_bytes ((guint8 *)&sin6->sin6_addr, AF_INET6);
+
+#else /* !G_OS_WIN32 */
+
+  if (inet_pton (AF_INET, string, &in_addr) > 0)
+    return g_inet_address_new_from_bytes ((guint8 *)&in_addr, AF_INET);
+  else if (inet_pton (AF_INET6, string, &in6_addr) > 0)
+    return g_inet_address_new_from_bytes ((guint8 *)&in6_addr, AF_INET6);
+#endif
+
+  return NULL;
+}
+
+#define G_INET_ADDRESS_FAMILY_IS_VALID(family) ((family) == AF_INET || (family) == AF_INET6)
+
+/**
+ * g_inet_address_new_from_bytes:
+ * @bytes: raw address data
+ * @family: the address family of @bytes
+ *
+ * Creates a new #GInetAddress from the given @family and @bytes.
+ * @bytes should be 4 bytes for %G_INET_ADDRESS_IPV4 and 16 bytes for
+ * %G_INET_ADDRESS_IPV6.
+ *
+ * Returns: a new #GInetAddress corresponding to @family and @bytes.
+ *
+ * Since: 2.22
+ */
+GInetAddress *
+g_inet_address_new_from_bytes (const guint8         *bytes,
+                              GSocketFamily  family)
+{
+  g_return_val_if_fail (G_INET_ADDRESS_FAMILY_IS_VALID (family), NULL);
+
+  return g_object_new (G_TYPE_INET_ADDRESS,
+                      "family", family,
+                      "bytes", bytes,
+                      NULL);
+}
+
+/**
+ * g_inet_address_new_loopback:
+ * @family: the address family
+ *
+ * Creates a #GInetAddress for the loopback address for @family.
+ *
+ * Returns: a new #GInetAddress corresponding to the loopback address
+ * for @family.
+ *
+ * Since: 2.22
+ */
+GInetAddress *
+g_inet_address_new_loopback (GSocketFamily family)
+{
+  g_return_val_if_fail (G_INET_ADDRESS_FAMILY_IS_VALID (family), NULL);
+
+  if (family == AF_INET)
+    {    
+      guint8 addr[4] = {127, 0, 0, 1};
+
+      return g_inet_address_new_from_bytes (addr, family);
+    }
+  else
+    return g_inet_address_new_from_bytes (in6addr_loopback.s6_addr, family);
+}
+
+/**
+ * g_inet_address_new_any:
+ * @family: the address family
+ *
+ * Creates a #GInetAddress for the "any" address (unassigned/"don't
+ * care") for @family.
+ *
+ * Returns: a new #GInetAddress corresponding to the "any" address
+ * for @family.
+ *
+ * Since: 2.22
+ */
+GInetAddress *
+g_inet_address_new_any (GSocketFamily family)
+{
+  g_return_val_if_fail (G_INET_ADDRESS_FAMILY_IS_VALID (family), NULL);
+
+  if (family == AF_INET)
+    {    
+      guint8 addr[4] = {0, 0, 0, 0};
+
+      return g_inet_address_new_from_bytes (addr, family);
+    }
+  else
+    return g_inet_address_new_from_bytes (in6addr_any.s6_addr, family);
+}
+
+
+/**
+ * g_inet_address_to_string:
+ * @address: a #GInetAddress
+ *
+ * Converts @address to string form.
+ *
+ * Returns: a representation of @address as a string, which should be
+ * freed after use.
+ *
+ * Since: 2.22
+ */
+gchar *
+g_inet_address_to_string (GInetAddress *address)
+{
+  gchar buffer[INET6_ADDRSTRLEN];
+#ifdef G_OS_WIN32
+  DWORD buflen = sizeof (buffer), addrlen;
+  struct sockaddr_storage sa;
+  struct sockaddr_in *sin = (struct sockaddr_in *)&sa;
+  struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)&sa;
+#endif
+
+  g_return_val_if_fail (G_IS_INET_ADDRESS (address), NULL);
+
+#ifdef G_OS_WIN32
+  sa.ss_family = address->priv->family;
+  if (address->priv->family == AF_INET)
+    {
+      addrlen = sizeof (*sin);
+      memcpy (&sin->sin_addr, &address->priv->addr.ipv4,
+             sizeof (sin->sin_addr));
+      sin->sin_port = 0;
+    }
+  else
+    {
+      addrlen = sizeof (*sin6);
+      memcpy (&sin6->sin6_addr, &address->priv->addr.ipv6,
+             sizeof (sin6->sin6_addr));
+      sin6->sin6_port = 0;
+    }
+  if (WSAAddressToString ((LPSOCKADDR) &sa, addrlen, NULL, buffer, &buflen) != 0)
+    return NULL;
+
+#else /* !G_OS_WIN32 */
+
+  if (address->priv->family == AF_INET)
+    inet_ntop (AF_INET, &address->priv->addr.ipv4, buffer, sizeof (buffer));
+  else
+    inet_ntop (AF_INET6, &address->priv->addr.ipv6, buffer, sizeof (buffer));
+#endif
+
+  return g_strdup (buffer);
+}
+
+/**
+ * g_inet_address_to_bytes:
+ * @address: a #GInetAddress
+ *
+ * Gets the raw binary address data from @address.
+ *
+ * Returns: a pointer to an internal array of the bytes in @address,
+ * which should not be modified, stored, or freed.
+ *
+ * Since: 2.22
+ */
+const guint8 *
+g_inet_address_to_bytes (GInetAddress *address)
+{
+  g_return_val_if_fail (G_IS_INET_ADDRESS (address), NULL);
+
+  return (guint8 *)&address->priv->addr;
+}
+
+/**
+ * g_inet_address_get_family:
+ * @address: a #GInetAddress
+ *
+ * Gets @address's family
+ *
+ * Returns: @address's family
+ *
+ * Since: 2.22
+ */
+GSocketFamily
+g_inet_address_get_family (GInetAddress *address)
+{
+  g_return_val_if_fail (G_IS_INET_ADDRESS (address), FALSE);
+
+  return address->priv->family;
+}
+
+/**
+ * g_inet_address_get_is_any:
+ * @address: a #GInetAddress
+ *
+ * Tests whether @address is the "any" address for its family.
+ *
+ * Returns: %TRUE if @address is the "any" address for its family.
+ *
+ * Since: 2.22
+ */
+gboolean
+g_inet_address_get_is_any (GInetAddress *address)
+{
+  g_return_val_if_fail (G_IS_INET_ADDRESS (address), FALSE);
+
+  if (address->priv->family == AF_INET)
+    {
+      guint32 addr4 = g_ntohl (address->priv->addr.ipv4.s_addr);
+
+      return addr4 == INADDR_ANY;
+    }
+  else
+    return IN6_IS_ADDR_UNSPECIFIED (&address->priv->addr.ipv6.s6_addr);
+}
+
+/**
+ * g_inet_address_get_is_loopback:
+ * @address: a #GInetAddress
+ *
+ * Tests whether @address is the loopback address for its family.
+ *
+ * Returns: %TRUE if @address is the loopback address for its family.
+ *
+ * Since: 2.22
+ */
+gboolean
+g_inet_address_get_is_loopback (GInetAddress *address)
+{
+  g_return_val_if_fail (G_IS_INET_ADDRESS (address), FALSE);
+
+  if (address->priv->family == AF_INET)
+    {
+      guint32 addr4 = g_ntohl (address->priv->addr.ipv4.s_addr);
+
+      /* 127.0.0.0/8 */
+      return ((addr4 & 0xff000000) == 0x7f000000);
+    }
+  else
+    return IN6_IS_ADDR_LOOPBACK (&address->priv->addr.ipv6.s6_addr);
+}
+
+/**
+ * g_inet_address_get_is_link_local:
+ * @address: a #GInetAddress
+ *
+ * Tests whether @address is a link-local address (that is, if it
+ * identifies a host on a local network that is not connected to the
+ * Internet).
+ *
+ * Returns: %TRUE if @address is a link-local address.
+ *
+ * Since: 2.22
+ */
+gboolean
+g_inet_address_get_is_link_local (GInetAddress *address)
+{
+  g_return_val_if_fail (G_IS_INET_ADDRESS (address), FALSE);
+
+  if (address->priv->family == AF_INET)
+    {
+      guint32 addr4 = g_ntohl (address->priv->addr.ipv4.s_addr);
+
+      /* 169.254.0.0/16 */
+      return ((addr4 & 0xffff0000) == 0xa9fe0000);
+    }
+  else
+    return IN6_IS_ADDR_LINKLOCAL (&address->priv->addr.ipv6.s6_addr);
+}
+
+/**
+ * g_inet_address_get_is_site_local:
+ * @address: a #GInetAddress
+ *
+ * Tests whether @address is a site-local address such as 10.0.0.1
+ * (that is, the address identifies a host on a local network that can
+ * not be reached directly from the Internet, but which may have
+ * outgoing Internet connectivity via a NAT or firewall).
+ *
+ * Returns: %TRUE if @address is a site-local address.
+ *
+ * Since: 2.22
+ */
+gboolean
+g_inet_address_get_is_site_local (GInetAddress *address)
+{
+  g_return_val_if_fail (G_IS_INET_ADDRESS (address), FALSE);
+
+  if (address->priv->family == AF_INET)
+    {
+      guint32 addr4 = g_ntohl (address->priv->addr.ipv4.s_addr);
+
+      /* 10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16 */
+      return ((addr4 & 0xff000000) == 0x0a000000 ||
+             (addr4 & 0xfff00000) == 0xac100000 ||
+             (addr4 & 0xffff0000) == 0xc0a80000);
+    }
+  else
+    return IN6_IS_ADDR_SITELOCAL (&address->priv->addr.ipv6.s6_addr);
+}
+
+/**
+ * g_inet_address_get_is_multicast:
+ * @address: a #GInetAddress
+ *
+ * Tests whether @address is a multicast address.
+ *
+ * Returns: %TRUE if @address is a multicast address.
+ *
+ * Since: 2.22
+ */
+gboolean
+g_inet_address_get_is_multicast (GInetAddress *address)
+{
+  g_return_val_if_fail (G_IS_INET_ADDRESS (address), FALSE);
+
+  if (address->priv->family == AF_INET)
+    {
+      guint32 addr4 = g_ntohl (address->priv->addr.ipv4.s_addr);
+
+      return IN_MULTICAST (addr4);
+    }
+  else
+    return IN6_IS_ADDR_MULTICAST (&address->priv->addr.ipv6.s6_addr);
+}
+
+/**
+ * g_inet_address_get_is_mc_global:
+ * @address: a #GInetAddress
+ *
+ * Tests whether @address is a global multicast address.
+ *
+ * Returns: %TRUE if @address is a global multicast address.
+ *
+ * Since: 2.22
+ */
+gboolean
+g_inet_address_get_is_mc_global (GInetAddress *address)
+{
+  g_return_val_if_fail (G_IS_INET_ADDRESS (address), FALSE);
+
+  if (address->priv->family == AF_INET)
+    return FALSE;
+  else
+    return IN6_IS_ADDR_MC_GLOBAL (&address->priv->addr.ipv6.s6_addr);
+}
+
+/**
+ * g_inet_address_get_is_mc_link_local:
+ * @address: a #GInetAddress
+ *
+ * Tests whether @address is a link-local multicast address.
+ *
+ * Returns: %TRUE if @address is a link-local multicast address.
+ *
+ * Since: 2.22
+ */
+gboolean
+g_inet_address_get_is_mc_link_local (GInetAddress *address)
+{
+  g_return_val_if_fail (G_IS_INET_ADDRESS (address), FALSE);
+
+  if (address->priv->family == AF_INET)
+    return FALSE;
+  else
+    return IN6_IS_ADDR_MC_LINKLOCAL (&address->priv->addr.ipv6.s6_addr);
+}
+
+/**
+ * g_inet_address_get_is_mc_node_local:
+ * @address: a #GInetAddress
+ *
+ * Tests whether @address is a node-local multicast address.
+ *
+ * Returns: %TRUE if @address is a node-local multicast address.
+ *
+ * Since: 2.22
+ */
+gboolean
+g_inet_address_get_is_mc_node_local (GInetAddress *address)
+{
+  g_return_val_if_fail (G_IS_INET_ADDRESS (address), FALSE);
+
+  if (address->priv->family == AF_INET)
+    return FALSE;
+  else
+    return IN6_IS_ADDR_MC_NODELOCAL (&address->priv->addr.ipv6.s6_addr);
+}
+
+/**
+ * g_inet_address_get_is_mc_org_local:
+ * @address: a #GInetAddress
+ *
+ * Tests whether @address is an organization-local multicast address.
+ *
+ * Returns: %TRUE if @address is an organization-local multicast address.
+ *
+ * Since: 2.22
+ */
+gboolean
+g_inet_address_get_is_mc_org_local  (GInetAddress *address)
+{
+  g_return_val_if_fail (G_IS_INET_ADDRESS (address), FALSE);
+
+  if (address->priv->family == AF_INET)
+    return FALSE;
+  else
+    return IN6_IS_ADDR_MC_ORGLOCAL (&address->priv->addr.ipv6.s6_addr);
+}
+
+/**
+ * g_inet_address_get_is_mc_site_local:
+ * @address: a #GInetAddress
+ *
+ * Tests whether @address is a site-local multicast address.
+ *
+ * Returns: %TRUE if @address is a site-local multicast address.
+ *
+ * Since: 2.22
+ */
+gboolean
+g_inet_address_get_is_mc_site_local (GInetAddress *address)
+{
+  g_return_val_if_fail (G_IS_INET_ADDRESS (address), FALSE);
+
+  if (address->priv->family == AF_INET)
+    return FALSE;
+  else
+    return IN6_IS_ADDR_MC_SITELOCAL (&address->priv->addr.ipv6.s6_addr);
+}
+
+#define __G_INET_ADDRESS_C__
+#include "gioaliasdef.c"
diff --git a/gio/ginetaddress.h b/gio/ginetaddress.h
new file mode 100644 (file)
index 0000000..3f9e499
--- /dev/null
@@ -0,0 +1,101 @@
+/* GIO - GLib Input, Output and Streaming Library
+ *
+ * Copyright (C) 2008 Christian Kellner, Samuel Cormier-Iijima
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Authors: Christian Kellner <gicmo@gnome.org>
+ *          Samuel Cormier-Iijima <sciyoshi@gmail.com>
+ */
+
+#if !defined (__GIO_GIO_H_INSIDE__) && !defined (GIO_COMPILATION)
+#error "Only <gio/gio.h> can be included directly."
+#endif
+
+#ifndef __G_INET_ADDRESS_H__
+#define __G_INET_ADDRESS_H__
+
+#include <gio/giotypes.h>
+
+G_BEGIN_DECLS
+
+#define G_TYPE_INET_ADDRESS         (g_inet_address_get_type ())
+#define G_INET_ADDRESS(o)           (G_TYPE_CHECK_INSTANCE_CAST ((o), G_TYPE_INET_ADDRESS, GInetAddress))
+#define G_INET_ADDRESS_CLASS(k)     (G_TYPE_CHECK_CLASS_CAST((k), G_TYPE_INET_ADDRESS, GInetAddressClass))
+#define G_IS_INET_ADDRESS(o)        (G_TYPE_CHECK_INSTANCE_TYPE ((o), G_TYPE_INET_ADDRESS))
+#define G_IS_INET_ADDRESS_CLASS(k)  (G_TYPE_CHECK_CLASS_TYPE ((k), G_TYPE_INET_ADDRESS))
+#define G_INET_ADDRESS_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), G_TYPE_INET_ADDRESS, GInetAddressClass))
+
+typedef struct _GInetAddressClass   GInetAddressClass;
+typedef struct _GInetAddressPrivate GInetAddressPrivate;
+
+struct _GInetAddress
+{
+  GObject parent_instance;
+
+  /*< private >*/
+  GInetAddressPrivate *priv;
+};
+
+struct _GInetAddressClass
+{
+  GObjectClass parent_class;
+
+  gchar *        (*to_string) (GInetAddress *address);
+  const guint8 * (*to_bytes)  (GInetAddress *address);
+};
+
+GType                 g_inet_address_get_type             (void) G_GNUC_CONST;
+
+GInetAddress *        g_inet_address_new_from_string      (const gchar          *string);
+
+GInetAddress *        g_inet_address_new_from_bytes       (const guint8         *bytes,
+                                                          GSocketFamily         family);
+
+GInetAddress *        g_inet_address_new_loopback         (GSocketFamily         family);
+
+GInetAddress *        g_inet_address_new_any              (GSocketFamily         family);
+
+gchar *               g_inet_address_to_string            (GInetAddress         *address);
+
+const guint8 *        g_inet_address_to_bytes             (GInetAddress         *address);
+
+GSocketFamily         g_inet_address_get_family           (GInetAddress         *address);
+
+gboolean              g_inet_address_get_is_any           (GInetAddress         *address);
+
+gboolean              g_inet_address_get_is_loopback      (GInetAddress         *address);
+
+gboolean              g_inet_address_get_is_link_local    (GInetAddress         *address);
+
+gboolean              g_inet_address_get_is_site_local    (GInetAddress         *address);
+
+gboolean              g_inet_address_get_is_multicast     (GInetAddress         *address);
+
+gboolean              g_inet_address_get_is_mc_global     (GInetAddress         *address);
+
+gboolean              g_inet_address_get_is_mc_link_local (GInetAddress         *address);
+
+gboolean              g_inet_address_get_is_mc_node_local (GInetAddress         *address);
+
+gboolean              g_inet_address_get_is_mc_org_local  (GInetAddress         *address);
+
+gboolean              g_inet_address_get_is_mc_site_local (GInetAddress         *address);
+
+G_END_DECLS
+
+#endif /* __G_INET_ADDRESS_H__ */
+
diff --git a/gio/ginetsocketaddress.c b/gio/ginetsocketaddress.c
new file mode 100644 (file)
index 0000000..b8275a8
--- /dev/null
@@ -0,0 +1,306 @@
+/* GIO - GLib Input, Output and Streaming Library
+ *
+ * Copyright (C) 2008 Christian Kellner, Samuel Cormier-Iijima
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Authors: Christian Kellner <gicmo@gnome.org>
+ *          Samuel Cormier-Iijima <sciyoshi@gmail.com>
+ */
+
+#include <config.h>
+#include <glib.h>
+#include <string.h>
+
+#include "ginetsocketaddress.h"
+#include "ginetaddress.h"
+#include "gnetworkingprivate.h"
+
+#include "gioalias.h"
+
+/**
+ * SECTION:ginetsocketaddress
+ * @short_description: Internet socket addresses
+ *
+ * An IPv4 or IPv6 socket address; that is, the combination of a
+ * #GInetAddress and a port number.
+ **/
+
+/**
+ * GInetSocketAddress:
+ *
+ * An IPv4 or IPv6 socket address, corresponding to a <type>struct
+ * sockaddr_in</type> or <type>struct sockaddr_in6</type>.
+ **/
+G_DEFINE_TYPE (GInetSocketAddress, g_inet_socket_address, G_TYPE_SOCKET_ADDRESS);
+
+enum {
+  PROP_0,
+  PROP_ADDRESS,
+  PROP_PORT
+};
+
+struct _GInetSocketAddressPrivate
+{
+  GInetAddress *address;
+  guint16       port;
+};
+
+static void
+g_inet_socket_address_finalize (GObject *object)
+{
+  GInetSocketAddress *address G_GNUC_UNUSED = G_INET_SOCKET_ADDRESS (object);
+
+  if (G_OBJECT_CLASS (g_inet_socket_address_parent_class)->finalize)
+    (*G_OBJECT_CLASS (g_inet_socket_address_parent_class)->finalize) (object);
+}
+
+static void
+g_inet_socket_address_dispose (GObject *object)
+{
+  GInetSocketAddress *address G_GNUC_UNUSED = G_INET_SOCKET_ADDRESS (object);
+
+  g_object_unref (address->priv->address);
+
+  if (G_OBJECT_CLASS (g_inet_socket_address_parent_class)->dispose)
+    (*G_OBJECT_CLASS (g_inet_socket_address_parent_class)->dispose) (object);
+}
+
+static void
+g_inet_socket_address_get_property (GObject    *object,
+                                    guint       prop_id,
+                                    GValue     *value,
+                                    GParamSpec *pspec)
+{
+  GInetSocketAddress *address = G_INET_SOCKET_ADDRESS (object);
+
+  switch (prop_id)
+    {
+      case PROP_ADDRESS:
+        g_value_set_object (value, address->priv->address);
+        break;
+
+      case PROP_PORT:
+        g_value_set_uint (value, address->priv->port);
+        break;
+
+      default:
+        G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+    }
+}
+
+static void
+g_inet_socket_address_set_property (GObject      *object,
+                                    guint         prop_id,
+                                    const GValue *value,
+                                    GParamSpec   *pspec)
+{
+  GInetSocketAddress *address = G_INET_SOCKET_ADDRESS (object);
+
+  switch (prop_id)
+    {
+      case PROP_ADDRESS:
+        address->priv->address = g_object_ref (g_value_get_object (value));
+        break;
+
+      case PROP_PORT:
+        address->priv->port = (guint16) g_value_get_uint (value);
+        break;
+
+      default:
+        G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+    }
+}
+
+static GSocketFamily
+g_inet_socket_address_get_family (GSocketAddress *address)
+{
+  GInetSocketAddress *addr;
+
+  g_return_val_if_fail (G_IS_INET_SOCKET_ADDRESS (address), 0);
+
+  addr = G_INET_SOCKET_ADDRESS (address);
+
+  return g_inet_address_get_family (addr->priv->address);
+}
+
+static gssize
+g_inet_socket_address_get_native_size (GSocketAddress *address)
+{
+  GInetSocketAddress *addr;
+  GSocketFamily family;
+
+  g_return_val_if_fail (G_IS_INET_SOCKET_ADDRESS (address), 0);
+
+  addr = G_INET_SOCKET_ADDRESS (address);
+  family = g_inet_address_get_family (addr->priv->address);
+
+  if (family == AF_INET)
+    return sizeof (struct sockaddr_in);
+  else if (family == AF_INET6)
+    return sizeof (struct sockaddr_in6);
+  else
+    return -1;
+}
+
+static gboolean
+g_inet_socket_address_to_native (GSocketAddress *address,
+                                 gpointer        dest,
+                                gsize           destlen)
+{
+  GInetSocketAddress *addr;
+  GSocketFamily family;
+
+  g_return_val_if_fail (G_IS_INET_SOCKET_ADDRESS (address), 0);
+
+  addr = G_INET_SOCKET_ADDRESS (address);
+  family = g_inet_address_get_family (addr->priv->address);
+
+  if (family == AF_INET)
+    {
+      struct sockaddr_in *sock = (struct sockaddr_in *) dest;
+
+      if (destlen < sizeof (*sock))
+       return FALSE;
+
+      sock->sin_family = AF_INET;
+      sock->sin_port = g_htons (addr->priv->port);
+      memcpy (&(sock->sin_addr.s_addr), g_inet_address_to_bytes (addr->priv->address), sizeof (sock->sin_addr));
+      memset (sock->sin_zero, 0, sizeof (sock->sin_zero));
+      return TRUE;
+    }
+  else if (family == AF_INET6)
+    {
+      struct sockaddr_in6 *sock = (struct sockaddr_in6 *) dest;
+
+      if (destlen < sizeof (*sock))
+       return FALSE;
+
+      memset (sock, 0, sizeof (sock));
+      sock->sin6_family = AF_INET6;
+      sock->sin6_port = g_htons (addr->priv->port);
+      memcpy (&(sock->sin6_addr.s6_addr), g_inet_address_to_bytes (addr->priv->address), sizeof (sock->sin6_addr));
+      return TRUE;
+    }
+  else
+    return FALSE;
+}
+
+static void
+g_inet_socket_address_class_init (GInetSocketAddressClass *klass)
+{
+  GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+  GSocketAddressClass *gsocketaddress_class = G_SOCKET_ADDRESS_CLASS (klass);
+
+  g_type_class_add_private (klass, sizeof (GInetSocketAddressPrivate));
+
+  gobject_class->finalize = g_inet_socket_address_finalize;
+  gobject_class->dispose = g_inet_socket_address_dispose;
+  gobject_class->set_property = g_inet_socket_address_set_property;
+  gobject_class->get_property = g_inet_socket_address_get_property;
+
+  gsocketaddress_class->get_family = g_inet_socket_address_get_family;
+  gsocketaddress_class->to_native = g_inet_socket_address_to_native;
+  gsocketaddress_class->get_native_size = g_inet_socket_address_get_native_size;
+
+  g_object_class_install_property (gobject_class, PROP_ADDRESS,
+                                   g_param_spec_object ("address",
+                                                        "address",
+                                                        "address",
+                                                        G_TYPE_INET_ADDRESS,
+                                                        G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | G_PARAM_STATIC_NAME | G_PARAM_STATIC_BLURB | G_PARAM_STATIC_NICK));
+
+  g_object_class_install_property (gobject_class, PROP_PORT,
+                                   g_param_spec_uint ("port",
+                                                      "port",
+                                                      "port",
+                                                      0,
+                                                      65535,
+                                                      0,
+                                                      G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | G_PARAM_STATIC_NAME | G_PARAM_STATIC_BLURB | G_PARAM_STATIC_NICK));
+}
+
+static void
+g_inet_socket_address_init (GInetSocketAddress *address)
+{
+  address->priv = G_TYPE_INSTANCE_GET_PRIVATE (address,
+                                               G_TYPE_INET_SOCKET_ADDRESS,
+                                               GInetSocketAddressPrivate);
+
+  address->priv->address = NULL;
+  address->priv->port = 0;
+}
+
+/**
+ * g_inet_socket_address_new:
+ * @address: a #GInetAddress
+ * @port: a port number
+ *
+ * Creates a new #GInetSocketAddress for @address and @port.
+ *
+ * Returns: a new #GInetSocketAddress
+ *
+ * Since: 2.22
+ */
+GSocketAddress *
+g_inet_socket_address_new (GInetAddress *address,
+                           guint16       port)
+{
+  return g_object_new (G_TYPE_INET_SOCKET_ADDRESS,
+                      "address", address,
+                      "port", port,
+                      NULL);
+}
+
+/**
+ * g_inet_socket_address_get_address:
+ * @address: a #GInetSocketAddress
+ *
+ * Gets @address's #GInetAddress.
+ *
+ * Returns: the #GInetAddress for @address, which must be
+ * g_object_ref()'d if it will be stored
+ *
+ * Since: 2.22
+ */
+GInetAddress *
+g_inet_socket_address_get_address (GInetSocketAddress *address)
+{
+  g_return_val_if_fail (G_IS_INET_SOCKET_ADDRESS (address), NULL);
+
+  return address->priv->address;
+}
+
+/**
+ * g_inet_socket_address_get_port:
+ * @address: a #GInetSocketAddress
+ *
+ * Gets @address's port.
+ *
+ * Returns: the port for @address
+ *
+ * Since: 2.22
+ */
+guint16
+g_inet_socket_address_get_port (GInetSocketAddress *address)
+{
+  g_return_val_if_fail (G_IS_INET_SOCKET_ADDRESS (address), 0);
+
+  return address->priv->port;
+}
+
+#define __G_INET_SOCKET_ADDRESS_C__
+#include "gioaliasdef.c"
diff --git a/gio/ginetsocketaddress.h b/gio/ginetsocketaddress.h
new file mode 100644 (file)
index 0000000..b455ac5
--- /dev/null
@@ -0,0 +1,69 @@
+/* GIO - GLib Input, Output and Streaming Library
+ *
+ * Copyright (C) 2008 Christian Kellner, Samuel Cormier-Iijima
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Authors: Christian Kellner <gicmo@gnome.org>
+ *          Samuel Cormier-Iijima <sciyoshi@gmail.com>
+ */
+
+#if !defined (__GIO_GIO_H_INSIDE__) && !defined (GIO_COMPILATION)
+#error "Only <gio/gio.h> can be included directly."
+#endif
+
+#ifndef __G_INET_SOCKET_ADDRESS_H__
+#define __G_INET_SOCKET_ADDRESS_H__
+
+#include <gio/gsocketaddress.h>
+
+G_BEGIN_DECLS
+
+#define G_TYPE_INET_SOCKET_ADDRESS         (g_inet_socket_address_get_type ())
+#define G_INET_SOCKET_ADDRESS(o)           (G_TYPE_CHECK_INSTANCE_CAST ((o), G_TYPE_INET_SOCKET_ADDRESS, GInetSocketAddress))
+#define G_INET_SOCKET_ADDRESS_CLASS(k)     (G_TYPE_CHECK_CLASS_CAST((k), G_TYPE_INET_SOCKET_ADDRESS, GInetSocketAddressClass))
+#define G_IS_INET_SOCKET_ADDRESS(o)        (G_TYPE_CHECK_INSTANCE_TYPE ((o), G_TYPE_INET_SOCKET_ADDRESS))
+#define G_IS_INET_SOCKET_ADDRESS_CLASS(k)  (G_TYPE_CHECK_CLASS_TYPE ((k), G_TYPE_INET_SOCKET_ADDRESS))
+#define G_INET_SOCKET_ADDRESS_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), G_TYPE_INET_SOCKET_ADDRESS, GInetSocketAddressClass))
+
+typedef struct _GInetSocketAddressClass   GInetSocketAddressClass;
+typedef struct _GInetSocketAddressPrivate GInetSocketAddressPrivate;
+
+struct _GInetSocketAddress
+{
+  GSocketAddress parent_instance;
+
+  /*< private >*/
+  GInetSocketAddressPrivate *priv;
+};
+
+struct _GInetSocketAddressClass
+{
+  GSocketAddressClass parent_class;
+};
+
+GType           g_inet_socket_address_get_type    (void) G_GNUC_CONST;
+
+GSocketAddress *g_inet_socket_address_new         (GInetAddress       *address,
+                                                  guint16             port);
+
+GInetAddress *  g_inet_socket_address_get_address (GInetSocketAddress *address);
+
+guint16         g_inet_socket_address_get_port    (GInetSocketAddress *address);
+
+G_END_DECLS
+
+#endif /* __G_INET_SOCKET_ADDRESS_H__ */
index e3a0b14..6e809ba 100644 (file)
--- a/gio/gio.h
+++ b/gio/gio.h
@@ -49,6 +49,8 @@
 #include <gio/gfilterinputstream.h>
 #include <gio/gfilteroutputstream.h>
 #include <gio/gicon.h>
+#include <gio/ginetaddress.h>
+#include <gio/ginetsocketaddress.h>
 #include <gio/ginputstream.h>
 #include <gio/gioenums.h>
 #include <gio/gioenumtypes.h>
@@ -64,6 +66,7 @@
 #include <gio/goutputstream.h>
 #include <gio/gseekable.h>
 #include <gio/gsimpleasyncresult.h>
+#include <gio/gsocketaddress.h>
 #include <gio/gthemedicon.h>
 #include <gio/gvfs.h>
 #include <gio/gvolume.h>
index 4dc5917..99ad117 100644 (file)
@@ -833,6 +833,7 @@ g_output_stream_splice_flags_get_type G_GNUC_CONST
 g_ask_password_flags_get_type G_GNUC_CONST
 g_password_save_get_type G_GNUC_CONST
 g_emblem_origin_get_type G_GNUC_CONST
+g_socket_family_get_type G_GNUC_CONST
 #endif
 #endif
 
@@ -857,3 +858,53 @@ g_emblem_get_origin
 #endif
 #endif
 
+#if IN_HEADER(__G_INET_ADDRESS_H__)
+#if IN_FILE(__G_INET_ADDRESS_C__)
+g_inet_address_new_from_string
+g_inet_address_new_from_bytes
+g_inet_address_new_any
+g_inet_address_new_loopback
+g_inet_address_get_family
+g_inet_address_get_type G_GNUC_CONST
+g_inet_address_get_is_any
+g_inet_address_get_is_link_local
+g_inet_address_get_is_loopback
+g_inet_address_get_is_mc_global
+g_inet_address_get_is_mc_link_local
+g_inet_address_get_is_mc_node_local
+g_inet_address_get_is_mc_org_local
+g_inet_address_get_is_mc_site_local
+g_inet_address_get_is_multicast
+g_inet_address_get_is_site_local
+g_inet_address_to_bytes
+g_inet_address_to_string
+#endif
+#endif
+
+#if IN_HEADER(__G_INET_SOCKET_ADDRESS_H__)
+#if IN_FILE(__G_INET_SOCKET_ADDRESS_C__)
+g_inet_socket_address_get_address
+g_inet_socket_address_get_port
+g_inet_socket_address_get_type G_GNUC_CONST
+g_inet_socket_address_new
+#endif
+#endif
+
+#if IN_HEADER(__G_UNIX_SOCKET_ADDRESS_H__)
+#if IN_FILE(__G_UNIX_SOCKET_ADDRESS_C__)
+#ifdef G_OS_UNIX
+g_unix_socket_address_get_type G_GNUC_CONST
+g_unix_socket_address_new
+#endif
+#endif
+#endif
+
+#if IN_HEADER(__G_SOCKET_ADDRESS_H__)
+#if IN_FILE(__G_SOCKET_ADDRESS_C__)
+g_socket_address_new_from_native
+g_socket_address_get_type G_GNUC_CONST
+g_socket_address_get_family
+g_socket_address_get_native_size
+g_socket_address_to_native
+#endif
+#endif
index 3bb50ff..e6e6dfc 100644 (file)
@@ -477,6 +477,26 @@ typedef enum  {
 } GEmblemOrigin;
 
 
+/**
+ * GSocketFamily:
+ * @G_SOCKET_FAMILY_INVALID: no address family
+ * @G_SOCKET_FAMILY_IPV4: the IPv4 family
+ * @G_SOCKET_FAMILY_IPV6: the IPv6 family
+ * @G_SOCKET_FAMILY_UNIX: the UNIX domain family
+ *
+ * The protocol family of a #GSocketAddress. (These values are
+ * identical to the system defines %AF_INET, %AF_INET6 and %AF_UNIX,
+ * if available.)
+ */
+typedef enum {
+  G_SOCKET_FAMILY_INVALID,
+#ifdef GLIB_SYSDEF_AF_UNIX
+  G_SOCKET_FAMILY_UNIX = GLIB_SYSDEF_AF_UNIX,
+#endif
+  G_SOCKET_FAMILY_IPV4 = GLIB_SYSDEF_AF_INET,
+  G_SOCKET_FAMILY_IPV6 = GLIB_SYSDEF_AF_INET6
+} GSocketFamily;
+
 G_END_DECLS
 
 #endif /* __GIO_ENUMS_H__ */
index 981c195..6ea1c1b 100644 (file)
@@ -75,6 +75,8 @@ typedef struct _GFilenameCompleter            GFilenameCompleter;
 
 
 typedef struct _GIcon                         GIcon; /* Dummy typedef */
+typedef struct _GInetAddress                  GInetAddress;
+typedef struct _GInetSocketAddress            GInetSocketAddress;
 typedef struct _GInputStream                  GInputStream;
 typedef struct _GIOModule                     GIOModule;
 typedef struct _GIOExtensionPoint             GIOExtensionPoint;
@@ -97,9 +99,12 @@ typedef struct _GMemoryOutputStream           GMemoryOutputStream;
  **/
 typedef struct _GMount                        GMount; /* Dummy typedef */
 typedef struct _GMountOperation               GMountOperation;
+typedef struct _GNetworkAddress               GNetworkAddress;
+typedef struct _GNetworkService               GNetworkService;
 typedef struct _GOutputStream                 GOutputStream;
 typedef struct _GSeekable                     GSeekable;
 typedef struct _GSimpleAsyncResult            GSimpleAsyncResult;
+typedef struct _GSocketAddress                GSocketAddress;
 typedef struct _GThemedIcon                   GThemedIcon;
 typedef struct _GVfs                          GVfs; /* Dummy typedef */
 
diff --git a/gio/gnetworkingprivate.h b/gio/gnetworkingprivate.h
new file mode 100644 (file)
index 0000000..a90d264
--- /dev/null
@@ -0,0 +1,53 @@
+/* GIO - GLib Input, Output and Streaming Library
+ *
+ * Copyright (C) 2008 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __G_NETWORKINGPRIVATE_H__
+#define __G_NETWORKINGPRIVATE_H__
+
+#ifdef G_OS_WIN32
+
+#define WINVER 0x0501 // FIXME?
+#include <winsock2.h>
+#undef interface
+#include <ws2tcpip.h>
+#include <windns.h>
+
+#else /* !G_OS_WIN32 */
+
+#define BIND_4_COMPAT
+
+#include <arpa/inet.h>
+#include <arpa/nameser.h>
+/* We're supposed to define _GNU_SOURCE to get EAI_NODATA, but that
+ * won't actually work since <features.h> has already been included at
+ * this point. So we define __USE_GNU instead.
+ */
+#define __USE_GNU
+#include <netdb.h>
+#undef __USE_GNU
+#include <netinet/in.h>
+#include <netinet/tcp.h>
+#include <resolv.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+
+#endif
+
+#endif /* __G_NETWORKINGPRIVATE_H__ */
diff --git a/gio/gsocketaddress.c b/gio/gsocketaddress.c
new file mode 100644 (file)
index 0000000..33e8ffd
--- /dev/null
@@ -0,0 +1,233 @@
+/* GIO - GLib Input, Output and Streaming Library
+ *
+ * Copyright (C) 2008 Christian Kellner, Samuel Cormier-Iijima
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Authors: Christian Kellner <gicmo@gnome.org>
+ *          Samuel Cormier-Iijima <sciyoshi@gmail.com>
+ */
+
+#include <config.h>
+#include <glib.h>
+
+#include "gsocketaddress.h"
+#include "ginetaddress.h"
+#include "ginetsocketaddress.h"
+#include "gnetworkingprivate.h"
+#include "glibintl.h"
+#include "gioenumtypes.h"
+
+#ifdef G_OS_UNIX
+#include "gunixsocketaddress.h"
+#endif
+
+#include "gioalias.h"
+
+/**
+ * SECTION:gsocketaddress
+ * @short_description: Abstract base class representing endpoints for
+ * socket communication
+ *
+ * #GSocketAddress is the equivalent of <type>struct sockaddr</type>
+ * in the BSD sockets API. This is an abstract class; use
+ * #GInetSocketAddress for internet sockets, or #GUnixSocketAddress
+ * for UNIX domain sockets.
+ **/
+
+/**
+ * GSocketAddress:
+ *
+ * A socket endpoint address, corresponding to <type>struct sockaddr</type>
+ * or one of its subtypes.
+ **/
+
+enum
+{
+  PROP_NONE,
+  PROP_FAMILY
+};
+
+G_DEFINE_ABSTRACT_TYPE (GSocketAddress, g_socket_address, G_TYPE_OBJECT);
+
+/**
+ * g_socket_address_get_family:
+ * @address: a #GSocketAddress
+ *
+ * Gets the socket family type of @address.
+ *
+ * Returns: the socket family type of @address.
+ *
+ * Since: 2.22
+ */
+GSocketFamily
+g_socket_address_get_family (GSocketAddress *address)
+{
+  g_return_val_if_fail (G_IS_SOCKET_ADDRESS (address), 0);
+
+  return G_SOCKET_ADDRESS_GET_CLASS (address)->get_family (address);
+}
+
+static void
+g_socket_address_get_property (GObject *object, guint prop_id,
+                              GValue *value, GParamSpec *pspec)
+{
+  GSocketAddress *address = G_SOCKET_ADDRESS (object);
+
+  switch (prop_id)
+    {
+     case PROP_FAMILY:
+      g_value_set_enum (value, g_socket_address_get_family (address));
+      break;
+
+     default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+    }
+}
+
+static void
+g_socket_address_class_init (GSocketAddressClass *klass)
+{
+  GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+
+  gobject_class->get_property = g_socket_address_get_property;
+
+  g_object_class_install_property (gobject_class, PROP_FAMILY,
+                                   g_param_spec_enum ("family",
+                                                     _("Address family"),
+                                                     _("The family of the socket address"),
+                                                     G_TYPE_SOCKET_FAMILY,
+                                                     G_SOCKET_FAMILY_INVALID,
+                                                     G_PARAM_READABLE | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB | G_PARAM_STATIC_NAME));
+}
+
+static void
+g_socket_address_init (GSocketAddress *address)
+{
+
+}
+
+/**
+ * g_socket_address_get_native_size:
+ * @address: a #GSocketAddress
+ *
+ * Gets the size of @address's native <type>struct sockaddr</type>.
+ * You can use this to allocate memory to pass to
+ * g_socket_address_to_native().
+ *
+ * Returns: the size of the native <type>struct sockaddr</type> that
+ * @address represents
+ *
+ * Since: 2.22
+ */
+gssize
+g_socket_address_get_native_size (GSocketAddress *address)
+{
+  g_return_val_if_fail (G_IS_SOCKET_ADDRESS (address), -1);
+
+  return G_SOCKET_ADDRESS_GET_CLASS (address)->get_native_size (address);
+}
+
+/**
+ * g_socket_address_to_native:
+ * @address: a #GSocketAddress
+ * @dest: a pointer to a memory location that will contain the native
+ * <type>struct sockaddr</type>.
+ * @destlen: the size of @dest. Must be at least as large as
+ * g_socket_address_get_native_size().
+ *
+ * Converts a #GSocketAddress to a native <type>struct
+ * sockaddr</type>, which can be passed to low-level functions like
+ * connect() or bind().
+ *
+ * Returns: %TRUE if @dest was filled in, %FALSE if @address is invalid
+ * or @destlen is too small.
+ *
+ * Since: 2.22
+ */
+gboolean
+g_socket_address_to_native (GSocketAddress *address,
+                           gpointer        dest,
+                           gsize           destlen)
+{
+  g_return_val_if_fail (G_IS_SOCKET_ADDRESS (address), FALSE);
+
+  return G_SOCKET_ADDRESS_GET_CLASS (address)->to_native (address, dest, destlen);
+}
+
+/**
+ * g_socket_address_new_from_native:
+ * @native: a pointer to a <type>struct sockaddr</type>
+ * @len: the size of the memory location pointed to by @native
+ *
+ * Creates a #GSocketAddress subclass corresponding to the native
+ * <type>struct sockaddr</type> @native.
+ *
+ * Returns: a new #GSocketAddress if @native could successfully be converted,
+ * otherwise %NULL.
+ *
+ * Since: 2.22
+ */
+GSocketAddress *
+g_socket_address_new_from_native (gpointer native,
+                                 gsize    len)
+{
+  gshort family;
+
+  if (len < sizeof (gshort))
+    return NULL;
+
+  family = ((struct sockaddr *) native)->sa_family;
+
+  if (family == AF_UNSPEC)
+    return NULL;
+
+  if (family == AF_INET)
+    {
+      struct sockaddr_in *addr = (struct sockaddr_in *) native;
+      GInetAddress *iaddr = g_inet_address_new_from_bytes ((guint8 *) &(addr->sin_addr), AF_INET);
+      GSocketAddress *sockaddr;
+
+      sockaddr = g_inet_socket_address_new (iaddr, g_ntohs (addr->sin_port));
+      g_object_unref (iaddr);
+      return sockaddr;
+    }
+
+  if (family == AF_INET6)
+    {
+      struct sockaddr_in6 *addr = (struct sockaddr_in6 *) native;
+      GInetAddress *iaddr = g_inet_address_new_from_bytes ((guint8 *) &(addr->sin6_addr), AF_INET6);
+      GSocketAddress *sockaddr;
+
+      sockaddr = g_inet_socket_address_new (iaddr, g_ntohs (addr->sin6_port));
+      g_object_unref (iaddr);
+      return sockaddr;
+    }
+
+#ifdef G_OS_UNIX
+  if (family == AF_UNIX)
+    {
+      struct sockaddr_un *addr = (struct sockaddr_un *) native;
+
+      return g_unix_socket_address_new (addr->sun_path);
+    }
+#endif
+
+  return NULL;
+}
+
+#define __G_SOCKET_ADDRESS_C__
+#include "gioaliasdef.c"
diff --git a/gio/gsocketaddress.h b/gio/gsocketaddress.h
new file mode 100644 (file)
index 0000000..1649ba6
--- /dev/null
@@ -0,0 +1,77 @@
+/* GIO - GLib Input, Output and Streaming Library
+ *
+ * Copyright (C) 2008 Christian Kellner, Samuel Cormier-Iijima
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Authors: Christian Kellner <gicmo@gnome.org>
+ *          Samuel Cormier-Iijima <sciyoshi@gmail.com>
+ */
+
+#if !defined (__GIO_GIO_H_INSIDE__) && !defined (GIO_COMPILATION)
+#error "Only <gio/gio.h> can be included directly."
+#endif
+
+#ifndef __G_SOCKET_ADDRESS_H__
+#define __G_SOCKET_ADDRESS_H__
+
+#include <gio/giotypes.h>
+
+G_BEGIN_DECLS
+
+#define G_TYPE_SOCKET_ADDRESS         (g_socket_address_get_type ())
+#define G_SOCKET_ADDRESS(o)           (G_TYPE_CHECK_INSTANCE_CAST ((o), G_TYPE_SOCKET_ADDRESS, GSocketAddress))
+#define G_SOCKET_ADDRESS_CLASS(k)     (G_TYPE_CHECK_CLASS_CAST((k), G_TYPE_SOCKET_ADDRESS, GSocketAddressClass))
+#define G_IS_SOCKET_ADDRESS(o)        (G_TYPE_CHECK_INSTANCE_TYPE ((o), G_TYPE_SOCKET_ADDRESS))
+#define G_IS_SOCKET_ADDRESS_CLASS(k)  (G_TYPE_CHECK_CLASS_TYPE ((k), G_TYPE_SOCKET_ADDRESS))
+#define G_SOCKET_ADDRESS_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), G_TYPE_SOCKET_ADDRESS, GSocketAddressClass))
+
+typedef struct _GSocketAddressClass   GSocketAddressClass;
+
+struct _GSocketAddress
+{
+  GObject parent_instance;
+};
+
+struct _GSocketAddressClass
+{
+  GObjectClass parent_class;
+
+  GSocketFamily  (*get_family)      (GSocketAddress *address);
+
+  gssize         (*get_native_size) (GSocketAddress *address);
+
+  gboolean       (*to_native)       (GSocketAddress *address,
+                                     gpointer        dest,
+                                     gsize           destlen);
+};
+
+GType                 g_socket_address_get_type        (void) G_GNUC_CONST;
+
+GSocketFamily         g_socket_address_get_family      (GSocketAddress *address);
+
+GSocketAddress *      g_socket_address_new_from_native (gpointer        native,
+                                                        gsize           len);
+
+gboolean              g_socket_address_to_native       (GSocketAddress *address,
+                                                        gpointer        dest,
+                                                        gsize           destlen);
+
+gssize                g_socket_address_get_native_size (GSocketAddress *address);
+
+G_END_DECLS
+
+#endif /* __G_SOCKET_ADDRESS_H__ */
diff --git a/gio/gunixsocketaddress.c b/gio/gunixsocketaddress.c
new file mode 100644 (file)
index 0000000..0b1b7e3
--- /dev/null
@@ -0,0 +1,206 @@
+/* GIO - GLib Input, Output and Streaming Library
+ *
+ * Copyright (C) 2008 Christian Kellner, Samuel Cormier-Iijima
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Authors: Christian Kellner <gicmo@gnome.org>
+ *          Samuel Cormier-Iijima <sciyoshi@gmail.com>
+ */
+
+#include <config.h>
+#include <glib.h>
+#include <string.h>
+
+#include "gunixsocketaddress.h"
+#include "glibintl.h"
+#include "gnetworkingprivate.h"
+
+#include "gioalias.h"
+
+/**
+ * SECTION:gunixsocketaddress
+ * @short_description: Unix socket addresses
+ *
+ * Support for UNIX-domain (aka local) sockets.
+ **/
+
+/**
+ * GUnixSocketAddress:
+ *
+ * A UNIX-domain (local) socket address, corresponding to a
+ * <type>struct sockaddr_un</type>.
+ **/
+G_DEFINE_TYPE (GUnixSocketAddress, g_unix_socket_address, G_TYPE_SOCKET_ADDRESS);
+
+enum
+{
+  PROP_0,
+  PROP_PATH,
+};
+
+struct _GUnixSocketAddressPrivate
+{
+  char *path;
+};
+
+static void
+g_unix_socket_address_finalize (GObject *object)
+{
+  GUnixSocketAddress *address G_GNUC_UNUSED = G_UNIX_SOCKET_ADDRESS (object);
+
+  g_free (address->priv->path);
+
+  if (G_OBJECT_CLASS (g_unix_socket_address_parent_class)->finalize)
+    (G_OBJECT_CLASS (g_unix_socket_address_parent_class)->finalize) (object);
+}
+
+static void
+g_unix_socket_address_dispose (GObject *object)
+{
+  GUnixSocketAddress *address G_GNUC_UNUSED = G_UNIX_SOCKET_ADDRESS (object);
+
+  if (G_OBJECT_CLASS (g_unix_socket_address_parent_class)->dispose)
+    (*G_OBJECT_CLASS (g_unix_socket_address_parent_class)->dispose) (object);
+}
+
+static void
+g_unix_socket_address_get_property (GObject    *object,
+                                    guint       prop_id,
+                                    GValue     *value,
+                                    GParamSpec *pspec)
+{
+  GUnixSocketAddress *address = G_UNIX_SOCKET_ADDRESS (object);
+
+  switch (prop_id)
+    {
+      case PROP_PATH:
+        g_value_set_string (value, address->priv->path);
+        break;
+
+      default:
+        G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+    }
+}
+
+static GSocketFamily
+g_unix_socket_address_get_family (GSocketAddress *address)
+{
+  g_assert (PF_UNIX == G_SOCKET_FAMILY_UNIX);
+
+  return G_SOCKET_FAMILY_UNIX;
+}
+
+static void
+g_unix_socket_address_set_property (GObject      *object,
+                                    guint         prop_id,
+                                    const GValue *value,
+                                    GParamSpec   *pspec)
+{
+  GUnixSocketAddress *address = G_UNIX_SOCKET_ADDRESS (object);
+
+  switch (prop_id)
+    {
+      case PROP_PATH:
+        g_free (address->priv->path);
+        address->priv->path = g_value_dup_string (value);
+        break;
+
+      default:
+        G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+    }
+}
+
+static gssize
+g_unix_socket_address_get_native_size (GSocketAddress *address)
+{
+  return sizeof (struct sockaddr_un);
+}
+
+static gboolean
+g_unix_socket_address_to_native (GSocketAddress *address,
+                                gpointer        dest,
+                                gsize           destlen)
+{
+  GUnixSocketAddress *addr = G_UNIX_SOCKET_ADDRESS (address);
+  struct sockaddr_un *sock;
+
+  if (destlen < sizeof (*sock))
+    return FALSE;
+
+  sock = (struct sockaddr_un *) dest;
+  sock->sun_family = AF_UNIX;
+  g_strlcpy (sock->sun_path, addr->priv->path, sizeof (sock->sun_path));
+
+  return TRUE;
+}
+
+static void
+g_unix_socket_address_class_init (GUnixSocketAddressClass *klass)
+{
+  GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+  GSocketAddressClass *gsocketaddress_class = G_SOCKET_ADDRESS_CLASS (klass);
+
+  g_type_class_add_private (klass, sizeof (GUnixSocketAddressPrivate));
+
+  gobject_class->finalize = g_unix_socket_address_finalize;
+  gobject_class->dispose = g_unix_socket_address_dispose;
+  gobject_class->set_property = g_unix_socket_address_set_property;
+  gobject_class->get_property = g_unix_socket_address_get_property;
+
+  gsocketaddress_class->get_family = g_unix_socket_address_get_family;
+  gsocketaddress_class->to_native = g_unix_socket_address_to_native;
+  gsocketaddress_class->get_native_size = g_unix_socket_address_get_native_size;
+
+  g_object_class_install_property (gobject_class,
+                                   PROP_PATH,
+                                   g_param_spec_string ("path",
+                                                        _("Path"),
+                                                        _("UNIX socket path"),
+                                                        NULL,
+                                                        G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB));
+}
+
+static void
+g_unix_socket_address_init (GUnixSocketAddress *address)
+{
+  address->priv = G_TYPE_INSTANCE_GET_PRIVATE (address,
+                                               G_TYPE_UNIX_SOCKET_ADDRESS,
+                                               GUnixSocketAddressPrivate);
+
+  address->priv->path = NULL;
+}
+
+/**
+ * g_unix_socket_address_new:
+ * @path: the socket path
+ *
+ * Creates a new #GUnixSocketAddress for @path.
+ *
+ * Returns: a new #GUnixSocketAddress
+ *
+ * Since: 2.22
+ */
+GSocketAddress *
+g_unix_socket_address_new (const gchar *path)
+{
+  return g_object_new (G_TYPE_UNIX_SOCKET_ADDRESS,
+                      "path", path,
+                      NULL);
+}
+
+#define __G_UNIX_SOCKET_ADDRESS_C__
+#include "gioaliasdef.c"
diff --git a/gio/gunixsocketaddress.h b/gio/gunixsocketaddress.h
new file mode 100644 (file)
index 0000000..527937f
--- /dev/null
@@ -0,0 +1,61 @@
+/* GIO - GLib Input, Output and Streaming Library
+ *
+ * Copyright (C) 2008 Christian Kellner, Samuel Cormier-Iijima
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Authors: Christian Kellner <gicmo@gnome.org>
+ *          Samuel Cormier-Iijima <sciyoshi@gmail.com>
+ */
+
+#ifndef __G_UNIX_SOCKET_ADDRESS_H__
+#define __G_UNIX_SOCKET_ADDRESS_H__
+
+#include <gio/gio.h>
+
+G_BEGIN_DECLS
+
+#define G_TYPE_UNIX_SOCKET_ADDRESS         (g_unix_socket_address_get_type ())
+#define G_UNIX_SOCKET_ADDRESS(o)           (G_TYPE_CHECK_INSTANCE_CAST ((o), G_TYPE_UNIX_SOCKET_ADDRESS, GUnixSocketAddress))
+#define G_UNIX_SOCKET_ADDRESS_CLASS(k)     (G_TYPE_CHECK_CLASS_CAST((k), G_TYPE_UNIX_SOCKET_ADDRESS, GUnixSocketAddressClass))
+#define G_IS_UNIX_SOCKET_ADDRESS(o)        (G_TYPE_CHECK_INSTANCE_TYPE ((o), G_TYPE_UNIX_SOCKET_ADDRESS))
+#define G_IS_UNIX_SOCKET_ADDRESS_CLASS(k)  (G_TYPE_CHECK_CLASS_TYPE ((k), G_TYPE_UNIX_SOCKET_ADDRESS))
+#define G_UNIX_SOCKET_ADDRESS_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), G_TYPE_UNIX_SOCKET_ADDRESS, GUnixSocketAddressClass))
+
+typedef struct _GUnixSocketAddress        GUnixSocketAddress;
+typedef struct _GUnixSocketAddressClass   GUnixSocketAddressClass;
+typedef struct _GUnixSocketAddressPrivate GUnixSocketAddressPrivate;
+
+struct _GUnixSocketAddress
+{
+  GSocketAddress parent_instance;
+
+  /*< private >*/
+  GUnixSocketAddressPrivate *priv;
+};
+
+struct _GUnixSocketAddressClass
+{
+  GSocketAddressClass parent_class;
+};
+
+GType           g_unix_socket_address_get_type    (void) G_GNUC_CONST;
+
+GSocketAddress *g_unix_socket_address_new         (const gchar *path);
+
+G_END_DECLS
+
+#endif /* __G_UNIX_SOCKET_ADDRESS_H__ */
index 92e8964..f10fa32 100644 (file)
@@ -250,6 +250,9 @@ union _GSystemThread
  */
 typedef void * GPid;
 
+#define GLIB_SYSDEF_AF_INET 2
+#define GLIB_SYSDEF_AF_INET6 23
+
 G_END_DECLS
 
 #endif /* GLIBCONFIG_H */