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,5 +1,6 @@
#include <gio/gio.h>
#include <gio/gunixfdmessage.h>
#include <gio/gunixsocketaddress.h>
#include <sys/socket.h>
#include <string.h>
#include <unistd.h>
@@ -40,10 +41,12 @@ create_fd_list (gint *fd_list)
static void
test_fds (void)
{
GError *err = NULL;
GUnixFDMessage *message;
GUnixFDMessage **mv;
GUnixFDList *list, *l2;
GSocket *sockets[2];
GSocketAddress *addr;
const gint *peek;
char buffer[1024];
gint fd_list[40];
@@ -81,24 +84,32 @@ test_fds (void)
g_assert_cmpint (stolen[2], ==, sv[2]);
g_free (stolen);
g_unix_fd_message_append_fd (message, sv[0], NULL);
g_unix_fd_message_append_fd (message, sv[0], &err);
g_assert_no_error (err);
s = close (sv[0]);
g_assert_cmpint (s, ==, 0);
g_unix_fd_message_append_fd (message, sv[1], NULL);
g_unix_fd_message_append_fd (message, sv[1], &err);
g_assert_no_error (err);
s = close (sv[1]);
g_assert_cmpint (s, ==, 0);
s = close (g_unix_fd_list_get (list, 0, NULL));
s = close (g_unix_fd_list_get (list, 0, &err));
g_assert_no_error (err);
g_assert_cmpint (s, ==, 0);
s = close (g_unix_fd_list_get (list, 1, NULL));
s = close (g_unix_fd_list_get (list, 1, &err));
g_assert_no_error (err);
g_assert_cmpint (s, ==, 0);
s = close (g_unix_fd_list_get (list, 0, NULL));
s = close (g_unix_fd_list_get (list, 0, &err));
g_assert_no_error (err);
g_assert_cmpint (s, ==, 0);
s = close (g_unix_fd_list_get (list, 1, NULL));
s = close (g_unix_fd_list_get (list, 1, &err));
g_assert_no_error (err);
g_assert_cmpint (s, ==, 0);
s = close (g_unix_fd_list_get (list, 0, NULL));
s = close (g_unix_fd_list_get (list, 0, &err));
g_assert_no_error (err);
g_assert_cmpint (s, ==, 0);
s = close (g_unix_fd_list_get (list, 1, NULL));
s = close (g_unix_fd_list_get (list, 1, &err));
g_assert_no_error (err);
g_assert_cmpint (s, ==, 0);
g_object_unref (message);
@@ -111,34 +122,48 @@ test_fds (void)
s = pipe (sv);
g_assert_cmpint (s, ==, 0);
s = g_unix_fd_list_append (list, sv[0], NULL);
s = g_unix_fd_list_append (list, sv[0], &err);
g_assert_no_error (err);
g_assert_cmpint (s, >=, 0);
s = g_unix_fd_list_append (list, sv[1], NULL);
s = g_unix_fd_list_append (list, sv[1], &err);
g_assert_no_error (err);
g_assert_cmpint (s, >=, 0);
s = close (sv[0]);
g_assert_cmpint (s, ==, 0);
s = close (sv[1]);
g_assert_cmpint (s, ==, 0);
s = close (g_unix_fd_list_get (list, 0, NULL));
s = close (g_unix_fd_list_get (list, 0, &err));
g_assert_no_error (err);
g_assert_cmpint (s, ==, 0);
s = close (g_unix_fd_list_get (list, 1, NULL));
s = close (g_unix_fd_list_get (list, 1, &err));
g_assert_no_error (err);
g_assert_cmpint (s, ==, 0);
s = socketpair (PF_UNIX, SOCK_STREAM, 0, sv);
g_assert_cmpint (s, ==, 0);
sockets[0] = g_socket_new_from_fd (sv[0], NULL);
sockets[0] = g_socket_new_from_fd (sv[0], &err);
g_assert_no_error (err);
g_assert (G_IS_SOCKET (sockets[0]));
sockets[1] = g_socket_new_from_fd (sv[1], NULL);
sockets[1] = g_socket_new_from_fd (sv[1], &err);
g_assert_no_error (err);
g_assert (G_IS_SOCKET (sockets[1]));
addr = g_socket_get_local_address (sockets[0], &err);
g_assert_no_error (err);
g_assert (G_IS_UNIX_SOCKET_ADDRESS (addr));
g_assert_cmpint (g_unix_socket_address_get_address_type (G_UNIX_SOCKET_ADDRESS (addr)), ==, G_UNIX_SOCKET_ADDRESS_ANONYMOUS);
g_assert_cmpint (g_unix_socket_address_get_path_len (G_UNIX_SOCKET_ADDRESS (addr)), ==, 0);
g_object_unref (addr);
buffer[0] = 0xff;
ov.buffer = buffer;
ov.size = 1;
s = g_socket_send_message (sockets[0], NULL, &ov, 1,
(GSocketControlMessage **) &message,
1, 0, NULL, NULL);
1, 0, NULL, &err);
g_assert_no_error (err);
g_assert_cmpint (s, ==, 1);
g_object_unref (message);
@@ -149,7 +174,8 @@ test_fds (void)
iv.size = 1;
s = g_socket_receive_message (sockets[1], NULL, &iv, 1,
(GSocketControlMessage ***) &mv,
&nm, &flags, NULL, NULL);
&nm, &flags, NULL, &err);
g_assert_no_error (err);
g_assert_cmpint (s, ==, 1);
g_object_unref (sockets[0]);
g_object_unref (sockets[1]);
@@ -164,7 +190,8 @@ test_fds (void)
peek = g_unix_fd_list_peek_fds (list, &s);
g_assert_cmpint (s, ==, 2);
sv[0] = g_unix_fd_list_get (list, 1, NULL);
sv[0] = g_unix_fd_list_get (list, 1, &err);
g_assert_no_error (err);
strcpy (buffer, "failure to say failure to say 'i love gnome-panel!'.");
s = write (sv[0], buffer, strlen (buffer) + 1);