From ad5eb2f8d6f32c69603e658e14d813d71ba5b220 Mon Sep 17 00:00:00 2001 From: Max Kellermann Date: Wed, 30 Jan 2013 12:56:23 +0100 Subject: ServerSocket: expose the class Eliminate the C wrappers. --- src/Listen.cxx | 24 +++--- src/event/ServerSocket.cxx | 162 ++++++++++++++------------------------- src/event/ServerSocket.hxx | 125 ++++++++++++++++++------------ src/output/HttpdInternal.hxx | 3 +- src/output/HttpdOutputPlugin.cxx | 15 ++-- 5 files changed, 155 insertions(+), 174 deletions(-) diff --git a/src/Listen.cxx b/src/Listen.cxx index f1d6e4fe..e56a0ead 100644 --- a/src/Listen.cxx +++ b/src/Listen.cxx @@ -36,7 +36,7 @@ #define DEFAULT_PORT 6600 -static struct server_socket *listen_socket; +static ServerSocket *listen_socket; int listen_port; static void @@ -55,13 +55,11 @@ listen_add_config_param(unsigned int port, assert(param != NULL); if (0 == strcmp(param->value, "any")) { - return server_socket_add_port(listen_socket, port, error_r); + return listen_socket->AddPort(port, error_r); } else if (param->value[0] == '/') { - return server_socket_add_path(listen_socket, param->value, - error_r); + return listen_socket->AddPath(param->value, error_r); } else { - return server_socket_add_host(listen_socket, param->value, - port, error_r); + return listen_socket->AddHost(param->value, port, error_r); } } @@ -79,7 +77,7 @@ listen_systemd_activation(GError **error_r) for (int i = SD_LISTEN_FDS_START, end = SD_LISTEN_FDS_START + n; i != end; ++i) - if (!server_socket_add_fd(listen_socket, i, error_r)) + if (!listen_socket->AddFD(i, error_r)) return false; return true; @@ -100,7 +98,7 @@ listen_global_init(GError **error_r) bool success; GError *error = NULL; - listen_socket = server_socket_new(*main_loop, listen_callback, NULL); + listen_socket = new ServerSocket(*main_loop, listen_callback, nullptr); if (listen_systemd_activation(&error)) return true; @@ -117,6 +115,7 @@ listen_global_init(GError **error_r) do { success = listen_add_config_param(port, param, &error); if (!success) { + delete listen_socket; g_propagate_prefixed_error(error_r, error, "Failed to listen on %s (line %i): ", param->value, param->line); @@ -130,8 +129,9 @@ listen_global_init(GError **error_r) /* no "bind_to_address" configured, bind the configured port on all interfaces */ - success = server_socket_add_port(listen_socket, port, error_r); + success = listen_socket->AddPort(port, error_r); if (!success) { + delete listen_socket; g_propagate_prefixed_error(error_r, error, "Failed to listen on *:%d: ", port); @@ -139,8 +139,10 @@ listen_global_init(GError **error_r) } } - if (!server_socket_open(listen_socket, error_r)) + if (!listen_socket->Open(error_r)) { + delete listen_socket; return false; + } listen_port = port; return true; @@ -152,5 +154,5 @@ void listen_global_finish(void) assert(listen_socket != NULL); - server_socket_free(listen_socket); + delete listen_socket; } diff --git a/src/event/ServerSocket.cxx b/src/event/ServerSocket.cxx index a1e2ee01..ea2f07e3 100644 --- a/src/event/ServerSocket.cxx +++ b/src/event/ServerSocket.cxx @@ -30,8 +30,6 @@ #include "resolver.h" #include "fd_util.h" -#include - #include #include #include @@ -55,8 +53,8 @@ #define DEFAULT_PORT 6600 -struct OneServerSocket final : private SocketMonitor { - const server_socket &parent; +class OneServerSocket final : private SocketMonitor { + const ServerSocket &parent; const unsigned serial; @@ -65,7 +63,8 @@ struct OneServerSocket final : private SocketMonitor { size_t address_length; struct sockaddr *address; - OneServerSocket(EventLoop &_loop, const server_socket &_parent, +public: + OneServerSocket(EventLoop &_loop, const ServerSocket &_parent, unsigned _serial, const struct sockaddr *_address, size_t _address_length) @@ -87,6 +86,16 @@ struct OneServerSocket final : private SocketMonitor { g_free(address); } + unsigned GetSerial() const { + return serial; + } + + void SetPath(const char *_path) { + assert(path == nullptr); + + path = g_strdup(_path); + } + bool Open(GError **error_r); using SocketMonitor::Close; @@ -104,44 +113,12 @@ private: virtual bool OnSocketReady(unsigned flags) override; }; -struct server_socket { - EventLoop &loop; - - server_socket_callback_t callback; - void *callback_ctx; - - std::forward_list sockets; - - unsigned next_serial; - - server_socket(EventLoop &_loop, - server_socket_callback_t _callback, void *_callback_ctx) - :loop(_loop), - callback(_callback), callback_ctx(_callback_ctx), - next_serial(1) {} - - void Close(); -}; - static GQuark server_socket_quark(void) { return g_quark_from_static_string("server_socket"); } -struct server_socket * -server_socket_new(EventLoop &loop, - server_socket_callback_t callback, void *callback_ctx) -{ - return new server_socket(loop, callback, callback_ctx); -} - -void -server_socket_free(struct server_socket *ss) -{ - delete ss; -} - /** * Wraper for sockaddr_to_string() which never fails. */ @@ -236,25 +213,36 @@ OneServerSocket::Open(GError **error_r) return true; } +ServerSocket::ServerSocket(EventLoop &_loop, + server_socket_callback_t _callback, + void *_callback_ctx) + :loop(_loop), + callback(_callback), callback_ctx(_callback_ctx), + next_serial(1) {} + +/* this is just here to allow the OneServerSocket forward + declaration */ +ServerSocket::~ServerSocket() {} + bool -server_socket_open(struct server_socket *ss, GError **error_r) +ServerSocket::Open(GError **error_r) { - struct OneServerSocket *good = nullptr, *bad = nullptr; + OneServerSocket *good = nullptr, *bad = nullptr; GError *last_error = nullptr; - for (auto &i : ss->sockets) { - assert(i.serial > 0); - assert(good == nullptr || i.serial <= good->serial); + for (auto &i : sockets) { + assert(i.GetSerial() > 0); + assert(good == nullptr || i.GetSerial() <= good->GetSerial()); - if (bad != nullptr && i.serial != bad->serial) { - server_socket_close(ss); + if (bad != nullptr && i.GetSerial() != bad->GetSerial()) { + Close(); g_propagate_error(error_r, last_error); return false; } GError *error = nullptr; if (!i.Open(&error)) { - if (good != nullptr && good->serial == i.serial) { + if (good != nullptr && good->GetSerial() == i.GetSerial()) { char *address_string = i.ToString(); char *good_string = good->ToString(); g_warning("bind to '%s' failed: %s " @@ -291,7 +279,7 @@ server_socket_open(struct server_socket *ss, GError **error_r) } if (bad != nullptr) { - server_socket_close(ss); + Close(); g_propagate_error(error_r, last_error); return false; } @@ -300,35 +288,24 @@ server_socket_open(struct server_socket *ss, GError **error_r) } void -server_socket::Close() +ServerSocket::Close() { for (auto &i : sockets) i.Close(); } -void -server_socket_close(struct server_socket *ss) +OneServerSocket & +ServerSocket::AddAddress(const sockaddr &address, size_t address_length) { - ss->Close(); -} - -static OneServerSocket & -server_socket_add_address(struct server_socket *ss, - const struct sockaddr *address, - size_t address_length) -{ - assert(ss != nullptr); - - ss->sockets.emplace_front(ss->loop, *ss, ss->next_serial, - address, address_length); + sockets.emplace_front(loop, *this, next_serial, + &address, address_length); - return ss->sockets.front(); + return sockets.front(); } bool -server_socket_add_fd(struct server_socket *ss, int fd, GError **error_r) +ServerSocket::AddFD(int fd, GError **error_r) { - assert(ss != nullptr); assert(fd >= 0); struct sockaddr_storage address; @@ -340,9 +317,8 @@ server_socket_add_fd(struct server_socket *ss, int fd, GError **error_r) return false; } - OneServerSocket &s = - server_socket_add_address(ss, (struct sockaddr *)&address, - address_length); + OneServerSocket &s = AddAddress((const sockaddr &)address, + address_length); s.SetFD(fd); return true; @@ -350,13 +326,8 @@ server_socket_add_fd(struct server_socket *ss, int fd, GError **error_r) #ifdef HAVE_TCP -/** - * Add a listener on a port on all IPv4 interfaces. - * - * @param port the TCP port - */ -static void -server_socket_add_port_ipv4(struct server_socket *ss, unsigned port) +inline void +ServerSocket::AddPortIPv4(unsigned port) { struct sockaddr_in sin; memset(&sin, 0, sizeof(sin)); @@ -364,34 +335,26 @@ server_socket_add_port_ipv4(struct server_socket *ss, unsigned port) sin.sin_family = AF_INET; sin.sin_addr.s_addr = INADDR_ANY; - server_socket_add_address(ss, (const struct sockaddr *)&sin, - sizeof(sin)); + AddAddress((const sockaddr &)sin, sizeof(sin)); } #ifdef HAVE_IPV6 -/** - * Add a listener on a port on all IPv6 interfaces. - * - * @param port the TCP port - */ -static void -server_socket_add_port_ipv6(struct server_socket *ss, unsigned port) +inline void +ServerSocket::AddPortIPv6(unsigned port) { struct sockaddr_in6 sin; memset(&sin, 0, sizeof(sin)); sin.sin6_port = htons(port); sin.sin6_family = AF_INET6; - server_socket_add_address(ss, (const struct sockaddr *)&sin, - sizeof(sin)); + AddAddress((const sockaddr &)sin, sizeof(sin)); } #endif /* HAVE_IPV6 */ #endif /* HAVE_TCP */ bool -server_socket_add_port(struct server_socket *ss, unsigned port, - GError **error_r) +ServerSocket::AddPort(unsigned port, GError **error_r) { #ifdef HAVE_TCP if (port == 0 || port > 0xffff) { @@ -401,15 +364,14 @@ server_socket_add_port(struct server_socket *ss, unsigned port, } #ifdef HAVE_IPV6 - server_socket_add_port_ipv6(ss, port); + AddPortIPv6(port); #endif - server_socket_add_port_ipv4(ss, port); + AddPortIPv4(port); - ++ss->next_serial; + ++next_serial; return true; #else /* HAVE_TCP */ - (void)ss; (void)port; g_set_error(error_r, server_socket_quark(), 0, @@ -419,8 +381,7 @@ server_socket_add_port(struct server_socket *ss, unsigned port, } bool -server_socket_add_host(struct server_socket *ss, const char *hostname, - unsigned port, GError **error_r) +ServerSocket::AddHost(const char *hostname, unsigned port, GError **error_r) { #ifdef HAVE_TCP struct addrinfo *ai = resolve_host_port(hostname, port, @@ -430,15 +391,14 @@ server_socket_add_host(struct server_socket *ss, const char *hostname, return false; for (const struct addrinfo *i = ai; i != nullptr; i = i->ai_next) - server_socket_add_address(ss, i->ai_addr, i->ai_addrlen); + AddAddress(*i->ai_addr, i->ai_addrlen); freeaddrinfo(ai); - ++ss->next_serial; + ++next_serial; return true; #else /* HAVE_TCP */ - (void)ss; (void)hostname; (void)port; @@ -449,8 +409,7 @@ server_socket_add_host(struct server_socket *ss, const char *hostname, } bool -server_socket_add_path(struct server_socket *ss, const char *path, - GError **error_r) +ServerSocket::AddPath(const char *path, GError **error_r) { #ifdef HAVE_UN struct sockaddr_un s_un; @@ -467,14 +426,11 @@ server_socket_add_path(struct server_socket *ss, const char *path, s_un.sun_family = AF_UNIX; memcpy(s_un.sun_path, path, path_length + 1); - OneServerSocket &s = - server_socket_add_address(ss, (const struct sockaddr *)&s_un, - sizeof(s_un)); - s.path = g_strdup(path); + OneServerSocket &s = AddAddress((const sockaddr &)s_un, sizeof(s_un)); + s.SetPath(path); return true; #else /* !HAVE_UN */ - (void)ss; (void)path; g_set_error(error_r, server_socket_quark(), 0, diff --git a/src/event/ServerSocket.hxx b/src/event/ServerSocket.hxx index eea4b085..bfa4d3f3 100644 --- a/src/event/ServerSocket.hxx +++ b/src/event/ServerSocket.hxx @@ -22,6 +22,8 @@ #include "gerror.h" +#include + #include struct sockaddr; @@ -32,63 +34,84 @@ typedef void (*server_socket_callback_t)(int fd, size_t address_length, int uid, void *ctx); -struct server_socket * -server_socket_new(EventLoop &loop, - server_socket_callback_t callback, void *callback_ctx); +class OneServerSocket; -void -server_socket_free(struct server_socket *ss); +class ServerSocket { + friend class OneServerSocket; -bool -server_socket_open(struct server_socket *ss, GError **error_r); + EventLoop &loop; -void -server_socket_close(struct server_socket *ss); + server_socket_callback_t callback; + void *callback_ctx; -/** - * Add a socket descriptor that is accepting connections. After this - * has been called, don't call server_socket_open(), because the - * socket is already open. - */ -bool -server_socket_add_fd(struct server_socket *ss, int fd, GError **error_r); + std::forward_list sockets; -/** - * Add a listener on a port on all interfaces. - * - * @param port the TCP port - * @param error_r location to store the error occurring, or NULL to - * ignore errors - * @return true on success - */ -bool -server_socket_add_port(struct server_socket *ss, unsigned port, - GError **error_r); + unsigned next_serial; -/** - * Resolves a host name, and adds listeners on all addresses in the - * result set. - * - * @param hostname the host name to be resolved - * @param port the TCP port - * @param error_r location to store the error occurring, or NULL to - * ignore errors - * @return true on success - */ -bool -server_socket_add_host(struct server_socket *ss, const char *hostname, - unsigned port, GError **error_r); +public: + ServerSocket(EventLoop &_loop, + server_socket_callback_t _callback, void *_callback_ctx); + ~ServerSocket(); -/** - * Add a listener on a Unix domain socket. - * - * @param path the absolute socket path - * @param error_r location to store the error occurring, or NULL to - * ignore errors - * @return true on success - */ -bool -server_socket_add_path(struct server_socket *ss, const char *path, - GError **error_r); +private: + OneServerSocket &AddAddress(const sockaddr &address, size_t length); + + /** + * Add a listener on a port on all IPv4 interfaces. + * + * @param port the TCP port + */ + void AddPortIPv4(unsigned port); + + /** + * Add a listener on a port on all IPv6 interfaces. + * + * @param port the TCP port + */ + void AddPortIPv6(unsigned port); + +public: + /** + * Add a listener on a port on all interfaces. + * + * @param port the TCP port + * @param error_r location to store the error occurring, or NULL to + * ignore errors + * @return true on success + */ + bool AddPort(unsigned port, GError **error_r); + + /** + * Resolves a host name, and adds listeners on all addresses in the + * result set. + * + * @param hostname the host name to be resolved + * @param port the TCP port + * @param error_r location to store the error occurring, or NULL to + * ignore errors + * @return true on success + */ + bool AddHost(const char *hostname, unsigned port, GError **error_r); + + /** + * Add a listener on a Unix domain socket. + * + * @param path the absolute socket path + * @param error_r location to store the error occurring, or NULL to + * ignore errors + * @return true on success + */ + bool AddPath(const char *path, GError **error_r); + + /** + * Add a socket descriptor that is accepting connections. After this + * has been called, don't call server_socket_open(), because the + * socket is already open. + */ + bool AddFD(int fd, GError **error_r); + + bool Open(GError **error_r); + void Close(); +}; #endif diff --git a/src/output/HttpdInternal.hxx b/src/output/HttpdInternal.hxx index 702f4ad3..5c5abd0d 100644 --- a/src/output/HttpdInternal.hxx +++ b/src/output/HttpdInternal.hxx @@ -36,6 +36,7 @@ #include +class ServerSocket; class HttpdClient; struct HttpdOutput { @@ -80,7 +81,7 @@ struct HttpdOutput { /** * The listener socket. */ - struct server_socket *server_socket; + ServerSocket *server_socket; /** * The header page, which is sent to every client on connect. diff --git a/src/output/HttpdOutputPlugin.cxx b/src/output/HttpdOutputPlugin.cxx index 871047a5..f9a40a4e 100644 --- a/src/output/HttpdOutputPlugin.cxx +++ b/src/output/HttpdOutputPlugin.cxx @@ -64,7 +64,7 @@ HttpdOutput::Bind(GError **error_r) open = false; const ScopeLock protect(mutex); - return server_socket_open(server_socket, error_r); + return server_socket->Open(error_r); } inline void @@ -73,7 +73,7 @@ HttpdOutput::Unbind() assert(!open); const ScopeLock protect(mutex); - server_socket_close(server_socket); + server_socket->Close(); } static struct audio_output * @@ -112,16 +112,15 @@ httpd_output_init(const struct config_param *param, /* set up bind_to_address */ - httpd->server_socket = server_socket_new(*main_loop, - httpd_listen_in_event, httpd); + httpd->server_socket = new ServerSocket(*main_loop, + httpd_listen_in_event, httpd); const char *bind_to_address = 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); + ? httpd->server_socket->AddHost(bind_to_address, port, error) + : httpd->server_socket->AddPort(port, error); if (!success) { ao_base_finish(&httpd->base); g_free(httpd); @@ -159,7 +158,7 @@ httpd_output_finish(struct audio_output *ao) httpd->metadata->Unref(); encoder_finish(httpd->encoder); - server_socket_free(httpd->server_socket); + delete httpd->server_socket; ao_base_finish(&httpd->base); delete httpd; } -- cgit v1.2.3