Added miner uptime to dashboard

WIP SSL/TLS for CC communication and Dashboard
This commit is contained in:
BenDroid 2018-02-05 22:53:38 +01:00
parent e6f05b3648
commit 1b7b48f6e3
13 changed files with 146 additions and 10 deletions

View file

@ -10,6 +10,7 @@ option(WITH_AEON "CryptoNight-Lite support" ON)
option(WITH_HTTPD "HTTP REST API" OFF)
option(WITH_CC_CLIENT "CC Client" ON)
option(WITH_CC_SERVER "CC Server" ON)
option(WITH_SSL_TLS "SSL/TLS support" ON)
include (CheckIncludeFile)
include (cmake/cpu.cmake)
@ -54,6 +55,7 @@ set(SOURCES_COMMON
src/log/Log.cpp
src/Platform.cpp
src/Cpu.cpp
)
if (WIN32)
@ -106,6 +108,26 @@ find_package(UV REQUIRED)
include(cmake/flags.cmake)
if (WITH_SSL_TLS)
find_package(OpenSSL REQUIRED)
add_definitions(/DCPPHTTPLIB_OPENSSL_SUPPORT)
if (OPENSSL_FOUND)
include_directories(${OPENSSL_INCLUDE_DIR})
include_directories(src/3rdparty/evt-tls)
include_directories(src/3rdparty/evt-tls/api)
set(SOURCES_SSL_TLS
src/3rdparty/evt-tls/src/uv_tls.c
src/3rdparty/evt-tls/src/evt_tls.c)
else()
message(FATAL_ERROR "OpenSSL NOT found: use `-DWITH_SSL_TLS=OFF` to build without SSL/TLS support")
endif()
else()
add_definitions(/DXMRIG_NO_SSL_TLS)
endif()
if (WITH_LIBCPUID)
add_subdirectory(src/3rdparty/libcpuid)
@ -189,10 +211,10 @@ if (WITH_CC_SERVER OR WITH_CC_CLIENT)
add_library(xmrig_cc_common STATIC ${SOURCES_CC_COMMON})
endif (WITH_CC_SERVER OR WITH_CC_CLIENT)
add_executable(xmrigMiner ${SOURCES} ${SOURCES_CRYPTO} ${HTTPD_SOURCES} ${SOURCES_CC_CLIENT} res/app.rc)
add_executable(xmrigMiner ${SOURCES} ${SOURCES_CRYPTO} ${HTTPD_SOURCES} ${SOURCES_CC_CLIENT} ${SOURCES_SSL_TLS} res/app.rc)
target_link_libraries(xmrigMiner xmrig_common xmrig_os_dependencies xmrig_cpuid
${UV_LIBRARIES} ${MHD_LIBRARY} ${EXTRA_LIBS} ${CPUID_LIB})
${UV_LIBRARIES} ${MHD_LIBRARY} ${EXTRA_LIBS} ${CPUID_LIB} ${OPENSSL_LIBRARIES})
if (WITH_CC_CLIENT)
target_link_libraries(xmrigMiner xmrig_cc_common)

View file

