Merge branch 'feature-jsonrpc' into dev

This commit is contained in:
XMRig 2019-08-12 21:38:17 +07:00
commit e6db34d86e
20 changed files with 259 additions and 151 deletions

View file

@ -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})

View file

@ -28,7 +28,6 @@
#include <uv.h>
#include "api/Api.h"
#include "App.h"
#include "backend/cpu/Cpu.h"
#include "base/io/Console.h"

View file

@ -1,87 +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 "api/requests/HttpApiRequest.h"
#include "base/net/http/HttpData.h"
#include "rapidjson/error/en.h"
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;
}
}
}
const rapidjson::Value &xmrig::HttpApiRequest::json() const
{
return m_body;
}
xmrig::IApiRequest::Method xmrig::HttpApiRequest::method() const
{
return static_cast<IApiRequest::Method>(m_req.method);
}
void xmrig::HttpApiRequest::accept()
{
using namespace rapidjson;
ApiRequest::accept();
if (!m_parsed && !m_req.body.empty()) {
m_parsed = true;
m_body.Parse<kParseCommentsFlag | kParseTrailingCommasFlag>(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);
m_res.end();
}

View file

@ -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

View file

@ -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"

View file

@ -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;
};

View file

@ -23,7 +23,7 @@
*/
#include "api/requests/ApiRequest.h"
#include "base/api/requests/ApiRequest.h"
xmrig::ApiRequest::ApiRequest(Source source, bool restricted) :

View file

@ -27,7 +27,8 @@
#define XMRIG_APIREQUEST_H
#include "api/interfaces/IApiRequest.h"
#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;
};

View file

@ -0,0 +1,178 @@
/* 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 "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_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 (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;
}
}
}
bool xmrig::HttpApiRequest::accept()
{
using namespace rapidjson;
ApiRequest::accept();
if (m_parsed == 0 && !m_req.body.empty()) {
m_body.Parse<kParseCommentsFlag | kParseTrailingCommasFlag>(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;
}
xmrig::IApiRequest::Method xmrig::HttpApiRequest::method() const
{
return static_cast<IApiRequest::Method>(m_req.method);
}
void xmrig::HttpApiRequest::done(int status)
{
ApiRequest::done(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();
}

View file

@ -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"
@ -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;
};

View file

@ -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

View file

@ -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

View file

@ -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"

View file

@ -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
@ -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

View file

@ -29,7 +29,7 @@
#include <vector>
#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"

View file

@ -34,7 +34,6 @@
#include <time.h>
#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

View file

@ -30,7 +30,7 @@
#include <vector>
#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"