From 2ec257284f5bffce5277c35458d3893430c2d843 Mon Sep 17 00:00:00 2001 From: XMRig Date: Mon, 12 Aug 2019 16:52:16 +0700 Subject: [PATCH 1/2] Common API code moved to base/api. --- CMakeLists.txt | 19 +------------------ src/App.cpp | 1 - src/{ => base}/api/Api.cpp | 8 ++++---- src/{ => base}/api/Api.h | 0 src/{ => base}/api/Httpd.cpp | 4 ++-- src/{ => base}/api/Httpd.h | 0 src/{ => base}/api/interfaces/IApiListener.h | 0 src/{ => base}/api/interfaces/IApiRequest.h | 0 src/{ => base}/api/requests/ApiRequest.cpp | 2 +- src/{ => base}/api/requests/ApiRequest.h | 2 +- .../api/requests/HttpApiRequest.cpp | 2 +- src/{ => base}/api/requests/HttpApiRequest.h | 2 +- src/base/base.cmake | 10 ++++++++++ src/base/kernel/Base.cpp | 17 ++++++++--------- src/base/kernel/Base.h | 2 +- src/core/Miner.cpp | 4 ++-- src/core/Miner.h | 2 +- src/net/Network.cpp | 5 ++--- src/net/Network.h | 2 +- 19 files changed, 36 insertions(+), 46 deletions(-) rename src/{ => base}/api/Api.cpp (97%) rename src/{ => base}/api/Api.h (100%) rename src/{ => base}/api/Httpd.cpp (98%) rename src/{ => base}/api/Httpd.h (100%) rename src/{ => base}/api/interfaces/IApiListener.h (100%) rename src/{ => base}/api/interfaces/IApiRequest.h (100%) rename src/{ => base}/api/requests/ApiRequest.cpp (97%) rename src/{ => base}/api/requests/ApiRequest.h (98%) rename src/{ => base}/api/requests/HttpApiRequest.cpp (98%) rename src/{ => base}/api/requests/HttpApiRequest.h (98%) diff --git a/CMakeLists.txt b/CMakeLists.txt index 7600d556e..152883198 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -32,7 +32,6 @@ set(HEADERS "${HEADERS_BASE}" "${HEADERS_BASE_HTTP}" "${HEADERS_BACKEND}" - src/api/interfaces/IApiListener.h src/App.h src/core/config/Config_default.h src/core/config/Config_platform.h @@ -232,22 +231,6 @@ if (WITH_EMBEDDED_CONFIG) add_definitions(/DXMRIG_FEATURE_EMBEDDED_CONFIG) endif() -if (WITH_HTTP) - set(HTTP_SOURCES - src/api/Api.cpp - src/api/Api.h - src/api/Httpd.cpp - src/api/Httpd.h - src/api/interfaces/IApiRequest.h - src/api/requests/ApiRequest.cpp - src/api/requests/ApiRequest.h - src/api/requests/HttpApiRequest.cpp - src/api/requests/HttpApiRequest.h - ) -else() - set(HTTP_SOURCES "") -endif() - include_directories(src) include_directories(src/3rdparty) include_directories(${UV_INCLUDE_DIR}) @@ -260,5 +243,5 @@ if (WITH_DEBUG_LOG) add_definitions(/DAPP_DEBUG) endif() -add_executable(${CMAKE_PROJECT_NAME} ${HEADERS} ${SOURCES} ${SOURCES_OS} ${SOURCES_CPUID} ${HEADERS_CRYPTO} ${SOURCES_CRYPTO} ${SOURCES_SYSLOG} ${HTTP_SOURCES} ${TLS_SOURCES} ${XMRIG_ASM_SOURCES} ${CN_GPU_SOURCES}) +add_executable(${CMAKE_PROJECT_NAME} ${HEADERS} ${SOURCES} ${SOURCES_OS} ${SOURCES_CPUID} ${HEADERS_CRYPTO} ${SOURCES_CRYPTO} ${SOURCES_SYSLOG} ${TLS_SOURCES} ${XMRIG_ASM_SOURCES} ${CN_GPU_SOURCES}) target_link_libraries(${CMAKE_PROJECT_NAME} ${XMRIG_ASM_LIBRARY} ${OPENSSL_LIBRARIES} ${UV_LIBRARIES} ${EXTRA_LIBS} ${CPUID_LIB}) diff --git a/src/App.cpp b/src/App.cpp index ccbaad4fc..de45a499c 100644 --- a/src/App.cpp +++ b/src/App.cpp @@ -28,7 +28,6 @@ #include -#include "api/Api.h" #include "App.h" #include "backend/cpu/Cpu.h" #include "base/io/Console.h" diff --git a/src/api/Api.cpp b/src/base/api/Api.cpp similarity index 97% rename from src/api/Api.cpp rename to src/base/api/Api.cpp index 4c8e73230..f358ac4b4 100644 --- a/src/api/Api.cpp +++ b/src/base/api/Api.cpp @@ -32,9 +32,9 @@ #include "3rdparty/http-parser/http_parser.h" -#include "api/Api.h" -#include "api/interfaces/IApiListener.h" -#include "api/requests/HttpApiRequest.h" +#include "base/api/Api.h" +#include "base/api/interfaces/IApiListener.h" +#include "base/api/requests/HttpApiRequest.h" #include "base/kernel/Base.h" #include "base/tools/Buffer.h" #include "base/tools/Chrono.h" @@ -45,7 +45,7 @@ #ifdef XMRIG_FEATURE_HTTP -# include "api/Httpd.h" +# include "base/api/Httpd.h" #endif diff --git a/src/api/Api.h b/src/base/api/Api.h similarity index 100% rename from src/api/Api.h rename to src/base/api/Api.h diff --git a/src/api/Httpd.cpp b/src/base/api/Httpd.cpp similarity index 98% rename from src/api/Httpd.cpp rename to src/base/api/Httpd.cpp index 57a112e94..e61e66f1c 100644 --- a/src/api/Httpd.cpp +++ b/src/base/api/Httpd.cpp @@ -24,8 +24,8 @@ #include "3rdparty/http-parser/http_parser.h" -#include "api/Api.h" -#include "api/Httpd.h" +#include "base/api/Api.h" +#include "base/api/Httpd.h" #include "base/io/log/Log.h" #include "base/net/http/HttpApiResponse.h" #include "base/net/http/HttpData.h" diff --git a/src/api/Httpd.h b/src/base/api/Httpd.h similarity index 100% rename from src/api/Httpd.h rename to src/base/api/Httpd.h diff --git a/src/api/interfaces/IApiListener.h b/src/base/api/interfaces/IApiListener.h similarity index 100% rename from src/api/interfaces/IApiListener.h rename to src/base/api/interfaces/IApiListener.h diff --git a/src/api/interfaces/IApiRequest.h b/src/base/api/interfaces/IApiRequest.h similarity index 100% rename from src/api/interfaces/IApiRequest.h rename to src/base/api/interfaces/IApiRequest.h diff --git a/src/api/requests/ApiRequest.cpp b/src/base/api/requests/ApiRequest.cpp similarity index 97% rename from src/api/requests/ApiRequest.cpp rename to src/base/api/requests/ApiRequest.cpp index 3812e4198..da73adee4 100644 --- a/src/api/requests/ApiRequest.cpp +++ b/src/base/api/requests/ApiRequest.cpp @@ -23,7 +23,7 @@ */ -#include "api/requests/ApiRequest.h" +#include "base/api/requests/ApiRequest.h" xmrig::ApiRequest::ApiRequest(Source source, bool restricted) : diff --git a/src/api/requests/ApiRequest.h b/src/base/api/requests/ApiRequest.h similarity index 98% rename from src/api/requests/ApiRequest.h rename to src/base/api/requests/ApiRequest.h index 05716e29d..1fd721f19 100644 --- a/src/api/requests/ApiRequest.h +++ b/src/base/api/requests/ApiRequest.h @@ -27,7 +27,7 @@ #define XMRIG_APIREQUEST_H -#include "api/interfaces/IApiRequest.h" +#include "base/api/interfaces/IApiRequest.h" namespace xmrig { diff --git a/src/api/requests/HttpApiRequest.cpp b/src/base/api/requests/HttpApiRequest.cpp similarity index 98% rename from src/api/requests/HttpApiRequest.cpp rename to src/base/api/requests/HttpApiRequest.cpp index b4dc18107..c3c2dac46 100644 --- a/src/api/requests/HttpApiRequest.cpp +++ b/src/base/api/requests/HttpApiRequest.cpp @@ -23,7 +23,7 @@ */ -#include "api/requests/HttpApiRequest.h" +#include "base/api/requests/HttpApiRequest.h" #include "base/net/http/HttpData.h" #include "rapidjson/error/en.h" diff --git a/src/api/requests/HttpApiRequest.h b/src/base/api/requests/HttpApiRequest.h similarity index 98% rename from src/api/requests/HttpApiRequest.h rename to src/base/api/requests/HttpApiRequest.h index f34d4be5d..dc3eb0377 100644 --- a/src/api/requests/HttpApiRequest.h +++ b/src/base/api/requests/HttpApiRequest.h @@ -27,7 +27,7 @@ #define XMRIG_HTTPAPIREQUEST_H -#include "api/requests/ApiRequest.h" +#include "base/api/requests/ApiRequest.h" #include "base/net/http/HttpApiResponse.h" #include "base/tools/String.h" diff --git a/src/base/base.cmake b/src/base/base.cmake index ef4da1310..bc022c70c 100644 --- a/src/base/base.cmake +++ b/src/base/base.cmake @@ -1,4 +1,5 @@ set(HEADERS_BASE + src/base/api/interfaces/IApiListener.h src/base/io/Console.h src/base/io/json/Json.h src/base/io/json/JsonChain.h @@ -114,6 +115,11 @@ endif() if (WITH_HTTP) set(HEADERS_BASE_HTTP src/3rdparty/http-parser/http_parser.h + src/base/api/Api.h + src/base/api/Httpd.h + src/base/api/interfaces/IApiRequest.h + src/base/api/requests/ApiRequest.h + src/base/api/requests/HttpApiRequest.h src/base/kernel/interfaces/IHttpListener.h src/base/kernel/interfaces/IJsonReader.h src/base/kernel/interfaces/ITcpServerListener.h @@ -129,6 +135,10 @@ if (WITH_HTTP) set(SOURCES_BASE_HTTP src/3rdparty/http-parser/http_parser.c + src/base/api/Api.cpp + src/base/api/Httpd.cpp + src/base/api/requests/ApiRequest.cpp + src/base/api/requests/HttpApiRequest.cpp src/base/net/http/HttpApiResponse.cpp src/base/net/http/HttpClient.cpp src/base/net/http/HttpContext.cpp diff --git a/src/base/kernel/Base.cpp b/src/base/kernel/Base.cpp index 03feef89f..152f6bccd 100644 --- a/src/base/kernel/Base.cpp +++ b/src/base/kernel/Base.cpp @@ -47,15 +47,8 @@ #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 - +# include "base/api/Api.h" +# include "base/api/interfaces/IApiRequest.h" namespace xmrig { @@ -63,6 +56,12 @@ static const char *kConfigPathV1 = "/1/config"; static const char *kConfigPathV2 = "/2/config"; } // namespace xmrig +#endif + + +#ifdef XMRIG_FEATURE_EMBEDDED_CONFIG +# include "core/config/Config_default.h" +#endif class xmrig::BasePrivate diff --git a/src/base/kernel/Base.h b/src/base/kernel/Base.h index 6a33a802a..8eb688664 100644 --- a/src/base/kernel/Base.h +++ b/src/base/kernel/Base.h @@ -26,7 +26,7 @@ #define XMRIG_BASE_H -#include "api/interfaces/IApiListener.h" +#include "base/api/interfaces/IApiListener.h" #include "base/kernel/interfaces/IConfigListener.h" #include "base/kernel/interfaces/IWatcherListener.h" #include "rapidjson/fwd.h" diff --git a/src/core/Miner.cpp b/src/core/Miner.cpp index 4406ce529..801b27c75 100644 --- a/src/core/Miner.cpp +++ b/src/core/Miner.cpp @@ -45,8 +45,8 @@ #ifdef XMRIG_FEATURE_API -# include "api/Api.h" -# include "api/interfaces/IApiRequest.h" +# include "base/api/Api.h" +# include "base/api/interfaces/IApiRequest.h" #endif diff --git a/src/core/Miner.h b/src/core/Miner.h index 035c02058..6fc75cd09 100644 --- a/src/core/Miner.h +++ b/src/core/Miner.h @@ -29,7 +29,7 @@ #include -#include "api/interfaces/IApiListener.h" +#include "base/api/interfaces/IApiListener.h" #include "base/kernel/interfaces/IBaseListener.h" #include "base/kernel/interfaces/ITimerListener.h" #include "crypto/common/Algorithm.h" diff --git a/src/net/Network.cpp b/src/net/Network.cpp index 547a86387..3ab8bec05 100644 --- a/src/net/Network.cpp +++ b/src/net/Network.cpp @@ -34,7 +34,6 @@ #include -#include "api/Api.h" #include "base/io/log/Log.h" #include "base/net/stratum/Client.h" #include "base/net/stratum/SubmitResult.h" @@ -51,8 +50,8 @@ #ifdef XMRIG_FEATURE_API -# include "api/Api.h" -# include "api/interfaces/IApiRequest.h" +# include "base/api/Api.h" +# include "base/api/interfaces/IApiRequest.h" #endif diff --git a/src/net/Network.h b/src/net/Network.h index ddf6d6f39..716ce6105 100644 --- a/src/net/Network.h +++ b/src/net/Network.h @@ -30,7 +30,7 @@ #include -#include "api/interfaces/IApiListener.h" +#include "base/api/interfaces/IApiListener.h" #include "base/kernel/interfaces/IBaseListener.h" #include "base/kernel/interfaces/IStrategyListener.h" #include "base/kernel/interfaces/ITimerListener.h" From 6955f4a484ed47327c316fa68880b8057ecad4f9 Mon Sep 17 00:00:00 2001 From: XMRig Date: Mon, 12 Aug 2019 21:13:38 +0700 Subject: [PATCH 2/2] Added pause and resume methods via JSON RPC 2.0 API. --- src/base/api/interfaces/IApiRequest.h | 15 ++- src/base/api/requests/ApiRequest.h | 31 +++--- src/base/api/requests/HttpApiRequest.cpp | 129 +++++++++++++++++++---- src/base/api/requests/HttpApiRequest.h | 7 +- src/core/Miner.cpp | 12 +++ 5 files changed, 156 insertions(+), 38 deletions(-) diff --git a/src/base/api/interfaces/IApiRequest.h b/src/base/api/interfaces/IApiRequest.h index 8e65a9215..4f74581c8 100644 --- a/src/base/api/interfaces/IApiRequest.h +++ b/src/base/api/interfaces/IApiRequest.h @@ -54,16 +54,28 @@ public: enum RequestType { REQ_UNKNOWN, - REQ_SUMMARY + REQ_SUMMARY, + REQ_JSON_RPC + }; + + + enum ErrorCode : int { + RPC_PARSE_ERROR = -32700, + RPC_INVALID_REQUEST = -32600, + RPC_METHOD_NOT_FOUND = -32601, + RPC_INVALID_PARAMS = -32602 }; virtual ~IApiRequest() = default; + virtual bool accept() = 0; + virtual bool hasParseError() const = 0; virtual bool isDone() const = 0; virtual bool isNew() const = 0; virtual bool isRestricted() const = 0; virtual const rapidjson::Value &json() const = 0; + virtual const String &rpcMethod() const = 0; virtual const String &url() const = 0; virtual int version() const = 0; virtual Method method() const = 0; @@ -71,7 +83,6 @@ public: 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; }; diff --git a/src/base/api/requests/ApiRequest.h b/src/base/api/requests/ApiRequest.h index 1fd721f19..ad4b0c350 100644 --- a/src/base/api/requests/ApiRequest.h +++ b/src/base/api/requests/ApiRequest.h @@ -28,6 +28,7 @@ #include "base/api/interfaces/IApiRequest.h" +#include "base/tools/String.h" namespace xmrig { @@ -40,28 +41,30 @@ public: ~ApiRequest() override; 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, STATE_ACCEPTED, STATE_DONE }; + inline bool accept() override { m_state = STATE_ACCEPTED; return true; } + 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 const String &rpcMethod() const override { return m_rpcMethod; } + 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 done(int) override { m_state = STATE_DONE; } + + int m_version = 1; + RequestType m_type = REQ_UNKNOWN; + State m_state = STATE_NEW; + String m_rpcMethod; + +private: bool m_restricted; Source m_source; - State m_state = STATE_NEW; }; diff --git a/src/base/api/requests/HttpApiRequest.cpp b/src/base/api/requests/HttpApiRequest.cpp index c3c2dac46..ed13e47d2 100644 --- a/src/base/api/requests/HttpApiRequest.cpp +++ b/src/base/api/requests/HttpApiRequest.cpp @@ -23,14 +23,45 @@ */ +#include "3rdparty/http-parser/http_parser.h" #include "base/api/requests/HttpApiRequest.h" +#include "base/io/json/Json.h" #include "base/net/http/HttpData.h" #include "rapidjson/error/en.h" +namespace xmrig { + + +static const char *kError = "error"; +static const char *kId = "id"; +static const char *kResult = "result"; + + +static inline const char *rpcError(int code) { + switch (code) { + case IApiRequest::RPC_PARSE_ERROR: + return "Parse error"; + + case IApiRequest::RPC_INVALID_REQUEST: + return "Invalid Request"; + + case IApiRequest::RPC_METHOD_NOT_FOUND: + return "Method not found"; + + case IApiRequest::RPC_INVALID_PARAMS: + return "Invalid params"; + } + + return "Internal error"; +} + + +} // namespace xmrig + + 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()) @@ -41,6 +72,28 @@ xmrig::HttpApiRequest::HttpApiRequest(const HttpData &req, bool restricted) : } } + if (method() == METHOD_POST && url() == "/json_rpc") { + m_type = REQ_JSON_RPC; + accept(); + + if (hasParseError()) { + done(RPC_PARSE_ERROR); + + return; + } + + m_rpcMethod = Json::getString(json(), "method"); + if (m_rpcMethod.isEmpty()) { + done(RPC_INVALID_REQUEST); + + return; + } + + m_state = STATE_NEW; + + return; + } + if (url().size() > 4) { if (memcmp(url().data(), "/2/", 3) == 0) { m_version = 2; @@ -49,6 +102,31 @@ xmrig::HttpApiRequest::HttpApiRequest(const HttpData &req, bool restricted) : } +bool xmrig::HttpApiRequest::accept() +{ + using namespace rapidjson; + + ApiRequest::accept(); + + if (m_parsed == 0 && !m_req.body.empty()) { + m_body.Parse(m_req.body.c_str()); + m_parsed = m_body.HasParseError() ? 2 : 1; + + if (!hasParseError()) { + return true; + } + + if (type() != REQ_JSON_RPC) { + reply().AddMember(StringRef(kError), StringRef(GetParseError_En(m_body.GetParseError())), doc().GetAllocator()); + } + + return false; + } + + return hasParseError(); +} + + const rapidjson::Value &xmrig::HttpApiRequest::json() const { return m_body; @@ -61,27 +139,40 @@ xmrig::IApiRequest::Method xmrig::HttpApiRequest::method() const } -void xmrig::HttpApiRequest::accept() -{ - using namespace rapidjson; - - ApiRequest::accept(); - - if (!m_parsed && !m_req.body.empty()) { - m_parsed = true; - m_body.Parse(m_req.body.c_str()); - - if (m_body.HasParseError()) { - reply().AddMember("error", StringRef(GetParseError_En(m_body.GetParseError())), doc().GetAllocator());; - } - } -} - - void xmrig::HttpApiRequest::done(int status) { ApiRequest::done(status); - m_res.setStatus(status); + if (type() == REQ_JSON_RPC) { + using namespace rapidjson; + auto &allocator = doc().GetAllocator(); + + m_res.setStatus(HTTP_STATUS_OK); + + if (status != HTTP_STATUS_OK) { + if (status == HTTP_STATUS_NOT_FOUND) { + status = RPC_METHOD_NOT_FOUND; + } + + Value error(kObjectType); + error.AddMember("code", status, allocator); + error.AddMember("message", StringRef(rpcError(status)), allocator); + + reply().AddMember(StringRef(kError), error, allocator); + } + else if (!reply().HasMember(kResult)) { + Value result(kObjectType); + result.AddMember("status", "OK", allocator); + + reply().AddMember(StringRef(kResult), result, allocator); + } + + reply().AddMember("jsonrpc", "2.0", allocator); + reply().AddMember(StringRef(kId), Value().CopyFrom(Json::getValue(json(), kId), allocator), allocator); + } + else { + m_res.setStatus(status); + } + m_res.end(); } diff --git a/src/base/api/requests/HttpApiRequest.h b/src/base/api/requests/HttpApiRequest.h index dc3eb0377..309b5a6b0 100644 --- a/src/base/api/requests/HttpApiRequest.h +++ b/src/base/api/requests/HttpApiRequest.h @@ -44,19 +44,20 @@ public: HttpApiRequest(const HttpData &req, bool restricted); protected: + inline bool hasParseError() const override { return m_parsed == 2; } + inline const String &url() const override { return m_url; } inline rapidjson::Document &doc() override { return m_res.doc(); } inline rapidjson::Value &reply() override { return m_res.doc(); } - inline const String &url() const override { return m_url; } + bool accept() override; const rapidjson::Value &json() const override; Method method() const override; - void accept() override; void done(int status) override; private: - bool m_parsed; const HttpData &m_req; HttpApiResponse m_res; + int m_parsed = 0; rapidjson::Document m_body; String m_url; }; diff --git a/src/core/Miner.cpp b/src/core/Miner.cpp index 801b27c75..26a5d7e75 100644 --- a/src/core/Miner.cpp +++ b/src/core/Miner.cpp @@ -477,5 +477,17 @@ void xmrig::Miner::onRequest(IApiRequest &request) d_ptr->getBackends(request.reply(), request.doc()); } } + else if (request.type() == IApiRequest::REQ_JSON_RPC) { + if (request.rpcMethod() == "pause") { + request.accept(); + + setEnabled(false); + } + else if (request.rpcMethod() == "resume") { + request.accept(); + + setEnabled(true); + } + } } #endif