kike: allow listening on multiple ports

This commit is contained in:
Přemysl Eric Janouch 2014-08-10 02:53:36 +02:00
parent b8f002eaf5
commit 9977a07353

63
kike.c
View File

@ -508,11 +508,11 @@ channel_user_count (const struct channel *chan)
struct server_context
{
int listen_fds[1]; ///< Listening socket FD's
int *listen_fds; ///< Listening socket FD's
size_t n_listen_fds; ///< Number of listening sockets
struct client *clients; ///< Clients
SSL_CTX *ssl_ctx; ///< SSL context
struct client *clients; ///< Clients
unsigned n_clients; ///< Current number of connections
struct str_map users; ///< Maps nicknames to clients
@ -535,6 +535,7 @@ struct server_context
static void
server_context_init (struct server_context *self)
{
self->listen_fds = NULL;
self->n_listen_fds = 0;
self->clients = NULL;
self->n_clients = 0;
@ -572,9 +573,10 @@ server_context_free (struct server_context *self)
for (size_t i = 0; i < self->n_listen_fds; i++)
xclose (self->listen_fds[i]);
free (self->listen_fds);
if (self->ssl_ctx)
SSL_CTX_free (self->ssl_ctx);
struct client *link, *tmp;
for (link = self->clients; link; link = tmp)
{
@ -2936,11 +2938,11 @@ irc_listen (struct addrinfo *gai_iter)
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",
print_error ("listen on %s:%s failed: %s",
real_host, real_port, strerror (errno));
else
{
print_status ("listening at %s:%s", real_host, real_port);
print_status ("listening on %s:%s", real_host, real_port);
return fd;
}
@ -2948,32 +2950,22 @@ irc_listen (struct addrinfo *gai_iter)
return -1;
}
static bool
irc_setup_listen_fds (struct server_context *ctx, struct error **e)
static void
irc_listen_resolve (struct server_context *ctx,
const char *host, const char *port, struct addrinfo *gai_hints)
{
const char *bind_host = str_map_find (&ctx->config, "bind_host");
const char *bind_port = str_map_find (&ctx->config, "bind_port");
hard_assert (bind_port != NULL); // We have a default value for this
struct addrinfo gai_hints, *gai_result, *gai_iter;
memset (&gai_hints, 0, sizeof gai_hints);
gai_hints.ai_socktype = SOCK_STREAM;
gai_hints.ai_flags = AI_PASSIVE;
int err = getaddrinfo (bind_host, bind_port, &gai_hints, &gai_result);
struct addrinfo *gai_result, *gai_iter;
int err = getaddrinfo (host, port, gai_hints, &gai_result);
if (err)
{
error_set (e, "%s: %s: %s",
"network setup failed", "getaddrinfo", gai_strerror (err));
return false;
print_error ("bind to %s:%s failed: %s: %s",
host, port, "getaddrinfo", gai_strerror (err));
return;
}
int fd;
for (gai_iter = gai_result; gai_iter; gai_iter = gai_iter->ai_next)
{
if (ctx->n_listen_fds >= N_ELEMENTS (ctx->listen_fds))
break;
if ((fd = irc_listen (gai_iter)) == -1)
continue;
@ -2984,10 +2976,33 @@ irc_setup_listen_fds (struct server_context *ctx, struct error **e)
break;
}
freeaddrinfo (gai_result);
}
static bool
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");
hard_assert (bind_port != NULL); // We have a default value for this
struct addrinfo gai_hints;
memset (&gai_hints, 0, sizeof gai_hints);
gai_hints.ai_socktype = SOCK_STREAM;
gai_hints.ai_flags = AI_PASSIVE;
struct str_vector ports;
str_vector_init (&ports);
split_str_ignore_empty (bind_port, ',', &ports);
ctx->listen_fds = xcalloc (ports.len, sizeof *ctx->listen_fds);
for (size_t i = 0; i < ports.len; i++)
irc_listen_resolve (ctx, bind_host, ports.vector[i], &gai_hints);
str_vector_free (&ports);
if (!ctx->n_listen_fds)
{
error_set (e, "network setup failed");
error_set (e, "%s: %s",
"network setup failed", "no ports to listen on");
return false;
}
return true;