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