summaryrefslogtreecommitdiff
path: root/src/net/AddressInfo.hxx
diff options
context:
space:
mode:
authorMax Kellermann <max@musicpd.org>2018-08-21 08:26:12 +0200
committerMax Kellermann <max@musicpd.org>2018-08-21 08:26:12 +0200
commit4a1e885c0a0e63ef4a8408b33e1de818a0cdb39f (patch)
tree28934864d5b15f6a12815e14a38dcc535f548073 /src/net/AddressInfo.hxx
parenteee91aa4eadd5dae7438e3c7abfa32c546290d6b (diff)
net/Resolver: replace with more advanced implementation
The new implementation is copied from another project and is BSD-licensed. It is exception-safe and can parse IPv6 scope ids with interface names.
Diffstat (limited to 'src/net/AddressInfo.hxx')
-rw-r--r--src/net/AddressInfo.hxx142
1 files changed, 142 insertions, 0 deletions
diff --git a/src/net/AddressInfo.hxx b/src/net/AddressInfo.hxx
new file mode 100644
index 000000000..63f8ebe64
--- /dev/null
+++ b/src/net/AddressInfo.hxx
@@ -0,0 +1,142 @@
+/*
+ * Copyright (C) 2016-2017 Max Kellermann <max.kellermann@gmail.com>
+ *
+ * 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_ADDRESS_INFO_HXX
+#define NET_ADDRESS_INFO_HXX
+
+#include "SocketAddress.hxx"
+
+#include <algorithm>
+#include <utility>
+
+#ifdef _WIN32
+#include <ws2tcpip.h>
+#else
+#include <netdb.h>
+#endif
+
+class AddressInfo : addrinfo {
+ /* this class cannot be instantiated, it can only be cast from
+ a struct addrinfo pointer */
+ AddressInfo() = delete;
+ ~AddressInfo() = delete;
+
+public:
+ constexpr int GetFamily() const {
+ return ai_family;
+ }
+
+ constexpr int GetType() const {
+ return ai_socktype;
+ }
+
+ constexpr int GetProtocol() const {
+ return ai_protocol;
+ }
+
+ constexpr operator SocketAddress() const {
+ return {ai_addr, (SocketAddress::size_type)ai_addrlen};
+ }
+};
+
+class AddressInfoList {
+ struct addrinfo *value = nullptr;
+
+public:
+ AddressInfoList() = default;
+ explicit AddressInfoList(struct addrinfo *_value):value(_value) {}
+
+ AddressInfoList(AddressInfoList &&src)
+ :value(std::exchange(src.value, nullptr)) {}
+
+ ~AddressInfoList() {
+ freeaddrinfo(value);
+ }
+
+ AddressInfoList &operator=(AddressInfoList &&src) {
+ std::swap(value, src.value);
+ return *this;
+ }
+
+ bool empty() const {
+ return value == nullptr;
+ }
+
+ const AddressInfo &front() const {
+ return *(const AddressInfo *)value;
+ }
+
+ /**
+ * Pick the best address from the list, e.g. prefer IPv6 over
+ * IPv4 (if both are available). We do this because binding
+ * to an IPv6 wildcard address also allows accepting IPv4
+ * connections.
+ */
+ gcc_pure
+ const AddressInfo &GetBest() const;
+
+ class const_iterator {
+ struct addrinfo *cursor;
+
+ public:
+ explicit constexpr const_iterator(struct addrinfo *_cursor)
+ :cursor(_cursor) {}
+
+ constexpr bool operator==(const_iterator other) const {
+ return cursor == other.cursor;
+ }
+
+ constexpr bool operator!=(const_iterator other) const {
+ return cursor != other.cursor;
+ }
+
+ const_iterator &operator++() {
+ cursor = cursor->ai_next;
+ return *this;
+ }
+
+ constexpr const AddressInfo &operator*() const {
+ return *(const AddressInfo *)cursor;
+ }
+
+ constexpr const AddressInfo *operator->() const {
+ return (const AddressInfo *)cursor;
+ }
+ };
+
+ const_iterator begin() const {
+ return const_iterator(value);
+ }
+
+ const_iterator end() const {
+ return const_iterator(nullptr);
+ }
+};
+
+#endif