Added DaemonClient.
This commit is contained in:
parent
0d496aaf2f
commit
62012a1a50
20 changed files with 610 additions and 122 deletions
|
@ -108,6 +108,7 @@ if (WITH_HTTP)
|
||||||
src/base/net/http/HttpData.h
|
src/base/net/http/HttpData.h
|
||||||
src/base/net/http/HttpResponse.h
|
src/base/net/http/HttpResponse.h
|
||||||
src/base/net/http/HttpServer.h
|
src/base/net/http/HttpServer.h
|
||||||
|
src/base/net/stratum/DaemonClient.h
|
||||||
src/base/net/tools/TcpServer.h
|
src/base/net/tools/TcpServer.h
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -118,6 +119,7 @@ if (WITH_HTTP)
|
||||||
src/base/net/http/HttpContext.cpp
|
src/base/net/http/HttpContext.cpp
|
||||||
src/base/net/http/HttpResponse.cpp
|
src/base/net/http/HttpResponse.cpp
|
||||||
src/base/net/http/HttpServer.cpp
|
src/base/net/http/HttpServer.cpp
|
||||||
|
src/base/net/stratum/DaemonClient.cpp
|
||||||
src/base/net/tools/TcpServer.cpp
|
src/base/net/tools/TcpServer.cpp
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
@ -33,7 +33,7 @@ namespace xmrig {
|
||||||
|
|
||||||
|
|
||||||
class Algorithm;
|
class Algorithm;
|
||||||
class Client;
|
class IClient;
|
||||||
class JobResult;
|
class JobResult;
|
||||||
|
|
||||||
|
|
||||||
|
@ -43,7 +43,7 @@ public:
|
||||||
virtual ~IStrategy() = default;
|
virtual ~IStrategy() = default;
|
||||||
|
|
||||||
virtual bool isActive() const = 0;
|
virtual bool isActive() const = 0;
|
||||||
virtual Client *client() const = 0;
|
virtual IClient *client() const = 0;
|
||||||
virtual int64_t submit(const JobResult &result) = 0;
|
virtual int64_t submit(const JobResult &result) = 0;
|
||||||
virtual void connect() = 0;
|
virtual void connect() = 0;
|
||||||
virtual void resume() = 0;
|
virtual void resume() = 0;
|
||||||
|
|
|
@ -40,11 +40,11 @@ namespace xmrig {
|
||||||
static const char *kCRLF = "\r\n";
|
static const char *kCRLF = "\r\n";
|
||||||
|
|
||||||
|
|
||||||
class WriteBaton : public Baton<uv_write_t>
|
class ClientWriteBaton : public Baton<uv_write_t>
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
inline WriteBaton(const std::string &header, std::string &&body) :
|
inline ClientWriteBaton(const std::string &header, std::string &&body) :
|
||||||
m_body(body),
|
m_body(std::move(body)),
|
||||||
m_header(header)
|
m_header(header)
|
||||||
{
|
{
|
||||||
bufs[0].len = m_header.size();
|
bufs[0].len = m_header.size();
|
||||||
|
@ -63,7 +63,7 @@ public:
|
||||||
|
|
||||||
inline size_t count() const { return bufs[1].base == nullptr ? 1 : 2; }
|
inline size_t count() const { return bufs[1].base == nullptr ? 1 : 2; }
|
||||||
inline size_t size() const { return bufs[0].len + bufs[1].len; }
|
inline size_t size() const { return bufs[0].len + bufs[1].len; }
|
||||||
inline static void onWrite(uv_write_t *req, int) { delete reinterpret_cast<WriteBaton *>(req->data); }
|
inline static void onWrite(uv_write_t *req, int) { delete reinterpret_cast<ClientWriteBaton *>(req->data); }
|
||||||
|
|
||||||
|
|
||||||
uv_buf_t bufs[2];
|
uv_buf_t bufs[2];
|
||||||
|
@ -117,7 +117,9 @@ void xmrig::HttpClient::onResolved(const Dns &dns, int status)
|
||||||
this->status = status;
|
this->status = status;
|
||||||
|
|
||||||
if (status < 0 && dns.isEmpty()) {
|
if (status < 0 && dns.isEmpty()) {
|
||||||
LOG_ERR("[%s:%d] DNS error: \"%s\"", dns.host().data(), m_port, uv_strerror(status));
|
if (!m_quiet) {
|
||||||
|
LOG_ERR("[%s:%d] DNS error: \"%s\"", dns.host().data(), m_port, uv_strerror(status));
|
||||||
|
}
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -159,15 +161,15 @@ void xmrig::HttpClient::handshake()
|
||||||
void xmrig::HttpClient::read(const char *data, size_t size)
|
void xmrig::HttpClient::read(const char *data, size_t size)
|
||||||
{
|
{
|
||||||
if (parse(data, size) < size) {
|
if (parse(data, size) < size) {
|
||||||
close();
|
close(UV_EPROTO);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void xmrig::HttpClient::write(const std::string &header)
|
void xmrig::HttpClient::write(const std::string &header)
|
||||||
{
|
{
|
||||||
WriteBaton *baton = new WriteBaton(header, std::move(body));
|
ClientWriteBaton *baton = new ClientWriteBaton(header, std::move(body));
|
||||||
uv_write(&baton->req, stream(), baton->bufs, baton->count(), WriteBaton::onWrite);
|
uv_write(&baton->req, stream(), baton->bufs, baton->count(), ClientWriteBaton::onWrite);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -180,10 +182,12 @@ void xmrig::HttpClient::onConnect(uv_connect_t *req, int status)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (status < 0) {
|
if (status < 0) {
|
||||||
LOG_ERR("[%s:%d] connect error: \"%s\"", client->m_dns->host().data(), client->m_port, uv_strerror(status));
|
if (!client->m_quiet) {
|
||||||
|
LOG_ERR("[%s:%d] connect error: \"%s\"", client->m_dns->host().data(), client->m_port, uv_strerror(status));
|
||||||
|
}
|
||||||
|
|
||||||
delete req;
|
delete req;
|
||||||
client->close();
|
client->close(status);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -205,11 +209,11 @@ void xmrig::HttpClient::onConnect(uv_connect_t *req, int status)
|
||||||
if (nread >= 0) {
|
if (nread >= 0) {
|
||||||
client->read(buf->base, static_cast<size_t>(nread));
|
client->read(buf->base, static_cast<size_t>(nread));
|
||||||
} else {
|
} else {
|
||||||
if (nread != UV_EOF) {
|
if (!client->m_quiet && nread != UV_EOF) {
|
||||||
LOG_ERR("[%s:%d] read error: \"%s\"", client->m_dns->host().data(), client->m_port, uv_strerror(static_cast<int>(nread)));
|
LOG_ERR("[%s:%d] read error: \"%s\"", client->m_dns->host().data(), client->m_port, uv_strerror(static_cast<int>(nread)));
|
||||||
}
|
}
|
||||||
|
|
||||||
client->close();
|
client->close(static_cast<int>(nread));
|
||||||
}
|
}
|
||||||
|
|
||||||
delete [] buf->base;
|
delete [] buf->base;
|
||||||
|
|
|
@ -44,7 +44,8 @@ public:
|
||||||
HttpClient(int method, const String &url, IHttpListener *listener, const char *data = nullptr, size_t size = 0);
|
HttpClient(int method, const String &url, IHttpListener *listener, const char *data = nullptr, size_t size = 0);
|
||||||
~HttpClient() override;
|
~HttpClient() override;
|
||||||
|
|
||||||
inline uint16_t port() const { return m_port; }
|
inline uint16_t port() const { return m_port; }
|
||||||
|
inline void setQuiet(bool quiet) { m_quiet = quiet; }
|
||||||
|
|
||||||
bool connect(const String &host, uint16_t port);
|
bool connect(const String &host, uint16_t port);
|
||||||
const String &host() const;
|
const String &host() const;
|
||||||
|
@ -59,6 +60,7 @@ protected:
|
||||||
private:
|
private:
|
||||||
static void onConnect(uv_connect_t *req, int status);
|
static void onConnect(uv_connect_t *req, int status);
|
||||||
|
|
||||||
|
bool m_quiet;
|
||||||
Dns *m_dns;
|
Dns *m_dns;
|
||||||
uint16_t m_port;
|
uint16_t m_port;
|
||||||
};
|
};
|
||||||
|
|
|
@ -96,8 +96,13 @@ std::string xmrig::HttpContext::ip() const
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void xmrig::HttpContext::close()
|
void xmrig::HttpContext::close(int status)
|
||||||
{
|
{
|
||||||
|
if (status < 0 && m_listener) {
|
||||||
|
this->status = status;
|
||||||
|
m_listener->onHttpData(*this);
|
||||||
|
}
|
||||||
|
|
||||||
auto it = storage.find(id());
|
auto it = storage.find(id());
|
||||||
if (it != storage.end()) {
|
if (it != storage.end()) {
|
||||||
storage.erase(it);
|
storage.erase(it);
|
||||||
|
@ -203,8 +208,9 @@ void xmrig::HttpContext::attach(http_parser_settings *settings)
|
||||||
|
|
||||||
settings->on_message_complete = [](http_parser *parser) -> int
|
settings->on_message_complete = [](http_parser *parser) -> int
|
||||||
{
|
{
|
||||||
const HttpContext *ctx = static_cast<const HttpContext*>(parser->data);
|
HttpContext *ctx = static_cast<HttpContext*>(parser->data);
|
||||||
ctx->m_listener->onHttpData(*ctx);
|
ctx->m_listener->onHttpData(*ctx);
|
||||||
|
ctx->m_listener = nullptr;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
};
|
};
|
||||||
|
|
|
@ -56,7 +56,7 @@ public:
|
||||||
|
|
||||||
size_t parse(const char *data, size_t size);
|
size_t parse(const char *data, size_t size);
|
||||||
std::string ip() const;
|
std::string ip() const;
|
||||||
void close();
|
void close(int status = 0);
|
||||||
|
|
||||||
static HttpContext *get(uint64_t id);
|
static HttpContext *get(uint64_t id);
|
||||||
static void closeAll();
|
static void closeAll();
|
||||||
|
|
|
@ -96,7 +96,7 @@ void xmrig::HttpsClient::read(const char *data, size_t size)
|
||||||
X509 *cert = SSL_get_peer_certificate(m_ssl);
|
X509 *cert = SSL_get_peer_certificate(m_ssl);
|
||||||
if (!verify(cert)) {
|
if (!verify(cert)) {
|
||||||
X509_free(cert);
|
X509_free(cert);
|
||||||
return close();
|
return close(UV_EPROTO);
|
||||||
}
|
}
|
||||||
|
|
||||||
X509_free(cert);
|
X509_free(cert);
|
||||||
|
@ -142,7 +142,7 @@ void xmrig::HttpsClient::flush()
|
||||||
result = uv_try_write(stream(), &buf, 1) == buf.len;
|
result = uv_try_write(stream(), &buf, 1) == buf.len;
|
||||||
|
|
||||||
if (!result) {
|
if (!result) {
|
||||||
close();
|
close(UV_EIO);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -23,7 +23,16 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#include "base/kernel/interfaces/IClientListener.h"
|
||||||
#include "base/net/stratum/BaseClient.h"
|
#include "base/net/stratum/BaseClient.h"
|
||||||
|
#include "base/net/stratum/SubmitResult.h"
|
||||||
|
|
||||||
|
|
||||||
|
namespace xmrig {
|
||||||
|
|
||||||
|
int64_t BaseClient::m_sequence = 1;
|
||||||
|
|
||||||
|
} /* namespace xmrig */
|
||||||
|
|
||||||
|
|
||||||
xmrig::BaseClient::BaseClient(int id, IClientListener *listener) :
|
xmrig::BaseClient::BaseClient(int id, IClientListener *listener) :
|
||||||
|
@ -31,7 +40,23 @@ xmrig::BaseClient::BaseClient(int id, IClientListener *listener) :
|
||||||
m_listener(listener),
|
m_listener(listener),
|
||||||
m_id(id),
|
m_id(id),
|
||||||
m_retries(5),
|
m_retries(5),
|
||||||
|
m_failures(0),
|
||||||
|
m_state(UnconnectedState),
|
||||||
m_retryPause(5000)
|
m_retryPause(5000)
|
||||||
{
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool xmrig::BaseClient::handleSubmitResponse(int64_t id, const char *error)
|
||||||
|
{
|
||||||
|
auto it = m_results.find(id);
|
||||||
|
if (it != m_results.end()) {
|
||||||
|
it->second.done();
|
||||||
|
m_listener->onResultAccepted(this, it->second, error);
|
||||||
|
m_results.erase(it);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,6 +26,9 @@
|
||||||
#define XMRIG_BASECLIENT_H
|
#define XMRIG_BASECLIENT_H
|
||||||
|
|
||||||
|
|
||||||
|
#include <map>
|
||||||
|
|
||||||
|
|
||||||
#include "base/kernel/interfaces/IClient.h"
|
#include "base/kernel/interfaces/IClient.h"
|
||||||
#include "base/net/stratum/Job.h"
|
#include "base/net/stratum/Job.h"
|
||||||
#include "base/net/stratum/Pool.h"
|
#include "base/net/stratum/Pool.h"
|
||||||
|
@ -35,6 +38,7 @@ namespace xmrig {
|
||||||
|
|
||||||
|
|
||||||
class IClientListener;
|
class IClientListener;
|
||||||
|
class SubmitResult;
|
||||||
|
|
||||||
|
|
||||||
class BaseClient : public IClient
|
class BaseClient : public IClient
|
||||||
|
@ -55,15 +59,32 @@ public:
|
||||||
inline void setRetryPause(uint64_t ms) override { m_retryPause = ms; }
|
inline void setRetryPause(uint64_t ms) override { m_retryPause = ms; }
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
enum SocketState {
|
||||||
|
UnconnectedState,
|
||||||
|
HostLookupState,
|
||||||
|
ConnectingState,
|
||||||
|
ConnectedState,
|
||||||
|
ClosingState
|
||||||
|
};
|
||||||
|
|
||||||
|
inline bool isQuiet() const { return m_quiet || m_failures >= m_retries; }
|
||||||
|
|
||||||
|
bool handleSubmitResponse(int64_t id, const char *error = nullptr);
|
||||||
|
|
||||||
bool m_quiet;
|
bool m_quiet;
|
||||||
IClientListener *m_listener;
|
IClientListener *m_listener;
|
||||||
int m_id;
|
int m_id;
|
||||||
int m_retries;
|
int m_retries;
|
||||||
|
int64_t m_failures;
|
||||||
Job m_job;
|
Job m_job;
|
||||||
Pool m_pool;
|
Pool m_pool;
|
||||||
|
SocketState m_state;
|
||||||
|
std::map<int64_t, SubmitResult> m_results;
|
||||||
String m_ip;
|
String m_ip;
|
||||||
uint64_t m_retryPause;
|
uint64_t m_retryPause;
|
||||||
|
|
||||||
|
static int64_t m_sequence;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool m_enabled;
|
bool m_enabled;
|
||||||
};
|
};
|
||||||
|
|
|
@ -57,7 +57,6 @@
|
||||||
|
|
||||||
namespace xmrig {
|
namespace xmrig {
|
||||||
|
|
||||||
int64_t Client::m_sequence = 1;
|
|
||||||
Storage<Client> Client::m_storage;
|
Storage<Client> Client::m_storage;
|
||||||
|
|
||||||
} /* namespace xmrig */
|
} /* namespace xmrig */
|
||||||
|
@ -77,8 +76,6 @@ static const char *states[] = {
|
||||||
xmrig::Client::Client(int id, const char *agent, IClientListener *listener) :
|
xmrig::Client::Client(int id, const char *agent, IClientListener *listener) :
|
||||||
BaseClient(id, listener),
|
BaseClient(id, listener),
|
||||||
m_agent(agent),
|
m_agent(agent),
|
||||||
m_failures(0),
|
|
||||||
m_state(UnconnectedState),
|
|
||||||
m_tls(nullptr),
|
m_tls(nullptr),
|
||||||
m_expire(0),
|
m_expire(0),
|
||||||
m_jobs(0),
|
m_jobs(0),
|
||||||
|
@ -99,57 +96,6 @@ xmrig::Client::~Client()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void xmrig::Client::connect()
|
|
||||||
{
|
|
||||||
# ifdef XMRIG_FEATURE_TLS
|
|
||||||
if (m_pool.isTLS()) {
|
|
||||||
m_tls = new Tls(this);
|
|
||||||
}
|
|
||||||
# endif
|
|
||||||
|
|
||||||
resolve(m_pool.host());
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void xmrig::Client::connect(const Pool &pool)
|
|
||||||
{
|
|
||||||
setPool(pool);
|
|
||||||
connect();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void xmrig::Client::deleteLater()
|
|
||||||
{
|
|
||||||
if (!m_listener) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
m_listener = nullptr;
|
|
||||||
|
|
||||||
if (!disconnect()) {
|
|
||||||
m_storage.remove(m_key);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void xmrig::Client::tick(uint64_t now)
|
|
||||||
{
|
|
||||||
if (m_state == ConnectedState) {
|
|
||||||
if (m_expire && now > m_expire) {
|
|
||||||
LOG_DEBUG_ERR("[%s] timeout", url());
|
|
||||||
close();
|
|
||||||
}
|
|
||||||
else if (m_keepAlive && now > m_keepAlive) {
|
|
||||||
ping();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (m_expire && now > m_expire && m_state == ConnectingState) {
|
|
||||||
connect();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
bool xmrig::Client::disconnect()
|
bool xmrig::Client::disconnect()
|
||||||
{
|
{
|
||||||
m_keepAlive = 0;
|
m_keepAlive = 0;
|
||||||
|
@ -247,6 +193,57 @@ int64_t xmrig::Client::submit(const JobResult &result)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void xmrig::Client::connect()
|
||||||
|
{
|
||||||
|
# ifdef XMRIG_FEATURE_TLS
|
||||||
|
if (m_pool.isTLS()) {
|
||||||
|
m_tls = new Tls(this);
|
||||||
|
}
|
||||||
|
# endif
|
||||||
|
|
||||||
|
resolve(m_pool.host());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void xmrig::Client::connect(const Pool &pool)
|
||||||
|
{
|
||||||
|
setPool(pool);
|
||||||
|
connect();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void xmrig::Client::deleteLater()
|
||||||
|
{
|
||||||
|
if (!m_listener) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_listener = nullptr;
|
||||||
|
|
||||||
|
if (!disconnect()) {
|
||||||
|
m_storage.remove(m_key);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void xmrig::Client::tick(uint64_t now)
|
||||||
|
{
|
||||||
|
if (m_state == ConnectedState) {
|
||||||
|
if (m_expire && now > m_expire) {
|
||||||
|
LOG_DEBUG_ERR("[%s] timeout", url());
|
||||||
|
close();
|
||||||
|
}
|
||||||
|
else if (m_keepAlive && now > m_keepAlive) {
|
||||||
|
ping();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_expire && now > m_expire && m_state == ConnectingState) {
|
||||||
|
connect();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void xmrig::Client::onResolved(const Dns &dns, int status)
|
void xmrig::Client::onResolved(const Dns &dns, int status)
|
||||||
{
|
{
|
||||||
assert(m_listener != nullptr);
|
assert(m_listener != nullptr);
|
||||||
|
@ -749,14 +746,8 @@ void xmrig::Client::parseResponse(int64_t id, const rapidjson::Value &result, co
|
||||||
if (error.IsObject()) {
|
if (error.IsObject()) {
|
||||||
const char *message = error["message"].GetString();
|
const char *message = error["message"].GetString();
|
||||||
|
|
||||||
auto it = m_results.find(id);
|
if (!handleSubmitResponse(id, message) && !isQuiet()) {
|
||||||
if (it != m_results.end()) {
|
LOG_ERR("[%s] error: " RED_BOLD("\"%s\"") RED_S ", code: %d", url(), message, error["code"].GetInt());
|
||||||
it->second.done();
|
|
||||||
m_listener->onResultAccepted(this, it->second, message);
|
|
||||||
m_results.erase(it);
|
|
||||||
}
|
|
||||||
else if (!isQuiet()) {
|
|
||||||
LOG_ERR("[%s] error: \"%s\", code: %d", url(), message, error["code"].GetInt());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isCriticalError(message)) {
|
if (isCriticalError(message)) {
|
||||||
|
@ -787,12 +778,7 @@ void xmrig::Client::parseResponse(int64_t id, const rapidjson::Value &result, co
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto it = m_results.find(id);
|
handleSubmitResponse(id);
|
||||||
if (it != m_results.end()) {
|
|
||||||
it->second.done();
|
|
||||||
m_listener->onResultAccepted(this, it->second, nullptr);
|
|
||||||
m_results.erase(it);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -43,7 +43,6 @@
|
||||||
#include "common/crypto/Algorithm.h"
|
#include "common/crypto/Algorithm.h"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
typedef struct bio_st BIO;
|
typedef struct bio_st BIO;
|
||||||
|
|
||||||
|
|
||||||
|
@ -68,6 +67,7 @@ public:
|
||||||
Client(int id, const char *agent, IClientListener *listener);
|
Client(int id, const char *agent, IClientListener *listener);
|
||||||
~Client() override;
|
~Client() override;
|
||||||
|
|
||||||
|
protected:
|
||||||
bool disconnect() override;
|
bool disconnect() override;
|
||||||
bool isTLS() const override;
|
bool isTLS() const override;
|
||||||
const char *tlsFingerprint() const override;
|
const char *tlsFingerprint() const override;
|
||||||
|
@ -78,23 +78,13 @@ public:
|
||||||
void deleteLater() override;
|
void deleteLater() override;
|
||||||
void tick(uint64_t now) override;
|
void tick(uint64_t now) override;
|
||||||
|
|
||||||
inline bool hasExtension(Extension extension) const noexcept override { return m_extensions.test(extension); }
|
|
||||||
inline const char *mode() const override { return "pool"; }
|
|
||||||
|
|
||||||
protected:
|
|
||||||
inline void onLine(char *line, size_t size) override { parse(line, size); }
|
|
||||||
|
|
||||||
void onResolved(const Dns &dns, int status) override;
|
void onResolved(const Dns &dns, int status) override;
|
||||||
|
|
||||||
private:
|
inline bool hasExtension(Extension extension) const noexcept override { return m_extensions.test(extension); }
|
||||||
enum SocketState {
|
inline const char *mode() const override { return "pool"; }
|
||||||
UnconnectedState,
|
inline void onLine(char *line, size_t size) override { parse(line, size); }
|
||||||
HostLookupState,
|
|
||||||
ConnectingState,
|
|
||||||
ConnectedState,
|
|
||||||
ClosingState
|
|
||||||
};
|
|
||||||
|
|
||||||
|
private:
|
||||||
class Tls;
|
class Tls;
|
||||||
|
|
||||||
bool close();
|
bool close();
|
||||||
|
@ -120,7 +110,6 @@ private:
|
||||||
void setState(SocketState state);
|
void setState(SocketState state);
|
||||||
void startTimeout();
|
void startTimeout();
|
||||||
|
|
||||||
inline bool isQuiet() const { return m_quiet || m_failures >= m_retries; }
|
|
||||||
inline const char *url() const { return m_pool.url(); }
|
inline const char *url() const { return m_pool.url(); }
|
||||||
inline SocketState state() const { return m_state; }
|
inline SocketState state() const { return m_state; }
|
||||||
inline void setExtension(Extension ext, bool enable) noexcept { m_extensions.set(ext, enable); }
|
inline void setExtension(Extension ext, bool enable) noexcept { m_extensions.set(ext, enable); }
|
||||||
|
@ -136,11 +125,8 @@ private:
|
||||||
char m_sendBuf[2048];
|
char m_sendBuf[2048];
|
||||||
const char *m_agent;
|
const char *m_agent;
|
||||||
Dns *m_dns;
|
Dns *m_dns;
|
||||||
int64_t m_failures;
|
|
||||||
RecvBuf<kInputBufferSize> m_recvBuf;
|
RecvBuf<kInputBufferSize> m_recvBuf;
|
||||||
SocketState m_state;
|
|
||||||
std::bitset<EXT_MAX> m_extensions;
|
std::bitset<EXT_MAX> m_extensions;
|
||||||
std::map<int64_t, SubmitResult> m_results;
|
|
||||||
String m_rpcId;
|
String m_rpcId;
|
||||||
Tls *m_tls;
|
Tls *m_tls;
|
||||||
uint64_t m_expire;
|
uint64_t m_expire;
|
||||||
|
@ -150,7 +136,6 @@ private:
|
||||||
uv_stream_t *m_stream;
|
uv_stream_t *m_stream;
|
||||||
uv_tcp_t *m_socket;
|
uv_tcp_t *m_socket;
|
||||||
|
|
||||||
static int64_t m_sequence;
|
|
||||||
static Storage<Client> m_storage;
|
static Storage<Client> m_storage;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
350
src/base/net/stratum/DaemonClient.cpp
Normal file
350
src/base/net/stratum/DaemonClient.cpp
Normal file
|
@ -0,0 +1,350 @@
|
||||||
|
/* 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 2019 Howard Chu <https://github.com/hyc>
|
||||||
|
* 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 <algorithm>
|
||||||
|
#include <assert.h>
|
||||||
|
|
||||||
|
|
||||||
|
#include "3rdparty/http-parser/http_parser.h"
|
||||||
|
#include "base/io/Json.h"
|
||||||
|
#include "base/io/log/Log.h"
|
||||||
|
#include "base/kernel/interfaces/IClientListener.h"
|
||||||
|
#include "base/net/http/HttpClient.h"
|
||||||
|
#include "base/net/stratum/DaemonClient.h"
|
||||||
|
#include "base/net/stratum/SubmitResult.h"
|
||||||
|
#include "base/tools/Buffer.h"
|
||||||
|
#include "base/tools/Timer.h"
|
||||||
|
#include "net/JobResult.h"
|
||||||
|
#include "rapidjson/document.h"
|
||||||
|
#include "rapidjson/error/en.h"
|
||||||
|
#include "rapidjson/stringbuffer.h"
|
||||||
|
#include "rapidjson/writer.h"
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef XMRIG_FEATURE_TLS
|
||||||
|
# include "base/net/http/HttpsClient.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
xmrig::DaemonClient::DaemonClient(int id, IClientListener *listener) :
|
||||||
|
BaseClient(id, listener)
|
||||||
|
{
|
||||||
|
m_timer = new Timer(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
xmrig::DaemonClient::~DaemonClient()
|
||||||
|
{
|
||||||
|
delete m_timer;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool xmrig::DaemonClient::disconnect()
|
||||||
|
{
|
||||||
|
setState(UnconnectedState);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool xmrig::DaemonClient::isTLS() const
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const char *xmrig::DaemonClient::tlsFingerprint() const
|
||||||
|
{
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const char *xmrig::DaemonClient::tlsVersion() const
|
||||||
|
{
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int64_t xmrig::DaemonClient::submit(const JobResult &result)
|
||||||
|
{
|
||||||
|
if (result.jobId != (m_blocktemplate.data() + m_blocktemplate.size() - 48)) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
Buffer::toHex(reinterpret_cast<const uint8_t *>(&result.nonce), 4, m_blocktemplate.data() + 78);
|
||||||
|
|
||||||
|
using namespace rapidjson;
|
||||||
|
Document doc(kObjectType);
|
||||||
|
auto &allocator = doc.GetAllocator();
|
||||||
|
|
||||||
|
doc.AddMember("id", m_sequence, allocator);
|
||||||
|
doc.AddMember("jsonrpc", "2.0", allocator);
|
||||||
|
doc.AddMember("method", "submitblock", allocator);
|
||||||
|
|
||||||
|
Value params(kArrayType);
|
||||||
|
params.PushBack(m_blocktemplate.toJSON(), allocator);
|
||||||
|
|
||||||
|
doc.AddMember("params", params, allocator);
|
||||||
|
|
||||||
|
# ifdef XMRIG_PROXY_PROJECT
|
||||||
|
m_results[m_sequence] = SubmitResult(m_sequence, result.diff, result.actualDiff(), result.id);
|
||||||
|
# else
|
||||||
|
m_results[m_sequence] = SubmitResult(m_sequence, result.diff, result.actualDiff());
|
||||||
|
# endif
|
||||||
|
|
||||||
|
send(HTTP_POST, "/json_rpc", doc);
|
||||||
|
|
||||||
|
return m_sequence++;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void xmrig::DaemonClient::connect()
|
||||||
|
{
|
||||||
|
setState(ConnectingState);
|
||||||
|
getBlockTemplate();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void xmrig::DaemonClient::connect(const Pool &pool)
|
||||||
|
{
|
||||||
|
setPool(pool);
|
||||||
|
connect();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void xmrig::DaemonClient::onHttpData(const HttpData &data)
|
||||||
|
{
|
||||||
|
if (data.status != HTTP_STATUS_OK) {
|
||||||
|
return retry();
|
||||||
|
}
|
||||||
|
|
||||||
|
LOG_DEBUG("[%s:%d] received (%d bytes): \"%.*s\"", m_pool.host().data(), m_pool.port(), static_cast<int>(data.body.size()), static_cast<int>(data.body.size()), data.body.c_str());
|
||||||
|
|
||||||
|
m_ip = static_cast<const HttpContext &>(data).ip().c_str();
|
||||||
|
|
||||||
|
rapidjson::Document doc;
|
||||||
|
if (doc.Parse(data.body.c_str()).HasParseError()) {
|
||||||
|
if (!isQuiet()) {
|
||||||
|
LOG_ERR("[%s:%d] JSON decode failed: \"%s\"", m_pool.host().data(), m_pool.port(), rapidjson::GetParseError_En(doc.GetParseError()));
|
||||||
|
}
|
||||||
|
|
||||||
|
return retry();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (data.method == HTTP_GET && data.url == "/getheight") {
|
||||||
|
if (m_job.height() != Json::getUint64(doc, "height")) {
|
||||||
|
getBlockTemplate();
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!parseResponse(Json::getInt64(doc, "id", -1), Json::getObject(doc, "result"), Json::getObject(doc, "error"))) {
|
||||||
|
retry();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void xmrig::DaemonClient::onTimer(const Timer *)
|
||||||
|
{
|
||||||
|
if (m_state == ConnectingState) {
|
||||||
|
getBlockTemplate();
|
||||||
|
}
|
||||||
|
else if (m_state == ConnectedState) {
|
||||||
|
send(HTTP_GET, "/getheight");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool xmrig::DaemonClient::parseJob(const rapidjson::Value ¶ms, int *code)
|
||||||
|
{
|
||||||
|
Job job(m_id, false, m_pool.algorithm(), String());
|
||||||
|
|
||||||
|
String blocktemplate = Json::getString(params, "blocktemplate_blob");
|
||||||
|
if (blocktemplate.isNull() || !job.setBlob(Json::getString(params, "blockhashing_blob"))) {
|
||||||
|
*code = 4;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
job.setHeight(Json::getUint64(params, "height"));
|
||||||
|
job.setDiff(Json::getUint64(params, "difficulty"));
|
||||||
|
job.setId(blocktemplate.data() + blocktemplate.size() - 48);
|
||||||
|
|
||||||
|
m_job = std::move(job);
|
||||||
|
m_blocktemplate = std::move(blocktemplate);
|
||||||
|
|
||||||
|
if (m_state == ConnectingState) {
|
||||||
|
setState(ConnectedState);
|
||||||
|
}
|
||||||
|
|
||||||
|
m_listener->onJobReceived(this, m_job, params);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool xmrig::DaemonClient::parseResponse(int64_t id, const rapidjson::Value &result, const rapidjson::Value &error)
|
||||||
|
{
|
||||||
|
if (id == -1) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (error.IsObject()) {
|
||||||
|
const char *message = error["message"].GetString();
|
||||||
|
|
||||||
|
if (!handleSubmitResponse(id, message) && !isQuiet()) {
|
||||||
|
LOG_ERR("[%s:%d] error: " RED_BOLD("\"%s\"") RED_S ", code: %d", m_pool.host().data(), m_pool.port(), message, error["code"].GetInt());
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!result.IsObject()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
int code = -1;
|
||||||
|
if (result.HasMember("blocktemplate_blob") && parseJob(result, &code)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (handleSubmitResponse(id)) {
|
||||||
|
getBlockTemplate();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int64_t xmrig::DaemonClient::getBlockTemplate()
|
||||||
|
{
|
||||||
|
using namespace rapidjson;
|
||||||
|
Document doc(kObjectType);
|
||||||
|
auto &allocator = doc.GetAllocator();
|
||||||
|
|
||||||
|
doc.AddMember("id", m_sequence, allocator);
|
||||||
|
doc.AddMember("jsonrpc", "2.0", allocator);
|
||||||
|
doc.AddMember("method", "getblocktemplate", allocator);
|
||||||
|
|
||||||
|
Value params(kObjectType);
|
||||||
|
params.AddMember("wallet_address", m_pool.user().toJSON(), allocator);
|
||||||
|
params.AddMember("reserve_size", 8, allocator);
|
||||||
|
|
||||||
|
doc.AddMember("params", params, allocator);
|
||||||
|
|
||||||
|
send(HTTP_POST, "/json_rpc", doc);
|
||||||
|
|
||||||
|
return m_sequence++;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void xmrig::DaemonClient::retry()
|
||||||
|
{
|
||||||
|
m_failures++;
|
||||||
|
m_listener->onClose(this, static_cast<int>(m_failures));
|
||||||
|
|
||||||
|
if (m_failures == -1) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_state == ConnectedState) {
|
||||||
|
setState(ConnectingState);
|
||||||
|
}
|
||||||
|
|
||||||
|
m_timer->stop();
|
||||||
|
m_timer->start(m_retryPause, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void xmrig::DaemonClient::send(int method, const char *url, const char *data, size_t size)
|
||||||
|
{
|
||||||
|
LOG_DEBUG("[%s:%d] " MAGENTA_BOLD("\"%s %s\"") BLACK_BOLD_S " send (%zu bytes): \"%.*s\"",
|
||||||
|
m_pool.host().data(),
|
||||||
|
m_pool.port(),
|
||||||
|
http_method_str(static_cast<http_method>(method)),
|
||||||
|
url,
|
||||||
|
size,
|
||||||
|
static_cast<int>(size),
|
||||||
|
data);
|
||||||
|
|
||||||
|
HttpClient *client;
|
||||||
|
# ifdef XMRIG_FEATURE_TLS
|
||||||
|
if (m_pool.isTLS()) {
|
||||||
|
client = new HttpsClient(method, url, this, data, size);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
# endif
|
||||||
|
{
|
||||||
|
client = new HttpClient(method, url, this, data, size);
|
||||||
|
}
|
||||||
|
|
||||||
|
client->setQuiet(isQuiet());
|
||||||
|
client->connect(m_pool.host(), m_pool.port());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void xmrig::DaemonClient::send(int method, const char *url, const rapidjson::Document &doc)
|
||||||
|
{
|
||||||
|
using namespace rapidjson;
|
||||||
|
|
||||||
|
StringBuffer buffer(nullptr, 512);
|
||||||
|
Writer<StringBuffer> writer(buffer);
|
||||||
|
doc.Accept(writer);
|
||||||
|
|
||||||
|
send(method, url, buffer.GetString(), buffer.GetSize());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void xmrig::DaemonClient::setState(SocketState state)
|
||||||
|
{
|
||||||
|
assert(m_state != state);
|
||||||
|
if (m_state == state) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_state = state;
|
||||||
|
|
||||||
|
switch (state) {
|
||||||
|
case ConnectedState:
|
||||||
|
{
|
||||||
|
m_failures = 0;
|
||||||
|
m_listener->onLoginSuccess(this);
|
||||||
|
|
||||||
|
const uint64_t interval = std::max<uint64_t>(20, m_pool.pollInterval());
|
||||||
|
m_timer->start(interval, interval);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case UnconnectedState:
|
||||||
|
m_failures = -1;
|
||||||
|
m_timer->stop();
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
78
src/base/net/stratum/DaemonClient.h
Normal file
78
src/base/net/stratum/DaemonClient.h
Normal file
|
@ -0,0 +1,78 @@
|
||||||
|
/* 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 2019 Howard Chu <https://github.com/hyc>
|
||||||
|
* 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_DAEMONCLIENT_H
|
||||||
|
#define XMRIG_DAEMONCLIENT_H
|
||||||
|
|
||||||
|
|
||||||
|
#include "base/net/stratum/BaseClient.h"
|
||||||
|
#include "base/kernel/interfaces/ITimerListener.h"
|
||||||
|
#include "base/kernel/interfaces/IHttpListener.h"
|
||||||
|
|
||||||
|
|
||||||
|
namespace xmrig {
|
||||||
|
|
||||||
|
|
||||||
|
class DaemonClient : public BaseClient, public ITimerListener, public IHttpListener
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
DaemonClient(int id, IClientListener *listener);
|
||||||
|
~DaemonClient() override;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
bool disconnect() override;
|
||||||
|
bool isTLS() const override;
|
||||||
|
const char *tlsFingerprint() const override;
|
||||||
|
const char *tlsVersion() const override;
|
||||||
|
int64_t submit(const JobResult &result) override;
|
||||||
|
void connect() override;
|
||||||
|
void connect(const Pool &pool) override;
|
||||||
|
|
||||||
|
void onHttpData(const HttpData &data) override;
|
||||||
|
void onTimer(const Timer *timer) override;
|
||||||
|
|
||||||
|
inline bool hasExtension(Extension) const noexcept override { return false; }
|
||||||
|
inline const char *mode() const override { return "daemon"; }
|
||||||
|
inline void deleteLater() override { delete this; }
|
||||||
|
inline void tick(uint64_t) override {}
|
||||||
|
|
||||||
|
private:
|
||||||
|
bool parseJob(const rapidjson::Value ¶ms, int *code);
|
||||||
|
bool parseResponse(int64_t id, const rapidjson::Value &result, const rapidjson::Value &error);
|
||||||
|
int64_t getBlockTemplate();
|
||||||
|
void retry();
|
||||||
|
void send(int method, const char *url, const char *data = nullptr, size_t size = 0);
|
||||||
|
void send(int method, const char *url, const rapidjson::Document &doc);
|
||||||
|
void setState(SocketState state);
|
||||||
|
|
||||||
|
String m_blocktemplate;
|
||||||
|
Timer *m_timer;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
} /* namespace xmrig */
|
||||||
|
|
||||||
|
|
||||||
|
#endif /* XMRIG_DAEMONCLIENT_H */
|
|
@ -84,6 +84,7 @@ public:
|
||||||
inline const String &user() const { return !m_user.isNull() ? m_user : kDefaultUser; }
|
inline const String &user() const { return !m_user.isNull() ? m_user : kDefaultUser; }
|
||||||
inline int keepAlive() const { return m_keepAlive; }
|
inline int keepAlive() const { return m_keepAlive; }
|
||||||
inline uint16_t port() const { return m_port; }
|
inline uint16_t port() const { return m_port; }
|
||||||
|
inline uint64_t pollInterval() const { return m_pollInterval; }
|
||||||
|
|
||||||
inline bool operator!=(const Pool &other) const { return !isEqual(other); }
|
inline bool operator!=(const Pool &other) const { return !isEqual(other); }
|
||||||
inline bool operator==(const Pool &other) const { return isEqual(other); }
|
inline bool operator==(const Pool &other) const { return isEqual(other); }
|
||||||
|
|
|
@ -29,6 +29,11 @@
|
||||||
#include "common/Platform.h"
|
#include "common/Platform.h"
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef XMRIG_FEATURE_HTTP
|
||||||
|
# include "base/net/stratum/DaemonClient.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
xmrig::FailoverStrategy::FailoverStrategy(const std::vector<Pool> &pools, int retryPause, int retries, IStrategyListener *listener, bool quiet) :
|
xmrig::FailoverStrategy::FailoverStrategy(const std::vector<Pool> &pools, int retryPause, int retries, IStrategyListener *listener, bool quiet) :
|
||||||
m_quiet(quiet),
|
m_quiet(quiet),
|
||||||
m_retries(retries),
|
m_retries(retries),
|
||||||
|
@ -56,7 +61,7 @@ xmrig::FailoverStrategy::FailoverStrategy(int retryPause, int retries, IStrategy
|
||||||
|
|
||||||
xmrig::FailoverStrategy::~FailoverStrategy()
|
xmrig::FailoverStrategy::~FailoverStrategy()
|
||||||
{
|
{
|
||||||
for (Client *client : m_pools) {
|
for (IClient *client : m_pools) {
|
||||||
client->deleteLater();
|
client->deleteLater();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -64,7 +69,15 @@ xmrig::FailoverStrategy::~FailoverStrategy()
|
||||||
|
|
||||||
void xmrig::FailoverStrategy::add(const Pool &pool)
|
void xmrig::FailoverStrategy::add(const Pool &pool)
|
||||||
{
|
{
|
||||||
Client *client = new Client(static_cast<int>(m_pools.size()), Platform::userAgent(), this);
|
const int id = static_cast<int>(m_pools.size());
|
||||||
|
|
||||||
|
# ifdef XMRIG_FEATURE_HTTP
|
||||||
|
IClient *client = !pool.isDaemon() ? static_cast<IClient *>(new Client(id, Platform::userAgent(), this))
|
||||||
|
: static_cast<IClient *>(new DaemonClient(id, this));
|
||||||
|
# else
|
||||||
|
IClient *client = new Client(id, Platform::userAgent(), this);
|
||||||
|
# endif
|
||||||
|
|
||||||
client->setPool(pool);
|
client->setPool(pool);
|
||||||
client->setRetries(m_retries);
|
client->setRetries(m_retries);
|
||||||
client->setRetryPause(m_retryPause * 1000);
|
client->setRetryPause(m_retryPause * 1000);
|
||||||
|
@ -102,7 +115,7 @@ void xmrig::FailoverStrategy::resume()
|
||||||
|
|
||||||
void xmrig::FailoverStrategy::setAlgo(const xmrig::Algorithm &algo)
|
void xmrig::FailoverStrategy::setAlgo(const xmrig::Algorithm &algo)
|
||||||
{
|
{
|
||||||
for (Client *client : m_pools) {
|
for (IClient *client : m_pools) {
|
||||||
client->setAlgo(algo);
|
client->setAlgo(algo);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -123,7 +136,7 @@ void xmrig::FailoverStrategy::stop()
|
||||||
|
|
||||||
void xmrig::FailoverStrategy::tick(uint64_t now)
|
void xmrig::FailoverStrategy::tick(uint64_t now)
|
||||||
{
|
{
|
||||||
for (Client *client : m_pools) {
|
for (IClient *client : m_pools) {
|
||||||
client->tick(now);
|
client->tick(now);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -52,7 +52,7 @@ public:
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
inline bool isActive() const override { return m_active >= 0; }
|
inline bool isActive() const override { return m_active >= 0; }
|
||||||
inline Client *client() const override { return active(); }
|
inline IClient *client() const override { return active(); }
|
||||||
inline void onLogin(IClient *, rapidjson::Document &, rapidjson::Value &) override {}
|
inline void onLogin(IClient *, rapidjson::Document &, rapidjson::Value &) override {}
|
||||||
|
|
||||||
int64_t submit(const JobResult &result) override;
|
int64_t submit(const JobResult &result) override;
|
||||||
|
@ -68,7 +68,7 @@ protected:
|
||||||
void onResultAccepted(IClient *client, const SubmitResult &result, const char *error) override;
|
void onResultAccepted(IClient *client, const SubmitResult &result, const char *error) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
inline Client *active() const { return m_pools[static_cast<size_t>(m_active)]; }
|
inline IClient *active() const { return m_pools[static_cast<size_t>(m_active)]; }
|
||||||
|
|
||||||
const bool m_quiet;
|
const bool m_quiet;
|
||||||
const int m_retries;
|
const int m_retries;
|
||||||
|
@ -76,7 +76,7 @@ private:
|
||||||
int m_active;
|
int m_active;
|
||||||
IStrategyListener *m_listener;
|
IStrategyListener *m_listener;
|
||||||
size_t m_index;
|
size_t m_index;
|
||||||
std::vector<Client*> m_pools;
|
std::vector<IClient*> m_pools;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -29,11 +29,26 @@
|
||||||
#include "common/Platform.h"
|
#include "common/Platform.h"
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef XMRIG_FEATURE_HTTP
|
||||||
|
# include "base/net/stratum/DaemonClient.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
xmrig::SinglePoolStrategy::SinglePoolStrategy(const Pool &pool, int retryPause, int retries, IStrategyListener *listener, bool quiet) :
|
xmrig::SinglePoolStrategy::SinglePoolStrategy(const Pool &pool, int retryPause, int retries, IStrategyListener *listener, bool quiet) :
|
||||||
m_active(false),
|
m_active(false),
|
||||||
m_listener(listener)
|
m_listener(listener)
|
||||||
{
|
{
|
||||||
|
# ifdef XMRIG_FEATURE_HTTP
|
||||||
|
if (!pool.isDaemon()) {
|
||||||
|
m_client = new Client(0, Platform::userAgent(), this);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
m_client = new DaemonClient(0, this);
|
||||||
|
}
|
||||||
|
# else
|
||||||
m_client = new Client(0, Platform::userAgent(), this);
|
m_client = new Client(0, Platform::userAgent(), this);
|
||||||
|
# endif
|
||||||
|
|
||||||
m_client->setPool(pool);
|
m_client->setPool(pool);
|
||||||
m_client->setRetries(retries);
|
m_client->setRetries(retries);
|
||||||
m_client->setRetryPause(retryPause * 1000);
|
m_client->setRetryPause(retryPause * 1000);
|
||||||
|
|
|
@ -46,7 +46,7 @@ public:
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
inline bool isActive() const override { return m_active; }
|
inline bool isActive() const override { return m_active; }
|
||||||
inline Client *client() const override { return m_client; }
|
inline IClient *client() const override { return m_client; }
|
||||||
inline void onLogin(IClient *, rapidjson::Document &, rapidjson::Value &) override {}
|
inline void onLogin(IClient *, rapidjson::Document &, rapidjson::Value &) override {}
|
||||||
|
|
||||||
int64_t submit(const JobResult &result) override;
|
int64_t submit(const JobResult &result) override;
|
||||||
|
@ -63,7 +63,7 @@ protected:
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool m_active;
|
bool m_active;
|
||||||
Client *m_client;
|
IClient *m_client;
|
||||||
IStrategyListener *m_listener;
|
IStrategyListener *m_listener;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -231,8 +231,8 @@ xmrig::Client *xmrig::DonateStrategy::createProxy()
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
const Client *client = strategy->client();
|
const IClient *client = strategy->client();
|
||||||
m_tls = client->hasExtension(IClient::EXT_TLS);
|
m_tls = client->hasExtension(IClient::EXT_TLS);
|
||||||
|
|
||||||
Pool pool(client->ip(), client->pool().port(), m_userId, client->pool().password(), 0, true, client->isTLS());
|
Pool pool(client->ip(), client->pool().port(), m_userId, client->pool().password(), 0, true, client->isTLS());
|
||||||
pool.setAlgo(client->pool().algorithm());
|
pool.setAlgo(client->pool().algorithm());
|
||||||
|
|
|
@ -52,7 +52,7 @@ public:
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
inline bool isActive() const override { return state() == STATE_ACTIVE; }
|
inline bool isActive() const override { return state() == STATE_ACTIVE; }
|
||||||
inline Client *client() const override { return m_proxy ? m_proxy : m_strategy->client(); }
|
inline IClient *client() const override { return m_proxy ? m_proxy : m_strategy->client(); }
|
||||||
inline void onJob(IStrategy *, IClient *client, const Job &job) override { setJob(client, job); }
|
inline void onJob(IStrategy *, IClient *client, const Job &job) override { setJob(client, job); }
|
||||||
inline void onJobReceived(IClient *client, const Job &job, const rapidjson::Value &) override { setJob(client, job); }
|
inline void onJobReceived(IClient *client, const Job &job, const rapidjson::Value &) override { setJob(client, job); }
|
||||||
inline void onResultAccepted(IClient *client, const SubmitResult &result, const char *error) override { setResult(client, result, error); }
|
inline void onResultAccepted(IClient *client, const SubmitResult &result, const char *error) override { setResult(client, result, error); }
|
||||||
|
@ -93,7 +93,7 @@ private:
|
||||||
|
|
||||||
bool m_tls;
|
bool m_tls;
|
||||||
char m_userId[65];
|
char m_userId[65];
|
||||||
Client *m_proxy;
|
IClient *m_proxy;
|
||||||
const uint64_t m_donateTime;
|
const uint64_t m_donateTime;
|
||||||
const uint64_t m_idleTime;
|
const uint64_t m_idleTime;
|
||||||
Controller *m_controller;
|
Controller *m_controller;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue