aboutsummaryrefslogtreecommitdiffstats
path: root/src/net/Resolver.cxx
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/net/Resolver.cxx (renamed from src/system/Resolver.cxx)57
1 files changed, 43 insertions, 14 deletions
diff --git a/src/system/Resolver.cxx b/src/net/Resolver.cxx
index a94217bac..19df84096 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,9 +19,12 @@
#include "config.h"
#include "Resolver.hxx"
+#include "SocketAddress.hxx"
#include "util/Error.hxx"
#include "util/Domain.hxx"
+#include <algorithm>
+
#ifndef WIN32
#include <sys/socket.h>
#include <netdb.h>
@@ -42,29 +45,55 @@
const Domain resolver_domain("resolver");
+#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
+
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)
- return "local";
-
- return s_un.sun_path;
- }
+ return LocalAddressToString(*(const sockaddr_un *)address.GetAddress(),
+ address.GetSize());
#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 +103,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";