diff options
author | fireice-uk <fireice2@o2.pl> | 2017-03-03 21:02:27 +0000 |
---|---|---|
committer | fireice-uk <fireice2@o2.pl> | 2017-03-03 21:02:27 +0000 |
commit | 84317cfef411e5664a0447d95b12d83c008b81bc (patch) | |
tree | 3d9404a8e05739d1f136d824970f4c98c4b12fde | |
parent | b5902fd0b75415d61a938db9ab06122e5c4c3a12 (diff) | |
download | xmr-stak-84317cfef411e5664a0447d95b12d83c008b81bc.zip xmr-stak-84317cfef411e5664a0447d95b12d83c008b81bc.tar.gz |
New webdesign for the HTTP report
-rw-r--r-- | executor.cpp | 143 | ||||
-rw-r--r-- | executor.h | 8 | ||||
-rw-r--r-- | httpd.cpp | 26 | ||||
-rw-r--r-- | webdesign.cpp | 166 | ||||
-rw-r--r-- | webdesign.h | 19 | ||||
-rw-r--r-- | xmr-stak-cpu.cbp | 2 |
6 files changed, 349 insertions, 15 deletions
diff --git a/executor.cpp b/executor.cpp index 3a1c9b2..edfa39c 100644 --- a/executor.cpp +++ b/executor.cpp @@ -33,6 +33,7 @@ #include "jconf.h" #include "console.h" #include "donate-level.h" +#include "webdesign.h" #ifdef _WIN32 #define strncasecmp _strnicmp @@ -478,13 +479,11 @@ void executor::ex_main() inline const char* hps_format(double h, char* buf, size_t l) { - if(std::isnormal(h)) + if(std::isnormal(h) || h == 0.0) { snprintf(buf, l, " %03.1f", h); return buf; } - else if(h == 0.0) //Zero is not normal but we want it - return " 0.0"; else return " (na)"; } @@ -695,6 +694,138 @@ void executor::print_report(ex_event_name ev) printer::inst()->print_str(out.c_str()); } +void executor::http_hashrate_report(std::string& out) +{ + char num_a[32], num_b[32], num_c[32], num_d[32]; + char buffer[4096]; + size_t nthd = pvThreads->size(); + + out.reserve(4096); + + snprintf(buffer, sizeof(buffer), sHtmlCommonHeader, "Hashrate Report", "Hashrate Report"); + out.append(buffer); + + snprintf(buffer, sizeof(buffer), sHtmlHashrateBodyHigh, (unsigned int)nthd + 3); + out.append(buffer); + + double fTotal[3] = { 0.0, 0.0, 0.0}; + for(size_t i=0; i < nthd; i++) + { + double fHps[3]; + + fHps[0] = telem->calc_telemetry_data(2500, i); + fHps[1] = telem->calc_telemetry_data(60000, i); + fHps[2] = telem->calc_telemetry_data(900000, i); + + num_a[0] = num_b[0] = num_c[0] ='\0'; + hps_format(fHps[0], num_a, sizeof(num_a)); + hps_format(fHps[1], num_b, sizeof(num_b)); + hps_format(fHps[2], num_c, sizeof(num_c)); + + fTotal[0] += fHps[0]; + fTotal[1] += fHps[1]; + fTotal[2] += fHps[2]; + + snprintf(buffer, sizeof(buffer), sHtmlHashrateTableRow, (unsigned int)i, num_a, num_b, num_c); + out.append(buffer); + } + + num_a[0] = num_b[0] = num_c[0] = num_d[0] ='\0'; + hps_format(fTotal[0], num_a, sizeof(num_a)); + hps_format(fTotal[1], num_b, sizeof(num_b)); + hps_format(fTotal[2], num_c, sizeof(num_c)); + hps_format(fHighestHps, num_d, sizeof(num_d)); + + snprintf(buffer, sizeof(buffer), sHtmlHashrateBodyLow, num_a, num_b, num_c, num_d); + out.append(buffer); +} + +void executor::http_result_report(std::string& out) +{ + char date[128]; + char buffer[4096]; + + out.reserve(4096); + + snprintf(buffer, sizeof(buffer), sHtmlCommonHeader, "Result Report", "Result Report"); + out.append(buffer); + + size_t iGoodRes = vMineResults[0].count, iTotalRes = iGoodRes; + size_t ln = vMineResults.size(); + + for(size_t i=1; i < ln; i++) + iTotalRes += vMineResults[i].count; + + double fGoodResPrc = 0.0; + if(iTotalRes > 0) + fGoodResPrc = 100.0 * iGoodRes / iTotalRes; + + double fAvgResTime = 0.0; + if(iPoolCallTimes.size() > 0) + { + using namespace std::chrono; + fAvgResTime = ((double)duration_cast<seconds>(system_clock::now() - tPoolConnTime).count()) + / iPoolCallTimes.size(); + } + + snprintf(buffer, sizeof(buffer), sHtmlResultBodyHigh, + iPoolDiff, iGoodRes, iTotalRes, fGoodResPrc, fAvgResTime, iPoolHashes, + int_port(iTopDiff[0]), int_port(iTopDiff[1]), int_port(iTopDiff[2]), int_port(iTopDiff[3]), + int_port(iTopDiff[4]), int_port(iTopDiff[5]), int_port(iTopDiff[6]), int_port(iTopDiff[7]), + int_port(iTopDiff[8]), int_port(iTopDiff[9])); + + out.append(buffer); + + for(size_t i=1; i < vMineResults.size(); i++) + { + snprintf(buffer, sizeof(buffer), sHtmlResultTableRow, vMineResults[i].msg.c_str(), + int_port(vMineResults[i].count), time_format(date, sizeof(date), vMineResults[i].time)); + out.append(buffer); + } + + out.append(sHtmlResultBodyLow); +} + +void executor::http_connection_report(std::string& out) +{ + char date[128]; + char buffer[4096]; + + out.reserve(4096); + + snprintf(buffer, sizeof(buffer), sHtmlCommonHeader, "Connection Report", "Connection Report"); + out.append(buffer); + + jpsock* pool = pick_pool_by_id(dev_pool_id + 1); + const char* cdate = "not connected"; + if (pool->is_running() && pool->is_logged_in()) + cdate = time_format(date, sizeof(date), tPoolConnTime); + + size_t n_calls = iPoolCallTimes.size(); + unsigned int ping_time = 0; + if (n_calls > 1) + { + //Not-really-but-good-enough median + std::nth_element(iPoolCallTimes.begin(), iPoolCallTimes.begin() + n_calls/2, iPoolCallTimes.end()); + ping_time = iPoolCallTimes[n_calls/2]; + } + + snprintf(buffer, sizeof(buffer), sHtmlConnectionBodyHigh, + jconf::inst()->GetPoolAddress(), + cdate, ping_time); + out.append(buffer); + + + for(size_t i=0; i < vSocketLog.size(); i++) + { + snprintf(buffer, sizeof(buffer), sHtmlConnectionTableRow, + time_format(date, sizeof(date), vSocketLog[i].time), vSocketLog[i].msg.c_str()); + out.append(buffer); + } + + out.append(sHtmlConnectionBodyLow); +} + void executor::http_report(ex_event_name ev) { assert(pHttpString != nullptr); @@ -702,15 +833,15 @@ void executor::http_report(ex_event_name ev) switch(ev) { case EV_HTML_HASHRATE: - hashrate_report(*pHttpString); + http_hashrate_report(*pHttpString); break; case EV_HTML_RESULTS: - result_report(*pHttpString); + http_result_report(*pHttpString); break; case EV_HTML_CONNSTAT: - connection_report(*pHttpString); + http_connection_report(*pHttpString); break; default: assert(false); @@ -74,6 +74,10 @@ private: void result_report(std::string& out); void connection_report(std::string& out); + void http_hashrate_report(std::string& out); + void http_result_report(std::string& out); + void http_connection_report(std::string& out); + void http_report(ex_event_name ev); void print_report(ex_event_name ev); @@ -136,8 +140,8 @@ private: std::array<size_t, 10> iTopDiff { { } }; //Initialize to zero std::chrono::system_clock::time_point tPoolConnTime; - size_t iPoolHashes; - uint64_t iPoolDiff; + size_t iPoolHashes = 0; + uint64_t iPoolDiff = 0; // Set it to 16 bit so that we can just let it grow // Maximum realistic growth rate - 5MB / month @@ -32,6 +32,8 @@ #include "executor.h" #include "jconf.h" +#include "webdesign.h" + #ifdef _WIN32 #include "libmicrohttpd/microhttpd.h" #define strcasecmp _stricmp @@ -63,27 +65,37 @@ int httpd::req_handler(void * cls, *ptr = nullptr; std::string str; - if(strcasecmp(url, "/h") == 0 || strcasecmp(url, "/hashrate") == 0) + if(strcasecmp(url, "/style.css") == 0) + { + const char* req_etag = MHD_lookup_connection_value(connection, MHD_HEADER_KIND, "If-None-Match"); + + if(req_etag != NULL && strcmp(req_etag, sHtmlCssEtag) == 0) + { //Cache hit + rsp = MHD_create_response_from_buffer(0, nullptr, MHD_RESPMEM_PERSISTENT); + + int ret = MHD_queue_response(connection, MHD_HTTP_NOT_MODIFIED, rsp); + MHD_destroy_response(rsp); + return ret; + } + + rsp = MHD_create_response_from_buffer(sHtmlCssSize, (void*)sHtmlCssFile, MHD_RESPMEM_PERSISTENT); + MHD_add_response_header(rsp, "ETag", sHtmlCssEtag); + } + else if(strcasecmp(url, "/h") == 0 || strcasecmp(url, "/hashrate") == 0) { - str.append("<html><head><title>Hashrate Report</title></head><body><pre>"); executor::inst()->get_http_report(EV_HTML_HASHRATE, str); - str.append("</pre></body></html>"); rsp = MHD_create_response_from_buffer(str.size(), (void*)str.c_str(), MHD_RESPMEM_MUST_COPY); } else if(strcasecmp(url, "/c") == 0 || strcasecmp(url, "/connection") == 0) { - str.append("<html><head><title>Connection Report</title></head><body><pre>"); executor::inst()->get_http_report(EV_HTML_CONNSTAT, str); - str.append("</pre></body></html>"); rsp = MHD_create_response_from_buffer(str.size(), (void*)str.c_str(), MHD_RESPMEM_MUST_COPY); } else if(strcasecmp(url, "/r") == 0 || strcasecmp(url, "/results") == 0) { - str.append("<html><head><title>Results Report</title></head><body><pre>"); executor::inst()->get_http_report(EV_HTML_RESULTS, str); - str.append("</pre></body></html>"); rsp = MHD_create_response_from_buffer(str.size(), (void*)str.c_str(), MHD_RESPMEM_MUST_COPY); } diff --git a/webdesign.cpp b/webdesign.cpp new file mode 100644 index 0000000..6d96824 --- /dev/null +++ b/webdesign.cpp @@ -0,0 +1,166 @@ +#include <stdlib.h> + +extern const char sHtmlCssEtag [] = "00000005"; +extern const char sHtmlCssFile [] = + "body {" + "font-family: Tahoma, Arial, sans-serif;" + "font-size: 80%;" + "background-color: rgb(230, 230, 230);" + "}" + + "a {" + "color: rgb(43, 51, 62);" + "}" + + "a:link {" + "text-decoration: none;" + "}" + + "a:visited {" + "color: rgb(43, 51, 62);" + "}" + + "a:hover {" + "color: rgb(255, 153, 0);" + "}" + + "a:active {" + "color: rgb(204, 122, 0);" + "}" + + ".header {" + "background-color: rgb(30, 30, 30);" + "color: white;" + "padding: 10px;" + "font-weight: bold;" + "margin: 10px 0px;" + "}" + + ".links {" + "padding: 5px;" + "text-align: center;" + "background-color: rgb(213, 213, 213);" + "box-shadow: 0px 1px 3px 0px rgba(0, 0, 0, 0.2), 0px 1px 1px 0px rgba(0, 0, 0, 0.14), 0px 2px 1px -1px rgba(0, 0, 0, 0.12);" + "}" + + ".data th, td {" + "padding: 5px 12px;" + "text-align: right;" + "border-bottom: 1px solid #ccc;" + "}" + + ".data tr:nth-child(even) {" + "background-color: #ddd;" + "}" + + ".data th {" + "background-color: #ccc;" + "}" + + ".data table {" + "width: 100%;" + "max-width: 600px;" + "}" + + ".letter {" + "font-weight: bold;" + "}" + + "h4 {" + "background-color: rgb(0, 129, 124);" + "color: white;" + "padding: 10px;" + "margin: 10px 0px;" + "}" + + ".flex-container {" + "display: -webkit-flex;" + "display: flex;" + "}" + + ".flex-item {" + "width: 33%;" + "margin: 6px;" + "}"; + +size_t sHtmlCssSize = sizeof(sHtmlCssFile) - 1; + +extern const char sHtmlCommonHeader [] = + "<!DOCTYPE html>" + "<html>" + "<head><meta name='viewport' content='width=device-width' />" + "<link rel='stylesheet' href='style.css' /><title>%s</title></head>" + "<body>" + "<div class='header'><span style='color: rgb(255, 153, 0)'>XMR</span>-Stak-CPU</div>" + + "<div class='flex-container'>" + "<div class='links flex-item'>" + "<a href='/h'><div><span class='letter'>H</span>ashrate</div></a>" + "</div>" + "<div class='links flex-item'>" + "<a href='/r'><div><span class='letter'>R</span>esults</div></a>" + "</div>" + "<div class='links flex-item'>" + "<a href='/c'><div><span class='letter'>C</span>onnection</div></a>" + "</div>" + "</div>" + "<h4>%s</h4>"; + +extern const char sHtmlHashrateBodyHigh [] = + "<div class=data>" + "<table>" + "<tr><th>Thread ID</th><th>2.5s</th><th>60s</th><th>15m</th><th rowspan='%u'>H/s</td></tr>"; + +extern const char sHtmlHashrateTableRow [] = + "<tr><th>%u</th><td>%s</td><td>%s</td><td>%s</td></tr>"; + +extern const char sHtmlHashrateBodyLow [] = + "<tr><th>Totals:</th><td>%s</td><td>%s</td><td>%s</td></tr>" + "<tr><th>Highest:</th><td>%s</td><td colspan='2'></td></tr>" + "</table>" + "</div></body></html>"; + +extern const char sHtmlConnectionBodyHigh [] = + "<div class=data>" + "<table>" + "<tr><th>Pool address</th><td>%s</td></tr>" + "<tr><th>Connected since</th><td>%s</td></tr>" + "<tr><th>Pool ping time</th><td>%u ms</td></tr>" + "</table>" + "<h4>Network error log</h4>" + "<table style='max-width: 1000px;'>" + "<tr><th style='width: 20%; min-width: 10em;'>Date</th><th>Error</th></tr>"; + +extern const char sHtmlConnectionTableRow [] = + "<tr><td>%s</td><td>%s</td></tr>"; + +extern const char sHtmlConnectionBodyLow [] = + "</table></div></body></html>"; + +extern const char sHtmlResultBodyHigh [] = + "<div class=data>" + "<table>" + "<tr><th>Difficulty</th><td>%u</td></tr>" + "<tr><th>Good results</th><td>%u / %u (%.1f %%)</td></tr>" + "<tr><th>Avg result time</th><td>%.1f sec</td></tr>" + "<tr><th>Pool-side hashes</th><td>%u</td></tr>" + "</table>" + "<h4>Top 10 best results found</h4>" + "<table>" + "<tr><th style='width: 2em;'>1</th><td>%llu</td><th style='width: 2em;'>2</th><td>%llu</td></tr>" + "<tr><th>3</th><td>%llu</td><th>4</th><td>%llu</td></tr>" + "<tr><th>5</th><td>%llu</td><th>6</th><td>%llu</td></tr>" + "<tr><th>7</th><td>%llu</td><th>8</th><td>%llu</td></tr>" + "<tr><th>9</th><td>%llu</td><th>10</th><td>%llu</td></tr>" + "</table>" + "<h4>Error details</h4>" + "<table style='max-width: 1000px;'>" + "<tr><th colspan='2'>Error text</th></tr>" + "<tr><th style='width: 5em;'>Count</th><th>Last seen</th></tr>"; + +extern const char sHtmlResultTableRow [] = + "<tr><td colspan='2'>%s</td></tr><tr><td>%llu</td><td>%s</td></tr>"; + +extern const char sHtmlResultBodyLow [] = + "</table></div></body></html>"; + diff --git a/webdesign.h b/webdesign.h new file mode 100644 index 0000000..a516afb --- /dev/null +++ b/webdesign.h @@ -0,0 +1,19 @@ +#pragma once + +extern const char sHtmlCssEtag[]; +extern const char sHtmlCssFile[]; +extern size_t sHtmlCssSize; + +extern const char sHtmlCommonHeader[]; + +extern const char sHtmlHashrateBodyHigh[]; +extern const char sHtmlHashrateTableRow[]; +extern const char sHtmlHashrateBodyLow[]; + +extern const char sHtmlConnectionBodyHigh[]; +extern const char sHtmlConnectionTableRow[]; +extern const char sHtmlConnectionBodyLow[]; + +extern const char sHtmlResultBodyHigh[]; +extern const char sHtmlResultTableRow[]; +extern const char sHtmlResultBodyLow[]; diff --git a/xmr-stak-cpu.cbp b/xmr-stak-cpu.cbp index cd0f77d..cc606fd 100644 --- a/xmr-stak-cpu.cbp +++ b/xmr-stak-cpu.cbp @@ -153,6 +153,8 @@ <Unit filename="socket.h" /> <Unit filename="socks.h" /> <Unit filename="thdq.hpp" /> + <Unit filename="webdesign.cpp" /> + <Unit filename="webdesign.h" /> <Extensions> <code_completion /> <debugger /> |