diff options
author | Thomas Jansen <mithi@mithi.net> | 2010-09-25 15:00:43 +0200 |
---|---|---|
committer | Thomas Jansen <mithi@mithi.net> | 2010-09-25 15:00:43 +0200 |
commit | 9af9fd140032138894e4781caabee8a5a96edab8 (patch) | |
tree | e8afa3fcc319b9a8f9b810c32ae398edeee2372f /src/output | |
parent | 0c80bd5fc09fad536424b139331b0f8f43437d1b (diff) | |
download | mpd-9af9fd140032138894e4781caabee8a5a96edab8.tar.gz mpd-9af9fd140032138894e4781caabee8a5a96edab8.tar.xz mpd-9af9fd140032138894e4781caabee8a5a96edab8.zip |
output/httpd: bind_to_address support (including IPv6)
Added support for a new optional configuration setting for the httpd output
named "bind_to_address". Setting it to a specific IP address (v4 or v6) will
cause the httpd output to bind to that address exclusively. Supporting
multiple addresses in parallel is future work.
This implements the feature requests #2998 and #2646.
Diffstat (limited to 'src/output')
-rw-r--r-- | src/output/httpd_output_plugin.c | 64 |
1 files changed, 52 insertions, 12 deletions
diff --git a/src/output/httpd_output_plugin.c b/src/output/httpd_output_plugin.c index bff56bf6b..43b635472 100644 --- a/src/output/httpd_output_plugin.c +++ b/src/output/httpd_output_plugin.c @@ -71,8 +71,8 @@ httpd_output_bind(struct httpd_output *httpd, GError **error_r) /* create and set up listener socket */ - httpd->fd = socket_bind_listen(PF_INET, SOCK_STREAM, 0, - (struct sockaddr *)&httpd->address, + httpd->fd = socket_bind_listen(httpd->address.ss_family, SOCK_STREAM, + 0, (struct sockaddr *)&httpd->address, httpd->address_size, 16, error_r); if (httpd->fd < 0) @@ -103,16 +103,52 @@ httpd_output_unbind(struct httpd_output *httpd) g_mutex_unlock(httpd->mutex); } +static void +httpd_output_parse_bind_to_address(struct httpd_output *httpd, + const char *bind_to_address, + guint port, GError **error) +{ + struct addrinfo hints, *ai; + char service[20]; + int ret; + + memset(&hints, 0, sizeof(hints)); + hints.ai_flags = AI_PASSIVE; +#ifdef AI_ADDRCONFIG + hints.ai_flags |= AI_ADDRCONFIG; +#endif + hints.ai_family = PF_UNSPEC; + hints.ai_socktype = SOCK_STREAM; + hints.ai_protocol = IPPROTO_TCP; + + g_snprintf(service, sizeof(service), "%u", port); + ret = getaddrinfo(bind_to_address, service, &hints, &ai); + if (ret != 0) { + g_set_error(error, httpd_output_quark(), ret, + "Failed to look up host \"%s\": %s", + bind_to_address, gai_strerror(ret)); + return; + } + + assert(ai); + + /* Choose the first address, even if multiple are available. We do + * not support multiple addresses yet. */ + memcpy(&httpd->address, ai->ai_addr, ai->ai_addrlen); + httpd->address_size = ai->ai_addrlen; + + freeaddrinfo(ai); +} + static void * httpd_output_init(G_GNUC_UNUSED const struct audio_format *audio_format, const struct config_param *param, GError **error) { struct httpd_output *httpd = g_new(struct httpd_output, 1); - const char *encoder_name; + const char *encoder_name, *bind_to_address; const struct encoder_plugin *encoder_plugin; guint port; - struct sockaddr_in *sin; /* read configuration */ httpd->name = @@ -134,14 +170,18 @@ httpd_output_init(G_GNUC_UNUSED const struct audio_format *audio_format, httpd->clients_max = config_get_block_unsigned(param,"max_clients", 0); - /* initialize listen address */ - - sin = (struct sockaddr_in *)&httpd->address; - memset(sin, 0, sizeof(sin)); - sin->sin_port = htons(port); - sin->sin_family = AF_INET; - sin->sin_addr.s_addr = INADDR_ANY; - httpd->address_size = sizeof(*sin); + /* set up bind_to_address */ + bind_to_address = + config_get_block_string(param, "bind_to_address", +#ifdef HAVE_IPV6 + "::" +#else + "0.0.0.0" +#endif + ); + httpd_output_parse_bind_to_address(httpd, bind_to_address, port, error); + if (*error) + return NULL; /* initialize metadata */ httpd->metadata = NULL; |