From 4c95136e6ab8435098b33ac67e83ac25a0f12226 Mon Sep 17 00:00:00 2001 From: XMRig Date: Tue, 19 Mar 2019 21:31:54 +0700 Subject: [PATCH] Implemented donate over proxy. --- src/base/kernel/interfaces/IStrategy.h | 6 +- src/base/net/stratum/Client.cpp | 20 +-- src/base/net/stratum/Client.h | 3 +- .../stratum/strategies/FailoverStrategy.cpp | 14 +- .../net/stratum/strategies/FailoverStrategy.h | 11 +- .../stratum/strategies/SinglePoolStrategy.h | 7 +- src/net/Network.h | 2 + src/net/strategies/DonateStrategy.cpp | 125 +++++++++++++++--- src/net/strategies/DonateStrategy.h | 28 ++-- 9 files changed, 161 insertions(+), 55 deletions(-) diff --git a/src/base/kernel/interfaces/IStrategy.h b/src/base/kernel/interfaces/IStrategy.h index 1e9c19bc..31798b9c 100644 --- a/src/base/kernel/interfaces/IStrategy.h +++ b/src/base/kernel/interfaces/IStrategy.h @@ -29,13 +29,12 @@ #include -class JobResult; - - namespace xmrig { class Algorithm; +class Client; +class JobResult; class IStrategy @@ -44,6 +43,7 @@ public: virtual ~IStrategy() = default; virtual bool isActive() const = 0; + virtual Client *client() const = 0; virtual int64_t submit(const JobResult &result) = 0; virtual void connect() = 0; virtual void resume() = 0; diff --git a/src/base/net/stratum/Client.cpp b/src/base/net/stratum/Client.cpp index d88acfc7..db6f2663 100644 --- a/src/base/net/stratum/Client.cpp +++ b/src/base/net/stratum/Client.cpp @@ -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 { # 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 ¶ms, int *code) { if (!params.IsObject()) { diff --git a/src/base/net/stratum/Client.h b/src/base/net/stratum/Client.h index e41d01ad..c0ea8a93 100644 --- a/src/base/net/stratum/Client.h +++ b/src/base/net/stratum/Client.h @@ -85,6 +85,7 @@ public: ~Client() override; bool disconnect(); + bool isTLS() const; const char *tlsFingerprint() const; const char *tlsVersion() const; int64_t submit(const JobResult &result); @@ -99,6 +100,7 @@ public: 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(); } @@ -120,7 +122,6 @@ private: bool close(); bool isCriticalError(const char *message); - bool isTLS() const; bool parseJob(const rapidjson::Value ¶ms, int *code); bool parseLogin(const rapidjson::Value &result, int *code); bool send(BIO *bio); diff --git a/src/base/net/stratum/strategies/FailoverStrategy.cpp b/src/base/net/stratum/strategies/FailoverStrategy.cpp index d2e4a6da..7a59e2a6 100644 --- a/src/base/net/stratum/strategies/FailoverStrategy.cpp +++ b/src/base/net/stratum/strategies/FailoverStrategy.cpp @@ -34,8 +34,8 @@ xmrig::FailoverStrategy::FailoverStrategy(const std::vector &pools, int re m_retries(retries), m_retryPause(retryPause), m_active(-1), - m_index(0), - m_listener(listener) + m_listener(listener), + m_index(0) { for (const Pool &pool : pools) { add(pool); @@ -48,8 +48,8 @@ xmrig::FailoverStrategy::FailoverStrategy(int retryPause, int retries, IStrategy m_retries(retries), m_retryPause(retryPause), 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() { - m_pools[static_cast(m_index)]->connect(); + m_pools[m_index]->connect(); } @@ -144,8 +144,8 @@ void xmrig::FailoverStrategy::onClose(Client *client, int failures) return; } - if (m_index == client->id() && (m_pools.size() - static_cast(m_index)) > 1) { - m_pools[static_cast(++m_index)]->connect(); + if (m_index == static_cast(client->id()) && (m_pools.size() - m_index) > 1) { + m_pools[++m_index]->connect(); } } diff --git a/src/base/net/stratum/strategies/FailoverStrategy.h b/src/base/net/stratum/strategies/FailoverStrategy.h index 3517de9d..fcebc52f 100644 --- a/src/base/net/stratum/strategies/FailoverStrategy.h +++ b/src/base/net/stratum/strategies/FailoverStrategy.h @@ -50,8 +50,10 @@ public: void add(const Pool &pool); -public: - inline bool isActive() const override { return m_active >= 0; } +protected: + 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; void connect() override; @@ -60,9 +62,6 @@ public: void stop() 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 onJobReceived(Client *client, const Job &job, const rapidjson::Value ¶ms) override; void onLoginSuccess(Client *client) override; @@ -75,8 +74,8 @@ private: const int m_retries; const int m_retryPause; int m_active; - int m_index; IStrategyListener *m_listener; + size_t m_index; std::vector m_pools; }; diff --git a/src/base/net/stratum/strategies/SinglePoolStrategy.h b/src/base/net/stratum/strategies/SinglePoolStrategy.h index 5b3016c1..8d9f9fd1 100644 --- a/src/base/net/stratum/strategies/SinglePoolStrategy.h +++ b/src/base/net/stratum/strategies/SinglePoolStrategy.h @@ -44,8 +44,10 @@ public: SinglePoolStrategy(const Pool &pool, int retryPause, int retries, IStrategyListener *listener, bool quiet = false); ~SinglePoolStrategy() override; -public: +protected: 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; void connect() override; @@ -54,9 +56,6 @@ public: void stop() 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 onJobReceived(Client *client, const Job &job, const rapidjson::Value ¶ms) override; void onLoginSuccess(Client *client) override; diff --git a/src/net/Network.h b/src/net/Network.h index 8afc5492..ac74384e 100644 --- a/src/net/Network.h +++ b/src/net/Network.h @@ -49,6 +49,8 @@ public: Network(Controller *controller); ~Network() override; + inline IStrategy *strategy() const { return m_strategy; } + void connect(); protected: diff --git a/src/net/strategies/DonateStrategy.cpp b/src/net/strategies/DonateStrategy.cpp index 37a9c7c9..adfb9a99 100644 --- a/src/net/strategies/DonateStrategy.cpp +++ b/src/net/strategies/DonateStrategy.cpp @@ -39,6 +39,7 @@ #include "core/Controller.h" #include "net/Network.h" #include "net/strategies/DonateStrategy.h" +#include "rapidjson/document.h" namespace xmrig { @@ -55,6 +56,8 @@ static const char *kDonateHostTls = "donate.ssl.xmrig.com"; xmrig::DonateStrategy::DonateStrategy(Controller *controller, IStrategyListener *listener) : + m_tls(false), + m_userId(), m_proxy(nullptr), m_donateTime(static_cast(controller->config()->pools().donateLevel()) * 60 * 1000), m_idleTime((100 - static_cast(controller->config()->pools().donateLevel())) * 60 * 1000), @@ -63,19 +66,18 @@ xmrig::DonateStrategy::DonateStrategy(Controller *controller, IStrategyListener m_listener(listener), m_state(STATE_NEW), m_now(0), - m_stop(0) + m_timestamp(0) { uint8_t hash[200]; - char userId[65] = { 0 }; const String &user = controller->config()->pools().data().front().user(); keccak(reinterpret_cast(user.data()), user.size(), hash); - Buffer::toHex(hash, 32, userId); + Buffer::toHex(hash, 32, m_userId); # 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 - 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) { pool.adjust(Algorithm(controller->config()->algorithm().algo(), VARIANT_AUTO)); @@ -98,18 +100,31 @@ xmrig::DonateStrategy::~DonateStrategy() { delete m_timer; delete m_strategy; + + if (m_proxy) { + m_proxy->deleteLater(); + } } 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() { - m_strategy->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(); + } } @@ -132,13 +147,17 @@ void xmrig::DonateStrategy::tick(uint64_t 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); } } -void xmrig::DonateStrategy::onActive(IStrategy *strategy, Client *client) +void xmrig::DonateStrategy::onActive(IStrategy *, Client *client) { if (isActive()) { 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 *) { - if (isActive()) { - m_listener->onJob(this, client, job); +} + + +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::onPause(IStrategy *strategy) +void xmrig::DonateStrategy::onLogin(Client *, rapidjson::Document &doc, rapidjson::Value ¶ms) { + 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::onResultAccepted(IStrategy *strategy, Client *client, const SubmitResult &result, const char *error) +void xmrig::DonateStrategy::onLoginSuccess(Client *client) { - m_listener->onResultAccepted(this, client, result, error); + if (isActive()) { + return; + } + + setState(STATE_ACTIVE); + m_listener->onActive(this, client); } @@ -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()) { + return nullptr; + } + + const Client *client = strategy->client(); + m_tls = client->has(); + + 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) { 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) { constexpr const uint64_t waitTime = 3000; @@ -200,8 +285,16 @@ void xmrig::DonateStrategy::setState(State state) if (prev == STATE_NEW) { idle(0.5, 1.5); } + else if (prev == STATE_CONNECT) { + m_timer->start(20000, 0); + } else { m_strategy->stop(); + if (m_proxy) { + m_proxy->deleteLater(); + m_proxy = nullptr; + } + idle(0.8, 1.2); } break; @@ -215,7 +308,7 @@ void xmrig::DonateStrategy::setState(State state) break; case STATE_WAIT: - m_stop = m_now + waitTime; + m_timestamp = m_now + waitTime; m_listener->onPause(this); break; } diff --git a/src/net/strategies/DonateStrategy.h b/src/net/strategies/DonateStrategy.h index a06f901f..827596f3 100644 --- a/src/net/strategies/DonateStrategy.h +++ b/src/net/strategies/DonateStrategy.h @@ -44,15 +44,20 @@ class Controller; class IStrategyListener; -class DonateStrategy : public IStrategy, public IStrategyListener, public ITimerListener +class DonateStrategy : public IStrategy, public IStrategyListener, public ITimerListener, public IClientListener { public: DonateStrategy(Controller *controller, IStrategyListener *listener); ~DonateStrategy() override; -public: - inline bool isActive() const override { return state() == STATE_ACTIVE; } - inline void resume() override {} +protected: + 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 {} int64_t submit(const JobResult &result) override; void connect() override; @@ -60,11 +65,13 @@ public: void stop() override; void tick(uint64_t now) override; -protected: void onActive(IStrategy *strategy, Client *client) override; - void onJob(IStrategy *strategy, Client *client, const Job &job) 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 ¶ms) override; + void onLoginSuccess(Client *client) override; + void onTimer(const Timer *timer) override; private: @@ -78,9 +85,14 @@ private: inline State state() const { return m_state; } + Client *createProxy(); 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); + bool m_tls; + char m_userId[65]; Client *m_proxy; const uint64_t m_donateTime; const uint64_t m_idleTime; @@ -91,7 +103,7 @@ private: std::vector m_pools; Timer *m_timer; uint64_t m_now; - uint64_t m_stop; + uint64_t m_timestamp; };