[RFC wayland 16/18] connection: Use bulk transfers for fd_static on remote connections
Derek Foreman
derekf at osg.samsung.com
Tue Feb 9 16:56:03 UTC 2016
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 <derekf at 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
More information about the wayland-devel
mailing list