GUnixSocketAddress: handle abstract sockets with non-0-padded names

There are apparently two incompatible ways of naming abstract sockets:
pad the sockaddr with 0s and use the entire thing as the name, or else
don't, and just pass a shorter length value to the relevant functions.
We previously only supported the former method. Add support for the
latter.

Also correctly handle "anonymous" unix sockaddrs (eg, the client side
of a connection, or a socketpair() socket), and add unix domain socket
support to the socket-client and socket-server test programs to make
sure this all works.

https://bugzilla.gnome.org/show_bug.cgi?id=615960
This commit is contained in:
Dan Winship
2010-04-20 17:23:49 -04:00
parent 5e892de8af
commit 19d8cc3375
11 changed files with 439 additions and 110 deletions

View File

@@ -1,9 +1,12 @@
#include <gio/gio.h>
#include <gio/gunixsocketaddress.h>
#include <glib.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "socket-common.c"
GMainLoop *loop;
gboolean verbose = FALSE;
@@ -11,6 +14,7 @@ gboolean non_blocking = FALSE;
gboolean use_udp = FALSE;
gboolean use_source = FALSE;
int cancel_timeout = 0;
gboolean unix_socket = FALSE;
static GOptionEntry cmd_entries[] = {
{"cancel", 'c', 0, G_OPTION_ARG_INT, &cancel_timeout,
@@ -23,24 +27,11 @@ static GOptionEntry cmd_entries[] = {
"Enable non-blocking i/o", NULL},
{"use-source", 's', 0, G_OPTION_ARG_NONE, &use_source,
"Use GSource to wait for non-blocking i/o", NULL},
{"unix", 'U', 0, G_OPTION_ARG_NONE, &unix_socket,
"Use a unix socket instead of IP", NULL},
{NULL}
};
static char *
socket_address_to_string (GSocketAddress *address)
{
GInetAddress *inet_address;
char *str, *res;
int port;
inet_address = g_inet_socket_address_get_address (G_INET_SOCKET_ADDRESS (address));
str = g_inet_address_to_string (inet_address);
port = g_inet_socket_address_get_port (G_INET_SOCKET_ADDRESS (address));
res = g_strdup_printf ("%s:%d", str, port);
g_free (str);
return res;
}
static gboolean
source_ready (gpointer data,
GIOCondition condition)
@@ -104,6 +95,7 @@ main (int argc,
GSocketAddress *src_address;
GSocketAddress *address;
GSocketType socket_type;
GSocketFamily socket_family;
GError *error = NULL;
GOptionContext *context;
GCancellable *cancellable;
@@ -124,7 +116,7 @@ main (int argc,
if (argc != 2)
{
g_printerr ("%s: %s\n", argv[0], "Need to specify hostname");
g_printerr ("%s: %s\n", argv[0], "Need to specify hostname / unix socket name");
return 1;
}
@@ -145,18 +137,38 @@ main (int argc,
else
socket_type = G_SOCKET_TYPE_STREAM;
socket = g_socket_new (G_SOCKET_FAMILY_IPV4, socket_type, 0, &error);
if (unix_socket)
socket_family = G_SOCKET_FAMILY_UNIX;
else
socket_family = G_SOCKET_FAMILY_IPV4;
socket = g_socket_new (socket_family, socket_type, 0, &error);
if (socket == NULL)
{
g_printerr ("%s: %s\n", argv[0], error->message);
return 1;
}
connectable = g_network_address_parse (argv[1], 7777, &error);
if (connectable == NULL)
if (unix_socket)
{
g_printerr ("%s: %s\n", argv[0], error->message);
return 1;
GSocketAddress *addr;
addr = socket_address_from_string (argv[1]);
if (addr == NULL)
{
g_printerr ("%s: Could not parse '%s' as unix socket name\n", argv[0], argv[1]);
return 1;
}
connectable = G_SOCKET_CONNECTABLE (addr);
}
else
{
connectable = g_network_address_parse (argv[1], 7777, &error);
if (connectable == NULL)
{
g_printerr ("%s: %s\n", argv[0], error->message);
return 1;
}
}
enumerator = g_socket_connectable_enumerate (connectable);