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
1 changed files with 39 additions and 24 deletions

63
kike.c
View File

@ -508,11 +508,11 @@ channel_user_count (const struct channel *chan)
struct server_context 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 size_t n_listen_fds; ///< Number of listening sockets
struct client *clients; ///< Clients
SSL_CTX *ssl_ctx; ///< SSL context SSL_CTX *ssl_ctx; ///< SSL context
struct client *clients; ///< Clients
unsigned n_clients; ///< Current number of connections unsigned n_clients; ///< Current number of connections
struct str_map users; ///< Maps nicknames to clients struct str_map users; ///< Maps nicknames to clients
@ -535,6 +535,7 @@ struct server_context
static void static void
server_context_init (struct server_context *self) server_context_init (struct server_context *self)
{ {
self->listen_fds = NULL;
self->n_listen_fds = 0; self->n_listen_fds = 0;
self->clients = NULL; self->clients = NULL;
self->n_clients = 0; 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++) for (size_t i = 0; i < self->n_listen_fds; i++)
xclose (self->listen_fds[i]); xclose (self->listen_fds[i]);
free (self->listen_fds);
if (self->ssl_ctx) if (self->ssl_ctx)
SSL_CTX_free (self->ssl_ctx); SSL_CTX_free (self->ssl_ctx);
struct client *link, *tmp; struct client *link, *tmp;
for (link = self->clients; link; 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", print_error ("bind to %s:%s failed: %s",
real_host, real_port, strerror (errno)); real_host, real_port, strerror (errno));
else if (listen (fd, 16 /* arbitrary number */)) 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)); real_host, real_port, strerror (errno));
else else
{ {
print_status ("listening at %s:%s", real_host, real_port); print_status ("listening on %s:%s", real_host, real_port);
return fd; return fd;
} }
@ -2948,32 +2950,22 @@ irc_listen (struct addrinfo *gai_iter)
return -1; return -1;
} }
static bool static void
irc_setup_listen_fds (struct server_context *ctx, struct error **e) 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"); struct addrinfo *gai_result, *gai_iter;
const char *bind_port = str_map_find (&ctx->config, "bind_port"); int err = getaddrinfo (host, port, gai_hints, &gai_result);
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);
if (err) if (err)
{ {
error_set (e, "%s: %s: %s", print_error ("bind to %s:%s failed: %s: %s",
"network setup failed", "getaddrinfo", gai_strerror (err)); host, port, "getaddrinfo", gai_strerror (err));
return false; return;
} }
int fd; int fd;
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)
{ {
if (ctx->n_listen_fds >= N_ELEMENTS (ctx->listen_fds))
break;
if ((fd = irc_listen (gai_iter)) == -1) if ((fd = irc_listen (gai_iter)) == -1)
continue; continue;
@ -2984,10 +2976,33 @@ irc_setup_listen_fds (struct server_context *ctx, struct error **e)
break; break;
} }
freeaddrinfo (gai_result); 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) 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 false;
} }
return true; return true;