Compare commits

...

63 Commits

Author SHA1 Message Date
XMRig
6e839d2c92 Use fake algorithm for test. 2019-08-09 15:08:39 +07:00
XMRig
57ebee8ea7 v2.99.1-beta 2019-08-09 14:21:02 +07:00
XMRig
13a44dda16 Sync changes with miner. 2019-08-09 14:01:43 +07:00
XMRig
e661835b83 v2.99.0-beta 2019-08-04 18:22:30 +07:00
XMRig
704ffd4b26 Merge branch 'evo' into beta 2019-08-04 18:19:08 +07:00
xmrig
8564da0b18 Update CHANGELOG.md 2019-08-04 15:53:51 +07:00
XMRig
216c33a633 v2.99.0-evo 2019-08-03 23:34:53 +07:00
XMRig
90261ac1d2 Merge branch 'v2_99' into evo 2019-08-03 23:21:40 +07:00
XMRig
5bda61755f Updated default config.json. 2019-08-03 12:53:52 +07:00
XMRig
cf48ac311c Restored old donate method. 2019-08-03 12:38:07 +07:00
XMRig
a76e56a30d Sync changes. 2019-08-02 21:36:38 +07:00
XMRig
e796b84198 Move files. 2019-07-29 11:30:42 +07:00
XMRig
971e905ccb Removed unused source files. 2019-07-29 08:17:42 +07:00
XMRig
22605fdb29 Sync changes. 2019-07-28 21:24:06 +07:00
XMRig
9fc2b8b2d2 Merge branch 'beta' into evo 2019-07-28 18:16:32 +07:00
XMRig
ed820e9eae v2.16.1-beta 2019-07-21 23:47:55 +07:00
XMRig
bfc2c27bb1 Merge branch 'evo' into beta 2019-07-21 23:44:44 +07:00
xmrig
c6e0d4ef09 Update CHANGELOG.md 2019-07-21 03:05:39 +07:00
xmrig
3c80356961 Update CHANGELOG.md 2019-07-21 03:05:13 +07:00
XMRig
d51dcd6315 Added "rx/loki" algorithm. 2019-07-20 00:41:01 +07:00
XMRig
be09f9ef3c v2.16.1-evo 2019-06-26 11:09:29 +07:00
XMRig
4f1ad0aea3 Merge branch 'beta' into evo 2019-06-26 11:08:45 +07:00
xmrig
9c1fba5a25 Update CHANGELOG.md 2019-06-26 11:03:56 +07:00
xmrig
eabbfc1ec4 Update CHANGELOG.md 2019-06-25 14:49:45 +07:00
XMRig
be8fdaf6f0 v2.16.0-beta 2019-06-25 14:14:42 +07:00
XMRig
fe002102c6 Merge branch 'evo' into beta 2019-06-25 14:13:50 +07:00
XMRig
98e04e24cf Fix. 2019-06-25 10:52:59 +07:00
XMRig
d7faffc0a0 Added RandomWOW support. 2019-06-25 10:22:34 +07:00
XMRig
816489d110 Sync changes. 2019-06-01 13:13:06 +07:00
XMRig
96e2a36d41 Merge branch 'dev' into evo 2019-06-01 12:40:50 +07:00
XMRig
e3a62ab274 v2.14.5-dev 2019-05-31 23:06:10 +07:00
XMRig
3549bc687e Merge branch 'master' into dev 2019-05-31 22:55:02 +07:00
XMRig
157ba8ec42 v2.14.4 2019-05-30 12:03:32 +07:00
XMRig
cd848f27f9 Merge branch 'dev' 2019-05-30 12:03:03 +07:00
xmrig
64117d6bc7 Update CHANGELOG.md 2019-05-29 17:25:50 +07:00
XMRig
6634b61dab Merge branch 'master' into dev 2019-05-29 17:08:09 +07:00
XMRig
d2fb04ead8 v2.14.4-dev 2019-05-29 17:03:55 +07:00
XMRig
79d5be209f Removed obsolete automatic variants. 2019-05-26 19:02:16 +07:00
XMRig
354dd60f7f v2.15.4-beta 2019-04-18 21:01:29 +07:00
XMRig
20998e2c77 Merge branch 'beta' into evo 2019-04-18 21:00:27 +07:00
XMRig
02efd26a50 Fixed regression, default value for algo option was not applied. 2019-04-18 15:27:26 +07:00
XMRig
234b96bc16 v2.15.2-beta 2019-04-18 00:26:45 +07:00
XMRig
8e0507d865 Merge branch 'evo' into beta 2019-04-18 00:26:16 +07:00
xmrig
8d5802b77e Update CHANGELOG.md 2019-04-18 00:02:40 +07:00
XMRig
9620faf35c Updated default config. 2019-04-17 19:06:05 +07:00
XMRig
f234fd71a9 Fixed Linux build. 2019-04-14 03:40:04 +07:00
XMRig
6aba4bd787 Sync changes. 2019-04-14 03:36:21 +07:00
XMRig
aa7a64ae04 Added daemon support. 2019-04-13 19:06:33 +07:00
XMRig
a11aceb69a Fix build on FreeBSD. 2019-04-06 21:19:25 +07:00
XMRig
513db3012e Merge branch 'feature-json-centric-config' into evo 2019-04-06 18:31:35 +07:00
XMRig
26815f93eb New config subsystem. 2019-04-06 17:48:31 +07:00
XMRig
fc4ffc0a1b Fixed, big HTTP responses was truncated. 2019-04-02 17:47:37 +07:00
XMRig
0f3a0afc13 v2.15.2-evo 2019-04-02 00:00:54 +07:00
XMRig
8caed995de Merge branch 'beta' into evo 2019-04-01 23:42:11 +07:00
XMRig
7ddbcb0c21 v2.15.1-beta 2019-04-01 19:06:32 +07:00
XMRig
beeaf14784 Merge branch 'evo' into beta 2019-04-01 19:06:03 +07:00
xmrig
b1ef6268aa Update CHANGELOG.md 2019-04-01 19:02:23 +07:00
XMRig
0bfee737cb Fixed wrong status code for "GET /1/config" and updated app.rc. 2019-04-01 17:37:03 +07:00
XMRig
1158294789 Sync changes. 2019-04-01 12:31:49 +07:00
XMRig
b49a51e569 Better compatibility with previous configs. 2019-04-01 00:28:09 +07:00
XMRig
f7f8e54498 Fixed malformed HTTP response on Linux. 2019-04-01 00:20:11 +07:00
XMRig
916eb43349 Fix compile issue. 2019-04-01 00:01:10 +07:00
XMRig
294dd9f2e1 Merge branch 'feature-httpd' into evo 2019-03-31 23:38:35 +07:00
144 changed files with 4954 additions and 3453 deletions

View File

