mirror of
https://github.com/xmrig/xmrig.git
synced 2024-11-18 00:37:46 +00:00
Added pause and resume methods via JSON RPC 2.0 API.
This commit is contained in:
parent
2ec257284f
commit
6955f4a484
5 changed files with 156 additions and 38 deletions
|
@ -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;
|
||||
};
|
||||
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in a new issue