aboutsummaryrefslogtreecommitdiffstats
path: root/src/net
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/net/AllocatedSocketAddress.cxx85
-rw-r--r--src/net/AllocatedSocketAddress.hxx151
-rw-r--r--src/net/Features.hxx27
-rw-r--r--src/net/Resolver.cxx (renamed from src/system/Resolver.cxx)78
-rw-r--r--src/net/Resolver.hxx (renamed from src/system/Resolver.hxx)19
-rw-r--r--src/net/SocketAddress.cxx38
-rw-r--r--src/net/SocketAddress.hxx103
-rw-r--r--src/net/SocketError.cxx (renamed from src/system/SocketError.cxx)27
-rw-r--r--src/net/SocketError.hxx (renamed from src/system/SocketError.hxx)2
-rw-r--r--src/net/SocketUtil.cxx (renamed from src/system/SocketUtil.cxx)18
-rw-r--r--src/net/SocketUtil.hxx (renamed from src/system/SocketUtil.hxx)9
-rw-r--r--src/net/StaticSocketAddress.cxx43
-rw-r--r--src/net/StaticSocketAddress.hxx104
-rw-r--r--src/net/ToString.cxx152
-rw-r--r--src/net/ToString.hxx48
15 files changed, 793 insertions, 111 deletions
diff --git a/src/net/AllocatedSocketAddress.cxx b/src/net/AllocatedSocketAddress.cxx
new file mode 100644
index 000000000..61615a72b
--- /dev/null
+++ b/src/net/AllocatedSocketAddress.cxx
@@ -0,0 +1,85 @@
+/*
+ * Copyright (C) 2012-2015 Max Kellermann <max@duempel.org>
+ *
+ * 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 "config.h"
+#include "AllocatedSocketAddress.hxx"
+
+#include <assert.h>
+#include <string.h>
+
+#ifdef HAVE_UN
+#include <sys/un.h>
+#endif
+
+AllocatedSocketAddress &
+AllocatedSocketAddress::operator=(SocketAddress src)
+{
+ if (src.IsNull()) {
+ Clear();
+ } else {
+ SetSize(src.GetSize());
+ memcpy(address, src.GetAddress(), size);
+ }
+
+ return *this;
+}
+
+void
+AllocatedSocketAddress::SetSize(size_type new_size)
+{
+ if (size == new_size)
+ return;
+
+ free(address);
+ size = new_size;
+ address = (struct sockaddr *)malloc(size);
+}
+
+#ifdef HAVE_UN
+
+void
+AllocatedSocketAddress::SetLocal(const char *path)
+{
+ const bool is_abstract = *path == '@';
+
+ /* sun_path must be null-terminated unless it's an abstract
+ socket */
+ const size_t path_length = strlen(path) + !is_abstract;
+
+ struct sockaddr_un *sun;
+ SetSize(sizeof(*sun) - sizeof(sun->sun_path) + path_length);
+ sun = (struct sockaddr_un *)address;
+ sun->sun_family = AF_UNIX;
+ memcpy(sun->sun_path, path, path_length);
+
+ if (is_abstract)
+ sun->sun_path[0] = 0;
+}
+
+#endif
diff --git a/src/net/AllocatedSocketAddress.hxx b/src/net/AllocatedSocketAddress.hxx
new file mode 100644
index 000000000..db02488df
--- /dev/null
+++ b/src/net/AllocatedSocketAddress.hxx
@@ -0,0 +1,151 @@
+/*
+ * Copyright (C) 2012-2015 Max Kellermann <max@duempel.org>
+ *
+ * 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 ALLOCATED_SOCKET_ADDRESS_HPP
+#define ALLOCATED_SOCKET_ADDRESS_HPP
+
+#include "SocketAddress.hxx"
+#include "Features.hxx"
+#include "Compiler.h"
+
+#include <algorithm>
+
+#include <stdlib.h>
+
+struct sockaddr;
+class Error;
+
+class AllocatedSocketAddress {
+public:
+ typedef SocketAddress::size_type size_type;
+
+private:
+ struct sockaddr *address;
+ size_type size;
+
+ AllocatedSocketAddress(struct sockaddr *_address,
+ size_type _size)
+ :address(_address), size(_size) {}
+
+public:
+ AllocatedSocketAddress():address(nullptr), size(0) {}
+
+ explicit AllocatedSocketAddress(SocketAddress src)
+ :address(nullptr), size(0) {
+ *this = src;
+ }
+
+ AllocatedSocketAddress(const AllocatedSocketAddress &) = delete;
+
+ AllocatedSocketAddress(AllocatedSocketAddress &&src)
+ :address(src.address), size(src.size) {
+ src.address = nullptr;
+ src.size = 0;
+ }
+
+ ~AllocatedSocketAddress() {
+ free(address);
+ }
+
+ AllocatedSocketAddress &operator=(SocketAddress src);
+
+ AllocatedSocketAddress &operator=(const AllocatedSocketAddress &) = delete;
+
+ AllocatedSocketAddress &operator=(AllocatedSocketAddress &&src) {
+ std::swap(address, src.address);
+ std::swap(size, src.size);
+ return *this;
+ }
+
+ gcc_pure
+ bool operator==(SocketAddress other) const {
+ return (SocketAddress)*this == other;
+ }
+
+ bool operator!=(SocketAddress &other) const {
+ return !(*this == other);
+ }
+
+ gcc_const
+ static AllocatedSocketAddress Null() {
+ return AllocatedSocketAddress(nullptr, 0);
+ }
+
+ bool IsNull() const {
+ return address == nullptr;
+ }
+
+ size_type GetSize() const {
+ return size;
+ }
+
+ const struct sockaddr *GetAddress() const {
+ return address;
+ }
+
+ operator SocketAddress() const {
+ return SocketAddress(address, size);
+ }
+
+ operator const struct sockaddr *() const {
+ return address;
+ }
+
+ 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;
+ }
+
+ void Clear() {
+ free(address);
+ address = nullptr;
+ size = 0;
+ }
+
+#ifdef HAVE_UN
+ /**
+ * Make this a "local" address (UNIX domain socket). If the path
+ * begins with a '@', then the rest specifies an "abstract" local
+ * address.
+ */
+ void SetLocal(const char *path);
+#endif
+
+private:
+ void SetSize(size_type new_size);
+};
+
+#endif
diff --git a/src/net/Features.hxx b/src/net/Features.hxx
new file mode 100644
index 000000000..05dcc5659
--- /dev/null
+++ b/src/net/Features.hxx
@@ -0,0 +1,27 @@
+/*
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
+ * http://www.musicpd.org
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifndef NET_FEATURES_HXX
+#define NET_FEATURES_HXX
+
+/* feature macros are defined in config.h, and this header verifies
+ that it has been included earlier */
+#include "check.h"
+
+#endif
diff --git a/src/system/Resolver.cxx b/src/net/Resolver.cxx
index a94217bac..189c5bc9c 100644
--- a/src/system/Resolver.cxx
+++ b/src/net/Resolver.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
@@ -19,22 +19,16 @@
#include "config.h"
#include "Resolver.hxx"
+#include "SocketAddress.hxx"
#include "util/Error.hxx"
#include "util/Domain.hxx"
-#ifndef WIN32
-#include <sys/socket.h>
-#include <netdb.h>
-#ifdef HAVE_TCP
-#include <netinet/in.h>
-#endif
-#else
-#include <ws2tcpip.h>
-#include <winsock.h>
-#endif
+#include <string>
-#ifdef HAVE_UN
-#include <sys/un.h>
+#ifdef WIN32
+#include <ws2tcpip.h>
+#else
+#include <netdb.h>
#endif
#include <string.h>
@@ -42,64 +36,6 @@
const Domain resolver_domain("resolver");
-std::string
-sockaddr_to_string(const struct sockaddr *sa, size_t length)
-{
-#ifdef HAVE_UN
- if (sa->sa_family == 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)
- return "local";
-
- return s_un.sun_path;
- }
-#endif
-
-#if defined(HAVE_IPV6) && defined(IN6_IS_ADDR_V4MAPPED)
- const struct sockaddr_in6 *a6 = (const struct sockaddr_in6 *)sa;
- 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 &&
- IN6_IS_ADDR_V4MAPPED(&a6->sin6_addr)) {
- /* convert "::ffff:127.0.0.1" to "127.0.0.1" */
-
- memset(&a4, 0, sizeof(a4));
- a4.sin_family = AF_INET;
- memcpy(&a4.sin_addr, ((const char *)&a6->sin6_addr) + 12,
- sizeof(a4.sin_addr));
- a4.sin_port = a6->sin6_port;
-
- sa = (const struct sockaddr *)&a4;
- length = sizeof(a4);
- }
-#endif
-
- ret = getnameinfo(sa, length, host, sizeof(host), serv, sizeof(serv),
- NI_NUMERICHOST|NI_NUMERICSERV);
- if (ret != 0)
- return "unknown";
-
-#ifdef HAVE_IPV6
- if (strchr(host, ':') != nullptr) {
- std::string result("[");
- result.append(host);
- result.append("]:");
- result.append(serv);
- return result;
- }
-#endif
-
- std::string result(host);
- result.push_back(':');
- result.append(serv);
- return result;
-}
-
struct addrinfo *
resolve_host_port(const char *host_port, unsigned default_port,
int flags, int socktype,
diff --git a/src/system/Resolver.hxx b/src/net/Resolver.hxx
index 54922d98f..826cc4787 100644
--- a/src/system/Resolver.hxx
+++ b/src/net/Resolver.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
@@ -20,13 +20,9 @@
#ifndef MPD_RESOLVER_HXX
#define MPD_RESOLVER_HXX
+#include "check.h"
#include "Compiler.h"
-#include <string>
-
-#include <stddef.h>
-
-struct sockaddr;
struct addrinfo;
class Error;
class Domain;
@@ -34,17 +30,6 @@ class Domain;
extern const Domain resolver_domain;
/**
- * Converts the specified socket address into a string in the form
- * "IP:PORT".
- *
- * @param sa the sockaddr struct
- * @param length the length of #sa in bytes
- */
-gcc_pure
-std::string
-sockaddr_to_string(const sockaddr *sa, size_t length);
-
-/**
* Resolve a specification in the form "host", "host:port",
* "[host]:port". This is a convenience wrapper for getaddrinfo().
*
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 <max@duempel.org>
+ *
+ * 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 <string.h>
+
+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 <max@duempel.org>
+ *
+ * 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 <cstddef>
+
+#ifdef WIN32
+#include <winsock2.h>
+#else
+#include <sys/socket.h>
+#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/system/SocketError.cxx b/src/net/SocketError.cxx
index e138f4dd3..efa969b1f 100644
--- a/src/system/SocketError.cxx
+++ b/src/net/SocketError.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
@@ -20,6 +20,7 @@
#include "config.h"
#include "SocketError.hxx"
#include "util/Domain.hxx"
+#include "util/Macros.hxx"
#include <string.h>
@@ -29,13 +30,31 @@ const Domain socket_domain("socket");
SocketErrorMessage::SocketErrorMessage(socket_error_t code)
{
+#ifdef _UNICODE
+ wchar_t buffer[ARRAY_SIZE(msg)];
+#else
+ auto *buffer = msg;
+#endif
+
DWORD nbytes = FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM |
FORMAT_MESSAGE_IGNORE_INSERTS |
FORMAT_MESSAGE_MAX_WIDTH_MASK,
- NULL, code, 0,
- (LPSTR)msg, sizeof(msg), NULL);
- if (nbytes == 0)
+ nullptr, code, 0,
+ buffer, ARRAY_SIZE(msg), nullptr);
+ if (nbytes == 0) {
strcpy(msg, "Unknown error");
+ return;
+ }
+
+#ifdef _UNICODE
+ auto length = WideCharToMultiByte(CP_UTF8, 0, buffer, -1,
+ msg, ARRAY_SIZE(msg),
+ nullptr, nullptr);
+ if (length <= 0) {
+ strcpy(msg, "WideCharToMultiByte() error");
+ return;
+ }
+#endif
}
#else
diff --git a/src/system/SocketError.hxx b/src/net/SocketError.hxx
index 01abc9884..c9435d6fb 100644
--- a/src/system/SocketError.hxx
+++ b/src/net/SocketError.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/system/SocketUtil.cxx b/src/net/SocketUtil.cxx
index b9df0d59d..72d710862 100644
--- a/src/system/SocketUtil.cxx
+++ b/src/net/SocketUtil.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
@@ -19,25 +19,19 @@
#include "config.h"
#include "SocketUtil.hxx"
+#include "SocketAddress.hxx"
#include "SocketError.hxx"
-#include "fd_util.h"
+#include "system/fd_util.h"
#include <unistd.h>
-#ifndef WIN32
-#include <sys/socket.h>
-#else
-#include <ws2tcpip.h>
-#include <winsock.h>
-#endif
-
#ifdef HAVE_IPV6
#include <string.h>
#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);
@@ -75,7 +69,7 @@ socket_bind_listen(int domain, int type, int protocol,
return -1;
}
-#ifdef HAVE_STRUCT_UCRED
+#if defined(HAVE_STRUCT_UCRED) && defined(SO_PASSCRED)
setsockopt(fd, SOL_SOCKET, SO_PASSCRED,
(const char *) &reuse, sizeof(reuse));
#endif
diff --git a/src/system/SocketUtil.hxx b/src/net/SocketUtil.hxx
index 652788759..e7f6b8eaa 100644
--- a/src/system/SocketUtil.hxx
+++ b/src/net/SocketUtil.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
@@ -26,9 +26,7 @@
#ifndef MPD_SOCKET_UTIL_HXX
#define MPD_SOCKET_UTIL_HXX
-#include <stddef.h>
-
-struct sockaddr;
+class SocketAddress;
class Error;
/**
@@ -39,7 +37,6 @@ class Error;
* @param type the socket type, e.g. SOCK_STREAM
* @param protocol the protocol, usually 0 to let the kernel choose
* @param address the address to listen on
- * @param address_length the size of #address
* @param backlog the backlog parameter for the listen() system call
* @param error location to store the error occurring, or NULL to
* ignore errors
@@ -47,7 +44,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);
diff --git a/src/net/StaticSocketAddress.cxx b/src/net/StaticSocketAddress.cxx
new file mode 100644
index 000000000..94db4a49c
--- /dev/null
+++ b/src/net/StaticSocketAddress.cxx
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2012-2015 Max Kellermann <max@duempel.org>
+ *
+ * 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 "config.h"
+#include "StaticSocketAddress.hxx"
+
+#include <algorithm>
+
+#include <string.h>
+
+StaticSocketAddress &
+StaticSocketAddress::operator=(SocketAddress other)
+{
+ size = std::min(other.GetSize(), GetCapacity());
+ memcpy(&address, other.GetAddress(), size);
+ return *this;
+}
diff --git a/src/net/StaticSocketAddress.hxx b/src/net/StaticSocketAddress.hxx
new file mode 100644
index 000000000..c8cef9dfe
--- /dev/null
+++ b/src/net/StaticSocketAddress.hxx
@@ -0,0 +1,104 @@
+/*
+ * Copyright (C) 2012-2015 Max Kellermann <max@duempel.org>
+ *
+ * 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 STATIC_SOCKET_ADDRESS_HXX
+#define STATIC_SOCKET_ADDRESS_HXX
+
+#include "SocketAddress.hxx"
+#include "Compiler.h"
+
+#include <assert.h>
+
+/**
+ * An OO wrapper for struct sockaddr_storage.
+ */
+class StaticSocketAddress {
+public:
+ typedef SocketAddress::size_type size_type;
+
+private:
+ size_type size;
+ struct sockaddr_storage address;
+
+public:
+ StaticSocketAddress() = default;
+
+ StaticSocketAddress &operator=(SocketAddress other);
+
+ operator SocketAddress() const {
+ return SocketAddress(reinterpret_cast<const struct sockaddr *>(&address),
+ size);
+ }
+
+ struct sockaddr *GetAddress() {
+ return reinterpret_cast<struct sockaddr *>(&address);
+ }
+
+ const struct sockaddr *GetAddress() const {
+ return reinterpret_cast<const struct sockaddr *>(&address);
+ }
+
+ constexpr size_type GetCapacity() const {
+ return sizeof(address);
+ }
+
+ size_type GetSize() const {
+ return size;
+ }
+
+ void SetSize(size_type _size) {
+ assert(_size > 0);
+ assert(size_t(_size) <= sizeof(address));
+
+ size = _size;
+ }
+
+ int GetFamily() const {
+ return address.ss_family;
+ }
+
+ bool IsDefined() const {
+ return GetFamily() != AF_UNSPEC;
+ }
+
+ void Clear() {
+ address.ss_family = AF_UNSPEC;
+ }
+
+ gcc_pure
+ bool operator==(SocketAddress other) const {
+ return (SocketAddress)*this == other;
+ }
+
+ bool operator!=(SocketAddress &other) const {
+ return !(*this == other);
+ }
+};
+
+#endif
diff --git a/src/net/ToString.cxx b/src/net/ToString.cxx
new file mode 100644
index 000000000..1acf0320b
--- /dev/null
+++ b/src/net/ToString.cxx
@@ -0,0 +1,152 @@
+/*
+ * Copyright (C) 2011-2015 Max Kellermann <max@duempel.org>
+ *
+ * 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 "config.h"
+#include "ToString.hxx"
+#include "Features.hxx"
+#include "SocketAddress.hxx"
+
+#include <algorithm>
+
+#ifdef WIN32
+#include <ws2tcpip.h>
+#else
+#include <netdb.h>
+#ifdef HAVE_TCP
+#include <netinet/in.h>
+#endif
+#endif
+
+#ifdef HAVE_UN
+#include <sys/un.h>
+#endif
+
+#include <assert.h>
+#include <string.h>
+
+#ifdef HAVE_UN
+
+static std::string
+LocalAddressToString(const struct sockaddr_un &s_un, size_t size)
+{
+ const size_t prefix_size = (size_t)
+ ((struct sockaddr_un *)nullptr)->sun_path;
+ assert(size >= prefix_size);
+
+ size_t result_length = size - prefix_size;
+
+ /* remove the trailing null terminator */
+ if (result_length > 0 && s_un.sun_path[result_length - 1] == 0)
+ --result_length;
+
+ if (result_length == 0)
+ return "local";
+
+ std::string result(s_un.sun_path, result_length);
+
+ /* replace all null bytes with '@'; this also handles abstract
+ addresses (Linux specific) */
+ std::replace(result.begin(), result.end(), '\0', '@');
+
+ return result;
+}
+
+#endif
+
+#if defined(HAVE_IPV6) && defined(IN6_IS_ADDR_V4MAPPED)
+
+gcc_pure
+static bool
+IsV4Mapped(SocketAddress address)
+{
+ if (address.GetFamily() != AF_INET6)
+ return false;
+
+ const auto &a6 = *(const struct sockaddr_in6 *)address.GetAddress();
+ return IN6_IS_ADDR_V4MAPPED(&a6.sin6_addr);
+}
+
+/**
+ * Convert "::ffff:127.0.0.1" to "127.0.0.1".
+ */
+static SocketAddress
+UnmapV4(SocketAddress src, struct sockaddr_in &buffer)
+{
+ assert(IsV4Mapped(src));
+
+ const auto &src6 = *(const struct sockaddr_in6 *)src.GetAddress();
+ memset(&buffer, 0, sizeof(buffer));
+ buffer.sin_family = AF_INET;
+ memcpy(&buffer.sin_addr, ((const char *)&src6.sin6_addr) + 12,
+ sizeof(buffer.sin_addr));
+ buffer.sin_port = src6.sin6_port;
+
+ return { (const struct sockaddr *)&buffer, sizeof(buffer) };
+}
+
+#endif
+
+std::string
+ToString(SocketAddress address)
+{
+#ifdef HAVE_UN
+ if (address.GetFamily() == AF_UNIX)
+ /* return path of UNIX domain sockets */
+ return LocalAddressToString(*(const sockaddr_un *)address.GetAddress(),
+ address.GetSize());
+#endif
+
+#if defined(HAVE_IPV6) && defined(IN6_IS_ADDR_V4MAPPED)
+ struct sockaddr_in in_buffer;
+ if (IsV4Mapped(address))
+ address = UnmapV4(address, in_buffer);
+#endif
+
+ char host[NI_MAXHOST], serv[NI_MAXSERV];
+ int ret = getnameinfo(address.GetAddress(), address.GetSize(),
+ host, sizeof(host), serv, sizeof(serv),
+ NI_NUMERICHOST|NI_NUMERICSERV);
+ if (ret != 0)
+ return "unknown";
+
+#ifdef HAVE_IPV6
+ if (strchr(host, ':') != nullptr) {
+ std::string result("[");
+ result.append(host);
+ result.append("]:");
+ result.append(serv);
+ return result;
+ }
+#endif
+
+ std::string result(host);
+ result.push_back(':');
+ result.append(serv);
+ return result;
+}
diff --git a/src/net/ToString.hxx b/src/net/ToString.hxx
new file mode 100644
index 000000000..4b676008a
--- /dev/null
+++ b/src/net/ToString.hxx
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2011-2015 Max Kellermann <max@duempel.org>
+ *
+ * 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 NET_TO_STRING_HXX
+#define NET_TO_STRING_HXX
+
+#include "check.h"
+#include "Compiler.h"
+
+#include <string>
+
+class SocketAddress;
+
+/**
+ * Converts the specified socket address into a string in the form
+ * "IP:PORT".
+ */
+gcc_pure
+std::string
+ToString(SocketAddress address);
+
+#endif