34 #include <netinet/in.h>
35 #include <netinet/tcp.h>
36 #include <sys/socket.h>
37 #include <sys/types.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);