/* * \brief Support for communication over Unix domain sockets * \author Norman Feske * \date 2012-08-10 */ /* * Copyright (C) 2011-2017 Genode Labs GmbH * * This file is part of the Genode OS framework, which is distributed * under the terms of the GNU Affero General Public License version 3. */ #ifndef _CORE__INCLUDE__SERVER_SOCKET_PAIR_H_ #define _CORE__INCLUDE__SERVER_SOCKET_PAIR_H_ /* Linux syscall bindings */ #include #include #include /* base-internal includes */ #include #include /* core-local includes */ #include /** * Utility: Create socket address for server entrypoint at thread ID */ struct Uds_addr : sockaddr_un { Uds_addr(long thread_id) : sockaddr_un({.sun_family = AF_UNIX, .sun_path = { }}) { Genode::snprintf(sun_path, sizeof(sun_path), "%s/ep-%ld", resource_path(), thread_id); } }; /** * Utility: Create named socket pair for given unique ID */ static inline Genode::Socket_pair create_server_socket_pair(long id) { Genode::Socket_pair socket_pair; using Genode::raw; /* * Main thread uses 'Ipc_server' for 'sleep_forever()' only. No need for * binding. */ if (id == -1) return socket_pair; Uds_addr addr(id); /* * Create server-side socket */ socket_pair.server_sd = lx_socket(AF_UNIX, SOCK_DGRAM | SOCK_CLOEXEC, 0); if (socket_pair.server_sd < 0) { raw("Error: Could not create server-side socket (ret=", socket_pair.server_sd, ")"); class Server_socket_failed { }; throw Server_socket_failed(); } /* make sure bind succeeds */ lx_unlink(addr.sun_path); int const bind_ret = lx_bind(socket_pair.server_sd, (sockaddr *)&addr, sizeof(addr)); if (bind_ret < 0) { raw("Error: Could not bind server socket (ret=", bind_ret, ")"); class Bind_failed { }; throw Bind_failed(); } /* * Create client-side socket */ socket_pair.client_sd = lx_socket(AF_UNIX, SOCK_DGRAM | SOCK_CLOEXEC, 0); if (socket_pair.client_sd < 0) { raw("Error: Could not create client-side socket (ret=", socket_pair.client_sd, ")"); class Client_socket_failed { }; throw Client_socket_failed(); } int const conn_ret = lx_connect(socket_pair.client_sd, (sockaddr *)&addr, sizeof(addr)); if (conn_ret < 0) { raw("Error: Could not connect client-side socket (ret=", conn_ret, ")"); class Connect_failed { }; throw Connect_failed(); } socket_pair.client_sd = Genode::ep_sd_registry().try_associate(socket_pair.client_sd, id); /* * Wipe Unix domain socket from the file system. It will live as long as * there exist references to it in the form of file descriptors. */ lx_unlink(addr.sun_path); return socket_pair; } #endif /* _CORE__INCLUDE__SERVER_SOCKET_PAIR_H_ */