diff options
Diffstat (limited to 'xmrstak/http')
-rw-r--r-- | xmrstak/http/httpd.cpp | 153 | ||||
-rw-r--r-- | xmrstak/http/httpd.hpp | 31 | ||||
-rw-r--r-- | xmrstak/http/webdesign.cpp | 207 | ||||
-rw-r--r-- | xmrstak/http/webdesign.hpp | 24 |
4 files changed, 415 insertions, 0 deletions
diff --git a/xmrstak/http/httpd.cpp b/xmrstak/http/httpd.cpp new file mode 100644 index 0000000..53b73f1 --- /dev/null +++ b/xmrstak/http/httpd.cpp @@ -0,0 +1,153 @@ +/* + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + * + * Additional permission under GNU GPL version 3 section 7 + * + * If you modify this Program, or any covered work, by linking or combining + * it with OpenSSL (or a modified version of that library), containing parts + * covered by the terms of OpenSSL License and SSLeay License, the licensors + * of this Program grant you additional permission to convey the resulting work. + * + */ + +#ifndef CONF_NO_HTTPD + +#include <stdlib.h> +#include <stdio.h> +#include <string.h> +#include <string> + +#include "msgstruct.h" +#include "httpd.h" +#include "console.h" +#include "executor.h" +#include "jconf.h" + +#include "webdesign.h" + +#include <microhttpd.h> +#ifdef _WIN32 +#define strcasecmp _stricmp +#endif // _WIN32 + +httpd* httpd::oInst = nullptr; + +httpd::httpd() +{ + +} + +int httpd::req_handler(void * cls, + MHD_Connection* connection, + const char* url, + const char* method, + const char* version, + const char* upload_data, + size_t* upload_data_size, + void ** ptr) +{ + struct MHD_Response * rsp; + + if (strcmp(method, "GET") != 0) + return MHD_NO; + + *ptr = nullptr; + + std::string str; + 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); + MHD_add_response_header(rsp, "Content-Type", "text/css; charset=utf-8"); + } + else if(strcasecmp(url, "/api.json") == 0) + { + executor::inst()->get_http_report(EV_HTML_JSON, str); + + rsp = MHD_create_response_from_buffer(str.size(), (void*)str.c_str(), MHD_RESPMEM_MUST_COPY); + MHD_add_response_header(rsp, "Content-Type", "application/json; charset=utf-8"); + } + else if(strcasecmp(url, "/h") == 0 || strcasecmp(url, "/hashrate") == 0) + { + executor::inst()->get_http_report(EV_HTML_HASHRATE, str); + + rsp = MHD_create_response_from_buffer(str.size(), (void*)str.c_str(), MHD_RESPMEM_MUST_COPY); + MHD_add_response_header(rsp, "Content-Type", "text/html; charset=utf-8"); + } + else if(strcasecmp(url, "/c") == 0 || strcasecmp(url, "/connection") == 0) + { + executor::inst()->get_http_report(EV_HTML_CONNSTAT, str); + + rsp = MHD_create_response_from_buffer(str.size(), (void*)str.c_str(), MHD_RESPMEM_MUST_COPY); + MHD_add_response_header(rsp, "Content-Type", "text/html; charset=utf-8"); + } + else if(strcasecmp(url, "/r") == 0 || strcasecmp(url, "/results") == 0) + { + executor::inst()->get_http_report(EV_HTML_RESULTS, str); + + rsp = MHD_create_response_from_buffer(str.size(), (void*)str.c_str(), MHD_RESPMEM_MUST_COPY); + MHD_add_response_header(rsp, "Content-Type", "text/html; charset=utf-8"); + } + else + { + //Do a 302 redirect to /h + char loc_path[256]; + const char* host_val = MHD_lookup_connection_value(connection, MHD_HEADER_KIND, "Host"); + + if(host_val != nullptr) + snprintf(loc_path, sizeof(loc_path), "http://%s/h", host_val); + else + snprintf(loc_path, sizeof(loc_path), "/h"); + + rsp = MHD_create_response_from_buffer(0, nullptr, MHD_RESPMEM_PERSISTENT); + int ret = MHD_queue_response(connection, MHD_HTTP_TEMPORARY_REDIRECT, rsp); + MHD_add_response_header(rsp, "Location", loc_path); + MHD_destroy_response(rsp); + return ret; + } + + int ret = MHD_queue_response(connection, MHD_HTTP_OK, rsp); + MHD_destroy_response(rsp); + return ret; +} + +bool httpd::start_daemon() +{ + d = MHD_start_daemon(MHD_USE_THREAD_PER_CONNECTION, + jconf::inst()->GetHttpdPort(), NULL, NULL, + &httpd::req_handler, + NULL, MHD_OPTION_END); + + if(d == nullptr) + { + printer::inst()->print_str("HTTP Daemon failed to start."); + return false; + } + + return true; +} + +#endif + diff --git a/xmrstak/http/httpd.hpp b/xmrstak/http/httpd.hpp new file mode 100644 index 0000000..bc8bcf6 --- /dev/null +++ b/xmrstak/http/httpd.hpp @@ -0,0 +1,31 @@ +#pragma once + +struct MHD_Daemon; +struct MHD_Connection; + +class httpd +{ +public: + static httpd* inst() + { + if (oInst == nullptr) oInst = new httpd; + return oInst; + }; + + bool start_daemon(); + +private: + httpd(); + static httpd* oInst; + + static int req_handler(void * cls, + MHD_Connection* connection, + const char* url, + const char* method, + const char* version, + const char* upload_data, + size_t* upload_data_size, + void ** ptr); + + MHD_Daemon *d; +}; diff --git a/xmrstak/http/webdesign.cpp b/xmrstak/http/webdesign.cpp new file mode 100644 index 0000000..4dfd3c2 --- /dev/null +++ b/xmrstak/http/webdesign.cpp @@ -0,0 +1,207 @@ +#include <stdlib.h> + +extern const char sHtmlCssEtag [] = "00000006"; +extern const char sHtmlCssFile [] = + "body {" + "font-family: Tahoma, Arial, sans-serif;" + "font-size: 80%;" + "background-color: rgb(240, 240, 240);" + "}" + + "a {" + "color: rgb(44, 55, 66);" + "}" + + "a:link {" + "text-decoration: none;" + "}" + + "a:visited {" + "color: rgb(44, 55, 66);" + "}" + + "a:hover {" + "color: rgb(255, 153, 0);" + "}" + + "a:active {" + "color: rgb(204, 122, 0);" + "}" + + ".all {" + "max-width:600px;" + "margin: auto;" + "}" + + ".header {" + "background-color: rgb(30, 30, 30);" + "color: white;" + "padding: 10px;" + "font-weight: bold;" + "margin: 10px 0px;" + "}" + + ".links {" + "padding: 7px;" + "text-align: center;" + "background-color: rgb(215, 215, 215);" + "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, 130, 130);" + "color: white;" + "padding: 10px;" + "margin: 10px 0px;" + "}" + + ".flex-container {" + "display: -webkit-flex;" + "display: flex;" + "}" + + ".flex-item {" + "width: 33%;" + "margin: 3px;" + "}"; + +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='all'>" + "<div class='header'><span style='color: rgb(255, 160, 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>10s</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></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>" + "<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></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>" + "<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></div></body></html>"; + +extern const char sJsonApiThdHashrate[] = + "[%s,%s,%s]"; + +extern const char sJsonApiResultError[] = + "{\"count\":%llu,\"last_seen\":%llu,\"text\":\"%s\"}"; + +extern const char sJsonApiConnectionError[] = + "{\"last_seen\":%llu,\"text\":\"%s\"}"; + +extern const char sJsonApiFormat [] = +"{" + "\"hashrate\":{" + "\"threads\":[%s]," + "\"total\":%s," + "\"highest\":%s" + "}," + + "\"results\":{" + "\"diff_current\":%llu," + "\"shares_good\":%llu," + "\"shares_total\":%llu," + "\"avg_time\":%.1f," + "\"hashes_total\":%llu," + "\"best\":[%llu,%llu,%llu,%llu,%llu,%llu,%llu,%llu,%llu,%llu]," + "\"error_log\":[%s]" + "}," + + "\"connection\":{" + "\"pool\": \"%s\"," + "\"uptime\":%llu," + "\"ping\":%llu," + "\"error_log\":[%s]" + "}" +"}"; + diff --git a/xmrstak/http/webdesign.hpp b/xmrstak/http/webdesign.hpp new file mode 100644 index 0000000..92639a0 --- /dev/null +++ b/xmrstak/http/webdesign.hpp @@ -0,0 +1,24 @@ +#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[]; + +extern const char sJsonApiThdHashrate[]; +extern const char sJsonApiResultError[]; +extern const char sJsonApiConnectionError[]; +extern const char sJsonApiFormat[]; |