diff --git a/gdk/broadway/broadwayd.c b/gdk/broadway/broadwayd.c index e36c8fce1f..f29eb774d8 100644 --- a/gdk/broadway/broadwayd.c +++ b/gdk/broadway/broadwayd.c @@ -13,6 +13,7 @@ #include #ifdef G_OS_UNIX #include +#include #endif #include "broadway-server.h" @@ -54,8 +55,15 @@ typedef struct { GSList *serial_mappings; GList *windows; guint disconnect_idle; + GList *fds; } BroadwayClient; +static void +close_fd (void *data) +{ + close (GPOINTER_TO_INT (data)); +} + static void client_free (BroadwayClient *client) { @@ -66,6 +74,7 @@ client_free (BroadwayClient *client) g_object_unref (client->in); g_string_free (client->buffer, TRUE); g_slist_free_full (client->serial_mappings, g_free); + g_list_free_full (client->fds, close_fd); g_free (client); } @@ -341,6 +350,9 @@ client_input_cb (GPollableInputStream *stream, gsize old_len; guchar *buffer; gsize buffer_len; + GInputVector input_vector; + GSocketControlMessage **messages = NULL; + int i, num_messages; old_len = client->buffer->len; @@ -348,10 +360,13 @@ client_input_cb (GPollableInputStream *stream, g_string_set_size (client->buffer, old_len + INPUT_BUFFER_SIZE); g_string_set_size (client->buffer, old_len); - res = g_socket_receive_with_blocking (socket, client->buffer->str + old_len, - client->buffer->allocated_len - client->buffer->len -1, - FALSE, NULL, NULL); + input_vector.buffer = client->buffer->str + old_len; + input_vector.size = client->buffer->allocated_len - client->buffer->len -1; + res = g_socket_receive_message (socket, NULL, + &input_vector, 1, + &messages, &num_messages, + NULL, NULL, NULL); if (res <= 0) { client->source = NULL; @@ -359,6 +374,23 @@ client_input_cb (GPollableInputStream *stream, return G_SOURCE_REMOVE; } + for (i = 0; i < num_messages; i++) + { + if (G_IS_UNIX_FD_MESSAGE (messages[i])) + { + int j, n_fds; + int *fds = g_unix_fd_message_steal_fds (G_UNIX_FD_MESSAGE (messages[i]), &n_fds); + for (j = 0; j < n_fds; j++) + { + int fd = fds[i]; + client->fds = g_list_append (client->fds, GINT_TO_POINTER (fd)); + } + g_free (fds); + } + g_object_unref (messages[i]); + } + g_free (messages); + g_string_set_size (client->buffer, old_len + res); buffer = (guchar *)client->buffer->str; diff --git a/gdk/broadway/gdkbroadway-server.c b/gdk/broadway/gdkbroadway-server.c index d81690ec5e..57cb48d5b8 100644 --- a/gdk/broadway/gdkbroadway-server.c +++ b/gdk/broadway/gdkbroadway-server.c @@ -12,9 +12,8 @@ #include #include -#ifdef G_OS_UNIX #include -#endif +#include #include #include #include @@ -160,30 +159,73 @@ _gdk_broadway_server_get_last_seen_time (GdkBroadwayServer *server) static guint32 gdk_broadway_server_send_message_with_size (GdkBroadwayServer *server, BroadwayRequestBase *base, - gsize size, guint32 type) + gsize size, guint32 type, int fd) { GOutputStream *out; gsize written; + guchar *buf; base->size = size; base->type = type; base->serial = server->next_serial++; - out = g_io_stream_get_output_stream (G_IO_STREAM (server->connection)); + buf = (guchar *)base; - if (!g_output_stream_write_all (out, base, size, &written, NULL, NULL)) + if (fd != -1) { - g_printerr ("Unable to write to server\n"); - exit (1); + GUnixFDList *fd_list = g_unix_fd_list_new_from_array (&fd, 1); + GSocketControlMessage *control_message = g_unix_fd_message_new_with_fd_list (fd_list); + GSocket *socket = g_socket_connection_get_socket (server->connection); + GOutputVector vector; + gssize bytes_written; + + vector.buffer = buf; + vector.size = size; + + bytes_written = g_socket_send_message (socket, + NULL, /* address */ + &vector, + 1, + &control_message, 1, + G_SOCKET_MSG_NONE, + NULL, + NULL); + + if (bytes_written <= 0) + { + g_printerr ("Unable to write to server\n"); + exit (1); + } + + g_print ("socket send message wrote %d of %d\n", (int)bytes_written, (int)size); + buf += bytes_written; + size -= bytes_written; + + g_object_unref (control_message); + g_object_unref (fd_list); + } + + if (size > 0) + { + out = g_io_stream_get_output_stream (G_IO_STREAM (server->connection)); + if (!g_output_stream_write_all (out, buf, size, &written, NULL, NULL)) + { + g_printerr ("Unable to write to server\n"); + exit (1); + } + + g_assert (written == size); } - g_assert (written == size); return base->serial; } #define gdk_broadway_server_send_message(_server, _msg, _type) \ - gdk_broadway_server_send_message_with_size(_server, (BroadwayRequestBase *)&_msg, sizeof (_msg), _type) + gdk_broadway_server_send_message_with_size(_server, (BroadwayRequestBase *)&_msg, sizeof (_msg), _type, -1) + +#define gdk_broadway_server_send_fd_message(_server, _msg, _type, _fd) \ + gdk_broadway_server_send_message_with_size(_server, (BroadwayRequestBase *)&_msg, sizeof (_msg), _type, _fd) static void parse_all_input (GdkBroadwayServer *server)