Add classes Dns, DnsRecord, IDnsListener.

This commit is contained in:
XMRig 2019-03-15 18:14:25 +07:00
parent 3094741c64
commit af3655c27e
10 changed files with 514 additions and 131 deletions

View file

@ -26,6 +26,7 @@ set(HEADERS
src/base/kernel/Entry.h
src/base/kernel/interfaces/IClientListener.h
src/base/kernel/interfaces/IConfigListener.h
src/base/kernel/interfaces/IDnsListener.h
src/base/kernel/interfaces/ILineListener.h
src/base/kernel/interfaces/ISignalListener.h
src/base/kernel/interfaces/IStrategy.h
@ -33,6 +34,8 @@ set(HEADERS
src/base/kernel/interfaces/IWatcherListener.h
src/base/kernel/Process.h
src/base/kernel/Signals.h
src/base/net/dns/Dns.h
src/base/net/dns/DnsRecord.h
src/base/net/stratum/Client.h
src/base/net/stratum/Job.h
src/base/net/stratum/Pool.h
@ -118,6 +121,8 @@ set(SOURCES
src/base/kernel/Entry.cpp
src/base/kernel/Process.cpp
src/base/kernel/Signals.cpp
src/base/net/dns/Dns.cpp
src/base/net/dns/DnsRecord.cpp
src/base/net/stratum/Client.cpp
src/base/net/stratum/Job.cpp
src/base/net/stratum/Pool.cpp

View file

@ -0,0 +1,47 @@
/* XMRig
* Copyright 2010 Jeff Garzik <jgarzik@pobox.com>
* Copyright 2012-2014 pooler <pooler@litecoinpool.org>
* Copyright 2014 Lucas Jones <https://github.com/lucasjones>
* Copyright 2014-2016 Wolf9466 <https://github.com/OhGodAPet>
* Copyright 2016 Jay D Dee <jayddee246@gmail.com>
* Copyright 2017-2018 XMR-Stak <https://github.com/fireice-uk>, <https://github.com/psychocrypt>
* Copyright 2018-2019 SChernykh <https://github.com/SChernykh>
* Copyright 2016-2019 XMRig <https://github.com/xmrig>, <support@xmrig.com>
*
* 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 <http://www.gnu.org/licenses/>.
*/
#ifndef XMRIG_IDNSLISTENER_H
#define XMRIG_IDNSLISTENER_H
namespace xmrig {
class Dns;
class IDnsListener
{
public:
virtual ~IDnsListener() = default;
virtual void onResolved(const Dns &dns, int status) = 0;
};
} /* namespace xmrig */
#endif // XMRIG_IDNSLISTENER_H

158
src/base/net/dns/Dns.cpp Normal file
View file

@ -0,0 +1,158 @@
/* XMRig
* Copyright 2010 Jeff Garzik <jgarzik@pobox.com>
* Copyright 2012-2014 pooler <pooler@litecoinpool.org>
* Copyright 2014 Lucas Jones <https://github.com/lucasjones>
* Copyright 2014-2016 Wolf9466 <https://github.com/OhGodAPet>
* Copyright 2016 Jay D Dee <jayddee246@gmail.com>
* Copyright 2017-2018 XMR-Stak <https://github.com/fireice-uk>, <https://github.com/psychocrypt>
* Copyright 2018-2019 SChernykh <https://github.com/SChernykh>
* Copyright 2016-2019 XMRig <https://github.com/xmrig>, <support@xmrig.com>
*
* 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 <http://www.gnu.org/licenses/>.
*/
#include "base/kernel/interfaces/IDnsListener.h"
#include "base/net/dns/Dns.h"
#include "base/tools/Handle.h"
namespace xmrig {
Storage<Dns> Dns::m_storage;
static const DnsRecord defaultRecord;
}
xmrig::Dns::Dns(IDnsListener *listener) :
m_hints(),
m_listener(listener),
m_status(0)
{
m_key = m_storage.add(this);
m_resolver = new uv_getaddrinfo_t;
m_resolver->data = m_storage.ptr(m_key);
m_hints.ai_family = AF_UNSPEC;
m_hints.ai_socktype = SOCK_STREAM;
m_hints.ai_protocol = IPPROTO_TCP;
}
xmrig::Dns::~Dns()
{
Handle::close(m_resolver);
m_storage.release(m_key);
}
bool xmrig::Dns::resolve(const String &host)
{
if (m_host != host) {
m_host = host;
clear();
}
m_status = uv_getaddrinfo(uv_default_loop(), m_resolver, Dns::onResolved, m_host.data(), nullptr, &m_hints);
return m_status == 0;
}
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<size_t>(rand()) % ipv6];
}
if (ipv4) {
return m_ipv4[ipv4 == 1 ? 0 : static_cast<size_t>(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);
}
clear();
addrinfo *ptr = res;
while (ptr != nullptr) {
if (ptr->ai_family == AF_INET) {
m_ipv4.push_back(ptr);
}
if (ptr->ai_family == AF_INET6) {
m_ipv6.push_back(ptr);
}
ptr = ptr->ai_next;
}
m_listener->onResolved(*this, status);
}
void xmrig::Dns::onResolved(uv_getaddrinfo_t *req, int status, addrinfo *res)
{
Dns *dns = m_storage.get(req->data);
if (dns) {
dns->onResolved(status, res);
}
uv_freeaddrinfo(res);
}

80
src/base/net/dns/Dns.h Normal file
View file

@ -0,0 +1,80 @@
/* XMRig
* Copyright 2010 Jeff Garzik <jgarzik@pobox.com>
* Copyright 2012-2014 pooler <pooler@litecoinpool.org>
* Copyright 2014 Lucas Jones <https://github.com/lucasjones>
* Copyright 2014-2016 Wolf9466 <https://github.com/OhGodAPet>
* Copyright 2016 Jay D Dee <jayddee246@gmail.com>
* Copyright 2017-2018 XMR-Stak <https://github.com/fireice-uk>, <https://github.com/psychocrypt>
* Copyright 2018-2019 SChernykh <https://github.com/SChernykh>
* Copyright 2016-2019 XMRig <https://github.com/xmrig>, <support@xmrig.com>
*
* 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 <http://www.gnu.org/licenses/>.
*/
#ifndef XMRIG_DNS_H
#define XMRIG_DNS_H
#include <vector>
#include <uv.h>
#include "base/net/dns/DnsRecord.h"
#include "base/net/tools/Storage.h"
#include "base/tools/String.h"
namespace xmrig {
class IDnsListener;
class Dns
{
public:
Dns(IDnsListener *listener);
~Dns();
inline bool isEmpty() const { return m_ipv4.empty() && m_ipv6.empty(); }
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;
IDnsListener *m_listener;
int m_status;
std::vector<DnsRecord> m_ipv4;
std::vector<DnsRecord> m_ipv6;
String m_host;
uintptr_t m_key;
uv_getaddrinfo_t *m_resolver;
static Storage<Dns> m_storage;
};
} /* namespace xmrig */
#endif /* XMRIG_DNS_H */

View file

@ -0,0 +1,66 @@
/* XMRig
* Copyright 2010 Jeff Garzik <jgarzik@pobox.com>
* Copyright 2012-2014 pooler <pooler@litecoinpool.org>
* Copyright 2014 Lucas Jones <https://github.com/lucasjones>
* Copyright 2014-2016 Wolf9466 <https://github.com/OhGodAPet>
* Copyright 2016 Jay D Dee <jayddee246@gmail.com>
* Copyright 2017-2018 XMR-Stak <https://github.com/fireice-uk>, <https://github.com/psychocrypt>
* Copyright 2018-2019 SChernykh <https://github.com/SChernykh>
* Copyright 2016-2019 XMRig <https://github.com/xmrig>, <support@xmrig.com>
*
* 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 <http://www.gnu.org/licenses/>.
*/
#include <uv.h>
#include "base/net/dns/DnsRecord.h"
xmrig::DnsRecord::DnsRecord(const addrinfo *addr) :
m_type(addr->ai_family == AF_INET6 ? AAAA : A)
{
char *buf = nullptr;
if (m_type == AAAA) {
buf = new char[45]();
uv_ip6_name(reinterpret_cast<sockaddr_in6*>(addr->ai_addr), buf, 45);
}
else {
buf = new char[16]();
uv_ip4_name(reinterpret_cast<sockaddr_in*>(addr->ai_addr), buf, 16);
}
m_ip = buf;
}
sockaddr *xmrig::DnsRecord::addr(uint16_t port) const
{
if (m_type == A) {
sockaddr_in *addr = new sockaddr_in();
uv_ip4_addr(m_ip.data(), port, addr);
return reinterpret_cast<sockaddr *>(addr);
}
else if (m_type == AAAA) {
sockaddr_in6 *addr = new sockaddr_in6();
uv_ip6_addr(m_ip.data(), port, addr);
return reinterpret_cast<sockaddr *>(addr);
}
return nullptr;
}

View file

@ -0,0 +1,66 @@
/* XMRig
* Copyright 2010 Jeff Garzik <jgarzik@pobox.com>
* Copyright 2012-2014 pooler <pooler@litecoinpool.org>
* Copyright 2014 Lucas Jones <https://github.com/lucasjones>
* Copyright 2014-2016 Wolf9466 <https://github.com/OhGodAPet>
* Copyright 2016 Jay D Dee <jayddee246@gmail.com>
* Copyright 2017-2018 XMR-Stak <https://github.com/fireice-uk>, <https://github.com/psychocrypt>
* Copyright 2018-2019 SChernykh <https://github.com/SChernykh>
* Copyright 2016-2019 XMRig <https://github.com/xmrig>, <support@xmrig.com>
*
* 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 <http://www.gnu.org/licenses/>.
*/
#ifndef XMRIG_DNSRECORD_H
#define XMRIG_DNSRECORD_H
struct addrinfo;
struct sockaddr;
#include "base/tools/String.h"
namespace xmrig {
class DnsRecord
{
public:
enum Type {
Unknown,
A,
AAAA
};
inline DnsRecord() : m_type(Unknown) {}
DnsRecord(const addrinfo *addr);
sockaddr *addr(uint16_t port = 0) const;
inline bool isValid() const { return m_type != Unknown; }
inline const String &ip() const { return m_ip; }
inline Type type() const { return m_type; }
private:
Type m_type;
String m_ip;
};
} /* namespace xmrig */
#endif /* XMRIG_DNSRECORD_H */

View file

@ -38,6 +38,7 @@
#include "base/kernel/interfaces/IClientListener.h"
#include "base/net/dns/Dns.h"
#include "base/net/stratum/Client.h"
#include "base/tools/Buffer.h"
#include "base/tools/Chrono.h"
@ -93,20 +94,13 @@ xmrig::Client::Client(int id, const char *agent, IClientListener *listener) :
m_socket(nullptr)
{
m_key = m_storage.add(this);
memset(m_ip, 0, sizeof(m_ip));
memset(&m_hints, 0, sizeof(m_hints));
m_resolver.data = m_storage.ptr(m_key);
m_hints.ai_family = AF_UNSPEC;
m_hints.ai_socktype = SOCK_STREAM;
m_hints.ai_protocol = IPPROTO_TCP;
m_dns = new Dns(this);
}
xmrig::Client::~Client()
{
delete m_dns;
delete m_socket;
}
@ -164,7 +158,7 @@ void xmrig::Client::tick(uint64_t now)
{
if (m_state == ConnectedState) {
if (m_expire && now > m_expire) {
LOG_DEBUG_ERR("[%s] timeout", m_pool.url());
LOG_DEBUG_ERR("[%s] timeout", url());
close();
}
else if (m_keepAlive && now > m_keepAlive) {
@ -265,6 +259,36 @@ int64_t xmrig::Client::submit(const JobResult &result)
}
void xmrig::Client::onResolved(const Dns &dns, int status)
{
assert(client->m_listener != nullptr);
if (!m_listener) {
return reconnect();
}
if (status < 0 && dns.isEmpty()) {
if (!isQuiet()) {
LOG_ERR("[%s] DNS error: \"%s\"", url(), uv_strerror(status));
}
return reconnect();
}
if (dns.isEmpty()) {
if (!isQuiet()) {
LOG_ERR("[%s] DNS error: \"No IPv4 (A) or IPv6 (AAAA) records found\"", url());
}
return reconnect();
}
const DnsRecord &record = dns.get();
m_ip = record.ip();
connect(record.addr(m_pool.port()));
}
bool xmrig::Client::close()
{
if (m_state == ClosingState) {
@ -384,7 +408,7 @@ bool xmrig::Client::parseJob(const rapidjson::Value &params, int *code)
}
if (!isQuiet()) {
LOG_WARN("[%s] duplicate job received, reconnect", m_pool.url());
LOG_WARN("[%s] duplicate job received, reconnect", url());
}
close();
@ -419,7 +443,7 @@ bool xmrig::Client::send(BIO *bio)
return true;
}
LOG_DEBUG("[%s] TLS send (%d bytes)", m_pool.url(), static_cast<int>(buf.len));
LOG_DEBUG("[%s] TLS send (%d bytes)", url(), static_cast<int>(buf.len));
bool result = false;
if (state() == ConnectedState && uv_is_writable(m_stream)) {
@ -430,7 +454,7 @@ bool xmrig::Client::send(BIO *bio)
}
}
else {
LOG_DEBUG_ERR("[%s] send failed, invalid state: %d", m_pool.url(), m_state);
LOG_DEBUG_ERR("[%s] send failed, invalid state: %d", url(), m_state);
}
(void) BIO_reset(bio);
@ -469,7 +493,7 @@ bool xmrig::Client::verifyAlgorithm(const Algorithm &algorithm) const
}
int xmrig::Client::resolve(const char *host)
int xmrig::Client::resolve(const String &host)
{
setState(HostLookupState);
@ -480,11 +504,11 @@ int xmrig::Client::resolve(const char *host)
m_failures = 0;
}
const int r = uv_getaddrinfo(uv_default_loop(), &m_resolver, Client::onResolved, host, nullptr, &m_hints);
if (r) {
if (!m_dns->resolve(host)) {
if (!isQuiet()) {
LOG_ERR("[%s:%u] getaddrinfo error: \"%s\"", host, m_pool.port(), uv_strerror(r));
LOG_ERR("[%s:%u] getaddrinfo error: \"%s\"", host.data(), m_pool.port(), uv_strerror(m_dns->status()));
}
return 1;
}
@ -502,7 +526,7 @@ int64_t xmrig::Client::send(const rapidjson::Document &doc)
const size_t size = buffer.GetSize();
if (size > (sizeof(m_sendBuf) - 2)) {
LOG_ERR("[%s] send failed: \"send buffer overflow: %zu > %zu\"", m_pool.url(), size, (sizeof(m_sendBuf) - 2));
LOG_ERR("[%s] send failed: \"send buffer overflow: %zu > %zu\"", url(), size, (sizeof(m_sendBuf) - 2));
close();
return -1;
}
@ -517,7 +541,7 @@ int64_t xmrig::Client::send(const rapidjson::Document &doc)
int64_t xmrig::Client::send(size_t size)
{
LOG_DEBUG("[%s] send (%d bytes): \"%s\"", m_pool.url(), size, m_sendBuf);
LOG_DEBUG("[%s] send (%d bytes): \"%s\"", url(), size, m_sendBuf);
# ifndef XMRIG_NO_TLS
if (isTLS()) {
@ -529,7 +553,7 @@ int64_t xmrig::Client::send(size_t size)
# endif
{
if (state() != ConnectedState || !uv_is_writable(m_stream)) {
LOG_DEBUG_ERR("[%s] send failed, invalid state: %d", m_pool.url(), m_state);
LOG_DEBUG_ERR("[%s] send failed, invalid state: %d", url(), m_state);
return -1;
}
@ -546,24 +570,6 @@ int64_t xmrig::Client::send(size_t size)
}
void xmrig::Client::connect(const std::vector<addrinfo*> &ipv4, const std::vector<addrinfo*> &ipv6)
{
addrinfo *addr = nullptr;
m_ipv6 = ipv4.empty() && !ipv6.empty();
if (m_ipv6) {
addr = ipv6[ipv6.size() == 1 ? 0 : rand() % ipv6.size()];
uv_ip6_name(reinterpret_cast<sockaddr_in6*>(addr->ai_addr), m_ip, 45);
}
else {
addr = ipv4[ipv4.size() == 1 ? 0 : rand() % ipv4.size()];
uv_ip4_name(reinterpret_cast<sockaddr_in*>(addr->ai_addr), m_ip, 16);
}
connect(addr->ai_addr);
}
void xmrig::Client::connect(sockaddr *addr)
{
setState(ConnectingState);
@ -616,12 +622,12 @@ void xmrig::Client::login()
doc.AddMember("method", "login", allocator);
Value params(kObjectType);
params.AddMember("login", StringRef(m_pool.user()), allocator);
params.AddMember("pass", StringRef(m_pool.password()), allocator);
params.AddMember("login", m_pool.user().toJSON(), allocator);
params.AddMember("pass", m_pool.password().toJSON(), allocator);
params.AddMember("agent", StringRef(m_agent), allocator);
if (m_pool.rigId()) {
params.AddMember("rigid", StringRef(m_pool.rigId()), allocator);
if (!m_pool.rigId().isNull()) {
params.AddMember("rigid", m_pool.rigId().toJSON(), allocator);
}
# ifdef XMRIG_PROXY_PROJECT
@ -668,11 +674,11 @@ void xmrig::Client::parse(char *line, size_t len)
{
startTimeout();
LOG_DEBUG("[%s] received (%d bytes): \"%s\"", m_pool.url(), len, line);
LOG_DEBUG("[%s] received (%d bytes): \"%s\"", url(), len, line);
if (len < 32 || line[0] != '{') {
if (!isQuiet()) {
LOG_ERR("[%s] JSON decode failed", m_pool.url());
LOG_ERR("[%s] JSON decode failed", url());
}
return;
@ -681,7 +687,7 @@ void xmrig::Client::parse(char *line, size_t len)
rapidjson::Document doc;
if (doc.ParseInsitu(line).HasParseError()) {
if (!isQuiet()) {
LOG_ERR("[%s] JSON decode failed: \"%s\"", m_pool.url(), rapidjson::GetParseError_En(doc.GetParseError()));
LOG_ERR("[%s] JSON decode failed: \"%s\"", url(), rapidjson::GetParseError_En(doc.GetParseError()));
}
return;
@ -741,7 +747,7 @@ void xmrig::Client::parseNotification(const char *method, const rapidjson::Value
{
if (error.IsObject()) {
if (!isQuiet()) {
LOG_ERR("[%s] error: \"%s\", code: %d", m_pool.url(), error["message"].GetString(), error["code"].GetInt());
LOG_ERR("[%s] error: \"%s\", code: %d", url(), error["message"].GetString(), error["code"].GetInt());
}
return;
}
@ -759,7 +765,7 @@ void xmrig::Client::parseNotification(const char *method, const rapidjson::Value
return;
}
LOG_WARN("[%s] unsupported method: \"%s\"", m_pool.url(), method);
LOG_WARN("[%s] unsupported method: \"%s\"", url(), method);
}
@ -775,7 +781,7 @@ void xmrig::Client::parseResponse(int64_t id, const rapidjson::Value &result, co
m_results.erase(it);
}
else if (!isQuiet()) {
LOG_ERR("[%s] error: \"%s\", code: %d", m_pool.url(), message, error["code"].GetInt());
LOG_ERR("[%s] error: \"%s\", code: %d", url(), message, error["code"].GetInt());
}
if (isCriticalError(message)) {
@ -793,7 +799,7 @@ void xmrig::Client::parseResponse(int64_t id, const rapidjson::Value &result, co
int code = -1;
if (!parseLogin(result, &code)) {
if (!isQuiet()) {
LOG_ERR("[%s] login error code: %d", m_pool.url(), code);
LOG_ERR("[%s] login error code: %d", url(), code);
}
close();
@ -831,7 +837,7 @@ void xmrig::Client::read(ssize_t nread)
if (nread < 0) {
if (!isQuiet()) {
LOG_ERR("[%s] read error: \"%s\"", m_pool.url(), uv_strerror(static_cast<int>(nread)));
LOG_ERR("[%s] read error: \"%s\"", url(), uv_strerror(static_cast<int>(nread)));
}
close();
@ -847,7 +853,7 @@ void xmrig::Client::read(ssize_t nread)
# ifndef XMRIG_NO_TLS
if (isTLS()) {
LOG_DEBUG("[%s] TLS received (%d bytes)", m_pool.url(), static_cast<int>(nread));
LOG_DEBUG("[%s] TLS received (%d bytes)", url(), static_cast<int>(nread));
m_tls->read(m_recvBuf.base(), m_recvBuf.pos());
m_recvBuf.reset();
@ -885,7 +891,7 @@ void xmrig::Client::reconnect()
void xmrig::Client::setState(SocketState state)
{
LOG_DEBUG("[%s] state: \"%s\"", m_pool.url(), states[state]);
LOG_DEBUG("[%s] state: \"%s\"", url(), states[state]);
if (m_state == state) {
return;
@ -945,7 +951,7 @@ void xmrig::Client::onConnect(uv_connect_t *req, int status)
if (status < 0) {
if (!client->isQuiet()) {
LOG_ERR("[%s] connect error: \"%s\"", client->m_pool.url(), uv_strerror(status));
LOG_ERR("[%s] connect error: \"%s\"", client->url(), uv_strerror(status));
}
delete req;
@ -971,53 +977,3 @@ void xmrig::Client::onRead(uv_stream_t *stream, ssize_t nread, const uv_buf_t *)
client->read(nread);
}
}
void xmrig::Client::onResolved(uv_getaddrinfo_t *req, int status, struct addrinfo *res)
{
auto client = getClient(req->data);
if (!client) {
return;
}
assert(client->m_listener != nullptr);
if (!client->m_listener) {
return client->reconnect();
}
if (status < 0) {
if (!client->isQuiet()) {
LOG_ERR("[%s] DNS error: \"%s\"", client->m_pool.url(), uv_strerror(status));
}
return client->reconnect();
}
addrinfo *ptr = res;
std::vector<addrinfo*> ipv4;
std::vector<addrinfo*> ipv6;
while (ptr != nullptr) {
if (ptr->ai_family == AF_INET) {
ipv4.push_back(ptr);
}
if (ptr->ai_family == AF_INET6) {
ipv6.push_back(ptr);
}
ptr = ptr->ai_next;
}
if (ipv4.empty() && ipv6.empty()) {
if (!client->isQuiet()) {
LOG_ERR("[%s] DNS error: \"No IPv4 (A) or IPv6 (AAAA) records found\"", client->m_pool.url());
}
uv_freeaddrinfo(res);
return client->reconnect();
}
client->connect(ipv4, ipv6);
uv_freeaddrinfo(res);
}

View file

@ -32,6 +32,7 @@
#include <vector>
#include "base/kernel/interfaces/IDnsListener.h"
#include "base/kernel/interfaces/ILineListener.h"
#include "base/net/stratum/Job.h"
#include "base/net/stratum/Pool.h"
@ -39,7 +40,7 @@
#include "base/net/tools/RecvBuf.h"
#include "base/net/tools/Storage.h"
#include "common/crypto/Algorithm.h"
#include "rapidjson/fwd.h"
typedef struct bio_st BIO;
@ -52,7 +53,7 @@ class IClientListener;
class JobResult;
class Client : public ILineListener
class Client : public IDnsListener, public ILineListener
{
public:
enum SocketState {
@ -111,6 +112,8 @@ public:
protected:
inline void onLine(char *line, size_t size) override { parse(line, size); }
void onResolved(const Dns &dns, int status) override;
private:
class Tls;
@ -121,10 +124,9 @@ private:
bool parseLogin(const rapidjson::Value &result, int *code);
bool send(BIO *bio);
bool verifyAlgorithm(const Algorithm &algorithm) const;
int resolve(const char *host);
int resolve(const String &host);
int64_t send(const rapidjson::Document &doc);
int64_t send(size_t size);
void connect(const std::vector<addrinfo*> &ipv4, const std::vector<addrinfo*> &ipv6);
void connect(sockaddr *addr);
void handshake();
void login();
@ -140,23 +142,22 @@ private:
void startTimeout();
inline bool isQuiet() const { return m_quiet || m_failures >= m_retries; }
inline const char *url() const { return m_pool.url(); }
inline void setExtension(Extension ext, bool enable) noexcept { m_extensions.set(ext, enable); }
static void onAllocBuffer(uv_handle_t *handle, size_t suggested_size, uv_buf_t *buf);
static void onClose(uv_handle_t *handle);
static void onConnect(uv_connect_t *req, int status);
static void onRead(uv_stream_t *stream, ssize_t nread, const uv_buf_t *buf);
static void onResolved(uv_getaddrinfo_t *req, int status, struct addrinfo *res);
static inline Client *getClient(void *data) { return m_storage.get(data); }
addrinfo m_hints;
bool m_enabled;
bool m_ipv6;
bool m_quiet;
char m_ip[46];
char m_sendBuf[2048];
const char *m_agent;
Dns *m_dns;
IClientListener *m_listener;
int m_id;
int m_retries;
@ -168,13 +169,13 @@ private:
SocketState m_state;
std::bitset<EXT_MAX> m_extensions;
std::map<int64_t, SubmitResult> m_results;
String m_ip;
String m_rpcId;
Tls *m_tls;
uint64_t m_expire;
uint64_t m_jobs;
uint64_t m_keepAlive;
uintptr_t m_key;
uv_getaddrinfo_t m_resolver;
uv_stream_t *m_stream;
uv_tcp_t *m_socket;

View file

@ -47,16 +47,19 @@
namespace xmrig {
static const char *kEnabled = "enabled";
static const char *kFingerprint = "tls-fingerprint";
static const char *kKeepalive = "keepalive";
static const char *kNicehash = "nicehash";
static const char *kPass = "pass";
static const char *kRigId = "rig-id";
static const char *kTls = "tls";
static const char *kUrl = "url";
static const char *kUser = "user";
static const char *kVariant = "variant";
static const char *kEnabled = "enabled";
static const char *kFingerprint = "tls-fingerprint";
static const char *kKeepalive = "keepalive";
static const char *kNicehash = "nicehash";
static const char *kPass = "pass";
static const char *kRigId = "rig-id";
static const char *kTls = "tls";
static const char *kUrl = "url";
static const char *kUser = "user";
static const char *kVariant = "variant";
const String Pool::kDefaultPassword = "x";
const String Pool::kDefaultUser = "x";
}

View file

@ -40,8 +40,9 @@ namespace xmrig {
class Pool
{
public:
constexpr static const char *kDefaultPassword = "x";
constexpr static const char *kDefaultUser = "x";
static const String kDefaultPassword;
static const String kDefaultUser;
constexpr static uint16_t kDefaultPort = 3333;
constexpr static int kKeepAliveTimeout = 60;
@ -57,28 +58,28 @@ public:
bool tls = false
);
inline Algorithm &algorithm() { return m_algorithm; }
inline bool isNicehash() const { return m_nicehash; }
inline bool isTLS() const { return m_tls; }
inline bool isValid() const { return !m_host.isNull() && m_port > 0; }
inline const char *fingerprint() const { return m_fingerprint.data(); }
inline const char *host() const { return m_host.data(); }
inline const char *password() const { return !m_password.isNull() ? m_password.data() : kDefaultPassword; }
inline const char *rigId() const { return m_rigId.data(); }
inline const char *url() const { return m_url.data(); }
inline const char *user() const { return !m_user.isNull() ? m_user.data() : kDefaultUser; }
inline const Algorithm &algorithm() const { return m_algorithm; }
inline const Algorithms &algorithms() const { return m_algorithms; }
inline const String &fingerprint() const { return m_fingerprint; }
inline const String &host() const { return m_host; }
inline const String &password() const { return !m_password.isNull() ? m_password : kDefaultPassword; }
inline const String &rigId() const { return m_rigId; }
inline const String &url() const { return m_url; }
inline const String &user() const { return !m_user.isNull() ? m_user : kDefaultUser; }
inline int keepAlive() const { return m_keepAlive; }
inline uint16_t port() const { return m_port; }
inline void setFingerprint(const char *fingerprint) { m_fingerprint = fingerprint; }
inline void setKeepAlive(int keepAlive) { m_keepAlive = keepAlive >= 0 ? keepAlive : 0; }
inline void setKeepAlive(bool enable) { setKeepAlive(enable ? kKeepAliveTimeout : 0); }
inline void setKeepAlive(int keepAlive) { m_keepAlive = keepAlive >= 0 ? keepAlive : 0; }
inline void setNicehash(bool nicehash) { m_nicehash = nicehash; }
inline void setPassword(const char *password) { m_password = password; }
inline void setRigId(const char *rigId) { m_rigId = rigId; }
inline void setTLS(bool tls) { m_tls = tls; }
inline void setUser(const char *user) { m_user = user; }
inline Algorithm &algorithm() { return m_algorithm; }
inline bool operator!=(const Pool &other) const { return !isEqual(other); }
inline bool operator==(const Pool &other) const { return isEqual(other); }