#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"
#include "gunixsocketaddress.h"
#endif
-#include "gioalias.h"
/**
* SECTION:gsocketaddress
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,
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
* 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.
*
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;
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;
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
} 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
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;
+}