From 5b189696d7773c843b26b11ac547a271a5a1b9a1 Mon Sep 17 00:00:00 2001 From: XMRig Date: Sun, 14 Mar 2021 09:44:56 +0700 Subject: [PATCH] Added DnsRecords class. --- src/base/base.cmake | 2 + src/base/kernel/interfaces/IDnsListener.h | 8 +- src/base/net/dns/Dns.cpp | 76 ++----------- src/base/net/dns/Dns.h | 15 +-- src/base/net/dns/DnsRecords.cpp | 107 ++++++++++++++++++ src/base/net/dns/DnsRecords.h | 48 ++++++++ src/base/net/http/HttpClient.cpp | 6 +- src/base/net/http/HttpClient.h | 4 +- src/base/net/stratum/Client.cpp | 6 +- src/base/net/stratum/Client.h | 3 +- .../net/stratum/benchmark/BenchClient.cpp | 8 +- src/base/net/stratum/benchmark/BenchClient.h | 2 +- 12 files changed, 187 insertions(+), 98 deletions(-) create mode 100644 src/base/net/dns/DnsRecords.cpp create mode 100644 src/base/net/dns/DnsRecords.h diff --git a/src/base/base.cmake b/src/base/base.cmake index 5949c050..ead3b4cb 100644 --- a/src/base/base.cmake +++ b/src/base/base.cmake @@ -44,6 +44,7 @@ set(HEADERS_BASE src/base/kernel/Process.h src/base/net/dns/Dns.h src/base/net/dns/DnsRecord.h + src/base/net/dns/DnsRecords.h src/base/net/http/Http.h src/base/net/http/HttpListener.h src/base/net/stratum/BaseClient.h @@ -100,6 +101,7 @@ set(SOURCES_BASE src/base/kernel/Process.cpp src/base/net/dns/Dns.cpp src/base/net/dns/DnsRecord.cpp + src/base/net/dns/DnsRecords.cpp src/base/net/http/Http.cpp src/base/net/stratum/BaseClient.cpp src/base/net/stratum/Client.cpp diff --git a/src/base/kernel/interfaces/IDnsListener.h b/src/base/kernel/interfaces/IDnsListener.h index 7d0e14e3..7e688a89 100644 --- a/src/base/kernel/interfaces/IDnsListener.h +++ b/src/base/kernel/interfaces/IDnsListener.h @@ -1,6 +1,6 @@ /* XMRig - * Copyright (c) 2018-2020 SChernykh - * Copyright (c) 2016-2020 XMRig , + * Copyright (c) 2018-2021 SChernykh + * Copyright (c) 2016-2021 XMRig , * * 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 @@ -26,7 +26,7 @@ namespace xmrig { -class Dns; +class DnsRecords; class IDnsListener @@ -37,7 +37,7 @@ public: IDnsListener() = default; virtual ~IDnsListener() = default; - virtual void onResolved(const Dns &dns, int status) = 0; + virtual void onResolved(const DnsRecords &records, int status) = 0; }; diff --git a/src/base/net/dns/Dns.cpp b/src/base/net/dns/Dns.cpp index ef50b20d..ddc9ef20 100644 --- a/src/base/net/dns/Dns.cpp +++ b/src/base/net/dns/Dns.cpp @@ -1,6 +1,6 @@ /* XMRig - * Copyright (c) 2018-2020 SChernykh - * Copyright (c) 2016-2020 XMRig , + * Copyright (c) 2018-2021 SChernykh + * Copyright (c) 2016-2021 XMRig , * * 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 @@ -23,7 +23,6 @@ namespace xmrig { Storage Dns::m_storage; - static const DnsRecord defaultRecord; } @@ -54,7 +53,7 @@ bool xmrig::Dns::resolve(const String &host) if (m_host != host) { m_host = host; - clear(); + m_records.clear(); } m_status = uv_getaddrinfo(uv_default_loop(), m_resolver, Dns::onResolved, m_host.data(), nullptr, &m_hints); @@ -63,82 +62,21 @@ bool xmrig::Dns::resolve(const String &host) } -const char *xmrig::Dns::error() const -{ - return uv_strerror(m_status); -} - - -const xmrig::DnsRecord &xmrig::Dns::get(DnsRecord::Type prefered) const -{ - if (count() == 0) { - return defaultRecord; - } - - const size_t ipv4 = m_ipv4.size(); - const size_t ipv6 = m_ipv6.size(); - - if (ipv6 && (prefered == DnsRecord::AAAA || !ipv4)) { - return m_ipv6[ipv6 == 1 ? 0 : static_cast(rand()) % ipv6]; - } - - if (ipv4) { - return m_ipv4[ipv4 == 1 ? 0 : static_cast(rand()) % ipv4]; - } - - return defaultRecord; -} - - -size_t xmrig::Dns::count(DnsRecord::Type type) const -{ - if (type == DnsRecord::A) { - return m_ipv4.size(); - } - - if (type == DnsRecord::AAAA) { - return m_ipv6.size(); - } - - return m_ipv4.size() + m_ipv6.size(); -} - - -void xmrig::Dns::clear() -{ - m_ipv4.clear(); - m_ipv6.clear(); -} - - void xmrig::Dns::onResolved(int status, addrinfo *res) { m_status = status; if (m_status < 0) { - return m_listener->onResolved(*this, status); + return m_listener->onResolved(m_records, status); } - clear(); + m_records.parse(res); - addrinfo *ptr = res; - while (ptr != nullptr) { - if (ptr->ai_family == AF_INET) { - m_ipv4.emplace_back(ptr); - } - - if (ptr->ai_family == AF_INET6) { - m_ipv6.emplace_back(ptr); - } - - ptr = ptr->ai_next; - } - - if (isEmpty()) { + if (m_records.isEmpty()) { m_status = UV_EAI_NONAME; } - m_listener->onResolved(*this, m_status); + m_listener->onResolved(m_records, m_status); } diff --git a/src/base/net/dns/Dns.h b/src/base/net/dns/Dns.h index 86f90145..a2da01b2 100644 --- a/src/base/net/dns/Dns.h +++ b/src/base/net/dns/Dns.h @@ -1,6 +1,6 @@ /* XMRig - * Copyright (c) 2018-2020 SChernykh - * Copyright (c) 2016-2020 XMRig , + * Copyright (c) 2018-2021 SChernykh + * Copyright (c) 2016-2021 XMRig , * * 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 @@ -24,10 +24,9 @@ #include -#include "base/net/dns/DnsRecord.h" +#include "base/net/dns/DnsRecords.h" #include "base/net/tools/Storage.h" #include "base/tools/Object.h" -#include "base/tools/String.h" namespace xmrig { @@ -44,26 +43,20 @@ public: Dns(IDnsListener *listener); ~Dns(); - inline bool isEmpty() const { return m_ipv4.empty() && m_ipv6.empty(); } inline const String &host() const { return m_host; } inline int status() const { return m_status; } bool resolve(const String &host); - const char *error() const; - const DnsRecord &get(DnsRecord::Type prefered = DnsRecord::A) const; - size_t count(DnsRecord::Type type = DnsRecord::Unknown) const; private: - void clear(); void onResolved(int status, addrinfo *res); static void onResolved(uv_getaddrinfo_t *req, int status, addrinfo *res); addrinfo m_hints{}; + DnsRecords m_records; IDnsListener *m_listener; int m_status = 0; - std::vector m_ipv4; - std::vector m_ipv6; String m_host; uintptr_t m_key; uv_getaddrinfo_t *m_resolver = nullptr; diff --git a/src/base/net/dns/DnsRecords.cpp b/src/base/net/dns/DnsRecords.cpp new file mode 100644 index 00000000..583d4814 --- /dev/null +++ b/src/base/net/dns/DnsRecords.cpp @@ -0,0 +1,107 @@ +/* XMRig + * Copyright (c) 2018-2021 SChernykh + * Copyright (c) 2016-2021 XMRig , + * + * 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 3 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, see . + */ + + +#include + + +#include "base/net/dns/DnsRecords.h" + + +const xmrig::DnsRecord &xmrig::DnsRecords::get(DnsRecord::Type prefered) const +{ + static const DnsRecord defaultRecord; + + if (isEmpty()) { + return defaultRecord; + } + + const size_t ipv4 = m_ipv4.size(); + const size_t ipv6 = m_ipv6.size(); + + if (ipv6 && (prefered == DnsRecord::AAAA || !ipv4)) { + return m_ipv6[ipv6 == 1 ? 0 : static_cast(rand()) % ipv6]; + } + + if (ipv4) { + return m_ipv4[ipv4 == 1 ? 0 : static_cast(rand()) % ipv4]; + } + + return defaultRecord; +} + + +size_t xmrig::DnsRecords::count(DnsRecord::Type type) const +{ + if (type == DnsRecord::A) { + return m_ipv4.size(); + } + + if (type == DnsRecord::AAAA) { + return m_ipv6.size(); + } + + return m_ipv4.size() + m_ipv6.size(); +} + + +void xmrig::DnsRecords::clear() +{ + m_ipv4.clear(); + m_ipv6.clear(); +} + + +void xmrig::DnsRecords::parse(addrinfo *res) +{ + clear(); + + addrinfo *ptr = res; + size_t ipv4 = 0; + size_t ipv6 = 0; + + while (ptr != nullptr) { + if (ptr->ai_family == AF_INET) { + ++ipv4; + } + else if (ptr->ai_family == AF_INET6) { + ++ipv6; + } + + ptr = ptr->ai_next; + } + + if (ipv4 == 0 && ipv6 == 0) { + return; + } + + m_ipv4.reserve(ipv4); + m_ipv6.reserve(ipv6); + + ptr = res; + while (ptr != nullptr) { + if (ptr->ai_family == AF_INET) { + m_ipv4.emplace_back(ptr); + } + else if (ptr->ai_family == AF_INET6) { + m_ipv6.emplace_back(ptr); + } + + ptr = ptr->ai_next; + } +} diff --git a/src/base/net/dns/DnsRecords.h b/src/base/net/dns/DnsRecords.h new file mode 100644 index 00000000..e59966a2 --- /dev/null +++ b/src/base/net/dns/DnsRecords.h @@ -0,0 +1,48 @@ +/* XMRig + * Copyright (c) 2018-2021 SChernykh + * Copyright (c) 2016-2021 XMRig , + * + * 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 3 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, see . + */ + +#ifndef XMRIG_DNSRECORDS_H +#define XMRIG_DNSRECORDS_H + + +#include "base/net/dns/DnsRecord.h" + + +namespace xmrig { + + +class DnsRecords +{ +public: + inline bool isEmpty() const { return m_ipv4.empty() && m_ipv6.empty(); } + + const DnsRecord &get(DnsRecord::Type prefered = DnsRecord::A) const; + size_t count(DnsRecord::Type type = DnsRecord::Unknown) const; + void clear(); + void parse(addrinfo *res); + +private: + std::vector m_ipv4; + std::vector m_ipv6; +}; + + +} /* namespace xmrig */ + + +#endif /* XMRIG_DNSRECORDS_H */ diff --git a/src/base/net/http/HttpClient.cpp b/src/base/net/http/HttpClient.cpp index 09e99553..4437c8e8 100644 --- a/src/base/net/http/HttpClient.cpp +++ b/src/base/net/http/HttpClient.cpp @@ -62,11 +62,11 @@ bool xmrig::HttpClient::connect() } -void xmrig::HttpClient::onResolved(const Dns &dns, int status) +void xmrig::HttpClient::onResolved(const DnsRecords &records, int status) { this->status = status; - if (status < 0 && dns.isEmpty()) { + if (status < 0 && records.isEmpty()) { if (!isQuiet()) { LOG_ERR("%s " RED("DNS error: ") RED_BOLD("\"%s\""), tag(), uv_strerror(status)); } @@ -77,7 +77,7 @@ void xmrig::HttpClient::onResolved(const Dns &dns, int status) auto req = new uv_connect_t; req->data = this; - uv_tcp_connect(req, m_tcp, dns.get().addr(port()), onConnect); + uv_tcp_connect(req, m_tcp, records.get().addr(port()), onConnect); } diff --git a/src/base/net/http/HttpClient.h b/src/base/net/http/HttpClient.h index d012d26f..08e3e8d8 100644 --- a/src/base/net/http/HttpClient.h +++ b/src/base/net/http/HttpClient.h @@ -32,7 +32,7 @@ namespace xmrig { -class String; +class Dns; class HttpClient : public HttpContext, public IDnsListener, public ITimerListener @@ -51,7 +51,7 @@ public: bool connect(); protected: - void onResolved(const Dns &dns, int status) override; + void onResolved(const DnsRecords &records, int status) override; void onTimer(const Timer *timer) override; virtual void handshake(); diff --git a/src/base/net/stratum/Client.cpp b/src/base/net/stratum/Client.cpp index 7bef6055..911267e8 100644 --- a/src/base/net/stratum/Client.cpp +++ b/src/base/net/stratum/Client.cpp @@ -295,14 +295,14 @@ void xmrig::Client::tick(uint64_t now) } -void xmrig::Client::onResolved(const Dns &dns, int status) +void xmrig::Client::onResolved(const DnsRecords &records, int status) { assert(m_listener != nullptr); if (!m_listener) { return reconnect(); } - if (status < 0 && dns.isEmpty()) { + if (status < 0 && records.isEmpty()) { if (!isQuiet()) { LOG_ERR("%s " RED("DNS error: ") RED_BOLD("\"%s\""), tag(), uv_strerror(status)); } @@ -310,7 +310,7 @@ void xmrig::Client::onResolved(const Dns &dns, int status) return reconnect(); } - const auto &record = dns.get(); + const auto &record = records.get(); m_ip = record.ip(); connect(record.addr(m_socks5 ? m_pool.proxy().port() : m_pool.port())); diff --git a/src/base/net/stratum/Client.h b/src/base/net/stratum/Client.h index 5721539c..94331c63 100644 --- a/src/base/net/stratum/Client.h +++ b/src/base/net/stratum/Client.h @@ -50,6 +50,7 @@ using BIO = struct bio_st; namespace xmrig { +class Dns; class IClientListener; class JobResult; @@ -79,7 +80,7 @@ protected: void deleteLater() override; void tick(uint64_t now) override; - void onResolved(const Dns &dns, int status) override; + void onResolved(const DnsRecords &records, int status) override; inline bool hasExtension(Extension extension) const noexcept override { return m_extensions.test(extension); } inline const char *mode() const override { return "pool"; } diff --git a/src/base/net/stratum/benchmark/BenchClient.cpp b/src/base/net/stratum/benchmark/BenchClient.cpp index 0e1093a1..1236c54d 100644 --- a/src/base/net/stratum/benchmark/BenchClient.cpp +++ b/src/base/net/stratum/benchmark/BenchClient.cpp @@ -185,16 +185,16 @@ void xmrig::BenchClient::onHttpData(const HttpData &data) } -void xmrig::BenchClient::onResolved(const Dns &dns, int status) +void xmrig::BenchClient::onResolved(const DnsRecords &records, int status) { # ifdef XMRIG_FEATURE_HTTP assert(!m_httpListener); if (status < 0) { - return setError(dns.error(), "DNS error"); + return setError(uv_strerror(status), "DNS error"); } - m_ip = dns.get().ip(); + m_ip = records.get().ip(); m_httpListener = std::make_shared(this, tag()); if (m_mode == ONLINE_BENCH) { @@ -310,7 +310,7 @@ void xmrig::BenchClient::resolve() m_dns = std::make_shared(this); if (!m_dns->resolve(BenchConfig::kApiHost)) { - setError(m_dns->error(), "getaddrinfo error"); + setError(uv_strerror(m_dns->status()), "getaddrinfo error"); } } diff --git a/src/base/net/stratum/benchmark/BenchClient.h b/src/base/net/stratum/benchmark/BenchClient.h index 7eac1ee8..f55ff6ca 100644 --- a/src/base/net/stratum/benchmark/BenchClient.h +++ b/src/base/net/stratum/benchmark/BenchClient.h @@ -70,7 +70,7 @@ protected: void onBenchDone(uint64_t result, uint64_t diff, uint64_t ts) override; void onBenchReady(uint64_t ts, uint32_t threads, const IBackend *backend) override; void onHttpData(const HttpData &data) override; - void onResolved(const Dns &dns, int status) override; + void onResolved(const DnsRecords &records, int status) override; private: enum Mode : uint32_t {