From 4aa7f01f137034ba7e7c59f1d6c443f24e1d22ff Mon Sep 17 00:00:00 2001 From: XMRig Date: Mon, 1 Apr 2019 23:45:23 +0700 Subject: [PATCH 01/34] v2.15.2-evo --- src/version.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/version.h b/src/version.h index c90a12fa..0f5a456a 100644 --- a/src/version.h +++ b/src/version.h @@ -28,7 +28,7 @@ #define APP_ID "xmrig" #define APP_NAME "XMRig" #define APP_DESC "XMRig CPU miner" -#define APP_VERSION "2.15.1-beta" +#define APP_VERSION "2.15.2-evo" #define APP_DOMAIN "xmrig.com" #define APP_SITE "www.xmrig.com" #define APP_COPYRIGHT "Copyright (C) 2016-2019 xmrig.com" @@ -36,7 +36,7 @@ #define APP_VER_MAJOR 2 #define APP_VER_MINOR 15 -#define APP_VER_PATCH 1 +#define APP_VER_PATCH 2 #ifdef _MSC_VER # if (_MSC_VER >= 1910) From 85ee55f309a534d97fdd402f6bb90dcf775bc857 Mon Sep 17 00:00:00 2001 From: XMRig Date: Tue, 2 Apr 2019 17:46:26 +0700 Subject: [PATCH 02/34] Fixed, big HTTP responses was truncated. --- src/base/base.cmake | 1 + src/base/net/http/HttpResponse.cpp | 76 ++++++++++++++++++++---------- src/base/tools/Baton.h | 45 ++++++++++++++++++ 3 files changed, 97 insertions(+), 25 deletions(-) create mode 100644 src/base/tools/Baton.h diff --git a/src/base/base.cmake b/src/base/base.cmake index 5f32f425..688f3ef8 100644 --- a/src/base/base.cmake +++ b/src/base/base.cmake @@ -33,6 +33,7 @@ set(HEADERS_BASE src/base/net/tools/RecvBuf.h src/base/net/tools/Storage.h src/base/tools/Arguments.h + src/base/tools/Baton.h src/base/tools/Buffer.h src/base/tools/Chrono.h src/base/tools/Handle.h diff --git a/src/base/net/http/HttpResponse.cpp b/src/base/net/http/HttpResponse.cpp index 3b88e29b..d782217b 100644 --- a/src/base/net/http/HttpResponse.cpp +++ b/src/base/net/http/HttpResponse.cpp @@ -33,6 +33,7 @@ #include "base/io/log/Log.h" #include "base/net/http/HttpContext.h" #include "base/net/http/HttpResponse.h" +#include "base/tools/Baton.h" namespace xmrig { @@ -40,6 +41,52 @@ namespace xmrig { static const char *kCRLF = "\r\n"; static const char *kUserAgent = "user-agent"; + +class WriteBaton : public Baton +{ +public: + inline WriteBaton(const std::stringstream &ss, const char *data, size_t size, HttpContext *ctx) : + m_ctx(ctx), + m_header(ss.str()) + { + req.data = this; + bufs[0].len = m_header.size(); + bufs[0].base = const_cast(m_header.c_str()); + + if (data) { + bufs[1].len = size; + bufs[1].base = new char[size]; + memcpy(bufs[1].base, data, size); + } + else { + bufs[1].base = nullptr; + bufs[1].len = 0; + } + } + + + inline ~WriteBaton() + { + if (count() == 2) { + delete [] bufs[1].base; + } + + m_ctx->close(); + } + + + inline size_t count() const { return bufs[1].base == nullptr ? 1 : 2; } + inline size_t size() const { return bufs[0].len + bufs[1].len; } + inline static void onWrite(uv_write_t *req, int) { delete reinterpret_cast(req->data); } + + + uv_buf_t bufs[2]; + +private: + HttpContext *m_ctx; + std::string m_header; +}; + } // namespace xmrig @@ -82,28 +129,9 @@ void xmrig::HttpResponse::end(const char *data, size_t size) } ss << kCRLF; - const std::string header = ss.str(); - uv_buf_t bufs[2]; - bufs[0].base = const_cast(header.c_str()); - -# ifdef _WIN32 - bufs[0].len = static_cast(header.size()); -# else - bufs[0].len = header.size(); -# endif - - if (data) { - bufs[1].base = const_cast(data); - -# ifdef _WIN32 - bufs[1].len = static_cast(size); -# else - bufs[1].len = size; -# endif - } - - HttpContext *ctx = HttpContext::get(m_id); + HttpContext *ctx = HttpContext::get(m_id); + WriteBaton *baton = new WriteBaton(ss, data, size, ctx); # ifndef APP_DEBUG if (statusCode() >= 400) @@ -128,12 +156,10 @@ void xmrig::HttpResponse::end(const char *data, size_t size) ctx->url.c_str(), err ? 31 : 32, statusCode(), - header.size() + size, + baton->size(), ctx->headers.count(kUserAgent) ? ctx->headers.at(kUserAgent).c_str() : nullptr ); } - uv_try_write(ctx->stream(), bufs, data ? 2 : 1); - - ctx->close(); + uv_write(&baton->req, ctx->stream(), baton->bufs, baton->count(), WriteBaton::onWrite); } diff --git a/src/base/tools/Baton.h b/src/base/tools/Baton.h new file mode 100644 index 00000000..7bea0af0 --- /dev/null +++ b/src/base/tools/Baton.h @@ -0,0 +1,45 @@ +/* XMRig + * Copyright 2010 Jeff Garzik + * Copyright 2012-2014 pooler + * Copyright 2014 Lucas Jones + * Copyright 2014-2016 Wolf9466 + * Copyright 2016 Jay D Dee + * Copyright 2017-2018 XMR-Stak , + * Copyright 2018-2019 SChernykh + * Copyright 2016-2019 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 XMRIG_BATON_H +#define XMRIG_BATON_H + + +namespace xmrig { + + +template +class Baton +{ +public: + inline Baton() { req.data = this; } + + T req; +}; + + +} /* namespace xmrig */ + + +#endif /* XMRIG_BATON_H */ From fa2a0b9b7911ec02c18bde7fbd875f031f449b5b Mon Sep 17 00:00:00 2001 From: XMRig Date: Fri, 5 Apr 2019 22:14:01 +0700 Subject: [PATCH 03/34] New config subsystem --- CMakeLists.txt | 13 +- src/api/Api.cpp | 19 +- src/api/Api.h | 10 +- src/api/Httpd.cpp | 14 +- src/api/Httpd.h | 10 +- src/api/v1/ApiRouter.cpp | 16 +- src/api/v1/ApiRouter.h | 6 +- src/base/base.cmake | 13 +- src/base/io/Json.cpp | 46 ++ src/base/io/Json.h | 26 ++ src/base/io/JsonChain.cpp | 201 +++++++++ src/base/io/JsonChain.h | 74 +++ src/base/io/Json_win.cpp | 2 +- src/base/kernel/Base.cpp | 283 ++++++++++++ .../ConfigWatcher.cpp => base/kernel/Base.h} | 68 +-- src/base/kernel/config/BaseConfig.cpp | 195 ++++++++ .../kernel/config/BaseConfig.h} | 54 +-- src/base/kernel/config/BaseTransform.cpp | 255 +++++++++++ src/base/kernel/config/BaseTransform.h | 123 +++++ ...{IControllerListener.h => IBaseListener.h} | 10 +- .../kernel}/interfaces/IConfig.h | 23 +- .../kernel/interfaces/IConfigTransform.h} | 29 +- .../kernel/interfaces/IJsonReader.h} | 45 +- src/base/net/stratum/Pools.cpp | 33 +- src/base/net/stratum/Pools.h | 14 - src/common/config/CommonConfig.cpp | 426 ------------------ src/common/config/ConfigLoader.cpp | 262 ----------- src/common/crypto/Algorithm.cpp | 2 +- src/core/Controller.cpp | 167 +------ src/core/Controller.h | 28 +- src/core/config/Config.cpp | 196 +++----- src/core/config/Config.h | 25 +- src/core/config/ConfigTransform.cpp | 106 +++++ src/core/config/ConfigTransform.h | 51 +++ ...onfigLoader_default.h => Config_default.h} | 9 +- ...figLoader_platform.h => Config_platform.h} | 24 +- src/net/Network.h | 4 +- 37 files changed, 1628 insertions(+), 1254 deletions(-) create mode 100644 src/base/io/JsonChain.cpp create mode 100644 src/base/io/JsonChain.h create mode 100644 src/base/kernel/Base.cpp rename src/{common/config/ConfigWatcher.cpp => base/kernel/Base.h} (62%) create mode 100644 src/base/kernel/config/BaseConfig.cpp rename src/{common/config/CommonConfig.h => base/kernel/config/BaseConfig.h} (71%) create mode 100644 src/base/kernel/config/BaseTransform.cpp create mode 100644 src/base/kernel/config/BaseTransform.h rename src/base/kernel/interfaces/{IControllerListener.h => IBaseListener.h} (88%) rename src/{common => base/kernel}/interfaces/IConfig.h (85%) rename src/{common/config/ConfigWatcher.h => base/kernel/interfaces/IConfigTransform.h} (72%) rename src/{common/config/ConfigLoader.h => base/kernel/interfaces/IJsonReader.h} (53%) delete mode 100644 src/common/config/CommonConfig.cpp delete mode 100644 src/common/config/ConfigLoader.cpp create mode 100644 src/core/config/ConfigTransform.cpp create mode 100644 src/core/config/ConfigTransform.h rename src/core/config/{ConfigLoader_default.h => Config_default.h} (94%) rename src/core/config/{ConfigLoader_platform.h => Config_platform.h} (88%) diff --git a/CMakeLists.txt b/CMakeLists.txt index c9513258..550de480 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -24,20 +24,17 @@ set(HEADERS "${HEADERS_BASE_HTTP}" src/api/interfaces/IApiListener.h src/App.h - src/common/config/CommonConfig.h - src/common/config/ConfigLoader.h - src/common/config/ConfigWatcher.h src/common/cpu/Cpu.h src/common/crypto/Algorithm.h src/common/crypto/keccak.h - src/common/interfaces/IConfig.h src/common/interfaces/ICpuInfo.h src/common/Platform.h src/common/utils/mm_malloc.h src/common/xmrig.h src/core/config/Config.h - src/core/config/ConfigLoader_default.h - src/core/config/ConfigLoader_platform.h + src/core/config/ConfigTransform.h + src/core/config/Config_default.h + src/core/config/Config_platform.h src/core/config/usage.h src/core/Controller.h src/interfaces/IJobResultListener.h @@ -84,13 +81,11 @@ set(SOURCES "${SOURCES_BASE}" "${SOURCES_BASE_HTTP}" src/App.cpp - src/common/config/CommonConfig.cpp - src/common/config/ConfigLoader.cpp - src/common/config/ConfigWatcher.cpp src/common/crypto/Algorithm.cpp src/common/crypto/keccak.cpp src/common/Platform.cpp src/core/config/Config.cpp + src/core/config/ConfigTransform.cpp src/core/Controller.cpp src/Mem.cpp src/net/Network.cpp diff --git a/src/api/Api.cpp b/src/api/Api.cpp index fc82ac9c..1b7210f6 100644 --- a/src/api/Api.cpp +++ b/src/api/Api.cpp @@ -36,6 +36,7 @@ #include "api/interfaces/IApiListener.h" #include "api/requests/HttpApiRequest.h" #include "api/v1/ApiRouter.h" +#include "base/kernel/Base.h" #include "base/tools/Buffer.h" #include "common/crypto/keccak.h" #include "core/config/Config.h" @@ -48,17 +49,17 @@ #endif -xmrig::Api::Api(Controller *controller) : +xmrig::Api::Api(Base *base) : + m_base(base), m_id(), m_workerId(), - m_controller(controller), m_httpd(nullptr) { - controller->addListener(this); + base->addListener(this); - genId(m_controller->config()->apiId()); + genId(base->config()->apiId()); - m_v1 = new ApiRouter(controller); + m_v1 = new ApiRouter(base); addListener(m_v1); } @@ -75,7 +76,7 @@ xmrig::Api::~Api() void xmrig::Api::request(const HttpRequest &req) { - HttpApiRequest request(req, m_controller->config()->http().isRestricted()); + HttpApiRequest request(req, m_base->config()->http().isRestricted()); exec(request); } @@ -83,10 +84,10 @@ void xmrig::Api::request(const HttpRequest &req) void xmrig::Api::start() { - genWorkerId(m_controller->config()->apiWorkerId()); + genWorkerId(m_base->config()->apiWorkerId()); # ifdef XMRIG_FEATURE_HTTP - m_httpd = new Httpd(m_controller); + m_httpd = new Httpd(m_base); m_httpd->start(); # endif } @@ -155,7 +156,7 @@ void xmrig::Api::genId(const String &id) uint8_t hash[200]; const size_t addrSize = sizeof(interfaces[i].phys_addr); const size_t inSize = strlen(APP_KIND) + addrSize + sizeof(uint16_t); - const uint16_t port = static_cast(m_controller->config()->http().port()); + const uint16_t port = static_cast(m_base->config()->http().port()); uint8_t *input = new uint8_t[inSize](); memcpy(input, &port, sizeof(uint16_t)); diff --git a/src/api/Api.h b/src/api/Api.h index d76e3105..9d391901 100644 --- a/src/api/Api.h +++ b/src/api/Api.h @@ -29,14 +29,14 @@ #include -#include "base/kernel/interfaces/IControllerListener.h" +#include "base/kernel/interfaces/IBaseListener.h" namespace xmrig { class ApiRouter; -class Controller; +class Base; class Httpd; class HttpRequest; class IApiListener; @@ -44,10 +44,10 @@ class IApiRequest; class String; -class Api : public IControllerListener +class Api : public IBaseListener { public: - Api(Controller *controller); + Api(Base *base); ~Api() override; inline const char *id() const { return m_id; } @@ -67,9 +67,9 @@ private: void genWorkerId(const String &id); ApiRouter *m_v1; + Base *m_base; char m_id[32]; char m_workerId[128]; - Controller *m_controller; Httpd *m_httpd; std::vector m_listeners; }; diff --git a/src/api/Httpd.cpp b/src/api/Httpd.cpp index 726f75e0..0aba6072 100644 --- a/src/api/Httpd.cpp +++ b/src/api/Httpd.cpp @@ -48,13 +48,13 @@ static size_t faviconSize = 0; } // namespace xmrig -xmrig::Httpd::Httpd(Controller *controller) : - m_controller(controller), +xmrig::Httpd::Httpd(Base *base) : + m_base(base), m_http(nullptr), m_server(nullptr), m_port(0) { - controller->addListener(this); + base->addListener(this); } @@ -65,7 +65,7 @@ xmrig::Httpd::~Httpd() bool xmrig::Httpd::start() { - const Http &config = m_controller->config()->http(); + const Http &config = m_base->config()->http(); if (!config.isEnabled()) { return true; @@ -157,7 +157,7 @@ void xmrig::Httpd::onHttpRequest(const HttpRequest &req) } if (req.method != HTTP_GET) { - if (m_controller->config()->http().isRestricted()) { + if (m_base->config()->http().isRestricted()) { return HttpApiResponse(req.id(), HTTP_STATUS_FORBIDDEN).end(); } @@ -166,13 +166,13 @@ void xmrig::Httpd::onHttpRequest(const HttpRequest &req) } } - m_controller->api()->request(req); + m_base->api()->request(req); } int xmrig::Httpd::auth(const HttpRequest &req) const { - const Http &config = m_controller->config()->http(); + const Http &config = m_base->config()->http(); if (!req.headers.count(kAuthorization)) { return config.isAuthRequired() ? HTTP_STATUS_UNAUTHORIZED : HTTP_STATUS_OK; diff --git a/src/api/Httpd.h b/src/api/Httpd.h index 99ee2e88..ae6cbfc8 100644 --- a/src/api/Httpd.h +++ b/src/api/Httpd.h @@ -29,22 +29,22 @@ #include -#include "base/kernel/interfaces/IControllerListener.h" +#include "base/kernel/interfaces/IBaseListener.h" #include "base/kernel/interfaces/IHttpListener.h" namespace xmrig { -class Controller; +class Base; class HttpServer; class TcpServer; -class Httpd : public IControllerListener, public IHttpListener +class Httpd : public IBaseListener, public IHttpListener { public: - Httpd(Controller *controller); + Httpd(Base *base); ~Httpd() override; bool start(); @@ -57,7 +57,7 @@ protected: private: int auth(const HttpRequest &req) const; - Controller *m_controller; + Base *m_base; HttpServer *m_http; TcpServer *m_server; uint16_t m_port; diff --git a/src/api/v1/ApiRouter.cpp b/src/api/v1/ApiRouter.cpp index cef4b7fc..1f3641c3 100644 --- a/src/api/v1/ApiRouter.cpp +++ b/src/api/v1/ApiRouter.cpp @@ -29,10 +29,10 @@ #include "api/interfaces/IApiRequest.h" #include "api/v1/ApiRouter.h" +#include "base/kernel/Base.h" #include "common/cpu/Cpu.h" #include "common/Platform.h" #include "core/config/Config.h" -#include "core/Controller.h" #include "interfaces/IThread.h" #include "rapidjson/document.h" #include "version.h" @@ -50,8 +50,8 @@ static inline double normalize(double d) } -xmrig::ApiRouter::ApiRouter(xmrig::Controller *controller) : - m_controller(controller) +xmrig::ApiRouter::ApiRouter(Base *base) : + m_base(base) { } @@ -79,14 +79,14 @@ void xmrig::ApiRouter::onRequest(IApiRequest &request) } request.accept(); - m_controller->config()->getJSON(request.doc()); + m_base->config()->getJSON(request.doc()); } } else if (request.method() == IApiRequest::METHOD_PUT || request.method() == IApiRequest::METHOD_POST) { if (request.url() == "/1/config") { request.accept(); - if (!m_controller->config()->reload(request.json())) { + if (!m_base->reload(request.json())) { return request.done(400); } @@ -142,9 +142,9 @@ void xmrig::ApiRouter::getMiner(rapidjson::Value &reply, rapidjson::Document &do reply.AddMember("kind", APP_KIND, allocator); reply.AddMember("ua", StringRef(Platform::userAgent()), allocator); reply.AddMember("cpu", cpu, allocator); - reply.AddMember("algo", StringRef(m_controller->config()->algorithm().name()), allocator); + reply.AddMember("algo", StringRef(m_base->config()->algorithm().shortName()), allocator); reply.AddMember("hugepages", Workers::hugePages() > 0, allocator); - reply.AddMember("donate_level", m_controller->config()->pools().donateLevel(), allocator); + reply.AddMember("donate_level", m_base->config()->pools().donateLevel(), allocator); } @@ -156,7 +156,7 @@ void xmrig::ApiRouter::getThreads(rapidjson::Value &reply, rapidjson::Document & Workers::threadsSummary(doc); - const std::vector &threads = m_controller->config()->threads(); + const std::vector &threads = m_base->config()->threads(); Value list(kArrayType); size_t i = 0; diff --git a/src/api/v1/ApiRouter.h b/src/api/v1/ApiRouter.h index 9bb99244..bdbbaea4 100644 --- a/src/api/v1/ApiRouter.h +++ b/src/api/v1/ApiRouter.h @@ -36,13 +36,13 @@ class Hashrate; namespace xmrig { -class Controller; +class Base; class ApiRouter : public xmrig::IApiListener { public: - ApiRouter(Controller *controller); + ApiRouter(Base *base); ~ApiRouter() override; protected: @@ -53,7 +53,7 @@ private: void getMiner(rapidjson::Value &reply, rapidjson::Document &doc) const; void getThreads(rapidjson::Value &reply, rapidjson::Document &doc) const; - Controller *m_controller; + Base *m_base; }; diff --git a/src/base/base.cmake b/src/base/base.cmake index 688f3ef8..04016f01 100644 --- a/src/base/base.cmake +++ b/src/base/base.cmake @@ -1,15 +1,21 @@ set(HEADERS_BASE src/base/io/Console.h src/base/io/Json.h + src/base/io/JsonChain.h src/base/io/log/backends/ConsoleLog.h src/base/io/log/backends/FileLog.h src/base/io/log/Log.h src/base/io/Watcher.h + src/base/kernel/Base.h + src/base/kernel/config/BaseConfig.h + src/base/kernel/config/BaseTransform.h src/base/kernel/Entry.h + src/base/kernel/interfaces/IBaseListener.h src/base/kernel/interfaces/IClientListener.h + src/base/kernel/interfaces/IConfig.h src/base/kernel/interfaces/IConfigListener.h + src/base/kernel/interfaces/IConfigTransform.h src/base/kernel/interfaces/IConsoleListener.h - src/base/kernel/interfaces/IControllerListener.h src/base/kernel/interfaces/IDnsListener.h src/base/kernel/interfaces/ILineListener.h src/base/kernel/interfaces/ILogBackend.h @@ -44,11 +50,15 @@ set(HEADERS_BASE set(SOURCES_BASE src/base/io/Console.cpp src/base/io/Json.cpp + src/base/io/JsonChain.cpp src/base/io/log/backends/ConsoleLog.cpp src/base/io/log/backends/FileLog.cpp src/base/io/log/Log.cpp src/base/io/Watcher.cpp + src/base/kernel/config/BaseConfig.cpp + src/base/kernel/config/BaseTransform.cpp src/base/kernel/Entry.cpp + src/base/kernel/Base.cpp src/base/kernel/Process.cpp src/base/kernel/Signals.cpp src/base/net/dns/Dns.cpp @@ -87,6 +97,7 @@ if (WITH_HTTPD) set(HEADERS_BASE_HTTP src/3rdparty/http-parser/http_parser.h src/base/kernel/interfaces/IHttpListener.h + src/base/kernel/interfaces/IJsonReader.h src/base/kernel/interfaces/ITcpServerListener.h src/base/net/http/HttpApiResponse.h src/base/net/http/HttpContext.h diff --git a/src/base/io/Json.cpp b/src/base/io/Json.cpp index b95994e4..91646453 100644 --- a/src/base/io/Json.cpp +++ b/src/base/io/Json.cpp @@ -27,6 +27,13 @@ #include "rapidjson/document.h" +namespace xmrig { + +static const rapidjson::Value kNullValue; + +} + + bool xmrig::Json::getBool(const rapidjson::Value &obj, const char *key, bool defaultValue) { auto i = obj.FindMember(key); @@ -49,6 +56,39 @@ const char *xmrig::Json::getString(const rapidjson::Value &obj, const char *key, } +const rapidjson::Value &xmrig::Json::getArray(const rapidjson::Value &obj, const char *key) +{ + auto i = obj.FindMember(key); + if (i != obj.MemberEnd() && i->value.IsArray()) { + return i->value; + } + + return kNullValue; +} + + +const rapidjson::Value &xmrig::Json::getObject(const rapidjson::Value &obj, const char *key) +{ + auto i = obj.FindMember(key); + if (i != obj.MemberEnd() && i->value.IsObject()) { + return i->value; + } + + return kNullValue; +} + + +const rapidjson::Value &xmrig::Json::getValue(const rapidjson::Value &obj, const char *key) +{ + auto i = obj.FindMember(key); + if (i != obj.MemberEnd()) { + return i->value; + } + + return kNullValue; +} + + int xmrig::Json::getInt(const rapidjson::Value &obj, const char *key, int defaultValue) { auto i = obj.FindMember(key); @@ -91,3 +131,9 @@ unsigned xmrig::Json::getUint(const rapidjson::Value &obj, const char *key, unsi return defaultValue; } + + +bool xmrig::JsonReader::isEmpty() const +{ + return !m_obj.IsObject() || m_obj.ObjectEmpty(); +} diff --git a/src/base/io/Json.h b/src/base/io/Json.h index 28dcf9a3..80fe5dc2 100644 --- a/src/base/io/Json.h +++ b/src/base/io/Json.h @@ -26,6 +26,7 @@ #define XMRIG_JSON_H +#include "base/kernel/interfaces/IJsonReader.h" #include "rapidjson/fwd.h" @@ -37,6 +38,9 @@ class Json public: static bool getBool(const rapidjson::Value &obj, const char *key, bool defaultValue = false); static const char *getString(const rapidjson::Value &obj, const char *key, const char *defaultValue = nullptr); + static const rapidjson::Value &getArray(const rapidjson::Value &obj, const char *key); + static const rapidjson::Value &getObject(const rapidjson::Value &obj, const char *key); + static const rapidjson::Value &getValue(const rapidjson::Value &obj, const char *key); static int getInt(const rapidjson::Value &obj, const char *key, int defaultValue = 0); static int64_t getInt64(const rapidjson::Value &obj, const char *key, int64_t defaultValue = 0); static uint64_t getUint64(const rapidjson::Value &obj, const char *key, uint64_t defaultValue = 0); @@ -47,6 +51,28 @@ public: }; +class JsonReader : public IJsonReader +{ +public: + inline JsonReader(const rapidjson::Value &obj) : m_obj(obj) {} + + inline bool getBool(const char *key, bool defaultValue = false) const override { return Json::getBool(m_obj, key, defaultValue); } + inline const char *getString(const char *key, const char *defaultValue = nullptr) const override { return Json::getString(m_obj, key, defaultValue); } + inline const rapidjson::Value &getArray(const char *key) const override { return Json::getArray(m_obj, key); } + inline const rapidjson::Value &getObject(const char *key) const override { return Json::getObject(m_obj, key); } + inline const rapidjson::Value &getValue(const char *key) const override { return Json::getValue(m_obj, key); } + inline int getInt(const char *key, int defaultValue = 0) const override { return Json::getInt(m_obj, key, defaultValue); } + inline int64_t getInt64(const char *key, int64_t defaultValue = 0) const override { return Json::getInt64(m_obj, key, defaultValue); } + inline uint64_t getUint64(const char *key, uint64_t defaultValue = 0) const override { return Json::getUint64(m_obj, key, defaultValue); } + inline unsigned getUint(const char *key, unsigned defaultValue = 0) const override { return Json::getUint(m_obj, key, defaultValue); } + + bool isEmpty() const override; + +private: + const rapidjson::Value &m_obj; +}; + + } /* namespace xmrig */ diff --git a/src/base/io/JsonChain.cpp b/src/base/io/JsonChain.cpp new file mode 100644 index 00000000..d65427cc --- /dev/null +++ b/src/base/io/JsonChain.cpp @@ -0,0 +1,201 @@ +/* XMRig + * Copyright 2010 Jeff Garzik + * Copyright 2012-2014 pooler + * Copyright 2014 Lucas Jones + * Copyright 2014-2016 Wolf9466 + * Copyright 2016 Jay D Dee + * Copyright 2017-2018 XMR-Stak , + * Copyright 2018-2019 SChernykh + * Copyright 2016-2019 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 "base/io/Json.h" +#include "base/io/JsonChain.h" +#include "base/io/log/Log.h" +#include "rapidjson/error/en.h" + + +namespace xmrig { + +static const rapidjson::Value kNullValue; + +} + + +xmrig::JsonChain::JsonChain() +{ +} + + +bool xmrig::JsonChain::add(rapidjson::Document &&doc) +{ + if (doc.HasParseError() || !doc.IsObject() || doc.ObjectEmpty()) { + return false; + } + + m_chain.push_back(std::move(doc)); + + return true; +} + + +bool xmrig::JsonChain::addFile(const char *fileName) +{ + using namespace rapidjson; + Document doc; + if (Json::get(fileName, doc)) { + m_fileName = fileName; + + return add(std::move(doc)); + } + + if (doc.HasParseError()) { + LOG_ERR("%s: \"%s\"", fileName, doc.GetErrorOffset(), GetParseError_En(doc.GetParseError())); + } + else { + LOG_ERR("unable to open \"%s\".", fileName); + } + + return false; +} + + +bool xmrig::JsonChain::addRaw(const char *json) +{ + using namespace rapidjson; + Document doc; + doc.Parse(json); + + return add(std::move(doc)); +} + + +bool xmrig::JsonChain::getBool(const char *key, bool defaultValue) const +{ + for (auto it = m_chain.rbegin(); it != m_chain.rend(); ++it) { + auto i = it->FindMember(key); + if (i != it->MemberEnd() && i->value.IsBool()) { + return i->value.GetBool(); + } + } + + return defaultValue; +} + + +const char *xmrig::JsonChain::getString(const char *key, const char *defaultValue) const +{ + for (auto it = m_chain.rbegin(); it != m_chain.rend(); ++it) { + auto i = it->FindMember(key); + if (i != it->MemberEnd() && i->value.IsString()) { + return i->value.GetString(); + } + } + + return defaultValue; +} + + +const rapidjson::Value &xmrig::JsonChain::getArray(const char *key) const +{ + for (auto it = m_chain.rbegin(); it != m_chain.rend(); ++it) { + auto i = it->FindMember(key); + if (i != it->MemberEnd() && i->value.IsArray()) { + return i->value; + } + } + + return kNullValue; +} + + +const rapidjson::Value &xmrig::JsonChain::getObject(const char *key) const +{ + for (auto it = m_chain.rbegin(); it != m_chain.rend(); ++it) { + auto i = it->FindMember(key); + if (i != it->MemberEnd() && i->value.IsObject()) { + return i->value; + } + } + + return kNullValue; +} + + +const rapidjson::Value &xmrig::JsonChain::getValue(const char *key) const +{ + for (auto it = m_chain.rbegin(); it != m_chain.rend(); ++it) { + auto i = it->FindMember(key); + if (i != it->MemberEnd()) { + return i->value; + } + } + + return kNullValue; +} + + +int xmrig::JsonChain::getInt(const char *key, int defaultValue) const +{ + for (auto it = m_chain.rbegin(); it != m_chain.rend(); ++it) { + auto i = it->FindMember(key); + if (i != it->MemberEnd() && i->value.IsInt()) { + return i->value.GetInt(); + } + } + + return defaultValue; +} + + +int64_t xmrig::JsonChain::getInt64(const char *key, int64_t defaultValue) const +{ + for (auto it = m_chain.rbegin(); it != m_chain.rend(); ++it) { + auto i = it->FindMember(key); + if (i != it->MemberEnd() && i->value.IsInt64()) { + return i->value.GetInt64(); + } + } + + return defaultValue; +} + + +uint64_t xmrig::JsonChain::getUint64(const char *key, uint64_t defaultValue) const +{ + for (auto it = m_chain.rbegin(); it != m_chain.rend(); ++it) { + auto i = it->FindMember(key); + if (i != it->MemberEnd() && i->value.IsUint64()) { + return i->value.GetUint64(); + } + } + + return defaultValue; +} + + +unsigned xmrig::JsonChain::getUint(const char *key, unsigned defaultValue) const +{ + for (auto it = m_chain.rbegin(); it != m_chain.rend(); ++it) { + auto i = it->FindMember(key); + if (i != it->MemberEnd() && i->value.IsUint()) { + return i->value.GetUint(); + } + } + + return defaultValue; +} diff --git a/src/base/io/JsonChain.h b/src/base/io/JsonChain.h new file mode 100644 index 00000000..dab01218 --- /dev/null +++ b/src/base/io/JsonChain.h @@ -0,0 +1,74 @@ +/* XMRig + * Copyright 2010 Jeff Garzik + * Copyright 2012-2014 pooler + * Copyright 2014 Lucas Jones + * Copyright 2014-2016 Wolf9466 + * Copyright 2016 Jay D Dee + * Copyright 2017-2018 XMR-Stak , + * Copyright 2018-2019 SChernykh + * Copyright 2016-2019 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 XMRIG_JSONCHAIN_H +#define XMRIG_JSONCHAIN_H + + +#include + + +#include "base/kernel/interfaces/IJsonReader.h" +#include "base/tools/String.h" +#include "rapidjson/document.h" + + +namespace xmrig { + + +class JsonChain : public IJsonReader +{ +public: + JsonChain(); + + bool add(rapidjson::Document &&doc); + bool addFile(const char *fileName); + bool addRaw(const char *json); + + inline const String &fileName() const { return m_fileName; } + inline size_t size() const { return m_chain.size(); } + +protected: + inline bool isEmpty() const override { return m_chain.empty(); } + + bool getBool(const char *key, bool defaultValue = false) const override; + const char *getString(const char *key, const char *defaultValue = nullptr) const override; + const rapidjson::Value &getArray(const char *key) const override; + const rapidjson::Value &getObject(const char *key) const override; + const rapidjson::Value &getValue(const char *key) const override; + int getInt(const char *key, int defaultValue = 0) const override; + int64_t getInt64(const char *key, int64_t defaultValue = 0) const override; + uint64_t getUint64(const char *key, uint64_t defaultValue = 0) const override; + unsigned getUint(const char *key, unsigned defaultValue = 0) const override; + +private: + std::vector m_chain; + String m_fileName; +}; + + +} /* namespace xmrig */ + + +#endif /* XMRIG_JSONCHAIN_H */ diff --git a/src/base/io/Json_win.cpp b/src/base/io/Json_win.cpp index 4a1c5266..58ee26b7 100644 --- a/src/base/io/Json_win.cpp +++ b/src/base/io/Json_win.cpp @@ -102,7 +102,7 @@ bool xmrig::Json::save(const char *fileName, const rapidjson::Document &doc) return false; } # elif defined(__GNUC__) - const int fd = _wopen(toUtf16(fileName).c_str(), _O_WRONLY | _O_BINARY | _O_TRUNC); + const int fd = _wopen(toUtf16(fileName).c_str(), _O_WRONLY | _O_BINARY | _O_CREAT | _O_TRUNC); if (fd == -1) { return false; } diff --git a/src/base/kernel/Base.cpp b/src/base/kernel/Base.cpp new file mode 100644 index 00000000..84152441 --- /dev/null +++ b/src/base/kernel/Base.cpp @@ -0,0 +1,283 @@ +/* XMRig + * Copyright 2010 Jeff Garzik + * Copyright 2012-2014 pooler + * Copyright 2014 Lucas Jones + * Copyright 2014-2016 Wolf9466 + * Copyright 2016 Jay D Dee + * Copyright 2017-2018 XMR-Stak , + * Copyright 2018-2019 SChernykh + * Copyright 2016-2019 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 +#include + + +#include "base/io/Json.h" +#include "base/io/JsonChain.h" +#include "base/io/log/backends/ConsoleLog.h" +#include "base/io/log/backends/FileLog.h" +#include "base/io/log/Log.h" +#include "base/io/Watcher.h" +#include "base/kernel/Base.h" +#include "base/kernel/interfaces/IBaseListener.h" +#include "base/kernel/Process.h" +#include "common/Platform.h" +#include "core/config/Config_default.h" +#include "core/config/Config.h" +#include "core/config/ConfigTransform.h" + + +#ifdef HAVE_SYSLOG_H +# include "base/io/log/backends/SysLog.h" +#endif + + +#ifdef XMRIG_FEATURE_API +# include "api/Api.h" +#endif + + +class xmrig::BasePrivate +{ +public: + inline BasePrivate(Process *process) : + api(nullptr), + config(nullptr), + process(process), + watcher(nullptr) + {} + + + inline ~BasePrivate() + { +# ifdef XMRIG_FEATURE_API + delete api; +# endif + + delete config; + delete watcher; + } + + + inline bool read(const JsonChain &chain, std::unique_ptr &config) + { + config = std::unique_ptr(new Config()); + + return config->read(chain, chain.fileName()); + } + + + inline Config *load() + { + JsonChain chain; + ConfigTransform transform; + std::unique_ptr config; + + transform.load(chain, process, transform); + + if (read(chain, config)) { + return config.release(); + } + + chain.addFile(process->location(Process::ExeLocation, "config.json")); + + if (read(chain, config)) { + return config.release(); + } + +# ifdef XMRIG_FEATURE_EMBEDDED_CONFIG + chain.addRaw(default_config); + + if (read(chain, config)) { + return config.release(); + } +# endif + + return nullptr; + } + + + inline void replace(Config *newConfig) + { + Config *previousConfig = config; + config = newConfig; + + for (IBaseListener *listener : listeners) { + listener->onConfigChanged(config, previousConfig); + } + + delete previousConfig; + } + + + Api *api; + Config *config; + Process *process; + std::vector listeners; + Watcher *watcher; +}; + + +xmrig::Base::Base(Process *process) + : d_ptr(new BasePrivate(process)) +{ +} + + +xmrig::Base::~Base() +{ + delete d_ptr; +} + + +bool xmrig::Base::isReady() const +{ + return d_ptr->config != nullptr; +} + + +int xmrig::Base::init() +{ + d_ptr->config = d_ptr->load(); + + if (!d_ptr->config) { + LOG_EMERG("No valid configuration found. Exiting."); + + return 1; + } + +# ifdef XMRIG_FEATURE_API + d_ptr->api = new Api(this); +# endif + + Platform::init(config()->userAgent()); + Platform::setProcessPriority(config()->priority()); + + if (!config()->isBackground()) { + Log::add(new ConsoleLog()); + } + + if (config()->logFile()) { + Log::add(new FileLog(config()->logFile())); + } + +# ifdef HAVE_SYSLOG_H + if (config()->isSyslog()) { + Log::add(new SysLog()); + } +# endif + + return 0; +} + + +void xmrig::Base::start() +{ +# ifdef XMRIG_FEATURE_API + api()->start(); +# endif + + if (config()->isShouldSave()) { + config()->save(); + } + + if (config()->isWatch()) { + d_ptr->watcher = new Watcher(config()->fileName(), this); + } +} + + +void xmrig::Base::stop() +{ +# ifdef XMRIG_FEATURE_API + api()->stop(); +# endif + + delete d_ptr->watcher; + d_ptr->watcher = nullptr; +} + + +xmrig::Api *xmrig::Base::api() const +{ + assert(d_ptr->api != nullptr); + + return d_ptr->api; +} + + +bool xmrig::Base::reload(const rapidjson::Value &json) +{ + JsonReader reader(json); + if (reader.isEmpty()) { + return false; + } + + Config *config = new Config(); + if (!config->read(reader, d_ptr->config->fileName())) { + delete config; + + return false; + } + + const bool saved = config->save(); + + if (config->isWatch() && d_ptr->watcher && saved) { + delete config; + + return true; + } + + d_ptr->replace(config); + + return true; +} + + +xmrig::Config *xmrig::Base::config() const +{ + assert(d_ptr->config != nullptr); + + return d_ptr->config; +} + + +void xmrig::Base::addListener(IBaseListener *listener) +{ + d_ptr->listeners.push_back(listener); +} + + +void xmrig::Base::onFileChanged(const String &fileName) +{ + LOG_WARN("\"%s\" was changed, reloading configuration", fileName.data()); + + JsonChain chain; + chain.addFile(fileName); + + Config *config = new Config(); + + if (!config->read(chain, chain.fileName())) { + LOG_ERR("reloading failed"); + + delete config; + return; + } + + d_ptr->replace(config); +} diff --git a/src/common/config/ConfigWatcher.cpp b/src/base/kernel/Base.h similarity index 62% rename from src/common/config/ConfigWatcher.cpp rename to src/base/kernel/Base.h index 1c70547e..592d3a37 100644 --- a/src/common/config/ConfigWatcher.cpp +++ b/src/base/kernel/Base.h @@ -22,42 +22,50 @@ * along with this program. If not, see . */ +#ifndef XMRIG_BASE_H +#define XMRIG_BASE_H + -#include "base/io/log/Log.h" -#include "base/io/Watcher.h" #include "base/kernel/interfaces/IConfigListener.h" -#include "common/config/ConfigLoader.h" -#include "common/config/ConfigWatcher.h" -#include "core/config/Config.h" +#include "base/kernel/interfaces/IWatcherListener.h" +#include "rapidjson/fwd.h" -xmrig::ConfigWatcher::ConfigWatcher(const String &path, IConfigListener *listener) : - m_listener(listener) +namespace xmrig { + + +class Api; +class Config; +class BasePrivate; +class IBaseListener; +class Process; + + +class Base : public IWatcherListener { - m_watcher = new Watcher(path, this); -} +public: + Base(Process *process); + ~Base() override; + + virtual bool isReady() const; + virtual int init(); + virtual void start(); + virtual void stop(); + + Api *api() const; + bool reload(const rapidjson::Value &json); + Config *config() const; + void addListener(IBaseListener *listener); + +protected: + void onFileChanged(const String &fileName) override; + +private: + BasePrivate *d_ptr; +}; -xmrig::ConfigWatcher::~ConfigWatcher() -{ - delete m_watcher; -} +} /* namespace xmrig */ - -void xmrig::ConfigWatcher::onFileChanged(const String &fileName) -{ - LOG_WARN("\"%s\" was changed, reloading configuration", fileName.data()); - - IConfig *config = Config::create(); - ConfigLoader::loadFromFile(config, fileName); - - if (!config->finalize()) { - LOG_ERR("reloading failed"); - - delete config; - return; - } - - m_listener->onNewConfig(config); -} +#endif /* XMRIG_BASE_H */ diff --git a/src/base/kernel/config/BaseConfig.cpp b/src/base/kernel/config/BaseConfig.cpp new file mode 100644 index 00000000..7284c263 --- /dev/null +++ b/src/base/kernel/config/BaseConfig.cpp @@ -0,0 +1,195 @@ +/* XMRig + * Copyright 2010 Jeff Garzik + * Copyright 2012-2014 pooler + * Copyright 2014 Lucas Jones + * Copyright 2014-2016 Wolf9466 + * Copyright 2016 Jay D Dee + * Copyright 2017-2018 XMR-Stak , + * Copyright 2018-2019 SChernykh + * Copyright 2016-2019 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 +#include +#include +#include +#include + + +#ifdef XMRIG_FEATURE_TLS +# include +#endif + + +#ifdef XMRIG_AMD_PROJECT +# if defined(__APPLE__) +# include +# else +# include "3rdparty/CL/cl.h" +# endif +#endif + + +#ifdef XMRIG_NVIDIA_PROJECT +# include "nvidia/cryptonight.h" +#endif + + +#include "base/io/Json.h" +#include "base/io/log/Log.h" +#include "base/kernel/config/BaseConfig.h" +#include "base/kernel/interfaces/IJsonReader.h" +#include "donate.h" +#include "rapidjson/document.h" +#include "rapidjson/filewritestream.h" +#include "rapidjson/prettywriter.h" +#include "version.h" + + +xmrig::BaseConfig::BaseConfig() : + m_algorithm(CRYPTONIGHT, VARIANT_AUTO), + m_autoSave(true), + m_background(false), + m_dryRun(false), + m_syslog(false), + m_upgrade(false), + m_watch(true) +{ +} + + +void xmrig::BaseConfig::printVersions() +{ + char buf[256] = { 0 }; + +# if defined(__clang__) + snprintf(buf, sizeof buf, "clang/%d.%d.%d", __clang_major__, __clang_minor__, __clang_patchlevel__); +# elif defined(__GNUC__) + snprintf(buf, sizeof buf, "gcc/%d.%d.%d", __GNUC__, __GNUC_MINOR__, __GNUC_PATCHLEVEL__); +# elif defined(_MSC_VER) + snprintf(buf, sizeof buf, "MSVC/%d", MSVC_VERSION); +# endif + + Log::print(GREEN_BOLD(" * ") WHITE_BOLD("%-13s") CYAN_BOLD("%s/%s") WHITE_BOLD(" %s"), "ABOUT", APP_NAME, APP_VERSION, buf); + +# if defined(XMRIG_AMD_PROJECT) +# if CL_VERSION_2_0 + const char *ocl = "2.0"; +# elif CL_VERSION_1_2 + const char *ocl = "1.2"; +# elif CL_VERSION_1_1 + const char *ocl = "1.1"; +# elif CL_VERSION_1_0 + const char *ocl = "1.0"; +# else + const char *ocl = "0.0"; +# endif + int length = snprintf(buf, sizeof buf, "OpenCL/%s ", ocl); +# elif defined(XMRIG_NVIDIA_PROJECT) + const int cudaVersion = cuda_get_runtime_version(); + int length = snprintf(buf, sizeof buf, "CUDA/%d.%d ", cudaVersion / 1000, cudaVersion % 100); +# else + memset(buf, 0, 16); + +# if defined(XMRIG_FEATURE_HTTP) || defined(XMRIG_FEATURE_TLS) + int length = 0; +# endif +# endif + +# if defined(XMRIG_FEATURE_TLS) && defined(OPENSSL_VERSION_TEXT) + { + constexpr const char *v = OPENSSL_VERSION_TEXT + 8; + length += snprintf(buf + length, (sizeof buf) - length, "OpenSSL/%.*s ", static_cast(strchr(v, ' ') - v), v); + } +# endif + + Log::print(GREEN_BOLD(" * ") WHITE_BOLD("%-13slibuv/%s %s"), "LIBS", uv_version_string(), buf); +} + + +bool xmrig::BaseConfig::read(const IJsonReader &reader, const char *fileName) +{ + m_fileName = fileName; + + if (reader.isEmpty()) { + return false; + } + + m_autoSave = reader.getBool("autosave", m_autoSave); + m_background = reader.getBool("background", m_background); + m_dryRun = reader.getBool("dry-run", m_dryRun); + m_syslog = reader.getBool("syslog", m_syslog); + m_watch = reader.getBool("watch", m_watch); + m_logFile = reader.getString("log-file"); + m_userAgent = reader.getString("user-agent"); + + setPrintTime(reader.getUint("print-time", 60)); + + const rapidjson::Value &api = reader.getObject("api"); + if (api.IsObject()) { + m_apiId = Json::getString(api, "id"); + m_apiWorkerId = Json::getString(api, "worker-id"); + } + +# ifdef XMRIG_DEPRECATED + if (api.IsObject() && api.HasMember("port")) { + m_upgrade = true; + m_http.load(api); + m_http.setEnabled(Json::getUint(api, "port") > 0); + m_http.setHost("0.0.0.0"); + } + else { + m_http.load(reader.getObject("http")); + } +# else + m_http.load(chain.getObject("http")); +# endif + + m_algorithm.parseAlgorithm(reader.getString("algo")); + + m_pools.load(reader.getArray("pools")); + m_pools.setDonateLevel(reader.getInt("donate-level", kDefaultDonateLevel)); + m_pools.setProxyDonate(reader.getInt("donate-over-proxy", Pools::PROXY_DONATE_AUTO)); + m_pools.setRetries(reader.getInt("retries")); + m_pools.setRetryPause(reader.getInt("retry-pause")); + + if (!m_algorithm.isValid()) { + return false; + } + + m_pools.adjust(m_algorithm); + + return m_pools.active() > 0; +} + + +bool xmrig::BaseConfig::save() +{ + if (m_fileName.isNull()) { + return false; + } + + rapidjson::Document doc; + getJSON(doc); + + if (Json::save(m_fileName, doc)) { + LOG_NOTICE("configuration saved to: \"%s\"", m_fileName.data()); + return true; + } + + return false; +} diff --git a/src/common/config/CommonConfig.h b/src/base/kernel/config/BaseConfig.h similarity index 71% rename from src/common/config/CommonConfig.h rename to src/base/kernel/config/BaseConfig.h index 55f36d0d..f0c52536 100644 --- a/src/common/config/CommonConfig.h +++ b/src/base/kernel/config/BaseConfig.h @@ -22,60 +22,54 @@ * along with this program. If not, see . */ -#ifndef XMRIG_COMMONCONFIG_H -#define XMRIG_COMMONCONFIG_H +#ifndef XMRIG_BASECONFIG_H +#define XMRIG_BASECONFIG_H +#include "base/kernel/interfaces/IConfig.h" #include "base/net/http/Http.h" #include "base/net/stratum/Pools.h" -#include "common/interfaces/IConfig.h" #include "common/xmrig.h" +struct option; + + namespace xmrig { -class CommonConfig : public IConfig +class IJsonReader; + + +class BaseConfig : public IConfig { public: - CommonConfig(); + BaseConfig(); inline bool isAutoSave() const { return m_autoSave; } inline bool isBackground() const { return m_background; } inline bool isDryRun() const { return m_dryRun; } inline bool isSyslog() const { return m_syslog; } - inline const String &apiId() const { return m_apiId; } - inline const String &apiWorkerId() const { return m_apiWorkerId; } inline const char *logFile() const { return m_logFile.data(); } inline const char *userAgent() const { return m_userAgent.data(); } inline const Http &http() const { return m_http; } inline const Pools &pools() const { return m_pools; } - inline int printTime() const { return m_printTime; } + inline const String &apiId() const { return m_apiId; } + inline const String &apiWorkerId() const { return m_apiWorkerId; } + inline uint32_t printTime() const { return m_printTime; } - inline bool isWatch() const override { return m_watch && !m_fileName.isNull(); } - inline const Algorithm &algorithm() const override { return m_algorithm; } - inline const String &fileName() const override { return m_fileName; } + inline bool isWatch() const override { return m_watch && !m_fileName.isNull(); } + inline const Algorithm &algorithm() const override { return m_algorithm; } + inline const String &fileName() const override { return m_fileName; } + inline void setFileName(const char *fileName) override { m_fileName = fileName; } + bool read(const IJsonReader &reader, const char *fileName) override; bool save() override; void printVersions(); protected: - enum State { - NoneState, - ReadyState, - ErrorState - }; - - bool finalize() override; - bool parseBoolean(int key, bool enable) override; - bool parseString(int key, const char *arg) override; - bool parseUint64(int key, uint64_t arg) override; - void parseJSON(const rapidjson::Value &json) override; - void setFileName(const char *fileName) override; - Algorithm m_algorithm; - bool m_adjusted; bool m_autoSave; bool m_background; bool m_dryRun; @@ -83,20 +77,20 @@ protected: bool m_upgrade; bool m_watch; Http m_http; - int m_printTime; Pools m_pools; - State m_state; String m_apiId; String m_apiWorkerId; String m_fileName; String m_logFile; String m_userAgent; + uint32_t m_printTime; private: - bool parseInt(int key, int arg); + inline void setPrintTime(uint32_t printTime) { if (printTime <= 3600) { m_printTime = printTime; } } }; -} /* namespace xmrig */ +} // namespace xmrig -#endif /* XMRIG_COMMONCONFIG_H */ + +#endif /* XMRIG_BASECONFIG_H */ diff --git a/src/base/kernel/config/BaseTransform.cpp b/src/base/kernel/config/BaseTransform.cpp new file mode 100644 index 00000000..c676330e --- /dev/null +++ b/src/base/kernel/config/BaseTransform.cpp @@ -0,0 +1,255 @@ +/* XMRig + * Copyright 2010 Jeff Garzik + * Copyright 2012-2014 pooler + * Copyright 2014 Lucas Jones + * Copyright 2014-2016 Wolf9466 + * Copyright 2016 Jay D Dee + * Copyright 2017-2018 XMR-Stak , + * Copyright 2018-2019 SChernykh + * Copyright 2016-2019 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 . + */ + + +#ifdef _MSC_VER +# include "getopt/getopt.h" +#else +# include +#endif + + +#include "base/kernel/config/BaseTransform.h" +#include "base/kernel/Process.h" +#include "base/io/log/Log.h" +#include "base/kernel/interfaces/IConfig.h" +#include "base/io/JsonChain.h" +#include "core/config/Config_platform.h" + + +namespace xmrig +{ + +static const char *kApi = "api"; +static const char *kHttp = "http"; +static const char *kPools = "pools"; + +} + + +xmrig::BaseTransform::BaseTransform() +{ +} + + +void xmrig::BaseTransform::load(JsonChain &chain, Process *process, IConfigTransform &transform) +{ + using namespace rapidjson; + + int key; + int argc = process->arguments().argc(); + char **argv = process->arguments().argv(); + + Document doc(kObjectType); + + while (1) { + key = getopt_long(argc, argv, short_options, options, nullptr); + if (key < 0) { + break; + } + + if (key == IConfig::ConfigKey) { + chain.add(std::move(doc)); + chain.addFile(optarg); + + doc = Document(kObjectType); + } + else { + transform.transform(doc, key, optarg); + } + } + + if (optind < argc) { + LOG_WARN("%s: unsupported non-option argument '%s'", argv[0], argv[optind]); + } + + chain.add(std::move(doc)); +} + + +void xmrig::BaseTransform::transform(rapidjson::Document &doc, int key, const char *arg) +{ + switch (key) { + case IConfig::AlgorithmKey: /* --algo */ + return set(doc, "algo", arg); + + case IConfig::UserpassKey: /* --userpass */ + return add(doc, kPools, "userpass", arg); + + case IConfig::UrlKey: /* --url */ + return add(doc, kPools, "url", arg, true); + + case IConfig::UserKey: /* --user */ + return add(doc, kPools, "user", arg); + + case IConfig::PasswordKey: /* --pass */ + return add(doc, kPools, "pass", arg); + + case IConfig::RigIdKey: /* --rig-id */ + return add(doc, kPools, "rig-id", arg); + + case IConfig::FingerprintKey: /* --tls-fingerprint */ + return add(doc, kPools, "tls-fingerprint", arg); + + case IConfig::VariantKey: /* --variant */ + return add(doc, kPools, "variant", arg); + + case IConfig::LogFileKey: /* --log-file */ + return set(doc, "log-file", arg); + +# ifdef XMRIG_DEPRECATED + case IConfig::ApiAccessTokenKey: /* --api-access-token */ + fputs("option \"--api-access-token\" deprecated, use \"--http-access-token\" instead.\n", stderr); + fflush(stdout); + return set(doc, kHttp, "access-token", arg); +# endif + + case IConfig::HttpAccessTokenKey: /* --http-access-token */ + return set(doc, kHttp, "access-token", arg); + + case IConfig::HttpHostKey: /* --http-host */ + return set(doc, kHttp, "host", arg); + + case IConfig::ApiWorkerIdKey: /* --api-worker-id */ + return set(doc, kApi, "worker-id", arg); + + case IConfig::ApiIdKey: /* --api-id */ + return set(doc, kApi, "id", arg); + + case IConfig::UserAgentKey: /* --user-agent */ + return set(doc, "user-agent", arg); + + case IConfig::RetriesKey: /* --retries */ + case IConfig::RetryPauseKey: /* --retry-pause */ + case IConfig::PrintTimeKey: /* --print-time */ + case IConfig::HttpPort: /* --http-port */ + case IConfig::DonateLevelKey: /* --donate-level */ +# ifdef XMRIG_DEPRECATED + case IConfig::ApiPort: /* --api-port */ +# endif + return transformUint64(doc, key, static_cast(strtol(arg, nullptr, 10))); + + case IConfig::BackgroundKey: /* --background */ + case IConfig::SyslogKey: /* --syslog */ + case IConfig::KeepAliveKey: /* --keepalive */ + case IConfig::NicehashKey: /* --nicehash */ + case IConfig::TlsKey: /* --tls */ + case IConfig::DryRunKey: /* --dry-run */ + case IConfig::HttpEnabledKey: /* --http-enabled */ + return transformBoolean(doc, key, true); + + case IConfig::ColorKey: /* --no-color */ + case IConfig::HttpRestrictedKey: /* --http-no-restricted */ +# ifdef XMRIG_DEPRECATED + case IConfig::ApiRestrictedKey: /* --api-no-restricted */ + case IConfig::ApiIPv6Key: /* --api-ipv6 */ +# endif + return transformBoolean(doc, key, false); + + default: + break; + } +} + + +void xmrig::BaseTransform::transformBoolean(rapidjson::Document &doc, int key, bool enable) +{ + switch (key) { + case IConfig::BackgroundKey: /* --background */ + return set(doc, "background", enable); + + case IConfig::SyslogKey: /* --syslog */ + return set(doc, "syslog", enable); + + case IConfig::KeepAliveKey: /* --keepalive */ + return add(doc, kPools, "keepalive", enable); + + case IConfig::TlsKey: /* --tls */ + return add(doc, kPools, "tls", enable); + +# ifndef XMRIG_PROXY_PROJECT + case IConfig::NicehashKey: /* --nicehash */ + return add(doc, kPools, "nicehash", enable); +# endif + + case IConfig::ColorKey: /* --no-color */ + return set(doc, "colors", enable); + +# ifdef XMRIG_DEPRECATED + case IConfig::ApiIPv6Key: /* --api-ipv6 */ + break; + + case IConfig::ApiRestrictedKey: /* --api-no-restricted */ + fputs("option \"--api-no-restricted\" deprecated, use \"--http-no-restricted\" instead.\n", stderr); + fflush(stdout); + return set(doc, kHttp, "restricted", enable); +# endif + + case IConfig::HttpRestrictedKey: /* --http-no-restricted */ + return set(doc, kHttp, "restricted", enable); + + case IConfig::HttpEnabledKey: /* --http-enabled */ + return set(doc, kHttp, "enabled", enable); + + case IConfig::DryRunKey: /* --dry-run */ + return set(doc, "dry-run", enable); + + default: + break; + } +} + + +void xmrig::BaseTransform::transformUint64(rapidjson::Document &doc, int key, uint64_t arg) +{ + switch (key) { + case IConfig::RetriesKey: /* --retries */ + return set(doc, "retries", arg); + + case IConfig::RetryPauseKey: /* --retry-pause */ + return set(doc, "retry-pause", arg); + + case IConfig::DonateLevelKey: /* --donate-level */ + return set(doc, "donate-level", arg); + + case IConfig::ProxyDonateKey: /* --donate-over-proxy */ + return set(doc, "donate-over-proxy", arg); + +# ifdef XMRIG_DEPRECATED + case IConfig::ApiPort: /* --api-port */ + fputs("option \"--api-port\" deprecated, use \"--http-port\" instead.\n", stderr); + fflush(stdout); + return set(doc, kHttp, "port", arg); +# endif + + case IConfig::HttpPort: /* --http-port */ + return set(doc, kHttp, "port", arg); + + case IConfig::PrintTimeKey: /* --print-time */ + return set(doc, "print-time", arg); + + default: + break; + } +} diff --git a/src/base/kernel/config/BaseTransform.h b/src/base/kernel/config/BaseTransform.h new file mode 100644 index 00000000..3952e22b --- /dev/null +++ b/src/base/kernel/config/BaseTransform.h @@ -0,0 +1,123 @@ +/* XMRig + * Copyright 2010 Jeff Garzik + * Copyright 2012-2014 pooler + * Copyright 2014 Lucas Jones + * Copyright 2014-2016 Wolf9466 + * Copyright 2016 Jay D Dee + * Copyright 2017-2018 XMR-Stak , + * Copyright 2018-2019 SChernykh + * Copyright 2016-2019 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 XMRIG_BASETRANSFORM_H +#define XMRIG_BASETRANSFORM_H + + +#include "base/kernel/interfaces/IConfigTransform.h" +#include "rapidjson/document.h" + + +struct option; + + +namespace xmrig { + + +class IConfigTransform; +class JsonChain; +class Process; + + +class BaseTransform : public IConfigTransform +{ +public: + BaseTransform(); + + static void load(JsonChain &chain, Process *process, IConfigTransform &transform); + +protected: + void transform(rapidjson::Document &doc, int key, const char *arg) override; + + + template + inline void set(rapidjson::Document &doc, const char *key, T value) { set(doc, doc, key, value); } + + + template + inline void set(rapidjson::Document &doc, const char *objKey, const char *key, T value) + { + if (!doc.HasMember(objKey)) { + doc.AddMember(rapidjson::StringRef(objKey), rapidjson::kObjectType, doc.GetAllocator()); + } + + set(doc, doc[objKey], key, value); + } + + + template + inline void add(rapidjson::Document &doc, const char *arrayKey, const char *key, T value, bool force = false) + { + auto &allocator = doc.GetAllocator(); + + if (!doc.HasMember(arrayKey)) { + doc.AddMember(rapidjson::StringRef(arrayKey), rapidjson::kArrayType, allocator); + } + + rapidjson::Value &array = doc[arrayKey]; + if (force || array.Size() == 0) { + array.PushBack(rapidjson::kObjectType, allocator); + } + + set(doc, array[array.Size() - 1], key, value); + } + + + template + inline void set(rapidjson::Document &doc, rapidjson::Value &obj, const char *key, T value) + { + if (obj.HasMember(key)) { + obj[key] = value; + } + else { + obj.AddMember(rapidjson::StringRef(key), value, doc.GetAllocator()); + } + } + + +private: + void transformBoolean(rapidjson::Document &doc, int key, bool enable); + void transformUint64(rapidjson::Document &doc, int key, uint64_t arg); +}; + + +template<> +inline void BaseTransform::set(rapidjson::Document &doc, rapidjson::Value &obj, const char *key, const char *value) +{ + auto &allocator = doc.GetAllocator(); + + if (obj.HasMember(key)) { + obj[key] = rapidjson::Value(value, allocator); + } + else { + obj.AddMember(rapidjson::StringRef(key), rapidjson::Value(value, allocator), allocator); + } +} + + +} // namespace xmrig + + +#endif /* XMRIG_BASETRANSFORM_H */ diff --git a/src/base/kernel/interfaces/IControllerListener.h b/src/base/kernel/interfaces/IBaseListener.h similarity index 88% rename from src/base/kernel/interfaces/IControllerListener.h rename to src/base/kernel/interfaces/IBaseListener.h index c6157408..1f212369 100644 --- a/src/base/kernel/interfaces/IControllerListener.h +++ b/src/base/kernel/interfaces/IBaseListener.h @@ -22,8 +22,8 @@ * along with this program. If not, see . */ -#ifndef XMRIG_ICONTROLLERLISTENER_H -#define XMRIG_ICONTROLLERLISTENER_H +#ifndef XMRIG_IBASELISTENER_H +#define XMRIG_IBASELISTENER_H namespace xmrig { @@ -32,10 +32,10 @@ namespace xmrig { class Config; -class IControllerListener +class IBaseListener { public: - virtual ~IControllerListener() = default; + virtual ~IBaseListener() = default; virtual void onConfigChanged(Config *config, Config *previousConfig) = 0; }; @@ -44,4 +44,4 @@ public: } /* namespace xmrig */ -#endif // XMRIG_ICONTROLLERLISTENER_H +#endif // XMRIG_IBASELISTENER_H diff --git a/src/common/interfaces/IConfig.h b/src/base/kernel/interfaces/IConfig.h similarity index 85% rename from src/common/interfaces/IConfig.h rename to src/base/kernel/interfaces/IConfig.h index 071b3478..44628129 100644 --- a/src/common/interfaces/IConfig.h +++ b/src/base/kernel/interfaces/IConfig.h @@ -33,6 +33,7 @@ namespace xmrig { +class IJsonReader; class String; @@ -66,10 +67,8 @@ public: UserpassKey = 'O', VariantKey = 1010, VerboseKey = 1100, - WatchKey = 1105, TlsKey = 1013, FingerprintKey = 1014, - AutoSaveKey = 1016, ProxyDonateKey = 1017, # ifdef XMRIG_DEPRECATED @@ -92,7 +91,7 @@ public: MaxCPUUsageKey = 1004, SafeKey = 1005, ThreadsKey = 't', - HardwareAESKey = 1011, +// HardwareAESKey = 1011, AssemblyKey = 1015, // xmrig amd @@ -141,17 +140,13 @@ public: virtual ~IConfig() = default; - virtual bool finalize() = 0; - virtual bool isWatch() const = 0; - virtual bool parseBoolean(int key, bool enable) = 0; - virtual bool parseString(int key, const char *arg) = 0; - virtual bool parseUint64(int key, uint64_t arg) = 0; - virtual bool save() = 0; - virtual const Algorithm &algorithm() const = 0; - virtual const String &fileName() const = 0; - virtual void getJSON(rapidjson::Document &doc) const = 0; - virtual void parseJSON(const rapidjson::Value &json) = 0; - virtual void setFileName(const char *fileName) = 0; + virtual bool isWatch() const = 0; + virtual bool read(const IJsonReader &reader, const char *fileName) = 0; + virtual bool save() = 0; + virtual const Algorithm &algorithm() const = 0; + virtual const String &fileName() const = 0; + virtual void getJSON(rapidjson::Document &doc) const = 0; + virtual void setFileName(const char *fileName) = 0; }; diff --git a/src/common/config/ConfigWatcher.h b/src/base/kernel/interfaces/IConfigTransform.h similarity index 72% rename from src/common/config/ConfigWatcher.h rename to src/base/kernel/interfaces/IConfigTransform.h index 77b41cf5..37ceaba1 100644 --- a/src/common/config/ConfigWatcher.h +++ b/src/base/kernel/interfaces/IConfigTransform.h @@ -22,40 +22,31 @@ * along with this program. If not, see . */ -#ifndef XMRIG_CONFIGWATCHER_H -#define XMRIG_CONFIGWATCHER_H +#ifndef XMRIG_ICONFIGTRANSFORM_H +#define XMRIG_ICONFIGTRANSFORM_H -#include "base/kernel/interfaces/IWatcherListener.h" -#include "base/tools/String.h" +#include "common/crypto/Algorithm.h" #include "rapidjson/fwd.h" -struct option; - - namespace xmrig { -class IConfigListener; -class Watcher; +class IJsonReader; +class String; -class ConfigWatcher : public IWatcherListener +class IConfigTransform { public: - ConfigWatcher(const String &path, IConfigListener *listener); - ~ConfigWatcher() override; + virtual ~IConfigTransform() = default; -protected: - void onFileChanged(const String &fileName) override; - -private: - IConfigListener *m_listener; - Watcher *m_watcher; + virtual void transform(rapidjson::Document &doc, int key, const char *arg) = 0; }; } /* namespace xmrig */ -#endif /* __CONFIGWATCHER_H__ */ + +#endif // XMRIG_ICONFIGTRANSFORM_H diff --git a/src/common/config/ConfigLoader.h b/src/base/kernel/interfaces/IJsonReader.h similarity index 53% rename from src/common/config/ConfigLoader.h rename to src/base/kernel/interfaces/IJsonReader.h index f03de711..c0fe09cb 100644 --- a/src/common/config/ConfigLoader.h +++ b/src/base/kernel/interfaces/IJsonReader.h @@ -22,50 +22,35 @@ * along with this program. If not, see . */ -#ifndef XMRIG_CONFIGLOADER_H -#define XMRIG_CONFIGLOADER_H - - -#include +#ifndef XMRIG_IJSONREADER_H +#define XMRIG_IJSONREADER_H #include "rapidjson/fwd.h" -struct option; - - namespace xmrig { -class ConfigWatcher; -class IConfigListener; -class IConfig; -class Process; - - -class ConfigLoader +class IJsonReader { public: - static bool loadFromFile(IConfig *config, const char *fileName); - static bool loadFromJSON(IConfig *config, const char *json); - static bool loadFromJSON(IConfig *config, const rapidjson::Value &json); - static bool reload(IConfig *oldConfig, const rapidjson::Value &json); - static bool watch(IConfig *config); - static IConfig *load(Process *process, IConfigListener *listener); - static void release(); + virtual ~IJsonReader() = default; -private: - static bool getJSON(const char *fileName, rapidjson::Document &doc); - static bool parseArg(IConfig *config, int key, const char *arg); - static void parseJSON(IConfig *config, const struct option *option, const rapidjson::Value &object); - - static ConfigWatcher *m_watcher; - static IConfigListener *m_listener; + virtual bool getBool(const char *key, bool defaultValue = false) const = 0; + virtual bool isEmpty() const = 0; + virtual const char *getString(const char *key, const char *defaultValue = nullptr) const = 0; + virtual const rapidjson::Value &getArray(const char *key) const = 0; + virtual const rapidjson::Value &getObject(const char *key) const = 0; + virtual const rapidjson::Value &getValue(const char *key) const = 0; + virtual int getInt(const char *key, int defaultValue = 0) const = 0; + virtual int64_t getInt64(const char *key, int64_t defaultValue = 0) const = 0; + virtual uint64_t getUint64(const char *key, uint64_t defaultValue = 0) const = 0; + virtual unsigned getUint(const char *key, unsigned defaultValue = 0) const = 0; }; } /* namespace xmrig */ -#endif /* XMRIG_CONFIGLOADER_H */ +#endif // XMRIG_IJSONREADER_H diff --git a/src/base/net/stratum/Pools.cpp b/src/base/net/stratum/Pools.cpp index 63102c00..638ba5ea 100644 --- a/src/base/net/stratum/Pools.cpp +++ b/src/base/net/stratum/Pools.cpp @@ -44,16 +44,6 @@ xmrig::Pools::Pools() : } -xmrig::Pool &xmrig::Pools::current() -{ - if (m_data.empty()) { - m_data.push_back(Pool()); - } - - return m_data.back(); -} - - bool xmrig::Pools::isEqual(const Pools &other) const { if (m_data.size() != other.m_data.size() || m_retries != other.m_retries || m_retryPause != other.m_retryPause) { @@ -64,25 +54,6 @@ bool xmrig::Pools::isEqual(const Pools &other) const } -bool xmrig::Pools::setUrl(const char *url) -{ - if (m_data.empty() || m_data.back().isValid()) { - Pool pool(url); - - if (pool.isValid()) { - m_data.push_back(std::move(pool)); - return true; - } - - return false; - } - - current().parse(url); - - return m_data.back().isValid(); -} - - xmrig::IStrategy *xmrig::Pools::createStrategy(IStrategyListener *listener) const { if (active() == 1) { @@ -144,6 +115,10 @@ void xmrig::Pools::load(const rapidjson::Value &pools) { m_data.clear(); + if (!pools.IsArray()) { + return; + } + for (const rapidjson::Value &value : pools.GetArray()) { if (!value.IsObject()) { continue; diff --git a/src/base/net/stratum/Pools.h b/src/base/net/stratum/Pools.h index f563f243..6a63f166 100644 --- a/src/base/net/stratum/Pools.h +++ b/src/base/net/stratum/Pools.h @@ -50,28 +50,16 @@ public: Pools(); - inline bool setUserpass(const char *userpass) { return current().setUserpass(userpass); } inline const std::vector &data() const { return m_data; } inline int donateLevel() const { return m_donateLevel; } inline int retries() const { return m_retries; } inline int retryPause() const { return m_retryPause; } inline ProxyDonate proxyDonate() const { return m_proxyDonate; } - inline void setFingerprint(const char *fingerprint) { current().setFingerprint(fingerprint); } - inline void setKeepAlive(bool enable) { current().setKeepAlive(enable); } - inline void setKeepAlive(int keepAlive) { current().setKeepAlive(keepAlive); } - inline void setNicehash(bool enable) { current().setNicehash(enable); } - inline void setPassword(const char *password) { current().setPassword(password); } - inline void setRigId(const char *rigId) { current().setRigId(rigId); } - inline void setTLS(bool enable) { current().setTLS(enable); } - inline void setUser(const char *user) { current().setUser(user); } - inline void setVariant(const char *variant) { current().algorithm().parseVariant(variant); } - inline void setVariant(int variant) { current().algorithm().parseVariant(variant); } inline bool operator!=(const Pools &other) const { return !isEqual(other); } inline bool operator==(const Pools &other) const { return isEqual(other); } bool isEqual(const Pools &other) const; - bool setUrl(const char *url); IStrategy *createStrategy(IStrategyListener *listener) const; rapidjson::Value toJSON(rapidjson::Document &doc) const; size_t active() const; @@ -84,8 +72,6 @@ public: void setRetryPause(int retryPause); private: - Pool ¤t(); - int m_donateLevel; int m_retries; int m_retryPause; diff --git a/src/common/config/CommonConfig.cpp b/src/common/config/CommonConfig.cpp deleted file mode 100644 index b0b716c1..00000000 --- a/src/common/config/CommonConfig.cpp +++ /dev/null @@ -1,426 +0,0 @@ -/* XMRig - * Copyright 2010 Jeff Garzik - * Copyright 2012-2014 pooler - * Copyright 2014 Lucas Jones - * Copyright 2014-2016 Wolf9466 - * Copyright 2016 Jay D Dee - * Copyright 2017-2018 XMR-Stak , - * Copyright 2018-2019 SChernykh - * Copyright 2016-2019 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 -#include -#include -#include -#include - - -#ifdef XMRIG_FEATURE_TLS -# include -#endif - - -#ifdef XMRIG_AMD_PROJECT -# if defined(__APPLE__) -# include -# else -# include "3rdparty/CL/cl.h" -# endif -#endif - - -#ifdef XMRIG_NVIDIA_PROJECT -# include "nvidia/cryptonight.h" -#endif - - -#include "base/io/Json.h" -#include "base/io/log/Log.h" -#include "common/config/CommonConfig.h" -#include "rapidjson/document.h" -#include "rapidjson/filewritestream.h" -#include "rapidjson/prettywriter.h" -#include "version.h" - - -xmrig::CommonConfig::CommonConfig() : - m_algorithm(CRYPTONIGHT, VARIANT_AUTO), - m_adjusted(false), - m_autoSave(true), - m_background(false), - m_dryRun(false), - m_syslog(false), - m_upgrade(false), - m_watch(true), - m_printTime(60), - m_state(NoneState) -{ -} - - -void xmrig::CommonConfig::printVersions() -{ - char buf[256] = { 0 }; - -# if defined(__clang__) - snprintf(buf, sizeof buf, "clang/%d.%d.%d", __clang_major__, __clang_minor__, __clang_patchlevel__); -# elif defined(__GNUC__) - snprintf(buf, sizeof buf, "gcc/%d.%d.%d", __GNUC__, __GNUC_MINOR__, __GNUC_PATCHLEVEL__); -# elif defined(_MSC_VER) - snprintf(buf, sizeof buf, "MSVC/%d", MSVC_VERSION); -# endif - - Log::print(GREEN_BOLD(" * ") WHITE_BOLD("%-13s") CYAN_BOLD("%s/%s") WHITE_BOLD(" %s"), "ABOUT", APP_NAME, APP_VERSION, buf); - -# if defined(XMRIG_AMD_PROJECT) -# if CL_VERSION_2_0 - const char *ocl = "2.0"; -# elif CL_VERSION_1_2 - const char *ocl = "1.2"; -# elif CL_VERSION_1_1 - const char *ocl = "1.1"; -# elif CL_VERSION_1_0 - const char *ocl = "1.0"; -# else - const char *ocl = "0.0"; -# endif - int length = snprintf(buf, sizeof buf, "OpenCL/%s ", ocl); -# elif defined(XMRIG_NVIDIA_PROJECT) - const int cudaVersion = cuda_get_runtime_version(); - int length = snprintf(buf, sizeof buf, "CUDA/%d.%d ", cudaVersion / 1000, cudaVersion % 100); -# else - memset(buf, 0, 16); - -# if defined(XMRIG_FEATURE_HTTP) || defined(XMRIG_FEATURE_TLS) - int length = 0; -# endif -# endif - -# if defined(XMRIG_FEATURE_TLS) && defined(OPENSSL_VERSION_TEXT) - { - constexpr const char *v = OPENSSL_VERSION_TEXT + 8; - length += snprintf(buf + length, (sizeof buf) - length, "OpenSSL/%.*s ", static_cast(strchr(v, ' ') - v), v); - } -# endif - - Log::print(GREEN_BOLD(" * ") WHITE_BOLD("%-13slibuv/%s %s"), "LIBS", uv_version_string(), buf); -} - - -bool xmrig::CommonConfig::save() -{ - if (m_fileName.isNull()) { - return false; - } - - rapidjson::Document doc; - getJSON(doc); - - if (Json::save(m_fileName, doc)) { - LOG_NOTICE("configuration saved to: \"%s\"", m_fileName.data()); - return true; - } - - return false; -} - - -bool xmrig::CommonConfig::finalize() -{ - if (m_state == ReadyState) { - return true; - } - - if (m_state == ErrorState) { - return false; - } - - if (!m_algorithm.isValid()) { - return false; - } - - m_pools.adjust(m_algorithm); - - if (!m_pools.active()) { - m_state = ErrorState; - return false; - } - - m_state = ReadyState; - return true; -} - - -bool xmrig::CommonConfig::parseBoolean(int key, bool enable) -{ - switch (key) { - case BackgroundKey: /* --background */ - m_background = enable; - break; - - case SyslogKey: /* --syslog */ - m_syslog = enable; - break; - - case KeepAliveKey: /* --keepalive */ - m_pools.setKeepAlive(enable); - break; - - case TlsKey: /* --tls */ - m_pools.setTLS(enable); - break; - -# ifndef XMRIG_PROXY_PROJECT - case NicehashKey: /* --nicehash */ - m_pools.setNicehash(enable); - break; -# endif - - case ColorKey: /* --no-color */ - Log::colors = enable; - break; - - case WatchKey: /* watch */ - m_watch = enable; - break; - -# ifdef XMRIG_DEPRECATED - case ApiIPv6Key: /* --api-ipv6 */ - break; - - case ApiRestrictedKey: /* --api-no-restricted */ - fputs("option \"--api-no-restricted\" deprecated, use \"--http-no-restricted\" instead.\n", stderr); - fflush(stdout); - m_http.setRestricted(enable); - break; -# endif - - case HttpRestrictedKey: /* --http-no-restricted */ - m_http.setRestricted(enable); - break; - - case HttpEnabledKey: /* --http-enabled */ - m_http.setEnabled(enable); - break; - - case DryRunKey: /* --dry-run */ - m_dryRun = enable; - break; - - case AutoSaveKey: - m_autoSave = enable; - break; - - default: - break; - } - - return true; -} - - -bool xmrig::CommonConfig::parseString(int key, const char *arg) -{ - switch (key) { - case AlgorithmKey: /* --algo */ - m_algorithm.parseAlgorithm(arg); - break; - - case UserpassKey: /* --userpass */ - return m_pools.setUserpass(arg); - - case UrlKey: /* --url */ - return m_pools.setUrl(arg); - - case UserKey: /* --user */ - m_pools.setUser(arg); - break; - - case PasswordKey: /* --pass */ - m_pools.setPassword(arg); - break; - - case RigIdKey: /* --rig-id */ - m_pools.setRigId(arg); - break; - - case FingerprintKey: /* --tls-fingerprint */ - m_pools.setFingerprint(arg); - break; - - case VariantKey: /* --variant */ - m_pools.setVariant(arg); - break; - - case LogFileKey: /* --log-file */ - m_logFile = arg; - break; - -# ifdef XMRIG_DEPRECATED - case ApiAccessTokenKey: /* --api-access-token */ - fputs("option \"--api-access-token\" deprecated, use \"--http-access-token\" instead.\n", stderr); - fflush(stdout); - m_http.setToken(arg); - break; -# endif - - case HttpAccessTokenKey: /* --http-access-token */ - m_http.setToken(arg); - break; - - case HttpHostKey: /* --http-host */ - m_http.setHost(arg); - break; - - case ApiWorkerIdKey: /* --api-worker-id */ - m_apiWorkerId = arg; - break; - - case ApiIdKey: /* --api-id */ - m_apiId = arg; - break; - - case UserAgentKey: /* --user-agent */ - m_userAgent = arg; - break; - - case RetriesKey: /* --retries */ - case RetryPauseKey: /* --retry-pause */ - case PrintTimeKey: /* --print-time */ - case HttpPort: /* --http-port */ -# ifdef XMRIG_DEPRECATED - case ApiPort: /* --api-port */ -# endif - return parseUint64(key, static_cast(strtol(arg, nullptr, 10))); - - case BackgroundKey: /* --background */ - case SyslogKey: /* --syslog */ - case KeepAliveKey: /* --keepalive */ - case NicehashKey: /* --nicehash */ - case TlsKey: /* --tls */ - case DryRunKey: /* --dry-run */ - case HttpEnabledKey: /* --http-enabled */ - return parseBoolean(key, true); - - case ColorKey: /* --no-color */ - case WatchKey: /* --no-watch */ - case HttpRestrictedKey: /* --http-no-restricted */ -# ifdef XMRIG_DEPRECATED - case ApiRestrictedKey: /* --api-no-restricted */ - case ApiIPv6Key: /* --api-ipv6 */ -# endif - return parseBoolean(key, false); - - case DonateLevelKey: /* --donate-level */ - return parseUint64(key, static_cast(strtol(arg, nullptr, 10))); - - default: - break; - } - - return true; -} - - -bool xmrig::CommonConfig::parseUint64(int key, uint64_t arg) -{ - return parseInt(key, static_cast(arg)); -} - - -void xmrig::CommonConfig::parseJSON(const rapidjson::Value &json) -{ - const rapidjson::Value &pools = json["pools"]; - if (pools.IsArray()) { - m_pools.load(pools); - } - -# ifdef XMRIG_DEPRECATED - const rapidjson::Value &api = json["api"]; - if (api.IsObject() && api.HasMember("port")) { - m_upgrade = true; - m_http.load(api); - m_http.setEnabled(Json::getUint(api, "port") > 0); - m_http.setHost("0.0.0.0"); - } - else { - m_http.load(json["http"]); - } -# else - m_http.load(doc["http"]); -# endif -} - - -void xmrig::CommonConfig::setFileName(const char *fileName) -{ - m_fileName = fileName; -} - - -bool xmrig::CommonConfig::parseInt(int key, int arg) -{ - switch (key) { - case RetriesKey: /* --retries */ - m_pools.setRetries(arg); - break; - - case RetryPauseKey: /* --retry-pause */ - m_pools.setRetryPause(arg); - break; - - case KeepAliveKey: /* --keepalive */ - m_pools.setKeepAlive(arg); - break; - - case VariantKey: /* --variant */ - m_pools.setVariant(arg); - break; - - case DonateLevelKey: /* --donate-level */ - m_pools.setDonateLevel(arg); - break; - - case ProxyDonateKey: /* --donate-over-proxy */ - m_pools.setProxyDonate(arg); - break; - -# ifdef XMRIG_DEPRECATED - case ApiPort: /* --api-port */ - fputs("option \"--api-port\" deprecated, use \"--http-port\" instead.\n", stderr); - fflush(stdout); - m_http.setPort(arg); - break; -# endif - - case HttpPort: /* --http-port */ - m_http.setPort(arg); - break; - - case PrintTimeKey: /* --print-time */ - if (arg >= 0 && arg <= 3600) { - m_printTime = arg; - } - break; - - default: - break; - } - - return true; -} diff --git a/src/common/config/ConfigLoader.cpp b/src/common/config/ConfigLoader.cpp deleted file mode 100644 index 2b7f50ce..00000000 --- a/src/common/config/ConfigLoader.cpp +++ /dev/null @@ -1,262 +0,0 @@ -/* XMRig - * Copyright 2010 Jeff Garzik - * Copyright 2012-2014 pooler - * Copyright 2014 Lucas Jones - * Copyright 2014-2016 Wolf9466 - * Copyright 2016 Jay D Dee - * Copyright 2017-2018 XMR-Stak , - * Copyright 2018-2019 SChernykh - * Copyright 2016-2019 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 -#include -#include -#include - - -#include "base/io/Json.h" -#include "base/kernel/interfaces/IConfigListener.h" -#include "base/kernel/Process.h" -#include "common/config/ConfigLoader.h" -#include "common/config/ConfigWatcher.h" -#include "common/interfaces/IConfig.h" -#include "common/Platform.h" -#include "core/config/Config.h" -#include "core/config/ConfigLoader_platform.h" -#include "rapidjson/document.h" -#include "rapidjson/error/en.h" -#include "rapidjson/fwd.h" - - -#ifdef XMRIG_FEATURE_EMBEDDED_CONFIG -# include "core/config/ConfigLoader_default.h" -#endif - - -namespace xmrig { - -ConfigWatcher *ConfigLoader::m_watcher = nullptr; -IConfigListener *ConfigLoader::m_listener = nullptr; - -} // namespace xmrig - - -#ifndef ARRAY_SIZE -# define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0])) -#endif - - -bool xmrig::ConfigLoader::loadFromFile(xmrig::IConfig *config, const char *fileName) -{ - rapidjson::Document doc; - if (!getJSON(fileName, doc)) { - return false; - } - - config->setFileName(fileName); - - return loadFromJSON(config, doc); -} - - -bool xmrig::ConfigLoader::loadFromJSON(xmrig::IConfig *config, const char *json) -{ - using namespace rapidjson; - Document doc; - doc.Parse(json); - - if (doc.HasParseError() || !doc.IsObject()) { - return false; - } - - return loadFromJSON(config, doc); -} - - -bool xmrig::ConfigLoader::loadFromJSON(xmrig::IConfig *config, const rapidjson::Value &json) -{ - for (size_t i = 0; i < ARRAY_SIZE(config_options); i++) { - parseJSON(config, &config_options[i], json); - } - - const rapidjson::Value &api = json["api"]; - if (api.IsObject()) { - for (size_t i = 0; i < ARRAY_SIZE(api_options); i++) { - parseJSON(config, &api_options[i], api); - } - } - - config->parseJSON(json); - - return config->finalize(); -} - - -bool xmrig::ConfigLoader::reload(xmrig::IConfig *oldConfig, const rapidjson::Value &json) -{ - IConfig *config = Config::create(); - if (!loadFromJSON(config, json)) { - delete config; - - return false; - } - - config->setFileName(oldConfig->fileName()); - const bool saved = config->save(); - - if (config->isWatch() && m_watcher && saved) { - delete config; - - return true; - } - - m_listener->onNewConfig(config); - return true; -} - - -bool xmrig::ConfigLoader::watch(IConfig *config) -{ - if (!config->isWatch()) { - return false; - } - - assert(m_watcher == nullptr); - - m_watcher = new ConfigWatcher(config->fileName(), m_listener); - return true; -} - - -xmrig::IConfig *xmrig::ConfigLoader::load(Process *process, IConfigListener *listener) -{ - m_listener = listener; - - IConfig *config = Config::create(); - int key; - int argc = process->arguments().argc(); - char **argv = process->arguments().argv(); - - while (1) { - key = getopt_long(argc, argv, short_options, options, nullptr); - if (key < 0) { - break; - } - - if (!parseArg(config, key, optarg)) { - delete config; - return nullptr; - } - } - - if (optind < argc) { - fprintf(stderr, "%s: unsupported non-option argument '%s'\n", argv[0], argv[optind]); - delete config; - return nullptr; - } - - if (!config->finalize()) { - delete config; - - config = Config::create(); - loadFromFile(config, process->location(Process::ExeLocation, "config.json")); - } - -# ifdef XMRIG_FEATURE_EMBEDDED_CONFIG - if (!config->finalize()) { - delete config; - - config = Config::create(); - loadFromJSON(config, default_config); - } -# endif - - if (!config->finalize()) { - if (!config->algorithm().isValid()) { - fprintf(stderr, "No valid algorithm specified. Exiting.\n"); - } - else { - fprintf(stderr, "No valid configuration found. Exiting.\n"); - } - - delete config; - return nullptr; - } - - return config; -} - - -void xmrig::ConfigLoader::release() -{ - delete m_watcher; - - m_watcher = nullptr; -} - - -bool xmrig::ConfigLoader::getJSON(const char *fileName, rapidjson::Document &doc) -{ - if (Json::get(fileName, doc)) { - return true; - } - - if (doc.HasParseError()) { - printf("%s: \"%s\"\n", fileName, doc.GetErrorOffset(), rapidjson::GetParseError_En(doc.GetParseError())); - } - else { - fprintf(stderr, "unable to open \"%s\".\n", fileName); - } - - return false; -} - - -bool xmrig::ConfigLoader::parseArg(xmrig::IConfig *config, int key, const char *arg) -{ - if (key == IConfig::ConfigKey) { - return loadFromFile(config, arg); - } - - return config->parseString(key, arg); -} - - -void xmrig::ConfigLoader::parseJSON(xmrig::IConfig *config, const struct option *option, const rapidjson::Value &object) -{ - if (!option->name || !object.HasMember(option->name)) { - return; - } - - const rapidjson::Value &value = object[option->name]; - - if (option->has_arg) { - if (value.IsString()) { - config->parseString(option->val, value.GetString()); - } - else if (value.IsInt64()) { - config->parseUint64(option->val, value.GetUint64()); - } - else if (value.IsBool()) { - config->parseBoolean(option->val, value.IsTrue()); - } - } - else if (value.IsBool()) { - config->parseBoolean(option->val, value.IsTrue()); - } -} diff --git a/src/common/crypto/Algorithm.cpp b/src/common/crypto/Algorithm.cpp index f14d034d..d9d3ead9 100644 --- a/src/common/crypto/Algorithm.cpp +++ b/src/common/crypto/Algorithm.cpp @@ -176,7 +176,7 @@ void xmrig::Algorithm::parseAlgorithm(const char *algo) m_algo = INVALID_ALGO; m_variant = VARIANT_AUTO; - assert(algo != nullptr); +// assert(algo != nullptr); if (algo == nullptr || strlen(algo) < 1) { return; } diff --git a/src/core/Controller.cpp b/src/core/Controller.cpp index 32507e90..493b3e11 100644 --- a/src/core/Controller.cpp +++ b/src/core/Controller.cpp @@ -26,89 +26,28 @@ #include -#include "base/io/log/backends/ConsoleLog.h" -#include "base/io/log/backends/FileLog.h" -#include "base/io/log/Log.h" -#include "base/kernel/interfaces/IControllerListener.h" -#include "common/config/ConfigLoader.h" #include "common/cpu/Cpu.h" #include "common/Platform.h" -#include "core/config/Config.h" #include "core/Controller.h" #include "net/Network.h" -#ifdef HAVE_SYSLOG_H -# include "base/io/log/backends/SysLog.h" -#endif - - -#ifdef XMRIG_FEATURE_API -# include "api/Api.h" -#endif - - -class xmrig::ControllerPrivate -{ -public: - inline ControllerPrivate(Process *process) : - api(nullptr), - config(nullptr), - network(nullptr), - process(process) - {} - - - inline ~ControllerPrivate() - { -# ifdef XMRIG_FEATURE_API - delete api; -# endif - - delete network; - delete config; - } - - - Api *api; - Config *config; - Network *network; - Process *process; - std::vector listeners; -}; - - -xmrig::Controller::Controller(Process *process) - : d_ptr(new ControllerPrivate(process)) +xmrig::Controller::Controller(Process *process) : + Base(process), + m_network(nullptr) { } xmrig::Controller::~Controller() { - delete d_ptr; -} - - -xmrig::Api *xmrig::Controller::api() const -{ - assert(d_ptr->api != nullptr); - - return d_ptr->api; + delete m_network; } bool xmrig::Controller::isReady() const { - return d_ptr->config && d_ptr->network; -} - - -xmrig::Config *xmrig::Controller::config() const -{ - assert(d_ptr->config != nullptr); - - return d_ptr->config; + return Base::isReady() && m_network; } @@ -116,98 +55,36 @@ int xmrig::Controller::init() { Cpu::init(); - d_ptr->config = Config::load(d_ptr->process, this); - if (!d_ptr->config) { - return 1; + const int rc = Base::init(); + if (rc != 0) { + return rc; } -# ifdef XMRIG_FEATURE_API - d_ptr->api = new Api(this); -# endif - - Platform::init(config()->userAgent()); - Platform::setProcessPriority(d_ptr->config->priority()); - - if (!config()->isBackground()) { - Log::add(new ConsoleLog()); - } - - if (config()->logFile()) { - Log::add(new FileLog(config()->logFile())); - } - -# ifdef HAVE_SYSLOG_H - if (config()->isSyslog()) { - Log::add(new SysLog()); - } -# endif - - d_ptr->network = new Network(this); + m_network = new Network(this); return 0; } -xmrig::Network *xmrig::Controller::network() const -{ - assert(d_ptr->network != nullptr); - - return d_ptr->network; -} - - -void xmrig::Controller::addListener(IControllerListener *listener) -{ - d_ptr->listeners.push_back(listener); -} - - -void xmrig::Controller::save() -{ - if (!config()) { - return; - } - - if (d_ptr->config->isShouldSave()) { - d_ptr->config->save(); - } - - ConfigLoader::watch(d_ptr->config); -} - - -void xmrig::Controller::onNewConfig(IConfig *config) -{ - Config *previousConfig = d_ptr->config; - d_ptr->config = static_cast(config); - - for (IControllerListener *listener : d_ptr->listeners) { - listener->onConfigChanged(d_ptr->config, previousConfig); - } - - delete previousConfig; -} - - void xmrig::Controller::start() { + Base::start(); + network()->connect(); - -# ifdef XMRIG_FEATURE_API - api()->start(); -# endif - - save(); } void xmrig::Controller::stop() { -# ifdef XMRIG_FEATURE_API - api()->stop(); -# endif + Base::stop(); - ConfigLoader::release(); - - delete d_ptr->network; - d_ptr->network = nullptr; + delete m_network; + m_network = nullptr; +} + + +xmrig::Network *xmrig::Controller::network() const +{ + assert(m_network != nullptr); + + return m_network; } diff --git a/src/core/Controller.h b/src/core/Controller.h index c1ca3da3..10e12147 100644 --- a/src/core/Controller.h +++ b/src/core/Controller.h @@ -26,45 +26,35 @@ #define XMRIG_CONTROLLER_H -#include "base/kernel/interfaces/IConfigListener.h" +#include "base/kernel/Base.h" namespace xmrig { -class Api; -class Config; -class ControllerPrivate; -class IControllerListener; class Network; class Process; -class Controller : public IConfigListener +class Controller : public Base { public: Controller(Process *process); ~Controller() override; - Api *api() const; - bool isReady() const; - Config *config() const; - int init(); - Network *network() const; - void addListener(IControllerListener *listener); - void save(); - void start(); - void stop(); + bool isReady() const override; + int init() override; + void start() override; + void stop() override; -protected: - void onNewConfig(IConfig *config) override; + Network *network() const; private: - ControllerPrivate *d_ptr; + Network *m_network; }; -} /* namespace xmrig */ +} // namespace xmrig #endif /* XMRIG_CONTROLLER_H */ diff --git a/src/core/config/Config.cpp b/src/core/config/Config.cpp index 2b706d74..1249b8ba 100644 --- a/src/core/config/Config.cpp +++ b/src/core/config/Config.cpp @@ -28,7 +28,7 @@ #include "base/io/log/Log.h" -#include "common/config/ConfigLoader.h" +#include "base/kernel/interfaces/IJsonReader.h" #include "common/cpu/Cpu.h" #include "core/config/Config.h" #include "crypto/Asm.h" @@ -42,7 +42,7 @@ static char affinity_tmp[20] = { 0 }; -xmrig::Config::Config() : xmrig::CommonConfig(), +xmrig::Config::Config() : m_aesMode(AES_AUTO), m_algoVariant(AV_AUTO), m_assembly(ASM_AUTO), @@ -55,9 +55,23 @@ xmrig::Config::Config() : xmrig::CommonConfig(), } -bool xmrig::Config::reload(const rapidjson::Value &json) +bool xmrig::Config::read(const IJsonReader &reader, const char *fileName) { - return xmrig::ConfigLoader::reload(this, json); + if (!BaseConfig::read(reader, fileName)) { + return false; + } + + m_hugePages = reader.getBool("huge-pages", true); + m_safe = reader.getBool("safe"); + + setAesMode(reader.getValue("hw-aes")); + setAlgoVariant(reader.getInt("av")); + setAssembly(reader.getValue("asm")); + setMaxCpuUsage(reader.getInt("max-cpu-usage", 100)); + setPriority(reader.getInt("cpu-priority", -1)); + setThreads(reader.getValue("threads")); + + return finalize(); } @@ -126,22 +140,8 @@ void xmrig::Config::getJSON(rapidjson::Document &doc) const } -xmrig::Config *xmrig::Config::load(Process *process, IConfigListener *listener) -{ - return static_cast(ConfigLoader::load(process, listener)); -} - - bool xmrig::Config::finalize() { - if (m_state != NoneState) { - return CommonConfig::finalize(); - } - - if (!CommonConfig::finalize()) { - return false; - } - if (!m_threads.cpu.empty()) { m_threads.mode = Advanced; const bool softAES = (m_aesMode == AES_AUTO ? (Cpu::info()->hasAES() ? AES_HW : AES_SOFT) : m_aesMode) == AES_SOFT; @@ -153,7 +153,7 @@ bool xmrig::Config::finalize() return true; } - const AlgoVariant av = getAlgoVariant(); + const AlgoVariant av = getAlgoVariant(); m_threads.mode = m_threads.count ? Simple : Automatic; const size_t size = CpuThread::multiway(av) * cn_select_memory(m_algorithm.algo()) / 1024; @@ -173,117 +173,54 @@ bool xmrig::Config::finalize() } m_shouldSave = m_threads.mode == Automatic; - return true; -} - - -bool xmrig::Config::parseBoolean(int key, bool enable) -{ - if (!CommonConfig::parseBoolean(key, enable)) { - return false; - } - - switch (key) { - case SafeKey: /* --safe */ - m_safe = enable; - break; - - case HugePagesKey: /* --no-huge-pages */ - m_hugePages = enable; - break; - - case HardwareAESKey: /* hw-aes config only */ - m_aesMode = enable ? AES_HW : AES_SOFT; - break; - -# ifndef XMRIG_NO_ASM - case AssemblyKey: - m_assembly = Asm::parse(enable); - break; -# endif - - default: - break; - } return true; } -bool xmrig::Config::parseString(int key, const char *arg) +void xmrig::Config::setAesMode(const rapidjson::Value &aesMode) { - if (!CommonConfig::parseString(key, arg)) { - return false; + if (aesMode.IsBool()) { + m_aesMode = aesMode.GetBool() ? AES_HW : AES_SOFT; } - - switch (key) { - case AVKey: /* --av */ - case MaxCPUUsageKey: /* --max-cpu-usage */ - case CPUPriorityKey: /* --cpu-priority */ - return parseUint64(key, strtol(arg, nullptr, 10)); - - case SafeKey: /* --safe */ - return parseBoolean(key, true); - - case HugePagesKey: /* --no-huge-pages */ - return parseBoolean(key, false); - - case ThreadsKey: /* --threads */ - if (strncmp(arg, "all", 3) == 0) { - m_threads.count = Cpu::info()->threads(); - return true; - } - - return parseUint64(key, strtol(arg, nullptr, 10)); - - case CPUAffinityKey: /* --cpu-affinity */ - { - const char *p = strstr(arg, "0x"); - return parseUint64(key, p ? strtoull(p, nullptr, 16) : strtoull(arg, nullptr, 10)); - } - -# ifndef XMRIG_NO_ASM - case AssemblyKey: /* --asm */ - m_assembly = Asm::parse(arg); - break; -# endif - - default: - break; - } - - return true; } -bool xmrig::Config::parseUint64(int key, uint64_t arg) +void xmrig::Config::setAlgoVariant(int av) { - if (!CommonConfig::parseUint64(key, arg)) { - return false; + if (av >= AV_AUTO && av < AV_MAX) { + m_algoVariant = static_cast(av); } - - switch (key) { - case CPUAffinityKey: /* --cpu-affinity */ - if (arg) { - m_threads.mask = static_cast(arg); - } - break; - - default: - return parseInt(key, static_cast(arg)); - } - - return true; } -void xmrig::Config::parseJSON(const rapidjson::Value &json) +void xmrig::Config::setAssembly(const rapidjson::Value &assembly) { - CommonConfig::parseJSON(json); + m_assembly = Asm::parse(assembly); +} - const rapidjson::Value &threads = json["threads"]; +void xmrig::Config::setMaxCpuUsage(int max) +{ + if (max > 0 && max <= 100) { + m_maxCpuUsage = max; + } +} + + +void xmrig::Config::setPriority(int priority) +{ + if (priority >= 0 && priority <= 5) { + m_priority = priority; + } +} + + +void xmrig::Config::setThreads(const rapidjson::Value &threads) +{ if (threads.IsArray()) { + m_threads.cpu.clear(); + for (const rapidjson::Value &value : threads.GetArray()) { if (!value.IsObject()) { continue; @@ -298,41 +235,12 @@ void xmrig::Config::parseJSON(const rapidjson::Value &json) } } } -} - - -bool xmrig::Config::parseInt(int key, int arg) -{ - switch (key) { - case ThreadsKey: /* --threads */ - if (arg >= 0 && arg < 1024) { - m_threads.count = arg; + else if (threads.IsUint()) { + const unsigned count = threads.GetUint(); + if (count < 1024) { + m_threads.count = count; } - break; - - case AVKey: /* --av */ - if (arg >= AV_AUTO && arg < AV_MAX) { - m_algoVariant = static_cast(arg); - } - break; - - case MaxCPUUsageKey: /* --max-cpu-usage */ - if (m_maxCpuUsage > 0 && arg <= 100) { - m_maxCpuUsage = arg; - } - break; - - case CPUPriorityKey: /* --cpu-priority */ - if (arg >= 0 && arg <= 5) { - m_priority = arg; - } - break; - - default: - break; } - - return true; } diff --git a/src/core/config/Config.h b/src/core/config/Config.h index 2a8ca11d..19c70cf1 100644 --- a/src/core/config/Config.h +++ b/src/core/config/Config.h @@ -29,7 +29,7 @@ #include -#include "common/config/CommonConfig.h" +#include "base/kernel/config/BaseConfig.h" #include "common/xmrig.h" #include "rapidjson/fwd.h" #include "workers/CpuThread.h" @@ -55,7 +55,7 @@ class Process; * api/worker-id * pools/ */ -class Config : public CommonConfig +class Config : public BaseConfig { public: enum ThreadsMode { @@ -67,8 +67,7 @@ public: Config(); - bool reload(const rapidjson::Value &json); - + bool read(const IJsonReader &reader, const char *fileName) override; void getJSON(rapidjson::Document &doc) const override; inline AesMode aesMode() const { return m_aesMode; } @@ -80,20 +79,16 @@ public: inline int priority() const { return m_priority; } inline int threadsCount() const { return static_cast(m_threads.list.size()); } inline int64_t affinity() const { return m_threads.mask; } - inline static IConfig *create() { return new Config(); } inline ThreadsMode threadsMode() const { return m_threads.mode; } - static Config *load(Process *process, IConfigListener *listener); - -protected: - bool finalize() override; - bool parseBoolean(int key, bool enable) override; - bool parseString(int key, const char *arg) override; - bool parseUint64(int key, uint64_t arg) override; - void parseJSON(const rapidjson::Value &json) override; - private: - bool parseInt(int key, int arg); + bool finalize(); + void setAesMode(const rapidjson::Value &aesMode); + void setAlgoVariant(int av); + void setAssembly(const rapidjson::Value &assembly); + void setMaxCpuUsage(int max); + void setPriority(int priority); + void setThreads(const rapidjson::Value &threads); AlgoVariant getAlgoVariant() const; # ifndef XMRIG_NO_AEON diff --git a/src/core/config/ConfigTransform.cpp b/src/core/config/ConfigTransform.cpp new file mode 100644 index 00000000..7c9afc17 --- /dev/null +++ b/src/core/config/ConfigTransform.cpp @@ -0,0 +1,106 @@ +/* XMRig + * Copyright 2010 Jeff Garzik + * Copyright 2012-2014 pooler + * Copyright 2014 Lucas Jones + * Copyright 2014-2016 Wolf9466 + * Copyright 2016 Jay D Dee + * Copyright 2017-2018 XMR-Stak , + * Copyright 2018-2019 SChernykh + * Copyright 2016-2019 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 "core/config/ConfigTransform.h" +#include "base/kernel/interfaces/IConfig.h" + + +xmrig::ConfigTransform::ConfigTransform() +{ + +} + + +void xmrig::ConfigTransform::transform(rapidjson::Document &doc, int key, const char *arg) +{ + BaseTransform::transform(doc, key, arg); + + switch (key) { + case IConfig::AVKey: /* --av */ + case IConfig::MaxCPUUsageKey: /* --max-cpu-usage */ + case IConfig::CPUPriorityKey: /* --cpu-priority */ + case IConfig::ThreadsKey: /* --threads */ + return transformUint64(doc, key, static_cast(strtol(arg, nullptr, 10))); + + case IConfig::SafeKey: /* --safe */ + return transformBoolean(doc, key, true); + + case IConfig::HugePagesKey: /* --no-huge-pages */ + return transformBoolean(doc, key, false); + + case IConfig::CPUAffinityKey: /* --cpu-affinity */ + { + const char *p = strstr(arg, "0x"); + return transformUint64(doc, key, p ? strtoull(p, nullptr, 16) : strtoull(arg, nullptr, 10)); + } + +# ifndef XMRIG_NO_ASM + case IConfig::AssemblyKey: /* --asm */ + return set(doc, "asm", arg); +# endif + + default: + break; + } +} + + +void xmrig::ConfigTransform::transformBoolean(rapidjson::Document &doc, int key, bool enable) +{ + switch (key) { + case IConfig::SafeKey: /* --safe */ + return set(doc, "safe", enable); + + case IConfig::HugePagesKey: /* --no-huge-pages */ + return set(doc, "huge-pages", enable); + + default: + break; + } +} + + +void xmrig::ConfigTransform::transformUint64(rapidjson::Document &doc, int key, uint64_t arg) +{ + switch (key) { + case IConfig::CPUAffinityKey: /* --cpu-affinity */ + return set(doc, "cpu-affinity", static_cast(arg)); + + case IConfig::ThreadsKey: /* --threads */ + return set(doc, "threads", arg); + + case IConfig::AVKey: /* --av */ + return set(doc, "av", arg); + + case IConfig::MaxCPUUsageKey: /* --max-cpu-usage */ + return set(doc, "max-cpu-usage", arg); + + case IConfig::CPUPriorityKey: /* --cpu-priority */ + return set(doc, "cpu-priority", arg); + + default: + break; + } +} diff --git a/src/core/config/ConfigTransform.h b/src/core/config/ConfigTransform.h new file mode 100644 index 00000000..2d291d8f --- /dev/null +++ b/src/core/config/ConfigTransform.h @@ -0,0 +1,51 @@ +/* XMRig + * Copyright 2010 Jeff Garzik + * Copyright 2012-2014 pooler + * Copyright 2014 Lucas Jones + * Copyright 2014-2016 Wolf9466 + * Copyright 2016 Jay D Dee + * Copyright 2017-2018 XMR-Stak , + * Copyright 2016-2018 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 XMRIG_CONFIGTRANSFORM_H +#define XMRIG_CONFIGTRANSFORM_H + + +#include "base/kernel/config/BaseTransform.h" + + +namespace xmrig { + + +class ConfigTransform : public BaseTransform +{ +public: + ConfigTransform(); + +protected: + void transform(rapidjson::Document &doc, int key, const char *arg) override; + +private: + void transformBoolean(rapidjson::Document &doc, int key, bool enable); + void transformUint64(rapidjson::Document &doc, int key, uint64_t arg); +}; + + +} // namespace xmrig + + +#endif /* XMRIG_CONFIGTRANSFORM_H */ diff --git a/src/core/config/ConfigLoader_default.h b/src/core/config/Config_default.h similarity index 94% rename from src/core/config/ConfigLoader_default.h rename to src/core/config/Config_default.h index 9ef81fd2..3462ad19 100644 --- a/src/core/config/ConfigLoader_default.h +++ b/src/core/config/Config_default.h @@ -22,8 +22,8 @@ * along with this program. If not, see . */ -#ifndef XMRIG_CONFIGLOADER_DEFAULT_H -#define XMRIG_CONFIGLOADER_DEFAULT_H +#ifndef XMRIG_CONFIG_DEFAULT_H +#define XMRIG_CONFIG_DEFAULT_H namespace xmrig { @@ -85,6 +85,7 @@ R"===( #endif -} /* namespace xmrig */ +} // namespace xmrig -#endif /* XMRIG_CONFIGLOADER_DEFAULT_H */ + +#endif /* XMRIG_CONFIG_DEFAULT_H */ diff --git a/src/core/config/ConfigLoader_platform.h b/src/core/config/Config_platform.h similarity index 88% rename from src/core/config/ConfigLoader_platform.h rename to src/core/config/Config_platform.h index 5026888d..8ece4105 100644 --- a/src/core/config/ConfigLoader_platform.h +++ b/src/core/config/Config_platform.h @@ -22,8 +22,8 @@ * along with this program. If not, see . */ -#ifndef XMRIG_CONFIGLOADER_PLATFORM_H -#define XMRIG_CONFIGLOADER_PLATFORM_H +#ifndef XMRIG_CONFIG_PLATFORM_H +#define XMRIG_CONFIG_PLATFORM_H #ifdef _MSC_VER @@ -33,17 +33,17 @@ #endif -#include "common/interfaces/IConfig.h" +#include "base/kernel/interfaces/IConfig.h" #include "version.h" namespace xmrig { -static char const short_options[] = "a:c:kBp:Px:r:R:s:t:T:o:u:O:v:l:S"; +static const char short_options[] = "a:c:kBp:Px:r:R:s:t:T:o:u:O:v:l:S"; -static struct option const options[] = { +static const option options[] = { { "algo", 1, nullptr, IConfig::AlgorithmKey }, { "api-worker-id", 1, nullptr, IConfig::ApiWorkerIdKey }, { "api-id", 1, nullptr, IConfig::ApiIdKey }, @@ -65,7 +65,6 @@ static struct option const options[] = { { "max-cpu-usage", 1, nullptr, IConfig::MaxCPUUsageKey }, { "nicehash", 0, nullptr, IConfig::NicehashKey }, { "no-color", 0, nullptr, IConfig::ColorKey }, - { "no-watch", 0, nullptr, IConfig::WatchKey }, { "no-huge-pages", 0, nullptr, IConfig::HugePagesKey }, { "variant", 1, nullptr, IConfig::VariantKey }, { "pass", 1, nullptr, IConfig::PasswordKey }, @@ -115,21 +114,12 @@ static struct option const config_options[] = { { "syslog", 0, nullptr, IConfig::SyslogKey }, { "threads", 1, nullptr, IConfig::ThreadsKey }, { "user-agent", 1, nullptr, IConfig::UserAgentKey }, - { "watch", 0, nullptr, IConfig::WatchKey }, - { "hw-aes", 0, nullptr, IConfig::HardwareAESKey }, { "asm", 1, nullptr, IConfig::AssemblyKey }, - { "autosave", 0, nullptr, IConfig::AutoSaveKey }, { nullptr, 0, nullptr, 0 } }; -static struct option const api_options[] = { - { "worker-id", 1, nullptr, IConfig::ApiWorkerIdKey }, - { "id", 1, nullptr, IConfig::ApiIdKey }, - { nullptr, 0, nullptr, 0 } -}; +} // namespace xmrig -} /* namespace xmrig */ - -#endif /* XMRIG_CONFIGLOADER_PLATFORM_H */ +#endif /* XMRIG_CONFIG_PLATFORM_H */ diff --git a/src/net/Network.h b/src/net/Network.h index 09e7c815..1b8f4934 100644 --- a/src/net/Network.h +++ b/src/net/Network.h @@ -30,7 +30,7 @@ #include "api/interfaces/IApiListener.h" -#include "base/kernel/interfaces/IControllerListener.h" +#include "base/kernel/interfaces/IBaseListener.h" #include "base/kernel/interfaces/IStrategyListener.h" #include "base/kernel/interfaces/ITimerListener.h" #include "interfaces/IJobResultListener.h" @@ -45,7 +45,7 @@ class Controller; class IStrategy; -class Network : public IJobResultListener, public IStrategyListener, public IControllerListener, public ITimerListener, public IApiListener +class Network : public IJobResultListener, public IStrategyListener, public IBaseListener, public ITimerListener, public IApiListener { public: Network(Controller *controller); From 1774b423456838a6b5dafb0d3cb001080d0bc0b9 Mon Sep 17 00:00:00 2001 From: XMRig Date: Sat, 6 Apr 2019 02:10:08 +0700 Subject: [PATCH 04/34] Fix "colors" option. --- src/base/kernel/config/BaseConfig.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/base/kernel/config/BaseConfig.cpp b/src/base/kernel/config/BaseConfig.cpp index 7284c263..e5fa7293 100644 --- a/src/base/kernel/config/BaseConfig.cpp +++ b/src/base/kernel/config/BaseConfig.cpp @@ -134,6 +134,7 @@ bool xmrig::BaseConfig::read(const IJsonReader &reader, const char *fileName) m_dryRun = reader.getBool("dry-run", m_dryRun); m_syslog = reader.getBool("syslog", m_syslog); m_watch = reader.getBool("watch", m_watch); + Log::colors = reader.getBool("colors", Log::colors); m_logFile = reader.getString("log-file"); m_userAgent = reader.getString("user-agent"); From 5d9648956bfcb3b1d2cb1edb099bb2dd0ee55d6b Mon Sep 17 00:00:00 2001 From: XMRig Date: Sat, 6 Apr 2019 02:11:02 +0700 Subject: [PATCH 05/34] Add milliseconds to log. --- src/base/io/log/Log.cpp | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/base/io/log/Log.cpp b/src/base/io/log/Log.cpp index fe5aa205..22972a7e 100644 --- a/src/base/io/log/Log.cpp +++ b/src/base/io/log/Log.cpp @@ -40,6 +40,7 @@ #include "base/io/log/Log.h" #include "base/kernel/interfaces/ILogBackend.h" +#include "base/tools/Chrono.h" namespace xmrig { @@ -134,7 +135,8 @@ private: return; } - time_t now = time(nullptr); + const uint64_t ms = Chrono::currentMSecsSinceEpoch(); + time_t now = ms / 1000; tm stime; # ifdef _WIN32 @@ -143,13 +145,14 @@ private: localtime_r(&now, &stime); # endif - const int rc = snprintf(m_buf, sizeof(m_buf) - 1, "[%d-%02d-%02d %02d:%02d:%02d] ", + const int rc = snprintf(m_buf, sizeof(m_buf) - 1, "[%d-%02d-%02d %02d:%02d:%02d" BLACK_BOLD(".%03d") "] ", stime.tm_year + 1900, stime.tm_mon + 1, stime.tm_mday, stime.tm_hour, stime.tm_min, - stime.tm_sec + stime.tm_sec, + static_cast(ms % 1000) ); if (rc > 0) { From 09df8c38462f02cd8b397c609641b05c824e60d4 Mon Sep 17 00:00:00 2001 From: XMRig Date: Sat, 6 Apr 2019 18:32:24 +0700 Subject: [PATCH 06/34] Sync changes. --- CMakeLists.txt | 4 +- src/base/io/JsonChain.cpp | 12 +++++ src/base/io/JsonChain.h | 2 + src/base/kernel/Base.cpp | 9 +++- src/base/kernel/config/BaseTransform.cpp | 62 ++++++++++++------------ src/base/kernel/interfaces/IConfig.h | 1 - src/core/Controller.h | 1 - src/core/config/ConfigTransform.cpp | 57 ---------------------- 8 files changed, 55 insertions(+), 93 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 550de480..2bc90d43 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -31,10 +31,10 @@ set(HEADERS src/common/Platform.h src/common/utils/mm_malloc.h src/common/xmrig.h - src/core/config/Config.h - src/core/config/ConfigTransform.h src/core/config/Config_default.h src/core/config/Config_platform.h + src/core/config/Config.h + src/core/config/ConfigTransform.h src/core/config/usage.h src/core/Controller.h src/interfaces/IJobResultListener.h diff --git a/src/base/io/JsonChain.cpp b/src/base/io/JsonChain.cpp index d65427cc..4dd75f0b 100644 --- a/src/base/io/JsonChain.cpp +++ b/src/base/io/JsonChain.cpp @@ -84,6 +84,18 @@ bool xmrig::JsonChain::addRaw(const char *json) } +void xmrig::JsonChain::dump(const char *fileName) +{ + rapidjson::Document doc(rapidjson::kArrayType); + + for (rapidjson::Document &value : m_chain) { + doc.PushBack(value, doc.GetAllocator()); + } + + Json::save(fileName, doc); +} + + bool xmrig::JsonChain::getBool(const char *key, bool defaultValue) const { for (auto it = m_chain.rbegin(); it != m_chain.rend(); ++it) { diff --git a/src/base/io/JsonChain.h b/src/base/io/JsonChain.h index dab01218..275f789e 100644 --- a/src/base/io/JsonChain.h +++ b/src/base/io/JsonChain.h @@ -46,6 +46,8 @@ public: bool addFile(const char *fileName); bool addRaw(const char *json); + void dump(const char *fileName); + inline const String &fileName() const { return m_fileName; } inline size_t size() const { return m_chain.size(); } diff --git a/src/base/kernel/Base.cpp b/src/base/kernel/Base.cpp index 84152441..157363f0 100644 --- a/src/base/kernel/Base.cpp +++ b/src/base/kernel/Base.cpp @@ -37,7 +37,6 @@ #include "base/kernel/interfaces/IBaseListener.h" #include "base/kernel/Process.h" #include "common/Platform.h" -#include "core/config/Config_default.h" #include "core/config/Config.h" #include "core/config/ConfigTransform.h" @@ -52,6 +51,11 @@ #endif +#ifdef XMRIG_FEATURE_EMBEDDED_CONFIG +# include "core/config/Config_default.h" +#endif + + class xmrig::BasePrivate { public: @@ -166,7 +170,10 @@ int xmrig::Base::init() # endif Platform::init(config()->userAgent()); + +# ifndef XMRIG_PROXY_PROJECT Platform::setProcessPriority(config()->priority()); +# endif if (!config()->isBackground()) { Log::add(new ConsoleLog()); diff --git a/src/base/kernel/config/BaseTransform.cpp b/src/base/kernel/config/BaseTransform.cpp index c676330e..c794d071 100644 --- a/src/base/kernel/config/BaseTransform.cpp +++ b/src/base/kernel/config/BaseTransform.cpp @@ -92,53 +92,53 @@ void xmrig::BaseTransform::transform(rapidjson::Document &doc, int key, const ch { switch (key) { case IConfig::AlgorithmKey: /* --algo */ - return set(doc, "algo", arg); + return set(doc, "algo", arg); case IConfig::UserpassKey: /* --userpass */ - return add(doc, kPools, "userpass", arg); + return add(doc, kPools, "userpass", arg); case IConfig::UrlKey: /* --url */ - return add(doc, kPools, "url", arg, true); + return add(doc, kPools, "url", arg, true); case IConfig::UserKey: /* --user */ - return add(doc, kPools, "user", arg); + return add(doc, kPools, "user", arg); case IConfig::PasswordKey: /* --pass */ - return add(doc, kPools, "pass", arg); + return add(doc, kPools, "pass", arg); case IConfig::RigIdKey: /* --rig-id */ - return add(doc, kPools, "rig-id", arg); + return add(doc, kPools, "rig-id", arg); case IConfig::FingerprintKey: /* --tls-fingerprint */ - return add(doc, kPools, "tls-fingerprint", arg); + return add(doc, kPools, "tls-fingerprint", arg); case IConfig::VariantKey: /* --variant */ - return add(doc, kPools, "variant", arg); + return add(doc, kPools, "variant", arg); case IConfig::LogFileKey: /* --log-file */ - return set(doc, "log-file", arg); + return set(doc, "log-file", arg); # ifdef XMRIG_DEPRECATED case IConfig::ApiAccessTokenKey: /* --api-access-token */ fputs("option \"--api-access-token\" deprecated, use \"--http-access-token\" instead.\n", stderr); fflush(stdout); - return set(doc, kHttp, "access-token", arg); + return set(doc, kHttp, "access-token", arg); # endif case IConfig::HttpAccessTokenKey: /* --http-access-token */ - return set(doc, kHttp, "access-token", arg); + return set(doc, kHttp, "access-token", arg); case IConfig::HttpHostKey: /* --http-host */ - return set(doc, kHttp, "host", arg); + return set(doc, kHttp, "host", arg); case IConfig::ApiWorkerIdKey: /* --api-worker-id */ - return set(doc, kApi, "worker-id", arg); + return set(doc, kApi, "worker-id", arg); case IConfig::ApiIdKey: /* --api-id */ - return set(doc, kApi, "id", arg); + return set(doc, kApi, "id", arg); case IConfig::UserAgentKey: /* --user-agent */ - return set(doc, "user-agent", arg); + return set(doc, "user-agent", arg); case IConfig::RetriesKey: /* --retries */ case IConfig::RetryPauseKey: /* --retry-pause */ @@ -177,16 +177,16 @@ void xmrig::BaseTransform::transformBoolean(rapidjson::Document &doc, int key, b { switch (key) { case IConfig::BackgroundKey: /* --background */ - return set(doc, "background", enable); + return set(doc, "background", enable); case IConfig::SyslogKey: /* --syslog */ - return set(doc, "syslog", enable); + return set(doc, "syslog", enable); case IConfig::KeepAliveKey: /* --keepalive */ - return add(doc, kPools, "keepalive", enable); + return add(doc, kPools, "keepalive", enable); case IConfig::TlsKey: /* --tls */ - return add(doc, kPools, "tls", enable); + return add(doc, kPools, "tls", enable); # ifndef XMRIG_PROXY_PROJECT case IConfig::NicehashKey: /* --nicehash */ @@ -194,7 +194,7 @@ void xmrig::BaseTransform::transformBoolean(rapidjson::Document &doc, int key, b # endif case IConfig::ColorKey: /* --no-color */ - return set(doc, "colors", enable); + return set(doc, "colors", enable); # ifdef XMRIG_DEPRECATED case IConfig::ApiIPv6Key: /* --api-ipv6 */ @@ -203,17 +203,17 @@ void xmrig::BaseTransform::transformBoolean(rapidjson::Document &doc, int key, b case IConfig::ApiRestrictedKey: /* --api-no-restricted */ fputs("option \"--api-no-restricted\" deprecated, use \"--http-no-restricted\" instead.\n", stderr); fflush(stdout); - return set(doc, kHttp, "restricted", enable); + return set(doc, kHttp, "restricted", enable); # endif case IConfig::HttpRestrictedKey: /* --http-no-restricted */ - return set(doc, kHttp, "restricted", enable); + return set(doc, kHttp, "restricted", enable); case IConfig::HttpEnabledKey: /* --http-enabled */ - return set(doc, kHttp, "enabled", enable); + return set(doc, kHttp, "enabled", enable); case IConfig::DryRunKey: /* --dry-run */ - return set(doc, "dry-run", enable); + return set(doc, "dry-run", enable); default: break; @@ -225,29 +225,29 @@ void xmrig::BaseTransform::transformUint64(rapidjson::Document &doc, int key, ui { switch (key) { case IConfig::RetriesKey: /* --retries */ - return set(doc, "retries", arg); + return set(doc, "retries", arg); case IConfig::RetryPauseKey: /* --retry-pause */ - return set(doc, "retry-pause", arg); + return set(doc, "retry-pause", arg); case IConfig::DonateLevelKey: /* --donate-level */ - return set(doc, "donate-level", arg); + return set(doc, "donate-level", arg); case IConfig::ProxyDonateKey: /* --donate-over-proxy */ - return set(doc, "donate-over-proxy", arg); + return set(doc, "donate-over-proxy", arg); # ifdef XMRIG_DEPRECATED case IConfig::ApiPort: /* --api-port */ fputs("option \"--api-port\" deprecated, use \"--http-port\" instead.\n", stderr); fflush(stdout); - return set(doc, kHttp, "port", arg); + return set(doc, kHttp, "port", arg); # endif case IConfig::HttpPort: /* --http-port */ - return set(doc, kHttp, "port", arg); + return set(doc, kHttp, "port", arg); case IConfig::PrintTimeKey: /* --print-time */ - return set(doc, "print-time", arg); + return set(doc, "print-time", arg); default: break; diff --git a/src/base/kernel/interfaces/IConfig.h b/src/base/kernel/interfaces/IConfig.h index 44628129..d592c4cb 100644 --- a/src/base/kernel/interfaces/IConfig.h +++ b/src/base/kernel/interfaces/IConfig.h @@ -110,7 +110,6 @@ public: // xmrig-proxy AccessLogFileKey = 'A', BindKey = 'b', - CoinKey = 1104, CustomDiffKey = 1102, DebugKey = 1101, ModeKey = 'm', diff --git a/src/core/Controller.h b/src/core/Controller.h index 10e12147..02f9ca92 100644 --- a/src/core/Controller.h +++ b/src/core/Controller.h @@ -33,7 +33,6 @@ namespace xmrig { class Network; -class Process; class Controller : public Base diff --git a/src/core/config/ConfigTransform.cpp b/src/core/config/ConfigTransform.cpp index 7c9afc17..7d313726 100644 --- a/src/core/config/ConfigTransform.cpp +++ b/src/core/config/ConfigTransform.cpp @@ -36,71 +36,14 @@ xmrig::ConfigTransform::ConfigTransform() void xmrig::ConfigTransform::transform(rapidjson::Document &doc, int key, const char *arg) { BaseTransform::transform(doc, key, arg); - - switch (key) { - case IConfig::AVKey: /* --av */ - case IConfig::MaxCPUUsageKey: /* --max-cpu-usage */ - case IConfig::CPUPriorityKey: /* --cpu-priority */ - case IConfig::ThreadsKey: /* --threads */ - return transformUint64(doc, key, static_cast(strtol(arg, nullptr, 10))); - - case IConfig::SafeKey: /* --safe */ - return transformBoolean(doc, key, true); - - case IConfig::HugePagesKey: /* --no-huge-pages */ - return transformBoolean(doc, key, false); - - case IConfig::CPUAffinityKey: /* --cpu-affinity */ - { - const char *p = strstr(arg, "0x"); - return transformUint64(doc, key, p ? strtoull(p, nullptr, 16) : strtoull(arg, nullptr, 10)); - } - -# ifndef XMRIG_NO_ASM - case IConfig::AssemblyKey: /* --asm */ - return set(doc, "asm", arg); -# endif - - default: - break; - } } void xmrig::ConfigTransform::transformBoolean(rapidjson::Document &doc, int key, bool enable) { - switch (key) { - case IConfig::SafeKey: /* --safe */ - return set(doc, "safe", enable); - - case IConfig::HugePagesKey: /* --no-huge-pages */ - return set(doc, "huge-pages", enable); - - default: - break; - } } void xmrig::ConfigTransform::transformUint64(rapidjson::Document &doc, int key, uint64_t arg) { - switch (key) { - case IConfig::CPUAffinityKey: /* --cpu-affinity */ - return set(doc, "cpu-affinity", static_cast(arg)); - - case IConfig::ThreadsKey: /* --threads */ - return set(doc, "threads", arg); - - case IConfig::AVKey: /* --av */ - return set(doc, "av", arg); - - case IConfig::MaxCPUUsageKey: /* --max-cpu-usage */ - return set(doc, "max-cpu-usage", arg); - - case IConfig::CPUPriorityKey: /* --cpu-priority */ - return set(doc, "cpu-priority", arg); - - default: - break; - } } From 466aad8543d810edf3817a99ac87f95660b98a46 Mon Sep 17 00:00:00 2001 From: XMRig Date: Sat, 6 Apr 2019 20:07:20 +0700 Subject: [PATCH 07/34] Fix build without ASM. --- src/core/config/Config.cpp | 19 ++++++++++++------- src/core/config/Config.h | 5 ++++- 2 files changed, 16 insertions(+), 8 deletions(-) diff --git a/src/core/config/Config.cpp b/src/core/config/Config.cpp index 1249b8ba..f49ba05d 100644 --- a/src/core/config/Config.cpp +++ b/src/core/config/Config.cpp @@ -66,11 +66,14 @@ bool xmrig::Config::read(const IJsonReader &reader, const char *fileName) setAesMode(reader.getValue("hw-aes")); setAlgoVariant(reader.getInt("av")); - setAssembly(reader.getValue("asm")); setMaxCpuUsage(reader.getInt("max-cpu-usage", 100)); setPriority(reader.getInt("cpu-priority", -1)); setThreads(reader.getValue("threads")); +# ifndef XMRIG_NO_ASM + setAssembly(reader.getValue("asm")); +# endif + return finalize(); } @@ -194,12 +197,6 @@ void xmrig::Config::setAlgoVariant(int av) } -void xmrig::Config::setAssembly(const rapidjson::Value &assembly) -{ - m_assembly = Asm::parse(assembly); -} - - void xmrig::Config::setMaxCpuUsage(int max) { if (max > 0 && max <= 100) { @@ -278,3 +275,11 @@ xmrig::AlgoVariant xmrig::Config::getAlgoVariantLite() const return m_algoVariant; } #endif + + +#ifndef XMRIG_NO_ASM +void xmrig::Config::setAssembly(const rapidjson::Value &assembly) +{ + m_assembly = Asm::parse(assembly); +} +#endif diff --git a/src/core/config/Config.h b/src/core/config/Config.h index 19c70cf1..861840c7 100644 --- a/src/core/config/Config.h +++ b/src/core/config/Config.h @@ -85,7 +85,6 @@ private: bool finalize(); void setAesMode(const rapidjson::Value &aesMode); void setAlgoVariant(int av); - void setAssembly(const rapidjson::Value &assembly); void setMaxCpuUsage(int max); void setPriority(int priority); void setThreads(const rapidjson::Value &threads); @@ -95,6 +94,10 @@ private: AlgoVariant getAlgoVariantLite() const; # endif +# ifndef XMRIG_NO_ASM + void setAssembly(const rapidjson::Value &assembly); +# endif + struct Threads { From 9561570c50179cc08ca8c4944ae25c8db0fbc964 Mon Sep 17 00:00:00 2001 From: XMRig Date: Sat, 6 Apr 2019 21:10:26 +0700 Subject: [PATCH 08/34] Fix build on FreeBSD. --- src/base/kernel/config/BaseTransform.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/base/kernel/config/BaseTransform.cpp b/src/base/kernel/config/BaseTransform.cpp index c794d071..5a05111b 100644 --- a/src/base/kernel/config/BaseTransform.cpp +++ b/src/base/kernel/config/BaseTransform.cpp @@ -23,6 +23,9 @@ */ +#include + + #ifdef _MSC_VER # include "getopt/getopt.h" #else From d6da0652ceae8aa02284ab4d5d7e91153b244350 Mon Sep 17 00:00:00 2001 From: XMRig Date: Sun, 7 Apr 2019 21:31:32 +0700 Subject: [PATCH 09/34] Removed unused setters in Pool class. --- src/base/net/stratum/Pool.cpp | 54 ++++++++++++++++------------------- src/base/net/stratum/Pool.h | 31 ++++++++++---------- src/base/tools/String.cpp | 14 +++++++++ src/base/tools/String.h | 1 + 4 files changed, 55 insertions(+), 45 deletions(-) diff --git a/src/base/net/stratum/Pool.cpp b/src/base/net/stratum/Pool.cpp index 2c48ab0b..c618707a 100644 --- a/src/base/net/stratum/Pool.cpp +++ b/src/base/net/stratum/Pool.cpp @@ -65,10 +65,8 @@ const String Pool::kDefaultUser = "x"; xmrig::Pool::Pool() : - m_enabled(true), - m_nicehash(false), - m_tls(false), m_keepAlive(0), + m_flags(0), m_port(kDefaultPort) { } @@ -86,10 +84,8 @@ xmrig::Pool::Pool() : * @param url */ xmrig::Pool::Pool(const char *url) : - m_enabled(true), - m_nicehash(false), - m_tls(false), m_keepAlive(0), + m_flags(1), m_port(kDefaultPort) { parse(url); @@ -97,22 +93,24 @@ xmrig::Pool::Pool(const char *url) : xmrig::Pool::Pool(const rapidjson::Value &object) : - m_enabled(true), - m_nicehash(false), - m_tls(false), m_keepAlive(0), + m_flags(1), m_port(kDefaultPort) { if (!parse(Json::getString(object, kUrl))) { return; } - setUser(Json::getString(object, kUser)); - setPassword(Json::getString(object, kPass)); - setRigId(Json::getString(object, kRigId)); - setNicehash(Json::getBool(object, kNicehash)); + m_user = Json::getString(object, kUser); + m_password = Json::getString(object, kPass); + m_rigId = Json::getString(object, kRigId); + m_fingerprint = Json::getString(object, kFingerprint); - const rapidjson::Value &keepalive = object[kKeepalive]; + m_flags.set(FLAG_ENABLED, Json::getBool(object, kEnabled, true)); + m_flags.set(FLAG_NICEHASH, Json::getBool(object, kNicehash)); + m_flags.set(FLAG_TLS, Json::getBool(object, kTls, m_flags.test(FLAG_TLS))); + + const rapidjson::Value &keepalive = Json::getValue(object, kKeepalive); if (keepalive.IsInt()) { setKeepAlive(keepalive.GetInt()); } @@ -120,7 +118,7 @@ xmrig::Pool::Pool(const rapidjson::Value &object) : setKeepAlive(keepalive.GetBool()); } - const rapidjson::Value &variant = object[kVariant]; + const rapidjson::Value &variant = Json::getValue(object, kVariant); if (variant.IsString()) { algorithm().parseVariant(variant.GetString()); } @@ -128,17 +126,12 @@ xmrig::Pool::Pool(const rapidjson::Value &object) : algorithm().parseVariant(variant.GetInt()); } - m_enabled = Json::getBool(object, kEnabled, true); - m_tls = Json::getBool(object, kTls); - m_fingerprint = Json::getString(object, kFingerprint); } xmrig::Pool::Pool(const char *host, uint16_t port, const char *user, const char *password, int keepAlive, bool nicehash, bool tls) : - m_enabled(true), - m_nicehash(nicehash), - m_tls(tls), m_keepAlive(keepAlive), + m_flags(1), m_host(host), m_password(password), m_user(user), @@ -151,6 +144,9 @@ xmrig::Pool::Pool(const char *host, uint16_t port, const char *user, const char snprintf(url, size - 1, "%s:%d", m_host.data(), m_port); m_url = url; + + m_flags.set(FLAG_NICEHASH, nicehash); + m_flags.set(FLAG_TLS, tls); } @@ -184,15 +180,13 @@ bool xmrig::Pool::isEnabled() const } # endif - return m_enabled && isValid() && algorithm().isValid(); + return m_flags.test(FLAG_ENABLED) && isValid() && algorithm().isValid(); } bool xmrig::Pool::isEqual(const Pool &other) const { - return (m_nicehash == other.m_nicehash - && m_enabled == other.m_enabled - && m_tls == other.m_tls + return (m_flags == other.m_flags && m_keepAlive == other.m_keepAlive && m_port == other.m_port && m_algorithm == other.m_algorithm @@ -214,10 +208,10 @@ bool xmrig::Pool::parse(const char *url) if (p) { if (strncasecmp(url, "stratum+tcp://", 14) == 0) { - m_tls = false; + m_flags.set(FLAG_TLS, false); } else if (strncasecmp(url, "stratum+ssl://", 14) == 0) { - m_tls = true; + m_flags.set(FLAG_TLS, true); } else { return false; @@ -309,7 +303,7 @@ rapidjson::Value xmrig::Pool::toJSON(rapidjson::Document &doc) const break; } - obj.AddMember(StringRef(kEnabled), m_enabled, allocator); + obj.AddMember(StringRef(kEnabled), m_flags.test(FLAG_ENABLED), allocator); obj.AddMember(StringRef(kTls), isTLS(), allocator); obj.AddMember(StringRef(kFingerprint), m_fingerprint.toJSON(), allocator); @@ -396,8 +390,8 @@ void xmrig::Pool::adjustVariant(const xmrig::Variant variantHint) using namespace xmrig; if (m_host.contains(".nicehash.com")) { + m_flags.set(FLAG_NICEHASH, true); m_keepAlive = false; - m_nicehash = true; bool valid = true; switch (m_port) { @@ -432,7 +426,7 @@ void xmrig::Pool::adjustVariant(const xmrig::Variant variantHint) m_algorithm.setAlgo(INVALID_ALGO); } - m_tls = m_port > 33000; + m_flags.set(FLAG_TLS, m_port > 33000); return; } diff --git a/src/base/net/stratum/Pool.h b/src/base/net/stratum/Pool.h index f681f0c4..d933bb86 100644 --- a/src/base/net/stratum/Pool.h +++ b/src/base/net/stratum/Pool.h @@ -26,6 +26,7 @@ #define XMRIG_POOL_H +#include #include @@ -40,6 +41,13 @@ namespace xmrig { class Pool { public: + enum Flags { + FLAG_ENABLED, + FLAG_NICEHASH, + FLAG_TLS, + FLAG_MAX + }; + static const String kDefaultPassword; static const String kDefaultUser; @@ -59,8 +67,8 @@ public: ); inline Algorithm &algorithm() { return m_algorithm; } - inline bool isNicehash() const { return m_nicehash; } - inline bool isTLS() const { return m_tls; } + inline bool isNicehash() const { return m_flags.test(FLAG_NICEHASH); } + inline bool isTLS() const { return m_flags.test(FLAG_TLS); } inline bool isValid() const { return !m_host.isNull() && m_port > 0; } inline const Algorithm &algorithm() const { return m_algorithm; } inline const Algorithms &algorithms() const { return m_algorithms; } @@ -72,17 +80,9 @@ public: inline const String &user() const { return !m_user.isNull() ? m_user : kDefaultUser; } inline int keepAlive() const { return m_keepAlive; } inline uint16_t port() const { return m_port; } - inline void setFingerprint(const char *fingerprint) { m_fingerprint = fingerprint; } - inline void setKeepAlive(bool enable) { setKeepAlive(enable ? kKeepAliveTimeout : 0); } - 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 setRigId(const char *rigId) { m_rigId = rigId; } - inline void setTLS(bool tls) { m_tls = tls; } - inline void setUser(const char *user) { m_user = user; } - inline bool operator!=(const Pool &other) const { return !isEqual(other); } - inline bool operator==(const Pool &other) const { return isEqual(other); } + inline bool operator!=(const Pool &other) const { return !isEqual(other); } + inline bool operator==(const Pool &other) const { return isEqual(other); } bool isCompatible(const Algorithm &algorithm) const; bool isEnabled() const; @@ -98,6 +98,9 @@ public: # endif private: + inline void setKeepAlive(bool enable) { setKeepAlive(enable ? kKeepAliveTimeout : 0); } + inline void setKeepAlive(int keepAlive) { m_keepAlive = keepAlive >= 0 ? keepAlive : 0; } + bool parseIPv6(const char *addr); void addVariant(Variant variant); void adjustVariant(const Variant variantHint); @@ -105,10 +108,8 @@ private: Algorithm m_algorithm; Algorithms m_algorithms; - bool m_enabled; - bool m_nicehash; - bool m_tls; int m_keepAlive; + std::bitset m_flags; String m_fingerprint; String m_host; String m_password; diff --git a/src/base/tools/String.cpp b/src/base/tools/String.cpp index c908fe9a..c7bc3d1b 100644 --- a/src/base/tools/String.cpp +++ b/src/base/tools/String.cpp @@ -129,6 +129,20 @@ std::vector xmrig::String::split(char sep) const } +xmrig::String &xmrig::String::toLower() +{ + if (isNull() || isEmpty()) { + return *this; + } + + for (size_t i = 0; i < size(); ++i) { + m_data[i] = static_cast(tolower(m_data[i])); + } + + return *this; +} + + xmrig::String xmrig::String::join(const std::vector &vec, char sep) { if (vec.empty()) { diff --git a/src/base/tools/String.h b/src/base/tools/String.h index a640469a..eb0a1820 100644 --- a/src/base/tools/String.h +++ b/src/base/tools/String.h @@ -85,6 +85,7 @@ public: rapidjson::Value toJSON() const; rapidjson::Value toJSON(rapidjson::Document &doc) const; std::vector split(char sep) const; + String &toLower(); static String join(const std::vector &vec, char sep); From 35d868fb48a29a5954300e31fd02853eb08cf97b Mon Sep 17 00:00:00 2001 From: XMRig Date: Mon, 8 Apr 2019 02:16:54 +0700 Subject: [PATCH 10/34] Fix --userpass option. --- src/base/kernel/config/BaseTransform.cpp | 15 ++++++++++++++- src/base/net/stratum/Client.cpp | 4 ++-- src/base/net/stratum/Pool.cpp | 19 +------------------ src/base/net/stratum/Pool.h | 1 - 4 files changed, 17 insertions(+), 22 deletions(-) diff --git a/src/base/kernel/config/BaseTransform.cpp b/src/base/kernel/config/BaseTransform.cpp index 5a05111b..3b6b6d82 100644 --- a/src/base/kernel/config/BaseTransform.cpp +++ b/src/base/kernel/config/BaseTransform.cpp @@ -98,7 +98,20 @@ void xmrig::BaseTransform::transform(rapidjson::Document &doc, int key, const ch return set(doc, "algo", arg); case IConfig::UserpassKey: /* --userpass */ - return add(doc, kPools, "userpass", arg); + { + const char *p = strrchr(arg, ':'); + if (!p) { + return; + } + + char *user = new char[p - arg + 1](); + strncpy(user, arg, static_cast(p - arg)); + + add(doc, kPools, "user", user); + add(doc, kPools, "pass", p + 1); + delete [] user; + } + break; case IConfig::UrlKey: /* --url */ return add(doc, kPools, "url", arg, true); diff --git a/src/base/net/stratum/Client.cpp b/src/base/net/stratum/Client.cpp index 667dd448..62c15f5a 100644 --- a/src/base/net/stratum/Client.cpp +++ b/src/base/net/stratum/Client.cpp @@ -541,7 +541,7 @@ int64_t xmrig::Client::send(const rapidjson::Document &doc) int64_t xmrig::Client::send(size_t size) { - LOG_DEBUG("[%s] send (%d bytes): \"%s\"", url(), size, m_sendBuf); + LOG_DEBUG("[%s] send (%d bytes): \"%.*s\"", url(), size, static_cast(size) - 1, m_sendBuf); # ifdef XMRIG_FEATURE_TLS if (isTLS()) { @@ -676,7 +676,7 @@ void xmrig::Client::parse(char *line, size_t len) { startTimeout(); - LOG_DEBUG("[%s] received (%d bytes): \"%s\"", url(), len, line); + LOG_DEBUG("[%s] received (%d bytes): \"%.*s\"", url(), len, static_cast(len), line); if (len < 32 || line[0] != '{') { if (!isQuiet()) { diff --git a/src/base/net/stratum/Pool.cpp b/src/base/net/stratum/Pool.cpp index c618707a..25fd13aa 100644 --- a/src/base/net/stratum/Pool.cpp +++ b/src/base/net/stratum/Pool.cpp @@ -246,23 +246,6 @@ bool xmrig::Pool::parse(const char *url) } -bool xmrig::Pool::setUserpass(const char *userpass) -{ - const char *p = strchr(userpass, ':'); - if (!p) { - return false; - } - - char *user = new char[p - userpass + 1](); - strncpy(user, userpass, static_cast(p - userpass)); - - m_user = user; - m_password = p + 1; - - return true; -} - - rapidjson::Value xmrig::Pool::toJSON(rapidjson::Document &doc) const { using namespace rapidjson; @@ -344,7 +327,7 @@ void xmrig::Pool::print() const LOG_DEBUG ("pass: %s", m_password.data()); LOG_DEBUG ("rig-id %s", m_rigId.data()); LOG_DEBUG ("algo: %s", m_algorithm.name()); - LOG_DEBUG ("nicehash: %d", static_cast(m_nicehash)); + LOG_DEBUG ("nicehash: %d", static_cast(m_flags.test(FLAG_NICEHASH))); LOG_DEBUG ("keepAlive: %d", m_keepAlive); } #endif diff --git a/src/base/net/stratum/Pool.h b/src/base/net/stratum/Pool.h index d933bb86..c8a7c44b 100644 --- a/src/base/net/stratum/Pool.h +++ b/src/base/net/stratum/Pool.h @@ -88,7 +88,6 @@ public: bool isEnabled() const; bool isEqual(const Pool &other) const; bool parse(const char *url); - bool setUserpass(const char *userpass); rapidjson::Value toJSON(rapidjson::Document &doc) const; void adjust(const Algorithm &algorithm); void setAlgo(const Algorithm &algorithm); From 241383068c29bad2d691ba95e6f8893ae9034875 Mon Sep 17 00:00:00 2001 From: XMRig Date: Tue, 9 Apr 2019 01:59:22 +0700 Subject: [PATCH 11/34] Added HttpClient class. --- src/api/Httpd.cpp | 34 +-- src/api/Httpd.h | 4 +- src/api/requests/HttpApiRequest.cpp | 4 +- src/api/requests/HttpApiRequest.h | 6 +- src/base/base.cmake | 4 +- src/base/kernel/interfaces/IHttpListener.h | 4 +- src/base/net/dns/Dns.cpp | 6 +- src/base/net/dns/Dns.h | 5 +- src/base/net/http/HttpClient.cpp | 198 ++++++++++++++++++ src/base/net/http/HttpClient.h | 64 ++++++ src/base/net/http/HttpContext.cpp | 165 +++++++++------ src/base/net/http/HttpContext.h | 24 +-- .../net/http/{HttpRequest.h => HttpData.h} | 12 +- src/base/net/http/HttpResponse.cpp | 16 +- src/base/net/http/HttpServer.cpp | 10 +- src/base/net/stratum/Client.cpp | 14 +- src/base/tools/Baton.h | 4 +- 17 files changed, 421 insertions(+), 153 deletions(-) create mode 100644 src/base/net/http/HttpClient.cpp create mode 100644 src/base/net/http/HttpClient.h rename src/base/net/http/{HttpRequest.h => HttpData.h} (89%) diff --git a/src/api/Httpd.cpp b/src/api/Httpd.cpp index 0aba6072..57a112e9 100644 --- a/src/api/Httpd.cpp +++ b/src/api/Httpd.cpp @@ -28,7 +28,7 @@ #include "api/Httpd.h" #include "base/io/log/Log.h" #include "base/net/http/HttpApiResponse.h" -#include "base/net/http/HttpRequest.h" +#include "base/net/http/HttpData.h" #include "base/net/http/HttpServer.h" #include "base/net/tools/TcpServer.h" #include "core/config/Config.h" @@ -128,49 +128,49 @@ void xmrig::Httpd::onConfigChanged(Config *config, Config *previousConfig) } -void xmrig::Httpd::onHttpRequest(const HttpRequest &req) +void xmrig::Httpd::onHttpData(const HttpData &data) { - if (req.method == HTTP_OPTIONS) { - return HttpApiResponse(req.id()).end(); + if (data.method == HTTP_OPTIONS) { + return HttpApiResponse(data.id()).end(); } - if (req.method == HTTP_GET && req.url == "/favicon.ico") { + if (data.method == HTTP_GET && data.url == "/favicon.ico") { # ifdef _WIN32 if (favicon != nullptr) { - HttpResponse response(req.id()); + HttpResponse response(data.id()); response.setHeader("Content-Type", "image/x-icon"); return response.end(favicon, faviconSize); } # endif - return HttpResponse(req.id(), 404).end(); + return HttpResponse(data.id(), 404).end(); } - if (req.method > 4) { - return HttpApiResponse(req.id(), HTTP_STATUS_METHOD_NOT_ALLOWED).end(); + if (data.method > 4) { + return HttpApiResponse(data.id(), HTTP_STATUS_METHOD_NOT_ALLOWED).end(); } - const int status = auth(req); + const int status = auth(data); if (status != HTTP_STATUS_OK) { - return HttpApiResponse(req.id(), status).end(); + return HttpApiResponse(data.id(), status).end(); } - if (req.method != HTTP_GET) { + if (data.method != HTTP_GET) { if (m_base->config()->http().isRestricted()) { - return HttpApiResponse(req.id(), HTTP_STATUS_FORBIDDEN).end(); + return HttpApiResponse(data.id(), HTTP_STATUS_FORBIDDEN).end(); } - if (!req.headers.count(kContentType) || req.headers.at(kContentType) != "application/json") { - return HttpApiResponse(req.id(), HTTP_STATUS_UNSUPPORTED_MEDIA_TYPE).end(); + if (!data.headers.count(kContentType) || data.headers.at(kContentType) != "application/json") { + return HttpApiResponse(data.id(), HTTP_STATUS_UNSUPPORTED_MEDIA_TYPE).end(); } } - m_base->api()->request(req); + m_base->api()->request(data); } -int xmrig::Httpd::auth(const HttpRequest &req) const +int xmrig::Httpd::auth(const HttpData &req) const { const Http &config = m_base->config()->http(); diff --git a/src/api/Httpd.h b/src/api/Httpd.h index ae6cbfc8..220bb7f5 100644 --- a/src/api/Httpd.h +++ b/src/api/Httpd.h @@ -52,10 +52,10 @@ public: protected: void onConfigChanged(Config *config, Config *previousConfig) override; - void onHttpRequest(const HttpRequest &req) override; + void onHttpData(const HttpData &data) override; private: - int auth(const HttpRequest &req) const; + int auth(const HttpData &req) const; Base *m_base; HttpServer *m_http; diff --git a/src/api/requests/HttpApiRequest.cpp b/src/api/requests/HttpApiRequest.cpp index a61dde8d..e4f2de1e 100644 --- a/src/api/requests/HttpApiRequest.cpp +++ b/src/api/requests/HttpApiRequest.cpp @@ -24,11 +24,11 @@ #include "api/requests/HttpApiRequest.h" -#include "base/net/http/HttpRequest.h" +#include "base/net/http/HttpData.h" #include "rapidjson/error/en.h" -xmrig::HttpApiRequest::HttpApiRequest(const HttpRequest &req, bool restricted) : +xmrig::HttpApiRequest::HttpApiRequest(const HttpData &req, bool restricted) : ApiRequest(SOURCE_HTTP, restricted), m_parsed(false), m_req(req), diff --git a/src/api/requests/HttpApiRequest.h b/src/api/requests/HttpApiRequest.h index 26f26f39..f34d4be5 100644 --- a/src/api/requests/HttpApiRequest.h +++ b/src/api/requests/HttpApiRequest.h @@ -35,13 +35,13 @@ namespace xmrig { -class HttpRequest; +class HttpData; class HttpApiRequest : public ApiRequest { public: - HttpApiRequest(const HttpRequest &req, bool restricted); + HttpApiRequest(const HttpData &req, bool restricted); protected: inline rapidjson::Document &doc() override { return m_res.doc(); } @@ -55,7 +55,7 @@ protected: private: bool m_parsed; - const HttpRequest &m_req; + const HttpData &m_req; HttpApiResponse m_res; rapidjson::Document m_body; String m_url; diff --git a/src/base/base.cmake b/src/base/base.cmake index 04016f01..886d4c11 100644 --- a/src/base/base.cmake +++ b/src/base/base.cmake @@ -100,8 +100,9 @@ if (WITH_HTTPD) src/base/kernel/interfaces/IJsonReader.h src/base/kernel/interfaces/ITcpServerListener.h src/base/net/http/HttpApiResponse.h + src/base/net/http/HttpClient.h src/base/net/http/HttpContext.h - src/base/net/http/HttpRequest.h + src/base/net/http/HttpData.h src/base/net/http/HttpResponse.h src/base/net/http/HttpServer.h src/base/net/tools/TcpServer.h @@ -110,6 +111,7 @@ if (WITH_HTTPD) set(SOURCES_BASE_HTTP src/3rdparty/http-parser/http_parser.c src/base/net/http/HttpApiResponse.cpp + src/base/net/http/HttpClient.cpp src/base/net/http/HttpContext.cpp src/base/net/http/HttpResponse.cpp src/base/net/http/HttpServer.cpp diff --git a/src/base/kernel/interfaces/IHttpListener.h b/src/base/kernel/interfaces/IHttpListener.h index d4d905ca..94fd1d18 100644 --- a/src/base/kernel/interfaces/IHttpListener.h +++ b/src/base/kernel/interfaces/IHttpListener.h @@ -29,7 +29,7 @@ namespace xmrig { -class HttpRequest; +class HttpData; class HttpResponse; @@ -38,7 +38,7 @@ class IHttpListener public: virtual ~IHttpListener() = default; - virtual void onHttpRequest(const HttpRequest &req) = 0; + virtual void onHttpData(const HttpData &data) = 0; }; diff --git a/src/base/net/dns/Dns.cpp b/src/base/net/dns/Dns.cpp index f57278c4..40d2a6e3 100644 --- a/src/base/net/dns/Dns.cpp +++ b/src/base/net/dns/Dns.cpp @@ -144,7 +144,11 @@ void xmrig::Dns::onResolved(int status, addrinfo *res) ptr = ptr->ai_next; } - m_listener->onResolved(*this, status); + if (isEmpty()) { + m_status = UV_EAI_NONAME; + } + + m_listener->onResolved(*this, m_status); } diff --git a/src/base/net/dns/Dns.h b/src/base/net/dns/Dns.h index 73c47cdd..11f5bf80 100644 --- a/src/base/net/dns/Dns.h +++ b/src/base/net/dns/Dns.h @@ -47,8 +47,9 @@ public: Dns(IDnsListener *listener); ~Dns(); - inline bool isEmpty() const { return m_ipv4.empty() && m_ipv6.empty(); } - inline int status() const { return m_status; } + inline bool isEmpty() const { return m_ipv4.empty() && m_ipv6.empty(); } + inline const String &host() const { return m_host; } + inline int status() const { return m_status; } bool resolve(const String &host); const char *error() const; diff --git a/src/base/net/http/HttpClient.cpp b/src/base/net/http/HttpClient.cpp new file mode 100644 index 00000000..d33daf2c --- /dev/null +++ b/src/base/net/http/HttpClient.cpp @@ -0,0 +1,198 @@ +/* XMRig + * Copyright 2010 Jeff Garzik + * Copyright 2012-2014 pooler + * Copyright 2014 Lucas Jones + * Copyright 2014-2016 Wolf9466 + * Copyright 2016 Jay D Dee + * Copyright 2017-2018 XMR-Stak , + * Copyright 2014-2019 heapwolf + * Copyright 2018-2019 SChernykh + * Copyright 2016-2019 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 + + +#include "3rdparty/http-parser/http_parser.h" +#include "base/io/log/Log.h" +#include "base/net/dns/Dns.h" +#include "base/net/http/HttpClient.h" +#include "base/tools/Baton.h" +#include "common/Platform.h" + + +namespace xmrig { + +static const char *kCRLF = "\r\n"; + + +class WriteBaton : public Baton +{ +public: + inline WriteBaton(const std::stringstream &ss, std::string &&body) : + m_body(body), + m_header(ss.str()) + { + bufs[0].len = m_header.size(); + bufs[0].base = const_cast(m_header.c_str()); + + if (!m_body.empty()) { + bufs[1].len = m_body.size(); + bufs[1].base = const_cast(m_body.c_str()); + } + else { + bufs[1].base = nullptr; + bufs[1].len = 0; + } + } + + + inline size_t count() const { return bufs[1].base == nullptr ? 1 : 2; } + inline size_t size() const { return bufs[0].len + bufs[1].len; } + inline static void onWrite(uv_write_t *req, int) { delete reinterpret_cast(req->data); } + + + uv_buf_t bufs[2]; + +private: + std::string m_body; + std::string m_header; +}; + + +} // namespace xmrig + + +xmrig::HttpClient::HttpClient(const String &host, uint16_t port, int method, const String &url, IHttpListener *listener, const char *data, size_t size) : + HttpContext(HTTP_RESPONSE, listener), + m_port(port) +{ + this->method = method; + this->url = url; + + if (data) { + body = size ? std::string(data, size) : data; + } + + m_dns = new Dns(this); + + status = m_dns->resolve(host); +} + + +xmrig::HttpClient::~HttpClient() +{ + delete m_dns; +} + + +void xmrig::HttpClient::onResolved(const Dns &dns, int status) +{ + this->status = status; + + if (status < 0 && dns.isEmpty()) { + LOG_ERR("[%s:%d] DNS error: \"%s\"", dns.host().data(), m_port, uv_strerror(status)); + + return; + } + + sockaddr *addr = dns.get().addr(m_port); + + uv_connect_t *req = new uv_connect_t; + req->data = this; + + uv_tcp_connect(req, m_tcp, addr, onConnect); +} + + +void xmrig::HttpClient::send() +{ + headers.insert({ "Host", m_dns->host().data() }); + headers.insert({ "Connection", "close" }); + headers.insert({ "User-Agent", Platform::userAgent() }); + + if (body.size()) { + headers.insert({ "Content-Length", std::to_string(body.size()) }); + } + + std::stringstream ss; + ss << http_method_str(static_cast(method)) << " " << url << " HTTP/1.1" << kCRLF; + + for (auto &header : headers) { + ss << header.first << ": " << header.second << kCRLF; + } + + ss << kCRLF; + + headers.clear(); + + WriteBaton *baton = new WriteBaton(ss, std::move(body)); + uv_write(&baton->req, stream(), baton->bufs, baton->count(), WriteBaton::onWrite); +} + + +void xmrig::HttpClient::onConnect(uv_connect_t *req, int status) +{ + HttpClient *client = static_cast(req->data); + if (!client) { + delete req; + return; + } + + if (status < 0) { + LOG_ERR("[%s:%d] connect error: \"%s\"", client->m_dns->host().data(), client->m_port, uv_strerror(status)); + + delete req; + client->close(); + return; + } + + uv_read_start(client->stream(), + [](uv_handle_t *, size_t suggested_size, uv_buf_t *buf) + { + buf->base = new char[suggested_size]; + +# ifdef _WIN32 + buf->len = static_cast(suggested_size); +# else + buf->len = suggested_size; +# endif + }, + [](uv_stream_t *tcp, ssize_t nread, const uv_buf_t *buf) + { + HttpClient *client = static_cast(tcp->data); + + if (nread >= 0) { + const size_t size = static_cast(nread); + const size_t parsed = client->parse(buf->base, size); + + if (parsed < size) { + client->close(); + } + } else { + if (nread != UV_EOF) { + LOG_ERR("[%s:%d] read error: \"%s\"", client->m_dns->host().data(), client->m_port, uv_strerror(static_cast(nread))); + } + + client->close(); + } + + delete [] buf->base; + }); + + client->send(); +} diff --git a/src/base/net/http/HttpClient.h b/src/base/net/http/HttpClient.h new file mode 100644 index 00000000..c31b9a3e --- /dev/null +++ b/src/base/net/http/HttpClient.h @@ -0,0 +1,64 @@ +/* XMRig + * Copyright 2010 Jeff Garzik + * Copyright 2012-2014 pooler + * Copyright 2014 Lucas Jones + * Copyright 2014-2016 Wolf9466 + * Copyright 2016 Jay D Dee + * Copyright 2017-2018 XMR-Stak , + * Copyright 2014-2019 heapwolf + * Copyright 2018-2019 SChernykh + * Copyright 2016-2019 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 XMRIG_HTTPCLIENT_H +#define XMRIG_HTTPCLIENT_H + + +#include "base/net/http/HttpContext.h" +#include "base/kernel/interfaces/IDnsListener.h" + + +namespace xmrig { + + +class String; + + +class HttpClient : public HttpContext, public IDnsListener +{ +public: + HttpClient(const String &host, uint16_t port, int method, const String &url, IHttpListener *listener, const char *data = nullptr, size_t size = 0); + ~HttpClient(); + +protected: + void onResolved(const Dns &dns, int status); + +private: + void send(); + + static void onConnect(uv_connect_t *req, int status); + + Dns *m_dns; + uint16_t m_port; +}; + + +} // namespace xmrig + + +#endif // XMRIG_HTTPCLIENT_H + diff --git a/src/base/net/http/HttpContext.cpp b/src/base/net/http/HttpContext.cpp index de32f34d..c98b4ad2 100644 --- a/src/base/net/http/HttpContext.cpp +++ b/src/base/net/http/HttpContext.cpp @@ -35,43 +35,72 @@ namespace xmrig { +static http_parser_settings http_settings; +static std::map storage; static uint64_t SEQUENCE = 0; -std::map HttpContext::m_storage; } // namespace xmrig xmrig::HttpContext::HttpContext(int parser_type, IHttpListener *listener) : - HttpRequest(SEQUENCE++), - listener(listener), - connect(nullptr), - m_wasHeaderValue(false) + HttpData(SEQUENCE++), + m_wasHeaderValue(false), + m_listener(listener) { - m_storage[id()] = this; + storage[id()] = this; - parser = new http_parser; - tcp = new uv_tcp_t; + m_parser = new http_parser; + m_tcp = new uv_tcp_t; - uv_tcp_init(uv_default_loop(), tcp); - http_parser_init(parser, static_cast(parser_type)); + uv_tcp_init(uv_default_loop(), m_tcp); + uv_tcp_nodelay(m_tcp, 1); - parser->data = tcp->data = this; + http_parser_init(m_parser, static_cast(parser_type)); + + m_parser->data = m_tcp->data = this; + + if (http_settings.on_message_complete == nullptr) { + attach(&http_settings); + } } xmrig::HttpContext::~HttpContext() { - delete connect; - delete tcp; - delete parser; + delete m_tcp; + delete m_parser; +} + + +size_t xmrig::HttpContext::parse(const char *data, size_t size) +{ + return http_parser_execute(m_parser, &http_settings, data, size); +} + + +std::string xmrig::HttpContext::ip() const +{ + char ip[46] = {}; + sockaddr_storage addr = {}; + int size = sizeof(addr); + + uv_tcp_getpeername(m_tcp, reinterpret_cast(&addr), &size); + if (reinterpret_cast(&addr)->sin_family == AF_INET6) { + uv_ip6_name(reinterpret_cast(&addr), ip, 45); + } + else { + uv_ip4_name(reinterpret_cast(&addr), ip, 16); + } + + return ip; } void xmrig::HttpContext::close() { - auto it = m_storage.find(id()); - if (it != m_storage.end()) { - m_storage.erase(it); + auto it = storage.find(id()); + if (it != storage.end()) { + storage.erase(it); } if (!uv_is_closing(handle())) { @@ -82,65 +111,17 @@ void xmrig::HttpContext::close() xmrig::HttpContext *xmrig::HttpContext::get(uint64_t id) { - if (m_storage.count(id) == 0) { + if (storage.count(id) == 0) { return nullptr; } - return m_storage[id]; -} - - -void xmrig::HttpContext::attach(http_parser_settings *settings) -{ - if (settings->on_message_complete != nullptr) { - return; - } - - settings->on_message_begin = nullptr; - settings->on_status = nullptr; - settings->on_chunk_header = nullptr; - settings->on_chunk_complete = nullptr; - - settings->on_url = [](http_parser *parser, const char *at, size_t length) -> int - { - static_cast(parser->data)->url = std::string(at, length); - return 0; - }; - - settings->on_header_field = onHeaderField; - settings->on_header_value = onHeaderValue; - - settings->on_headers_complete = [](http_parser* parser) -> int { - HttpContext *ctx = static_cast(parser->data); - ctx->method = parser->method; - - if (!ctx->m_lastHeaderField.empty()) { - ctx->setHeader(); - } - - return 0; - }; - - settings->on_body = [](http_parser *parser, const char *at, size_t len) -> int - { - static_cast(parser->data)->body += std::string(at, len); - - return 0; - }; - - settings->on_message_complete = [](http_parser *parser) -> int - { - const HttpContext *ctx = reinterpret_cast(parser->data); - ctx->listener->onHttpRequest(*ctx); - - return 0; - }; + return storage[id]; } void xmrig::HttpContext::closeAll() { - for (auto kv : m_storage) { + for (auto kv : storage) { if (!uv_is_closing(kv.second->handle())) { uv_close(kv.second->handle(), [](uv_handle_t *handle) -> void { delete reinterpret_cast(handle->data); }); } @@ -182,6 +163,54 @@ int xmrig::HttpContext::onHeaderValue(http_parser *parser, const char *at, size_ } +void xmrig::HttpContext::attach(http_parser_settings *settings) +{ + settings->on_message_begin = nullptr; + settings->on_status = nullptr; + settings->on_chunk_header = nullptr; + settings->on_chunk_complete = nullptr; + + settings->on_url = [](http_parser *parser, const char *at, size_t length) -> int + { + static_cast(parser->data)->url = std::string(at, length); + return 0; + }; + + settings->on_header_field = onHeaderField; + settings->on_header_value = onHeaderValue; + + settings->on_headers_complete = [](http_parser* parser) -> int { + HttpContext *ctx = static_cast(parser->data); + ctx->status = parser->status_code; + + if (parser->type == HTTP_REQUEST) { + ctx->method = parser->method; + } + + if (!ctx->m_lastHeaderField.empty()) { + ctx->setHeader(); + } + + return 0; + }; + + settings->on_body = [](http_parser *parser, const char *at, size_t len) -> int + { + static_cast(parser->data)->body += std::string(at, len); + + return 0; + }; + + settings->on_message_complete = [](http_parser *parser) -> int + { + const HttpContext *ctx = static_cast(parser->data); + ctx->m_listener->onHttpData(*ctx); + + return 0; + }; +} + + void xmrig::HttpContext::setHeader() { std::transform(m_lastHeaderField.begin(), m_lastHeaderField.end(), m_lastHeaderField.begin(), ::tolower); diff --git a/src/base/net/http/HttpContext.h b/src/base/net/http/HttpContext.h index 3b2dead3..ee11a072 100644 --- a/src/base/net/http/HttpContext.h +++ b/src/base/net/http/HttpContext.h @@ -36,7 +36,7 @@ typedef struct uv_stream_s uv_stream_t; typedef struct uv_tcp_s uv_tcp_t; -#include "base/net/http/HttpRequest.h" +#include "base/net/http/HttpData.h" namespace xmrig { @@ -45,37 +45,37 @@ namespace xmrig { class IHttpListener; -class HttpContext : public HttpRequest +class HttpContext : public HttpData { public: HttpContext(int parser_type, IHttpListener *listener); - ~HttpContext(); + virtual ~HttpContext(); - inline uv_stream_t *stream() const { return reinterpret_cast(tcp); } - inline uv_handle_t *handle() const { return reinterpret_cast(tcp); } + inline uv_stream_t *stream() const { return reinterpret_cast(m_tcp); } + inline uv_handle_t *handle() const { return reinterpret_cast(m_tcp); } + size_t parse(const char *data, size_t size); + std::string ip() const; void close(); static HttpContext *get(uint64_t id); - static void attach(http_parser_settings *settings); static void closeAll(); - http_parser *parser; - IHttpListener *listener; - uv_connect_t *connect; - uv_tcp_t *tcp; +protected: + uv_tcp_t *m_tcp; private: static int onHeaderField(http_parser *parser, const char *at, size_t length); static int onHeaderValue(http_parser *parser, const char *at, size_t length); + static void attach(http_parser_settings *settings); void setHeader(); bool m_wasHeaderValue; + http_parser *m_parser; + IHttpListener *m_listener; std::string m_lastHeaderField; std::string m_lastHeaderValue; - - static std::map m_storage; }; diff --git a/src/base/net/http/HttpRequest.h b/src/base/net/http/HttpData.h similarity index 89% rename from src/base/net/http/HttpRequest.h rename to src/base/net/http/HttpData.h index b97f0b8d..ceb19b8e 100644 --- a/src/base/net/http/HttpRequest.h +++ b/src/base/net/http/HttpData.h @@ -24,26 +24,26 @@ */ -#ifndef XMRIG_HTTPREQUEST_H -#define XMRIG_HTTPREQUEST_H +#ifndef XMRIG_HTTPDATA_H +#define XMRIG_HTTPDATA_H #include -#include #include namespace xmrig { -class HttpRequest +class HttpData { public: - inline HttpRequest(uint64_t id) : method(0), m_id(id) {} + inline HttpData(uint64_t id) : method(0), status(0), m_id(id) {} inline uint64_t id() const { return m_id; } int method; + int status; std::map headers; std::string body; std::string url; @@ -56,5 +56,5 @@ private: } // namespace xmrig -#endif // XMRIG_HTTPREQUEST_H +#endif // XMRIG_HTTPDATA_H diff --git a/src/base/net/http/HttpResponse.cpp b/src/base/net/http/HttpResponse.cpp index d782217b..7a4af838 100644 --- a/src/base/net/http/HttpResponse.cpp +++ b/src/base/net/http/HttpResponse.cpp @@ -49,7 +49,6 @@ public: m_ctx(ctx), m_header(ss.str()) { - req.data = this; bufs[0].len = m_header.size(); bufs[0].base = const_cast(m_header.c_str()); @@ -137,21 +136,10 @@ void xmrig::HttpResponse::end(const char *data, size_t size) if (statusCode() >= 400) # endif { - const bool err = statusCode() >= 400; - char ip[46] = {}; - sockaddr_storage addr = {}; - int aSize = sizeof(addr); - - uv_tcp_getpeername(ctx->tcp, reinterpret_cast(&addr), &aSize); - if (reinterpret_cast(&addr)->sin_family == AF_INET6) { - uv_ip6_name(reinterpret_cast(&addr), ip, 45); - } - else { - uv_ip4_name(reinterpret_cast(&addr), ip, 16); - } + const bool err = statusCode() >= 400; Log::print(err ? Log::ERR : Log::INFO, CYAN("%s ") CLEAR MAGENTA_BOLD("%s") WHITE_BOLD(" %s ") CSI "1;%dm%d " CLEAR WHITE_BOLD("%zu ") BLACK_BOLD("\"%s\""), - ip, + ctx->ip().c_str(), http_method_str(static_cast(ctx->method)), ctx->url.c_str(), err ? 31 : 32, diff --git a/src/base/net/http/HttpServer.cpp b/src/base/net/http/HttpServer.cpp index c6e02e44..60db31f6 100644 --- a/src/base/net/http/HttpServer.cpp +++ b/src/base/net/http/HttpServer.cpp @@ -35,17 +35,9 @@ #include "base/net/http/HttpServer.h" -namespace xmrig { - -static http_parser_settings http_settings; - -} // namespace xmrig - - xmrig::HttpServer::HttpServer(IHttpListener *listener) : m_listener(listener) { - HttpContext::attach(&http_settings); } @@ -77,7 +69,7 @@ void xmrig::HttpServer::onConnection(uv_stream_t *stream, uint16_t) if (nread >= 0) { const size_t size = static_cast(nread); - const size_t parsed = http_parser_execute(ctx->parser, &http_settings, buf->base, size); + const size_t parsed = ctx->parse(buf->base, size); if (parsed < size) { ctx->close(); diff --git a/src/base/net/stratum/Client.cpp b/src/base/net/stratum/Client.cpp index 62c15f5a..dba84cb1 100644 --- a/src/base/net/stratum/Client.cpp +++ b/src/base/net/stratum/Client.cpp @@ -284,14 +284,6 @@ void xmrig::Client::onResolved(const Dns &dns, int status) return reconnect(); } - if (dns.isEmpty()) { - if (!isQuiet()) { - LOG_ERR("[%s] DNS error: \"No IPv4 (A) or IPv6 (AAAA) records found\"", url()); - } - - return reconnect(); - } - const DnsRecord &record = dns.get(); m_ip = record.ip(); @@ -574,8 +566,6 @@ void xmrig::Client::connect(sockaddr *addr) { setState(ConnectingState); - reinterpret_cast(addr)->sin_port = htons(m_pool.port()); - uv_connect_t *req = new uv_connect_t; req->data = m_storage.ptr(m_key); @@ -589,7 +579,7 @@ void xmrig::Client::connect(sockaddr *addr) uv_tcp_keepalive(m_socket, 1, 60); # endif - uv_tcp_connect(req, m_socket, reinterpret_cast(addr), Client::onConnect); + uv_tcp_connect(req, m_socket, addr, onConnect); delete addr; } @@ -970,7 +960,7 @@ void xmrig::Client::onConnect(uv_connect_t *req, int status) client->m_stream->data = req->data; client->setState(ConnectedState); - uv_read_start(client->m_stream, Client::onAllocBuffer, Client::onRead); + uv_read_start(client->m_stream, onAllocBuffer, onRead); delete req; client->handshake(); diff --git a/src/base/tools/Baton.h b/src/base/tools/Baton.h index 7bea0af0..646dc0b8 100644 --- a/src/base/tools/Baton.h +++ b/src/base/tools/Baton.h @@ -29,13 +29,13 @@ namespace xmrig { -template +template class Baton { public: inline Baton() { req.data = this; } - T req; + REQ req; }; From 6812d22d63f02be97dc25327c79fe7abe263c136 Mon Sep 17 00:00:00 2001 From: XMRig Date: Tue, 9 Apr 2019 02:27:19 +0700 Subject: [PATCH 12/34] Rename cmake option WITH_HTTPD to WITH_HTTP. --- CMakeLists.txt | 10 +++++----- src/base/base.cmake | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 2bc90d43..c7098f37 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -6,7 +6,7 @@ option(WITH_AEON "CryptoNight-Lite support" ON) option(WITH_SUMO "CryptoNight-Heavy support" ON) option(WITH_CN_PICO "CryptoNight-Pico support" ON) option(WITH_CN_GPU "CryptoNight-GPU support" ON) -option(WITH_HTTPD "HTTP REST API" ON) +option(WITH_HTTP "HTTP protocol support (client/server)" ON) option(WITH_DEBUG_LOG "Enable debug log output" OFF) option(WITH_TLS "Enable OpenSSL support" ON) option(WITH_ASM "Enable ASM PoW implementations" ON) @@ -198,8 +198,8 @@ if (WITH_EMBEDDED_CONFIG) add_definitions(/DXMRIG_FEATURE_EMBEDDED_CONFIG) endif() -if (WITH_HTTPD) - set(HTTPD_SOURCES +if (WITH_HTTP) + set(HTTP_SOURCES src/api/Api.cpp src/api/Api.h src/api/Httpd.cpp @@ -213,7 +213,7 @@ if (WITH_HTTPD) src/api/v1/ApiRouter.h ) else() - set(HTTPD_SOURCES "") + set(HTTP_SOURCES "") endif() include_directories(src) @@ -228,5 +228,5 @@ if (WITH_DEBUG_LOG) add_definitions(/DAPP_DEBUG) endif() -add_executable(${CMAKE_PROJECT_NAME} ${HEADERS} ${SOURCES} ${SOURCES_OS} ${SOURCES_CPUID} ${HEADERS_CRYPTO} ${SOURCES_CRYPTO} ${SOURCES_SYSLOG} ${HTTPD_SOURCES} ${TLS_SOURCES} ${XMRIG_ASM_SOURCES} ${CN_GPU_SOURCES}) +add_executable(${CMAKE_PROJECT_NAME} ${HEADERS} ${SOURCES} ${SOURCES_OS} ${SOURCES_CPUID} ${HEADERS_CRYPTO} ${SOURCES_CRYPTO} ${SOURCES_SYSLOG} ${HTTP_SOURCES} ${TLS_SOURCES} ${XMRIG_ASM_SOURCES} ${CN_GPU_SOURCES}) target_link_libraries(${CMAKE_PROJECT_NAME} ${XMRIG_ASM_LIBRARY} ${OPENSSL_LIBRARIES} ${UV_LIBRARIES} ${EXTRA_LIBS} ${CPUID_LIB}) diff --git a/src/base/base.cmake b/src/base/base.cmake index 886d4c11..5263ed92 100644 --- a/src/base/base.cmake +++ b/src/base/base.cmake @@ -93,7 +93,7 @@ if (NOT WIN32) endif() -if (WITH_HTTPD) +if (WITH_HTTP) set(HEADERS_BASE_HTTP src/3rdparty/http-parser/http_parser.h src/base/kernel/interfaces/IHttpListener.h From c823c54f9bd39d9e67f53c558add72fabc31bd35 Mon Sep 17 00:00:00 2001 From: XMRig Date: Tue, 9 Apr 2019 14:06:56 +0700 Subject: [PATCH 13/34] Added HttpsClient. --- cmake/OpenSSL.cmake | 4 + src/base/net/http/HttpClient.cpp | 51 +++++++--- src/base/net/http/HttpClient.h | 17 +++- src/base/net/http/HttpsClient.cpp | 150 ++++++++++++++++++++++++++++++ src/base/net/http/HttpsClient.h | 70 ++++++++++++++ 5 files changed, 272 insertions(+), 20 deletions(-) create mode 100644 src/base/net/http/HttpsClient.cpp create mode 100644 src/base/net/http/HttpsClient.h diff --git a/cmake/OpenSSL.cmake b/cmake/OpenSSL.cmake index bcdea0c6..ea46081c 100644 --- a/cmake/OpenSSL.cmake +++ b/cmake/OpenSSL.cmake @@ -13,6 +13,10 @@ if (WITH_TLS) if (OPENSSL_FOUND) set(TLS_SOURCES src/base/net/stratum/Tls.h src/base/net/stratum/Tls.cpp) include_directories(${OPENSSL_INCLUDE_DIR}) + + if (WITH_HTTP) + set(TLS_SOURCES ${TLS_SOURCES} src/base/net/http/HttpsClient.h src/base/net/http/HttpsClient.cpp) + endif() else() message(FATAL_ERROR "OpenSSL NOT found: use `-DWITH_TLS=OFF` to build without TLS support") endif() diff --git a/src/base/net/http/HttpClient.cpp b/src/base/net/http/HttpClient.cpp index d33daf2c..a512989c 100644 --- a/src/base/net/http/HttpClient.cpp +++ b/src/base/net/http/HttpClient.cpp @@ -43,9 +43,9 @@ static const char *kCRLF = "\r\n"; class WriteBaton : public Baton { public: - inline WriteBaton(const std::stringstream &ss, std::string &&body) : + inline WriteBaton(const std::string &header, std::string &&body) : m_body(body), - m_header(ss.str()) + m_header(header) { bufs[0].len = m_header.size(); bufs[0].base = const_cast(m_header.c_str()); @@ -77,9 +77,9 @@ private: } // namespace xmrig -xmrig::HttpClient::HttpClient(const String &host, uint16_t port, int method, const String &url, IHttpListener *listener, const char *data, size_t size) : +xmrig::HttpClient::HttpClient(int method, const String &url, IHttpListener *listener, const char *data, size_t size) : HttpContext(HTTP_RESPONSE, listener), - m_port(port) + m_port(0) { this->method = method; this->url = url; @@ -89,8 +89,6 @@ xmrig::HttpClient::HttpClient(const String &host, uint16_t port, int method, con } m_dns = new Dns(this); - - status = m_dns->resolve(host); } @@ -100,6 +98,20 @@ xmrig::HttpClient::~HttpClient() } +bool xmrig::HttpClient::connect(const String &host, uint16_t port) +{ + m_port = port; + + return m_dns->resolve(host); +} + + +const xmrig::String &xmrig::HttpClient::host() const +{ + return m_dns->host(); +} + + void xmrig::HttpClient::onResolved(const Dns &dns, int status) { this->status = status; @@ -119,7 +131,7 @@ void xmrig::HttpClient::onResolved(const Dns &dns, int status) } -void xmrig::HttpClient::send() +void xmrig::HttpClient::handshake() { headers.insert({ "Host", m_dns->host().data() }); headers.insert({ "Connection", "close" }); @@ -140,7 +152,21 @@ void xmrig::HttpClient::send() headers.clear(); - WriteBaton *baton = new WriteBaton(ss, std::move(body)); + write(ss.str()); +} + + +void xmrig::HttpClient::read(const char *data, size_t size) +{ + if (parse(data, size) < size) { + close(); + } +} + + +void xmrig::HttpClient::write(const std::string &header) +{ + WriteBaton *baton = new WriteBaton(header, std::move(body)); uv_write(&baton->req, stream(), baton->bufs, baton->count(), WriteBaton::onWrite); } @@ -177,12 +203,7 @@ void xmrig::HttpClient::onConnect(uv_connect_t *req, int status) HttpClient *client = static_cast(tcp->data); if (nread >= 0) { - const size_t size = static_cast(nread); - const size_t parsed = client->parse(buf->base, size); - - if (parsed < size) { - client->close(); - } + client->read(buf->base, static_cast(nread)); } else { if (nread != UV_EOF) { LOG_ERR("[%s:%d] read error: \"%s\"", client->m_dns->host().data(), client->m_port, uv_strerror(static_cast(nread))); @@ -194,5 +215,5 @@ void xmrig::HttpClient::onConnect(uv_connect_t *req, int status) delete [] buf->base; }); - client->send(); + client->handshake(); } diff --git a/src/base/net/http/HttpClient.h b/src/base/net/http/HttpClient.h index c31b9a3e..b92c4733 100644 --- a/src/base/net/http/HttpClient.h +++ b/src/base/net/http/HttpClient.h @@ -41,15 +41,22 @@ class String; class HttpClient : public HttpContext, public IDnsListener { public: - HttpClient(const String &host, uint16_t port, int method, const String &url, IHttpListener *listener, const char *data = nullptr, size_t size = 0); - ~HttpClient(); + HttpClient(int method, const String &url, IHttpListener *listener, const char *data = nullptr, size_t size = 0); + ~HttpClient() override; + + inline uint16_t port() const { return m_port; } + + bool connect(const String &host, uint16_t port); + const String &host() const; protected: - void onResolved(const Dns &dns, int status); + void onResolved(const Dns &dns, int status) override; + + virtual void handshake(); + virtual void read(const char *data, size_t size); + virtual void write(const std::string &header); private: - void send(); - static void onConnect(uv_connect_t *req, int status); Dns *m_dns; diff --git a/src/base/net/http/HttpsClient.cpp b/src/base/net/http/HttpsClient.cpp new file mode 100644 index 00000000..8fd26a2e --- /dev/null +++ b/src/base/net/http/HttpsClient.cpp @@ -0,0 +1,150 @@ +/* XMRig + * Copyright 2010 Jeff Garzik + * Copyright 2012-2014 pooler + * Copyright 2014 Lucas Jones + * Copyright 2014-2016 Wolf9466 + * Copyright 2016 Jay D Dee + * Copyright 2017-2018 XMR-Stak , + * Copyright 2014-2019 heapwolf + * Copyright 2018-2019 SChernykh + * Copyright 2016-2019 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 +#include +#include + + +#include "base/net/http/HttpsClient.h" +#include "base/tools/String.h" + + +xmrig::HttpsClient::HttpsClient(int method, const String &url, IHttpListener *listener, const char *data, size_t size) : + HttpClient(method, url, listener, data, size), + m_ready(false), + m_buf(), + m_ssl(nullptr) +{ + m_ctx = SSL_CTX_new(SSLv23_method()); + assert(m_ctx != nullptr); + + if (!m_ctx) { + return; + } + + m_writeBio = BIO_new(BIO_s_mem()); + m_readBio = BIO_new(BIO_s_mem()); + SSL_CTX_set_options(m_ctx, SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3); +} + + +xmrig::HttpsClient::~HttpsClient() +{ + if (m_ctx) { + SSL_CTX_free(m_ctx); + } + + if (m_ssl) { + SSL_free(m_ssl); + } +} + + +void xmrig::HttpsClient::handshake() +{ + m_ssl = SSL_new(m_ctx); + assert(m_ssl != nullptr); + + if (!m_ssl) { + return; + } + + SSL_set_connect_state(m_ssl); + SSL_set_bio(m_ssl, m_readBio, m_writeBio); + SSL_set_tlsext_host_name(m_ssl, host().data()); + + SSL_do_handshake(m_ssl); + + flush(); +} + + +void xmrig::HttpsClient::read(const char *data, size_t size) +{ + BIO_write(m_readBio, data, size); + + if (!SSL_is_init_finished(m_ssl)) { + const int rc = SSL_connect(m_ssl); + + if (rc < 0 && SSL_get_error(m_ssl, rc) == SSL_ERROR_WANT_READ) { + flush(); + } else if (rc == 1) { + X509 *cert = SSL_get_peer_certificate(m_ssl); + if (!verify(cert)) { + X509_free(cert); + return close(); + } + + X509_free(cert); + m_ready = true; + + HttpClient::handshake(); + } + + return; + } + + int bytes_read = 0; + while ((bytes_read = SSL_read(m_ssl, m_buf, sizeof(m_buf))) > 0) { + HttpClient::read(m_buf, static_cast(bytes_read)); + } +} + + +void xmrig::HttpsClient::write(const std::string &header) +{ + SSL_write(m_ssl, (header + body).c_str(), header.size() + body.size()); + flush(); +} + + +bool xmrig::HttpsClient::verify(X509 *cert) const +{ + return cert != nullptr; +} + + +void xmrig::HttpsClient::flush() +{ + uv_buf_t buf; + buf.len = BIO_get_mem_data(m_writeBio, &buf.base); + + if (buf.len == 0) { + return; + } + + bool result = false; + if (uv_is_writable(stream())) { + result = uv_try_write(stream(), &buf, 1) == buf.len; + + if (!result) { + close(); + } + } + + (void) BIO_reset(m_writeBio); +} diff --git a/src/base/net/http/HttpsClient.h b/src/base/net/http/HttpsClient.h new file mode 100644 index 00000000..76b90c66 --- /dev/null +++ b/src/base/net/http/HttpsClient.h @@ -0,0 +1,70 @@ +/* XMRig + * Copyright 2010 Jeff Garzik + * Copyright 2012-2014 pooler + * Copyright 2014 Lucas Jones + * Copyright 2014-2016 Wolf9466 + * Copyright 2016 Jay D Dee + * Copyright 2017-2018 XMR-Stak , + * Copyright 2014-2019 heapwolf + * Copyright 2018-2019 SChernykh + * Copyright 2016-2019 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 XMRIG_HTTPSCLIENT_H +#define XMRIG_HTTPSCLIENT_H + + +typedef struct bio_st BIO; +typedef struct ssl_ctx_st SSL_CTX; +typedef struct ssl_st SSL; +typedef struct x509_st X509; + + +#include "base/net/http/HttpClient.h" + + +namespace xmrig { + + +class HttpsClient : public HttpClient +{ +public: + HttpsClient(int method, const String &url, IHttpListener *listener, const char *data = nullptr, size_t size = 0); + ~HttpsClient() override; + +protected: + void handshake() override; + void read(const char *data, size_t size) override; + void write(const std::string &header) override; + +private: + bool verify(X509 *cert) const; + void flush(); + + BIO *m_readBio; + BIO *m_writeBio; + bool m_ready; + char m_buf[1024 * 2]; + SSL *m_ssl; + SSL_CTX *m_ctx; +}; + + +} // namespace xmrig + + +#endif // XMRIG_HTTPSCLIENT_H From c41889477cf4be49d96abf17223476717877005c Mon Sep 17 00:00:00 2001 From: XMRig Date: Wed, 10 Apr 2019 00:10:02 +0700 Subject: [PATCH 14/34] Fix build. --- src/api/Api.cpp | 2 +- src/api/Api.h | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/api/Api.cpp b/src/api/Api.cpp index 1b7210f6..d1bac212 100644 --- a/src/api/Api.cpp +++ b/src/api/Api.cpp @@ -74,7 +74,7 @@ xmrig::Api::~Api() } -void xmrig::Api::request(const HttpRequest &req) +void xmrig::Api::request(const HttpData &req) { HttpApiRequest request(req, m_base->config()->http().isRestricted()); diff --git a/src/api/Api.h b/src/api/Api.h index 9d391901..0c7fac52 100644 --- a/src/api/Api.h +++ b/src/api/Api.h @@ -38,7 +38,7 @@ namespace xmrig { class ApiRouter; class Base; class Httpd; -class HttpRequest; +class HttpData; class IApiListener; class IApiRequest; class String; @@ -54,7 +54,7 @@ public: inline const char *workerId() const { return m_workerId; } inline void addListener(IApiListener *listener) { m_listeners.push_back(listener); } - void request(const HttpRequest &req); + void request(const HttpData &req); void start(); void stop(); From 1bd8d6350842c73153758db06023c163eff34f39 Mon Sep 17 00:00:00 2001 From: XMRig Date: Wed, 10 Apr 2019 03:42:00 +0700 Subject: [PATCH 15/34] 64bit diff support. --- src/base/net/stratum/Job.h | 2 +- src/base/net/stratum/SubmitResult.h | 8 ++++---- src/net/JobResult.h | 12 ++++++------ src/net/Network.cpp | 8 ++++---- src/net/NetworkState.cpp | 4 ++-- src/net/NetworkState.h | 2 +- 6 files changed, 18 insertions(+), 18 deletions(-) diff --git a/src/base/net/stratum/Job.h b/src/base/net/stratum/Job.h index 8fc3d709..c8dced4b 100644 --- a/src/base/net/stratum/Job.h +++ b/src/base/net/stratum/Job.h @@ -67,7 +67,7 @@ public: inline int threadId() const { return m_threadId; } inline size_t size() const { return m_size; } inline uint32_t *nonce() { return reinterpret_cast(m_blob + 39); } - inline uint32_t diff() const { return static_cast(m_diff); } + inline uint64_t diff() const { return m_diff; } inline uint64_t height() const { return m_height; } inline uint64_t target() const { return m_target; } inline uint8_t fixedByte() const { return *(m_blob + 42); } diff --git a/src/base/net/stratum/SubmitResult.h b/src/base/net/stratum/SubmitResult.h index 583d426f..5abd3e4b 100644 --- a/src/base/net/stratum/SubmitResult.h +++ b/src/base/net/stratum/SubmitResult.h @@ -38,17 +38,17 @@ public: inline SubmitResult() : reqId(0), seq(0), - diff(0), actualDiff(0), + diff(0), elapsed(0), m_start(0) {} - inline SubmitResult(int64_t seq, uint32_t diff, uint64_t actualDiff, int64_t reqId = 0) : + inline SubmitResult(int64_t seq, uint64_t diff, uint64_t actualDiff, int64_t reqId = 0) : reqId(reqId), seq(seq), - diff(diff), actualDiff(actualDiff), + diff(diff), elapsed(0), m_start(Chrono::steadyMSecs()) {} @@ -57,8 +57,8 @@ public: int64_t reqId; int64_t seq; - uint32_t diff; uint64_t actualDiff; + uint64_t diff; uint64_t elapsed; private: diff --git a/src/net/JobResult.h b/src/net/JobResult.h index 9d2300b5..9fe1238e 100644 --- a/src/net/JobResult.h +++ b/src/net/JobResult.h @@ -41,20 +41,20 @@ namespace xmrig { class JobResult { public: - inline JobResult() : poolId(0), diff(0), nonce(0) {} - inline JobResult(int poolId, const String &jobId, const String &clientId, uint32_t nonce, const uint8_t *result, uint32_t diff, const Algorithm &algorithm) : + inline JobResult() : poolId(0), nonce(0), diff(0) {} + inline JobResult(int poolId, const String &jobId, const String &clientId, uint32_t nonce, const uint8_t *result, uint64_t diff, const Algorithm &algorithm) : algorithm(algorithm), poolId(poolId), clientId(clientId), jobId(jobId), - diff(diff), - nonce(nonce) + nonce(nonce), + diff(diff) { memcpy(this->result, result, sizeof(this->result)); } - inline JobResult(const Job &job) : poolId(0), diff(0), nonce(0) + inline JobResult(const Job &job) : poolId(0), nonce(0), diff(0) { jobId = job.id(); clientId = job.clientId(); @@ -75,8 +75,8 @@ public: int poolId; String clientId; String jobId; - uint32_t diff; uint32_t nonce; + uint64_t diff; uint8_t result[32]; }; diff --git a/src/net/Network.cpp b/src/net/Network.cpp index 5de840ea..be853cfa 100644 --- a/src/net/Network.cpp +++ b/src/net/Network.cpp @@ -181,11 +181,11 @@ void xmrig::Network::onResultAccepted(IStrategy *, Client *, const SubmitResult m_state.add(result, error); if (error) { - LOG_INFO(RED_BOLD("rejected") " (%" PRId64 "/%" PRId64 ") diff " WHITE_BOLD("%u") " " RED("\"%s\"") " " BLACK_BOLD("(%" PRIu64 " ms)"), + LOG_INFO(RED_BOLD("rejected") " (%" PRId64 "/%" PRId64 ") diff " WHITE_BOLD("%" PRIu64) " " RED("\"%s\"") " " BLACK_BOLD("(%" PRIu64 " ms)"), m_state.accepted, m_state.rejected, result.diff, error, result.elapsed); } else { - LOG_INFO(GREEN_BOLD("accepted") " (%" PRId64 "/%" PRId64 ") diff " WHITE_BOLD("%u") " " BLACK_BOLD("(%" PRIu64 " ms)"), + LOG_INFO(GREEN_BOLD("accepted") " (%" PRId64 "/%" PRId64 ") diff " WHITE_BOLD("%" PRIu64) " " BLACK_BOLD("(%" PRIu64 " ms)"), m_state.accepted, m_state.rejected, result.diff, result.elapsed); } } @@ -194,11 +194,11 @@ void xmrig::Network::onResultAccepted(IStrategy *, Client *, const SubmitResult void xmrig::Network::setJob(Client *client, const Job &job, bool donate) { if (job.height()) { - LOG_INFO(MAGENTA_BOLD("new job") " from " WHITE_BOLD("%s:%d") " diff " WHITE_BOLD("%d") " algo " WHITE_BOLD("%s") " height " WHITE_BOLD("%" PRIu64), + LOG_INFO(MAGENTA_BOLD("new job") " from " WHITE_BOLD("%s:%d") " diff " WHITE_BOLD("%" PRIu64) " algo " WHITE_BOLD("%s") " height " WHITE_BOLD("%" PRIu64), client->host(), client->port(), job.diff(), job.algorithm().shortName(), job.height()); } else { - LOG_INFO(MAGENTA_BOLD("new job") " from " WHITE_BOLD("%s:%d") " diff " WHITE_BOLD("%d") " algo " WHITE_BOLD("%s"), + LOG_INFO(MAGENTA_BOLD("new job") " from " WHITE_BOLD("%s:%d") " diff " WHITE_BOLD("%" PRIu64) " algo " WHITE_BOLD("%s"), client->host(), client->port(), job.diff(), job.algorithm().shortName()); } diff --git a/src/net/NetworkState.cpp b/src/net/NetworkState.cpp index df248602..c55422db 100644 --- a/src/net/NetworkState.cpp +++ b/src/net/NetworkState.cpp @@ -35,14 +35,14 @@ xmrig::NetworkState::NetworkState() : - diff(0), + pool(), accepted(0), + diff(0), failures(0), rejected(0), total(0), m_active(false) { - memset(pool, 0, sizeof(pool)); } diff --git a/src/net/NetworkState.h b/src/net/NetworkState.h index 2f88d9b3..cf9a649a 100644 --- a/src/net/NetworkState.h +++ b/src/net/NetworkState.h @@ -50,8 +50,8 @@ public: char pool[256]; std::array topDiff { { } }; - uint32_t diff; uint64_t accepted; + uint64_t diff; uint64_t failures; uint64_t rejected; uint64_t total; From 9a6944d6949d38e5911a0483f781594bcfa4d6a3 Mon Sep 17 00:00:00 2001 From: XMRig Date: Wed, 10 Apr 2019 18:29:33 +0700 Subject: [PATCH 16/34] Add IClient and BaseClient. --- src/base/base.cmake | 3 + src/base/kernel/interfaces/IClient.h | 84 +++++++++++++++++++ src/base/kernel/interfaces/IClientListener.h | 12 +-- .../kernel/interfaces/IStrategyListener.h | 10 +-- src/base/net/stratum/BaseClient.cpp | 37 ++++++++ src/base/net/stratum/BaseClient.h | 75 +++++++++++++++++ src/base/net/stratum/Client.cpp | 28 +------ src/base/net/stratum/Client.h | 76 +++++------------ .../stratum/strategies/FailoverStrategy.cpp | 8 +- .../net/stratum/strategies/FailoverStrategy.h | 14 ++-- .../stratum/strategies/SinglePoolStrategy.cpp | 8 +- .../stratum/strategies/SinglePoolStrategy.h | 14 ++-- src/net/Network.cpp | 16 ++-- src/net/Network.h | 8 +- src/net/strategies/DonateStrategy.cpp | 18 ++-- src/net/strategies/DonateStrategy.h | 26 +++--- 16 files changed, 291 insertions(+), 146 deletions(-) create mode 100644 src/base/kernel/interfaces/IClient.h create mode 100644 src/base/net/stratum/BaseClient.cpp create mode 100644 src/base/net/stratum/BaseClient.h diff --git a/src/base/base.cmake b/src/base/base.cmake index 5263ed92..3c7ee1b3 100644 --- a/src/base/base.cmake +++ b/src/base/base.cmake @@ -11,6 +11,7 @@ set(HEADERS_BASE src/base/kernel/config/BaseTransform.h src/base/kernel/Entry.h src/base/kernel/interfaces/IBaseListener.h + src/base/kernel/interfaces/IClient.h src/base/kernel/interfaces/IClientListener.h src/base/kernel/interfaces/IConfig.h src/base/kernel/interfaces/IConfigListener.h @@ -29,6 +30,7 @@ set(HEADERS_BASE src/base/net/dns/Dns.h src/base/net/dns/DnsRecord.h src/base/net/http/Http.h + src/base/net/stratum/BaseClient.h src/base/net/stratum/Client.h src/base/net/stratum/Job.h src/base/net/stratum/Pool.h @@ -64,6 +66,7 @@ set(SOURCES_BASE src/base/net/dns/Dns.cpp src/base/net/dns/DnsRecord.cpp src/base/net/http/Http.cpp + src/base/net/stratum/BaseClient.cpp src/base/net/stratum/Client.cpp src/base/net/stratum/Job.cpp src/base/net/stratum/Pool.cpp diff --git a/src/base/kernel/interfaces/IClient.h b/src/base/kernel/interfaces/IClient.h new file mode 100644 index 00000000..52ef83a1 --- /dev/null +++ b/src/base/kernel/interfaces/IClient.h @@ -0,0 +1,84 @@ +/* XMRig + * Copyright 2010 Jeff Garzik + * Copyright 2012-2014 pooler + * Copyright 2014 Lucas Jones + * Copyright 2014-2016 Wolf9466 + * Copyright 2016 Jay D Dee + * Copyright 2017-2018 XMR-Stak , + * Copyright 2018-2019 SChernykh + * Copyright 2016-2019 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 XMRIG_ICLIENT_H +#define XMRIG_ICLIENT_H + + +#include + + +namespace xmrig { + + +class Algorithm; +class Job; +class JobResult; +class Pool; +class String; + + +class IClient +{ +public: + enum Extension { + EXT_ALGO, + EXT_NICEHASH, + EXT_CONNECT, + EXT_TLS, + EXT_KEEPALIVE, + EXT_MAX + }; + + virtual ~IClient() = default; + + virtual bool disconnect() = 0; + virtual bool hasExtension(Extension extension) const noexcept = 0; + virtual bool isEnabled() const = 0; + virtual bool isTLS() const = 0; + virtual const char *tlsFingerprint() const = 0; + virtual const char *tlsVersion() const = 0; + virtual const Job &job() const = 0; + virtual const Pool &pool() const = 0; + virtual const String &ip() const = 0; + virtual int id() const = 0; + virtual int64_t submit(const JobResult &result) = 0; + virtual void connect() = 0; + virtual void connect(const Pool &pool) = 0; + virtual void deleteLater() = 0; + virtual void setAlgo(const Algorithm &algo) = 0; + virtual void setEnabled(bool enabled) = 0; + virtual void setPool(const Pool &pool) = 0; + virtual void setQuiet(bool quiet) = 0; + virtual void setRetries(int retries) = 0; + virtual void setRetryPause(uint64_t ms) = 0; + virtual void tick(uint64_t now) = 0; + +}; + + +} /* namespace xmrig */ + + +#endif // XMRIG_ICLIENT_H diff --git a/src/base/kernel/interfaces/IClientListener.h b/src/base/kernel/interfaces/IClientListener.h index 753847ee..de4dd81d 100644 --- a/src/base/kernel/interfaces/IClientListener.h +++ b/src/base/kernel/interfaces/IClientListener.h @@ -35,7 +35,7 @@ namespace xmrig { -class Client; +class IClient; class Job; class SubmitResult; @@ -45,11 +45,11 @@ class IClientListener public: virtual ~IClientListener() = default; - virtual void onClose(Client *client, int failures) = 0; - virtual void onJobReceived(Client *client, const Job &job, const rapidjson::Value ¶ms) = 0; - virtual void onLogin(Client *client, rapidjson::Document &doc, rapidjson::Value ¶ms) = 0; - virtual void onLoginSuccess(Client *client) = 0; - virtual void onResultAccepted(Client *client, const SubmitResult &result, const char *error) = 0; + virtual void onClose(IClient *client, int failures) = 0; + virtual void onJobReceived(IClient *client, const Job &job, const rapidjson::Value ¶ms) = 0; + virtual void onLogin(IClient *client, rapidjson::Document &doc, rapidjson::Value ¶ms) = 0; + virtual void onLoginSuccess(IClient *client) = 0; + virtual void onResultAccepted(IClient *client, const SubmitResult &result, const char *error) = 0; }; diff --git a/src/base/kernel/interfaces/IStrategyListener.h b/src/base/kernel/interfaces/IStrategyListener.h index cbec7742..2e63449b 100644 --- a/src/base/kernel/interfaces/IStrategyListener.h +++ b/src/base/kernel/interfaces/IStrategyListener.h @@ -32,7 +32,7 @@ namespace xmrig { -class Client; +class IClient; class IStrategy; class Job; class SubmitResult; @@ -43,10 +43,10 @@ class IStrategyListener public: virtual ~IStrategyListener() = default; - virtual void onActive(IStrategy *strategy, Client *client) = 0; - virtual void onJob(IStrategy *strategy, Client *client, const Job &job) = 0; - virtual void onPause(IStrategy *strategy) = 0; - virtual void onResultAccepted(IStrategy *strategy, Client *client, const SubmitResult &result, const char *error) = 0; + virtual void onActive(IStrategy *strategy, IClient *client) = 0; + virtual void onJob(IStrategy *strategy, IClient *client, const Job &job) = 0; + virtual void onPause(IStrategy *strategy) = 0; + virtual void onResultAccepted(IStrategy *strategy, IClient *client, const SubmitResult &result, const char *error) = 0; }; diff --git a/src/base/net/stratum/BaseClient.cpp b/src/base/net/stratum/BaseClient.cpp new file mode 100644 index 00000000..9107116b --- /dev/null +++ b/src/base/net/stratum/BaseClient.cpp @@ -0,0 +1,37 @@ +/* XMRig + * Copyright 2010 Jeff Garzik + * Copyright 2012-2014 pooler + * Copyright 2014 Lucas Jones + * Copyright 2014-2016 Wolf9466 + * Copyright 2016 Jay D Dee + * Copyright 2017-2018 XMR-Stak , + * Copyright 2018-2019 SChernykh + * Copyright 2016-2019 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 "base/net/stratum/BaseClient.h" + + +xmrig::BaseClient::BaseClient(int id, IClientListener *listener) : + m_quiet(false), + m_listener(listener), + m_id(id), + m_retries(5), + m_retryPause(5000) +{ + +} diff --git a/src/base/net/stratum/BaseClient.h b/src/base/net/stratum/BaseClient.h new file mode 100644 index 00000000..27432a2f --- /dev/null +++ b/src/base/net/stratum/BaseClient.h @@ -0,0 +1,75 @@ +/* XMRig + * Copyright 2010 Jeff Garzik + * Copyright 2012-2014 pooler + * Copyright 2014 Lucas Jones + * Copyright 2014-2016 Wolf9466 + * Copyright 2016 Jay D Dee + * Copyright 2017-2018 XMR-Stak , + * Copyright 2018-2019 SChernykh + * Copyright 2016-2019 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 XMRIG_BASECLIENT_H +#define XMRIG_BASECLIENT_H + + +#include "base/kernel/interfaces/IClient.h" +#include "base/net/stratum/Job.h" +#include "base/net/stratum/Pool.h" + + +namespace xmrig { + + +class IClientListener; + + +class BaseClient : public IClient +{ +public: + BaseClient(int id, IClientListener *listener); + + inline bool isEnabled() const override { return m_enabled; } + inline const Job &job() const override { return m_job; } + inline const Pool &pool() const override { return m_pool; } + inline const String &ip() const override { return m_ip; } + inline int id() const override { return m_id; } + inline void setAlgo(const Algorithm &algo) override { m_pool.setAlgo(algo); } + inline void setEnabled(bool enabled) override { m_enabled = enabled; } + inline void setPool(const Pool &pool) override { if (pool.isValid()) { m_pool = pool; } } + inline void setQuiet(bool quiet) override { m_quiet = quiet; } + inline void setRetries(int retries) override { m_retries = retries; } + inline void setRetryPause(uint64_t ms) override { m_retryPause = ms; } + +protected: + bool m_quiet; + IClientListener *m_listener; + int m_id; + int m_retries; + Job m_job; + Pool m_pool; + String m_ip; + uint64_t m_retryPause; + +private: + bool m_enabled; +}; + + +} /* namespace xmrig */ + + +#endif /* XMRIG_BASECLIENT_H */ diff --git a/src/base/net/stratum/Client.cpp b/src/base/net/stratum/Client.cpp index dba84cb1..27075d48 100644 --- a/src/base/net/stratum/Client.cpp +++ b/src/base/net/stratum/Client.cpp @@ -75,14 +75,8 @@ static const char *states[] = { xmrig::Client::Client(int id, const char *agent, IClientListener *listener) : - m_enabled(true), - m_ipv6(false), - m_quiet(false), + BaseClient(id, listener), m_agent(agent), - m_listener(listener), - m_id(id), - m_retries(5), - m_retryPause(5000), m_failures(0), m_state(UnconnectedState), m_tls(nullptr), @@ -117,14 +111,9 @@ void xmrig::Client::connect() } -/** - * @brief Connect to server. - * - * @param url - */ -void xmrig::Client::connect(const Pool &url) +void xmrig::Client::connect(const Pool &pool) { - setPool(url); + setPool(pool); connect(); } @@ -143,17 +132,6 @@ void xmrig::Client::deleteLater() } - -void xmrig::Client::setPool(const Pool &pool) -{ - if (!pool.isValid()) { - return; - } - - m_pool = pool; -} - - void xmrig::Client::tick(uint64_t now) { if (m_state == ConnectedState) { diff --git a/src/base/net/stratum/Client.h b/src/base/net/stratum/Client.h index 65b44a5b..e334896c 100644 --- a/src/base/net/stratum/Client.h +++ b/src/base/net/stratum/Client.h @@ -34,6 +34,7 @@ #include "base/kernel/interfaces/IDnsListener.h" #include "base/kernel/interfaces/ILineListener.h" +#include "base/net/stratum/BaseClient.h" #include "base/net/stratum/Job.h" #include "base/net/stratum/Pool.h" #include "base/net/stratum/SubmitResult.h" @@ -53,26 +54,9 @@ class IClientListener; class JobResult; -class Client : public IDnsListener, public ILineListener +class Client : public BaseClient, public IDnsListener, public ILineListener { public: - enum SocketState { - UnconnectedState, - HostLookupState, - ConnectingState, - ConnectedState, - ClosingState - }; - - enum Extension { - EXT_ALGO, - EXT_NICEHASH, - EXT_CONNECT, - EXT_TLS, - EXT_KEEPALIVE, - EXT_MAX - }; - constexpr static int kResponseTimeout = 20 * 1000; # ifdef XMRIG_FEATURE_TLS @@ -84,33 +68,17 @@ public: Client(int id, const char *agent, IClientListener *listener); ~Client() override; - bool disconnect(); - bool isTLS() const; - const char *tlsFingerprint() const; - const char *tlsVersion() const; - int64_t submit(const JobResult &result); - void connect(); - void connect(const Pool &pool); - void deleteLater(); - void setPool(const Pool &pool); - void tick(uint64_t now); + bool disconnect() override; + bool isTLS() const override; + const char *tlsFingerprint() const override; + const char *tlsVersion() const override; + int64_t submit(const JobResult &result) override; + void connect() override; + void connect(const Pool &pool) override; + void deleteLater() override; + void tick(uint64_t now) override; - inline bool isEnabled() const { return m_enabled; } - inline bool isReady() const { return m_state == ConnectedState && m_failures == 0; } - inline const char *host() const { return m_pool.host(); } - inline const char *ip() const { return m_ip; } - inline const Job &job() const { return m_job; } - inline const Pool &pool() const { return m_pool; } - inline int id() const { return m_id; } - inline SocketState state() const { return m_state; } - inline uint16_t port() const { return m_pool.port(); } - inline void setAlgo(const Algorithm &algo) { m_pool.setAlgo(algo); } - inline void setEnabled(bool enabled) { m_enabled = enabled; } - inline void setQuiet(bool quiet) { m_quiet = quiet; } - inline void setRetries(int retries) { m_retries = retries; } - inline void setRetryPause(int ms) { m_retryPause = ms; } - - template inline bool has() const noexcept { return m_extensions.test(ext); } + inline bool hasExtension(Extension extension) const noexcept override { return m_extensions.test(extension); } protected: inline void onLine(char *line, size_t size) override { parse(line, size); } @@ -118,6 +86,14 @@ protected: void onResolved(const Dns &dns, int status) override; private: + enum SocketState { + UnconnectedState, + HostLookupState, + ConnectingState, + ConnectedState, + ClosingState + }; + class Tls; bool close(); @@ -145,7 +121,9 @@ private: inline bool isQuiet() const { return m_quiet || m_failures >= m_retries; } inline const char *url() const { return m_pool.url(); } + inline SocketState state() const { return m_state; } inline void setExtension(Extension ext, bool enable) noexcept { m_extensions.set(ext, enable); } + template inline bool has() const noexcept { return m_extensions.test(ext); } static void onAllocBuffer(uv_handle_t *handle, size_t suggested_size, uv_buf_t *buf); static void onClose(uv_handle_t *handle); @@ -154,24 +132,14 @@ private: static inline Client *getClient(void *data) { return m_storage.get(data); } - bool m_enabled; - bool m_ipv6; - bool m_quiet; char m_sendBuf[2048]; const char *m_agent; Dns *m_dns; - IClientListener *m_listener; - int m_id; - int m_retries; - int m_retryPause; int64_t m_failures; - Job m_job; - Pool m_pool; RecvBuf m_recvBuf; SocketState m_state; std::bitset m_extensions; std::map m_results; - String m_ip; String m_rpcId; Tls *m_tls; uint64_t m_expire; diff --git a/src/base/net/stratum/strategies/FailoverStrategy.cpp b/src/base/net/stratum/strategies/FailoverStrategy.cpp index 7a59e2a6..0c574a5d 100644 --- a/src/base/net/stratum/strategies/FailoverStrategy.cpp +++ b/src/base/net/stratum/strategies/FailoverStrategy.cpp @@ -129,7 +129,7 @@ void xmrig::FailoverStrategy::tick(uint64_t now) } -void xmrig::FailoverStrategy::onClose(Client *client, int failures) +void xmrig::FailoverStrategy::onClose(IClient *client, int failures) { if (failures == -1) { return; @@ -150,7 +150,7 @@ void xmrig::FailoverStrategy::onClose(Client *client, int failures) } -void xmrig::FailoverStrategy::onJobReceived(Client *client, const Job &job, const rapidjson::Value &) +void xmrig::FailoverStrategy::onJobReceived(IClient *client, const Job &job, const rapidjson::Value &) { if (m_active == client->id()) { m_listener->onJob(this, client, job); @@ -158,7 +158,7 @@ void xmrig::FailoverStrategy::onJobReceived(Client *client, const Job &job, cons } -void xmrig::FailoverStrategy::onLoginSuccess(Client *client) +void xmrig::FailoverStrategy::onLoginSuccess(IClient *client) { int active = m_active; @@ -179,7 +179,7 @@ void xmrig::FailoverStrategy::onLoginSuccess(Client *client) } -void xmrig::FailoverStrategy::onResultAccepted(Client *client, const SubmitResult &result, const char *error) +void xmrig::FailoverStrategy::onResultAccepted(IClient *client, const SubmitResult &result, const char *error) { m_listener->onResultAccepted(this, client, result, error); } diff --git a/src/base/net/stratum/strategies/FailoverStrategy.h b/src/base/net/stratum/strategies/FailoverStrategy.h index fcebc52f..748eddda 100644 --- a/src/base/net/stratum/strategies/FailoverStrategy.h +++ b/src/base/net/stratum/strategies/FailoverStrategy.h @@ -51,9 +51,9 @@ public: void add(const Pool &pool); 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 {} + inline bool isActive() const override { return m_active >= 0; } + inline Client *client() const override { return active(); } + inline void onLogin(IClient *, rapidjson::Document &, rapidjson::Value &) override {} int64_t submit(const JobResult &result) override; void connect() override; @@ -62,10 +62,10 @@ protected: void stop() override; void tick(uint64_t now) 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; - void onResultAccepted(Client *client, const SubmitResult &result, const char *error) override; + void onClose(IClient *client, int failures) override; + void onJobReceived(IClient *client, const Job &job, const rapidjson::Value ¶ms) override; + void onLoginSuccess(IClient *client) override; + void onResultAccepted(IClient *client, const SubmitResult &result, const char *error) override; private: inline Client *active() const { return m_pools[static_cast(m_active)]; } diff --git a/src/base/net/stratum/strategies/SinglePoolStrategy.cpp b/src/base/net/stratum/strategies/SinglePoolStrategy.cpp index b81594e1..45dce5d9 100644 --- a/src/base/net/stratum/strategies/SinglePoolStrategy.cpp +++ b/src/base/net/stratum/strategies/SinglePoolStrategy.cpp @@ -87,7 +87,7 @@ void xmrig::SinglePoolStrategy::tick(uint64_t now) } -void xmrig::SinglePoolStrategy::onClose(Client *, int) +void xmrig::SinglePoolStrategy::onClose(IClient *, int) { if (!isActive()) { return; @@ -98,20 +98,20 @@ void xmrig::SinglePoolStrategy::onClose(Client *, int) } -void xmrig::SinglePoolStrategy::onJobReceived(Client *client, const Job &job, const rapidjson::Value &) +void xmrig::SinglePoolStrategy::onJobReceived(IClient *client, const Job &job, const rapidjson::Value &) { m_listener->onJob(this, client, job); } -void xmrig::SinglePoolStrategy::onLoginSuccess(Client *client) +void xmrig::SinglePoolStrategy::onLoginSuccess(IClient *client) { m_active = true; m_listener->onActive(this, client); } -void xmrig::SinglePoolStrategy::onResultAccepted(Client *client, const SubmitResult &result, const char *error) +void xmrig::SinglePoolStrategy::onResultAccepted(IClient *client, const SubmitResult &result, const char *error) { m_listener->onResultAccepted(this, client, result, error); } diff --git a/src/base/net/stratum/strategies/SinglePoolStrategy.h b/src/base/net/stratum/strategies/SinglePoolStrategy.h index 8d9f9fd1..b8a4fe1e 100644 --- a/src/base/net/stratum/strategies/SinglePoolStrategy.h +++ b/src/base/net/stratum/strategies/SinglePoolStrategy.h @@ -45,9 +45,9 @@ public: ~SinglePoolStrategy() override; 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 {} + inline bool isActive() const override { return m_active; } + inline Client *client() const override { return m_client; } + inline void onLogin(IClient *, rapidjson::Document &, rapidjson::Value &) override {} int64_t submit(const JobResult &result) override; void connect() override; @@ -56,10 +56,10 @@ protected: void stop() override; void tick(uint64_t now) 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; - void onResultAccepted(Client *client, const SubmitResult &result, const char *error) override; + void onClose(IClient *client, int failures) override; + void onJobReceived(IClient *client, const Job &job, const rapidjson::Value ¶ms) override; + void onLoginSuccess(IClient *client) override; + void onResultAccepted(IClient *client, const SubmitResult &result, const char *error) override; private: bool m_active; diff --git a/src/net/Network.cpp b/src/net/Network.cpp index be853cfa..9a9944eb 100644 --- a/src/net/Network.cpp +++ b/src/net/Network.cpp @@ -91,18 +91,18 @@ void xmrig::Network::connect() } -void xmrig::Network::onActive(IStrategy *strategy, Client *client) +void xmrig::Network::onActive(IStrategy *strategy, IClient *client) { if (m_donate && m_donate == strategy) { LOG_NOTICE("dev donate started"); return; } - m_state.setPool(client->host(), client->port(), client->ip()); + m_state.setPool(client->pool().host(), client->pool().port(), client->ip()); const char *tlsVersion = client->tlsVersion(); LOG_INFO(WHITE_BOLD("use pool ") CYAN_BOLD("%s:%d ") GREEN_BOLD("%s") " " BLACK_BOLD("%s"), - client->host(), client->port(), tlsVersion ? tlsVersion : "", client->ip()); + client->pool().host().data(), client->pool().port(), tlsVersion ? tlsVersion : "", client->ip().data()); const char *fingerprint = client->tlsFingerprint(); if (fingerprint != nullptr) { @@ -127,7 +127,7 @@ void xmrig::Network::onConfigChanged(Config *config, Config *previousConfig) } -void xmrig::Network::onJob(IStrategy *strategy, Client *client, const Job &job) +void xmrig::Network::onJob(IStrategy *strategy, IClient *client, const Job &job) { if (m_donate && m_donate->isActive() && m_donate != strategy) { return; @@ -176,7 +176,7 @@ void xmrig::Network::onRequest(IApiRequest &request) } -void xmrig::Network::onResultAccepted(IStrategy *, Client *, const SubmitResult &result, const char *error) +void xmrig::Network::onResultAccepted(IStrategy *, IClient *, const SubmitResult &result, const char *error) { m_state.add(result, error); @@ -191,15 +191,15 @@ void xmrig::Network::onResultAccepted(IStrategy *, Client *, const SubmitResult } -void xmrig::Network::setJob(Client *client, const Job &job, bool donate) +void xmrig::Network::setJob(IClient *client, const Job &job, bool donate) { if (job.height()) { LOG_INFO(MAGENTA_BOLD("new job") " from " WHITE_BOLD("%s:%d") " diff " WHITE_BOLD("%" PRIu64) " algo " WHITE_BOLD("%s") " height " WHITE_BOLD("%" PRIu64), - client->host(), client->port(), job.diff(), job.algorithm().shortName(), job.height()); + client->pool().host().data(), client->pool().port(), job.diff(), job.algorithm().shortName(), job.height()); } else { LOG_INFO(MAGENTA_BOLD("new job") " from " WHITE_BOLD("%s:%d") " diff " WHITE_BOLD("%" PRIu64) " algo " WHITE_BOLD("%s"), - client->host(), client->port(), job.diff(), job.algorithm().shortName()); + client->pool().host().data(), client->pool().port(), job.diff(), job.algorithm().shortName()); } if (!donate && m_donate) { diff --git a/src/net/Network.h b/src/net/Network.h index 1b8f4934..cee15f69 100644 --- a/src/net/Network.h +++ b/src/net/Network.h @@ -58,18 +58,18 @@ public: protected: inline void onTimer(const Timer *) override { tick(); } - void onActive(IStrategy *strategy, Client *client) override; + void onActive(IStrategy *strategy, IClient *client) override; void onConfigChanged(Config *config, Config *previousConfig) override; - void onJob(IStrategy *strategy, Client *client, const Job &job) override; + void onJob(IStrategy *strategy, IClient *client, const Job &job) override; void onJobResult(const JobResult &result) override; void onPause(IStrategy *strategy) override; void onRequest(IApiRequest &request) override; - void onResultAccepted(IStrategy *strategy, Client *client, const SubmitResult &result, const char *error) override; + void onResultAccepted(IStrategy *strategy, IClient *client, const SubmitResult &result, const char *error) override; private: constexpr static int kTickInterval = 1 * 1000; - void setJob(Client *client, const Job &job, bool donate); + void setJob(IClient *client, const Job &job, bool donate); void tick(); # ifdef XMRIG_FEATURE_API diff --git a/src/net/strategies/DonateStrategy.cpp b/src/net/strategies/DonateStrategy.cpp index 9275bde9..7a9f9e60 100644 --- a/src/net/strategies/DonateStrategy.cpp +++ b/src/net/strategies/DonateStrategy.cpp @@ -157,7 +157,7 @@ void xmrig::DonateStrategy::tick(uint64_t now) } -void xmrig::DonateStrategy::onActive(IStrategy *, Client *client) +void xmrig::DonateStrategy::onActive(IStrategy *, IClient *client) { if (isActive()) { return; @@ -173,7 +173,7 @@ void xmrig::DonateStrategy::onPause(IStrategy *) } -void xmrig::DonateStrategy::onClose(Client *, int failures) +void xmrig::DonateStrategy::onClose(IClient *, int failures) { if (failures == 2 && m_controller->config()->pools().proxyDonate() == Pools::PROXY_DONATE_AUTO) { m_proxy->deleteLater(); @@ -184,7 +184,7 @@ void xmrig::DonateStrategy::onClose(Client *, int failures) } -void xmrig::DonateStrategy::onLogin(Client *, rapidjson::Document &doc, rapidjson::Value ¶ms) +void xmrig::DonateStrategy::onLogin(IClient *, rapidjson::Document &doc, rapidjson::Value ¶ms) { auto &allocator = doc.GetAllocator(); @@ -203,7 +203,7 @@ void xmrig::DonateStrategy::onLogin(Client *, rapidjson::Document &doc, rapidjso } -void xmrig::DonateStrategy::onLoginSuccess(Client *client) +void xmrig::DonateStrategy::onLoginSuccess(IClient *client) { if (isActive()) { return; @@ -227,14 +227,14 @@ xmrig::Client *xmrig::DonateStrategy::createProxy() } IStrategy *strategy = m_controller->network()->strategy(); - if (!strategy->isActive() || !strategy->client()->has()) { + if (!strategy->isActive() || !strategy->client()->hasExtension(IClient::EXT_CONNECT)) { return nullptr; } const Client *client = strategy->client(); - m_tls = client->has(); + m_tls = client->hasExtension(IClient::EXT_TLS); - Pool pool(client->ip(), client->port(), m_userId, client->pool().password(), 0, true, client->isTLS()); + Pool pool(client->ip(), client->pool().port(), m_userId, client->pool().password(), 0, true, client->isTLS()); pool.setAlgo(client->pool().algorithm()); Client *proxy = new Client(-1, Platform::userAgent(), this); @@ -251,7 +251,7 @@ void xmrig::DonateStrategy::idle(double min, double max) } -void xmrig::DonateStrategy::setJob(Client *client, const Job &job) +void xmrig::DonateStrategy::setJob(IClient *client, const Job &job) { if (isActive()) { m_listener->onJob(this, client, job); @@ -259,7 +259,7 @@ void xmrig::DonateStrategy::setJob(Client *client, const Job &job) } -void xmrig::DonateStrategy::setResult(Client *client, const SubmitResult &result, const char *error) +void xmrig::DonateStrategy::setResult(IClient *client, const SubmitResult &result, const char *error) { m_listener->onResultAccepted(this, client, result, error); } diff --git a/src/net/strategies/DonateStrategy.h b/src/net/strategies/DonateStrategy.h index 827596f3..69bf8dbd 100644 --- a/src/net/strategies/DonateStrategy.h +++ b/src/net/strategies/DonateStrategy.h @@ -51,13 +51,13 @@ public: ~DonateStrategy() 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 {} + 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 *, IClient *client, const Job &job) override { setJob(client, job); } + inline void onJobReceived(IClient *client, const Job &job, const rapidjson::Value &) override { setJob(client, job); } + inline void onResultAccepted(IClient *client, const SubmitResult &result, const char *error) override { setResult(client, result, error); } + inline void onResultAccepted(IStrategy *, IClient *client, const SubmitResult &result, const char *error) override { setResult(client, result, error); } + inline void resume() override {} int64_t submit(const JobResult &result) override; void connect() override; @@ -65,12 +65,12 @@ protected: void stop() override; void tick(uint64_t now) override; - void onActive(IStrategy *strategy, Client *client) override; + void onActive(IStrategy *strategy, IClient *client) override; void onPause(IStrategy *strategy) override; - void onClose(Client *client, int failures) override; - void onLogin(Client *client, rapidjson::Document &doc, rapidjson::Value ¶ms) override; - void onLoginSuccess(Client *client) override; + void onClose(IClient *client, int failures) override; + void onLogin(IClient *client, rapidjson::Document &doc, rapidjson::Value ¶ms) override; + void onLoginSuccess(IClient *client) override; void onTimer(const Timer *timer) override; @@ -87,8 +87,8 @@ private: 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 setJob(IClient *client, const Job &job); + void setResult(IClient *client, const SubmitResult &result, const char *error); void setState(State state); bool m_tls; From 0d496aaf2f638e41937fe8358bc60f7695aeb4b3 Mon Sep 17 00:00:00 2001 From: XMRig Date: Thu, 11 Apr 2019 00:18:33 +0700 Subject: [PATCH 17/34] Prepare for daemon support. --- src/base/kernel/interfaces/IClient.h | 1 + src/base/net/stratum/Client.h | 1 + src/base/net/stratum/Job.cpp | 6 +- src/base/net/stratum/Job.h | 4 +- src/base/net/stratum/Pool.cpp | 117 ++++++++++++++++++--------- src/base/net/stratum/Pool.h | 9 ++- src/net/Network.cpp | 5 +- src/net/Network.h | 1 + 8 files changed, 97 insertions(+), 47 deletions(-) diff --git a/src/base/kernel/interfaces/IClient.h b/src/base/kernel/interfaces/IClient.h index 52ef83a1..c872a37a 100644 --- a/src/base/kernel/interfaces/IClient.h +++ b/src/base/kernel/interfaces/IClient.h @@ -57,6 +57,7 @@ public: virtual bool hasExtension(Extension extension) const noexcept = 0; virtual bool isEnabled() const = 0; virtual bool isTLS() const = 0; + virtual const char *mode() const = 0; virtual const char *tlsFingerprint() const = 0; virtual const char *tlsVersion() const = 0; virtual const Job &job() const = 0; diff --git a/src/base/net/stratum/Client.h b/src/base/net/stratum/Client.h index e334896c..b42fa613 100644 --- a/src/base/net/stratum/Client.h +++ b/src/base/net/stratum/Client.h @@ -79,6 +79,7 @@ public: void tick(uint64_t now) override; inline bool hasExtension(Extension extension) const noexcept override { return m_extensions.test(extension); } + inline const char *mode() const override { return "pool"; } protected: inline void onLine(char *line, size_t size) override { parse(line, size); } diff --git a/src/base/net/stratum/Job.cpp b/src/base/net/stratum/Job.cpp index f8239459..8ef607ad 100644 --- a/src/base/net/stratum/Job.cpp +++ b/src/base/net/stratum/Job.cpp @@ -7,6 +7,7 @@ * Copyright 2017-2018 XMR-Stak , * Copyright 2018 Lee Clagett * Copyright 2018 SChernykh + * Copyright 2019 Howard Chu * Copyright 2016-2019 XMRig , * * This program is free software: you can redistribute it and/or modify @@ -180,9 +181,10 @@ void xmrig::Job::setAlgorithm(const char *algo) } -void xmrig::Job::setHeight(uint64_t height) +void xmrig::Job::setDiff(uint64_t diff) { - m_height = height; + m_diff = diff; + m_target = toDiff(diff); } diff --git a/src/base/net/stratum/Job.h b/src/base/net/stratum/Job.h index c8dced4b..16e9a861 100644 --- a/src/base/net/stratum/Job.h +++ b/src/base/net/stratum/Job.h @@ -7,6 +7,7 @@ * Copyright 2017-2018 XMR-Stak , * Copyright 2018 Lee Clagett * Copyright 2018-2019 SChernykh + * Copyright 2019 Howard Chu * Copyright 2016-2019 XMRig , * * This program is free software: you can redistribute it and/or modify @@ -53,7 +54,7 @@ public: bool setBlob(const char *blob); bool setTarget(const char *target); void setAlgorithm(const char *algo); - void setHeight(uint64_t height); + void setDiff(uint64_t diff); inline bool isNicehash() const { return m_nicehash; } inline bool isValid() const { return m_size > 0 && m_diff > 0; } @@ -73,6 +74,7 @@ public: inline uint8_t fixedByte() const { return *(m_blob + 42); } inline void reset() { m_size = 0; m_diff = 0; } inline void setClientId(const String &id) { m_clientId = id; } + inline void setHeight(uint64_t height) { m_height = height; } inline void setPoolId(int poolId) { m_poolId = poolId; } inline void setThreadId(int threadId) { m_threadId = threadId; } inline void setVariant(const char *variant) { m_algorithm.parseVariant(variant); } diff --git a/src/base/net/stratum/Pool.cpp b/src/base/net/stratum/Pool.cpp index 25fd13aa..d23781ad 100644 --- a/src/base/net/stratum/Pool.cpp +++ b/src/base/net/stratum/Pool.cpp @@ -6,6 +6,7 @@ * Copyright 2016 Jay D Dee * Copyright 2017-2019 XMR-Stak , * Copyright 2018-2019 SChernykh + * Copyright 2019 Howard Chu * Copyright 2016-2019 XMRig , * * This program is free software: you can redistribute it and/or modify @@ -41,25 +42,34 @@ #ifdef _MSC_VER # define strncasecmp _strnicmp -# define strcasecmp _stricmp #endif namespace xmrig { -static const char *kEnabled = "enabled"; -static const char *kFingerprint = "tls-fingerprint"; -static const char *kKeepalive = "keepalive"; -static const char *kNicehash = "nicehash"; -static const char *kPass = "pass"; -static const char *kRigId = "rig-id"; -static const char *kTls = "tls"; -static const char *kUrl = "url"; -static const char *kUser = "user"; -static const char *kVariant = "variant"; +static const char *kDaemon = "daemon"; +static const char *kDaemonPollInterval = "daemon-poll-interval"; +static const char *kEnabled = "enabled"; +static const char *kFingerprint = "tls-fingerprint"; +static const char *kKeepalive = "keepalive"; +static const char *kNicehash = "nicehash"; +static const char *kPass = "pass"; +static const char *kRigId = "rig-id"; +static const char *kTls = "tls"; +static const char *kUrl = "url"; +static const char *kUser = "user"; +static const char *kVariant = "variant"; -const String Pool::kDefaultPassword = "x"; -const String Pool::kDefaultUser = "x"; +const String Pool::kDefaultPassword = "x"; +const String Pool::kDefaultUser = "x"; + +static const char kStratumTcp[] = "stratum+tcp://"; +static const char kStratumSsl[] = "stratum+ssl://"; + +#ifdef XMRIG_FEATURE_HTTP +static const char kDaemonHttp[] = "daemon+http://"; +static const char kDaemonHttps[] = "daemon+https://"; +#endif } @@ -67,7 +77,8 @@ const String Pool::kDefaultUser = "x"; xmrig::Pool::Pool() : m_keepAlive(0), m_flags(0), - m_port(kDefaultPort) + m_port(kDefaultPort), + m_pollInterval(kDefaultPollInterval) { } @@ -86,7 +97,8 @@ xmrig::Pool::Pool() : xmrig::Pool::Pool(const char *url) : m_keepAlive(0), m_flags(1), - m_port(kDefaultPort) + m_port(kDefaultPort), + m_pollInterval(kDefaultPollInterval) { parse(url); } @@ -95,20 +107,23 @@ xmrig::Pool::Pool(const char *url) : xmrig::Pool::Pool(const rapidjson::Value &object) : m_keepAlive(0), m_flags(1), - m_port(kDefaultPort) + m_port(kDefaultPort), + m_pollInterval(kDefaultPollInterval) { if (!parse(Json::getString(object, kUrl))) { return; } - m_user = Json::getString(object, kUser); - m_password = Json::getString(object, kPass); - m_rigId = Json::getString(object, kRigId); - m_fingerprint = Json::getString(object, kFingerprint); + m_user = Json::getString(object, kUser); + m_password = Json::getString(object, kPass); + m_rigId = Json::getString(object, kRigId); + m_fingerprint = Json::getString(object, kFingerprint); + m_pollInterval = Json::getUint64(object, kDaemonPollInterval, kDefaultPollInterval); m_flags.set(FLAG_ENABLED, Json::getBool(object, kEnabled, true)); m_flags.set(FLAG_NICEHASH, Json::getBool(object, kNicehash)); m_flags.set(FLAG_TLS, Json::getBool(object, kTls, m_flags.test(FLAG_TLS))); + m_flags.set(FLAG_DAEMON, Json::getBool(object, kDaemon, m_flags.test(FLAG_DAEMON))); const rapidjson::Value &keepalive = Json::getValue(object, kKeepalive); if (keepalive.IsInt()) { @@ -135,7 +150,8 @@ xmrig::Pool::Pool(const char *host, uint16_t port, const char *user, const char m_host(host), m_password(password), m_user(user), - m_port(port) + m_port(port), + m_pollInterval(kDefaultPollInterval) { const size_t size = m_host.size() + 8; assert(size > 8); @@ -180,22 +196,29 @@ bool xmrig::Pool::isEnabled() const } # endif +# ifndef XMRIG_FEATURE_HTTP + if (isDaemon()) { + return false; + } +# endif + return m_flags.test(FLAG_ENABLED) && isValid() && algorithm().isValid(); } bool xmrig::Pool::isEqual(const Pool &other) const { - return (m_flags == other.m_flags - && m_keepAlive == other.m_keepAlive - && m_port == other.m_port - && m_algorithm == other.m_algorithm - && m_fingerprint == other.m_fingerprint - && m_host == other.m_host - && m_password == other.m_password - && m_rigId == other.m_rigId - && m_url == other.m_url - && m_user == other.m_user); + return (m_flags == other.m_flags + && m_keepAlive == other.m_keepAlive + && m_port == other.m_port + && m_algorithm == other.m_algorithm + && m_fingerprint == other.m_fingerprint + && m_host == other.m_host + && m_password == other.m_password + && m_rigId == other.m_rigId + && m_url == other.m_url + && m_user == other.m_user + && m_pollInterval == other.m_pollInterval); } @@ -203,21 +226,33 @@ bool xmrig::Pool::parse(const char *url) { assert(url != nullptr); - const char *p = strstr(url, "://"); + const char *p = strstr(url, "://"); const char *base = url; if (p) { - if (strncasecmp(url, "stratum+tcp://", 14) == 0) { - m_flags.set(FLAG_TLS, false); + if (strncasecmp(url, kStratumTcp, sizeof(kStratumTcp) - 1) == 0) { + m_flags.set(FLAG_DAEMON, false); + m_flags.set(FLAG_TLS, false); } - else if (strncasecmp(url, "stratum+ssl://", 14) == 0) { - m_flags.set(FLAG_TLS, true); + else if (strncasecmp(url, kStratumSsl, sizeof(kStratumSsl) - 1) == 0) { + m_flags.set(FLAG_DAEMON, false); + m_flags.set(FLAG_TLS, true); } +# ifdef XMRIG_FEATURE_HTTP + else if (strncasecmp(url, kDaemonHttps, sizeof(kDaemonHttps) - 1) == 0) { + m_flags.set(FLAG_DAEMON, true); + m_flags.set(FLAG_TLS, true); + } + else if (strncasecmp(url, kDaemonHttp, sizeof(kDaemonHttp) - 1) == 0) { + m_flags.set(FLAG_DAEMON, true); + m_flags.set(FLAG_TLS, false); + } +# endif else { return false; } - base = url + 14; + base = p + 3; } if (!strlen(base) || *base == '/') { @@ -286,9 +321,11 @@ rapidjson::Value xmrig::Pool::toJSON(rapidjson::Document &doc) const break; } - obj.AddMember(StringRef(kEnabled), m_flags.test(FLAG_ENABLED), allocator); - obj.AddMember(StringRef(kTls), isTLS(), allocator); - obj.AddMember(StringRef(kFingerprint), m_fingerprint.toJSON(), allocator); + obj.AddMember(StringRef(kEnabled), m_flags.test(FLAG_ENABLED), allocator); + obj.AddMember(StringRef(kTls), isTLS(), allocator); + obj.AddMember(StringRef(kFingerprint), m_fingerprint.toJSON(), allocator); + obj.AddMember(StringRef(kDaemon), m_flags.test(FLAG_DAEMON), allocator); + obj.AddMember(StringRef(kDaemonPollInterval), m_pollInterval, allocator); return obj; } diff --git a/src/base/net/stratum/Pool.h b/src/base/net/stratum/Pool.h index c8a7c44b..d3c9b141 100644 --- a/src/base/net/stratum/Pool.h +++ b/src/base/net/stratum/Pool.h @@ -6,6 +6,7 @@ * Copyright 2016 Jay D Dee * Copyright 2017-2018 XMR-Stak , * Copyright 2018-2019 SChernykh + * Copyright 2019 Howard Chu * Copyright 2016-2019 XMRig , * * This program is free software: you can redistribute it and/or modify @@ -45,14 +46,16 @@ public: FLAG_ENABLED, FLAG_NICEHASH, FLAG_TLS, + FLAG_DAEMON, FLAG_MAX }; static const String kDefaultPassword; static const String kDefaultUser; - constexpr static uint16_t kDefaultPort = 3333; - constexpr static int kKeepAliveTimeout = 60; + constexpr static int kKeepAliveTimeout = 60; + constexpr static uint16_t kDefaultPort = 3333; + constexpr static uint64_t kDefaultPollInterval = 1000; Pool(); Pool(const char *url); @@ -67,6 +70,7 @@ public: ); inline Algorithm &algorithm() { return m_algorithm; } + inline bool isDaemon() const { return m_flags.test(FLAG_DAEMON); } inline bool isNicehash() const { return m_flags.test(FLAG_NICEHASH); } inline bool isTLS() const { return m_flags.test(FLAG_TLS); } inline bool isValid() const { return !m_host.isNull() && m_port > 0; } @@ -116,6 +120,7 @@ private: String m_url; String m_user; uint16_t m_port; + uint64_t m_pollInterval; }; diff --git a/src/net/Network.cpp b/src/net/Network.cpp index 9a9944eb..cc5d59e4 100644 --- a/src/net/Network.cpp +++ b/src/net/Network.cpp @@ -6,6 +6,7 @@ * Copyright 2016 Jay D Dee * Copyright 2017-2018 XMR-Stak , * Copyright 2018-2019 SChernykh + * Copyright 2019 Howard Chu * Copyright 2016-2019 XMRig , * * This program is free software: you can redistribute it and/or modify @@ -101,8 +102,8 @@ void xmrig::Network::onActive(IStrategy *strategy, IClient *client) m_state.setPool(client->pool().host(), client->pool().port(), client->ip()); const char *tlsVersion = client->tlsVersion(); - LOG_INFO(WHITE_BOLD("use pool ") CYAN_BOLD("%s:%d ") GREEN_BOLD("%s") " " BLACK_BOLD("%s"), - client->pool().host().data(), client->pool().port(), tlsVersion ? tlsVersion : "", client->ip().data()); + LOG_INFO(WHITE_BOLD("use %s ") CYAN_BOLD("%s:%d ") GREEN_BOLD("%s") " " BLACK_BOLD("%s"), + client->mode(), client->pool().host().data(), client->pool().port(), tlsVersion ? tlsVersion : "", client->ip().data()); const char *fingerprint = client->tlsFingerprint(); if (fingerprint != nullptr) { diff --git a/src/net/Network.h b/src/net/Network.h index cee15f69..079d997a 100644 --- a/src/net/Network.h +++ b/src/net/Network.h @@ -6,6 +6,7 @@ * Copyright 2016 Jay D Dee * Copyright 2017-2018 XMR-Stak , * Copyright 2018-2019 SChernykh + * Copyright 2019 Howard Chu * Copyright 2016-2019 XMRig , * * This program is free software: you can redistribute it and/or modify From cf7ce13986e81b7c359a08149bb97b4d78901c04 Mon Sep 17 00:00:00 2001 From: stoffu Date: Thu, 11 Apr 2019 14:01:07 +0900 Subject: [PATCH 18/34] Config: fix std::max issue with msvc2017 to fix the following errors: xmrig\src\core\Config.cpp(165): error C2065: 'max': undeclared identifier xmrig\src\core\Config.cpp(165): error C2275: 'size_t': illegal use of this type as an expression --- src/core/Config.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/core/Config.cpp b/src/core/Config.cpp index 82a96117..9216027a 100644 --- a/src/core/Config.cpp +++ b/src/core/Config.cpp @@ -22,6 +22,7 @@ * along with this program. If not, see . */ +#include #include #include #include From 62012a1a50a6bcddd905e60c88f330ec41e5c6e3 Mon Sep 17 00:00:00 2001 From: XMRig Date: Fri, 12 Apr 2019 03:25:21 +0700 Subject: [PATCH 19/34] Added DaemonClient. --- src/base/base.cmake | 2 + src/base/kernel/interfaces/IStrategy.h | 4 +- src/base/net/http/HttpClient.cpp | 28 +- src/base/net/http/HttpClient.h | 4 +- src/base/net/http/HttpContext.cpp | 10 +- src/base/net/http/HttpContext.h | 2 +- src/base/net/http/HttpsClient.cpp | 4 +- src/base/net/stratum/BaseClient.cpp | 27 +- src/base/net/stratum/BaseClient.h | 21 ++ src/base/net/stratum/Client.cpp | 122 +++--- src/base/net/stratum/Client.h | 25 +- src/base/net/stratum/DaemonClient.cpp | 350 ++++++++++++++++++ src/base/net/stratum/DaemonClient.h | 78 ++++ src/base/net/stratum/Pool.h | 1 + .../stratum/strategies/FailoverStrategy.cpp | 21 +- .../net/stratum/strategies/FailoverStrategy.h | 6 +- .../stratum/strategies/SinglePoolStrategy.cpp | 15 + .../stratum/strategies/SinglePoolStrategy.h | 4 +- src/net/strategies/DonateStrategy.cpp | 4 +- src/net/strategies/DonateStrategy.h | 4 +- 20 files changed, 610 insertions(+), 122 deletions(-) create mode 100644 src/base/net/stratum/DaemonClient.cpp create mode 100644 src/base/net/stratum/DaemonClient.h diff --git a/src/base/base.cmake b/src/base/base.cmake index 3c7ee1b3..6d478b39 100644 --- a/src/base/base.cmake +++ b/src/base/base.cmake @@ -108,6 +108,7 @@ if (WITH_HTTP) src/base/net/http/HttpData.h src/base/net/http/HttpResponse.h src/base/net/http/HttpServer.h + src/base/net/stratum/DaemonClient.h src/base/net/tools/TcpServer.h ) @@ -118,6 +119,7 @@ if (WITH_HTTP) src/base/net/http/HttpContext.cpp src/base/net/http/HttpResponse.cpp src/base/net/http/HttpServer.cpp + src/base/net/stratum/DaemonClient.cpp src/base/net/tools/TcpServer.cpp ) diff --git a/src/base/kernel/interfaces/IStrategy.h b/src/base/kernel/interfaces/IStrategy.h index 31798b9c..f2e58408 100644 --- a/src/base/kernel/interfaces/IStrategy.h +++ b/src/base/kernel/interfaces/IStrategy.h @@ -33,7 +33,7 @@ namespace xmrig { class Algorithm; -class Client; +class IClient; class JobResult; @@ -43,7 +43,7 @@ public: virtual ~IStrategy() = default; virtual bool isActive() const = 0; - virtual Client *client() const = 0; + virtual IClient *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/http/HttpClient.cpp b/src/base/net/http/HttpClient.cpp index a512989c..d58e7299 100644 --- a/src/base/net/http/HttpClient.cpp +++ b/src/base/net/http/HttpClient.cpp @@ -40,11 +40,11 @@ namespace xmrig { static const char *kCRLF = "\r\n"; -class WriteBaton : public Baton +class ClientWriteBaton : public Baton { public: - inline WriteBaton(const std::string &header, std::string &&body) : - m_body(body), + inline ClientWriteBaton(const std::string &header, std::string &&body) : + m_body(std::move(body)), m_header(header) { bufs[0].len = m_header.size(); @@ -63,7 +63,7 @@ public: inline size_t count() const { return bufs[1].base == nullptr ? 1 : 2; } inline size_t size() const { return bufs[0].len + bufs[1].len; } - inline static void onWrite(uv_write_t *req, int) { delete reinterpret_cast(req->data); } + inline static void onWrite(uv_write_t *req, int) { delete reinterpret_cast(req->data); } uv_buf_t bufs[2]; @@ -117,7 +117,9 @@ void xmrig::HttpClient::onResolved(const Dns &dns, int status) this->status = status; if (status < 0 && dns.isEmpty()) { - LOG_ERR("[%s:%d] DNS error: \"%s\"", dns.host().data(), m_port, uv_strerror(status)); + if (!m_quiet) { + LOG_ERR("[%s:%d] DNS error: \"%s\"", dns.host().data(), m_port, uv_strerror(status)); + } return; } @@ -159,15 +161,15 @@ void xmrig::HttpClient::handshake() void xmrig::HttpClient::read(const char *data, size_t size) { if (parse(data, size) < size) { - close(); + close(UV_EPROTO); } } void xmrig::HttpClient::write(const std::string &header) { - WriteBaton *baton = new WriteBaton(header, std::move(body)); - uv_write(&baton->req, stream(), baton->bufs, baton->count(), WriteBaton::onWrite); + ClientWriteBaton *baton = new ClientWriteBaton(header, std::move(body)); + uv_write(&baton->req, stream(), baton->bufs, baton->count(), ClientWriteBaton::onWrite); } @@ -180,10 +182,12 @@ void xmrig::HttpClient::onConnect(uv_connect_t *req, int status) } if (status < 0) { - LOG_ERR("[%s:%d] connect error: \"%s\"", client->m_dns->host().data(), client->m_port, uv_strerror(status)); + if (!client->m_quiet) { + LOG_ERR("[%s:%d] connect error: \"%s\"", client->m_dns->host().data(), client->m_port, uv_strerror(status)); + } delete req; - client->close(); + client->close(status); return; } @@ -205,11 +209,11 @@ void xmrig::HttpClient::onConnect(uv_connect_t *req, int status) if (nread >= 0) { client->read(buf->base, static_cast(nread)); } else { - if (nread != UV_EOF) { + if (!client->m_quiet && nread != UV_EOF) { LOG_ERR("[%s:%d] read error: \"%s\"", client->m_dns->host().data(), client->m_port, uv_strerror(static_cast(nread))); } - client->close(); + client->close(static_cast(nread)); } delete [] buf->base; diff --git a/src/base/net/http/HttpClient.h b/src/base/net/http/HttpClient.h index b92c4733..e9866483 100644 --- a/src/base/net/http/HttpClient.h +++ b/src/base/net/http/HttpClient.h @@ -44,7 +44,8 @@ public: HttpClient(int method, const String &url, IHttpListener *listener, const char *data = nullptr, size_t size = 0); ~HttpClient() override; - inline uint16_t port() const { return m_port; } + inline uint16_t port() const { return m_port; } + inline void setQuiet(bool quiet) { m_quiet = quiet; } bool connect(const String &host, uint16_t port); const String &host() const; @@ -59,6 +60,7 @@ protected: private: static void onConnect(uv_connect_t *req, int status); + bool m_quiet; Dns *m_dns; uint16_t m_port; }; diff --git a/src/base/net/http/HttpContext.cpp b/src/base/net/http/HttpContext.cpp index c98b4ad2..e97f989b 100644 --- a/src/base/net/http/HttpContext.cpp +++ b/src/base/net/http/HttpContext.cpp @@ -96,8 +96,13 @@ std::string xmrig::HttpContext::ip() const } -void xmrig::HttpContext::close() +void xmrig::HttpContext::close(int status) { + if (status < 0 && m_listener) { + this->status = status; + m_listener->onHttpData(*this); + } + auto it = storage.find(id()); if (it != storage.end()) { storage.erase(it); @@ -203,8 +208,9 @@ void xmrig::HttpContext::attach(http_parser_settings *settings) settings->on_message_complete = [](http_parser *parser) -> int { - const HttpContext *ctx = static_cast(parser->data); + HttpContext *ctx = static_cast(parser->data); ctx->m_listener->onHttpData(*ctx); + ctx->m_listener = nullptr; return 0; }; diff --git a/src/base/net/http/HttpContext.h b/src/base/net/http/HttpContext.h index ee11a072..fbb453aa 100644 --- a/src/base/net/http/HttpContext.h +++ b/src/base/net/http/HttpContext.h @@ -56,7 +56,7 @@ public: size_t parse(const char *data, size_t size); std::string ip() const; - void close(); + void close(int status = 0); static HttpContext *get(uint64_t id); static void closeAll(); diff --git a/src/base/net/http/HttpsClient.cpp b/src/base/net/http/HttpsClient.cpp index 8fd26a2e..ff103a34 100644 --- a/src/base/net/http/HttpsClient.cpp +++ b/src/base/net/http/HttpsClient.cpp @@ -96,7 +96,7 @@ void xmrig::HttpsClient::read(const char *data, size_t size) X509 *cert = SSL_get_peer_certificate(m_ssl); if (!verify(cert)) { X509_free(cert); - return close(); + return close(UV_EPROTO); } X509_free(cert); @@ -142,7 +142,7 @@ void xmrig::HttpsClient::flush() result = uv_try_write(stream(), &buf, 1) == buf.len; if (!result) { - close(); + close(UV_EIO); } } diff --git a/src/base/net/stratum/BaseClient.cpp b/src/base/net/stratum/BaseClient.cpp index 9107116b..f44415d5 100644 --- a/src/base/net/stratum/BaseClient.cpp +++ b/src/base/net/stratum/BaseClient.cpp @@ -23,7 +23,16 @@ */ +#include "base/kernel/interfaces/IClientListener.h" #include "base/net/stratum/BaseClient.h" +#include "base/net/stratum/SubmitResult.h" + + +namespace xmrig { + +int64_t BaseClient::m_sequence = 1; + +} /* namespace xmrig */ xmrig::BaseClient::BaseClient(int id, IClientListener *listener) : @@ -31,7 +40,23 @@ xmrig::BaseClient::BaseClient(int id, IClientListener *listener) : m_listener(listener), m_id(id), m_retries(5), + m_failures(0), + m_state(UnconnectedState), m_retryPause(5000) { - +} + + +bool xmrig::BaseClient::handleSubmitResponse(int64_t id, const char *error) +{ + auto it = m_results.find(id); + if (it != m_results.end()) { + it->second.done(); + m_listener->onResultAccepted(this, it->second, error); + m_results.erase(it); + + return true; + } + + return false; } diff --git a/src/base/net/stratum/BaseClient.h b/src/base/net/stratum/BaseClient.h index 27432a2f..9e1c7ffb 100644 --- a/src/base/net/stratum/BaseClient.h +++ b/src/base/net/stratum/BaseClient.h @@ -26,6 +26,9 @@ #define XMRIG_BASECLIENT_H +#include + + #include "base/kernel/interfaces/IClient.h" #include "base/net/stratum/Job.h" #include "base/net/stratum/Pool.h" @@ -35,6 +38,7 @@ namespace xmrig { class IClientListener; +class SubmitResult; class BaseClient : public IClient @@ -55,15 +59,32 @@ public: inline void setRetryPause(uint64_t ms) override { m_retryPause = ms; } protected: + enum SocketState { + UnconnectedState, + HostLookupState, + ConnectingState, + ConnectedState, + ClosingState + }; + + inline bool isQuiet() const { return m_quiet || m_failures >= m_retries; } + + bool handleSubmitResponse(int64_t id, const char *error = nullptr); + bool m_quiet; IClientListener *m_listener; int m_id; int m_retries; + int64_t m_failures; Job m_job; Pool m_pool; + SocketState m_state; + std::map m_results; String m_ip; uint64_t m_retryPause; + static int64_t m_sequence; + private: bool m_enabled; }; diff --git a/src/base/net/stratum/Client.cpp b/src/base/net/stratum/Client.cpp index 27075d48..df6f4837 100644 --- a/src/base/net/stratum/Client.cpp +++ b/src/base/net/stratum/Client.cpp @@ -57,7 +57,6 @@ namespace xmrig { -int64_t Client::m_sequence = 1; Storage Client::m_storage; } /* namespace xmrig */ @@ -77,8 +76,6 @@ static const char *states[] = { xmrig::Client::Client(int id, const char *agent, IClientListener *listener) : BaseClient(id, listener), m_agent(agent), - m_failures(0), - m_state(UnconnectedState), m_tls(nullptr), m_expire(0), m_jobs(0), @@ -99,57 +96,6 @@ xmrig::Client::~Client() } -void xmrig::Client::connect() -{ -# ifdef XMRIG_FEATURE_TLS - if (m_pool.isTLS()) { - m_tls = new Tls(this); - } -# endif - - resolve(m_pool.host()); -} - - -void xmrig::Client::connect(const Pool &pool) -{ - setPool(pool); - connect(); -} - - -void xmrig::Client::deleteLater() -{ - if (!m_listener) { - return; - } - - m_listener = nullptr; - - if (!disconnect()) { - m_storage.remove(m_key); - } -} - - -void xmrig::Client::tick(uint64_t now) -{ - if (m_state == ConnectedState) { - if (m_expire && now > m_expire) { - LOG_DEBUG_ERR("[%s] timeout", url()); - close(); - } - else if (m_keepAlive && now > m_keepAlive) { - ping(); - } - } - - if (m_expire && now > m_expire && m_state == ConnectingState) { - connect(); - } -} - - bool xmrig::Client::disconnect() { m_keepAlive = 0; @@ -247,6 +193,57 @@ int64_t xmrig::Client::submit(const JobResult &result) } +void xmrig::Client::connect() +{ +# ifdef XMRIG_FEATURE_TLS + if (m_pool.isTLS()) { + m_tls = new Tls(this); + } +# endif + + resolve(m_pool.host()); +} + + +void xmrig::Client::connect(const Pool &pool) +{ + setPool(pool); + connect(); +} + + +void xmrig::Client::deleteLater() +{ + if (!m_listener) { + return; + } + + m_listener = nullptr; + + if (!disconnect()) { + m_storage.remove(m_key); + } +} + + +void xmrig::Client::tick(uint64_t now) +{ + if (m_state == ConnectedState) { + if (m_expire && now > m_expire) { + LOG_DEBUG_ERR("[%s] timeout", url()); + close(); + } + else if (m_keepAlive && now > m_keepAlive) { + ping(); + } + } + + if (m_expire && now > m_expire && m_state == ConnectingState) { + connect(); + } +} + + void xmrig::Client::onResolved(const Dns &dns, int status) { assert(m_listener != nullptr); @@ -749,14 +746,8 @@ void xmrig::Client::parseResponse(int64_t id, const rapidjson::Value &result, co 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 (!isQuiet()) { - LOG_ERR("[%s] error: \"%s\", code: %d", url(), message, error["code"].GetInt()); + if (!handleSubmitResponse(id, message) && !isQuiet()) { + LOG_ERR("[%s] error: " RED_BOLD("\"%s\"") RED_S ", code: %d", url(), message, error["code"].GetInt()); } if (isCriticalError(message)) { @@ -787,12 +778,7 @@ void xmrig::Client::parseResponse(int64_t id, const rapidjson::Value &result, co 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); - } + handleSubmitResponse(id); } diff --git a/src/base/net/stratum/Client.h b/src/base/net/stratum/Client.h index b42fa613..c7aeabfe 100644 --- a/src/base/net/stratum/Client.h +++ b/src/base/net/stratum/Client.h @@ -43,7 +43,6 @@ #include "common/crypto/Algorithm.h" - typedef struct bio_st BIO; @@ -68,6 +67,7 @@ public: Client(int id, const char *agent, IClientListener *listener); ~Client() override; +protected: bool disconnect() override; bool isTLS() const override; const char *tlsFingerprint() const override; @@ -78,23 +78,13 @@ public: void deleteLater() override; void tick(uint64_t now) override; - inline bool hasExtension(Extension extension) const noexcept override { return m_extensions.test(extension); } - inline const char *mode() const override { return "pool"; } - -protected: - inline void onLine(char *line, size_t size) override { parse(line, size); } - void onResolved(const Dns &dns, int status) override; -private: - enum SocketState { - UnconnectedState, - HostLookupState, - ConnectingState, - ConnectedState, - ClosingState - }; + inline bool hasExtension(Extension extension) const noexcept override { return m_extensions.test(extension); } + inline const char *mode() const override { return "pool"; } + inline void onLine(char *line, size_t size) override { parse(line, size); } +private: class Tls; bool close(); @@ -120,7 +110,6 @@ private: void setState(SocketState state); void startTimeout(); - inline bool isQuiet() const { return m_quiet || m_failures >= m_retries; } inline const char *url() const { return m_pool.url(); } inline SocketState state() const { return m_state; } inline void setExtension(Extension ext, bool enable) noexcept { m_extensions.set(ext, enable); } @@ -136,11 +125,8 @@ private: char m_sendBuf[2048]; const char *m_agent; Dns *m_dns; - int64_t m_failures; RecvBuf m_recvBuf; - SocketState m_state; std::bitset m_extensions; - std::map m_results; String m_rpcId; Tls *m_tls; uint64_t m_expire; @@ -150,7 +136,6 @@ private: uv_stream_t *m_stream; uv_tcp_t *m_socket; - static int64_t m_sequence; static Storage m_storage; }; diff --git a/src/base/net/stratum/DaemonClient.cpp b/src/base/net/stratum/DaemonClient.cpp new file mode 100644 index 00000000..a5aef54d --- /dev/null +++ b/src/base/net/stratum/DaemonClient.cpp @@ -0,0 +1,350 @@ +/* XMRig + * Copyright 2010 Jeff Garzik + * Copyright 2012-2014 pooler + * Copyright 2014 Lucas Jones + * Copyright 2014-2016 Wolf9466 + * Copyright 2016 Jay D Dee + * Copyright 2017-2018 XMR-Stak , + * Copyright 2018-2019 SChernykh + * Copyright 2019 Howard Chu + * Copyright 2016-2019 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 +#include + + +#include "3rdparty/http-parser/http_parser.h" +#include "base/io/Json.h" +#include "base/io/log/Log.h" +#include "base/kernel/interfaces/IClientListener.h" +#include "base/net/http/HttpClient.h" +#include "base/net/stratum/DaemonClient.h" +#include "base/net/stratum/SubmitResult.h" +#include "base/tools/Buffer.h" +#include "base/tools/Timer.h" +#include "net/JobResult.h" +#include "rapidjson/document.h" +#include "rapidjson/error/en.h" +#include "rapidjson/stringbuffer.h" +#include "rapidjson/writer.h" + + +#ifdef XMRIG_FEATURE_TLS +# include "base/net/http/HttpsClient.h" +#endif + + +xmrig::DaemonClient::DaemonClient(int id, IClientListener *listener) : + BaseClient(id, listener) +{ + m_timer = new Timer(this); +} + + +xmrig::DaemonClient::~DaemonClient() +{ + delete m_timer; +} + + +bool xmrig::DaemonClient::disconnect() +{ + setState(UnconnectedState); + + return true; +} + + +bool xmrig::DaemonClient::isTLS() const +{ + return false; +} + + +const char *xmrig::DaemonClient::tlsFingerprint() const +{ + return nullptr; +} + + +const char *xmrig::DaemonClient::tlsVersion() const +{ + return nullptr; +} + + +int64_t xmrig::DaemonClient::submit(const JobResult &result) +{ + if (result.jobId != (m_blocktemplate.data() + m_blocktemplate.size() - 48)) { + return -1; + } + + Buffer::toHex(reinterpret_cast(&result.nonce), 4, m_blocktemplate.data() + 78); + + using namespace rapidjson; + Document doc(kObjectType); + auto &allocator = doc.GetAllocator(); + + doc.AddMember("id", m_sequence, allocator); + doc.AddMember("jsonrpc", "2.0", allocator); + doc.AddMember("method", "submitblock", allocator); + + Value params(kArrayType); + params.PushBack(m_blocktemplate.toJSON(), allocator); + + doc.AddMember("params", params, allocator); + +# ifdef XMRIG_PROXY_PROJECT + m_results[m_sequence] = SubmitResult(m_sequence, result.diff, result.actualDiff(), result.id); +# else + m_results[m_sequence] = SubmitResult(m_sequence, result.diff, result.actualDiff()); +# endif + + send(HTTP_POST, "/json_rpc", doc); + + return m_sequence++; +} + + +void xmrig::DaemonClient::connect() +{ + setState(ConnectingState); + getBlockTemplate(); +} + + +void xmrig::DaemonClient::connect(const Pool &pool) +{ + setPool(pool); + connect(); +} + + +void xmrig::DaemonClient::onHttpData(const HttpData &data) +{ + if (data.status != HTTP_STATUS_OK) { + return retry(); + } + + LOG_DEBUG("[%s:%d] received (%d bytes): \"%.*s\"", m_pool.host().data(), m_pool.port(), static_cast(data.body.size()), static_cast(data.body.size()), data.body.c_str()); + + m_ip = static_cast(data).ip().c_str(); + + rapidjson::Document doc; + if (doc.Parse(data.body.c_str()).HasParseError()) { + if (!isQuiet()) { + LOG_ERR("[%s:%d] JSON decode failed: \"%s\"", m_pool.host().data(), m_pool.port(), rapidjson::GetParseError_En(doc.GetParseError())); + } + + return retry(); + } + + if (data.method == HTTP_GET && data.url == "/getheight") { + if (m_job.height() != Json::getUint64(doc, "height")) { + getBlockTemplate(); + } + + return; + } + + if (!parseResponse(Json::getInt64(doc, "id", -1), Json::getObject(doc, "result"), Json::getObject(doc, "error"))) { + retry(); + } +} + + +void xmrig::DaemonClient::onTimer(const Timer *) +{ + if (m_state == ConnectingState) { + getBlockTemplate(); + } + else if (m_state == ConnectedState) { + send(HTTP_GET, "/getheight"); + } +} + + +bool xmrig::DaemonClient::parseJob(const rapidjson::Value ¶ms, int *code) +{ + Job job(m_id, false, m_pool.algorithm(), String()); + + String blocktemplate = Json::getString(params, "blocktemplate_blob"); + if (blocktemplate.isNull() || !job.setBlob(Json::getString(params, "blockhashing_blob"))) { + *code = 4; + return false; + } + + job.setHeight(Json::getUint64(params, "height")); + job.setDiff(Json::getUint64(params, "difficulty")); + job.setId(blocktemplate.data() + blocktemplate.size() - 48); + + m_job = std::move(job); + m_blocktemplate = std::move(blocktemplate); + + if (m_state == ConnectingState) { + setState(ConnectedState); + } + + m_listener->onJobReceived(this, m_job, params); + return true; +} + + +bool xmrig::DaemonClient::parseResponse(int64_t id, const rapidjson::Value &result, const rapidjson::Value &error) +{ + if (id == -1) { + return false; + } + + if (error.IsObject()) { + const char *message = error["message"].GetString(); + + if (!handleSubmitResponse(id, message) && !isQuiet()) { + LOG_ERR("[%s:%d] error: " RED_BOLD("\"%s\"") RED_S ", code: %d", m_pool.host().data(), m_pool.port(), message, error["code"].GetInt()); + } + + return false; + } + + if (!result.IsObject()) { + return false; + } + + int code = -1; + if (result.HasMember("blocktemplate_blob") && parseJob(result, &code)) { + return true; + } + + if (handleSubmitResponse(id)) { + getBlockTemplate(); + return true; + } + + + return false; +} + + +int64_t xmrig::DaemonClient::getBlockTemplate() +{ + using namespace rapidjson; + Document doc(kObjectType); + auto &allocator = doc.GetAllocator(); + + doc.AddMember("id", m_sequence, allocator); + doc.AddMember("jsonrpc", "2.0", allocator); + doc.AddMember("method", "getblocktemplate", allocator); + + Value params(kObjectType); + params.AddMember("wallet_address", m_pool.user().toJSON(), allocator); + params.AddMember("reserve_size", 8, allocator); + + doc.AddMember("params", params, allocator); + + send(HTTP_POST, "/json_rpc", doc); + + return m_sequence++; +} + + +void xmrig::DaemonClient::retry() +{ + m_failures++; + m_listener->onClose(this, static_cast(m_failures)); + + if (m_failures == -1) { + return; + } + + if (m_state == ConnectedState) { + setState(ConnectingState); + } + + m_timer->stop(); + m_timer->start(m_retryPause, 0); +} + + +void xmrig::DaemonClient::send(int method, const char *url, const char *data, size_t size) +{ + LOG_DEBUG("[%s:%d] " MAGENTA_BOLD("\"%s %s\"") BLACK_BOLD_S " send (%zu bytes): \"%.*s\"", + m_pool.host().data(), + m_pool.port(), + http_method_str(static_cast(method)), + url, + size, + static_cast(size), + data); + + HttpClient *client; +# ifdef XMRIG_FEATURE_TLS + if (m_pool.isTLS()) { + client = new HttpsClient(method, url, this, data, size); + } + else +# endif + { + client = new HttpClient(method, url, this, data, size); + } + + client->setQuiet(isQuiet()); + client->connect(m_pool.host(), m_pool.port()); +} + + +void xmrig::DaemonClient::send(int method, const char *url, const rapidjson::Document &doc) +{ + using namespace rapidjson; + + StringBuffer buffer(nullptr, 512); + Writer writer(buffer); + doc.Accept(writer); + + send(method, url, buffer.GetString(), buffer.GetSize()); +} + + +void xmrig::DaemonClient::setState(SocketState state) +{ + assert(m_state != state); + if (m_state == state) { + return; + } + + m_state = state; + + switch (state) { + case ConnectedState: + { + m_failures = 0; + m_listener->onLoginSuccess(this); + + const uint64_t interval = std::max(20, m_pool.pollInterval()); + m_timer->start(interval, interval); + } + break; + + case UnconnectedState: + m_failures = -1; + m_timer->stop(); + break; + + default: + break; + } +} diff --git a/src/base/net/stratum/DaemonClient.h b/src/base/net/stratum/DaemonClient.h new file mode 100644 index 00000000..740af6d0 --- /dev/null +++ b/src/base/net/stratum/DaemonClient.h @@ -0,0 +1,78 @@ +/* XMRig + * Copyright 2010 Jeff Garzik + * Copyright 2012-2014 pooler + * Copyright 2014 Lucas Jones + * Copyright 2014-2016 Wolf9466 + * Copyright 2016 Jay D Dee + * Copyright 2017-2018 XMR-Stak , + * Copyright 2018-2019 SChernykh + * Copyright 2019 Howard Chu + * Copyright 2016-2019 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 XMRIG_DAEMONCLIENT_H +#define XMRIG_DAEMONCLIENT_H + + +#include "base/net/stratum/BaseClient.h" +#include "base/kernel/interfaces/ITimerListener.h" +#include "base/kernel/interfaces/IHttpListener.h" + + +namespace xmrig { + + +class DaemonClient : public BaseClient, public ITimerListener, public IHttpListener +{ +public: + DaemonClient(int id, IClientListener *listener); + ~DaemonClient() override; + +protected: + bool disconnect() override; + bool isTLS() const override; + const char *tlsFingerprint() const override; + const char *tlsVersion() const override; + int64_t submit(const JobResult &result) override; + void connect() override; + void connect(const Pool &pool) override; + + void onHttpData(const HttpData &data) override; + void onTimer(const Timer *timer) override; + + inline bool hasExtension(Extension) const noexcept override { return false; } + inline const char *mode() const override { return "daemon"; } + inline void deleteLater() override { delete this; } + inline void tick(uint64_t) override {} + +private: + bool parseJob(const rapidjson::Value ¶ms, int *code); + bool parseResponse(int64_t id, const rapidjson::Value &result, const rapidjson::Value &error); + int64_t getBlockTemplate(); + void retry(); + void send(int method, const char *url, const char *data = nullptr, size_t size = 0); + void send(int method, const char *url, const rapidjson::Document &doc); + void setState(SocketState state); + + String m_blocktemplate; + Timer *m_timer; +}; + + +} /* namespace xmrig */ + + +#endif /* XMRIG_DAEMONCLIENT_H */ diff --git a/src/base/net/stratum/Pool.h b/src/base/net/stratum/Pool.h index d3c9b141..6eec7aa5 100644 --- a/src/base/net/stratum/Pool.h +++ b/src/base/net/stratum/Pool.h @@ -84,6 +84,7 @@ public: inline const String &user() const { return !m_user.isNull() ? m_user : kDefaultUser; } inline int keepAlive() const { return m_keepAlive; } inline uint16_t port() const { return m_port; } + inline uint64_t pollInterval() const { return m_pollInterval; } inline bool operator!=(const Pool &other) const { return !isEqual(other); } inline bool operator==(const Pool &other) const { return isEqual(other); } diff --git a/src/base/net/stratum/strategies/FailoverStrategy.cpp b/src/base/net/stratum/strategies/FailoverStrategy.cpp index 0c574a5d..b89cd955 100644 --- a/src/base/net/stratum/strategies/FailoverStrategy.cpp +++ b/src/base/net/stratum/strategies/FailoverStrategy.cpp @@ -29,6 +29,11 @@ #include "common/Platform.h" +#ifdef XMRIG_FEATURE_HTTP +# include "base/net/stratum/DaemonClient.h" +#endif + + xmrig::FailoverStrategy::FailoverStrategy(const std::vector &pools, int retryPause, int retries, IStrategyListener *listener, bool quiet) : m_quiet(quiet), m_retries(retries), @@ -56,7 +61,7 @@ xmrig::FailoverStrategy::FailoverStrategy(int retryPause, int retries, IStrategy xmrig::FailoverStrategy::~FailoverStrategy() { - for (Client *client : m_pools) { + for (IClient *client : m_pools) { client->deleteLater(); } } @@ -64,7 +69,15 @@ xmrig::FailoverStrategy::~FailoverStrategy() void xmrig::FailoverStrategy::add(const Pool &pool) { - Client *client = new Client(static_cast(m_pools.size()), Platform::userAgent(), this); + const int id = static_cast(m_pools.size()); + +# ifdef XMRIG_FEATURE_HTTP + IClient *client = !pool.isDaemon() ? static_cast(new Client(id, Platform::userAgent(), this)) + : static_cast(new DaemonClient(id, this)); +# else + IClient *client = new Client(id, Platform::userAgent(), this); +# endif + client->setPool(pool); client->setRetries(m_retries); client->setRetryPause(m_retryPause * 1000); @@ -102,7 +115,7 @@ void xmrig::FailoverStrategy::resume() void xmrig::FailoverStrategy::setAlgo(const xmrig::Algorithm &algo) { - for (Client *client : m_pools) { + for (IClient *client : m_pools) { client->setAlgo(algo); } } @@ -123,7 +136,7 @@ void xmrig::FailoverStrategy::stop() void xmrig::FailoverStrategy::tick(uint64_t now) { - for (Client *client : m_pools) { + for (IClient *client : m_pools) { client->tick(now); } } diff --git a/src/base/net/stratum/strategies/FailoverStrategy.h b/src/base/net/stratum/strategies/FailoverStrategy.h index 748eddda..344d815c 100644 --- a/src/base/net/stratum/strategies/FailoverStrategy.h +++ b/src/base/net/stratum/strategies/FailoverStrategy.h @@ -52,7 +52,7 @@ public: protected: inline bool isActive() const override { return m_active >= 0; } - inline Client *client() const override { return active(); } + inline IClient *client() const override { return active(); } inline void onLogin(IClient *, rapidjson::Document &, rapidjson::Value &) override {} int64_t submit(const JobResult &result) override; @@ -68,7 +68,7 @@ protected: void onResultAccepted(IClient *client, const SubmitResult &result, const char *error) override; private: - inline Client *active() const { return m_pools[static_cast(m_active)]; } + inline IClient *active() const { return m_pools[static_cast(m_active)]; } const bool m_quiet; const int m_retries; @@ -76,7 +76,7 @@ private: int m_active; IStrategyListener *m_listener; size_t m_index; - std::vector m_pools; + std::vector m_pools; }; diff --git a/src/base/net/stratum/strategies/SinglePoolStrategy.cpp b/src/base/net/stratum/strategies/SinglePoolStrategy.cpp index 45dce5d9..f432514e 100644 --- a/src/base/net/stratum/strategies/SinglePoolStrategy.cpp +++ b/src/base/net/stratum/strategies/SinglePoolStrategy.cpp @@ -29,11 +29,26 @@ #include "common/Platform.h" +#ifdef XMRIG_FEATURE_HTTP +# include "base/net/stratum/DaemonClient.h" +#endif + + xmrig::SinglePoolStrategy::SinglePoolStrategy(const Pool &pool, int retryPause, int retries, IStrategyListener *listener, bool quiet) : m_active(false), m_listener(listener) { +# ifdef XMRIG_FEATURE_HTTP + if (!pool.isDaemon()) { + m_client = new Client(0, Platform::userAgent(), this); + } + else { + m_client = new DaemonClient(0, this); + } +# else m_client = new Client(0, Platform::userAgent(), this); +# endif + m_client->setPool(pool); m_client->setRetries(retries); m_client->setRetryPause(retryPause * 1000); diff --git a/src/base/net/stratum/strategies/SinglePoolStrategy.h b/src/base/net/stratum/strategies/SinglePoolStrategy.h index b8a4fe1e..af0bd7d6 100644 --- a/src/base/net/stratum/strategies/SinglePoolStrategy.h +++ b/src/base/net/stratum/strategies/SinglePoolStrategy.h @@ -46,7 +46,7 @@ public: protected: inline bool isActive() const override { return m_active; } - inline Client *client() const override { return m_client; } + inline IClient *client() const override { return m_client; } inline void onLogin(IClient *, rapidjson::Document &, rapidjson::Value &) override {} int64_t submit(const JobResult &result) override; @@ -63,7 +63,7 @@ protected: private: bool m_active; - Client *m_client; + IClient *m_client; IStrategyListener *m_listener; }; diff --git a/src/net/strategies/DonateStrategy.cpp b/src/net/strategies/DonateStrategy.cpp index 7a9f9e60..fb958a4c 100644 --- a/src/net/strategies/DonateStrategy.cpp +++ b/src/net/strategies/DonateStrategy.cpp @@ -231,8 +231,8 @@ xmrig::Client *xmrig::DonateStrategy::createProxy() return nullptr; } - const Client *client = strategy->client(); - m_tls = client->hasExtension(IClient::EXT_TLS); + const IClient *client = strategy->client(); + m_tls = client->hasExtension(IClient::EXT_TLS); Pool pool(client->ip(), client->pool().port(), m_userId, client->pool().password(), 0, true, client->isTLS()); pool.setAlgo(client->pool().algorithm()); diff --git a/src/net/strategies/DonateStrategy.h b/src/net/strategies/DonateStrategy.h index 69bf8dbd..c9fc312d 100644 --- a/src/net/strategies/DonateStrategy.h +++ b/src/net/strategies/DonateStrategy.h @@ -52,7 +52,7 @@ public: protected: inline bool isActive() const override { return state() == STATE_ACTIVE; } - inline Client *client() const override { return m_proxy ? m_proxy : m_strategy->client(); } + inline IClient *client() const override { return m_proxy ? m_proxy : m_strategy->client(); } inline void onJob(IStrategy *, IClient *client, const Job &job) override { setJob(client, job); } inline void onJobReceived(IClient *client, const Job &job, const rapidjson::Value &) override { setJob(client, job); } inline void onResultAccepted(IClient *client, const SubmitResult &result, const char *error) override { setResult(client, result, error); } @@ -93,7 +93,7 @@ private: bool m_tls; char m_userId[65]; - Client *m_proxy; + IClient *m_proxy; const uint64_t m_donateTime; const uint64_t m_idleTime; Controller *m_controller; From 5e369a5af85b9cf6b72c0b205d5a5bc878a6160e Mon Sep 17 00:00:00 2001 From: XMRig Date: Fri, 12 Apr 2019 04:25:47 +0700 Subject: [PATCH 20/34] Fixed daemon support over HTTPS. --- src/base/net/http/HttpClient.cpp | 1 + src/base/net/http/HttpClient.h | 3 +- src/base/net/http/HttpsClient.cpp | 70 ++++++++++++++++++++++++--- src/base/net/http/HttpsClient.h | 11 ++++- src/base/net/stratum/DaemonClient.cpp | 23 ++++----- src/base/net/stratum/DaemonClient.h | 6 ++- 6 files changed, 90 insertions(+), 24 deletions(-) diff --git a/src/base/net/http/HttpClient.cpp b/src/base/net/http/HttpClient.cpp index d58e7299..319bb4dd 100644 --- a/src/base/net/http/HttpClient.cpp +++ b/src/base/net/http/HttpClient.cpp @@ -79,6 +79,7 @@ private: xmrig::HttpClient::HttpClient(int method, const String &url, IHttpListener *listener, const char *data, size_t size) : HttpContext(HTTP_RESPONSE, listener), + m_quiet(false), m_port(0) { this->method = method; diff --git a/src/base/net/http/HttpClient.h b/src/base/net/http/HttpClient.h index e9866483..c5dfc43d 100644 --- a/src/base/net/http/HttpClient.h +++ b/src/base/net/http/HttpClient.h @@ -57,10 +57,11 @@ protected: virtual void read(const char *data, size_t size); virtual void write(const std::string &header); + bool m_quiet; + private: static void onConnect(uv_connect_t *req, int status); - bool m_quiet; Dns *m_dns; uint16_t m_port; }; diff --git a/src/base/net/http/HttpsClient.cpp b/src/base/net/http/HttpsClient.cpp index ff103a34..2c287330 100644 --- a/src/base/net/http/HttpsClient.cpp +++ b/src/base/net/http/HttpsClient.cpp @@ -29,15 +29,22 @@ #include +#include "base/io/log/Log.h" #include "base/net/http/HttpsClient.h" -#include "base/tools/String.h" +#include "base/tools/Buffer.h" -xmrig::HttpsClient::HttpsClient(int method, const String &url, IHttpListener *listener, const char *data, size_t size) : +#ifdef _MSC_VER +# define strncasecmp(x,y,z) _strnicmp(x,y,z) +#endif + + +xmrig::HttpsClient::HttpsClient(int method, const String &url, IHttpListener *listener, const char *data, size_t size, const String &fingerprint) : HttpClient(method, url, listener, data, size), m_ready(false), m_buf(), - m_ssl(nullptr) + m_ssl(nullptr), + m_fp(fingerprint) { m_ctx = SSL_CTX_new(SSLv23_method()); assert(m_ctx != nullptr); @@ -64,6 +71,18 @@ xmrig::HttpsClient::~HttpsClient() } +const char *xmrig::HttpsClient::fingerprint() const +{ + return m_ready ? m_fingerprint : nullptr; +} + + +const char *xmrig::HttpsClient::version() const +{ + return m_ready ? SSL_get_version(m_ssl) : nullptr; +} + + void xmrig::HttpsClient::handshake() { m_ssl = SSL_new(m_ctx); @@ -118,13 +137,52 @@ void xmrig::HttpsClient::read(const char *data, size_t size) void xmrig::HttpsClient::write(const std::string &header) { SSL_write(m_ssl, (header + body).c_str(), header.size() + body.size()); + body.clear(); + flush(); } -bool xmrig::HttpsClient::verify(X509 *cert) const +bool xmrig::HttpsClient::verify(X509 *cert) { - return cert != nullptr; + if (cert == nullptr) { + return false; + } + + if (!verifyFingerprint(cert)) { + if (!m_quiet) { + LOG_ERR("[%s:%d] Failed to verify server certificate fingerprint", host().data(), port()); + + if (strlen(m_fingerprint) == 64 && !m_fp.isNull()) { + LOG_ERR("\"%s\" was given", m_fingerprint); + LOG_ERR("\"%s\" was configured", m_fp.data()); + } + } + + return false; + } + + return true; +} + + +bool xmrig::HttpsClient::verifyFingerprint(X509 *cert) +{ + const EVP_MD *digest = EVP_get_digestbyname("sha256"); + if (digest == nullptr) { + return false; + } + + unsigned char md[EVP_MAX_MD_SIZE]; + unsigned int dlen; + + if (X509_digest(cert, digest, md, &dlen) != 1) { + return false; + } + + Buffer::toHex(md, 32, m_fingerprint); + + return m_fp.isNull() || strncasecmp(m_fingerprint, m_fp.data(), 64) == 0; } @@ -139,7 +197,7 @@ void xmrig::HttpsClient::flush() bool result = false; if (uv_is_writable(stream())) { - result = uv_try_write(stream(), &buf, 1) == buf.len; + result = uv_try_write(stream(), &buf, 1) == static_cast(buf.len); if (!result) { close(UV_EIO); diff --git a/src/base/net/http/HttpsClient.h b/src/base/net/http/HttpsClient.h index 76b90c66..c6a22809 100644 --- a/src/base/net/http/HttpsClient.h +++ b/src/base/net/http/HttpsClient.h @@ -35,6 +35,7 @@ typedef struct x509_st X509; #include "base/net/http/HttpClient.h" +#include "base/tools/String.h" namespace xmrig { @@ -43,24 +44,30 @@ namespace xmrig { class HttpsClient : public HttpClient { public: - HttpsClient(int method, const String &url, IHttpListener *listener, const char *data = nullptr, size_t size = 0); + HttpsClient(int method, const String &url, IHttpListener *listener, const char *data, size_t size, const String &fingerprint); ~HttpsClient() override; + const char *fingerprint() const; + const char *version() const; + protected: void handshake() override; void read(const char *data, size_t size) override; void write(const std::string &header) override; private: - bool verify(X509 *cert) const; + bool verify(X509 *cert); + bool verifyFingerprint(X509 *cert); void flush(); BIO *m_readBio; BIO *m_writeBio; bool m_ready; char m_buf[1024 * 2]; + char m_fingerprint[32 * 2 + 8]; SSL *m_ssl; SSL_CTX *m_ctx; + String m_fp; }; diff --git a/src/base/net/stratum/DaemonClient.cpp b/src/base/net/stratum/DaemonClient.cpp index a5aef54d..251c5fd5 100644 --- a/src/base/net/stratum/DaemonClient.cpp +++ b/src/base/net/stratum/DaemonClient.cpp @@ -72,19 +72,11 @@ bool xmrig::DaemonClient::disconnect() bool xmrig::DaemonClient::isTLS() const { +# ifdef XMRIG_FEATURE_TLS + return m_pool.isTLS(); +# else return false; -} - - -const char *xmrig::DaemonClient::tlsFingerprint() const -{ - return nullptr; -} - - -const char *xmrig::DaemonClient::tlsVersion() const -{ - return nullptr; +# endif } @@ -145,6 +137,11 @@ void xmrig::DaemonClient::onHttpData(const HttpData &data) m_ip = static_cast(data).ip().c_str(); + if (isTLS()) { + m_tlsVersion = static_cast(data).version(); + m_tlsFingerprint = static_cast(data).fingerprint(); + } + rapidjson::Document doc; if (doc.Parse(data.body.c_str()).HasParseError()) { if (!isQuiet()) { @@ -294,7 +291,7 @@ void xmrig::DaemonClient::send(int method, const char *url, const char *data, si HttpClient *client; # ifdef XMRIG_FEATURE_TLS if (m_pool.isTLS()) { - client = new HttpsClient(method, url, this, data, size); + client = new HttpsClient(method, url, this, data, size, m_pool.fingerprint()); } else # endif diff --git a/src/base/net/stratum/DaemonClient.h b/src/base/net/stratum/DaemonClient.h index 740af6d0..f9438f67 100644 --- a/src/base/net/stratum/DaemonClient.h +++ b/src/base/net/stratum/DaemonClient.h @@ -44,8 +44,6 @@ public: protected: bool disconnect() override; bool isTLS() const override; - const char *tlsFingerprint() const override; - const char *tlsVersion() const override; int64_t submit(const JobResult &result) override; void connect() override; void connect(const Pool &pool) override; @@ -55,6 +53,8 @@ protected: inline bool hasExtension(Extension) const noexcept override { return false; } inline const char *mode() const override { return "daemon"; } + inline const char *tlsFingerprint() const override { return m_tlsFingerprint; } + inline const char *tlsVersion() const override { return m_tlsVersion; } inline void deleteLater() override { delete this; } inline void tick(uint64_t) override {} @@ -68,6 +68,8 @@ private: void setState(SocketState state); String m_blocktemplate; + String m_tlsFingerprint; + String m_tlsVersion; Timer *m_timer; }; From 867478b983a6a8b8bbd853e5a9f14cc8c447cfe3 Mon Sep 17 00:00:00 2001 From: XMRig Date: Fri, 12 Apr 2019 18:30:08 +0700 Subject: [PATCH 21/34] Added command line option --daemon and --daemon-poll-interval --- src/base/kernel/config/BaseTransform.cpp | 8 ++ src/base/kernel/interfaces/IConfig.h | 2 + src/core/config/Config_platform.h | 2 + src/core/config/usage.h | 101 +++++++++++++---------- 4 files changed, 71 insertions(+), 42 deletions(-) diff --git a/src/base/kernel/config/BaseTransform.cpp b/src/base/kernel/config/BaseTransform.cpp index 3b6b6d82..e4165a4c 100644 --- a/src/base/kernel/config/BaseTransform.cpp +++ b/src/base/kernel/config/BaseTransform.cpp @@ -161,6 +161,7 @@ void xmrig::BaseTransform::transform(rapidjson::Document &doc, int key, const ch case IConfig::PrintTimeKey: /* --print-time */ case IConfig::HttpPort: /* --http-port */ case IConfig::DonateLevelKey: /* --donate-level */ + case IConfig::DaemonPollKey: /* --daemon-poll-interval */ # ifdef XMRIG_DEPRECATED case IConfig::ApiPort: /* --api-port */ # endif @@ -173,6 +174,7 @@ void xmrig::BaseTransform::transform(rapidjson::Document &doc, int key, const ch case IConfig::TlsKey: /* --tls */ case IConfig::DryRunKey: /* --dry-run */ case IConfig::HttpEnabledKey: /* --http-enabled */ + case IConfig::DaemonKey: /* --daemon */ return transformBoolean(doc, key, true); case IConfig::ColorKey: /* --no-color */ @@ -204,6 +206,9 @@ void xmrig::BaseTransform::transformBoolean(rapidjson::Document &doc, int key, b case IConfig::TlsKey: /* --tls */ return add(doc, kPools, "tls", enable); + case IConfig::DaemonKey: /* --daemon */ + return add(doc, kPools, "daemon", enable); + # ifndef XMRIG_PROXY_PROJECT case IConfig::NicehashKey: /* --nicehash */ return add(doc, kPools, "nicehash", enable); @@ -265,6 +270,9 @@ void xmrig::BaseTransform::transformUint64(rapidjson::Document &doc, int key, ui case IConfig::PrintTimeKey: /* --print-time */ return set(doc, "print-time", arg); + case IConfig::DaemonPollKey: /* --daemon-poll-interval */ + return add(doc, kPools, "daemon-poll-interval", arg); + default: break; } diff --git a/src/base/kernel/interfaces/IConfig.h b/src/base/kernel/interfaces/IConfig.h index d592c4cb..07849e35 100644 --- a/src/base/kernel/interfaces/IConfig.h +++ b/src/base/kernel/interfaces/IConfig.h @@ -70,6 +70,8 @@ public: TlsKey = 1013, FingerprintKey = 1014, ProxyDonateKey = 1017, + DaemonKey = 1018, + DaemonPollKey = 1019, # ifdef XMRIG_DEPRECATED ApiPort = 4000, diff --git a/src/core/config/Config_platform.h b/src/core/config/Config_platform.h index 8ece4105..ca06a703 100644 --- a/src/core/config/Config_platform.h +++ b/src/core/config/Config_platform.h @@ -82,6 +82,8 @@ static const option options[] = { { "tls", 0, nullptr, IConfig::TlsKey }, { "tls-fingerprint", 1, nullptr, IConfig::FingerprintKey }, { "asm", 1, nullptr, IConfig::AssemblyKey }, + { "daemon", 0, nullptr, IConfig::DaemonKey }, + { "daemon-poll-interval", 1, nullptr, IConfig::DaemonPollKey }, # ifdef XMRIG_DEPRECATED { "api-port", 1, nullptr, IConfig::ApiPort }, diff --git a/src/core/config/usage.h b/src/core/config/usage.h index 430a60c7..ce172778 100644 --- a/src/core/config/usage.h +++ b/src/core/config/usage.h @@ -35,59 +35,76 @@ namespace xmrig { static char const usage[] = "\ Usage: " APP_ID " [OPTIONS]\n\ Options:\n\ - -a, --algo=ALGO specify the algorithm to use\n\ - cryptonight\n" + -a, --algo=ALGO specify the algorithm to use\n\ + cryptonight\n" #ifndef XMRIG_NO_AEON "\ - cryptonight-lite\n" + cryptonight-lite\n" #endif #ifndef XMRIG_NO_SUMO "\ - cryptonight-heavy\n" + cryptonight-heavy\n" +#endif +#ifndef XMRIG_NO_CN_PICO +"\ + cryptonight-pico\n" #endif "\ - -o, --url=URL URL of mining server\n\ - -O, --userpass=U:P username:password pair for mining server\n\ - -u, --user=USERNAME username for mining server\n\ - -p, --pass=PASSWORD password for mining server\n\ - --rig-id=ID rig identifier for pool-side statistics (needs pool support)\n\ - -t, --threads=N number of miner threads\n\ - -v, --av=N algorithm variation, 0 auto select\n\ - -k, --keepalive send keepalived packet for prevent timeout (needs pool support)\n\ - --nicehash enable nicehash.com support\n\ - --tls enable SSL/TLS support (needs pool support)\n\ - --tls-fingerprint=F pool TLS certificate fingerprint, if set enable strict certificate pinning\n\ - -r, --retries=N number of times to retry before switch to backup server (default: 5)\n\ - -R, --retry-pause=N time to pause between retries (default: 5)\n\ - --cpu-affinity set process affinity to CPU core(s), mask 0x3 for cores 0 and 1\n\ - --cpu-priority set process priority (0 idle, 2 normal to 5 highest)\n\ - --no-huge-pages disable huge pages support\n\ - --no-color disable colored output\n\ - --variant algorithm PoW variant\n\ - --donate-level=N donate level, default 5%% (5 minutes in 100 minutes)\n\ - --user-agent set custom user-agent string for pool\n\ - -B, --background run the miner in the background\n\ - -c, --config=FILE load a JSON-format configuration file\n\ - -l, --log-file=FILE log all output to a file\n" + -o, --url=URL URL of mining server\n\ + -O, --userpass=U:P username:password pair for mining server\n\ + -u, --user=USERNAME username for mining server\n\ + -p, --pass=PASSWORD password for mining server\n\ + --rig-id=ID rig identifier for pool-side statistics (needs pool support)\n\ + -t, --threads=N number of miner threads\n\ + -v, --av=N algorithm variation, 0 auto select\n\ + -k, --keepalive send keepalived packet for prevent timeout (needs pool support)\n\ + --nicehash enable nicehash.com support\n" +#ifdef XMRIG_FEATURE_TLS +"\ + --tls enable SSL/TLS support (needs pool support)\n\ + --tls-fingerprint=F pool TLS certificate fingerprint, if set enable strict certificate pinning\n" +#endif +#ifdef XMRIG_FEATURE_HTTP +"\ + --daemon use daemon RPC instead of pool for solo mining\n\ + --daemon-poll-interval=N daemon poll interval in milliseconds (default: 1000)\n" +#endif +"\ + -r, --retries=N number of times to retry before switch to backup server (default: 5)\n\ + -R, --retry-pause=N time to pause between retries (default: 5)\n\ + --cpu-affinity set process affinity to CPU core(s), mask 0x3 for cores 0 and 1\n\ + --cpu-priority set process priority (0 idle, 2 normal to 5 highest)\n\ + --no-huge-pages disable huge pages support\n\ + --no-color disable colored output\n\ + --variant algorithm PoW variant\n\ + --donate-level=N donate level, default 5%% (5 minutes in 100 minutes)\n\ + --user-agent set custom user-agent string for pool\n\ + -B, --background run the miner in the background\n\ + -c, --config=FILE load a JSON-format configuration file\n\ + -l, --log-file=FILE log all output to a file\n" # ifdef HAVE_SYSLOG_H "\ - -S, --syslog use system log for output messages\n" + -S, --syslog use system log for output messages\n" # endif "\ - --max-cpu-usage=N maximum CPU usage for automatic threads mode (default 75)\n\ - --safe safe adjust threads and av settings for current CPU\n\ - --asm=ASM ASM code for cn/2, possible values: auto, none, intel, ryzen, bulldozer.\n\ - --print-time=N print hashrate report every N seconds\n\ - --api-worker-id=ID custom worker-id for API\n\ - --api-id=ID custom instance ID for API\n\ - --http-enabled enable HTTP API\n\ - --http-host=HOST bind host for HTTP API (by default 127.0.0.1)\n\ - --http-port=N bind port for HTTP API\n\ - --http-access-token=T access token for HTTP API\n\ - --http-no-restricted enable full remote access to HTTP API (only if access token set)\n\ - --dry-run test configuration and exit\n\ - -h, --help display this help and exit\n\ - -V, --version output version information and exit\n\ + --max-cpu-usage=N maximum CPU usage for automatic threads mode (default: 100)\n\ + --safe safe adjust threads and av settings for current CPU\n\ + --asm=ASM ASM optimizations, possible values: auto, none, intel, ryzen, bulldozer.\n\ + --print-time=N print hashrate report every N seconds\n" +#ifdef XMRIG_FEATURE_HTTP +"\ + --api-worker-id=ID custom worker-id for API\n\ + --api-id=ID custom instance ID for API\n\ + --http-enabled enable HTTP API\n\ + --http-host=HOST bind host for HTTP API (default: 127.0.0.1)\n\ + --http-port=N bind port for HTTP API\n\ + --http-access-token=T access token for HTTP API\n\ + --http-no-restricted enable full remote access to HTTP API (only if access token set)\n" +#endif +"\ + --dry-run test configuration and exit\n\ + -h, --help display this help and exit\n\ + -V, --version output version information and exit\n\ "; From 83a7a88b11a31f1a1a3056e5d2565bcef38fc0a2 Mon Sep 17 00:00:00 2001 From: XMRig Date: Fri, 12 Apr 2019 19:25:03 +0700 Subject: [PATCH 22/34] Fixed build without TLS support. --- src/base/net/stratum/DaemonClient.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/base/net/stratum/DaemonClient.cpp b/src/base/net/stratum/DaemonClient.cpp index 251c5fd5..a6826e67 100644 --- a/src/base/net/stratum/DaemonClient.cpp +++ b/src/base/net/stratum/DaemonClient.cpp @@ -137,10 +137,12 @@ void xmrig::DaemonClient::onHttpData(const HttpData &data) m_ip = static_cast(data).ip().c_str(); +# ifdef XMRIG_FEATURE_TLS if (isTLS()) { m_tlsVersion = static_cast(data).version(); m_tlsFingerprint = static_cast(data).fingerprint(); } +# endif rapidjson::Document doc; if (doc.Parse(data.body.c_str()).HasParseError()) { From 23b0e3799e9e6874ff9f47450478d4a00fc2376a Mon Sep 17 00:00:00 2001 From: XMRig Date: Fri, 12 Apr 2019 22:32:45 +0700 Subject: [PATCH 23/34] Fixed build on some systems. --- src/base/tools/String.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/base/tools/String.cpp b/src/base/tools/String.cpp index c7bc3d1b..7778c6da 100644 --- a/src/base/tools/String.cpp +++ b/src/base/tools/String.cpp @@ -23,6 +23,9 @@ */ +#include + + #include "base/tools/String.h" #include "rapidjson/document.h" From 21798edb8bfb4f86daa63befff970b171ef09c09 Mon Sep 17 00:00:00 2001 From: XMRig Date: Sat, 13 Apr 2019 19:09:22 +0700 Subject: [PATCH 24/34] Sync changes. --- src/base/net/stratum/DaemonClient.cpp | 12 +++++++++--- src/base/net/stratum/Job.cpp | 5 +++++ src/base/net/stratum/Pool.h | 3 +++ 3 files changed, 17 insertions(+), 3 deletions(-) diff --git a/src/base/net/stratum/DaemonClient.cpp b/src/base/net/stratum/DaemonClient.cpp index a6826e67..0944b6e6 100644 --- a/src/base/net/stratum/DaemonClient.cpp +++ b/src/base/net/stratum/DaemonClient.cpp @@ -64,7 +64,9 @@ xmrig::DaemonClient::~DaemonClient() bool xmrig::DaemonClient::disconnect() { - setState(UnconnectedState); + if (m_state != UnconnectedState) { + setState(UnconnectedState); + } return true; } @@ -82,11 +84,15 @@ bool xmrig::DaemonClient::isTLS() const int64_t xmrig::DaemonClient::submit(const JobResult &result) { - if (result.jobId != (m_blocktemplate.data() + m_blocktemplate.size() - 48)) { + if (result.jobId != (m_blocktemplate.data() + m_blocktemplate.size() - 32)) { return -1; } +# ifdef XMRIG_PROXY_PROJECT + memcpy(m_blocktemplate.data() + 78, result.nonce, 8); +# else Buffer::toHex(reinterpret_cast(&result.nonce), 4, m_blocktemplate.data() + 78); +# endif using namespace rapidjson; Document doc(kObjectType); @@ -190,7 +196,7 @@ bool xmrig::DaemonClient::parseJob(const rapidjson::Value ¶ms, int *code) job.setHeight(Json::getUint64(params, "height")); job.setDiff(Json::getUint64(params, "difficulty")); - job.setId(blocktemplate.data() + blocktemplate.size() - 48); + job.setId(blocktemplate.data() + blocktemplate.size() - 32); m_job = std::move(job); m_blocktemplate = std::move(blocktemplate); diff --git a/src/base/net/stratum/Job.cpp b/src/base/net/stratum/Job.cpp index 8ef607ad..663818e2 100644 --- a/src/base/net/stratum/Job.cpp +++ b/src/base/net/stratum/Job.cpp @@ -185,6 +185,11 @@ void xmrig::Job::setDiff(uint64_t diff) { m_diff = diff; m_target = toDiff(diff); + +# ifdef XMRIG_PROXY_PROJECT + Buffer::toHex(reinterpret_cast(&m_target), 8, m_rawTarget); + m_rawTarget[16] = '\0'; +# endif } diff --git a/src/base/net/stratum/Pool.h b/src/base/net/stratum/Pool.h index 6eec7aa5..f7987707 100644 --- a/src/base/net/stratum/Pool.h +++ b/src/base/net/stratum/Pool.h @@ -85,6 +85,9 @@ public: inline int keepAlive() const { return m_keepAlive; } inline uint16_t port() const { return m_port; } inline uint64_t pollInterval() const { return m_pollInterval; } + inline void setPassword(const String &password) { m_password = password; } + inline void setRigId(const String &rigId) { m_rigId = rigId; } + inline void setUser(const String &user) { m_user = user; } inline bool operator!=(const Pool &other) const { return !isEqual(other); } inline bool operator==(const Pool &other) const { return isEqual(other); } From c0e668f36f04414eab011cfa0e607b3781640136 Mon Sep 17 00:00:00 2001 From: XMRig Date: Sat, 13 Apr 2019 23:58:58 +0700 Subject: [PATCH 25/34] Move files. --- src/base/base.cmake | 12 ++++++------ src/base/io/{ => json}/Json.cpp | 2 +- src/base/io/{ => json}/Json.h | 0 src/base/io/{ => json}/JsonChain.cpp | 4 ++-- src/base/io/{ => json}/JsonChain.h | 0 src/base/io/{ => json}/Json_unix.cpp | 0 src/base/io/{ => json}/Json_win.cpp | 2 +- src/base/kernel/Base.cpp | 4 ++-- src/base/kernel/config/BaseConfig.cpp | 2 +- src/base/kernel/config/BaseTransform.cpp | 2 +- src/base/net/http/Http.cpp | 2 +- src/base/net/stratum/DaemonClient.cpp | 2 +- src/base/net/stratum/Pool.cpp | 2 +- 13 files changed, 17 insertions(+), 17 deletions(-) rename src/base/io/{ => json}/Json.cpp (99%) rename src/base/io/{ => json}/Json.h (100%) rename src/base/io/{ => json}/JsonChain.cpp (98%) rename src/base/io/{ => json}/JsonChain.h (100%) rename src/base/io/{ => json}/Json_unix.cpp (100%) rename src/base/io/{ => json}/Json_win.cpp (99%) diff --git a/src/base/base.cmake b/src/base/base.cmake index 6d478b39..c1718316 100644 --- a/src/base/base.cmake +++ b/src/base/base.cmake @@ -1,7 +1,7 @@ set(HEADERS_BASE src/base/io/Console.h - src/base/io/Json.h - src/base/io/JsonChain.h + src/base/io/json/Json.h + src/base/io/json/JsonChain.h src/base/io/log/backends/ConsoleLog.h src/base/io/log/backends/FileLog.h src/base/io/log/Log.h @@ -51,8 +51,8 @@ set(HEADERS_BASE set(SOURCES_BASE src/base/io/Console.cpp - src/base/io/Json.cpp - src/base/io/JsonChain.cpp + src/base/io/json/Json.cpp + src/base/io/json/JsonChain.cpp src/base/io/log/backends/ConsoleLog.cpp src/base/io/log/backends/FileLog.cpp src/base/io/log/Log.cpp @@ -81,9 +81,9 @@ set(SOURCES_BASE if (WIN32) - set(SOURCES_OS src/base/io/Json_win.cpp) + set(SOURCES_OS src/base/io/json/Json_win.cpp) else() - set(SOURCES_OS src/base/io/Json_unix.cpp) + set(SOURCES_OS src/base/io/json/Json_unix.cpp) endif() diff --git a/src/base/io/Json.cpp b/src/base/io/json/Json.cpp similarity index 99% rename from src/base/io/Json.cpp rename to src/base/io/json/Json.cpp index 91646453..07986c4a 100644 --- a/src/base/io/Json.cpp +++ b/src/base/io/json/Json.cpp @@ -23,7 +23,7 @@ */ -#include "base/io/Json.h" +#include "base/io/json/Json.h" #include "rapidjson/document.h" diff --git a/src/base/io/Json.h b/src/base/io/json/Json.h similarity index 100% rename from src/base/io/Json.h rename to src/base/io/json/Json.h diff --git a/src/base/io/JsonChain.cpp b/src/base/io/json/JsonChain.cpp similarity index 98% rename from src/base/io/JsonChain.cpp rename to src/base/io/json/JsonChain.cpp index 4dd75f0b..bbaabbde 100644 --- a/src/base/io/JsonChain.cpp +++ b/src/base/io/json/JsonChain.cpp @@ -23,8 +23,8 @@ */ -#include "base/io/Json.h" -#include "base/io/JsonChain.h" +#include "base/io/json/Json.h" +#include "base/io/json/JsonChain.h" #include "base/io/log/Log.h" #include "rapidjson/error/en.h" diff --git a/src/base/io/JsonChain.h b/src/base/io/json/JsonChain.h similarity index 100% rename from src/base/io/JsonChain.h rename to src/base/io/json/JsonChain.h diff --git a/src/base/io/Json_unix.cpp b/src/base/io/json/Json_unix.cpp similarity index 100% rename from src/base/io/Json_unix.cpp rename to src/base/io/json/Json_unix.cpp diff --git a/src/base/io/Json_win.cpp b/src/base/io/json/Json_win.cpp similarity index 99% rename from src/base/io/Json_win.cpp rename to src/base/io/json/Json_win.cpp index 58ee26b7..0faccdea 100644 --- a/src/base/io/Json_win.cpp +++ b/src/base/io/json/Json_win.cpp @@ -35,7 +35,7 @@ #include -#include "base/io/Json.h" +#include "base/io/json/Json.h" #include "rapidjson/document.h" #include "rapidjson/istreamwrapper.h" #include "rapidjson/ostreamwrapper.h" diff --git a/src/base/kernel/Base.cpp b/src/base/kernel/Base.cpp index 157363f0..1083efe9 100644 --- a/src/base/kernel/Base.cpp +++ b/src/base/kernel/Base.cpp @@ -27,8 +27,8 @@ #include -#include "base/io/Json.h" -#include "base/io/JsonChain.h" +#include "base/io/json/Json.h" +#include "base/io/json/JsonChain.h" #include "base/io/log/backends/ConsoleLog.h" #include "base/io/log/backends/FileLog.h" #include "base/io/log/Log.h" diff --git a/src/base/kernel/config/BaseConfig.cpp b/src/base/kernel/config/BaseConfig.cpp index e5fa7293..b2166240 100644 --- a/src/base/kernel/config/BaseConfig.cpp +++ b/src/base/kernel/config/BaseConfig.cpp @@ -49,7 +49,7 @@ #endif -#include "base/io/Json.h" +#include "base/io/json/Json.h" #include "base/io/log/Log.h" #include "base/kernel/config/BaseConfig.h" #include "base/kernel/interfaces/IJsonReader.h" diff --git a/src/base/kernel/config/BaseTransform.cpp b/src/base/kernel/config/BaseTransform.cpp index e4165a4c..615342b9 100644 --- a/src/base/kernel/config/BaseTransform.cpp +++ b/src/base/kernel/config/BaseTransform.cpp @@ -37,7 +37,7 @@ #include "base/kernel/Process.h" #include "base/io/log/Log.h" #include "base/kernel/interfaces/IConfig.h" -#include "base/io/JsonChain.h" +#include "base/io/json/JsonChain.h" #include "core/config/Config_platform.h" diff --git a/src/base/net/http/Http.cpp b/src/base/net/http/Http.cpp index 597260cf..3c275824 100644 --- a/src/base/net/http/Http.cpp +++ b/src/base/net/http/Http.cpp @@ -24,7 +24,7 @@ #include "3rdparty/rapidjson/document.h" -#include "base/io/Json.h" +#include "base/io/json/Json.h" #include "base/net/http/Http.h" diff --git a/src/base/net/stratum/DaemonClient.cpp b/src/base/net/stratum/DaemonClient.cpp index 0944b6e6..0b2a2ec1 100644 --- a/src/base/net/stratum/DaemonClient.cpp +++ b/src/base/net/stratum/DaemonClient.cpp @@ -29,7 +29,7 @@ #include "3rdparty/http-parser/http_parser.h" -#include "base/io/Json.h" +#include "base/io/json/Json.h" #include "base/io/log/Log.h" #include "base/kernel/interfaces/IClientListener.h" #include "base/net/http/HttpClient.h" diff --git a/src/base/net/stratum/Pool.cpp b/src/base/net/stratum/Pool.cpp index d23781ad..f441ba63 100644 --- a/src/base/net/stratum/Pool.cpp +++ b/src/base/net/stratum/Pool.cpp @@ -30,7 +30,7 @@ #include -#include "base/io/Json.h" +#include "base/io/json/Json.h" #include "base/net/stratum/Pool.h" #include "rapidjson/document.h" From 074b3869d2648101a9ffeb2bde1f1682686da31e Mon Sep 17 00:00:00 2001 From: XMRig Date: Sun, 14 Apr 2019 01:10:24 +0700 Subject: [PATCH 26/34] Added JsonRequest. --- src/base/base.cmake | 4 ++- src/base/io/json/JsonRequest.cpp | 38 ++++++++++++++++++++++ src/base/io/json/JsonRequest.h | 45 +++++++++++++++++++++++++++ src/base/net/stratum/Client.cpp | 15 +++------ src/base/net/stratum/DaemonClient.cpp | 16 +++------- 5 files changed, 94 insertions(+), 24 deletions(-) create mode 100644 src/base/io/json/JsonRequest.cpp create mode 100644 src/base/io/json/JsonRequest.h diff --git a/src/base/base.cmake b/src/base/base.cmake index c1718316..dcc10495 100644 --- a/src/base/base.cmake +++ b/src/base/base.cmake @@ -2,6 +2,7 @@ set(HEADERS_BASE src/base/io/Console.h src/base/io/json/Json.h src/base/io/json/JsonChain.h + src/base/io/json/JsonRequest.h src/base/io/log/backends/ConsoleLog.h src/base/io/log/backends/FileLog.h src/base/io/log/Log.h @@ -53,14 +54,15 @@ set(SOURCES_BASE src/base/io/Console.cpp src/base/io/json/Json.cpp src/base/io/json/JsonChain.cpp + src/base/io/json/JsonRequest.cpp src/base/io/log/backends/ConsoleLog.cpp src/base/io/log/backends/FileLog.cpp src/base/io/log/Log.cpp src/base/io/Watcher.cpp + src/base/kernel/Base.cpp src/base/kernel/config/BaseConfig.cpp src/base/kernel/config/BaseTransform.cpp src/base/kernel/Entry.cpp - src/base/kernel/Base.cpp src/base/kernel/Process.cpp src/base/kernel/Signals.cpp src/base/net/dns/Dns.cpp diff --git a/src/base/io/json/JsonRequest.cpp b/src/base/io/json/JsonRequest.cpp new file mode 100644 index 00000000..4556f3f0 --- /dev/null +++ b/src/base/io/json/JsonRequest.cpp @@ -0,0 +1,38 @@ +/* XMRig + * Copyright 2010 Jeff Garzik + * Copyright 2012-2014 pooler + * Copyright 2014 Lucas Jones + * Copyright 2014-2016 Wolf9466 + * Copyright 2016 Jay D Dee + * Copyright 2017-2018 XMR-Stak , + * Copyright 2018-2019 SChernykh + * Copyright 2016-2019 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 "base/io/json/JsonRequest.h" +#include "rapidjson/document.h" + + +void xmrig::JsonRequest::create(rapidjson::Document &doc, int64_t id, const char *method, rapidjson::Value ¶ms) +{ + auto &allocator = doc.GetAllocator(); + + doc.AddMember("id", id, allocator); + doc.AddMember("jsonrpc", "2.0", allocator); + doc.AddMember("method", rapidjson::StringRef(method), allocator); + doc.AddMember("params", params, allocator); +} diff --git a/src/base/io/json/JsonRequest.h b/src/base/io/json/JsonRequest.h new file mode 100644 index 00000000..e98c0bae --- /dev/null +++ b/src/base/io/json/JsonRequest.h @@ -0,0 +1,45 @@ +/* XMRig + * Copyright 2010 Jeff Garzik + * Copyright 2012-2014 pooler + * Copyright 2014 Lucas Jones + * Copyright 2014-2016 Wolf9466 + * Copyright 2016 Jay D Dee + * Copyright 2017-2018 XMR-Stak , + * Copyright 2018-2019 SChernykh + * Copyright 2016-2019 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 XMRIG_JSONREQUEST_H +#define XMRIG_JSONREQUEST_H + + +#include "rapidjson/fwd.h" + + +namespace xmrig { + + +class JsonRequest +{ +public: + static void create(rapidjson::Document &doc, int64_t id, const char *method, rapidjson::Value ¶ms); +}; + + +} /* namespace xmrig */ + + +#endif /* XMRIG_JSONREQUEST_H */ diff --git a/src/base/net/stratum/Client.cpp b/src/base/net/stratum/Client.cpp index df6f4837..1d448ddf 100644 --- a/src/base/net/stratum/Client.cpp +++ b/src/base/net/stratum/Client.cpp @@ -37,6 +37,7 @@ #endif +#include "base/io/json/JsonRequest.h" #include "base/io/log/Log.h" #include "base/kernel/interfaces/IClientListener.h" #include "base/net/dns/Dns.h" @@ -167,10 +168,6 @@ int64_t xmrig::Client::submit(const JobResult &result) Document doc(kObjectType); auto &allocator = doc.GetAllocator(); - doc.AddMember("id", m_sequence, allocator); - doc.AddMember("jsonrpc", "2.0", allocator); - doc.AddMember("method", "submit", allocator); - Value params(kObjectType); params.AddMember("id", StringRef(m_rpcId.data()), allocator); params.AddMember("job_id", StringRef(result.jobId.data()), allocator); @@ -181,7 +178,7 @@ int64_t xmrig::Client::submit(const JobResult &result) params.AddMember("algo", StringRef(result.algorithm.shortName()), allocator); } - doc.AddMember("params", params, allocator); + JsonRequest::create(doc, m_sequence, "submit", params); # ifdef XMRIG_PROXY_PROJECT m_results[m_sequence] = SubmitResult(m_sequence, result.diff, result.actualDiff(), result.id); @@ -584,14 +581,10 @@ void xmrig::Client::login() Document doc(kObjectType); auto &allocator = doc.GetAllocator(); - doc.AddMember("id", 1, allocator); - doc.AddMember("jsonrpc", "2.0", allocator); - doc.AddMember("method", "login", allocator); - Value params(kObjectType); params.AddMember("login", m_pool.user().toJSON(), allocator); params.AddMember("pass", m_pool.password().toJSON(), allocator); - params.AddMember("agent", StringRef(m_agent), allocator); + params.AddMember("agent", StringRef(m_agent), allocator); if (!m_pool.rigId().isNull()) { params.AddMember("rigid", m_pool.rigId().toJSON(), allocator); @@ -612,7 +605,7 @@ void xmrig::Client::login() m_listener->onLogin(this, doc, params); - doc.AddMember("params", params, allocator); + JsonRequest::create(doc, 1, "login", params); send(doc); } diff --git a/src/base/net/stratum/DaemonClient.cpp b/src/base/net/stratum/DaemonClient.cpp index 0b2a2ec1..b4492e7e 100644 --- a/src/base/net/stratum/DaemonClient.cpp +++ b/src/base/net/stratum/DaemonClient.cpp @@ -30,6 +30,7 @@ #include "3rdparty/http-parser/http_parser.h" #include "base/io/json/Json.h" +#include "base/io/json/JsonRequest.h" #include "base/io/log/Log.h" #include "base/kernel/interfaces/IClientListener.h" #include "base/net/http/HttpClient.h" @@ -96,16 +97,11 @@ int64_t xmrig::DaemonClient::submit(const JobResult &result) using namespace rapidjson; Document doc(kObjectType); - auto &allocator = doc.GetAllocator(); - - doc.AddMember("id", m_sequence, allocator); - doc.AddMember("jsonrpc", "2.0", allocator); - doc.AddMember("method", "submitblock", allocator); Value params(kArrayType); - params.PushBack(m_blocktemplate.toJSON(), allocator); + params.PushBack(m_blocktemplate.toJSON(), doc.GetAllocator()); - doc.AddMember("params", params, allocator); + JsonRequest::create(doc, m_sequence, "submitblock", params); # ifdef XMRIG_PROXY_PROJECT m_results[m_sequence] = SubmitResult(m_sequence, result.diff, result.actualDiff(), result.id); @@ -251,15 +247,11 @@ int64_t xmrig::DaemonClient::getBlockTemplate() Document doc(kObjectType); auto &allocator = doc.GetAllocator(); - doc.AddMember("id", m_sequence, allocator); - doc.AddMember("jsonrpc", "2.0", allocator); - doc.AddMember("method", "getblocktemplate", allocator); - Value params(kObjectType); params.AddMember("wallet_address", m_pool.user().toJSON(), allocator); params.AddMember("reserve_size", 8, allocator); - doc.AddMember("params", params, allocator); + JsonRequest::create(doc, m_sequence, "getblocktemplate", params); send(HTTP_POST, "/json_rpc", doc); From a3b303e885acbf79240c200e92659674a30720ec Mon Sep 17 00:00:00 2001 From: XMRig Date: Sun, 14 Apr 2019 03:21:23 +0700 Subject: [PATCH 27/34] Added checking for top_block_hash/hash. --- src/base/net/stratum/DaemonClient.cpp | 49 ++++++++++++++++++++++----- src/base/net/stratum/DaemonClient.h | 3 ++ 2 files changed, 43 insertions(+), 9 deletions(-) diff --git a/src/base/net/stratum/DaemonClient.cpp b/src/base/net/stratum/DaemonClient.cpp index b4492e7e..769e2116 100644 --- a/src/base/net/stratum/DaemonClient.cpp +++ b/src/base/net/stratum/DaemonClient.cpp @@ -50,8 +50,21 @@ #endif +namespace xmrig { + +static const char *kBlocktemplateBlob = "blocktemplate_blob"; +static const char *kGetHeight = "/getheight"; +static const char *kGetInfo = "/getinfo"; +static const char *kHash = "hash"; +static const char *kHeight = "height"; +static const char *kJsonRPC = "/json_rpc"; + +} + + xmrig::DaemonClient::DaemonClient(int id, IClientListener *listener) : - BaseClient(id, listener) + BaseClient(id, listener), + m_monero(true) { m_timer = new Timer(this); } @@ -109,7 +122,7 @@ int64_t xmrig::DaemonClient::submit(const JobResult &result) m_results[m_sequence] = SubmitResult(m_sequence, result.diff, result.actualDiff()); # endif - send(HTTP_POST, "/json_rpc", doc); + send(HTTP_POST, kJsonRPC, doc); return m_sequence++; } @@ -155,8 +168,19 @@ void xmrig::DaemonClient::onHttpData(const HttpData &data) return retry(); } - if (data.method == HTTP_GET && data.url == "/getheight") { - if (m_job.height() != Json::getUint64(doc, "height")) { + if (data.method == HTTP_GET) { + if (data.url == kGetHeight) { + if (!doc.HasMember(kHash)) { + m_monero = false; + + return send(HTTP_GET, kGetInfo); + } + + if (isOutdated(Json::getUint64(doc, kHeight), Json::getString(doc, kHash))) { + getBlockTemplate(); + } + } + else if (data.url == kGetInfo && isOutdated(Json::getUint64(doc, kHeight), Json::getString(doc, "top_block_hash"))) { getBlockTemplate(); } @@ -175,27 +199,34 @@ void xmrig::DaemonClient::onTimer(const Timer *) getBlockTemplate(); } else if (m_state == ConnectedState) { - send(HTTP_GET, "/getheight"); + send(HTTP_GET, m_monero ? kGetHeight : kGetInfo); } } +bool xmrig::DaemonClient::isOutdated(uint64_t height, const char *hash) const +{ + return m_job.height() != height || m_prevHash != hash; +} + + bool xmrig::DaemonClient::parseJob(const rapidjson::Value ¶ms, int *code) { Job job(m_id, false, m_pool.algorithm(), String()); - String blocktemplate = Json::getString(params, "blocktemplate_blob"); + String blocktemplate = Json::getString(params, kBlocktemplateBlob); if (blocktemplate.isNull() || !job.setBlob(Json::getString(params, "blockhashing_blob"))) { *code = 4; return false; } - job.setHeight(Json::getUint64(params, "height")); + job.setHeight(Json::getUint64(params, kHeight)); job.setDiff(Json::getUint64(params, "difficulty")); job.setId(blocktemplate.data() + blocktemplate.size() - 32); m_job = std::move(job); m_blocktemplate = std::move(blocktemplate); + m_prevHash = Json::getString(params, "prev_hash"); if (m_state == ConnectingState) { setState(ConnectedState); @@ -227,7 +258,7 @@ bool xmrig::DaemonClient::parseResponse(int64_t id, const rapidjson::Value &resu } int code = -1; - if (result.HasMember("blocktemplate_blob") && parseJob(result, &code)) { + if (result.HasMember(kBlocktemplateBlob) && parseJob(result, &code)) { return true; } @@ -253,7 +284,7 @@ int64_t xmrig::DaemonClient::getBlockTemplate() JsonRequest::create(doc, m_sequence, "getblocktemplate", params); - send(HTTP_POST, "/json_rpc", doc); + send(HTTP_POST, kJsonRPC, doc); return m_sequence++; } diff --git a/src/base/net/stratum/DaemonClient.h b/src/base/net/stratum/DaemonClient.h index f9438f67..00b62e39 100644 --- a/src/base/net/stratum/DaemonClient.h +++ b/src/base/net/stratum/DaemonClient.h @@ -59,6 +59,7 @@ protected: inline void tick(uint64_t) override {} private: + bool isOutdated(uint64_t height, const char *hash) const; bool parseJob(const rapidjson::Value ¶ms, int *code); bool parseResponse(int64_t id, const rapidjson::Value &result, const rapidjson::Value &error); int64_t getBlockTemplate(); @@ -67,7 +68,9 @@ private: void send(int method, const char *url, const rapidjson::Document &doc); void setState(SocketState state); + bool m_monero; String m_blocktemplate; + String m_prevHash; String m_tlsFingerprint; String m_tlsVersion; Timer *m_timer; From ee1d61d117efcfc591691c9936921a621bac65e4 Mon Sep 17 00:00:00 2001 From: XMRig Date: Sun, 14 Apr 2019 03:24:14 +0700 Subject: [PATCH 28/34] Fix Linux build. --- src/base/io/json/Json_unix.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/base/io/json/Json_unix.cpp b/src/base/io/json/Json_unix.cpp index da3902d8..eeef9564 100644 --- a/src/base/io/json/Json_unix.cpp +++ b/src/base/io/json/Json_unix.cpp @@ -26,7 +26,7 @@ #include -#include "base/io/Json.h" +#include "base/io/json/Json.h" #include "rapidjson/document.h" #include "rapidjson/istreamwrapper.h" #include "rapidjson/ostreamwrapper.h" From 32c3d4b9f6469d57ab4d5fbbb007f3463c2ccac5 Mon Sep 17 00:00:00 2001 From: Tony Butler Date: Mon, 15 Apr 2019 10:39:16 -0600 Subject: [PATCH 29/34] Repair compilation with Clang 9.0.0 (which now includes its own _rotr intrinsic) --- src/crypto/soft_aes.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/crypto/soft_aes.h b/src/crypto/soft_aes.h index 26c1b06a..52fd9b7a 100644 --- a/src/crypto/soft_aes.h +++ b/src/crypto/soft_aes.h @@ -130,7 +130,7 @@ static inline uint32_t sub_word(uint32_t key) saes_sbox[key & 0xff]; } -#if defined(__clang__) || defined(XMRIG_ARM) +#if (defined(__clang__) && __clang_major__ != 9) || defined(XMRIG_ARM) static inline uint32_t _rotr(uint32_t value, uint32_t amount) { return (value >> amount) | (value << ((32 - amount) & 31)); From f9f7ef26b8c9757bb5e6733f420f880fbdb0464a Mon Sep 17 00:00:00 2001 From: XMRig Date: Tue, 16 Apr 2019 01:20:50 +0700 Subject: [PATCH 30/34] #1012 Added checks for _rotr. --- cmake/flags.cmake | 7 +++++++ src/crypto/soft_aes.h | 2 +- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/cmake/flags.cmake b/cmake/flags.cmake index 3989cb71..2f3eb208 100644 --- a/cmake/flags.cmake +++ b/cmake/flags.cmake @@ -10,6 +10,8 @@ if (CMAKE_BUILD_TYPE STREQUAL "Release") add_definitions(/DNDEBUG) endif() +include(CheckSymbolExists) + if (CMAKE_CXX_COMPILER_ID MATCHES GNU) set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Wno-strict-aliasing") @@ -27,6 +29,8 @@ if (CMAKE_CXX_COMPILER_ID MATCHES GNU) else() set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -maes") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -maes") + + add_definitions(/DHAVE_ROTR) endif() if (WIN32) @@ -50,6 +54,7 @@ elseif (CMAKE_CXX_COMPILER_ID MATCHES MSVC) add_definitions(/D_CRT_SECURE_NO_WARNINGS) add_definitions(/D_CRT_NONSTDC_NO_WARNINGS) add_definitions(/DNOMINMAX) + add_definitions(/DHAVE_ROTR) elseif (CMAKE_CXX_COMPILER_ID MATCHES Clang) @@ -68,6 +73,8 @@ elseif (CMAKE_CXX_COMPILER_ID MATCHES Clang) else() set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -maes") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -maes") + + check_symbol_exists("_rotr" "x86intrin.h" HAVE_ROTR) endif() endif() diff --git a/src/crypto/soft_aes.h b/src/crypto/soft_aes.h index 26c1b06a..4ad9bdd9 100644 --- a/src/crypto/soft_aes.h +++ b/src/crypto/soft_aes.h @@ -130,7 +130,7 @@ static inline uint32_t sub_word(uint32_t key) saes_sbox[key & 0xff]; } -#if defined(__clang__) || defined(XMRIG_ARM) +#ifndef HAVE_ROTR static inline uint32_t _rotr(uint32_t value, uint32_t amount) { return (value >> amount) | (value << ((32 - amount) & 31)); From 9137f59ec1216ceef8e4569640748d8bdc452593 Mon Sep 17 00:00:00 2001 From: XMRig Date: Tue, 16 Apr 2019 02:00:27 +0700 Subject: [PATCH 31/34] #1012 Fixed _rotr detection. --- cmake/flags.cmake | 3 +++ 1 file changed, 3 insertions(+) diff --git a/cmake/flags.cmake b/cmake/flags.cmake index 2f3eb208..d50b5c84 100644 --- a/cmake/flags.cmake +++ b/cmake/flags.cmake @@ -75,6 +75,9 @@ elseif (CMAKE_CXX_COMPILER_ID MATCHES Clang) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -maes") check_symbol_exists("_rotr" "x86intrin.h" HAVE_ROTR) + if (HAVE_ROTR) + add_definitions(/DHAVE_ROTR) + endif() endif() endif() From 699269bbae408001f19c53f5e130d93f67d06e0b Mon Sep 17 00:00:00 2001 From: Tony Butler Date: Mon, 15 Apr 2019 13:26:55 -0600 Subject: [PATCH 32/34] Upstream fixed it for good with [Added checks for _rotr.] and [Fixed _rotr detection.] --- cmake/flags.cmake | 10 ++++++++++ src/crypto/soft_aes.h | 2 +- 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/cmake/flags.cmake b/cmake/flags.cmake index 3989cb71..d50b5c84 100644 --- a/cmake/flags.cmake +++ b/cmake/flags.cmake @@ -10,6 +10,8 @@ if (CMAKE_BUILD_TYPE STREQUAL "Release") add_definitions(/DNDEBUG) endif() +include(CheckSymbolExists) + if (CMAKE_CXX_COMPILER_ID MATCHES GNU) set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Wno-strict-aliasing") @@ -27,6 +29,8 @@ if (CMAKE_CXX_COMPILER_ID MATCHES GNU) else() set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -maes") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -maes") + + add_definitions(/DHAVE_ROTR) endif() if (WIN32) @@ -50,6 +54,7 @@ elseif (CMAKE_CXX_COMPILER_ID MATCHES MSVC) add_definitions(/D_CRT_SECURE_NO_WARNINGS) add_definitions(/D_CRT_NONSTDC_NO_WARNINGS) add_definitions(/DNOMINMAX) + add_definitions(/DHAVE_ROTR) elseif (CMAKE_CXX_COMPILER_ID MATCHES Clang) @@ -68,6 +73,11 @@ elseif (CMAKE_CXX_COMPILER_ID MATCHES Clang) else() set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -maes") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -maes") + + check_symbol_exists("_rotr" "x86intrin.h" HAVE_ROTR) + if (HAVE_ROTR) + add_definitions(/DHAVE_ROTR) + endif() endif() endif() diff --git a/src/crypto/soft_aes.h b/src/crypto/soft_aes.h index 52fd9b7a..4ad9bdd9 100644 --- a/src/crypto/soft_aes.h +++ b/src/crypto/soft_aes.h @@ -130,7 +130,7 @@ static inline uint32_t sub_word(uint32_t key) saes_sbox[key & 0xff]; } -#if (defined(__clang__) && __clang_major__ != 9) || defined(XMRIG_ARM) +#ifndef HAVE_ROTR static inline uint32_t _rotr(uint32_t value, uint32_t amount) { return (value >> amount) | (value << ((32 - amount) & 31)); From ff6544a14c07fc0849909878a591d3233e8c99f6 Mon Sep 17 00:00:00 2001 From: XMRig Date: Wed, 17 Apr 2019 19:03:15 +0700 Subject: [PATCH 33/34] Updated default config. --- src/config.json | 4 +++- src/core/config/Config_default.h | 4 +++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/src/config.json b/src/config.json index dbb980d0..53df5486 100644 --- a/src/config.json +++ b/src/config.json @@ -35,7 +35,9 @@ "variant": -1, "enabled": true, "tls": false, - "tls-fingerprint": null + "tls-fingerprint": null, + "daemon": false, + "daemon-poll-interval": 1000 } ], "print-time": 60, diff --git a/src/core/config/Config_default.h b/src/core/config/Config_default.h index 3462ad19..d6145cf4 100644 --- a/src/core/config/Config_default.h +++ b/src/core/config/Config_default.h @@ -69,7 +69,9 @@ R"===( "variant": -1, "enabled": true, "tls": false, - "tls-fingerprint": null + "tls-fingerprint": null, + "daemon": false, + "daemon-poll-interval": 1000 } ], "print-time": 60, From 552858b9e331601a9aa04a17f1d06a505473a3b9 Mon Sep 17 00:00:00 2001 From: xmrig Date: Wed, 17 Apr 2019 23:59:21 +0700 Subject: [PATCH 34/34] Update CHANGELOG.md --- CHANGELOG.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index ada15bed..a4eb3a07 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,9 @@ +# v2.15.2-beta +- [#1010](https://github.com/xmrig/xmrig/pull/1010#issuecomment-482632107) Added daemon support (solo mining). +- [#1012](https://github.com/xmrig/xmrig/pull/1012) Fixed compatibility with clang 9. +- Config subsystem was rewritten, internally JSON is primary format now. +- Fixed regression, big HTTP responses was truncated. + # v2.15.1-beta - [#1007](https://github.com/xmrig/xmrig/issues/1007) Old HTTP API backend based on libmicrohttpd, replaced to custom HTTP server (libuv + http_parser). - [#257](https://github.com/xmrig/xmrig-nvidia/pull/257) New logging subsystem, file and syslog now always without colors.