Commit a0ccc705 authored by Dominik Charousset's avatar Dominik Charousset Committed by GitHub

Merge pull request #15

Add function to resolve hosts to IP address
parents e23a402f dc71ebef
......@@ -11,6 +11,7 @@ set(LIBCAF_NET_SRCS
src/datagram_socket.cpp
src/endpoint_manager.cpp
src/host.cpp
src/ip.cpp
src/multiplexer.cpp
src/network_socket.cpp
src/pipe_socket.cpp
......
......@@ -23,6 +23,7 @@
#include "caf/config.hpp"
// clang-format off
#ifdef CAF_WINDOWS
# ifndef WIN32_LEAN_AND_MEAN
# define WIN32_LEAN_AND_MEAN
......@@ -42,6 +43,7 @@
# include <ws2ipdef.h>
# include <ws2tcpip.h>
#else // CAF_WINDOWS
# include <sys/types.h>
# include <arpa/inet.h>
# include <cerrno>
# include <fcntl.h>
......@@ -51,3 +53,4 @@
# include <sys/socket.h>
# include <unistd.h>
#endif
// clang-format on
/******************************************************************************
* ____ _ _____ *
* / ___| / \ | ___| C++ *
* | | / _ \ | |_ Actor *
* | |___ / ___ \| _| Framework *
* \____/_/ \_|_| *
* *
* Copyright 2011-2019 Dominik Charousset *
* *
* Distributed under the terms and conditions of the BSD 3-Clause License or *
* (at your option) under the terms and conditions of the Boost Software *
* License 1.0. See accompanying files LICENSE and LICENSE_ALTERNATIVE. *
* *
* If you did not receive a copy of the license files, see *
* http://opensource.org/licenses/BSD-3-Clause and *
* http://www.boost.org/LICENSE_1_0.txt. *
******************************************************************************/
#pragma once
#include <string>
#include <vector>
#include "caf/fwd.hpp"
namespace caf {
namespace net {
namespace ip {
/// Returns all IP addresses of to `host` (if any).
std::vector<ip_address> resolve(string_view host);
/// Returns the hostname of this device.
std::string hostname();
} // namespace ip
} // namespace net
} // namespace caf
/******************************************************************************
* ____ _ _____ *
* / ___| / \ | ___| C++ *
* | | / _ \ | |_ Actor *
* | |___ / ___ \| _| Framework *
* \____/_/ \_|_| *
* *
* Copyright 2011-2019 Dominik Charousset *
* *
* Distributed under the terms and conditions of the BSD 3-Clause License or *
* (at your option) under the terms and conditions of the Boost Software *
* License 1.0. See accompanying files LICENSE and LICENSE_ALTERNATIVE. *
* *
* If you did not receive a copy of the license files, see *
* http://opensource.org/licenses/BSD-3-Clause and *
* http://www.boost.org/LICENSE_1_0.txt. *
******************************************************************************/
#include <cstddef>
#include <string>
#include <utility>
#include <vector>
#include "caf/config.hpp"
#include "caf/detail/socket_sys_includes.hpp"
#include "caf/error.hpp"
#include "caf/ip_address.hpp"
#include "caf/logger.hpp"
#include "caf/string_view.hpp"
#ifdef CAF_WINDOWS
# ifndef _WIN32_WINNT
# define _WIN32_WINNT 0x0600
# endif
# include <iphlpapi.h>
# include <winsock.h>
#else
# include <ifaddrs.h>
# include <net/if.h>
# include <netdb.h>
# include <sys/ioctl.h>
#endif
#ifndef HOST_NAME_MAX
# define HOST_NAME_MAX 255
#endif
using std::pair;
using std::string;
using std::vector;
namespace caf {
namespace net {
namespace ip {
namespace {
void* fetch_in_addr(int family, sockaddr* addr) {
if (family == AF_INET)
return &reinterpret_cast<sockaddr_in*>(addr)->sin_addr;
return &reinterpret_cast<sockaddr_in6*>(addr)->sin6_addr;
}
int fetch_addr_str(char (&buf)[INET6_ADDRSTRLEN], sockaddr* addr) {
if (addr == nullptr)
return AF_UNSPEC;
auto family = addr->sa_family;
auto in_addr = fetch_in_addr(family, addr);
return (family == AF_INET || family == AF_INET6)
&& inet_ntop(family, in_addr, buf, INET6_ADDRSTRLEN) == buf
? family
: AF_UNSPEC;
}
} // namespace
std::vector<ip_address> resolve(string_view host) {
addrinfo hint;
memset(&hint, 0, sizeof(hint));
hint.ai_socktype = SOCK_STREAM;
hint.ai_family = AF_UNSPEC;
if (host.empty())
hint.ai_flags = AI_PASSIVE;
addrinfo* tmp = nullptr;
std::string host_str{host.begin(), host.end()};
if (getaddrinfo(host_str.c_str(), nullptr, &hint, &tmp) != 0)
return {};
std::unique_ptr<addrinfo, decltype(freeaddrinfo)*> addrs{tmp, freeaddrinfo};
char buffer[INET6_ADDRSTRLEN];
std::vector<ip_address> results;
for (auto i = addrs.get(); i != nullptr; i = i->ai_next) {
auto family = fetch_addr_str(buffer, i->ai_addr);
if (family != AF_UNSPEC) {
ip_address ip;
if (auto err = parse(buffer, ip))
CAF_LOG_ERROR("could not parse IP address: " << buffer);
else
results.emplace_back(ip);
}
}
// TODO: Should we just prefer ipv6 or use a config option?
// std::stable_sort(std::begin(results), std::end(results),
// [](const ip_address& lhs, const ip_address& rhs) {
// return !lhs.embeds_v4() && rhs.embeds_v4();
// });
return results;
}
std::string hostname() {
char buf[HOST_NAME_MAX + 1];
buf[HOST_NAME_MAX] = '\0';
gethostname(buf, HOST_NAME_MAX);
return buf;
}
} // namespace ip
} // namespace net
} // namespace caf
/******************************************************************************
* ____ _ _____ *
* / ___| / \ | ___| C++ *
* | | / _ \ | |_ Actor *
* | |___ / ___ \| _| Framework *
* \____/_/ \_|_| *
* *
* Copyright 2011-2019 Dominik Charousset *
* *
* Distributed under the terms and conditions of the BSD 3-Clause License or *
* (at your option) under the terms and conditions of the Boost Software *
* License 1.0. See accompanying files LICENSE and LICENSE_ALTERNATIVE. *
* *
* If you did not receive a copy of the license files, see *
* http://opensource.org/licenses/BSD-3-Clause and *
* http://www.boost.org/LICENSE_1_0.txt. *
******************************************************************************/
#define CAF_SUITE ip
#include "caf/net/ip.hpp"
#include "caf/test/dsl.hpp"
#include "host_fixture.hpp"
#include "caf/ip_address.hpp"
#include "caf/ipv4_address.hpp"
using namespace caf;
using namespace caf::net;
CAF_TEST_FIXTURE_SCOPE(ip_tests, host_fixture)
CAF_TEST(resolve) {
ip_address v4_local{make_ipv4_address(127, 0, 0, 1)};
ip_address v6_local{{0}, {0x1}};
auto addrs = ip::resolve("localhost");
CAF_CHECK(!addrs.empty());
auto contains = [&](ip_address x) {
return std::count(addrs.begin(), addrs.end(), x) > 0;
};
CAF_CHECK(contains(v4_local) || contains(v6_local));
}
CAF_TEST_FIXTURE_SCOPE_END()
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment