Add classes Dns, DnsRecord, IDnsListener.
This commit is contained in:
parent
3094741c64
commit
af3655c27e
10 changed files with 514 additions and 131 deletions
|
@ -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 ¶ms, 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);
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue