From 9977a07353f5c7f84c14653df85fd18a17b824d1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?P=C5=99emysl=20Janouch?= Date: Sun, 10 Aug 2014 02:53:36 +0200 Subject: [PATCH] kike: allow listening on multiple ports --- kike.c | 63 ++++++++++++++++++++++++++++++++++++---------------------- 1 file changed, 39 insertions(+), 24 deletions(-) diff --git a/kike.c b/kike.c index 32be85c..bd30529 100644 --- a/kike.c +++ b/kike.c @@ -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;