Move shared network code to common folder.
This commit is contained in:
parent
a9178bd468
commit
2d22f2aeff
28 changed files with 60 additions and 58 deletions
61
src/common/Console.cpp
Normal file
61
src/common/Console.cpp
Normal file
|
@ -0,0 +1,61 @@
|
|||
/* 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 2016-2018 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 "common/Console.h"
|
||||
#include "interfaces/IConsoleListener.h"
|
||||
|
||||
|
||||
Console::Console(IConsoleListener *listener)
|
||||
: m_listener(listener)
|
||||
{
|
||||
m_tty.data = this;
|
||||
uv_tty_init(uv_default_loop(), &m_tty, 0, 1);
|
||||
|
||||
if (!uv_is_readable(reinterpret_cast<uv_stream_t*>(&m_tty))) {
|
||||
return;
|
||||
}
|
||||
|
||||
uv_tty_set_mode(&m_tty, UV_TTY_MODE_RAW);
|
||||
uv_read_start(reinterpret_cast<uv_stream_t*>(&m_tty), Console::onAllocBuffer, Console::onRead);
|
||||
}
|
||||
|
||||
|
||||
void Console::onAllocBuffer(uv_handle_t *handle, size_t suggested_size, uv_buf_t *buf)
|
||||
{
|
||||
auto console = static_cast<Console*>(handle->data);
|
||||
buf->len = 1;
|
||||
buf->base = console->m_buf;
|
||||
}
|
||||
|
||||
|
||||
void Console::onRead(uv_stream_t *stream, ssize_t nread, const uv_buf_t *buf)
|
||||
{
|
||||
if (nread < 0) {
|
||||
return uv_close(reinterpret_cast<uv_handle_t*>(stream), nullptr);
|
||||
}
|
||||
|
||||
if (nread == 1) {
|
||||
static_cast<Console*>(stream->data)->m_listener->onConsoleCommand(buf->base[0]);
|
||||
}
|
||||
}
|
49
src/common/Console.h
Normal file
49
src/common/Console.h
Normal file
|
@ -0,0 +1,49 @@
|
|||
/* 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 2016-2018 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 __CONSOLE_H__
|
||||
#define __CONSOLE_H__
|
||||
|
||||
|
||||
#include <uv.h>
|
||||
|
||||
|
||||
class IConsoleListener;
|
||||
|
||||
|
||||
class Console
|
||||
{
|
||||
public:
|
||||
Console(IConsoleListener *listener);
|
||||
|
||||
private:
|
||||
static void onAllocBuffer(uv_handle_t *handle, size_t suggested_size, uv_buf_t *buf);
|
||||
static void onRead(uv_stream_t *stream, ssize_t nread, const uv_buf_t *buf);
|
||||
|
||||
char m_buf[1];
|
||||
IConsoleListener *m_listener;
|
||||
uv_tty_t m_tty;
|
||||
};
|
||||
|
||||
|
||||
#endif /* __CONSOLE_H__ */
|
|
@ -32,7 +32,6 @@
|
|||
#include "common/config/CommonConfig.h"
|
||||
#include "donate.h"
|
||||
#include "log/Log.h"
|
||||
#include "net/Pool.h"
|
||||
#include "rapidjson/document.h"
|
||||
#include "rapidjson/filewritestream.h"
|
||||
#include "rapidjson/prettywriter.h"
|
||||
|
|
|
@ -28,10 +28,10 @@
|
|||
#include <vector>
|
||||
|
||||
|
||||
#include "common/net/Pool.h"
|
||||
#include "common/utils/c_str.h"
|
||||
#include "common/xmrig.h"
|
||||
#include "interfaces/IConfig.h"
|
||||
#include "net/Pool.h"
|
||||
|
||||
|
||||
namespace xmrig {
|
||||
|
|
|
@ -34,12 +34,12 @@
|
|||
|
||||
#include "common/config/ConfigLoader.h"
|
||||
#include "common/config/ConfigWatcher.h"
|
||||
#include "common/net/Pool.h"
|
||||
#include "common/Platform.h"
|
||||
#include "core/ConfigCreator.h"
|
||||
#include "core/ConfigLoader_platform.h"
|
||||
#include "interfaces/IConfig.h"
|
||||
#include "interfaces/IWatcherListener.h"
|
||||
#include "net/Pool.h"
|
||||
#include "rapidjson/document.h"
|
||||
#include "rapidjson/error/en.h"
|
||||
#include "rapidjson/filereadstream.h"
|
||||
|
|
785
src/common/net/Client.cpp
Normal file
785
src/common/net/Client.cpp
Normal file
|
@ -0,0 +1,785 @@
|
|||
/* 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 2016-2018 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 <assert.h>
|
||||
#include <inttypes.h>
|
||||
#include <iterator>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <utility>
|
||||
|
||||
|
||||
#include "common/net/Client.h"
|
||||
#include "interfaces/IClientListener.h"
|
||||
#include "log/Log.h"
|
||||
#include "rapidjson/document.h"
|
||||
#include "rapidjson/error/en.h"
|
||||
#include "rapidjson/stringbuffer.h"
|
||||
#include "rapidjson/writer.h"
|
||||
|
||||
|
||||
#ifdef XMRIG_PROXY_PROJECT
|
||||
# include "proxy/JobResult.h"
|
||||
#else
|
||||
# include "net/JobResult.h"
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef _MSC_VER
|
||||
# define strncasecmp(x,y,z) _strnicmp(x,y,z)
|
||||
#endif
|
||||
|
||||
|
||||
int64_t Client::m_sequence = 1;
|
||||
xmrig::Storage<Client> Client::m_storage;
|
||||
|
||||
|
||||
Client::Client(int id, const char *agent, IClientListener *listener) :
|
||||
m_ipv6(false),
|
||||
m_nicehash(false),
|
||||
m_quiet(false),
|
||||
m_agent(agent),
|
||||
m_listener(listener),
|
||||
m_id(id),
|
||||
m_retryPause(5000),
|
||||
m_failures(0),
|
||||
m_recvBufPos(0),
|
||||
m_state(UnconnectedState),
|
||||
m_expire(0),
|
||||
m_jobs(0),
|
||||
m_keepAlive(0),
|
||||
m_key(0),
|
||||
m_stream(nullptr),
|
||||
m_socket(nullptr)
|
||||
{
|
||||
m_key = m_storage.add(this);
|
||||
|
||||
memset(m_ip, 0, sizeof(m_ip));
|
||||
memset(&m_hints, 0, sizeof(m_hints));
|
||||
|
||||
m_resolver.data = m_storage.ptr(m_key);
|
||||
|
||||
m_hints.ai_family = AF_UNSPEC;
|
||||
m_hints.ai_socktype = SOCK_STREAM;
|
||||
m_hints.ai_protocol = IPPROTO_TCP;
|
||||
|
||||
m_recvBuf.base = m_buf;
|
||||
m_recvBuf.len = sizeof(m_buf);
|
||||
}
|
||||
|
||||
|
||||
Client::~Client()
|
||||
{
|
||||
delete m_socket;
|
||||
}
|
||||
|
||||
|
||||
void Client::connect()
|
||||
{
|
||||
resolve(m_pool.host());
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Connect to server.
|
||||
*
|
||||
* @param url
|
||||
*/
|
||||
void Client::connect(const Pool &url)
|
||||
{
|
||||
setPool(url);
|
||||
connect();
|
||||
}
|
||||
|
||||
|
||||
void Client::deleteLater()
|
||||
{
|
||||
if (!m_listener) {
|
||||
return;
|
||||
}
|
||||
|
||||
m_listener = nullptr;
|
||||
|
||||
if (!disconnect()) {
|
||||
m_storage.remove(m_key);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Client::setPool(const Pool &pool)
|
||||
{
|
||||
if (!pool.isValid()) {
|
||||
return;
|
||||
}
|
||||
|
||||
m_pool = pool;
|
||||
}
|
||||
|
||||
|
||||
void Client::tick(uint64_t now)
|
||||
{
|
||||
if (m_state == ConnectedState) {
|
||||
if (m_expire && now > m_expire) {
|
||||
LOG_DEBUG_ERR("[%s] timeout", m_pool.url());
|
||||
close();
|
||||
}
|
||||
else if (m_keepAlive && now > m_keepAlive) {
|
||||
ping();
|
||||
}
|
||||
}
|
||||
|
||||
if (m_expire && now > m_expire && m_state == ConnectingState) {
|
||||
connect();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool Client::disconnect()
|
||||
{
|
||||
m_keepAlive = 0;
|
||||
m_expire = 0;
|
||||
m_failures = -1;
|
||||
|
||||
return close();
|
||||
}
|
||||
|
||||
|
||||
int64_t Client::submit(const JobResult &result)
|
||||
{
|
||||
# ifdef XMRIG_PROXY_PROJECT
|
||||
const char *nonce = result.nonce;
|
||||
const char *data = result.result;
|
||||
# else
|
||||
char nonce[9];
|
||||
char data[65];
|
||||
|
||||
Job::toHex(reinterpret_cast<const unsigned char*>(&result.nonce), 4, nonce);
|
||||
nonce[8] = '\0';
|
||||
|
||||
Job::toHex(result.result, 32, data);
|
||||
data[64] = '\0';
|
||||
# endif
|
||||
|
||||
const size_t size = snprintf(m_sendBuf, sizeof(m_sendBuf), "{\"id\":%" PRIu64 ",\"jsonrpc\":\"2.0\",\"method\":\"submit\",\"params\":{\"id\":\"%s\",\"job_id\":\"%s\",\"nonce\":\"%s\",\"result\":\"%s\"}}\n",
|
||||
m_sequence, m_rpcId.data(), result.jobId.data(), nonce, data);
|
||||
|
||||
# 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
|
||||
|
||||
return send(size);
|
||||
}
|
||||
|
||||
|
||||
bool Client::close()
|
||||
{
|
||||
if (m_state == UnconnectedState || m_state == ClosingState || !m_socket) {
|
||||
return false;
|
||||
}
|
||||
|
||||
setState(ClosingState);
|
||||
|
||||
if (uv_is_closing(reinterpret_cast<uv_handle_t*>(m_socket)) == 0) {
|
||||
uv_close(reinterpret_cast<uv_handle_t*>(m_socket), Client::onClose);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool Client::isCriticalError(const char *message)
|
||||
{
|
||||
if (!message) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (strncasecmp(message, "Unauthenticated", 15) == 0) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (strncasecmp(message, "your IP is banned", 17) == 0) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (strncasecmp(message, "IP Address currently banned", 27) == 0) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool Client::parseJob(const rapidjson::Value ¶ms, int *code)
|
||||
{
|
||||
if (!params.IsObject()) {
|
||||
*code = 2;
|
||||
return false;
|
||||
}
|
||||
|
||||
# ifdef XMRIG_PROXY_PROJECT
|
||||
Job job(m_id, m_pool.variant());
|
||||
job.setClientId(m_rpcId);
|
||||
# else
|
||||
Job job(m_id, m_nicehash, m_pool.algo(), m_pool.variant());
|
||||
# endif
|
||||
|
||||
if (!job.setId(params["job_id"].GetString())) {
|
||||
*code = 3;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!job.setBlob(params["blob"].GetString())) {
|
||||
*code = 4;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!job.setTarget(params["target"].GetString())) {
|
||||
*code = 5;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (params.HasMember("coin")) {
|
||||
job.setCoin(params["coin"].GetString());
|
||||
}
|
||||
|
||||
if (params.HasMember("variant")) {
|
||||
job.setVariant(params["variant"].GetInt());
|
||||
}
|
||||
|
||||
if (m_job != job) {
|
||||
m_jobs++;
|
||||
m_job = std::move(job);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (m_jobs == 0) { // https://github.com/xmrig/xmrig/issues/459
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!m_quiet) {
|
||||
LOG_WARN("[%s] duplicate job received, reconnect", m_pool.url());
|
||||
}
|
||||
|
||||
close();
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool Client::parseLogin(const rapidjson::Value &result, int *code)
|
||||
{
|
||||
if (!m_rpcId.setId(result["id"].GetString())) {
|
||||
*code = 1;
|
||||
return false;
|
||||
}
|
||||
|
||||
# ifndef XMRIG_PROXY_PROJECT
|
||||
m_nicehash = m_pool.isNicehash();
|
||||
# endif
|
||||
|
||||
if (result.HasMember("extensions")) {
|
||||
parseExtensions(result["extensions"]);
|
||||
}
|
||||
|
||||
const bool rc = parseJob(result["job"], code);
|
||||
m_jobs = 0;
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
int Client::resolve(const char *host)
|
||||
{
|
||||
setState(HostLookupState);
|
||||
|
||||
m_expire = 0;
|
||||
m_recvBufPos = 0;
|
||||
|
||||
if (m_failures == -1) {
|
||||
m_failures = 0;
|
||||
}
|
||||
|
||||
const int r = uv_getaddrinfo(uv_default_loop(), &m_resolver, Client::onResolved, host, nullptr, &m_hints);
|
||||
if (r) {
|
||||
if (!m_quiet) {
|
||||
LOG_ERR("[%s:%u] getaddrinfo error: \"%s\"", host, m_pool.port(), uv_strerror(r));
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int64_t Client::send(size_t size)
|
||||
{
|
||||
LOG_DEBUG("[%s] send (%d bytes): \"%s\"", m_pool.url(), size, m_sendBuf);
|
||||
if (state() != ConnectedState || !uv_is_writable(m_stream)) {
|
||||
LOG_DEBUG_ERR("[%s] send failed, invalid state: %d", m_pool.url(), m_state);
|
||||
return -1;
|
||||
}
|
||||
|
||||
uv_buf_t buf = uv_buf_init(m_sendBuf, (unsigned int) size);
|
||||
|
||||
if (uv_try_write(m_stream, &buf, 1) < 0) {
|
||||
close();
|
||||
return -1;
|
||||
}
|
||||
|
||||
m_expire = uv_now(uv_default_loop()) + kResponseTimeout;
|
||||
return m_sequence++;
|
||||
}
|
||||
|
||||
|
||||
void Client::connect(const std::vector<addrinfo*> &ipv4, const std::vector<addrinfo*> &ipv6)
|
||||
{
|
||||
addrinfo *addr = nullptr;
|
||||
m_ipv6 = ipv4.empty() && !ipv6.empty();
|
||||
|
||||
if (m_ipv6) {
|
||||
addr = ipv6[ipv6.size() == 1 ? 0 : rand() % ipv6.size()];
|
||||
uv_ip6_name(reinterpret_cast<sockaddr_in6*>(addr->ai_addr), m_ip, 45);
|
||||
}
|
||||
else {
|
||||
addr = ipv4[ipv4.size() == 1 ? 0 : rand() % ipv4.size()];
|
||||
uv_ip4_name(reinterpret_cast<sockaddr_in*>(addr->ai_addr), m_ip, 16);
|
||||
}
|
||||
|
||||
connect(addr->ai_addr);
|
||||
}
|
||||
|
||||
|
||||
void Client::connect(sockaddr *addr)
|
||||
{
|
||||
setState(ConnectingState);
|
||||
|
||||
reinterpret_cast<sockaddr_in*>(addr)->sin_port = htons(m_pool.port());
|
||||
delete m_socket;
|
||||
|
||||
uv_connect_t *req = new uv_connect_t;
|
||||
req->data = m_storage.ptr(m_key);
|
||||
|
||||
m_socket = new uv_tcp_t;
|
||||
m_socket->data = m_storage.ptr(m_key);
|
||||
|
||||
uv_tcp_init(uv_default_loop(), m_socket);
|
||||
uv_tcp_nodelay(m_socket, 1);
|
||||
|
||||
# ifndef WIN32
|
||||
uv_tcp_keepalive(m_socket, 1, 60);
|
||||
# endif
|
||||
|
||||
uv_tcp_connect(req, m_socket, reinterpret_cast<const sockaddr*>(addr), Client::onConnect);
|
||||
}
|
||||
|
||||
|
||||
void Client::login()
|
||||
{
|
||||
m_results.clear();
|
||||
|
||||
rapidjson::Document doc;
|
||||
doc.SetObject();
|
||||
|
||||
auto &allocator = doc.GetAllocator();
|
||||
|
||||
doc.AddMember("id", 1, allocator);
|
||||
doc.AddMember("jsonrpc", "2.0", allocator);
|
||||
doc.AddMember("method", "login", allocator);
|
||||
|
||||
rapidjson::Value params(rapidjson::kObjectType);
|
||||
params.AddMember("login", rapidjson::StringRef(m_pool.user()), allocator);
|
||||
params.AddMember("pass", rapidjson::StringRef(m_pool.password()), allocator);
|
||||
params.AddMember("agent", rapidjson::StringRef(m_agent), allocator);
|
||||
|
||||
doc.AddMember("params", params, allocator);
|
||||
|
||||
rapidjson::StringBuffer buffer(0, 512);
|
||||
rapidjson::Writer<rapidjson::StringBuffer> writer(buffer);
|
||||
doc.Accept(writer);
|
||||
|
||||
const size_t size = buffer.GetSize();
|
||||
if (size > (sizeof(m_buf) - 2)) {
|
||||
return;
|
||||
}
|
||||
|
||||
memcpy(m_sendBuf, buffer.GetString(), size);
|
||||
m_sendBuf[size] = '\n';
|
||||
m_sendBuf[size + 1] = '\0';
|
||||
|
||||
send(size + 1);
|
||||
}
|
||||
|
||||
|
||||
void Client::onClose()
|
||||
{
|
||||
delete m_socket;
|
||||
|
||||
m_stream = nullptr;
|
||||
m_socket = nullptr;
|
||||
setState(UnconnectedState);
|
||||
|
||||
reconnect();
|
||||
}
|
||||
|
||||
|
||||
void Client::parse(char *line, size_t len)
|
||||
{
|
||||
startTimeout();
|
||||
|
||||
line[len - 1] = '\0';
|
||||
|
||||
LOG_DEBUG("[%s] received (%d bytes): \"%s\"", m_pool.url(), len, line);
|
||||
|
||||
if (len < 32 || line[0] != '{') {
|
||||
if (!m_quiet) {
|
||||
LOG_ERR("[%s] JSON decode failed", m_pool.url());
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
rapidjson::Document doc;
|
||||
if (doc.ParseInsitu(line).HasParseError()) {
|
||||
if (!m_quiet) {
|
||||
LOG_ERR("[%s] JSON decode failed: \"%s\"", m_pool.url(), rapidjson::GetParseError_En(doc.GetParseError()));
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (!doc.IsObject()) {
|
||||
return;
|
||||
}
|
||||
|
||||
const rapidjson::Value &id = doc["id"];
|
||||
if (id.IsInt64()) {
|
||||
parseResponse(id.GetInt64(), doc["result"], doc["error"]);
|
||||
}
|
||||
else {
|
||||
parseNotification(doc["method"].GetString(), doc["params"], doc["error"]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Client::parseExtensions(const rapidjson::Value &value)
|
||||
{
|
||||
if (!value.IsArray()) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (const rapidjson::Value &ext : value.GetArray()) {
|
||||
if (!ext.IsString()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (strcmp(ext.GetString(), "nicehash") == 0) {
|
||||
m_nicehash = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Client::parseNotification(const char *method, const rapidjson::Value ¶ms, const rapidjson::Value &error)
|
||||
{
|
||||
if (error.IsObject()) {
|
||||
if (!m_quiet) {
|
||||
LOG_ERR("[%s] error: \"%s\", code: %d", m_pool.url(), error["message"].GetString(), error["code"].GetInt());
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (!method) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (strcmp(method, "job") == 0) {
|
||||
int code = -1;
|
||||
if (parseJob(params, &code)) {
|
||||
m_listener->onJobReceived(this, m_job);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
LOG_WARN("[%s] unsupported method: \"%s\"", m_pool.url(), method);
|
||||
}
|
||||
|
||||
|
||||
void Client::parseResponse(int64_t id, const rapidjson::Value &result, const rapidjson::Value &error)
|
||||
{
|
||||
if (error.IsObject()) {
|
||||
const char *message = error["message"].GetString();
|
||||
|
||||
auto it = m_results.find(id);
|
||||
if (it != m_results.end()) {
|
||||
it->second.done();
|
||||
m_listener->onResultAccepted(this, it->second, message);
|
||||
m_results.erase(it);
|
||||
}
|
||||
else if (!m_quiet) {
|
||||
LOG_ERR("[%s] error: \"%s\", code: %d", m_pool.url(), message, error["code"].GetInt());
|
||||
}
|
||||
|
||||
if (isCriticalError(message)) {
|
||||
close();
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (!result.IsObject()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (id == 1) {
|
||||
int code = -1;
|
||||
if (!parseLogin(result, &code)) {
|
||||
if (!m_quiet) {
|
||||
LOG_ERR("[%s] login error code: %d", m_pool.url(), code);
|
||||
}
|
||||
|
||||
close();
|
||||
return;
|
||||
}
|
||||
|
||||
m_failures = 0;
|
||||
m_listener->onLoginSuccess(this);
|
||||
m_listener->onJobReceived(this, m_job);
|
||||
return;
|
||||
}
|
||||
|
||||
auto it = m_results.find(id);
|
||||
if (it != m_results.end()) {
|
||||
it->second.done();
|
||||
m_listener->onResultAccepted(this, it->second, nullptr);
|
||||
m_results.erase(it);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Client::ping()
|
||||
{
|
||||
send(snprintf(m_sendBuf, sizeof(m_sendBuf), "{\"id\":%" PRId64 ",\"jsonrpc\":\"2.0\",\"method\":\"keepalived\",\"params\":{\"id\":\"%s\"}}\n", m_sequence, m_rpcId.data()));
|
||||
}
|
||||
|
||||
|
||||
void Client::reconnect()
|
||||
{
|
||||
if (!m_listener) {
|
||||
m_storage.remove(m_key);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
setState(ConnectingState);
|
||||
m_keepAlive = 0;
|
||||
|
||||
if (m_failures == -1) {
|
||||
return m_listener->onClose(this, -1);
|
||||
}
|
||||
|
||||
m_failures++;
|
||||
m_listener->onClose(this, (int) m_failures);
|
||||
|
||||
m_expire = uv_now(uv_default_loop()) + m_retryPause;
|
||||
}
|
||||
|
||||
|
||||
void Client::setState(SocketState state)
|
||||
{
|
||||
LOG_DEBUG("[%s] state: %d", m_pool.url(), state);
|
||||
|
||||
if (m_state == state) {
|
||||
return;
|
||||
}
|
||||
|
||||
m_state = state;
|
||||
}
|
||||
|
||||
|
||||
void Client::startTimeout()
|
||||
{
|
||||
m_expire = 0;
|
||||
|
||||
if (m_pool.keepAlive()) {
|
||||
m_keepAlive = uv_now(uv_default_loop()) + (m_pool.keepAlive() * 1000);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Client::onAllocBuffer(uv_handle_t *handle, size_t suggested_size, uv_buf_t *buf)
|
||||
{
|
||||
auto client = getClient(handle->data);
|
||||
if (!client) {
|
||||
return;
|
||||
}
|
||||
|
||||
buf->base = &client->m_recvBuf.base[client->m_recvBufPos];
|
||||
buf->len = client->m_recvBuf.len - client->m_recvBufPos;
|
||||
}
|
||||
|
||||
|
||||
void Client::onClose(uv_handle_t *handle)
|
||||
{
|
||||
auto client = getClient(handle->data);
|
||||
if (!client) {
|
||||
return;
|
||||
}
|
||||
|
||||
client->onClose();
|
||||
}
|
||||
|
||||
|
||||
void Client::onConnect(uv_connect_t *req, int status)
|
||||
{
|
||||
auto client = getClient(req->data);
|
||||
if (!client) {
|
||||
delete req;
|
||||
return;
|
||||
}
|
||||
|
||||
if (status < 0) {
|
||||
if (!client->m_quiet) {
|
||||
LOG_ERR("[%s] connect error: \"%s\"", client->m_pool.url(), uv_strerror(status));
|
||||
}
|
||||
|
||||
delete req;
|
||||
client->close();
|
||||
return;
|
||||
}
|
||||
|
||||
client->m_stream = static_cast<uv_stream_t*>(req->handle);
|
||||
client->m_stream->data = req->data;
|
||||
client->setState(ConnectedState);
|
||||
|
||||
uv_read_start(client->m_stream, Client::onAllocBuffer, Client::onRead);
|
||||
delete req;
|
||||
|
||||
client->login();
|
||||
}
|
||||
|
||||
|
||||
void Client::onRead(uv_stream_t *stream, ssize_t nread, const uv_buf_t *buf)
|
||||
{
|
||||
auto client = getClient(stream->data);
|
||||
if (!client) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (nread < 0) {
|
||||
if (nread != UV_EOF && !client->m_quiet) {
|
||||
LOG_ERR("[%s] read error: \"%s\"", client->m_pool.url(), uv_strerror((int) nread));
|
||||
}
|
||||
|
||||
client->close();
|
||||
return;
|
||||
}
|
||||
|
||||
if ((size_t) nread > (sizeof(m_buf) - 8 - client->m_recvBufPos)) {
|
||||
client->close();
|
||||
return;
|
||||
}
|
||||
|
||||
assert(client->m_listener != nullptr);
|
||||
if (!client->m_listener) {
|
||||
return client->reconnect();
|
||||
}
|
||||
|
||||
client->m_recvBufPos += nread;
|
||||
|
||||
char* end;
|
||||
char* start = client->m_recvBuf.base;
|
||||
size_t remaining = client->m_recvBufPos;
|
||||
|
||||
while ((end = static_cast<char*>(memchr(start, '\n', remaining))) != nullptr) {
|
||||
end++;
|
||||
size_t len = end - start;
|
||||
client->parse(start, len);
|
||||
|
||||
remaining -= len;
|
||||
start = end;
|
||||
}
|
||||
|
||||
if (remaining == 0) {
|
||||
client->m_recvBufPos = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
if (start == client->m_recvBuf.base) {
|
||||
return;
|
||||
}
|
||||
|
||||
memcpy(client->m_recvBuf.base, start, remaining);
|
||||
client->m_recvBufPos = remaining;
|
||||
}
|
||||
|
||||
|
||||
void Client::onResolved(uv_getaddrinfo_t *req, int status, struct addrinfo *res)
|
||||
{
|
||||
auto client = getClient(req->data);
|
||||
if (!client) {
|
||||
return;
|
||||
}
|
||||
|
||||
assert(client->m_listener != nullptr);
|
||||
if (!client->m_listener) {
|
||||
return client->reconnect();
|
||||
}
|
||||
|
||||
if (status < 0) {
|
||||
if (!client->m_quiet) {
|
||||
LOG_ERR("[%s] DNS error: \"%s\"", client->m_pool.url(), uv_strerror(status));
|
||||
}
|
||||
|
||||
return client->reconnect();
|
||||
}
|
||||
|
||||
addrinfo *ptr = res;
|
||||
std::vector<addrinfo*> ipv4;
|
||||
std::vector<addrinfo*> ipv6;
|
||||
|
||||
while (ptr != nullptr) {
|
||||
if (ptr->ai_family == AF_INET) {
|
||||
ipv4.push_back(ptr);
|
||||
}
|
||||
|
||||
if (ptr->ai_family == AF_INET6) {
|
||||
ipv6.push_back(ptr);
|
||||
}
|
||||
|
||||
ptr = ptr->ai_next;
|
||||
}
|
||||
|
||||
if (ipv4.empty() && ipv6.empty()) {
|
||||
if (!client->m_quiet) {
|
||||
LOG_ERR("[%s] DNS error: \"No IPv4 (A) or IPv6 (AAAA) records found\"", client->m_pool.url());
|
||||
}
|
||||
|
||||
uv_freeaddrinfo(res);
|
||||
return client->reconnect();
|
||||
}
|
||||
|
||||
client->connect(ipv4, ipv6);
|
||||
uv_freeaddrinfo(res);
|
||||
}
|
139
src/common/net/Client.h
Normal file
139
src/common/net/Client.h
Normal file
|
@ -0,0 +1,139 @@
|
|||
/* 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 2016-2018 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 __CLIENT_H__
|
||||
#define __CLIENT_H__
|
||||
|
||||
|
||||
#include <map>
|
||||
#include <uv.h>
|
||||
#include <vector>
|
||||
|
||||
|
||||
#include "common/net/Id.h"
|
||||
#include "common/net/Pool.h"
|
||||
#include "common/net/Storage.h"
|
||||
#include "common/net/SubmitResult.h"
|
||||
#include "net/Job.h"
|
||||
#include "rapidjson/fwd.h"
|
||||
|
||||
|
||||
class IClientListener;
|
||||
class JobResult;
|
||||
|
||||
|
||||
class Client
|
||||
{
|
||||
public:
|
||||
enum SocketState {
|
||||
UnconnectedState,
|
||||
HostLookupState,
|
||||
ConnectingState,
|
||||
ConnectedState,
|
||||
ClosingState
|
||||
};
|
||||
|
||||
constexpr static int kResponseTimeout = 20 * 1000;
|
||||
|
||||
Client(int id, const char *agent, IClientListener *listener);
|
||||
~Client();
|
||||
|
||||
bool disconnect();
|
||||
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 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 int id() const { return m_id; }
|
||||
inline SocketState state() const { return m_state; }
|
||||
inline uint16_t port() const { return m_pool.port(); }
|
||||
inline void setQuiet(bool quiet) { m_quiet = quiet; }
|
||||
inline void setRetryPause(int ms) { m_retryPause = ms; }
|
||||
|
||||
private:
|
||||
bool close();
|
||||
bool isCriticalError(const char *message);
|
||||
bool parseJob(const rapidjson::Value ¶ms, int *code);
|
||||
bool parseLogin(const rapidjson::Value &result, int *code);
|
||||
int resolve(const char *host);
|
||||
int64_t send(size_t size);
|
||||
void connect(const std::vector<addrinfo*> &ipv4, const std::vector<addrinfo*> &ipv6);
|
||||
void connect(sockaddr *addr);
|
||||
void login();
|
||||
void onClose();
|
||||
void parse(char *line, size_t len);
|
||||
void parseExtensions(const rapidjson::Value &value);
|
||||
void parseNotification(const char *method, const rapidjson::Value ¶ms, const rapidjson::Value &error);
|
||||
void parseResponse(int64_t id, const rapidjson::Value &result, const rapidjson::Value &error);
|
||||
void ping();
|
||||
void reconnect();
|
||||
void setState(SocketState state);
|
||||
void startTimeout();
|
||||
|
||||
static void onAllocBuffer(uv_handle_t *handle, size_t suggested_size, uv_buf_t *buf);
|
||||
static void onClose(uv_handle_t *handle);
|
||||
static void onConnect(uv_connect_t *req, int status);
|
||||
static void onRead(uv_stream_t *stream, ssize_t nread, const uv_buf_t *buf);
|
||||
static void onResolved(uv_getaddrinfo_t *req, int status, struct addrinfo *res);
|
||||
|
||||
static inline Client *getClient(void *data) { return m_storage.get(data); }
|
||||
|
||||
addrinfo m_hints;
|
||||
bool m_ipv6;
|
||||
bool m_nicehash;
|
||||
bool m_quiet;
|
||||
char m_buf[2048];
|
||||
char m_ip[46];
|
||||
char m_sendBuf[768];
|
||||
const char *m_agent;
|
||||
IClientListener *m_listener;
|
||||
int m_id;
|
||||
int m_retryPause;
|
||||
int64_t m_failures;
|
||||
Job m_job;
|
||||
Pool m_pool;
|
||||
size_t m_recvBufPos;
|
||||
SocketState m_state;
|
||||
std::map<int64_t, SubmitResult> m_results;
|
||||
uint64_t m_expire;
|
||||
uint64_t m_jobs;
|
||||
uint64_t m_keepAlive;
|
||||
uintptr_t m_key;
|
||||
uv_buf_t m_recvBuf;
|
||||
uv_getaddrinfo_t m_resolver;
|
||||
uv_stream_t *m_stream;
|
||||
uv_tcp_t *m_socket;
|
||||
xmrig::Id m_rpcId;
|
||||
|
||||
static int64_t m_sequence;
|
||||
static xmrig::Storage<Client> m_storage;
|
||||
};
|
||||
|
||||
|
||||
#endif /* __CLIENT_H__ */
|
98
src/common/net/Id.h
Normal file
98
src/common/net/Id.h
Normal file
|
@ -0,0 +1,98 @@
|
|||
/* 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 2016-2018 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 __ID_H__
|
||||
#define __ID_H__
|
||||
|
||||
|
||||
#include <string.h>
|
||||
|
||||
|
||||
namespace xmrig {
|
||||
|
||||
|
||||
class Id
|
||||
{
|
||||
public:
|
||||
inline Id() :
|
||||
m_data()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
inline Id(const char *id, size_t sizeFix = 0)
|
||||
{
|
||||
setId(id, sizeFix);
|
||||
}
|
||||
|
||||
|
||||
inline bool operator==(const Id &other) const
|
||||
{
|
||||
return memcmp(m_data, other.m_data, sizeof(m_data)) == 0;
|
||||
}
|
||||
|
||||
|
||||
inline bool operator!=(const Id &other) const
|
||||
{
|
||||
return memcmp(m_data, other.m_data, sizeof(m_data)) != 0;
|
||||
}
|
||||
|
||||
|
||||
Id &operator=(const Id &other)
|
||||
{
|
||||
memcpy(m_data, other.m_data, sizeof(m_data));
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
inline bool setId(const char *id, size_t sizeFix = 0)
|
||||
{
|
||||
memset(m_data, 0, sizeof(m_data));
|
||||
if (!id) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const size_t size = strlen(id);
|
||||
if (size >= sizeof(m_data)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
memcpy(m_data, id, size - sizeFix);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
inline const char *data() const { return m_data; }
|
||||
inline bool isValid() const { return *m_data != '\0'; }
|
||||
|
||||
|
||||
private:
|
||||
char m_data[64];
|
||||
};
|
||||
|
||||
|
||||
} /* namespace xmrig */
|
||||
|
||||
|
||||
#endif /* __ID_H__ */
|
280
src/common/net/Pool.cpp
Normal file
280
src/common/net/Pool.cpp
Normal file
|
@ -0,0 +1,280 @@
|
|||
/* 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 2016-2018 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 <assert.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
|
||||
|
||||
#include "common/net/Pool.h"
|
||||
|
||||
|
||||
#ifdef _MSC_VER
|
||||
# define strncasecmp _strnicmp
|
||||
# define strcasecmp _stricmp
|
||||
#endif
|
||||
|
||||
|
||||
static const char *algoNames[] = {
|
||||
"cryptonight",
|
||||
# ifndef XMRIG_NO_AEON
|
||||
"cryptonight-lite",
|
||||
# else
|
||||
nullptr,
|
||||
# endif
|
||||
# ifndef XMRIG_NO_SUMO
|
||||
"cryptonight-heavy"
|
||||
# else
|
||||
nullptr
|
||||
# endif
|
||||
};
|
||||
|
||||
|
||||
static const char *algoNamesShort[] = {
|
||||
"cn",
|
||||
# ifndef XMRIG_NO_AEON
|
||||
"cn-lite",
|
||||
# else
|
||||
nullptr,
|
||||
# endif
|
||||
# ifndef XMRIG_NO_SUMO
|
||||
"cn-heavy"
|
||||
# else
|
||||
nullptr
|
||||
# endif
|
||||
};
|
||||
|
||||
|
||||
Pool::Pool() :
|
||||
m_nicehash(false),
|
||||
m_keepAlive(0),
|
||||
m_port(kDefaultPort),
|
||||
m_algo(xmrig::CRYPTONIGHT),
|
||||
m_variant(xmrig::VARIANT_AUTO)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Parse url.
|
||||
*
|
||||
* Valid urls:
|
||||
* example.com
|
||||
* example.com:3333
|
||||
* stratum+tcp://example.com
|
||||
* stratum+tcp://example.com:3333
|
||||
*
|
||||
* @param url
|
||||
*/
|
||||
Pool::Pool(const char *url) :
|
||||
m_nicehash(false),
|
||||
m_keepAlive(0),
|
||||
m_port(kDefaultPort),
|
||||
m_algo(xmrig::CRYPTONIGHT),
|
||||
m_variant(xmrig::VARIANT_AUTO)
|
||||
{
|
||||
parse(url);
|
||||
}
|
||||
|
||||
|
||||
Pool::Pool(const char *host, uint16_t port, const char *user, const char *password, int keepAlive, bool nicehash, xmrig::Variant variant) :
|
||||
m_nicehash(nicehash),
|
||||
m_keepAlive(keepAlive),
|
||||
m_port(port),
|
||||
m_algo(xmrig::CRYPTONIGHT),
|
||||
m_host(host),
|
||||
m_password(password),
|
||||
m_user(user),
|
||||
m_variant(variant)
|
||||
{
|
||||
const size_t size = m_host.size() + 8;
|
||||
assert(size > 8);
|
||||
|
||||
char *url = new char[size]();
|
||||
snprintf(url, size - 1, "%s:%d", m_host.data(), m_port);
|
||||
|
||||
m_url = url;
|
||||
}
|
||||
|
||||
|
||||
const char *Pool::algoName(xmrig::Algo algorithm)
|
||||
{
|
||||
return algoNames[algorithm];
|
||||
}
|
||||
|
||||
|
||||
xmrig::Algo Pool::algorithm(const char *algo)
|
||||
{
|
||||
# ifndef XMRIG_NO_AEON
|
||||
if (strcasecmp(algo, "cryptonight-light") == 0) {
|
||||
fprintf(stderr, "Algorithm \"cryptonight-light\" is deprecated, use \"cryptonight-lite\" instead\n");
|
||||
|
||||
return xmrig::CRYPTONIGHT_LITE;
|
||||
}
|
||||
# endif
|
||||
|
||||
const size_t size = sizeof(algoNames) / sizeof(algoNames[0]);
|
||||
|
||||
assert(size == (sizeof(algoNamesShort) / sizeof(algoNamesShort[0])));
|
||||
|
||||
for (size_t i = 0; i < size; i++) {
|
||||
if ((algoNames[i] && strcasecmp(algo, algoNames[i]) == 0) || (algoNamesShort[i] && strcasecmp(algo, algoNamesShort[i]) == 0)) {
|
||||
return static_cast<xmrig::Algo>(i);
|
||||
}
|
||||
}
|
||||
|
||||
fprintf(stderr, "Unknown algorithm \"%s\" specified.\n", algo);
|
||||
return xmrig::INVALID_ALGO;
|
||||
}
|
||||
|
||||
|
||||
bool Pool::parse(const char *url)
|
||||
{
|
||||
assert(url != nullptr);
|
||||
|
||||
const char *p = strstr(url, "://");
|
||||
const char *base = url;
|
||||
|
||||
if (p) {
|
||||
if (strncasecmp(url, "stratum+tcp://", 14)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
base = url + 14;
|
||||
}
|
||||
|
||||
if (!strlen(base) || *base == '/') {
|
||||
return false;
|
||||
}
|
||||
|
||||
m_url = url;
|
||||
if (base[0] == '[') {
|
||||
return parseIPv6(base);
|
||||
}
|
||||
|
||||
const char *port = strchr(base, ':');
|
||||
if (!port) {
|
||||
m_host = base;
|
||||
return true;
|
||||
}
|
||||
|
||||
const size_t size = port++ - base + 1;
|
||||
char *host = new char[size]();
|
||||
memcpy(host, base, size - 1);
|
||||
|
||||
m_host = host;
|
||||
m_port = static_cast<uint16_t>(strtol(port, nullptr, 10));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool Pool::setUserpass(const char *userpass)
|
||||
{
|
||||
const char *p = strchr(userpass, ':');
|
||||
if (!p) {
|
||||
return false;
|
||||
}
|
||||
|
||||
char *user = new char[p - userpass + 1]();
|
||||
strncpy(user, userpass, p - userpass);
|
||||
|
||||
m_user = user;
|
||||
m_password = p + 1;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
void Pool::adjust(xmrig::Algo algo)
|
||||
{
|
||||
if (!isValid()) {
|
||||
return;
|
||||
}
|
||||
|
||||
m_algo = algo;
|
||||
|
||||
if (strstr(m_host.data(), ".nicehash.com")) {
|
||||
m_keepAlive = false;
|
||||
m_nicehash = true;
|
||||
}
|
||||
|
||||
if (strstr(m_host.data(), ".minergate.com")) {
|
||||
m_keepAlive = false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Pool::setVariant(int variant)
|
||||
{
|
||||
switch (variant) {
|
||||
case xmrig::VARIANT_AUTO:
|
||||
case xmrig::VARIANT_NONE:
|
||||
case xmrig::VARIANT_V1:
|
||||
m_variant = static_cast<xmrig::Variant>(variant);
|
||||
break;
|
||||
|
||||
default:
|
||||
assert(false);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool Pool::isEqual(const Pool &other) const
|
||||
{
|
||||
return (m_nicehash == other.m_nicehash
|
||||
&& m_keepAlive == other.m_keepAlive
|
||||
&& m_port == other.m_port
|
||||
&& m_algo == other.m_algo
|
||||
&& m_host == other.m_host
|
||||
&& m_password == other.m_password
|
||||
&& m_url == other.m_url
|
||||
&& m_user == other.m_user
|
||||
&& m_variant == other.m_variant);
|
||||
}
|
||||
|
||||
|
||||
bool Pool::parseIPv6(const char *addr)
|
||||
{
|
||||
const char *end = strchr(addr, ']');
|
||||
if (!end) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const char *port = strchr(end, ':');
|
||||
if (!port) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const size_t size = end - addr;
|
||||
char *host = new char[size]();
|
||||
memcpy(host, addr + 1, size - 1);
|
||||
|
||||
m_host = host;
|
||||
m_port = static_cast<uint16_t>(strtol(port + 1, nullptr, 10));
|
||||
|
||||
return true;
|
||||
}
|
96
src/common/net/Pool.h
Normal file
96
src/common/net/Pool.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 2016-2018 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 __POOL_H__
|
||||
#define __POOL_H__
|
||||
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
|
||||
#include "common/utils/c_str.h"
|
||||
#include "common/xmrig.h"
|
||||
|
||||
|
||||
class Pool
|
||||
{
|
||||
public:
|
||||
constexpr static const char *kDefaultPassword = "x";
|
||||
constexpr static const char *kDefaultUser = "x";
|
||||
constexpr static uint16_t kDefaultPort = 3333;
|
||||
constexpr static int kKeepAliveTimeout = 60;
|
||||
|
||||
Pool();
|
||||
Pool(const char *url);
|
||||
Pool(const char *host,
|
||||
uint16_t port,
|
||||
const char *user = nullptr,
|
||||
const char *password = nullptr,
|
||||
int keepAlive = 0,
|
||||
bool nicehash = false,
|
||||
xmrig::Variant variant = xmrig::VARIANT_AUTO
|
||||
);
|
||||
|
||||
static const char *algoName(xmrig::Algo algorithm);
|
||||
static xmrig::Algo algorithm(const char *algo);
|
||||
|
||||
inline bool isNicehash() const { return m_nicehash; }
|
||||
inline bool isValid() const { return !m_host.isNull() && m_port > 0; }
|
||||
inline const char *host() const { return m_host.data(); }
|
||||
inline const char *password() const { return !m_password.isNull() ? m_password.data() : kDefaultPassword; }
|
||||
inline const char *url() const { return m_url.data(); }
|
||||
inline const char *user() const { return !m_user.isNull() ? m_user.data() : kDefaultUser; }
|
||||
inline int keepAlive() const { return m_keepAlive; }
|
||||
inline uint16_t port() const { return m_port; }
|
||||
inline void setKeepAlive(int keepAlive) { m_keepAlive = keepAlive >= 0 ? keepAlive : 0; }
|
||||
inline void setNicehash(bool nicehash) { m_nicehash = nicehash; }
|
||||
inline void setPassword(const char *password) { m_password = password; }
|
||||
inline void setUser(const char *user) { m_user = user; }
|
||||
inline xmrig::Algo algo() const { return m_algo; }
|
||||
inline xmrig::Variant variant() const { return m_variant; }
|
||||
|
||||
inline bool operator!=(const Pool &other) const { return !isEqual(other); }
|
||||
inline bool operator==(const Pool &other) const { return isEqual(other); }
|
||||
|
||||
bool parse(const char *url);
|
||||
bool setUserpass(const char *userpass);
|
||||
void adjust(xmrig::Algo algo);
|
||||
void setVariant(int variant);
|
||||
|
||||
bool isEqual(const Pool &other) const;
|
||||
|
||||
private:
|
||||
bool parseIPv6(const char *addr);
|
||||
|
||||
bool m_nicehash;
|
||||
int m_keepAlive;
|
||||
uint16_t m_port;
|
||||
xmrig::Algo m_algo;
|
||||
xmrig::c_str m_host;
|
||||
xmrig::c_str m_password;
|
||||
xmrig::c_str m_url;
|
||||
xmrig::c_str m_user;
|
||||
xmrig::Variant m_variant;
|
||||
};
|
||||
|
||||
#endif /* __POOL_H__ */
|
97
src/common/net/Storage.h
Normal file
97
src/common/net/Storage.h
Normal file
|
@ -0,0 +1,97 @@
|
|||
/* 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 2016-2018 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 __STORAGE_H__
|
||||
#define __STORAGE_H__
|
||||
|
||||
|
||||
#include <assert.h>
|
||||
#include <map>
|
||||
|
||||
#include "log/Log.h"
|
||||
|
||||
|
||||
namespace xmrig {
|
||||
|
||||
|
||||
template <class TYPE>
|
||||
class Storage
|
||||
{
|
||||
public:
|
||||
inline Storage() :
|
||||
m_counter(0)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
inline uintptr_t add(TYPE *ptr)
|
||||
{
|
||||
m_data[m_counter] = ptr;
|
||||
|
||||
return m_counter++;
|
||||
}
|
||||
|
||||
|
||||
inline static void *ptr(uintptr_t id) { return reinterpret_cast<void *>(id); }
|
||||
|
||||
|
||||
inline TYPE *get(void *id) const { return get(reinterpret_cast<uintptr_t>(id)); }
|
||||
inline TYPE *get(uintptr_t id) const
|
||||
{
|
||||
assert(m_data.count(id) > 0);
|
||||
|
||||
if (m_data.count(id) == 0) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return m_data.at(id);
|
||||
}
|
||||
|
||||
|
||||
inline void remove(void *id) { remove(reinterpret_cast<uintptr_t>(id)); }
|
||||
inline void remove(uintptr_t id)
|
||||
{
|
||||
TYPE *obj = get(id);
|
||||
if (obj == nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto it = m_data.find(id);
|
||||
if (it != m_data.end()) {
|
||||
m_data.erase(it);
|
||||
}
|
||||
|
||||
delete obj;
|
||||
}
|
||||
|
||||
|
||||
private:
|
||||
std::map<uintptr_t, TYPE *> m_data;
|
||||
uint64_t m_counter;
|
||||
};
|
||||
|
||||
|
||||
} /* namespace xmrig */
|
||||
|
||||
|
||||
#endif /* __STORAGE_H__ */
|
45
src/common/net/SubmitResult.cpp
Normal file
45
src/common/net/SubmitResult.cpp
Normal file
|
@ -0,0 +1,45 @@
|
|||
/* 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 2016-2018 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 <uv.h>
|
||||
|
||||
|
||||
#include "common/net/SubmitResult.h"
|
||||
|
||||
|
||||
SubmitResult::SubmitResult(int64_t seq, uint32_t diff, uint64_t actualDiff, int64_t reqId) :
|
||||
reqId(reqId),
|
||||
seq(seq),
|
||||
diff(diff),
|
||||
actualDiff(actualDiff),
|
||||
elapsed(0)
|
||||
{
|
||||
start = uv_hrtime();
|
||||
}
|
||||
|
||||
|
||||
void SubmitResult::done()
|
||||
{
|
||||
elapsed = (uv_hrtime() - start) / 1000000;
|
||||
}
|
49
src/common/net/SubmitResult.h
Normal file
49
src/common/net/SubmitResult.h
Normal file
|
@ -0,0 +1,49 @@
|
|||
/* 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 2016-2018 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 __SUBMITRESULT_H__
|
||||
#define __SUBMITRESULT_H__
|
||||
|
||||
|
||||
#include <uv.h>
|
||||
|
||||
|
||||
class SubmitResult
|
||||
{
|
||||
public:
|
||||
inline SubmitResult() : reqId(0), seq(0), diff(0), actualDiff(0), elapsed(0), start(0) {}
|
||||
SubmitResult(int64_t seq, uint32_t diff, uint64_t actualDiff, int64_t reqId = 0);
|
||||
|
||||
void done();
|
||||
|
||||
int64_t reqId;
|
||||
int64_t seq;
|
||||
uint32_t diff;
|
||||
uint64_t actualDiff;
|
||||
uint64_t elapsed;
|
||||
|
||||
private:
|
||||
uint64_t start;
|
||||
};
|
||||
|
||||
#endif /* __SUBMITRESULT_H__ */
|
164
src/common/net/strategies/FailoverStrategy.cpp
Normal file
164
src/common/net/strategies/FailoverStrategy.cpp
Normal file
|
@ -0,0 +1,164 @@
|
|||
/* 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 2016-2018 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 "common/net/Client.h"
|
||||
#include "common/net/strategies/FailoverStrategy.h"
|
||||
#include "common/Platform.h"
|
||||
#include "interfaces/IStrategyListener.h"
|
||||
|
||||
|
||||
FailoverStrategy::FailoverStrategy(const std::vector<Pool> &urls, int retryPause, int retries, IStrategyListener *listener, bool quiet) :
|
||||
m_quiet(quiet),
|
||||
m_retries(retries),
|
||||
m_retryPause(retryPause),
|
||||
m_active(-1),
|
||||
m_index(0),
|
||||
m_listener(listener)
|
||||
{
|
||||
for (const Pool &url : urls) {
|
||||
add(url);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
FailoverStrategy::~FailoverStrategy()
|
||||
{
|
||||
for (Client *client : m_pools) {
|
||||
client->deleteLater();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int64_t FailoverStrategy::submit(const JobResult &result)
|
||||
{
|
||||
if (m_active == -1) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
return m_pools[m_active]->submit(result);
|
||||
}
|
||||
|
||||
|
||||
void FailoverStrategy::connect()
|
||||
{
|
||||
m_pools[m_index]->connect();
|
||||
}
|
||||
|
||||
|
||||
void FailoverStrategy::resume()
|
||||
{
|
||||
if (!isActive()) {
|
||||
return;
|
||||
}
|
||||
|
||||
m_listener->onJob(this, m_pools[m_active], m_pools[m_active]->job());
|
||||
}
|
||||
|
||||
|
||||
void FailoverStrategy::stop()
|
||||
{
|
||||
for (size_t i = 0; i < m_pools.size(); ++i) {
|
||||
m_pools[i]->disconnect();
|
||||
}
|
||||
|
||||
m_index = 0;
|
||||
m_active = -1;
|
||||
|
||||
m_listener->onPause(this);
|
||||
}
|
||||
|
||||
|
||||
void FailoverStrategy::tick(uint64_t now)
|
||||
{
|
||||
for (Client *client : m_pools) {
|
||||
client->tick(now);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
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 < m_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(this, 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<int>(i)) {
|
||||
m_pools[i]->disconnect();
|
||||
}
|
||||
}
|
||||
|
||||
if (active >= 0 && active != m_active) {
|
||||
m_index = m_active = active;
|
||||
m_listener->onActive(this, client);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void FailoverStrategy::onResultAccepted(Client *client, const SubmitResult &result, const char *error)
|
||||
{
|
||||
m_listener->onResultAccepted(this, client, result, error);
|
||||
}
|
||||
|
||||
|
||||
void FailoverStrategy::add(const Pool &pool)
|
||||
{
|
||||
Client *client = new Client((int) m_pools.size(), Platform::userAgent(), this);
|
||||
client->setPool(pool);
|
||||
client->setRetryPause(m_retryPause * 1000);
|
||||
client->setQuiet(m_quiet);
|
||||
|
||||
m_pools.push_back(client);
|
||||
}
|
74
src/common/net/strategies/FailoverStrategy.h
Normal file
74
src/common/net/strategies/FailoverStrategy.h
Normal file
|
@ -0,0 +1,74 @@
|
|||
/* 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 2016-2018 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 __FAILOVERSTRATEGY_H__
|
||||
#define __FAILOVERSTRATEGY_H__
|
||||
|
||||
|
||||
#include <vector>
|
||||
|
||||
|
||||
#include "common/net/Pool.h"
|
||||
#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<Pool> &urls, int retryPause, int retries, IStrategyListener *listener, bool quiet = false);
|
||||
~FailoverStrategy();
|
||||
|
||||
public:
|
||||
inline bool isActive() const override { return m_active >= 0; }
|
||||
|
||||
int64_t submit(const JobResult &result) override;
|
||||
void connect() override;
|
||||
void resume() override;
|
||||
void stop() override;
|
||||
void tick(uint64_t now) override;
|
||||
|
||||
protected:
|
||||
void onClose(Client *client, int failures) override;
|
||||
void onJobReceived(Client *client, const Job &job) override;
|
||||
void onLoginSuccess(Client *client) override;
|
||||
void onResultAccepted(Client *client, const SubmitResult &result, const char *error) override;
|
||||
|
||||
private:
|
||||
void add(const Pool &pool);
|
||||
|
||||
const bool m_quiet;
|
||||
const int m_retries;
|
||||
const int m_retryPause;
|
||||
int m_active;
|
||||
int m_index;
|
||||
IStrategyListener *m_listener;
|
||||
std::vector<Client*> m_pools;
|
||||
};
|
||||
|
||||
#endif /* __FAILOVERSTRATEGY_H__ */
|
109
src/common/net/strategies/SinglePoolStrategy.cpp
Normal file
109
src/common/net/strategies/SinglePoolStrategy.cpp
Normal file
|
@ -0,0 +1,109 @@
|
|||
/* 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 2016-2018 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 "common/net/Client.h"
|
||||
#include "common/net/strategies/SinglePoolStrategy.h"
|
||||
#include "common/Platform.h"
|
||||
#include "interfaces/IStrategyListener.h"
|
||||
|
||||
|
||||
SinglePoolStrategy::SinglePoolStrategy(const Pool &pool, int retryPause, IStrategyListener *listener, bool quiet) :
|
||||
m_active(false),
|
||||
m_listener(listener)
|
||||
{
|
||||
m_client = new Client(0, Platform::userAgent(), this);
|
||||
m_client->setPool(pool);
|
||||
m_client->setRetryPause(retryPause * 1000);
|
||||
m_client->setQuiet(quiet);
|
||||
}
|
||||
|
||||
|
||||
SinglePoolStrategy::~SinglePoolStrategy()
|
||||
{
|
||||
m_client->deleteLater();
|
||||
}
|
||||
|
||||
|
||||
int64_t SinglePoolStrategy::submit(const JobResult &result)
|
||||
{
|
||||
return m_client->submit(result);
|
||||
}
|
||||
|
||||
|
||||
void SinglePoolStrategy::connect()
|
||||
{
|
||||
m_client->connect();
|
||||
}
|
||||
|
||||
|
||||
void SinglePoolStrategy::resume()
|
||||
{
|
||||
if (!isActive()) {
|
||||
return;
|
||||
}
|
||||
|
||||
m_listener->onJob(this, m_client, m_client->job());
|
||||
}
|
||||
|
||||
|
||||
void SinglePoolStrategy::stop()
|
||||
{
|
||||
m_client->disconnect();
|
||||
}
|
||||
|
||||
|
||||
void SinglePoolStrategy::tick(uint64_t now)
|
||||
{
|
||||
m_client->tick(now);
|
||||
}
|
||||
|
||||
|
||||
void SinglePoolStrategy::onClose(Client *client, int failures)
|
||||
{
|
||||
if (!isActive()) {
|
||||
return;
|
||||
}
|
||||
|
||||
m_active = false;
|
||||
m_listener->onPause(this);
|
||||
}
|
||||
|
||||
|
||||
void SinglePoolStrategy::onJobReceived(Client *client, const Job &job)
|
||||
{
|
||||
m_listener->onJob(this, client, job);
|
||||
}
|
||||
|
||||
|
||||
void SinglePoolStrategy::onLoginSuccess(Client *client)
|
||||
{
|
||||
m_active = true;
|
||||
m_listener->onActive(this, client);
|
||||
}
|
||||
|
||||
|
||||
void SinglePoolStrategy::onResultAccepted(Client *client, const SubmitResult &result, const char *error)
|
||||
{
|
||||
m_listener->onResultAccepted(this, client, result, error);
|
||||
}
|
64
src/common/net/strategies/SinglePoolStrategy.h
Normal file
64
src/common/net/strategies/SinglePoolStrategy.h
Normal file
|
@ -0,0 +1,64 @@
|
|||
/* 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 2016-2018 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 __SINGLEPOOLSTRATEGY_H__
|
||||
#define __SINGLEPOOLSTRATEGY_H__
|
||||
|
||||
|
||||
#include "interfaces/IClientListener.h"
|
||||
#include "interfaces/IStrategy.h"
|
||||
|
||||
|
||||
class Client;
|
||||
class IStrategyListener;
|
||||
class Url;
|
||||
|
||||
|
||||
class SinglePoolStrategy : public IStrategy, public IClientListener
|
||||
{
|
||||
public:
|
||||
SinglePoolStrategy(const Pool &pool, int retryPause, IStrategyListener *listener, bool quiet = false);
|
||||
~SinglePoolStrategy();
|
||||
|
||||
public:
|
||||
inline bool isActive() const override { return m_active; }
|
||||
|
||||
int64_t submit(const JobResult &result) override;
|
||||
void connect() override;
|
||||
void resume() override;
|
||||
void stop() override;
|
||||
void tick(uint64_t now) override;
|
||||
|
||||
protected:
|
||||
void onClose(Client *client, int failures) override;
|
||||
void onJobReceived(Client *client, const Job &job) override;
|
||||
void onLoginSuccess(Client *client) override;
|
||||
void onResultAccepted(Client *client, const SubmitResult &result, const char *error) override;
|
||||
|
||||
private:
|
||||
bool m_active;
|
||||
Client *m_client;
|
||||
IStrategyListener *m_listener;
|
||||
};
|
||||
|
||||
#endif /* __SINGLEPOOLSTRATEGY_H__ */
|
Loading…
Add table
Add a link
Reference in a new issue