From 4e30e747390ac6bb6a6e5ededfbcdae937579393 Mon Sep 17 00:00:00 2001 From: Max Kellermann Date: Tue, 10 Feb 2015 20:30:10 +0100 Subject: net/SocketAddress: light wrapper for struct sockaddr --- src/net/Resolver.cxx | 21 ++++++---- src/net/Resolver.hxx | 4 +- src/net/SocketAddress.cxx | 38 +++++++++++++++++ src/net/SocketAddress.hxx | 103 ++++++++++++++++++++++++++++++++++++++++++++++ src/net/SocketUtil.cxx | 12 ++---- src/net/SocketUtil.hxx | 6 +-- 6 files changed, 160 insertions(+), 24 deletions(-) create mode 100644 src/net/SocketAddress.cxx create mode 100644 src/net/SocketAddress.hxx (limited to 'src/net') diff --git a/src/net/Resolver.cxx b/src/net/Resolver.cxx index 389b3d4b5..cfbce5ff6 100644 --- a/src/net/Resolver.cxx +++ b/src/net/Resolver.cxx @@ -19,6 +19,7 @@ #include "config.h" #include "Resolver.hxx" +#include "SocketAddress.hxx" #include "util/Error.hxx" #include "util/Domain.hxx" @@ -43,13 +44,14 @@ const Domain resolver_domain("resolver"); std::string -sockaddr_to_string(const struct sockaddr *sa, size_t length) +sockaddr_to_string(SocketAddress address) { #ifdef HAVE_UN - if (sa->sa_family == AF_UNIX) { + if (address.GetFamily() == AF_UNIX) { /* return path of UNIX domain sockets */ - const sockaddr_un &s_un = *(const sockaddr_un *)sa; - if (length < sizeof(s_un) || s_un.sun_path[0] == 0) + const sockaddr_un &s_un = *(const sockaddr_un *) + address.GetAddress(); + if (address.GetSize() < sizeof(s_un) || s_un.sun_path[0] == 0) return "local"; return s_un.sun_path; @@ -57,14 +59,15 @@ sockaddr_to_string(const struct sockaddr *sa, size_t length) #endif #if defined(HAVE_IPV6) && defined(IN6_IS_ADDR_V4MAPPED) - const struct sockaddr_in6 *a6 = (const struct sockaddr_in6 *)sa; + const struct sockaddr_in6 *a6 = (const struct sockaddr_in6 *) + address.GetAddress(); struct sockaddr_in a4; #endif int ret; char host[NI_MAXHOST], serv[NI_MAXSERV]; #if defined(HAVE_IPV6) && defined(IN6_IS_ADDR_V4MAPPED) - if (sa->sa_family == AF_INET6 && + if (address.GetFamily() == AF_INET6 && IN6_IS_ADDR_V4MAPPED(&a6->sin6_addr)) { /* convert "::ffff:127.0.0.1" to "127.0.0.1" */ @@ -74,12 +77,12 @@ sockaddr_to_string(const struct sockaddr *sa, size_t length) sizeof(a4.sin_addr)); a4.sin_port = a6->sin6_port; - sa = (const struct sockaddr *)&a4; - length = sizeof(a4); + address = { (const struct sockaddr *)&a4, sizeof(a4) }; } #endif - ret = getnameinfo(sa, length, host, sizeof(host), serv, sizeof(serv), + ret = getnameinfo(address.GetAddress(), address.GetSize(), + host, sizeof(host), serv, sizeof(serv), NI_NUMERICHOST|NI_NUMERICSERV); if (ret != 0) return "unknown"; diff --git a/src/net/Resolver.hxx b/src/net/Resolver.hxx index a9596c299..7567983f0 100644 --- a/src/net/Resolver.hxx +++ b/src/net/Resolver.hxx @@ -26,10 +26,10 @@ #include -struct sockaddr; struct addrinfo; class Error; class Domain; +class SocketAddress; extern const Domain resolver_domain; @@ -42,7 +42,7 @@ extern const Domain resolver_domain; */ gcc_pure std::string -sockaddr_to_string(const sockaddr *sa, size_t length); +sockaddr_to_string(SocketAddress address); /** * Resolve a specification in the form "host", "host:port", diff --git a/src/net/SocketAddress.cxx b/src/net/SocketAddress.cxx new file mode 100644 index 000000000..38aeb8d6d --- /dev/null +++ b/src/net/SocketAddress.cxx @@ -0,0 +1,38 @@ +/* + * Copyright (C) 2012-2015 Max Kellermann + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "SocketAddress.hxx" + +#include + +bool +SocketAddress::operator==(SocketAddress other) const +{ + return size == other.size && memcmp(address, other.address, size) == 0; +} diff --git a/src/net/SocketAddress.hxx b/src/net/SocketAddress.hxx new file mode 100644 index 000000000..0577edd72 --- /dev/null +++ b/src/net/SocketAddress.hxx @@ -0,0 +1,103 @@ +/* + * Copyright (C) 2012-2015 Max Kellermann + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef SOCKET_ADDRESS_HXX +#define SOCKET_ADDRESS_HXX + +#include "Compiler.h" + +#include + +#ifdef WIN32 +#include +#else +#include +#endif + +/** + * An OO wrapper for struct sockaddr. + */ +class SocketAddress { +public: +#ifdef WIN32 + typedef int size_type; +#else + typedef socklen_t size_type; +#endif + +private: + const struct sockaddr *address; + size_type size; + +public: + SocketAddress() = default; + + constexpr SocketAddress(std::nullptr_t):address(nullptr), size(0) {} + + constexpr SocketAddress(const struct sockaddr *_address, + size_type _size) + :address(_address), size(_size) {} + + static constexpr SocketAddress Null() { + return nullptr; + } + + constexpr bool IsNull() const { + return address == nullptr; + } + + const struct sockaddr *GetAddress() const { + return address; + } + + constexpr size_type GetSize() const { + return size; + } + + constexpr int GetFamily() const { + return address->sa_family; + } + + /** + * Does the object have a well-defined address? Check !IsNull() + * before calling this method. + */ + bool IsDefined() const { + return GetFamily() != AF_UNSPEC; + } + + gcc_pure + bool operator==(const SocketAddress other) const; + + bool operator!=(const SocketAddress other) const { + return !(*this == other); + } +}; + +#endif diff --git a/src/net/SocketUtil.cxx b/src/net/SocketUtil.cxx index 556a8d037..b2ea63985 100644 --- a/src/net/SocketUtil.cxx +++ b/src/net/SocketUtil.cxx @@ -19,25 +19,19 @@ #include "config.h" #include "SocketUtil.hxx" +#include "SocketAddress.hxx" #include "SocketError.hxx" #include "system/fd_util.h" #include -#ifndef WIN32 -#include -#else -#include -#include -#endif - #ifdef HAVE_IPV6 #include #endif int socket_bind_listen(int domain, int type, int protocol, - const struct sockaddr *address, size_t address_length, + SocketAddress address, int backlog, Error &error) { @@ -60,7 +54,7 @@ socket_bind_listen(int domain, int type, int protocol, return -1; } - ret = bind(fd, address, address_length); + ret = bind(fd, address.GetAddress(), address.GetSize()); if (ret < 0) { SetSocketError(error); close_socket(fd); diff --git a/src/net/SocketUtil.hxx b/src/net/SocketUtil.hxx index ad02ef481..c0a0c95db 100644 --- a/src/net/SocketUtil.hxx +++ b/src/net/SocketUtil.hxx @@ -26,9 +26,7 @@ #ifndef MPD_SOCKET_UTIL_HXX #define MPD_SOCKET_UTIL_HXX -#include - -struct sockaddr; +class SocketAddress; class Error; /** @@ -47,7 +45,7 @@ class Error; */ int socket_bind_listen(int domain, int type, int protocol, - const struct sockaddr *address, size_t address_length, + SocketAddress address, int backlog, Error &error); -- cgit v1.2.3