kike: preparation for multiple listening sockets
It should be only a matter of modifying irc_setup_listen_fds() now.
This commit is contained in:
parent
e3010f2d6d
commit
a7ba1eb15f
118
src/kike.c
118
src/kike.c
@ -425,7 +425,9 @@ channel_get_mode (struct channel *self, bool disclose_secrets)
|
||||
|
||||
struct server_context
|
||||
{
|
||||
int listen_fd; ///< Listening socket FD
|
||||
int listen_fds[1]; ///< Listening socket FD's
|
||||
size_t n_listen_fds; ///< Number of listening sockets
|
||||
|
||||
struct client *clients; ///< Clients
|
||||
SSL_CTX *ssl_ctx; ///< SSL context
|
||||
unsigned n_clients; ///< Current number of connections
|
||||
@ -450,7 +452,7 @@ struct server_context
|
||||
static void
|
||||
server_context_init (struct server_context *self)
|
||||
{
|
||||
self->listen_fd = -1;
|
||||
self->n_listen_fds = 0;
|
||||
self->clients = NULL;
|
||||
self->n_clients = 0;
|
||||
|
||||
@ -485,8 +487,8 @@ server_context_free (struct server_context *self)
|
||||
{
|
||||
str_map_free (&self->config);
|
||||
|
||||
if (self->listen_fd != -1)
|
||||
xclose (self->listen_fd);
|
||||
for (size_t i = 0; i < self->n_listen_fds; i++)
|
||||
xclose (self->listen_fds[i]);
|
||||
if (self->ssl_ctx)
|
||||
SSL_CTX_free (self->ssl_ctx);
|
||||
|
||||
@ -763,12 +765,14 @@ irc_initiate_quit (struct server_context *ctx)
|
||||
if (!iter->closing_link)
|
||||
irc_close_link (iter, "Shutting down");
|
||||
|
||||
ssize_t i = poller_find_by_fd (&ctx->poller, ctx->listen_fd);
|
||||
if (soft_assert (i != -1))
|
||||
poller_remove_at_index (&ctx->poller, i);
|
||||
if (ctx->listen_fd != -1)
|
||||
xclose (ctx->listen_fd);
|
||||
ctx->listen_fd = -1;
|
||||
for (size_t i = 0; i < ctx->n_listen_fds; i++)
|
||||
{
|
||||
ssize_t index = poller_find_by_fd (&ctx->poller, ctx->listen_fds[i]);
|
||||
if (soft_assert (index != -1))
|
||||
poller_remove_at_index (&ctx->poller, index);
|
||||
xclose (ctx->listen_fds[i]);
|
||||
}
|
||||
ctx->n_listen_fds = 0;
|
||||
|
||||
ctx->quitting = true;
|
||||
irc_try_finish_quit (ctx);
|
||||
@ -2501,7 +2505,7 @@ on_irc_client_available (const struct pollfd *pfd, void *user_data)
|
||||
struct sockaddr_storage peer;
|
||||
socklen_t peer_len = sizeof peer;
|
||||
|
||||
int fd = accept (ctx->listen_fd, (struct sockaddr *) &peer, &peer_len);
|
||||
int fd = accept (pfd->fd, (struct sockaddr *) &peer, &peer_len);
|
||||
if (fd == -1)
|
||||
{
|
||||
if (errno == EAGAIN)
|
||||
@ -2774,8 +2778,47 @@ irc_initialize_server_name (struct server_context *ctx, struct error **e)
|
||||
return true;
|
||||
}
|
||||
|
||||
static int
|
||||
irc_listen (struct addrinfo *gai_iter)
|
||||
{
|
||||
int fd = socket (gai_iter->ai_family,
|
||||
gai_iter->ai_socktype, gai_iter->ai_protocol);
|
||||
if (fd == -1)
|
||||
return -1;
|
||||
set_cloexec (fd);
|
||||
|
||||
int yes = 1;
|
||||
soft_assert (setsockopt (fd, SOL_SOCKET, SO_KEEPALIVE,
|
||||
&yes, sizeof yes) != -1);
|
||||
soft_assert (setsockopt (fd, SOL_SOCKET, SO_REUSEADDR,
|
||||
&yes, sizeof yes) != -1);
|
||||
|
||||
char real_host[NI_MAXHOST], real_port[NI_MAXSERV];
|
||||
real_host[0] = real_port[0] = '\0';
|
||||
int err = getnameinfo (gai_iter->ai_addr, gai_iter->ai_addrlen,
|
||||
real_host, sizeof real_host, real_port, sizeof real_port,
|
||||
NI_NUMERICHOST | NI_NUMERICSERV);
|
||||
if (err)
|
||||
print_debug ("%s: %s", "getnameinfo", gai_strerror (err));
|
||||
|
||||
if (bind (fd, gai_iter->ai_addr, gai_iter->ai_addrlen))
|
||||
print_error ("bind to %s:%s failed: %s",
|
||||
real_host, real_port, strerror (errno));
|
||||
else if (listen (fd, 16 /* arbitrary number */))
|
||||
print_error ("listen at %s:%s failed: %s",
|
||||
real_host, real_port, strerror (errno));
|
||||
else
|
||||
{
|
||||
print_status ("listening at %s:%s", real_host, real_port);
|
||||
return fd;
|
||||
}
|
||||
|
||||
xclose (fd);
|
||||
return -1;
|
||||
}
|
||||
|
||||
static bool
|
||||
irc_listen (struct server_context *ctx, struct error **e)
|
||||
irc_setup_listen_fds (struct server_context *ctx, struct error **e)
|
||||
{
|
||||
const char *bind_host = str_map_find (&ctx->config, "bind_host");
|
||||
const char *bind_port = str_map_find (&ctx->config, "bind_port");
|
||||
@ -2795,56 +2838,27 @@ irc_listen (struct server_context *ctx, struct error **e)
|
||||
return false;
|
||||
}
|
||||
|
||||
int sockfd;
|
||||
char real_host[NI_MAXHOST], real_port[NI_MAXSERV];
|
||||
|
||||
int fd;
|
||||
for (gai_iter = gai_result; gai_iter; gai_iter = gai_iter->ai_next)
|
||||
{
|
||||
sockfd = socket (gai_iter->ai_family,
|
||||
gai_iter->ai_socktype, gai_iter->ai_protocol);
|
||||
if (sockfd == -1)
|
||||
continue;
|
||||
set_cloexec (sockfd);
|
||||
|
||||
int yes = 1;
|
||||
soft_assert (setsockopt (sockfd, SOL_SOCKET, SO_KEEPALIVE,
|
||||
&yes, sizeof yes) != -1);
|
||||
soft_assert (setsockopt (sockfd, SOL_SOCKET, SO_REUSEADDR,
|
||||
&yes, sizeof yes) != -1);
|
||||
|
||||
real_host[0] = real_port[0] = '\0';
|
||||
err = getnameinfo (gai_iter->ai_addr, gai_iter->ai_addrlen,
|
||||
real_host, sizeof real_host, real_port, sizeof real_port,
|
||||
NI_NUMERICHOST | NI_NUMERICSERV);
|
||||
if (err)
|
||||
print_debug ("%s: %s", "getnameinfo", gai_strerror (err));
|
||||
|
||||
if (bind (sockfd, gai_iter->ai_addr, gai_iter->ai_addrlen))
|
||||
print_error ("bind to %s:%s failed: %s",
|
||||
real_host, real_port, strerror (errno));
|
||||
else if (listen (sockfd, 16 /* arbitrary number */))
|
||||
print_error ("listen at %s:%s failed: %s",
|
||||
real_host, real_port, strerror (errno));
|
||||
else
|
||||
if (ctx->n_listen_fds >= N_ELEMENTS (ctx->listen_fds))
|
||||
break;
|
||||
if ((fd = irc_listen (gai_iter)) == -1)
|
||||
continue;
|
||||
|
||||
xclose (sockfd);
|
||||
ctx->listen_fds[ctx->n_listen_fds++] = fd;
|
||||
set_blocking (fd, false);
|
||||
poller_set (&ctx->poller, fd, POLLIN,
|
||||
(poller_dispatcher_func) on_irc_client_available, ctx);
|
||||
break;
|
||||
}
|
||||
|
||||
freeaddrinfo (gai_result);
|
||||
|
||||
if (!gai_iter)
|
||||
if (!ctx->n_listen_fds)
|
||||
{
|
||||
error_set (e, "network setup failed");
|
||||
return false;
|
||||
}
|
||||
|
||||
set_blocking (sockfd, false);
|
||||
ctx->listen_fd = sockfd;
|
||||
poller_set (&ctx->poller, ctx->listen_fd, POLLIN,
|
||||
(poller_dispatcher_func) on_irc_client_available, ctx);
|
||||
|
||||
print_status ("listening at %s:%s", real_host, real_port);
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -2979,7 +2993,7 @@ main (int argc, char *argv[])
|
||||
|| !irc_initialize_motd (&ctx, &e)
|
||||
|| !irc_initialize_catalog (&ctx, &e)
|
||||
|| !irc_parse_config (&ctx, &e)
|
||||
|| !irc_listen (&ctx, &e))
|
||||
|| !irc_setup_listen_fds (&ctx, &e))
|
||||
{
|
||||
print_error ("%s", e->message);
|
||||
error_free (e);
|
||||
|
Loading…
Reference in New Issue
Block a user