Commit 84e03763 authored by Max Kellermann's avatar Max Kellermann

output/httpd: use the new server_socket library

parent 18e3d0b5
......@@ -998,6 +998,7 @@ if HAVE_LIBSAMPLERATE
test_run_convert_SOURCES += src/pcm_resample_libsamplerate.c
endif
test_run_output_CFLAGS = $(AM_CFLAGS) $(MPD_CFLAGS)
test_run_output_CPPFLAGS = $(AM_CPPFLAGS) \
$(ENCODER_CFLAGS) \
$(OUTPUT_CFLAGS)
......@@ -1033,6 +1034,7 @@ test_run_output_SOURCES = test/run_output.c \
src/replay_gain_info.c \
src/replay_gain_config.c \
src/fd_util.c \
src/server_socket.c \
$(OUTPUT_SRC)
test_read_mixer_CPPFLAGS = $(AM_CPPFLAGS) \
......
......@@ -29,12 +29,6 @@
#include <glib.h>
#ifdef WIN32
#include <winsock2.h>
#include <ws2tcpip.h>
#else
#include <sys/socket.h>
#endif
#include <stdbool.h>
struct httpd_client;
......@@ -65,16 +59,6 @@ struct httpd_output {
const char *content_type;
/**
* The configured address of the listener socket.
*/
struct sockaddr_storage address;
/**
* The size of #address.
*/
socklen_t address_size;
/**
* This mutex protects the listener socket and the client
* list.
*/
......@@ -89,12 +73,7 @@ struct httpd_output {
/**
* The listener socket.
*/
int fd;
/**
* A GLib main loop source id for the listener socket.
*/
guint source_id;
struct server_socket *server_socket;
/**
* The header page, which is sent to every client on connect.
......
......@@ -27,17 +27,11 @@
#include "page.h"
#include "icy_server.h"
#include "fd_util.h"
#include "server_socket.h"
#include <assert.h>
#include <sys/types.h>
#ifdef WIN32
#include <winsock2.h>
#include <ws2tcpip.h>
#else
#include <netinet/in.h>
#include <netdb.h>
#endif
#include <unistd.h>
#include <errno.h>
......@@ -57,37 +51,20 @@ httpd_output_quark(void)
return g_quark_from_static_string("httpd_output");
}
static gboolean
httpd_listen_in_event(G_GNUC_UNUSED GIOChannel *source,
G_GNUC_UNUSED GIOCondition condition,
gpointer data);
static void
httpd_listen_in_event(int fd, const struct sockaddr *address,
size_t address_length, int uid, void *ctx);
static bool
httpd_output_bind(struct httpd_output *httpd, GError **error_r)
{
GIOChannel *channel;
httpd->open = false;
/* create and set up listener socket */
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)
return false;
g_mutex_lock(httpd->mutex);
channel = g_io_channel_unix_new(httpd->fd);
httpd->source_id = g_io_add_watch(channel, G_IO_IN,
httpd_listen_in_event, httpd);
g_io_channel_unref(channel);
bool success = server_socket_open(httpd->server_socket, error_r);
g_mutex_unlock(httpd->mutex);
return true;
return success;
}
static void
......@@ -96,50 +73,10 @@ httpd_output_unbind(struct httpd_output *httpd)
assert(!httpd->open);
g_mutex_lock(httpd->mutex);
g_source_remove(httpd->source_id);
close(httpd->fd);
server_socket_close(httpd->server_socket);
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,
......@@ -171,16 +108,17 @@ httpd_output_init(G_GNUC_UNUSED const struct audio_format *audio_format,
httpd->clients_max = config_get_block_unsigned(param,"max_clients", 0);
/* set up bind_to_address */
httpd->server_socket = server_socket_new(httpd_listen_in_event, httpd);
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)
config_get_block_string(param, "bind_to_address", NULL);
bool success = bind_to_address != NULL &&
strcmp(bind_to_address, "any") != 0
? server_socket_add_host(httpd->server_socket, bind_to_address,
port, error)
: server_socket_add_port(httpd->server_socket, port, error);
if (!success)
return NULL;
/* initialize metadata */
......@@ -212,6 +150,7 @@ httpd_output_finish(void *data)
page_unref(httpd->metadata);
encoder_finish(httpd->encoder);
server_socket_free(httpd->server_socket);
g_mutex_free(httpd->mutex);
g_free(httpd);
}
......@@ -235,26 +174,18 @@ httpd_client_add(struct httpd_output *httpd, int fd)
httpd_client_send_metadata(client, httpd->metadata);
}
static gboolean
httpd_listen_in_event(G_GNUC_UNUSED GIOChannel *source,
G_GNUC_UNUSED GIOCondition condition,
gpointer data)
static void
httpd_listen_in_event(int fd, const struct sockaddr *address,
size_t address_length, G_GNUC_UNUSED int uid, void *ctx)
{
struct httpd_output *httpd = data;
int fd;
struct sockaddr_storage sa;
size_t sa_length = sizeof(sa);
g_mutex_lock(httpd->mutex);
struct httpd_output *httpd = ctx;
/* the listener socket has become readable - a client has
connected */
fd = accept_cloexec_nonblock(httpd->fd, (struct sockaddr*)&sa,
&sa_length);
#ifdef HAVE_LIBWRAP
if (sa.ss_family != AF_UNIX) {
char *hostaddr = sockaddr_to_string((const struct sockaddr *)&sa, sa_length, NULL);
if (address->sa_family != AF_UNIX) {
char *hostaddr = sockaddr_to_string(address, address_length, NULL);
const char *progname = g_get_prgname();
struct request_info req;
......@@ -269,12 +200,18 @@ httpd_listen_in_event(G_GNUC_UNUSED GIOChannel *source,
g_free(hostaddr);
close(fd);
g_mutex_unlock(httpd->mutex);
return true;
return;
}
g_free(hostaddr);
}
#else
(void)address;
(void)address_length;
#endif /* HAVE_WRAP */
g_mutex_lock(httpd->mutex);
if (fd >= 0) {
/* can we allow additional client */
if (httpd->open &&
......@@ -288,8 +225,6 @@ httpd_listen_in_event(G_GNUC_UNUSED GIOChannel *source,
}
g_mutex_unlock(httpd->mutex);
return true;
}
/**
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment