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;
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();
request.accept();
@ -145,14 +145,6 @@ void xmrig::Api::exec(IApiRequest &request)
features.PushBack("tls", allocator);
# endif
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) {

View file

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

View file

@ -4,7 +4,9 @@
* 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 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
* 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 bool isDone() const = 0;
@ -57,9 +65,11 @@ public:
virtual bool isRestricted() const = 0;
virtual const rapidjson::Value &json() const = 0;
virtual const String &url() const = 0;
virtual int version() const = 0;
virtual Method method() const = 0;
virtual rapidjson::Document &doc() = 0;
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

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

View file

@ -43,10 +43,15 @@ 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,
@ -56,7 +61,7 @@ private:
bool m_restricted;
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_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"
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) :
m_base(base)
{
@ -64,12 +52,7 @@ xmrig::ApiRouter::~ApiRouter()
void xmrig::ApiRouter::onRequest(IApiRequest &request)
{
if (request.method() == IApiRequest::METHOD_GET) {
if (request.url() == "/1/summary" || request.url() == "/api.json") {
request.accept();
getMiner(request.reply(), request.doc());
// getHashrate(request.reply(), request.doc());
}
else if (request.url() == "/1/threads") {
if (request.url() == "/1/threads") {
request.accept();
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
{
// using namespace rapidjson;

View file

@ -39,7 +39,7 @@ namespace xmrig {
class Base;
class ApiRouter : public xmrig::IApiListener
class ApiRouter : public IApiListener
{
public:
ApiRouter(Base *base);
@ -49,8 +49,6 @@ protected:
void onRequest(IApiRequest &request) override;
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;
Base *m_base;

View file

@ -29,9 +29,10 @@
#include <stdio.h>
#include "backend/common/Hashrate.h"
#include "base/tools/Chrono.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)
@ -162,3 +163,15 @@ const char *xmrig::Hashrate::format(double h, char *buf, size_t 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 "rapidjson/fwd.h"
namespace xmrig {
@ -53,6 +56,7 @@ public:
inline size_t threads() const { return m_threads; }
static const char *format(double h, char *buf, size_t size);
static rapidjson::Value normalize(double d);
private:
constexpr static size_t kBucketSize = 2 << 11;

View file

@ -28,14 +28,24 @@
#include "backend/common/Hashrate.h"
#include "backend/cpu/Cpu.h"
#include "backend/cpu/CpuBackend.h"
#include "base/io/log/Log.h"
#include "base/kernel/Platform.h"
#include "base/net/stratum/Job.h"
#include "base/tools/Timer.h"
#include "core/config/Config.h"
#include "core/Controller.h"
#include "core/Miner.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 {
@ -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;
bool active = false;
bool enabled = true;
@ -137,6 +231,10 @@ xmrig::Miner::Miner(Controller *controller)
{
controller->addListener(this);
# ifdef XMRIG_FEATURE_API
controller->api()->addListener(this);
# endif
d_ptr->timer = new Timer(this);
d_ptr->backends.push_back(new CpuBackend(controller));
@ -309,3 +407,16 @@ void xmrig::Miner::onTimer(const Timer *)
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 "api/interfaces/IApiListener.h"
#include "base/kernel/interfaces/IBaseListener.h"
#include "base/kernel/interfaces/ITimerListener.h"
#include "crypto/common/Algorithm.h"
@ -43,7 +44,7 @@ class MinerPrivate;
class IBackend;
class Miner : public ITimerListener, public IBaseListener
class Miner : public ITimerListener, public IBaseListener, public IApiListener
{
public:
Miner(Controller *controller);
@ -64,6 +65,10 @@ protected:
void onConfigChanged(Config *config, Config *previousConfig) override;
void onTimer(const Timer *timer) override;
# ifdef XMRIG_FEATURE_API
void onRequest(IApiRequest &request) override;
# endif
private:
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)
{
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)
{
if (job.height()) {
@ -256,7 +256,7 @@ void xmrig::Network::tick()
#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;
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("tls", m_state.tls().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);
}
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;
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);
}
results.AddMember("best", best, allocator);
results.AddMember("error_log", Value(kArrayType), allocator);
results.AddMember("best", best, allocator);
if (version == 1) {
results.AddMember("error_log", Value(kArrayType), allocator);
}
reply.AddMember("results", results, allocator);
}

View file

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