@ -46,6 +46,7 @@
<script type="text/javascript" language="javascript" src="https://cdn.datatables.net/buttons/1.5.0/js/buttons.bootstrap.min.js"></script>
<script type="text/javascript" language="javascript" src="https://cdn.datatables.net/select/1.2.4/js/dataTables.select.min.js"></script>
<script type="text/javascript" language="javascript" src="https://cdnjs.cloudflare.com/ajax/libs/jquery-timeago/1.6.1/jquery.timeago.min.js"></script>
<script type="text/javascript" language="javascript" src="https://cdnjs.cloudflare.com/ajax/libs/moment-duration-format/2.2.1/moment-duration-format.min.js"></script>
<script src="https://gitcdn.github.io/bootstrap-toggle/2.2.2/js/bootstrap-toggle.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>
<script src="https://use.fontawesome.com/6b3cdfc597.js"></script>
@ -112,6 +113,7 @@
{data: "client_status.avg_time", className: "right"},
{data: "client_status.shares_good", className: "right"},
{data: "client_status.shares_total", className: "right"},
{data: "client_status.uptime", render: uptime},
{data: "client_status.last_status_update", render: laststatus},
{
data: null,
@ -450,6 +452,14 @@
});
}
function uptime( data, type, row ) {
if (type !== 'sort') {
return moment.duration(data, "milliseconds");
}
return data;
}
function laststatus( data, type, row ) {
if (type !== 'sort') {
var date = new Date(data*1000 - clockDrift);

View file

@ -40,7 +40,7 @@ struct cryptonight_ctx;
class Mem
{
public:
typedef std::bitset<64> ThreadBitSet;
typedef std::bitset<128> ThreadBitSet;
enum Flags {
HugepagesAvailable = 1,
HugepagesEnabled = 2,

View file

@ -269,6 +269,8 @@ Options::Options(int argc, char **argv) :
m_safe(false),
m_syslog(false),
m_daemonized(false),
m_useTls(true),
m_ccUseTls(true),
m_configFile(Platform::defaultConfigName()),
m_apiToken(nullptr),
m_apiWorkerId(nullptr),
@ -281,6 +283,8 @@ Options::Options(int argc, char **argv) :
m_ccAdminPass(nullptr),
m_ccClientConfigFolder(nullptr),
m_ccCustomDashboard(nullptr),
m_ccKeyFile(nullptr),
m_ccCertFile(nullptr),
m_algo(ALGO_CRYPTONIGHT),
m_algoVariant(AV0_AUTO),
m_aesni(AESNI_AUTO),

View file

@ -69,6 +69,8 @@ public:
inline bool hugePages() const { return m_hugePages; }
inline bool syslog() const { return m_syslog; }
inline bool daemonized() const { return m_daemonized; }
inline bool useTls() const { return m_useTls; }
inline bool ccUseTls() const { return m_ccUseTls; }
inline const char *configFile() const { return m_configFile; }
inline const char *apiToken() const { return m_apiToken; }
inline const char *apiWorkerId() const { return m_apiWorkerId; }
@ -81,6 +83,8 @@ public:
inline const char *ccAdminPass() const { return m_ccAdminPass; }
inline const char *ccClientConfigFolder() const { return m_ccClientConfigFolder; }
inline const char *ccCustomDashboard() const { return m_ccCustomDashboard == nullptr ? "index.html" : m_ccCustomDashboard; }
inline const char *ccKeyFile() const { return m_ccKeyFile == nullptr ? "server.key" : m_ccKeyFile; }
inline const char *ccCertFile() const { return m_ccCertFile == nullptr ? "server.pem" : m_ccCertFile; }
inline const std::vector<Url*> &pools() const { return m_pools; }
inline Algo algo() const { return m_algo; }
inline bool aesni() const { return m_aesni == AESNI_ON; }
@ -134,6 +138,8 @@ private:
bool m_safe;
bool m_syslog;
bool m_daemonized;
bool m_useTls;
bool m_ccUseTls;
const char* m_configFile;
char *m_apiToken;
char *m_apiWorkerId;
@ -146,6 +152,8 @@ private:
char *m_ccAdminPass;
char *m_ccClientConfigFolder;
char *m_ccCustomDashboard;
char *m_ccKeyFile;
char *m_ccCertFile;
Algo m_algo;
AlgoVariant m_algoVariant;
AesNi m_aesni;

View file

@ -92,6 +92,8 @@ CCClient::CCClient(Options* options, uv_async_t* async)
m_clientStatus.setCpuL3(Cpu::l3());
m_clientStatus.setCurrentThreads(m_options->threads());
m_startTime = std::chrono::system_clock::now();
if (m_options->ccToken() != nullptr) {
m_authorization = std::string("Bearer ") + m_self->m_options->ccToken();
}
@ -138,6 +140,8 @@ void CCClient::updateNetworkState(const NetworkState& network)
void CCClient::publishClientStatusReport()
{
refreshUptime();
std::string requestUrl = "/client/setClientStatus?clientId=" + m_self->m_clientStatus.getClientId();
std::string requestBuffer = m_self->m_clientStatus.toJsonString();
@ -256,7 +260,17 @@ std::shared_ptr<httplib::Response> CCClient::performRequest(const std::string& r
const std::string& requestBuffer,
const std::string& operation)
{
httplib::Client cli(m_self->m_options->ccHost(), m_self->m_options->ccPort());
std::shared_ptr<httplib::Client> cli;
# ifndef XMRIG_NO_SSL_TLS
if (m_self->m_options->ccUseTls()) {
cli = std::make_shared<httplib::SSLClient>(m_self->m_options->ccHost(), m_self->m_options->ccPort());
}
# endif
if (!cli) {
cli = std::make_shared<httplib::Client>(m_self->m_options->ccHost(), m_self->m_options->ccPort());
}
httplib::Request req;
req.method = operation;
@ -277,7 +291,15 @@ std::shared_ptr<httplib::Response> CCClient::performRequest(const std::string& r
auto res = std::make_shared<httplib::Response>();
return cli.send(req, *res) ? res : nullptr;
return cli->send(req, *res) ? res : nullptr;
}
void CCClient::refreshUptime()
{
std::chrono::time_point<std::chrono::system_clock> now = std::chrono::system_clock::now();
auto uptime = std::chrono::duration_cast<std::chrono::milliseconds>(m_self->m_startTime - now);
m_self->m_clientStatus.setUptime(static_cast<uint64_t>(uptime.count()));
}
void CCClient::onThreadStarted(void* handle)

View file

@ -28,6 +28,8 @@
#ifndef XMRIG_NO_CC
#include <uv.h>
#include <chrono>
#include <ctime>
#include <3rdparty/cpp-httplib/httplib.h>
#include "Options.h"
#include "ClientStatus.h"
@ -65,11 +67,14 @@ private:
std::string m_authorization;
std::chrono::time_point<std::chrono::system_clock> m_startTime;
uv_async_t* m_async;
uv_timer_t m_timer;
uv_loop_t m_client_loop;
uv_thread_t m_thread;
static void refreshUptime();
};
#endif

View file

@ -90,7 +90,7 @@ CCServer::~CCServer()
int CCServer::start()
{
if (!m_options) {
return 0;
return EINVAL;
}
uv_signal_start(&m_signal, CCServer::onSignal, SIGHUP);
@ -106,7 +106,9 @@ int CCServer::start()
Service::start();
m_httpd = new Httpd(m_options);
m_httpd->start();
if (!m_httpd->start()) {
return EINVAL;
}
const int r = uv_run(uv_default_loop(), UV_RUN_DEFAULT);
uv_loop_close(uv_default_loop());

View file

@ -51,6 +51,7 @@ ClientStatus::ClientStatus()
m_sharesGood(0),
m_sharesTotal(0),
m_hashesTotal(0),
m_uptime(0),
m_avgTime(0),
m_lastStatusUpdate(0)
{
@ -321,6 +322,16 @@ std::time_t ClientStatus::getLastStatusUpdate() const
return m_lastStatusUpdate;
}
uint64_t ClientStatus::getUptime() const
{
return m_uptime;
}
void ClientStatus::setUptime(uint64_t uptime)
{
m_uptime = uptime;
}
bool ClientStatus::parseFromJson(const rapidjson::Document& document)
{
bool result = false;
@ -433,6 +444,10 @@ bool ClientStatus::parseFromJson(const rapidjson::Document& document)
m_avgTime = clientStatus["avg_time"].GetUint();
}
if (clientStatus.HasMember("uptime")) {
m_uptime = clientStatus["uptime"].GetUint64();
}
auto time_point = std::chrono::system_clock::now();
m_lastStatusUpdate = std::chrono::system_clock::to_time_t(time_point);
@ -481,6 +496,8 @@ rapidjson::Value ClientStatus::toJson(rapidjson::MemoryPoolAllocator<rapidjson::
clientStatus.AddMember("avg_time", m_avgTime, allocator);
clientStatus.AddMember("uptime", m_uptime, allocator);
clientStatus.AddMember("last_status_update", static_cast<uint64_t >(m_lastStatusUpdate), allocator);
return clientStatus;

View file

@ -137,6 +137,9 @@ public:
std::time_t getLastStatusUpdate() const;
void setUptime(uint64_t uptime);
uint64_t getUptime() const;
std::string toJsonString();
rapidjson::Value toJson(rapidjson::MemoryPoolAllocator<rapidjson::CrtAllocator>& allocator);
bool parseFromJson(const rapidjson::Document& document);
@ -179,6 +182,7 @@ private:
uint64_t m_sharesGood;
uint64_t m_sharesTotal;
uint64_t m_hashesTotal;
uint64_t m_uptime;
uint32_t m_avgTime;

View file

@ -23,6 +23,8 @@
*/
#include <cstring>
#include <sstream>
#include <fstream>
#include <microhttpd.h>
#include <memory>
@ -43,8 +45,30 @@ bool Httpd::start()
return false;
}
# ifndef XMRIG_NO_SSL_TLS
if (m_options->ccUseTls()) {
m_keyPem = readFile(m_options->ccKeyFile());
m_certPem = readFile(m_options->ccCertFile());
if (m_keyPem.length() == 0 || m_certPem.length() == 0) {
LOG_ERR("HTTPS Daemon failed to start. Unable to load Key/Cert.");
return false;
}
m_daemon = MHD_start_daemon (MHD_USE_SELECT_INTERNALLY | MHD_USE_SSL,
static_cast<uint16_t>(m_options->ccPort()), nullptr, nullptr, &Httpd::handler,
this, MHD_OPTION_CONNECTION_TIMEOUT, (unsigned int) 10,
MHD_OPTION_HTTPS_MEM_KEY, m_keyPem,
MHD_OPTION_HTTPS_MEM_CERT, m_certPem,
MHD_OPTION_END);
}
# endif
if (!m_daemon) {
m_daemon = MHD_start_daemon(MHD_USE_SELECT_INTERNALLY, static_cast<uint16_t>(m_options->ccPort()), nullptr, nullptr, &Httpd::handler,
this, MHD_OPTION_CONNECTION_TIMEOUT, (unsigned int) 10, MHD_OPTION_END);
}
if (!m_daemon) {
LOG_ERR("HTTP Daemon failed to start.");
@ -56,6 +80,18 @@ bool Httpd::start()
return true;
}
std::string Httpd::readFile(const std::string &fileName)
{
std::stringstream data;
std::ifstream file(fileName);
if (file) {
data << file.rdbuf();
file.close();
}
return data.str();
}
unsigned Httpd::tokenAuth(struct MHD_Connection* connection)
{
if (!m_options->ccToken()) {

View file

@ -58,9 +58,13 @@ private:
static int handleGET(const Httpd* httpd, MHD_Connection* connection, const char* url);
static int handlePOST(const Httpd* httpd, MHD_Connection* connection, const char* url, const char* upload_data, size_t* upload_data_size, void** con_cls);
static std::string readFile(const std::string &fileName);
const Options* m_options;
MHD_Daemon* m_daemon;
std::string m_keyPem;
std::string m_certPem;
};
#endif /* __HTTPD_H__ */

View file

@ -27,6 +27,7 @@
#include <map>
#include <uv.h>
#include <memory>
#include "net/Job.h"
@ -124,6 +125,7 @@ private:
# ifndef XMRIG_PROXY_PROJECT
uv_timer_t m_keepAliveTimer;
# endif
};