@@ -1,4 +1,33 @@
# v2.99.1-beta
- [#1066](https://github.com/xmrig/xmrig/issues/1066#issuecomment-518080529) Added error message if pool not ready for RandomX.
- Name for reference RandomX configuration changed to `rx/text` to avoid potential conflicts in future.
# v2.99.0-beta
* [#335](https://github.com/xmrig/xmrig-proxy/issues/335) Added support for unlimited algorithm switching.
* Config files from previous versions NOT compatible, `variant` option replaced to `algo`, global option `algo` removed.
* Command line options also not compatible, `--variant` option replaced to `--algo`.
* Algorithm `cn/msr` renamed to `cn/fast`.
* Algorithm `cn/xtl` removed.
# v2.16.1-beta
- Added RandomXL algorithm for [Loki](https://loki.network/).
- Algorithm name used by proxy is `randomx/loki` or `rx/loki`.
# v2.16.0-beta
- [#1036](https://github.com/xmrig/xmrig/pull/1036) Added RandomWOW (RandomX with different preferences) algorithm support for [Wownero](http://wownero.org/).
- Algorithm name used by proxy is `randomx/wow` or `rx/wow`.
- Currently runtime algorithm switching NOT supported with other algorithms.
# v2.15.3-beta
- [#1014](https://github.com/xmrig/xmrig/issues/1014) Fixed regression, default value for `algo` option was not applied.
# v2.15.2-beta
- [#1010](https://github.com/xmrig/xmrig/pull/1010#issuecomment-482632107) Added daemon support (solo mining).
- Config subsystem was rewritten, internally JSON is primary format now.
- Fixed regression, big HTTP responses was truncated.
# v2.15.1-beta
- [#1007](https://github.com/xmrig/xmrig/issues/1007) Old HTTP API backend based on libmicrohttpd, replaced to custom HTTP server (libuv + http_parser).
- [#257](https://github.com/xmrig/xmrig-nvidia/pull/257) New logging subsystem, file and syslog now always without colors.
# v2.15.0-beta
@@ -6,6 +35,10 @@
- Added new options `algo-ext` and `access-password`.
- Added real graceful exit.
# v2.14.4
- Fixed MSVC 2019 version detection.
- Removed obsolete automatic variants.
# v2.14.1
- [#306](https://github.com/xmrig/xmrig-proxy/issues/306) [#310](https://github.com/xmrig/xmrig-proxy/issues/310) Fixed compile issues and random crashing if verbose mode or access log was enabled.

View File

@@ -4,7 +4,7 @@ project(xmrig-proxy)
option(WITH_GOOGLE_BREAKPAD "Use Google Breakpad" OFF)
option(WITH_DEBUG_LOG "Enable debug log output" OFF)
option(WITH_HTTPD "HTTP REST API" ON)
option(WITH_HTTP "HTTP protocol support (client/server)" ON)
option(WITH_TLS "Enable OpenSSL support" ON)
@@ -15,26 +15,16 @@ include (src/base/base.cmake)
set(HEADERS
"${HEADERS_BASE}"
"${HEADERS_BASE_HTTP}"
src/3rdparty/align.h
src/App.h
src/common/config/CommonConfig.h
src/common/config/ConfigLoader.h
src/common/config/ConfigWatcher.h
src/common/crypto/Algorithm.h
src/common/crypto/keccak.h
src/common/interfaces/IConfig.h
src/common/Platform.h
src/common/xmrig.h
src/core/config/Config_platform.h
src/core/config/Config.h
src/core/config/ConfigLoader_platform.h
src/core/config/ConfigTransform.h
src/core/config/usage.h
src/core/Controller.h
src/crypto/cn/CnAlgo.h
src/crypto/common/Algorithm.h
src/crypto/common/keccak.h
src/donate.h
src/interfaces/IEvent.h
src/interfaces/IEventListener.h
src/interfaces/ISplitter.h
src/log/AccessLog.h
src/log/ShareLog.h
src/net/JobResult.h
src/net/strategies/DonateStrategy.h
src/proxy/BindHost.h
@@ -49,6 +39,11 @@ set(HEADERS
src/proxy/events/LoginEvent.h
src/proxy/events/MinerEvent.h
src/proxy/events/SubmitEvent.h
src/proxy/interfaces/IEvent.h
src/proxy/interfaces/IEventListener.h
src/proxy/interfaces/ISplitter.h
src/proxy/log/AccessLog.h
src/proxy/log/ShareLog.h
src/proxy/Login.h
src/proxy/Miner.h
src/proxy/Miners.h
@@ -77,16 +72,11 @@ set(SOURCES
"${SOURCES_BASE}"
"${SOURCES_BASE_HTTP}"
src/App.cpp
src/common/config/CommonConfig.cpp
src/common/config/ConfigLoader.cpp
src/common/config/ConfigWatcher.cpp
src/common/crypto/Algorithm.cpp
src/common/crypto/keccak.cpp
src/common/Platform.cpp
src/core/config/Config.cpp
src/core/config/ConfigTransform.cpp
src/core/Controller.cpp
src/log/AccessLog.cpp
src/log/ShareLog.cpp
src/crypto/common/Algorithm.cpp
src/crypto/common/keccak.cpp
src/net/JobResult.cpp
src/net/strategies/DonateStrategy.cpp
src/proxy/BindHost.cpp
@@ -97,6 +87,8 @@ set(SOURCES
src/proxy/events/ConnectionEvent.h
src/proxy/events/Event.cpp
src/proxy/events/MinerEvent.cpp
src/proxy/log/AccessLog.cpp
src/proxy/log/ShareLog.cpp
src/proxy/Login.cpp
src/proxy/Miner.cpp
src/proxy/Miners.cpp
@@ -120,10 +112,9 @@ set(SOURCES
if (WIN32)
set(SOURCES_OS
"${SOURCES_OS}"
res/app.rc
src/App_win.cpp
src/base/io/Json_win.cpp
src/common/Platform_win.cpp
src/proxy/Uuid_win.cpp
)
@@ -131,9 +122,8 @@ if (WIN32)
set(EXTRA_LIBS ws2_32 psapi iphlpapi userenv)
elseif (APPLE)
set(SOURCES_OS
"${SOURCES_OS}"
src/App_unix.cpp
src/base/io/Json_unix.cpp
src/common/Platform_mac.cpp
src/proxy/Uuid_mac.cpp
)
@@ -141,9 +131,8 @@ elseif (APPLE)
set(EXTRA_LIBS ${CFLIB})
else()
set(SOURCES_OS
"${SOURCES_OS}"
src/App_unix.cpp
src/base/io/Json_unix.cpp
src/common/Platform_unix.cpp
src/proxy/Uuid_unix.cpp
)
@@ -160,6 +149,12 @@ add_definitions(/D__STDC_FORMAT_MACROS)
add_definitions(/DAPP_DEVEL)
add_definitions(/DXMRIG_NO_ASM)
add_definitions(/DXMRIG_ALGO_RANDOMX)
add_definitions(/DXMRIG_ALGO_CN_LITE)
add_definitions(/DXMRIG_ALGO_CN_HEAVY)
add_definitions(/DXMRIG_ALGO_CN_PICO)
add_definitions(/DXMRIG_ALGO_CN_GPU)
if (CMAKE_SYSTEM_PROCESSOR MATCHES "^(x86_64|AMD64)$" AND CMAKE_SIZEOF_VOID_P EQUAL 8)
add_definitions(/DRAPIDJSON_SSE2)
endif()
@@ -225,8 +220,8 @@ else()
add_definitions(/DXMRIG_NO_GOOGLE_BREAKPAD)
endif()
if (WITH_HTTPD)
set(HTTPD_SOURCES
if (WITH_HTTP)
set(HTTP_SOURCES
src/api/Api.cpp
src/api/Api.h
src/api/Httpd.cpp
@@ -240,9 +235,7 @@ if (WITH_HTTPD)
src/api/v1/ApiRouter.h
)
else()
set(HTTPD_SOURCES "")
add_definitions(/DXMRIG_NO_HTTPD)
add_definitions(/DXMRIG_NO_API)
set(HTTP_SOURCES "")
endif()
if (WITH_DEBUG_LOG)
@@ -253,5 +246,5 @@ include_directories(src)
include_directories(src/3rdparty)
include_directories(${UV_INCLUDE_DIR})
add_executable(${CMAKE_PROJECT_NAME} ${HEADERS} ${SOURCES} ${SOURCES_OS} ${SOURCES_SYSLOG} ${HTTPD_SOURCES} ${TLS_SOURCES})
add_executable(${CMAKE_PROJECT_NAME} ${HEADERS} ${SOURCES} ${SOURCES_OS} ${SOURCES_SYSLOG} ${HTTP_SOURCES} ${TLS_SOURCES})
target_link_libraries(${CMAKE_PROJECT_NAME} ${OPENSSL_LIBRARIES} ${UV_LIBRARIES} ${EXTRA_LIBS} ${GOOGLE_BREAKPAD_LIBS})

View File

@@ -21,7 +21,12 @@ if (WITH_TLS)
src/proxy/tls/TlsContext.cpp
src/proxy/tls/TlsContext.h
)
include_directories(${OPENSSL_INCLUDE_DIR})
if (WITH_HTTP)
set(TLS_SOURCES ${TLS_SOURCES} src/base/net/http/HttpsClient.h src/base/net/http/HttpsClient.cpp)
endif()
else()
message(FATAL_ERROR "OpenSSL NOT found: use `-DWITH_TLS=OFF` to build without TLS support")
endif()

View File

@@ -1,7 +1,7 @@
#include <windows.h>
#include "../src/version.h"
IDI_ICON1 ICON DISCARDABLE "app.ico"
101 ICON "app.ico"
VS_VERSION_INFO VERSIONINFO
FILEVERSION APP_VER_MAJOR,APP_VER_MINOR,APP_VER_PATCH,0

33
src/3rdparty/align.h vendored
View File

@@ -1,33 +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 2016-2017 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 __ALIGN_H__
#define __ALIGN_H__
#ifdef _MSC_VER
# define VAR_ALIGN(x, decl) __declspec(align(x)) decl
#else
# define VAR_ALIGN(x, decl) decl __attribute__ ((aligned(x)))
#endif
#endif /* __ALIGN_H__ */

View File

@@ -32,7 +32,6 @@
#include "base/io/Console.h"
#include "base/io/log/Log.h"
#include "base/kernel/Signals.h"
#include "common/Platform.h"
#include "core/config/Config.h"
#include "core/Controller.h"
#include "proxy/Proxy.h"

View File

@@ -30,7 +30,7 @@
#include "App.h"
#include "base/io/log/Log.h"
#include "core/Config.h"
#include "core/config/Config.h"
#include "core/Controller.h"

View File

@@ -41,12 +41,6 @@ static void print_mode(xmrig::Controller *controller)
}
static void print_algo(xmrig::Controller *controller)
{
xmrig::Log::print(GREEN_BOLD(" * ") WHITE_BOLD("%-13s") MAGENTA_BOLD("%s"), "ALGO", controller->config()->algorithm().name());
}
static void print_bind(xmrig::Controller *controller)
{
const xmrig::BindHosts &bind = controller->config()->bind();
@@ -81,7 +75,6 @@ void Summary::print(xmrig::Controller *controller)
{
controller->config()->printVersions();
print_mode(controller);
print_algo(controller);
controller->config()->pools().print();
print_bind(controller);
print_commands(controller);

View File

@@ -36,10 +36,11 @@
#include "api/interfaces/IApiListener.h"
#include "api/requests/HttpApiRequest.h"
#include "api/v1/ApiRouter.h"
#include "base/kernel/Base.h"
#include "base/tools/Buffer.h"
#include "common/crypto/keccak.h"
#include "core/config/Config.h"
#include "core/Controller.h"
#include "crypto/common/keccak.h"
#include "version.h"
@@ -48,17 +49,18 @@
#endif
xmrig::Api::Api(Controller *controller) :
xmrig::Api::Api(Base *base) :
m_base(base),
m_id(),
m_workerId(),
m_controller(controller),
m_timestamp(Chrono::currentMSecsSinceEpoch()),
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);
}
@@ -73,9 +75,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);
}
@@ -83,10 +85,10 @@ void xmrig::Api::request(const HttpRequest &req)
void xmrig::Api::start()
{
genWorkerId(m_controller->config()->apiWorkerId());
genWorkerId(m_base->config()->apiWorkerId());
# ifdef XMRIG_FEATURE_HTTP
m_httpd = new Httpd(m_controller);
m_httpd = new Httpd(m_base);
m_httpd->start();
# endif
}
@@ -116,10 +118,34 @@ void xmrig::Api::exec(IApiRequest &request)
{
using namespace rapidjson;
if (request.method() == IApiRequest::METHOD_GET && (request.url() == "/1/summary" || request.url() == "/api.json")) {
if (request.type() == IApiRequest::REQ_SUMMARY) {
auto &allocator = request.doc().GetAllocator();
request.accept();
request.reply().AddMember("id", StringRef(m_id), request.doc().GetAllocator());
request.reply().AddMember("worker_id", StringRef(m_workerId), request.doc().GetAllocator());;
request.reply().AddMember("id", StringRef(m_id), allocator);
request.reply().AddMember("worker_id", StringRef(m_workerId), allocator);
request.reply().AddMember("uptime", (Chrono::currentMSecsSinceEpoch() - m_timestamp) / 1000, allocator);
Value features(kArrayType);
# ifdef XMRIG_FEATURE_API
features.PushBack("api", allocator);
# endif
# ifdef XMRIG_FEATURE_ASM
features.PushBack("asm", allocator);
# endif
# ifdef XMRIG_FEATURE_HTTP
features.PushBack("http", allocator);
# endif
# ifdef XMRIG_FEATURE_LIBCPUID
features.PushBack("cpuid", allocator);
# endif
# ifdef XMRIG_FEATURE_HWLOC
features.PushBack("hwloc", allocator);
# endif
# ifdef XMRIG_FEATURE_TLS
features.PushBack("tls", allocator);
# endif
request.reply().AddMember("features", features, allocator);
}
for (IApiListener *listener : m_listeners) {
@@ -155,15 +181,15 @@ void xmrig::Api::genId(const String &id)
uint8_t hash[200];
const size_t addrSize = sizeof(interfaces[i].phys_addr);
const size_t inSize = strlen(APP_KIND) + addrSize + sizeof(uint16_t);
const uint16_t port = static_cast<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]();
memcpy(input, &port, sizeof(uint16_t));
memcpy(input + sizeof(uint16_t), interfaces[i].phys_addr, addrSize);
memcpy(input + sizeof(uint16_t) + addrSize, APP_KIND, strlen(APP_KIND));
xmrig::keccak(input, inSize, hash);
xmrig::Buffer::toHex(hash, 8, m_id);
keccak(input, inSize, hash);
Buffer::toHex(hash, 8, m_id);
delete [] input;
break;

View File

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

View File

@@ -28,7 +28,7 @@
#include "api/Httpd.h"
#include "base/io/log/Log.h"
#include "base/net/http/HttpApiResponse.h"
#include "base/net/http/HttpRequest.h"
#include "base/net/http/HttpData.h"
#include "base/net/http/HttpServer.h"
#include "base/net/tools/TcpServer.h"
#include "core/config/Config.h"
@@ -40,16 +40,21 @@ namespace xmrig {
static const char *kAuthorization = "authorization";
static const char *kContentType = "content-type";
#ifdef _WIN32
static const char *favicon = nullptr;
static size_t faviconSize = 0;
#endif
} // namespace xmrig
xmrig::Httpd::Httpd(Controller *controller) :
m_controller(controller),
xmrig::Httpd::Httpd(Base *base) :
m_base(base),
m_http(nullptr),
m_server(nullptr),
m_port(0)
{
controller->addListener(this);
base->addListener(this);
}
@@ -60,7 +65,7 @@ xmrig::Httpd::~Httpd()
bool xmrig::Httpd::start()
{
const Http &config = m_controller->config()->http();
const Http &config = m_base->config()->http();
if (!config.isEnabled()) {
return true;
@@ -85,6 +90,17 @@ bool xmrig::Httpd::start()
m_port = static_cast<uint16_t>(rc);
# ifdef _WIN32
HRSRC src = FindResource(nullptr, MAKEINTRESOURCE(1), RT_ICON);
if (src != nullptr) {
HGLOBAL res = LoadResource(nullptr, src);
if (res != nullptr) {
favicon = static_cast<const char *>(LockResource(res));
faviconSize = SizeofResource(nullptr, src);
}
}
# endif
return true;
}
@@ -112,38 +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) {
return HttpApiResponse(req.id()).end();
if (data.method == HTTP_OPTIONS) {
return HttpApiResponse(data.id()).end();
}
if (req.method > 4) {
return HttpApiResponse(req.id(), HTTP_STATUS_METHOD_NOT_ALLOWED).end();
if (data.method == HTTP_GET && data.url == "/favicon.ico") {
# ifdef _WIN32
if (favicon != nullptr) {
HttpResponse response(data.id());
response.setHeader("Content-Type", "image/x-icon");
return response.end(favicon, faviconSize);
}
# endif
return HttpResponse(data.id(), 404).end();
}
const int status = auth(req);
if (data.method > 4) {
return HttpApiResponse(data.id(), HTTP_STATUS_METHOD_NOT_ALLOWED).end();
}
const int status = auth(data);
if (status != HTTP_STATUS_OK) {
return HttpApiResponse(req.id(), status).end();
return HttpApiResponse(data.id(), status).end();
}
if (req.method != HTTP_GET) {
if (m_controller->config()->http().isRestricted()) {
return HttpApiResponse(req.id(), HTTP_STATUS_FORBIDDEN).end();
if (data.method != HTTP_GET) {
if (m_base->config()->http().isRestricted()) {
return HttpApiResponse(data.id(), HTTP_STATUS_FORBIDDEN).end();
}
if (!req.headers.count(kContentType) || req.headers.at(kContentType) != "application/json") {
return HttpApiResponse(req.id(), HTTP_STATUS_UNSUPPORTED_MEDIA_TYPE).end();
if (!data.headers.count(kContentType) || data.headers.at(kContentType) != "application/json") {
return HttpApiResponse(data.id(), HTTP_STATUS_UNSUPPORTED_MEDIA_TYPE).end();
}
}
m_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)) {
return config.isAuthRequired() ? HTTP_STATUS_UNAUTHORIZED : HTTP_STATUS_OK;

View File

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

View File

@@ -35,7 +35,9 @@ class IApiListener
public:
virtual ~IApiListener() = default;
# ifdef XMRIG_FEATURE_API
virtual void onRequest(IApiRequest &request) = 0;
# endif
};

View File

@@ -4,7 +4,9 @@
* 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 2016-2018 XMRig <support@xmrig.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
@@ -50,6 +52,12 @@ public:
};
enum RequestType {
REQ_UNKNOWN,
REQ_SUMMARY
};
virtual ~IApiRequest() = default;
virtual bool isDone() const = 0;
@@ -57,9 +65,11 @@ public:
virtual bool isRestricted() const = 0;
virtual const rapidjson::Value &json() const = 0;
virtual const String &url() const = 0;
virtual int version() const = 0;
virtual Method method() const = 0;
virtual rapidjson::Document &doc() = 0;
virtual rapidjson::Value &reply() = 0;
virtual RequestType type() const = 0;
virtual Source source() const = 0;
virtual void accept() = 0;
virtual void done(int status) = 0;

View File

@@ -28,8 +28,7 @@
xmrig::ApiRequest::ApiRequest(Source source, bool restricted) :
m_restricted(restricted),
m_source(source),
m_state(STATE_NEW)
m_source(source)
{
}

View File

@@ -43,10 +43,15 @@ protected:
inline bool isDone() const override { return m_state == STATE_DONE; }
inline bool isNew() const override { return m_state == STATE_NEW; }
inline bool isRestricted() const override { return m_restricted; }
inline int version() const override { return m_version; }
inline RequestType type() const override { return m_type; }
inline Source source() const override { return m_source; }
inline void accept() override { m_state = STATE_ACCEPTED; }
inline void done(int) override { m_state = STATE_DONE; }
int m_version = 1;
RequestType m_type = REQ_UNKNOWN;
private:
enum State {
STATE_NEW,
@@ -56,7 +61,7 @@ private:
bool m_restricted;
Source m_source;
State m_state;
State m_state = STATE_NEW;
};

View File

@@ -24,17 +24,28 @@
#include "api/requests/HttpApiRequest.h"
#include "base/net/http/HttpRequest.h"
#include "base/net/http/HttpData.h"
#include "rapidjson/error/en.h"
xmrig::HttpApiRequest::HttpApiRequest(const HttpRequest &req, bool restricted) :
xmrig::HttpApiRequest::HttpApiRequest(const HttpData &req, bool restricted) :
ApiRequest(SOURCE_HTTP, restricted),
m_parsed(false),
m_req(req),
m_res(req.id()),
m_url(req.url.c_str())
{
if (method() == METHOD_GET) {
if (url() == "/1/summary" || url() == "/2/summary" || url() == "/api.json") {
m_type = REQ_SUMMARY;
}
}
if (url().size() > 4) {
if (memcmp(url().data(), "/2/", 3) == 0) {
m_version = 2;
}
}
}

View File

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

View File

@@ -28,10 +28,10 @@
#include <thread>
#include "api/interfaces/IApiRequest.h"
#include "api/v1/ApiRouter.h"
#include "base/kernel/Platform.h"
#include "base/tools/Buffer.h"
#include "common/crypto/keccak.h"
#include "common/Platform.h"
#include "core/config/Config.h"
#include "core/Controller.h"
#include "proxy/Miner.h"
@@ -39,7 +39,6 @@
#include "rapidjson/prettywriter.h"
#include "rapidjson/stringbuffer.h"
#include "version.h"
#include "api/interfaces/IApiRequest.h"
static inline double normalize(double d)
@@ -52,8 +51,8 @@ static inline double normalize(double d)
}
xmrig::ApiRouter::ApiRouter(Controller *controller) :
m_controller(controller)
xmrig::ApiRouter::ApiRouter(Base *base) :
m_base(base)
{
}
@@ -66,7 +65,7 @@ xmrig::ApiRouter::~ApiRouter()
void xmrig::ApiRouter::onRequest(IApiRequest &request)
{
if (request.method() == IApiRequest::METHOD_GET) {
if (request.url() == "/1/summary") {
if (request.type() == IApiRequest::REQ_SUMMARY) {
request.accept();
getMiner(request.reply(), request.doc());
getHashrate(request.reply(), request.doc());
@@ -83,24 +82,6 @@ void xmrig::ApiRouter::onRequest(IApiRequest &request)
request.accept();
getMiners(request.reply(), request.doc());
}
else if (request.url() == "/1/config") {
if (request.isRestricted()) {
return request.done(403);
}
m_controller->config()->getJSON(request.doc());
}
}
else if (request.method() == IApiRequest::METHOD_PUT || request.method() == IApiRequest::METHOD_POST) {
if (request.url() == "/1/config") {
request.accept();
if (!m_controller->config()->reload(request.json())) {
return request.done(400);
}
request.done(204);
}
}
}
@@ -112,7 +93,7 @@ void xmrig::ApiRouter::getHashrate(rapidjson::Value &reply, rapidjson::Document
rapidjson::Value hashrate(rapidjson::kObjectType);
rapidjson::Value total(rapidjson::kArrayType);
auto &stats = m_controller->statsData();
auto &stats = static_cast<Controller *>(m_base)->statsData();
for (size_t i = 0; i < sizeof(stats.hashrate) / sizeof(stats.hashrate[0]); i++) {
total.PushBack(normalize(stats.hashrate[i]), allocator);
@@ -126,15 +107,14 @@ void xmrig::ApiRouter::getHashrate(rapidjson::Value &reply, rapidjson::Document
void xmrig::ApiRouter::getMiner(rapidjson::Value &reply, rapidjson::Document &doc) const
{
auto &allocator = doc.GetAllocator();
auto &stats = m_controller->statsData();
auto &stats = static_cast<Controller *>(m_base)->statsData();
reply.AddMember("version", APP_VERSION, allocator);
reply.AddMember("kind", APP_KIND, allocator);
reply.AddMember("algo", rapidjson::StringRef(m_controller->config()->algorithm().name()), allocator);
reply.AddMember("mode", rapidjson::StringRef(m_controller->config()->modeName()), allocator);
reply.AddMember("algo", "invalid", allocator);
reply.AddMember("mode", rapidjson::StringRef(m_base->config()->modeName()), allocator);
reply.AddMember("ua", rapidjson::StringRef(Platform::userAgent()), allocator);
reply.AddMember("uptime", stats.uptime(), allocator);
reply.AddMember("donate_level", m_controller->config()->pools().donateLevel(), allocator);
reply.AddMember("donate_level", m_base->config()->pools().donateLevel(), allocator);
if (stats.hashes && stats.donateHashes) {
reply.AddMember("donated", normalize((double) stats.donateHashes / stats.hashes * 100.0), allocator);
@@ -150,7 +130,7 @@ void xmrig::ApiRouter::getMiners(rapidjson::Value &reply, rapidjson::Document &d
using namespace rapidjson;
auto &allocator = doc.GetAllocator();
auto list = m_controller->miners();
auto list = static_cast<Controller *>(m_base)->miners();
Value miners(kArrayType);
@@ -194,7 +174,7 @@ void xmrig::ApiRouter::getMiners(rapidjson::Value &reply, rapidjson::Document &d
void xmrig::ApiRouter::getMinersSummary(rapidjson::Value &reply, rapidjson::Document &doc) const
{
auto &allocator = doc.GetAllocator();
auto &stats = m_controller->statsData();
auto &stats = static_cast<Controller *>(m_base)->statsData();
rapidjson::Value miners(rapidjson::kObjectType);
@@ -202,7 +182,7 @@ void xmrig::ApiRouter::getMinersSummary(rapidjson::Value &reply, rapidjson::Docu
miners.AddMember("max", stats.maxMiners, allocator);
reply.AddMember("miners", miners, allocator);
reply.AddMember("workers", static_cast<uint64_t>(m_controller->workers().size()), allocator);
reply.AddMember("workers", static_cast<uint64_t>(static_cast<Controller *>(m_base)->workers().size()), allocator);
rapidjson::Value upstreams(rapidjson::kObjectType);
@@ -249,7 +229,7 @@ void xmrig::ApiRouter::getResourcesSummary(rapidjson::Value &reply, rapidjson::D
void xmrig::ApiRouter::getResults(rapidjson::Value &reply, rapidjson::Document &doc) const
{
auto &allocator = doc.GetAllocator();
auto &stats = m_controller->statsData();
auto &stats = static_cast<Controller *>(m_base)->statsData();
rapidjson::Value results(rapidjson::kObjectType);
@@ -278,7 +258,7 @@ void xmrig::ApiRouter::getWorkers(rapidjson::Value &reply, rapidjson::Document &
using namespace rapidjson;
auto &allocator = doc.GetAllocator();
auto &list = m_controller->workers();
auto &list = static_cast<Controller *>(m_base)->workers();
Value workers(kArrayType);
@@ -301,6 +281,6 @@ void xmrig::ApiRouter::getWorkers(rapidjson::Value &reply, rapidjson::Document &
workers.PushBack(array, allocator);
}
reply.AddMember("mode", StringRef(Workers::modeName(m_controller->config()->workersMode())), allocator);
reply.AddMember("mode", StringRef(Workers::modeName(static_cast<Controller *>(m_base)->config()->workersMode())), allocator);
reply.AddMember("workers", workers, allocator);
}

View File

@@ -34,21 +34,15 @@
namespace xmrig {
class Controller;
class HttpReply;
class HttpRequest;
class Base;
class ApiRouter : public xmrig::IApiListener
{
public:
ApiRouter(Controller *controller);
ApiRouter(Base *base);
~ApiRouter() override;
// void get(const xmrig::HttpRequest &req, xmrig::HttpReply &reply) const;
// void exec(const xmrig::HttpRequest &req, xmrig::HttpReply &reply);
protected:
void onRequest(IApiRequest &request) override;
@@ -62,7 +56,7 @@ private:
void getResults(rapidjson::Value &reply, rapidjson::Document &doc) const;
void getWorkers(rapidjson::Value &reply, rapidjson::Document &doc) const;
Controller *m_controller;
Base *m_base;
};

View File

@@ -1,15 +1,23 @@
set(HEADERS_BASE
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/FileLog.h
src/base/io/log/Log.h
src/base/io/Watcher.h
src/base/kernel/Base.h
src/base/kernel/config/BaseConfig.h
src/base/kernel/config/BaseTransform.h
src/base/kernel/Entry.h
src/base/kernel/interfaces/IBaseListener.h
src/base/kernel/interfaces/IClient.h
src/base/kernel/interfaces/IClientListener.h
src/base/kernel/interfaces/IConfig.h
src/base/kernel/interfaces/IConfigListener.h
src/base/kernel/interfaces/IConfigTransform.h
src/base/kernel/interfaces/IConsoleListener.h
src/base/kernel/interfaces/IControllerListener.h
src/base/kernel/interfaces/IDnsListener.h
src/base/kernel/interfaces/ILineListener.h
src/base/kernel/interfaces/ILogBackend.h
@@ -18,11 +26,13 @@ set(HEADERS_BASE
src/base/kernel/interfaces/IStrategyListener.h
src/base/kernel/interfaces/ITimerListener.h
src/base/kernel/interfaces/IWatcherListener.h
src/base/kernel/Platform.h
src/base/kernel/Process.h
src/base/kernel/Signals.h
src/base/net/dns/Dns.h
src/base/net/dns/DnsRecord.h
src/base/net/http/Http.h
src/base/net/stratum/BaseClient.h
src/base/net/stratum/Client.h
src/base/net/stratum/Job.h
src/base/net/stratum/Pool.h
@@ -33,6 +43,7 @@ set(HEADERS_BASE
src/base/net/tools/RecvBuf.h
src/base/net/tools/Storage.h
src/base/tools/Arguments.h
src/base/tools/Baton.h
src/base/tools/Buffer.h
src/base/tools/Chrono.h
src/base/tools/Handle.h
@@ -42,17 +53,24 @@ set(HEADERS_BASE
set(SOURCES_BASE
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/FileLog.cpp
src/base/io/log/Log.cpp
src/base/io/Watcher.cpp
src/base/kernel/Base.cpp
src/base/kernel/config/BaseConfig.cpp
src/base/kernel/config/BaseTransform.cpp
src/base/kernel/Entry.cpp
src/base/kernel/Platform.cpp
src/base/kernel/Process.cpp
src/base/kernel/Signals.cpp
src/base/net/dns/Dns.cpp
src/base/net/dns/DnsRecord.cpp
src/base/net/http/Http.cpp
src/base/net/stratum/BaseClient.cpp
src/base/net/stratum/Client.cpp
src/base/net/stratum/Job.cpp
src/base/net/stratum/Pool.cpp
@@ -67,9 +85,20 @@ set(SOURCES_BASE
if (WIN32)
set(SOURCES_OS src/base/io/Json_win.cpp)
set(SOURCES_OS
src/base/io/json/Json_win.cpp
src/base/kernel/Platform_win.cpp
)
elseif (APPLE)
set(SOURCES_OS
src/base/io/json/Json_unix.cpp
src/base/kernel/Platform_mac.cpp
)
else()
set(SOURCES_OS src/base/io/Json_unix.cpp)
set(SOURCES_OS
src/base/io/json/Json_unix.cpp
src/base/kernel//Platform_unix.cpp
)
endif()
@@ -82,25 +111,30 @@ if (NOT WIN32)
endif()
if (WITH_HTTPD)
if (WITH_HTTP)
set(HEADERS_BASE_HTTP
src/3rdparty/http-parser/http_parser.h
src/base/kernel/interfaces/IHttpListener.h
src/base/kernel/interfaces/IJsonReader.h
src/base/kernel/interfaces/ITcpServerListener.h
src/base/net/http/HttpApiResponse.h
src/base/net/http/HttpClient.h
src/base/net/http/HttpContext.h
src/base/net/http/HttpRequest.h
src/base/net/http/HttpData.h
src/base/net/http/HttpResponse.h
src/base/net/http/HttpServer.h
src/base/net/stratum/DaemonClient.h
src/base/net/tools/TcpServer.h
)
set(SOURCES_BASE_HTTP
src/3rdparty/http-parser/http_parser.c
src/base/net/http/HttpApiResponse.cpp
src/base/net/http/HttpClient.cpp
src/base/net/http/HttpContext.cpp
src/base/net/http/HttpResponse.cpp
src/base/net/http/HttpServer.cpp
src/base/net/stratum/DaemonClient.cpp
src/base/net/tools/TcpServer.cpp
)
@@ -112,5 +146,3 @@ else()
remove_definitions(/DXMRIG_FEATURE_HTTP)
remove_definitions(/DXMRIG_FEATURE_API)
endif()
add_definitions(/DXMRIG_DEPRECATED)

View File

@@ -23,10 +23,17 @@
*/
#include "base/io/Json.h"
#include "base/io/json/Json.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)
{
auto i = obj.FindMember(key);
@@ -49,6 +56,39 @@ const char *xmrig::Json::getString(const rapidjson::Value &obj, const char *key,
}
const rapidjson::Value &xmrig::Json::getArray(const rapidjson::Value &obj, const char *key)
{
auto i = obj.FindMember(key);
if (i != obj.MemberEnd() && i->value.IsArray()) {
return i->value;
}
return kNullValue;
}
const rapidjson::Value &xmrig::Json::getObject(const rapidjson::Value &obj, const char *key)
{
auto i = obj.FindMember(key);
if (i != obj.MemberEnd() && i->value.IsObject()) {
return i->value;
}
return kNullValue;
}
const rapidjson::Value &xmrig::Json::getValue(const rapidjson::Value &obj, const char *key)
{
auto i = obj.FindMember(key);
if (i != obj.MemberEnd()) {
return i->value;
}
return kNullValue;
}
int xmrig::Json::getInt(const rapidjson::Value &obj, const char *key, int defaultValue)
{
auto i = obj.FindMember(key);
@@ -91,3 +131,9 @@ unsigned xmrig::Json::getUint(const rapidjson::Value &obj, const char *key, unsi
return defaultValue;
}
bool xmrig::JsonReader::isEmpty() const
{
return !m_obj.IsObject() || m_obj.ObjectEmpty();
}

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

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

View File

@@ -0,0 +1,213 @@
/* XMRig
* Copyright 2010 Jeff Garzik <jgarzik@pobox.com>
* Copyright 2012-2014 pooler <pooler@litecoinpool.org>
* Copyright 2014 Lucas Jones <https://github.com/lucasjones>
* Copyright 2014-2016 Wolf9466 <https://github.com/OhGodAPet>
* Copyright 2016 Jay D Dee <jayddee246@gmail.com>
* Copyright 2017-2018 XMR-Stak <https://github.com/fireice-uk>, <https://github.com/psychocrypt>
* Copyright 2018-2019 SChernykh <https://github.com/SChernykh>
* Copyright 2016-2019 XMRig <https://github.com/xmrig>, <support@xmrig.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "base/io/json/Json.h"
#include "base/io/json/JsonChain.h"
#include "base/io/log/Log.h"
#include "rapidjson/error/en.h"
namespace xmrig {
static const rapidjson::Value kNullValue;
}
xmrig::JsonChain::JsonChain()
{
}
bool xmrig::JsonChain::add(rapidjson::Document &&doc)
{
if (doc.HasParseError() || !doc.IsObject() || doc.ObjectEmpty()) {
return false;
}
m_chain.push_back(std::move(doc));
return true;
}
bool xmrig::JsonChain::addFile(const char *fileName)
{
using namespace rapidjson;
Document doc;
if (Json::get(fileName, doc)) {
m_fileName = fileName;
return add(std::move(doc));
}
if (doc.HasParseError()) {
LOG_ERR("%s<offset:%zu>: \"%s\"", fileName, doc.GetErrorOffset(), GetParseError_En(doc.GetParseError()));
}
else {
LOG_ERR("unable to open \"%s\".", fileName);
}
return false;
}
bool xmrig::JsonChain::addRaw(const char *json)
{
using namespace rapidjson;
Document doc;
doc.Parse<kParseCommentsFlag | kParseTrailingCommasFlag>(json);
return add(std::move(doc));
}
void xmrig::JsonChain::dump(const char *fileName)
{
rapidjson::Document doc(rapidjson::kArrayType);
for (rapidjson::Document &value : m_chain) {
doc.PushBack(value, doc.GetAllocator());
}
Json::save(fileName, doc);
}
bool xmrig::JsonChain::getBool(const char *key, bool defaultValue) const
{
for (auto it = m_chain.rbegin(); it != m_chain.rend(); ++it) {
auto i = it->FindMember(key);
if (i != it->MemberEnd() && i->value.IsBool()) {
return i->value.GetBool();
}
}
return defaultValue;
}
const char *xmrig::JsonChain::getString(const char *key, const char *defaultValue) const
{
for (auto it = m_chain.rbegin(); it != m_chain.rend(); ++it) {
auto i = it->FindMember(key);
if (i != it->MemberEnd() && i->value.IsString()) {
return i->value.GetString();
}
}
return defaultValue;
}
const rapidjson::Value &xmrig::JsonChain::getArray(const char *key) const
{
for (auto it = m_chain.rbegin(); it != m_chain.rend(); ++it) {
auto i = it->FindMember(key);
if (i != it->MemberEnd() && i->value.IsArray()) {
return i->value;
}
}
return kNullValue;
}
const rapidjson::Value &xmrig::JsonChain::getObject(const char *key) const
{
for (auto it = m_chain.rbegin(); it != m_chain.rend(); ++it) {
auto i = it->FindMember(key);
if (i != it->MemberEnd() && i->value.IsObject()) {
return i->value;
}
}
return kNullValue;
}
const rapidjson::Value &xmrig::JsonChain::getValue(const char *key) const
{
for (auto it = m_chain.rbegin(); it != m_chain.rend(); ++it) {
auto i = it->FindMember(key);
if (i != it->MemberEnd()) {
return i->value;
}
}
return kNullValue;
}
int xmrig::JsonChain::getInt(const char *key, int defaultValue) const
{
for (auto it = m_chain.rbegin(); it != m_chain.rend(); ++it) {
auto i = it->FindMember(key);
if (i != it->MemberEnd() && i->value.IsInt()) {
return i->value.GetInt();
}
}
return defaultValue;
}
int64_t xmrig::JsonChain::getInt64(const char *key, int64_t defaultValue) const
{
for (auto it = m_chain.rbegin(); it != m_chain.rend(); ++it) {
auto i = it->FindMember(key);
if (i != it->MemberEnd() && i->value.IsInt64()) {
return i->value.GetInt64();
}
}
return defaultValue;
}
uint64_t xmrig::JsonChain::getUint64(const char *key, uint64_t defaultValue) const
{
for (auto it = m_chain.rbegin(); it != m_chain.rend(); ++it) {
auto i = it->FindMember(key);
if (i != it->MemberEnd() && i->value.IsUint64()) {
return i->value.GetUint64();
}
}
return defaultValue;
}
unsigned xmrig::JsonChain::getUint(const char *key, unsigned defaultValue) const
{
for (auto it = m_chain.rbegin(); it != m_chain.rend(); ++it) {
auto i = it->FindMember(key);
if (i != it->MemberEnd() && i->value.IsUint()) {
return i->value.GetUint();
}
}
return defaultValue;
}

View File

@@ -0,0 +1,76 @@
/* XMRig
* Copyright 2010 Jeff Garzik <jgarzik@pobox.com>
* Copyright 2012-2014 pooler <pooler@litecoinpool.org>
* Copyright 2014 Lucas Jones <https://github.com/lucasjones>
* Copyright 2014-2016 Wolf9466 <https://github.com/OhGodAPet>
* Copyright 2016 Jay D Dee <jayddee246@gmail.com>
* Copyright 2017-2018 XMR-Stak <https://github.com/fireice-uk>, <https://github.com/psychocrypt>
* Copyright 2018-2019 SChernykh <https://github.com/SChernykh>
* Copyright 2016-2019 XMRig <https://github.com/xmrig>, <support@xmrig.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef XMRIG_JSONCHAIN_H
#define XMRIG_JSONCHAIN_H
#include <vector>
#include "base/kernel/interfaces/IJsonReader.h"
#include "base/tools/String.h"
#include "rapidjson/document.h"
namespace xmrig {
class JsonChain : public IJsonReader
{
public:
JsonChain();
bool add(rapidjson::Document &&doc);
bool addFile(const char *fileName);
bool addRaw(const char *json);
void dump(const char *fileName);
inline const String &fileName() const { return m_fileName; }
inline size_t size() const { return m_chain.size(); }
protected:
inline bool isEmpty() const override { return m_chain.empty(); }
bool getBool(const char *key, bool defaultValue = false) const override;
const char *getString(const char *key, const char *defaultValue = nullptr) const override;
const rapidjson::Value &getArray(const char *key) const override;
const rapidjson::Value &getObject(const char *key) const override;
const rapidjson::Value &getValue(const char *key) const override;
int getInt(const char *key, int defaultValue = 0) const override;
int64_t getInt64(const char *key, int64_t defaultValue = 0) const override;
uint64_t getUint64(const char *key, uint64_t defaultValue = 0) const override;
unsigned getUint(const char *key, unsigned defaultValue = 0) const override;
private:
std::vector<rapidjson::Document> m_chain;
String m_fileName;
};
} /* namespace xmrig */
#endif /* XMRIG_JSONCHAIN_H */

View File

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

View File

@@ -5,7 +5,8 @@
* 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>
* 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
@@ -21,23 +22,24 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef __MM_MALLOC_PORTABLE_H__
#define __MM_MALLOC_PORTABLE_H__
#ifndef XMRIG_JSONREQUEST_H
#define XMRIG_JSONREQUEST_H
#ifdef _WIN32
# ifdef __GNUC__
# include <mm_malloc.h>
# else
# include <malloc.h>
# endif
#else
# if defined(XMRIG_ARM) && !defined(__clang__)
# include "aligned_malloc.h"
# else
# include <mm_malloc.h>
# endif
#endif
#include "rapidjson/fwd.h"
#endif /* __MM_MALLOC_PORTABLE_H__ */
namespace xmrig {
class JsonRequest
{
public:
static void create(rapidjson::Document &doc, int64_t id, const char *method, rapidjson::Value &params);
};
} /* namespace xmrig */
#endif /* XMRIG_JSONREQUEST_H */

View File

@@ -26,7 +26,7 @@
#include <fstream>
#include "base/io/Json.h"
#include "base/io/json/Json.h"
#include "rapidjson/document.h"
#include "rapidjson/istreamwrapper.h"
#include "rapidjson/ostreamwrapper.h"
@@ -56,6 +56,8 @@ bool xmrig::Json::save(const char *fileName, const rapidjson::Document &doc)
rapidjson::OStreamWrapper osw(ofs);
rapidjson::PrettyWriter<rapidjson::OStreamWrapper> writer(osw);
writer.SetFormatOptions(rapidjson::kFormatSingleLineArray);
doc.Accept(writer);
return true;

View File

@@ -35,7 +35,7 @@
#include <fstream>
#include "base/io/Json.h"
#include "base/io/json/Json.h"
#include "rapidjson/document.h"
#include "rapidjson/istreamwrapper.h"
#include "rapidjson/ostreamwrapper.h"
@@ -102,7 +102,7 @@ bool xmrig::Json::save(const char *fileName, const rapidjson::Document &doc)
return false;
}
# elif defined(__GNUC__)
const int fd = _wopen(toUtf16(fileName).c_str(), _O_WRONLY | _O_BINARY | _O_TRUNC);
const int fd = _wopen(toUtf16(fileName).c_str(), _O_WRONLY | _O_BINARY | _O_CREAT | _O_TRUNC);
if (fd == -1) {
return false;
}
@@ -118,6 +118,8 @@ bool xmrig::Json::save(const char *fileName, const rapidjson::Document &doc)
OStreamWrapper osw(ofs);
PrettyWriter<OStreamWrapper> writer(osw);
writer.SetFormatOptions(kFormatSingleLineArray);
doc.Accept(writer);
return true;

View File

@@ -30,6 +30,8 @@
#endif
#include <algorithm>
#include <mutex>
#include <string.h>
#include <string>
#include <time.h>
@@ -39,6 +41,7 @@
#include "base/io/log/Log.h"
#include "base/kernel/interfaces/ILogBackend.h"
#include "base/tools/Chrono.h"
namespace xmrig {
@@ -67,14 +70,11 @@ public:
inline LogPrivate() :
m_buf()
{
uv_mutex_init(&m_mutex);
}
inline ~LogPrivate()
{
uv_mutex_destroy(&m_mutex);
for (ILogBackend *backend : m_backends) {
delete backend;
}
@@ -89,13 +89,14 @@ public:
size_t size = 0;
size_t offset = 0;
lock();
std::lock_guard<std::mutex> lock(m_mutex);
timestamp(level, size, offset);
color(level, size);
const int rc = vsnprintf(m_buf + size, sizeof (m_buf) - offset - 32, fmt, args);
if (rc < 0) {
return unlock();
return;
}
size += std::min(static_cast<size_t>(rc), sizeof (m_buf) - offset - 32);
@@ -117,23 +118,18 @@ public:
fputs(txt.c_str(), stdout);
fflush(stdout);
}
unlock();
}
private:
inline void lock() { uv_mutex_lock(&m_mutex); }
inline void unlock() { uv_mutex_unlock(&m_mutex); }
inline void timestamp(Log::Level level, size_t &size, size_t &offset)
{
if (level == Log::NONE) {
return;
}
time_t now = time(nullptr);
const uint64_t ms = Chrono::currentMSecsSinceEpoch();
time_t now = ms / 1000;
tm stime;
# ifdef _WIN32
@@ -142,13 +138,14 @@ private:
localtime_r(&now, &stime);
# endif
const int rc = snprintf(m_buf, sizeof(m_buf) - 1, "[%d-%02d-%02d %02d:%02d:%02d] ",
const int rc = snprintf(m_buf, sizeof(m_buf) - 1, "[%d-%02d-%02d %02d:%02d:%02d" BLACK_BOLD(".%03d") "] ",
stime.tm_year + 1900,
stime.tm_mon + 1,
stime.tm_mday,
stime.tm_hour,
stime.tm_min,
stime.tm_sec
stime.tm_sec,
static_cast<int>(ms % 1000)
);
if (rc > 0) {
@@ -188,8 +185,8 @@ private:
char m_buf[4096];
std::mutex m_mutex;
std::vector<ILogBackend*> m_backends;
uv_mutex_t m_mutex;
};

View File

@@ -61,43 +61,57 @@ private:
};
#define CSI "\x1B[" // Control Sequence Introducer (ANSI spec name)
#define CLEAR CSI "0m" // all attributes off
#define BRIGHT_BLACK_S CSI "0;90m" // somewhat MD.GRAY
#define BLACK_S CSI "0;30m"
#define BLACK_BOLD_S CSI "1;30m" // another name for GRAY
#define RED_S CSI "0;31m"
#define RED_BOLD_S CSI "1;31m"
#define GREEN_S CSI "0;32m"
#define GREEN_BOLD_S CSI "1;32m"
#define YELLOW_S CSI "0;33m"
#define YELLOW_BOLD_S CSI "1;33m"
#define BLUE_S CSI "0;34m"
#define BLUE_BOLD_S CSI "1;34m"
#define MAGENTA_S CSI "0;35m"
#define MAGENTA_BOLD_S CSI "1;35m"
#define CYAN_S CSI "0;36m"
#define CYAN_BOLD_S CSI "1;36m"
#define WHITE_S CSI "0;37m" // another name for LT.GRAY
#define WHITE_BOLD_S CSI "1;37m" // actually white
#define CSI "\x1B[" // Control Sequence Introducer (ANSI spec name)
#define CLEAR CSI "0m" // all attributes off
#define BRIGHT_BLACK_S CSI "0;90m" // somewhat MD.GRAY
#define BLACK_S CSI "0;30m"
#define BLACK_BOLD_S CSI "1;30m" // another name for GRAY
#define RED_S CSI "0;31m"
#define RED_BOLD_S CSI "1;31m"
#define GREEN_S CSI "0;32m"
#define GREEN_BOLD_S CSI "1;32m"
#define YELLOW_S CSI "0;33m"
#define YELLOW_BOLD_S CSI "1;33m"
#define BLUE_S CSI "0;34m"
#define BLUE_BOLD_S CSI "1;34m"
#define MAGENTA_S CSI "0;35m"
#define MAGENTA_BOLD_S CSI "1;35m"
#define CYAN_S CSI "0;36m"
#define CYAN_BOLD_S CSI "1;36m"
#define WHITE_S CSI "0;37m" // another name for LT.GRAY
#define WHITE_BOLD_S CSI "1;37m" // actually white
#define BLUE_BG_S CSI "44m"
#define BLUE_BG_BOLD_S CSI "44;1m"
#define MAGENTA_BG_S CSI "45m"
#define MAGENTA_BG_BOLD_S CSI "45;1m"
#define CYAN_BG_S CSI "46m"
#define CYAN_BG_BOLD_S CSI "46;1m"
//color wrappings
#define BLACK(x) BLACK_S x CLEAR
#define BLACK_BOLD(x) BLACK_BOLD_S x CLEAR
#define RED(x) RED_S x CLEAR
#define RED_BOLD(x) RED_BOLD_S x CLEAR
#define GREEN(x) GREEN_S x CLEAR
#define GREEN_BOLD(x) GREEN_BOLD_S x CLEAR
#define YELLOW(x) YELLOW_S x CLEAR
#define YELLOW_BOLD(x) YELLOW_BOLD_S x CLEAR
#define BLUE(x) BLUE_S x CLEAR
#define BLUE_BOLD(x) BLUE_BOLD_S x CLEAR
#define MAGENTA(x) MAGENTA_S x CLEAR
#define MAGENTA_BOLD(x) MAGENTA_BOLD_S x CLEAR
#define CYAN(x) CYAN_S x CLEAR
#define CYAN_BOLD(x) CYAN_BOLD_S x CLEAR
#define WHITE(x) WHITE_S x CLEAR
#define WHITE_BOLD(x) WHITE_BOLD_S x CLEAR
#define BLACK(x) BLACK_S x CLEAR
#define BLACK_BOLD(x) BLACK_BOLD_S x CLEAR
#define RED(x) RED_S x CLEAR
#define RED_BOLD(x) RED_BOLD_S x CLEAR
#define GREEN(x) GREEN_S x CLEAR
#define GREEN_BOLD(x) GREEN_BOLD_S x CLEAR
#define YELLOW(x) YELLOW_S x CLEAR
#define YELLOW_BOLD(x) YELLOW_BOLD_S x CLEAR
#define BLUE(x) BLUE_S x CLEAR
#define BLUE_BOLD(x) BLUE_BOLD_S x CLEAR
#define MAGENTA(x) MAGENTA_S x CLEAR
#define MAGENTA_BOLD(x) MAGENTA_BOLD_S x CLEAR
#define CYAN(x) CYAN_S x CLEAR
#define CYAN_BOLD(x) CYAN_BOLD_S x CLEAR
#define WHITE(x) WHITE_S x CLEAR
#define WHITE_BOLD(x) WHITE_BOLD_S x CLEAR
#define BLUE_BG(x) BLUE_BG_S x CLEAR
#define BLUE_BG_BOLD(x) BLUE_BG_BOLD_S x CLEAR
#define MAGENTA_BG(x) MAGENTA_BG_S x CLEAR
#define MAGENTA_BG_BOLD(x) MAGENTA_BG_BOLD_S x CLEAR
#define CYAN_BG(x) CYAN_BG_S x CLEAR
#define CYAN_BG_BOLD(x) CYAN_BG_BOLD_S x CLEAR
#define LOG_EMERG(x, ...) xmrig::Log::print(xmrig::Log::EMERG, x, ##__VA_ARGS__)

328
src/base/kernel/Base.cpp Normal file
View File

@@ -0,0 +1,328 @@
/* 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/Platform.h"
#include "base/kernel/Process.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"
# include "api/interfaces/IApiRequest.h"
#endif
#ifdef XMRIG_FEATURE_EMBEDDED_CONFIG
# include "core/config/Config_default.h"
#endif
namespace xmrig {
static const char *kConfigPathV1 = "/1/config";
static const char *kConfigPathV2 = "/2/config";
} // namespace xmrig
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);
d_ptr->api->addListener(this);
# endif
Platform::init(config()->userAgent());
# ifndef XMRIG_PROXY_PROJECT
Platform::setProcessPriority(config()->cpu().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);
}
#ifdef XMRIG_FEATURE_API
void xmrig::Base::onRequest(IApiRequest &request)
{
if (request.method() == IApiRequest::METHOD_GET) {
if (request.url() == kConfigPathV1 || request.url() == kConfigPathV2) {
if (request.isRestricted()) {
return request.done(403);
}
request.accept();
config()->getJSON(request.doc());
}
}
else if (request.method() == IApiRequest::METHOD_PUT || request.method() == IApiRequest::METHOD_POST) {
if (request.url() == kConfigPathV1 || request.url() == kConfigPathV2) {
request.accept();
if (!reload(request.json())) {
return request.done(400);
}
request.done(204);
}
}
}
#endif

View File

@@ -22,32 +22,55 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef XMRIG_JSON_H
#define XMRIG_JSON_H
#ifndef XMRIG_BASE_H
#define XMRIG_BASE_H
#include "api/interfaces/IApiListener.h"
#include "base/kernel/interfaces/IConfigListener.h"
#include "base/kernel/interfaces/IWatcherListener.h"
#include "rapidjson/fwd.h"
namespace xmrig {
class Json
class Api;
class BasePrivate;
class Config;
class IBaseListener;
class Process;
class Base : public IWatcherListener, public IApiListener
{
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 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);
Base(Process *process);
~Base() override;
static bool get(const char *fileName, rapidjson::Document &doc);
static bool save(const char *fileName, const rapidjson::Document &doc);
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;
# ifdef XMRIG_FEATURE_API
void onRequest(IApiRequest &request) override;
# endif
private:
BasePrivate *d_ptr;
};
} /* namespace xmrig */
#endif /* XMRIG_JSON_H */
#endif /* XMRIG_BASE_H */

View File

@@ -31,6 +31,9 @@
# include <openssl/opensslv.h>
#endif
#ifdef XMRIG_FEATURE_HWLOC
# include <hwloc.h>
#endif
#include "base/kernel/Entry.h"
#include "base/kernel/Process.h"
@@ -38,6 +41,9 @@
#include "version.h"
namespace xmrig {
static int showVersion()
{
printf(APP_NAME " " APP_VERSION "\n built on " __DATE__
@@ -75,10 +81,50 @@ static int showVersion()
}
# endif
# if defined(XMRIG_FEATURE_HWLOC)
# if defined(HWLOC_VERSION)
printf("hwloc/%s\n", HWLOC_VERSION);
# elif HWLOC_API_VERSION >= 0x20000
printf("hwloc/2\n");
# else
printf("hwloc/1\n");
# endif
# endif
return 0;
}
#ifdef XMRIG_FEATURE_HWLOC
static int exportTopology(const Process &process)
{
const String path = process.location(Process::ExeLocation, "topology.xml");
hwloc_topology_t topology;
hwloc_topology_init(&topology);
hwloc_topology_load(topology);
# if HWLOC_API_VERSION >= 0x20000
if (hwloc_topology_export_xml(topology, path, 0) == -1) {
# else
if (hwloc_topology_export_xml(topology, path) == -1) {
# endif
printf("failed to export hwloc topology.\n");
}
else {
printf("hwloc topology successfully exported to \"%s\"\n", path.data());
}
hwloc_topology_destroy(topology);
return 0;
}
#endif
} // namespace xmrig
xmrig::Entry::Id xmrig::Entry::get(const Process &process)
{
const Arguments &args = process.arguments();
@@ -90,11 +136,17 @@ xmrig::Entry::Id xmrig::Entry::get(const Process &process)
return Version;
}
# ifdef XMRIG_FEATURE_HWLOC
if (args.hasArg("--export-topology")) {
return Topo;
}
# endif
return Default;
}
int xmrig::Entry::exec(const Process &, Id id)
int xmrig::Entry::exec(const Process &process, Id id)
{
switch (id) {
case Usage:
@@ -104,6 +156,11 @@ int xmrig::Entry::exec(const Process &, Id id)
case Version:
return showVersion();
# ifdef XMRIG_FEATURE_HWLOC
case Topo:
return exportTopology(process);
# endif
default:
break;
}

View File

@@ -38,7 +38,8 @@ public:
enum Id {
Default,
Usage,
Version
Version,
Topo
};
static Id get(const Process &process);

View File

@@ -35,6 +35,15 @@
class Platform
{
public:
static inline bool trySetThreadAffinity(int64_t cpu_id)
{
if (cpu_id < 0) {
return false;
}
return setThreadAffinity(static_cast<uint64_t>(cpu_id));
}
static bool setThreadAffinity(uint64_t cpu_id);
static uint32_t setTimerResolution(uint32_t resolution);
static void init(const char *userAgent);

View File

@@ -0,0 +1,168 @@
/* 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_FEATURE_HWLOC
# include "backend/cpu/Cpu.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()
{
}
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);
# endif
std::string libs;
# if defined(XMRIG_FEATURE_TLS) && defined(OPENSSL_VERSION_TEXT)
{
constexpr const char *v = OPENSSL_VERSION_TEXT + 8;
snprintf(buf, sizeof buf, "OpenSSL/%.*s ", static_cast<int>(strchr(v, ' ') - v), v);
libs += buf;
}
# endif
# if defined(XMRIG_FEATURE_HWLOC)
libs += Cpu::info()->backend();
# endif
Log::print(GREEN_BOLD(" * ") WHITE_BOLD("%-13slibuv/%s %s"), "LIBS", uv_version_string(), libs.c_str());
}
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");
}
m_http.load(reader.getObject("http"));
m_pools.load(reader);
return m_pools.active() > 0;
}
bool xmrig::BaseConfig::save()
{
if (m_fileName.isNull()) {
return false;
}
rapidjson::Document doc;
getJSON(doc);
if (Json::save(m_fileName, doc)) {
LOG_NOTICE("configuration saved to: \"%s\"", m_fileName.data());
return true;
}
return false;
}

View File

@@ -22,81 +22,72 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef XMRIG_COMMONCONFIG_H
#define XMRIG_COMMONCONFIG_H
#ifndef XMRIG_BASECONFIG_H
#define XMRIG_BASECONFIG_H
#include "base/kernel/interfaces/IConfig.h"
#include "base/net/http/Http.h"
#include "base/net/stratum/Pools.h"
#include "common/interfaces/IConfig.h"
#include "common/xmrig.h"
struct option;
namespace xmrig {
class CommonConfig : public IConfig
class IJsonReader;
class BaseConfig : public IConfig
{
public:
CommonConfig();
BaseConfig();
inline bool isAutoSave() const { return m_autoSave; }
inline bool isBackground() const { return m_background; }
inline bool isDryRun() const { return m_dryRun; }
inline bool isSyslog() const { return m_syslog; }
inline const String &apiId() const { return m_apiId; }
inline const String &apiWorkerId() const { return m_apiWorkerId; }
inline const char *logFile() const { return m_logFile.data(); }
inline const char *userAgent() const { return m_userAgent.data(); }
inline const Http &http() const { return m_http; }
inline const Pools &pools() const { return m_pools; }
inline int printTime() const { return m_printTime; }
inline const String &apiId() const { return m_apiId; }
inline const String &apiWorkerId() const { return m_apiWorkerId; }
inline uint32_t printTime() const { return m_printTime; }
inline bool isWatch() const override { return m_watch && !m_fileName.isNull(); }
inline const Algorithm &algorithm() const override { return m_algorithm; }
inline const String &fileName() const override { return m_fileName; }
inline bool isWatch() const override { return m_watch && !m_fileName.isNull(); }
inline const String &fileName() const override { return m_fileName; }
inline void setFileName(const char *fileName) override { m_fileName = fileName; }
bool read(const IJsonReader &reader, const char *fileName) override;
bool save() override;
void printVersions();
protected:
enum State {
NoneState,
ReadyState,
ErrorState
};
bool finalize() override;
bool parseBoolean(int key, bool enable) override;
bool parseString(int key, const char *arg) override;
bool parseUint64(int key, uint64_t arg) override;
void parseJSON(const rapidjson::Value &json) override;
void setFileName(const char *fileName) override;
Algorithm m_algorithm;
bool m_adjusted;
bool m_autoSave;
bool m_background;
bool m_dryRun;
bool m_syslog;
bool m_upgrade;
bool m_watch;
bool m_autoSave = true;
bool m_background = false;
bool m_dryRun = false;
bool m_syslog = false;
bool m_upgrade = false;
bool m_watch = true;
Http m_http;
int m_printTime;
Pools m_pools;
State m_state;
String m_apiId;
String m_apiWorkerId;
String m_fileName;
String m_logFile;
String m_userAgent;
uint32_t m_printTime;
private:
bool parseInt(int key, int arg);
inline void setPrintTime(uint32_t printTime) { if (printTime <= 3600) { m_printTime = printTime; } }
};
} /* namespace xmrig */
} // namespace xmrig
#endif /* XMRIG_COMMONCONFIG_H */
#endif /* XMRIG_BASECONFIG_H */

View File

@@ -0,0 +1,269 @@
/* 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 *kAlgo = "algo";
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]);
}
transform.finalize(doc);
chain.add(std::move(doc));
}
void xmrig::BaseTransform::finalize(rapidjson::Document &doc)
{
using namespace rapidjson;
auto &allocator = doc.GetAllocator();
if (m_algorithm.isValid() && doc.HasMember(kPools)) {
auto &pools = doc[kPools];
for (Value &pool : pools.GetArray()) {
if (!pool.HasMember(kAlgo)) {
pool.AddMember(StringRef(kAlgo), m_algorithm.toJSON(), allocator);
}
}
}
}
void xmrig::BaseTransform::transform(rapidjson::Document &doc, int key, const char *arg)
{
switch (key) {
case IConfig::AlgorithmKey: /* --algo */
if (!doc.HasMember(kPools)) {
m_algorithm = arg;
}
else {
return add(doc, kPools, kAlgo, arg);
}
break;
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::LogFileKey: /* --log-file */
return set(doc, "log-file", arg);
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 */
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 */
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);
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);
case IConfig::HttpPort: /* --http-port */
return set(doc, kHttp, "port", arg);
case IConfig::PrintTimeKey: /* --print-time */
return set(doc, "print-time", arg);
case IConfig::DaemonPollKey: /* --daemon-poll-interval */
return add(doc, kPools, "daemon-poll-interval", arg);
default:
break;
}
}

View File

@@ -0,0 +1,127 @@
/* 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 finalize(rapidjson::Document &doc) override;
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());
}
}
protected:
Algorithm m_algorithm;
private:
void transformBoolean(rapidjson::Document &doc, int key, bool enable);
void transformUint64(rapidjson::Document &doc, int key, uint64_t arg);
};
template<>
inline void BaseTransform::set(rapidjson::Document &doc, rapidjson::Value &obj, const char *key, const char *value)
{
auto &allocator = doc.GetAllocator();
if (obj.HasMember(key)) {
obj[key] = rapidjson::Value(value, allocator);
}
else {
obj.AddMember(rapidjson::StringRef(key), rapidjson::Value(value, allocator), allocator);
}
}
} // namespace xmrig
#endif /* XMRIG_BASETRANSFORM_H */

View File

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

View File

@@ -0,0 +1,85 @@
/* XMRig
* Copyright 2010 Jeff Garzik <jgarzik@pobox.com>
* Copyright 2012-2014 pooler <pooler@litecoinpool.org>
* Copyright 2014 Lucas Jones <https://github.com/lucasjones>
* Copyright 2014-2016 Wolf9466 <https://github.com/OhGodAPet>
* Copyright 2016 Jay D Dee <jayddee246@gmail.com>
* Copyright 2017-2018 XMR-Stak <https://github.com/fireice-uk>, <https://github.com/psychocrypt>
* Copyright 2018-2019 SChernykh <https://github.com/SChernykh>
* Copyright 2016-2019 XMRig <https://github.com/xmrig>, <support@xmrig.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef XMRIG_ICLIENT_H
#define XMRIG_ICLIENT_H
#include <stdint.h>
namespace xmrig {
class Algorithm;
class Job;
class JobResult;
class Pool;
class String;
class IClient
{
public:
enum Extension {
EXT_ALGO,
EXT_NICEHASH,
EXT_CONNECT,
EXT_TLS,
EXT_KEEPALIVE,
EXT_MAX
};
virtual ~IClient() = default;
virtual bool disconnect() = 0;
virtual bool hasExtension(Extension extension) const noexcept = 0;
virtual bool isEnabled() const = 0;
virtual bool isTLS() const = 0;
virtual const char *mode() const = 0;
virtual const char *tlsFingerprint() const = 0;
virtual const char *tlsVersion() const = 0;
virtual const Job &job() const = 0;
virtual const Pool &pool() const = 0;
virtual const String &ip() const = 0;
virtual int id() const = 0;
virtual int64_t submit(const JobResult &result) = 0;
virtual void connect() = 0;
virtual void connect(const Pool &pool) = 0;
virtual void deleteLater() = 0;
virtual void setAlgo(const Algorithm &algo) = 0;
virtual void setEnabled(bool enabled) = 0;
virtual void setPool(const Pool &pool) = 0;
virtual void setQuiet(bool quiet) = 0;
virtual void setRetries(int retries) = 0;
virtual void setRetryPause(uint64_t ms) = 0;
virtual void tick(uint64_t now) = 0;
};
} /* namespace xmrig */
#endif // XMRIG_ICLIENT_H

View File

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

View File

@@ -26,13 +26,14 @@
#define XMRIG_ICONFIG_H
#include "common/crypto/Algorithm.h"
#include "crypto/common/Algorithm.h"
#include "rapidjson/fwd.h"
namespace xmrig {
class IJsonReader;
class String;
@@ -64,20 +65,12 @@ public:
UserAgentKey = 1008,
UserKey = 'u',
UserpassKey = 'O',
VariantKey = 1010,
VerboseKey = 1100,
WatchKey = 1105,
TlsKey = 1013,
FingerprintKey = 1014,
AutoSaveKey = 1016,
ProxyDonateKey = 1017,
# ifdef XMRIG_DEPRECATED
ApiPort = 4000,
ApiAccessTokenKey = 4001,
ApiIPv6Key = 4003,
ApiRestrictedKey = 4004,
# endif
DaemonKey = 1018,
DaemonPollKey = 1019,
// xmrig common
CPUPriorityKey = 1021,
@@ -89,11 +82,10 @@ public:
CPUAffinityKey = 1020,
DryRunKey = 5000,
HugePagesKey = 1009,
MaxCPUUsageKey = 1004,
SafeKey = 1005,
ThreadsKey = 't',
HardwareAESKey = 1011,
AssemblyKey = 1015,
RandomXInitKey = 1022,
RandomXNumaKey = 1023,
// xmrig amd
OclPlatformKey = 1400,
@@ -111,7 +103,6 @@ public:
// xmrig-proxy
AccessLogFileKey = 'A',
BindKey = 'b',
CoinKey = 1104,
CustomDiffKey = 1102,
DebugKey = 1101,
ModeKey = 'm',
@@ -141,17 +132,12 @@ public:
virtual ~IConfig() = default;
virtual bool finalize() = 0;
virtual bool isWatch() const = 0;
virtual bool parseBoolean(int key, bool enable) = 0;
virtual bool parseString(int key, const char *arg) = 0;
virtual bool parseUint64(int key, uint64_t arg) = 0;
virtual bool save() = 0;
virtual const Algorithm &algorithm() const = 0;
virtual const String &fileName() const = 0;
virtual void getJSON(rapidjson::Document &doc) const = 0;
virtual void parseJSON(const rapidjson::Value &json) = 0;
virtual void setFileName(const char *fileName) = 0;
virtual bool isWatch() const = 0;
virtual bool read(const IJsonReader &reader, const char *fileName) = 0;
virtual bool save() = 0;
virtual const String &fileName() const = 0;
virtual void getJSON(rapidjson::Document &doc) const = 0;
virtual void setFileName(const char *fileName) = 0;
};

View File

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

View File

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

View File

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

View File

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

View File

@@ -26,13 +26,14 @@
#define XMRIG_ISTRATEGYLISTENER_H
#include <stdint.h>
#include "rapidjson/fwd.h"
namespace xmrig {
class Client;
class Algorithm;
class IClient;
class IStrategy;
class Job;
class SubmitResult;
@@ -43,10 +44,12 @@ class IStrategyListener
public:
virtual ~IStrategyListener() = default;
virtual void onActive(IStrategy *strategy, Client *client) = 0;
virtual void onJob(IStrategy *strategy, Client *client, const Job &job) = 0;
virtual void onPause(IStrategy *strategy) = 0;
virtual void onResultAccepted(IStrategy *strategy, Client *client, const SubmitResult &result, const char *error) = 0;
virtual void onActive(IStrategy *strategy, IClient *client) = 0;
virtual void onJob(IStrategy *strategy, IClient *client, const Job &job) = 0;
virtual void onLogin(IStrategy *strategy, IClient *client, rapidjson::Document &doc, rapidjson::Value &params) = 0;
virtual void onPause(IStrategy *strategy) = 0;
virtual void onResultAccepted(IStrategy *strategy, IClient *client, const SubmitResult &result, const char *error) = 0;
virtual void onVerifyAlgorithm(IStrategy *strategy, const IClient *client, const Algorithm &algorithm, bool *ok) = 0;
};

View File

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

View File

@@ -47,8 +47,9 @@ public:
Dns(IDnsListener *listener);
~Dns();
inline bool isEmpty() const { return m_ipv4.empty() && m_ipv6.empty(); }
inline int status() const { return m_status; }
inline bool isEmpty() const { return m_ipv4.empty() && m_ipv6.empty(); }
inline const String &host() const { return m_host; }
inline int status() const { return m_status; }
bool resolve(const String &host);
const char *error() const;

View File

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

View File

@@ -80,6 +80,8 @@ void xmrig::HttpApiResponse::end()
StringBuffer buffer(nullptr, 4096);
PrettyWriter<StringBuffer> writer(buffer);
writer.SetMaxDecimalPlaces(10);
writer.SetFormatOptions(kFormatSingleLineArray);
m_doc.Accept(writer);
HttpResponse::end(buffer.GetString(), buffer.GetSize());

View File

@@ -0,0 +1,224 @@
/* XMRig
* Copyright 2010 Jeff Garzik <jgarzik@pobox.com>
* Copyright 2012-2014 pooler <pooler@litecoinpool.org>
* Copyright 2014 Lucas Jones <https://github.com/lucasjones>
* Copyright 2014-2016 Wolf9466 <https://github.com/OhGodAPet>
* Copyright 2016 Jay D Dee <jayddee246@gmail.com>
* Copyright 2017-2018 XMR-Stak <https://github.com/fireice-uk>, <https://github.com/psychocrypt>
* Copyright 2014-2019 heapwolf <https://github.com/heapwolf>
* Copyright 2018-2019 SChernykh <https://github.com/SChernykh>
* Copyright 2016-2019 XMRig <https://github.com/xmrig>, <support@xmrig.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <sstream>
#include "3rdparty/http-parser/http_parser.h"
#include "base/io/log/Log.h"
#include "base/kernel/Platform.h"
#include "base/net/dns/Dns.h"
#include "base/net/http/HttpClient.h"
#include "base/tools/Baton.h"
namespace xmrig {
static const char *kCRLF = "\r\n";
class ClientWriteBaton : public Baton<uv_write_t>
{
public:
inline ClientWriteBaton(const std::string &header, std::string &&body) :
m_body(std::move(body)),
m_header(header)
{
bufs[0].len = m_header.size();
bufs[0].base = const_cast<char *>(m_header.c_str());
if (!m_body.empty()) {
bufs[1].len = m_body.size();
bufs[1].base = const_cast<char *>(m_body.c_str());
}
else {
bufs[1].base = nullptr;
bufs[1].len = 0;
}
}
inline size_t count() const { return bufs[1].base == nullptr ? 1 : 2; }
inline size_t size() const { return bufs[0].len + bufs[1].len; }
inline static void onWrite(uv_write_t *req, int) { delete reinterpret_cast<ClientWriteBaton *>(req->data); }
uv_buf_t bufs[2];
private:
std::string m_body;
std::string m_header;
};
} // namespace xmrig
xmrig::HttpClient::HttpClient(int method, const String &url, IHttpListener *listener, const char *data, size_t size) :
HttpContext(HTTP_RESPONSE, listener),
m_quiet(false),
m_port(0)
{
this->method = method;
this->url = url;
if (data) {
body = size ? std::string(data, size) : data;
}
m_dns = new Dns(this);
}
xmrig::HttpClient::~HttpClient()
{
delete m_dns;
}
bool xmrig::HttpClient::connect(const String &host, uint16_t port)
{
m_port = port;
return m_dns->resolve(host);
}
const xmrig::String &xmrig::HttpClient::host() const
{
return m_dns->host();
}
void xmrig::HttpClient::onResolved(const Dns &dns, int status)
{
this->status = status;
if (status < 0 && dns.isEmpty()) {
if (!m_quiet) {
LOG_ERR("[%s:%d] DNS error: \"%s\"", dns.host().data(), m_port, uv_strerror(status));
}
return;
}
sockaddr *addr = dns.get().addr(m_port);
uv_connect_t *req = new uv_connect_t;
req->data = this;
uv_tcp_connect(req, m_tcp, addr, onConnect);
}
void xmrig::HttpClient::handshake()
{
headers.insert({ "Host", m_dns->host().data() });
headers.insert({ "Connection", "close" });
headers.insert({ "User-Agent", Platform::userAgent() });
if (body.size()) {
headers.insert({ "Content-Length", std::to_string(body.size()) });
}
std::stringstream ss;
ss << http_method_str(static_cast<http_method>(method)) << " " << url << " HTTP/1.1" << kCRLF;
for (auto &header : headers) {
ss << header.first << ": " << header.second << kCRLF;
}
ss << kCRLF;
headers.clear();
write(ss.str());
}
void xmrig::HttpClient::read(const char *data, size_t size)
{
if (parse(data, size) < size) {
close(UV_EPROTO);
}
}
void xmrig::HttpClient::write(const std::string &header)
{
ClientWriteBaton *baton = new ClientWriteBaton(header, std::move(body));
uv_write(&baton->req, stream(), baton->bufs, baton->count(), ClientWriteBaton::onWrite);
}
void xmrig::HttpClient::onConnect(uv_connect_t *req, int status)
{
HttpClient *client = static_cast<HttpClient *>(req->data);
if (!client) {
delete req;
return;
}
if (status < 0) {
if (!client->m_quiet) {
LOG_ERR("[%s:%d] connect error: \"%s\"", client->m_dns->host().data(), client->m_port, uv_strerror(status));
}
delete req;
client->close(status);
return;
}
uv_read_start(client->stream(),
[](uv_handle_t *, size_t suggested_size, uv_buf_t *buf)
{
buf->base = new char[suggested_size];
# ifdef _WIN32
buf->len = static_cast<unsigned int>(suggested_size);
# else
buf->len = suggested_size;
# endif
},
[](uv_stream_t *tcp, ssize_t nread, const uv_buf_t *buf)
{
HttpClient *client = static_cast<HttpClient*>(tcp->data);
if (nread >= 0) {
client->read(buf->base, static_cast<size_t>(nread));
} else {
if (!client->m_quiet && nread != UV_EOF) {
LOG_ERR("[%s:%d] read error: \"%s\"", client->m_dns->host().data(), client->m_port, uv_strerror(static_cast<int>(nread)));
}
client->close(static_cast<int>(nread));
}
delete [] buf->base;
});
client->handshake();
}

View File

@@ -5,6 +5,7 @@
* Copyright 2014-2016 Wolf9466 <https://github.com/OhGodAPet>
* Copyright 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>
*
@@ -22,50 +23,52 @@
* 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 "rapidjson/fwd.h"
struct option;
#include "base/net/http/HttpContext.h"
#include "base/kernel/interfaces/IDnsListener.h"
namespace xmrig {
class ConfigWatcher;
class IConfigListener;
class IConfig;
class Process;
class String;
class ConfigLoader
class HttpClient : public HttpContext, public IDnsListener
{
public:
static bool loadFromFile(IConfig *config, const char *fileName);
static bool loadFromJSON(IConfig *config, const char *json);
static bool loadFromJSON(IConfig *config, const rapidjson::Value &json);
static bool reload(IConfig *oldConfig, const rapidjson::Value &json);
static bool watch(IConfig *config);
static IConfig *load(Process *process, IConfigListener *listener);
static void release();
HttpClient(int method, const String &url, IHttpListener *listener, const char *data = nullptr, size_t size = 0);
~HttpClient() override;
inline uint16_t port() const { return m_port; }
inline void setQuiet(bool quiet) { m_quiet = quiet; }
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:
static bool getJSON(const char *fileName, rapidjson::Document &doc);
static bool parseArg(IConfig *config, int key, const char *arg);
static void parseJSON(IConfig *config, const struct option *option, const rapidjson::Value &object);
static void onConnect(uv_connect_t *req, int status);
static ConfigWatcher *m_watcher;
static IConfigListener *m_listener;
Dns *m_dns;
uint16_t m_port;
};
} /* namespace xmrig */
} // namespace xmrig
#endif /* XMRIG_CONFIGLOADER_H */
#endif // XMRIG_HTTPCLIENT_H

View File

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

View File

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

View File

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

View File

@@ -30,20 +30,68 @@
#include "3rdparty/http-parser/http_parser.h"
#include "base/io/log/Log.h"
#include "base/net/http/HttpContext.h"
#include "base/net/http/HttpResponse.h"
#include "base/tools/Baton.h"
namespace xmrig {
static const char *kCRLF = "\r\n";
static const char *kCRLF = "\r\n";
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
xmrig::HttpResponse::HttpResponse(uint64_t id) :
xmrig::HttpResponse::HttpResponse(uint64_t id, int statusCode) :
m_id(id),
m_statusCode(HTTP_STATUS_OK)
m_statusCode(statusCode)
{
}
@@ -80,29 +128,26 @@ void xmrig::HttpResponse::end(const char *data, size_t size)
}
ss << kCRLF;
const std::string header = ss.str();
uv_buf_t bufs[2];
bufs[0].base = const_cast<char *>(header.c_str());
HttpContext *ctx = HttpContext::get(m_id);
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();
# ifndef APP_DEBUG
if (statusCode() >= 400)
# endif
{
const bool err = statusCode() >= 400;
if (data) {
bufs[1].base = const_cast<char *>(data);
# ifdef _WIN32
bufs[1].len = static_cast<unsigned int>(size);
# else
bufs[0].len = size;
# endif
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\""),
ctx->ip().c_str(),
http_method_str(static_cast<http_method>(ctx->method)),
ctx->url.c_str(),
err ? 31 : 32,
statusCode(),
baton->size(),
ctx->headers.count(kUserAgent) ? ctx->headers.at(kUserAgent).c_str() : nullptr
);
}
HttpContext *ctx = HttpContext::get(m_id);
uv_try_write(ctx->stream(), bufs, data ? 2 : 1);
ctx->close();
uv_write(&baton->req, ctx->stream(), baton->bufs, baton->count(), WriteBaton::onWrite);
}

View File

@@ -38,7 +38,7 @@ namespace xmrig {
class HttpResponse
{
public:
HttpResponse(uint64_t id);
HttpResponse(uint64_t id, int statusCode = 200);
inline int statusCode() const { return m_statusCode; }
inline void setHeader(const std::string &key, const std::string &value) { m_headers.insert({ key, value }); }

View File

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

View File

@@ -0,0 +1,208 @@
/* XMRig
* Copyright 2010 Jeff Garzik <jgarzik@pobox.com>
* Copyright 2012-2014 pooler <pooler@litecoinpool.org>
* Copyright 2014 Lucas Jones <https://github.com/lucasjones>
* Copyright 2014-2016 Wolf9466 <https://github.com/OhGodAPet>
* Copyright 2016 Jay D Dee <jayddee246@gmail.com>
* Copyright 2017-2018 XMR-Stak <https://github.com/fireice-uk>, <https://github.com/psychocrypt>
* Copyright 2014-2019 heapwolf <https://github.com/heapwolf>
* Copyright 2018-2019 SChernykh <https://github.com/SChernykh>
* Copyright 2016-2019 XMRig <https://github.com/xmrig>, <support@xmrig.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <assert.h>
#include <openssl/ssl.h>
#include <uv.h>
#include "base/io/log/Log.h"
#include "base/net/http/HttpsClient.h"
#include "base/tools/Buffer.h"
#ifdef _MSC_VER
# define strncasecmp(x,y,z) _strnicmp(x,y,z)
#endif
xmrig::HttpsClient::HttpsClient(int method, const String &url, IHttpListener *listener, const char *data, size_t size, const String &fingerprint) :
HttpClient(method, url, listener, data, size),
m_ready(false),
m_buf(),
m_ssl(nullptr),
m_fp(fingerprint)
{
m_ctx = SSL_CTX_new(SSLv23_method());
assert(m_ctx != nullptr);
if (!m_ctx) {
return;
}
m_writeBio = BIO_new(BIO_s_mem());
m_readBio = BIO_new(BIO_s_mem());
SSL_CTX_set_options(m_ctx, SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3);
}
xmrig::HttpsClient::~HttpsClient()
{
if (m_ctx) {
SSL_CTX_free(m_ctx);
}
if (m_ssl) {
SSL_free(m_ssl);
}
}
const char *xmrig::HttpsClient::fingerprint() const
{
return m_ready ? m_fingerprint : nullptr;
}
const char *xmrig::HttpsClient::version() const
{
return m_ready ? SSL_get_version(m_ssl) : nullptr;
}
void xmrig::HttpsClient::handshake()
{
m_ssl = SSL_new(m_ctx);
assert(m_ssl != nullptr);
if (!m_ssl) {
return;
}
SSL_set_connect_state(m_ssl);
SSL_set_bio(m_ssl, m_readBio, m_writeBio);
SSL_set_tlsext_host_name(m_ssl, host().data());
SSL_do_handshake(m_ssl);
flush();
}
void xmrig::HttpsClient::read(const char *data, size_t size)
{
BIO_write(m_readBio, data, size);
if (!SSL_is_init_finished(m_ssl)) {
const int rc = SSL_connect(m_ssl);
if (rc < 0 && SSL_get_error(m_ssl, rc) == SSL_ERROR_WANT_READ) {
flush();
} else if (rc == 1) {
X509 *cert = SSL_get_peer_certificate(m_ssl);
if (!verify(cert)) {
X509_free(cert);
return close(UV_EPROTO);
}
X509_free(cert);
m_ready = true;
HttpClient::handshake();
}
return;
}
int bytes_read = 0;
while ((bytes_read = SSL_read(m_ssl, m_buf, sizeof(m_buf))) > 0) {
HttpClient::read(m_buf, static_cast<size_t>(bytes_read));
}
}
void xmrig::HttpsClient::write(const std::string &header)
{
SSL_write(m_ssl, (header + body).c_str(), header.size() + body.size());
body.clear();
flush();
}
bool xmrig::HttpsClient::verify(X509 *cert)
{
if (cert == nullptr) {
return false;
}
if (!verifyFingerprint(cert)) {
if (!m_quiet) {
LOG_ERR("[%s:%d] Failed to verify server certificate fingerprint", host().data(), port());
if (strlen(m_fingerprint) == 64 && !m_fp.isNull()) {
LOG_ERR("\"%s\" was given", m_fingerprint);
LOG_ERR("\"%s\" was configured", m_fp.data());
}
}
return false;
}
return true;
}
bool xmrig::HttpsClient::verifyFingerprint(X509 *cert)
{
const EVP_MD *digest = EVP_get_digestbyname("sha256");
if (digest == nullptr) {
return false;
}
unsigned char md[EVP_MAX_MD_SIZE];
unsigned int dlen;
if (X509_digest(cert, digest, md, &dlen) != 1) {
return false;
}
Buffer::toHex(md, 32, m_fingerprint);
return m_fp.isNull() || strncasecmp(m_fingerprint, m_fp.data(), 64) == 0;
}
void xmrig::HttpsClient::flush()
{
uv_buf_t buf;
buf.len = BIO_get_mem_data(m_writeBio, &buf.base);
if (buf.len == 0) {
return;
}
bool result = false;
if (uv_is_writable(stream())) {
result = uv_try_write(stream(), &buf, 1) == static_cast<int>(buf.len);
if (!result) {
close(UV_EIO);
}
}
(void) BIO_reset(m_writeBio);
}

View File

@@ -0,0 +1,77 @@
/* XMRig
* Copyright 2010 Jeff Garzik <jgarzik@pobox.com>
* Copyright 2012-2014 pooler <pooler@litecoinpool.org>
* Copyright 2014 Lucas Jones <https://github.com/lucasjones>
* Copyright 2014-2016 Wolf9466 <https://github.com/OhGodAPet>
* Copyright 2016 Jay D Dee <jayddee246@gmail.com>
* Copyright 2017-2018 XMR-Stak <https://github.com/fireice-uk>, <https://github.com/psychocrypt>
* Copyright 2014-2019 heapwolf <https://github.com/heapwolf>
* Copyright 2018-2019 SChernykh <https://github.com/SChernykh>
* Copyright 2016-2019 XMRig <https://github.com/xmrig>, <support@xmrig.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef XMRIG_HTTPSCLIENT_H
#define XMRIG_HTTPSCLIENT_H
typedef struct bio_st BIO;
typedef struct ssl_ctx_st SSL_CTX;
typedef struct ssl_st SSL;
typedef struct x509_st X509;
#include "base/net/http/HttpClient.h"
#include "base/tools/String.h"
namespace xmrig {
class HttpsClient : public HttpClient
{
public:
HttpsClient(int method, const String &url, IHttpListener *listener, const char *data, size_t size, const String &fingerprint);
~HttpsClient() override;
const char *fingerprint() const;
const char *version() const;
protected:
void handshake() override;
void read(const char *data, size_t size) override;
void write(const std::string &header) override;
private:
bool verify(X509 *cert);
bool verifyFingerprint(X509 *cert);
void flush();
BIO *m_readBio;
BIO *m_writeBio;
bool m_ready;
char m_buf[1024 * 2];
char m_fingerprint[32 * 2 + 8];
SSL *m_ssl;
SSL_CTX *m_ctx;
String m_fp;
};
} // namespace xmrig
#endif // XMRIG_HTTPSCLIENT_H

View File

@@ -23,41 +23,40 @@
*/
#include "base/io/log/Log.h"
#include "base/io/Watcher.h"
#include "base/kernel/interfaces/IConfigListener.h"
#include "common/config/ConfigLoader.h"
#include "common/config/ConfigWatcher.h"
#include "core/config/Config.h"
#include "base/kernel/interfaces/IClientListener.h"
#include "base/net/stratum/BaseClient.h"
#include "base/net/stratum/SubmitResult.h"
xmrig::ConfigWatcher::ConfigWatcher(const String &path, IConfigListener *listener) :
m_listener(listener)
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)
{
m_watcher = new Watcher(path, this);
}
xmrig::ConfigWatcher::~ConfigWatcher()
bool xmrig::BaseClient::handleSubmitResponse(int64_t id, const char *error)
{
delete m_watcher;
}
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);
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;
return true;
}
m_listener->onNewConfig(config);
return false;
}

View File

@@ -0,0 +1,96 @@
/* XMRig
* Copyright 2010 Jeff Garzik <jgarzik@pobox.com>
* Copyright 2012-2014 pooler <pooler@litecoinpool.org>
* Copyright 2014 Lucas Jones <https://github.com/lucasjones>
* Copyright 2014-2016 Wolf9466 <https://github.com/OhGodAPet>
* Copyright 2016 Jay D Dee <jayddee246@gmail.com>
* Copyright 2017-2018 XMR-Stak <https://github.com/fireice-uk>, <https://github.com/psychocrypt>
* Copyright 2018-2019 SChernykh <https://github.com/SChernykh>
* Copyright 2016-2019 XMRig <https://github.com/xmrig>, <support@xmrig.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef XMRIG_BASECLIENT_H
#define XMRIG_BASECLIENT_H
#include <map>
#include "base/kernel/interfaces/IClient.h"
#include "base/net/stratum/Job.h"
#include "base/net/stratum/Pool.h"
namespace xmrig {
class IClientListener;
class SubmitResult;
class BaseClient : public IClient
{
public:
BaseClient(int id, IClientListener *listener);
inline bool isEnabled() const override { return m_enabled; }
inline const Job &job() const override { return m_job; }
inline const Pool &pool() const override { return m_pool; }
inline const String &ip() const override { return m_ip; }
inline int id() const override { return m_id; }
inline void setAlgo(const Algorithm &algo) override { m_pool.setAlgo(algo); }
inline void setEnabled(bool enabled) override { m_enabled = enabled; }
inline void setPool(const Pool &pool) override { if (pool.isValid()) { m_pool = pool; } }
inline void setQuiet(bool quiet) override { m_quiet = quiet; }
inline void setRetries(int retries) override { m_retries = retries; }
inline void setRetryPause(uint64_t ms) override { m_retryPause = ms; }
protected:
enum SocketState {
UnconnectedState,
HostLookupState,
ConnectingState,
ConnectedState,
ClosingState
};
inline bool isQuiet() const { return m_quiet || m_failures >= m_retries; }
bool handleSubmitResponse(int64_t id, const char *error = nullptr);
bool m_quiet;
IClientListener *m_listener;
int m_id;
int m_retries;
int64_t m_failures;
Job m_job;
Pool m_pool;
SocketState m_state;
std::map<int64_t, SubmitResult> m_results;
String m_ip;
uint64_t m_retryPause;
static int64_t m_sequence;
private:
bool m_enabled;
};
} /* namespace xmrig */
#endif /* XMRIG_BASECLIENT_H */

View File

@@ -37,6 +37,8 @@
#endif
#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/dns/Dns.h"
@@ -57,7 +59,6 @@
namespace xmrig {
int64_t Client::m_sequence = 1;
Storage<Client> Client::m_storage;
} /* namespace xmrig */
@@ -75,16 +76,8 @@ static const char *states[] = {
xmrig::Client::Client(int id, const char *agent, IClientListener *listener) :
m_enabled(true),
m_ipv6(false),
m_quiet(false),
BaseClient(id, listener),
m_agent(agent),
m_listener(listener),
m_id(id),
m_retries(5),
m_retryPause(5000),
m_failures(0),
m_state(UnconnectedState),
m_tls(nullptr),
m_expire(0),
m_jobs(0),
@@ -105,73 +98,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()
{
m_keepAlive = 0;
@@ -236,17 +162,13 @@ int64_t xmrig::Client::submit(const JobResult &result)
Buffer::toHex(reinterpret_cast<const char*>(&result.nonce), 4, nonce);
nonce[8] = '\0';
Buffer::toHex(result.result, 32, data);
Buffer::toHex(result.result(), 32, data);
data[64] = '\0';
# endif
Document doc(kObjectType);
auto &allocator = doc.GetAllocator();
doc.AddMember("id", m_sequence, allocator);
doc.AddMember("jsonrpc", "2.0", allocator);
doc.AddMember("method", "submit", allocator);
Value params(kObjectType);
params.AddMember("id", StringRef(m_rpcId.data()), allocator);
params.AddMember("job_id", StringRef(result.jobId.data()), allocator);
@@ -257,7 +179,7 @@ int64_t xmrig::Client::submit(const JobResult &result)
params.AddMember("algo", StringRef(result.algorithm.shortName()), allocator);
}
doc.AddMember("params", params, allocator);
JsonRequest::create(doc, m_sequence, "submit", params);
# ifdef XMRIG_PROXY_PROJECT
m_results[m_sequence] = SubmitResult(m_sequence, result.diff, result.actualDiff(), result.id);
@@ -269,6 +191,57 @@ int64_t xmrig::Client::submit(const JobResult &result)
}
void xmrig::Client::connect()
{
# ifdef XMRIG_FEATURE_TLS
if (m_pool.isTLS()) {
m_tls = new Tls(this);
}
# endif
resolve(m_pool.host());
}
void xmrig::Client::connect(const Pool &pool)
{
setPool(pool);
connect();
}
void xmrig::Client::deleteLater()
{
if (!m_listener) {
return;
}
m_listener = nullptr;
if (!disconnect()) {
m_storage.remove(m_key);
}
}
void xmrig::Client::tick(uint64_t now)
{
if (m_state == ConnectedState) {
if (m_expire && now > m_expire) {
LOG_DEBUG_ERR("[%s] timeout", url());
close();
}
else if (m_keepAlive && now > m_keepAlive) {
ping();
}
}
if (m_expire && now > m_expire && m_state == ConnectingState) {
connect();
}
}
void xmrig::Client::onResolved(const Dns &dns, int status)
{
assert(m_listener != nullptr);
@@ -284,14 +257,6 @@ void xmrig::Client::onResolved(const Dns &dns, int status)
return reconnect();
}
if (dns.isEmpty()) {
if (!isQuiet()) {
LOG_ERR("[%s] DNS error: \"No IPv4 (A) or IPv6 (AAAA) records found\"", url());
}
return reconnect();
}
const DnsRecord &record = dns.get();
m_ip = record.ip();
@@ -348,7 +313,7 @@ bool xmrig::Client::parseJob(const rapidjson::Value &params, int *code)
return false;
}
Job job(m_id, has<EXT_NICEHASH>(), m_pool.algorithm(), m_rpcId);
Job job(has<EXT_NICEHASH>(), m_pool.algorithm(), m_rpcId);
if (!job.setId(params["job_id"].GetString())) {
*code = 3;
@@ -365,33 +330,24 @@ bool xmrig::Client::parseJob(const rapidjson::Value &params, int *code)
return false;
}
if (params.HasMember("algo")) {
job.setAlgorithm(params["algo"].GetString());
const char *algo = Json::getString(params, "algo");
if (algo) {
job.setAlgorithm(algo);
}
if (params.HasMember("variant")) {
const rapidjson::Value &variant = params["variant"];
job.setHeight(Json::getUint64(params, "height"));
if (variant.IsInt()) {
job.setVariant(variant.GetInt());
}
else if (variant.IsString()){
job.setVariant(variant.GetString());
}
}
if (params.HasMember("height")) {
const rapidjson::Value &variant = params["height"];
if (variant.IsUint64()) {
job.setHeight(variant.GetUint64());
}
}
if (!verifyAlgorithm(job.algorithm())) {
if (!verifyAlgorithm(job.algorithm(), algo)) {
*code = 6;
return false;
}
close();
if (job.algorithm().family() == Algorithm::RANDOM_X && !job.setSeedHash(Json::getString(params, "seed_hash"))) {
if (!isQuiet()) {
LOG_ERR("[%s] failed to parse field \"seed_hash\" required by RandomX", url(), algo);
}
*code = 7;
return false;
}
@@ -466,30 +422,24 @@ bool xmrig::Client::send(BIO *bio)
}
bool xmrig::Client::verifyAlgorithm(const Algorithm &algorithm) const
bool xmrig::Client::verifyAlgorithm(const Algorithm &algorithm, const char *algo) const
{
# ifdef XMRIG_PROXY_PROJECT
if (m_pool.algorithm().variant() == VARIANT_AUTO || m_id == -1) {
return true;
}
# endif
if (!algorithm.isValid()) {
if (!isQuiet()) {
LOG_ERR("[%s] Unknown/unsupported algorithm \"%s\" detected, reconnect", url(), algo);
}
if (m_pool.isCompatible(algorithm)) {
return true;
}
if (isQuiet()) {
return false;
}
if (algorithm.isValid()) {
LOG_ERR("Incompatible algorithm \"%s\" detected, reconnect", algorithm.name());
}
else {
LOG_ERR("Unknown/unsupported algorithm detected, reconnect");
bool ok = true;
m_listener->onVerifyAlgorithm(this, algorithm, &ok);
if (!ok && !isQuiet()) {
LOG_ERR("[%s] Incompatible/disabled algorithm \"%s\" detected, reconnect", url(), algorithm.shortName());
}
return false;
return ok;
}
@@ -541,7 +491,7 @@ int64_t xmrig::Client::send(const rapidjson::Document &doc)
int64_t xmrig::Client::send(size_t size)
{
LOG_DEBUG("[%s] send (%d bytes): \"%s\"", url(), size, m_sendBuf);
LOG_DEBUG("[%s] send (%d bytes): \"%.*s\"", url(), size, static_cast<int>(size) - 1, m_sendBuf);
# ifdef XMRIG_FEATURE_TLS
if (isTLS()) {
@@ -574,8 +524,6 @@ void xmrig::Client::connect(sockaddr *addr)
{
setState(ConnectingState);
reinterpret_cast<sockaddr_in*>(addr)->sin_port = htons(m_pool.port());
uv_connect_t *req = new uv_connect_t;
req->data = m_storage.ptr(m_key);
@@ -589,7 +537,7 @@ void xmrig::Client::connect(sockaddr *addr)
uv_tcp_keepalive(m_socket, 1, 60);
# endif
uv_tcp_connect(req, m_socket, reinterpret_cast<const sockaddr*>(addr), Client::onConnect);
uv_tcp_connect(req, m_socket, addr, onConnect);
delete addr;
}
@@ -619,35 +567,18 @@ void xmrig::Client::login()
Document doc(kObjectType);
auto &allocator = doc.GetAllocator();
doc.AddMember("id", 1, allocator);
doc.AddMember("jsonrpc", "2.0", allocator);
doc.AddMember("method", "login", allocator);
Value params(kObjectType);
params.AddMember("login", m_pool.user().toJSON(), allocator);
params.AddMember("pass", m_pool.password().toJSON(), allocator);
params.AddMember("agent", StringRef(m_agent), allocator);
params.AddMember("agent", StringRef(m_agent), allocator);
if (!m_pool.rigId().isNull()) {
params.AddMember("rigid", m_pool.rigId().toJSON(), allocator);
}
# ifdef XMRIG_PROXY_PROJECT
if (m_pool.algorithm().variant() != xmrig::VARIANT_AUTO)
# endif
{
Value algo(kArrayType);
for (const auto &a : m_pool.algorithms()) {
algo.PushBack(StringRef(a.shortName()), allocator);
}
params.AddMember("algo", algo, allocator);
}
m_listener->onLogin(this, doc, params);
doc.AddMember("params", params, allocator);
JsonRequest::create(doc, 1, "login", params);
send(doc);
}
@@ -676,7 +607,7 @@ void xmrig::Client::parse(char *line, size_t len)
{
startTimeout();
LOG_DEBUG("[%s] received (%d bytes): \"%s\"", url(), len, line);
LOG_DEBUG("[%s] received (%d bytes): \"%.*s\"", url(), len, static_cast<int>(len), line);
if (len < 32 || line[0] != '{') {
if (!isQuiet()) {
@@ -768,6 +699,9 @@ void xmrig::Client::parseNotification(const char *method, const rapidjson::Value
if (parseJob(params, &code)) {
m_listener->onJobReceived(this, m_job, params);
}
else {
close();
}
return;
}
@@ -781,17 +715,11 @@ void xmrig::Client::parseResponse(int64_t id, const rapidjson::Value &result, co
if (error.IsObject()) {
const char *message = error["message"].GetString();
auto it = m_results.find(id);
if (it != m_results.end()) {
it->second.done();
m_listener->onResultAccepted(this, it->second, message);
m_results.erase(it);
}
else if (!isQuiet()) {
LOG_ERR("[%s] error: \"%s\", code: %d", url(), message, error["code"].GetInt());
if (!handleSubmitResponse(id, message) && !isQuiet()) {
LOG_ERR("[%s] error: " RED_BOLD("\"%s\"") RED_S ", code: %d", url(), message, error["code"].GetInt());
}
if (isCriticalError(message)) {
if (m_id == 1 || isCriticalError(message)) {
close();
}
@@ -819,12 +747,7 @@ void xmrig::Client::parseResponse(int64_t id, const rapidjson::Value &result, co
return;
}
auto it = m_results.find(id);
if (it != m_results.end()) {
it->second.done();
m_listener->onResultAccepted(this, it->second, nullptr);
m_results.erase(it);
}
handleSubmitResponse(id);
}
@@ -970,7 +893,7 @@ void xmrig::Client::onConnect(uv_connect_t *req, int status)
client->m_stream->data = req->data;
client->setState(ConnectedState);
uv_read_start(client->m_stream, Client::onAllocBuffer, Client::onRead);
uv_read_start(client->m_stream, onAllocBuffer, onRead);
delete req;
client->handshake();

View File

@@ -34,13 +34,13 @@
#include "base/kernel/interfaces/IDnsListener.h"
#include "base/kernel/interfaces/ILineListener.h"
#include "base/net/stratum/BaseClient.h"
#include "base/net/stratum/Job.h"
#include "base/net/stratum/Pool.h"
#include "base/net/stratum/SubmitResult.h"
#include "base/net/tools/RecvBuf.h"
#include "base/net/tools/Storage.h"
#include "common/crypto/Algorithm.h"
#include "crypto/common/Algorithm.h"
typedef struct bio_st BIO;
@@ -53,26 +53,9 @@ class IClientListener;
class JobResult;
class Client : public IDnsListener, public ILineListener
class Client : public BaseClient, public IDnsListener, public ILineListener
{
public:
enum SocketState {
UnconnectedState,
HostLookupState,
ConnectingState,
ConnectedState,
ClosingState
};
enum Extension {
EXT_ALGO,
EXT_NICEHASH,
EXT_CONNECT,
EXT_TLS,
EXT_KEEPALIVE,
EXT_MAX
};
constexpr static int kResponseTimeout = 20 * 1000;
# ifdef XMRIG_FEATURE_TLS
@@ -84,39 +67,23 @@ public:
Client(int id, const char *agent, IClientListener *listener);
~Client() override;
bool disconnect();
bool isTLS() const;
const char *tlsFingerprint() const;
const char *tlsVersion() const;
int64_t submit(const JobResult &result);
void connect();
void connect(const Pool &pool);
void deleteLater();
void setPool(const Pool &pool);
void tick(uint64_t now);
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:
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;
inline bool hasExtension(Extension extension) const noexcept override { return m_extensions.test(extension); }
inline const char *mode() const override { return "pool"; }
inline void onLine(char *line, size_t size) override { parse(line, size); }
private:
class Tls;
@@ -125,7 +92,7 @@ private:
bool parseJob(const rapidjson::Value &params, int *code);
bool parseLogin(const rapidjson::Value &result, int *code);
bool send(BIO *bio);
bool verifyAlgorithm(const Algorithm &algorithm) const;
bool verifyAlgorithm(const Algorithm &algorithm, const char *algo) const;
int resolve(const String &host);
int64_t send(const rapidjson::Document &doc);
int64_t send(size_t size);
@@ -143,9 +110,10 @@ private:
void setState(SocketState state);
void startTimeout();
inline bool isQuiet() const { return m_quiet || m_failures >= m_retries; }
inline const char *url() const { return m_pool.url(); }
inline SocketState state() const { return m_state; }
inline void setExtension(Extension ext, bool enable) noexcept { m_extensions.set(ext, enable); }
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 onClose(uv_handle_t *handle);
@@ -154,24 +122,11 @@ private:
static inline Client *getClient(void *data) { return m_storage.get(data); }
bool m_enabled;
bool m_ipv6;
bool m_quiet;
char m_sendBuf[2048];
const char *m_agent;
Dns *m_dns;
IClientListener *m_listener;
int m_id;
int m_retries;
int m_retryPause;
int64_t m_failures;
Job m_job;
Pool m_pool;
RecvBuf<kInputBufferSize> m_recvBuf;
SocketState m_state;
std::bitset<EXT_MAX> m_extensions;
std::map<int64_t, SubmitResult> m_results;
String m_ip;
String m_rpcId;
Tls *m_tls;
uint64_t m_expire;
@@ -181,7 +136,6 @@ private:
uv_stream_t *m_stream;
uv_tcp_t *m_socket;
static int64_t m_sequence;
static Storage<Client> m_storage;
};

View File

@@ -0,0 +1,379 @@
/* XMRig
* Copyright 2010 Jeff Garzik <jgarzik@pobox.com>
* Copyright 2012-2014 pooler <pooler@litecoinpool.org>
* Copyright 2014 Lucas Jones <https://github.com/lucasjones>
* Copyright 2014-2016 Wolf9466 <https://github.com/OhGodAPet>
* Copyright 2016 Jay D Dee <jayddee246@gmail.com>
* Copyright 2017-2018 XMR-Stak <https://github.com/fireice-uk>, <https://github.com/psychocrypt>
* Copyright 2018-2019 SChernykh <https://github.com/SChernykh>
* Copyright 2019 Howard Chu <https://github.com/hyc>
* Copyright 2016-2019 XMRig <https://github.com/xmrig>, <support@xmrig.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <algorithm>
#include <assert.h>
#include "3rdparty/http-parser/http_parser.h"
#include "base/io/json/Json.h"
#include "base/io/json/JsonRequest.h"
#include "base/io/log/Log.h"
#include "base/kernel/interfaces/IClientListener.h"
#include "base/net/http/HttpClient.h"
#include "base/net/stratum/DaemonClient.h"
#include "base/net/stratum/SubmitResult.h"
#include "base/tools/Buffer.h"
#include "base/tools/Timer.h"
#include "net/JobResult.h"
#include "rapidjson/document.h"
#include "rapidjson/error/en.h"
#include "rapidjson/stringbuffer.h"
#include "rapidjson/writer.h"
#ifdef XMRIG_FEATURE_TLS
# include "base/net/http/HttpsClient.h"
#endif
namespace xmrig {
static const char *kBlocktemplateBlob = "blocktemplate_blob";
static const char *kGetHeight = "/getheight";
static const char *kGetInfo = "/getinfo";
static const char *kHash = "hash";
static const char *kHeight = "height";
static const char *kJsonRPC = "/json_rpc";
}
xmrig::DaemonClient::DaemonClient(int id, IClientListener *listener) :
BaseClient(id, listener),
m_monero(true)
{
m_timer = new Timer(this);
}
xmrig::DaemonClient::~DaemonClient()
{
delete m_timer;
}
bool xmrig::DaemonClient::disconnect()
{
if (m_state != UnconnectedState) {
setState(UnconnectedState);
}
return true;
}
bool xmrig::DaemonClient::isTLS() const
{
# ifdef XMRIG_FEATURE_TLS
return m_pool.isTLS();
# else
return false;
# endif
}
int64_t xmrig::DaemonClient::submit(const JobResult &result)
{
if (result.jobId != (m_blocktemplate.data() + m_blocktemplate.size() - 32)) {
return -1;
}
# ifdef XMRIG_PROXY_PROJECT
memcpy(m_blocktemplate.data() + 78, result.nonce, 8);
# else
Buffer::toHex(reinterpret_cast<const uint8_t *>(&result.nonce), 4, m_blocktemplate.data() + 78);
# endif
using namespace rapidjson;
Document doc(kObjectType);
Value params(kArrayType);
params.PushBack(m_blocktemplate.toJSON(), doc.GetAllocator());
JsonRequest::create(doc, m_sequence, "submitblock", params);
# ifdef XMRIG_PROXY_PROJECT
m_results[m_sequence] = SubmitResult(m_sequence, result.diff, result.actualDiff(), result.id);
# else
m_results[m_sequence] = SubmitResult(m_sequence, result.diff, result.actualDiff());
# endif
send(HTTP_POST, kJsonRPC, doc);
return m_sequence++;
}
void xmrig::DaemonClient::connect()
{
setState(ConnectingState);
getBlockTemplate();
}
void xmrig::DaemonClient::connect(const Pool &pool)
{
setPool(pool);
connect();
}
void xmrig::DaemonClient::onHttpData(const HttpData &data)
{
if (data.status != HTTP_STATUS_OK) {
return retry();
}
LOG_DEBUG("[%s:%d] received (%d bytes): \"%.*s\"", m_pool.host().data(), m_pool.port(), static_cast<int>(data.body.size()), static_cast<int>(data.body.size()), data.body.c_str());
m_ip = static_cast<const HttpContext &>(data).ip().c_str();
# ifdef XMRIG_FEATURE_TLS
if (isTLS()) {
m_tlsVersion = static_cast<const HttpsClient &>(data).version();
m_tlsFingerprint = static_cast<const HttpsClient &>(data).fingerprint();
}
# endif
rapidjson::Document doc;
if (doc.Parse(data.body.c_str()).HasParseError()) {
if (!isQuiet()) {
LOG_ERR("[%s:%d] JSON decode failed: \"%s\"", m_pool.host().data(), m_pool.port(), rapidjson::GetParseError_En(doc.GetParseError()));
}
return retry();
}
if (data.method == HTTP_GET) {
if (data.url == kGetHeight) {
if (!doc.HasMember(kHash)) {
m_monero = false;
return send(HTTP_GET, kGetInfo);
}
if (isOutdated(Json::getUint64(doc, kHeight), Json::getString(doc, kHash))) {
getBlockTemplate();
}
}
else if (data.url == kGetInfo && isOutdated(Json::getUint64(doc, kHeight), Json::getString(doc, "top_block_hash"))) {
getBlockTemplate();
}
return;
}
if (!parseResponse(Json::getInt64(doc, "id", -1), Json::getObject(doc, "result"), Json::getObject(doc, "error"))) {
retry();
}
}
void xmrig::DaemonClient::onTimer(const Timer *)
{
if (m_state == ConnectingState) {
getBlockTemplate();
}
else if (m_state == ConnectedState) {
send(HTTP_GET, m_monero ? kGetHeight : kGetInfo);
}
}
bool xmrig::DaemonClient::isOutdated(uint64_t height, const char *hash) const
{
return m_job.height() != height || m_prevHash != hash;
}
bool xmrig::DaemonClient::parseJob(const rapidjson::Value &params, int *code)
{
Job job(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.setSeedHash(Json::getString(params, "seed_hash"));
job.setHeight(Json::getUint64(params, kHeight));
job.setDiff(Json::getUint64(params, "difficulty"));
job.setId(blocktemplate.data() + blocktemplate.size() - 32);
m_job = std::move(job);
m_blocktemplate = std::move(blocktemplate);
m_prevHash = Json::getString(params, "prev_hash");
if (m_state == ConnectingState) {
setState(ConnectedState);
}
m_listener->onJobReceived(this, m_job, params);
return true;
}
bool xmrig::DaemonClient::parseResponse(int64_t id, const rapidjson::Value &result, const rapidjson::Value &error)
{
if (id == -1) {
return false;
}
if (error.IsObject()) {
const char *message = error["message"].GetString();
if (!handleSubmitResponse(id, message) && !isQuiet()) {
LOG_ERR("[%s:%d] error: " RED_BOLD("\"%s\"") RED_S ", code: %d", m_pool.host().data(), m_pool.port(), message, error["code"].GetInt());
}
return false;
}
if (!result.IsObject()) {
return false;
}
int code = -1;
if (result.HasMember(kBlocktemplateBlob) && parseJob(result, &code)) {
return true;
}
if (handleSubmitResponse(id)) {
getBlockTemplate();
return true;
}
return false;
}
int64_t xmrig::DaemonClient::getBlockTemplate()
{
using namespace rapidjson;
Document doc(kObjectType);
auto &allocator = doc.GetAllocator();
Value params(kObjectType);
params.AddMember("wallet_address", m_pool.user().toJSON(), allocator);
params.AddMember("reserve_size", 8, allocator);
JsonRequest::create(doc, m_sequence, "getblocktemplate", params);
send(HTTP_POST, kJsonRPC, doc);
return m_sequence++;
}
void xmrig::DaemonClient::retry()
{
m_failures++;
m_listener->onClose(this, static_cast<int>(m_failures));
if (m_failures == -1) {
return;
}
if (m_state == ConnectedState) {
setState(ConnectingState);
}
m_timer->stop();
m_timer->start(m_retryPause, 0);
}
void xmrig::DaemonClient::send(int method, const char *url, const char *data, size_t size)
{
LOG_DEBUG("[%s:%d] " MAGENTA_BOLD("\"%s %s\"") BLACK_BOLD_S " send (%zu bytes): \"%.*s\"",
m_pool.host().data(),
m_pool.port(),
http_method_str(static_cast<http_method>(method)),
url,
size,
static_cast<int>(size),
data);
HttpClient *client;
# ifdef XMRIG_FEATURE_TLS
if (m_pool.isTLS()) {
client = new HttpsClient(method, url, this, data, size, m_pool.fingerprint());
}
else
# endif
{
client = new HttpClient(method, url, this, data, size);
}
client->setQuiet(isQuiet());
client->connect(m_pool.host(), m_pool.port());
}
void xmrig::DaemonClient::send(int method, const char *url, const rapidjson::Document &doc)
{
using namespace rapidjson;
StringBuffer buffer(nullptr, 512);
Writer<StringBuffer> writer(buffer);
doc.Accept(writer);
send(method, url, buffer.GetString(), buffer.GetSize());
}
void xmrig::DaemonClient::setState(SocketState state)
{
assert(m_state != state);
if (m_state == state) {
return;
}
m_state = state;
switch (state) {
case ConnectedState:
{
m_failures = 0;
m_listener->onLoginSuccess(this);
const uint64_t interval = std::max<uint64_t>(20, m_pool.pollInterval());
m_timer->start(interval, interval);
}
break;
case UnconnectedState:
m_failures = -1;
m_timer->stop();
break;
default:
break;
}
}

View File

@@ -0,0 +1,83 @@
/* XMRig
* Copyright 2010 Jeff Garzik <jgarzik@pobox.com>
* Copyright 2012-2014 pooler <pooler@litecoinpool.org>
* Copyright 2014 Lucas Jones <https://github.com/lucasjones>
* Copyright 2014-2016 Wolf9466 <https://github.com/OhGodAPet>
* Copyright 2016 Jay D Dee <jayddee246@gmail.com>
* Copyright 2017-2018 XMR-Stak <https://github.com/fireice-uk>, <https://github.com/psychocrypt>
* Copyright 2018-2019 SChernykh <https://github.com/SChernykh>
* Copyright 2019 Howard Chu <https://github.com/hyc>
* Copyright 2016-2019 XMRig <https://github.com/xmrig>, <support@xmrig.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef XMRIG_DAEMONCLIENT_H
#define XMRIG_DAEMONCLIENT_H
#include "base/net/stratum/BaseClient.h"
#include "base/kernel/interfaces/ITimerListener.h"
#include "base/kernel/interfaces/IHttpListener.h"
namespace xmrig {
class DaemonClient : public BaseClient, public ITimerListener, public IHttpListener
{
public:
DaemonClient(int id, IClientListener *listener);
~DaemonClient() override;
protected:
bool disconnect() override;
bool isTLS() const override;
int64_t submit(const JobResult &result) override;
void connect() override;
void connect(const Pool &pool) override;
void onHttpData(const HttpData &data) override;
void onTimer(const Timer *timer) override;
inline bool hasExtension(Extension) const noexcept override { return false; }
inline const char *mode() const override { return "daemon"; }
inline const char *tlsFingerprint() const override { return m_tlsFingerprint; }
inline const char *tlsVersion() const override { return m_tlsVersion; }
inline void deleteLater() override { delete this; }
inline void tick(uint64_t) override {}
private:
bool isOutdated(uint64_t height, const char *hash) const;
bool parseJob(const rapidjson::Value &params, int *code);
bool parseResponse(int64_t id, const rapidjson::Value &result, const rapidjson::Value &error);
int64_t getBlockTemplate();
void retry();
void send(int method, const char *url, const char *data = nullptr, size_t size = 0);
void send(int method, const char *url, const rapidjson::Document &doc);
void setState(SocketState state);
bool m_monero;
String m_blocktemplate;
String m_prevHash;
String m_tlsFingerprint;
String m_tlsVersion;
Timer *m_timer;
};
} /* namespace xmrig */
#endif /* XMRIG_DAEMONCLIENT_H */

View File

@@ -7,6 +7,7 @@
* Copyright 2017-2018 XMR-Stak <https://github.com/fireice-uk>, <https://github.com/psychocrypt>
* Copyright 2018 Lee Clagett <https://github.com/vtnerd>
* 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>
*
* This program is free software: you can redistribute it and/or modify
@@ -33,31 +34,18 @@
xmrig::Job::Job() :
m_autoVariant(false),
m_nicehash(false),
m_poolId(-2),
m_threadId(-1),
m_size(0),
m_diff(0),
m_height(0),
m_target(0),
m_blob()
m_blob(),
m_seedHash()
{
}
xmrig::Job::Job(int poolId, bool nicehash, const Algorithm &algorithm, const String &clientId) :
xmrig::Job::Job(bool nicehash, const Algorithm &algorithm, const String &clientId) :
m_algorithm(algorithm),
m_autoVariant(algorithm.variant() == VARIANT_AUTO),
m_nicehash(nicehash),
m_poolId(poolId),
m_threadId(-1),
m_size(0),
m_clientId(clientId),
m_diff(0),
m_height(0),
m_target(0),
m_blob()
m_blob(),
m_seedHash()
{
}
@@ -97,28 +85,6 @@ bool xmrig::Job::setBlob(const char *blob)
m_nicehash = true;
}
if (m_autoVariant) {
m_algorithm.setVariant(variant());
}
if (!m_algorithm.isForced()) {
if (m_algorithm.variant() == VARIANT_XTL && m_blob[0] >= 9) {
m_algorithm.setVariant(VARIANT_HALF);
}
else if (m_algorithm.variant() == VARIANT_MSR && m_blob[0] >= 8) {
m_algorithm.setVariant(VARIANT_HALF);
}
else if (m_algorithm.variant() == VARIANT_WOW && m_blob[0] < 11) {
m_algorithm.setVariant(VARIANT_2);
}
else if (m_algorithm.variant() == VARIANT_RWZ && m_blob[0] < 12) {
m_algorithm.setVariant(VARIANT_2);
}
else if (m_algorithm.variant() == VARIANT_ZLS && m_blob[0] < 8) {
m_algorithm.setVariant(VARIANT_2);
}
}
# ifdef XMRIG_PROXY_PROJECT
memset(m_rawBlob, 0, sizeof(m_rawBlob));
memcpy(m_rawBlob, blob, m_size * 2);
@@ -128,6 +94,20 @@ bool xmrig::Job::setBlob(const char *blob)
}
bool xmrig::Job::setSeedHash(const char *hash)
{
if (!hash || (strlen(hash) != sizeof(m_seedHash) * 2)) {
return false;
}
# ifdef XMRIG_PROXY_PROJECT
m_rawSeedHash = hash;
# endif
return Buffer::fromHex(hash, sizeof(m_seedHash) * 2, m_seedHash);
}
bool xmrig::Job::setTarget(const char *target)
{
if (!target) {
@@ -170,37 +150,37 @@ bool xmrig::Job::setTarget(const char *target)
}
void xmrig::Job::setAlgorithm(const char *algo)
void xmrig::Job::setDiff(uint64_t diff)
{
m_algorithm.parseAlgorithm(algo);
m_diff = diff;
m_target = toDiff(diff);
if (m_algorithm.variant() == xmrig::VARIANT_AUTO) {
m_algorithm.setVariant(variant());
}
# ifdef XMRIG_PROXY_PROJECT
Buffer::toHex(reinterpret_cast<uint8_t *>(&m_target), 8, m_rawTarget);
m_rawTarget[16] = '\0';
# endif
}
void xmrig::Job::setHeight(uint64_t height)
void xmrig::Job::copy(const Job &other)
{
m_height = height;
}
xmrig::Variant xmrig::Job::variant() const
{
switch (m_algorithm.algo()) {
case CRYPTONIGHT:
return (m_blob[0] >= 10) ? VARIANT_4 : ((m_blob[0] >= 8) ? VARIANT_2 : VARIANT_1);
case CRYPTONIGHT_LITE:
return VARIANT_1;
case CRYPTONIGHT_HEAVY:
return VARIANT_0;
default:
break;
}
return m_algorithm.variant();
m_algorithm = other.m_algorithm;
m_nicehash = other.m_nicehash;
m_size = other.m_size;
m_clientId = other.m_clientId;
m_id = other.m_id;
m_diff = other.m_diff;
m_height = other.m_height;
m_target = other.m_target;
m_index = other.m_index;
memcpy(m_blob, other.m_blob, sizeof(m_blob));
memcpy(m_seedHash, other.m_seedHash, sizeof(m_seedHash));
# ifdef XMRIG_PROXY_PROJECT
m_rawSeedHash = other.m_rawSeedHash;
memcpy(m_rawBlob, other.m_rawBlob, sizeof(m_rawBlob));
memcpy(m_rawTarget, other.m_rawTarget, sizeof(m_rawTarget));
# endif
}

View File

@@ -7,6 +7,7 @@
* Copyright 2017-2018 XMR-Stak <https://github.com/fireice-uk>, <https://github.com/psychocrypt>
* Copyright 2018 Lee Clagett <https://github.com/vtnerd>
* 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
@@ -32,7 +33,7 @@
#include "base/tools/String.h"
#include "common/crypto/Algorithm.h"
#include "crypto/common/Algorithm.h"
namespace xmrig {
@@ -46,14 +47,14 @@ public:
static constexpr const size_t kMaxBlobSize = 128;
Job();
Job(int poolId, bool nicehash, const Algorithm &algorithm, const String &clientId);
Job(bool nicehash, const Algorithm &algorithm, const String &clientId);
~Job();
bool isEqual(const Job &other) const;
bool setBlob(const char *blob);
bool setSeedHash(const char *hash);
bool setTarget(const char *target);
void setAlgorithm(const char *algo);
void setHeight(uint64_t height);
void setDiff(uint64_t diff);
inline bool isNicehash() const { return m_nicehash; }
inline bool isValid() const { return m_size > 0 && m_diff > 0; }
@@ -63,25 +64,25 @@ public:
inline const String &id() const { return m_id; }
inline const uint32_t *nonce() const { return reinterpret_cast<const uint32_t*>(m_blob + 39); }
inline const uint8_t *blob() const { return m_blob; }
inline int poolId() const { return m_poolId; }
inline int threadId() const { return m_threadId; }
inline const uint8_t *seedHash() const { return m_seedHash; }
inline size_t size() const { return m_size; }
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 target() const { return m_target; }
inline uint8_t fixedByte() const { return *(m_blob + 42); }
inline uint8_t index() const { return m_index; }
inline void reset() { m_size = 0; m_diff = 0; }
inline void setAlgorithm(const char *algo) { m_algorithm = algo; }
inline void setClientId(const String &id) { m_clientId = id; }
inline void setPoolId(int poolId) { m_poolId = poolId; }
inline void setThreadId(int threadId) { m_threadId = threadId; }
inline void setVariant(const char *variant) { m_algorithm.parseVariant(variant); }
inline void setVariant(int variant) { m_algorithm.parseVariant(variant); }
inline void setHeight(uint64_t height) { m_height = height; }
inline void setIndex(uint8_t index) { m_index = index; }
# ifdef XMRIG_PROXY_PROJECT
inline char *rawBlob() { return m_rawBlob; }
inline const char *rawBlob() const { return m_rawBlob; }
inline const char *rawTarget() const { return m_rawTarget; }
inline char *rawBlob() { return m_rawBlob; }
inline const char *rawBlob() const { return m_rawBlob; }
inline const char *rawTarget() const { return m_rawTarget; }
inline const String &rawSeedHash() const { return m_rawSeedHash; }
# endif
static inline uint32_t *nonce(uint8_t *blob) { return reinterpret_cast<uint32_t*>(blob + 39); }
@@ -89,26 +90,27 @@ public:
inline bool operator==(const Job &other) const { return isEqual(other); }
inline bool operator!=(const Job &other) const { return !isEqual(other); }
inline Job &operator=(const Job &other) { copy(other); return *this; }
private:
Variant variant() const;
void copy(const Job &other);
Algorithm m_algorithm;
bool m_autoVariant;
bool m_nicehash;
int m_poolId;
int m_threadId;
size_t m_size;
bool m_nicehash = false;
size_t m_size = 0;
String m_clientId;
String m_id;
uint64_t m_diff;
uint64_t m_height;
uint64_t m_target;
uint64_t m_diff = 0;
uint64_t m_height = 0;
uint64_t m_target = 0;
uint8_t m_blob[kMaxBlobSize];
uint8_t m_index = 0;
uint8_t m_seedHash[32];
# ifdef XMRIG_PROXY_PROJECT
char m_rawBlob[kMaxBlobSize * 2 + 8];
char m_rawTarget[24];
String m_rawSeedHash;
# endif
};

View File

@@ -6,6 +6,7 @@
* Copyright 2016 Jay D Dee <jayddee246@gmail.com>
* Copyright 2017-2019 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
@@ -29,7 +30,7 @@
#include <stdio.h>
#include "base/io/Json.h"
#include "base/io/json/Json.h"
#include "base/net/stratum/Pool.h"
#include "rapidjson/document.h"
@@ -41,35 +42,43 @@
#ifdef _MSC_VER
# define strncasecmp _strnicmp
# define strcasecmp _stricmp
#endif
namespace xmrig {
static const char *kEnabled = "enabled";
static const char *kFingerprint = "tls-fingerprint";
static const char *kKeepalive = "keepalive";
static const char *kNicehash = "nicehash";
static const char *kPass = "pass";
static const char *kRigId = "rig-id";
static const char *kTls = "tls";
static const char *kUrl = "url";
static const char *kUser = "user";
static const char *kVariant = "variant";
static const char *kAlgo = "algo";
static const char *kDaemon = "daemon";
static const char *kDaemonPollInterval = "daemon-poll-interval";
static const char *kEnabled = "enabled";
static const char *kFingerprint = "tls-fingerprint";
static const char *kKeepalive = "keepalive";
static const char *kNicehash = "nicehash";
static const char *kPass = "pass";
static const char *kRigId = "rig-id";
static const char *kTls = "tls";
static const char *kUrl = "url";
static const char *kUser = "user";
const String Pool::kDefaultPassword = "x";
const String Pool::kDefaultUser = "x";
const String Pool::kDefaultPassword = "x";
const String Pool::kDefaultUser = "x";
static const char kStratumTcp[] = "stratum+tcp://";
static const char kStratumSsl[] = "stratum+ssl://";
#ifdef XMRIG_FEATURE_HTTP
static const char kDaemonHttp[] = "daemon+http://";
static const char kDaemonHttps[] = "daemon+https://";
#endif
}
xmrig::Pool::Pool() :
m_enabled(true),
m_nicehash(false),
m_tls(false),
m_keepAlive(0),
m_port(kDefaultPort)
m_flags(0),
m_port(kDefaultPort),
m_pollInterval(kDefaultPollInterval)
{
}
@@ -86,63 +95,55 @@ xmrig::Pool::Pool() :
* @param url
*/
xmrig::Pool::Pool(const char *url) :
m_enabled(true),
m_nicehash(false),
m_tls(false),
m_keepAlive(0),
m_port(kDefaultPort)
m_flags(1),
m_port(kDefaultPort),
m_pollInterval(kDefaultPollInterval)
{
parse(url);
}
xmrig::Pool::Pool(const rapidjson::Value &object) :
m_enabled(true),
m_nicehash(false),
m_tls(false),
m_keepAlive(0),
m_port(kDefaultPort)
m_flags(1),
m_port(kDefaultPort),
m_pollInterval(kDefaultPollInterval)
{
if (!parse(Json::getString(object, kUrl))) {
return;
}
setUser(Json::getString(object, kUser));
setPassword(Json::getString(object, kPass));
setRigId(Json::getString(object, kRigId));
setNicehash(Json::getBool(object, kNicehash));
m_user = Json::getString(object, kUser);
m_password = Json::getString(object, kPass);
m_rigId = Json::getString(object, kRigId);
m_fingerprint = Json::getString(object, kFingerprint);
m_pollInterval = Json::getUint64(object, kDaemonPollInterval, kDefaultPollInterval);
m_algorithm = Json::getString(object, kAlgo);
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()) {
setKeepAlive(keepalive.GetInt());
}
else if (keepalive.IsBool()) {
setKeepAlive(keepalive.GetBool());
}
const rapidjson::Value &variant = object[kVariant];
if (variant.IsString()) {
algorithm().parseVariant(variant.GetString());
}
else if (variant.IsInt()) {
algorithm().parseVariant(variant.GetInt());
}
m_enabled = Json::getBool(object, kEnabled, true);
m_tls = Json::getBool(object, kTls);
m_fingerprint = Json::getString(object, kFingerprint);
}
xmrig::Pool::Pool(const char *host, uint16_t port, const char *user, const char *password, int keepAlive, bool nicehash, bool tls) :
m_enabled(true),
m_nicehash(nicehash),
m_tls(tls),
m_keepAlive(keepAlive),
m_flags(1),
m_host(host),
m_password(password),
m_user(user),
m_port(port)
m_port(port),
m_pollInterval(kDefaultPollInterval)
{
const size_t size = m_host.size() + 8;
assert(size > 8);
@@ -151,28 +152,9 @@ xmrig::Pool::Pool(const char *host, uint16_t port, const char *user, const char
snprintf(url, size - 1, "%s:%d", m_host.data(), m_port);
m_url = url;
}
bool xmrig::Pool::isCompatible(const Algorithm &algorithm) const
{
if (m_algorithms.empty()) {
return true;
}
for (const auto &a : m_algorithms) {
if (algorithm == a) {
return true;
}
}
# ifdef XMRIG_PROXY_PROJECT
if (m_algorithm.algo() == xmrig::CRYPTONIGHT && algorithm.algo() == xmrig::CRYPTONIGHT) {
return m_algorithm.variant() == xmrig::VARIANT_RWZ || m_algorithm.variant() == xmrig::VARIANT_ZLS;
}
# endif
return false;
m_flags.set(FLAG_NICEHASH, nicehash);
m_flags.set(FLAG_TLS, tls);
}
@@ -184,24 +166,34 @@ bool xmrig::Pool::isEnabled() const
}
# endif
return m_enabled && isValid() && algorithm().isValid();
# ifndef XMRIG_FEATURE_HTTP
if (isDaemon()) {
return false;
}
# endif
if (isDaemon() && !algorithm().isValid()) {
return false;
}
return m_flags.test(FLAG_ENABLED) && isValid();
}
bool xmrig::Pool::isEqual(const Pool &other) const
{
return (m_nicehash == other.m_nicehash
&& m_enabled == other.m_enabled
&& m_tls == other.m_tls
&& m_keepAlive == other.m_keepAlive
&& m_port == other.m_port
&& m_algorithm == other.m_algorithm
&& m_fingerprint == other.m_fingerprint
&& m_host == other.m_host
&& m_password == other.m_password
&& m_rigId == other.m_rigId
&& m_url == other.m_url
&& m_user == other.m_user);
return (m_flags == other.m_flags
&& m_keepAlive == other.m_keepAlive
&& m_port == other.m_port
&& m_algorithm == other.m_algorithm
&& m_fingerprint == other.m_fingerprint
&& m_host == other.m_host
&& m_password == other.m_password
&& m_rigId == other.m_rigId
&& m_url == other.m_url
&& m_user == other.m_user
&& m_pollInterval == other.m_pollInterval
);
}
@@ -209,21 +201,33 @@ bool xmrig::Pool::parse(const char *url)
{
assert(url != nullptr);
const char *p = strstr(url, "://");
const char *p = strstr(url, "://");
const char *base = url;
if (p) {
if (strncasecmp(url, "stratum+tcp://", 14) == 0) {
m_tls = false;
if (strncasecmp(url, kStratumTcp, sizeof(kStratumTcp) - 1) == 0) {
m_flags.set(FLAG_DAEMON, false);
m_flags.set(FLAG_TLS, false);
}
else if (strncasecmp(url, "stratum+ssl://", 14) == 0) {
m_tls = true;
else if (strncasecmp(url, kStratumSsl, sizeof(kStratumSsl) - 1) == 0) {
m_flags.set(FLAG_DAEMON, false);
m_flags.set(FLAG_TLS, true);
}
# ifdef XMRIG_FEATURE_HTTP
else if (strncasecmp(url, kDaemonHttps, sizeof(kDaemonHttps) - 1) == 0) {
m_flags.set(FLAG_DAEMON, true);
m_flags.set(FLAG_TLS, true);
}
else if (strncasecmp(url, kDaemonHttp, sizeof(kDaemonHttp) - 1) == 0) {
m_flags.set(FLAG_DAEMON, true);
m_flags.set(FLAG_TLS, false);
}
# endif
else {
return false;
}
base = url + 14;
base = p + 3;
}
if (!strlen(base) || *base == '/') {
@@ -252,23 +256,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
{
using namespace rapidjson;
@@ -277,69 +264,39 @@ rapidjson::Value xmrig::Pool::toJSON(rapidjson::Document &doc) const
Value obj(kObjectType);
obj.AddMember(StringRef(kAlgo), m_algorithm.toJSON(), allocator);
obj.AddMember(StringRef(kUrl), m_url.toJSON(), allocator);
obj.AddMember(StringRef(kUser), m_user.toJSON(), allocator);
obj.AddMember(StringRef(kPass), m_password.toJSON(), allocator);
obj.AddMember(StringRef(kRigId), m_rigId.toJSON(), allocator);
# ifndef XMRIG_PROXY_PROJECT
obj.AddMember(StringRef(kNicehash), isNicehash(), allocator);
# endif
if (!isDaemon()) {
obj.AddMember(StringRef(kPass), m_password.toJSON(), allocator);
obj.AddMember(StringRef(kRigId), m_rigId.toJSON(), allocator);
if (m_keepAlive == 0 || m_keepAlive == kKeepAliveTimeout) {
obj.AddMember(StringRef(kKeepalive), m_keepAlive > 0, allocator);
}
else {
obj.AddMember(StringRef(kKeepalive), m_keepAlive, allocator);
# ifndef XMRIG_PROXY_PROJECT
obj.AddMember(StringRef(kNicehash), isNicehash(), allocator);
# endif
if (m_keepAlive == 0 || m_keepAlive == kKeepAliveTimeout) {
obj.AddMember(StringRef(kKeepalive), m_keepAlive > 0, allocator);
}
else {
obj.AddMember(StringRef(kKeepalive), m_keepAlive, allocator);
}
}
switch (m_algorithm.variant()) {
case VARIANT_AUTO:
case VARIANT_0:
case VARIANT_1:
obj.AddMember(StringRef(kVariant), m_algorithm.variant(), allocator);
break;
obj.AddMember(StringRef(kEnabled), m_flags.test(FLAG_ENABLED), allocator);
obj.AddMember(StringRef(kTls), isTLS(), allocator);
obj.AddMember(StringRef(kFingerprint), m_fingerprint.toJSON(), allocator);
obj.AddMember(StringRef(kDaemon), m_flags.test(FLAG_DAEMON), allocator);
case VARIANT_2:
obj.AddMember(StringRef(kVariant), 2, allocator);
break;
default:
obj.AddMember(StringRef(kVariant), StringRef(m_algorithm.variantName()), allocator);
break;
if (isDaemon()) {
obj.AddMember(StringRef(kDaemonPollInterval), m_pollInterval, allocator);
}
obj.AddMember(StringRef(kEnabled), m_enabled, allocator);
obj.AddMember(StringRef(kTls), isTLS(), allocator);
obj.AddMember(StringRef(kFingerprint), m_fingerprint.toJSON(), allocator);
return obj;
}
void xmrig::Pool::adjust(const Algorithm &algorithm)
{
if (!isValid()) {
return;
}
if (!m_algorithm.isValid()) {
m_algorithm.setAlgo(algorithm.algo());
adjustVariant(algorithm.variant());
}
rebuild();
}
void xmrig::Pool::setAlgo(const xmrig::Algorithm &algorithm)
{
m_algorithm = algorithm;
rebuild();
}
#ifdef APP_DEBUG
void xmrig::Pool::print() const
{
@@ -350,7 +307,7 @@ void xmrig::Pool::print() const
LOG_DEBUG ("pass: %s", m_password.data());
LOG_DEBUG ("rig-id %s", m_rigId.data());
LOG_DEBUG ("algo: %s", m_algorithm.name());
LOG_DEBUG ("nicehash: %d", static_cast<int>(m_nicehash));
LOG_DEBUG ("nicehash: %d", static_cast<int>(m_flags.test(FLAG_NICEHASH)));
LOG_DEBUG ("keepAlive: %d", m_keepAlive);
}
#endif
@@ -377,132 +334,3 @@ bool xmrig::Pool::parseIPv6(const char *addr)
return true;
}
void xmrig::Pool::addVariant(xmrig::Variant variant)
{
const xmrig::Algorithm algorithm(m_algorithm.algo(), variant);
if (!algorithm.isValid() || m_algorithm == algorithm) {
return;
}
m_algorithms.push_back(algorithm);
}
void xmrig::Pool::adjustVariant(const xmrig::Variant variantHint)
{
# ifndef XMRIG_PROXY_PROJECT
using namespace xmrig;
if (m_host.contains(".nicehash.com")) {
m_keepAlive = false;
m_nicehash = true;
bool valid = true;
switch (m_port) {
case 3355:
case 33355:
valid = m_algorithm.algo() == CRYPTONIGHT && m_host.contains("cryptonight.");
m_algorithm.setVariant(VARIANT_0);
break;
case 3363:
case 33363:
valid = m_algorithm.algo() == CRYPTONIGHT && m_host.contains("cryptonightv7.");
m_algorithm.setVariant(VARIANT_1);
break;
case 3364:
valid = m_algorithm.algo() == CRYPTONIGHT_HEAVY && m_host.contains("cryptonightheavy.");
m_algorithm.setVariant(VARIANT_0);
break;
case 3367:
case 33367:
valid = m_algorithm.algo() == CRYPTONIGHT && m_host.contains("cryptonightv8.");
m_algorithm.setVariant(VARIANT_2);
break;
default:
break;
}
if (!valid) {
m_algorithm.setAlgo(INVALID_ALGO);
}
m_tls = m_port > 33000;
return;
}
if (m_host.contains(".minergate.com")) {
m_keepAlive = false;
bool valid = true;
m_algorithm.setVariant(VARIANT_1);
if (m_host.contains("xmr.pool.")) {
valid = m_algorithm.algo() == CRYPTONIGHT;
m_algorithm.setVariant(m_port == 45700 ? VARIANT_AUTO : VARIANT_0);
}
else if (m_host.contains("aeon.pool.") && m_port == 45690) {
valid = m_algorithm.algo() == CRYPTONIGHT_LITE;
m_algorithm.setVariant(VARIANT_1);
}
if (!valid) {
m_algorithm.setAlgo(INVALID_ALGO);
}
return;
}
if (variantHint != VARIANT_AUTO) {
m_algorithm.setVariant(variantHint);
return;
}
if (m_algorithm.variant() != VARIANT_AUTO) {
return;
}
if (m_algorithm.algo() == CRYPTONIGHT_HEAVY) {
m_algorithm.setVariant(VARIANT_0);
}
else if (m_algorithm.algo() == CRYPTONIGHT_LITE) {
m_algorithm.setVariant(VARIANT_1);
}
# endif
}
void xmrig::Pool::rebuild()
{
m_algorithms.clear();
if (!m_algorithm.isValid()) {
return;
}
m_algorithms.push_back(m_algorithm);
# ifndef XMRIG_PROXY_PROJECT
addVariant(VARIANT_4);
addVariant(VARIANT_WOW);
addVariant(VARIANT_2);
addVariant(VARIANT_1);
addVariant(VARIANT_0);
addVariant(VARIANT_HALF);
addVariant(VARIANT_XTL);
addVariant(VARIANT_TUBE);
addVariant(VARIANT_MSR);
addVariant(VARIANT_XHV);
addVariant(VARIANT_XAO);
addVariant(VARIANT_RTO);
addVariant(VARIANT_GPU);
addVariant(VARIANT_RWZ);
addVariant(VARIANT_ZLS);
addVariant(VARIANT_DOUBLE);
addVariant(VARIANT_AUTO);
# endif
}

View File

@@ -6,6 +6,7 @@
* 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
@@ -26,11 +27,12 @@
#define XMRIG_POOL_H
#include <bitset>
#include <vector>
#include "base/tools/String.h"
#include "common/crypto/Algorithm.h"
#include "crypto/common/Algorithm.h"
#include "rapidjson/fwd.h"
@@ -40,11 +42,20 @@ namespace xmrig {
class Pool
{
public:
enum Flags {
FLAG_ENABLED,
FLAG_NICEHASH,
FLAG_TLS,
FLAG_DAEMON,
FLAG_MAX
};
static const String kDefaultPassword;
static const String kDefaultUser;
constexpr static uint16_t kDefaultPort = 3333;
constexpr static int kKeepAliveTimeout = 60;
constexpr static int kKeepAliveTimeout = 60;
constexpr static uint16_t kDefaultPort = 3333;
constexpr static uint64_t kDefaultPollInterval = 1000;
Pool();
Pool(const char *url);
@@ -58,12 +69,11 @@ public:
bool tls = false
);
inline Algorithm &algorithm() { return m_algorithm; }
inline bool isNicehash() const { return m_nicehash; }
inline bool isTLS() const { return m_tls; }
inline bool isDaemon() const { return m_flags.test(FLAG_DAEMON); }
inline bool isNicehash() const { return m_flags.test(FLAG_NICEHASH); }
inline bool isTLS() const { return m_flags.test(FLAG_TLS); }
inline bool isValid() const { return !m_host.isNull() && m_port > 0; }
inline const Algorithm &algorithm() const { return m_algorithm; }
inline const Algorithms &algorithms() const { return m_algorithms; }
inline const String &fingerprint() const { return m_fingerprint; }
inline const String &host() const { return m_host; }
inline const String &password() const { return !m_password.isNull() ? m_password : kDefaultPassword; }
@@ -72,43 +82,33 @@ public:
inline const String &user() const { return !m_user.isNull() ? m_user : kDefaultUser; }
inline int keepAlive() const { return m_keepAlive; }
inline uint16_t port() const { return m_port; }
inline void setFingerprint(const char *fingerprint) { m_fingerprint = fingerprint; }
inline void setKeepAlive(bool enable) { setKeepAlive(enable ? kKeepAliveTimeout : 0); }
inline void setKeepAlive(int keepAlive) { m_keepAlive = keepAlive >= 0 ? keepAlive : 0; }
inline void setNicehash(bool nicehash) { m_nicehash = nicehash; }
inline void setPassword(const char *password) { m_password = password; }
inline void setRigId(const char *rigId) { m_rigId = rigId; }
inline void setTLS(bool tls) { m_tls = tls; }
inline void setUser(const char *user) { m_user = user; }
inline uint64_t pollInterval() const { return m_pollInterval; }
inline void setAlgo(const Algorithm &algorithm) { m_algorithm = algorithm; }
inline void setPassword(const String &password) { m_password = password; }
inline void setRigId(const String &rigId) { m_rigId = rigId; }
inline void setUser(const String &user) { m_user = user; }
inline bool operator!=(const Pool &other) const { return !isEqual(other); }
inline bool operator==(const Pool &other) const { return isEqual(other); }
inline bool operator!=(const Pool &other) const { return !isEqual(other); }
inline bool operator==(const Pool &other) const { return isEqual(other); }
bool isCompatible(const Algorithm &algorithm) const;
bool isEnabled() const;
bool isEqual(const Pool &other) const;
bool parse(const char *url);
bool setUserpass(const char *userpass);
rapidjson::Value toJSON(rapidjson::Document &doc) const;
void adjust(const Algorithm &algorithm);
void setAlgo(const Algorithm &algorithm);
# ifdef APP_DEBUG
void print() const;
# endif
private:
inline void setKeepAlive(bool enable) { setKeepAlive(enable ? kKeepAliveTimeout : 0); }
inline void setKeepAlive(int keepAlive) { m_keepAlive = keepAlive >= 0 ? keepAlive : 0; }
bool parseIPv6(const char *addr);
void addVariant(Variant variant);
void adjustVariant(const Variant variantHint);
void rebuild();
Algorithm m_algorithm;
Algorithms m_algorithms;
bool m_enabled;
bool m_nicehash;
bool m_tls;
int m_keepAlive;
std::bitset<FLAG_MAX> m_flags;
String m_fingerprint;
String m_host;
String m_password;
@@ -116,6 +116,7 @@ private:
String m_url;
String m_user;
uint16_t m_port;
uint64_t m_pollInterval;
};

View File

@@ -24,6 +24,7 @@
#include "base/io/log/Log.h"
#include "base/kernel/interfaces/IJsonReader.h"
#include "base/net/stratum/Pools.h"
#include "base/net/stratum/strategies/FailoverStrategy.h"
#include "base/net/stratum/strategies/SinglePoolStrategy.h"
@@ -44,16 +45,6 @@ xmrig::Pools::Pools() :
}
xmrig::Pool &xmrig::Pools::current()
{
if (m_data.empty()) {
m_data.push_back(Pool());
}
return m_data.back();
}
bool xmrig::Pools::isEqual(const Pools &other) const
{
if (m_data.size() != other.m_data.size() || m_retries != other.m_retries || m_retryPause != other.m_retryPause) {
@@ -64,25 +55,6 @@ bool xmrig::Pools::isEqual(const Pools &other) const
}
bool xmrig::Pools::setUrl(const char *url)
{
if (m_data.empty() || m_data.back().isValid()) {
Pool pool(url);
if (pool.isValid()) {
m_data.push_back(std::move(pool));
return true;
}
return false;
}
current().parse(url);
return m_data.back().isValid();
}
xmrig::IStrategy *xmrig::Pools::createStrategy(IStrategyListener *listener) const
{
if (active() == 1) {
@@ -132,18 +104,15 @@ size_t xmrig::Pools::active() const
}
void xmrig::Pools::adjust(const Algorithm &algorithm)
{
for (Pool &pool : m_data) {
pool.adjust(algorithm);
}
}
void xmrig::Pools::load(const rapidjson::Value &pools)
void xmrig::Pools::load(const IJsonReader &reader)
{
m_data.clear();
const rapidjson::Value &pools = reader.getArray("pools");
if (!pools.IsArray()) {
return;
}
for (const rapidjson::Value &value : pools.GetArray()) {
if (!value.IsObject()) {
continue;
@@ -154,6 +123,11 @@ void xmrig::Pools::load(const rapidjson::Value &pools)
m_data.push_back(std::move(pool));
}
}
setDonateLevel(reader.getInt("donate-level", kDefaultDonateLevel));
setProxyDonate(reader.getInt("donate-over-proxy", PROXY_DONATE_AUTO));
setRetries(reader.getInt("retries"));
setRetryPause(reader.getInt("retry-pause"));
}
@@ -161,11 +135,11 @@ void xmrig::Pools::print() const
{
size_t i = 1;
for (const Pool &pool : m_data) {
Log::print(GREEN_BOLD(" * ") WHITE_BOLD("POOL #%-7zu") CSI "1;%dm%s" CLEAR " variant " WHITE_BOLD("%s"),
Log::print(GREEN_BOLD(" * ") WHITE_BOLD("POOL #%-7zu") CSI "1;%dm%s" CLEAR " algo " WHITE_BOLD("%s"),
i,
(pool.isEnabled() ? (pool.isTLS() ? 32 : 36) : 31),
pool.url().data(),
pool.algorithm().variantName()
pool.algorithm().isValid() ? pool.algorithm().shortName() : "auto"
);
i++;

View File

@@ -35,6 +35,7 @@
namespace xmrig {
class IJsonReader;
class IStrategy;
class IStrategyListener;
@@ -50,42 +51,28 @@ public:
Pools();
inline bool setUserpass(const char *userpass) { return current().setUserpass(userpass); }
inline const std::vector<Pool> &data() const { return m_data; }
inline int donateLevel() const { return m_donateLevel; }
inline int retries() const { return m_retries; }
inline int retryPause() const { return m_retryPause; }
inline ProxyDonate proxyDonate() const { return m_proxyDonate; }
inline void setFingerprint(const char *fingerprint) { current().setFingerprint(fingerprint); }
inline void setKeepAlive(bool enable) { current().setKeepAlive(enable); }
inline void setKeepAlive(int keepAlive) { current().setKeepAlive(keepAlive); }
inline void setNicehash(bool enable) { current().setNicehash(enable); }
inline void setPassword(const char *password) { current().setPassword(password); }
inline void setRigId(const char *rigId) { current().setRigId(rigId); }
inline void setTLS(bool enable) { current().setTLS(enable); }
inline void setUser(const char *user) { current().setUser(user); }
inline void setVariant(const char *variant) { current().algorithm().parseVariant(variant); }
inline void setVariant(int variant) { current().algorithm().parseVariant(variant); }
inline bool operator!=(const Pools &other) const { return !isEqual(other); }
inline bool operator==(const Pools &other) const { return isEqual(other); }
bool isEqual(const Pools &other) const;
bool setUrl(const char *url);
IStrategy *createStrategy(IStrategyListener *listener) const;
rapidjson::Value toJSON(rapidjson::Document &doc) const;
size_t active() const;
void adjust(const Algorithm &algorithm);
void load(const rapidjson::Value &pools);
void load(const IJsonReader &reader);
void print() const;
private:
void setDonateLevel(int level);
void setProxyDonate(int value);
void setRetries(int retries);
void setRetryPause(int retryPause);
private:
Pool &current();
int m_donateLevel;
int m_retries;
int m_retryPause;

View File

@@ -38,17 +38,17 @@ public:
inline SubmitResult() :
reqId(0),
seq(0),
diff(0),
actualDiff(0),
diff(0),
elapsed(0),
m_start(0)
{}
inline SubmitResult(int64_t seq, uint32_t diff, uint64_t actualDiff, int64_t reqId = 0) :
inline SubmitResult(int64_t seq, uint64_t diff, uint64_t actualDiff, int64_t reqId = 0) :
reqId(reqId),
seq(seq),
diff(diff),
actualDiff(actualDiff),
diff(diff),
elapsed(0),
m_start(Chrono::steadyMSecs())
{}
@@ -57,8 +57,8 @@ public:
int64_t reqId;
int64_t seq;
uint32_t diff;
uint64_t actualDiff;
uint64_t diff;
uint64_t elapsed;
private:

View File

@@ -24,9 +24,14 @@
#include "base/kernel/interfaces/IStrategyListener.h"
#include "base/kernel/Platform.h"
#include "base/net/stratum/Client.h"
#include "base/net/stratum/strategies/FailoverStrategy.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) :
@@ -56,7 +61,7 @@ xmrig::FailoverStrategy::FailoverStrategy(int retryPause, int retries, IStrategy
xmrig::FailoverStrategy::~FailoverStrategy()
{
for (Client *client : m_pools) {
for (IClient *client : m_pools) {
client->deleteLater();
}
}
@@ -64,7 +69,15 @@ xmrig::FailoverStrategy::~FailoverStrategy()
void xmrig::FailoverStrategy::add(const Pool &pool)
{
Client *client = new Client(static_cast<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->setRetries(m_retries);
client->setRetryPause(m_retryPause * 1000);
@@ -76,7 +89,7 @@ void xmrig::FailoverStrategy::add(const Pool &pool)
int64_t xmrig::FailoverStrategy::submit(const JobResult &result)
{
if (m_active == -1) {
if (!isActive()) {
return -1;
}
@@ -100,9 +113,9 @@ void xmrig::FailoverStrategy::resume()
}
void xmrig::FailoverStrategy::setAlgo(const xmrig::Algorithm &algo)
void xmrig::FailoverStrategy::setAlgo(const Algorithm &algo)
{
for (Client *client : m_pools) {
for (IClient *client : m_pools) {
client->setAlgo(algo);
}
}
@@ -123,13 +136,13 @@ void xmrig::FailoverStrategy::stop()
void xmrig::FailoverStrategy::tick(uint64_t now)
{
for (Client *client : m_pools) {
for (IClient *client : m_pools) {
client->tick(now);
}
}
void xmrig::FailoverStrategy::onClose(Client *client, int failures)
void xmrig::FailoverStrategy::onClose(IClient *client, int failures)
{
if (failures == -1) {
return;
@@ -150,7 +163,13 @@ void xmrig::FailoverStrategy::onClose(Client *client, int failures)
}
void xmrig::FailoverStrategy::onJobReceived(Client *client, const Job &job, const rapidjson::Value &)
void xmrig::FailoverStrategy::onLogin(IClient *client, rapidjson::Document &doc, rapidjson::Value &params)
{
m_listener->onLogin(this, client, doc, params);
}
void xmrig::FailoverStrategy::onJobReceived(IClient *client, const Job &job, const rapidjson::Value &)
{
if (m_active == client->id()) {
m_listener->onJob(this, client, job);
@@ -158,7 +177,7 @@ void xmrig::FailoverStrategy::onJobReceived(Client *client, const Job &job, cons
}
void xmrig::FailoverStrategy::onLoginSuccess(Client *client)
void xmrig::FailoverStrategy::onLoginSuccess(IClient *client)
{
int active = m_active;
@@ -179,7 +198,13 @@ 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);
}
void xmrig::FailoverStrategy::onVerifyAlgorithm(const IClient *client, const Algorithm &algorithm, bool *ok)
{
m_listener->onVerifyAlgorithm(this, client, algorithm, ok);
}

View File

@@ -51,9 +51,8 @@ public:
void add(const Pool &pool);
protected:
inline bool isActive() const override { return m_active >= 0; }
inline Client *client() const override { return active(); }
inline void onLogin(Client *, rapidjson::Document &, rapidjson::Value &) override {}
inline bool isActive() const override { return m_active >= 0; }
inline IClient *client() const override { return isActive() ? active() : m_pools[m_index]; }
int64_t submit(const JobResult &result) override;
void connect() override;
@@ -62,13 +61,15 @@ protected:
void stop() override;
void tick(uint64_t now) override;
void onClose(Client *client, int failures) override;
void onJobReceived(Client *client, const Job &job, const rapidjson::Value &params) override;
void onLoginSuccess(Client *client) override;
void onResultAccepted(Client *client, const SubmitResult &result, const char *error) override;
void onClose(IClient *client, int failures) override;
void onJobReceived(IClient *client, const Job &job, const rapidjson::Value &params) override;
void onLogin(IClient *client, rapidjson::Document &doc, rapidjson::Value &params) override;
void onLoginSuccess(IClient *client) override;
void onResultAccepted(IClient *client, const SubmitResult &result, const char *error) override;
void onVerifyAlgorithm(const IClient *client, const Algorithm &algorithm, bool *ok) override;
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 int m_retries;
@@ -76,7 +77,7 @@ private:
int m_active;
IStrategyListener *m_listener;
size_t m_index;
std::vector<Client*> m_pools;
std::vector<IClient*> m_pools;
};

View File

@@ -24,16 +24,31 @@
#include "base/kernel/interfaces/IStrategyListener.h"
#include "base/kernel/Platform.h"
#include "base/net/stratum/Client.h"
#include "base/net/stratum/strategies/SinglePoolStrategy.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) :
m_active(false),
m_listener(listener)
{
# ifdef XMRIG_FEATURE_HTTP
if (!pool.isDaemon()) {
m_client = new Client(0, Platform::userAgent(), this);
}
else {
m_client = new DaemonClient(0, this);
}
# else
m_client = new Client(0, Platform::userAgent(), this);
# endif
m_client->setPool(pool);
m_client->setRetries(retries);
m_client->setRetryPause(retryPause * 1000);
@@ -69,7 +84,7 @@ void xmrig::SinglePoolStrategy::resume()
}
void xmrig::SinglePoolStrategy::setAlgo(const xmrig::Algorithm &algo)
void xmrig::SinglePoolStrategy::setAlgo(const Algorithm &algo)
{
m_client->setAlgo(algo);
}
@@ -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()) {
return;
@@ -98,20 +113,32 @@ void xmrig::SinglePoolStrategy::onClose(Client *, int)
}
void xmrig::SinglePoolStrategy::onJobReceived(Client *client, const Job &job, const rapidjson::Value &)
void xmrig::SinglePoolStrategy::onJobReceived(IClient *client, const Job &job, const rapidjson::Value &)
{
m_listener->onJob(this, client, job);
}
void xmrig::SinglePoolStrategy::onLoginSuccess(Client *client)
void xmrig::SinglePoolStrategy::onLogin(IClient *client, rapidjson::Document &doc, rapidjson::Value &params)
{
m_listener->onLogin(this, client, doc, params);
}
void xmrig::SinglePoolStrategy::onLoginSuccess(IClient *client)
{
m_active = true;
m_listener->onActive(this, client);
}
void xmrig::SinglePoolStrategy::onResultAccepted(Client *client, const SubmitResult &result, const char *error)
void xmrig::SinglePoolStrategy::onResultAccepted(IClient *client, const SubmitResult &result, const char *error)
{
m_listener->onResultAccepted(this, client, result, error);
}
void xmrig::SinglePoolStrategy::onVerifyAlgorithm(const IClient *client, const Algorithm &algorithm, bool *ok)
{
m_listener->onVerifyAlgorithm(this, client, algorithm, ok);
}

View File

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

View File

@@ -5,7 +5,8 @@
* 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>
* 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
@@ -21,26 +22,24 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef XMRIG_CPU_H
#define XMRIG_CPU_H
#include "common/interfaces/ICpuInfo.h"
#ifndef XMRIG_BATON_H
#define XMRIG_BATON_H
namespace xmrig {
class Cpu
template<typename REQ>
class Baton
{
public:
static ICpuInfo *info();
static void init();
static void release();
inline Baton() { req.data = this; }
REQ req;
};
} /* namespace xmrig */
#endif /* XMRIG_CPU_H */
#endif /* XMRIG_BATON_H */

View File

@@ -43,17 +43,20 @@ public:
~Buffer();
inline char *data() { return m_data; }
inline const char *data() const { return m_data; }
inline size_t size() const { return m_size; }
inline void from(const Buffer &other) { from(other.data(), other.size()); }
inline bool isEqual(const Buffer &other) const { return m_size == other.m_size && (m_size == 0 || memcmp(m_data, other.m_data, m_size) == 0); }
inline char *data() { return m_data; }
inline const char *data() const { return m_data; }
inline size_t size() const { return m_size; }
inline void from(const Buffer &other) { from(other.data(), other.size()); }
void from(const char *data, size_t size);
inline Buffer &operator=(const Buffer &other) { from(other); return *this; }
inline Buffer &operator=(Buffer &&other) { move(std::move(other)); return *this; }
inline bool operator!=(const Buffer &other) const { return !isEqual(other); }
inline bool operator==(const Buffer &other) const { return isEqual(other); }
inline Buffer &operator=(Buffer &&other) { move(std::move(other)); return *this; }
inline Buffer &operator=(const Buffer &other) { from(other); return *this; }
static Buffer allocUnsafe(size_t size);

View File

@@ -35,6 +35,14 @@ namespace xmrig {
class Chrono
{
public:
static inline uint64_t highResolutionMSecs()
{
using namespace std::chrono;
return static_cast<uint64_t>(time_point_cast<milliseconds>(high_resolution_clock::now()).time_since_epoch().count());
}
static inline uint64_t steadyMSecs()
{
using namespace std::chrono;

View File

@@ -23,6 +23,9 @@
*/
#include <ctype.h>
#include "base/tools/String.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)
{
if (vec.empty()) {

View File

@@ -80,11 +80,13 @@ public:
inline String &operator=(char *str) { move(str); return *this; }
inline String &operator=(const char *str) { copy(str); return *this; }
inline String &operator=(const String &str) { copy(str); return *this; }
inline String &operator=(std::nullptr_t) { delete [] m_data; m_data = nullptr; m_size = 0; return *this; }
inline String &operator=(String &&other) { move(std::move(other)); return *this; }
rapidjson::Value toJSON() const;
rapidjson::Value toJSON(rapidjson::Document &doc) const;
std::vector<xmrig::String> split(char sep) const;
String &toLower();
static String join(const std::vector<xmrig::String> &vec, char sep);

View File

@@ -1,424 +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);
}
else {
m_http.load(json["http"]);
}
# else
m_http.load(doc["http"]);
# endif
}
void xmrig::CommonConfig::setFileName(const char *fileName)
{
m_fileName = fileName;
}
bool xmrig::CommonConfig::parseInt(int key, int arg)
{
switch (key) {
case RetriesKey: /* --retries */
m_pools.setRetries(arg);
break;
case RetryPauseKey: /* --retry-pause */
m_pools.setRetryPause(arg);
break;
case KeepAliveKey: /* --keepalive */
m_pools.setKeepAlive(arg);
break;
case VariantKey: /* --variant */
m_pools.setVariant(arg);
break;
case DonateLevelKey: /* --donate-level */
m_pools.setDonateLevel(arg);
break;
case ProxyDonateKey: /* --donate-over-proxy */
m_pools.setProxyDonate(arg);
break;
# ifdef XMRIG_DEPRECATED
case ApiPort: /* --api-port */
fputs("option \"--api-port\" deprecated, use \"--http-port\" instead.\n", stderr);
fflush(stdout);
m_http.setPort(arg);
break;
# endif
case HttpPort: /* --http-port */
m_http.setPort(arg);
break;
case PrintTimeKey: /* --print-time */
if (arg >= 0 && arg <= 3600) {
m_printTime = arg;
}
break;
default:
break;
}
return true;
}

View File

@@ -1,262 +0,0 @@
/* XMRig
* Copyright 2010 Jeff Garzik <jgarzik@pobox.com>
* Copyright 2012-2014 pooler <pooler@litecoinpool.org>
* Copyright 2014 Lucas Jones <https://github.com/lucasjones>
* Copyright 2014-2016 Wolf9466 <https://github.com/OhGodAPet>
* Copyright 2016 Jay D Dee <jayddee246@gmail.com>
* Copyright 2017-2018 XMR-Stak <https://github.com/fireice-uk>, <https://github.com/psychocrypt>
* Copyright 2018-2019 SChernykh <https://github.com/SChernykh>
* Copyright 2016-2019 XMRig <https://github.com/xmrig>, <support@xmrig.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <assert.h>
#include <limits.h>
#include <stdio.h>
#include <uv.h>
#include "base/io/Json.h"
#include "base/kernel/interfaces/IConfigListener.h"
#include "base/kernel/Process.h"
#include "common/config/ConfigLoader.h"
#include "common/config/ConfigWatcher.h"
#include "common/interfaces/IConfig.h"
#include "common/Platform.h"
#include "core/config/Config.h"
#include "core/config/ConfigLoader_platform.h"
#include "rapidjson/document.h"
#include "rapidjson/error/en.h"
#include "rapidjson/fwd.h"
#ifdef XMRIG_FEATURE_EMBEDDED_CONFIG
# include "core/config/ConfigLoader_default.h"
#endif
namespace xmrig {
ConfigWatcher *ConfigLoader::m_watcher = nullptr;
IConfigListener *ConfigLoader::m_listener = nullptr;
} // namespace xmrig
#ifndef ARRAY_SIZE
# define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]))
#endif
bool xmrig::ConfigLoader::loadFromFile(xmrig::IConfig *config, const char *fileName)
{
rapidjson::Document doc;
if (!getJSON(fileName, doc)) {
return false;
}
config->setFileName(fileName);
return loadFromJSON(config, doc);
}
bool xmrig::ConfigLoader::loadFromJSON(xmrig::IConfig *config, const char *json)
{
using namespace rapidjson;
Document doc;
doc.Parse<kParseCommentsFlag | kParseTrailingCommasFlag>(json);
if (doc.HasParseError() || !doc.IsObject()) {
return false;
}
return loadFromJSON(config, doc);
}
bool xmrig::ConfigLoader::loadFromJSON(xmrig::IConfig *config, const rapidjson::Value &json)
{
for (size_t i = 0; i < ARRAY_SIZE(config_options); i++) {
parseJSON(config, &config_options[i], json);
}
const rapidjson::Value &api = json["api"];
if (api.IsObject()) {
for (size_t i = 0; i < ARRAY_SIZE(api_options); i++) {
parseJSON(config, &api_options[i], api);
}
}
config->parseJSON(json);
return config->finalize();
}
bool xmrig::ConfigLoader::reload(xmrig::IConfig *oldConfig, const rapidjson::Value &json)
{
IConfig *config = Config::create();
if (!loadFromJSON(config, json)) {
delete config;
return false;
}
config->setFileName(oldConfig->fileName());
const bool saved = config->save();
if (config->isWatch() && m_watcher && saved) {
delete config;
return true;
}
m_listener->onNewConfig(config);
return true;
}
bool xmrig::ConfigLoader::watch(IConfig *config)
{
if (!config->isWatch()) {
return false;
}
assert(m_watcher == nullptr);
m_watcher = new ConfigWatcher(config->fileName(), m_listener);
return true;
}
xmrig::IConfig *xmrig::ConfigLoader::load(Process *process, IConfigListener *listener)
{
m_listener = listener;
IConfig *config = Config::create();
int key;
int argc = process->arguments().argc();
char **argv = process->arguments().argv();
while (1) {
key = getopt_long(argc, argv, short_options, options, nullptr);
if (key < 0) {
break;
}
if (!parseArg(config, key, optarg)) {
delete config;
return nullptr;
}
}
if (optind < argc) {
fprintf(stderr, "%s: unsupported non-option argument '%s'\n", argv[0], argv[optind]);
delete config;
return nullptr;
}
if (!config->finalize()) {
delete config;
config = Config::create();
loadFromFile(config, process->location(Process::ExeLocation, "config.json"));
}
# ifdef XMRIG_FEATURE_EMBEDDED_CONFIG
if (!config->finalize()) {
delete config;
config = Config::create();
loadFromJSON(config, default_config);
}
# endif
if (!config->finalize()) {
if (!config->algorithm().isValid()) {
fprintf(stderr, "No valid algorithm specified. Exiting.\n");
}
else {
fprintf(stderr, "No valid configuration found. Exiting.\n");
}
delete config;
return nullptr;
}
return config;
}
void xmrig::ConfigLoader::release()
{
delete m_watcher;
m_watcher = nullptr;
}
bool xmrig::ConfigLoader::getJSON(const char *fileName, rapidjson::Document &doc)
{
if (Json::get(fileName, doc)) {
return true;
}
if (doc.HasParseError()) {
printf("%s<offset:%zu>: \"%s\"\n", fileName, doc.GetErrorOffset(), rapidjson::GetParseError_En(doc.GetParseError()));
}
else {
fprintf(stderr, "unable to open \"%s\".\n", fileName);
}
return false;
}
bool xmrig::ConfigLoader::parseArg(xmrig::IConfig *config, int key, const char *arg)
{
if (key == IConfig::ConfigKey) {
return loadFromFile(config, arg);
}
return config->parseString(key, arg);
}
void xmrig::ConfigLoader::parseJSON(xmrig::IConfig *config, const struct option *option, const rapidjson::Value &object)
{
if (!option->name || !object.HasMember(option->name)) {
return;
}
const rapidjson::Value &value = object[option->name];
if (option->has_arg) {
if (value.IsString()) {
config->parseString(option->val, value.GetString());
}
else if (value.IsInt64()) {
config->parseUint64(option->val, value.GetUint64());
}
else if (value.IsBool()) {
config->parseBoolean(option->val, value.IsTrue());
}
}
else if (value.IsBool()) {
config->parseBoolean(option->val, value.IsTrue());
}
}

View File

@@ -1,159 +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-2019 XMR-Stak <https://github.com/fireice-uk>, <https://github.com/psychocrypt>
* Copyright 2018-2019 SChernykh <https://github.com/SChernykh>
* Copyright 2016-2019 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 <string.h>
#include <thread>
#ifdef _MSC_VER
# include <intrin.h>
#else
# include <cpuid.h>
#endif
#ifndef bit_AES
# define bit_AES (1 << 25)
#endif
#ifndef bit_OSXSAVE
# define bit_OSXSAVE (1 << 27)
#endif
#ifndef bit_AVX2
# define bit_AVX2 (1 << 5)
#endif
#include "common/cpu/BasicCpuInfo.h"
#define VENDOR_ID (0)
#define PROCESSOR_INFO (1)
#define CACHE_TLB_DESCRIPTOR (2)
#define EXTENDED_FEATURES (7)
#define PROCESSOR_BRAND_STRING_1 (0x80000002)
#define PROCESSOR_BRAND_STRING_2 (0x80000003)
#define PROCESSOR_BRAND_STRING_3 (0x80000004)
#define EAX_Reg (0)
#define EBX_Reg (1)
#define ECX_Reg (2)
#define EDX_Reg (3)
#ifdef _MSC_VER
static inline void cpuid(int level, int output[4]) {
__cpuid(output, level);
}
#else
static inline void cpuid(int level, int output[4]) {
int a, b, c, d;
__cpuid_count(level, 0, a, b, c, d);
output[0] = a;
output[1] = b;
output[2] = c;
output[3] = d;
}
#endif
static inline void cpu_brand_string(char* s) {
int32_t cpu_info[4] = { 0 };
cpuid(VENDOR_ID, cpu_info);
if (cpu_info[EAX_Reg] >= 4) {
for (int i = 0; i < 4; i++) {
cpuid(0x80000002 + i, cpu_info);
memcpy(s, cpu_info, sizeof(cpu_info));
s += 16;
}
}
}
static inline bool has_aes_ni()
{
int32_t cpu_info[4] = { 0 };
cpuid(PROCESSOR_INFO, cpu_info);
return (cpu_info[ECX_Reg] & bit_AES) != 0;
}
static inline bool has_avx2()
{
int32_t cpu_info[4] = { 0 };
cpuid(EXTENDED_FEATURES, cpu_info);
return (cpu_info[EBX_Reg] & bit_AVX2) != 0;
}
static inline bool has_ossave()
{
int32_t cpu_info[4] = { 0 };
cpuid(PROCESSOR_INFO, cpu_info);
return (cpu_info[ECX_Reg] & bit_OSXSAVE) != 0;
}
xmrig::BasicCpuInfo::BasicCpuInfo() :
m_assembly(ASM_NONE),
m_aes(has_aes_ni()),
m_avx2(has_avx2() && has_ossave()),
m_brand(),
m_threads(std::thread::hardware_concurrency())
{
cpu_brand_string(m_brand);
# ifndef XMRIG_NO_ASM
if (hasAES()) {
char vendor[13] = { 0 };
int32_t data[4] = { 0 };
cpuid(0, data);
memcpy(vendor + 0, &data[1], 4);
memcpy(vendor + 4, &data[3], 4);
memcpy(vendor + 8, &data[2], 4);
if (memcmp(vendor, "GenuineIntel", 12) == 0) {
m_assembly = ASM_INTEL;
}
else if (memcmp(vendor, "AuthenticAMD", 12) == 0) {
m_assembly = ASM_RYZEN;
}
}
# endif
}
size_t xmrig::BasicCpuInfo::optimalThreadsCount(size_t memSize, int maxCpuUsage) const
{
const size_t count = threads() / 2;
return count < 1 ? 1 : count;
}

View File

@@ -1,73 +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-2019 XMR-Stak <https://github.com/fireice-uk>, <https://github.com/psychocrypt>
* Copyright 2018-2019 SChernykh <https://github.com/SChernykh>
* Copyright 2016-2019 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_BASICCPUINFO_H
#define XMRIG_BASICCPUINFO_H
#include "common/interfaces/ICpuInfo.h"
namespace xmrig {
class BasicCpuInfo : public ICpuInfo
{
public:
BasicCpuInfo();
protected:
size_t optimalThreadsCount(size_t memSize, int maxCpuUsage) const override;
inline Assembly assembly() const override { return m_assembly; }
inline bool hasAES() const override { return m_aes; }
inline bool hasAVX2() const override { return m_avx2; }
inline bool isSupported() const override { return true; }
inline const char *brand() const override { return m_brand; }
inline int32_t cores() const override { return -1; }
inline int32_t L2() const override { return -1; }
inline int32_t L3() const override { return -1; }
inline int32_t nodes() const override { return -1; }
inline int32_t sockets() const override { return 1; }
inline int32_t threads() const override { return m_threads; }
# if defined(__x86_64__) || defined(_M_AMD64) || defined (__arm64__) || defined (__aarch64__)
inline bool isX64() const override { return true; }
# else
inline bool isX64() const override { return false; }
# endif
private:
Assembly m_assembly;
bool m_aes;
bool m_avx2;
char m_brand[64];
int32_t m_threads;
};
} /* namespace xmrig */
#endif /* XMRIG_BASICCPUINFO_H */

View File

@@ -1,58 +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-2019 XMR-Stak <https://github.com/fireice-uk>, <https://github.com/psychocrypt>
* Copyright 2018-2019 SChernykh <https://github.com/SChernykh>
* Copyright 2016-2019 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 <string.h>
#include <thread>
#if __ARM_FEATURE_CRYPTO
# include <sys/auxv.h>
# include <asm/hwcap.h>
#endif
#include "common/cpu/BasicCpuInfo.h"
xmrig::BasicCpuInfo::BasicCpuInfo() :
m_aes(false),
m_avx2(false),
m_brand(),
m_threads(std::thread::hardware_concurrency())
{
# ifdef XMRIG_ARMv8
memcpy(m_brand, "ARMv8", 5);
# else
memcpy(m_brand, "ARMv7", 5);
# endif
# if __ARM_FEATURE_CRYPTO
m_aes = getauxval(AT_HWCAP) & HWCAP_AES;
# endif
}
size_t xmrig::BasicCpuInfo::optimalThreadsCount(size_t memSize, int maxCpuUsage) const
{
return threads();
}

View File

@@ -1,57 +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 2016-2017 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 "common/cpu/BasicCpuInfo.h"
#include "common/cpu/Cpu.h"
static xmrig::ICpuInfo *cpuInfo = nullptr;
xmrig::ICpuInfo *xmrig::Cpu::info()
{
assert(cpuInfo != nullptr);
return cpuInfo;
}
void xmrig::Cpu::init()
{
assert(cpuInfo == nullptr);
cpuInfo = new BasicCpuInfo();
}
void xmrig::Cpu::release()
{
assert(cpuInfo != nullptr);
delete cpuInfo;
cpuInfo = nullptr;
}

View File

@@ -1,297 +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 Lee Clagett <https://github.com/vtnerd>
* 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 <string.h>
#include <stdlib.h>
#include <stdio.h>
#include "common/crypto/Algorithm.h"
#ifdef _MSC_VER
# define strncasecmp _strnicmp
# define strcasecmp _stricmp
#endif
#ifndef ARRAY_SIZE
# define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]))
#endif
struct AlgoData
{
const char *name;
const char *shortName;
xmrig::Algo algo;
xmrig::Variant variant;
};
static AlgoData const algorithms[] = {
{ "cryptonight", "cn", xmrig::CRYPTONIGHT, xmrig::VARIANT_AUTO },
{ "cryptonight/0", "cn/0", xmrig::CRYPTONIGHT, xmrig::VARIANT_0 },
{ "cryptonight/1", "cn/1", xmrig::CRYPTONIGHT, xmrig::VARIANT_1 },
{ "cryptonight/xtl", "cn/xtl", xmrig::CRYPTONIGHT, xmrig::VARIANT_XTL },
{ "cryptonight/msr", "cn/msr", xmrig::CRYPTONIGHT, xmrig::VARIANT_MSR },
{ "cryptonight/xao", "cn/xao", xmrig::CRYPTONIGHT, xmrig::VARIANT_XAO },
{ "cryptonight/rto", "cn/rto", xmrig::CRYPTONIGHT, xmrig::VARIANT_RTO },
{ "cryptonight/2", "cn/2", xmrig::CRYPTONIGHT, xmrig::VARIANT_2 },
{ "cryptonight/half", "cn/half", xmrig::CRYPTONIGHT, xmrig::VARIANT_HALF },
{ "cryptonight/xtlv9", "cn/xtlv9", xmrig::CRYPTONIGHT, xmrig::VARIANT_HALF },
{ "cryptonight/wow", "cn/wow", xmrig::CRYPTONIGHT, xmrig::VARIANT_WOW },
{ "cryptonight/r", "cn/r", xmrig::CRYPTONIGHT, xmrig::VARIANT_4 },
{ "cryptonight/rwz", "cn/rwz", xmrig::CRYPTONIGHT, xmrig::VARIANT_RWZ },
{ "cryptonight/zls", "cn/zls", xmrig::CRYPTONIGHT, xmrig::VARIANT_ZLS },
{ "cryptonight/double", "cn/double", xmrig::CRYPTONIGHT, xmrig::VARIANT_DOUBLE },
# ifndef XMRIG_NO_AEON
{ "cryptonight-lite", "cn-lite", xmrig::CRYPTONIGHT_LITE, xmrig::VARIANT_AUTO },
{ "cryptonight-light", "cn-light", xmrig::CRYPTONIGHT_LITE, xmrig::VARIANT_AUTO },
{ "cryptonight-lite/0", "cn-lite/0", xmrig::CRYPTONIGHT_LITE, xmrig::VARIANT_0 },
{ "cryptonight-lite/1", "cn-lite/1", xmrig::CRYPTONIGHT_LITE, xmrig::VARIANT_1 },
# endif
# ifndef XMRIG_NO_SUMO
{ "cryptonight-heavy", "cn-heavy", xmrig::CRYPTONIGHT_HEAVY, xmrig::VARIANT_AUTO },
{ "cryptonight-heavy/0", "cn-heavy/0", xmrig::CRYPTONIGHT_HEAVY, xmrig::VARIANT_0 },
{ "cryptonight-heavy/xhv", "cn-heavy/xhv", xmrig::CRYPTONIGHT_HEAVY, xmrig::VARIANT_XHV },
{ "cryptonight-heavy/tube", "cn-heavy/tube", xmrig::CRYPTONIGHT_HEAVY, xmrig::VARIANT_TUBE },
# endif
# ifndef XMRIG_NO_CN_PICO
{ "cryptonight-pico/trtl", "cn-pico/trtl", xmrig::CRYPTONIGHT_PICO, xmrig::VARIANT_TRTL },
{ "cryptonight-pico", "cn-pico", xmrig::CRYPTONIGHT_PICO, xmrig::VARIANT_TRTL },
{ "cryptonight-turtle", "cn-trtl", xmrig::CRYPTONIGHT_PICO, xmrig::VARIANT_TRTL },
{ "cryptonight-ultralite", "cn-ultralite", xmrig::CRYPTONIGHT_PICO, xmrig::VARIANT_TRTL },
{ "cryptonight_turtle", "cn_turtle", xmrig::CRYPTONIGHT_PICO, xmrig::VARIANT_TRTL },
# endif
# ifndef XMRIG_NO_CN_GPU
{ "cryptonight/gpu", "cn/gpu", xmrig::CRYPTONIGHT, xmrig::VARIANT_GPU },
# endif
};
#ifdef XMRIG_PROXY_PROJECT
static AlgoData const xmrStakAlgorithms[] = {
{ "cryptonight-monerov7", nullptr, xmrig::CRYPTONIGHT, xmrig::VARIANT_1 },
{ "cryptonight_v7", nullptr, xmrig::CRYPTONIGHT, xmrig::VARIANT_1 },
{ "cryptonight-monerov8", nullptr, xmrig::CRYPTONIGHT, xmrig::VARIANT_2 },
{ "cryptonight_v8", nullptr, xmrig::CRYPTONIGHT, xmrig::VARIANT_2 },
{ "cryptonight_v7_stellite", nullptr, xmrig::CRYPTONIGHT, xmrig::VARIANT_XTL },
{ "cryptonight_lite", nullptr, xmrig::CRYPTONIGHT_LITE, xmrig::VARIANT_0 },
{ "cryptonight-aeonv7", nullptr, xmrig::CRYPTONIGHT_LITE, xmrig::VARIANT_1 },
{ "cryptonight_lite_v7", nullptr, xmrig::CRYPTONIGHT_LITE, xmrig::VARIANT_1 },
{ "cryptonight_heavy", nullptr, xmrig::CRYPTONIGHT_HEAVY, xmrig::VARIANT_0 },
{ "cryptonight_haven", nullptr, xmrig::CRYPTONIGHT_HEAVY, xmrig::VARIANT_XHV },
{ "cryptonight_masari", nullptr, xmrig::CRYPTONIGHT, xmrig::VARIANT_MSR },
{ "cryptonight_masari", nullptr, xmrig::CRYPTONIGHT, xmrig::VARIANT_MSR },
{ "cryptonight-bittube2", nullptr, xmrig::CRYPTONIGHT_HEAVY, xmrig::VARIANT_TUBE }, // bittube-miner
{ "cryptonight_alloy", nullptr, xmrig::CRYPTONIGHT, xmrig::VARIANT_XAO }, // xmr-stak-alloy
{ "cryptonight_turtle", nullptr, xmrig::CRYPTONIGHT_PICO, xmrig::VARIANT_TRTL },
{ "cryptonight_gpu", nullptr, xmrig::CRYPTONIGHT, xmrig::VARIANT_GPU },
{ "cryptonight_r", nullptr, xmrig::CRYPTONIGHT, xmrig::VARIANT_4 },
};
#endif
static const char *variants[] = {
"0",
"1",
"tube",
"xtl",
"msr",
"xhv",
"xao",
"rto",
"2",
"half",
"trtl",
"gpu",
"wow",
"r",
"rwz",
"zls",
"double"
};
static_assert(xmrig::VARIANT_MAX == ARRAY_SIZE(variants), "variants size mismatch");
bool xmrig::Algorithm::isValid() const
{
if (m_algo == INVALID_ALGO) {
return false;
}
for (size_t i = 0; i < ARRAY_SIZE(algorithms); i++) {
if (algorithms[i].algo == m_algo && algorithms[i].variant == m_variant) {
return true;
}
}
return false;
}
const char *xmrig::Algorithm::variantName() const
{
if (m_variant == VARIANT_AUTO) {
return "auto";
}
return variants[m_variant];
}
void xmrig::Algorithm::parseAlgorithm(const char *algo)
{
m_algo = INVALID_ALGO;
m_variant = VARIANT_AUTO;
assert(algo != nullptr);
if (algo == nullptr || strlen(algo) < 1) {
return;
}
if (*algo == '!') {
m_flags |= Forced;
return parseAlgorithm(algo + 1);
}
for (size_t i = 0; i < ARRAY_SIZE(algorithms); i++) {
if ((strcasecmp(algo, algorithms[i].name) == 0) || (strcasecmp(algo, algorithms[i].shortName) == 0)) {
m_algo = algorithms[i].algo;
m_variant = algorithms[i].variant;
break;
}
}
if (m_algo == INVALID_ALGO) {
assert(false);
}
}
void xmrig::Algorithm::parseVariant(const char *variant)
{
m_variant = VARIANT_AUTO;
if (variant == nullptr || strlen(variant) < 1) {
return;
}
if (*variant == '!') {
m_flags |= Forced;
return parseVariant(variant + 1);
}
for (size_t i = 0; i < ARRAY_SIZE(variants); i++) {
if (strcasecmp(variant, variants[i]) == 0) {
m_variant = static_cast<Variant>(i);
return;
}
}
if (strcasecmp(variant, "xtlv9") == 0) {
m_variant = VARIANT_HALF;
}
}
void xmrig::Algorithm::parseVariant(int variant)
{
assert(variant >= -1 && variant <= 2);
switch (variant) {
case -1:
case 0:
case 1:
m_variant = static_cast<Variant>(variant);
break;
case 2:
m_variant = VARIANT_2;
break;
default:
break;
}
}
void xmrig::Algorithm::setAlgo(Algo algo)
{
m_algo = algo;
if (m_algo == CRYPTONIGHT_PICO && m_variant == VARIANT_AUTO) {
m_variant = xmrig::VARIANT_TRTL;
}
}
#ifdef XMRIG_PROXY_PROJECT
void xmrig::Algorithm::parseXmrStakAlgorithm(const char *algo)
{
m_algo = INVALID_ALGO;
m_variant = VARIANT_AUTO;
assert(algo != nullptr);
if (algo == nullptr) {
return;
}
for (size_t i = 0; i < ARRAY_SIZE(xmrStakAlgorithms); i++) {
if (strcasecmp(algo, xmrStakAlgorithms[i].name) == 0) {
m_algo = xmrStakAlgorithms[i].algo;
m_variant = xmrStakAlgorithms[i].variant;
break;
}
}
if (m_algo == INVALID_ALGO) {
assert(false);
}
}
#endif
const char *xmrig::Algorithm::name(bool shortName) const
{
for (size_t i = 0; i < ARRAY_SIZE(algorithms); i++) {
if (algorithms[i].algo == m_algo && algorithms[i].variant == m_variant) {
return shortName ? algorithms[i].shortName : algorithms[i].name;
}
}
return "invalid";
}

View File

@@ -1,103 +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 Lee Clagett <https://github.com/vtnerd>
* 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_ALGORITHM_H
#define XMRIG_ALGORITHM_H
#include <vector>
#include "common/xmrig.h"
namespace xmrig {
class Algorithm
{
public:
enum Flags {
None = 0,
Forced = 1
};
inline Algorithm() :
m_algo(INVALID_ALGO),
m_flags(0),
m_variant(VARIANT_AUTO)
{}
inline Algorithm(Algo algo, Variant variant) :
m_flags(0),
m_variant(variant)
{
setAlgo(algo);
}
inline Algorithm(const char *algo) :
m_flags(0)
{
parseAlgorithm(algo);
}
inline Algo algo() const { return m_algo; }
inline bool isEqual(const Algorithm &other) const { return m_algo == other.m_algo && m_variant == other.m_variant; }
inline bool isForced() const { return m_flags & Forced; }
inline const char *name() const { return name(false); }
inline const char *shortName() const { return name(true); }
inline int flags() const { return m_flags; }
inline Variant variant() const { return m_variant; }
inline void setVariant(Variant variant) { m_variant = variant; }
inline bool operator!=(const Algorithm &other) const { return !isEqual(other); }
inline bool operator==(const Algorithm &other) const { return isEqual(other); }
bool isValid() const;
const char *variantName() const;
void parseAlgorithm(const char *algo);
void parseVariant(const char *variant);
void parseVariant(int variant);
void setAlgo(Algo algo);
# ifdef XMRIG_PROXY_PROJECT
void parseXmrStakAlgorithm(const char *algo);
# endif
private:
const char *name(bool shortName) const;
Algo m_algo;
int m_flags;
Variant m_variant;
};
typedef std::vector<xmrig::Algorithm> Algorithms;
} /* namespace xmrig */
#endif /* __ALGORITHM_H__ */

View File

@@ -1,121 +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/>.
*/
#ifndef XMRIG_XMRIG_H
#define XMRIG_XMRIG_H
namespace xmrig
{
enum Algo {
INVALID_ALGO = -1,
CRYPTONIGHT, /* CryptoNight (2 MB) */
CRYPTONIGHT_LITE, /* CryptoNight (1 MB) */
CRYPTONIGHT_HEAVY, /* CryptoNight (4 MB) */
CRYPTONIGHT_PICO, /* CryptoNight (256 KB) */
ALGO_MAX
};
//--av=1 For CPUs with hardware AES.
//--av=2 Lower power mode (double hash) of 1.
//--av=3 Software AES implementation.
//--av=4 Lower power mode (double hash) of 3.
enum AlgoVariant {
AV_AUTO, // --av=0 Automatic mode.
AV_SINGLE, // --av=1 Single hash mode
AV_DOUBLE, // --av=2 Double hash mode
AV_SINGLE_SOFT, // --av=3 Single hash mode (Software AES)
AV_DOUBLE_SOFT, // --av=4 Double hash mode (Software AES)
AV_TRIPLE, // --av=5 Triple hash mode
AV_QUAD, // --av=6 Quard hash mode
AV_PENTA, // --av=7 Penta hash mode
AV_TRIPLE_SOFT, // --av=8 Triple hash mode (Software AES)
AV_QUAD_SOFT, // --av=9 Quard hash mode (Software AES)
AV_PENTA_SOFT, // --av=10 Penta hash mode (Software AES)
AV_MAX
};
enum Variant {
VARIANT_AUTO = -1, // Autodetect
VARIANT_0 = 0, // Original CryptoNight or CryptoNight-Heavy
VARIANT_1 = 1, // CryptoNight variant 1 also known as Monero7 and CryptoNightV7
VARIANT_TUBE = 2, // Modified CryptoNight-Heavy (TUBE only)
VARIANT_XTL = 3, // Modified CryptoNight variant 1 (Stellite only)
VARIANT_MSR = 4, // Modified CryptoNight variant 1 (Masari only)
VARIANT_XHV = 5, // Modified CryptoNight-Heavy (Haven Protocol only)
VARIANT_XAO = 6, // Modified CryptoNight variant 0 (Alloy only)
VARIANT_RTO = 7, // Modified CryptoNight variant 1 (Arto only)
VARIANT_2 = 8, // CryptoNight variant 2
VARIANT_HALF = 9, // CryptoNight variant 2 with half iterations (Masari/Stellite)
VARIANT_TRTL = 10, // CryptoNight Turtle (TRTL)
VARIANT_GPU = 11, // CryptoNight-GPU (Ryo)
VARIANT_WOW = 12, // CryptoNightR (Wownero)
VARIANT_4 = 13, // CryptoNightR (Monero's variant 4)
VARIANT_RWZ = 14, // CryptoNight variant 2 with 3/4 iterations and reversed shuffle operation (Graft)
VARIANT_ZLS = 15, // CryptoNight variant 2 with 3/4 iterations (Zelerius)
VARIANT_DOUBLE = 16, // CryptoNight variant 2 with double iterations (X-CASH)
VARIANT_MAX
};
enum AlgoVerify {
VERIFY_HW_AES = 1,
VERIFY_SOFT_AES = 2
};
enum AesMode {
AES_AUTO,
AES_HW,
AES_SOFT
};
enum OclVendor {
OCL_VENDOR_UNKNOWN = -2,
OCL_VENDOR_MANUAL = -1,
OCL_VENDOR_AMD = 0,
OCL_VENDOR_NVIDIA = 1,
OCL_VENDOR_INTEL = 2
};
enum Assembly {
ASM_NONE,
ASM_AUTO,
ASM_INTEL,
ASM_RYZEN,
ASM_BULLDOZER,
ASM_MAX
};
} /* namespace xmrig */
#endif /* XMRIG_XMRIG_H */

View File

@@ -1,14 +1,16 @@
{
"access-log-file": null,
"access-password": null,
"algo": "cryptonight",
"algo-ext": true,
"api": {
"id": null,
"worker-id": null
},
"http": {
"enabled": false,
"host": "127.0.0.1",
"port": 0,
"access-token": null,
"id": null,
"worker-id": null,
"ipv6": false,
"restricted": true
},
"background": false,
@@ -26,20 +28,21 @@
],
"colors": true,
"custom-diff": 0,
"donate-level": 2,
"donate-level": 0,
"log-file": null,
"mode": "nicehash",
"pools": [
{
"algo": null,
"url": "donate.v2.xmrig.com:5555",
"user": "YOUR_WALLET",
"pass": "x",
"rig-id": null,
"keepalive": false,
"variant": -1,
"enabled": true,
"tls": false,
"tls-fingerprint": null
"tls-fingerprint": null,
"daemon": false
}
],
"retries": 2,
@@ -54,6 +57,7 @@
"dhparam": null
},
"user-agent": null,
"syslog": false,
"verbose": false,
"watch": true,
"workers": true

View File

@@ -26,80 +26,50 @@
#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/Platform.h"
#include "core/config/Config.h"
#include "core/Controller.h"
#include "proxy/Proxy.h"
#ifdef HAVE_SYSLOG_H
# include "base/io/log/backends/SysLog.h"
#endif
#ifdef XMRIG_FEATURE_API
# include "api/Api.h"
#endif
class xmrig::ControllerPrivate
{
public:
inline ControllerPrivate(Process *process) :
process(process),
proxy(nullptr),
config(nullptr)
{}
inline ~ControllerPrivate()
{
# ifdef XMRIG_FEATURE_API
delete api;
# endif
delete proxy;
delete config;
}
Api *api;
Process *process;
Proxy *proxy;
std::vector<IControllerListener *> listeners;
xmrig::Config *config;
};
xmrig::Controller::Controller(Process *process)
: d_ptr(new ControllerPrivate(process))
: Base(process),
m_proxy(nullptr)
{
}
xmrig::Controller::~Controller()
{
delete d_ptr;
delete m_proxy;
}
xmrig::Api *xmrig::Controller::api() const
int xmrig::Controller::init()
{
assert(d_ptr->api != nullptr);
const int rc = Base::init();
if (rc != 0) {
return rc;
}
return d_ptr->api;
m_proxy = new Proxy(this);
return 0;
}
xmrig::Config *xmrig::Controller::config() const
void xmrig::Controller::start()
{
assert(d_ptr->config != nullptr);
Base::start();
return d_ptr->config;
proxy()->connect();
}
void xmrig::Controller::stop()
{
Base::stop();
delete m_proxy;
m_proxy = nullptr;
}
@@ -115,41 +85,9 @@ const std::vector<xmrig::Worker> &xmrig::Controller::workers() const
}
int xmrig::Controller::init()
{
d_ptr->config = Config::load(d_ptr->process, this);
if (!d_ptr->config) {
return 1;
}
# ifdef XMRIG_FEATURE_API
d_ptr->api = new Api(this);
# endif
Platform::init(config()->userAgent());
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->proxy = new Proxy(this);
return 0;
}
xmrig::Proxy *xmrig::Controller::proxy() const
{
return d_ptr->proxy;
return m_proxy;
}
@@ -157,61 +95,3 @@ std::vector<xmrig::Miner*> xmrig::Controller::miners() const
{
return proxy()->miners();
}
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::start()
{
proxy()->connect();
# ifdef XMRIG_FEATURE_API
api()->start();
# endif
save();
}
void xmrig::Controller::stop()
{
# ifdef XMRIG_FEATURE_API
api()->stop();
# endif
ConfigLoader::release();
delete d_ptr->proxy;
d_ptr->proxy = nullptr;
}
void xmrig::Controller::onNewConfig(IConfig *config)
{
Config *previousConfig = d_ptr->config;
d_ptr->config = static_cast<Config*>(config);
for (xmrig::IControllerListener *listener : d_ptr->listeners) {
listener->onConfigChanged(d_ptr->config, previousConfig);
}
delete previousConfig;
}

Some files were not shown because too many files have changed in this diff Show More