34#include <netinet/in.h>
35#include <netinet/tcp.h>
36#include <sys/socket.h>
44#if defined(__cpp_lib_filesystem) || __has_include(<filesystem>)
53 #include <experimental/filesystem>
55 namespace filesystem = experimental::filesystem;
85 panic(
"Too late to disable all listeners, already have a listener");
99 panic(
"Too late to bind to loopback, already have a listener");
109 type |= SOCK_CLOEXEC;
118#if defined(_GNU_SOURCE) && defined(SOCK_CLOEXEC)
119 return ::accept4(sockfd,
addr, addrlen, SOCK_CLOEXEC);
121 return ::accept(sockfd,
addr, addrlen);
142 struct sockaddr_in sockaddr;
143 socklen_t slen =
sizeof(sockaddr);
145 panic_if(sfd == -1,
"%s: Failed to accept connection: %s",
146 name(), strerror(errno));
155 if (value.size() == 0) {
158 }
else if (value[0] ==
'@') {
161 }
else if (value[0] ==
'P') {
162 std::filesystem::path
p(value.substr(1));
165 }
else if (value[0] ==
'#') {
167 bool ret =
to_number(value.substr(1), port);
173 panic(
"Can't interpret %s as a host socket.", value);
189 int ret = ::setsockopt(sfd, IPPROTO_TCP, TCP_NODELAY, &
i,
sizeof(
i));
190 warn_if(ret < 0,
"ListenSocket(accept): setsockopt() TCP_NODELAY failed!");
204 panic_if(
fd < 0,
"Can't create socket:%s !", strerror(errno));
208 int ret = ::setsockopt(
fd, SOL_SOCKET, SO_REUSEADDR, &
i,
sizeof(
i));
210 "ListenSocket(listen): setsockopt() SO_REUSEADDR failed!");
212 struct sockaddr_in sockaddr;
213 sockaddr.sin_family = PF_INET;
214 sockaddr.sin_addr.s_addr =
216 sockaddr.sin_port = htons(port);
218 std::memset(&sockaddr.sin_zero, 0,
sizeof(sockaddr.sin_zero));
219 ret = ::bind(
fd, (
struct sockaddr *)&sockaddr,
sizeof (sockaddr));
221 panic_if(ret == -1 && errno != EADDRINUSE,
222 "ListenSocket(listen): bind() failed!");
228 "ListenSocket(listen): listen() failed!");
249 ccprintf(std::cerr,
"%s: Listening for connections on %s\n",
263 return std::make_unique<ListenSocketInet>(
name, port);
271 "Length of socket path '%s' is %d, greater than max %d.",
272 original, original.size(), max_len);
283 panic_if(
fd < 0,
"%s: Can't create unix socket:%s !",
284 name(), strerror(errno));
287 sockaddr_un serv_addr;
288 std::memset(&serv_addr, 0,
sizeof(serv_addr));
291 fatal_if(bind(
fd, (
struct sockaddr *)&(serv_addr), addr_size) != 0,
292 "%s: Cannot bind unix socket %s: %s",
name(), *
this,
296 name(), *
this, strerror(errno));
298 ccprintf(std::cerr,
"%s: Listening for connections on %s\n",
305 const std::string &_dir,
const std::string &_fname) :
324 return ::unlink(path.c_str()) == 0;
330 addr.sun_family = AF_UNIX;
332 return sizeof(
addr.sun_path);
340 "%s: server path %s was occupied and will be replaced. Please "
341 "make sure there is no other server using the same path.",
347 fatal_if(
ec,
"Failed to create directory %s",
ec.message());
351 auto cwd = std::filesystem::current_path(
ec);
352 panic_if(
ec,
"Failed to get current working directory %s",
ec.message());
354 fatal_if(
ec,
"Failed to change to directory %s: %s",
359 std::filesystem::current_path(cwd,
ec);
360 panic_if(
ec,
"Failed to change back working directory %s",
ec.message());
366 os <<
"socket \"" <<
dir <<
"/" <<
fname <<
"\"";
373 return std::make_unique<ListenSocketUnixFile>(
name, dir, fname);
380 addr.sun_family = AF_UNIX;
381 addr.sun_path[0] =
'\0';
382 std::memcpy(&
addr.sun_path[1],
path.c_str(),
path.size());
383 return offsetof(sockaddr_un, sun_path) +
path.size() + 1;
387 const std::string &_name,
const std::string &_path) :
396 os <<
"abstract socket \"" <<
path <<
"\"";
403 return std::make_unique<ListenSocketUnixAbstract>(
name, path);
Defines global host-dependent types: Counter, Tick, and (indirectly) {int,uint}{8,...
static bool parseIni(const std::string &value, ListenSocketConfig &retval)
ListenSocketInet(const std::string &_name, int port)
void output(std::ostream &os) const override
size_t prepSockaddrUn(sockaddr_un &addr) const override
ListenSocketUnixAbstract(const std::string &_name, const std::string &_path)
void output(std::ostream &os) const override
size_t prepSockaddrUn(sockaddr_un &addr) const override
void output(std::ostream &os) const override
ListenSocketUnixFile(const std::string &_name, const std::string &_dir, const std::string &_fname)
virtual size_t prepSockaddrUn(sockaddr_un &addr) const =0
void checkPathLength(const std::string &original, size_t max_len)
ListenSocket(const std::string &_name)
static bool bindToLoopback
static bool listeningDisabled
The following variables are only used by socket unit tests: listeningDisabled, anyListening,...
static void loopbackOnly()
static int socketCloexec(int domain, int type, int protocol)
static bool allDisabled()
static int acceptCloexec(int sockfd, struct sockaddr *addr, socklen_t *addrlen)
Interface for things with names.
virtual std::string name() const
std::string resolve(const std::string &name) const
Returns relative file names prepended with name of this directory.
#define panic(...)
This implements a cprintf based panic() function.
#define fatal_if(cond,...)
Conditional fatal macro that checks the supplied condition and only causes a fatal error if the condi...
#define panic_if(cond,...)
Conditional panic macro that checks the supplied condition and only panics if the condition is true a...
#define warn_if(cond,...)
Conditional warning macro that checks the supplied condition and only prints a warning if the conditi...
Copyright (c) 2024 - Pranith Kumar Copyright (c) 2020 Inria All rights reserved.
bool to_number(const std::string &value, Pixel &retval)
ListenSocketConfig listenSocketUnixAbstractConfig(std::string path)
ListenSocketConfig listenSocketInetConfig(int port)
ListenSocketConfig listenSocketUnixFileConfig(std::string dir, std::string fname)
static ListenSocketConfig listenSocketEmptyConfig()
void ccprintf(cp::Print &print)
Overload hash function for BasicBlockRange type.
const std::string & name()