diff --git a/CHANGELOG.md b/CHANGELOG.md index ad7bf8994..651892f9f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,12 @@ +# v2.9.0 +- [#275](https://github.com/xmrig/xmrig-proxy/issues/275) Added SSL/TLS support for incoming connections. +- [#899](https://github.com/xmrig/xmrig/issues/899) Added support for new algoritm `cn/half` for Masari and Stellite forks. +- [#271](https://github.com/xmrig/xmrig-proxy/issues/271) Fixed broken pool options cascading (mixed configuration). +- Added memory and load_average information to API. + # v2.8.1 -- [#258](https://github.com/xmrig/xmrig/issues/258) Force NDEBUG for release builds. -- [#108](https://github.com/xmrig/xmrig/issues/108) Fixed possible crash in simple mode when heavy load. +- [#258](https://github.com/xmrig/xmrig-proxy/issues/258) Force NDEBUG for release builds. +- [#108](https://github.com/xmrig/xmrig-proxy/issues/108) Fixed possible crash in simple mode when heavy load. - [#777](https://github.com/xmrig/xmrig/issues/777) Better report about pool connection issues. - Fixed error when handle malformed result from miner (divide to zero). - Fixed malformed login reply. diff --git a/CMakeLists.txt b/CMakeLists.txt index 58e279bcf..2485d9d77 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -14,6 +14,7 @@ include (CheckIncludeFile) set(HEADERS src/3rdparty/align.h src/App.h + src/base/tools/String.h src/common/config/CommonConfig.h src/common/config/ConfigLoader.h src/common/config/ConfigWatcher.h @@ -53,7 +54,7 @@ set(HEADERS src/log/ShareLog.h src/net/JobResult.h src/net/strategies/DonateStrategy.h - src/proxy/Addr.h + src/proxy/BindHost.h src/proxy/Counters.h src/proxy/CustomDiff.h src/proxy/Error.h @@ -89,6 +90,7 @@ set(HEADERS set(SOURCES src/App.cpp + src/base/tools/String.cpp src/common/config/CommonConfig.cpp src/common/config/ConfigLoader.cpp src/common/config/ConfigWatcher.cpp @@ -112,6 +114,7 @@ set(SOURCES src/log/ShareLog.cpp src/net/JobResult.cpp src/net/strategies/DonateStrategy.cpp + src/proxy/BindHost.cpp src/proxy/Counters.cpp src/proxy/CustomDiff.cpp src/proxy/Error.cpp @@ -167,7 +170,7 @@ else() if (CMAKE_SYSTEM_NAME STREQUAL FreeBSD) set(EXTRA_LIBS pthread) else() - set(EXTRA_LIBS pthread uuid rt dl) + set(EXTRA_LIBS pthread uuid.a rt dl) endif() endif() diff --git a/README.md b/README.md index b0a92a5f5..2de6801e2 100644 --- a/README.md +++ b/README.md @@ -60,6 +60,14 @@ Use [config.xmrig.com](https://config.xmrig.com/proxy) to generate, edit or shar --api-worker-id=ID custom worker-id for API --api-no-ipv6 disable IPv6 support for API --api-no-restricted enable full remote access (only if API token set) + --tls enable SSL/TLS support for pool connection (needs pool support) + --tls-bind=ADDR bind to specified address with enabled TLS + --tls-cert=FILE load TLS certificate chain from a file in the PEM format + --tls-cert-key=FILE load TLS certificate private key from a file in the PEM format + --tls-dhparam=FILE load DH parameters for DHE ciphers from a file in the PEM format + --tls-protocols=N enable specified TLS protocols, example: "TLSv1 TLSv1.1 TLSv1.2 TLSv1.3" + --tls-ciphers=S set list of available ciphers (TLSv1.2 and below) + --tls-ciphersuites=S set list of available TLSv1.3 ciphersuites -h, --help display this help and exit -V, --version output version information and exit ``` diff --git a/cmake/OpenSSL.cmake b/cmake/OpenSSL.cmake index ed287e7e3..b4b9f107a 100644 --- a/cmake/OpenSSL.cmake +++ b/cmake/OpenSSL.cmake @@ -11,7 +11,16 @@ if (WITH_TLS) find_package(OpenSSL) if (OPENSSL_FOUND) - set(TLS_SOURCES src/common/net/Tls.h src/common/net/Tls.cpp) + set(TLS_SOURCES + src/common/net/Tls.cpp + src/common/net/Tls.h + src/proxy/tls/Tls.cpp + src/proxy/tls/Tls.h + src/proxy/tls/TlsConfig.cpp + src/proxy/tls/TlsConfig.h + src/proxy/tls/TlsContext.cpp + src/proxy/tls/TlsContext.h + ) include_directories(${OPENSSL_INCLUDE_DIR}) else() message(FATAL_ERROR "OpenSSL NOT found: use `-DWITH_TLS=OFF` to build without TLS support") @@ -20,4 +29,6 @@ else() set(TLS_SOURCES "") set(OPENSSL_LIBRARIES "") add_definitions(/DXMRIG_NO_TLS) + + set(CMAKE_PROJECT_NAME "${CMAKE_PROJECT_NAME}-notls") endif() diff --git a/doc/STRATUM_EXT.md b/doc/STRATUM_EXT.md index 2050bf6c7..294442d68 100644 --- a/doc/STRATUM_EXT.md +++ b/doc/STRATUM_EXT.md @@ -84,23 +84,24 @@ Note about xmr-stak, this miner use [different algorithm names](#15-xmr-stak-alg ### 1.4 Algorithm names and variants Both miner and pool should support short algorithm name aliases: -| Long name | Short name | Base algorithm | Variant | Notes | -|--------------------------|-----------------|----------------|-------------|------------------------------------------------------| -| `cryptonight` | `cn` | `cn` | `-1` | Autodetect works only for Monero. | -| `cryptonight/0` | `cn/0` | `cn` | `0` | Original/old CryptoNight. | -| `cryptonight/1` | `cn/1` | `cn` | `1` | Also known as `monero7` and `CryptoNightV7`. | -| `cryptonight/2` | `cn/2` | `cn` | `2` | CryptoNight variant 2. | -| `cryptonight/xtl` | `cn/xtl` | `cn` | `"xtl"` | Stellite (XTL). | -| `cryptonight/msr` | `cn/msr` | `cn` | `"msr"` | Masari (MSR), also known as `cryptonight-fast` | -| `cryptonight/xao` | `cn/xao` | `cn` | `"xao"` | Alloy (XAO) | -| `cryptonight/rto` | `cn/rto` | `cn` | `"rto"` | Arto (RTO) | -| `cryptonight-lite` | `cn-lite` | `cn-lite` | `-1` | Autodetect works only for Aeon. | -| `cryptonight-lite/0` | `cn-lite/0` | `cn-lite` | `0` | Original/old CryptoNight-Lite. | -| `cryptonight-lite/1` | `cn-lite/1` | `cn-lite` | `1` | Also known as `aeon7` | -| `cryptonight-lite/ipbc` | `cn-lite/ipbc` | `cn-lite` | `"ipbc"` | IPBC variant, **obsolete** | -| `cryptonight-heavy` | `cn-heavy` | `cn-heavy` | `0` | Ryo and Loki | -| `cryptonight-heavy/xhv` | `cn-heavy/xhv` | `cn-heavy` | `"xhv"` | Haven Protocol | -| `cryptonight-heavy/tube` | `cn-heavy/tube` | `cn-heavy` | `"tube"` | BitTube (TUBE) | +| Long name | Short name | Variant | Notes | +|--------------------------|-----------------|-------------|------------------------------------------------------| +| `cryptonight` | `cn` | `-1` | Autodetect works only for Monero. | +| `cryptonight/0` | `cn/0` | `0` | Original/old CryptoNight. | +| `cryptonight/1` | `cn/1` | `1` | Also known as `monero7` and `CryptoNightV7`. | +| `cryptonight/2` | `cn/2` | `2` | CryptoNight variant 2. | +| `cryptonight/xtl` | `cn/xtl` | `"xtl"` | Stellite (XTL). | +| `cryptonight/msr` | `cn/msr` | `"msr"` | Masari (MSR), also known as `cryptonight-fast`. | +| `cryptonight/xao` | `cn/xao` | `"xao"` | Alloy (XAO) | +| `cryptonight/rto` | `cn/rto` | `"rto"` | Arto (RTO) | +| `cryptonight/half` | `cn/half` | `"half"` | CryptoNight variant 2 with half iterations. | +| `cryptonight-lite` | `cn-lite` | `-1` | Autodetect works only for Aeon. | +| `cryptonight-lite/0` | `cn-lite/0` | `0` | Original/old CryptoNight-Lite. | +| `cryptonight-lite/1` | `cn-lite/1` | `1` | Also known as `aeon7` | +| `cryptonight-lite/ipbc` | `cn-lite/ipbc` | `"ipbc"` | IPBC variant, **obsolete** | +| `cryptonight-heavy` | `cn-heavy` | `0` | Ryo and Loki | +| `cryptonight-heavy/xhv` | `cn-heavy/xhv` | `"xhv"` | Haven Protocol | +| `cryptonight-heavy/tube` | `cn-heavy/tube` | `"tube"` | BitTube (TUBE) | Proper pool/proxy implementation should avoid any automatic/autodetect variants, variant must explicitly specified. diff --git a/src/Summary.cpp b/src/Summary.cpp index fbbca4715..2cce673fd 100644 --- a/src/Summary.cpp +++ b/src/Summary.cpp @@ -30,7 +30,7 @@ #include "common/net/Pool.h" #include "core/Config.h" #include "core/Controller.h" -#include "proxy/Addr.h" +#include "proxy/BindHost.h" #include "Summary.h" #include "version.h" @@ -53,16 +53,29 @@ static void print_algo(xmrig::Controller *controller) static void print_bind(xmrig::Controller *controller) { - const std::vector &addrs = controller->config()->addrs(); + const xmrig::BindHosts &bind = controller->config()->bind(); - for (size_t i = 0; i < addrs.size(); ++i) { - Log::i()->text(controller->config()->isColors() ? GREEN_BOLD(" * ") WHITE_BOLD("BIND #%-7zu") CYAN("%s%s%s:") CYAN_BOLD("%d") - : " * BIND #%-7zu%s%s%s:%d", - i + 1, - addrs[i].isIPv6() ? "[" : "", - addrs[i].ip(), - addrs[i].isIPv6() ? "]" : "", - addrs[i].port()); + if (controller->config()->isColors()) { + for (size_t i = 0; i < bind.size(); ++i) { + Log::i()->text(GREEN_BOLD(" * ") WHITE_BOLD("BIND #%-7zu") CYAN("%s%s%s:") "\x1B[1;%dm%d\x1B[0m", + i + 1, + bind[i].isIPv6() ? "[" : "", + bind[i].host(), + bind[i].isIPv6() ? "]" : "", + bind[i].isTLS() ? 32 : 36, + bind[i].port()); + } + } + else { + for (size_t i = 0; i < bind.size(); ++i) { + Log::i()->text(" * BIND #%-7zu%s%s%s:%d TLS=%d", + i + 1, + bind[i].isIPv6() ? "[" : "", + bind[i].host(), + bind[i].isIPv6() ? "]" : "", + bind[i].port(), + static_cast(bind[i].isTLS())); + } } } diff --git a/src/api/ApiRouter.cpp b/src/api/ApiRouter.cpp index 04d059ae4..0af4dbed6 100644 --- a/src/api/ApiRouter.cpp +++ b/src/api/ApiRouter.cpp @@ -24,6 +24,7 @@ #include #include #include +#include #if _WIN32 # include "winsock2.h" @@ -110,6 +111,7 @@ void ApiRouter::get(const xmrig::HttpRequest &req, xmrig::HttpReply &reply) cons getIdentify(doc); getMiner(doc); getHashrate(doc); + getResourcesSummary(doc); getMinersSummary(doc, req.match("/1/summary")); getResults(doc); @@ -310,6 +312,35 @@ void ApiRouter::getMinersSummary(rapidjson::Document &doc, bool advanced) const +void ApiRouter::getResourcesSummary(rapidjson::Document &doc) const +{ + using namespace rapidjson; + auto &allocator = doc.GetAllocator(); + + size_t rss = 0; + uv_resident_set_memory(&rss); + + Value resources(kObjectType); + Value memory(kObjectType); + Value load_average(kArrayType); + + memory.AddMember("total", uv_get_total_memory(), allocator); + memory.AddMember("resident_set_memory", static_cast(rss), allocator); + + double loadavg[3] = { 1.0 }; + uv_loadavg(loadavg); + load_average.PushBack(loadavg[0], allocator); + load_average.PushBack(loadavg[1], allocator); + load_average.PushBack(loadavg[2], allocator); + + resources.AddMember("memory", memory, allocator); + resources.AddMember("load_average", load_average, allocator); + resources.AddMember("hardware_concurrency", std::thread::hardware_concurrency(), allocator); + + doc.AddMember("resources", resources, allocator); +} + + void ApiRouter::getResources(rapidjson::Document &doc) const { auto &allocator = doc.GetAllocator(); @@ -317,7 +348,7 @@ void ApiRouter::getResources(rapidjson::Document &doc) const uv_resident_set_memory(&rss); doc.AddMember("total_memory", uv_get_total_memory(), allocator); - doc.AddMember("resident_set_memory", (uint64_t) rss, allocator); + doc.AddMember("resident_set_memory", static_cast(rss), allocator); } diff --git a/src/api/ApiRouter.h b/src/api/ApiRouter.h index b0230778c..f2a12615a 100644 --- a/src/api/ApiRouter.h +++ b/src/api/ApiRouter.h @@ -21,8 +21,8 @@ * along with this program. If not, see . */ -#ifndef __APIROUTER_H__ -#define __APIROUTER_H__ +#ifndef XMRIG_APIROUTER_H +#define XMRIG_APIROUTER_H #include "common/interfaces/IControllerListener.h" @@ -60,6 +60,7 @@ class ApiRouter : public xmrig::IControllerListener void getMiner(rapidjson::Document &doc) const; void getMiners(rapidjson::Document &doc) const; void getMinersSummary(rapidjson::Document &doc, bool advanced) const; + void getResourcesSummary(rapidjson::Document &doc) const; void getResources(rapidjson::Document &doc) const; void getResults(rapidjson::Document &doc) const; void getWorkers(rapidjson::Document &doc) const; @@ -71,4 +72,4 @@ class ApiRouter : public xmrig::IControllerListener xmrig::Controller *m_controller; }; -#endif /* __APIROUTER_H__ */ +#endif /* XMRIG_APIROUTER_H */ diff --git a/src/base/tools/String.cpp b/src/base/tools/String.cpp new file mode 100644 index 000000000..fe2792c72 --- /dev/null +++ b/src/base/tools/String.cpp @@ -0,0 +1,225 @@ +/* XMRig + * Copyright 2010 Jeff Garzik + * Copyright 2012-2014 pooler + * Copyright 2014 Lucas Jones + * Copyright 2014-2016 Wolf9466 + * Copyright 2016 Jay D Dee + * Copyright 2017-2018 XMR-Stak , + * Copyright 2016-2018 XMRig , + * + * 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 + * (at your option) 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 . + */ + + +#include "base/tools/String.h" +#include "rapidjson/document.h" + + +xmrig::String::String(const char *str) : + m_data(nullptr), + m_size(str == nullptr ? 0 : strlen(str)) +{ + if (m_size == 0) { + return; + } + + m_data = new char[m_size + 1]; + memcpy(m_data, str, m_size + 1); +} + + +xmrig::String::String(const char *str, size_t size) : + m_data(nullptr), + m_size(size) +{ + if (str == nullptr) { + m_size = 0; + + return; + } + + m_data = new char[m_size + 1]; + memcpy(m_data, str, m_size); + m_data[m_size] = '\0'; +} + + +xmrig::String::String(const String &other) : + m_data(nullptr), + m_size(other.m_size) +{ + if (other.m_data == nullptr) { + return; + } + + m_data = new char[m_size + 1]; + memcpy(m_data, other.m_data, m_size + 1); +} + + +bool xmrig::String::isEqual(const char *str) const +{ + return (m_data != nullptr && str != nullptr && strcmp(m_data, str) == 0) || (m_data == nullptr && str == nullptr); +} + + +bool xmrig::String::isEqual(const String &other) const +{ + if (m_size != other.m_size) { + return false; + } + + return (m_data != nullptr && other.m_data != nullptr && memcmp(m_data, other.m_data, m_size) == 0) || (m_data == nullptr && other.m_data == nullptr); +} + + +rapidjson::Value xmrig::String::toJSON() const +{ + using namespace rapidjson; + + return isNull() ? Value(kNullType) : Value(StringRef(m_data)); +} + + +rapidjson::Value xmrig::String::toJSON(rapidjson::Document &doc) const +{ + using namespace rapidjson; + + return isNull() ? Value(kNullType) : Value(m_data, doc.GetAllocator()); +} + + +std::vector xmrig::String::split(char sep) const +{ + std::vector out; + if (m_size == 0) { + return out; + } + + size_t start = 0; + size_t pos = 0; + + for (pos = 0; pos < m_size; ++pos) { + if (m_data[pos] == sep) { + if ((pos - start) > 0) { + out.push_back(std::move(String(m_data + start, pos - start))); + } + + start = pos + 1; + } + } + + if ((pos - start) > 0) { + out.push_back(std::move(String(m_data + start, pos - start))); + } + + return out; +} + + +xmrig::String xmrig::String::join(const std::vector &vec, char sep) +{ + if (vec.empty()) { + return String(); + } + + size_t size = vec.size(); + for (const String &str : vec) { + size += str.size(); + } + + size_t offset = 0; + char *buf = new char[size]; + + for (const String &str : vec) { + memcpy(buf + offset, str.data(), str.size()); + + offset += str.size() + 1; + + if (offset < size) { + buf[offset - 1] = sep; + } + } + + buf[size - 1] = '\0'; + + return String(buf); +} + + +void xmrig::String::copy(const char *str) +{ + delete [] m_data; + + if (str == nullptr) { + m_size = 0; + m_data = nullptr; + + return; + } + + m_size = strlen(str); + m_data = new char[m_size + 1]; + + memcpy(m_data, str, m_size + 1); +} + + +void xmrig::String::copy(const String &other) +{ + if (m_size > 0) { + if (m_size == other.m_size) { + memcpy(m_data, other.m_data, m_size + 1); + + return; + } + + delete [] m_data; + } + + delete [] m_data; + + if (other.m_data == nullptr) { + m_size = 0; + m_data = nullptr; + + return; + } + + m_size = other.m_size; + m_data = new char[m_size + 1]; + + memcpy(m_data, other.m_data, m_size + 1); +} + + +void xmrig::String::move(char *str) +{ + delete [] m_data; + + m_size = str == nullptr ? 0 : strlen(str); + m_data = str; +} + + +void xmrig::String::move(String &&other) +{ + delete [] m_data; + + m_data = other.m_data; + m_size = other.m_size; + + other.m_data = nullptr; + other.m_size = 0; +} diff --git a/src/base/tools/String.h b/src/base/tools/String.h new file mode 100644 index 000000000..0c191dfde --- /dev/null +++ b/src/base/tools/String.h @@ -0,0 +1,104 @@ +/* XMRig + * Copyright 2010 Jeff Garzik + * Copyright 2012-2014 pooler + * Copyright 2014 Lucas Jones + * Copyright 2014-2016 Wolf9466 + * Copyright 2016 Jay D Dee + * Copyright 2017-2018 XMR-Stak , + * Copyright 2016-2018 XMRig , + * + * 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 + * (at your option) 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 . + */ + +#ifndef XMRIG_STRING_H +#define XMRIG_STRING_H + + +#include +#include + + +#include "rapidjson/fwd.h" + + +namespace xmrig { + + +/** + * @brief Simple C string wrapper. + * + * 1. I know about std:string. + * 2. For some reason I prefer don't use std:string in miner, eg because of file size of MSYS2 builds. + * 3. nullptr and JSON conversion supported. + */ +class String +{ +public: + inline String() : m_data(nullptr), m_size(0) {} + inline String(char *str) : m_data(str), m_size(str == nullptr ? 0 : strlen(str)) {} + inline String(String &&other) : m_data(other.m_data), m_size(other.m_size) { other.m_data = nullptr; other.m_size = 0; } + + String(const char *str); + String(const char *str, size_t size); + String(const String &other); + + inline ~String() { delete [] m_data; } + + + bool isEqual(const char *str) const; + bool isEqual(const String &other) const; + + + inline bool contains(const char *str) const { return isNull() ? false : strstr(m_data, str) != nullptr; } + + + inline bool isEmpty() const { return size() == 0; } + inline bool isNull() const { return m_data == nullptr; } + inline char *data() { return m_data; } + inline const char *data() const { return m_data; } + inline size_t size() const { return m_size; } + + + inline bool operator!=(const char *str) const { return !isEqual(str); } + inline bool operator!=(const String &other) const { return !isEqual(other); } + inline bool operator<(const String &str) const { return strcmp(data(), str.data()) < 0; } + inline bool operator==(const char *str) const { return isEqual(str); } + inline bool operator==(const String &other) const { return isEqual(other); } + inline operator const char*() const { return m_data; } + inline String &operator=(char *str) { move(str); return *this; } + inline String &operator=(const char *str) { copy(str); return *this; } + inline String &operator=(const String &str) { copy(str); return *this; } + inline String &operator=(String &&other) { move(std::move(other)); return *this; } + + rapidjson::Value toJSON() const; + rapidjson::Value toJSON(rapidjson::Document &doc) const; + std::vector split(char sep) const; + + static String join(const std::vector &vec, char sep); + +private: + void copy(const char *str); + void copy(const String &other); + void move(char *str); + void move(String &&other); + + char *m_data; + size_t m_size; +}; + + +} /* namespace xmrig */ + + +#endif /* XMRIG_STRING_H */ diff --git a/src/common/Platform.cpp b/src/common/Platform.cpp index a95f78e7e..17fcc38e6 100644 --- a/src/common/Platform.cpp +++ b/src/common/Platform.cpp @@ -4,8 +4,9 @@ * Copyright 2014 Lucas Jones * Copyright 2014-2016 Wolf9466 * Copyright 2016 Jay D Dee - * Copyright 2016-2017 XMRig - * + * Copyright 2017-2018 XMR-Stak , + * Copyright 2018 SChernykh + * Copyright 2016-2018 XMRig , * * 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 @@ -36,7 +37,7 @@ char Platform::m_defaultConfigName[520] = { 0 }; -xmrig::c_str Platform::m_userAgent; +xmrig::String Platform::m_userAgent; const char *Platform::defaultConfigName() diff --git a/src/common/Platform.h b/src/common/Platform.h index 5dfb9ff7f..fc10e83b3 100644 --- a/src/common/Platform.h +++ b/src/common/Platform.h @@ -4,8 +4,9 @@ * Copyright 2014 Lucas Jones * Copyright 2014-2016 Wolf9466 * Copyright 2016 Jay D Dee - * Copyright 2016-2017 XMRig - * + * Copyright 2017-2018 XMR-Stak , + * Copyright 2018 SChernykh + * Copyright 2016-2018 XMRig , * * 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 @@ -28,7 +29,7 @@ #include -#include "common/utils/c_str.h" +#include "base/tools/String.h" class Platform @@ -36,7 +37,9 @@ class Platform public: static bool setThreadAffinity(uint64_t cpu_id); static const char *defaultConfigName(); + static uint32_t setTimerResolution(uint32_t resolution); static void init(const char *userAgent); + static void restoreTimerResolution(); static void setProcessPriority(int priority); static void setThreadPriority(int priority); @@ -46,7 +49,7 @@ class Platform static char *createUserAgent(); static char m_defaultConfigName[520]; - static xmrig::c_str m_userAgent; + static xmrig::String m_userAgent; }; diff --git a/src/common/Platform_mac.cpp b/src/common/Platform_mac.cpp index d0c533b08..4e4aa0ad1 100644 --- a/src/common/Platform_mac.cpp +++ b/src/common/Platform_mac.cpp @@ -40,15 +40,20 @@ char *Platform::createUserAgent() { - const size_t max = 160; + constexpr const size_t max = 256; - char *buf = new char[max]; + char *buf = new char[max](); + int length = snprintf(buf, max, "%s/%s (Macintosh; Intel Mac OS X) libuv/%s", APP_NAME, APP_VERSION, uv_version_string()); # ifdef XMRIG_NVIDIA_PROJECT const int cudaVersion = cuda_get_runtime_version(); - snprintf(buf, max, "%s/%s (Macintosh; Intel Mac OS X) libuv/%s CUDA/%d.%d clang/%d.%d.%d", APP_NAME, APP_VERSION, uv_version_string(), cudaVersion / 1000, cudaVersion % 100, __clang_major__, __clang_minor__, __clang_patchlevel__); -# else - snprintf(buf, max, "%s/%s (Macintosh; Intel Mac OS X) libuv/%s clang/%d.%d.%d", APP_NAME, APP_VERSION, uv_version_string(), __clang_major__, __clang_minor__, __clang_patchlevel__); + length += snprintf(buf + length, max - length, " CUDA/%d.%d", cudaVersion / 1000, cudaVersion % 100); +# endif + +# ifdef __clang__ + length += snprintf(buf + length, max - length, " clang/%d.%d.%d", __clang_major__, __clang_minor__, __clang_patchlevel__); +# elif defined(__GNUC__) + length += snprintf(buf + length, max - length, " gcc/%d.%d.%d", __GNUC__, __GNUC_MINOR__, __GNUC_PATCHLEVEL__); # endif return buf; @@ -65,9 +70,19 @@ bool Platform::setThreadAffinity(uint64_t cpu_id) } -void Platform::setProcessPriority(int priority) +uint32_t Platform::setTimerResolution(uint32_t resolution) { + return resolution; +} + +void Platform::restoreTimerResolution() +{ +} + + +void Platform::setProcessPriority(int priority) +{ } diff --git a/src/common/Platform_unix.cpp b/src/common/Platform_unix.cpp index 058920ec5..901df4be5 100644 --- a/src/common/Platform_unix.cpp +++ b/src/common/Platform_unix.cpp @@ -54,9 +54,9 @@ typedef cpuset_t cpu_set_t; char *Platform::createUserAgent() { - const size_t max = 160; + constexpr const size_t max = 256; - char *buf = new char[max]; + char *buf = new char[max](); int length = snprintf(buf, max, "%s/%s (Linux ", APP_NAME, APP_VERSION); # if defined(__x86_64__) @@ -70,7 +70,9 @@ char *Platform::createUserAgent() length += snprintf(buf + length, max - length, " CUDA/%d.%d", cudaVersion / 1000, cudaVersion % 100); # endif -# ifdef __GNUC__ +# ifdef __clang__ + length += snprintf(buf + length, max - length, " clang/%d.%d.%d", __clang_major__, __clang_minor__, __clang_patchlevel__); +# elif defined(__GNUC__) length += snprintf(buf + length, max - length, " gcc/%d.%d.%d", __GNUC__, __GNUC_MINOR__, __GNUC_PATCHLEVEL__); # endif @@ -92,6 +94,17 @@ bool Platform::setThreadAffinity(uint64_t cpu_id) } +uint32_t Platform::setTimerResolution(uint32_t resolution) +{ + return resolution; +} + + +void Platform::restoreTimerResolution() +{ +} + + void Platform::setProcessPriority(int priority) { } diff --git a/src/common/Platform_win.cpp b/src/common/Platform_win.cpp index 32b850d14..9e9b772d2 100644 --- a/src/common/Platform_win.cpp +++ b/src/common/Platform_win.cpp @@ -4,8 +4,9 @@ * Copyright 2014 Lucas Jones * Copyright 2014-2016 Wolf9466 * Copyright 2016 Jay D Dee - * Copyright 2016-2017 XMRig - * + * Copyright 2017-2018 XMR-Stak , + * Copyright 2018 SChernykh + * Copyright 2016-2019 XMRig , * * 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 @@ -22,6 +23,7 @@ */ +#include #include #include #include @@ -37,6 +39,11 @@ #endif +#ifdef XMRIG_AMD_PROJECT +static uint32_t timerResolution = 0; +#endif + + static inline OSVERSIONINFOEX winOsVersion() { typedef NTSTATUS (NTAPI *RtlGetVersionFunction)(LPOSVERSIONINFO); @@ -58,9 +65,9 @@ static inline OSVERSIONINFOEX winOsVersion() char *Platform::createUserAgent() { const auto osver = winOsVersion(); - const size_t max = 160; + constexpr const size_t max = 256; - char *buf = new char[max]; + char *buf = new char[max](); int length = snprintf(buf, max, "%s/%s (Windows NT %lu.%lu", APP_NAME, APP_VERSION, osver.dwMajorVersion, osver.dwMinorVersion); # if defined(__x86_64__) || defined(_M_AMD64) @@ -94,6 +101,34 @@ bool Platform::setThreadAffinity(uint64_t cpu_id) } +uint32_t Platform::setTimerResolution(uint32_t resolution) +{ +# ifdef XMRIG_AMD_PROJECT + TIMECAPS tc; + + if (timeGetDevCaps(&tc, sizeof(TIMECAPS)) != TIMERR_NOERROR) { + return 0; + } + + timerResolution = std::min(std::max(tc.wPeriodMin, resolution), tc.wPeriodMax); + + return timeBeginPeriod(timerResolution) == TIMERR_NOERROR ? timerResolution : 0; +# else + return resolution; +# endif +} + + +void Platform::restoreTimerResolution() +{ +# ifdef XMRIG_AMD_PROJECT + if (timerResolution) { + timeEndPeriod(timerResolution); + } +# endif +} + + void Platform::setProcessPriority(int priority) { if (priority == -1) { @@ -121,6 +156,7 @@ void Platform::setProcessPriority(int priority) case 5: prio = REALTIME_PRIORITY_CLASS; + break; default: break; diff --git a/src/common/config/CommonConfig.cpp b/src/common/config/CommonConfig.cpp index beb2d0c92..f2a001829 100644 --- a/src/common/config/CommonConfig.cpp +++ b/src/common/config/CommonConfig.cpp @@ -174,8 +174,11 @@ void xmrig::CommonConfig::printVersions() int length = snprintf(buf, sizeof buf, "CUDA/%d.%d ", cudaVersion / 1000, cudaVersion % 100); # else memset(buf, 0, 16); + +# if !defined(XMRIG_NO_HTTPD) || !defined(XMRIG_NO_TLS) int length = 0; # endif +# endif # if !defined(XMRIG_NO_TLS) && defined(OPENSSL_VERSION_TEXT) { @@ -280,16 +283,16 @@ bool xmrig::CommonConfig::parseBoolean(int key, bool enable) break; case KeepAliveKey: /* --keepalive */ - m_pools.back().setKeepAlive(enable ? Pool::kKeepAliveTimeout : 0); + currentPool().setKeepAlive(enable ? Pool::kKeepAliveTimeout : 0); break; case TlsKey: /* --tls */ - m_pools.back().setTLS(enable); + currentPool().setTLS(enable); break; # ifndef XMRIG_PROXY_PROJECT case NicehashKey: /* --nicehash */ - m_pools.back().setNicehash(enable); + currentPool().setNicehash(enable); break; # endif @@ -333,13 +336,15 @@ bool xmrig::CommonConfig::parseString(int key, const char *arg) break; case UserpassKey: /* --userpass */ - if (!m_pools.back().setUserpass(arg)) { + if (!currentPool().setUserpass(arg)) { return false; } break; case UrlKey: /* --url */ + fixup(); + if (m_pools.size() > 1 || m_pools[0].isValid()) { Pool pool(arg); @@ -358,23 +363,23 @@ bool xmrig::CommonConfig::parseString(int key, const char *arg) break; case UserKey: /* --user */ - m_pools.back().setUser(arg); + currentPool().setUser(arg); break; case PasswordKey: /* --pass */ - m_pools.back().setPassword(arg); + currentPool().setPassword(arg); break; case RigIdKey: /* --rig-id */ - m_pools.back().setRigId(arg); + currentPool().setRigId(arg); break; case FingerprintKey: /* --tls-fingerprint */ - m_pools.back().setFingerprint(arg); + currentPool().setFingerprint(arg); break; case VariantKey: /* --variant */ - m_pools.back().algorithm().parseVariant(arg); + currentPool().algorithm().parseVariant(arg); break; case LogFileKey: /* --log-file */ @@ -400,7 +405,7 @@ bool xmrig::CommonConfig::parseString(int key, const char *arg) case RetriesKey: /* --retries */ case RetryPauseKey: /* --retry-pause */ case ApiPort: /* --api-port */ - case PrintTimeKey: /* --cpu-priority */ + case PrintTimeKey: /* --print-time */ return parseUint64(key, strtol(arg, nullptr, 10)); case BackgroundKey: /* --background */ @@ -462,11 +467,11 @@ bool xmrig::CommonConfig::parseInt(int key, int arg) break; case KeepAliveKey: /* --keepalive */ - m_pools.back().setKeepAlive(arg); + currentPool().setKeepAlive(arg); break; case VariantKey: /* --variant */ - m_pools.back().algorithm().parseVariant(arg); + currentPool().algorithm().parseVariant(arg); break; case DonateLevelKey: /* --donate-level */ @@ -493,3 +498,30 @@ bool xmrig::CommonConfig::parseInt(int key, int arg) return true; } + + +Pool &xmrig::CommonConfig::currentPool() +{ + fixup(); + + return m_pools.back(); +} + + +void xmrig::CommonConfig::fixup() +{ + if (m_state == NoneState) { + return; + } + + if (m_pools.empty()) { + if (!m_activePools.empty()) { + std::swap(m_pools, m_activePools); + } + else { + m_pools.push_back(Pool()); + } + + m_state = NoneState; + } +} diff --git a/src/common/config/CommonConfig.h b/src/common/config/CommonConfig.h index 422a6bb2f..a864033b0 100644 --- a/src/common/config/CommonConfig.h +++ b/src/common/config/CommonConfig.h @@ -112,9 +112,11 @@ class CommonConfig : public IConfig private: bool parseInt(int key, int arg); + Pool ¤tPool(); + void fixup(); }; } /* namespace xmrig */ -#endif /* __COMMONCONFIG_H__ */ +#endif /* XMRIG_COMMONCONFIG_H */ diff --git a/src/common/config/ConfigLoader.cpp b/src/common/config/ConfigLoader.cpp index 484c2f8fb..b3b3ecb0f 100644 --- a/src/common/config/ConfigLoader.cpp +++ b/src/common/config/ConfigLoader.cpp @@ -5,7 +5,7 @@ * Copyright 2014-2016 Wolf9466 * Copyright 2016 Jay D Dee * Copyright 2017-2018 XMR-Stak , - * Copyright 2016-2018 XMRig , + * Copyright 2016-2019 XMRig , * * 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 @@ -50,6 +50,7 @@ #include "rapidjson/filereadstream.h" +bool xmrig::ConfigLoader::m_done = false; xmrig::ConfigWatcher *xmrig::ConfigLoader::m_watcher = nullptr; xmrig::IConfigCreator *xmrig::ConfigLoader::m_creator = nullptr; xmrig::IWatcherListener *xmrig::ConfigLoader::m_listener = nullptr; @@ -283,12 +284,16 @@ void xmrig::ConfigLoader::parseJSON(xmrig::IConfig *config, const struct option void xmrig::ConfigLoader::showUsage() { + m_done = true; + printf(usage); } void xmrig::ConfigLoader::showVersion() { + m_done = true; + printf(APP_NAME " " APP_VERSION "\n built on " __DATE__ # if defined(__clang__) diff --git a/src/common/config/ConfigLoader.h b/src/common/config/ConfigLoader.h index 64638af3d..b9e045379 100644 --- a/src/common/config/ConfigLoader.h +++ b/src/common/config/ConfigLoader.h @@ -5,7 +5,7 @@ * Copyright 2014-2016 Wolf9466 * Copyright 2016 Jay D Dee * Copyright 2017-2018 XMR-Stak , - * Copyright 2016-2018 XMRig , + * Copyright 2016-2019 XMRig , * * 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 @@ -21,8 +21,8 @@ * along with this program. If not, see . */ -#ifndef __CONFIGLOADER_H__ -#define __CONFIGLOADER_H__ +#ifndef XMRIG_CONFIGLOADER_H +#define XMRIG_CONFIGLOADER_H #include @@ -53,6 +53,8 @@ class ConfigLoader static IConfig *load(int argc, char **argv, IConfigCreator *creator, IWatcherListener *listener); static void release(); + static inline bool isDone() { return m_done; } + private: static bool getJSON(const char *fileName, rapidjson::Document &doc); static bool parseArg(IConfig *config, int key, const char *arg); @@ -60,6 +62,7 @@ class ConfigLoader static void showUsage(); static void showVersion(); + static bool m_done; static ConfigWatcher *m_watcher; static IConfigCreator *m_creator; static IWatcherListener *m_listener; @@ -68,4 +71,4 @@ class ConfigLoader } /* namespace xmrig */ -#endif /* __CONFIGLOADER_H__ */ +#endif /* XMRIG_CONFIGLOADER_H */ diff --git a/src/common/crypto/Algorithm.cpp b/src/common/crypto/Algorithm.cpp index a3cf48b2d..2f2593726 100644 --- a/src/common/crypto/Algorithm.cpp +++ b/src/common/crypto/Algorithm.cpp @@ -7,7 +7,7 @@ * Copyright 2017-2018 XMR-Stak , * Copyright 2018 Lee Clagett * Copyright 2018 SChernykh - * Copyright 2016-2018 XMRig , + * Copyright 2016-2019 XMRig , * * 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 @@ -62,6 +62,8 @@ static AlgoData const algorithms[] = { { "cryptonight/xao", "cn/xao", xmrig::CRYPTONIGHT, xmrig::VARIANT_XAO }, { "cryptonight/rto", "cn/rto", xmrig::CRYPTONIGHT, xmrig::VARIANT_RTO }, { "cryptonight/2", "cn/2", xmrig::CRYPTONIGHT, xmrig::VARIANT_2 }, + { "cryptonight/half", "cn/half", xmrig::CRYPTONIGHT, xmrig::VARIANT_HALF }, + { "cryptonight/xtlv9", "cn/xtlv9", xmrig::CRYPTONIGHT, xmrig::VARIANT_HALF }, # ifndef XMRIG_NO_AEON { "cryptonight-lite", "cn-lite", xmrig::CRYPTONIGHT_LITE, xmrig::VARIANT_AUTO }, @@ -109,9 +111,13 @@ static const char *variants[] = { "xao", "rto", "2", + "half" }; +static_assert(xmrig::VARIANT_MAX == ARRAY_SIZE(variants), "variants size mismatch"); + + bool xmrig::Algorithm::isValid() const { if (m_algo == INVALID_ALGO) { @@ -144,10 +150,16 @@ void xmrig::Algorithm::parseAlgorithm(const char *algo) m_variant = VARIANT_AUTO; assert(algo != nullptr); - if (algo == nullptr) { + if (algo == nullptr || strlen(algo) < 1) { return; } + if (*algo == '!') { + m_flags |= Forced; + + return parseAlgorithm(algo + 1); + } + for (size_t i = 0; i < ARRAY_SIZE(algorithms); i++) { if ((strcasecmp(algo, algorithms[i].name) == 0) || (strcasecmp(algo, algorithms[i].shortName) == 0)) { m_algo = algorithms[i].algo; @@ -166,12 +178,26 @@ void xmrig::Algorithm::parseVariant(const char *variant) { m_variant = VARIANT_AUTO; + if (variant == nullptr || strlen(variant) < 1) { + return; + } + + if (*variant == '!') { + m_flags |= Forced; + + return parseVariant(variant + 1); + } + for (size_t i = 0; i < ARRAY_SIZE(variants); i++) { if (strcasecmp(variant, variants[i]) == 0) { m_variant = static_cast(i); - break; + return; } } + + if (strcasecmp(variant, "xtlv9") == 0) { + m_variant = VARIANT_HALF; + } } diff --git a/src/common/crypto/Algorithm.h b/src/common/crypto/Algorithm.h index 731fa7937..f4380d45f 100644 --- a/src/common/crypto/Algorithm.h +++ b/src/common/crypto/Algorithm.h @@ -7,7 +7,7 @@ * Copyright 2017-2018 XMR-Stak , * Copyright 2018 Lee Clagett * Copyright 2018 SChernykh - * Copyright 2016-2018 XMRig , + * Copyright 2016-2019 XMRig , * * 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 @@ -39,28 +39,38 @@ namespace xmrig { class Algorithm { public: + enum Flags { + None = 0, + Forced = 1 + }; + inline Algorithm() : m_algo(INVALID_ALGO), + m_flags(0), m_variant(VARIANT_AUTO) {} inline Algorithm(Algo algo, Variant variant) : + m_flags(0), m_variant(variant) { setAlgo(algo); } - inline Algorithm(const char *algo) + inline Algorithm(const char *algo) : + m_flags(0) { parseAlgorithm(algo); } - bool isEqual(const Algorithm &other) const { return m_algo == other.m_algo && m_variant == other.m_variant; } - inline Algo algo() const { return m_algo; } - inline const char *name() const { return name(false); } - inline const char *shortName() const { return name(true); } - inline Variant variant() const { return m_variant; } - inline void setVariant(Variant variant) { m_variant = variant; } + inline Algo algo() const { return m_algo; } + inline bool isEqual(const Algorithm &other) const { return m_algo == other.m_algo && m_variant == other.m_variant; } + inline bool isForced() const { return m_flags & Forced; } + inline const char *name() const { return name(false); } + inline const char *shortName() const { return name(true); } + inline int flags() const { return m_flags; } + inline Variant variant() const { return m_variant; } + inline void setVariant(Variant variant) { m_variant = variant; } inline bool operator!=(const Algorithm &other) const { return !isEqual(other); } inline bool operator==(const Algorithm &other) const { return isEqual(other); } @@ -80,6 +90,7 @@ class Algorithm const char *name(bool shortName) const; Algo m_algo; + int m_flags; Variant m_variant; }; diff --git a/src/common/interfaces/IConfig.h b/src/common/interfaces/IConfig.h index 69f2ffab9..0c8cfc28d 100644 --- a/src/common/interfaces/IConfig.h +++ b/src/common/interfaces/IConfig.h @@ -97,16 +97,23 @@ class IConfig OclCompModeKey = 1410, // xmrig-proxy - AccessLogFileKey = 'A', - BindKey = 'b', - CoinKey = 1104, - CustomDiffKey = 1102, - DebugKey = 1101, - ModeKey = 'm', - PoolCoinKey = 'C', - ReuseTimeoutKey = 1106, - WorkersKey = 1103, - WorkersAdvKey = 1107, + AccessLogFileKey = 'A', + BindKey = 'b', + CoinKey = 1104, + CustomDiffKey = 1102, + DebugKey = 1101, + ModeKey = 'm', + PoolCoinKey = 'C', + ReuseTimeoutKey = 1106, + WorkersKey = 1103, + WorkersAdvKey = 1107, + TlsBindKey = 1108, + TlsCertKey = 1109, + TlsCertKeyKey = 1110, + TlsDHparamKey = 1111, + TlsCiphersKey = 1112, + TlsCipherSuitesKey = 1113, + TlsProtocolsKey = 1114, // xmrig nvidia CudaMaxThreadsKey = 1200, diff --git a/src/common/log/Log.h b/src/common/log/Log.h index 2774ae0c5..788ad2631 100644 --- a/src/common/log/Log.h +++ b/src/common/log/Log.h @@ -21,8 +21,8 @@ * along with this program. If not, see . */ -#ifndef __LOG_H__ -#define __LOG_H__ +#ifndef XMRIG_LOG_H +#define XMRIG_LOG_H #include @@ -39,7 +39,7 @@ class Log static inline Log* i() { if (!m_self) { defaultInit(); } return m_self; } static inline void add(ILogBackend *backend) { i()->m_backends.push_back(backend); } static inline void init() { if (!m_self) { new Log(); } } - static inline void release() { assert(m_self != nullptr); delete m_self; } + static inline void release() { delete m_self; } void message(ILogBackend::Level level, const char* fmt, ...); void text(const char* fmt, ...); @@ -98,4 +98,4 @@ class Log # define LOG_DEBUG_WARN(x, ...) #endif -#endif /* __LOG_H__ */ +#endif /* XMRIG_LOG_H */ diff --git a/src/common/net/Client.cpp b/src/common/net/Client.cpp index 1d1d86c7f..6da639424 100644 --- a/src/common/net/Client.cpp +++ b/src/common/net/Client.cpp @@ -5,7 +5,7 @@ * Copyright 2014-2016 Wolf9466 * Copyright 2016 Jay D Dee * Copyright 2017-2018 XMR-Stak , - * Copyright 2016-2018 XMRig , + * Copyright 2016-2019 XMRig , * * 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 @@ -212,6 +212,12 @@ const char *Client::tlsVersion() const int64_t Client::submit(const JobResult &result) { +# ifndef XMRIG_PROXY_PROJECT + if (result.clientId != m_rpcId) { + return -1; + } +# endif + using namespace rapidjson; # ifdef XMRIG_PROXY_PROJECT @@ -336,8 +342,7 @@ bool Client::parseJob(const rapidjson::Value ¶ms, int *code) if (params.HasMember("algo")) { job.setAlgorithm(params["algo"].GetString()); } - - if (params.HasMember("variant")) { + else if (params.HasMember("variant")) { const rapidjson::Value &variant = params["variant"]; if (variant.IsInt()) { @@ -355,6 +360,8 @@ bool Client::parseJob(const rapidjson::Value ¶ms, int *code) return false; } + m_job.setClientId(m_rpcId); + if (m_job != job) { m_jobs++; m_job = std::move(job); diff --git a/src/common/net/Client.h b/src/common/net/Client.h index d64183384..a05710fc3 100644 --- a/src/common/net/Client.h +++ b/src/common/net/Client.h @@ -5,7 +5,7 @@ * Copyright 2014-2016 Wolf9466 * Copyright 2016 Jay D Dee * Copyright 2017-2018 XMR-Stak , - * Copyright 2016-2018 XMRig , + * Copyright 2016-2019 XMRig , * * 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 diff --git a/src/common/net/Id.h b/src/common/net/Id.h index 5fb2db521..999e7837a 100644 --- a/src/common/net/Id.h +++ b/src/common/net/Id.h @@ -5,7 +5,7 @@ * Copyright 2014-2016 Wolf9466 * Copyright 2016 Jay D Dee * Copyright 2017-2018 XMR-Stak , - * Copyright 2016-2018 XMRig , + * Copyright 2016-2019 XMRig , * * 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 @@ -21,8 +21,8 @@ * along with this program. If not, see . */ -#ifndef __ID_H__ -#define __ID_H__ +#ifndef XMRIG_ID_H +#define XMRIG_ID_H #include @@ -95,4 +95,4 @@ class Id } /* namespace xmrig */ -#endif /* __ID_H__ */ +#endif /* XMRIG_ID_H */ diff --git a/src/common/net/Job.cpp b/src/common/net/Job.cpp index 2bfb39f0e..7da2ed83b 100644 --- a/src/common/net/Job.cpp +++ b/src/common/net/Job.cpp @@ -7,7 +7,7 @@ * Copyright 2017-2018 XMR-Stak , * Copyright 2018 Lee Clagett * Copyright 2018 SChernykh - * Copyright 2016-2018 XMRig , + * Copyright 2016-2019 XMRig , * * 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 @@ -91,6 +91,12 @@ Job::~Job() } +bool Job::isEqual(const Job &other) const +{ + return m_id == other.m_id && m_clientId == other.m_clientId && memcmp(m_blob, other.m_blob, sizeof(m_blob)) == 0; +} + + bool Job::setBlob(const char *blob) { if (!blob) { @@ -119,6 +125,15 @@ bool Job::setBlob(const char *blob) m_algorithm.setVariant(variant()); } + if (!m_algorithm.isForced()) { + if (m_algorithm.variant() == xmrig::VARIANT_XTL && m_blob[0] >= 9) { + m_algorithm.setVariant(xmrig::VARIANT_HALF); + } + else if (m_algorithm.variant() == xmrig::VARIANT_MSR && m_blob[0] >= 8) { + m_algorithm.setVariant(xmrig::VARIANT_HALF); + } + } + # ifdef XMRIG_PROXY_PROJECT memset(m_rawBlob, 0, sizeof(m_rawBlob)); memcpy(m_rawBlob, blob, m_size * 2); @@ -214,18 +229,6 @@ char *Job::toHex(const unsigned char* in, unsigned int len) #endif -bool Job::operator==(const Job &other) const -{ - return m_id == other.m_id && memcmp(m_blob, other.m_blob, sizeof(m_blob)) == 0; -} - - -bool Job::operator!=(const Job &other) const -{ - return m_id != other.m_id || memcmp(m_blob, other.m_blob, sizeof(m_blob)) != 0; -} - - xmrig::Variant Job::variant() const { using namespace xmrig; diff --git a/src/common/net/Job.h b/src/common/net/Job.h index b561b9c1b..394727dfe 100644 --- a/src/common/net/Job.h +++ b/src/common/net/Job.h @@ -7,7 +7,7 @@ * Copyright 2017-2018 XMR-Stak , * Copyright 2018 Lee Clagett * Copyright 2018 SChernykh - * Copyright 2016-2018 XMRig , + * Copyright 2016-2019 XMRig , * * 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 @@ -42,6 +42,7 @@ class Job Job(int poolId, bool nicehash, const xmrig::Algorithm &algorithm, const xmrig::Id &clientId); ~Job(); + bool isEqual(const Job &other) const; bool setBlob(const char *blob); bool setTarget(const char *target); void setAlgorithm(const char *algo); @@ -81,8 +82,8 @@ class Job static char *toHex(const unsigned char* in, unsigned int len); # endif - bool operator==(const Job &other) const; - bool operator!=(const Job &other) const; + inline bool operator==(const Job &other) const { return isEqual(other); } + inline bool operator!=(const Job &other) const { return !isEqual(other); } private: xmrig::Variant variant() const; diff --git a/src/common/net/Pool.cpp b/src/common/net/Pool.cpp index 141e51158..a44f8a41f 100644 --- a/src/common/net/Pool.cpp +++ b/src/common/net/Pool.cpp @@ -6,7 +6,7 @@ * Copyright 2016 Jay D Dee * Copyright 2017-2018 XMR-Stak , * Copyright 2018 SChernykh - * Copyright 2016-2018 XMRig , + * Copyright 2016-2019 XMRig , * * 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 @@ -322,23 +322,39 @@ void Pool::adjustVariant(const xmrig::Variant variantHint) m_nicehash = true; bool valid = true; - if (m_host.contains("cryptonight.") && m_port == 3355) { - valid = m_algorithm.algo() == CRYPTONIGHT; + switch (m_port) { + case 3355: + case 33355: + valid = m_algorithm.algo() == CRYPTONIGHT && m_host.contains("cryptonight."); m_algorithm.setVariant(VARIANT_0); - } - else if (m_host.contains("cryptonightv7.") && m_port == 3363) { - valid = m_algorithm.algo() == CRYPTONIGHT; + break; + + case 3363: + case 33363: + valid = m_algorithm.algo() == CRYPTONIGHT && m_host.contains("cryptonightv7."); m_algorithm.setVariant(VARIANT_1); - } - else if (m_host.contains("cryptonightheavy.") && m_port == 3364) { - valid = m_algorithm.algo() == CRYPTONIGHT_HEAVY; + break; + + case 3364: + valid = m_algorithm.algo() == CRYPTONIGHT_HEAVY && m_host.contains("cryptonightheavy."); m_algorithm.setVariant(VARIANT_0); + break; + + case 3367: + case 33367: + valid = m_algorithm.algo() == CRYPTONIGHT && m_host.contains("cryptonightv8."); + m_algorithm.setVariant(VARIANT_2); + break; + + default: + break; } if (!valid) { m_algorithm.setAlgo(INVALID_ALGO); } + m_tls = m_port > 33000; return; } @@ -349,7 +365,7 @@ void Pool::adjustVariant(const xmrig::Variant variantHint) if (m_host.contains("xmr.pool.")) { valid = m_algorithm.algo() == CRYPTONIGHT; - m_algorithm.setVariant(m_port == 45700 ? VARIANT_1 : VARIANT_0); + m_algorithm.setVariant(m_port == 45700 ? VARIANT_AUTO : VARIANT_0); } else if (m_host.contains("aeon.pool.") && m_port == 45690) { valid = m_algorithm.algo() == CRYPTONIGHT_LITE; @@ -396,6 +412,7 @@ void Pool::rebuild() addVariant(xmrig::VARIANT_2); addVariant(xmrig::VARIANT_1); addVariant(xmrig::VARIANT_0); + addVariant(xmrig::VARIANT_HALF); addVariant(xmrig::VARIANT_XTL); addVariant(xmrig::VARIANT_TUBE); addVariant(xmrig::VARIANT_MSR); diff --git a/src/common/net/Pool.h b/src/common/net/Pool.h index 123cc131f..c051b0ee2 100644 --- a/src/common/net/Pool.h +++ b/src/common/net/Pool.h @@ -6,7 +6,7 @@ * Copyright 2016 Jay D Dee * Copyright 2017-2018 XMR-Stak , * Copyright 2018 SChernykh - * Copyright 2016-2018 XMRig , + * Copyright 2016-2019 XMRig , * * 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 diff --git a/src/common/net/Tls.h b/src/common/net/Tls.h index 6e38f32f7..083adfc45 100644 --- a/src/common/net/Tls.h +++ b/src/common/net/Tls.h @@ -21,8 +21,8 @@ * along with this program. If not, see . */ -#ifndef XMRIG_TLS_H -#define XMRIG_TLS_H +#ifndef XMRIG_CLIENT_TLS_H +#define XMRIG_CLIENT_TLS_H #include @@ -59,4 +59,4 @@ class Client::Tls }; -#endif /* XMRIG_TLS_H */ +#endif /* XMRIG_CLIENT_TLS_H */ diff --git a/src/common/utils/c_str.h b/src/common/utils/c_str.h index 7ce63754e..fe0164b9e 100644 --- a/src/common/utils/c_str.h +++ b/src/common/utils/c_str.h @@ -21,82 +21,19 @@ * along with this program. If not, see . */ -#ifndef __C_STR_H__ -#define __C_STR_H__ +#ifndef XMRIG_C_STR_H +#define XMRIG_C_STR_H -#include -#include - -#include +#include "base/tools/String.h" namespace xmrig { -/** - * @brief Simple C string wrapper. - * - * 1. I know about std:string. - * 2. For some reason I prefer don't use std:string in miner, eg because of file size of MSYS2 builds. - */ -class c_str -{ -public: - inline c_str() : m_data(nullptr) {} - inline c_str(c_str &&other) { m_data = other.m_data; other.m_data = nullptr; } - inline c_str(const c_str &other) : m_data(nullptr) { set(other.data()); } - inline c_str(const char *str) : m_data(nullptr) { set(str); } - inline ~c_str() { free(m_data); } - - - inline void set(const char *str) - { - free(m_data); - - m_data = str != nullptr ? strdup(str) : nullptr; - } - - - inline void set(char *str) - { - free(m_data); - - m_data = str; - } - - - inline bool isEqual(const char *str) const - { - return (m_data != nullptr && str != nullptr && strcmp(m_data, str) == 0) || (m_data == nullptr && m_data == nullptr); - } - - - inline bool contains(const char *str) const - { - return strstr(m_data, str) != nullptr; - } - - - inline bool isNull() const { return m_data == nullptr; } - inline const char *data() const { return m_data; } - inline size_t size() const { return m_data == nullptr ? 0 : strlen(m_data); } - - - inline bool operator!=(const c_str &str) const { return !isEqual(str.data()); } - inline bool operator!=(const char *str) const { return !isEqual(str); } - inline bool operator==(const c_str &str) const { return isEqual(str.data()); } - inline bool operator==(const char *str) const { return isEqual(str); } - inline c_str &operator=(char *str) { set(str); return *this; } - inline c_str &operator=(const c_str &str) { set(str.data()); return *this; } - inline c_str &operator=(const char *str) { set(str); return *this; } - - -private: - char *m_data; -}; +typedef String c_str; } /* namespace xmrig */ -#endif /* __C_STR_H__ */ +#endif /* XMRIG_C_STR_H */ diff --git a/src/common/utils/timestamp.h b/src/common/utils/timestamp.h index 6b6a8ab24..55b4c21d6 100644 --- a/src/common/utils/timestamp.h +++ b/src/common/utils/timestamp.h @@ -5,7 +5,7 @@ * Copyright 2014-2016 Wolf9466 * Copyright 2016 Jay D Dee * Copyright 2017-2018 XMR-Stak , - * Copyright 2016-2018 XMRig , + * Copyright 2016-2019 XMRig , * * 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 @@ -31,7 +31,7 @@ namespace xmrig { -static inline int64_t currentMSecsSinceEpoch() +static inline int64_t steadyTimestamp() { using namespace std::chrono; if (high_resolution_clock::is_steady) { @@ -42,6 +42,14 @@ static inline int64_t currentMSecsSinceEpoch() } +static inline int64_t currentMSecsSinceEpoch() +{ + using namespace std::chrono; + + return time_point_cast(system_clock::now()).time_since_epoch().count(); +} + + } /* namespace xmrig */ #endif /* XMRIG_TIMESTAMP_H */ diff --git a/src/common/xmrig.h b/src/common/xmrig.h index 52650f0d2..883d866d5 100644 --- a/src/common/xmrig.h +++ b/src/common/xmrig.h @@ -5,7 +5,8 @@ * Copyright 2014-2016 Wolf9466 * Copyright 2016 Jay D Dee * Copyright 2017-2018 XMR-Stak , - * Copyright 2016-2018 XMRig , + * Copyright 2018 SChernykh + * Copyright 2016-2019 XMRig , * * 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 @@ -68,6 +69,7 @@ enum Variant { VARIANT_XAO = 6, // Modified CryptoNight variant 0 (Alloy only) VARIANT_RTO = 7, // Modified CryptoNight variant 1 (Arto only) VARIANT_2 = 8, // CryptoNight variant 2 + VARIANT_HALF = 9, // CryptoNight variant 2 with half iterations (Masari/Stellite) VARIANT_MAX }; @@ -99,6 +101,7 @@ enum Assembly { ASM_AUTO, ASM_INTEL, ASM_RYZEN, + ASM_BULLDOZER, ASM_MAX }; diff --git a/src/config.json b/src/config.json index a206e9bcf..c742bf401 100644 --- a/src/config.json +++ b/src/config.json @@ -11,8 +11,16 @@ }, "background": false, "bind": [ - "0.0.0.0:3333", - "[::]:3333" + { + "host": "0.0.0.0", + "port": 3333, + "tls": false + }, + { + "host": "::", + "port": 3333, + "tls": false + } ], "colors": true, "custom-diff": 0, @@ -34,6 +42,14 @@ "retries": 2, "retry-pause": 1, "reuse-timeout": 0, + "tls": { + "protocols": null, + "cert": null, + "cert_key": null, + "ciphers": null, + "ciphersuites": null, + "dhparam": null + }, "user-agent": null, "verbose": false, "watch": true, diff --git a/src/core/Config.cpp b/src/core/Config.cpp index dbaf52926..c681473d4 100644 --- a/src/core/Config.cpp +++ b/src/core/Config.cpp @@ -61,6 +61,20 @@ xmrig::Config::Config() : xmrig::CommonConfig(), } +bool xmrig::Config::isTLS() const +{ +# ifndef XMRIG_NO_TLS + for (const BindHost &host : m_bind) { + if (host.isTLS()) { + return true; + } + } +# endif + + return false; +} + + bool xmrig::Config::reload(const char *json) { return xmrig::ConfigLoader::reload(this, json); @@ -96,8 +110,8 @@ void xmrig::Config::getJSON(rapidjson::Document &doc) const doc.AddMember("background", isBackground(), allocator); Value bind(kArrayType); - for (const Addr &addr : m_addrs) { - bind.PushBack(StringRef(addr.addr()), allocator); + for (const xmrig::BindHost &host : m_bind) { + bind.PushBack(host.toJSON(doc), allocator); } doc.AddMember("bind", bind, allocator); @@ -118,6 +132,11 @@ void xmrig::Config::getJSON(rapidjson::Document &doc) const doc.AddMember("retries", retries(), allocator); doc.AddMember("retry-pause", retryPause(), allocator); doc.AddMember("reuse-timeout", reuseTimeout(), allocator); + +# ifndef XMRIG_NO_TLS + doc.AddMember("tls", m_tls.toJSON(doc), allocator); +# endif + doc.AddMember("user-agent", userAgent() ? Value(StringRef(userAgent())).Move() : Value(kNullType).Move(), allocator); # ifdef HAVE_SYSLOG_H @@ -146,9 +165,9 @@ bool xmrig::Config::finalize() return false; } - if (m_addrs.empty()) { - m_addrs.push_back(Addr("0.0.0.0:3333")); - m_addrs.push_back(Addr("[::]:3333")); + if (m_bind.empty()) { + m_bind.push_back(xmrig::BindHost("0.0.0.0", 3333, 4)); + m_bind.push_back(xmrig::BindHost("::", 3333, 6)); } return true; @@ -194,11 +213,14 @@ bool xmrig::Config::parseString(int key, const char *arg) setMode(arg); break; - case BindKey: /* --bind */ + case BindKey: /* --bind */ + case TlsBindKey: /* --tls-bind */ { - Addr addr(arg); - if (addr.isValid()) { - m_addrs.push_back(std::move(addr)); + xmrig::BindHost host(arg); + host.setTLS(key == TlsBindKey); + + if (host.isValid()) { + m_bind.push_back(std::move(host)); } } break; @@ -221,9 +243,35 @@ bool xmrig::Config::parseString(int key, const char *arg) m_workersMode = Workers::parseMode(arg); break; - case CustomDiffKey: /* --custom-diff */ + case CustomDiffKey: /* --custom-diff */ return parseUint64(key, strtol(arg, nullptr, 10)); +# ifndef XMRIG_NO_TLS + case TlsCertKey: /* --tls-cert */ + m_tls.setCert(arg); + break; + + case TlsCertKeyKey: /* --tls-cert-key */ + m_tls.setKey(arg); + break; + + case TlsDHparamKey: /* --tls-dhparam */ + m_tls.setDH(arg); + break; + + case TlsCiphersKey: /* --tls-ciphers */ + m_tls.setCiphers(arg); + break; + + case TlsCipherSuitesKey: /* --tls-ciphersuites */ + m_tls.setCipherSuites(arg); + break; + + case TlsProtocolsKey: /* --tls-protocols */ + m_tls.setProtocols(arg); + break; +# endif + default: break; } @@ -262,13 +310,24 @@ void xmrig::Config::parseJSON(const rapidjson::Document &doc) const rapidjson::Value &bind = doc["bind"]; if (bind.IsArray()) { for (const rapidjson::Value &value : bind.GetArray()) { - if (!value.IsString()) { - continue; + if (value.IsObject()) { + xmrig::BindHost host(value); + if (host.isValid()) { + m_bind.push_back(std::move(host)); + } + } + else if (value.IsString()) { + parseString(BindKey, value.GetString()); } - - parseString(BindKey, value.GetString()); } } + +# ifndef XMRIG_NO_TLS + const rapidjson::Value &tls = doc["tls"]; + if (tls.IsObject()) { + m_tls = std::move(TlsConfig(tls)); + } +# endif } diff --git a/src/core/Config.h b/src/core/Config.h index 5be10efc1..5183fe681 100644 --- a/src/core/Config.h +++ b/src/core/Config.h @@ -31,13 +31,14 @@ #include "common/config/CommonConfig.h" #include "common/utils/c_str.h" -#include "proxy/Addr.h" +#include "proxy/BindHost.h" #include "proxy/workers/Workers.h" #include "rapidjson/fwd.h" -class Addr; -class Url; +#ifndef XMRIG_NO_TLS +# include "proxy/tls/TlsConfig.h" +#endif namespace xmrig { @@ -68,17 +69,19 @@ class Config : public CommonConfig Config(); + bool isTLS() const; bool reload(const char *json); - const char *modeName() const; + void getJSON(rapidjson::Document &doc) const override; + static Config *load(int argc, char **argv, IWatcherListener *listener); inline bool isDebug() const { return m_debug; } inline bool isVerbose() const { return m_verbose; } inline const char *accessLog() const { return m_accessLog.data(); } - inline const std::vector &addrs() const { return m_addrs; } + inline const xmrig::BindHosts &bind() const { return m_bind; } inline int mode() const { return m_mode; } inline int reuseTimeout() const { return m_reuseTimeout; } inline uint64_t diff() const { return m_diff; } @@ -87,6 +90,10 @@ class Config : public CommonConfig inline void toggleVerbose() { m_verbose = !m_verbose; } inline Workers::Mode workersMode() const { return m_workersMode; } +# ifndef XMRIG_NO_TLS + inline const xmrig::TlsConfig &tls() const { return m_tls; } +# endif + protected: bool finalize() override; bool parseBoolean(int key, bool enable) override; @@ -103,10 +110,14 @@ class Config : public CommonConfig int m_mode; int m_reuseTimeout; - std::vector m_addrs; uint64_t m_diff; Workers::Mode m_workersMode; + xmrig::BindHosts m_bind; xmrig::c_str m_accessLog; + +# ifndef XMRIG_NO_TLS + xmrig::TlsConfig m_tls; +# endif }; diff --git a/src/core/ConfigLoader_platform.h b/src/core/ConfigLoader_platform.h index 6f9cb686a..59ae18bd8 100644 --- a/src/core/ConfigLoader_platform.h +++ b/src/core/ConfigLoader_platform.h @@ -51,7 +51,6 @@ Options:\n\ -u, --user=USERNAME username for mining server\n\ -p, --pass=PASSWORD password for mining server\n\ --rig-id=ID rig identifier for pool-side statistics (needs pool support)\n\ - --tls enable SSL/TLS support (needs pool support)\n\ --tls-fingerprint=F pool TLS certificate fingerprint, if set enable strict certificate pinning\n\ -k, --keepalive prevent timeout (needs pool support)\n\ -r, --retries=N number of times to retry before switch to backup server (default: 1)\n\ @@ -68,10 +67,10 @@ Options:\n\ -c, --config=FILE load a JSON-format configuration file\n\ --no-watch disable configuration file watching\n\ -l, --log-file=FILE log all output to a file\n" -# ifdef HAVE_SYSLOG_H +#ifdef HAVE_SYSLOG_H "\ -S, --syslog use system log for output messages\n" -# endif +#endif "\ -A --access-log-file=N log all workers access to a file\n\ --api-port=N port for the miner API\n\ @@ -79,7 +78,19 @@ Options:\n\ --api-worker-id=ID custom worker-id (instance name) for API\n\ --api-id=ID custom instance ID for API\n\ --api-ipv6 enable IPv6 support for API\n\ - --api-no-restricted enable full remote access (only if API token set)\n\ + --api-no-restricted enable full remote access (only if API token set)\n" +#ifndef XMRIG_NO_TLS +"\ + --tls enable SSL/TLS support for pool connection (needs pool support)\n\ + --tls-bind=ADDR bind to specified address with enabled TLS\n\ + --tls-cert=FILE load TLS certificate chain from a file in the PEM format\n\ + --tls-cert-key=FILE load TLS certificate private key from a file in the PEM format\n\ + --tls-dhparam=FILE load DH parameters for DHE ciphers from a file in the PEM format\n\ + --tls-protocols=N enable specified TLS protocols, example: \"TLSv1 TLSv1.1 TLSv1.2 TLSv1.3\"\n\ + --tls-ciphers=S set list of available ciphers (TLSv1.2 and below)\n\ + --tls-ciphersuites=S set list of available TLSv1.3 ciphersuites\n" +#endif +"\ -h, --help display this help and exit\n\ -V, --version output version information and exit\n\ "; @@ -128,6 +139,13 @@ static struct option const options[] = { { "rig-id", 1, nullptr, xmrig::IConfig::RigIdKey }, { "tls", 0, nullptr, xmrig::IConfig::TlsKey }, { "tls-fingerprint", 1, nullptr, xmrig::IConfig::FingerprintKey }, + { "tls-bind", 1, nullptr, xmrig::IConfig::TlsBindKey }, + { "tls-cert", 1, nullptr, xmrig::IConfig::TlsCertKey }, + { "tls-cert-key", 1, nullptr, xmrig::IConfig::TlsCertKeyKey }, + { "tls-dhparam", 1, nullptr, xmrig::IConfig::TlsDHparamKey }, + { "tls-protocols", 1, nullptr, xmrig::IConfig::TlsProtocolsKey }, + { "tls-ciphers", 1, nullptr, xmrig::IConfig::TlsCiphersKey }, + { "tls-ciphersuites", 1, nullptr, xmrig::IConfig::TlsCipherSuitesKey}, { nullptr, 0, nullptr, 0 } }; diff --git a/src/proxy/Addr.h b/src/proxy/Addr.h deleted file mode 100644 index 6c4750f70..000000000 --- a/src/proxy/Addr.h +++ /dev/null @@ -1,118 +0,0 @@ -/* XMRig - * Copyright 2010 Jeff Garzik - * Copyright 2012-2014 pooler - * Copyright 2014 Lucas Jones - * Copyright 2014-2016 Wolf9466 - * Copyright 2016 Jay D Dee - * Copyright 2017-2018 XMR-Stak , - * Copyright 2016-2018 XMRig , - * - * 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 - * (at your option) 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 . - */ - -#ifndef __ADDR_H__ -#define __ADDR_H__ - - -#include -#include -#include - - -#include "common/utils/c_str.h" - - -class Addr -{ -public: - constexpr static uint16_t kDefaultPort = 3333; - - - inline Addr() : - m_version(0), - m_port(0) - {} - - - inline Addr(const char *addr) : - m_version(0), - m_port(0), - m_addr(addr) - { - if (!addr || strlen(addr) < 5) { - return; - } - - if (addr[0] == '[') { - parseIPv6(addr); - return; - } - - parseIPv4(addr); - } - - - inline bool isIPv6() const { return m_version == 6; } - inline bool isValid() const { return m_version && !m_ip.isNull() && m_port > 0; } - inline const char *addr() const { return m_addr.data(); } - inline const char *ip() const { return m_ip.data(); } - inline uint16_t port() const { return m_port; } - -private: - void parseIPv4(const char *addr) - { - const char *port = strchr(addr, ':'); - if (!port) { - return; - } - - m_version = 4; - const size_t size = port++ - addr + 1; - char *ip = new char[size](); - memcpy(ip, addr, size - 1); - - m_ip = ip; - m_port = static_cast(strtol(port, nullptr, 10)); - } - - - void parseIPv6(const char *addr) - { - const char *end = strchr(addr, ']'); - if (!end) { - return; - } - - const char *port = strchr(end, ':'); - if (!port) { - return; - } - - m_version = 6; - const size_t size = end - addr; - char *ip = new char[size](); - memcpy(ip, addr + 1, size - 1); - - m_ip = ip; - m_port = static_cast(strtol(port + 1, nullptr, 10)); - } - - - int m_version; - uint16_t m_port; - xmrig::c_str m_addr; - xmrig::c_str m_ip; -}; - -#endif /* __ADDR_H__ */ diff --git a/src/proxy/BindHost.cpp b/src/proxy/BindHost.cpp new file mode 100644 index 000000000..a5c7735d3 --- /dev/null +++ b/src/proxy/BindHost.cpp @@ -0,0 +1,158 @@ +/* XMRig + * Copyright 2010 Jeff Garzik + * Copyright 2012-2014 pooler + * Copyright 2014 Lucas Jones + * Copyright 2014-2016 Wolf9466 + * Copyright 2016 Jay D Dee + * Copyright 2017-2018 XMR-Stak , + * Copyright 2016-2018 XMRig , + * + * 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 + * (at your option) 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 . + */ + + +#include +#include +#include + + +#include "proxy/BindHost.h" +#include "rapidjson/document.h" + + +xmrig::BindHost::BindHost(const char *addr) : + m_tls(false), + m_version(0), + m_port(0) +{ + if (!addr || strlen(addr) < 5) { + return; + } + + if (addr[0] == '[') { + parseIPv6(addr); + return; + } + + parseIPv4(addr); +} + + +xmrig::BindHost::BindHost(const char *host, uint16_t port, int version) : + m_tls(false), + m_version(version), + m_port(port), + m_host(host) +{ +} + + +xmrig::BindHost::BindHost(const rapidjson::Value &object) : + m_tls(false), + m_version(0), + m_port(0) +{ + if (!parseHost(object["host"].GetString())) { + return; + } + + m_port = object["port"].GetUint(); + m_tls = object["tls"].GetBool(); +} + + +rapidjson::Value xmrig::BindHost::toJSON(rapidjson::Document &doc) const +{ + using namespace rapidjson; + + auto &allocator = doc.GetAllocator(); + + Value obj(kObjectType); + + obj.AddMember("host", StringRef(host()), allocator); + obj.AddMember("port", port(), allocator); + obj.AddMember("tls", isTLS(), allocator); + + return obj; +} + + +bool xmrig::BindHost::parseHost(const char *host) +{ + assert(host != nullptr && strlen(host) >= 2); + m_version = 0; + + if (host == nullptr || strlen(host) < 2) { + return false; + } + + if (host[0] == '[') { + const char *end = strchr(host, ']'); + if (!end) { + return false; + } + + const size_t size = end - host; + char *buf = new char[size](); + memcpy(buf, host + 1, size - 1); + + m_version = 6; + m_host = buf; + } + else { + m_version = strchr(host, ':') != nullptr ? 6 : 4; + m_host = host; + } + + return m_version > 0; +} + + +void xmrig::BindHost::parseIPv4(const char *addr) +{ + const char *port = strchr(addr, ':'); + if (!port) { + return; + } + + m_version = 4; + const size_t size = port++ - addr + 1; + char *host = new char[size](); + memcpy(host, addr, size - 1); + + m_host = host; + m_port = static_cast(strtol(port, nullptr, 10)); +} + + +void xmrig::BindHost::parseIPv6(const char *addr) +{ + const char *end = strchr(addr, ']'); + if (!end) { + return; + } + + const char *port = strchr(end, ':'); + if (!port) { + return; + } + + m_version = 6; + const size_t size = end - addr; + char *host = new char[size](); + memcpy(host, addr + 1, size - 1); + + m_host = host; + m_port = static_cast(strtol(port + 1, nullptr, 10)); +} diff --git a/src/proxy/BindHost.h b/src/proxy/BindHost.h new file mode 100644 index 000000000..e142b1fa7 --- /dev/null +++ b/src/proxy/BindHost.h @@ -0,0 +1,82 @@ +/* XMRig + * Copyright 2010 Jeff Garzik + * Copyright 2012-2014 pooler + * Copyright 2014 Lucas Jones + * Copyright 2014-2016 Wolf9466 + * Copyright 2016 Jay D Dee + * Copyright 2017-2018 XMR-Stak , + * Copyright 2016-2018 XMRig , + * + * 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 + * (at your option) 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 . + */ + +#ifndef XMRIG_BINDHOST_H +#define XMRIG_BINDHOST_H + + +#include +#include + + +#include "common/utils/c_str.h" +#include "rapidjson/fwd.h" + + +namespace xmrig { + + +class BindHost +{ +public: + constexpr static uint16_t kDefaultPort = 3333; + + + inline BindHost() : + m_tls(false), + m_version(0), + m_port(0) + {} + + + BindHost(const char *addr); + BindHost(const char *host, uint16_t port, int version); + BindHost(const rapidjson::Value &object); + + rapidjson::Value toJSON(rapidjson::Document &doc) const; + + inline bool isIPv6() const { return m_version == 6; } + inline bool isTLS() const { return m_tls; } + inline bool isValid() const { return m_version && !m_host.isNull() && m_port > 0; } + inline const char *host() const { return m_host.data(); } + inline uint16_t port() const { return m_port; } + inline void setTLS(bool enable) { m_tls = enable; } + +private: + bool parseHost(const char *host); + void parseIPv4(const char *addr); + void parseIPv6(const char *addr); + + bool m_tls; + int m_version; + uint16_t m_port; + xmrig::c_str m_host; +}; + + +typedef std::vector BindHosts; + + +} /* namespace xmrig */ + +#endif /* XMRIG_BINDHOST_H */ diff --git a/src/proxy/Miner.cpp b/src/proxy/Miner.cpp index b501f27a4..3dccc2e42 100644 --- a/src/proxy/Miner.cpp +++ b/src/proxy/Miner.cpp @@ -37,6 +37,7 @@ #include "proxy/events/LoginEvent.h" #include "proxy/events/SubmitEvent.h" #include "proxy/Miner.h" +#include "proxy/tls/TlsContext.h" #include "proxy/Uuid.h" #include "rapidjson/document.h" #include "rapidjson/error/en.h" @@ -44,19 +45,28 @@ #include "rapidjson/writer.h" +#ifndef XMRIG_NO_TLS +# include "proxy/tls/Tls.h" +#endif + + static int64_t nextId = 0; +char Miner::m_sendBuf[2048] = { 0 }; xmrig::Storage Miner::m_storage; -Miner::Miner(bool nicehash, bool ipv6) : +Miner::Miner(const xmrig::TlsContext *ctx, bool ipv6, uint16_t port) : m_ipv6(ipv6), - m_nicehash(nicehash), + m_nicehash(true), m_ip(), + m_routeId(-1), m_id(++nextId), m_loginId(0), m_recvBufPos(0), m_mapperId(-1), m_state(WaitLoginState), + m_tls(nullptr), + m_localPort(port), m_customDiff(0), m_diff(0), m_expire(uv_now(uv_default_loop()) + kLoginTimeout), @@ -75,6 +85,12 @@ Miner::Miner(bool nicehash, bool ipv6) : m_recvBuf.base = m_buf; m_recvBuf.len = sizeof(m_buf); +# ifndef XMRIG_NO_TLS + if (ctx != nullptr) { + m_tls = new Tls(ctx->ctx(), this); + } +# endif + Counters::connections++; } @@ -83,6 +99,10 @@ Miner::~Miner() { m_socket.data = nullptr; +# ifndef XMRIG_NO_TLS + delete m_tls; +# endif + Counters::connections--; } @@ -108,6 +128,12 @@ bool Miner::accept(uv_stream_t *server) uv_read_start(reinterpret_cast(&m_socket), Miner::onAllocBuffer, Miner::onRead); +# ifndef XMRIG_NO_TLS + if (isTLS()) { + return m_tls->accept(); + } +# endif + return true; } @@ -181,20 +207,7 @@ void Miner::setJob(Job &job) doc.AddMember("params", params, allocator); } - StringBuffer buffer(0, 512); - Writer writer(buffer); - doc.Accept(writer); - - const size_t size = buffer.GetSize(); - if (size > (sizeof(m_sendBuf) - 2)) { - return; - } - - memcpy(m_sendBuf, buffer.GetString(), size); - m_sendBuf[size] = '\n'; - m_sendBuf[size + 1] = '\0'; - - send(size + 1); + send(doc); } @@ -204,6 +217,12 @@ void Miner::success(int64_t id, const char *status) } +bool Miner::isWritable() const +{ + return m_state != ClosingState && uv_is_writable(reinterpret_cast(&m_socket)) == 1; +} + + bool Miner::parseRequest(int64_t id, const char *method, const rapidjson::Value ¶ms) { if (!method || !params.IsObject()) { @@ -293,6 +312,40 @@ bool Miner::parseRequest(int64_t id, const char *method, const rapidjson::Value } +bool Miner::send(BIO *bio) +{ +# ifndef XMRIG_NO_TLS + uv_buf_t buf; + buf.len = BIO_get_mem_data(bio, &buf.base); + + if (buf.len == 0) { + return true; + } + + LOG_DEBUG("[%s] TLS send (%d bytes)", m_ip, static_cast(buf.len)); + + if (!isWritable()) { + return false; + } + + const int rc = uv_try_write(reinterpret_cast(&m_socket), &buf, 1); + (void) BIO_reset(bio); + + if (rc < 0) { + shutdown(true); + + return false; + } + + m_tx += buf.len; + + return true; +# else + return false; +# endif +} + + void Miner::heartbeat() { m_expire = uv_now(uv_default_loop()) + kSocketTimeout; @@ -333,16 +386,97 @@ void Miner::parse(char *line, size_t len) } +void Miner::read() +{ + char* end; + char* start = m_recvBuf.base; + size_t remaining = m_recvBufPos; + + while ((end = static_cast(memchr(start, '\n', remaining))) != nullptr) { + end++; + size_t len = end - start; + parse(start, len); + + remaining -= len; + start = end; + } + + if (remaining == 0) { + m_recvBufPos = 0; + return; + } + + if (start == m_recvBuf.base) { + return; + } + + memcpy(m_recvBuf.base, start, remaining); + m_recvBufPos = remaining; +} + + +void Miner::readTLS(int nread) +{ +# ifndef XMRIG_NO_TLS + if (isTLS()) { + LOG_DEBUG("[%s] TLS received (%d bytes)", m_ip, nread); + + m_tls->read(m_recvBuf.base, m_recvBufPos); + m_recvBufPos = 0; + } + else + { + read(); + } +# else + read(); +# endif +} + + +void Miner::send(const rapidjson::Document &doc) +{ + using namespace rapidjson; + + StringBuffer buffer(0, 512); + Writer writer(buffer); + doc.Accept(writer); + + const size_t size = buffer.GetSize(); + if (size > (sizeof(m_sendBuf) - 2)) { + LOG_ERR("[%s] send failed: \"send buffer overflow: %zu > %zu\"", m_ip, size, (sizeof(m_sendBuf) - 2)); + shutdown(true); + + return; + } + + memcpy(m_sendBuf, buffer.GetString(), size); + m_sendBuf[size] = '\n'; + m_sendBuf[size + 1] = '\0'; + + return send(size + 1); +} + + void Miner::send(int size) { LOG_DEBUG("[%s] send (%d bytes): \"%s\"", m_ip, size, m_sendBuf); - if (size <= 0 || (m_state != ReadyState && m_state != WaitReadyState) || uv_is_writable(reinterpret_cast(&m_socket)) == 0) { + if (size <= 0 || !isWritable()) { return; } - uv_buf_t buf = uv_buf_init(m_sendBuf, (unsigned int) size); - const int rc = uv_try_write(reinterpret_cast(&m_socket), &buf, 1); + int rc = -1; +# ifndef XMRIG_NO_TLS + if (isTLS()) { + rc = m_tls->send(m_sendBuf, size) ? 0 : -1; + } + else +# endif + { + uv_buf_t buf = uv_buf_init(m_sendBuf, (unsigned int) size); + rc = uv_try_write(reinterpret_cast(&m_socket), &buf, 1); + } if (rc < 0) { return shutdown(true); @@ -413,7 +547,7 @@ void Miner::onAllocBuffer(uv_handle_t *handle, size_t suggested_size, uv_buf_t * void Miner::onRead(uv_stream_t *stream, ssize_t nread, const uv_buf_t *buf) { - auto miner = getMiner(stream->data); + Miner *miner = getMiner(stream->data); if (!miner) { return; } @@ -425,30 +559,7 @@ void Miner::onRead(uv_stream_t *stream, ssize_t nread, const uv_buf_t *buf) miner->m_rx += nread; miner->m_recvBufPos += nread; - char* end; - char* start = miner->m_recvBuf.base; - size_t remaining = miner->m_recvBufPos; - - while ((end = static_cast(memchr(start, '\n', remaining))) != nullptr) { - end++; - size_t len = end - start; - miner->parse(start, len); - - remaining -= len; - start = end; - } - - if (remaining == 0) { - miner->m_recvBufPos = 0; - return; - } - - if (start == miner->m_recvBuf.base) { - return; - } - - memcpy(miner->m_recvBuf.base, start, remaining); - miner->m_recvBufPos = remaining; + miner->readTLS(static_cast(nread)); } diff --git a/src/proxy/Miner.h b/src/proxy/Miner.h index 8fa9caae5..cb1dd50cf 100644 --- a/src/proxy/Miner.h +++ b/src/proxy/Miner.h @@ -38,6 +38,14 @@ class Job; class RejectEvent; +namespace xmrig { + class TlsContext; +} + + +typedef struct bio_st BIO; + + class Miner { public: @@ -48,7 +56,7 @@ class Miner ClosingState }; - Miner(bool nicehash, bool ipv6); + Miner(const xmrig::TlsContext *ctx, bool ipv6, uint16_t port); ~Miner(); bool accept(uv_stream_t *server); void replyWithError(int64_t id, const char *message); @@ -60,9 +68,11 @@ class Miner inline const char *password() const { return m_password.data(); } inline const char *rigId(bool safe = false) const { return (safe ? (m_rigId.size() > 0 ? m_rigId.data() : m_user.data()) : m_rigId.data()); } inline const char *user() const { return m_user.data(); } + inline int32_t routeId() const { return m_routeId; } inline int64_t id() const { return m_id; } inline ssize_t mapperId() const { return m_mapperId; } inline State state() const { return m_state; } + inline uint16_t localPort() const { return m_localPort; } inline uint64_t customDiff() const { return m_customDiff; } inline uint64_t diff() const { return (m_customDiff ? std::min(m_customDiff, m_diff) : m_diff); } inline uint64_t expire() const { return m_expire; } @@ -74,14 +84,23 @@ class Miner inline void setCustomDiff(uint64_t diff) { m_customDiff = diff; } inline void setFixedByte(uint8_t fixedByte) { m_fixedByte = fixedByte; } inline void setMapperId(ssize_t mapperId) { m_mapperId = mapperId; } + inline void setNiceHash(bool nicehash) { m_nicehash = nicehash; } + inline void setRouteId(int32_t id) { m_routeId = id; } private: + class Tls; + constexpr static size_t kLoginTimeout = 10 * 1000; constexpr static size_t kSocketTimeout = 60 * 10 * 1000; + bool isWritable() const; bool parseRequest(int64_t id, const char *method, const rapidjson::Value ¶ms); + bool send(BIO *bio); void heartbeat(); void parse(char *line, size_t len); + void read(); + void readTLS(int nread); + void send(const rapidjson::Document &doc); void send(int size); void setState(State state); void shutdown(bool had_error); @@ -90,19 +109,23 @@ class Miner static void onRead(uv_stream_t *stream, ssize_t nread, const uv_buf_t *buf); static void onTimeout(uv_timer_t *handle); + inline bool isTLS() const { return m_tls != nullptr; } + static inline Miner *getMiner(void *data) { return m_storage.get(data); } bool m_ipv6; bool m_nicehash; - char m_buf[2048]; + char m_buf[1024]; char m_ip[46]; char m_rpcId[37]; - char m_sendBuf[768]; + int32_t m_routeId; int64_t m_id; int64_t m_loginId; size_t m_recvBufPos; ssize_t m_mapperId; State m_state; + Tls *m_tls; + uint16_t m_localPort; uint64_t m_customDiff; uint64_t m_diff; uint64_t m_expire; @@ -118,6 +141,7 @@ class Miner xmrig::c_str m_rigId; xmrig::c_str m_user; + static char m_sendBuf[2048]; static xmrig::Storage m_storage; }; diff --git a/src/proxy/Proxy.cpp b/src/proxy/Proxy.cpp index 33db10f7b..173000ba1 100644 --- a/src/proxy/Proxy.cpp +++ b/src/proxy/Proxy.cpp @@ -37,7 +37,6 @@ #include "Counters.h" #include "log/AccessLog.h" #include "log/ShareLog.h" -#include "proxy/Addr.h" #include "proxy/Events.h" #include "proxy/events/ConnectionEvent.h" #include "proxy/Login.h" @@ -52,10 +51,16 @@ #include "proxy/workers/Workers.h" +#ifndef XMRIG_NO_TLS +# include "proxy/tls/TlsContext.h" +#endif + + Proxy::Proxy(xmrig::Controller *controller) : m_customDiff(controller), m_ticks(0), - m_controller(controller) + m_controller(controller), + m_tls(nullptr) { srand(time(0) ^ (uintptr_t) this); @@ -120,16 +125,31 @@ Proxy::~Proxy() delete m_accessLog; delete m_debug; delete m_workers; + +# ifndef XMRIG_NO_TLS + delete m_tls; +# endif } void Proxy::connect() { +# ifndef XMRIG_NO_TLS + if (m_controller->config()->isTLS()) { + m_tls = new xmrig::TlsContext(); + + if (!m_tls->load(m_controller->config()->tls())) { + delete m_tls; + m_tls = nullptr; + } + } +# endif + m_splitter->connect(); - const std::vector &addrs = m_controller->config()->addrs(); - for (const Addr &addr : addrs) { - bind(addr); + const xmrig::BindHosts &bind = m_controller->config()->bind(); + for (const xmrig::BindHost &host : bind) { + this->bind(host); } uv_timer_start(&m_timer, Proxy::onTick, 1000, 1000); @@ -204,9 +224,17 @@ bool Proxy::isColors() const } -void Proxy::bind(const Addr &addr) +void Proxy::bind(const xmrig::BindHost &host) { - auto server = new Server(addr, m_controller->config()->mode() == xmrig::Config::NICEHASH_MODE); +# ifndef XMRIG_NO_TLS + if (host.isTLS() && !m_tls) { + LOG_ERR("Failed to bind \"%s:%d\" error: \"TLS not available\".", host.host(), host.port()); + + return; + } +# endif + + auto server = new Server(host, m_tls); if (server->bind()) { m_servers.push_back(server); diff --git a/src/proxy/Proxy.h b/src/proxy/Proxy.h index 69fbc66dd..f43abfbbb 100644 --- a/src/proxy/Proxy.h +++ b/src/proxy/Proxy.h @@ -21,8 +21,8 @@ * along with this program. If not, see . */ -#ifndef __PROXY_H__ -#define __PROXY_H__ +#ifndef XMRIG_PROXY_H +#define XMRIG_PROXY_H #include @@ -51,6 +51,8 @@ class Workers; namespace xmrig { class Controller; + class BindHost; + class TlsContext; } @@ -82,7 +84,7 @@ class Proxy : public xmrig::IControllerListener constexpr static int kGCInterval = 60; bool isColors() const; - void bind(const Addr &addr); + void bind(const xmrig::BindHost &host); void gc(); void print(); void tick(); @@ -103,7 +105,8 @@ class Proxy : public xmrig::IControllerListener uv_timer_t m_timer; Workers *m_workers; xmrig::Controller *m_controller; + xmrig::TlsContext *m_tls; }; -#endif /* __PROXY_H__ */ +#endif /* XMRIG_PROXY_H */ diff --git a/src/proxy/Server.cpp b/src/proxy/Server.cpp index 972cf1556..684b5e5a7 100644 --- a/src/proxy/Server.cpp +++ b/src/proxy/Server.cpp @@ -23,29 +23,29 @@ #include "common/log/Log.h" -#include "proxy/Addr.h" +#include "proxy/BindHost.h" #include "proxy/events/ConnectionEvent.h" #include "proxy/Miner.h" #include "proxy/Server.h" -Server::Server(const Addr &addr, bool nicehash) : - m_nicehash(nicehash), +Server::Server(const xmrig::BindHost &host, const xmrig::TlsContext *ctx) : + m_ctx(host.isTLS() ? ctx : nullptr), m_version(0), - m_port(addr.port()), - m_ip(addr.ip()) + m_port(host.port()), + m_host(host.host()) { uv_tcp_init(uv_default_loop(), &m_server); m_server.data = this; uv_tcp_nodelay(&m_server, 1); - if (addr.isIPv6() && uv_ip6_addr(m_ip.data(), m_port, &m_addr6) == 0) { + if (host.isIPv6() && uv_ip6_addr(m_host.data(), m_port, &m_addr6) == 0) { m_version = 6; return; } - if (uv_ip4_addr(m_ip.data(), m_port, &m_addr) == 0) { + if (uv_ip4_addr(m_host.data(), m_port, &m_addr) == 0) { m_version = 4; } } @@ -62,7 +62,7 @@ bool Server::bind() const int r = uv_listen(reinterpret_cast(&m_server), 511, Server::onConnection); if (r) { - LOG_ERR("[%s:%u] listen error: \"%s\"", m_ip.data(), m_port, uv_strerror(r)); + LOG_ERR("[%s:%u] listen error: \"%s\"", m_host.data(), m_port, uv_strerror(r)); return false; } @@ -73,11 +73,11 @@ bool Server::bind() void Server::create(uv_stream_t *server, int status) { if (status < 0) { - LOG_ERR("[%s:%u] new connection error: \"%s\"", m_ip.data(), m_port, uv_strerror(status)); + LOG_ERR("[%s:%u] new connection error: \"%s\"", m_host.data(), m_port, uv_strerror(status)); return; } - Miner *miner = new Miner(m_nicehash, m_version == 6); + Miner *miner = new Miner(m_ctx, m_version == 6, m_port); if (!miner) { return; } diff --git a/src/proxy/Server.h b/src/proxy/Server.h index 8cdec4205..60e6721e3 100644 --- a/src/proxy/Server.h +++ b/src/proxy/Server.h @@ -21,8 +21,8 @@ * along with this program. If not, see . */ -#ifndef __SERVER_H__ -#define __SERVER_H__ +#ifndef XMRIG_SERVER_H +#define XMRIG_SERVER_H #include @@ -31,13 +31,16 @@ #include "common/utils/c_str.h" -class Addr; +namespace xmrig { + class BindHost; + class TlsContext; +} class Server { public: - Server(const Addr &addr, bool nicehash); + Server(const xmrig::BindHost &host, const xmrig::TlsContext *ctx); bool bind(); private: @@ -45,13 +48,13 @@ class Server static void onConnection(uv_stream_t *server, int status); - bool m_nicehash; + const xmrig::TlsContext *m_ctx; int m_version; sockaddr_in m_addr; sockaddr_in6 m_addr6; uint16_t m_port; uv_tcp_t m_server; - xmrig::c_str m_ip; + xmrig::c_str m_host; }; -#endif /* __SERVER_H__ */ +#endif /* XMRIG_SERVER_H */ diff --git a/src/proxy/splitters/nicehash/NonceMapper.cpp b/src/proxy/splitters/nicehash/NonceMapper.cpp index afcd49673..d83b75e6e 100644 --- a/src/proxy/splitters/nicehash/NonceMapper.cpp +++ b/src/proxy/splitters/nicehash/NonceMapper.cpp @@ -79,6 +79,7 @@ bool NonceMapper::add(Miner *miner) connect(); } + miner->setNiceHash(true); miner->setMapperId(m_id); return true; } diff --git a/src/proxy/splitters/simple/SimpleMapper.cpp b/src/proxy/splitters/simple/SimpleMapper.cpp index 7c05d3656..b8f5b5a52 100644 --- a/src/proxy/splitters/simple/SimpleMapper.cpp +++ b/src/proxy/splitters/simple/SimpleMapper.cpp @@ -71,6 +71,7 @@ SimpleMapper::~SimpleMapper() void SimpleMapper::add(Miner *miner) { m_miner = miner; + m_miner->setNiceHash(false); m_miner->setMapperId(m_id); connect(); diff --git a/src/proxy/tls/Tls.cpp b/src/proxy/tls/Tls.cpp new file mode 100644 index 000000000..7aadebc1f --- /dev/null +++ b/src/proxy/tls/Tls.cpp @@ -0,0 +1,127 @@ +/* XMRig + * Copyright 2010 Jeff Garzik + * Copyright 2012-2014 pooler + * Copyright 2014 Lucas Jones + * Copyright 2014-2016 Wolf9466 + * Copyright 2016 Jay D Dee + * Copyright 2017-2018 XMR-Stak , + * Copyright 2018 Lee Clagett + * Copyright 2018 SChernykh + * Copyright 2016-2018 XMRig , + * + * 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 + * (at your option) 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 . + */ + + +#include + + +#include "proxy/tls/Tls.h" + + +Miner::Tls::Tls(SSL_CTX *ctx, Miner *miner) : + m_ready(false), + m_buf(), + m_fingerprint(), + m_miner(miner), + m_ssl(nullptr), + m_ctx(ctx) +{ + m_writeBio = BIO_new(BIO_s_mem()); + m_readBio = BIO_new(BIO_s_mem()); +} + + +Miner::Tls::~Tls() +{ + if (m_ssl) { + SSL_free(m_ssl); + } +} + + +bool Miner::Tls::accept() +{ + m_ssl = SSL_new(m_ctx); + assert(m_ssl != nullptr); + + if (!m_ssl) { + return false; + } + + SSL_set_accept_state(m_ssl); + SSL_set_bio(m_ssl, m_readBio, m_writeBio); + + return send(); +} + + +bool Miner::Tls::send(const char *data, size_t size) +{ + SSL_write(m_ssl, data, size); + + return send(); +} + + +const char *Miner::Tls::fingerprint() const +{ + return m_ready ? m_fingerprint : nullptr; +} + + +const char *Miner::Tls::version() const +{ + return m_ready ? SSL_get_version(m_ssl) : nullptr; +} + + +void Miner::Tls::read(const char *data, size_t size) +{ + BIO_write(m_readBio, data, size); + + if (!SSL_is_init_finished(m_ssl)) { + const int rc = SSL_do_handshake(m_ssl); + + if (rc < 0 && SSL_get_error(m_ssl, rc) == SSL_ERROR_WANT_READ) { + send(); + } else if (rc == 1) { + m_ready = true; + send(); + read(); + } + else { + m_miner->close(); + } + + return; + } + + read(); +} + + +bool Miner::Tls::send() +{ + return m_miner->send(m_writeBio); +} + + +void Miner::Tls::read() +{ + int bytes_read = 0; + while ((bytes_read = SSL_read(m_ssl, m_buf, sizeof(m_buf))) > 0) { + m_miner->parse(m_buf, bytes_read); + } +} diff --git a/src/proxy/tls/Tls.h b/src/proxy/tls/Tls.h new file mode 100644 index 000000000..3c6e200e6 --- /dev/null +++ b/src/proxy/tls/Tls.h @@ -0,0 +1,62 @@ +/* XMRig + * Copyright 2010 Jeff Garzik + * Copyright 2012-2014 pooler + * Copyright 2014 Lucas Jones + * Copyright 2014-2016 Wolf9466 + * Copyright 2016 Jay D Dee + * Copyright 2017-2018 XMR-Stak , + * Copyright 2016-2018 XMRig , + * + * 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 + * (at your option) 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 . + */ + +#ifndef XMRIG_MINER_TLS_H +#define XMRIG_MINER_TLS_H + + +#include + + +#include "proxy/Miner.h" + + +class Miner::Tls +{ +public: + Tls(SSL_CTX *ctx, Miner *miner); + ~Tls(); + + bool accept(); + bool send(const char *data, size_t size); + const char *fingerprint() const; + const char *version() const; + void read(const char *data, size_t size); + +private: + bool send(); + bool verify(X509 *cert); + void read(); + + BIO *m_readBio; + BIO *m_writeBio; + bool m_ready; + char m_buf[1024 * 1]; + char m_fingerprint[32 * 2 + 8]; + Miner *m_miner; + SSL *m_ssl; + SSL_CTX *m_ctx; +}; + + +#endif /* XMRIG_MINER_TLS_H */ diff --git a/src/proxy/tls/TlsConfig.cpp b/src/proxy/tls/TlsConfig.cpp new file mode 100644 index 000000000..52370c1da --- /dev/null +++ b/src/proxy/tls/TlsConfig.cpp @@ -0,0 +1,134 @@ +/* XMRig + * Copyright 2010 Jeff Garzik + * Copyright 2012-2014 pooler + * Copyright 2014 Lucas Jones + * Copyright 2014-2016 Wolf9466 + * Copyright 2016 Jay D Dee + * Copyright 2017-2018 XMR-Stak , + * Copyright 2018 Lee Clagett + * Copyright 2016-2018 XMRig , + * + * 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 + * (at your option) 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 . + */ + + +#include "proxy/tls/TlsConfig.h" +#include "rapidjson/document.h" + + +xmrig::TlsConfig::TlsConfig() : + m_protocols(0) +{ +} + + +/** + * "cert" load TLS certificate chain from file. + * "cert_key" load TLS private key from file. + * "ciphers" set list of available ciphers (TLSv1.2 and below). + * "ciphersuites" set list of available TLSv1.3 ciphersuites. + * "dhparam" load DH parameters for DHE ciphers from file. + */ +xmrig::TlsConfig::TlsConfig(const rapidjson::Value &object) : + m_protocols(0) +{ + setProtocols(object["protocols"]); + setCert(object["cert"].GetString()); + setKey(object["cert_key"].GetString()); + setCiphers(object["ciphers"].GetString()); + setCipherSuites(object["ciphersuites"].GetString()); + setDH(object["dhparam"].GetString()); +} + + +xmrig::TlsConfig::~TlsConfig() +{ +} + + +rapidjson::Value xmrig::TlsConfig::toJSON(rapidjson::Document &doc) const +{ + using namespace rapidjson; + + auto &allocator = doc.GetAllocator(); + Value obj(kObjectType); + + if (m_protocols > 0) { + std::vector protocols; + + if (m_protocols & TLSv1) { + protocols.push_back("TLSv1"); + } + + if (m_protocols & TLSv1_1) { + protocols.push_back("TLSv1.1"); + } + + if (m_protocols & TLSv1_2) { + protocols.push_back("TLSv1.2"); + } + + if (m_protocols & TLSv1_3) { + protocols.push_back("TLSv1.3"); + } + + obj.AddMember("protocols", String::join(protocols, ' ').toJSON(doc), allocator); + } + else { + obj.AddMember("protocols", kNullType, allocator); + } + + obj.AddMember("cert", m_cert.toJSON(), allocator); + obj.AddMember("cert_key", m_key.toJSON(), allocator); + obj.AddMember("ciphers", m_ciphers.toJSON(), allocator); + obj.AddMember("ciphersuites", m_cipherSuites.toJSON(), allocator); + obj.AddMember("dhparam", m_dhparam.toJSON(), allocator); + + return obj; +} + + +void xmrig::TlsConfig::setProtocols(const char *protocols) +{ + const std::vector vec = String(protocols).split(' '); + + for (const String &value : vec) { + if (value == "TLSv1") { + m_protocols |= TLSv1; + } + else if (value == "TLSv1.1") { + m_protocols |= TLSv1_1; + } + else if (value == "TLSv1.2") { + m_protocols |= TLSv1_2; + } + else if (value == "TLSv1.3") { + m_protocols |= TLSv1_3; + } + } +} + + +void xmrig::TlsConfig::setProtocols(const rapidjson::Value &protocols) +{ + m_protocols = 0; + + if (protocols.IsUint()) { + return setProtocols(protocols.GetUint()); + } + + if (protocols.IsString()) { + return setProtocols(protocols.GetString()); + } +} diff --git a/src/proxy/tls/TlsConfig.h b/src/proxy/tls/TlsConfig.h new file mode 100644 index 000000000..461abd5b3 --- /dev/null +++ b/src/proxy/tls/TlsConfig.h @@ -0,0 +1,80 @@ +/* XMRig + * Copyright 2010 Jeff Garzik + * Copyright 2012-2014 pooler + * Copyright 2014 Lucas Jones + * Copyright 2014-2016 Wolf9466 + * Copyright 2016 Jay D Dee + * Copyright 2017-2018 XMR-Stak , + * Copyright 2018 Lee Clagett + * Copyright 2016-2018 XMRig , + * + * 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 + * (at your option) 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 . + */ + +#ifndef XMRIG_TLSCONFIG_H +#define XMRIG_TLSCONFIG_H + + +#include "base/tools/String.h" +#include "rapidjson/fwd.h" + + +namespace xmrig { + + +class TlsConfig +{ +public: + enum Versions { + TLSv1 = 1, + TLSv1_1 = 2, + TLSv1_2 = 4, + TLSv1_3 = 8 + }; + + TlsConfig(); + TlsConfig(const rapidjson::Value &object); + ~TlsConfig(); + + inline bool isValid() const { return !m_cert.isEmpty() && !m_key.isEmpty(); } + inline const char *cert() const { return m_cert.data(); } + inline const char *ciphers() const { return m_ciphers.isEmpty() ? nullptr : m_ciphers.data(); } + inline const char *cipherSuites() const { return m_cipherSuites.isEmpty() ? nullptr : m_cipherSuites.data(); } + inline const char *dhparam() const { return m_dhparam.isEmpty() ? nullptr : m_dhparam.data(); } + inline const char *key() const { return m_key.data(); } + inline uint32_t protocols() const { return m_protocols; } + inline void setCert(const char *cert) { m_cert = cert; } + inline void setCiphers(const char *ciphers) { m_ciphers = ciphers; } + inline void setCipherSuites(const char *ciphers) { m_cipherSuites = ciphers; } + inline void setDH(const char *dhparam) { m_dhparam = dhparam; } + inline void setKey(const char *key) { m_key = key; } + inline void setProtocols(uint32_t protocols) { m_protocols = protocols; } + + rapidjson::Value toJSON(rapidjson::Document &doc) const; + void setProtocols(const char *protocols); + void setProtocols(const rapidjson::Value &protocols); + +private: + uint32_t m_protocols; + String m_cert; + String m_ciphers; + String m_cipherSuites; + String m_dhparam; + String m_key; +}; + + +} /* namespace xmrig */ + +#endif /* XMRIG_TLSCONFIG_H */ diff --git a/src/proxy/tls/TlsContext.cpp b/src/proxy/tls/TlsContext.cpp new file mode 100644 index 000000000..0ff3fd77f --- /dev/null +++ b/src/proxy/tls/TlsContext.cpp @@ -0,0 +1,184 @@ +/* XMRig + * Copyright 2010 Jeff Garzik + * Copyright 2012-2014 pooler + * Copyright 2014 Lucas Jones + * Copyright 2014-2016 Wolf9466 + * Copyright 2016 Jay D Dee + * Copyright 2017-2018 XMR-Stak , + * Copyright 2018 Lee Clagett + * Copyright 2016-2018 XMRig , + * + * 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 + * (at your option) 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 . + */ + + +#include +#include + + +#include "common/log/Log.h" +#include "proxy/tls/TlsConfig.h" +#include "proxy/tls/TlsContext.h" + + +xmrig::TlsContext::TlsContext() : + m_ctx(nullptr) +{ + m_ctx = SSL_CTX_new(SSLv23_server_method()); +} + + +xmrig::TlsContext::~TlsContext() +{ + SSL_CTX_free(m_ctx); +} + + +bool xmrig::TlsContext::load(const TlsConfig &config) +{ + if (m_ctx == nullptr) { + LOG_ERR("Unable to create SSL context"); + + return false; + } + + if (!config.isValid()) { + LOG_ERR("No valid TLS configuration provided"); + + return false; + } + + if (SSL_CTX_use_certificate_chain_file(m_ctx, config.cert()) <= 0) { + LOG_ERR("SSL_CTX_use_certificate_chain_file(\"%s\") failed.", config.cert()); + + return false; + } + + if (SSL_CTX_use_PrivateKey_file(m_ctx, config.key(), SSL_FILETYPE_PEM) <= 0) { + LOG_ERR("SSL_CTX_use_PrivateKey_file(\"%s\") failed.", config.key()); + + return false; + } + + SSL_CTX_set_options(m_ctx, SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3); + SSL_CTX_set_options(m_ctx, SSL_OP_CIPHER_SERVER_PREFERENCE); + +# if OPENSSL_VERSION_NUMBER >= 0x1010100fL + SSL_CTX_set_max_early_data(m_ctx, 0); +# endif + + setProtocols(config.protocols()); + + return setCiphers(config.ciphers()) && setCipherSuites(config.cipherSuites()) && setDH(config.dhparam()); +} + + +bool xmrig::TlsContext::setCiphers(const char *ciphers) +{ + if (ciphers == nullptr || SSL_CTX_set_cipher_list(m_ctx, ciphers) == 1) { + return true; + } + + LOG_ERR("SSL_CTX_set_cipher_list(\"%s\") failed.", ciphers); + + return true; +} + + +bool xmrig::TlsContext::setCipherSuites(const char *ciphersuites) +{ + if (ciphersuites == nullptr) { + return true; + } + +# if OPENSSL_VERSION_NUMBER >= 0x1010100fL + if (SSL_CTX_set_ciphersuites(m_ctx, ciphersuites) == 1) { + return true; + } +# endif + + LOG_ERR("SSL_CTX_set_ciphersuites(\"%s\") failed.", ciphersuites); + + return false; +} + + +bool xmrig::TlsContext::setDH(const char *dhparam) +{ + if (dhparam == nullptr) { + return true; + } + + BIO *bio = BIO_new_file(dhparam, "r"); + if (bio == nullptr) { + LOG_ERR("BIO_new_file(\"%s\") failed.", dhparam); + + return false; + } + + DH *dh = PEM_read_bio_DHparams(bio, nullptr, nullptr, nullptr); + if (dh == nullptr) { + LOG_ERR("PEM_read_bio_DHparams(\"%s\") failed.", dhparam); + + BIO_free(bio); + + return false; + } + + const int rc = SSL_CTX_set_tmp_dh(m_ctx, dh); + + DH_free(dh); + BIO_free(bio); + + if (rc == 0) { + LOG_ERR("SSL_CTX_set_tmp_dh(\"%s\") failed.", dhparam); + + return false; + } + + return true; +} + + +void xmrig::TlsContext::setProtocols(uint32_t protocols) +{ + if (protocols == 0) { + return; + } + + if (!(protocols & TlsConfig::TLSv1)) { + SSL_CTX_set_options(m_ctx, SSL_OP_NO_TLSv1); + } + +# ifdef SSL_OP_NO_TLSv1_1 + SSL_CTX_clear_options(m_ctx, SSL_OP_NO_TLSv1_1); + if (!(protocols & TlsConfig::TLSv1_1)) { + SSL_CTX_set_options(m_ctx, SSL_OP_NO_TLSv1_1); + } +# endif + +# ifdef SSL_OP_NO_TLSv1_2 + SSL_CTX_clear_options(m_ctx, SSL_OP_NO_TLSv1_2); + if (!(protocols & TlsConfig::TLSv1_2)) { + SSL_CTX_set_options(m_ctx, SSL_OP_NO_TLSv1_2); + } +# endif + +# ifdef SSL_OP_NO_TLSv1_3 + SSL_CTX_clear_options(m_ctx, SSL_OP_NO_TLSv1_3); + if (!(protocols & TlsConfig::TLSv1_3)) { + SSL_CTX_set_options(m_ctx, SSL_OP_NO_TLSv1_3); + } +# endif +} diff --git a/src/proxy/tls/TlsContext.h b/src/proxy/tls/TlsContext.h new file mode 100644 index 000000000..638a500a2 --- /dev/null +++ b/src/proxy/tls/TlsContext.h @@ -0,0 +1,63 @@ +/* XMRig + * Copyright 2010 Jeff Garzik + * Copyright 2012-2014 pooler + * Copyright 2014 Lucas Jones + * Copyright 2014-2016 Wolf9466 + * Copyright 2016 Jay D Dee + * Copyright 2017-2018 XMR-Stak , + * Copyright 2018 Lee Clagett + * Copyright 2016-2018 XMRig , + * + * 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 + * (at your option) 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 . + */ + +#ifndef XMRIG_TLSCONTEXT_H +#define XMRIG_TLSCONTEXT_H + + +#include + + +typedef struct ssl_ctx_st SSL_CTX; + + +namespace xmrig { + + +class TlsConfig; + + +class TlsContext +{ +public: + TlsContext(); + ~TlsContext(); + + bool load(const TlsConfig &config); + + inline SSL_CTX *ctx() const { return m_ctx; } + +private: + bool setCiphers(const char *ciphers); + bool setCipherSuites(const char *ciphersuites); + bool setDH(const char *dhparam); + void setProtocols(uint32_t protocols); + + SSL_CTX *m_ctx; +}; + + +} /* namespace xmrig */ + +#endif /* XMRIG_TLSCONTEXT_H */ diff --git a/src/version.h b/src/version.h index 8fd241aa8..d34f500c0 100644 --- a/src/version.h +++ b/src/version.h @@ -5,7 +5,7 @@ * Copyright 2014-2016 Wolf9466 * Copyright 2016 Jay D Dee * Copyright 2017-2018 XMR-Stak , - * Copyright 2016-2018 XMRig , + * Copyright 2016-2019 XMRig , * * 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 @@ -27,15 +27,15 @@ #define APP_ID "xmrig-proxy" #define APP_NAME "xmrig-proxy" #define APP_DESC "XMRig Stratum proxy" -#define APP_VERSION "2.8.1" +#define APP_VERSION "2.9.0-dev" #define APP_DOMAIN "xmrig.com" #define APP_SITE "www.xmrig.com" -#define APP_COPYRIGHT "Copyright (C) 2016-2018 xmrig.com" +#define APP_COPYRIGHT "Copyright (C) 2016-2019 xmrig.com" #define APP_KIND "proxy" #define APP_VER_MAJOR 2 -#define APP_VER_MINOR 8 -#define APP_VER_PATCH 1 +#define APP_VER_MINOR 9 +#define APP_VER_PATCH 0 #ifdef _MSC_VER # if (_MSC_VER >= 1910)