[gtk+/wip/alexl/broadway4: 4/5] broadway: Support fd passing in protocol



commit 97d5d69c51416cd3974e3b5fe3c01b4bd4b51761
Author: Alexander Larsson <alexl redhat com>
Date:   Fri Nov 17 15:57:28 2017 +0100

    broadway: Support fd passing in protocol
    
    This will be used to pass buffers

 gdk/broadway/broadwayd.c          |   38 +++++++++++++++++++++--
 gdk/broadway/gdkbroadway-server.c |   60 +++++++++++++++++++++++++++++++-----
 2 files changed, 86 insertions(+), 12 deletions(-)
---
diff --git a/gdk/broadway/broadwayd.c b/gdk/broadway/broadwayd.c
index e36c8fc..f29eb77 100644
--- a/gdk/broadway/broadwayd.c
+++ b/gdk/broadway/broadwayd.c
@@ -13,6 +13,7 @@
 #include <gio/gio.h>
 #ifdef G_OS_UNIX
 #include <gio/gunixsocketaddress.h>
+#include <gio/gunixfdmessage.h>
 #endif
 
 #include "broadway-server.h"
@@ -54,9 +55,16 @@ 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)
 {
   g_assert (client->windows == NULL);
@@ -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 d81690e..57cb48d 100644
--- a/gdk/broadway/gdkbroadway-server.c
+++ b/gdk/broadway/gdkbroadway-server.c
@@ -12,9 +12,8 @@
 
 #include <glib.h>
 #include <glib/gprintf.h>
-#ifdef G_OS_UNIX
 #include <gio/gunixsocketaddress.h>
-#endif
+#include <gio/gunixfdmessage.h>
 #include <stdlib.h>
 #include <string.h>
 #include <errno.h>
@@ -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)


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]