Restored "GET /1/summary" endpoint.

This commit is contained in:
XMRig 2019-07-19 02:24:37 +07:00
parent 691b2fabbf
commit d9164c0b7b
14 changed files with 199 additions and 108 deletions

View file

@ -120,7 +120,7 @@ void xmrig::Api::exec(IApiRequest &request)
{ {
using namespace rapidjson; 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(); auto &allocator = request.doc().GetAllocator();
request.accept(); request.accept();
@ -145,14 +145,6 @@ void xmrig::Api::exec(IApiRequest &request)
features.PushBack("tls", allocator); features.PushBack("tls", allocator);
# endif # endif
request.reply().AddMember("features", features, allocator); request.reply().AddMember("features", features, allocator);
Value algorithms(kArrayType);
for (int i = 0; i < Algorithm::MAX; ++i) {
algorithms.PushBack(StringRef(Algorithm(static_cast<Algorithm::Id>(i)).shortName()), allocator);
}
request.reply().AddMember("algorithms", algorithms, allocator);
} }
for (IApiListener *listener : m_listeners) { for (IApiListener *listener : m_listeners) {

View file

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

View file

@ -4,7 +4,9 @@
* Copyright 2014 Lucas Jones <https://github.com/lucasjones> * Copyright 2014 Lucas Jones <https://github.com/lucasjones>
* Copyright 2014-2016 Wolf9466 <https://github.com/OhGodAPet> * Copyright 2014-2016 Wolf9466 <https://github.com/OhGodAPet>
* Copyright 2016 Jay D Dee <jayddee246@gmail.com> * 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 * 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 * 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 ~IApiRequest() = default;
virtual bool isDone() const = 0; virtual bool isDone() const = 0;
@ -57,9 +65,11 @@ public:
virtual bool isRestricted() const = 0; virtual bool isRestricted() const = 0;
virtual const rapidjson::Value &json() const = 0; virtual const rapidjson::Value &json() const = 0;
virtual const String &url() const = 0; virtual const String &url() const = 0;
virtual int version() const = 0;
virtual Method method() const = 0; virtual Method method() const = 0;
virtual rapidjson::Document &doc() = 0; virtual rapidjson::Document &doc() = 0;
virtual rapidjson::Value &reply() = 0; virtual rapidjson::Value &reply() = 0;
virtual RequestType type() const = 0;
virtual Source source() const = 0; virtual Source source() const = 0;
virtual void accept() = 0; virtual void accept() = 0;
virtual void done(int status) = 0; virtual void done(int status) = 0;

View file

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

View file

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

View file

@ -35,6 +35,17 @@ xmrig::HttpApiRequest::HttpApiRequest(const HttpData &req, bool restricted) :
m_res(req.id()), m_res(req.id()),
m_url(req.url.c_str()) 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

@ -38,18 +38,6 @@
#include "version.h" #include "version.h"
static inline rapidjson::Value normalize(double d)
{
using namespace rapidjson;
if (!std::isnormal(d)) {
return Value(kNullType);
}
return Value(floor(d * 100.0) / 100.0);
}
xmrig::ApiRouter::ApiRouter(Base *base) : xmrig::ApiRouter::ApiRouter(Base *base) :
m_base(base) m_base(base)
{ {
@ -64,12 +52,7 @@ xmrig::ApiRouter::~ApiRouter()
void xmrig::ApiRouter::onRequest(IApiRequest &request) void xmrig::ApiRouter::onRequest(IApiRequest &request)
{ {
if (request.method() == IApiRequest::METHOD_GET) { if (request.method() == IApiRequest::METHOD_GET) {
if (request.url() == "/1/summary" || request.url() == "/api.json") { if (request.url() == "/1/threads") {
request.accept();
getMiner(request.reply(), request.doc());
// getHashrate(request.reply(), request.doc());
}
else if (request.url() == "/1/threads") {
request.accept(); request.accept();
getThreads(request.reply(), request.doc()); getThreads(request.reply(), request.doc());
} }
@ -96,57 +79,6 @@ void xmrig::ApiRouter::onRequest(IApiRequest &request)
} }
//void xmrig::ApiRouter::getHashrate(rapidjson::Value &reply, rapidjson::Document &doc) const
//{
// using namespace rapidjson;
// auto &allocator = doc.GetAllocator();
// Value hashrate(kObjectType);
// Value total(kArrayType);
// Value threads(kArrayType);
// const Hashrate *hr = WorkersLegacy::hashrate();
// total.PushBack(normalize(hr->calc(Hashrate::ShortInterval)), allocator);
// total.PushBack(normalize(hr->calc(Hashrate::MediumInterval)), allocator);
// total.PushBack(normalize(hr->calc(Hashrate::LargeInterval)), allocator);
// for (size_t i = 0; i < WorkersLegacy::threads(); i++) {
// Value thread(kArrayType);
// thread.PushBack(normalize(hr->calc(i, Hashrate::ShortInterval)), allocator);
// thread.PushBack(normalize(hr->calc(i, Hashrate::MediumInterval)), allocator);
// thread.PushBack(normalize(hr->calc(i, Hashrate::LargeInterval)), allocator);
// threads.PushBack(thread, allocator);
// }
// hashrate.AddMember("total", total, allocator);
// hashrate.AddMember("highest", normalize(hr->highest()), allocator);
// hashrate.AddMember("threads", threads, allocator);
// reply.AddMember("hashrate", hashrate, allocator);
//}
void xmrig::ApiRouter::getMiner(rapidjson::Value &reply, rapidjson::Document &doc) const
{
using namespace rapidjson;
auto &allocator = doc.GetAllocator();
Value cpu(kObjectType);
cpu.AddMember("brand", StringRef(Cpu::info()->brand()), allocator);
cpu.AddMember("aes", Cpu::info()->hasAES(), allocator);
cpu.AddMember("x64", Cpu::info()->isX64(), allocator);
cpu.AddMember("sockets", Cpu::info()->sockets(), allocator);
reply.AddMember("version", APP_VERSION, allocator);
reply.AddMember("kind", APP_KIND, allocator);
reply.AddMember("ua", StringRef(Platform::userAgent()), allocator);
reply.AddMember("cpu", cpu, allocator);
reply.AddMember("hugepages", false, allocator); // FIXME hugepages
reply.AddMember("donate_level", m_base->config()->pools().donateLevel(), allocator);
}
void xmrig::ApiRouter::getThreads(rapidjson::Value &reply, rapidjson::Document &doc) const void xmrig::ApiRouter::getThreads(rapidjson::Value &reply, rapidjson::Document &doc) const
{ {
// using namespace rapidjson; // using namespace rapidjson;

View file

@ -39,7 +39,7 @@ namespace xmrig {
class Base; class Base;
class ApiRouter : public xmrig::IApiListener class ApiRouter : public IApiListener
{ {
public: public:
ApiRouter(Base *base); ApiRouter(Base *base);
@ -49,8 +49,6 @@ protected:
void onRequest(IApiRequest &request) override; void onRequest(IApiRequest &request) override;
private: private:
// void getHashrate(rapidjson::Value &reply, rapidjson::Document &doc) const;
void getMiner(rapidjson::Value &reply, rapidjson::Document &doc) const;
void getThreads(rapidjson::Value &reply, rapidjson::Document &doc) const; void getThreads(rapidjson::Value &reply, rapidjson::Document &doc) const;
Base *m_base; Base *m_base;

View file

@ -29,9 +29,10 @@
#include <stdio.h> #include <stdio.h>
#include "backend/common/Hashrate.h"
#include "base/tools/Chrono.h" #include "base/tools/Chrono.h"
#include "base/tools/Handle.h" #include "base/tools/Handle.h"
#include "backend/common/Hashrate.h" #include "rapidjson/document.h"
inline static const char *format(double h, char *buf, size_t size) inline static const char *format(double h, char *buf, size_t size)
@ -162,3 +163,15 @@ const char *xmrig::Hashrate::format(double h, char *buf, size_t size)
{ {
return ::format(h, buf, size); return ::format(h, buf, size);
} }
rapidjson::Value xmrig::Hashrate::normalize(double d)
{
using namespace rapidjson;
if (!std::isnormal(d)) {
return Value(kNullType);
}
return Value(floor(d * 100.0) / 100.0);
}

View file

@ -30,6 +30,9 @@
#include <stdint.h> #include <stdint.h>
#include "rapidjson/fwd.h"
namespace xmrig { namespace xmrig {
@ -53,6 +56,7 @@ public:
inline size_t threads() const { return m_threads; } inline size_t threads() const { return m_threads; }
static const char *format(double h, char *buf, size_t size); static const char *format(double h, char *buf, size_t size);
static rapidjson::Value normalize(double d);
private: private:
constexpr static size_t kBucketSize = 2 << 11; constexpr static size_t kBucketSize = 2 << 11;

View file

@ -28,14 +28,24 @@
#include "backend/common/Hashrate.h" #include "backend/common/Hashrate.h"
#include "backend/cpu/Cpu.h"
#include "backend/cpu/CpuBackend.h" #include "backend/cpu/CpuBackend.h"
#include "base/io/log/Log.h" #include "base/io/log/Log.h"
#include "base/kernel/Platform.h"
#include "base/net/stratum/Job.h" #include "base/net/stratum/Job.h"
#include "base/tools/Timer.h" #include "base/tools/Timer.h"
#include "core/config/Config.h" #include "core/config/Config.h"
#include "core/Controller.h" #include "core/Controller.h"
#include "core/Miner.h" #include "core/Miner.h"
#include "crypto/common/Nonce.h" #include "crypto/common/Nonce.h"
#include "rapidjson/document.h"
#include "version.h"
#ifdef XMRIG_FEATURE_API
# include "api/Api.h"
# include "api/interfaces/IApiRequest.h"
#endif
namespace xmrig { namespace xmrig {
@ -114,6 +124,90 @@ public:
} }
# ifdef XMRIG_FEATURE_API
void getMiner(rapidjson::Value &reply, rapidjson::Document &doc, int version) const
{
using namespace rapidjson;
auto &allocator = doc.GetAllocator();
Value cpu(kObjectType);
cpu.AddMember("brand", StringRef(Cpu::info()->brand()), allocator);
cpu.AddMember("aes", Cpu::info()->hasAES(), allocator);
cpu.AddMember("x64", Cpu::info()->isX64(), allocator);
cpu.AddMember("sockets", Cpu::info()->sockets(), allocator);
reply.AddMember("version", APP_VERSION, allocator);
reply.AddMember("kind", APP_KIND, allocator);
reply.AddMember("ua", StringRef(Platform::userAgent()), allocator);
reply.AddMember("cpu", cpu, allocator);
if (version == 1) {
reply.AddMember("hugepages", false, allocator);
}
reply.AddMember("donate_level", controller->config()->pools().donateLevel(), allocator);
Value algo(kArrayType);
for (const Algorithm &a : algorithms) {
algo.PushBack(StringRef(a.shortName()), allocator);
}
reply.AddMember("algorithms", algo, allocator);
}
void getHashrate(rapidjson::Value &reply, rapidjson::Document &doc, int version) const
{
using namespace rapidjson;
auto &allocator = doc.GetAllocator();
Value hashrate(kObjectType);
Value total(kArrayType);
Value threads(kArrayType);
double t[3] = { 0.0 };
for (IBackend *backend : backends) {
const Hashrate *hr = backend->hashrate();
if (!hr) {
continue;
}
t[0] += hr->calc(Hashrate::ShortInterval);
t[1] += hr->calc(Hashrate::MediumInterval);
t[2] += hr->calc(Hashrate::LargeInterval);
if (version > 1) {
continue;
}
for (size_t i = 0; i < hr->threads(); i++) {
Value thread(kArrayType);
thread.PushBack(Hashrate::normalize(hr->calc(i, Hashrate::ShortInterval)), allocator);
thread.PushBack(Hashrate::normalize(hr->calc(i, Hashrate::MediumInterval)), allocator);
thread.PushBack(Hashrate::normalize(hr->calc(i, Hashrate::LargeInterval)), allocator);
threads.PushBack(thread, allocator);
}
}
total.PushBack(Hashrate::normalize(t[0]), allocator);
total.PushBack(Hashrate::normalize(t[1]), allocator);
total.PushBack(Hashrate::normalize(t[2]), allocator);
hashrate.AddMember("total", total, allocator);
hashrate.AddMember("highest", Hashrate::normalize(maxHashrate), allocator);
if (version == 1) {
hashrate.AddMember("threads", threads, allocator);
}
reply.AddMember("hashrate", hashrate, allocator);
}
# endif
Algorithms algorithms; Algorithms algorithms;
bool active = false; bool active = false;
bool enabled = true; bool enabled = true;
@ -137,6 +231,10 @@ xmrig::Miner::Miner(Controller *controller)
{ {
controller->addListener(this); controller->addListener(this);
# ifdef XMRIG_FEATURE_API
controller->api()->addListener(this);
# endif
d_ptr->timer = new Timer(this); d_ptr->timer = new Timer(this);
d_ptr->backends.push_back(new CpuBackend(controller)); d_ptr->backends.push_back(new CpuBackend(controller));
@ -309,3 +407,16 @@ void xmrig::Miner::onTimer(const Timer *)
d_ptr->ticks++; d_ptr->ticks++;
} }
#ifdef XMRIG_FEATURE_API
void xmrig::Miner::onRequest(IApiRequest &request)
{
if (request.type() == IApiRequest::REQ_SUMMARY) {
request.accept();
d_ptr->getMiner(request.reply(), request.doc(), request.version());
d_ptr->getHashrate(request.reply(), request.doc(), request.version());
}
}
#endif

View file

@ -29,6 +29,7 @@
#include <vector> #include <vector>
#include "api/interfaces/IApiListener.h"
#include "base/kernel/interfaces/IBaseListener.h" #include "base/kernel/interfaces/IBaseListener.h"
#include "base/kernel/interfaces/ITimerListener.h" #include "base/kernel/interfaces/ITimerListener.h"
#include "crypto/common/Algorithm.h" #include "crypto/common/Algorithm.h"
@ -43,7 +44,7 @@ class MinerPrivate;
class IBackend; class IBackend;
class Miner : public ITimerListener, public IBaseListener class Miner : public ITimerListener, public IBaseListener, public IApiListener
{ {
public: public:
Miner(Controller *controller); Miner(Controller *controller);
@ -64,6 +65,10 @@ protected:
void onConfigChanged(Config *config, Config *previousConfig) override; void onConfigChanged(Config *config, Config *previousConfig) override;
void onTimer(const Timer *timer) override; void onTimer(const Timer *timer) override;
# ifdef XMRIG_FEATURE_API
void onRequest(IApiRequest &request) override;
# endif
private: private:
MinerPrivate *d_ptr; MinerPrivate *d_ptr;
}; };

View file

@ -185,19 +185,6 @@ void xmrig::Network::onPause(IStrategy *strategy)
} }
void xmrig::Network::onRequest(IApiRequest &request)
{
# ifdef XMRIG_FEATURE_API
if (request.method() == IApiRequest::METHOD_GET && (request.url() == "/1/summary" || request.url() == "/api.json")) {
request.accept();
getResults(request.reply(), request.doc());
getConnection(request.reply(), request.doc());
}
# endif
}
void xmrig::Network::onResultAccepted(IStrategy *, IClient *, const SubmitResult &result, const char *error) void xmrig::Network::onResultAccepted(IStrategy *, IClient *, const SubmitResult &result, const char *error)
{ {
m_state.add(result, error); m_state.add(result, error);
@ -223,6 +210,19 @@ void xmrig::Network::onVerifyAlgorithm(IStrategy *, const IClient *, const Algor
} }
#ifdef XMRIG_FEATURE_API
void xmrig::Network::onRequest(IApiRequest &request)
{
if (request.type() == IApiRequest::REQ_SUMMARY) {
request.accept();
getResults(request.reply(), request.doc(), request.version());
getConnection(request.reply(), request.doc(), request.version());
}
}
#endif
void xmrig::Network::setJob(IClient *client, const Job &job, bool donate) void xmrig::Network::setJob(IClient *client, const Job &job, bool donate)
{ {
if (job.height()) { if (job.height()) {
@ -256,7 +256,7 @@ void xmrig::Network::tick()
#ifdef XMRIG_FEATURE_API #ifdef XMRIG_FEATURE_API
void xmrig::Network::getConnection(rapidjson::Value &reply, rapidjson::Document &doc) const void xmrig::Network::getConnection(rapidjson::Value &reply, rapidjson::Document &doc, int version) const
{ {
using namespace rapidjson; using namespace rapidjson;
auto &allocator = doc.GetAllocator(); auto &allocator = doc.GetAllocator();
@ -271,13 +271,16 @@ void xmrig::Network::getConnection(rapidjson::Value &reply, rapidjson::Document
connection.AddMember("failures", m_state.failures, allocator); connection.AddMember("failures", m_state.failures, allocator);
connection.AddMember("tls", m_state.tls().toJSON(), allocator); connection.AddMember("tls", m_state.tls().toJSON(), allocator);
connection.AddMember("tls-fingerprint", m_state.fingerprint().toJSON(), allocator); connection.AddMember("tls-fingerprint", m_state.fingerprint().toJSON(), allocator);
connection.AddMember("error_log", Value(kArrayType), allocator);
if (version == 1) {
connection.AddMember("error_log", Value(kArrayType), allocator);
}
reply.AddMember("connection", connection, allocator); reply.AddMember("connection", connection, allocator);
} }
void xmrig::Network::getResults(rapidjson::Value &reply, rapidjson::Document &doc) const void xmrig::Network::getResults(rapidjson::Value &reply, rapidjson::Document &doc, int version) const
{ {
using namespace rapidjson; using namespace rapidjson;
auto &allocator = doc.GetAllocator(); auto &allocator = doc.GetAllocator();
@ -295,8 +298,11 @@ void xmrig::Network::getResults(rapidjson::Value &reply, rapidjson::Document &do
best.PushBack(m_state.topDiff[i], allocator); best.PushBack(m_state.topDiff[i], allocator);
} }
results.AddMember("best", best, allocator); results.AddMember("best", best, allocator);
results.AddMember("error_log", Value(kArrayType), allocator);
if (version == 1) {
results.AddMember("error_log", Value(kArrayType), allocator);
}
reply.AddMember("results", results, allocator); reply.AddMember("results", results, allocator);
} }

View file

@ -65,10 +65,13 @@ protected:
void onJobResult(const JobResult &result) override; void onJobResult(const JobResult &result) override;
void onLogin(IStrategy *strategy, IClient *client, rapidjson::Document &doc, rapidjson::Value &params) override; void onLogin(IStrategy *strategy, IClient *client, rapidjson::Document &doc, rapidjson::Value &params) override;
void onPause(IStrategy *strategy) override; void onPause(IStrategy *strategy) override;
void onRequest(IApiRequest &request) override;
void onResultAccepted(IStrategy *strategy, IClient *client, const SubmitResult &result, const char *error) override; void onResultAccepted(IStrategy *strategy, IClient *client, const SubmitResult &result, const char *error) override;
void onVerifyAlgorithm(IStrategy *strategy, const IClient *client, const Algorithm &algorithm, bool *ok) override; void onVerifyAlgorithm(IStrategy *strategy, const IClient *client, const Algorithm &algorithm, bool *ok) override;
# ifdef XMRIG_FEATURE_API
void onRequest(IApiRequest &request) override;
# endif
private: private:
constexpr static int kTickInterval = 1 * 1000; constexpr static int kTickInterval = 1 * 1000;
@ -76,8 +79,8 @@ private:
void tick(); void tick();
# ifdef XMRIG_FEATURE_API # ifdef XMRIG_FEATURE_API
void getConnection(rapidjson::Value &reply, rapidjson::Document &doc) const; void getConnection(rapidjson::Value &reply, rapidjson::Document &doc, int version) const;
void getResults(rapidjson::Value &reply, rapidjson::Document &doc) const; void getResults(rapidjson::Value &reply, rapidjson::Document &doc, int version) const;
# endif # endif
Controller *m_controller; Controller *m_controller;