Skip to content

Commit

Permalink
Cleanup how listening sockets are created/passed down from systemd
Browse files Browse the repository at this point in the history
  • Loading branch information
lpereira committed Apr 14, 2024
1 parent 7985267 commit b9bd2b1
Showing 1 changed file with 42 additions and 46 deletions.
88 changes: 42 additions & 46 deletions src/lib/lwan-socket.c
Original file line number Diff line number Diff line change
Expand Up @@ -170,18 +170,6 @@ sa_family_t lwan_socket_parse_address(char *listener, char **node, char **port)
return parse_listener_ipv4(listener, node, port);
}

static sa_family_t parse_listener(char *listener, char **node, char **port)
{
if (streq(listener, "systemd")) {
lwan_status_critical(
"Listener configured to use systemd socket activation, "
"but started outside systemd.");
return AF_MAX;
}

return lwan_socket_parse_address(listener, node, port);
}

static int listen_addrinfo(int fd,
const struct addrinfo *addr,
bool print_listening_msg,
Expand Down Expand Up @@ -232,9 +220,7 @@ static int bind_and_listen_addrinfos(const struct addrinfo *addrs,

/* Try each address until we bind one successfully. */
for (addr = addrs; addr; addr = addr->ai_next) {
int fd = socket(addr->ai_family,
addr->ai_socktype,
addr->ai_protocol);
int fd = socket(addr->ai_family, addr->ai_socktype, addr->ai_protocol);
if (fd < 0)
continue;

Expand All @@ -254,14 +240,38 @@ static int bind_and_listen_addrinfos(const struct addrinfo *addrs,
lwan_status_critical("Could not bind socket");
}

static int set_socket_options(const struct lwan *l, int fd)
{
SET_SOCKET_OPTION(SOL_SOCKET, SO_LINGER,
(&(struct linger){.l_onoff = 1, .l_linger = 1}));

#ifdef __linux__

#ifndef TCP_FASTOPEN
#define TCP_FASTOPEN 23
#endif

SET_SOCKET_OPTION_MAY_FAIL(SOL_SOCKET, SO_REUSEADDR, (int[]){1});
SET_SOCKET_OPTION_MAY_FAIL(SOL_TCP, TCP_FASTOPEN, (int[]){5});
SET_SOCKET_OPTION_MAY_FAIL(SOL_TCP, TCP_QUICKACK, (int[]){0});
SET_SOCKET_OPTION_MAY_FAIL(SOL_TCP, TCP_DEFER_ACCEPT,
(int[]){(int)l->config.keep_alive_timeout});

if (is_reno_supported())
setsockopt(fd, IPPROTO_TCP, TCP_CONGESTION, "reno", 4);
#endif

return fd;
}

static int setup_socket_normally(const struct lwan *l,
bool print_listening_msg,
bool is_https,
const char *listener_from_config)
{
char *node, *port;
char *listener = strdupa(listener_from_config);
sa_family_t family = parse_listener(listener, &node, &port);
sa_family_t family = lwan_socket_parse_address(listener, &node, &port);

if (family == AF_MAX) {
lwan_status_critical("Could not parse listener: %s",
Expand All @@ -279,31 +289,7 @@ static int setup_socket_normally(const struct lwan *l,

int fd = bind_and_listen_addrinfos(addrs, print_listening_msg, is_https);
freeaddrinfo(addrs);
return fd;
}

static int set_socket_options(const struct lwan *l, int fd)
{
SET_SOCKET_OPTION(SOL_SOCKET, SO_LINGER,
(&(struct linger){.l_onoff = 1, .l_linger = 1}));

#ifdef __linux__

#ifndef TCP_FASTOPEN
#define TCP_FASTOPEN 23
#endif

SET_SOCKET_OPTION_MAY_FAIL(SOL_SOCKET, SO_REUSEADDR, (int[]){1});
SET_SOCKET_OPTION_MAY_FAIL(SOL_TCP, TCP_FASTOPEN, (int[]){5});
SET_SOCKET_OPTION_MAY_FAIL(SOL_TCP, TCP_QUICKACK, (int[]){0});
SET_SOCKET_OPTION_MAY_FAIL(SOL_TCP, TCP_DEFER_ACCEPT,
(int[]){(int)l->config.keep_alive_timeout});

if (is_reno_supported())
setsockopt(fd, IPPROTO_TCP, TCP_CONGESTION, "reno", 4);
#endif

return fd;
return set_socket_options(l, fd);
}

static int from_systemd_socket(const struct lwan *l, int fd)
Expand All @@ -320,22 +306,28 @@ int lwan_create_listen_socket(const struct lwan *l,
bool print_listening_msg,
bool is_https)
{
const char *listener = is_https ? l->config.tls_listener
: l->config.listener;
const char *listener =
is_https ? l->config.tls_listener : l->config.listener;

if (!strncmp(listener, "systemd:", sizeof("systemd:") - 1)) {
char **names = NULL;
int n = sd_listen_fds_with_names(false, &names);
int fd = -1;

listener += sizeof("systemd:") - 1;

if (n < 0) {
errno = -n;
lwan_status_perror(
"Could not parse socket activation data from systemd");
return n;
}

listener += sizeof("systemd:") - 1;
if (n == 0) {
lwan_status_critical("Not invoked from systemd "
"(expecting socket name %s)",
listener);
}

for (int i = 0; i < n; i++) {
if (!strcmp(names[i], listener)) {
Expand Down Expand Up @@ -363,6 +355,11 @@ int lwan_create_listen_socket(const struct lwan *l,
return n;
}

if (n == 0) {
lwan_status_critical(
"Not invoked from systemd (expecting 1 socket)");
}

if (n != 1) {
lwan_status_critical(
"%d listeners passed from systemd. Must specify listeners with "
Expand All @@ -373,8 +370,7 @@ int lwan_create_listen_socket(const struct lwan *l,
return from_systemd_socket(l, SD_LISTEN_FDS_START);
}

int fd = setup_socket_normally(l, print_listening_msg, is_https, listener);
return set_socket_options(l, fd);
return setup_socket_normally(l, print_listening_msg, is_https, listener);
}

#undef SET_SOCKET_OPTION
Expand Down

0 comments on commit b9bd2b1

Please sign in to comment.