diff --git a/CMakeLists.txt b/CMakeLists.txt index ec454660..b138744b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -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) diff --git a/index.html b/index.html index 09c521a6..ef7336d2 100644 --- a/index.html +++ b/index.html @@ -46,6 +46,7 @@ + @@ -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); diff --git a/src/Mem.h b/src/Mem.h index ffbc7d01..ee19ebb7 100644 --- a/src/Mem.h +++ b/src/Mem.h @@ -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, diff --git a/src/Options.cpp b/src/Options.cpp index 8e2d98e3..104ee499 100644 --- a/src/Options.cpp +++ b/src/Options.cpp @@ -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), diff --git a/src/Options.h b/src/Options.h index 24bae1af..40a8eea7 100644 --- a/src/Options.h +++ b/src/Options.h @@ -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 &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; diff --git a/src/cc/CCClient.cpp b/src/cc/CCClient.cpp index 43dee832..452cdc5b 100644 --- a/src/cc/CCClient.cpp +++ b/src/cc/CCClient.cpp @@ -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 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 cli; + +# ifndef XMRIG_NO_SSL_TLS + if (m_self->m_options->ccUseTls()) { + cli = std::make_shared(m_self->m_options->ccHost(), m_self->m_options->ccPort()); + } +# endif + + if (!cli) { + cli = std::make_shared(m_self->m_options->ccHost(), m_self->m_options->ccPort()); + } httplib::Request req; req.method = operation; @@ -277,7 +291,15 @@ std::shared_ptr CCClient::performRequest(const std::string& r auto res = std::make_shared(); - return cli.send(req, *res) ? res : nullptr; + return cli->send(req, *res) ? res : nullptr; +} + +void CCClient::refreshUptime() +{ + std::chrono::time_point now = std::chrono::system_clock::now(); + auto uptime = std::chrono::duration_cast(m_self->m_startTime - now); + + m_self->m_clientStatus.setUptime(static_cast(uptime.count())); } void CCClient::onThreadStarted(void* handle) diff --git a/src/cc/CCClient.h b/src/cc/CCClient.h index 07a347df..8471d11a 100644 --- a/src/cc/CCClient.h +++ b/src/cc/CCClient.h @@ -28,6 +28,8 @@ #ifndef XMRIG_NO_CC #include +#include +#include #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 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 diff --git a/src/cc/CCServer.cpp b/src/cc/CCServer.cpp index c4969853..a65b4816 100644 --- a/src/cc/CCServer.cpp +++ b/src/cc/CCServer.cpp @@ -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()); diff --git a/src/cc/ClientStatus.cpp b/src/cc/ClientStatus.cpp index d98e2d6c..7005699f 100644 --- a/src/cc/ClientStatus.cpp +++ b/src/cc/ClientStatus.cpp @@ -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(m_lastStatusUpdate), allocator); return clientStatus; diff --git a/src/cc/ClientStatus.h b/src/cc/ClientStatus.h index 6aff3eb2..f6afc824 100644 --- a/src/cc/ClientStatus.h +++ b/src/cc/ClientStatus.h @@ -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& 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; diff --git a/src/cc/Httpd.cpp b/src/cc/Httpd.cpp index 31bb6784..fea7b390 100644 --- a/src/cc/Httpd.cpp +++ b/src/cc/Httpd.cpp @@ -23,6 +23,8 @@ */ #include +#include +#include #include #include @@ -43,8 +45,30 @@ bool Httpd::start() return false; } - m_daemon = MHD_start_daemon(MHD_USE_SELECT_INTERNALLY, static_cast(m_options->ccPort()), nullptr, nullptr, &Httpd::handler, - this, MHD_OPTION_CONNECTION_TIMEOUT, (unsigned int) 10, MHD_OPTION_END); +# 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(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(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()) { diff --git a/src/cc/Httpd.h b/src/cc/Httpd.h index 95d5ecc8..8d3ee6fe 100644 --- a/src/cc/Httpd.h +++ b/src/cc/Httpd.h @@ -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); - const Options* m_options; + 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__ */ diff --git a/src/net/Client.h b/src/net/Client.h index 699f4903..f66f079c 100644 --- a/src/net/Client.h +++ b/src/net/Client.h @@ -27,6 +27,7 @@ #include #include +#include #include "net/Job.h" @@ -124,6 +125,7 @@ private: # ifndef XMRIG_PROXY_PROJECT uv_timer_t m_keepAliveTimer; # endif + };