summaryrefslogtreecommitdiff
path: root/louloulibs/network/resolver.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'louloulibs/network/resolver.cpp')
-rw-r--r--louloulibs/network/resolver.cpp281
1 files changed, 0 insertions, 281 deletions
diff --git a/louloulibs/network/resolver.cpp b/louloulibs/network/resolver.cpp
deleted file mode 100644
index db7fb32..0000000
--- a/louloulibs/network/resolver.cpp
+++ /dev/null
@@ -1,281 +0,0 @@
-#include <network/dns_handler.hpp>
-#include <utils/timed_events.hpp>
-#include <network/resolver.hpp>
-#include <string.h>
-#include <arpa/inet.h>
-#include <netinet/in.h>
-#ifdef UDNS_FOUND
-# include <udns.h>
-#endif
-
-#include <fstream>
-#include <cstdlib>
-#include <sstream>
-#include <chrono>
-#include <map>
-
-using namespace std::string_literals;
-
-#ifdef UDNS_FOUND
-static std::map<int, std::string> dns_error_messages {
- {DNS_E_TEMPFAIL, "Timeout while contacting DNS servers"},
- {DNS_E_PROTOCOL, "Misformatted DNS reply"},
- {DNS_E_NXDOMAIN, "Domain name not found"},
- {DNS_E_NOMEM, "Out of memory"},
- {DNS_E_BADQUERY, "Misformatted domain name"}
-};
-#endif
-
-Resolver::Resolver():
-#ifdef UDNS_FOUND
- resolved4(false),
- resolved6(false),
- resolving(false),
- port{},
-#endif
- resolved(false),
- error_msg{}
-{
-}
-
-void Resolver::resolve(const std::string& hostname, const std::string& port,
- SuccessCallbackType success_cb, ErrorCallbackType error_cb)
-{
- this->error_cb = error_cb;
- this->success_cb = success_cb;
-#ifdef UDNS_FOUND
- this->port = port;
-#endif
-
- this->start_resolving(hostname, port);
-}
-
-int Resolver::call_getaddrinfo(const char *name, const char* port, int flags)
-{
- struct addrinfo hints;
- memset(&hints, 0, sizeof(struct addrinfo));
- hints.ai_flags = flags;
- hints.ai_family = AF_UNSPEC;
- hints.ai_socktype = SOCK_STREAM;
- hints.ai_protocol = 0;
-
- struct addrinfo* addr_res = nullptr;
- const int res = ::getaddrinfo(name, port,
- &hints, &addr_res);
-
- if (res == 0 && addr_res)
- {
- if (!this->addr)
- this->addr.reset(addr_res);
- else
- { // Append this result at the end of the linked list
- struct addrinfo *rp = this->addr.get();
- while (rp->ai_next)
- rp = rp->ai_next;
- rp->ai_next = addr_res;
- }
- }
-
- return res;
-}
-
-#ifdef UDNS_FOUND
-void Resolver::start_resolving(const std::string& hostname, const std::string& port)
-{
- this->resolving = true;
- this->resolved = false;
- this->resolved4 = false;
- this->resolved6 = false;
-
- this->error_msg.clear();
- this->addr.reset(nullptr);
-
- // We first try to use it as an IP address directly. We tell getaddrinfo
- // to NOT use any DNS resolution.
- if (this->call_getaddrinfo(hostname.data(), port.data(), AI_NUMERICHOST) == 0)
- {
- this->on_resolved();
- return;
- }
-
- // Then we look into /etc/hosts to translate the given hostname
- const auto hosts = this->look_in_etc_hosts(hostname);
- if (!hosts.empty())
- {
- for (const auto &host: hosts)
- this->call_getaddrinfo(host.data(), port.data(), AI_NUMERICHOST);
- this->on_resolved();
- return;
- }
-
- // And finally, we try a DNS resolution
- auto hostname6_resolved = [](dns_ctx*, dns_rr_a6* result, void* data)
- {
- Resolver* resolver = static_cast<Resolver*>(data);
- resolver->on_hostname6_resolved(result);
- resolver->after_resolved();
- std::free(result);
- };
-
- auto hostname4_resolved = [](dns_ctx*, dns_rr_a4* result, void* data)
- {
- Resolver* resolver = static_cast<Resolver*>(data);
- resolver->on_hostname4_resolved(result);
- resolver->after_resolved();
- std::free(result);
- };
-
- DNSHandler::watch();
- auto res = dns_submit_a4(nullptr, hostname.data(), 0, hostname4_resolved, this);
- if (!res)
- this->on_hostname4_resolved(nullptr);
- res = dns_submit_a6(nullptr, hostname.data(), 0, hostname6_resolved, this);
- if (!res)
- this->on_hostname6_resolved(nullptr);
-
- this->start_timer();
-}
-
-void Resolver::start_timer()
-{
- const auto timeout = dns_timeouts(nullptr, -1, 0);
- if (timeout < 0)
- return;
- TimedEvent event(std::chrono::steady_clock::now() + std::chrono::seconds(timeout), [this]() { this->start_timer(); }, "DNS");
- TimedEventsManager::instance().add_event(std::move(event));
-}
-
-std::vector<std::string> Resolver::look_in_etc_hosts(const std::string &hostname)
-{
- std::ifstream hosts("/etc/hosts");
- std::string line;
-
- std::vector<std::string> results;
- while (std::getline(hosts, line))
- {
- if (line.empty())
- continue;
-
- std::string ip;
- std::istringstream line_stream(line);
- line_stream >> ip;
- if (ip.empty() || ip[0] == '#')
- continue;
-
- std::string host;
- while (line_stream >> host && !host.empty() && host[0] != '#')
- {
- if (hostname == host)
- {
- results.push_back(ip);
- break;
- }
- }
- }
- return results;
-}
-
-void Resolver::on_hostname4_resolved(dns_rr_a4 *result)
-{
- this->resolved4 = true;
-
- const auto status = dns_status(nullptr);
-
- if (status >= 0 && result)
- {
- char buf[INET6_ADDRSTRLEN];
-
- for (auto i = 0; i < result->dnsa4_nrr; ++i)
- {
- inet_ntop(AF_INET, &result->dnsa4_addr[i], buf, sizeof(buf));
- this->call_getaddrinfo(buf, this->port.data(), AI_NUMERICHOST);
- }
- }
- else
- {
- const auto error = dns_error_messages.find(status);
- if (error != end(dns_error_messages))
- this->error_msg = error->second;
- }
-}
-
-void Resolver::on_hostname6_resolved(dns_rr_a6 *result)
-{
- this->resolved6 = true;
-
- const auto status = dns_status(nullptr);
-
- if (status >= 0 && result)
- {
- char buf[INET6_ADDRSTRLEN];
- for (auto i = 0; i < result->dnsa6_nrr; ++i)
- {
- inet_ntop(AF_INET6, &result->dnsa6_addr[i], buf, sizeof(buf));
- this->call_getaddrinfo(buf, this->port.data(), AI_NUMERICHOST);
- }
- }
-}
-
-void Resolver::after_resolved()
-{
- if (dns_active(nullptr) == 0)
- DNSHandler::unwatch();
-
- if (this->resolved6 && this->resolved4)
- this->on_resolved();
-}
-
-void Resolver::on_resolved()
-{
- this->resolved = true;
- this->resolving = false;
- if (!this->addr)
- {
- if (this->error_cb)
- this->error_cb(this->error_msg.data());
- }
- else
- {
- if (this->success_cb)
- this->success_cb(this->addr.get());
- }
-}
-
-#else // ifdef UDNS_FOUND
-
-void Resolver::start_resolving(const std::string& hostname, const std::string& port)
-{
- // If the resolution fails, the addr will be unset
- this->addr.reset(nullptr);
-
- const auto res = this->call_getaddrinfo(hostname.data(), port.data(), 0);
-
- this->resolved = true;
-
- if (res != 0)
- {
- this->error_msg = gai_strerror(res);
- if (this->error_cb)
- this->error_cb(this->error_msg.data());
- }
- else
- {
- if (this->success_cb)
- this->success_cb(this->addr.get());
- }
-}
-#endif // ifdef UDNS_FOUND
-
-std::string addr_to_string(const struct addrinfo* rp)
-{
- char buf[INET6_ADDRSTRLEN];
- if (rp->ai_family == AF_INET)
- return ::inet_ntop(rp->ai_family,
- &reinterpret_cast<sockaddr_in*>(rp->ai_addr)->sin_addr,
- buf, sizeof(buf));
- else if (rp->ai_family == AF_INET6)
- return ::inet_ntop(rp->ai_family,
- &reinterpret_cast<sockaddr_in6*>(rp->ai_addr)->sin6_addr,
- buf, sizeof(buf));
- return {};
-}