Merge branch 'evo' into beta

This commit is contained in:
XMRig 2019-04-18 00:25:06 +07:00
commit fe9aa9f3c4
91 changed files with 3746 additions and 1876 deletions

View file

@ -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 # 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). - [#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. - [#257](https://github.com/xmrig/xmrig-nvidia/pull/257) New logging subsystem, file and syslog now always without colors.

View file

@ -6,7 +6,7 @@ option(WITH_AEON "CryptoNight-Lite support" ON)
option(WITH_SUMO "CryptoNight-Heavy support" ON) option(WITH_SUMO "CryptoNight-Heavy support" ON)
option(WITH_CN_PICO "CryptoNight-Pico support" ON) option(WITH_CN_PICO "CryptoNight-Pico support" ON)
option(WITH_CN_GPU "CryptoNight-GPU 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_DEBUG_LOG "Enable debug log output" OFF)
option(WITH_TLS "Enable OpenSSL support" ON) option(WITH_TLS "Enable OpenSSL support" ON)
option(WITH_ASM "Enable ASM PoW implementations" ON) option(WITH_ASM "Enable ASM PoW implementations" ON)
@ -24,20 +24,17 @@ set(HEADERS
"${HEADERS_BASE_HTTP}" "${HEADERS_BASE_HTTP}"
src/api/interfaces/IApiListener.h src/api/interfaces/IApiListener.h
src/App.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/cpu/Cpu.h
src/common/crypto/Algorithm.h src/common/crypto/Algorithm.h
src/common/crypto/keccak.h src/common/crypto/keccak.h
src/common/interfaces/IConfig.h
src/common/interfaces/ICpuInfo.h src/common/interfaces/ICpuInfo.h
src/common/Platform.h src/common/Platform.h
src/common/utils/mm_malloc.h src/common/utils/mm_malloc.h
src/common/xmrig.h src/common/xmrig.h
src/core/config/Config_default.h
src/core/config/Config_platform.h
src/core/config/Config.h src/core/config/Config.h
src/core/config/ConfigLoader_default.h src/core/config/ConfigTransform.h
src/core/config/ConfigLoader_platform.h
src/core/config/usage.h src/core/config/usage.h
src/core/Controller.h src/core/Controller.h
src/interfaces/IJobResultListener.h src/interfaces/IJobResultListener.h
@ -84,13 +81,11 @@ set(SOURCES
"${SOURCES_BASE}" "${SOURCES_BASE}"
"${SOURCES_BASE_HTTP}" "${SOURCES_BASE_HTTP}"
src/App.cpp 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/Algorithm.cpp
src/common/crypto/keccak.cpp src/common/crypto/keccak.cpp
src/common/Platform.cpp src/common/Platform.cpp
src/core/config/Config.cpp src/core/config/Config.cpp
src/core/config/ConfigTransform.cpp
src/core/Controller.cpp src/core/Controller.cpp
src/Mem.cpp src/Mem.cpp
src/net/Network.cpp src/net/Network.cpp
@ -203,8 +198,8 @@ if (WITH_EMBEDDED_CONFIG)
add_definitions(/DXMRIG_FEATURE_EMBEDDED_CONFIG) add_definitions(/DXMRIG_FEATURE_EMBEDDED_CONFIG)
endif() endif()
if (WITH_HTTPD) if (WITH_HTTP)
set(HTTPD_SOURCES set(HTTP_SOURCES
src/api/Api.cpp src/api/Api.cpp
src/api/Api.h src/api/Api.h
src/api/Httpd.cpp src/api/Httpd.cpp
@ -218,7 +213,7 @@ if (WITH_HTTPD)
src/api/v1/ApiRouter.h src/api/v1/ApiRouter.h
) )
else() else()
set(HTTPD_SOURCES "") set(HTTP_SOURCES "")
endif() endif()
include_directories(src) include_directories(src)
@ -233,5 +228,5 @@ if (WITH_DEBUG_LOG)
add_definitions(/DAPP_DEBUG) add_definitions(/DAPP_DEBUG)
endif() 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}) target_link_libraries(${CMAKE_PROJECT_NAME} ${XMRIG_ASM_LIBRARY} ${OPENSSL_LIBRARIES} ${UV_LIBRARIES} ${EXTRA_LIBS} ${CPUID_LIB})

View file

@ -13,6 +13,10 @@ if (WITH_TLS)
if (OPENSSL_FOUND) if (OPENSSL_FOUND)
set(TLS_SOURCES src/base/net/stratum/Tls.h src/base/net/stratum/Tls.cpp) set(TLS_SOURCES src/base/net/stratum/Tls.h src/base/net/stratum/Tls.cpp)
include_directories(${OPENSSL_INCLUDE_DIR}) 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() else()
message(FATAL_ERROR "OpenSSL NOT found: use `-DWITH_TLS=OFF` to build without TLS support") message(FATAL_ERROR "OpenSSL NOT found: use `-DWITH_TLS=OFF` to build without TLS support")
endif() endif()

View file

@ -10,6 +10,8 @@ if (CMAKE_BUILD_TYPE STREQUAL "Release")
add_definitions(/DNDEBUG) add_definitions(/DNDEBUG)
endif() endif()
include(CheckSymbolExists)
if (CMAKE_CXX_COMPILER_ID MATCHES GNU) if (CMAKE_CXX_COMPILER_ID MATCHES GNU)
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Wno-strict-aliasing") set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Wno-strict-aliasing")
@ -27,6 +29,8 @@ if (CMAKE_CXX_COMPILER_ID MATCHES GNU)
else() else()
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -maes") set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -maes")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -maes") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -maes")
add_definitions(/DHAVE_ROTR)
endif() endif()
if (WIN32) if (WIN32)
@ -50,6 +54,7 @@ elseif (CMAKE_CXX_COMPILER_ID MATCHES MSVC)
add_definitions(/D_CRT_SECURE_NO_WARNINGS) add_definitions(/D_CRT_SECURE_NO_WARNINGS)
add_definitions(/D_CRT_NONSTDC_NO_WARNINGS) add_definitions(/D_CRT_NONSTDC_NO_WARNINGS)
add_definitions(/DNOMINMAX) add_definitions(/DNOMINMAX)
add_definitions(/DHAVE_ROTR)
elseif (CMAKE_CXX_COMPILER_ID MATCHES Clang) elseif (CMAKE_CXX_COMPILER_ID MATCHES Clang)
@ -68,6 +73,11 @@ elseif (CMAKE_CXX_COMPILER_ID MATCHES Clang)
else() else()
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -maes") set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -maes")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_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()
endif() endif()

View file

@ -36,6 +36,7 @@
#include "api/interfaces/IApiListener.h" #include "api/interfaces/IApiListener.h"
#include "api/requests/HttpApiRequest.h" #include "api/requests/HttpApiRequest.h"
#include "api/v1/ApiRouter.h" #include "api/v1/ApiRouter.h"
#include "base/kernel/Base.h"
#include "base/tools/Buffer.h" #include "base/tools/Buffer.h"
#include "common/crypto/keccak.h" #include "common/crypto/keccak.h"
#include "core/config/Config.h" #include "core/config/Config.h"
@ -48,17 +49,17 @@
#endif #endif
xmrig::Api::Api(Controller *controller) : xmrig::Api::Api(Base *base) :
m_base(base),
m_id(), m_id(),
m_workerId(), m_workerId(),
m_controller(controller),
m_httpd(nullptr) 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); addListener(m_v1);
} }
@ -73,9 +74,9 @@ xmrig::Api::~Api()
} }
void xmrig::Api::request(const HttpRequest &req) void xmrig::Api::request(const HttpData &req)
{ {
HttpApiRequest request(req, m_controller->config()->http().isRestricted()); HttpApiRequest request(req, m_base->config()->http().isRestricted());
exec(request); exec(request);
} }
@ -83,10 +84,10 @@ void xmrig::Api::request(const HttpRequest &req)
void xmrig::Api::start() void xmrig::Api::start()
{ {
genWorkerId(m_controller->config()->apiWorkerId()); genWorkerId(m_base->config()->apiWorkerId());
# ifdef XMRIG_FEATURE_HTTP # ifdef XMRIG_FEATURE_HTTP
m_httpd = new Httpd(m_controller); m_httpd = new Httpd(m_base);
m_httpd->start(); m_httpd->start();
# endif # endif
} }
@ -155,7 +156,7 @@ void xmrig::Api::genId(const String &id)
uint8_t hash[200]; uint8_t hash[200];
const size_t addrSize = sizeof(interfaces[i].phys_addr); const size_t addrSize = sizeof(interfaces[i].phys_addr);
const size_t inSize = strlen(APP_KIND) + addrSize + sizeof(uint16_t); const size_t inSize = strlen(APP_KIND) + addrSize + sizeof(uint16_t);
const uint16_t port = static_cast<uint16_t>(m_controller->config()->http().port()); const uint16_t port = static_cast<uint16_t>(m_base->config()->http().port());
uint8_t *input = new uint8_t[inSize](); uint8_t *input = new uint8_t[inSize]();
memcpy(input, &port, sizeof(uint16_t)); memcpy(input, &port, sizeof(uint16_t));

View file

