diff options
author | sin-ack <sin-ack@users.noreply.github.com> | 2021-04-14 21:35:49 +0000 |
---|---|---|
committer | Andreas Kling <kling@serenityos.org> | 2021-04-15 21:04:49 +0200 |
commit | 5b95850e28ce25c7a7af6138aaff7da3f1829f75 (patch) | |
tree | 0b5fb9adfdb1658c6c75cbfc32cb3e135a0c3ff2 /Userland/Libraries/LibCore/LocalServer.cpp | |
parent | 4316e817dbe4147d714b9e5914452e9629358cb7 (diff) | |
download | serenity-5b95850e28ce25c7a7af6138aaff7da3f1829f75.zip |
SystemServer+LibCore: Allow service to request multiple sockets
SystemServer only allowed a single socket to be created for a service
before this. Now, SystemServer will allow any amount of sockets. The
sockets can be defined like so:
[SomeService]
Socket=/tmp/portal/socket1,/tmp/portal/socket2,/tmp/portal/socket3
SocketPermissions=660,600
The last item in SocketPermissions is applied to the remainder of the
sockets in the Socket= line, so multiple sockets can have the same
permissions without having to repeat them.
Defining multiple sockets is not allowed for socket-activated services
at the moment, and wouldn't make much sense anyway.
This patch also makes socket takeovers more robust by removing the
assumption that the socket will always be passed in fd 3. Now, the
SOCKET_TAKEOVER environment variable carries information about which
endpoint corresponds to which socket, like so:
SOCKET_TAKEOVER=/tmp/portal/socket1:3 /tmp/portal/socket2:4
and LocalServer/LocalService will parse this automatically and select
the correct one. The old behavior of getting the default socket is
preserved so long as the service only requests a single socket in
SystemServer.ini.
Diffstat (limited to 'Userland/Libraries/LibCore/LocalServer.cpp')
-rw-r--r-- | Userland/Libraries/LibCore/LocalServer.cpp | 31 |
1 files changed, 21 insertions, 10 deletions
diff --git a/Userland/Libraries/LibCore/LocalServer.cpp b/Userland/Libraries/LibCore/LocalServer.cpp index 46d7d3ddd2..14c17fbb0a 100644 --- a/Userland/Libraries/LibCore/LocalServer.cpp +++ b/Userland/Libraries/LibCore/LocalServer.cpp @@ -50,28 +50,39 @@ LocalServer::~LocalServer() ::close(m_fd); } -bool LocalServer::take_over_from_system_server() +bool LocalServer::take_over_from_system_server(String const& socket_path) { if (m_listening) return false; - constexpr auto socket_takeover = "SOCKET_TAKEOVER"; + if (!LocalSocket::s_overtaken_sockets_parsed) + LocalSocket::parse_sockets_from_system_server(); - if (getenv(socket_takeover)) { + int fd = -1; + if (socket_path.is_null()) { + // We want the first (and only) socket. + if (LocalSocket::s_overtaken_sockets.size() == 1) { + fd = LocalSocket::s_overtaken_sockets.begin()->value; + } + } else { + auto it = LocalSocket::s_overtaken_sockets.find(socket_path); + if (it != LocalSocket::s_overtaken_sockets.end()) { + fd = it->value; + } + } + + if (fd >= 0) { // Sanity check: it has to be a socket. struct stat stat; - int rc = fstat(3, &stat); + int rc = fstat(fd, &stat); if (rc == 0 && S_ISSOCK(stat.st_mode)) { - // The SystemServer has passed us the socket as fd 3, - // so use that instead of creating our own. - m_fd = 3; + // The SystemServer has passed us the socket, so use that instead of + // creating our own. + m_fd = fd; // It had to be !CLOEXEC for obvious reasons, but we // don't need it to be !CLOEXEC anymore, so set the // CLOEXEC flag now. fcntl(m_fd, F_SETFD, FD_CLOEXEC); - // We wouldn't want our children to think we're passing - // them a socket either, so unset the env variable. - unsetenv(socket_takeover); m_listening = true; setup_notifier(); |