diff --git a/index.html b/index.html index 7bf56f41..7ae349e9 100644 --- a/index.html +++ b/index.html @@ -12,6 +12,8 @@ .right{text-align:right;} .center{text-align:center;} .toolbar { float: right; padding-left: 10pt;} + .online { color: green} + .offline { color: red} @@ -26,10 +28,7 @@ $.fn.dataTable.ext.search.push( var hide = document.getElementById("hideOffline").checked; var lastStatus = settings.aoData[dataIndex]._aData.client_status.last_status_update * 1000; - var threshold = new Date().getTime() - 10*60*1000; - - console.log("lastStatus: " + new Date(lastStatus)); - console.log("threshold: " + new Date(threshold)); + var threshold = new Date().getTime() - 60 * 1000; if (lastStatus > threshold || !hide) { return true; @@ -50,7 +49,7 @@ $(document).ready(function() { dataSrc : 'client_status_list' }, columns: [ - { data: "client_status.client_id"}, + { data: "client_status.client_id", render: clientInfo}, { data: "client_status.current_pool"}, { data: "client_status.current_status"}, { data: "client_status.current_algo_name"}, @@ -138,14 +137,14 @@ $(document).ready(function() { }, 0 ); // Update footer - $( api.column(4).footer()).html(sumHashrateShort); - $( api.column(5).footer()).html(sumHashrateMedium); - $( api.column(6).footer()).html(sumHashrateLong); - $( api.column(7).footer()).html(sumHashrateHighest); - $( api.column(8).footer()).html(sumHashesTotal); - $( api.column(9).footer()).html(avgTimeTotal); - $( api.column(10).footer()).html(sumSharesGood); - $( api.column(11).footer()).html(sumSharedTotal); + $(api.column(4).footer()).html(sumHashrateShort); + $(api.column(5).footer()).html(sumHashrateMedium); + $(api.column(6).footer()).html(sumHashrateLong); + $(api.column(7).footer()).html(sumHashrateHighest); + $(api.column(8).footer()).html(sumHashesTotal); + $(api.column(9).footer()).html(avgTimeTotal); + $(api.column(10).footer()).html(sumSharesGood); + $(api.column(11).footer()).html(sumSharedTotal); } }); @@ -179,7 +178,7 @@ $(document).ready(function() { var htmlContent = "
" + ""+ "" + "
"; @@ -187,7 +186,7 @@ $(document).ready(function() { $('#editConfig').modal('show'); }, error: function (data) { - alert("Unable to fetch " + clientId + "_config.json or default_config.json, please check your configuration!"); + alert("Unable to fetch " + clientId + "_config.json or default_config.json, please check your Server configuration and the the config files are located on the Server!"); } }); } @@ -223,9 +222,40 @@ $(document).ready(function() { function laststatus( data, type, row ) { var date = new Date(data*1000); + return '' + jQuery.timeago(date) + ''; } +function clientInfo( data, type, row ) { + var tooltip = "CPU: " + row.client_status.cpu_brand; + tooltip += '\n'; + tooltip += "CPU Flags: " + (row.client_status.cpu_has_aes ? "AES-NI " : ""); + tooltip += (row.client_status.cpu_is_x64 ? "x64" : ""); + tooltip += '\n'; + tooltip += "CPU Cache L2/L3: " + (row.client_status.cpu_l2 / 1024) + " MB/"+ (row.client_status.cpu_l3 / 1024) + " MB"; + tooltip += '\n'; + tooltip += "Huge Pages: " + (row.client_status.hugepages_available ? " available, " : " unavailable, "); + tooltip += (row.client_status.hugepages_enabled ? "enabled" : "disabled"); + tooltip += '\n'; + tooltip += "Threads: " + row.client_status.current_threads; + tooltip += (row.client_status.double_hash_mode ? " [double hash mode]" :""); + tooltip += '\n'; + tooltip += "Client IP: " + row.client_status.external_ip; + tooltip += '\n'; + tooltip += "Status: "; + + var lastStatus = row.client_status.last_status_update * 1000; + var threshold = new Date().getTime() - 60 * 1000; + if (lastStatus > threshold) { + tooltip += "Online"; + return '
' + data + '
'; + } + else { + tooltip += "Offline"; + return '
' + data + '
'; + } +} + function round( data, type, row ) { return Math.round(data * 100) / 100; } diff --git a/src/cc/CCClient.cpp b/src/cc/CCClient.cpp index 471690ef..69d4b672 100644 --- a/src/cc/CCClient.cpp +++ b/src/cc/CCClient.cpp @@ -25,10 +25,12 @@ #include #include <3rdparty/rapidjson/stringbuffer.h> #include <3rdparty/rapidjson/prettywriter.h> -#include #include "CCClient.h" #include "App.h" +#include "Platform.h" +#include "Cpu.h" +#include "Mem.h" #include "ControlCommand.h" #include "api/NetworkState.h" @@ -69,6 +71,19 @@ CCClient::CCClient(const Options *options) m_clientStatus.setCurrentAlgoName(m_options->algoName()); } + m_clientStatus.setHugepagesEnabled(Mem::isHugepagesEnabled()); + m_clientStatus.setHugepages(Mem::isHugepagesAvailable()); + m_clientStatus.setDoubleHashMode(Mem::isDoubleHash()); + + m_clientStatus.setCpuBrand(Cpu::brand()); + m_clientStatus.setCpuAES(Cpu::hasAES()); + m_clientStatus.setCpuCores(Cpu::cores()); + m_clientStatus.setCpuX64(Cpu::isX64()); + + m_clientStatus.setCpuL2(Cpu::l2()); + m_clientStatus.setCpuL3(Cpu::l3()); + m_clientStatus.setCurrentThreads(Cpu::threads()); + if (m_options->ccToken() != nullptr) { m_authorization = std::string("Bearer ") + m_self->m_options->ccToken(); } diff --git a/src/cc/ClientStatus.cpp b/src/cc/ClientStatus.cpp index ad9ca03b..3382e558 100644 --- a/src/cc/ClientStatus.cpp +++ b/src/cc/ClientStatus.cpp @@ -43,6 +43,16 @@ ClientStatus::ClientStatus() } +ClientStatus::Status ClientStatus::getCurrentStatus() const +{ + return m_currentStatus; +} + +void ClientStatus::setCurrentStatus(Status currentStatus) +{ + m_currentStatus = currentStatus; +} + std::string ClientStatus::getClientId() const { return m_clientId; @@ -73,14 +83,74 @@ std::string ClientStatus::getCurrentAlgoName() const return m_currentAlgoName; } -ClientStatus::Status ClientStatus::getCurrentStatus() const +std::string ClientStatus::getCpuBrand() const { - return m_currentStatus; + return m_cpuBrand; } -void ClientStatus::setCurrentStatus(Status currentStatus) +void ClientStatus::setCpuBrand(const std::string& cpuBrand) { - m_currentStatus = currentStatus; + m_cpuBrand = cpuBrand; +} + +std::string ClientStatus::getExternalIp() const +{ + return m_externalIp; +} + +void ClientStatus::setExternalIp(const std::string& externalIp) +{ + m_externalIp = externalIp; +} + +bool ClientStatus::hasHugepages() const +{ + return m_hasHugepages; +} + +void ClientStatus::setHugepages(bool hasHugepages) +{ + m_hasHugepages = hasHugepages; +} + +bool ClientStatus::isHugepagesEnabled() const +{ + return m_isHugepagesEnabled; +} + +void ClientStatus::setHugepagesEnabled(bool hugepagesEnabled) +{ + m_isHugepagesEnabled = hugepagesEnabled; +} + +bool ClientStatus::isDoubleHashMode() const +{ + return m_isDoubleHashMode; +} + +void ClientStatus::setDoubleHashMode(bool isDoubleHashMode) +{ + m_isDoubleHashMode = isDoubleHashMode; +} + +bool ClientStatus::isCpuX64() const +{ + return m_isCpuX64; +} + +void ClientStatus::setCpuX64(bool isCpuX64) +{ + m_isCpuX64 = isCpuX64; +} + +bool ClientStatus::hasCpuAES() const +{ + return m_hasCpuAES; +} + +void ClientStatus::setCpuAES(bool hasCpuAES) +{ + m_hasCpuAES = hasCpuAES; } double ClientStatus::getHashrateShort() const @@ -113,6 +183,56 @@ void ClientStatus::setHashrateLong(double hashrateLong) m_hashrateLong = hashrateLong; } +void ClientStatus::setHashrateHighest(double hashrateHighest) +{ + m_hashrateHighest = hashrateHighest; +} + +double ClientStatus::getHashrateHighest() const +{ + return m_hashrateHighest; +} + +int ClientStatus::getCurrentThreads() const +{ + return m_currentThreads; +} + +void ClientStatus::setCurrentThreads(int currentThreads) +{ + m_currentThreads = currentThreads; +} + +int ClientStatus::getCpuCores() const +{ + return m_cpuCores; +} + +void ClientStatus::setCpuCores(int cpuCores) +{ + m_cpuCores = cpuCores; +} + +int ClientStatus::getCpuL2() const +{ + return m_cpuL2; +} + +void ClientStatus::setCpuL2(int cpuL2) +{ + m_cpuL2 = cpuL2; +} + +int ClientStatus::getCpuL3() const +{ + return m_cpuL3; +} + +void ClientStatus::setCpuL3(int cpuL3) +{ + m_cpuL3 = cpuL3; +} + uint64_t ClientStatus::getSharesGood() const { return m_sharesGood; @@ -142,17 +262,6 @@ void ClientStatus::setHashesTotal(uint64_t hashesTotal) { m_hashesTotal = hashesTotal; } - -void ClientStatus::setHashrateHighest(double hashrateHighest) -{ - m_hashrateHighest = hashrateHighest; -} - -double ClientStatus::getHashrateHighest() const -{ - return m_hashrateHighest; -} - void ClientStatus::setAvgTime(uint32_t avgTime) { m_avgTime = avgTime; @@ -176,6 +285,10 @@ bool ClientStatus::parseFromJson(const rapidjson::Document& document) { rapidjson::Value::ConstObject clientStatus = document["client_status"].GetObject(); + if (clientStatus.HasMember("current_status")) { + m_currentStatus = toStatus(clientStatus["current_status"].GetString()); + } + if (clientStatus.HasMember("client_id")) { m_clientId = clientStatus["client_id"].GetString(); } @@ -184,14 +297,38 @@ bool ClientStatus::parseFromJson(const rapidjson::Document& document) m_currentPool = clientStatus["current_pool"].GetString(); } - if (clientStatus.HasMember("current_status")) { - m_currentStatus = toStatus(clientStatus["current_status"].GetString()); - } - if (clientStatus.HasMember("current_algo_name")) { m_currentAlgoName = clientStatus["current_algo_name"].GetString(); } + if (clientStatus.HasMember("cpu_brand")) { + m_cpuBrand = clientStatus["cpu_brand"].GetString(); + } + + if (clientStatus.HasMember("external_ip")) { + m_externalIp = clientStatus["external_ip"].GetString(); + } + + if (clientStatus.HasMember("hugepages_available")) { + m_hasHugepages = clientStatus["hugepages_available"].GetBool(); + } + + if (clientStatus.HasMember("hugepages_enabled")) { + m_isHugepagesEnabled = clientStatus["hugepages_enabled"].GetBool(); + } + + if (clientStatus.HasMember("double_hash_mode")) { + m_isDoubleHashMode = clientStatus["double_hash_mode"].GetBool(); + } + + if (clientStatus.HasMember("cpu_is_x64")) { + m_isCpuX64 = clientStatus["cpu_is_x64"].GetBool(); + } + + if (clientStatus.HasMember("cpu_has_aes")) { + m_hasCpuAES = clientStatus["cpu_has_aes"].GetBool(); + } + if (clientStatus.HasMember("hashrate_short")) { m_hashrateShort = clientStatus["hashrate_short"].GetDouble(); } @@ -208,8 +345,20 @@ bool ClientStatus::parseFromJson(const rapidjson::Document& document) m_hashrateHighest = clientStatus["hashrate_highest"].GetDouble(); } - if (clientStatus.HasMember("avg_time")) { - m_avgTime = clientStatus["avg_time"].GetUint(); + if (clientStatus.HasMember("current_threads")) { + m_currentThreads = clientStatus["current_threads"].GetInt(); + } + + if (clientStatus.HasMember("cpu_cores")) { + m_cpuCores = clientStatus["cpu_cores"].GetInt(); + } + + if (clientStatus.HasMember("cpu_l2")) { + m_cpuL2 = clientStatus["cpu_l2"].GetInt(); + } + + if (clientStatus.HasMember("cpu_l3")) { + m_cpuL3 = clientStatus["cpu_l3"].GetInt(); } if (clientStatus.HasMember("shares_good")) { @@ -224,6 +373,10 @@ bool ClientStatus::parseFromJson(const rapidjson::Document& document) m_hashesTotal = clientStatus["hashes_total"].GetUint64(); } + if (clientStatus.HasMember("avg_time")) { + m_avgTime = clientStatus["avg_time"].GetUint(); + } + auto time_point = std::chrono::system_clock::now(); m_lastStatusUpdate = std::chrono::system_clock::to_time_t(time_point); @@ -239,21 +392,36 @@ rapidjson::Value ClientStatus::toJson(rapidjson::MemoryPoolAllocator #include -#include "rapidjson/document.h" +#include class ClientStatus { @@ -58,6 +58,9 @@ public: return Status::RUNNING; } + Status getCurrentStatus() const; + void setCurrentStatus(Status currentStatus); + std::string getClientId() const; void setClientId(const std::string& clientId); @@ -67,8 +70,26 @@ public: std::string getCurrentAlgoName() const; void setCurrentAlgoName(const std::string &algoName); - Status getCurrentStatus() const; - void setCurrentStatus(Status currentStatus); + std::string getCpuBrand() const; + void setCpuBrand(const std::string &cpuBrand); + + std::string getExternalIp() const; + void setExternalIp(const std::string &externalIp); + + bool hasHugepages() const; + void setHugepages(bool hasHugepages); + + bool isHugepagesEnabled() const; + void setHugepagesEnabled(bool hugepagesEnabled); + + bool isDoubleHashMode() const; + void setDoubleHashMode(bool isDoubleHashMode); + + bool isCpuX64() const; + void setCpuX64(bool isCpuX64); + + bool hasCpuAES() const; + void setCpuAES(bool hasCpuAES); double getHashrateShort() const; void setHashrateShort(double hashrateShort); @@ -79,6 +100,21 @@ public: double getHashrateLong() const; void setHashrateLong(double hashrateLong); + void setHashrateHighest(double hashrateHighest); + double getHashrateHighest() const; + + int getCurrentThreads() const; + void setCurrentThreads(int currentThreads); + + int getCpuCores() const; + void setCpuCores(int cpuCores); + + int getCpuL2() const; + void setCpuL2(int cpuL2); + + int getCpuL3() const; + void setCpuL3(int cpuL3); + uint64_t getSharesGood() const; void setSharesGood(uint64_t sharesGood); @@ -88,9 +124,6 @@ public: uint64_t getHashesTotal() const; void setHashesTotal(uint64_t hashesTotal); - void setHashrateHighest(double hashrateHighest); - double getHashrateHighest() const; - void setAvgTime(uint32_t avgTime); uint32_t getAvgTime() const; @@ -113,12 +146,25 @@ private: std::string m_clientId; std::string m_currentPool; std::string m_currentAlgoName; + std::string m_cpuBrand; + std::string m_externalIp; + + bool m_hasHugepages; + bool m_isHugepagesEnabled; + bool m_isDoubleHashMode; + bool m_isCpuX64; + bool m_hasCpuAES; double m_hashrateShort; double m_hashrateMedium; double m_hashrateLong; double m_hashrateHighest; + int m_currentThreads; + int m_cpuCores; + int m_cpuL2; + int m_cpuL3; + uint64_t m_sharesGood; uint64_t m_sharesTotal; uint64_t m_hashesTotal; diff --git a/src/cc/Httpd.cpp b/src/cc/Httpd.cpp index 6b0a95a1..ecee7e3f 100644 --- a/src/cc/Httpd.cpp +++ b/src/cc/Httpd.cpp @@ -212,15 +212,26 @@ int Httpd::handlePOST(const Httpd* httpd, struct MHD_Connection* connection, con } else { std::string resp; std::string url(urlPtr); + std::string clientIp; std::string clientId; + const MHD_ConnectionInfo *info = MHD_get_connection_info(connection, MHD_CONNECTION_INFO_CLIENT_ADDRESS); + if (info) { + char clientHost[NI_MAXHOST]; + int ec = getnameinfo(info->client_addr, sizeof(*info->client_addr), clientHost, sizeof(clientHost), + 0, 0, NI_NUMERICHOST|NI_NUMERICSERV); + + if (ec == 0) { + clientIp = std::string(clientHost); + } + } + const char* clientIdPtr = MHD_lookup_connection_value(connection, MHD_GET_ARGUMENT_KIND, "clientId"); - if (clientIdPtr) - { + if (clientIdPtr) { clientId = std::string(clientIdPtr); } - unsigned status = Service::handlePOST(httpd->m_options, url, clientId, cc->data.str(), resp); + unsigned status = Service::handlePOST(httpd->m_options, url, clientIp, clientId, cc->data.str(), resp); MHD_Response* rsp = nullptr; if (!resp.empty()) { diff --git a/src/cc/Service.cpp b/src/cc/Service.cpp index f8a2ca7e..ed8a6bd3 100644 --- a/src/cc/Service.cpp +++ b/src/cc/Service.cpp @@ -86,16 +86,18 @@ unsigned Service::handleGET(const Options* options, const std::string& url, cons return resultCode; } -unsigned Service::handlePOST(const Options* options, const std::string& url, const std::string& clientId, const std::string& data, std::string& resp) +unsigned Service::handlePOST(const Options* options, const std::string& url, const std::string& clientIp, + const std::string& clientId, const std::string& data, std::string& resp) { uv_mutex_lock(&m_mutex); unsigned resultCode = MHD_HTTP_NOT_FOUND; - LOG_INFO("POST(url='%s', clientId='%s', dataLen='%d')", url.c_str(), clientId.c_str(), data.length()); + LOG_INFO("POST(url='%s', clientIp='%s', clientId='%s', dataLen='%d')", + url.c_str(), clientId.c_str(), clientIp.c_str(), data.length()); if (url.rfind("/client/setClientStatus", 0) == 0) { - resultCode = setClientStatus(clientId, data, resp); + resultCode = setClientStatus(clientIp, clientId, data, resp); } else if (url.rfind("/admin/setClientConfig", 0) == 0) { resultCode = setClientConfig(options, clientId, data, resp); } else if (url.rfind("/admin/setClientCommand", 0) == 0) { @@ -204,7 +206,7 @@ unsigned Service::getClientStatusList(std::string& resp) return MHD_HTTP_OK; } -unsigned Service::setClientStatus(const std::string& clientId, const std::string& data, std::string& resp) +unsigned Service::setClientStatus(const std::string& clientIp, const std::string& clientId, const std::string& data, std::string& resp) { int resultCode = MHD_HTTP_BAD_REQUEST; @@ -214,6 +216,7 @@ unsigned Service::setClientStatus(const std::string& clientId, const std::string ClientStatus clientStatus; clientStatus.parseFromJson(document); + clientStatus.setExternalIp(clientIp); m_clientStatus[clientId] = clientStatus; diff --git a/src/cc/Service.h b/src/cc/Service.h index a80c9387..28767d43 100644 --- a/src/cc/Service.h +++ b/src/cc/Service.h @@ -43,7 +43,7 @@ public: static void release(); static unsigned handleGET(const Options* options, const std::string& url, const std::string& clientId, std::string& resp); - static unsigned handlePOST(const Options* options, const std::string& url, const std::string& clientId, const std::string& data, std::string& resp); + static unsigned handlePOST(const Options* options, const std::string& url, const std::string& clientIp, const std::string& clientId, const std::string& data, std::string& resp); private: static unsigned getClientConfig(const Options* options, const std::string& clientId, std::string& resp); @@ -51,7 +51,7 @@ private: static unsigned getClientStatusList(std::string& resp); static unsigned getAdminPage(const Options* options, std::string& resp); - static unsigned setClientStatus(const std::string& clientId, const std::string& data, std::string& resp); + static unsigned setClientStatus(const std::string& clientIp, const std::string& clientId, const std::string& data, std::string& resp); static unsigned setClientCommand(const std::string& clientId, const std::string& data, std::string& resp); static unsigned setClientConfig(const Options* options, const std::string &clientId, const std::string &data, std::string &resp); diff --git a/src/net/strategies/DonateStrategy.cpp b/src/net/strategies/DonateStrategy.cpp index d14a4738..3f795190 100644 --- a/src/net/strategies/DonateStrategy.cpp +++ b/src/net/strategies/DonateStrategy.cpp @@ -49,7 +49,7 @@ DonateStrategy::DonateStrategy(const char *agent, IStrategyListener *listener) : keccak(reinterpret_cast(user), static_cast(strlen(user)), hash, sizeof(hash)); Job::toHex(hash, 32, userId); - Url *url = new Url("donate.graef.in", Options::i()->algo() == Options::ALGO_CRYPTONIGHT_LITE ? 3333 : 4444, userId, nullptr, false, true); + Url *url = new Url("donate.graef.in", Options::i()->algo() == Options::ALGO_CRYPTONIGHT_LITE ? 80 : 443, userId, nullptr, false, true); m_client = new Client(-1, agent, this); m_client->setUrl(url); diff --git a/src/version.h b/src/version.h index 1ede7cc3..3a779dee 100644 --- a/src/version.h +++ b/src/version.h @@ -29,22 +29,21 @@ #define APP_ID "xmrigCC" #define APP_NAME "XMRigCC" #define APP_DESC "XMRigCC Command'n'Control Server" -#define APP_VERSION "1.0.9" #define APP_COPYRIGHT "Copyright (C) 2017- BenDr0id" # else #define APP_ID "xmrigCC" #define APP_NAME "XMRigCC" #define APP_DESC "XMRigCC CPU miner" -#define APP_VERSION "2.4.2" #define APP_COPYRIGHT "Copyright (C) 2017- BenDr0id" #endif +#define APP_VERSION "1.0.9 (based on XMRig 2.4.2)" #define APP_DOMAIN "" #define APP_SITE "https://github.com/Bendr0id/xmrigCC" #define APP_KIND "cpu" -#define APP_VER_MAJOR 2 -#define APP_VER_MINOR 4 -#define APP_VER_BUILD 2 +#define APP_VER_MAJOR 1 +#define APP_VER_MINOR 0 +#define APP_VER_BUILD 9 #define APP_VER_REV 0 #ifdef _MSC_VER