mirror of
https://github.com/xmrig/xmrig.git
synced 2024-11-18 18:11:05 +00:00
Merge branch 'evo' into beta
This commit is contained in:
commit
fe9aa9f3c4
91 changed files with 3746 additions and 1876 deletions
|
@ -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.
|
||||||
|
|
|
@ -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})
|
||||||
|
|
|
@ -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()
|
||||||
|
|
|
@ -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()
|
||||||
|
|
|
@ -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));
|
||||||
|
|
|
@ -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;
|
||||||
};
|
};
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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),
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
@ -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
79
src/base/io/json/Json.h
Normal 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 */
|
213
src/base/io/json/JsonChain.cpp
Normal file
213
src/base/io/json/JsonChain.cpp
Normal 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;
|
||||||
|
}
|
76
src/base/io/json/JsonChain.h
Normal file
76
src/base/io/json/JsonChain.h
Normal 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 */
|
38
src/base/io/json/JsonRequest.cpp
Normal file
38
src/base/io/json/JsonRequest.cpp
Normal 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 ¶ms)
|
||||||
|
{
|
||||||
|
auto &allocator = doc.GetAllocator();
|
||||||
|
|
||||||
|
doc.AddMember("id", id, allocator);
|
||||||
|
doc.AddMember("jsonrpc", "2.0", allocator);
|
||||||
|
doc.AddMember("method", rapidjson::StringRef(method), allocator);
|
||||||
|
doc.AddMember("params", params, allocator);
|
||||||
|
}
|
|
@ -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 ¶ms);
|
||||||
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 */
|
|
@ -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"
|
|
@ -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;
|
||||||
}
|
}
|
|
@ -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
290
src/base/kernel/Base.cpp
Normal 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);
|
||||||
|
}
|
|
@ -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);
|
|
||||||
}
|
|
196
src/base/kernel/config/BaseConfig.cpp
Normal file
196
src/base/kernel/config/BaseConfig.cpp
Normal 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;
|
||||||
|
}
|
|
@ -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 */
|
279
src/base/kernel/config/BaseTransform.cpp
Normal file
279
src/base/kernel/config/BaseTransform.cpp
Normal 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;
|
||||||
|
}
|
||||||
|
}
|
123
src/base/kernel/config/BaseTransform.h
Normal file
123
src/base/kernel/config/BaseTransform.h
Normal 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 */
|
|
@ -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
|
85
src/base/kernel/interfaces/IClient.h
Normal file
85
src/base/kernel/interfaces/IClient.h
Normal 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
|
|
@ -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 ¶ms) = 0;
|
virtual void onJobReceived(IClient *client, const Job &job, const rapidjson::Value ¶ms) = 0;
|
||||||
virtual void onLogin(Client *client, rapidjson::Document &doc, rapidjson::Value ¶ms) = 0;
|
virtual void onLogin(IClient *client, rapidjson::Document &doc, rapidjson::Value ¶ms) = 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;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -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,17 +141,13 @@ public:
|
||||||
|
|
||||||
virtual ~IConfig() = default;
|
virtual ~IConfig() = default;
|
||||||
|
|
||||||
virtual bool finalize() = 0;
|
virtual bool isWatch() const = 0;
|
||||||
virtual bool isWatch() const = 0;
|
virtual bool read(const IJsonReader &reader, const char *fileName) = 0;
|
||||||
virtual bool parseBoolean(int key, bool enable) = 0;
|
virtual bool save() = 0;
|
||||||
virtual bool parseString(int key, const char *arg) = 0;
|
virtual const Algorithm &algorithm() const = 0;
|
||||||
virtual bool parseUint64(int key, uint64_t arg) = 0;
|
virtual const String &fileName() const = 0;
|
||||||
virtual bool save() = 0;
|
virtual void getJSON(rapidjson::Document &doc) const = 0;
|
||||||
virtual const Algorithm &algorithm() const = 0;
|
virtual void setFileName(const char *fileName) = 0;
|
||||||
virtual const String &fileName() const = 0;
|
|
||||||
virtual void getJSON(rapidjson::Document &doc) const = 0;
|
|
||||||
virtual void parseJSON(const rapidjson::Value &json) = 0;
|
|
||||||
virtual void setFileName(const char *fileName) = 0;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -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
|
|
@ -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;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
56
src/base/kernel/interfaces/IJsonReader.h
Normal file
56
src/base/kernel/interfaces/IJsonReader.h
Normal 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
|
|
@ -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;
|
||||||
|
|
|
@ -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;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -47,8 +47,9 @@ public:
|
||||||
Dns(IDnsListener *listener);
|
Dns(IDnsListener *listener);
|
||||||
~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 int status() const { return m_status; }
|
inline const String &host() const { return m_host; }
|
||||||
|
inline int status() const { return m_status; }
|
||||||
|
|
||||||
bool resolve(const String &host);
|
bool resolve(const String &host);
|
||||||
const char *error() const;
|
const char *error() const;
|
||||||
|
|
|
@ -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"
|
||||||
|
|
||||||
|
|
||||||
|
|
224
src/base/net/http/HttpClient.cpp
Normal file
224
src/base/net/http/HttpClient.cpp
Normal 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();
|
||||||
|
}
|
|
@ -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
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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];
|
HttpContext *ctx = HttpContext::get(m_id);
|
||||||
bufs[0].base = const_cast<char *>(header.c_str());
|
WriteBaton *baton = new WriteBaton(ss, data, size, ctx);
|
||||||
|
|
||||||
# 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);
|
|
||||||
|
|
||||||
# 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();
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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();
|
||||||
|
|
208
src/base/net/http/HttpsClient.cpp
Normal file
208
src/base/net/http/HttpsClient.cpp
Normal 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);
|
||||||
|
}
|
77
src/base/net/http/HttpsClient.h
Normal file
77
src/base/net/http/HttpsClient.h
Normal 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
|
62
src/base/net/stratum/BaseClient.cpp
Normal file
62
src/base/net/stratum/BaseClient.cpp
Normal 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;
|
||||||
|
}
|
96
src/base/net/stratum/BaseClient.h
Normal file
96
src/base/net/stratum/BaseClient.h
Normal file
|
@ -0,0 +1,96 @@
|
||||||
|
/* XMRig
|
||||||
|
* Copyright 2010 Jeff Garzik <jgarzik@pobox.com>
|
||||||
|
* Copyright 2012-2014 pooler <pooler@litecoinpool.org>
|
||||||
|
* Copyright 2014 Lucas Jones <https://github.com/lucasjones>
|
||||||
|
* Copyright 2014-2016 Wolf9466 <https://github.com/OhGodAPet>
|
||||||
|
* Copyright 2016 Jay D Dee <jayddee246@gmail.com>
|
||||||
|
* Copyright 2017-2018 XMR-Stak <https://github.com/fireice-uk>, <https://github.com/psychocrypt>
|
||||||
|
* Copyright 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 */
|
|
@ -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,14 +581,10 @@ 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);
|
||||||
params.AddMember("agent", StringRef(m_agent), allocator);
|
params.AddMember("agent", StringRef(m_agent), allocator);
|
||||||
|
|
||||||
if (!m_pool.rigId().isNull()) {
|
if (!m_pool.rigId().isNull()) {
|
||||||
params.AddMember("rigid", m_pool.rigId().toJSON(), allocator);
|
params.AddMember("rigid", m_pool.rigId().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();
|
||||||
|
|
|
@ -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;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
378
src/base/net/stratum/DaemonClient.cpp
Normal file
378
src/base/net/stratum/DaemonClient.cpp
Normal 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 ¶ms, 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;
|
||||||
|
}
|
||||||
|
}
|
83
src/base/net/stratum/DaemonClient.h
Normal file
83
src/base/net/stratum/DaemonClient.h
Normal 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 ¶ms, int *code);
|
||||||
|
bool parseResponse(int64_t id, const rapidjson::Value &result, const rapidjson::Value &error);
|
||||||
|
int64_t getBlockTemplate();
|
||||||
|
void retry();
|
||||||
|
void send(int method, const char *url, const char *data = nullptr, size_t size = 0);
|
||||||
|
void send(int method, const char *url, const rapidjson::Document &doc);
|
||||||
|
void setState(SocketState state);
|
||||||
|
|
||||||
|
bool m_monero;
|
||||||
|
String m_blocktemplate;
|
||||||
|
String m_prevHash;
|
||||||
|
String m_tlsFingerprint;
|
||||||
|
String m_tlsVersion;
|
||||||
|
Timer *m_timer;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
} /* namespace xmrig */
|
||||||
|
|
||||||
|
|
||||||
|
#endif /* XMRIG_DAEMONCLIENT_H */
|
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -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); }
|
||||||
|
|
|
@ -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,35 +42,43 @@
|
||||||
|
|
||||||
#ifdef _MSC_VER
|
#ifdef _MSC_VER
|
||||||
# define strncasecmp _strnicmp
|
# define strncasecmp _strnicmp
|
||||||
# define strcasecmp _stricmp
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
namespace xmrig {
|
namespace xmrig {
|
||||||
|
|
||||||
static const char *kEnabled = "enabled";
|
static const char *kDaemon = "daemon";
|
||||||
static const char *kFingerprint = "tls-fingerprint";
|
static const char *kDaemonPollInterval = "daemon-poll-interval";
|
||||||
static const char *kKeepalive = "keepalive";
|
static const char *kEnabled = "enabled";
|
||||||
static const char *kNicehash = "nicehash";
|
static const char *kFingerprint = "tls-fingerprint";
|
||||||
static const char *kPass = "pass";
|
static const char *kKeepalive = "keepalive";
|
||||||
static const char *kRigId = "rig-id";
|
static const char *kNicehash = "nicehash";
|
||||||
static const char *kTls = "tls";
|
static const char *kPass = "pass";
|
||||||
static const char *kUrl = "url";
|
static const char *kRigId = "rig-id";
|
||||||
static const char *kUser = "user";
|
static const char *kTls = "tls";
|
||||||
static const char *kVariant = "variant";
|
static const char *kUrl = "url";
|
||||||
|
static const char *kUser = "user";
|
||||||
|
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,24 +196,29 @@ 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_keepAlive == other.m_keepAlive
|
||||||
&& m_tls == other.m_tls
|
&& m_port == other.m_port
|
||||||
&& m_keepAlive == other.m_keepAlive
|
&& m_algorithm == other.m_algorithm
|
||||||
&& m_port == other.m_port
|
&& m_fingerprint == other.m_fingerprint
|
||||||
&& m_algorithm == other.m_algorithm
|
&& m_host == other.m_host
|
||||||
&& m_fingerprint == other.m_fingerprint
|
&& m_password == other.m_password
|
||||||
&& m_host == other.m_host
|
&& m_rigId == other.m_rigId
|
||||||
&& m_password == other.m_password
|
&& m_url == other.m_url
|
||||||
&& m_rigId == other.m_rigId
|
&& m_user == other.m_user
|
||||||
&& m_url == other.m_url
|
&& m_pollInterval == other.m_pollInterval);
|
||||||
&& m_user == other.m_user);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -209,21 +226,33 @@ bool xmrig::Pool::parse(const char *url)
|
||||||
{
|
{
|
||||||
assert(url != nullptr);
|
assert(url != nullptr);
|
||||||
|
|
||||||
const char *p = strstr(url, "://");
|
const char *p = strstr(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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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,23 +84,18 @@ 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); }
|
||||||
|
|
||||||
bool isCompatible(const Algorithm &algorithm) const;
|
bool isCompatible(const Algorithm &algorithm) const;
|
||||||
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;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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 ¤t();
|
|
||||||
|
|
||||||
int m_donateLevel;
|
int m_donateLevel;
|
||||||
int m_retries;
|
int m_retries;
|
||||||
int m_retryPause;
|
int m_retryPause;
|
||||||
|
|
|
@ -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:
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
|
@ -51,9 +51,9 @@ public:
|
||||||
void add(const Pool &pool);
|
void add(const Pool &pool);
|
||||||
|
|
||||||
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 ¶ms) override;
|
void onJobReceived(IClient *client, const Job &job, const rapidjson::Value ¶ms) 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;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -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);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
m_client = new DaemonClient(0, this);
|
||||||
|
}
|
||||||
|
# else
|
||||||
m_client = new Client(0, Platform::userAgent(), this);
|
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);
|
||||||
}
|
}
|
||||||
|
|
|
@ -45,9 +45,9 @@ public:
|
||||||
~SinglePoolStrategy() override;
|
~SinglePoolStrategy() override;
|
||||||
|
|
||||||
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 ¶ms) override;
|
void onJobReceived(IClient *client, const Job &job, const rapidjson::Value ¶ms) 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
45
src/base/tools/Baton.h
Normal file
|
@ -0,0 +1,45 @@
|
||||||
|
/* XMRig
|
||||||
|
* Copyright 2010 Jeff Garzik <jgarzik@pobox.com>
|
||||||
|
* Copyright 2012-2014 pooler <pooler@litecoinpool.org>
|
||||||
|
* Copyright 2014 Lucas Jones <https://github.com/lucasjones>
|
||||||
|
* Copyright 2014-2016 Wolf9466 <https://github.com/OhGodAPet>
|
||||||
|
* Copyright 2016 Jay D Dee <jayddee246@gmail.com>
|
||||||
|
* Copyright 2017-2018 XMR-Stak <https://github.com/fireice-uk>, <https://github.com/psychocrypt>
|
||||||
|
* Copyright 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 */
|
|
@ -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()) {
|
||||||
|
|
|
@ -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);
|
||||||
|
|
||||||
|
|
|
@ -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;
|
|
||||||
}
|
|
|
@ -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());
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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 */
|
||||||
|
|
|
@ -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;
|
||||||
|
@ -153,7 +157,7 @@ bool xmrig::Config::finalize()
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
const AlgoVariant av = getAlgoVariant();
|
const AlgoVariant av = getAlgoVariant();
|
||||||
m_threads.mode = m_threads.count ? Simple : Automatic;
|
m_threads.mode = m_threads.count ? Simple : Automatic;
|
||||||
|
|
||||||
const size_t size = CpuThread::multiway(av) * cn_select_memory(m_algorithm.algo()) / 1024;
|
const size_t size = CpuThread::multiway(av) * cn_select_memory(m_algorithm.algo()) / 1024;
|
||||||
|
@ -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 */
|
|
||||||
return parseBoolean(key, true);
|
|
||||||
|
|
||||||
case HugePagesKey: /* --no-huge-pages */
|
|
||||||
return parseBoolean(key, false);
|
|
||||||
|
|
||||||
case ThreadsKey: /* --threads */
|
|
||||||
if (strncmp(arg, "all", 3) == 0) {
|
|
||||||
m_threads.count = Cpu::info()->threads();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return parseUint64(key, strtol(arg, nullptr, 10));
|
|
||||||
|
|
||||||
case CPUAffinityKey: /* --cpu-affinity */
|
|
||||||
{
|
|
||||||
const char *p = strstr(arg, "0x");
|
|
||||||
return parseUint64(key, p ? strtoull(p, nullptr, 16) : strtoull(arg, nullptr, 10));
|
|
||||||
}
|
|
||||||
|
|
||||||
# ifndef XMRIG_NO_ASM
|
|
||||||
case AssemblyKey: /* --asm */
|
|
||||||
m_assembly = Asm::parse(arg);
|
|
||||||
break;
|
|
||||||
# endif
|
|
||||||
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool xmrig::Config::parseUint64(int key, uint64_t arg)
|
void xmrig::Config::setAlgoVariant(int av)
|
||||||
{
|
{
|
||||||
if (!CommonConfig::parseUint64(key, arg)) {
|
if (av >= AV_AUTO && av < AV_MAX) {
|
||||||
return false;
|
m_algoVariant = static_cast<AlgoVariant>(av);
|
||||||
}
|
}
|
||||||
|
|
||||||
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::setMaxCpuUsage(int max)
|
||||||
{
|
{
|
||||||
CommonConfig::parseJSON(json);
|
if (max > 0 && max <= 100) {
|
||||||
|
m_maxCpuUsage = max;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const rapidjson::Value &threads = json["threads"];
|
|
||||||
|
|
||||||
|
void xmrig::Config::setPriority(int priority)
|
||||||
|
{
|
||||||
|
if (priority >= 0 && priority <= 5) {
|
||||||
|
m_priority = priority;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void xmrig::Config::setThreads(const rapidjson::Value &threads)
|
||||||
|
{
|
||||||
if (threads.IsArray()) {
|
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) {
|
||||||
bool xmrig::Config::parseInt(int key, int arg)
|
m_threads.count = count;
|
||||||
{
|
|
||||||
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
|
||||||
|
|
|
@ -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
|
||||||
{
|
{
|
||||||
|
|
49
src/core/config/ConfigTransform.cpp
Normal file
49
src/core/config/ConfigTransform.cpp
Normal file
|
@ -0,0 +1,49 @@
|
||||||
|
/* XMRig
|
||||||
|
* Copyright 2010 Jeff Garzik <jgarzik@pobox.com>
|
||||||
|
* Copyright 2012-2014 pooler <pooler@litecoinpool.org>
|
||||||
|
* Copyright 2014 Lucas Jones <https://github.com/lucasjones>
|
||||||
|
* Copyright 2014-2016 Wolf9466 <https://github.com/OhGodAPet>
|
||||||
|
* Copyright 2016 Jay D Dee <jayddee246@gmail.com>
|
||||||
|
* Copyright 2017-2018 XMR-Stak <https://github.com/fireice-uk>, <https://github.com/psychocrypt>
|
||||||
|
* Copyright 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)
|
||||||
|
{
|
||||||
|
}
|
51
src/core/config/ConfigTransform.h
Normal file
51
src/core/config/ConfigTransform.h
Normal 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 */
|
|
@ -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 */
|
|
@ -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 */
|
|
|
@ -35,59 +35,76 @@ namespace xmrig {
|
||||||
static char const usage[] = "\
|
static char const usage[] = "\
|
||||||
Usage: " APP_ID " [OPTIONS]\n\
|
Usage: " APP_ID " [OPTIONS]\n\
|
||||||
Options:\n\
|
Options:\n\
|
||||||
-a, --algo=ALGO specify the algorithm to use\n\
|
-a, --algo=ALGO specify the algorithm to use\n\
|
||||||
cryptonight\n"
|
cryptonight\n"
|
||||||
#ifndef XMRIG_NO_AEON
|
#ifndef XMRIG_NO_AEON
|
||||||
"\
|
"\
|
||||||
cryptonight-lite\n"
|
cryptonight-lite\n"
|
||||||
#endif
|
#endif
|
||||||
#ifndef XMRIG_NO_SUMO
|
#ifndef XMRIG_NO_SUMO
|
||||||
"\
|
"\
|
||||||
cryptonight-heavy\n"
|
cryptonight-heavy\n"
|
||||||
|
#endif
|
||||||
|
#ifndef XMRIG_NO_CN_PICO
|
||||||
|
"\
|
||||||
|
cryptonight-pico\n"
|
||||||
#endif
|
#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\
|
||||||
-u, --user=USERNAME username for mining server\n\
|
-u, --user=USERNAME username for mining server\n\
|
||||||
-p, --pass=PASSWORD password for mining server\n\
|
-p, --pass=PASSWORD password for mining server\n\
|
||||||
--rig-id=ID rig identifier for pool-side statistics (needs pool support)\n\
|
--rig-id=ID rig identifier for pool-side statistics (needs pool support)\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"
|
||||||
--tls enable SSL/TLS support (needs pool support)\n\
|
#ifdef XMRIG_FEATURE_TLS
|
||||||
--tls-fingerprint=F pool TLS certificate fingerprint, if set enable strict certificate pinning\n\
|
"\
|
||||||
-r, --retries=N number of times to retry before switch to backup server (default: 5)\n\
|
--tls enable SSL/TLS support (needs pool support)\n\
|
||||||
-R, --retry-pause=N time to pause between retries (default: 5)\n\
|
--tls-fingerprint=F pool TLS certificate fingerprint, if set enable strict certificate pinning\n"
|
||||||
--cpu-affinity set process affinity to CPU core(s), mask 0x3 for cores 0 and 1\n\
|
#endif
|
||||||
--cpu-priority set process priority (0 idle, 2 normal to 5 highest)\n\
|
#ifdef XMRIG_FEATURE_HTTP
|
||||||
--no-huge-pages disable huge pages support\n\
|
"\
|
||||||
--no-color disable colored output\n\
|
--daemon use daemon RPC instead of pool for solo mining\n\
|
||||||
--variant algorithm PoW variant\n\
|
--daemon-poll-interval=N daemon poll interval in milliseconds (default: 1000)\n"
|
||||||
--donate-level=N donate level, default 5%% (5 minutes in 100 minutes)\n\
|
#endif
|
||||||
--user-agent set custom user-agent string for pool\n\
|
"\
|
||||||
-B, --background run the miner in the background\n\
|
-r, --retries=N number of times to retry before switch to backup server (default: 5)\n\
|
||||||
-c, --config=FILE load a JSON-format configuration file\n\
|
-R, --retry-pause=N time to pause between retries (default: 5)\n\
|
||||||
-l, --log-file=FILE log all output to a file\n"
|
--cpu-affinity set process affinity to CPU core(s), mask 0x3 for cores 0 and 1\n\
|
||||||
|
--cpu-priority set process priority (0 idle, 2 normal to 5 highest)\n\
|
||||||
|
--no-huge-pages disable huge pages support\n\
|
||||||
|
--no-color disable colored output\n\
|
||||||
|
--variant algorithm PoW variant\n\
|
||||||
|
--donate-level=N donate level, default 5%% (5 minutes in 100 minutes)\n\
|
||||||
|
--user-agent set custom user-agent string for pool\n\
|
||||||
|
-B, --background run the miner in the background\n\
|
||||||
|
-c, --config=FILE load a JSON-format configuration file\n\
|
||||||
|
-l, --log-file=FILE log all output to a file\n"
|
||||||
# ifdef HAVE_SYSLOG_H
|
# ifdef HAVE_SYSLOG_H
|
||||||
"\
|
"\
|
||||||
-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"
|
||||||
--api-worker-id=ID custom worker-id for API\n\
|
#ifdef XMRIG_FEATURE_HTTP
|
||||||
--api-id=ID custom instance ID for API\n\
|
"\
|
||||||
--http-enabled enable HTTP API\n\
|
--api-worker-id=ID custom worker-id for API\n\
|
||||||
--http-host=HOST bind host for HTTP API (by default 127.0.0.1)\n\
|
--api-id=ID custom instance ID for API\n\
|
||||||
--http-port=N bind port for HTTP API\n\
|
--http-enabled enable HTTP API\n\
|
||||||
--http-access-token=T access token for HTTP API\n\
|
--http-host=HOST bind host for HTTP API (default: 127.0.0.1)\n\
|
||||||
--http-no-restricted enable full remote access to HTTP API (only if access token set)\n\
|
--http-port=N bind port for HTTP API\n\
|
||||||
--dry-run test configuration and exit\n\
|
--http-access-token=T access token for HTTP API\n\
|
||||||
-h, --help display this help and exit\n\
|
--http-no-restricted enable full remote access to HTTP API (only if access token set)\n"
|
||||||
-V, --version output version information and exit\n\
|
#endif
|
||||||
|
"\
|
||||||
|
--dry-run test configuration and exit\n\
|
||||||
|
-h, --help display this help and exit\n\
|
||||||
|
-V, --version output version information and exit\n\
|
||||||
";
|
";
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -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));
|
||||||
|
|
|
@ -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];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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 ¶ms)
|
void xmrig::DonateStrategy::onLogin(IClient *, rapidjson::Document &doc, rapidjson::Value ¶ms)
|
||||||
{
|
{
|
||||||
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);
|
||||||
}
|
}
|
||||||
|
|
|
@ -51,13 +51,13 @@ public:
|
||||||
~DonateStrategy() override;
|
~DonateStrategy() override;
|
||||||
|
|
||||||
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;
|
||||||
void connect() override;
|
void connect() 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 ¶ms) override;
|
void onLogin(IClient *client, rapidjson::Document &doc, rapidjson::Value ¶ms) 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;
|
||||||
|
|
|
@ -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)
|
||||||
|
|
Loading…
Reference in a new issue