Implemented donate over proxy.

This commit is contained in:
XMRig 2019-03-19 21:31:54 +07:00
parent 0907d1eb0c
commit 4c95136e6a
9 changed files with 161 additions and 55 deletions

View file

@ -29,13 +29,12 @@
#include <stdint.h> #include <stdint.h>
class JobResult;
namespace xmrig { namespace xmrig {
class Algorithm; class Algorithm;
class Client;
class JobResult;
class IStrategy class IStrategy
@ -44,6 +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 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;

View file

@ -182,6 +182,16 @@ bool xmrig::Client::disconnect()
} }
bool xmrig::Client::isTLS() const
{
# ifndef XMRIG_NO_TLS
return m_pool.isTLS() && m_tls;
# else
return false;
# endif
}
const char *xmrig::Client::tlsFingerprint() const const char *xmrig::Client::tlsFingerprint() const
{ {
# ifndef XMRIG_NO_TLS # ifndef XMRIG_NO_TLS
@ -331,16 +341,6 @@ bool xmrig::Client::isCriticalError(const char *message)
} }
bool xmrig::Client::isTLS() const
{
# ifndef XMRIG_NO_TLS
return m_pool.isTLS() && m_tls;
# else
return false;
# endif
}
bool xmrig::Client::parseJob(const rapidjson::Value &params, int *code) bool xmrig::Client::parseJob(const rapidjson::Value &params, int *code)
{ {
if (!params.IsObject()) { if (!params.IsObject()) {

View file

@ -85,6 +85,7 @@ public:
~Client() override; ~Client() override;
bool disconnect(); bool disconnect();
bool isTLS() const;
const char *tlsFingerprint() const; const char *tlsFingerprint() const;
const char *tlsVersion() const; const char *tlsVersion() const;
int64_t submit(const JobResult &result); int64_t submit(const JobResult &result);
@ -99,6 +100,7 @@ public:
inline const char *host() const { return m_pool.host(); } inline const char *host() const { return m_pool.host(); }
inline const char *ip() const { return m_ip; } inline const char *ip() const { return m_ip; }
inline const Job &job() const { return m_job; } inline const Job &job() const { return m_job; }
inline const Pool &pool() const { return m_pool; }
inline int id() const { return m_id; } inline int id() const { return m_id; }
inline SocketState state() const { return m_state; } inline SocketState state() const { return m_state; }
inline uint16_t port() const { return m_pool.port(); } inline uint16_t port() const { return m_pool.port(); }
@ -120,7 +122,6 @@ private:
bool close(); bool close();
bool isCriticalError(const char *message); bool isCriticalError(const char *message);
bool isTLS() const;
bool parseJob(const rapidjson::Value &params, int *code); bool parseJob(const rapidjson::Value &params, int *code);
bool parseLogin(const rapidjson::Value &result, int *code); bool parseLogin(const rapidjson::Value &result, int *code);
bool send(BIO *bio); bool send(BIO *bio);

View file

@ -34,8 +34,8 @@ xmrig::FailoverStrategy::FailoverStrategy(const std::vector<Pool> &pools, int re
m_retries(retries), m_retries(retries),
m_retryPause(retryPause), m_retryPause(retryPause),
m_active(-1), m_active(-1),
m_index(0), m_listener(listener),
m_listener(listener) m_index(0)
{ {
for (const Pool &pool : pools) { for (const Pool &pool : pools) {
add(pool); add(pool);
@ -48,8 +48,8 @@ xmrig::FailoverStrategy::FailoverStrategy(int retryPause, int retries, IStrategy
m_retries(retries), m_retries(retries),
m_retryPause(retryPause), m_retryPause(retryPause),
m_active(-1), m_active(-1),
m_index(0), m_listener(listener),
m_listener(listener) m_index(0)
{ {
} }
@ -86,7 +86,7 @@ int64_t xmrig::FailoverStrategy::submit(const JobResult &result)
void xmrig::FailoverStrategy::connect() void xmrig::FailoverStrategy::connect()
{ {
m_pools[static_cast<size_t>(m_index)]->connect(); m_pools[m_index]->connect();
} }
@ -144,8 +144,8 @@ void xmrig::FailoverStrategy::onClose(Client *client, int failures)
return; return;
} }
if (m_index == client->id() && (m_pools.size() - static_cast<size_t>(m_index)) > 1) { if (m_index == static_cast<size_t>(client->id()) && (m_pools.size() - m_index) > 1) {
m_pools[static_cast<size_t>(++m_index)]->connect(); m_pools[++m_index]->connect();
} }
} }

View file

@ -50,8 +50,10 @@ public:
void add(const Pool &pool); void add(const Pool &pool);
public: 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 void onLogin(Client *, 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;
@ -60,9 +62,6 @@ public:
void stop() override; void stop() override;
void tick(uint64_t now) override; void tick(uint64_t now) override;
protected:
inline void onLogin(Client *, rapidjson::Document &, rapidjson::Value &) override {}
void onClose(Client *client, int failures) override; void onClose(Client *client, int failures) override;
void onJobReceived(Client *client, const Job &job, const rapidjson::Value &params) override; void onJobReceived(Client *client, const Job &job, const rapidjson::Value &params) override;
void onLoginSuccess(Client *client) override; void onLoginSuccess(Client *client) override;
@ -75,8 +74,8 @@ private:
const int m_retries; const int m_retries;
const int m_retryPause; const int m_retryPause;
int m_active; int m_active;
int m_index;
IStrategyListener *m_listener; IStrategyListener *m_listener;
size_t m_index;
std::vector<Client*> m_pools; std::vector<Client*> m_pools;
}; };

View file

@ -44,8 +44,10 @@ public:
SinglePoolStrategy(const Pool &pool, int retryPause, int retries, IStrategyListener *listener, bool quiet = false); SinglePoolStrategy(const Pool &pool, int retryPause, int retries, IStrategyListener *listener, bool quiet = false);
~SinglePoolStrategy() override; ~SinglePoolStrategy() override;
public: 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 void onLogin(Client *, 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;
@ -54,9 +56,6 @@ public:
void stop() override; void stop() override;
void tick(uint64_t now) override; void tick(uint64_t now) override;
protected:
inline void onLogin(Client *, rapidjson::Document &, rapidjson::Value &) override {}
void onClose(Client *client, int failures) override; void onClose(Client *client, int failures) override;
void onJobReceived(Client *client, const Job &job, const rapidjson::Value &params) override; void onJobReceived(Client *client, const Job &job, const rapidjson::Value &params) override;
void onLoginSuccess(Client *client) override; void onLoginSuccess(Client *client) override;

View file

@ -49,6 +49,8 @@ public:
Network(Controller *controller); Network(Controller *controller);
~Network() override; ~Network() override;
inline IStrategy *strategy() const { return m_strategy; }
void connect(); void connect();
protected: protected:

View file

@ -39,6 +39,7 @@
#include "core/Controller.h" #include "core/Controller.h"
#include "net/Network.h" #include "net/Network.h"
#include "net/strategies/DonateStrategy.h" #include "net/strategies/DonateStrategy.h"
#include "rapidjson/document.h"
namespace xmrig { namespace xmrig {
@ -55,6 +56,8 @@ static const char *kDonateHostTls = "donate.ssl.xmrig.com";
xmrig::DonateStrategy::DonateStrategy(Controller *controller, IStrategyListener *listener) : xmrig::DonateStrategy::DonateStrategy(Controller *controller, IStrategyListener *listener) :
m_tls(false),
m_userId(),
m_proxy(nullptr), m_proxy(nullptr),
m_donateTime(static_cast<uint64_t>(controller->config()->pools().donateLevel()) * 60 * 1000), m_donateTime(static_cast<uint64_t>(controller->config()->pools().donateLevel()) * 60 * 1000),
m_idleTime((100 - static_cast<uint64_t>(controller->config()->pools().donateLevel())) * 60 * 1000), m_idleTime((100 - static_cast<uint64_t>(controller->config()->pools().donateLevel())) * 60 * 1000),
@ -63,19 +66,18 @@ xmrig::DonateStrategy::DonateStrategy(Controller *controller, IStrategyListener
m_listener(listener), m_listener(listener),
m_state(STATE_NEW), m_state(STATE_NEW),
m_now(0), m_now(0),
m_stop(0) m_timestamp(0)
{ {
uint8_t hash[200]; uint8_t hash[200];
char userId[65] = { 0 };
const String &user = controller->config()->pools().data().front().user(); const String &user = controller->config()->pools().data().front().user();
keccak(reinterpret_cast<const uint8_t *>(user.data()), user.size(), hash); keccak(reinterpret_cast<const uint8_t *>(user.data()), user.size(), hash);
Buffer::toHex(hash, 32, userId); Buffer::toHex(hash, 32, m_userId);
# ifdef XMRIG_FEATURE_TLS # ifdef XMRIG_FEATURE_TLS
m_pools.push_back(Pool(kDonateHostTls, 443, userId, nullptr, false, true, true)); m_pools.push_back(Pool(kDonateHostTls, 443, m_userId, nullptr, 0, true, true));
# endif # endif
m_pools.push_back(Pool(kDonateHost, 3333, userId, nullptr, false, true)); m_pools.push_back(Pool(kDonateHost, 3333, m_userId, nullptr, 0, true));
for (Pool &pool : m_pools) { for (Pool &pool : m_pools) {
pool.adjust(Algorithm(controller->config()->algorithm().algo(), VARIANT_AUTO)); pool.adjust(Algorithm(controller->config()->algorithm().algo(), VARIANT_AUTO));
@ -98,19 +100,32 @@ xmrig::DonateStrategy::~DonateStrategy()
{ {
delete m_timer; delete m_timer;
delete m_strategy; delete m_strategy;
if (m_proxy) {
m_proxy->deleteLater();
}
} }
int64_t xmrig::DonateStrategy::submit(const JobResult &result) int64_t xmrig::DonateStrategy::submit(const JobResult &result)
{ {
return m_strategy->submit(result); return m_proxy ? m_proxy->submit(result) : m_strategy->submit(result);
} }
void xmrig::DonateStrategy::connect() void xmrig::DonateStrategy::connect()
{ {
m_proxy = createProxy();
if (m_proxy) {
m_proxy->connect();
}
else if (m_controller->config()->pools().proxyDonate() == Pools::PROXY_DONATE_ALWAYS) {
setState(STATE_IDLE);
}
else {
m_strategy->connect(); m_strategy->connect();
} }
}
void xmrig::DonateStrategy::setAlgo(const xmrig::Algorithm &algo) void xmrig::DonateStrategy::setAlgo(const xmrig::Algorithm &algo)
@ -132,13 +147,17 @@ void xmrig::DonateStrategy::tick(uint64_t now)
m_strategy->tick(now); m_strategy->tick(now);
if (state() == STATE_WAIT && now > m_stop) { if (m_proxy) {
m_proxy->tick(now);
}
if (state() == STATE_WAIT && now > m_timestamp) {
setState(STATE_IDLE); setState(STATE_IDLE);
} }
} }
void xmrig::DonateStrategy::onActive(IStrategy *strategy, Client *client) void xmrig::DonateStrategy::onActive(IStrategy *, Client *client)
{ {
if (isActive()) { if (isActive()) {
return; return;
@ -149,22 +168,49 @@ void xmrig::DonateStrategy::onActive(IStrategy *strategy, Client *client)
} }
void xmrig::DonateStrategy::onJob(IStrategy *strategy, Client *client, const Job &job) void xmrig::DonateStrategy::onPause(IStrategy *)
{
}
void xmrig::DonateStrategy::onClose(Client *, int failures)
{
if (failures == 2 && m_controller->config()->pools().proxyDonate() == Pools::PROXY_DONATE_AUTO) {
m_proxy->deleteLater();
m_proxy = nullptr;
m_strategy->connect();
}
}
void xmrig::DonateStrategy::onLogin(Client *, rapidjson::Document &doc, rapidjson::Value &params)
{
auto &allocator = doc.GetAllocator();
# ifdef XMRIG_FEATURE_TLS
if (m_tls) {
char buf[40] = { 0 };
snprintf(buf, sizeof(buf), "stratum+ssl://%s", m_pools[0].url().data());
params.AddMember("url", rapidjson::Value(buf, allocator), allocator);
}
else {
params.AddMember("url", m_pools[1].url().toJSON(), allocator);
}
# else
params.AddMember("url", m_pools[0].url().toJSON(), allocator);
# endif
}
void xmrig::DonateStrategy::onLoginSuccess(Client *client)
{ {
if (isActive()) { if (isActive()) {
m_listener->onJob(this, client, job); return;
}
} }
setState(STATE_ACTIVE);
void xmrig::DonateStrategy::onPause(IStrategy *strategy) m_listener->onActive(this, client);
{
}
void xmrig::DonateStrategy::onResultAccepted(IStrategy *strategy, Client *client, const SubmitResult &result, const char *error)
{
m_listener->onResultAccepted(this, client, result, error);
} }
@ -174,12 +220,51 @@ void xmrig::DonateStrategy::onTimer(const Timer *)
} }
xmrig::Client *xmrig::DonateStrategy::createProxy()
{
if (m_controller->config()->pools().proxyDonate() == Pools::PROXY_DONATE_NONE) {
return nullptr;
}
IStrategy *strategy = m_controller->network()->strategy();
if (!strategy->isActive() || !strategy->client()->has<Client::EXT_CONNECT>()) {
return nullptr;
}
const Client *client = strategy->client();
m_tls = client->has<Client::EXT_TLS>();
Pool pool(client->ip(), client->port(), m_userId, client->pool().password(), 0, true, client->isTLS());
pool.setAlgo(client->pool().algorithm());
Client *proxy = new Client(-1, Platform::userAgent(), this);
proxy->setPool(pool);
proxy->setQuiet(true);
return proxy;
}
void xmrig::DonateStrategy::idle(double min, double max) void xmrig::DonateStrategy::idle(double min, double max)
{ {
m_timer->start(random(m_idleTime, min, max), 0); m_timer->start(random(m_idleTime, min, max), 0);
} }
void xmrig::DonateStrategy::setJob(Client *client, const Job &job)
{
if (isActive()) {
m_listener->onJob(this, client, job);
}
}
void xmrig::DonateStrategy::setResult(Client *client, const SubmitResult &result, const char *error)
{
m_listener->onResultAccepted(this, client, result, error);
}
void xmrig::DonateStrategy::setState(State state) void xmrig::DonateStrategy::setState(State state)
{ {
constexpr const uint64_t waitTime = 3000; constexpr const uint64_t waitTime = 3000;
@ -200,8 +285,16 @@ void xmrig::DonateStrategy::setState(State state)
if (prev == STATE_NEW) { if (prev == STATE_NEW) {
idle(0.5, 1.5); idle(0.5, 1.5);
} }
else if (prev == STATE_CONNECT) {
m_timer->start(20000, 0);
}
else { else {
m_strategy->stop(); m_strategy->stop();
if (m_proxy) {
m_proxy->deleteLater();
m_proxy = nullptr;
}
idle(0.8, 1.2); idle(0.8, 1.2);
} }
break; break;
@ -215,7 +308,7 @@ void xmrig::DonateStrategy::setState(State state)
break; break;
case STATE_WAIT: case STATE_WAIT:
m_stop = m_now + waitTime; m_timestamp = m_now + waitTime;
m_listener->onPause(this); m_listener->onPause(this);
break; break;
} }

View file

@ -44,14 +44,19 @@ class Controller;
class IStrategyListener; class IStrategyListener;
class DonateStrategy : public IStrategy, public IStrategyListener, public ITimerListener class DonateStrategy : public IStrategy, public IStrategyListener, public ITimerListener, public IClientListener
{ {
public: public:
DonateStrategy(Controller *controller, IStrategyListener *listener); DonateStrategy(Controller *controller, IStrategyListener *listener);
~DonateStrategy() override; ~DonateStrategy() override;
public: 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 void onJob(IStrategy *, Client *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 onResultAccepted(Client *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 resume() override {} inline void resume() override {}
int64_t submit(const JobResult &result) override; int64_t submit(const JobResult &result) override;
@ -60,11 +65,13 @@ public:
void stop() override; void stop() override;
void tick(uint64_t now) override; void tick(uint64_t now) override;
protected:
void onActive(IStrategy *strategy, Client *client) override; void onActive(IStrategy *strategy, Client *client) override;
void onJob(IStrategy *strategy, Client *client, const Job &job) override;
void onPause(IStrategy *strategy) override; void onPause(IStrategy *strategy) override;
void onResultAccepted(IStrategy *strategy, Client *client, const SubmitResult &result, const char *error) override;
void onClose(Client *client, int failures) override;
void onLogin(Client *client, rapidjson::Document &doc, rapidjson::Value &params) override;
void onLoginSuccess(Client *client) override;
void onTimer(const Timer *timer) override; void onTimer(const Timer *timer) override;
private: private:
@ -78,9 +85,14 @@ private:
inline State state() const { return m_state; } inline State state() const { return m_state; }
Client *createProxy();
void idle(double min, double max); void idle(double min, double max);
void setJob(Client *client, const Job &job);
void setResult(Client *client, const SubmitResult &result, const char *error);
void setState(State state); void setState(State state);
bool m_tls;
char m_userId[65];
Client *m_proxy; Client *m_proxy;
const uint64_t m_donateTime; const uint64_t m_donateTime;
const uint64_t m_idleTime; const uint64_t m_idleTime;
@ -91,7 +103,7 @@ private:
std::vector<Pool> m_pools; std::vector<Pool> m_pools;
Timer *m_timer; Timer *m_timer;
uint64_t m_now; uint64_t m_now;
uint64_t m_stop; uint64_t m_timestamp;
}; };