Added pause and resume methods via JSON RPC 2.0 API.

This commit is contained in:
XMRig 2019-08-12 21:13:38 +07:00
parent 2ec257284f
commit 6955f4a484
5 changed files with 156 additions and 38 deletions

View file

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