This copies the contents of keymaps over the network for remote
connections. Any future user of fd_static should Just Work too.

Signed-off-by: Derek Foreman <der...@osg.samsung.com>
---
 src/connection.c      | 60 ++++++++++++++++++++++++++++++++++++++++++++++++++-
 src/wayland-private.h |  2 ++
 2 files changed, 61 insertions(+), 1 deletion(-)

diff --git a/src/connection.c b/src/connection.c
index 8a44806..c1f65a4 100644
--- a/src/connection.c
+++ b/src/connection.c
@@ -562,9 +562,12 @@ wl_closure_marshal(struct wl_object *sender, uint32_t 
opcode,
        }
 
        memcpy(closure->args, args, count * sizeof *args);
+       closure->n_remote_fds = 0;
 
        signature = message->signature;
        for (i = 0; i < count; i++) {
+               bool has_bulk = false;
+
                signature = get_next_argument(signature, &arg);
 
                switch (arg.type) {
@@ -592,12 +595,25 @@ wl_closure_marshal(struct wl_object *sender, uint32_t 
opcode,
                                goto err_null;
                        break;
                case 'H':
+                       has_bulk = true;
                case 'h':
                        fd = args[i].h;
                        dup_fd = wl_os_dupfd_cloexec(fd, 0);
                        if (dup_fd < 0)
                                wl_abort("dup failed: %s\n", strerror(errno));
                        closure->args[i].h = dup_fd;
+                       if (sender->remote && has_bulk) {
+                               /* Dupe it again for sending its data later,
+                                * the other dupe will be automatically closed
+                                * on connection flush.
+                                */
+                               dup_fd = wl_os_dupfd_cloexec(dup_fd, 0);
+                               if (dup_fd < 0)
+                                       wl_abort("dup failed: %s\n",
+                                                strerror(errno));
+                               closure->remote_fds[closure->n_remote_fds] = 
dup_fd;
+                               closure->n_remote_fds++;
+                       }
                        break;
                default:
                        wl_abort("unhandled format code: '%c'\n", arg.type);
@@ -640,7 +656,7 @@ wl_connection_demarshal(struct wl_connection *connection,
                        const struct wl_message *message)
 {
        uint32_t *p, *next, *end, length, id;
-       int fd;
+       int fd, fdi;
        char *s;
        unsigned int i, count, num_arrays;
        const char *signature;
@@ -664,6 +680,8 @@ wl_connection_demarshal(struct wl_connection *connection,
                return NULL;
        }
 
+       closure->n_remote_fds = 0;
+
        array_extra = closure->extra;
        p = (uint32_t *)(closure->extra + num_arrays);
        end = p + size / sizeof *p;
@@ -674,6 +692,7 @@ wl_connection_demarshal(struct wl_connection *connection,
 
        signature = message->signature;
        for (i = 0; i < count; i++) {
+               bool has_bulk = false;
                signature = get_next_argument(signature, &arg);
 
                if (arg.type != 'h' && p + 1 > end) {
@@ -779,7 +798,16 @@ wl_connection_demarshal(struct wl_connection *connection,
                        p = next;
                        break;
                case 'H':
+                       has_bulk = true;
                case 'h':
+                       if (connection->remote) {
+                               closure->args[i].h = 
wl_os_create_anonymous_file(0);
+                               if (has_bulk) {
+                                       
closure->remote_fds[closure->n_remote_fds] = closure->args[i].h;
+                                       closure->n_remote_fds++;
+                               }
+                               break;
+                       }
                        if (connection->fds_in.tail == connection->fds_in.head) 
{
                                wl_log("file descriptor expected, "
                                       "object (%d), message %s(%s)\n",
@@ -804,6 +832,11 @@ wl_connection_demarshal(struct wl_connection *connection,
 
        wl_connection_consume(connection, size);
 
+       for (fdi = 0; fdi < closure->n_remote_fds; fdi++)
+               wl_connection_get_bulk_data(connection, 
closure->remote_fds[fdi]);
+
+       /* we don't want to clean them up in destroy... */
+       closure->n_remote_fds = 0;
        return closure;
 
  err:
@@ -1215,6 +1248,7 @@ wl_closure_send(struct wl_closure *closure, struct 
wl_connection *connection)
        uint32_t buffer_size;
        uint32_t *buffer;
        int result;
+       int i;
 
        if (copy_fds_to_connection(closure, connection))
                return -1;
@@ -1233,6 +1267,20 @@ wl_closure_send(struct wl_closure *closure, struct 
wl_connection *connection)
        result = wl_connection_write(connection, buffer, size);
        free(buffer);
 
+       if (result < 0 || !closure->n_remote_fds)
+               return result;
+
+       connection->want_flush = 1;
+       wl_connection_flush(connection);
+
+       for (i = 0; i < closure->n_remote_fds; i++) {
+               result = wl_connection_put_bulk_data(connection,
+                                           closure->remote_fds[i]);
+
+               if (result < 0)
+                       break;
+       }
+
        return result;
 }
 
@@ -1261,6 +1309,11 @@ wl_closure_queue(struct wl_closure *closure, struct 
wl_connection *connection)
        result = wl_connection_queue(connection, buffer, size);
        free(buffer);
 
+       if (closure->n_remote_fds) {
+               wl_log("Unable to queue closure with remote fds\n");
+               return -1;
+       }
+
        return result;
 }
 
@@ -1335,5 +1388,10 @@ wl_closure_print(struct wl_closure *closure, struct 
wl_object *target, int send)
 void
 wl_closure_destroy(struct wl_closure *closure)
 {
+       int i;
+
+       for (i = 0; i < closure->n_remote_fds; i++)
+               close(closure->remote_fds[i]);
+
        free(closure);
 }
diff --git a/src/wayland-private.h b/src/wayland-private.h
index be41e83..f5d6100 100644
--- a/src/wayland-private.h
+++ b/src/wayland-private.h
@@ -150,6 +150,8 @@ struct wl_closure {
        uint32_t opcode;
        uint32_t sender_id;
        union wl_argument args[WL_CLOSURE_MAX_ARGS];
+       int n_remote_fds;
+       int remote_fds[WL_CLOSURE_MAX_ARGS];
        struct wl_list link;
        struct wl_proxy *proxy;
        struct wl_array extra[0];
-- 
2.7.0

_______________________________________________
wayland-devel mailing list
wayland-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/wayland-devel

Reply via email to