diff --git a/CMakeLists.txt b/CMakeLists.txt index cecd78e10..3026905e3 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -28,6 +28,7 @@ set(HEADERS src/net/Network.h src/net/Url.h src/net/strategies/DonateStrategy.h + src/net/strategies/FailoverStrategy.h src/net/strategies/SinglePoolStrategy.h src/Options.h src/Summary.h @@ -65,6 +66,7 @@ set(SOURCES src/net/Network.cpp src/net/Url.cpp src/net/strategies/DonateStrategy.cpp + src/net/strategies/FailoverStrategy.cpp src/net/strategies/SinglePoolStrategy.cpp src/Options.cpp src/Summary.cpp @@ -120,7 +122,7 @@ else() endif() add_definitions(/DUNICODE) -#add_definitions(/DAPP_DEBUG) +add_definitions(/DAPP_DEBUG) set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}/cmake") diff --git a/src/Summary.cpp b/src/Summary.cpp index 9eb195d3b..08326458b 100644 --- a/src/Summary.cpp +++ b/src/Summary.cpp @@ -100,10 +100,11 @@ static void print_threads() buf[0] = '\0'; } - Log::i()->text(Options::i()->colors() ? "\x1B[01;32m * \x1B[01;37mTHREADS: \x1B[01;36m%d\x1B[01;37m, %s, av=%d, donate=%d%%%s" : " * THREADS: %d, %s, av=%d, donate=%d%%%s", + Log::i()->text(Options::i()->colors() ? "\x1B[01;32m * \x1B[01;37mTHREADS: \x1B[01;36m%d\x1B[01;37m, %s, av=%d, %sdonate=%d%%%s" : " * THREADS: %d, %s, av=%d, %sdonate=%d%%%s", Options::i()->threads(), Options::i()->algoName(), Options::i()->algoVariant(), + Options::i()->colors() && Options::i()->donateLevel() == 0 ? "\x1B[01;31m" : "", Options::i()->donateLevel(), buf); } diff --git a/src/net/Client.cpp b/src/net/Client.cpp index e9fcb0a78..3b9eecbd6 100644 --- a/src/net/Client.cpp +++ b/src/net/Client.cpp @@ -209,7 +209,10 @@ int Client::resolve(const char *host) setState(HostLookupState); m_recvBufPos = 0; - m_failures = 0; + + if (m_failures == -1) { + m_failures = 0; + } const int r = uv_getaddrinfo(uv_default_loop(), &m_resolver, Client::onResolved, host, NULL, &m_hints); if (r) { @@ -375,6 +378,8 @@ void Client::ping() void Client::reconnect() { + setState(ConnectingState); + uv_timer_stop(&m_responseTimer); if (m_url.isKeepAlive()) { uv_timer_stop(&m_keepAliveTimer); diff --git a/src/net/Network.cpp b/src/net/Network.cpp index 8e064e9a1..abd7ed117 100644 --- a/src/net/Network.cpp +++ b/src/net/Network.cpp @@ -29,6 +29,7 @@ #include "net/Client.h" #include "net/Network.h" #include "net/strategies/DonateStrategy.h" +#include "net/strategies/FailoverStrategy.h" #include "net/strategies/SinglePoolStrategy.h" #include "net/Url.h" #include "Options.h" @@ -45,7 +46,12 @@ Network::Network(const Options *options) : const std::vector &pools = options->pools(); - m_strategy = new SinglePoolStrategy(pools.front(), m_agent, this); + if (pools.size() > 1) { + m_strategy = new FailoverStrategy(pools, m_agent, this); + } + else { + m_strategy = new SinglePoolStrategy(pools.front(), m_agent, this); + } if (m_options->donateLevel() > 0) { m_donate = new DonateStrategy(m_agent, this); @@ -55,10 +61,6 @@ Network::Network(const Options *options) : Network::~Network() { -// for (auto client : m_pools) { -// delete client; -// } - free(m_agent); } @@ -80,28 +82,6 @@ void Network::onActive(Client *client) } -//void Network::onClose(Client *client, int failures) -//{ -// const int id = client->id(); -// if (id == 0) { -// if (failures == -1) { -// stopDonate(); -// } - -// return; -// } - -// if (m_pool == id) { -// m_pool = 0; -// Workers::pause(); -// } - -// if (id == 1 && m_pools.size() > 2 && failures == m_options->retries()) { -// m_pools[2]->connect(); -// } -//} - - void Network::onJob(Client *client, const Job &job) { if (m_donate && m_donate->isActive() && client->id() != -1) { @@ -124,27 +104,6 @@ void Network::onJobResult(const JobResult &result) } -//void Network::onLoginSuccess(Client *client) -//{ -// const int id = client->id(); -// if (id == 0) { -// return startDonate(); -// } - -// if (id == 2 && m_pool) { // primary pool is already active -// m_pools[2]->disconnect(); -// return; -// } - -// LOG_INFO(m_options->colors() ? "\x1B[01;37muse pool: \x1B[01;36m%s:%d" : "use pool: %s:%d", client->host(), client->port()); -// m_pool = id; - -// if (m_pool == 1 && m_pools.size() > 2) { // try disconnect from backup pool -// m_pools[2]->disconnect(); -// } -//} - - void Network::onPause(IStrategy *strategy) { if (m_donate && m_donate == strategy) { @@ -171,40 +130,3 @@ void Network::setJob(Client *client, const Job &job) Workers::setJob(job); } - - -void Network::stopDonate() -{ -// if (!m_donateActive) { -// return; -// } - -// LOG_NOTICE("dev donate finished"); - -// m_donateActive = false; -// if (!m_pool) { -// return; -// } - -// Client *client = m_pools[m_pool]; -// if (client->isReady()) { -// setJob(client, client->job()); -// } -} - - -//void Network::onTimer(uv_timer_t *handle) -//{ -// auto net = static_cast(handle->data); - -// if (!net->m_donateActive) { -// auto url = std::make_unique("donate.xmrig.com", net->m_options->algo() == Options::ALGO_CRYPTONIGHT_LITE ? 3333 : 443); -// net->m_pools[0]->connect(url.get()); - -// uv_timer_start(&net->m_timer, Network::onTimer, net->m_options->donateLevel() * 60 * 1000, 0); -// return; -// } - -// net->m_pools[0]->disconnect(); -// uv_timer_start(&net->m_timer, Network::onTimer, (100 - net->m_options->donateLevel()) * 60 * 1000, 0); -//} diff --git a/src/net/strategies/FailoverStrategy.cpp b/src/net/strategies/FailoverStrategy.cpp new file mode 100644 index 000000000..07eabcdeb --- /dev/null +++ b/src/net/strategies/FailoverStrategy.cpp @@ -0,0 +1,121 @@ +/* XMRig + * Copyright 2010 Jeff Garzik + * Copyright 2012-2014 pooler + * Copyright 2014 Lucas Jones + * Copyright 2014-2016 Wolf9466 + * Copyright 2016 Jay D Dee + * Copyright 2016-2017 XMRig + * + * + * 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 . + */ + + +#include "interfaces/IStrategyListener.h" +#include "net/Client.h" +#include "net/strategies/FailoverStrategy.h" +#include "Options.h" + + +FailoverStrategy::FailoverStrategy(const std::vector &urls, const char *agent, IStrategyListener *listener) : + m_active(-1), + m_index(0), + m_listener(listener) +{ + for (const Url *url : urls) { + add(url, agent); + } +} + + +void FailoverStrategy::connect() +{ + m_pools[m_index]->connect(); +} + + +void FailoverStrategy::resume() +{ + if (!isActive()) { + return; + } + + m_listener->onJob( m_pools[m_active], m_pools[m_active]->job()); +} + + +void FailoverStrategy::submit(const JobResult &result) +{ + m_pools[m_active]->submit(result); +} + + +void FailoverStrategy::onClose(Client *client, int failures) +{ + if (failures == -1) { + return; + } + + if (m_active == client->id()) { + m_active = -1; + m_listener->onPause(this); + } + + if (m_index == 0 && failures < Options::i()->retries()) { + return; + } + + if (m_index == client->id() && (m_pools.size() - m_index) > 1) { + m_pools[++m_index]->connect(); + } +} + + +void FailoverStrategy::onJobReceived(Client *client, const Job &job) +{ + if (m_active == client->id()) { + m_listener->onJob(client, job); + } +} + + +void FailoverStrategy::onLoginSuccess(Client *client) +{ + int active = m_active; + + if (client->id() == 0 || !isActive()) { + active = client->id(); + } + + for (size_t i = 1; i < m_pools.size(); ++i) { + if (active != static_cast(i)) { + m_pools[i]->disconnect(); + } + } + + if (active >= 0 && active != m_active) { + m_index = m_active = active; + m_listener->onActive(client); + } +} + + +void FailoverStrategy::add(const Url *url, const char *agent) +{ + Client *client = new Client(m_pools.size(), agent, this); + client->setUrl(url); + client->setRetryPause(Options::i()->retryPause() * 1000); + + m_pools.push_back(client); +} diff --git a/src/net/strategies/FailoverStrategy.h b/src/net/strategies/FailoverStrategy.h new file mode 100644 index 000000000..456ddc66f --- /dev/null +++ b/src/net/strategies/FailoverStrategy.h @@ -0,0 +1,66 @@ +/* XMRig + * Copyright 2010 Jeff Garzik + * Copyright 2012-2014 pooler + * Copyright 2014 Lucas Jones + * Copyright 2014-2016 Wolf9466 + * Copyright 2016 Jay D Dee + * Copyright 2016-2017 XMRig + * + * + * 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 . + */ + +#ifndef __FAILOVERSTRATEGY_H__ +#define __FAILOVERSTRATEGY_H__ + + +#include + + +#include "interfaces/IClientListener.h" +#include "interfaces/IStrategy.h" + + +class Client; +class IStrategyListener; +class Url; + + +class FailoverStrategy : public IStrategy, public IClientListener +{ +public: + FailoverStrategy(const std::vector &urls, const char *agent, IStrategyListener *listener); + +public: + inline bool isActive() const override { return m_active >= 0; } + + void connect() override; + void resume() override; + void submit(const JobResult &result) override; + +protected: + void onClose(Client *client, int failures) override; + void onJobReceived(Client *client, const Job &job) override; + void onLoginSuccess(Client *client) override; + +private: + void add(const Url *url, const char *agent); + + int m_active; + int m_index; + IStrategyListener *m_listener; + std::vector m_pools; +}; + +#endif /* __FAILOVERSTRATEGY_H__ */