GDBusWorker: move flush async op into continue_writing()
[platform/upstream/glib.git] / gio / gsocketaddress.c
index 70c9e36..477f720 100644 (file)
 
 #include <config.h>
 #include <glib.h>
+#include <string.h>
 
 #include "gsocketaddress.h"
 #include "ginetaddress.h"
 #include "ginetsocketaddress.h"
 #include "gnetworkingprivate.h"
+#include "gproxyaddress.h"
+#include "gproxyaddressenumerator.h"
 #include "gsocketaddressenumerator.h"
 #include "gsocketconnectable.h"
 #include "glibintl.h"
@@ -37,7 +40,6 @@
 #include "gunixsocketaddress.h"
 #endif
 
-#include "gioalias.h"
 
 /**
  * SECTION:gsocketaddress
@@ -63,8 +65,9 @@ enum
   PROP_FAMILY
 };
 
-static void                      g_socket_address_connectable_iface_init (GSocketConnectableIface *iface);
-static GSocketAddressEnumerator *g_socket_address_connectable_enumerate  (GSocketConnectable      *connectable);
+static void                      g_socket_address_connectable_iface_init       (GSocketConnectableIface *iface);
+static GSocketAddressEnumerator *g_socket_address_connectable_enumerate               (GSocketConnectable      *connectable);
+static GSocketAddressEnumerator *g_socket_address_connectable_proxy_enumerate  (GSocketConnectable      *connectable);
 
 G_DEFINE_ABSTRACT_TYPE_WITH_CODE (GSocketAddress, g_socket_address, G_TYPE_OBJECT,
                                  G_IMPLEMENT_INTERFACE (G_TYPE_SOCKET_CONNECTABLE,
@@ -126,6 +129,7 @@ static void
 g_socket_address_connectable_iface_init (GSocketConnectableIface *connectable_iface)
 {
   connectable_iface->enumerate  = g_socket_address_connectable_enumerate;
+  connectable_iface->proxy_enumerate  = g_socket_address_connectable_proxy_enumerate;
 }
 
 static void
@@ -168,7 +172,7 @@ g_socket_address_get_native_size (GSocketAddress *address)
  * sockaddr</type>, which can be passed to low-level functions like
  * connect() or bind().
  *
- * If not enough space is availible, a %G_IO_ERROR_NO_SPACE error is
+ * If not enough space is available, a %G_IO_ERROR_NO_SPACE error is
  * returned. If the address type is not known on the system
  * then a %G_IO_ERROR_NOT_SUPPORTED error is returned.
  *
@@ -217,9 +221,13 @@ g_socket_address_new_from_native (gpointer native,
   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);
+      GInetAddress *iaddr;
       GSocketAddress *sockaddr;
 
+      if (len < sizeof (*addr))
+       return NULL;
+
+      iaddr = g_inet_address_new_from_bytes ((guint8 *) &(addr->sin_addr), AF_INET);
       sockaddr = g_inet_socket_address_new (iaddr, g_ntohs (addr->sin_port));
       g_object_unref (iaddr);
       return sockaddr;
@@ -228,9 +236,26 @@ g_socket_address_new_from_native (gpointer native,
   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);
+      GInetAddress *iaddr;
       GSocketAddress *sockaddr;
 
+      if (len < sizeof (*addr))
+       return NULL;
+
+      if (IN6_IS_ADDR_V4MAPPED (&(addr->sin6_addr)))
+       {
+         struct sockaddr_in sin_addr;
+
+         sin_addr.sin_family = AF_INET;
+         sin_addr.sin_port = addr->sin6_port;
+         memcpy (&(sin_addr.sin_addr.s_addr), addr->sin6_addr.s6_addr + 12, 4);
+         iaddr = g_inet_address_new_from_bytes ((guint8 *) &(sin_addr.sin_addr), AF_INET);
+       }
+      else
+       {
+         iaddr = g_inet_address_new_from_bytes ((guint8 *) &(addr->sin6_addr), AF_INET6);
+       }
+
       sockaddr = g_inet_socket_address_new (iaddr, g_ntohs (addr->sin6_port));
       g_object_unref (iaddr);
       return sockaddr;
@@ -240,11 +265,35 @@ g_socket_address_new_from_native (gpointer native,
   if (family == AF_UNIX)
     {
       struct sockaddr_un *addr = (struct sockaddr_un *) native;
-
-      if (addr->sun_path[0] == 0)
-       return g_unix_socket_address_new_abstract (addr->sun_path+1,
-                                                  sizeof (addr->sun_path) - 1);
-      return g_unix_socket_address_new (addr->sun_path);
+      gint path_len = len - G_STRUCT_OFFSET (struct sockaddr_un, sun_path);
+
+      if (path_len == 0)
+       {
+         return g_unix_socket_address_new_with_type ("", 0,
+                                                     G_UNIX_SOCKET_ADDRESS_ANONYMOUS);
+       }
+      else if (addr->sun_path[0] == 0)
+       {
+         if (!g_unix_socket_address_abstract_names_supported ())
+           {
+             return g_unix_socket_address_new_with_type ("", 0,
+                                                         G_UNIX_SOCKET_ADDRESS_ANONYMOUS);
+           }
+         else if (len < sizeof (*addr))
+           {
+             return g_unix_socket_address_new_with_type (addr->sun_path + 1,
+                                                         path_len - 1,
+                                                         G_UNIX_SOCKET_ADDRESS_ABSTRACT);
+           }
+         else
+           {
+             return g_unix_socket_address_new_with_type (addr->sun_path + 1,
+                                                         path_len - 1,
+                                                         G_UNIX_SOCKET_ADDRESS_ABSTRACT_PADDED);
+           }
+       }
+      else
+       return g_unix_socket_address_new (addr->sun_path);
     }
 #endif
 
@@ -266,6 +315,7 @@ typedef struct {
 
 } GSocketAddressAddressEnumeratorClass;
 
+static GType _g_socket_address_address_enumerator_get_type (void);
 G_DEFINE_TYPE (GSocketAddressAddressEnumerator, _g_socket_address_address_enumerator, G_TYPE_SOCKET_ADDRESS_ENUMERATOR)
 
 static void
@@ -326,5 +376,37 @@ g_socket_address_connectable_enumerate (GSocketConnectable *connectable)
   return (GSocketAddressEnumerator *)sockaddr_enum;
 }
 
-#define __G_SOCKET_ADDRESS_C__
-#include "gioaliasdef.c"
+static GSocketAddressEnumerator *
+g_socket_address_connectable_proxy_enumerate (GSocketConnectable *connectable)
+{
+  GSocketAddressEnumerator *addr_enum = NULL;
+
+  if (G_IS_INET_SOCKET_ADDRESS (connectable) &&
+      !G_IS_PROXY_ADDRESS (connectable))
+    {
+      GInetAddress *addr;
+      guint port;
+      gchar *uri;
+      gchar *ip;
+
+      g_object_get (connectable, "address", &addr, "port", &port, NULL);
+
+      ip = g_inet_address_to_string (addr);
+      uri = _g_uri_from_authority ("none", ip, port, NULL);
+
+      addr_enum = g_object_new (G_TYPE_PROXY_ADDRESS_ENUMERATOR,
+                               "connectable", connectable,
+                               "uri", uri,
+                               NULL);
+
+      g_object_unref (addr);
+      g_free (ip);
+      g_free (uri);
+    }
+  else
+    {
+      addr_enum = g_socket_address_connectable_enumerate (connectable);
+    }
+
+  return addr_enum;
+}