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
|
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
|
struct client *clients; ///< Clients
|
||||||
SSL_CTX *ssl_ctx; ///< SSL context
|
SSL_CTX *ssl_ctx; ///< SSL context
|
||||||
unsigned n_clients; ///< Current number of connections
|
unsigned n_clients; ///< Current number of connections
|
||||||
|
@ -450,7 +452,7 @@ struct server_context
|
||||||
static void
|
static void
|
||||||
server_context_init (struct server_context *self)
|
server_context_init (struct server_context *self)
|
||||||
{
|
{
|
||||||
self->listen_fd = -1;
|
self->n_listen_fds = 0;
|
||||||
self->clients = NULL;
|
self->clients = NULL;
|
||||||
self->n_clients = 0;
|
self->n_clients = 0;
|
||||||
|
|
||||||
|
@ -485,8 +487,8 @@ server_context_free (struct server_context *self)
|
||||||
{
|
{
|
||||||
str_map_free (&self->config);
|
str_map_free (&self->config);
|
||||||
|
|
||||||
if (self->listen_fd != -1)
|
for (size_t i = 0; i < self->n_listen_fds; i++)
|
||||||
xclose (self->listen_fd);
|
xclose (self->listen_fds[i]);
|
||||||
if (self->ssl_ctx)
|
if (self->ssl_ctx)
|
||||||
SSL_CTX_free (self->ssl_ctx);
|
SSL_CTX_free (self->ssl_ctx);
|
||||||
|
|
||||||
|
@ -763,12 +765,14 @@ irc_initiate_quit (struct server_context *ctx)
|
||||||
if (!iter->closing_link)
|
if (!iter->closing_link)
|
||||||
irc_close_link (iter, "Shutting down");
|
irc_close_link (iter, "Shutting down");
|
||||||
|
|
||||||
ssize_t i = poller_find_by_fd (&ctx->poller, ctx->listen_fd);
|
for (size_t i = 0; i < ctx->n_listen_fds; i++)
|
||||||
if (soft_assert (i != -1))
|
{
|
||||||
poller_remove_at_index (&ctx->poller, i);
|
ssize_t index = poller_find_by_fd (&ctx->poller, ctx->listen_fds[i]);
|
||||||
if (ctx->listen_fd != -1)
|
if (soft_assert (index != -1))
|
||||||
xclose (ctx->listen_fd);
|
poller_remove_at_index (&ctx->poller, index);
|
||||||
ctx->listen_fd = -1;
|
xclose (ctx->listen_fds[i]);
|
||||||
|
}
|
||||||
|
ctx->n_listen_fds = 0;
|
||||||
|
|
||||||
ctx->quitting = true;
|
ctx->quitting = true;
|
||||||
irc_try_finish_quit (ctx);
|
irc_try_finish_quit (ctx);
|
||||||
|
@ -2501,7 +2505,7 @@ on_irc_client_available (const struct pollfd *pfd, void *user_data)
|
||||||
struct sockaddr_storage peer;
|
struct sockaddr_storage peer;
|
||||||
socklen_t peer_len = sizeof 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 (fd == -1)
|
||||||
{
|
{
|
||||||
if (errno == EAGAIN)
|
if (errno == EAGAIN)
|
||||||
|
@ -2774,8 +2778,47 @@ irc_initialize_server_name (struct server_context *ctx, struct error **e)
|
||||||
return true;
|
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
|
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_host = str_map_find (&ctx->config, "bind_host");
|
||||||
const char *bind_port = str_map_find (&ctx->config, "bind_port");
|
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;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
int sockfd;
|
int fd;
|
||||||
char real_host[NI_MAXHOST], real_port[NI_MAXSERV];
|
|
||||||
|
|
||||||
for (gai_iter = gai_result; gai_iter; gai_iter = gai_iter->ai_next)
|
for (gai_iter = gai_result; gai_iter; gai_iter = gai_iter->ai_next)
|
||||||
{
|
{
|
||||||
sockfd = socket (gai_iter->ai_family,
|
if (ctx->n_listen_fds >= N_ELEMENTS (ctx->listen_fds))
|
||||||
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
|
|
||||||
break;
|
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);
|
freeaddrinfo (gai_result);
|
||||||
|
|
||||||
if (!gai_iter)
|
if (!ctx->n_listen_fds)
|
||||||
{
|
{
|
||||||
error_set (e, "network setup failed");
|
error_set (e, "network setup failed");
|
||||||
return false;
|
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;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2979,7 +2993,7 @@ main (int argc, char *argv[])
|
||||||
|| !irc_initialize_motd (&ctx, &e)
|
|| !irc_initialize_motd (&ctx, &e)
|
||||||
|| !irc_initialize_catalog (&ctx, &e)
|
|| !irc_initialize_catalog (&ctx, &e)
|
||||||
|| !irc_parse_config (&ctx, &e)
|
|| !irc_parse_config (&ctx, &e)
|
||||||
|| !irc_listen (&ctx, &e))
|
|| !irc_setup_listen_fds (&ctx, &e))
|
||||||
{
|
{
|
||||||
print_error ("%s", e->message);
|
print_error ("%s", e->message);
|
||||||
error_free (e);
|
error_free (e);
|
||||||
|
|
Loading…
Reference in New Issue