mirror of
https://github.com/xmrig/xmrig.git
synced 2024-11-18 18:11:05 +00:00
Merge branch 'feature-daemon' into evo
This commit is contained in:
commit
60f6817d21
37 changed files with 1142 additions and 364 deletions
|
@ -11,6 +11,7 @@ set(HEADERS_BASE
|
||||||
src/base/kernel/config/BaseTransform.h
|
src/base/kernel/config/BaseTransform.h
|
||||||
src/base/kernel/Entry.h
|
src/base/kernel/Entry.h
|
||||||
src/base/kernel/interfaces/IBaseListener.h
|
src/base/kernel/interfaces/IBaseListener.h
|
||||||
|
src/base/kernel/interfaces/IClient.h
|
||||||
src/base/kernel/interfaces/IClientListener.h
|
src/base/kernel/interfaces/IClientListener.h
|
||||||
src/base/kernel/interfaces/IConfig.h
|
src/base/kernel/interfaces/IConfig.h
|
||||||
src/base/kernel/interfaces/IConfigListener.h
|
src/base/kernel/interfaces/IConfigListener.h
|
||||||
|
@ -29,6 +30,7 @@ set(HEADERS_BASE
|
||||||
src/base/net/dns/Dns.h
|
src/base/net/dns/Dns.h
|
||||||
src/base/net/dns/DnsRecord.h
|
src/base/net/dns/DnsRecord.h
|
||||||
src/base/net/http/Http.h
|
src/base/net/http/Http.h
|
||||||
|
src/base/net/stratum/BaseClient.h
|
||||||
src/base/net/stratum/Client.h
|
src/base/net/stratum/Client.h
|
||||||
src/base/net/stratum/Job.h
|
src/base/net/stratum/Job.h
|
||||||
src/base/net/stratum/Pool.h
|
src/base/net/stratum/Pool.h
|
||||||
|
@ -64,6 +66,7 @@ set(SOURCES_BASE
|
||||||
src/base/net/dns/Dns.cpp
|
src/base/net/dns/Dns.cpp
|
||||||
src/base/net/dns/DnsRecord.cpp
|
src/base/net/dns/DnsRecord.cpp
|
||||||
src/base/net/http/Http.cpp
|
src/base/net/http/Http.cpp
|
||||||
|
src/base/net/stratum/BaseClient.cpp
|
||||||
src/base/net/stratum/Client.cpp
|
src/base/net/stratum/Client.cpp
|
||||||
src/base/net/stratum/Job.cpp
|
src/base/net/stratum/Job.cpp
|
||||||
src/base/net/stratum/Pool.cpp
|
src/base/net/stratum/Pool.cpp
|
||||||
|
@ -105,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
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -115,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
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
@ -161,6 +161,7 @@ void xmrig::BaseTransform::transform(rapidjson::Document &doc, int key, const ch
|
||||||
case IConfig::PrintTimeKey: /* --print-time */
|
case IConfig::PrintTimeKey: /* --print-time */
|
||||||
case IConfig::HttpPort: /* --http-port */
|
case IConfig::HttpPort: /* --http-port */
|
||||||
case IConfig::DonateLevelKey: /* --donate-level */
|
case IConfig::DonateLevelKey: /* --donate-level */
|
||||||
|
case IConfig::DaemonPollKey: /* --daemon-poll-interval */
|
||||||
# ifdef XMRIG_DEPRECATED
|
# ifdef XMRIG_DEPRECATED
|
||||||
case IConfig::ApiPort: /* --api-port */
|
case IConfig::ApiPort: /* --api-port */
|
||||||
# endif
|
# endif
|
||||||
|
@ -173,6 +174,7 @@ void xmrig::BaseTransform::transform(rapidjson::Document &doc, int key, const ch
|
||||||
case IConfig::TlsKey: /* --tls */
|
case IConfig::TlsKey: /* --tls */
|
||||||
case IConfig::DryRunKey: /* --dry-run */
|
case IConfig::DryRunKey: /* --dry-run */
|
||||||
case IConfig::HttpEnabledKey: /* --http-enabled */
|
case IConfig::HttpEnabledKey: /* --http-enabled */
|
||||||
|
case IConfig::DaemonKey: /* --daemon */
|
||||||
return transformBoolean(doc, key, true);
|
return transformBoolean(doc, key, true);
|
||||||
|
|
||||||
case IConfig::ColorKey: /* --no-color */
|
case IConfig::ColorKey: /* --no-color */
|
||||||
|
@ -204,6 +206,9 @@ void xmrig::BaseTransform::transformBoolean(rapidjson::Document &doc, int key, b
|
||||||
case IConfig::TlsKey: /* --tls */
|
case IConfig::TlsKey: /* --tls */
|
||||||
return add(doc, kPools, "tls", enable);
|
return add(doc, kPools, "tls", enable);
|
||||||
|
|
||||||
|
case IConfig::DaemonKey: /* --daemon */
|
||||||
|
return add(doc, kPools, "daemon", enable);
|
||||||
|
|
||||||
# ifndef XMRIG_PROXY_PROJECT
|
# ifndef XMRIG_PROXY_PROJECT
|
||||||
case IConfig::NicehashKey: /* --nicehash */
|
case IConfig::NicehashKey: /* --nicehash */
|
||||||
return add<bool>(doc, kPools, "nicehash", enable);
|
return add<bool>(doc, kPools, "nicehash", enable);
|
||||||
|
@ -265,6 +270,9 @@ void xmrig::BaseTransform::transformUint64(rapidjson::Document &doc, int key, ui
|
||||||
case IConfig::PrintTimeKey: /* --print-time */
|
case IConfig::PrintTimeKey: /* --print-time */
|
||||||
return set(doc, "print-time", arg);
|
return set(doc, "print-time", arg);
|
||||||
|
|
||||||
|
case IConfig::DaemonPollKey: /* --daemon-poll-interval */
|
||||||
|
return add(doc, kPools, "daemon-poll-interval", arg);
|
||||||
|
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
85
src/base/kernel/interfaces/IClient.h
Normal file
85
src/base/kernel/interfaces/IClient.h
Normal file
|
@ -0,0 +1,85 @@
|
||||||
|
/* 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_ICLIENT_H
|
||||||
|
#define XMRIG_ICLIENT_H
|
||||||
|
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
|
||||||
|
namespace xmrig {
|
||||||
|
|
||||||
|
|
||||||
|
class Algorithm;
|
||||||
|
class Job;
|
||||||
|
class JobResult;
|
||||||
|
class Pool;
|
||||||
|
class String;
|
||||||
|
|
||||||
|
|
||||||
|
class IClient
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
enum Extension {
|
||||||
|
EXT_ALGO,
|
||||||
|
EXT_NICEHASH,
|
||||||
|
EXT_CONNECT,
|
||||||
|
EXT_TLS,
|
||||||
|
EXT_KEEPALIVE,
|
||||||
|
EXT_MAX
|
||||||
|
};
|
||||||
|
|
||||||
|
virtual ~IClient() = default;
|
||||||
|
|
||||||
|
virtual bool disconnect() = 0;
|
||||||
|
virtual bool hasExtension(Extension extension) const noexcept = 0;
|
||||||
|
virtual bool isEnabled() const = 0;
|
||||||
|
virtual bool isTLS() const = 0;
|
||||||
|
virtual const char *mode() const = 0;
|
||||||
|
virtual const char *tlsFingerprint() const = 0;
|
||||||
|
virtual const char *tlsVersion() const = 0;
|
||||||
|
virtual const Job &job() const = 0;
|
||||||
|
virtual const Pool &pool() const = 0;
|
||||||
|
virtual const String &ip() const = 0;
|
||||||
|
virtual int id() const = 0;
|
||||||
|
virtual int64_t submit(const JobResult &result) = 0;
|
||||||
|
virtual void connect() = 0;
|
||||||
|
virtual void connect(const Pool &pool) = 0;
|
||||||
|
virtual void deleteLater() = 0;
|
||||||
|
virtual void setAlgo(const Algorithm &algo) = 0;
|
||||||
|
virtual void setEnabled(bool enabled) = 0;
|
||||||
|
virtual void setPool(const Pool &pool) = 0;
|
||||||
|
virtual void setQuiet(bool quiet) = 0;
|
||||||
|
virtual void setRetries(int retries) = 0;
|
||||||
|
virtual void setRetryPause(uint64_t ms) = 0;
|
||||||
|
virtual void tick(uint64_t now) = 0;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
} /* namespace xmrig */
|
||||||
|
|
||||||
|
|
||||||
|
#endif // XMRIG_ICLIENT_H
|
|
@ -35,7 +35,7 @@
|
||||||
namespace xmrig {
|
namespace xmrig {
|
||||||
|
|
||||||
|
|
||||||
class Client;
|
class IClient;
|
||||||
class Job;
|
class Job;
|
||||||
class SubmitResult;
|
class SubmitResult;
|
||||||
|
|
||||||
|
@ -45,11 +45,11 @@ class IClientListener
|
||||||
public:
|
public:
|
||||||
virtual ~IClientListener() = default;
|
virtual ~IClientListener() = default;
|
||||||
|
|
||||||
virtual void onClose(Client *client, int failures) = 0;
|
virtual void onClose(IClient *client, int failures) = 0;
|
||||||
virtual void onJobReceived(Client *client, const Job &job, const rapidjson::Value ¶ms) = 0;
|
virtual void onJobReceived(IClient *client, const Job &job, const rapidjson::Value ¶ms) = 0;
|
||||||
virtual void onLogin(Client *client, rapidjson::Document &doc, rapidjson::Value ¶ms) = 0;
|
virtual void onLogin(IClient *client, rapidjson::Document &doc, rapidjson::Value ¶ms) = 0;
|
||||||
virtual void onLoginSuccess(Client *client) = 0;
|
virtual void onLoginSuccess(IClient *client) = 0;
|
||||||
virtual void onResultAccepted(Client *client, const SubmitResult &result, const char *error) = 0;
|
virtual void onResultAccepted(IClient *client, const SubmitResult &result, const char *error) = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -70,6 +70,8 @@ public:
|
||||||
TlsKey = 1013,
|
TlsKey = 1013,
|
||||||
FingerprintKey = 1014,
|
FingerprintKey = 1014,
|
||||||
ProxyDonateKey = 1017,
|
ProxyDonateKey = 1017,
|
||||||
|
DaemonKey = 1018,
|
||||||
|
DaemonPollKey = 1019,
|
||||||
|
|
||||||
# ifdef XMRIG_DEPRECATED
|
# ifdef XMRIG_DEPRECATED
|
||||||
ApiPort = 4000,
|
ApiPort = 4000,
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -32,7 +32,7 @@
|
||||||
namespace xmrig {
|
namespace xmrig {
|
||||||
|
|
||||||
|
|
||||||
class Client;
|
class IClient;
|
||||||
class IStrategy;
|
class IStrategy;
|
||||||
class Job;
|
class Job;
|
||||||
class SubmitResult;
|
class SubmitResult;
|
||||||
|
@ -43,10 +43,10 @@ class IStrategyListener
|
||||||
public:
|
public:
|
||||||
virtual ~IStrategyListener() = default;
|
virtual ~IStrategyListener() = default;
|
||||||
|
|
||||||
virtual void onActive(IStrategy *strategy, Client *client) = 0;
|
virtual void onActive(IStrategy *strategy, IClient *client) = 0;
|
||||||
virtual void onJob(IStrategy *strategy, Client *client, const Job &job) = 0;
|
virtual void onJob(IStrategy *strategy, IClient *client, const Job &job) = 0;
|
||||||
virtual void onPause(IStrategy *strategy) = 0;
|
virtual void onPause(IStrategy *strategy) = 0;
|
||||||
virtual void onResultAccepted(IStrategy *strategy, Client *client, const SubmitResult &result, const char *error) = 0;
|
virtual void onResultAccepted(IStrategy *strategy, IClient *client, const SubmitResult &result, const char *error) = 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];
|
||||||
|
@ -79,6 +79,7 @@ private:
|
||||||
|
|
||||||
xmrig::HttpClient::HttpClient(int method, const String &url, IHttpListener *listener, const char *data, size_t size) :
|
xmrig::HttpClient::HttpClient(int method, const String &url, IHttpListener *listener, const char *data, size_t size) :
|
||||||
HttpContext(HTTP_RESPONSE, listener),
|
HttpContext(HTTP_RESPONSE, listener),
|
||||||
|
m_quiet(false),
|
||||||
m_port(0)
|
m_port(0)
|
||||||
{
|
{
|
||||||
this->method = method;
|
this->method = method;
|
||||||
|
@ -117,7 +118,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 +162,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 +183,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 +210,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;
|
||||||
|
@ -56,6 +57,8 @@ protected:
|
||||||
virtual void read(const char *data, size_t size);
|
virtual void read(const char *data, size_t size);
|
||||||
virtual void write(const std::string &header);
|
virtual void write(const std::string &header);
|
||||||
|
|
||||||
|
bool m_quiet;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static void onConnect(uv_connect_t *req, int status);
|
static void onConnect(uv_connect_t *req, int status);
|
||||||
|
|
||||||
|
|
|
@ -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();
|
||||||
|
|
|
@ -29,15 +29,22 @@
|
||||||
#include <uv.h>
|
#include <uv.h>
|
||||||
|
|
||||||
|
|
||||||
|
#include "base/io/log/Log.h"
|
||||||
#include "base/net/http/HttpsClient.h"
|
#include "base/net/http/HttpsClient.h"
|
||||||
#include "base/tools/String.h"
|
#include "base/tools/Buffer.h"
|
||||||
|
|
||||||
|
|
||||||
xmrig::HttpsClient::HttpsClient(int method, const String &url, IHttpListener *listener, const char *data, size_t size) :
|
#ifdef _MSC_VER
|
||||||
|
# define strncasecmp(x,y,z) _strnicmp(x,y,z)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
xmrig::HttpsClient::HttpsClient(int method, const String &url, IHttpListener *listener, const char *data, size_t size, const String &fingerprint) :
|
||||||
HttpClient(method, url, listener, data, size),
|
HttpClient(method, url, listener, data, size),
|
||||||
m_ready(false),
|
m_ready(false),
|
||||||
m_buf(),
|
m_buf(),
|
||||||
m_ssl(nullptr)
|
m_ssl(nullptr),
|
||||||
|
m_fp(fingerprint)
|
||||||
{
|
{
|
||||||
m_ctx = SSL_CTX_new(SSLv23_method());
|
m_ctx = SSL_CTX_new(SSLv23_method());
|
||||||
assert(m_ctx != nullptr);
|
assert(m_ctx != nullptr);
|
||||||
|
@ -64,6 +71,18 @@ xmrig::HttpsClient::~HttpsClient()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const char *xmrig::HttpsClient::fingerprint() const
|
||||||
|
{
|
||||||
|
return m_ready ? m_fingerprint : nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const char *xmrig::HttpsClient::version() const
|
||||||
|
{
|
||||||
|
return m_ready ? SSL_get_version(m_ssl) : nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void xmrig::HttpsClient::handshake()
|
void xmrig::HttpsClient::handshake()
|
||||||
{
|
{
|
||||||
m_ssl = SSL_new(m_ctx);
|
m_ssl = SSL_new(m_ctx);
|
||||||
|
@ -96,7 +115,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);
|
||||||
|
@ -118,13 +137,52 @@ void xmrig::HttpsClient::read(const char *data, size_t size)
|
||||||
void xmrig::HttpsClient::write(const std::string &header)
|
void xmrig::HttpsClient::write(const std::string &header)
|
||||||
{
|
{
|
||||||
SSL_write(m_ssl, (header + body).c_str(), header.size() + body.size());
|
SSL_write(m_ssl, (header + body).c_str(), header.size() + body.size());
|
||||||
|
body.clear();
|
||||||
|
|
||||||
flush();
|
flush();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool xmrig::HttpsClient::verify(X509 *cert) const
|
bool xmrig::HttpsClient::verify(X509 *cert)
|
||||||
{
|
{
|
||||||
return cert != nullptr;
|
if (cert == nullptr) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!verifyFingerprint(cert)) {
|
||||||
|
if (!m_quiet) {
|
||||||
|
LOG_ERR("[%s:%d] Failed to verify server certificate fingerprint", host().data(), port());
|
||||||
|
|
||||||
|
if (strlen(m_fingerprint) == 64 && !m_fp.isNull()) {
|
||||||
|
LOG_ERR("\"%s\" was given", m_fingerprint);
|
||||||
|
LOG_ERR("\"%s\" was configured", m_fp.data());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool xmrig::HttpsClient::verifyFingerprint(X509 *cert)
|
||||||
|
{
|
||||||
|
const EVP_MD *digest = EVP_get_digestbyname("sha256");
|
||||||
|
if (digest == nullptr) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned char md[EVP_MAX_MD_SIZE];
|
||||||
|
unsigned int dlen;
|
||||||
|
|
||||||
|
if (X509_digest(cert, digest, md, &dlen) != 1) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
Buffer::toHex(md, 32, m_fingerprint);
|
||||||
|
|
||||||
|
return m_fp.isNull() || strncasecmp(m_fingerprint, m_fp.data(), 64) == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -139,10 +197,10 @@ void xmrig::HttpsClient::flush()
|
||||||
|
|
||||||
bool result = false;
|
bool result = false;
|
||||||
if (uv_is_writable(stream())) {
|
if (uv_is_writable(stream())) {
|
||||||
result = uv_try_write(stream(), &buf, 1) == buf.len;
|
result = uv_try_write(stream(), &buf, 1) == static_cast<int>(buf.len);
|
||||||
|
|
||||||
if (!result) {
|
if (!result) {
|
||||||
close();
|
close(UV_EIO);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -35,6 +35,7 @@ typedef struct x509_st X509;
|
||||||
|
|
||||||
|
|
||||||
#include "base/net/http/HttpClient.h"
|
#include "base/net/http/HttpClient.h"
|
||||||
|
#include "base/tools/String.h"
|
||||||
|
|
||||||
|
|
||||||
namespace xmrig {
|
namespace xmrig {
|
||||||
|
@ -43,24 +44,30 @@ namespace xmrig {
|
||||||
class HttpsClient : public HttpClient
|
class HttpsClient : public HttpClient
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
HttpsClient(int method, const String &url, IHttpListener *listener, const char *data = nullptr, size_t size = 0);
|
HttpsClient(int method, const String &url, IHttpListener *listener, const char *data, size_t size, const String &fingerprint);
|
||||||
~HttpsClient() override;
|
~HttpsClient() override;
|
||||||
|
|
||||||
|
const char *fingerprint() const;
|
||||||
|
const char *version() const;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void handshake() override;
|
void handshake() override;
|
||||||
void read(const char *data, size_t size) override;
|
void read(const char *data, size_t size) override;
|
||||||
void write(const std::string &header) override;
|
void write(const std::string &header) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool verify(X509 *cert) const;
|
bool verify(X509 *cert);
|
||||||
|
bool verifyFingerprint(X509 *cert);
|
||||||
void flush();
|
void flush();
|
||||||
|
|
||||||
BIO *m_readBio;
|
BIO *m_readBio;
|
||||||
BIO *m_writeBio;
|
BIO *m_writeBio;
|
||||||
bool m_ready;
|
bool m_ready;
|
||||||
char m_buf[1024 * 2];
|
char m_buf[1024 * 2];
|
||||||
|
char m_fingerprint[32 * 2 + 8];
|
||||||
SSL *m_ssl;
|
SSL *m_ssl;
|
||||||
SSL_CTX *m_ctx;
|
SSL_CTX *m_ctx;
|
||||||
|
String m_fp;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
62
src/base/net/stratum/BaseClient.cpp
Normal file
62
src/base/net/stratum/BaseClient.cpp
Normal file
|
@ -0,0 +1,62 @@
|
||||||
|
/* 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/IClientListener.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) :
|
||||||
|
m_quiet(false),
|
||||||
|
m_listener(listener),
|
||||||
|
m_id(id),
|
||||||
|
m_retries(5),
|
||||||
|
m_failures(0),
|
||||||
|
m_state(UnconnectedState),
|
||||||
|
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;
|
||||||
|
}
|
96
src/base/net/stratum/BaseClient.h
Normal file
96
src/base/net/stratum/BaseClient.h
Normal file
|
@ -0,0 +1,96 @@
|
||||||
|
/* 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_BASECLIENT_H
|
||||||
|
#define XMRIG_BASECLIENT_H
|
||||||
|
|
||||||
|
|
||||||
|
#include <map>
|
||||||
|
|
||||||
|
|
||||||
|
#include "base/kernel/interfaces/IClient.h"
|
||||||
|
#include "base/net/stratum/Job.h"
|
||||||
|
#include "base/net/stratum/Pool.h"
|
||||||
|
|
||||||
|
|
||||||
|
namespace xmrig {
|
||||||
|
|
||||||
|
|
||||||
|
class IClientListener;
|
||||||
|
class SubmitResult;
|
||||||
|
|
||||||
|
|
||||||
|
class BaseClient : public IClient
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
BaseClient(int id, IClientListener *listener);
|
||||||
|
|
||||||
|
inline bool isEnabled() const override { return m_enabled; }
|
||||||
|
inline const Job &job() const override { return m_job; }
|
||||||
|
inline const Pool &pool() const override { return m_pool; }
|
||||||
|
inline const String &ip() const override { return m_ip; }
|
||||||
|
inline int id() const override { return m_id; }
|
||||||
|
inline void setAlgo(const Algorithm &algo) override { m_pool.setAlgo(algo); }
|
||||||
|
inline void setEnabled(bool enabled) override { m_enabled = enabled; }
|
||||||
|
inline void setPool(const Pool &pool) override { if (pool.isValid()) { m_pool = pool; } }
|
||||||
|
inline void setQuiet(bool quiet) override { m_quiet = quiet; }
|
||||||
|
inline void setRetries(int retries) override { m_retries = retries; }
|
||||||
|
inline void setRetryPause(uint64_t ms) override { m_retryPause = ms; }
|
||||||
|
|
||||||
|
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;
|
||||||
|
IClientListener *m_listener;
|
||||||
|
int m_id;
|
||||||
|
int m_retries;
|
||||||
|
int64_t m_failures;
|
||||||
|
Job m_job;
|
||||||
|
Pool m_pool;
|
||||||
|
SocketState m_state;
|
||||||
|
std::map<int64_t, SubmitResult> m_results;
|
||||||
|
String m_ip;
|
||||||
|
uint64_t m_retryPause;
|
||||||
|
|
||||||
|
static int64_t m_sequence;
|
||||||
|
|
||||||
|
private:
|
||||||
|
bool m_enabled;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
} /* namespace xmrig */
|
||||||
|
|
||||||
|
|
||||||
|
#endif /* XMRIG_BASECLIENT_H */
|
|
@ -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 */
|
||||||
|
@ -75,16 +74,8 @@ static const char *states[] = {
|
||||||
|
|
||||||
|
|
||||||
xmrig::Client::Client(int id, const char *agent, IClientListener *listener) :
|
xmrig::Client::Client(int id, const char *agent, IClientListener *listener) :
|
||||||
m_enabled(true),
|
BaseClient(id, listener),
|
||||||
m_ipv6(false),
|
|
||||||
m_quiet(false),
|
|
||||||
m_agent(agent),
|
m_agent(agent),
|
||||||
m_listener(listener),
|
|
||||||
m_id(id),
|
|
||||||
m_retries(5),
|
|
||||||
m_retryPause(5000),
|
|
||||||
m_failures(0),
|
|
||||||
m_state(UnconnectedState),
|
|
||||||
m_tls(nullptr),
|
m_tls(nullptr),
|
||||||
m_expire(0),
|
m_expire(0),
|
||||||
m_jobs(0),
|
m_jobs(0),
|
||||||
|
@ -105,73 +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());
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Connect to server.
|
|
||||||
*
|
|
||||||
* @param url
|
|
||||||
*/
|
|
||||||
void xmrig::Client::connect(const Pool &url)
|
|
||||||
{
|
|
||||||
setPool(url);
|
|
||||||
connect();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void xmrig::Client::deleteLater()
|
|
||||||
{
|
|
||||||
if (!m_listener) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
m_listener = nullptr;
|
|
||||||
|
|
||||||
if (!disconnect()) {
|
|
||||||
m_storage.remove(m_key);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void xmrig::Client::setPool(const Pool &pool)
|
|
||||||
{
|
|
||||||
if (!pool.isValid()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
m_pool = pool;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
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;
|
||||||
|
@ -269,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);
|
||||||
|
@ -771,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)) {
|
||||||
|
@ -809,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);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -34,6 +34,7 @@
|
||||||
|
|
||||||
#include "base/kernel/interfaces/IDnsListener.h"
|
#include "base/kernel/interfaces/IDnsListener.h"
|
||||||
#include "base/kernel/interfaces/ILineListener.h"
|
#include "base/kernel/interfaces/ILineListener.h"
|
||||||
|
#include "base/net/stratum/BaseClient.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"
|
||||||
#include "base/net/stratum/SubmitResult.h"
|
#include "base/net/stratum/SubmitResult.h"
|
||||||
|
@ -42,7 +43,6 @@
|
||||||
#include "common/crypto/Algorithm.h"
|
#include "common/crypto/Algorithm.h"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
typedef struct bio_st BIO;
|
typedef struct bio_st BIO;
|
||||||
|
|
||||||
|
|
||||||
|
@ -53,26 +53,9 @@ class IClientListener;
|
||||||
class JobResult;
|
class JobResult;
|
||||||
|
|
||||||
|
|
||||||
class Client : public IDnsListener, public ILineListener
|
class Client : public BaseClient, public IDnsListener, public ILineListener
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
enum SocketState {
|
|
||||||
UnconnectedState,
|
|
||||||
HostLookupState,
|
|
||||||
ConnectingState,
|
|
||||||
ConnectedState,
|
|
||||||
ClosingState
|
|
||||||
};
|
|
||||||
|
|
||||||
enum Extension {
|
|
||||||
EXT_ALGO,
|
|
||||||
EXT_NICEHASH,
|
|
||||||
EXT_CONNECT,
|
|
||||||
EXT_TLS,
|
|
||||||
EXT_KEEPALIVE,
|
|
||||||
EXT_MAX
|
|
||||||
};
|
|
||||||
|
|
||||||
constexpr static int kResponseTimeout = 20 * 1000;
|
constexpr static int kResponseTimeout = 20 * 1000;
|
||||||
|
|
||||||
# ifdef XMRIG_FEATURE_TLS
|
# ifdef XMRIG_FEATURE_TLS
|
||||||
|
@ -84,39 +67,23 @@ public:
|
||||||
Client(int id, const char *agent, IClientListener *listener);
|
Client(int id, const char *agent, IClientListener *listener);
|
||||||
~Client() override;
|
~Client() override;
|
||||||
|
|
||||||
bool disconnect();
|
|
||||||
bool isTLS() const;
|
|
||||||
const char *tlsFingerprint() const;
|
|
||||||
const char *tlsVersion() const;
|
|
||||||
int64_t submit(const JobResult &result);
|
|
||||||
void connect();
|
|
||||||
void connect(const Pool &pool);
|
|
||||||
void deleteLater();
|
|
||||||
void setPool(const Pool &pool);
|
|
||||||
void tick(uint64_t now);
|
|
||||||
|
|
||||||
inline bool isEnabled() const { return m_enabled; }
|
|
||||||
inline bool isReady() const { return m_state == ConnectedState && m_failures == 0; }
|
|
||||||
inline const char *host() const { return m_pool.host(); }
|
|
||||||
inline const char *ip() const { return m_ip; }
|
|
||||||
inline const Job &job() const { return m_job; }
|
|
||||||
inline const Pool &pool() const { return m_pool; }
|
|
||||||
inline int id() const { return m_id; }
|
|
||||||
inline SocketState state() const { return m_state; }
|
|
||||||
inline uint16_t port() const { return m_pool.port(); }
|
|
||||||
inline void setAlgo(const Algorithm &algo) { m_pool.setAlgo(algo); }
|
|
||||||
inline void setEnabled(bool enabled) { m_enabled = enabled; }
|
|
||||||
inline void setQuiet(bool quiet) { m_quiet = quiet; }
|
|
||||||
inline void setRetries(int retries) { m_retries = retries; }
|
|
||||||
inline void setRetryPause(int ms) { m_retryPause = ms; }
|
|
||||||
|
|
||||||
template<Extension ext> inline bool has() const noexcept { return m_extensions.test(ext); }
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
inline void onLine(char *line, size_t size) override { parse(line, size); }
|
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 deleteLater() override;
|
||||||
|
void tick(uint64_t now) override;
|
||||||
|
|
||||||
void onResolved(const Dns &dns, int status) override;
|
void onResolved(const Dns &dns, int status) override;
|
||||||
|
|
||||||
|
inline bool hasExtension(Extension extension) const noexcept override { return m_extensions.test(extension); }
|
||||||
|
inline const char *mode() const override { return "pool"; }
|
||||||
|
inline void onLine(char *line, size_t size) override { parse(line, size); }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
class Tls;
|
class Tls;
|
||||||
|
|
||||||
|
@ -143,9 +110,10 @@ 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 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); }
|
||||||
|
template<Extension ext> inline bool has() const noexcept { return m_extensions.test(ext); }
|
||||||
|
|
||||||
static void onAllocBuffer(uv_handle_t *handle, size_t suggested_size, uv_buf_t *buf);
|
static void onAllocBuffer(uv_handle_t *handle, size_t suggested_size, uv_buf_t *buf);
|
||||||
static void onClose(uv_handle_t *handle);
|
static void onClose(uv_handle_t *handle);
|
||||||
|
@ -154,24 +122,11 @@ private:
|
||||||
|
|
||||||
static inline Client *getClient(void *data) { return m_storage.get(data); }
|
static inline Client *getClient(void *data) { return m_storage.get(data); }
|
||||||
|
|
||||||
bool m_enabled;
|
|
||||||
bool m_ipv6;
|
|
||||||
bool m_quiet;
|
|
||||||
char m_sendBuf[2048];
|
char m_sendBuf[2048];
|
||||||
const char *m_agent;
|
const char *m_agent;
|
||||||
Dns *m_dns;
|
Dns *m_dns;
|
||||||
IClientListener *m_listener;
|
|
||||||
int m_id;
|
|
||||||
int m_retries;
|
|
||||||
int m_retryPause;
|
|
||||||
int64_t m_failures;
|
|
||||||
Job m_job;
|
|
||||||
Pool m_pool;
|
|
||||||
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_ip;
|
|
||||||
String m_rpcId;
|
String m_rpcId;
|
||||||
Tls *m_tls;
|
Tls *m_tls;
|
||||||
uint64_t m_expire;
|
uint64_t m_expire;
|
||||||
|
@ -181,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;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
347
src/base/net/stratum/DaemonClient.cpp
Normal file
347
src/base/net/stratum/DaemonClient.cpp
Normal file
|
@ -0,0 +1,347 @@
|
||||||
|
/* 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
|
||||||
|
{
|
||||||
|
# ifdef XMRIG_FEATURE_TLS
|
||||||
|
return m_pool.isTLS();
|
||||||
|
# else
|
||||||
|
return false;
|
||||||
|
# endif
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
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();
|
||||||
|
|
||||||
|
if (isTLS()) {
|
||||||
|
m_tlsVersion = static_cast<const HttpsClient &>(data).version();
|
||||||
|
m_tlsFingerprint = static_cast<const HttpsClient &>(data).fingerprint();
|
||||||
|
}
|
||||||
|
|
||||||
|
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, m_pool.fingerprint());
|
||||||
|
}
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
80
src/base/net/stratum/DaemonClient.h
Normal file
80
src/base/net/stratum/DaemonClient.h
Normal 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 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;
|
||||||
|
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 const char *tlsFingerprint() const override { return m_tlsFingerprint; }
|
||||||
|
inline const char *tlsVersion() const override { return m_tlsVersion; }
|
||||||
|
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;
|
||||||
|
String m_tlsFingerprint;
|
||||||
|
String m_tlsVersion;
|
||||||
|
Timer *m_timer;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
} /* namespace xmrig */
|
||||||
|
|
||||||
|
|
||||||
|
#endif /* XMRIG_DAEMONCLIENT_H */
|
|
@ -7,6 +7,7 @@
|
||||||
* Copyright 2017-2018 XMR-Stak <https://github.com/fireice-uk>, <https://github.com/psychocrypt>
|
* Copyright 2017-2018 XMR-Stak <https://github.com/fireice-uk>, <https://github.com/psychocrypt>
|
||||||
* Copyright 2018 Lee Clagett <https://github.com/vtnerd>
|
* Copyright 2018 Lee Clagett <https://github.com/vtnerd>
|
||||||
* Copyright 2018 SChernykh <https://github.com/SChernykh>
|
* Copyright 2018 SChernykh <https://github.com/SChernykh>
|
||||||
|
* Copyright 2019 Howard Chu <https://github.com/hyc>
|
||||||
* Copyright 2016-2019 XMRig <https://github.com/xmrig>, <support@xmrig.com>
|
* Copyright 2016-2019 XMRig <https://github.com/xmrig>, <support@xmrig.com>
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
@ -180,9 +181,10 @@ void xmrig::Job::setAlgorithm(const char *algo)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void xmrig::Job::setHeight(uint64_t height)
|
void xmrig::Job::setDiff(uint64_t diff)
|
||||||
{
|
{
|
||||||
m_height = height;
|
m_diff = diff;
|
||||||
|
m_target = toDiff(diff);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -7,6 +7,7 @@
|
||||||
* Copyright 2017-2018 XMR-Stak <https://github.com/fireice-uk>, <https://github.com/psychocrypt>
|
* Copyright 2017-2018 XMR-Stak <https://github.com/fireice-uk>, <https://github.com/psychocrypt>
|
||||||
* Copyright 2018 Lee Clagett <https://github.com/vtnerd>
|
* Copyright 2018 Lee Clagett <https://github.com/vtnerd>
|
||||||
* Copyright 2018-2019 SChernykh <https://github.com/SChernykh>
|
* 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>
|
* Copyright 2016-2019 XMRig <https://github.com/xmrig>, <support@xmrig.com>
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
@ -53,7 +54,7 @@ public:
|
||||||
bool setBlob(const char *blob);
|
bool setBlob(const char *blob);
|
||||||
bool setTarget(const char *target);
|
bool setTarget(const char *target);
|
||||||
void setAlgorithm(const char *algo);
|
void setAlgorithm(const char *algo);
|
||||||
void setHeight(uint64_t height);
|
void setDiff(uint64_t diff);
|
||||||
|
|
||||||
inline bool isNicehash() const { return m_nicehash; }
|
inline bool isNicehash() const { return m_nicehash; }
|
||||||
inline bool isValid() const { return m_size > 0 && m_diff > 0; }
|
inline bool isValid() const { return m_size > 0 && m_diff > 0; }
|
||||||
|
@ -67,12 +68,13 @@ public:
|
||||||
inline int threadId() const { return m_threadId; }
|
inline int threadId() const { return m_threadId; }
|
||||||
inline size_t size() const { return m_size; }
|
inline size_t size() const { return m_size; }
|
||||||
inline uint32_t *nonce() { return reinterpret_cast<uint32_t*>(m_blob + 39); }
|
inline uint32_t *nonce() { return reinterpret_cast<uint32_t*>(m_blob + 39); }
|
||||||
inline uint32_t diff() const { return static_cast<uint32_t>(m_diff); }
|
inline uint64_t diff() const { return m_diff; }
|
||||||
inline uint64_t height() const { return m_height; }
|
inline uint64_t height() const { return m_height; }
|
||||||
inline uint64_t target() const { return m_target; }
|
inline uint64_t target() const { return m_target; }
|
||||||
inline uint8_t fixedByte() const { return *(m_blob + 42); }
|
inline uint8_t fixedByte() const { return *(m_blob + 42); }
|
||||||
inline void reset() { m_size = 0; m_diff = 0; }
|
inline void reset() { m_size = 0; m_diff = 0; }
|
||||||
inline void setClientId(const String &id) { m_clientId = id; }
|
inline void setClientId(const String &id) { m_clientId = id; }
|
||||||
|
inline void setHeight(uint64_t height) { m_height = height; }
|
||||||
inline void setPoolId(int poolId) { m_poolId = poolId; }
|
inline void setPoolId(int poolId) { m_poolId = poolId; }
|
||||||
inline void setThreadId(int threadId) { m_threadId = threadId; }
|
inline void setThreadId(int threadId) { m_threadId = threadId; }
|
||||||
inline void setVariant(const char *variant) { m_algorithm.parseVariant(variant); }
|
inline void setVariant(const char *variant) { m_algorithm.parseVariant(variant); }
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
* Copyright 2016 Jay D Dee <jayddee246@gmail.com>
|
* Copyright 2016 Jay D Dee <jayddee246@gmail.com>
|
||||||
* Copyright 2017-2019 XMR-Stak <https://github.com/fireice-uk>, <https://github.com/psychocrypt>
|
* Copyright 2017-2019 XMR-Stak <https://github.com/fireice-uk>, <https://github.com/psychocrypt>
|
||||||
* Copyright 2018-2019 SChernykh <https://github.com/SChernykh>
|
* 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>
|
* Copyright 2016-2019 XMRig <https://github.com/xmrig>, <support@xmrig.com>
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
@ -41,25 +42,34 @@
|
||||||
|
|
||||||
#ifdef _MSC_VER
|
#ifdef _MSC_VER
|
||||||
# define strncasecmp _strnicmp
|
# define strncasecmp _strnicmp
|
||||||
# define strcasecmp _stricmp
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
namespace xmrig {
|
namespace xmrig {
|
||||||
|
|
||||||
static const char *kEnabled = "enabled";
|
static const char *kDaemon = "daemon";
|
||||||
static const char *kFingerprint = "tls-fingerprint";
|
static const char *kDaemonPollInterval = "daemon-poll-interval";
|
||||||
static const char *kKeepalive = "keepalive";
|
static const char *kEnabled = "enabled";
|
||||||
static const char *kNicehash = "nicehash";
|
static const char *kFingerprint = "tls-fingerprint";
|
||||||
static const char *kPass = "pass";
|
static const char *kKeepalive = "keepalive";
|
||||||
static const char *kRigId = "rig-id";
|
static const char *kNicehash = "nicehash";
|
||||||
static const char *kTls = "tls";
|
static const char *kPass = "pass";
|
||||||
static const char *kUrl = "url";
|
static const char *kRigId = "rig-id";
|
||||||
static const char *kUser = "user";
|
static const char *kTls = "tls";
|
||||||
static const char *kVariant = "variant";
|
static const char *kUrl = "url";
|
||||||
|
static const char *kUser = "user";
|
||||||
|
static const char *kVariant = "variant";
|
||||||
|
|
||||||
const String Pool::kDefaultPassword = "x";
|
const String Pool::kDefaultPassword = "x";
|
||||||
const String Pool::kDefaultUser = "x";
|
const String Pool::kDefaultUser = "x";
|
||||||
|
|
||||||
|
static const char kStratumTcp[] = "stratum+tcp://";
|
||||||
|
static const char kStratumSsl[] = "stratum+ssl://";
|
||||||
|
|
||||||
|
#ifdef XMRIG_FEATURE_HTTP
|
||||||
|
static const char kDaemonHttp[] = "daemon+http://";
|
||||||
|
static const char kDaemonHttps[] = "daemon+https://";
|
||||||
|
#endif
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -67,7 +77,8 @@ const String Pool::kDefaultUser = "x";
|
||||||
xmrig::Pool::Pool() :
|
xmrig::Pool::Pool() :
|
||||||
m_keepAlive(0),
|
m_keepAlive(0),
|
||||||
m_flags(0),
|
m_flags(0),
|
||||||
m_port(kDefaultPort)
|
m_port(kDefaultPort),
|
||||||
|
m_pollInterval(kDefaultPollInterval)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -86,7 +97,8 @@ xmrig::Pool::Pool() :
|
||||||
xmrig::Pool::Pool(const char *url) :
|
xmrig::Pool::Pool(const char *url) :
|
||||||
m_keepAlive(0),
|
m_keepAlive(0),
|
||||||
m_flags(1),
|
m_flags(1),
|
||||||
m_port(kDefaultPort)
|
m_port(kDefaultPort),
|
||||||
|
m_pollInterval(kDefaultPollInterval)
|
||||||
{
|
{
|
||||||
parse(url);
|
parse(url);
|
||||||
}
|
}
|
||||||
|
@ -95,20 +107,23 @@ xmrig::Pool::Pool(const char *url) :
|
||||||
xmrig::Pool::Pool(const rapidjson::Value &object) :
|
xmrig::Pool::Pool(const rapidjson::Value &object) :
|
||||||
m_keepAlive(0),
|
m_keepAlive(0),
|
||||||
m_flags(1),
|
m_flags(1),
|
||||||
m_port(kDefaultPort)
|
m_port(kDefaultPort),
|
||||||
|
m_pollInterval(kDefaultPollInterval)
|
||||||
{
|
{
|
||||||
if (!parse(Json::getString(object, kUrl))) {
|
if (!parse(Json::getString(object, kUrl))) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
m_user = Json::getString(object, kUser);
|
m_user = Json::getString(object, kUser);
|
||||||
m_password = Json::getString(object, kPass);
|
m_password = Json::getString(object, kPass);
|
||||||
m_rigId = Json::getString(object, kRigId);
|
m_rigId = Json::getString(object, kRigId);
|
||||||
m_fingerprint = Json::getString(object, kFingerprint);
|
m_fingerprint = Json::getString(object, kFingerprint);
|
||||||
|
m_pollInterval = Json::getUint64(object, kDaemonPollInterval, kDefaultPollInterval);
|
||||||
|
|
||||||
m_flags.set(FLAG_ENABLED, Json::getBool(object, kEnabled, true));
|
m_flags.set(FLAG_ENABLED, Json::getBool(object, kEnabled, true));
|
||||||
m_flags.set(FLAG_NICEHASH, Json::getBool(object, kNicehash));
|
m_flags.set(FLAG_NICEHASH, Json::getBool(object, kNicehash));
|
||||||
m_flags.set(FLAG_TLS, Json::getBool(object, kTls, m_flags.test(FLAG_TLS)));
|
m_flags.set(FLAG_TLS, Json::getBool(object, kTls, m_flags.test(FLAG_TLS)));
|
||||||
|
m_flags.set(FLAG_DAEMON, Json::getBool(object, kDaemon, m_flags.test(FLAG_DAEMON)));
|
||||||
|
|
||||||
const rapidjson::Value &keepalive = Json::getValue(object, kKeepalive);
|
const rapidjson::Value &keepalive = Json::getValue(object, kKeepalive);
|
||||||
if (keepalive.IsInt()) {
|
if (keepalive.IsInt()) {
|
||||||
|
@ -135,7 +150,8 @@ xmrig::Pool::Pool(const char *host, uint16_t port, const char *user, const char
|
||||||
m_host(host),
|
m_host(host),
|
||||||
m_password(password),
|
m_password(password),
|
||||||
m_user(user),
|
m_user(user),
|
||||||
m_port(port)
|
m_port(port),
|
||||||
|
m_pollInterval(kDefaultPollInterval)
|
||||||
{
|
{
|
||||||
const size_t size = m_host.size() + 8;
|
const size_t size = m_host.size() + 8;
|
||||||
assert(size > 8);
|
assert(size > 8);
|
||||||
|
@ -180,22 +196,29 @@ bool xmrig::Pool::isEnabled() const
|
||||||
}
|
}
|
||||||
# endif
|
# endif
|
||||||
|
|
||||||
|
# ifndef XMRIG_FEATURE_HTTP
|
||||||
|
if (isDaemon()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
# endif
|
||||||
|
|
||||||
return m_flags.test(FLAG_ENABLED) && isValid() && algorithm().isValid();
|
return m_flags.test(FLAG_ENABLED) && isValid() && algorithm().isValid();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool xmrig::Pool::isEqual(const Pool &other) const
|
bool xmrig::Pool::isEqual(const Pool &other) const
|
||||||
{
|
{
|
||||||
return (m_flags == other.m_flags
|
return (m_flags == other.m_flags
|
||||||
&& m_keepAlive == other.m_keepAlive
|
&& m_keepAlive == other.m_keepAlive
|
||||||
&& m_port == other.m_port
|
&& m_port == other.m_port
|
||||||
&& m_algorithm == other.m_algorithm
|
&& m_algorithm == other.m_algorithm
|
||||||
&& m_fingerprint == other.m_fingerprint
|
&& m_fingerprint == other.m_fingerprint
|
||||||
&& m_host == other.m_host
|
&& m_host == other.m_host
|
||||||
&& m_password == other.m_password
|
&& m_password == other.m_password
|
||||||
&& m_rigId == other.m_rigId
|
&& m_rigId == other.m_rigId
|
||||||
&& m_url == other.m_url
|
&& m_url == other.m_url
|
||||||
&& m_user == other.m_user);
|
&& m_user == other.m_user
|
||||||
|
&& m_pollInterval == other.m_pollInterval);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -203,21 +226,33 @@ bool xmrig::Pool::parse(const char *url)
|
||||||
{
|
{
|
||||||
assert(url != nullptr);
|
assert(url != nullptr);
|
||||||
|
|
||||||
const char *p = strstr(url, "://");
|
const char *p = strstr(url, "://");
|
||||||
const char *base = url;
|
const char *base = url;
|
||||||
|
|
||||||
if (p) {
|
if (p) {
|
||||||
if (strncasecmp(url, "stratum+tcp://", 14) == 0) {
|
if (strncasecmp(url, kStratumTcp, sizeof(kStratumTcp) - 1) == 0) {
|
||||||
m_flags.set(FLAG_TLS, false);
|
m_flags.set(FLAG_DAEMON, false);
|
||||||
|
m_flags.set(FLAG_TLS, false);
|
||||||
}
|
}
|
||||||
else if (strncasecmp(url, "stratum+ssl://", 14) == 0) {
|
else if (strncasecmp(url, kStratumSsl, sizeof(kStratumSsl) - 1) == 0) {
|
||||||
m_flags.set(FLAG_TLS, true);
|
m_flags.set(FLAG_DAEMON, false);
|
||||||
|
m_flags.set(FLAG_TLS, true);
|
||||||
}
|
}
|
||||||
|
# ifdef XMRIG_FEATURE_HTTP
|
||||||
|
else if (strncasecmp(url, kDaemonHttps, sizeof(kDaemonHttps) - 1) == 0) {
|
||||||
|
m_flags.set(FLAG_DAEMON, true);
|
||||||
|
m_flags.set(FLAG_TLS, true);
|
||||||
|
}
|
||||||
|
else if (strncasecmp(url, kDaemonHttp, sizeof(kDaemonHttp) - 1) == 0) {
|
||||||
|
m_flags.set(FLAG_DAEMON, true);
|
||||||
|
m_flags.set(FLAG_TLS, false);
|
||||||
|
}
|
||||||
|
# endif
|
||||||
else {
|
else {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
base = url + 14;
|
base = p + 3;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!strlen(base) || *base == '/') {
|
if (!strlen(base) || *base == '/') {
|
||||||
|
@ -286,9 +321,11 @@ rapidjson::Value xmrig::Pool::toJSON(rapidjson::Document &doc) const
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
obj.AddMember(StringRef(kEnabled), m_flags.test(FLAG_ENABLED), allocator);
|
obj.AddMember(StringRef(kEnabled), m_flags.test(FLAG_ENABLED), allocator);
|
||||||
obj.AddMember(StringRef(kTls), isTLS(), allocator);
|
obj.AddMember(StringRef(kTls), isTLS(), allocator);
|
||||||
obj.AddMember(StringRef(kFingerprint), m_fingerprint.toJSON(), allocator);
|
obj.AddMember(StringRef(kFingerprint), m_fingerprint.toJSON(), allocator);
|
||||||
|
obj.AddMember(StringRef(kDaemon), m_flags.test(FLAG_DAEMON), allocator);
|
||||||
|
obj.AddMember(StringRef(kDaemonPollInterval), m_pollInterval, allocator);
|
||||||
|
|
||||||
return obj;
|
return obj;
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
* Copyright 2016 Jay D Dee <jayddee246@gmail.com>
|
* Copyright 2016 Jay D Dee <jayddee246@gmail.com>
|
||||||
* Copyright 2017-2018 XMR-Stak <https://github.com/fireice-uk>, <https://github.com/psychocrypt>
|
* Copyright 2017-2018 XMR-Stak <https://github.com/fireice-uk>, <https://github.com/psychocrypt>
|
||||||
* Copyright 2018-2019 SChernykh <https://github.com/SChernykh>
|
* 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>
|
* Copyright 2016-2019 XMRig <https://github.com/xmrig>, <support@xmrig.com>
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
@ -45,14 +46,16 @@ public:
|
||||||
FLAG_ENABLED,
|
FLAG_ENABLED,
|
||||||
FLAG_NICEHASH,
|
FLAG_NICEHASH,
|
||||||
FLAG_TLS,
|
FLAG_TLS,
|
||||||
|
FLAG_DAEMON,
|
||||||
FLAG_MAX
|
FLAG_MAX
|
||||||
};
|
};
|
||||||
|
|
||||||
static const String kDefaultPassword;
|
static const String kDefaultPassword;
|
||||||
static const String kDefaultUser;
|
static const String kDefaultUser;
|
||||||
|
|
||||||
constexpr static uint16_t kDefaultPort = 3333;
|
constexpr static int kKeepAliveTimeout = 60;
|
||||||
constexpr static int kKeepAliveTimeout = 60;
|
constexpr static uint16_t kDefaultPort = 3333;
|
||||||
|
constexpr static uint64_t kDefaultPollInterval = 1000;
|
||||||
|
|
||||||
Pool();
|
Pool();
|
||||||
Pool(const char *url);
|
Pool(const char *url);
|
||||||
|
@ -67,6 +70,7 @@ public:
|
||||||
);
|
);
|
||||||
|
|
||||||
inline Algorithm &algorithm() { return m_algorithm; }
|
inline Algorithm &algorithm() { return m_algorithm; }
|
||||||
|
inline bool isDaemon() const { return m_flags.test(FLAG_DAEMON); }
|
||||||
inline bool isNicehash() const { return m_flags.test(FLAG_NICEHASH); }
|
inline bool isNicehash() const { return m_flags.test(FLAG_NICEHASH); }
|
||||||
inline bool isTLS() const { return m_flags.test(FLAG_TLS); }
|
inline bool isTLS() const { return m_flags.test(FLAG_TLS); }
|
||||||
inline bool isValid() const { return !m_host.isNull() && m_port > 0; }
|
inline bool isValid() const { return !m_host.isNull() && m_port > 0; }
|
||||||
|
@ -80,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); }
|
||||||
|
@ -116,6 +121,7 @@ private:
|
||||||
String m_url;
|
String m_url;
|
||||||
String m_user;
|
String m_user;
|
||||||
uint16_t m_port;
|
uint16_t m_port;
|
||||||
|
uint64_t m_pollInterval;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -38,17 +38,17 @@ public:
|
||||||
inline SubmitResult() :
|
inline SubmitResult() :
|
||||||
reqId(0),
|
reqId(0),
|
||||||
seq(0),
|
seq(0),
|
||||||
diff(0),
|
|
||||||
actualDiff(0),
|
actualDiff(0),
|
||||||
|
diff(0),
|
||||||
elapsed(0),
|
elapsed(0),
|
||||||
m_start(0)
|
m_start(0)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
inline SubmitResult(int64_t seq, uint32_t diff, uint64_t actualDiff, int64_t reqId = 0) :
|
inline SubmitResult(int64_t seq, uint64_t diff, uint64_t actualDiff, int64_t reqId = 0) :
|
||||||
reqId(reqId),
|
reqId(reqId),
|
||||||
seq(seq),
|
seq(seq),
|
||||||
diff(diff),
|
|
||||||
actualDiff(actualDiff),
|
actualDiff(actualDiff),
|
||||||
|
diff(diff),
|
||||||
elapsed(0),
|
elapsed(0),
|
||||||
m_start(Chrono::steadyMSecs())
|
m_start(Chrono::steadyMSecs())
|
||||||
{}
|
{}
|
||||||
|
@ -57,8 +57,8 @@ public:
|
||||||
|
|
||||||
int64_t reqId;
|
int64_t reqId;
|
||||||
int64_t seq;
|
int64_t seq;
|
||||||
uint32_t diff;
|
|
||||||
uint64_t actualDiff;
|
uint64_t actualDiff;
|
||||||
|
uint64_t diff;
|
||||||
uint64_t elapsed;
|
uint64_t elapsed;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
|
@ -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,13 +136,13 @@ 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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void xmrig::FailoverStrategy::onClose(Client *client, int failures)
|
void xmrig::FailoverStrategy::onClose(IClient *client, int failures)
|
||||||
{
|
{
|
||||||
if (failures == -1) {
|
if (failures == -1) {
|
||||||
return;
|
return;
|
||||||
|
@ -150,7 +163,7 @@ void xmrig::FailoverStrategy::onClose(Client *client, int failures)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void xmrig::FailoverStrategy::onJobReceived(Client *client, const Job &job, const rapidjson::Value &)
|
void xmrig::FailoverStrategy::onJobReceived(IClient *client, const Job &job, const rapidjson::Value &)
|
||||||
{
|
{
|
||||||
if (m_active == client->id()) {
|
if (m_active == client->id()) {
|
||||||
m_listener->onJob(this, client, job);
|
m_listener->onJob(this, client, job);
|
||||||
|
@ -158,7 +171,7 @@ void xmrig::FailoverStrategy::onJobReceived(Client *client, const Job &job, cons
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void xmrig::FailoverStrategy::onLoginSuccess(Client *client)
|
void xmrig::FailoverStrategy::onLoginSuccess(IClient *client)
|
||||||
{
|
{
|
||||||
int active = m_active;
|
int active = m_active;
|
||||||
|
|
||||||
|
@ -179,7 +192,7 @@ void xmrig::FailoverStrategy::onLoginSuccess(Client *client)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void xmrig::FailoverStrategy::onResultAccepted(Client *client, const SubmitResult &result, const char *error)
|
void xmrig::FailoverStrategy::onResultAccepted(IClient *client, const SubmitResult &result, const char *error)
|
||||||
{
|
{
|
||||||
m_listener->onResultAccepted(this, client, result, error);
|
m_listener->onResultAccepted(this, client, result, error);
|
||||||
}
|
}
|
||||||
|
|
|
@ -51,9 +51,9 @@ public:
|
||||||
void add(const Pool &pool);
|
void add(const Pool &pool);
|
||||||
|
|
||||||
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(Client *, 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;
|
||||||
void connect() override;
|
void connect() override;
|
||||||
|
@ -62,13 +62,13 @@ protected:
|
||||||
void stop() override;
|
void stop() override;
|
||||||
void tick(uint64_t now) override;
|
void tick(uint64_t now) override;
|
||||||
|
|
||||||
void onClose(Client *client, int failures) override;
|
void onClose(IClient *client, int failures) override;
|
||||||
void onJobReceived(Client *client, const Job &job, const rapidjson::Value ¶ms) override;
|
void onJobReceived(IClient *client, const Job &job, const rapidjson::Value ¶ms) override;
|
||||||
void onLoginSuccess(Client *client) override;
|
void onLoginSuccess(IClient *client) override;
|
||||||
void onResultAccepted(Client *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);
|
||||||
|
@ -87,7 +102,7 @@ void xmrig::SinglePoolStrategy::tick(uint64_t now)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void xmrig::SinglePoolStrategy::onClose(Client *, int)
|
void xmrig::SinglePoolStrategy::onClose(IClient *, int)
|
||||||
{
|
{
|
||||||
if (!isActive()) {
|
if (!isActive()) {
|
||||||
return;
|
return;
|
||||||
|
@ -98,20 +113,20 @@ void xmrig::SinglePoolStrategy::onClose(Client *, int)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void xmrig::SinglePoolStrategy::onJobReceived(Client *client, const Job &job, const rapidjson::Value &)
|
void xmrig::SinglePoolStrategy::onJobReceived(IClient *client, const Job &job, const rapidjson::Value &)
|
||||||
{
|
{
|
||||||
m_listener->onJob(this, client, job);
|
m_listener->onJob(this, client, job);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void xmrig::SinglePoolStrategy::onLoginSuccess(Client *client)
|
void xmrig::SinglePoolStrategy::onLoginSuccess(IClient *client)
|
||||||
{
|
{
|
||||||
m_active = true;
|
m_active = true;
|
||||||
m_listener->onActive(this, client);
|
m_listener->onActive(this, client);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void xmrig::SinglePoolStrategy::onResultAccepted(Client *client, const SubmitResult &result, const char *error)
|
void xmrig::SinglePoolStrategy::onResultAccepted(IClient *client, const SubmitResult &result, const char *error)
|
||||||
{
|
{
|
||||||
m_listener->onResultAccepted(this, client, result, error);
|
m_listener->onResultAccepted(this, client, result, error);
|
||||||
}
|
}
|
||||||
|
|
|
@ -45,9 +45,9 @@ public:
|
||||||
~SinglePoolStrategy() override;
|
~SinglePoolStrategy() override;
|
||||||
|
|
||||||
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(Client *, 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;
|
||||||
void connect() override;
|
void connect() override;
|
||||||
|
@ -56,14 +56,14 @@ protected:
|
||||||
void stop() override;
|
void stop() override;
|
||||||
void tick(uint64_t now) override;
|
void tick(uint64_t now) override;
|
||||||
|
|
||||||
void onClose(Client *client, int failures) override;
|
void onClose(IClient *client, int failures) override;
|
||||||
void onJobReceived(Client *client, const Job &job, const rapidjson::Value ¶ms) override;
|
void onJobReceived(IClient *client, const Job &job, const rapidjson::Value ¶ms) override;
|
||||||
void onLoginSuccess(Client *client) override;
|
void onLoginSuccess(IClient *client) override;
|
||||||
void onResultAccepted(Client *client, const SubmitResult &result, const char *error) override;
|
void onResultAccepted(IClient *client, const SubmitResult &result, const char *error) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool m_active;
|
bool m_active;
|
||||||
Client *m_client;
|
IClient *m_client;
|
||||||
IStrategyListener *m_listener;
|
IStrategyListener *m_listener;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -82,6 +82,8 @@ static const option options[] = {
|
||||||
{ "tls", 0, nullptr, IConfig::TlsKey },
|
{ "tls", 0, nullptr, IConfig::TlsKey },
|
||||||
{ "tls-fingerprint", 1, nullptr, IConfig::FingerprintKey },
|
{ "tls-fingerprint", 1, nullptr, IConfig::FingerprintKey },
|
||||||
{ "asm", 1, nullptr, IConfig::AssemblyKey },
|
{ "asm", 1, nullptr, IConfig::AssemblyKey },
|
||||||
|
{ "daemon", 0, nullptr, IConfig::DaemonKey },
|
||||||
|
{ "daemon-poll-interval", 1, nullptr, IConfig::DaemonPollKey },
|
||||||
|
|
||||||
# ifdef XMRIG_DEPRECATED
|
# ifdef XMRIG_DEPRECATED
|
||||||
{ "api-port", 1, nullptr, IConfig::ApiPort },
|
{ "api-port", 1, nullptr, IConfig::ApiPort },
|
||||||
|
|
|
@ -35,59 +35,76 @@ namespace xmrig {
|
||||||
static char const usage[] = "\
|
static char const usage[] = "\
|
||||||
Usage: " APP_ID " [OPTIONS]\n\
|
Usage: " APP_ID " [OPTIONS]\n\
|
||||||
Options:\n\
|
Options:\n\
|
||||||
-a, --algo=ALGO specify the algorithm to use\n\
|
-a, --algo=ALGO specify the algorithm to use\n\
|
||||||
cryptonight\n"
|
cryptonight\n"
|
||||||
#ifndef XMRIG_NO_AEON
|
#ifndef XMRIG_NO_AEON
|
||||||
"\
|
"\
|
||||||
cryptonight-lite\n"
|
cryptonight-lite\n"
|
||||||
#endif
|
#endif
|
||||||
#ifndef XMRIG_NO_SUMO
|
#ifndef XMRIG_NO_SUMO
|
||||||
"\
|
"\
|
||||||
cryptonight-heavy\n"
|
cryptonight-heavy\n"
|
||||||
|
#endif
|
||||||
|
#ifndef XMRIG_NO_CN_PICO
|
||||||
|
"\
|
||||||
|
cryptonight-pico\n"
|
||||||
#endif
|
#endif
|
||||||
"\
|
"\
|
||||||
-o, --url=URL URL of mining server\n\
|
-o, --url=URL URL of mining server\n\
|
||||||
-O, --userpass=U:P username:password pair for mining server\n\
|
-O, --userpass=U:P username:password pair for mining server\n\
|
||||||
-u, --user=USERNAME username for mining server\n\
|
-u, --user=USERNAME username for mining server\n\
|
||||||
-p, --pass=PASSWORD password for mining server\n\
|
-p, --pass=PASSWORD password for mining server\n\
|
||||||
--rig-id=ID rig identifier for pool-side statistics (needs pool support)\n\
|
--rig-id=ID rig identifier for pool-side statistics (needs pool support)\n\
|
||||||
-t, --threads=N number of miner threads\n\
|
-t, --threads=N number of miner threads\n\
|
||||||
-v, --av=N algorithm variation, 0 auto select\n\
|
-v, --av=N algorithm variation, 0 auto select\n\
|
||||||
-k, --keepalive send keepalived packet for prevent timeout (needs pool support)\n\
|
-k, --keepalive send keepalived packet for prevent timeout (needs pool support)\n\
|
||||||
--nicehash enable nicehash.com support\n\
|
--nicehash enable nicehash.com support\n"
|
||||||
--tls enable SSL/TLS support (needs pool support)\n\
|
#ifdef XMRIG_FEATURE_TLS
|
||||||
--tls-fingerprint=F pool TLS certificate fingerprint, if set enable strict certificate pinning\n\
|
"\
|
||||||
-r, --retries=N number of times to retry before switch to backup server (default: 5)\n\
|
--tls enable SSL/TLS support (needs pool support)\n\
|
||||||
-R, --retry-pause=N time to pause between retries (default: 5)\n\
|
--tls-fingerprint=F pool TLS certificate fingerprint, if set enable strict certificate pinning\n"
|
||||||
--cpu-affinity set process affinity to CPU core(s), mask 0x3 for cores 0 and 1\n\
|
#endif
|
||||||
--cpu-priority set process priority (0 idle, 2 normal to 5 highest)\n\
|
#ifdef XMRIG_FEATURE_HTTP
|
||||||
--no-huge-pages disable huge pages support\n\
|
"\
|
||||||
--no-color disable colored output\n\
|
--daemon use daemon RPC instead of pool for solo mining\n\
|
||||||
--variant algorithm PoW variant\n\
|
--daemon-poll-interval=N daemon poll interval in milliseconds (default: 1000)\n"
|
||||||
--donate-level=N donate level, default 5%% (5 minutes in 100 minutes)\n\
|
#endif
|
||||||
--user-agent set custom user-agent string for pool\n\
|
"\
|
||||||
-B, --background run the miner in the background\n\
|
-r, --retries=N number of times to retry before switch to backup server (default: 5)\n\
|
||||||
-c, --config=FILE load a JSON-format configuration file\n\
|
-R, --retry-pause=N time to pause between retries (default: 5)\n\
|
||||||
-l, --log-file=FILE log all output to a file\n"
|
--cpu-affinity set process affinity to CPU core(s), mask 0x3 for cores 0 and 1\n\
|
||||||
|
--cpu-priority set process priority (0 idle, 2 normal to 5 highest)\n\
|
||||||
|
--no-huge-pages disable huge pages support\n\
|
||||||
|
--no-color disable colored output\n\
|
||||||
|
--variant algorithm PoW variant\n\
|
||||||
|
--donate-level=N donate level, default 5%% (5 minutes in 100 minutes)\n\
|
||||||
|
--user-agent set custom user-agent string for pool\n\
|
||||||
|
-B, --background run the miner in the background\n\
|
||||||
|
-c, --config=FILE load a JSON-format configuration file\n\
|
||||||
|
-l, --log-file=FILE log all output to a file\n"
|
||||||
# ifdef HAVE_SYSLOG_H
|
# ifdef HAVE_SYSLOG_H
|
||||||
"\
|
"\
|
||||||
-S, --syslog use system log for output messages\n"
|
-S, --syslog use system log for output messages\n"
|
||||||
# endif
|
# endif
|
||||||
"\
|
"\
|
||||||
--max-cpu-usage=N maximum CPU usage for automatic threads mode (default 75)\n\
|
--max-cpu-usage=N maximum CPU usage for automatic threads mode (default: 100)\n\
|
||||||
--safe safe adjust threads and av settings for current CPU\n\
|
--safe safe adjust threads and av settings for current CPU\n\
|
||||||
--asm=ASM ASM code for cn/2, possible values: auto, none, intel, ryzen, bulldozer.\n\
|
--asm=ASM ASM optimizations, possible values: auto, none, intel, ryzen, bulldozer.\n\
|
||||||
--print-time=N print hashrate report every N seconds\n\
|
--print-time=N print hashrate report every N seconds\n"
|
||||||
--api-worker-id=ID custom worker-id for API\n\
|
#ifdef XMRIG_FEATURE_HTTP
|
||||||
--api-id=ID custom instance ID for API\n\
|
"\
|
||||||
--http-enabled enable HTTP API\n\
|
--api-worker-id=ID custom worker-id for API\n\
|
||||||
--http-host=HOST bind host for HTTP API (by default 127.0.0.1)\n\
|
--api-id=ID custom instance ID for API\n\
|
||||||
--http-port=N bind port for HTTP API\n\
|
--http-enabled enable HTTP API\n\
|
||||||
--http-access-token=T access token for HTTP API\n\
|
--http-host=HOST bind host for HTTP API (default: 127.0.0.1)\n\
|
||||||
--http-no-restricted enable full remote access to HTTP API (only if access token set)\n\
|
--http-port=N bind port for HTTP API\n\
|
||||||
--dry-run test configuration and exit\n\
|
--http-access-token=T access token for HTTP API\n\
|
||||||
-h, --help display this help and exit\n\
|
--http-no-restricted enable full remote access to HTTP API (only if access token set)\n"
|
||||||
-V, --version output version information and exit\n\
|
#endif
|
||||||
|
"\
|
||||||
|
--dry-run test configuration and exit\n\
|
||||||
|
-h, --help display this help and exit\n\
|
||||||
|
-V, --version output version information and exit\n\
|
||||||
";
|
";
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -41,20 +41,20 @@ namespace xmrig {
|
||||||
class JobResult
|
class JobResult
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
inline JobResult() : poolId(0), diff(0), nonce(0) {}
|
inline JobResult() : poolId(0), nonce(0), diff(0) {}
|
||||||
inline JobResult(int poolId, const String &jobId, const String &clientId, uint32_t nonce, const uint8_t *result, uint32_t diff, const Algorithm &algorithm) :
|
inline JobResult(int poolId, const String &jobId, const String &clientId, uint32_t nonce, const uint8_t *result, uint64_t diff, const Algorithm &algorithm) :
|
||||||
algorithm(algorithm),
|
algorithm(algorithm),
|
||||||
poolId(poolId),
|
poolId(poolId),
|
||||||
clientId(clientId),
|
clientId(clientId),
|
||||||
jobId(jobId),
|
jobId(jobId),
|
||||||
diff(diff),
|
nonce(nonce),
|
||||||
nonce(nonce)
|
diff(diff)
|
||||||
{
|
{
|
||||||
memcpy(this->result, result, sizeof(this->result));
|
memcpy(this->result, result, sizeof(this->result));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
inline JobResult(const Job &job) : poolId(0), diff(0), nonce(0)
|
inline JobResult(const Job &job) : poolId(0), nonce(0), diff(0)
|
||||||
{
|
{
|
||||||
jobId = job.id();
|
jobId = job.id();
|
||||||
clientId = job.clientId();
|
clientId = job.clientId();
|
||||||
|
@ -75,8 +75,8 @@ public:
|
||||||
int poolId;
|
int poolId;
|
||||||
String clientId;
|
String clientId;
|
||||||
String jobId;
|
String jobId;
|
||||||
uint32_t diff;
|
|
||||||
uint32_t nonce;
|
uint32_t nonce;
|
||||||
|
uint64_t diff;
|
||||||
uint8_t result[32];
|
uint8_t result[32];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
* Copyright 2016 Jay D Dee <jayddee246@gmail.com>
|
* Copyright 2016 Jay D Dee <jayddee246@gmail.com>
|
||||||
* Copyright 2017-2018 XMR-Stak <https://github.com/fireice-uk>, <https://github.com/psychocrypt>
|
* Copyright 2017-2018 XMR-Stak <https://github.com/fireice-uk>, <https://github.com/psychocrypt>
|
||||||
* Copyright 2018-2019 SChernykh <https://github.com/SChernykh>
|
* 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>
|
* Copyright 2016-2019 XMRig <https://github.com/xmrig>, <support@xmrig.com>
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
@ -91,18 +92,18 @@ void xmrig::Network::connect()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void xmrig::Network::onActive(IStrategy *strategy, Client *client)
|
void xmrig::Network::onActive(IStrategy *strategy, IClient *client)
|
||||||
{
|
{
|
||||||
if (m_donate && m_donate == strategy) {
|
if (m_donate && m_donate == strategy) {
|
||||||
LOG_NOTICE("dev donate started");
|
LOG_NOTICE("dev donate started");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
m_state.setPool(client->host(), client->port(), client->ip());
|
m_state.setPool(client->pool().host(), client->pool().port(), client->ip());
|
||||||
|
|
||||||
const char *tlsVersion = client->tlsVersion();
|
const char *tlsVersion = client->tlsVersion();
|
||||||
LOG_INFO(WHITE_BOLD("use pool ") CYAN_BOLD("%s:%d ") GREEN_BOLD("%s") " " BLACK_BOLD("%s"),
|
LOG_INFO(WHITE_BOLD("use %s ") CYAN_BOLD("%s:%d ") GREEN_BOLD("%s") " " BLACK_BOLD("%s"),
|
||||||
client->host(), client->port(), tlsVersion ? tlsVersion : "", client->ip());
|
client->mode(), client->pool().host().data(), client->pool().port(), tlsVersion ? tlsVersion : "", client->ip().data());
|
||||||
|
|
||||||
const char *fingerprint = client->tlsFingerprint();
|
const char *fingerprint = client->tlsFingerprint();
|
||||||
if (fingerprint != nullptr) {
|
if (fingerprint != nullptr) {
|
||||||
|
@ -127,7 +128,7 @@ void xmrig::Network::onConfigChanged(Config *config, Config *previousConfig)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void xmrig::Network::onJob(IStrategy *strategy, Client *client, const Job &job)
|
void xmrig::Network::onJob(IStrategy *strategy, IClient *client, const Job &job)
|
||||||
{
|
{
|
||||||
if (m_donate && m_donate->isActive() && m_donate != strategy) {
|
if (m_donate && m_donate->isActive() && m_donate != strategy) {
|
||||||
return;
|
return;
|
||||||
|
@ -176,30 +177,30 @@ void xmrig::Network::onRequest(IApiRequest &request)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void xmrig::Network::onResultAccepted(IStrategy *, Client *, const SubmitResult &result, const char *error)
|
void xmrig::Network::onResultAccepted(IStrategy *, IClient *, const SubmitResult &result, const char *error)
|
||||||
{
|
{
|
||||||
m_state.add(result, error);
|
m_state.add(result, error);
|
||||||
|
|
||||||
if (error) {
|
if (error) {
|
||||||
LOG_INFO(RED_BOLD("rejected") " (%" PRId64 "/%" PRId64 ") diff " WHITE_BOLD("%u") " " RED("\"%s\"") " " BLACK_BOLD("(%" PRIu64 " ms)"),
|
LOG_INFO(RED_BOLD("rejected") " (%" PRId64 "/%" PRId64 ") diff " WHITE_BOLD("%" PRIu64) " " RED("\"%s\"") " " BLACK_BOLD("(%" PRIu64 " ms)"),
|
||||||
m_state.accepted, m_state.rejected, result.diff, error, result.elapsed);
|
m_state.accepted, m_state.rejected, result.diff, error, result.elapsed);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
LOG_INFO(GREEN_BOLD("accepted") " (%" PRId64 "/%" PRId64 ") diff " WHITE_BOLD("%u") " " BLACK_BOLD("(%" PRIu64 " ms)"),
|
LOG_INFO(GREEN_BOLD("accepted") " (%" PRId64 "/%" PRId64 ") diff " WHITE_BOLD("%" PRIu64) " " BLACK_BOLD("(%" PRIu64 " ms)"),
|
||||||
m_state.accepted, m_state.rejected, result.diff, result.elapsed);
|
m_state.accepted, m_state.rejected, result.diff, result.elapsed);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void xmrig::Network::setJob(Client *client, const Job &job, bool donate)
|
void xmrig::Network::setJob(IClient *client, const Job &job, bool donate)
|
||||||
{
|
{
|
||||||
if (job.height()) {
|
if (job.height()) {
|
||||||
LOG_INFO(MAGENTA_BOLD("new job") " from " WHITE_BOLD("%s:%d") " diff " WHITE_BOLD("%d") " algo " WHITE_BOLD("%s") " height " WHITE_BOLD("%" PRIu64),
|
LOG_INFO(MAGENTA_BOLD("new job") " from " WHITE_BOLD("%s:%d") " diff " WHITE_BOLD("%" PRIu64) " algo " WHITE_BOLD("%s") " height " WHITE_BOLD("%" PRIu64),
|
||||||
client->host(), client->port(), job.diff(), job.algorithm().shortName(), job.height());
|
client->pool().host().data(), client->pool().port(), job.diff(), job.algorithm().shortName(), job.height());
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
LOG_INFO(MAGENTA_BOLD("new job") " from " WHITE_BOLD("%s:%d") " diff " WHITE_BOLD("%d") " algo " WHITE_BOLD("%s"),
|
LOG_INFO(MAGENTA_BOLD("new job") " from " WHITE_BOLD("%s:%d") " diff " WHITE_BOLD("%" PRIu64) " algo " WHITE_BOLD("%s"),
|
||||||
client->host(), client->port(), job.diff(), job.algorithm().shortName());
|
client->pool().host().data(), client->pool().port(), job.diff(), job.algorithm().shortName());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!donate && m_donate) {
|
if (!donate && m_donate) {
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
* Copyright 2016 Jay D Dee <jayddee246@gmail.com>
|
* Copyright 2016 Jay D Dee <jayddee246@gmail.com>
|
||||||
* Copyright 2017-2018 XMR-Stak <https://github.com/fireice-uk>, <https://github.com/psychocrypt>
|
* Copyright 2017-2018 XMR-Stak <https://github.com/fireice-uk>, <https://github.com/psychocrypt>
|
||||||
* Copyright 2018-2019 SChernykh <https://github.com/SChernykh>
|
* 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>
|
* Copyright 2016-2019 XMRig <https://github.com/xmrig>, <support@xmrig.com>
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
@ -58,18 +59,18 @@ public:
|
||||||
protected:
|
protected:
|
||||||
inline void onTimer(const Timer *) override { tick(); }
|
inline void onTimer(const Timer *) override { tick(); }
|
||||||
|
|
||||||
void onActive(IStrategy *strategy, Client *client) override;
|
void onActive(IStrategy *strategy, IClient *client) override;
|
||||||
void onConfigChanged(Config *config, Config *previousConfig) override;
|
void onConfigChanged(Config *config, Config *previousConfig) override;
|
||||||
void onJob(IStrategy *strategy, Client *client, const Job &job) override;
|
void onJob(IStrategy *strategy, IClient *client, const Job &job) override;
|
||||||
void onJobResult(const JobResult &result) override;
|
void onJobResult(const JobResult &result) override;
|
||||||
void onPause(IStrategy *strategy) override;
|
void onPause(IStrategy *strategy) override;
|
||||||
void onRequest(IApiRequest &request) override;
|
void onRequest(IApiRequest &request) override;
|
||||||
void onResultAccepted(IStrategy *strategy, Client *client, const SubmitResult &result, const char *error) override;
|
void onResultAccepted(IStrategy *strategy, IClient *client, const SubmitResult &result, const char *error) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
constexpr static int kTickInterval = 1 * 1000;
|
constexpr static int kTickInterval = 1 * 1000;
|
||||||
|
|
||||||
void setJob(Client *client, const Job &job, bool donate);
|
void setJob(IClient *client, const Job &job, bool donate);
|
||||||
void tick();
|
void tick();
|
||||||
|
|
||||||
# ifdef XMRIG_FEATURE_API
|
# ifdef XMRIG_FEATURE_API
|
||||||
|
|
|
@ -35,14 +35,14 @@
|
||||||
|
|
||||||
|
|
||||||
xmrig::NetworkState::NetworkState() :
|
xmrig::NetworkState::NetworkState() :
|
||||||
diff(0),
|
pool(),
|
||||||
accepted(0),
|
accepted(0),
|
||||||
|
diff(0),
|
||||||
failures(0),
|
failures(0),
|
||||||
rejected(0),
|
rejected(0),
|
||||||
total(0),
|
total(0),
|
||||||
m_active(false)
|
m_active(false)
|
||||||
{
|
{
|
||||||
memset(pool, 0, sizeof(pool));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -50,8 +50,8 @@ public:
|
||||||
|
|
||||||
char pool[256];
|
char pool[256];
|
||||||
std::array<uint64_t, 10> topDiff { { } };
|
std::array<uint64_t, 10> topDiff { { } };
|
||||||
uint32_t diff;
|
|
||||||
uint64_t accepted;
|
uint64_t accepted;
|
||||||
|
uint64_t diff;
|
||||||
uint64_t failures;
|
uint64_t failures;
|
||||||
uint64_t rejected;
|
uint64_t rejected;
|
||||||
uint64_t total;
|
uint64_t total;
|
||||||
|
|
|
@ -157,7 +157,7 @@ void xmrig::DonateStrategy::tick(uint64_t now)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void xmrig::DonateStrategy::onActive(IStrategy *, Client *client)
|
void xmrig::DonateStrategy::onActive(IStrategy *, IClient *client)
|
||||||
{
|
{
|
||||||
if (isActive()) {
|
if (isActive()) {
|
||||||
return;
|
return;
|
||||||
|
@ -173,7 +173,7 @@ void xmrig::DonateStrategy::onPause(IStrategy *)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void xmrig::DonateStrategy::onClose(Client *, int failures)
|
void xmrig::DonateStrategy::onClose(IClient *, int failures)
|
||||||
{
|
{
|
||||||
if (failures == 2 && m_controller->config()->pools().proxyDonate() == Pools::PROXY_DONATE_AUTO) {
|
if (failures == 2 && m_controller->config()->pools().proxyDonate() == Pools::PROXY_DONATE_AUTO) {
|
||||||
m_proxy->deleteLater();
|
m_proxy->deleteLater();
|
||||||
|
@ -184,7 +184,7 @@ void xmrig::DonateStrategy::onClose(Client *, int failures)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void xmrig::DonateStrategy::onLogin(Client *, rapidjson::Document &doc, rapidjson::Value ¶ms)
|
void xmrig::DonateStrategy::onLogin(IClient *, rapidjson::Document &doc, rapidjson::Value ¶ms)
|
||||||
{
|
{
|
||||||
auto &allocator = doc.GetAllocator();
|
auto &allocator = doc.GetAllocator();
|
||||||
|
|
||||||
|
@ -203,7 +203,7 @@ void xmrig::DonateStrategy::onLogin(Client *, rapidjson::Document &doc, rapidjso
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void xmrig::DonateStrategy::onLoginSuccess(Client *client)
|
void xmrig::DonateStrategy::onLoginSuccess(IClient *client)
|
||||||
{
|
{
|
||||||
if (isActive()) {
|
if (isActive()) {
|
||||||
return;
|
return;
|
||||||
|
@ -227,14 +227,14 @@ xmrig::Client *xmrig::DonateStrategy::createProxy()
|
||||||
}
|
}
|
||||||
|
|
||||||
IStrategy *strategy = m_controller->network()->strategy();
|
IStrategy *strategy = m_controller->network()->strategy();
|
||||||
if (!strategy->isActive() || !strategy->client()->has<Client::EXT_CONNECT>()) {
|
if (!strategy->isActive() || !strategy->client()->hasExtension(IClient::EXT_CONNECT)) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
const Client *client = strategy->client();
|
const IClient *client = strategy->client();
|
||||||
m_tls = client->has<Client::EXT_TLS>();
|
m_tls = client->hasExtension(IClient::EXT_TLS);
|
||||||
|
|
||||||
Pool pool(client->ip(), client->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());
|
||||||
|
|
||||||
Client *proxy = new Client(-1, Platform::userAgent(), this);
|
Client *proxy = new Client(-1, Platform::userAgent(), this);
|
||||||
|
@ -251,7 +251,7 @@ void xmrig::DonateStrategy::idle(double min, double max)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void xmrig::DonateStrategy::setJob(Client *client, const Job &job)
|
void xmrig::DonateStrategy::setJob(IClient *client, const Job &job)
|
||||||
{
|
{
|
||||||
if (isActive()) {
|
if (isActive()) {
|
||||||
m_listener->onJob(this, client, job);
|
m_listener->onJob(this, client, job);
|
||||||
|
@ -259,7 +259,7 @@ void xmrig::DonateStrategy::setJob(Client *client, const Job &job)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void xmrig::DonateStrategy::setResult(Client *client, const SubmitResult &result, const char *error)
|
void xmrig::DonateStrategy::setResult(IClient *client, const SubmitResult &result, const char *error)
|
||||||
{
|
{
|
||||||
m_listener->onResultAccepted(this, client, result, error);
|
m_listener->onResultAccepted(this, client, result, error);
|
||||||
}
|
}
|
||||||
|
|
|
@ -51,13 +51,13 @@ public:
|
||||||
~DonateStrategy() override;
|
~DonateStrategy() override;
|
||||||
|
|
||||||
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 *, Client *client, const Job &job) override { setJob(client, job); }
|
inline void onJob(IStrategy *, IClient *client, const Job &job) override { setJob(client, job); }
|
||||||
inline void onJobReceived(Client *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(Client *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); }
|
||||||
inline void onResultAccepted(IStrategy *, Client *client, const SubmitResult &result, const char *error) override { setResult(client, result, error); }
|
inline void onResultAccepted(IStrategy *, IClient *client, const SubmitResult &result, const char *error) override { setResult(client, result, error); }
|
||||||
inline void resume() override {}
|
inline void resume() override {}
|
||||||
|
|
||||||
int64_t submit(const JobResult &result) override;
|
int64_t submit(const JobResult &result) override;
|
||||||
void connect() override;
|
void connect() override;
|
||||||
|
@ -65,12 +65,12 @@ protected:
|
||||||
void stop() override;
|
void stop() override;
|
||||||
void tick(uint64_t now) override;
|
void tick(uint64_t now) override;
|
||||||
|
|
||||||
void onActive(IStrategy *strategy, Client *client) override;
|
void onActive(IStrategy *strategy, IClient *client) override;
|
||||||
void onPause(IStrategy *strategy) override;
|
void onPause(IStrategy *strategy) override;
|
||||||
|
|
||||||
void onClose(Client *client, int failures) override;
|
void onClose(IClient *client, int failures) override;
|
||||||
void onLogin(Client *client, rapidjson::Document &doc, rapidjson::Value ¶ms) override;
|
void onLogin(IClient *client, rapidjson::Document &doc, rapidjson::Value ¶ms) override;
|
||||||
void onLoginSuccess(Client *client) override;
|
void onLoginSuccess(IClient *client) override;
|
||||||
|
|
||||||
void onTimer(const Timer *timer) override;
|
void onTimer(const Timer *timer) override;
|
||||||
|
|
||||||
|
@ -87,13 +87,13 @@ private:
|
||||||
|
|
||||||
Client *createProxy();
|
Client *createProxy();
|
||||||
void idle(double min, double max);
|
void idle(double min, double max);
|
||||||
void setJob(Client *client, const Job &job);
|
void setJob(IClient *client, const Job &job);
|
||||||
void setResult(Client *client, const SubmitResult &result, const char *error);
|
void setResult(IClient *client, const SubmitResult &result, const char *error);
|
||||||
void setState(State state);
|
void setState(State state);
|
||||||
|
|
||||||
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…
Reference in a new issue