This allows adding a tcp/ip socket and adds tracking of the remote status
for clients and proxies

Signed-off-by: Derek Foreman <[email protected]>
---
 src/connection.c          |  11 +++-
 src/wayland-client.c      | 103 +++++++++++++++++++++++++-------
 src/wayland-private.h     |   5 ++
 src/wayland-server-core.h |   7 +++
 src/wayland-server.c      | 146 ++++++++++++++++++++++++++++++++++++----------
 5 files changed, 221 insertions(+), 51 deletions(-)

diff --git a/src/connection.c b/src/connection.c
index 05806b6..5fd085f 100644
--- a/src/connection.c
+++ b/src/connection.c
@@ -39,6 +39,7 @@
 #include <sys/socket.h>
 #include <time.h>
 #include <ffi.h>
+#include <stdbool.h>
 
 #include "wayland-util.h"
 #include "wayland-private.h"
@@ -61,6 +62,7 @@ struct wl_connection {
        struct wl_buffer fds_in, fds_out;
        int fd;
        int want_flush;
+       bool remote;
 };
 
 static int
@@ -191,6 +193,12 @@ close_fds(struct wl_buffer *buffer, int max)
        buffer->tail += size;
 }
 
+void
+wl_connection_set_remote(struct wl_connection *connection)
+{
+       connection->remote = true;
+}
+
 int
 wl_connection_destroy(struct wl_connection *connection)
 {
@@ -278,6 +286,7 @@ wl_connection_flush(struct wl_connection *connection)
        char cmsg[CLEN];
        int len = 0, count, clen;
        uint32_t tail;
+       int wait = connection->remote ? 0 : MSG_DONTWAIT;
 
        if (!connection->want_flush)
                return 0;
@@ -298,7 +307,7 @@ wl_connection_flush(struct wl_connection *connection)
 
                do {
                        len = sendmsg(connection->fd, &msg,
-                                     MSG_NOSIGNAL | MSG_DONTWAIT);
+                                     MSG_NOSIGNAL | wait);
                } while (len == -1 && errno == EINTR);
 
                if (len == -1)
diff --git a/src/wayland-client.c b/src/wayland-client.c
index 8e7f612..1582760 100644
--- a/src/wayland-client.c
+++ b/src/wayland-client.c
@@ -36,11 +36,13 @@
 #include <unistd.h>
 #include <sys/socket.h>
 #include <sys/un.h>
+#include <netinet/in.h>
 #include <ctype.h>
 #include <assert.h>
 #include <fcntl.h>
 #include <poll.h>
 #include <pthread.h>
+#include <netdb.h>
 
 #include "wayland-util.h"
 #include "wayland-os.h"
@@ -344,6 +346,7 @@ proxy_create(struct wl_proxy *factory, const struct 
wl_interface *interface,
        proxy->refcount = 1;
        proxy->version = version;
 
+       proxy->object.remote = display->proxy.object.remote;
        proxy->object.id = wl_map_insert_new(&display->objects, 0, proxy);
 
        return proxy;
@@ -825,26 +828,41 @@ static const struct wl_display_listener display_listener 
= {
 };
 
 static int
-connect_to_socket(const char *name)
+connect_remote(const char *name)
 {
-       struct sockaddr_un addr;
-       socklen_t size;
-       const char *runtime_dir;
-       int name_size, fd;
+       int fd = -1;
+       char *host, *tmp;
+       struct addrinfo *result;
 
-       runtime_dir = getenv("XDG_RUNTIME_DIR");
-       if (!runtime_dir) {
-               wl_log("error: XDG_RUNTIME_DIR not set in the environment.\n");
-               /* to prevent programs reporting
-                * "failed to create display: Success" */
-               errno = ENOENT;
-               return -1;
+       host = strdup(strchr(name, ':')+1);
+       tmp = strchr(host, ':');
+       if (!tmp)
+               goto fail;
+       *tmp = 0;
+       fprintf(stderr, "CONNECT TO %s\n", host);
+
+       if (getaddrinfo(host, "31337", NULL, &result))
+               goto fail;
+
+       fd = wl_os_socket_cloexec(PF_INET, SOCK_STREAM, 0);
+
+       if (connect(fd, result->ai_addr, result->ai_addrlen) < 0) {
+               close(fd);
+               fd = -1;
+               goto fail;
        }
+fail:
+       free(host);
+       freeaddrinfo(result);
+       return fd;
+}
 
-       if (name == NULL)
-               name = getenv("WAYLAND_DISPLAY");
-       if (name == NULL)
-               name = "wayland-0";
+static int
+connect_local(const char *runtime_dir, const char *name)
+{
+       int fd, name_size;
+       struct sockaddr_un addr;
+       socklen_t size;
 
        fd = wl_os_socket_cloexec(PF_LOCAL, SOCK_STREAM, 0);
        if (fd < 0)
@@ -873,10 +891,36 @@ connect_to_socket(const char *name)
                close(fd);
                return -1;
        }
-
        return fd;
 }
 
+static int
+connect_to_socket(const char *name, bool *remote)
+{
+       const char *runtime_dir;
+
+       runtime_dir = getenv("XDG_RUNTIME_DIR");
+       if (!runtime_dir) {
+               wl_log("error: XDG_RUNTIME_DIR not set in the environment.\n");
+               /* to prevent programs reporting
+                * "failed to create display: Success" */
+               errno = ENOENT;
+               return -1;
+       }
+
+       if (name == NULL)
+               name = getenv("WAYLAND_DISPLAY");
+       if (name == NULL)
+               name = "wayland-0";
+
+       if (strchr(name, ':')) {
+               *remote = true;
+               return connect_remote(name);
+       }
+       *remote = false;
+       return connect_local(runtime_dir, name);
+}
+
 /** Connect to Wayland display on an already open fd
  *
  * \param fd The fd to use for the connection
@@ -923,6 +967,7 @@ wl_display_connect_to_fd(int fd)
        display->proxy.queue = &display->default_queue;
        display->proxy.flags = 0;
        display->proxy.refcount = 1;
+       display->proxy.object.remote = false;
 
        /* We set this version to 0 for backwards compatibility.
         *
@@ -973,8 +1018,10 @@ wl_display_connect_to_fd(int fd)
 WL_EXPORT struct wl_display *
 wl_display_connect(const char *name)
 {
+       struct wl_display *display;
        char *connection, *end;
        int flags, fd;
+       bool remote = false;
 
        connection = getenv("WAYLAND_SOCKET");
        if (connection) {
@@ -990,12 +1037,15 @@ wl_display_connect(const char *name)
                        fcntl(fd, F_SETFD, flags | FD_CLOEXEC);
                unsetenv("WAYLAND_SOCKET");
        } else {
-               fd = connect_to_socket(name);
+               fd = connect_to_socket(name, &remote);
                if (fd < 0)
                        return NULL;
        }
-
-       return wl_display_connect_to_fd(fd);
+       display = wl_display_connect_to_fd(fd);
+       display->proxy.object.remote = remote;
+       if (display->proxy.object.remote)
+               wl_connection_set_remote(display->connection);
+       return display;
 }
 
 /** Close a connection to a Wayland display
@@ -1904,6 +1954,19 @@ wl_proxy_get_hook_data(struct wl_proxy *proxy)
        return proxy->hook_data;
 }
 
+/** Get whether a proxy is remote or not
+ *
+ * \param proxy The proxy object
+ * \return True if the proxy is remote
+ *
+ * \memberof wl_proxy
+ */
+WL_EXPORT bool
+wl_proxy_get_remote(struct wl_proxy *proxy)
+{
+       return proxy->object.remote;
+}
+
 /** Get the id of a proxy object
  *
  * \param proxy The proxy object
diff --git a/src/wayland-private.h b/src/wayland-private.h
index 994bc45..67de269 100644
--- a/src/wayland-private.h
+++ b/src/wayland-private.h
@@ -30,6 +30,7 @@
 
 #include <stdarg.h>
 #include <stdlib.h>
+#include <stdbool.h>
 
 #define WL_HIDE_DEPRECATED 1
 
@@ -50,6 +51,7 @@ struct wl_object {
        const struct wl_interface *interface;
        const void *implementation;
        uint32_t id;
+       bool remote;
 };
 
 extern struct wl_object global_zombie_object;
@@ -114,6 +116,9 @@ int
 wl_connection_destroy(struct wl_connection *connection);
 
 void
+wl_connection_set_remote(struct wl_connection *connection);
+
+void
 wl_connection_copy(struct wl_connection *connection, void *data, size_t size);
 
 void
diff --git a/src/wayland-server-core.h b/src/wayland-server-core.h
index 3316022..72581a7 100644
--- a/src/wayland-server-core.h
+++ b/src/wayland-server-core.h
@@ -32,6 +32,7 @@ extern "C" {
 
 #include <sys/types.h>
 #include <stdint.h>
+#include <stdbool.h>
 #include "wayland-util.h"
 #include "wayland-version.h"
 
@@ -128,6 +129,9 @@ wl_display_get_event_loop(struct wl_display *display);
 int
 wl_display_add_socket(struct wl_display *display, const char *name);
 
+int
+wl_display_add_remote_socket(struct wl_display *display, const char *name);
+
 const char *
 wl_display_add_socket_auto(struct wl_display *display);
 
@@ -488,6 +492,9 @@ wl_shm_buffer_get_fd(struct wl_shm_buffer *buffer);
 
 void wl_log_set_handler_server(wl_log_func_t handler);
 
+bool
+wl_client_is_remote(struct wl_client *client);
+
 #ifdef  __cplusplus
 }
 #endif
diff --git a/src/wayland-server.c b/src/wayland-server.c
index ae9365f..270bcdb 100644
--- a/src/wayland-server.c
+++ b/src/wayland-server.c
@@ -36,6 +36,7 @@
 #include <unistd.h>
 #include <sys/socket.h>
 #include <sys/un.h>
+#include <netinet/in.h>
 #include <dlfcn.h>
 #include <assert.h>
 #include <sys/time.h>
@@ -59,13 +60,20 @@
 #define LOCK_SUFFIX    ".lock"
 #define LOCK_SUFFIXLEN 5
 
+struct wl_display;
+
 struct wl_socket {
        int fd;
        int fd_lock;
-       struct sockaddr_un addr;
+       bool remote;
+       union {
+               struct sockaddr_un local;
+               struct sockaddr_in remote;
+       } addr;
        char lock_addr[UNIX_PATH_MAX + LOCK_SUFFIXLEN];
        struct wl_list link;
        struct wl_event_source *source;
+       struct wl_display *display;
        char *display_name;
 };
 
@@ -81,6 +89,7 @@ struct wl_client {
        struct wl_signal destroy_signal;
        struct ucred ucred;
        int error;
+       bool remote;
 };
 
 struct wl_display {
@@ -123,6 +132,12 @@ struct wl_resource {
 
 static int debug_server = 0;
 
+WL_EXPORT bool
+wl_client_is_remote(struct wl_client *client)
+{
+       return client->remote;
+}
+
 WL_EXPORT void
 wl_resource_post_event_array(struct wl_resource *resource, uint32_t opcode,
                             union wl_argument *args)
@@ -878,8 +893,8 @@ wl_socket_destroy(struct wl_socket *s)
 {
        if (s->source)
                wl_event_source_remove(s->source);
-       if (s->addr.sun_path[0])
-               unlink(s->addr.sun_path);
+       if (!s->remote && s->addr.local.sun_path[0])
+                       unlink(s->addr.local.sun_path);
        if (s->fd >= 0)
                close(s->fd);
        if (s->lock_addr[0])
@@ -1073,7 +1088,9 @@ wl_display_flush_clients(struct wl_display *display)
 static int
 socket_data(int fd, uint32_t mask, void *data)
 {
-       struct wl_display *display = data;
+       struct wl_client *client;
+       struct wl_socket *socket = data;
+       struct wl_display *display = socket->display;
        struct sockaddr_un name;
        socklen_t length;
        int client_fd;
@@ -1081,11 +1098,20 @@ socket_data(int fd, uint32_t mask, void *data)
        length = sizeof name;
        client_fd = wl_os_accept_cloexec(fd, (struct sockaddr *) &name,
                                         &length);
-       if (client_fd < 0)
+       if (client_fd < 0) {
                wl_log("failed to accept: %m\n");
-       else
-               if (!wl_client_create(display, client_fd))
-                       close(client_fd);
+               return 1;
+       }
+
+       client = wl_client_create(display, client_fd);
+       if (!client) {
+               close(client_fd);
+               return 1;
+       }
+
+       client->remote = socket->remote;
+       if (client->remote)
+               wl_connection_set_remote(client->connection);
 
        return 1;
 }
@@ -1095,8 +1121,11 @@ wl_socket_lock(struct wl_socket *socket)
 {
        struct stat socket_stat;
 
+       if (socket->remote)
+               return 0;
+
        snprintf(socket->lock_addr, sizeof socket->lock_addr,
-                "%s%s", socket->addr.sun_path, LOCK_SUFFIX);
+                "%s%s", socket->addr.local.sun_path, LOCK_SUFFIX);
 
        socket->fd_lock = open(socket->lock_addr, O_CREAT | O_CLOEXEC,
                               (S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP));
@@ -1113,15 +1142,15 @@ wl_socket_lock(struct wl_socket *socket)
                goto err_fd;
        }
 
-       if (stat(socket->addr.sun_path, &socket_stat) < 0 ) {
+       if (stat(socket->addr.local.sun_path, &socket_stat) < 0 ) {
                if (errno != ENOENT) {
                        wl_log("did not manage to stat file %s\n",
-                               socket->addr.sun_path);
+                               socket->addr.local.sun_path);
                        goto err_fd;
                }
        } else if (socket_stat.st_mode & S_IWUSR ||
                   socket_stat.st_mode & S_IWGRP) {
-               unlink(socket->addr.sun_path);
+               unlink(socket->addr.local.sun_path);
        }
 
        return 0;
@@ -1134,16 +1163,17 @@ err:
         * socket won't be created anyway. This prevents the
         * wl_socket_destroy from unlinking already existing socket
         * created by other compositor */
-       *socket->addr.sun_path = 0;
+       *socket->addr.local.sun_path = 0;
 
        return -1;
 }
 
 static int
-wl_socket_init_for_display_name(struct wl_socket *s, const char *name)
+wl_socket_init_for_display_name(struct wl_socket *s, const char *name, bool 
remote)
 {
        int name_size;
        const char *runtime_dir;
+       char remote_lock[108];
 
        runtime_dir = getenv("XDG_RUNTIME_DIR");
        if (!runtime_dir) {
@@ -1155,17 +1185,28 @@ wl_socket_init_for_display_name(struct wl_socket *s, 
const char *name)
                return -1;
        }
 
-       s->addr.sun_family = AF_LOCAL;
-       name_size = snprintf(s->addr.sun_path, sizeof s->addr.sun_path,
-                            "%s/%s", runtime_dir, name) + 1;
-
-       s->display_name = (s->addr.sun_path + name_size - 1) - strlen(name);
+       s->remote = remote;
+       if (remote) {
+               s->addr.remote.sin_family = AF_INET;
+               s->addr.remote.sin_port = htons(31337);
+               s->addr.remote.sin_addr.s_addr = INADDR_ANY;
+               name_size = snprintf(remote_lock,
+                                    sizeof remote_lock,
+                                    "%s/%s", runtime_dir, name) + 1;
+               s->display_name = strdup(name);
+       } else {
+               s->addr.local.sun_family = AF_LOCAL;
+               name_size = snprintf(s->addr.local.sun_path,
+                                    sizeof s->addr.local.sun_path,
+                                    "%s/%s", runtime_dir, name) + 1;
 
+               s->display_name = (s->addr.local.sun_path + name_size - 1) - 
strlen(name);
+       }
        assert(name_size > 0);
-       if (name_size > (int)sizeof s->addr.sun_path) {
+       if (name_size > (int)sizeof s->addr.local.sun_path) {
                wl_log("error: socket path \"%s/%s\" plus null terminator"
                       " exceeds 108 bytes\n", runtime_dir, name);
-               *s->addr.sun_path = 0;
+               *s->addr.local.sun_path = 0;
                /* to prevent programs reporting
                 * "failed to add socket: Success" */
                errno = ENAMETOOLONG;
@@ -1176,17 +1217,29 @@ wl_socket_init_for_display_name(struct wl_socket *s, 
const char *name)
 }
 
 static int
-_wl_display_add_socket(struct wl_display *display, struct wl_socket *s)
+_wl_display_add_socket(struct wl_display *display, struct wl_socket *s, bool 
remote)
 {
        socklen_t size;
+       struct sockaddr *sockaddr;
+
+       if (remote) {
+               s->fd = wl_os_socket_cloexec(PF_INET, SOCK_STREAM, 0);
+               wl_os_socket_reuseaddr(s->fd);
+       } else
+               s->fd = wl_os_socket_cloexec(PF_LOCAL, SOCK_STREAM, 0);
 
-       s->fd = wl_os_socket_cloexec(PF_LOCAL, SOCK_STREAM, 0);
        if (s->fd < 0) {
                return -1;
        }
 
-       size = offsetof (struct sockaddr_un, sun_path) + 
strlen(s->addr.sun_path);
-       if (bind(s->fd, (struct sockaddr *) &s->addr, size) < 0) {
+       sockaddr = (struct sockaddr *)&s->addr;
+       if (remote)
+               size = sizeof(struct sockaddr_in);
+       else
+               size = offsetof (struct sockaddr_un, sun_path)
+                    + strlen(s->addr.local.sun_path);
+
+       if (bind(s->fd, sockaddr, size) < 0) {
                wl_log("bind() failed with error: %m\n");
                return -1;
        }
@@ -1196,9 +1249,10 @@ _wl_display_add_socket(struct wl_display *display, 
struct wl_socket *s)
                return -1;
        }
 
+       s->display = display;
        s->source = wl_event_loop_add_fd(display->loop, s->fd,
                                         WL_EVENT_READABLE,
-                                        socket_data, display);
+                                        socket_data, s);
        if (s->source == NULL) {
                return -1;
        }
@@ -1224,7 +1278,7 @@ wl_display_add_socket_auto(struct wl_display *display)
 
        do {
                snprintf(display_name, sizeof display_name, "wayland-%d", 
displayno);
-               if (wl_socket_init_for_display_name(s, display_name) < 0) {
+               if (wl_socket_init_for_display_name(s, display_name, false) < 
0) {
                        wl_socket_destroy(s);
                        return NULL;
                }
@@ -1232,7 +1286,7 @@ wl_display_add_socket_auto(struct wl_display *display)
                if (wl_socket_lock(s) < 0)
                        continue;
 
-               if (_wl_display_add_socket(display, s) < 0) {
+               if (_wl_display_add_socket(display, s, false) < 0) {
                        wl_socket_destroy(s);
                        return NULL;
                }
@@ -1328,7 +1382,38 @@ wl_display_add_socket(struct wl_display *display, const 
char *name)
        if (name == NULL)
                name = "wayland-0";
 
-       if (wl_socket_init_for_display_name(s, name) < 0) {
+       if (wl_socket_init_for_display_name(s, name, false) < 0) {
+               wl_socket_destroy(s);
+               return -1;
+       }
+
+       if (wl_socket_lock(s) < 0) {
+               wl_socket_destroy(s);
+               return -1;
+       }
+
+       if (_wl_display_add_socket(display, s, false) < 0) {
+               wl_socket_destroy(s);
+               return -1;
+       }
+
+       return 0;
+}
+
+WL_EXPORT int
+wl_display_add_remote_socket(struct wl_display *display, const char *name)
+{
+       struct wl_socket *s;
+
+       s = wl_socket_alloc();
+       if (s == NULL)
+               return -1;
+       if (name == NULL)
+               name = getenv("WAYLAND_DISPLAY");
+       if (name == NULL)
+               name = "wayland-0";
+
+       if (wl_socket_init_for_display_name(s, name, true) < 0) {
                wl_socket_destroy(s);
                return -1;
        }
@@ -1338,7 +1423,7 @@ wl_display_add_socket(struct wl_display *display, const 
char *name)
                return -1;
        }
 
-       if (_wl_display_add_socket(display, s) < 0) {
+       if (_wl_display_add_socket(display, s, true) < 0) {
                wl_socket_destroy(s);
                return -1;
        }
@@ -1400,6 +1485,7 @@ wl_resource_create(struct wl_client *client,
        resource->object.id = id;
        resource->object.interface = interface;
        resource->object.implementation = NULL;
+       resource->object.remote = client->remote;
 
        wl_signal_init(&resource->destroy_signal);
 
-- 
2.7.0

_______________________________________________
wayland-devel mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/wayland-devel

Reply via email to