[glib] Add network address and socket types



commit 68fc0556275edf6e63a3242841f2981a42ee11cb
Author: Dan Winship <danw gnome org>
Date:   Fri Dec 12 13:13:55 2008 -0500

    Add network address and socket types
    
    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.
---
 configure.in                        |   28 ++
 docs/reference/gio/gio-docs.xml     |    7 +
 docs/reference/gio/gio-sections.txt |   91 +++++
 docs/reference/gio/gio.types        |    4 +
 gio/Makefile.am                     |   11 +-
 gio/ginetaddress.c                  |  747 +++++++++++++++++++++++++++++++++++
 gio/ginetaddress.h                  |  101 +++++
 gio/ginetsocketaddress.c            |  306 ++++++++++++++
 gio/ginetsocketaddress.h            |   69 ++++
 gio/gio.h                           |    3 +
 gio/gio.symbols                     |   51 +++
 gio/gioenums.h                      |   20 +
 gio/giotypes.h                      |    5 +
 gio/gnetworkingprivate.h            |   53 +++
 gio/gsocketaddress.c                |  233 +++++++++++
 gio/gsocketaddress.h                |   77 ++++
 gio/gunixsocketaddress.c            |  206 ++++++++++
 gio/gunixsocketaddress.h            |   61 +++
 glibconfig.h.win32.in               |    3 +
 19 files changed, 2075 insertions(+), 1 deletions(-)

diff --git a/configure.in b/configure.in
index 514fd75..5c33ab9 100644
--- a/configure.in
+++ b/configure.in
@@ -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
diff --git a/docs/reference/gio/gio-docs.xml b/docs/reference/gio/gio-docs.xml
index 46af7fe..8872ed7 100644
--- a/docs/reference/gio/gio-docs.xml
+++ b/docs/reference/gio/gio-docs.xml
@@ -90,6 +90,13 @@
     	<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"/>
diff --git a/docs/reference/gio/gio-sections.txt b/docs/reference/gio/gio-sections.txt
index 36e9aee..a2d19b7 100644
--- a/docs/reference/gio/gio-sections.txt
+++ b/docs/reference/gio/gio-sections.txt
@@ -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>
diff --git a/docs/reference/gio/gio.types b/docs/reference/gio/gio.types
index c73282a..cedae87 100644
--- a/docs/reference/gio/gio.types
+++ b/docs/reference/gio/gio.types
@@ -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
diff --git a/gio/Makefile.am b/gio/Makefile.am
index be6568f..53b30c2 100644
--- a/gio/Makefile.am
+++ b/gio/Makefile.am
@@ -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
index 0000000..cc5856b
--- /dev/null
+++ b/gio/ginetaddress.c
@@ -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
index 0000000..3f9e499
--- /dev/null
+++ b/gio/ginetaddress.h
@@ -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
index 0000000..b8275a8
--- /dev/null
+++ b/gio/ginetsocketaddress.c
@@ -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
index 0000000..b455ac5
--- /dev/null
+++ b/gio/ginetsocketaddress.h
@@ -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__ */
diff --git a/gio/gio.h b/gio/gio.h
index e3a0b14..6e809ba 100644
--- 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>
diff --git a/gio/gio.symbols b/gio/gio.symbols
index 4dc5917..99ad117 100644
--- a/gio/gio.symbols
+++ b/gio/gio.symbols
@@ -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
diff --git a/gio/gioenums.h b/gio/gioenums.h
index 3bb50ff..e6e6dfc 100644
--- a/gio/gioenums.h
+++ b/gio/gioenums.h
@@ -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__ */
diff --git a/gio/giotypes.h b/gio/giotypes.h
index 981c195..6ea1c1b 100644
--- a/gio/giotypes.h
+++ b/gio/giotypes.h
@@ -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
index 0000000..a90d264
--- /dev/null
+++ b/gio/gnetworkingprivate.h
@@ -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
index 0000000..33e8ffd
--- /dev/null
+++ b/gio/gsocketaddress.c
@@ -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
index 0000000..1649ba6
--- /dev/null
+++ b/gio/gsocketaddress.h
@@ -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
index 0000000..0b1b7e3
--- /dev/null
+++ b/gio/gunixsocketaddress.c
@@ -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
index 0000000..527937f
--- /dev/null
+++ b/gio/gunixsocketaddress.h
@@ -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__ */
diff --git a/glibconfig.h.win32.in b/glibconfig.h.win32.in
index 92e8964..f10fa32 100644
--- a/glibconfig.h.win32.in
+++ b/glibconfig.h.win32.in
@@ -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 */



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]