@ -29,32 +29,32 @@
#include <vector> #include <vector>
#include "base/kernel/interfaces/IControllerListener.h" #include "base/kernel/interfaces/IBaseListener.h"
namespace xmrig { namespace xmrig {
class ApiRouter; class ApiRouter;
class Controller; class Base;
class Httpd; class Httpd;
class HttpRequest; class HttpData;
class IApiListener; class IApiListener;
class IApiRequest; class IApiRequest;
class String; class String;
class Api : public IControllerListener class Api : public IBaseListener
{ {
public: public:
Api(Controller *controller); Api(Base *base);
~Api() override; ~Api() override;
inline const char *id() const { return m_id; } inline const char *id() const { return m_id; }
inline const char *workerId() const { return m_workerId; } inline const char *workerId() const { return m_workerId; }
inline void addListener(IApiListener *listener) { m_listeners.push_back(listener); } inline void addListener(IApiListener *listener) { m_listeners.push_back(listener); }
void request(const HttpRequest &req); void request(const HttpData &req);
void start(); void start();
void stop(); void stop();
@ -67,9 +67,9 @@ private:
void genWorkerId(const String &id); void genWorkerId(const String &id);
ApiRouter *m_v1; ApiRouter *m_v1;
Base *m_base;
char m_id[32]; char m_id[32];
char m_workerId[128]; char m_workerId[128];
Controller *m_controller;
Httpd *m_httpd; Httpd *m_httpd;
std::vector<IApiListener *> m_listeners; std::vector<IApiListener *> m_listeners;
}; };

View file

@ -28,7 +28,7 @@
#include "api/Httpd.h" #include "api/Httpd.h"
#include "base/io/log/Log.h" #include "base/io/log/Log.h"
#include "base/net/http/HttpApiResponse.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/http/HttpServer.h"
#include "base/net/tools/TcpServer.h" #include "base/net/tools/TcpServer.h"
#include "core/config/Config.h" #include "core/config/Config.h"
@ -48,13 +48,13 @@ static size_t faviconSize = 0;
} // namespace xmrig } // namespace xmrig
xmrig::Httpd::Httpd(Controller *controller) : xmrig::Httpd::Httpd(Base *base) :
m_controller(controller), m_base(base),
m_http(nullptr), m_http(nullptr),
m_server(nullptr), m_server(nullptr),
m_port(0) m_port(0)
{ {
controller->addListener(this); base->addListener(this);
} }
@ -65,7 +65,7 @@ xmrig::Httpd::~Httpd()
bool xmrig::Httpd::start() bool xmrig::Httpd::start()
{ {
const Http &config = m_controller->config()->http(); const Http &config = m_base->config()->http();
if (!config.isEnabled()) { if (!config.isEnabled()) {
return true; return true;
@ -128,51 +128,51 @@ 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) { if (data.method == HTTP_OPTIONS) {
return HttpApiResponse(req.id()).end(); 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 # ifdef _WIN32
if (favicon != nullptr) { if (favicon != nullptr) {
HttpResponse response(req.id()); HttpResponse response(data.id());
response.setHeader("Content-Type", "image/x-icon"); response.setHeader("Content-Type", "image/x-icon");
return response.end(favicon, faviconSize); return response.end(favicon, faviconSize);
} }
# endif # endif
return HttpResponse(req.id(), 404).end(); return HttpResponse(data.id(), 404).end();
} }
if (req.method > 4) { if (data.method > 4) {
return HttpApiResponse(req.id(), HTTP_STATUS_METHOD_NOT_ALLOWED).end(); 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) { 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_controller->config()->http().isRestricted()) { 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") { if (!data.headers.count(kContentType) || data.headers.at(kContentType) != "application/json") {
return HttpApiResponse(req.id(), HTTP_STATUS_UNSUPPORTED_MEDIA_TYPE).end(); return HttpApiResponse(data.id(), HTTP_STATUS_UNSUPPORTED_MEDIA_TYPE).end();
} }
} }
m_controller->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_controller->config()->http(); const Http &config = m_base->config()->http();
if (!req.headers.count(kAuthorization)) { if (!req.headers.count(kAuthorization)) {
return config.isAuthRequired() ? HTTP_STATUS_UNAUTHORIZED : HTTP_STATUS_OK; return config.isAuthRequired() ? HTTP_STATUS_UNAUTHORIZED : HTTP_STATUS_OK;

View file

@ -29,22 +29,22 @@
#include <stdint.h> #include <stdint.h>
#include "base/kernel/interfaces/IControllerListener.h" #include "base/kernel/interfaces/IBaseListener.h"
#include "base/kernel/interfaces/IHttpListener.h" #include "base/kernel/interfaces/IHttpListener.h"
namespace xmrig { namespace xmrig {
class Controller; class Base;
class HttpServer; class HttpServer;
class TcpServer; class TcpServer;
class Httpd : public IControllerListener, public IHttpListener class Httpd : public IBaseListener, public IHttpListener
{ {
public: public:
Httpd(Controller *controller); Httpd(Base *base);
~Httpd() override; ~Httpd() override;
bool start(); bool start();
@ -52,12 +52,12 @@ public:
protected: protected:
void onConfigChanged(Config *config, Config *previousConfig) override; void onConfigChanged(Config *config, Config *previousConfig) override;
void onHttpRequest(const HttpRequest &req) override; void onHttpData(const HttpData &data) override;
private: private:
int auth(const HttpRequest &req) const; int auth(const HttpData &req) const;
Controller *m_controller; Base *m_base;
HttpServer *m_http; HttpServer *m_http;
TcpServer *m_server; TcpServer *m_server;
uint16_t m_port; uint16_t m_port;

View file

@ -24,11 +24,11 @@
#include "api/requests/HttpApiRequest.h" #include "api/requests/HttpApiRequest.h"
#include "base/net/http/HttpRequest.h" #include "base/net/http/HttpData.h"
#include "rapidjson/error/en.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), ApiRequest(SOURCE_HTTP, restricted),
m_parsed(false), m_parsed(false),
m_req(req), m_req(req),

View file

@ -35,13 +35,13 @@
namespace xmrig { namespace xmrig {
class HttpRequest; class HttpData;
class HttpApiRequest : public ApiRequest class HttpApiRequest : public ApiRequest
{ {
public: public:
HttpApiRequest(const HttpRequest &req, bool restricted); HttpApiRequest(const HttpData &req, bool restricted);
protected: protected:
inline rapidjson::Document &doc() override { return m_res.doc(); } inline rapidjson::Document &doc() override { return m_res.doc(); }
@ -55,7 +55,7 @@ protected:
private: private:
bool m_parsed; bool m_parsed;
const HttpRequest &m_req; const HttpData &m_req;
HttpApiResponse m_res; HttpApiResponse m_res;
rapidjson::Document m_body; rapidjson::Document m_body;
String m_url; String m_url;

View file

@ -29,10 +29,10 @@
#include "api/interfaces/IApiRequest.h" #include "api/interfaces/IApiRequest.h"
#include "api/v1/ApiRouter.h" #include "api/v1/ApiRouter.h"
#include "base/kernel/Base.h"
#include "common/cpu/Cpu.h" #include "common/cpu/Cpu.h"
#include "common/Platform.h" #include "common/Platform.h"
#include "core/config/Config.h" #include "core/config/Config.h"
#include "core/Controller.h"
#include "interfaces/IThread.h" #include "interfaces/IThread.h"
#include "rapidjson/document.h" #include "rapidjson/document.h"
#include "version.h" #include "version.h"
@ -50,8 +50,8 @@ static inline double normalize(double d)
} }
xmrig::ApiRouter::ApiRouter(xmrig::Controller *controller) : xmrig::ApiRouter::ApiRouter(Base *base) :
m_controller(controller) m_base(base)
{ {
} }
@ -79,14 +79,14 @@ void xmrig::ApiRouter::onRequest(IApiRequest &request)
} }
request.accept(); 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) { else if (request.method() == IApiRequest::METHOD_PUT || request.method() == IApiRequest::METHOD_POST) {
if (request.url() == "/1/config") { if (request.url() == "/1/config") {
request.accept(); request.accept();
if (!m_controller->config()->reload(request.json())) { if (!m_base->reload(request.json())) {
return request.done(400); 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("kind", APP_KIND, allocator);
reply.AddMember("ua", StringRef(Platform::userAgent()), allocator); reply.AddMember("ua", StringRef(Platform::userAgent()), allocator);
reply.AddMember("cpu", cpu, 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("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); Workers::threadsSummary(doc);
const std::vector<xmrig::IThread *> &threads = m_controller->config()->threads(); const std::vector<IThread *> &threads = m_base->config()->threads();
Value list(kArrayType); Value list(kArrayType);
size_t i = 0; size_t i = 0;

View file

@ -36,13 +36,13 @@ class Hashrate;
namespace xmrig { namespace xmrig {
class Controller; class Base;
class ApiRouter : public xmrig::IApiListener class ApiRouter : public xmrig::IApiListener
{ {
public: public:
ApiRouter(Controller *controller); ApiRouter(Base *base);
~ApiRouter() override; ~ApiRouter() override;
protected: protected:
@ -53,7 +53,7 @@ private:
void getMiner(rapidjson::Value &reply, rapidjson::Document &doc) const; void getMiner(rapidjson::Value &reply, rapidjson::Document &doc) const;
void getThreads(rapidjson::Value &reply, rapidjson::Document &doc) const; void getThreads(rapidjson::Value &reply, rapidjson::Document &doc) const;
Controller *m_controller; Base *m_base;
}; };

View file

@ -1,15 +1,23 @@
set(HEADERS_BASE set(HEADERS_BASE
src/base/io/Console.h src/base/io/Console.h
src/base/io/Json.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/ConsoleLog.h
src/base/io/log/backends/FileLog.h src/base/io/log/backends/FileLog.h
src/base/io/log/Log.h src/base/io/log/Log.h
src/base/io/Watcher.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/Entry.h
src/base/kernel/interfaces/IBaseListener.h
src/base/kernel/interfaces/IClient.h
src/base/kernel/interfaces/IClientListener.h src/base/kernel/interfaces/IClientListener.h
src/base/kernel/interfaces/IConfig.h
src/base/kernel/interfaces/IConfigListener.h src/base/kernel/interfaces/IConfigListener.h
src/base/kernel/interfaces/IConfigTransform.h
src/base/kernel/interfaces/IConsoleListener.h src/base/kernel/interfaces/IConsoleListener.h
src/base/kernel/interfaces/IControllerListener.h
src/base/kernel/interfaces/IDnsListener.h src/base/kernel/interfaces/IDnsListener.h
src/base/kernel/interfaces/ILineListener.h src/base/kernel/interfaces/ILineListener.h
src/base/kernel/interfaces/ILogBackend.h src/base/kernel/interfaces/ILogBackend.h
@ -23,6 +31,7 @@ set(HEADERS_BASE
src/base/net/dns/Dns.h src/base/net/dns/Dns.h
src/base/net/dns/DnsRecord.h src/base/net/dns/DnsRecord.h
src/base/net/http/Http.h src/base/net/http/Http.h
src/base/net/stratum/BaseClient.h
src/base/net/stratum/Client.h src/base/net/stratum/Client.h
src/base/net/stratum/Job.h src/base/net/stratum/Job.h
src/base/net/stratum/Pool.h src/base/net/stratum/Pool.h
@ -33,6 +42,7 @@ set(HEADERS_BASE
src/base/net/tools/RecvBuf.h src/base/net/tools/RecvBuf.h
src/base/net/tools/Storage.h src/base/net/tools/Storage.h
src/base/tools/Arguments.h src/base/tools/Arguments.h
src/base/tools/Baton.h
src/base/tools/Buffer.h src/base/tools/Buffer.h
src/base/tools/Chrono.h src/base/tools/Chrono.h
src/base/tools/Handle.h src/base/tools/Handle.h
@ -42,17 +52,23 @@ set(HEADERS_BASE
set(SOURCES_BASE set(SOURCES_BASE
src/base/io/Console.cpp src/base/io/Console.cpp
src/base/io/Json.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/ConsoleLog.cpp
src/base/io/log/backends/FileLog.cpp src/base/io/log/backends/FileLog.cpp
src/base/io/log/Log.cpp src/base/io/log/Log.cpp
src/base/io/Watcher.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/Entry.cpp
src/base/kernel/Process.cpp src/base/kernel/Process.cpp
src/base/kernel/Signals.cpp src/base/kernel/Signals.cpp
src/base/net/dns/Dns.cpp src/base/net/dns/Dns.cpp
src/base/net/dns/DnsRecord.cpp src/base/net/dns/DnsRecord.cpp
src/base/net/http/Http.cpp src/base/net/http/Http.cpp
src/base/net/stratum/BaseClient.cpp
src/base/net/stratum/Client.cpp src/base/net/stratum/Client.cpp
src/base/net/stratum/Job.cpp src/base/net/stratum/Job.cpp
src/base/net/stratum/Pool.cpp src/base/net/stratum/Pool.cpp
@ -67,9 +83,9 @@ set(SOURCES_BASE
if (WIN32) if (WIN32)
set(SOURCES_OS src/base/io/Json_win.cpp) set(SOURCES_OS src/base/io/json/Json_win.cpp)
else() else()
set(SOURCES_OS src/base/io/Json_unix.cpp) set(SOURCES_OS src/base/io/json/Json_unix.cpp)
endif() endif()
@ -82,25 +98,30 @@ if (NOT WIN32)
endif() endif()
if (WITH_HTTPD) if (WITH_HTTP)
set(HEADERS_BASE_HTTP set(HEADERS_BASE_HTTP
src/3rdparty/http-parser/http_parser.h src/3rdparty/http-parser/http_parser.h
src/base/kernel/interfaces/IHttpListener.h src/base/kernel/interfaces/IHttpListener.h
src/base/kernel/interfaces/IJsonReader.h
src/base/kernel/interfaces/ITcpServerListener.h src/base/kernel/interfaces/ITcpServerListener.h
src/base/net/http/HttpApiResponse.h src/base/net/http/HttpApiResponse.h
src/base/net/http/HttpClient.h
src/base/net/http/HttpContext.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/HttpResponse.h
src/base/net/http/HttpServer.h src/base/net/http/HttpServer.h
src/base/net/stratum/DaemonClient.h
src/base/net/tools/TcpServer.h src/base/net/tools/TcpServer.h
) )
set(SOURCES_BASE_HTTP set(SOURCES_BASE_HTTP
src/3rdparty/http-parser/http_parser.c src/3rdparty/http-parser/http_parser.c
src/base/net/http/HttpApiResponse.cpp src/base/net/http/HttpApiResponse.cpp
src/base/net/http/HttpClient.cpp
src/base/net/http/HttpContext.cpp src/base/net/http/HttpContext.cpp
src/base/net/http/HttpResponse.cpp src/base/net/http/HttpResponse.cpp
src/base/net/http/HttpServer.cpp src/base/net/http/HttpServer.cpp
src/base/net/stratum/DaemonClient.cpp
src/base/net/tools/TcpServer.cpp src/base/net/tools/TcpServer.cpp
) )

View file

@ -23,10 +23,17 @@
*/ */
#include "base/io/Json.h" #include "base/io/json/Json.h"
#include "rapidjson/document.h" #include "rapidjson/document.h"
namespace xmrig {
static const rapidjson::Value kNullValue;
}
bool xmrig::Json::getBool(const rapidjson::Value &obj, const char *key, bool defaultValue) bool xmrig::Json::getBool(const rapidjson::Value &obj, const char *key, bool defaultValue)
{ {
auto i = obj.FindMember(key); 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) int xmrig::Json::getInt(const rapidjson::Value &obj, const char *key, int defaultValue)
{ {
auto i = obj.FindMember(key); auto i = obj.FindMember(key);
@ -91,3 +131,9 @@ unsigned xmrig::Json::getUint(const rapidjson::Value &obj, const char *key, unsi
return defaultValue; return defaultValue;
} }
bool xmrig::JsonReader::isEmpty() const
{
return !m_obj.IsObject() || m_obj.ObjectEmpty();
}

79
src/base/io/json/Json.h Normal file
View file

@ -0,0 +1,79 @@
/* XMRig
* Copyright 2010 Jeff Garzik <jgarzik@pobox.com>
* Copyright 2012-2014 pooler <pooler@litecoinpool.org>
* Copyright 2014 Lucas Jones <https://github.com/lucasjones>
* Copyright 2014-2016 Wolf9466 <https://github.com/OhGodAPet>
* Copyright 2016 Jay D Dee <jayddee246@gmail.com>
* Copyright 2017-2018 XMR-Stak <https://github.com/fireice-uk>, <https://github.com/psychocrypt>
* Copyright 2018-2019 SChernykh <https://github.com/SChernykh>
* Copyright 2016-2019 XMRig <https://github.com/xmrig>, <support@xmrig.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef XMRIG_JSON_H
#define XMRIG_JSON_H
#include "base/kernel/interfaces/IJsonReader.h"
#include "rapidjson/fwd.h"
namespace xmrig {
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);
static unsigned getUint(const rapidjson::Value &obj, const char *key, unsigned defaultValue = 0);
static bool get(const char *fileName, rapidjson::Document &doc);
static bool save(const char *fileName, const rapidjson::Document &doc);
};
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 */
#endif /* XMRIG_JSON_H */

View file

@ -0,0 +1,213 @@
/* XMRig
* Copyright 2010 Jeff Garzik <jgarzik@pobox.com>
* Copyright 2012-2014 pooler <pooler@litecoinpool.org>
* Copyright 2014 Lucas Jones <https://github.com/lucasjones>
* Copyright 2014-2016 Wolf9466 <https://github.com/OhGodAPet>
* Copyright 2016 Jay D Dee <jayddee246@gmail.com>
* Copyright 2017-2018 XMR-Stak <https://github.com/fireice-uk>, <https://github.com/psychocrypt>
* Copyright 2018-2019 SChernykh <https://github.com/SChernykh>
* Copyright 2016-2019 XMRig <https://github.com/xmrig>, <support@xmrig.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "base/io/json/Json.h"
#include "base/io/json/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<offset:%zu>: \"%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<kParseCommentsFlag | kParseTrailingCommasFlag>(json);
return add(std::move(doc));
}
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) {
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;
}

View file

@ -0,0 +1,76 @@
/* XMRig
* Copyright 2010 Jeff Garzik <jgarzik@pobox.com>
* Copyright 2012-2014 pooler <pooler@litecoinpool.org>
* Copyright 2014 Lucas Jones <https://github.com/lucasjones>
* Copyright 2014-2016 Wolf9466 <https://github.com/OhGodAPet>
* Copyright 2016 Jay D Dee <jayddee246@gmail.com>
* Copyright 2017-2018 XMR-Stak <https://github.com/fireice-uk>, <https://github.com/psychocrypt>
* Copyright 2018-2019 SChernykh <https://github.com/SChernykh>
* Copyright 2016-2019 XMRig <https://github.com/xmrig>, <support@xmrig.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef XMRIG_JSONCHAIN_H
#define XMRIG_JSONCHAIN_H
#include <vector>
#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);
void dump(const char *fileName);
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<rapidjson::Document> m_chain;
String m_fileName;
};
} /* namespace xmrig */
#endif /* XMRIG_JSONCHAIN_H */

View file

@ -0,0 +1,38 @@
/* XMRig
* Copyright 2010 Jeff Garzik <jgarzik@pobox.com>
* Copyright 2012-2014 pooler <pooler@litecoinpool.org>
* Copyright 2014 Lucas Jones <https://github.com/lucasjones>
* Copyright 2014-2016 Wolf9466 <https://github.com/OhGodAPet>
* Copyright 2016 Jay D Dee <jayddee246@gmail.com>
* Copyright 2017-2018 XMR-Stak <https://github.com/fireice-uk>, <https://github.com/psychocrypt>
* Copyright 2018-2019 SChernykh <https://github.com/SChernykh>
* Copyright 2016-2019 XMRig <https://github.com/xmrig>, <support@xmrig.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "base/io/json/JsonRequest.h"
#include "rapidjson/document.h"
void xmrig::JsonRequest::create(rapidjson::Document &doc, int64_t id, const char *method, rapidjson::Value &params)
{
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);
}

View file

@ -22,8 +22,8 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#ifndef XMRIG_JSON_H #ifndef XMRIG_JSONREQUEST_H
#define XMRIG_JSON_H #define XMRIG_JSONREQUEST_H
#include "rapidjson/fwd.h" #include "rapidjson/fwd.h"
@ -32,22 +32,14 @@
namespace xmrig { namespace xmrig {
class Json class JsonRequest
{ {
public: public:
static bool getBool(const rapidjson::Value &obj, const char *key, bool defaultValue = false); static void create(rapidjson::Document &doc, int64_t id, const char *method, rapidjson::Value &params);
static const char *getString(const rapidjson::Value &obj, const char *key, const char *defaultValue = nullptr);
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);
static unsigned getUint(const rapidjson::Value &obj, const char *key, unsigned defaultValue = 0);
static bool get(const char *fileName, rapidjson::Document &doc);
static bool save(const char *fileName, const rapidjson::Document &doc);
}; };
} /* namespace xmrig */ } /* namespace xmrig */
#endif /* XMRIG_JSON_H */ #endif /* XMRIG_JSONREQUEST_H */

View file

@ -26,7 +26,7 @@
#include <fstream> #include <fstream>
#include "base/io/Json.h" #include "base/io/json/Json.h"
#include "rapidjson/document.h" #include "rapidjson/document.h"
#include "rapidjson/istreamwrapper.h" #include "rapidjson/istreamwrapper.h"
#include "rapidjson/ostreamwrapper.h" #include "rapidjson/ostreamwrapper.h"

View file

@ -35,7 +35,7 @@
#include <fstream> #include <fstream>
#include "base/io/Json.h" #include "base/io/json/Json.h"
#include "rapidjson/document.h" #include "rapidjson/document.h"
#include "rapidjson/istreamwrapper.h" #include "rapidjson/istreamwrapper.h"
#include "rapidjson/ostreamwrapper.h" #include "rapidjson/ostreamwrapper.h"
@ -102,7 +102,7 @@ bool xmrig::Json::save(const char *fileName, const rapidjson::Document &doc)
return false; return false;
} }
# elif defined(__GNUC__) # 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) { if (fd == -1) {
return false; return false;
} }

View file

@ -40,6 +40,7 @@
#include "base/io/log/Log.h" #include "base/io/log/Log.h"
#include "base/kernel/interfaces/ILogBackend.h" #include "base/kernel/interfaces/ILogBackend.h"
#include "base/tools/Chrono.h"
namespace xmrig { namespace xmrig {
@ -134,7 +135,8 @@ private:
return; return;
} }
time_t now = time(nullptr); const uint64_t ms = Chrono::currentMSecsSinceEpoch();
time_t now = ms / 1000;
tm stime; tm stime;
# ifdef _WIN32 # ifdef _WIN32
@ -143,13 +145,14 @@ private:
localtime_r(&now, &stime); localtime_r(&now, &stime);
# endif # 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_year + 1900,
stime.tm_mon + 1, stime.tm_mon + 1,
stime.tm_mday, stime.tm_mday,
stime.tm_hour, stime.tm_hour,
stime.tm_min, stime.tm_min,
stime.tm_sec stime.tm_sec,
static_cast<int>(ms % 1000)
); );
if (rc > 0) { if (rc > 0) {

290
src/base/kernel/Base.cpp Normal file
View file

@ -0,0 +1,290 @@
/* XMRig
* Copyright 2010 Jeff Garzik <jgarzik@pobox.com>
* Copyright 2012-2014 pooler <pooler@litecoinpool.org>
* Copyright 2014 Lucas Jones <https://github.com/lucasjones>
* Copyright 2014-2016 Wolf9466 <https://github.com/OhGodAPet>
* Copyright 2016 Jay D Dee <jayddee246@gmail.com>
* Copyright 2017-2018 XMR-Stak <https://github.com/fireice-uk>, <https://github.com/psychocrypt>
* Copyright 2018-2019 SChernykh <https://github.com/SChernykh>
* Copyright 2016-2019 XMRig <https://github.com/xmrig>, <support@xmrig.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <assert.h>
#include <memory>
#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"
#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.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
#ifdef XMRIG_FEATURE_EMBEDDED_CONFIG
# include "core/config/Config_default.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)
{
config = std::unique_ptr<Config>(new Config());
return config->read(chain, chain.fileName());
}
inline Config *load()
{
JsonChain chain;
ConfigTransform transform;
std::unique_ptr<Config> 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<IBaseListener *> 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());
# ifndef XMRIG_PROXY_PROJECT
Platform::setProcessPriority(config()->priority());
# endif
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);
}

View file

@ -22,42 +22,50 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#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 "base/kernel/interfaces/IConfigListener.h"
#include "common/config/ConfigLoader.h" #include "base/kernel/interfaces/IWatcherListener.h"
#include "common/config/ConfigWatcher.h" #include "rapidjson/fwd.h"
#include "core/config/Config.h"
xmrig::ConfigWatcher::ConfigWatcher(const String &path, IConfigListener *listener) : namespace xmrig {
m_listener(listener)
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() } /* namespace xmrig */
{
delete m_watcher;
}
#endif /* XMRIG_BASE_H */
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);
}

View file

@ -0,0 +1,196 @@
/* XMRig
* Copyright 2010 Jeff Garzik <jgarzik@pobox.com>
* Copyright 2012-2014 pooler <pooler@litecoinpool.org>
* Copyright 2014 Lucas Jones <https://github.com/lucasjones>
* Copyright 2014-2016 Wolf9466 <https://github.com/OhGodAPet>
* Copyright 2016 Jay D Dee <jayddee246@gmail.com>
* Copyright 2017-2018 XMR-Stak <https://github.com/fireice-uk>, <https://github.com/psychocrypt>
* Copyright 2018-2019 SChernykh <https://github.com/SChernykh>
* Copyright 2016-2019 XMRig <https://github.com/xmrig>, <support@xmrig.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <uv.h>
#ifdef XMRIG_FEATURE_TLS
# include <openssl/opensslv.h>
#endif
#ifdef XMRIG_AMD_PROJECT
# if defined(__APPLE__)
# include <OpenCL/cl.h>
# else
# include "3rdparty/CL/cl.h"
# endif
#endif
#ifdef XMRIG_NVIDIA_PROJECT
# include "nvidia/cryptonight.h"
#endif
#include "base/io/json/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<int>(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);
Log::colors = reader.getBool("colors", Log::colors);
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;
}

View file

@ -22,60 +22,54 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#ifndef XMRIG_COMMONCONFIG_H #ifndef XMRIG_BASECONFIG_H
#define XMRIG_COMMONCONFIG_H #define XMRIG_BASECONFIG_H
#include "base/kernel/interfaces/IConfig.h"
#include "base/net/http/Http.h" #include "base/net/http/Http.h"
#include "base/net/stratum/Pools.h" #include "base/net/stratum/Pools.h"
#include "common/interfaces/IConfig.h"
#include "common/xmrig.h" #include "common/xmrig.h"
struct option;
namespace xmrig { namespace xmrig {
class CommonConfig : public IConfig class IJsonReader;
class BaseConfig : public IConfig
{ {
public: public:
CommonConfig(); BaseConfig();
inline bool isAutoSave() const { return m_autoSave; } inline bool isAutoSave() const { return m_autoSave; }
inline bool isBackground() const { return m_background; } inline bool isBackground() const { return m_background; }
inline bool isDryRun() const { return m_dryRun; } inline bool isDryRun() const { return m_dryRun; }
inline bool isSyslog() const { return m_syslog; } 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 *logFile() const { return m_logFile.data(); }
inline const char *userAgent() const { return m_userAgent.data(); } inline const char *userAgent() const { return m_userAgent.data(); }
inline const Http &http() const { return m_http; } inline const Http &http() const { return m_http; }
inline const Pools &pools() const { return m_pools; } 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 bool isWatch() const override { return m_watch && !m_fileName.isNull(); }
inline const Algorithm &algorithm() const override { return m_algorithm; } inline const Algorithm &algorithm() const override { return m_algorithm; }
inline const String &fileName() const override { return m_fileName; } 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; bool save() override;
void printVersions(); void printVersions();
protected: 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; Algorithm m_algorithm;
bool m_adjusted;
bool m_autoSave; bool m_autoSave;
bool m_background; bool m_background;
bool m_dryRun; bool m_dryRun;
@ -83,20 +77,20 @@ protected:
bool m_upgrade; bool m_upgrade;
bool m_watch; bool m_watch;
Http m_http; Http m_http;
int m_printTime;
Pools m_pools; Pools m_pools;
State m_state;
String m_apiId; String m_apiId;
String m_apiWorkerId; String m_apiWorkerId;
String m_fileName; String m_fileName;
String m_logFile; String m_logFile;
String m_userAgent; String m_userAgent;
uint32_t m_printTime;
private: 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 */

View file

@ -0,0 +1,279 @@
/* XMRig
* Copyright 2010 Jeff Garzik <jgarzik@pobox.com>
* Copyright 2012-2014 pooler <pooler@litecoinpool.org>
* Copyright 2014 Lucas Jones <https://github.com/lucasjones>
* Copyright 2014-2016 Wolf9466 <https://github.com/OhGodAPet>
* Copyright 2016 Jay D Dee <jayddee246@gmail.com>
* Copyright 2017-2018 XMR-Stak <https://github.com/fireice-uk>, <https://github.com/psychocrypt>
* Copyright 2018-2019 SChernykh <https://github.com/SChernykh>
* Copyright 2016-2019 XMRig <https://github.com/xmrig>, <support@xmrig.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <stdio.h>
#ifdef _MSC_VER
# include "getopt/getopt.h"
#else
# include <getopt.h>
#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/json/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 */
{
const char *p = strrchr(arg, ':');
if (!p) {
return;
}
char *user = new char[p - arg + 1]();
strncpy(user, arg, static_cast<size_t>(p - arg));
add<const char *>(doc, kPools, "user", user);
add(doc, kPools, "pass", p + 1);
delete [] user;
}
break;
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 */
case IConfig::DaemonPollKey: /* --daemon-poll-interval */
# ifdef XMRIG_DEPRECATED
case IConfig::ApiPort: /* --api-port */
# endif
return transformUint64(doc, key, static_cast<uint64_t>(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 */
case IConfig::DaemonKey: /* --daemon */
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);
case IConfig::DaemonKey: /* --daemon */
return add(doc, kPools, "daemon", enable);
# ifndef XMRIG_PROXY_PROJECT
case IConfig::NicehashKey: /* --nicehash */
return add<bool>(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);
case IConfig::DaemonPollKey: /* --daemon-poll-interval */
return add(doc, kPools, "daemon-poll-interval", arg);
default:
break;
}
}

View file

@ -0,0 +1,123 @@
/* XMRig
* Copyright 2010 Jeff Garzik <jgarzik@pobox.com>
* Copyright 2012-2014 pooler <pooler@litecoinpool.org>
* Copyright 2014 Lucas Jones <https://github.com/lucasjones>
* Copyright 2014-2016 Wolf9466 <https://github.com/OhGodAPet>
* Copyright 2016 Jay D Dee <jayddee246@gmail.com>
* Copyright 2017-2018 XMR-Stak <https://github.com/fireice-uk>, <https://github.com/psychocrypt>
* Copyright 2018-2019 SChernykh <https://github.com/SChernykh>
* Copyright 2016-2019 XMRig <https://github.com/xmrig>, <support@xmrig.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef 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<typename T>
inline void set(rapidjson::Document &doc, const char *key, T value) { set<T>(doc, doc, key, value); }
template<typename T>
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<T>(doc, doc[objKey], key, value);
}
template<typename T>
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<T>(doc, array[array.Size() - 1], key, value);
}
template<typename T>
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 */

View file

@ -22,8 +22,8 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#ifndef XMRIG_ICONTROLLERLISTENER_H #ifndef XMRIG_IBASELISTENER_H
#define XMRIG_ICONTROLLERLISTENER_H #define XMRIG_IBASELISTENER_H
namespace xmrig { namespace xmrig {
@ -32,10 +32,10 @@ namespace xmrig {
class Config; class Config;
class IControllerListener class IBaseListener
{ {
public: public:
virtual ~IControllerListener() = default; virtual ~IBaseListener() = default;
virtual void onConfigChanged(Config *config, Config *previousConfig) = 0; virtual void onConfigChanged(Config *config, Config *previousConfig) = 0;
}; };
@ -44,4 +44,4 @@ public:
} /* namespace xmrig */ } /* namespace xmrig */
#endif // XMRIG_ICONTROLLERLISTENER_H #endif // XMRIG_IBASELISTENER_H

View file

@ -0,0 +1,85 @@
/* XMRig
* Copyright 2010 Jeff Garzik <jgarzik@pobox.com>
* Copyright 2012-2014 pooler <pooler@litecoinpool.org>
* Copyright 2014 Lucas Jones <https://github.com/lucasjones>
* Copyright 2014-2016 Wolf9466 <https://github.com/OhGodAPet>
* Copyright 2016 Jay D Dee <jayddee246@gmail.com>
* Copyright 2017-2018 XMR-Stak <https://github.com/fireice-uk>, <https://github.com/psychocrypt>
* Copyright 2018-2019 SChernykh <https://github.com/SChernykh>
* Copyright 2016-2019 XMRig <https://github.com/xmrig>, <support@xmrig.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef XMRIG_ICLIENT_H
#define XMRIG_ICLIENT_H
#include <stdint.h>
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 *mode() 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

View file

@ -35,7 +35,7 @@
namespace xmrig { namespace xmrig {
class Client; class IClient;
class Job; class Job;
class SubmitResult; class SubmitResult;
@ -45,11 +45,11 @@ class IClientListener
public: public:
virtual ~IClientListener() = default; virtual ~IClientListener() = default;
virtual void onClose(Client *client, int failures) = 0; virtual void onClose(IClient *client, int failures) = 0;
virtual void onJobReceived(Client *client, const Job &job, const rapidjson::Value &params) = 0; virtual void onJobReceived(IClient *client, const Job &job, const rapidjson::Value &params) = 0;
virtual void onLogin(Client *client, rapidjson::Document &doc, rapidjson::Value &params) = 0; virtual void onLogin(IClient *client, rapidjson::Document &doc, rapidjson::Value &params) = 0;
virtual void onLoginSuccess(Client *client) = 0; virtual void onLoginSuccess(IClient *client) = 0;
virtual void onResultAccepted(Client *client, const SubmitResult &result, const char *error) = 0; virtual void onResultAccepted(IClient *client, const SubmitResult &result, const char *error) = 0;
}; };

View file

@ -33,6 +33,7 @@
namespace xmrig { namespace xmrig {
class IJsonReader;
class String; class String;
@ -66,11 +67,11 @@ public:
UserpassKey = 'O', UserpassKey = 'O',
VariantKey = 1010, VariantKey = 1010,
VerboseKey = 1100, VerboseKey = 1100,
WatchKey = 1105,
TlsKey = 1013, TlsKey = 1013,
FingerprintKey = 1014, FingerprintKey = 1014,
AutoSaveKey = 1016,
ProxyDonateKey = 1017, ProxyDonateKey = 1017,
DaemonKey = 1018,
DaemonPollKey = 1019,
# ifdef XMRIG_DEPRECATED # ifdef XMRIG_DEPRECATED
ApiPort = 4000, ApiPort = 4000,
@ -92,7 +93,7 @@ public:
MaxCPUUsageKey = 1004, MaxCPUUsageKey = 1004,
SafeKey = 1005, SafeKey = 1005,
ThreadsKey = 't', ThreadsKey = 't',
HardwareAESKey = 1011, // HardwareAESKey = 1011,
AssemblyKey = 1015, AssemblyKey = 1015,
// xmrig amd // xmrig amd
@ -111,7 +112,6 @@ public:
// xmrig-proxy // xmrig-proxy
AccessLogFileKey = 'A', AccessLogFileKey = 'A',
BindKey = 'b', BindKey = 'b',
CoinKey = 1104,
CustomDiffKey = 1102, CustomDiffKey = 1102,
DebugKey = 1101, DebugKey = 1101,
ModeKey = 'm', ModeKey = 'm',
@ -141,16 +141,12 @@ public:
virtual ~IConfig() = default; virtual ~IConfig() = default;
virtual bool finalize() = 0;
virtual bool isWatch() const = 0; virtual bool isWatch() const = 0;
virtual bool parseBoolean(int key, bool enable) = 0; virtual bool read(const IJsonReader &reader, const char *fileName) = 0;
virtual bool parseString(int key, const char *arg) = 0;
virtual bool parseUint64(int key, uint64_t arg) = 0;
virtual bool save() = 0; virtual bool save() = 0;
virtual const Algorithm &algorithm() const = 0; virtual const Algorithm &algorithm() const = 0;
virtual const String &fileName() const = 0; virtual const String &fileName() const = 0;
virtual void getJSON(rapidjson::Document &doc) 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 void setFileName(const char *fileName) = 0;
}; };

View file

@ -22,40 +22,31 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#ifndef XMRIG_CONFIGWATCHER_H #ifndef XMRIG_ICONFIGTRANSFORM_H
#define XMRIG_CONFIGWATCHER_H #define XMRIG_ICONFIGTRANSFORM_H
#include "base/kernel/interfaces/IWatcherListener.h" #include "common/crypto/Algorithm.h"
#include "base/tools/String.h"
#include "rapidjson/fwd.h" #include "rapidjson/fwd.h"
struct option;
namespace xmrig { namespace xmrig {
class IConfigListener; class IJsonReader;
class Watcher; class String;
class ConfigWatcher : public IWatcherListener class IConfigTransform
{ {
public: public:
ConfigWatcher(const String &path, IConfigListener *listener); virtual ~IConfigTransform() = default;
~ConfigWatcher() override;
protected: virtual void transform(rapidjson::Document &doc, int key, const char *arg) = 0;
void onFileChanged(const String &fileName) override;
private:
IConfigListener *m_listener;
Watcher *m_watcher;
}; };
} /* namespace xmrig */ } /* namespace xmrig */
#endif /* __CONFIGWATCHER_H__ */
#endif // XMRIG_ICONFIGTRANSFORM_H

View file

@ -29,7 +29,7 @@
namespace xmrig { namespace xmrig {
class HttpRequest; class HttpData;
class HttpResponse; class HttpResponse;
@ -38,7 +38,7 @@ class IHttpListener
public: public:
virtual ~IHttpListener() = default; virtual ~IHttpListener() = default;
virtual void onHttpRequest(const HttpRequest &req) = 0; virtual void onHttpData(const HttpData &data) = 0;
}; };

View file

@ -0,0 +1,56 @@
/* XMRig
* Copyright 2010 Jeff Garzik <jgarzik@pobox.com>
* Copyright 2012-2014 pooler <pooler@litecoinpool.org>
* Copyright 2014 Lucas Jones <https://github.com/lucasjones>
* Copyright 2014-2016 Wolf9466 <https://github.com/OhGodAPet>
* Copyright 2016 Jay D Dee <jayddee246@gmail.com>
* Copyright 2017-2018 XMR-Stak <https://github.com/fireice-uk>, <https://github.com/psychocrypt>
* Copyright 2018-2019 SChernykh <https://github.com/SChernykh>
* Copyright 2016-2019 XMRig <https://github.com/xmrig>, <support@xmrig.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef XMRIG_IJSONREADER_H
#define XMRIG_IJSONREADER_H
#include "rapidjson/fwd.h"
namespace xmrig {
class IJsonReader
{
public:
virtual ~IJsonReader() = default;
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_IJSONREADER_H

View file

@ -33,7 +33,7 @@ namespace xmrig {
class Algorithm; class Algorithm;
class Client; class IClient;
class JobResult; class JobResult;
@ -43,7 +43,7 @@ public:
virtual ~IStrategy() = default; virtual ~IStrategy() = default;
virtual bool isActive() const = 0; virtual bool isActive() const = 0;
virtual Client *client() const = 0; virtual IClient *client() const = 0;
virtual int64_t submit(const JobResult &result) = 0; virtual int64_t submit(const JobResult &result) = 0;
virtual void connect() = 0; virtual void connect() = 0;
virtual void resume() = 0; virtual void resume() = 0;

View file

@ -32,7 +32,7 @@
namespace xmrig { namespace xmrig {
class Client; class IClient;
class IStrategy; class IStrategy;
class Job; class Job;
class SubmitResult; class SubmitResult;
@ -43,10 +43,10 @@ class IStrategyListener
public: public:
virtual ~IStrategyListener() = default; virtual ~IStrategyListener() = default;
virtual void onActive(IStrategy *strategy, Client *client) = 0; virtual void onActive(IStrategy *strategy, IClient *client) = 0;
virtual void onJob(IStrategy *strategy, Client *client, const Job &job) = 0; virtual void onJob(IStrategy *strategy, IClient *client, const Job &job) = 0;
virtual void onPause(IStrategy *strategy) = 0; virtual void onPause(IStrategy *strategy) = 0;
virtual void onResultAccepted(IStrategy *strategy, Client *client, const SubmitResult &result, const char *error) = 0; virtual void onResultAccepted(IStrategy *strategy, IClient *client, const SubmitResult &result, const char *error) = 0;
}; };

View file

@ -144,7 +144,11 @@ void xmrig::Dns::onResolved(int status, addrinfo *res)
ptr = ptr->ai_next; ptr = ptr->ai_next;
} }
m_listener->onResolved(*this, status); if (isEmpty()) {
m_status = UV_EAI_NONAME;
}
m_listener->onResolved(*this, m_status);
} }

View file

@ -48,6 +48,7 @@ public:
~Dns(); ~Dns();
inline bool isEmpty() const { return m_ipv4.empty() && m_ipv6.empty(); } 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; } inline int status() const { return m_status; }
bool resolve(const String &host); bool resolve(const String &host);

View file

@ -24,7 +24,7 @@
#include "3rdparty/rapidjson/document.h" #include "3rdparty/rapidjson/document.h"
#include "base/io/Json.h" #include "base/io/json/Json.h"
#include "base/net/http/Http.h" #include "base/net/http/Http.h"

View file

@ -0,0 +1,224 @@
/* XMRig
* Copyright 2010 Jeff Garzik <jgarzik@pobox.com>
* Copyright 2012-2014 pooler <pooler@litecoinpool.org>
* Copyright 2014 Lucas Jones <https://github.com/lucasjones>
* Copyright 2014-2016 Wolf9466 <https://github.com/OhGodAPet>
* Copyright 2016 Jay D Dee <jayddee246@gmail.com>
* Copyright 2017-2018 XMR-Stak <https://github.com/fireice-uk>, <https://github.com/psychocrypt>
* Copyright 2014-2019 heapwolf <https://github.com/heapwolf>
* Copyright 2018-2019 SChernykh <https://github.com/SChernykh>
* Copyright 2016-2019 XMRig <https://github.com/xmrig>, <support@xmrig.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <sstream>
#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 ClientWriteBaton : public Baton<uv_write_t>
{
public:
inline ClientWriteBaton(const std::string &header, std::string &&body) :
m_body(std::move(body)),
m_header(header)
{
bufs[0].len = m_header.size();
bufs[0].base = const_cast<char *>(m_header.c_str());
if (!m_body.empty()) {
bufs[1].len = m_body.size();
bufs[1].base = const_cast<char *>(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<ClientWriteBaton *>(req->data); }
uv_buf_t bufs[2];
private:
std::string m_body;
std::string m_header;
};
} // namespace xmrig
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;
this->url = url;
if (data) {
body = size ? std::string(data, size) : data;
}
m_dns = new Dns(this);
}
xmrig::HttpClient::~HttpClient()
{
delete m_dns;
}
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;
if (status < 0 && dns.isEmpty()) {
if (!m_quiet) {
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::handshake()
{
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<http_method>(method)) << " " << url << " HTTP/1.1" << kCRLF;
for (auto &header : headers) {
ss << header.first << ": " << header.second << kCRLF;
}
ss << kCRLF;
headers.clear();
write(ss.str());
}
void xmrig::HttpClient::read(const char *data, size_t size)
{
if (parse(data, size) < size) {
close(UV_EPROTO);
}
}
void xmrig::HttpClient::write(const std::string &header)
{
ClientWriteBaton *baton = new ClientWriteBaton(header, std::move(body));
uv_write(&baton->req, stream(), baton->bufs, baton->count(), ClientWriteBaton::onWrite);
}
void xmrig::HttpClient::onConnect(uv_connect_t *req, int status)
{
HttpClient *client = static_cast<HttpClient *>(req->data);
if (!client) {
delete req;
return;
}
if (status < 0) {
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(status);
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<unsigned int>(suggested_size);
# else
buf->len = suggested_size;
# endif
},
[](uv_stream_t *tcp, ssize_t nread, const uv_buf_t *buf)
{
HttpClient *client = static_cast<HttpClient*>(tcp->data);
if (nread >= 0) {
client->read(buf->base, static_cast<size_t>(nread));
} else {
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<int>(nread)));
}
client->close(static_cast<int>(nread));
}
delete [] buf->base;
});
client->handshake();
}

View file

@ -5,6 +5,7 @@
* Copyright 2014-2016 Wolf9466 <https://github.com/OhGodAPet> * Copyright 2014-2016 Wolf9466 <https://github.com/OhGodAPet>
* Copyright 2016 Jay D Dee <jayddee246@gmail.com> * Copyright 2016 Jay D Dee <jayddee246@gmail.com>
* Copyright 2017-2018 XMR-Stak <https://github.com/fireice-uk>, <https://github.com/psychocrypt> * Copyright 2017-2018 XMR-Stak <https://github.com/fireice-uk>, <https://github.com/psychocrypt>
* Copyright 2014-2019 heapwolf <https://github.com/heapwolf>
* Copyright 2018-2019 SChernykh <https://github.com/SChernykh> * Copyright 2018-2019 SChernykh <https://github.com/SChernykh>
* Copyright 2016-2019 XMRig <https://github.com/xmrig>, <support@xmrig.com> * Copyright 2016-2019 XMRig <https://github.com/xmrig>, <support@xmrig.com>
* *
@ -22,50 +23,52 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#ifndef XMRIG_CONFIGLOADER_H
#define XMRIG_CONFIGLOADER_H #ifndef XMRIG_HTTPCLIENT_H
#define XMRIG_HTTPCLIENT_H
#include <stdint.h> #include "base/net/http/HttpContext.h"
#include "base/kernel/interfaces/IDnsListener.h"
#include "rapidjson/fwd.h"
struct option;
namespace xmrig { namespace xmrig {
class ConfigWatcher; class String;
class IConfigListener;
class IConfig;
class Process;
class ConfigLoader class HttpClient : public HttpContext, public IDnsListener
{ {
public: public:
static bool loadFromFile(IConfig *config, const char *fileName); HttpClient(int method, const String &url, IHttpListener *listener, const char *data = nullptr, size_t size = 0);
static bool loadFromJSON(IConfig *config, const char *json); ~HttpClient() override;
static bool loadFromJSON(IConfig *config, const rapidjson::Value &json);
static bool reload(IConfig *oldConfig, const rapidjson::Value &json); inline uint16_t port() const { return m_port; }
static bool watch(IConfig *config); inline void setQuiet(bool quiet) { m_quiet = quiet; }
static IConfig *load(Process *process, IConfigListener *listener);
static void release(); bool connect(const String &host, uint16_t port);
const String &host() const;
protected:
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);
bool m_quiet;
private: private:
static bool getJSON(const char *fileName, rapidjson::Document &doc); static void onConnect(uv_connect_t *req, int status);
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; Dns *m_dns;
static IConfigListener *m_listener; uint16_t m_port;
}; };
} /* namespace xmrig */ } // namespace xmrig
#endif /* XMRIG_CONFIGLOADER_H */ #endif // XMRIG_HTTPCLIENT_H

View file

@ -35,43 +35,77 @@
namespace xmrig { namespace xmrig {
static http_parser_settings http_settings;
static std::map<uint64_t, HttpContext *> storage;
static uint64_t SEQUENCE = 0; static uint64_t SEQUENCE = 0;
std::map<uint64_t, HttpContext *> HttpContext::m_storage;
} // namespace xmrig } // namespace xmrig
xmrig::HttpContext::HttpContext(int parser_type, IHttpListener *listener) : xmrig::HttpContext::HttpContext(int parser_type, IHttpListener *listener) :
HttpRequest(SEQUENCE++), HttpData(SEQUENCE++),
listener(listener), m_wasHeaderValue(false),
connect(nullptr), m_listener(listener)
m_wasHeaderValue(false)
{ {
m_storage[id()] = this; storage[id()] = this;
parser = new http_parser; m_parser = new http_parser;
tcp = new uv_tcp_t; m_tcp = new uv_tcp_t;
uv_tcp_init(uv_default_loop(), tcp); uv_tcp_init(uv_default_loop(), m_tcp);
http_parser_init(parser, static_cast<http_parser_type>(parser_type)); uv_tcp_nodelay(m_tcp, 1);
parser->data = tcp->data = this; http_parser_init(m_parser, static_cast<http_parser_type>(parser_type));
m_parser->data = m_tcp->data = this;
if (http_settings.on_message_complete == nullptr) {
attach(&http_settings);
}
} }
xmrig::HttpContext::~HttpContext() xmrig::HttpContext::~HttpContext()
{ {
delete connect; delete m_tcp;
delete tcp; delete m_parser;
delete parser;
} }
void xmrig::HttpContext::close() size_t xmrig::HttpContext::parse(const char *data, size_t size)
{ {
auto it = m_storage.find(id()); return http_parser_execute(m_parser, &http_settings, data, size);
if (it != m_storage.end()) { }
m_storage.erase(it);
std::string xmrig::HttpContext::ip() const
{
char ip[46] = {};
sockaddr_storage addr = {};
int size = sizeof(addr);
uv_tcp_getpeername(m_tcp, reinterpret_cast<sockaddr*>(&addr), &size);
if (reinterpret_cast<sockaddr_in *>(&addr)->sin_family == AF_INET6) {
uv_ip6_name(reinterpret_cast<sockaddr_in6*>(&addr), ip, 45);
}
else {
uv_ip4_name(reinterpret_cast<sockaddr_in*>(&addr), ip, 16);
}
return ip;
}
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);
} }
if (!uv_is_closing(handle())) { if (!uv_is_closing(handle())) {
@ -82,65 +116,17 @@ void xmrig::HttpContext::close()
xmrig::HttpContext *xmrig::HttpContext::get(uint64_t id) xmrig::HttpContext *xmrig::HttpContext::get(uint64_t id)
{ {
if (m_storage.count(id) == 0) { if (storage.count(id) == 0) {
return nullptr; return nullptr;
} }
return m_storage[id]; return 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<HttpContext*>(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<HttpContext*>(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<HttpContext*>(parser->data)->body += std::string(at, len);
return 0;
};
settings->on_message_complete = [](http_parser *parser) -> int
{
const HttpContext *ctx = reinterpret_cast<const HttpContext*>(parser->data);
ctx->listener->onHttpRequest(*ctx);
return 0;
};
} }
void xmrig::HttpContext::closeAll() void xmrig::HttpContext::closeAll()
{ {
for (auto kv : m_storage) { for (auto kv : storage) {
if (!uv_is_closing(kv.second->handle())) { if (!uv_is_closing(kv.second->handle())) {
uv_close(kv.second->handle(), [](uv_handle_t *handle) -> void { delete reinterpret_cast<HttpContext*>(handle->data); }); uv_close(kv.second->handle(), [](uv_handle_t *handle) -> void { delete reinterpret_cast<HttpContext*>(handle->data); });
} }
@ -182,6 +168,55 @@ 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<HttpContext*>(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<HttpContext*>(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<HttpContext*>(parser->data)->body += std::string(at, len);
return 0;
};
settings->on_message_complete = [](http_parser *parser) -> int
{
HttpContext *ctx = static_cast<HttpContext*>(parser->data);
ctx->m_listener->onHttpData(*ctx);
ctx->m_listener = nullptr;
return 0;
};
}
void xmrig::HttpContext::setHeader() void xmrig::HttpContext::setHeader()
{ {
std::transform(m_lastHeaderField.begin(), m_lastHeaderField.end(), m_lastHeaderField.begin(), ::tolower); std::transform(m_lastHeaderField.begin(), m_lastHeaderField.end(), m_lastHeaderField.begin(), ::tolower);

View file

@ -36,7 +36,7 @@ typedef struct uv_stream_s uv_stream_t;
typedef struct uv_tcp_s uv_tcp_t; typedef struct uv_tcp_s uv_tcp_t;
#include "base/net/http/HttpRequest.h" #include "base/net/http/HttpData.h"
namespace xmrig { namespace xmrig {
@ -45,37 +45,37 @@ namespace xmrig {
class IHttpListener; class IHttpListener;
class HttpContext : public HttpRequest class HttpContext : public HttpData
{ {
public: public:
HttpContext(int parser_type, IHttpListener *listener); HttpContext(int parser_type, IHttpListener *listener);
~HttpContext(); virtual ~HttpContext();
inline uv_stream_t *stream() const { return reinterpret_cast<uv_stream_t *>(tcp); } inline uv_stream_t *stream() const { return reinterpret_cast<uv_stream_t *>(m_tcp); }
inline uv_handle_t *handle() const { return reinterpret_cast<uv_handle_t *>(tcp); } inline uv_handle_t *handle() const { return reinterpret_cast<uv_handle_t *>(m_tcp); }
void close(); size_t parse(const char *data, size_t size);
std::string ip() const;
void close(int status = 0);
static HttpContext *get(uint64_t id); static HttpContext *get(uint64_t id);
static void attach(http_parser_settings *settings);
static void closeAll(); static void closeAll();
http_parser *parser; protected:
IHttpListener *listener; uv_tcp_t *m_tcp;
uv_connect_t *connect;
uv_tcp_t *tcp;
private: private:
static int onHeaderField(http_parser *parser, const char *at, size_t length); 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 int onHeaderValue(http_parser *parser, const char *at, size_t length);
static void attach(http_parser_settings *settings);
void setHeader(); void setHeader();
bool m_wasHeaderValue; bool m_wasHeaderValue;
http_parser *m_parser;
IHttpListener *m_listener;
std::string m_lastHeaderField; std::string m_lastHeaderField;
std::string m_lastHeaderValue; std::string m_lastHeaderValue;
static std::map<uint64_t, HttpContext *> m_storage;
}; };

View file

@ -24,26 +24,26 @@
*/ */
#ifndef XMRIG_HTTPREQUEST_H #ifndef XMRIG_HTTPDATA_H
#define XMRIG_HTTPREQUEST_H #define XMRIG_HTTPDATA_H
#include <map> #include <map>
#include <sstream>
#include <string> #include <string>
namespace xmrig { namespace xmrig {
class HttpRequest class HttpData
{ {
public: 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; } inline uint64_t id() const { return m_id; }
int method; int method;
int status;
std::map<const std::string, const std::string> headers; std::map<const std::string, const std::string> headers;
std::string body; std::string body;
std::string url; std::string url;
@ -56,5 +56,5 @@ private:
} // namespace xmrig } // namespace xmrig
#endif // XMRIG_HTTPREQUEST_H #endif // XMRIG_HTTPDATA_H

View file

@ -33,6 +33,7 @@
#include "base/io/log/Log.h" #include "base/io/log/Log.h"
#include "base/net/http/HttpContext.h" #include "base/net/http/HttpContext.h"
#include "base/net/http/HttpResponse.h" #include "base/net/http/HttpResponse.h"
#include "base/tools/Baton.h"
namespace xmrig { namespace xmrig {
@ -40,6 +41,51 @@ namespace xmrig {
static const char *kCRLF = "\r\n"; static const char *kCRLF = "\r\n";
static const char *kUserAgent = "user-agent"; static const char *kUserAgent = "user-agent";
class WriteBaton : public Baton<uv_write_t>
{
public:
inline WriteBaton(const std::stringstream &ss, const char *data, size_t size, HttpContext *ctx) :
m_ctx(ctx),
m_header(ss.str())
{
bufs[0].len = m_header.size();
bufs[0].base = const_cast<char *>(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<WriteBaton *>(req->data); }
uv_buf_t bufs[2];
private:
HttpContext *m_ctx;
std::string m_header;
};
} // namespace xmrig } // namespace xmrig
@ -82,58 +128,26 @@ void xmrig::HttpResponse::end(const char *data, size_t size)
} }
ss << kCRLF; ss << kCRLF;
const std::string header = ss.str();
uv_buf_t bufs[2];
bufs[0].base = const_cast<char *>(header.c_str());
# ifdef _WIN32
bufs[0].len = static_cast<unsigned int>(header.size());
# else
bufs[0].len = header.size();
# endif
if (data) {
bufs[1].base = const_cast<char *>(data);
# ifdef _WIN32
bufs[1].len = static_cast<unsigned int>(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 # ifndef APP_DEBUG
if (statusCode() >= 400) if (statusCode() >= 400)
# endif # endif
{ {
const bool err = statusCode() >= 400; const bool err = statusCode() >= 400;
char ip[46] = {};
sockaddr_storage addr = {};
int aSize = sizeof(addr);
uv_tcp_getpeername(ctx->tcp, reinterpret_cast<sockaddr*>(&addr), &aSize);
if (reinterpret_cast<sockaddr_in *>(&addr)->sin_family == AF_INET6) {
uv_ip6_name(reinterpret_cast<sockaddr_in6*>(&addr), ip, 45);
}
else {
uv_ip4_name(reinterpret_cast<sockaddr_in*>(&addr), ip, 16);
}
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\""), 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<http_method>(ctx->method)), http_method_str(static_cast<http_method>(ctx->method)),
ctx->url.c_str(), ctx->url.c_str(),
err ? 31 : 32, err ? 31 : 32,
statusCode(), statusCode(),
header.size() + size, baton->size(),
ctx->headers.count(kUserAgent) ? ctx->headers.at(kUserAgent).c_str() : nullptr ctx->headers.count(kUserAgent) ? ctx->headers.at(kUserAgent).c_str() : nullptr
); );
} }
uv_try_write(ctx->stream(), bufs, data ? 2 : 1); uv_write(&baton->req, ctx->stream(), baton->bufs, baton->count(), WriteBaton::onWrite);
ctx->close();
} }

View file

@ -35,17 +35,9 @@
#include "base/net/http/HttpServer.h" #include "base/net/http/HttpServer.h"
namespace xmrig {
static http_parser_settings http_settings;
} // namespace xmrig
xmrig::HttpServer::HttpServer(IHttpListener *listener) : xmrig::HttpServer::HttpServer(IHttpListener *listener) :
m_listener(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) { if (nread >= 0) {
const size_t size = static_cast<size_t>(nread); const size_t size = static_cast<size_t>(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) { if (parsed < size) {
ctx->close(); ctx->close();

View file

@ -0,0 +1,208 @@
/* XMRig
* Copyright 2010 Jeff Garzik <jgarzik@pobox.com>
* Copyright 2012-2014 pooler <pooler@litecoinpool.org>
* Copyright 2014 Lucas Jones <https://github.com/lucasjones>
* Copyright 2014-2016 Wolf9466 <https://github.com/OhGodAPet>
* Copyright 2016 Jay D Dee <jayddee246@gmail.com>
* Copyright 2017-2018 XMR-Stak <https://github.com/fireice-uk>, <https://github.com/psychocrypt>
* Copyright 2014-2019 heapwolf <https://github.com/heapwolf>
* Copyright 2018-2019 SChernykh <https://github.com/SChernykh>
* Copyright 2016-2019 XMRig <https://github.com/xmrig>, <support@xmrig.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <assert.h>
#include <openssl/ssl.h>
#include <uv.h>
#include "base/io/log/Log.h"
#include "base/net/http/HttpsClient.h"
#include "base/tools/Buffer.h"
#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_fp(fingerprint)
{
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);
}
}
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);
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(UV_EPROTO);
}
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<size_t>(bytes_read));
}
}
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)
{
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;
}
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) == static_cast<int>(buf.len);
if (!result) {
close(UV_EIO);
}
}
(void) BIO_reset(m_writeBio);
}

View file

@ -0,0 +1,77 @@
/* XMRig
* Copyright 2010 Jeff Garzik <jgarzik@pobox.com>
* Copyright 2012-2014 pooler <pooler@litecoinpool.org>
* Copyright 2014 Lucas Jones <https://github.com/lucasjones>
* Copyright 2014-2016 Wolf9466 <https://github.com/OhGodAPet>
* Copyright 2016 Jay D Dee <jayddee246@gmail.com>
* Copyright 2017-2018 XMR-Stak <https://github.com/fireice-uk>, <https://github.com/psychocrypt>
* Copyright 2014-2019 heapwolf <https://github.com/heapwolf>
* Copyright 2018-2019 SChernykh <https://github.com/SChernykh>
* Copyright 2016-2019 XMRig <https://github.com/xmrig>, <support@xmrig.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef 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"
#include "base/tools/String.h"
namespace xmrig {
class HttpsClient : public HttpClient
{
public:
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);
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;
};
} // namespace xmrig
#endif // XMRIG_HTTPSCLIENT_H

View file

@ -0,0 +1,62 @@
/* XMRig
* Copyright 2010 Jeff Garzik <jgarzik@pobox.com>
* Copyright 2012-2014 pooler <pooler@litecoinpool.org>
* Copyright 2014 Lucas Jones <https://github.com/lucasjones>
* Copyright 2014-2016 Wolf9466 <https://github.com/OhGodAPet>
* Copyright 2016 Jay D Dee <jayddee246@gmail.com>
* Copyright 2017-2018 XMR-Stak <https://github.com/fireice-uk>, <https://github.com/psychocrypt>
* Copyright 2018-2019 SChernykh <https://github.com/SChernykh>
* Copyright 2016-2019 XMRig <https://github.com/xmrig>, <support@xmrig.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "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) :
m_quiet(false),
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;
}

View file

@ -0,0 +1,96 @@
/* XMRig
* Copyright 2010 Jeff Garzik <jgarzik@pobox.com>
* Copyright 2012-2014 pooler <pooler@litecoinpool.org>
* Copyright 2014 Lucas Jones <https://github.com/lucasjones>
* Copyright 2014-2016 Wolf9466 <https://github.com/OhGodAPet>
* Copyright 2016 Jay D Dee <jayddee246@gmail.com>
* Copyright 2017-2018 XMR-Stak <https://github.com/fireice-uk>, <https://github.com/psychocrypt>
* Copyright 2018-2019 SChernykh <https://github.com/SChernykh>
* Copyright 2016-2019 XMRig <https://github.com/xmrig>, <support@xmrig.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef XMRIG_BASECLIENT_H
#define XMRIG_BASECLIENT_H
#include <map>
#include "base/kernel/interfaces/IClient.h"
#include "base/net/stratum/Job.h"
#include "base/net/stratum/Pool.h"
namespace xmrig {
class IClientListener;
class SubmitResult;
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:
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<int64_t, SubmitResult> m_results;
String m_ip;
uint64_t m_retryPause;
static int64_t m_sequence;
private:
bool m_enabled;
};
} /* namespace xmrig */
#endif /* XMRIG_BASECLIENT_H */

View file

@ -37,6 +37,7 @@
#endif #endif
#include "base/io/json/JsonRequest.h"
#include "base/io/log/Log.h" #include "base/io/log/Log.h"
#include "base/kernel/interfaces/IClientListener.h" #include "base/kernel/interfaces/IClientListener.h"
#include "base/net/dns/Dns.h" #include "base/net/dns/Dns.h"
@ -57,7 +58,6 @@
namespace xmrig { namespace xmrig {
int64_t Client::m_sequence = 1;
Storage<Client> Client::m_storage; Storage<Client> Client::m_storage;
} /* namespace xmrig */ } /* namespace xmrig */
@ -75,16 +75,8 @@ static const char *states[] = {
xmrig::Client::Client(int id, const char *agent, IClientListener *listener) : xmrig::Client::Client(int id, const char *agent, IClientListener *listener) :
m_enabled(true), BaseClient(id, listener),
m_ipv6(false),
m_quiet(false),
m_agent(agent), m_agent(agent),
m_listener(listener),
m_id(id),
m_retries(5),
m_retryPause(5000),
m_failures(0),
m_state(UnconnectedState),
m_tls(nullptr), m_tls(nullptr),
m_expire(0), m_expire(0),
m_jobs(0), m_jobs(0),
@ -105,73 +97,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());
}
/**
* @brief Connect to server.
*
* @param url
*/
void xmrig::Client::connect(const Pool &url)
{
setPool(url);
connect();
}
void xmrig::Client::deleteLater()
{
if (!m_listener) {
return;
}
m_listener = nullptr;
if (!disconnect()) {
m_storage.remove(m_key);
}
}
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) {
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() bool xmrig::Client::disconnect()
{ {
m_keepAlive = 0; m_keepAlive = 0;
@ -243,10 +168,6 @@ int64_t xmrig::Client::submit(const JobResult &result)
Document doc(kObjectType); Document doc(kObjectType);
auto &allocator = doc.GetAllocator(); auto &allocator = doc.GetAllocator();
doc.AddMember("id", m_sequence, allocator);
doc.AddMember("jsonrpc", "2.0", allocator);
doc.AddMember("method", "submit", allocator);
Value params(kObjectType); Value params(kObjectType);
params.AddMember("id", StringRef(m_rpcId.data()), allocator); params.AddMember("id", StringRef(m_rpcId.data()), allocator);
params.AddMember("job_id", StringRef(result.jobId.data()), allocator); params.AddMember("job_id", StringRef(result.jobId.data()), allocator);
@ -257,7 +178,7 @@ int64_t xmrig::Client::submit(const JobResult &result)
params.AddMember("algo", StringRef(result.algorithm.shortName()), allocator); params.AddMember("algo", StringRef(result.algorithm.shortName()), allocator);
} }
doc.AddMember("params", params, allocator); JsonRequest::create(doc, m_sequence, "submit", params);
# ifdef XMRIG_PROXY_PROJECT # ifdef XMRIG_PROXY_PROJECT
m_results[m_sequence] = SubmitResult(m_sequence, result.diff, result.actualDiff(), result.id); m_results[m_sequence] = SubmitResult(m_sequence, result.diff, result.actualDiff(), result.id);
@ -269,6 +190,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) void xmrig::Client::onResolved(const Dns &dns, int status)
{ {
assert(m_listener != nullptr); assert(m_listener != nullptr);
@ -284,14 +256,6 @@ void xmrig::Client::onResolved(const Dns &dns, int status)
return reconnect(); 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(); const DnsRecord &record = dns.get();
m_ip = record.ip(); m_ip = record.ip();
@ -541,7 +505,7 @@ int64_t xmrig::Client::send(const rapidjson::Document &doc)
int64_t xmrig::Client::send(size_t size) 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<int>(size) - 1, m_sendBuf);
# ifdef XMRIG_FEATURE_TLS # ifdef XMRIG_FEATURE_TLS
if (isTLS()) { if (isTLS()) {
@ -574,8 +538,6 @@ void xmrig::Client::connect(sockaddr *addr)
{ {
setState(ConnectingState); setState(ConnectingState);
reinterpret_cast<sockaddr_in*>(addr)->sin_port = htons(m_pool.port());
uv_connect_t *req = new uv_connect_t; uv_connect_t *req = new uv_connect_t;
req->data = m_storage.ptr(m_key); req->data = m_storage.ptr(m_key);
@ -589,7 +551,7 @@ void xmrig::Client::connect(sockaddr *addr)
uv_tcp_keepalive(m_socket, 1, 60); uv_tcp_keepalive(m_socket, 1, 60);
# endif # endif
uv_tcp_connect(req, m_socket, reinterpret_cast<const sockaddr*>(addr), Client::onConnect); uv_tcp_connect(req, m_socket, addr, onConnect);
delete addr; delete addr;
} }
@ -619,10 +581,6 @@ void xmrig::Client::login()
Document doc(kObjectType); Document doc(kObjectType);
auto &allocator = doc.GetAllocator(); auto &allocator = doc.GetAllocator();
doc.AddMember("id", 1, allocator);
doc.AddMember("jsonrpc", "2.0", allocator);
doc.AddMember("method", "login", allocator);
Value params(kObjectType); Value params(kObjectType);
params.AddMember("login", m_pool.user().toJSON(), allocator); params.AddMember("login", m_pool.user().toJSON(), allocator);
params.AddMember("pass", m_pool.password().toJSON(), allocator); params.AddMember("pass", m_pool.password().toJSON(), allocator);
@ -647,7 +605,7 @@ void xmrig::Client::login()
m_listener->onLogin(this, doc, params); m_listener->onLogin(this, doc, params);
doc.AddMember("params", params, allocator); JsonRequest::create(doc, 1, "login", params);
send(doc); send(doc);
} }
@ -676,7 +634,7 @@ void xmrig::Client::parse(char *line, size_t len)
{ {
startTimeout(); startTimeout();
LOG_DEBUG("[%s] received (%d bytes): \"%s\"", url(), len, line); LOG_DEBUG("[%s] received (%d bytes): \"%.*s\"", url(), len, static_cast<int>(len), line);
if (len < 32 || line[0] != '{') { if (len < 32 || line[0] != '{') {
if (!isQuiet()) { if (!isQuiet()) {
@ -781,14 +739,8 @@ void xmrig::Client::parseResponse(int64_t id, const rapidjson::Value &result, co
if (error.IsObject()) { if (error.IsObject()) {
const char *message = error["message"].GetString(); const char *message = error["message"].GetString();
auto it = m_results.find(id); if (!handleSubmitResponse(id, message) && !isQuiet()) {
if (it != m_results.end()) { LOG_ERR("[%s] error: " RED_BOLD("\"%s\"") RED_S ", code: %d", url(), message, error["code"].GetInt());
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 (isCriticalError(message)) { if (isCriticalError(message)) {
@ -819,12 +771,7 @@ void xmrig::Client::parseResponse(int64_t id, const rapidjson::Value &result, co
return; return;
} }
auto it = m_results.find(id); handleSubmitResponse(id);
if (it != m_results.end()) {
it->second.done();
m_listener->onResultAccepted(this, it->second, nullptr);
m_results.erase(it);
}
} }
@ -970,7 +917,7 @@ void xmrig::Client::onConnect(uv_connect_t *req, int status)
client->m_stream->data = req->data; client->m_stream->data = req->data;
client->setState(ConnectedState); client->setState(ConnectedState);
uv_read_start(client->m_stream, Client::onAllocBuffer, Client::onRead); uv_read_start(client->m_stream, onAllocBuffer, onRead);
delete req; delete req;
client->handshake(); client->handshake();

View file

@ -34,6 +34,7 @@
#include "base/kernel/interfaces/IDnsListener.h" #include "base/kernel/interfaces/IDnsListener.h"
#include "base/kernel/interfaces/ILineListener.h" #include "base/kernel/interfaces/ILineListener.h"
#include "base/net/stratum/BaseClient.h"
#include "base/net/stratum/Job.h" #include "base/net/stratum/Job.h"
#include "base/net/stratum/Pool.h" #include "base/net/stratum/Pool.h"
#include "base/net/stratum/SubmitResult.h" #include "base/net/stratum/SubmitResult.h"
@ -42,7 +43,6 @@
#include "common/crypto/Algorithm.h" #include "common/crypto/Algorithm.h"
typedef struct bio_st BIO; typedef struct bio_st BIO;
@ -53,26 +53,9 @@ class IClientListener;
class JobResult; class JobResult;
class Client : public IDnsListener, public ILineListener class Client : public BaseClient, public IDnsListener, public ILineListener
{ {
public: 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; constexpr static int kResponseTimeout = 20 * 1000;
# ifdef XMRIG_FEATURE_TLS # ifdef XMRIG_FEATURE_TLS
@ -84,39 +67,23 @@ public:
Client(int id, const char *agent, IClientListener *listener); Client(int id, const char *agent, IClientListener *listener);
~Client() override; ~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);
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<Extension ext> inline bool has() const noexcept { return m_extensions.test(ext); }
protected: protected:
inline void onLine(char *line, size_t size) override { parse(line, size); } 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;
void onResolved(const Dns &dns, int status) override; void onResolved(const Dns &dns, int status) override;
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: private:
class Tls; class Tls;
@ -143,9 +110,10 @@ private:
void setState(SocketState state); void setState(SocketState state);
void startTimeout(); void startTimeout();
inline bool isQuiet() const { return m_quiet || m_failures >= m_retries; }
inline const char *url() const { return m_pool.url(); } 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); } inline void setExtension(Extension ext, bool enable) noexcept { m_extensions.set(ext, enable); }
template<Extension ext> 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 onAllocBuffer(uv_handle_t *handle, size_t suggested_size, uv_buf_t *buf);
static void onClose(uv_handle_t *handle); static void onClose(uv_handle_t *handle);
@ -154,24 +122,11 @@ private:
static inline Client *getClient(void *data) { return m_storage.get(data); } static inline Client *getClient(void *data) { return m_storage.get(data); }
bool m_enabled;
bool m_ipv6;
bool m_quiet;
char m_sendBuf[2048]; char m_sendBuf[2048];
const char *m_agent; const char *m_agent;
Dns *m_dns; 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<kInputBufferSize> m_recvBuf; RecvBuf<kInputBufferSize> m_recvBuf;
SocketState m_state;
std::bitset<EXT_MAX> m_extensions; std::bitset<EXT_MAX> m_extensions;
std::map<int64_t, SubmitResult> m_results;
String m_ip;
String m_rpcId; String m_rpcId;
Tls *m_tls; Tls *m_tls;
uint64_t m_expire; uint64_t m_expire;
@ -181,7 +136,6 @@ private:
uv_stream_t *m_stream; uv_stream_t *m_stream;
uv_tcp_t *m_socket; uv_tcp_t *m_socket;
static int64_t m_sequence;
static Storage<Client> m_storage; static Storage<Client> m_storage;
}; };

View file

@ -0,0 +1,378 @@
/* XMRig
* Copyright 2010 Jeff Garzik <jgarzik@pobox.com>
* Copyright 2012-2014 pooler <pooler@litecoinpool.org>
* Copyright 2014 Lucas Jones <https://github.com/lucasjones>
* Copyright 2014-2016 Wolf9466 <https://github.com/OhGodAPet>
* Copyright 2016 Jay D Dee <jayddee246@gmail.com>
* Copyright 2017-2018 XMR-Stak <https://github.com/fireice-uk>, <https://github.com/psychocrypt>
* Copyright 2018-2019 SChernykh <https://github.com/SChernykh>
* Copyright 2019 Howard Chu <https://github.com/hyc>
* Copyright 2016-2019 XMRig <https://github.com/xmrig>, <support@xmrig.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <algorithm>
#include <assert.h>
#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"
#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
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),
m_monero(true)
{
m_timer = new Timer(this);
}
xmrig::DaemonClient::~DaemonClient()
{
delete m_timer;
}
bool xmrig::DaemonClient::disconnect()
{
if (m_state != UnconnectedState) {
setState(UnconnectedState);
}
return true;
}
bool xmrig::DaemonClient::isTLS() const
{
# ifdef XMRIG_FEATURE_TLS
return m_pool.isTLS();
# else
return false;
# endif
}
int64_t xmrig::DaemonClient::submit(const JobResult &result)
{
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<const uint8_t *>(&result.nonce), 4, m_blocktemplate.data() + 78);
# endif
using namespace rapidjson;
Document doc(kObjectType);
Value params(kArrayType);
params.PushBack(m_blocktemplate.toJSON(), doc.GetAllocator());
JsonRequest::create(doc, m_sequence, "submitblock", params);
# 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, kJsonRPC, 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<int>(data.body.size()), static_cast<int>(data.body.size()), data.body.c_str());
m_ip = static_cast<const HttpContext &>(data).ip().c_str();
# ifdef XMRIG_FEATURE_TLS
if (isTLS()) {
m_tlsVersion = static_cast<const HttpsClient &>(data).version();
m_tlsFingerprint = static_cast<const HttpsClient &>(data).fingerprint();
}
# endif
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) {
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();
}
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, 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 &params, int *code)
{
Job job(m_id, false, m_pool.algorithm(), String());
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, 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);
}
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(kBlocktemplateBlob) && 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();
Value params(kObjectType);
params.AddMember("wallet_address", m_pool.user().toJSON(), allocator);
params.AddMember("reserve_size", 8, allocator);
JsonRequest::create(doc, m_sequence, "getblocktemplate", params);
send(HTTP_POST, kJsonRPC, doc);
return m_sequence++;
}
void xmrig::DaemonClient::retry()
{
m_failures++;
m_listener->onClose(this, static_cast<int>(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<http_method>(method)),
url,
size,
static_cast<int>(size),
data);
HttpClient *client;
# ifdef XMRIG_FEATURE_TLS
if (m_pool.isTLS()) {
client = new HttpsClient(method, url, this, data, size, m_pool.fingerprint());
}
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<StringBuffer> 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<uint64_t>(20, m_pool.pollInterval());
m_timer->start(interval, interval);
}
break;
case UnconnectedState:
m_failures = -1;
m_timer->stop();
break;
default:
break;
}
}

View file

@ -0,0 +1,83 @@
/* XMRig
* Copyright 2010 Jeff Garzik <jgarzik@pobox.com>
* Copyright 2012-2014 pooler <pooler@litecoinpool.org>
* Copyright 2014 Lucas Jones <https://github.com/lucasjones>
* Copyright 2014-2016 Wolf9466 <https://github.com/OhGodAPet>
* Copyright 2016 Jay D Dee <jayddee246@gmail.com>
* Copyright 2017-2018 XMR-Stak <https://github.com/fireice-uk>, <https://github.com/psychocrypt>
* Copyright 2018-2019 SChernykh <https://github.com/SChernykh>
* Copyright 2019 Howard Chu <https://github.com/hyc>
* Copyright 2016-2019 XMRig <https://github.com/xmrig>, <support@xmrig.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef 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;
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 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 {}
private:
bool isOutdated(uint64_t height, const char *hash) const;
bool parseJob(const rapidjson::Value &params, 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);
bool m_monero;
String m_blocktemplate;
String m_prevHash;
String m_tlsFingerprint;
String m_tlsVersion;
Timer *m_timer;
};
} /* namespace xmrig */
#endif /* XMRIG_DAEMONCLIENT_H */

View file

@ -7,6 +7,7 @@
* Copyright 2017-2018 XMR-Stak <https://github.com/fireice-uk>, <https://github.com/psychocrypt> * Copyright 2017-2018 XMR-Stak <https://github.com/fireice-uk>, <https://github.com/psychocrypt>
* Copyright 2018 Lee Clagett <https://github.com/vtnerd> * Copyright 2018 Lee Clagett <https://github.com/vtnerd>
* Copyright 2018 SChernykh <https://github.com/SChernykh> * Copyright 2018 SChernykh <https://github.com/SChernykh>
* Copyright 2019 Howard Chu <https://github.com/hyc>
* Copyright 2016-2019 XMRig <https://github.com/xmrig>, <support@xmrig.com> * Copyright 2016-2019 XMRig <https://github.com/xmrig>, <support@xmrig.com>
* *
* This program is free software: you can redistribute it and/or modify * This program is free software: you can redistribute it and/or modify
@ -180,9 +181,15 @@ 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);
# ifdef XMRIG_PROXY_PROJECT
Buffer::toHex(reinterpret_cast<uint8_t *>(&m_target), 8, m_rawTarget);
m_rawTarget[16] = '\0';
# endif
} }

View file

@ -7,6 +7,7 @@
* Copyright 2017-2018 XMR-Stak <https://github.com/fireice-uk>, <https://github.com/psychocrypt> * Copyright 2017-2018 XMR-Stak <https://github.com/fireice-uk>, <https://github.com/psychocrypt>
* Copyright 2018 Lee Clagett <https://github.com/vtnerd> * Copyright 2018 Lee Clagett <https://github.com/vtnerd>
* Copyright 2018-2019 SChernykh <https://github.com/SChernykh> * Copyright 2018-2019 SChernykh <https://github.com/SChernykh>
* Copyright 2019 Howard Chu <https://github.com/hyc>
* Copyright 2016-2019 XMRig <https://github.com/xmrig>, <support@xmrig.com> * Copyright 2016-2019 XMRig <https://github.com/xmrig>, <support@xmrig.com>
* *
* This program is free software: you can redistribute it and/or modify * This program is free software: you can redistribute it and/or modify
@ -53,7 +54,7 @@ public:
bool setBlob(const char *blob); bool setBlob(const char *blob);
bool setTarget(const char *target); bool setTarget(const char *target);
void setAlgorithm(const char *algo); void setAlgorithm(const char *algo);
void setHeight(uint64_t height); void setDiff(uint64_t diff);
inline bool isNicehash() const { return m_nicehash; } inline bool isNicehash() const { return m_nicehash; }
inline bool isValid() const { return m_size > 0 && m_diff > 0; } inline bool isValid() const { return m_size > 0 && m_diff > 0; }
@ -67,12 +68,13 @@ public:
inline int threadId() const { return m_threadId; } inline int threadId() const { return m_threadId; }
inline size_t size() const { return m_size; } inline size_t size() const { return m_size; }
inline uint32_t *nonce() { return reinterpret_cast<uint32_t*>(m_blob + 39); } inline uint32_t *nonce() { return reinterpret_cast<uint32_t*>(m_blob + 39); }
inline uint32_t diff() const { return static_cast<uint32_t>(m_diff); } inline uint64_t diff() const { return m_diff; }
inline uint64_t height() const { return m_height; } inline uint64_t height() const { return m_height; }
inline uint64_t target() const { return m_target; } inline uint64_t target() const { return m_target; }
inline uint8_t fixedByte() const { return *(m_blob + 42); } inline uint8_t fixedByte() const { return *(m_blob + 42); }
inline void reset() { m_size = 0; m_diff = 0; } inline void reset() { m_size = 0; m_diff = 0; }
inline void setClientId(const String &id) { m_clientId = id; } 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 setPoolId(int poolId) { m_poolId = poolId; }
inline void setThreadId(int threadId) { m_threadId = threadId; } inline void setThreadId(int threadId) { m_threadId = threadId; }
inline void setVariant(const char *variant) { m_algorithm.parseVariant(variant); } inline void setVariant(const char *variant) { m_algorithm.parseVariant(variant); }

View file

@ -6,6 +6,7 @@
* Copyright 2016 Jay D Dee <jayddee246@gmail.com> * Copyright 2016 Jay D Dee <jayddee246@gmail.com>
* Copyright 2017-2019 XMR-Stak <https://github.com/fireice-uk>, <https://github.com/psychocrypt> * Copyright 2017-2019 XMR-Stak <https://github.com/fireice-uk>, <https://github.com/psychocrypt>
* Copyright 2018-2019 SChernykh <https://github.com/SChernykh> * Copyright 2018-2019 SChernykh <https://github.com/SChernykh>
* Copyright 2019 Howard Chu <https://github.com/hyc>
* Copyright 2016-2019 XMRig <https://github.com/xmrig>, <support@xmrig.com> * Copyright 2016-2019 XMRig <https://github.com/xmrig>, <support@xmrig.com>
* *
* This program is free software: you can redistribute it and/or modify * This program is free software: you can redistribute it and/or modify
@ -29,7 +30,7 @@
#include <stdio.h> #include <stdio.h>
#include "base/io/Json.h" #include "base/io/json/Json.h"
#include "base/net/stratum/Pool.h" #include "base/net/stratum/Pool.h"
#include "rapidjson/document.h" #include "rapidjson/document.h"
@ -41,12 +42,13 @@
#ifdef _MSC_VER #ifdef _MSC_VER
# define strncasecmp _strnicmp # define strncasecmp _strnicmp
# define strcasecmp _stricmp
#endif #endif
namespace xmrig { namespace xmrig {
static const char *kDaemon = "daemon";
static const char *kDaemonPollInterval = "daemon-poll-interval";
static const char *kEnabled = "enabled"; static const char *kEnabled = "enabled";
static const char *kFingerprint = "tls-fingerprint"; static const char *kFingerprint = "tls-fingerprint";
static const char *kKeepalive = "keepalive"; static const char *kKeepalive = "keepalive";
@ -61,15 +63,22 @@ static const char *kVariant = "variant";
const String Pool::kDefaultPassword = "x"; const String Pool::kDefaultPassword = "x";
const String Pool::kDefaultUser = "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
} }
xmrig::Pool::Pool() : xmrig::Pool::Pool() :
m_enabled(true),
m_nicehash(false),
m_tls(false),
m_keepAlive(0), m_keepAlive(0),
m_port(kDefaultPort) m_flags(0),
m_port(kDefaultPort),
m_pollInterval(kDefaultPollInterval)
{ {
} }
@ -86,33 +95,37 @@ xmrig::Pool::Pool() :
* @param url * @param url
*/ */
xmrig::Pool::Pool(const char *url) : xmrig::Pool::Pool(const char *url) :
m_enabled(true),
m_nicehash(false),
m_tls(false),
m_keepAlive(0), m_keepAlive(0),
m_port(kDefaultPort) m_flags(1),
m_port(kDefaultPort),
m_pollInterval(kDefaultPollInterval)
{ {
parse(url); parse(url);
} }
xmrig::Pool::Pool(const rapidjson::Value &object) : xmrig::Pool::Pool(const rapidjson::Value &object) :
m_enabled(true),
m_nicehash(false),
m_tls(false),
m_keepAlive(0), m_keepAlive(0),
m_port(kDefaultPort) m_flags(1),
m_port(kDefaultPort),
m_pollInterval(kDefaultPollInterval)
{ {
if (!parse(Json::getString(object, kUrl))) { if (!parse(Json::getString(object, kUrl))) {
return; return;
} }
setUser(Json::getString(object, kUser)); m_user = Json::getString(object, kUser);
setPassword(Json::getString(object, kPass)); m_password = Json::getString(object, kPass);
setRigId(Json::getString(object, kRigId)); m_rigId = Json::getString(object, kRigId);
setNicehash(Json::getBool(object, kNicehash)); m_fingerprint = Json::getString(object, kFingerprint);
m_pollInterval = Json::getUint64(object, kDaemonPollInterval, kDefaultPollInterval);
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)));
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()) { if (keepalive.IsInt()) {
setKeepAlive(keepalive.GetInt()); setKeepAlive(keepalive.GetInt());
} }
@ -120,7 +133,7 @@ xmrig::Pool::Pool(const rapidjson::Value &object) :
setKeepAlive(keepalive.GetBool()); setKeepAlive(keepalive.GetBool());
} }
const rapidjson::Value &variant = object[kVariant]; const rapidjson::Value &variant = Json::getValue(object, kVariant);
if (variant.IsString()) { if (variant.IsString()) {
algorithm().parseVariant(variant.GetString()); algorithm().parseVariant(variant.GetString());
} }
@ -128,21 +141,17 @@ xmrig::Pool::Pool(const rapidjson::Value &object) :
algorithm().parseVariant(variant.GetInt()); 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) : 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_keepAlive(keepAlive),
m_flags(1),
m_host(host), m_host(host),
m_password(password), m_password(password),
m_user(user), m_user(user),
m_port(port) m_port(port),
m_pollInterval(kDefaultPollInterval)
{ {
const size_t size = m_host.size() + 8; const size_t size = m_host.size() + 8;
assert(size > 8); assert(size > 8);
@ -151,6 +160,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); snprintf(url, size - 1, "%s:%d", m_host.data(), m_port);
m_url = url; m_url = url;
m_flags.set(FLAG_NICEHASH, nicehash);
m_flags.set(FLAG_TLS, tls);
} }
@ -184,15 +196,19 @@ bool xmrig::Pool::isEnabled() const
} }
# endif # endif
return m_enabled && isValid() && algorithm().isValid(); # 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 bool xmrig::Pool::isEqual(const Pool &other) const
{ {
return (m_nicehash == other.m_nicehash return (m_flags == other.m_flags
&& m_enabled == other.m_enabled
&& m_tls == other.m_tls
&& m_keepAlive == other.m_keepAlive && m_keepAlive == other.m_keepAlive
&& m_port == other.m_port && m_port == other.m_port
&& m_algorithm == other.m_algorithm && m_algorithm == other.m_algorithm
@ -201,7 +217,8 @@ bool xmrig::Pool::isEqual(const Pool &other) const
&& m_password == other.m_password && m_password == other.m_password
&& m_rigId == other.m_rigId && m_rigId == other.m_rigId
&& m_url == other.m_url && m_url == other.m_url
&& m_user == other.m_user); && m_user == other.m_user
&& m_pollInterval == other.m_pollInterval);
} }
@ -213,17 +230,29 @@ bool xmrig::Pool::parse(const char *url)
const char *base = url; const char *base = url;
if (p) { if (p) {
if (strncasecmp(url, "stratum+tcp://", 14) == 0) { if (strncasecmp(url, kStratumTcp, sizeof(kStratumTcp) - 1) == 0) {
m_tls = false; m_flags.set(FLAG_DAEMON, false);
m_flags.set(FLAG_TLS, false);
} }
else if (strncasecmp(url, "stratum+ssl://", 14) == 0) { else if (strncasecmp(url, kStratumSsl, sizeof(kStratumSsl) - 1) == 0) {
m_tls = true; 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 { else {
return false; return false;
} }
base = url + 14; base = p + 3;
} }
if (!strlen(base) || *base == '/') { if (!strlen(base) || *base == '/') {
@ -252,23 +281,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<size_t>(p - userpass));
m_user = user;
m_password = p + 1;
return true;
}
rapidjson::Value xmrig::Pool::toJSON(rapidjson::Document &doc) const rapidjson::Value xmrig::Pool::toJSON(rapidjson::Document &doc) const
{ {
using namespace rapidjson; using namespace rapidjson;
@ -309,9 +321,11 @@ rapidjson::Value xmrig::Pool::toJSON(rapidjson::Document &doc) const
break; 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(kTls), isTLS(), allocator);
obj.AddMember(StringRef(kFingerprint), m_fingerprint.toJSON(), 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; return obj;
} }
@ -350,7 +364,7 @@ void xmrig::Pool::print() const
LOG_DEBUG ("pass: %s", m_password.data()); LOG_DEBUG ("pass: %s", m_password.data());
LOG_DEBUG ("rig-id %s", m_rigId.data()); LOG_DEBUG ("rig-id %s", m_rigId.data());
LOG_DEBUG ("algo: %s", m_algorithm.name()); LOG_DEBUG ("algo: %s", m_algorithm.name());
LOG_DEBUG ("nicehash: %d", static_cast<int>(m_nicehash)); LOG_DEBUG ("nicehash: %d", static_cast<int>(m_flags.test(FLAG_NICEHASH)));
LOG_DEBUG ("keepAlive: %d", m_keepAlive); LOG_DEBUG ("keepAlive: %d", m_keepAlive);
} }
#endif #endif
@ -396,8 +410,8 @@ void xmrig::Pool::adjustVariant(const xmrig::Variant variantHint)
using namespace xmrig; using namespace xmrig;
if (m_host.contains(".nicehash.com")) { if (m_host.contains(".nicehash.com")) {
m_flags.set(FLAG_NICEHASH, true);
m_keepAlive = false; m_keepAlive = false;
m_nicehash = true;
bool valid = true; bool valid = true;
switch (m_port) { switch (m_port) {
@ -432,7 +446,7 @@ void xmrig::Pool::adjustVariant(const xmrig::Variant variantHint)
m_algorithm.setAlgo(INVALID_ALGO); m_algorithm.setAlgo(INVALID_ALGO);
} }
m_tls = m_port > 33000; m_flags.set(FLAG_TLS, m_port > 33000);
return; return;
} }

View file

@ -6,6 +6,7 @@
* Copyright 2016 Jay D Dee <jayddee246@gmail.com> * Copyright 2016 Jay D Dee <jayddee246@gmail.com>
* Copyright 2017-2018 XMR-Stak <https://github.com/fireice-uk>, <https://github.com/psychocrypt> * Copyright 2017-2018 XMR-Stak <https://github.com/fireice-uk>, <https://github.com/psychocrypt>
* Copyright 2018-2019 SChernykh <https://github.com/SChernykh> * Copyright 2018-2019 SChernykh <https://github.com/SChernykh>
* Copyright 2019 Howard Chu <https://github.com/hyc>
* Copyright 2016-2019 XMRig <https://github.com/xmrig>, <support@xmrig.com> * Copyright 2016-2019 XMRig <https://github.com/xmrig>, <support@xmrig.com>
* *
* This program is free software: you can redistribute it and/or modify * This program is free software: you can redistribute it and/or modify
@ -26,6 +27,7 @@
#define XMRIG_POOL_H #define XMRIG_POOL_H
#include <bitset>
#include <vector> #include <vector>
@ -40,11 +42,20 @@ namespace xmrig {
class Pool class Pool
{ {
public: public:
enum Flags {
FLAG_ENABLED,
FLAG_NICEHASH,
FLAG_TLS,
FLAG_DAEMON,
FLAG_MAX
};
static const String kDefaultPassword; static const String kDefaultPassword;
static const String kDefaultUser; 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();
Pool(const char *url); Pool(const char *url);
@ -59,8 +70,9 @@ public:
); );
inline Algorithm &algorithm() { return m_algorithm; } inline Algorithm &algorithm() { return m_algorithm; }
inline bool isNicehash() const { return m_nicehash; } inline bool isDaemon() const { return m_flags.test(FLAG_DAEMON); }
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 bool isValid() const { return !m_host.isNull() && m_port > 0; }
inline const Algorithm &algorithm() const { return m_algorithm; } inline const Algorithm &algorithm() const { return m_algorithm; }
inline const Algorithms &algorithms() const { return m_algorithms; } inline const Algorithms &algorithms() const { return m_algorithms; }
@ -72,14 +84,10 @@ public:
inline const String &user() const { return !m_user.isNull() ? m_user : kDefaultUser; } inline const String &user() const { return !m_user.isNull() ? m_user : kDefaultUser; }
inline int keepAlive() const { return m_keepAlive; } inline int keepAlive() const { return m_keepAlive; }
inline uint16_t port() const { return m_port; } inline uint16_t port() const { return m_port; }
inline void setFingerprint(const char *fingerprint) { m_fingerprint = fingerprint; } inline uint64_t pollInterval() const { return m_pollInterval; }
inline void setKeepAlive(bool enable) { setKeepAlive(enable ? kKeepAliveTimeout : 0); } inline void setPassword(const String &password) { m_password = password; }
inline void setKeepAlive(int keepAlive) { m_keepAlive = keepAlive >= 0 ? keepAlive : 0; } inline void setRigId(const String &rigId) { m_rigId = rigId; }
inline void setNicehash(bool nicehash) { m_nicehash = nicehash; } inline void setUser(const String &user) { m_user = user; }
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); }
@ -88,7 +96,6 @@ public:
bool isEnabled() const; bool isEnabled() const;
bool isEqual(const Pool &other) const; bool isEqual(const Pool &other) const;
bool parse(const char *url); bool parse(const char *url);
bool setUserpass(const char *userpass);
rapidjson::Value toJSON(rapidjson::Document &doc) const; rapidjson::Value toJSON(rapidjson::Document &doc) const;
void adjust(const Algorithm &algorithm); void adjust(const Algorithm &algorithm);
void setAlgo(const Algorithm &algorithm); void setAlgo(const Algorithm &algorithm);
@ -98,6 +105,9 @@ public:
# endif # endif
private: 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); bool parseIPv6(const char *addr);
void addVariant(Variant variant); void addVariant(Variant variant);
void adjustVariant(const Variant variantHint); void adjustVariant(const Variant variantHint);
@ -105,10 +115,8 @@ private:
Algorithm m_algorithm; Algorithm m_algorithm;
Algorithms m_algorithms; Algorithms m_algorithms;
bool m_enabled;
bool m_nicehash;
bool m_tls;
int m_keepAlive; int m_keepAlive;
std::bitset<FLAG_MAX> m_flags;
String m_fingerprint; String m_fingerprint;
String m_host; String m_host;
String m_password; String m_password;
@ -116,6 +124,7 @@ private:
String m_url; String m_url;
String m_user; String m_user;
uint16_t m_port; uint16_t m_port;
uint64_t m_pollInterval;
}; };

View file

@ -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 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) { 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 xmrig::IStrategy *xmrig::Pools::createStrategy(IStrategyListener *listener) const
{ {
if (active() == 1) { if (active() == 1) {
@ -144,6 +115,10 @@ void xmrig::Pools::load(const rapidjson::Value &pools)
{ {
m_data.clear(); m_data.clear();
if (!pools.IsArray()) {
return;
}
for (const rapidjson::Value &value : pools.GetArray()) { for (const rapidjson::Value &value : pools.GetArray()) {
if (!value.IsObject()) { if (!value.IsObject()) {
continue; continue;

View file

@ -50,28 +50,16 @@ public:
Pools(); Pools();
inline bool setUserpass(const char *userpass) { return current().setUserpass(userpass); }
inline const std::vector<Pool> &data() const { return m_data; } inline const std::vector<Pool> &data() const { return m_data; }
inline int donateLevel() const { return m_donateLevel; } inline int donateLevel() const { return m_donateLevel; }
inline int retries() const { return m_retries; } inline int retries() const { return m_retries; }
inline int retryPause() const { return m_retryPause; } inline int retryPause() const { return m_retryPause; }
inline ProxyDonate proxyDonate() const { return m_proxyDonate; } 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); }
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 isEqual(const Pools &other) const;
bool setUrl(const char *url);
IStrategy *createStrategy(IStrategyListener *listener) const; IStrategy *createStrategy(IStrategyListener *listener) const;
rapidjson::Value toJSON(rapidjson::Document &doc) const; rapidjson::Value toJSON(rapidjson::Document &doc) const;
size_t active() const; size_t active() const;
@ -84,8 +72,6 @@ public:
void setRetryPause(int retryPause); void setRetryPause(int retryPause);
private: private:
Pool &current();
int m_donateLevel; int m_donateLevel;
int m_retries; int m_retries;
int m_retryPause; int m_retryPause;

View file

@ -38,17 +38,17 @@ public:
inline SubmitResult() : inline SubmitResult() :
reqId(0), reqId(0),
seq(0), seq(0),
diff(0),
actualDiff(0), actualDiff(0),
diff(0),
elapsed(0), elapsed(0),
m_start(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), reqId(reqId),
seq(seq), seq(seq),
diff(diff),
actualDiff(actualDiff), actualDiff(actualDiff),
diff(diff),
elapsed(0), elapsed(0),
m_start(Chrono::steadyMSecs()) m_start(Chrono::steadyMSecs())
{} {}
@ -57,8 +57,8 @@ public:
int64_t reqId; int64_t reqId;
int64_t seq; int64_t seq;
uint32_t diff;
uint64_t actualDiff; uint64_t actualDiff;
uint64_t diff;
uint64_t elapsed; uint64_t elapsed;
private: private:

View file

@ -29,6 +29,11 @@
#include "common/Platform.h" #include "common/Platform.h"
#ifdef XMRIG_FEATURE_HTTP
# include "base/net/stratum/DaemonClient.h"
#endif
xmrig::FailoverStrategy::FailoverStrategy(const std::vector<Pool> &pools, int retryPause, int retries, IStrategyListener *listener, bool quiet) : xmrig::FailoverStrategy::FailoverStrategy(const std::vector<Pool> &pools, int retryPause, int retries, IStrategyListener *listener, bool quiet) :
m_quiet(quiet), m_quiet(quiet),
m_retries(retries), m_retries(retries),
@ -56,7 +61,7 @@ xmrig::FailoverStrategy::FailoverStrategy(int retryPause, int retries, IStrategy
xmrig::FailoverStrategy::~FailoverStrategy() xmrig::FailoverStrategy::~FailoverStrategy()
{ {
for (Client *client : m_pools) { for (IClient *client : m_pools) {
client->deleteLater(); client->deleteLater();
} }
} }
@ -64,7 +69,15 @@ xmrig::FailoverStrategy::~FailoverStrategy()
void xmrig::FailoverStrategy::add(const Pool &pool) void xmrig::FailoverStrategy::add(const Pool &pool)
{ {
Client *client = new Client(static_cast<int>(m_pools.size()), Platform::userAgent(), this); const int id = static_cast<int>(m_pools.size());
# ifdef XMRIG_FEATURE_HTTP
IClient *client = !pool.isDaemon() ? static_cast<IClient *>(new Client(id, Platform::userAgent(), this))
: static_cast<IClient *>(new DaemonClient(id, this));
# else
IClient *client = new Client(id, Platform::userAgent(), this);
# endif
client->setPool(pool); client->setPool(pool);
client->setRetries(m_retries); client->setRetries(m_retries);
client->setRetryPause(m_retryPause * 1000); client->setRetryPause(m_retryPause * 1000);
@ -102,7 +115,7 @@ void xmrig::FailoverStrategy::resume()
void xmrig::FailoverStrategy::setAlgo(const xmrig::Algorithm &algo) void xmrig::FailoverStrategy::setAlgo(const xmrig::Algorithm &algo)
{ {
for (Client *client : m_pools) { for (IClient *client : m_pools) {
client->setAlgo(algo); client->setAlgo(algo);
} }
} }
@ -123,13 +136,13 @@ void xmrig::FailoverStrategy::stop()
void xmrig::FailoverStrategy::tick(uint64_t now) void xmrig::FailoverStrategy::tick(uint64_t now)
{ {
for (Client *client : m_pools) { for (IClient *client : m_pools) {
client->tick(now); client->tick(now);
} }
} }
void xmrig::FailoverStrategy::onClose(Client *client, int failures) void xmrig::FailoverStrategy::onClose(IClient *client, int failures)
{ {
if (failures == -1) { if (failures == -1) {
return; return;
@ -150,7 +163,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()) { if (m_active == client->id()) {
m_listener->onJob(this, client, job); m_listener->onJob(this, client, job);
@ -158,7 +171,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; int active = m_active;
@ -179,7 +192,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); m_listener->onResultAccepted(this, client, result, error);
} }

View file

@ -52,8 +52,8 @@ public:
protected: protected:
inline bool isActive() const override { return m_active >= 0; } inline bool isActive() const override { return m_active >= 0; }
inline Client *client() const override { return active(); } inline IClient *client() const override { return active(); }
inline void onLogin(Client *, rapidjson::Document &, rapidjson::Value &) override {} inline void onLogin(IClient *, rapidjson::Document &, rapidjson::Value &) override {}
int64_t submit(const JobResult &result) override; int64_t submit(const JobResult &result) override;
void connect() override; void connect() override;
@ -62,13 +62,13 @@ protected:
void stop() override; void stop() override;
void tick(uint64_t now) override; void tick(uint64_t now) override;
void onClose(Client *client, int failures) override; void onClose(IClient *client, int failures) override;
void onJobReceived(Client *client, const Job &job, const rapidjson::Value &params) override; void onJobReceived(IClient *client, const Job &job, const rapidjson::Value &params) override;
void onLoginSuccess(Client *client) override; void onLoginSuccess(IClient *client) override;
void onResultAccepted(Client *client, const SubmitResult &result, const char *error) override; void onResultAccepted(IClient *client, const SubmitResult &result, const char *error) override;
private: private:
inline Client *active() const { return m_pools[static_cast<size_t>(m_active)]; } inline IClient *active() const { return m_pools[static_cast<size_t>(m_active)]; }
const bool m_quiet; const bool m_quiet;
const int m_retries; const int m_retries;
@ -76,7 +76,7 @@ private:
int m_active; int m_active;
IStrategyListener *m_listener; IStrategyListener *m_listener;
size_t m_index; size_t m_index;
std::vector<Client*> m_pools; std::vector<IClient*> m_pools;
}; };

View file

@ -29,11 +29,26 @@
#include "common/Platform.h" #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) : xmrig::SinglePoolStrategy::SinglePoolStrategy(const Pool &pool, int retryPause, int retries, IStrategyListener *listener, bool quiet) :
m_active(false), m_active(false),
m_listener(listener) m_listener(listener)
{ {
# ifdef XMRIG_FEATURE_HTTP
if (!pool.isDaemon()) {
m_client = new Client(0, Platform::userAgent(), this); 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->setPool(pool);
m_client->setRetries(retries); m_client->setRetries(retries);
m_client->setRetryPause(retryPause * 1000); m_client->setRetryPause(retryPause * 1000);
@ -87,7 +102,7 @@ void xmrig::SinglePoolStrategy::tick(uint64_t now)
} }
void xmrig::SinglePoolStrategy::onClose(Client *, int) void xmrig::SinglePoolStrategy::onClose(IClient *, int)
{ {
if (!isActive()) { if (!isActive()) {
return; return;
@ -98,20 +113,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); m_listener->onJob(this, client, job);
} }
void xmrig::SinglePoolStrategy::onLoginSuccess(Client *client) void xmrig::SinglePoolStrategy::onLoginSuccess(IClient *client)
{ {
m_active = true; m_active = true;
m_listener->onActive(this, client); 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); m_listener->onResultAccepted(this, client, result, error);
} }

View file

@ -46,8 +46,8 @@ public:
protected: protected:
inline bool isActive() const override { return m_active; } inline bool isActive() const override { return m_active; }
inline Client *client() const override { return m_client; } inline IClient *client() const override { return m_client; }
inline void onLogin(Client *, rapidjson::Document &, rapidjson::Value &) override {} inline void onLogin(IClient *, rapidjson::Document &, rapidjson::Value &) override {}
int64_t submit(const JobResult &result) override; int64_t submit(const JobResult &result) override;
void connect() override; void connect() override;
@ -56,14 +56,14 @@ protected:
void stop() override; void stop() override;
void tick(uint64_t now) override; void tick(uint64_t now) override;
void onClose(Client *client, int failures) override; void onClose(IClient *client, int failures) override;
void onJobReceived(Client *client, const Job &job, const rapidjson::Value &params) override; void onJobReceived(IClient *client, const Job &job, const rapidjson::Value &params) override;
void onLoginSuccess(Client *client) override; void onLoginSuccess(IClient *client) override;
void onResultAccepted(Client *client, const SubmitResult &result, const char *error) override; void onResultAccepted(IClient *client, const SubmitResult &result, const char *error) override;
private: private:
bool m_active; bool m_active;
Client *m_client; IClient *m_client;
IStrategyListener *m_listener; IStrategyListener *m_listener;
}; };

45
src/base/tools/Baton.h Normal file
View file

@ -0,0 +1,45 @@
/* XMRig
* Copyright 2010 Jeff Garzik <jgarzik@pobox.com>
* Copyright 2012-2014 pooler <pooler@litecoinpool.org>
* Copyright 2014 Lucas Jones <https://github.com/lucasjones>
* Copyright 2014-2016 Wolf9466 <https://github.com/OhGodAPet>
* Copyright 2016 Jay D Dee <jayddee246@gmail.com>
* Copyright 2017-2018 XMR-Stak <https://github.com/fireice-uk>, <https://github.com/psychocrypt>
* Copyright 2018-2019 SChernykh <https://github.com/SChernykh>
* Copyright 2016-2019 XMRig <https://github.com/xmrig>, <support@xmrig.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef XMRIG_BATON_H
#define XMRIG_BATON_H
namespace xmrig {
template<typename REQ>
class Baton
{
public:
inline Baton() { req.data = this; }
REQ req;
};
} /* namespace xmrig */
#endif /* XMRIG_BATON_H */

View file

@ -23,6 +23,9 @@
*/ */
#include <ctype.h>
#include "base/tools/String.h" #include "base/tools/String.h"
#include "rapidjson/document.h" #include "rapidjson/document.h"
@ -129,6 +132,20 @@ std::vector<xmrig::String> 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<char>(tolower(m_data[i]));
}
return *this;
}
xmrig::String xmrig::String::join(const std::vector<xmrig::String> &vec, char sep) xmrig::String xmrig::String::join(const std::vector<xmrig::String> &vec, char sep)
{ {
if (vec.empty()) { if (vec.empty()) {

View file

@ -85,6 +85,7 @@ public:
rapidjson::Value toJSON() const; rapidjson::Value toJSON() const;
rapidjson::Value toJSON(rapidjson::Document &doc) const; rapidjson::Value toJSON(rapidjson::Document &doc) const;
std::vector<xmrig::String> split(char sep) const; std::vector<xmrig::String> split(char sep) const;
String &toLower();
static String join(const std::vector<xmrig::String> &vec, char sep); static String join(const std::vector<xmrig::String> &vec, char sep);

View file

@ -1,426 +0,0 @@
/* XMRig
* Copyright 2010 Jeff Garzik <jgarzik@pobox.com>
* Copyright 2012-2014 pooler <pooler@litecoinpool.org>
* Copyright 2014 Lucas Jones <https://github.com/lucasjones>
* Copyright 2014-2016 Wolf9466 <https://github.com/OhGodAPet>
* Copyright 2016 Jay D Dee <jayddee246@gmail.com>
* Copyright 2017-2018 XMR-Stak <https://github.com/fireice-uk>, <https://github.com/psychocrypt>
* Copyright 2018-2019 SChernykh <https://github.com/SChernykh>
* Copyright 2016-2019 XMRig <https://github.com/xmrig>, <support@xmrig.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <uv.h>
#ifdef XMRIG_FEATURE_TLS
# include <openssl/opensslv.h>
#endif
#ifdef XMRIG_AMD_PROJECT
# if defined(__APPLE__)
# include <OpenCL/cl.h>
# 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<int>(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<uint64_t>(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<uint64_t>(strtol(arg, nullptr, 10)));
default:
break;
}
return true;
}
bool xmrig::CommonConfig::parseUint64(int key, uint64_t arg)
{
return parseInt(key, static_cast<int>(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;
}

View file

@ -1,262 +0,0 @@
/* XMRig
* Copyright 2010 Jeff Garzik <jgarzik@pobox.com>
* Copyright 2012-2014 pooler <pooler@litecoinpool.org>
* Copyright 2014 Lucas Jones <https://github.com/lucasjones>
* Copyright 2014-2016 Wolf9466 <https://github.com/OhGodAPet>
* Copyright 2016 Jay D Dee <jayddee246@gmail.com>
* Copyright 2017-2018 XMR-Stak <https://github.com/fireice-uk>, <https://github.com/psychocrypt>
* Copyright 2018-2019 SChernykh <https://github.com/SChernykh>
* Copyright 2016-2019 XMRig <https://github.com/xmrig>, <support@xmrig.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <assert.h>
#include <limits.h>
#include <stdio.h>
#include <uv.h>
#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<kParseCommentsFlag | kParseTrailingCommasFlag>(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<offset:%zu>: \"%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());
}
}

View file

@ -176,7 +176,7 @@ void xmrig::Algorithm::parseAlgorithm(const char *algo)
m_algo = INVALID_ALGO; m_algo = INVALID_ALGO;
m_variant = VARIANT_AUTO; m_variant = VARIANT_AUTO;
assert(algo != nullptr); // assert(algo != nullptr);
if (algo == nullptr || strlen(algo) < 1) { if (algo == nullptr || strlen(algo) < 1) {
return; return;
} }

View file

@ -35,7 +35,9 @@
"variant": -1, "variant": -1,
"enabled": true, "enabled": true,
"tls": false, "tls": false,
"tls-fingerprint": null "tls-fingerprint": null,
"daemon": false,
"daemon-poll-interval": 1000
} }
], ],
"print-time": 60, "print-time": 60,

View file

@ -26,89 +26,28 @@
#include <assert.h> #include <assert.h>
#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/cpu/Cpu.h"
#include "common/Platform.h" #include "common/Platform.h"
#include "core/config/Config.h"
#include "core/Controller.h" #include "core/Controller.h"
#include "net/Network.h" #include "net/Network.h"
#ifdef HAVE_SYSLOG_H xmrig::Controller::Controller(Process *process) :
# include "base/io/log/backends/SysLog.h" Base(process),
#endif m_network(nullptr)
#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<IControllerListener *> listeners;
};
xmrig::Controller::Controller(Process *process)
: d_ptr(new ControllerPrivate(process))
{ {
} }
xmrig::Controller::~Controller() xmrig::Controller::~Controller()
{ {
delete d_ptr; delete m_network;
}
xmrig::Api *xmrig::Controller::api() const
{
assert(d_ptr->api != nullptr);
return d_ptr->api;
} }
bool xmrig::Controller::isReady() const bool xmrig::Controller::isReady() const
{ {
return d_ptr->config && d_ptr->network; return Base::isReady() && m_network;
}
xmrig::Config *xmrig::Controller::config() const
{
assert(d_ptr->config != nullptr);
return d_ptr->config;
} }
@ -116,98 +55,36 @@ int xmrig::Controller::init()
{ {
Cpu::init(); Cpu::init();
d_ptr->config = Config::load(d_ptr->process, this); const int rc = Base::init();
if (!d_ptr->config) { if (rc != 0) {
return 1; return rc;
} }
# ifdef XMRIG_FEATURE_API m_network = new Network(this);
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);
return 0; 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*>(config);
for (IControllerListener *listener : d_ptr->listeners) {
listener->onConfigChanged(d_ptr->config, previousConfig);
}
delete previousConfig;
}
void xmrig::Controller::start() void xmrig::Controller::start()
{ {
Base::start();
network()->connect(); network()->connect();
# ifdef XMRIG_FEATURE_API
api()->start();
# endif
save();
} }
void xmrig::Controller::stop() void xmrig::Controller::stop()
{ {
# ifdef XMRIG_FEATURE_API Base::stop();
api()->stop();
# endif
ConfigLoader::release(); delete m_network;
m_network = nullptr;
delete d_ptr->network; }
d_ptr->network = nullptr;
xmrig::Network *xmrig::Controller::network() const
{
assert(m_network != nullptr);
return m_network;
} }

View file

@ -26,45 +26,34 @@
#define XMRIG_CONTROLLER_H #define XMRIG_CONTROLLER_H
#include "base/kernel/interfaces/IConfigListener.h" #include "base/kernel/Base.h"
namespace xmrig { namespace xmrig {
class Api;
class Config;
class ControllerPrivate;
class IControllerListener;
class Network; class Network;
class Process;
class Controller : public IConfigListener class Controller : public Base
{ {
public: public:
Controller(Process *process); Controller(Process *process);
~Controller() override; ~Controller() override;
Api *api() const; bool isReady() const override;
bool isReady() const; int init() override;
Config *config() const; void start() override;
int init(); void stop() override;
Network *network() const;
void addListener(IControllerListener *listener);
void save();
void start();
void stop();
protected: Network *network() const;
void onNewConfig(IConfig *config) override;
private: private:
ControllerPrivate *d_ptr; Network *m_network;
}; };
} /* namespace xmrig */ } // namespace xmrig
#endif /* XMRIG_CONTROLLER_H */ #endif /* XMRIG_CONTROLLER_H */

View file

@ -22,13 +22,14 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#include <algorithm>
#include <string.h> #include <string.h>
#include <uv.h> #include <uv.h>
#include <inttypes.h> #include <inttypes.h>
#include "base/io/log/Log.h" #include "base/io/log/Log.h"
#include "common/config/ConfigLoader.h" #include "base/kernel/interfaces/IJsonReader.h"
#include "common/cpu/Cpu.h" #include "common/cpu/Cpu.h"
#include "core/config/Config.h" #include "core/config/Config.h"
#include "crypto/Asm.h" #include "crypto/Asm.h"
@ -42,7 +43,7 @@
static char affinity_tmp[20] = { 0 }; static char affinity_tmp[20] = { 0 };
xmrig::Config::Config() : xmrig::CommonConfig(), xmrig::Config::Config() :
m_aesMode(AES_AUTO), m_aesMode(AES_AUTO),
m_algoVariant(AV_AUTO), m_algoVariant(AV_AUTO),
m_assembly(ASM_AUTO), m_assembly(ASM_AUTO),
@ -55,9 +56,26 @@ 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"));
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();
} }
@ -126,22 +144,8 @@ void xmrig::Config::getJSON(rapidjson::Document &doc) const
} }
xmrig::Config *xmrig::Config::load(Process *process, IConfigListener *listener)
{
return static_cast<Config*>(ConfigLoader::load(process, listener));
}
bool xmrig::Config::finalize() bool xmrig::Config::finalize()
{ {
if (m_state != NoneState) {
return CommonConfig::finalize();
}
if (!CommonConfig::finalize()) {
return false;
}
if (!m_threads.cpu.empty()) { if (!m_threads.cpu.empty()) {
m_threads.mode = Advanced; m_threads.mode = Advanced;
const bool softAES = (m_aesMode == AES_AUTO ? (Cpu::info()->hasAES() ? AES_HW : AES_SOFT) : m_aesMode) == AES_SOFT; const bool softAES = (m_aesMode == AES_AUTO ? (Cpu::info()->hasAES() ? AES_HW : AES_SOFT) : m_aesMode) == AES_SOFT;
@ -173,117 +177,48 @@ bool xmrig::Config::finalize()
} }
m_shouldSave = m_threads.mode == Automatic; 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; return true;
} }
bool xmrig::Config::parseString(int key, const char *arg) void xmrig::Config::setAesMode(const rapidjson::Value &aesMode)
{ {
if (!CommonConfig::parseString(key, arg)) { if (aesMode.IsBool()) {
return false; 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 */ void xmrig::Config::setAlgoVariant(int av)
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"); if (av >= AV_AUTO && av < AV_MAX) {
return parseUint64(key, p ? strtoull(p, nullptr, 16) : strtoull(arg, nullptr, 10)); m_algoVariant = static_cast<AlgoVariant>(av);
} }
# 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::setMaxCpuUsage(int max)
{ {
if (!CommonConfig::parseUint64(key, arg)) { if (max > 0 && max <= 100) {
return false; m_maxCpuUsage = max;
} }
switch (key) {
case CPUAffinityKey: /* --cpu-affinity */
if (arg) {
m_threads.mask = static_cast<int64_t>(arg);
}
break;
default:
return parseInt(key, static_cast<int>(arg));
}
return true;
} }
void xmrig::Config::parseJSON(const rapidjson::Value &json) void xmrig::Config::setPriority(int priority)
{ {
CommonConfig::parseJSON(json); if (priority >= 0 && priority <= 5) {
m_priority = priority;
}
}
const rapidjson::Value &threads = json["threads"];
void xmrig::Config::setThreads(const rapidjson::Value &threads)
{
if (threads.IsArray()) { if (threads.IsArray()) {
m_threads.cpu.clear();
for (const rapidjson::Value &value : threads.GetArray()) { for (const rapidjson::Value &value : threads.GetArray()) {
if (!value.IsObject()) { if (!value.IsObject()) {
continue; continue;
@ -298,41 +233,12 @@ void xmrig::Config::parseJSON(const rapidjson::Value &json)
} }
} }
} }
else if (threads.IsUint()) {
const unsigned count = threads.GetUint();
if (count < 1024) {
m_threads.count = count;
} }
bool xmrig::Config::parseInt(int key, int arg)
{
switch (key) {
case ThreadsKey: /* --threads */
if (arg >= 0 && arg < 1024) {
m_threads.count = arg;
} }
break;
case AVKey: /* --av */
if (arg >= AV_AUTO && arg < AV_MAX) {
m_algoVariant = static_cast<AlgoVariant>(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;
} }
@ -370,3 +276,11 @@ xmrig::AlgoVariant xmrig::Config::getAlgoVariantLite() const
return m_algoVariant; return m_algoVariant;
} }
#endif #endif
#ifndef XMRIG_NO_ASM
void xmrig::Config::setAssembly(const rapidjson::Value &assembly)
{
m_assembly = Asm::parse(assembly);
}
#endif

View file

@ -29,7 +29,7 @@
#include <vector> #include <vector>
#include "common/config/CommonConfig.h" #include "base/kernel/config/BaseConfig.h"
#include "common/xmrig.h" #include "common/xmrig.h"
#include "rapidjson/fwd.h" #include "rapidjson/fwd.h"
#include "workers/CpuThread.h" #include "workers/CpuThread.h"
@ -55,7 +55,7 @@ class Process;
* api/worker-id * api/worker-id
* pools/ * pools/
*/ */
class Config : public CommonConfig class Config : public BaseConfig
{ {
public: public:
enum ThreadsMode { enum ThreadsMode {
@ -67,8 +67,7 @@ public:
Config(); Config();
bool reload(const rapidjson::Value &json); bool read(const IJsonReader &reader, const char *fileName) override;
void getJSON(rapidjson::Document &doc) const override; void getJSON(rapidjson::Document &doc) const override;
inline AesMode aesMode() const { return m_aesMode; } inline AesMode aesMode() const { return m_aesMode; }
@ -80,26 +79,25 @@ public:
inline int priority() const { return m_priority; } inline int priority() const { return m_priority; }
inline int threadsCount() const { return static_cast<int>(m_threads.list.size()); } inline int threadsCount() const { return static_cast<int>(m_threads.list.size()); }
inline int64_t affinity() const { return m_threads.mask; } inline int64_t affinity() const { return m_threads.mask; }
inline static IConfig *create() { return new Config(); }
inline ThreadsMode threadsMode() const { return m_threads.mode; } 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: private:
bool parseInt(int key, int arg); bool finalize();
void setAesMode(const rapidjson::Value &aesMode);
void setAlgoVariant(int av);
void setMaxCpuUsage(int max);
void setPriority(int priority);
void setThreads(const rapidjson::Value &threads);
AlgoVariant getAlgoVariant() const; AlgoVariant getAlgoVariant() const;
# ifndef XMRIG_NO_AEON # ifndef XMRIG_NO_AEON
AlgoVariant getAlgoVariantLite() const; AlgoVariant getAlgoVariantLite() const;
# endif # endif
# ifndef XMRIG_NO_ASM
void setAssembly(const rapidjson::Value &assembly);
# endif
struct Threads struct Threads
{ {

View file

@ -0,0 +1,49 @@
/* XMRig
* Copyright 2010 Jeff Garzik <jgarzik@pobox.com>
* Copyright 2012-2014 pooler <pooler@litecoinpool.org>
* Copyright 2014 Lucas Jones <https://github.com/lucasjones>
* Copyright 2014-2016 Wolf9466 <https://github.com/OhGodAPet>
* Copyright 2016 Jay D Dee <jayddee246@gmail.com>
* Copyright 2017-2018 XMR-Stak <https://github.com/fireice-uk>, <https://github.com/psychocrypt>
* Copyright 2018-2019 SChernykh <https://github.com/SChernykh>
* Copyright 2016-2019 XMRig <https://github.com/xmrig>, <support@xmrig.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "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);
}
void xmrig::ConfigTransform::transformBoolean(rapidjson::Document &doc, int key, bool enable)
{
}
void xmrig::ConfigTransform::transformUint64(rapidjson::Document &doc, int key, uint64_t arg)
{
}

View file

@ -0,0 +1,51 @@
/* XMRig
* Copyright 2010 Jeff Garzik <jgarzik@pobox.com>
* Copyright 2012-2014 pooler <pooler@litecoinpool.org>
* Copyright 2014 Lucas Jones <https://github.com/lucasjones>
* Copyright 2014-2016 Wolf9466 <https://github.com/OhGodAPet>
* Copyright 2016 Jay D Dee <jayddee246@gmail.com>
* Copyright 2017-2018 XMR-Stak <https://github.com/fireice-uk>, <https://github.com/psychocrypt>
* Copyright 2016-2018 XMRig <https://github.com/xmrig>, <support@xmrig.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef 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 */

View file

@ -22,8 +22,8 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#ifndef XMRIG_CONFIGLOADER_DEFAULT_H #ifndef XMRIG_CONFIG_DEFAULT_H
#define XMRIG_CONFIGLOADER_DEFAULT_H #define XMRIG_CONFIG_DEFAULT_H
namespace xmrig { namespace xmrig {
@ -69,7 +69,9 @@ R"===(
"variant": -1, "variant": -1,
"enabled": true, "enabled": true,
"tls": false, "tls": false,
"tls-fingerprint": null "tls-fingerprint": null,
"daemon": false,
"daemon-poll-interval": 1000
} }
], ],
"print-time": 60, "print-time": 60,
@ -85,6 +87,7 @@ R"===(
#endif #endif
} /* namespace xmrig */ } // namespace xmrig
#endif /* XMRIG_CONFIGLOADER_DEFAULT_H */
#endif /* XMRIG_CONFIG_DEFAULT_H */

View file

@ -22,8 +22,8 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#ifndef XMRIG_CONFIGLOADER_PLATFORM_H #ifndef XMRIG_CONFIG_PLATFORM_H
#define XMRIG_CONFIGLOADER_PLATFORM_H #define XMRIG_CONFIG_PLATFORM_H
#ifdef _MSC_VER #ifdef _MSC_VER
@ -33,17 +33,17 @@
#endif #endif
#include "common/interfaces/IConfig.h" #include "base/kernel/interfaces/IConfig.h"
#include "version.h" #include "version.h"
namespace xmrig { 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 }, { "algo", 1, nullptr, IConfig::AlgorithmKey },
{ "api-worker-id", 1, nullptr, IConfig::ApiWorkerIdKey }, { "api-worker-id", 1, nullptr, IConfig::ApiWorkerIdKey },
{ "api-id", 1, nullptr, IConfig::ApiIdKey }, { "api-id", 1, nullptr, IConfig::ApiIdKey },
@ -65,7 +65,6 @@ static struct option const options[] = {
{ "max-cpu-usage", 1, nullptr, IConfig::MaxCPUUsageKey }, { "max-cpu-usage", 1, nullptr, IConfig::MaxCPUUsageKey },
{ "nicehash", 0, nullptr, IConfig::NicehashKey }, { "nicehash", 0, nullptr, IConfig::NicehashKey },
{ "no-color", 0, nullptr, IConfig::ColorKey }, { "no-color", 0, nullptr, IConfig::ColorKey },
{ "no-watch", 0, nullptr, IConfig::WatchKey },
{ "no-huge-pages", 0, nullptr, IConfig::HugePagesKey }, { "no-huge-pages", 0, nullptr, IConfig::HugePagesKey },
{ "variant", 1, nullptr, IConfig::VariantKey }, { "variant", 1, nullptr, IConfig::VariantKey },
{ "pass", 1, nullptr, IConfig::PasswordKey }, { "pass", 1, nullptr, IConfig::PasswordKey },
@ -83,6 +82,8 @@ static struct option const options[] = {
{ "tls", 0, nullptr, IConfig::TlsKey }, { "tls", 0, nullptr, IConfig::TlsKey },
{ "tls-fingerprint", 1, nullptr, IConfig::FingerprintKey }, { "tls-fingerprint", 1, nullptr, IConfig::FingerprintKey },
{ "asm", 1, nullptr, IConfig::AssemblyKey }, { "asm", 1, nullptr, IConfig::AssemblyKey },
{ "daemon", 0, nullptr, IConfig::DaemonKey },
{ "daemon-poll-interval", 1, nullptr, IConfig::DaemonPollKey },
# ifdef XMRIG_DEPRECATED # ifdef XMRIG_DEPRECATED
{ "api-port", 1, nullptr, IConfig::ApiPort }, { "api-port", 1, nullptr, IConfig::ApiPort },
@ -115,21 +116,12 @@ static struct option const config_options[] = {
{ "syslog", 0, nullptr, IConfig::SyslogKey }, { "syslog", 0, nullptr, IConfig::SyslogKey },
{ "threads", 1, nullptr, IConfig::ThreadsKey }, { "threads", 1, nullptr, IConfig::ThreadsKey },
{ "user-agent", 1, nullptr, IConfig::UserAgentKey }, { "user-agent", 1, nullptr, IConfig::UserAgentKey },
{ "watch", 0, nullptr, IConfig::WatchKey },
{ "hw-aes", 0, nullptr, IConfig::HardwareAESKey },
{ "asm", 1, nullptr, IConfig::AssemblyKey }, { "asm", 1, nullptr, IConfig::AssemblyKey },
{ "autosave", 0, nullptr, IConfig::AutoSaveKey },
{ nullptr, 0, nullptr, 0 } { nullptr, 0, nullptr, 0 }
}; };
static struct option const api_options[] = { } // namespace xmrig
{ "worker-id", 1, nullptr, IConfig::ApiWorkerIdKey },
{ "id", 1, nullptr, IConfig::ApiIdKey },
{ nullptr, 0, nullptr, 0 }
};
} /* namespace xmrig */ #endif /* XMRIG_CONFIG_PLATFORM_H */
#endif /* XMRIG_CONFIGLOADER_PLATFORM_H */

View file

@ -45,6 +45,10 @@ Options:\n\
"\ "\
cryptonight-heavy\n" cryptonight-heavy\n"
#endif #endif
#ifndef XMRIG_NO_CN_PICO
"\
cryptonight-pico\n"
#endif
"\ "\
-o, --url=URL URL of mining server\n\ -o, --url=URL URL of mining server\n\
-O, --userpass=U:P username:password pair for mining server\n\ -O, --userpass=U:P username:password pair for mining server\n\
@ -54,9 +58,18 @@ Options:\n\
-t, --threads=N number of miner threads\n\ -t, --threads=N number of miner threads\n\
-v, --av=N algorithm variation, 0 auto select\n\ -v, --av=N algorithm variation, 0 auto select\n\
-k, --keepalive send keepalived packet for prevent timeout (needs pool support)\n\ -k, --keepalive send keepalived packet for prevent timeout (needs pool support)\n\
--nicehash enable nicehash.com support\n\ --nicehash enable nicehash.com support\n"
#ifdef XMRIG_FEATURE_TLS
"\
--tls enable SSL/TLS support (needs pool 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\ --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, --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\ -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-affinity set process affinity to CPU core(s), mask 0x3 for cores 0 and 1\n\
@ -74,17 +87,21 @@ Options:\n\
-S, --syslog use system log for output messages\n" -S, --syslog use system log for output messages\n"
# endif # endif
"\ "\
--max-cpu-usage=N maximum CPU usage for automatic threads mode (default 75)\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\ --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\ --asm=ASM ASM optimizations, possible values: auto, none, intel, ryzen, bulldozer.\n\
--print-time=N print hashrate report every N seconds\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-worker-id=ID custom worker-id for API\n\
--api-id=ID custom instance ID for API\n\ --api-id=ID custom instance ID for API\n\
--http-enabled enable HTTP API\n\ --http-enabled enable HTTP API\n\
--http-host=HOST bind host for HTTP API (by default 127.0.0.1)\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-port=N bind port for HTTP API\n\
--http-access-token=T access token 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\ --http-no-restricted enable full remote access to HTTP API (only if access token set)\n"
#endif
"\
--dry-run test configuration and exit\n\ --dry-run test configuration and exit\n\
-h, --help display this help and exit\n\ -h, --help display this help and exit\n\
-V, --version output version information and exit\n\ -V, --version output version information and exit\n\

View file

@ -130,7 +130,7 @@ static inline uint32_t sub_word(uint32_t key)
saes_sbox[key & 0xff]; saes_sbox[key & 0xff];
} }
#if defined(__clang__) || defined(XMRIG_ARM) #ifndef HAVE_ROTR
static inline uint32_t _rotr(uint32_t value, uint32_t amount) static inline uint32_t _rotr(uint32_t value, uint32_t amount)
{ {
return (value >> amount) | (value << ((32 - amount) & 31)); return (value >> amount) | (value << ((32 - amount) & 31));

View file

@ -41,20 +41,20 @@ namespace xmrig {
class JobResult class JobResult
{ {
public: public:
inline JobResult() : poolId(0), diff(0), nonce(0) {} 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, uint32_t diff, const Algorithm &algorithm) : 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), algorithm(algorithm),
poolId(poolId), poolId(poolId),
clientId(clientId), clientId(clientId),
jobId(jobId), jobId(jobId),
diff(diff), nonce(nonce),
nonce(nonce) diff(diff)
{ {
memcpy(this->result, result, sizeof(this->result)); 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(); jobId = job.id();
clientId = job.clientId(); clientId = job.clientId();
@ -75,8 +75,8 @@ public:
int poolId; int poolId;
String clientId; String clientId;
String jobId; String jobId;
uint32_t diff;
uint32_t nonce; uint32_t nonce;
uint64_t diff;
uint8_t result[32]; uint8_t result[32];
}; };

View file

@ -6,6 +6,7 @@
* Copyright 2016 Jay D Dee <jayddee246@gmail.com> * Copyright 2016 Jay D Dee <jayddee246@gmail.com>
* Copyright 2017-2018 XMR-Stak <https://github.com/fireice-uk>, <https://github.com/psychocrypt> * Copyright 2017-2018 XMR-Stak <https://github.com/fireice-uk>, <https://github.com/psychocrypt>
* Copyright 2018-2019 SChernykh <https://github.com/SChernykh> * Copyright 2018-2019 SChernykh <https://github.com/SChernykh>
* Copyright 2019 Howard Chu <https://github.com/hyc>
* Copyright 2016-2019 XMRig <https://github.com/xmrig>, <support@xmrig.com> * Copyright 2016-2019 XMRig <https://github.com/xmrig>, <support@xmrig.com>
* *
* This program is free software: you can redistribute it and/or modify * This program is free software: you can redistribute it and/or modify
@ -91,18 +92,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) { if (m_donate && m_donate == strategy) {
LOG_NOTICE("dev donate started"); LOG_NOTICE("dev donate started");
return; 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(); const char *tlsVersion = client->tlsVersion();
LOG_INFO(WHITE_BOLD("use pool ") CYAN_BOLD("%s:%d ") GREEN_BOLD("%s") " " BLACK_BOLD("%s"), LOG_INFO(WHITE_BOLD("use %s ") CYAN_BOLD("%s:%d ") GREEN_BOLD("%s") " " BLACK_BOLD("%s"),
client->host(), client->port(), tlsVersion ? tlsVersion : "", client->ip()); client->mode(), client->pool().host().data(), client->pool().port(), tlsVersion ? tlsVersion : "", client->ip().data());
const char *fingerprint = client->tlsFingerprint(); const char *fingerprint = client->tlsFingerprint();
if (fingerprint != nullptr) { if (fingerprint != nullptr) {
@ -127,7 +128,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) { if (m_donate && m_donate->isActive() && m_donate != strategy) {
return; return;
@ -176,30 +177,30 @@ 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); m_state.add(result, error);
if (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); m_state.accepted, m_state.rejected, result.diff, error, result.elapsed);
} }
else { 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); m_state.accepted, m_state.rejected, result.diff, result.elapsed);
} }
} }
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()) { 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()); client->pool().host().data(), client->pool().port(), job.diff(), job.algorithm().shortName(), job.height());
} }
else { 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()); client->pool().host().data(), client->pool().port(), job.diff(), job.algorithm().shortName());
} }
if (!donate && m_donate) { if (!donate && m_donate) {

View file

@ -6,6 +6,7 @@
* Copyright 2016 Jay D Dee <jayddee246@gmail.com> * Copyright 2016 Jay D Dee <jayddee246@gmail.com>
* Copyright 2017-2018 XMR-Stak <https://github.com/fireice-uk>, <https://github.com/psychocrypt> * Copyright 2017-2018 XMR-Stak <https://github.com/fireice-uk>, <https://github.com/psychocrypt>
* Copyright 2018-2019 SChernykh <https://github.com/SChernykh> * Copyright 2018-2019 SChernykh <https://github.com/SChernykh>
* Copyright 2019 Howard Chu <https://github.com/hyc>
* Copyright 2016-2019 XMRig <https://github.com/xmrig>, <support@xmrig.com> * Copyright 2016-2019 XMRig <https://github.com/xmrig>, <support@xmrig.com>
* *
* This program is free software: you can redistribute it and/or modify * This program is free software: you can redistribute it and/or modify
@ -30,7 +31,7 @@
#include "api/interfaces/IApiListener.h" #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/IStrategyListener.h"
#include "base/kernel/interfaces/ITimerListener.h" #include "base/kernel/interfaces/ITimerListener.h"
#include "interfaces/IJobResultListener.h" #include "interfaces/IJobResultListener.h"
@ -45,7 +46,7 @@ class Controller;
class IStrategy; 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: public:
Network(Controller *controller); Network(Controller *controller);
@ -58,18 +59,18 @@ public:
protected: protected:
inline void onTimer(const Timer *) override { tick(); } 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 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 onJobResult(const JobResult &result) override;
void onPause(IStrategy *strategy) override; void onPause(IStrategy *strategy) override;
void onRequest(IApiRequest &request) 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: private:
constexpr static int kTickInterval = 1 * 1000; 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(); void tick();
# ifdef XMRIG_FEATURE_API # ifdef XMRIG_FEATURE_API

View file

@ -35,14 +35,14 @@
xmrig::NetworkState::NetworkState() : xmrig::NetworkState::NetworkState() :
diff(0), pool(),
accepted(0), accepted(0),
diff(0),
failures(0), failures(0),
rejected(0), rejected(0),
total(0), total(0),
m_active(false) m_active(false)
{ {
memset(pool, 0, sizeof(pool));
} }

View file

@ -50,8 +50,8 @@ public:
char pool[256]; char pool[256];
std::array<uint64_t, 10> topDiff { { } }; std::array<uint64_t, 10> topDiff { { } };
uint32_t diff;
uint64_t accepted; uint64_t accepted;
uint64_t diff;
uint64_t failures; uint64_t failures;
uint64_t rejected; uint64_t rejected;
uint64_t total; uint64_t total;

View file

@ -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()) { if (isActive()) {
return; 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) { if (failures == 2 && m_controller->config()->pools().proxyDonate() == Pools::PROXY_DONATE_AUTO) {
m_proxy->deleteLater(); m_proxy->deleteLater();
@ -184,7 +184,7 @@ void xmrig::DonateStrategy::onClose(Client *, int failures)
} }
void xmrig::DonateStrategy::onLogin(Client *, rapidjson::Document &doc, rapidjson::Value &params) void xmrig::DonateStrategy::onLogin(IClient *, rapidjson::Document &doc, rapidjson::Value &params)
{ {
auto &allocator = doc.GetAllocator(); 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()) { if (isActive()) {
return; return;
@ -227,14 +227,14 @@ xmrig::Client *xmrig::DonateStrategy::createProxy()
} }
IStrategy *strategy = m_controller->network()->strategy(); IStrategy *strategy = m_controller->network()->strategy();
if (!strategy->isActive() || !strategy->client()->has<Client::EXT_CONNECT>()) { if (!strategy->isActive() || !strategy->client()->hasExtension(IClient::EXT_CONNECT)) {
return nullptr; return nullptr;
} }
const Client *client = strategy->client(); const IClient *client = strategy->client();
m_tls = client->has<Client::EXT_TLS>(); 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()); pool.setAlgo(client->pool().algorithm());
Client *proxy = new Client(-1, Platform::userAgent(), this); 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()) { if (isActive()) {
m_listener->onJob(this, client, job); 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); m_listener->onResultAccepted(this, client, result, error);
} }

View file

@ -52,11 +52,11 @@ public:
protected: protected:
inline bool isActive() const override { return state() == STATE_ACTIVE; } inline bool isActive() const override { return state() == STATE_ACTIVE; }
inline Client *client() const override { return m_proxy ? m_proxy : m_strategy->client(); } inline IClient *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 onJob(IStrategy *, IClient *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 onJobReceived(IClient *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(IClient *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 onResultAccepted(IStrategy *, IClient *client, const SubmitResult &result, const char *error) override { setResult(client, result, error); }
inline void resume() override {} inline void resume() override {}
int64_t submit(const JobResult &result) override; int64_t submit(const JobResult &result) override;
@ -65,12 +65,12 @@ protected:
void stop() override; void stop() override;
void tick(uint64_t now) 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 onPause(IStrategy *strategy) override;
void onClose(Client *client, int failures) override; void onClose(IClient *client, int failures) override;
void onLogin(Client *client, rapidjson::Document &doc, rapidjson::Value &params) override; void onLogin(IClient *client, rapidjson::Document &doc, rapidjson::Value &params) override;
void onLoginSuccess(Client *client) override; void onLoginSuccess(IClient *client) override;
void onTimer(const Timer *timer) override; void onTimer(const Timer *timer) override;
@ -87,13 +87,13 @@ private:
Client *createProxy(); Client *createProxy();
void idle(double min, double max); void idle(double min, double max);
void setJob(Client *client, const Job &job); void setJob(IClient *client, const Job &job);
void setResult(Client *client, const SubmitResult &result, const char *error); void setResult(IClient *client, const SubmitResult &result, const char *error);
void setState(State state); void setState(State state);
bool m_tls; bool m_tls;
char m_userId[65]; char m_userId[65];
Client *m_proxy; IClient *m_proxy;
const uint64_t m_donateTime; const uint64_t m_donateTime;
const uint64_t m_idleTime; const uint64_t m_idleTime;
Controller *m_controller; Controller *m_controller;

View file

@ -28,7 +28,7 @@
#define APP_ID "xmrig" #define APP_ID "xmrig"
#define APP_NAME "XMRig" #define APP_NAME "XMRig"
#define APP_DESC "XMRig CPU miner" #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_DOMAIN "xmrig.com"
#define APP_SITE "www.xmrig.com" #define APP_SITE "www.xmrig.com"
#define APP_COPYRIGHT "Copyright (C) 2016-2019 xmrig.com" #define APP_COPYRIGHT "Copyright (C) 2016-2019 xmrig.com"
@ -36,7 +36,7 @@
#define APP_VER_MAJOR 2 #define APP_VER_MAJOR 2
#define APP_VER_MINOR 15 #define APP_VER_MINOR 15
#define APP_VER_PATCH 1 #define APP_VER_PATCH 2
#ifdef _MSC_VER #ifdef _MSC_VER
# if (_MSC_VER >= 1910) # if (_MSC_VER >= 1910)