12a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Copyright 2013 The Chromium Authors. All rights reserved. 22a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 32a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// found in the LICENSE file. 42a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 52a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "ipc/unix_domain_socket_util.h" 62a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 72a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include <errno.h> 82a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include <fcntl.h> 92a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include <sys/socket.h> 102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include <sys/stat.h> 112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include <sys/un.h> 122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include <unistd.h> 132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/files/file_path.h" 151320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "base/files/file_util.h" 16a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "base/files/scoped_file.h" 172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/logging.h" 182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/posix/eintr_wrapper.h" 192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace IPC { 212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Verify that kMaxSocketNameLength is a decent size. 232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)COMPILE_ASSERT(sizeof(((sockaddr_un*)0)->sun_path) >= kMaxSocketNameLength, 242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) BAD_SUN_PATH_LENGTH); 252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace { 272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Returns fd (>= 0) on success, -1 on failure. If successful, fills in 292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// |unix_addr| with the appropriate data for the socket, and sets 302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// |unix_addr_len| to the length of the data therein. 312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)int MakeUnixAddrForPath(const std::string& socket_name, 322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) struct sockaddr_un* unix_addr, 332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) size_t* unix_addr_len) { 342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK(unix_addr); 352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK(unix_addr_len); 362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (socket_name.length() == 0) { 382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) LOG(ERROR) << "Empty socket name provided for unix socket address."; 392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return -1; 402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // We reject socket_name.length() == kMaxSocketNameLength to make room for 422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // the NUL terminator at the end of the string. 432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (socket_name.length() >= kMaxSocketNameLength) { 442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) LOG(ERROR) << "Socket name too long: " << socket_name; 452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return -1; 462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Create socket. 49a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) base::ScopedFD fd(socket(AF_UNIX, SOCK_STREAM, 0)); 50a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) if (!fd.is_valid()) { 512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) PLOG(ERROR) << "socket"; 522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return -1; 532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Make socket non-blocking 56a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) if (HANDLE_EINTR(fcntl(fd.get(), F_SETFL, O_NONBLOCK)) < 0) { 572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) PLOG(ERROR) << "fcntl(O_NONBLOCK)"; 582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return -1; 592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Create unix_addr structure. 622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) memset(unix_addr, 0, sizeof(struct sockaddr_un)); 632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) unix_addr->sun_family = AF_UNIX; 642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) strncpy(unix_addr->sun_path, socket_name.c_str(), kMaxSocketNameLength); 652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) *unix_addr_len = 662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) offsetof(struct sockaddr_un, sun_path) + socket_name.length(); 67a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) return fd.release(); 682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} // namespace 712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool CreateServerUnixDomainSocket(const base::FilePath& socket_path, 732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int* server_listen_fd) { 742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK(server_listen_fd); 752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) std::string socket_name = socket_path.value(); 772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::FilePath socket_dir = socket_path.DirName(); 782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) struct sockaddr_un unix_addr; 802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) size_t unix_addr_len; 81a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) base::ScopedFD fd( 82a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) MakeUnixAddrForPath(socket_name, &unix_addr, &unix_addr_len)); 83a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) if (!fd.is_valid()) 842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return false; 852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Make sure the path we need exists. 87a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) if (!base::CreateDirectory(socket_dir)) { 882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) LOG(ERROR) << "Couldn't create directory: " << socket_dir.value(); 892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return false; 902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Delete any old FS instances. 932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (unlink(socket_name.c_str()) < 0 && errno != ENOENT) { 942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) PLOG(ERROR) << "unlink " << socket_name; 952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return false; 962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Bind the socket. 99a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) if (bind(fd.get(), reinterpret_cast<const sockaddr*>(&unix_addr), 1002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) unix_addr_len) < 0) { 1012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) PLOG(ERROR) << "bind " << socket_path.value(); 1022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return false; 1032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 1042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Start listening on the socket. 106a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) if (listen(fd.get(), SOMAXCONN) < 0) { 1072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) PLOG(ERROR) << "listen " << socket_path.value(); 1082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) unlink(socket_name.c_str()); 1092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return false; 1102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 1112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 112a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) *server_listen_fd = fd.release(); 1132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return true; 1142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 1152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool CreateClientUnixDomainSocket(const base::FilePath& socket_path, 1172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int* client_socket) { 1182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK(client_socket); 1192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) std::string socket_name = socket_path.value(); 1212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::FilePath socket_dir = socket_path.DirName(); 1222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) struct sockaddr_un unix_addr; 1242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) size_t unix_addr_len; 125a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) base::ScopedFD fd( 126a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) MakeUnixAddrForPath(socket_name, &unix_addr, &unix_addr_len)); 127a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) if (!fd.is_valid()) 1282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return false; 1292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 130a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) if (HANDLE_EINTR(connect(fd.get(), reinterpret_cast<sockaddr*>(&unix_addr), 1312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) unix_addr_len)) < 0) { 1322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) PLOG(ERROR) << "connect " << socket_path.value(); 1332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return false; 1342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 1352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 136a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) *client_socket = fd.release(); 1372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return true; 1382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 1392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool GetPeerEuid(int fd, uid_t* peer_euid) { 1412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK(peer_euid); 1422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#if defined(OS_MACOSX) || defined(OS_OPENBSD) || defined(OS_FREEBSD) 1432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) uid_t socket_euid; 1442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) gid_t socket_gid; 1452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (getpeereid(fd, &socket_euid, &socket_gid) < 0) { 1462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) PLOG(ERROR) << "getpeereid " << fd; 1472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return false; 1482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 1492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) *peer_euid = socket_euid; 1502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return true; 1512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#else 1522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) struct ucred cred; 1532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) socklen_t cred_len = sizeof(cred); 1542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (getsockopt(fd, SOL_SOCKET, SO_PEERCRED, &cred, &cred_len) < 0) { 1552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) PLOG(ERROR) << "getsockopt " << fd; 1562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return false; 1572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 1582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (static_cast<unsigned>(cred_len) < sizeof(cred)) { 1592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) NOTREACHED() << "Truncated ucred from SO_PEERCRED?"; 1602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return false; 1612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 1622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) *peer_euid = cred.uid; 1632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return true; 1642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#endif 1652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 1662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool IsPeerAuthorized(int peer_fd) { 1682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) uid_t peer_euid; 1692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!GetPeerEuid(peer_fd, &peer_euid)) 1702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return false; 1712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (peer_euid != geteuid()) { 1722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DLOG(ERROR) << "Client euid is not authorised"; 1732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return false; 1742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 1752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return true; 1762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 1772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool IsRecoverableError(int err) { 1792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return errno == ECONNABORTED || errno == EMFILE || errno == ENFILE || 1802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) errno == ENOMEM || errno == ENOBUFS; 1812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 1822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool ServerAcceptConnection(int server_listen_fd, int* server_socket) { 1842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK(server_socket); 1852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) *server_socket = -1; 1862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 187a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) base::ScopedFD accept_fd(HANDLE_EINTR(accept(server_listen_fd, NULL, 0))); 188a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) if (!accept_fd.is_valid()) 1892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return IsRecoverableError(errno); 190a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) if (HANDLE_EINTR(fcntl(accept_fd.get(), F_SETFL, O_NONBLOCK)) < 0) { 191a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) PLOG(ERROR) << "fcntl(O_NONBLOCK) " << accept_fd.get(); 1922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // It's safe to keep listening on |server_listen_fd| even if the attempt to 1932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // set O_NONBLOCK failed on the client fd. 1942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return true; 1952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 1962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 197a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) *server_socket = accept_fd.release(); 1982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return true; 1992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 2002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} // namespace IPC 202