From aad19f1a35d6e05461539c866a81ee2677c7e3f8 Mon Sep 17 00:00:00 2001 From: XMRig Date: Sat, 31 Mar 2018 13:48:06 +0700 Subject: [PATCH] Added initial next gen config support from proxy. --- CMakeLists.txt | 12 + src/core/CommonConfig.cpp | 380 ++++++++++++++++++++++++++++++ src/core/CommonConfig.h | 106 +++++++++ src/core/Config.cpp | 329 ++++++++++++++++++++++++++ src/core/Config.h | 122 ++++++++++ src/core/ConfigCreator.h | 50 ++++ src/core/ConfigLoader.cpp | 311 ++++++++++++++++++++++++ src/core/ConfigLoader.h | 71 ++++++ src/core/ConfigLoader_platform.h | 171 ++++++++++++++ src/core/ConfigWatcher.cpp | 107 +++++++++ src/core/ConfigWatcher.h | 69 ++++++ src/core/Controller.cpp | 2 +- src/core/Controller.h | 2 +- src/donate.h | 3 +- src/interfaces/IConfig.h | 109 +++++++++ src/interfaces/IConfigCreator.h | 45 ++++ src/interfaces/IWatcherListener.h | 4 +- src/net/Url.cpp | 8 +- src/net/Url.h | 10 +- src/xmrig.h | 5 +- 20 files changed, 1901 insertions(+), 15 deletions(-) create mode 100644 src/core/CommonConfig.cpp create mode 100644 src/core/CommonConfig.h create mode 100644 src/core/Config.cpp create mode 100644 src/core/Config.h create mode 100644 src/core/ConfigCreator.h create mode 100644 src/core/ConfigLoader.cpp create mode 100644 src/core/ConfigLoader.h create mode 100644 src/core/ConfigLoader_platform.h create mode 100644 src/core/ConfigWatcher.cpp create mode 100644 src/core/ConfigWatcher.h create mode 100644 src/interfaces/IConfig.h create mode 100644 src/interfaces/IConfigCreator.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 1be15601f..a4347d69d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -15,9 +15,17 @@ set(HEADERS src/api/NetworkState.h src/App.h src/Console.h + src/core/CommonConfig.h + src/core/Config.cpp + src/core/ConfigLoader.cpp + src/core/ConfigLoader.h + src/core/ConfigLoader_platform.h + src/core/ConfigWatcher.cpp src/core/Controller.h src/Cpu.h src/interfaces/IClientListener.h + src/interfaces/IConfig.h + src/interfaces/IConfigCreator.h src/interfaces/IConsoleListener.h src/interfaces/IControllerListener.h src/interfaces/IJobResultListener.h @@ -79,6 +87,10 @@ set(SOURCES src/api/NetworkState.cpp src/App.cpp src/Console.cpp + src/core/CommonConfig.cpp + src/core/Config.cpp + src/core/ConfigLoader.cpp + src/core/ConfigWatcher.cpp src/core/Controller.cpp src/log/ConsoleLog.cpp src/log/FileLog.cpp diff --git a/src/core/CommonConfig.cpp b/src/core/CommonConfig.cpp new file mode 100644 index 000000000..38233b124 --- /dev/null +++ b/src/core/CommonConfig.cpp @@ -0,0 +1,380 @@ +/* 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 + + +#include "core/CommonConfig.h" +#include "donate.h" +#include "log/Log.h" +#include "net/Url.h" +#include "rapidjson/document.h" +#include "rapidjson/filewritestream.h" +#include "rapidjson/prettywriter.h" +#include "xmrig.h" + + +static const char *algoNames[] = { + "cryptonight", + "cryptonight-lite", + "cryptonight-heavy" +}; + + +#if defined(_WIN32) && !defined(strcasecmp) +# define strcasecmp _stricmp +#endif + + +xmrig::CommonConfig::CommonConfig() : + m_adjusted(false), + m_apiIPv6(true), + m_apiRestricted(true), + m_background(false), + m_colors(true), + m_apiToken(nullptr), + m_apiWorkerId(nullptr), + m_fileName(nullptr), + m_logFile(nullptr), + m_userAgent(nullptr), + m_algorithm(ALGO_CRYPTONIGHT), + m_apiPort(0), + m_donateLevel(kDefaultDonateLevel), + m_printTime(60), + m_retries(5), + m_retryPause(5) +{ + m_pools.push_back(new Url()); + +# ifdef XMRIG_PROXY_PROJECT + m_retries = 2; + m_retryPause = 1; +# endif +} + + +xmrig::CommonConfig::~CommonConfig() +{ + for (Url *url : m_pools) { + delete url; + } + + m_pools.clear(); + + free(m_fileName); + free(m_apiToken); + free(m_apiWorkerId); + free(m_logFile); + free(m_userAgent); +} + + +const char *xmrig::CommonConfig::algoName() const +{ + return algoNames[m_algorithm]; +} + + +bool xmrig::CommonConfig::adjust() +{ + if (m_adjusted) { + return false; + } + + m_adjusted = true; + + for (Url *url : m_pools) { + url->adjust(algorithm()); + } + + return true; +} + + +bool xmrig::CommonConfig::isValid() const +{ + return m_pools[0]->isValid(); +} + + +bool xmrig::CommonConfig::parseBoolean(int key, bool enable) +{ + switch (key) { + case BackgroundKey: /* --background */ + m_background = enable; + break; + + case SyslogKey: /* --syslog */ + m_syslog = enable; + break; + + case KeepAliveKey: /* --keepalive */ + m_pools.back()->setKeepAlive(enable ? Url::kKeepAliveTimeout : 0); + break; + +# ifndef XMRIG_PROXY_PROJECT + case NicehashKey: /* --nicehash */ + m_pools.back()->setNicehash(enable); + break; +# endif + + case ColorKey: /* --no-color */ + m_colors = enable; + break; + + case WatchKey: /* watch */ + m_watch = enable; + break; + + case ApiIPv6Key: /* ipv6 */ + m_apiIPv6 = enable; + + case ApiRestrictedKey: /* restricted */ + m_apiRestricted = enable; + + default: + break; + } + + return true; +} + + +bool xmrig::CommonConfig::parseString(int key, const char *arg) +{ + switch (key) { + case AlgorithmKey: /* --algo */ + setAlgo(arg); + break; + + case UserpassKey: /* --userpass */ + if (!m_pools.back()->setUserpass(arg)) { + return false; + } + + break; + + case UrlKey: /* --url */ + if (m_pools.size() > 1 || m_pools[0]->isValid()) { + Url *url = new Url(arg); + if (url->isValid()) { + m_pools.push_back(url); + } + else { + delete url; + } + } + else { + m_pools[0]->parse(arg); + } + + if (!m_pools.back()->isValid()) { + return false; + } + + break; + + case UserKey: /* --user */ + m_pools.back()->setUser(arg); + break; + + case PasswordKey: /* --pass */ + m_pools.back()->setPassword(arg); + break; + + case LogFileKey: /* --log-file */ + free(m_logFile); + m_logFile = strdup(arg); + break; + + case ApiAccessTokenKey: /* --api-access-token */ + free(m_apiToken); + m_apiToken = strdup(arg); + break; + + case ApiWorkerIdKey: /* --api-worker-id */ + free(m_apiWorkerId); + m_apiWorkerId = strdup(arg); + break; + + case UserAgentKey: /* --user-agent */ + free(m_userAgent); + m_userAgent = strdup(arg); + break; + + case RetriesKey: /* --retries */ + case RetryPauseKey: /* --retry-pause */ + case VariantKey: /* --variant */ + case ApiPort: /* --api-port */ + case PrintTimeKey: /* --cpu-priority */ + return parseUint64(key, strtol(arg, nullptr, 10)); + + case BackgroundKey: /* --background */ + case SyslogKey: /* --syslog */ + case KeepAliveKey: /* --keepalive */ + case NicehashKey: /* --nicehash */ + return parseBoolean(key, true); + + case ColorKey: /* --no-color */ + case WatchKey: /* --no-watch */ + case ApiRestrictedKey: /* --api-no-restricted */ + case ApiIPv6Key: /* --api-no-ipv6 */ + return parseBoolean(key, false); + +# ifdef XMRIG_PROXY_PROJECT + case 1003: /* --donate-level */ + if (strncmp(arg, "minemonero.pro", 14) == 0) { + m_donateLevel = 0; + } + else { + parseUint64(key, strtol(arg, nullptr, 10)); + } + break; +# endif + + default: + break; + } + + return true; +} + + +bool xmrig::CommonConfig::parseUint64(int key, uint64_t arg) +{ + return parseInt(key, static_cast(arg)); +} + + +bool xmrig::CommonConfig::save() +{ + if (!m_fileName) { + return false; + } + + uv_fs_t req; + const int fd = uv_fs_open(uv_default_loop(), &req, m_fileName, O_WRONLY | O_CREAT | O_TRUNC, 0644, nullptr); + if (fd < 0) { + return false; + } + + uv_fs_req_cleanup(&req); + + rapidjson::Document doc; + getJSON(doc); + + FILE *fp = fdopen(fd, "w"); + + char buf[4096]; + rapidjson::FileWriteStream os(fp, buf, sizeof(buf)); + rapidjson::PrettyWriter writer(os); + doc.Accept(writer); + + fclose(fp); + + uv_fs_close(uv_default_loop(), &req, fd, nullptr); + uv_fs_req_cleanup(&req); + + LOG_NOTICE("configuration saved to: \"%s\"", m_fileName); + return true; +} + + +void xmrig::CommonConfig::setFileName(const char *fileName) +{ + free(m_fileName); + m_fileName = fileName ? strdup(fileName) : nullptr; +} + + +bool xmrig::CommonConfig::parseInt(int key, int arg) +{ + switch (key) { + case RetriesKey: /* --retries */ + if (arg > 0 && arg <= 1000) { + m_retries = arg; + } + break; + + case RetryPauseKey: /* --retry-pause */ + if (arg > 0 && arg <= 3600) { + m_retryPause = arg; + } + break; + + case KeepAliveKey: /* --keepalive */ + m_pools.back()->setKeepAlive(arg); + break; + + case VariantKey: /* --variant */ + m_pools.back()->setVariant(arg); + break; + + case DonateLevelKey: /* --donate-level */ + if (arg >= kMinDonateLevel && arg <= 99) { + m_donateLevel = arg; + } + break; + + case ApiPort: /* --api-port */ + if (arg > 0 && arg <= 65536) { + m_apiPort = arg; + } + break; + + case PrintTimeKey: /* --print-time */ + if (arg >= 0 && arg <= 3600) { + m_printTime = arg; + } + break; + + default: + break; + } + + return true; +} + + +void xmrig::CommonConfig::setAlgo(const char *algo) +{ + if (strcasecmp(algo, "cryptonight-light") == 0) { + fprintf(stderr, "Algorithm \"cryptonight-light\" is deprecated, use \"cryptonight-lite\" instead\n"); + + m_algorithm = ALGO_CRYPTONIGHT_LITE; + return; + } + + const size_t size = sizeof(algoNames) / sizeof((algoNames)[0]); + + for (size_t i = 0; i < size; i++) { + if (algoNames[i] && strcasecmp(algo, algoNames[i]) == 0) { + m_algorithm = (int) i; + break; + } + } +} diff --git a/src/core/CommonConfig.h b/src/core/CommonConfig.h new file mode 100644 index 000000000..ab840a48b --- /dev/null +++ b/src/core/CommonConfig.h @@ -0,0 +1,106 @@ +/* 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 __COMMONCONFIG_H__ +#define __COMMONCONFIG_H__ + + +#include + + +#include "interfaces/IConfig.h" + + +class Url; + + +namespace xmrig { + + +class CommonConfig : public IConfig +{ +public: + CommonConfig(); + ~CommonConfig(); + + const char *algoName() const; + + inline bool isApiIPv6() const { return m_apiIPv6; } + inline bool isApiRestricted() const { return m_apiRestricted; } + inline bool isBackground() const { return m_background; } + inline bool isColors() const { return m_colors; } + inline bool isSyslog() const { return m_syslog; } + inline const char *apiToken() const { return m_apiToken; } + inline const char *apiWorkerId() const { return m_apiWorkerId; } + inline const char *logFile() const { return m_logFile; } + inline const char *userAgent() const { return m_userAgent; } + inline const std::vector &pools() const { return m_pools; } + inline int algorithm() const { return m_algorithm; } + inline int apiPort() const { return m_apiPort; } + inline int donateLevel() const { return m_donateLevel; } + inline int printTime() const { return m_printTime; } + inline int retries() const { return m_retries; } + inline int retryPause() const { return m_retryPause; } + inline void setColors(bool colors) { m_colors = colors; } + + inline bool isWatch() const override { return m_watch && m_fileName; } + inline const char *fileName() const override { return m_fileName; } + +protected: + bool adjust() override; + bool isValid() const override; + bool parseBoolean(int key, bool enable) override; + bool parseString(int key, const char *arg) override; + bool parseUint64(int key, uint64_t arg) override; + bool save() override; + void setFileName(const char *fileName) override; + + bool m_adjusted; + bool m_apiIPv6; + bool m_apiRestricted; + bool m_background; + bool m_colors; + bool m_syslog; + bool m_watch; + char *m_apiToken; + char *m_apiWorkerId; + char *m_fileName; + char *m_logFile; + char *m_userAgent; + int m_algorithm; + int m_apiPort; + int m_donateLevel; + int m_printTime; + int m_retries; + int m_retryPause; + std::vector m_pools; + +private: + bool parseInt(int key, int arg); + void setAlgo(const char *algo); +}; + + +} /* namespace xmrig */ + +#endif /* __COMMONCONFIG_H__ */ diff --git a/src/core/Config.cpp b/src/core/Config.cpp new file mode 100644 index 000000000..9bf44bc8e --- /dev/null +++ b/src/core/Config.cpp @@ -0,0 +1,329 @@ +/* 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 "core/Config.h" +#include "core/ConfigCreator.h" +#include "core/ConfigLoader.h" +#include "Cpu.h" +#include "rapidjson/document.h" +#include "rapidjson/filewritestream.h" +#include "rapidjson/prettywriter.h" +#include "xmrig.h" + + +xmrig::Config::Config() : xmrig::CommonConfig(), + m_doubleHash(false), + m_dryRun(false), + m_hugePages(true), + m_safe(false), + m_algo(0), + m_algoVariant(0), + m_maxCpuUsage(75), + m_printTime(60), + m_priority(-1), + m_threads(0), + m_affinity(-1L) +{ + +} + + +xmrig::Config::~Config() +{ +} + + +bool xmrig::Config::reload(const char *json) +{ + return xmrig::ConfigLoader::reload(this, json); +} + + +void xmrig::Config::getJSON(rapidjson::Document &doc) const +{ + doc.SetObject(); + +// auto &allocator = doc.GetAllocator(); + +// doc.AddMember("access-log-file", accessLog() ? rapidjson::Value(rapidjson::StringRef(accessLog())).Move() : rapidjson::Value(rapidjson::kNullType).Move(), allocator); +// doc.AddMember("algo", rapidjson::StringRef(algoName()), allocator); + +// rapidjson::Value api(rapidjson::kObjectType); +// api.AddMember("port", apiPort(), allocator); +// api.AddMember("access-token", apiToken() ? rapidjson::Value(rapidjson::StringRef(apiToken())).Move() : rapidjson::Value(rapidjson::kNullType).Move(), allocator); +// api.AddMember("worker-id", apiWorkerId() ? rapidjson::Value(rapidjson::StringRef(apiWorkerId())).Move() : rapidjson::Value(rapidjson::kNullType).Move(), allocator); +// api.AddMember("ipv6", isApiIPv6(), allocator); +// api.AddMember("restricted", isApiRestricted(), allocator); +// doc.AddMember("api", api, allocator); + +// doc.AddMember("background", isBackground(), allocator); + +// rapidjson::Value bind(rapidjson::kArrayType); +// for (const Addr *addr : m_addrs) { +// bind.PushBack(rapidjson::StringRef(addr->addr()), allocator); +// } + +// doc.AddMember("bind", bind, allocator); +// doc.AddMember("colors", isColors(), allocator); +// doc.AddMember("custom-diff", diff(), allocator); +// doc.AddMember("donate-level", donateLevel(), allocator); +// doc.AddMember("log-file", logFile() ? rapidjson::Value(rapidjson::StringRef(logFile())).Move() : rapidjson::Value(rapidjson::kNullType).Move(), allocator); +// doc.AddMember("mode", rapidjson::StringRef(modeName()), allocator); + +// rapidjson::Value pools(rapidjson::kArrayType); + +// for (const Url *url : m_pools) { +// rapidjson::Value obj(rapidjson::kObjectType); + +// obj.AddMember("url", rapidjson::StringRef(url->url()), allocator); +// obj.AddMember("user", rapidjson::StringRef(url->user()), allocator); +// obj.AddMember("pass", rapidjson::StringRef(url->password()), allocator); +// obj.AddMember("coin", rapidjson::StringRef(url->coin()), allocator); + +// if (url->keepAlive() == 0 || url->keepAlive() == Url::kKeepAliveTimeout) { +// obj.AddMember("keepalive", url->keepAlive() > 0, allocator); +// } +// else { +// obj.AddMember("keepalive", url->keepAlive(), allocator); +// } + +// obj.AddMember("variant", url->variant(), allocator); + +// pools.PushBack(obj, allocator); +// } + +// doc.AddMember("pools", pools, allocator); + +// doc.AddMember("retries", retries(), allocator); +// doc.AddMember("retry-pause", retryPause(), allocator); +// doc.AddMember("reuse-timeout", reuseTimeout(), allocator); +// doc.AddMember("user-agent", userAgent() ? rapidjson::Value(rapidjson::StringRef(userAgent())).Move() : rapidjson::Value(rapidjson::kNullType).Move(), allocator); + +//# ifdef HAVE_SYSLOG_H +// doc.AddMember("syslog", syslog(), allocator); +//# endif + +// doc.AddMember("verbose", isVerbose(), allocator); +// doc.AddMember("watch", m_watch, allocator); +// doc.AddMember("workers", isWorkers(), allocator); +} + + +xmrig::Config *xmrig::Config::load(int argc, char **argv, IWatcherListener *listener) +{ + return static_cast(ConfigLoader::load(argc, argv, new ConfigCreator(), listener)); +} + + +bool xmrig::Config::adjust() +{ + if (!CommonConfig::adjust()) { + return false; + } + + m_algoVariant = getAlgoVariant(); + if (m_algoVariant == AV2_AESNI_DOUBLE || m_algoVariant == AV4_SOFT_AES_DOUBLE) { + m_doubleHash = true; + } + + if (!m_threads) { + m_threads = Cpu::optimalThreadsCount(m_algo, m_doubleHash, m_maxCpuUsage); + } + else if (m_safe) { + const int count = Cpu::optimalThreadsCount(m_algo, m_doubleHash, m_maxCpuUsage); + if (m_threads > count) { + m_threads = count; + } + } + + return true; +} + + +bool xmrig::Config::parseBoolean(int key, bool enable) +{ + if (!CommonConfig::parseBoolean(key, enable)) { + return false; + } + + switch (key) { + case xmrig::IConfig::SafeKey: /* --safe */ + m_safe = enable; + break; + + case xmrig::IConfig::HugePagesKey: /* --no-huge-pages */ + m_hugePages = enable; + break; + + case xmrig::IConfig::DryRunKey: /* --dry-run */ + m_dryRun = enable; + break; + + default: + break; + } + + return true; +} + + +bool xmrig::Config::parseString(int key, const char *arg) +{ + if (!CommonConfig::parseString(key, arg)) { + return false; + } + + switch (key) { + case xmrig::IConfig::AVKey: /* --av */ + case xmrig::IConfig::MaxCPUUsageKey: /* --max-cpu-usage */ + case xmrig::IConfig::CPUPriorityKey: /* --cpu-priority */ + return parseUint64(key, strtol(arg, nullptr, 10)); + + case xmrig::IConfig::SafeKey: /* --safe */ + case xmrig::IConfig::DryRunKey: /* --dry-run */ + return parseBoolean(key, true); + + case xmrig::IConfig::HugePagesKey: /* --no-huge-pages */ + return parseBoolean(key, false); + + case xmrig::IConfig::ThreadsKey: /* --threads */ + if (strncmp(arg, "all", 3) == 0) { + m_threads = Cpu::threads(); + return true; + } + + return parseUint64(key, strtol(arg, nullptr, 10)); + + case xmrig::IConfig::CPUAffinityKey: /* --cpu-affinity */ + { + const char *p = strstr(arg, "0x"); + return parseUint64(key, p ? strtoull(p, nullptr, 16) : strtoull(arg, nullptr, 10)); + } + + default: + break; + } + + return true; +} + + +bool xmrig::Config::parseUint64(int key, uint64_t arg) +{ + if (!CommonConfig::parseUint64(key, arg)) { + return false; + } + + switch (key) { + case xmrig::IConfig::CPUAffinityKey: /* --cpu-affinity */ + if (arg) { + m_affinity = arg; + } + break; + + default: + return parseInt(key, static_cast(arg)); + } + + return true; +} + + +void xmrig::Config::parseJSON(const rapidjson::Document &doc) +{ +} + + +bool xmrig::Config::parseInt(int key, int arg) +{ + switch (key) { + case xmrig::IConfig::ThreadsKey: /* --threads */ + if (m_threads >= 0 && arg < 1024) { + m_threads = arg; + } + break; + + case xmrig::IConfig::AVKey: /* --av */ + if (arg >= AV0_AUTO && arg < AV_MAX) { + m_algoVariant = arg; + } + break; + + case xmrig::IConfig::MaxCPUUsageKey: /* --max-cpu-usage */ + if (m_maxCpuUsage > 0 && arg <= 100) { + m_maxCpuUsage = arg; + } + break; + + case xmrig::IConfig::CPUPriorityKey: /* --cpu-priority */ + if (arg >= 0 && arg <= 5) { + m_priority = arg; + } + break; + + default: + break; + } + + return true; +} + + +int xmrig::Config::getAlgoVariant() const +{ +# ifndef XMRIG_NO_AEON + if (m_algo == xmrig::ALGO_CRYPTONIGHT_LITE) { + return getAlgoVariantLite(); + } +# endif + + if (m_algoVariant <= AV0_AUTO || m_algoVariant >= AV_MAX) { + return Cpu::hasAES() ? AV1_AESNI : AV3_SOFT_AES; + } + + if (m_safe && !Cpu::hasAES() && m_algoVariant <= AV2_AESNI_DOUBLE) { + return m_algoVariant + 2; + } + + return m_algoVariant; +} + + +#ifndef XMRIG_NO_AEON +int xmrig::Config::getAlgoVariantLite() const +{ + if (m_algoVariant <= AV0_AUTO || m_algoVariant >= AV_MAX) { + return Cpu::hasAES() ? AV2_AESNI_DOUBLE : AV4_SOFT_AES_DOUBLE; + } + + if (m_safe && !Cpu::hasAES() && m_algoVariant <= AV2_AESNI_DOUBLE) { + return m_algoVariant + 2; + } + + return m_algoVariant; +} +#endif diff --git a/src/core/Config.h b/src/core/Config.h new file mode 100644 index 000000000..a10cd6965 --- /dev/null +++ b/src/core/Config.h @@ -0,0 +1,122 @@ +/* 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 __CONFIG_H__ +#define __CONFIG_H__ + + +#include +#include + + +#include "rapidjson/fwd.h" +#include "core/CommonConfig.h" + + +class Addr; +class Url; + + +namespace xmrig { + + +class ConfigLoader; +class IWatcherListener; + + +/** + * @brief The Config class + * + * Options with dynamic reload: + * colors + * debug + * verbose + * custom-diff (only for new connections) + * api/worker-id + * pools/ + */ +class Config : public CommonConfig +{ + friend class ConfigLoader; + +public: + enum AlgoVariant { + AV0_AUTO, + AV1_AESNI, + AV2_AESNI_DOUBLE, + AV3_SOFT_AES, + AV4_SOFT_AES_DOUBLE, + AV_MAX + }; + + Config(); + ~Config(); + + bool reload(const char *json); + + void getJSON(rapidjson::Document &doc) const override; + + inline bool isDoubleHash() const { return m_doubleHash; } + inline bool isDryRun() const { return m_dryRun; } + inline bool isHugePages() const { return m_hugePages; } + inline int algo() const { return m_algo; } + inline int algoVariant() const { return m_algoVariant; } + inline int printTime() const { return m_printTime; } + inline int priority() const { return m_priority; } + inline int threads() const { return m_threads; } + inline int64_t affinity() const { return m_affinity; } + + static Config *load(int argc, char **argv, IWatcherListener *listener); + +protected: + bool adjust() override; + bool parseBoolean(int key, bool enable) override; + bool parseString(int key, const char *arg) override; + bool parseUint64(int key, uint64_t arg) override; + void parseJSON(const rapidjson::Document &doc) override; + +private: + bool parseInt(int key, int arg); + + int getAlgoVariant() const; +# ifndef XMRIG_NO_AEON + int getAlgoVariantLite() const; +# endif + + bool m_doubleHash; + bool m_dryRun; + bool m_hugePages; + bool m_safe; + int m_algo; + int m_algoVariant; + int m_maxCpuUsage; + int m_printTime; + int m_priority; + int m_threads; + int64_t m_affinity; +}; + + +} /* namespace xmrig */ + +#endif /* __CONFIG_H__ */ diff --git a/src/core/ConfigCreator.h b/src/core/ConfigCreator.h new file mode 100644 index 000000000..fcc6c5960 --- /dev/null +++ b/src/core/ConfigCreator.h @@ -0,0 +1,50 @@ +/* XMRig + * Copyright 2010 Jeff Garzik + * Copyright 2012-2014 pooler + * Copyright 2014 Lucas Jones + * Copyright 2014-2016 Wolf9466 + * Copyright 2016 Jay D Dee + * 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 __CONFIGCREATOR_H__ +#define __CONFIGCREATOR_H__ + + +#include "core/Config.h" +#include "interfaces/IConfigCreator.h" + + +namespace xmrig { + + +class IConfig; + + +class ConfigCreator : public IConfigCreator +{ +public: + inline IConfig *create() const override + { + return new Config(); + } +}; + + +} /* namespace xmrig */ + + +#endif // __CONFIGCREATOR_H__ diff --git a/src/core/ConfigLoader.cpp b/src/core/ConfigLoader.cpp new file mode 100644 index 000000000..1dec4ecab --- /dev/null +++ b/src/core/ConfigLoader.cpp @@ -0,0 +1,311 @@ +/* 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 + + +#ifndef XMRIG_NO_HTTPD +# include +#endif + + +#include "core/ConfigCreator.h" +#include "core/ConfigLoader.h" +#include "core/ConfigLoader_platform.h" +#include "core/ConfigWatcher.h" +#include "interfaces/IConfig.h" +#include "interfaces/IWatcherListener.h" +#include "net/Url.h" +#include "Platform.h" +#include "rapidjson/document.h" +#include "rapidjson/error/en.h" +#include "rapidjson/filereadstream.h" + + +xmrig::ConfigWatcher *xmrig::ConfigLoader::m_watcher = nullptr; +xmrig::IConfigCreator *xmrig::ConfigLoader::m_creator = nullptr; +xmrig::IWatcherListener *xmrig::ConfigLoader::m_listener = nullptr; + + +#ifndef ARRAY_SIZE +# define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0])) +#endif + + +bool xmrig::ConfigLoader::loadFromFile(xmrig::IConfig *config, const char *fileName) +{ + rapidjson::Document doc; + if (!getJSON(fileName, doc)) { + return false; + } + + config->setFileName(fileName); + + return loadFromJSON(config, doc); +} + + +bool xmrig::ConfigLoader::loadFromJSON(xmrig::IConfig *config, const char *json) +{ + rapidjson::Document doc; + doc.Parse(json); + + if (doc.HasParseError() || !doc.IsObject()) { + return false; + } + + return loadFromJSON(config, doc); +} + + +bool xmrig::ConfigLoader::loadFromJSON(xmrig::IConfig *config, const rapidjson::Document &doc) +{ + for (size_t i = 0; i < ARRAY_SIZE(config_options); i++) { + parseJSON(config, &config_options[i], doc); + } + + const rapidjson::Value &pools = doc["pools"]; + if (pools.IsArray()) { + for (const rapidjson::Value &value : pools.GetArray()) { + if (!value.IsObject()) { + continue; + } + + for (size_t i = 0; i < ARRAY_SIZE(pool_options); i++) { + parseJSON(config, &pool_options[i], value); + } + } + } + + const rapidjson::Value &api = doc["api"]; + if (api.IsObject()) { + for (size_t i = 0; i < ARRAY_SIZE(api_options); i++) { + parseJSON(config, &api_options[i], api); + } + } + + config->parseJSON(doc); + config->adjust(); + + return config->isValid(); +} + + +bool xmrig::ConfigLoader::reload(xmrig::IConfig *oldConfig, const char *json) +{ + xmrig::IConfig *config = m_creator->create(); + if (!loadFromJSON(config, json)) { + delete config; + + return false; + } + + config->setFileName(oldConfig->fileName()); + const bool saved = config->save(); + + if (config->isWatch() && m_watcher && saved) { + delete config; + + return true; + } + + m_listener->onNewConfig(config); + return true; +} + + +xmrig::IConfig *xmrig::ConfigLoader::load(int argc, char **argv, IConfigCreator *creator, IWatcherListener *listener) +{ + m_creator = creator; + m_listener = listener; + + xmrig::IConfig *config = m_creator->create(); + int key; + + while (1) { + key = getopt_long(argc, argv, short_options, options, NULL); + if (key < 0) { + break; + } + + if (!parseArg(config, key, optarg)) { + delete config; + return nullptr; + } + } + + if (optind < argc) { + fprintf(stderr, "%s: unsupported non-option argument '%s'\n", argv[0], argv[optind]); + delete config; + return nullptr; + } + + if (!config->isValid()) { + loadFromFile(config, Platform::defaultConfigName()); + } + + if (!config->isValid()) { + fprintf(stderr, "No pool URL supplied. Exiting.\n"); + delete config; + return nullptr; + } + + if (config->isWatch()) { + m_watcher = new xmrig::ConfigWatcher(config->fileName(), creator, listener); + } + + config->adjust(); + return config; +} + + +void xmrig::ConfigLoader::release() +{ + delete m_watcher; + delete m_creator; + + m_watcher = nullptr; + m_creator = nullptr; +} + + +bool xmrig::ConfigLoader::getJSON(const char *fileName, rapidjson::Document &doc) +{ + uv_fs_t req; + const int fd = uv_fs_open(uv_default_loop(), &req, fileName, O_RDONLY, 0644, nullptr); + if (fd < 0) { + fprintf(stderr, "unable to open %s: %s\n", fileName, uv_strerror(fd)); + return false; + } + + uv_fs_req_cleanup(&req); + + FILE *fp = fdopen(fd, "rb"); + char buf[8192]; + rapidjson::FileReadStream is(fp, buf, sizeof(buf)); + + doc.ParseStream(is); + + uv_fs_close(uv_default_loop(), &req, fd, nullptr); + uv_fs_req_cleanup(&req); + + if (doc.HasParseError()) { + printf("%s<%d>: %s\n", fileName, (int) doc.GetErrorOffset(), rapidjson::GetParseError_En(doc.GetParseError())); + return false; + } + + return doc.IsObject(); +} + + +bool xmrig::ConfigLoader::parseArg(xmrig::IConfig *config, int key, const char *arg) +{ + switch (key) { + case xmrig::IConfig::VersionKey: /* --version */ + showVersion(); + return false; + + case xmrig::IConfig::HelpKey: /* --help */ + showUsage(); + return false; + + case xmrig::IConfig::ConfigKey: /* --config */ + loadFromFile(config, arg); + break; + + default: + return config->parseString(key, arg);; + } + + return true; +} + + +void xmrig::ConfigLoader::parseJSON(xmrig::IConfig *config, const struct option *option, const rapidjson::Value &object) +{ + if (!option->name || !object.HasMember(option->name)) { + return; + } + + const rapidjson::Value &value = object[option->name]; + + if (option->has_arg) { + if (value.IsString()) { + config->parseString(option->val, value.GetString()); + } + else if (value.IsInt64()) { + config->parseUint64(option->val, value.GetUint64()); + } + else if (value.IsBool()) { + config->parseBoolean(option->val, value.IsTrue()); + } + } + else if (value.IsBool()) { + config->parseBoolean(option->val, value.IsTrue()); + } +} + + +void xmrig::ConfigLoader::showUsage() +{ + printf(usage); +} + + +void xmrig::ConfigLoader::showVersion() +{ + printf(APP_NAME " " APP_VERSION "\n built on " __DATE__ + +# if defined(__clang__) + " with clang " __clang_version__); +# elif defined(__GNUC__) + " with GCC"); + printf(" %d.%d.%d", __GNUC__, __GNUC_MINOR__, __GNUC_PATCHLEVEL__); +# elif defined(_MSC_VER) + " with MSVC"); + printf(" %d", MSVC_VERSION); +# else + ); +# endif + + printf("\n features:" +# if defined(__i386__) || defined(_M_IX86) + " i386" +# elif defined(__x86_64__) || defined(_M_AMD64) + " x86_64" +# endif + +# if defined(__AES__) || defined(_MSC_VER) + " AES-NI" +# endif + "\n"); + + printf("\nlibuv/%s\n", uv_version_string()); + +# ifndef XMRIG_NO_HTTPD + printf("libmicrohttpd/%s\n", MHD_get_version()); +# endif +} diff --git a/src/core/ConfigLoader.h b/src/core/ConfigLoader.h new file mode 100644 index 000000000..64638af3d --- /dev/null +++ b/src/core/ConfigLoader.h @@ -0,0 +1,71 @@ +/* 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 __CONFIGLOADER_H__ +#define __CONFIGLOADER_H__ + + +#include + + +#include "rapidjson/fwd.h" + + +struct option; + + +namespace xmrig { + + +class ConfigWatcher; +class IConfigCreator; +class IWatcherListener; +class IConfig; + + +class ConfigLoader +{ +public: + static bool loadFromFile(IConfig *config, const char *fileName); + static bool loadFromJSON(IConfig *config, const char *json); + static bool loadFromJSON(IConfig *config, const rapidjson::Document &doc); + static bool reload(IConfig *oldConfig, const char *json); + static IConfig *load(int argc, char **argv, IConfigCreator *creator, IWatcherListener *listener); + static void release(); + +private: + static bool getJSON(const char *fileName, rapidjson::Document &doc); + static bool parseArg(IConfig *config, int key, const char *arg); + static void parseJSON(IConfig *config, const struct option *option, const rapidjson::Value &object); + static void showUsage(); + static void showVersion(); + + static ConfigWatcher *m_watcher; + static IConfigCreator *m_creator; + static IWatcherListener *m_listener; +}; + + +} /* namespace xmrig */ + +#endif /* __CONFIGLOADER_H__ */ diff --git a/src/core/ConfigLoader_platform.h b/src/core/ConfigLoader_platform.h new file mode 100644 index 000000000..59415f783 --- /dev/null +++ b/src/core/ConfigLoader_platform.h @@ -0,0 +1,171 @@ +/* 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 __CONFIGLOADER_PLATFORM_H__ +#define __CONFIGLOADER_PLATFORM_H__ + + +#ifdef _MSC_VER +# include "getopt/getopt.h" +#else +# include +#endif + + +#include "version.h" +#include "interfaces/IConfig.h" + + +namespace xmrig { + + +static char const usage[] = "\ +Usage: " APP_ID " [OPTIONS]\n\ +Options:\n\ + -a, --algo=ALGO cryptonight (default) or cryptonight-lite\n\ + -o, --url=URL URL of mining server\n\ + -O, --userpass=U:P username:password pair for mining server\n\ + -u, --user=USERNAME username for mining server\n\ + -p, --pass=PASSWORD password for mining server\n\ + -t, --threads=N number of miner threads\n\ + -v, --av=N algorithm variation, 0 auto select\n\ + -k, --keepalive send keepalived for prevent timeout (need pool support)\n\ + -r, --retries=N number of times to retry before switch to backup server (default: 5)\n\ + -R, --retry-pause=N time to pause between retries (default: 5)\n\ + --cpu-affinity set process affinity to CPU core(s), mask 0x3 for cores 0 and 1\n\ + --cpu-priority set process priority (0 idle, 2 normal to 5 highest)\n\ + --no-huge-pages disable huge pages support\n\ + --no-color disable colored output\n\ + --variant algorithm PoW variant\n\ + --donate-level=N donate level, default 5%% (5 minutes in 100 minutes)\n\ + --user-agent set custom user-agent string for pool\n\ + -B, --background run the miner in the background\n\ + -c, --config=FILE load a JSON-format configuration file\n\ + -l, --log-file=FILE log all output to a file\n" +# ifdef HAVE_SYSLOG_H +"\ + -S, --syslog use system log for output messages\n" +# endif +"\ + --max-cpu-usage=N maximum CPU usage for automatic threads mode (default 75)\n\ + --safe safe adjust threads and av settings for current CPU\n\ + --nicehash enable nicehash/xmrig-proxy support\n\ + --print-time=N print hashrate report every N seconds\n\ + --api-port=N port for the miner API\n\ + --api-access-token=T access token for API\n\ + --api-worker-id=ID custom worker-id for API\n\ + -h, --help display this help and exit\n\ + -V, --version output version information and exit\n\ +"; + + +static char const short_options[] = "a:c:khBp:Px:r:R:s:t:T:o:u:O:v:Vl:S"; + + +static struct option const options[] = { + { "algo", 1, nullptr, xmrig::IConfig::AlgorithmKey }, + { "api-access-token", 1, nullptr, xmrig::IConfig::ApiAccessTokenKey }, + { "api-port", 1, nullptr, xmrig::IConfig::ApiPort }, + { "api-worker-id", 1, nullptr, xmrig::IConfig::ApiWorkerIdKey }, + { "api-no-ipv6", 0, nullptr, xmrig::IConfig::ApiIPv6Key }, + { "api-no-restricted", 0, nullptr, xmrig::IConfig::ApiRestrictedKey }, + { "av", 1, nullptr, xmrig::IConfig::AVKey }, + { "background", 0, nullptr, xmrig::IConfig::BackgroundKey }, + { "config", 1, nullptr, xmrig::IConfig::ConfigKey }, + { "cpu-affinity", 1, nullptr, xmrig::IConfig::CPUAffinityKey }, + { "cpu-priority", 1, nullptr, xmrig::IConfig::CPUPriorityKey }, + { "donate-level", 1, nullptr, xmrig::IConfig::DonateLevelKey }, + { "dry-run", 0, nullptr, xmrig::IConfig::DryRunKey }, + { "help", 0, nullptr, xmrig::IConfig::HelpKey }, + { "keepalive", 0, nullptr, xmrig::IConfig::KeepAliveKey }, + { "log-file", 1, nullptr, xmrig::IConfig::LogFileKey }, + { "max-cpu-usage", 1, nullptr, xmrig::IConfig::MaxCPUUsageKey }, + { "nicehash", 0, nullptr, xmrig::IConfig::NicehashKey }, + { "no-color", 0, nullptr, xmrig::IConfig::ColorKey }, + { "no-huge-pages", 0, nullptr, xmrig::IConfig::HugePagesKey }, + { "variant", 1, nullptr, xmrig::IConfig::VariantKey }, + { "pass", 1, nullptr, xmrig::IConfig::PasswordKey }, + { "print-time", 1, nullptr, xmrig::IConfig::PrintTimeKey }, + { "retries", 1, nullptr, xmrig::IConfig::RetriesKey }, + { "retry-pause", 1, nullptr, xmrig::IConfig::RetryPauseKey }, + { "safe", 0, nullptr, xmrig::IConfig::SafeKey }, + { "syslog", 0, nullptr, xmrig::IConfig::SyslogKey }, + { "threads", 1, nullptr, xmrig::IConfig::ThreadsKey }, + { "url", 1, nullptr, xmrig::IConfig::UrlKey }, + { "user", 1, nullptr, xmrig::IConfig::UserKey }, + { "user-agent", 1, nullptr, xmrig::IConfig::UserAgentKey }, + { "userpass", 1, nullptr, xmrig::IConfig::UserpassKey }, + { "version", 0, nullptr, xmrig::IConfig::VersionKey }, + { 0, 0, 0, 0 } +}; + + +static struct option const config_options[] = { + { "algo", 1, nullptr, xmrig::IConfig::AlgorithmKey }, + { "av", 1, nullptr, xmrig::IConfig::AVKey }, + { "background", 0, nullptr, xmrig::IConfig::BackgroundKey }, + { "colors", 0, nullptr, xmrig::IConfig::ColorKey }, + { "cpu-affinity", 1, nullptr, xmrig::IConfig::CPUAffinityKey }, + { "cpu-priority", 1, nullptr, xmrig::IConfig::CPUPriorityKey }, + { "donate-level", 1, nullptr, xmrig::IConfig::DonateLevelKey }, + { "dry-run", 0, nullptr, xmrig::IConfig::DryRunKey }, + { "huge-pages", 0, nullptr, xmrig::IConfig::HugePagesKey }, + { "log-file", 1, nullptr, xmrig::IConfig::LogFileKey }, + { "max-cpu-usage", 1, nullptr, xmrig::IConfig::MaxCPUUsageKey }, + { "print-time", 1, nullptr, xmrig::IConfig::PrintTimeKey }, + { "retries", 1, nullptr, xmrig::IConfig::RetriesKey }, + { "retry-pause", 1, nullptr, xmrig::IConfig::RetryPauseKey }, + { "safe", 0, nullptr, xmrig::IConfig::SafeKey }, + { "syslog", 0, nullptr, xmrig::IConfig::SyslogKey }, + { "threads", 1, nullptr, xmrig::IConfig::SafeKey }, + { "user-agent", 1, nullptr, xmrig::IConfig::UserAgentKey }, + { 0, 0, 0, 0 } +}; + + +static struct option const pool_options[] = { + { "url", 1, nullptr, xmrig::IConfig::UrlKey }, + { "pass", 1, nullptr, xmrig::IConfig::PasswordKey }, + { "user", 1, nullptr, xmrig::IConfig::UserKey }, + { "userpass", 1, nullptr, xmrig::IConfig::UserpassKey }, + { "nicehash", 0, nullptr, xmrig::IConfig::NicehashKey }, + { "keepalive", 2, nullptr, xmrig::IConfig::KeepAliveKey }, + { "variant", 1, nullptr, xmrig::IConfig::VariantKey }, + { 0, 0, 0, 0 } +}; + + +static struct option const api_options[] = { + { "port", 1, nullptr, xmrig::IConfig::ApiPort }, + { "access-token", 1, nullptr, xmrig::IConfig::ApiAccessTokenKey }, + { "worker-id", 1, nullptr, xmrig::IConfig::ApiWorkerIdKey }, + { "ipv6", 0, nullptr, xmrig::IConfig::ApiIPv6Key }, + { "restricted", 0, nullptr, xmrig::IConfig::ApiRestrictedKey }, + { 0, 0, 0, 0 } +}; + + +} /* namespace xmrig */ + +#endif /* __CONFIGLOADER_PLATFORM_H__ */ diff --git a/src/core/ConfigWatcher.cpp b/src/core/ConfigWatcher.cpp new file mode 100644 index 000000000..b934b52b5 --- /dev/null +++ b/src/core/ConfigWatcher.cpp @@ -0,0 +1,107 @@ +/* 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 "core/ConfigCreator.h" +#include "core/ConfigLoader.h" +#include "core/ConfigWatcher.h" +#include "interfaces/IWatcherListener.h" +#include "log/Log.h" + + +xmrig::ConfigWatcher::ConfigWatcher(const char *path, IConfigCreator *creator, IWatcherListener *listener) : + m_path(strdup(path)), + m_creator(creator), + m_listener(listener) +{ + uv_fs_event_init(uv_default_loop(), &m_fsEvent); + uv_timer_init(uv_default_loop(), &m_timer); + + m_fsEvent.data = m_timer.data = this; + + start(); +} + + +xmrig::ConfigWatcher::~ConfigWatcher() +{ + uv_timer_stop(&m_timer); + uv_fs_event_stop(&m_fsEvent); + + free(m_path); +} + + +void xmrig::ConfigWatcher::onTimer(uv_timer_t* handle) +{ + static_cast(handle->data)->reload(); +} + + +void xmrig::ConfigWatcher::onFsEvent(uv_fs_event_t* handle, const char *filename, int events, int status) +{ + if (!filename) { + return; + } + + static_cast(handle->data)->queueUpdate(); +} + + +void xmrig::ConfigWatcher::queueUpdate() +{ + uv_timer_stop(&m_timer); + uv_timer_start(&m_timer, xmrig::ConfigWatcher::onTimer, kDelay, 0); +} + + +void xmrig::ConfigWatcher::reload() +{ + LOG_WARN("\"%s\" was changed, reloading configuration", m_path); + + IConfig *config = m_creator->create(); + ConfigLoader::loadFromFile(config, m_path); + + if (!config->isValid()) { + LOG_ERR("reloading failed"); + + delete config; + return; + } + + m_listener->onNewConfig(config); + +# ifndef _WIN32 + uv_fs_event_stop(&m_fsEvent); + start(); +# endif +} + + +void xmrig::ConfigWatcher::start() +{ + uv_fs_event_start(&m_fsEvent, xmrig::ConfigWatcher::onFsEvent, m_path, 0); +} diff --git a/src/core/ConfigWatcher.h b/src/core/ConfigWatcher.h new file mode 100644 index 000000000..74526e904 --- /dev/null +++ b/src/core/ConfigWatcher.h @@ -0,0 +1,69 @@ +/* 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 __CONFIGWATCHER_H__ +#define __CONFIGWATCHER_H__ + + +#include +#include + +#include "rapidjson/fwd.h" + + +struct option; + + +namespace xmrig { + + +class IConfigCreator; +class IWatcherListener; + + +class ConfigWatcher +{ +public: + ConfigWatcher(const char *path, IConfigCreator *creator, IWatcherListener *listener); + ~ConfigWatcher(); + +private: + constexpr static int kDelay = 500; + + static void onFsEvent(uv_fs_event_t* handle, const char *filename, int events, int status); + static void onTimer(uv_timer_t* handle); + void queueUpdate(); + void reload(); + void start(); + + char *m_path; + IConfigCreator *m_creator; + IWatcherListener *m_listener; + uv_fs_event_t m_fsEvent; + uv_timer_t m_timer; +}; + + +} /* namespace xmrig */ + +#endif /* __CONFIGWATCHER_H__ */ diff --git a/src/core/Controller.cpp b/src/core/Controller.cpp index af8a27d56..a5ffe236a 100644 --- a/src/core/Controller.cpp +++ b/src/core/Controller.cpp @@ -112,7 +112,7 @@ void xmrig::Controller::addListener(IControllerListener *listener) } -void xmrig::Controller::onNewConfig(Config *config) +void xmrig::Controller::onNewConfig(IConfig *config) { // xmrig::Config *previousConfig = d_ptr->config; // d_ptr->config = config; diff --git a/src/core/Controller.h b/src/core/Controller.h index 2fe37c154..9144cca7e 100644 --- a/src/core/Controller.h +++ b/src/core/Controller.h @@ -52,7 +52,7 @@ public: void addListener(IControllerListener *listener); protected: - void onNewConfig(Config *config) override; + void onNewConfig(IConfig *config) override; private: ControllerPrivate *d_ptr; diff --git a/src/donate.h b/src/donate.h index e8230b870..bdf7a00d2 100644 --- a/src/donate.h +++ b/src/donate.h @@ -38,7 +38,8 @@ * XMR: 48edfHu7V9Z84YzzMa6fUueoELZ9ZRXq9VetWzYGzKt52XU5xvqgzYnDK9URnRoJMk1j8nLwEVsaSWJ4fhdUyZijBGUicoD * BTC: 1P7ujsXeX7GxQwHNnJsRMgAdNkFZmNVqJT */ -constexpr const int kDonateLevel = 5; +constexpr const int kDefaultDonateLevel = 5; +constexpr const int kMinDonateLevel = 1; #endif /* __DONATE_H__ */ diff --git a/src/interfaces/IConfig.h b/src/interfaces/IConfig.h new file mode 100644 index 000000000..89aa62177 --- /dev/null +++ b/src/interfaces/IConfig.h @@ -0,0 +1,109 @@ +/* XMRig + * Copyright 2010 Jeff Garzik + * Copyright 2012-2014 pooler + * Copyright 2014 Lucas Jones + * Copyright 2014-2016 Wolf9466 + * Copyright 2016 Jay D Dee + * 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 __ICONFIG_H__ +#define __ICONFIG_H__ + + +#include "rapidjson/fwd.h" + + +namespace xmrig { + + +class IConfig +{ +public: + enum Keys { + // common + AlgorithmKey = 'a', + ApiPort = 4000, + ApiAccessTokenKey = 4001, + ApiWorkerIdKey = 4002, + ApiIPv6Key = 4003, + ApiRestrictedKey = 4004, + BackgroundKey = 'B', + ConfigKey = 'c', + DonateLevelKey = 1003, + HelpKey = 'h', + KeepAliveKey = 'k', + LogFileKey = 'l', + ColorKey = 1002, + WatchKey = 1105, + PasswordKey = 'p', + RetriesKey = 'r', + RetryPauseKey = 'R', + SyslogKey = 'S', + UrlKey = 'o', + UserKey = 'u', + UserAgentKey = 1008, + UserpassKey = 'O', + VerboseKey = 1100, + VersionKey = 'V', + VariantKey = 1010, + + // xmrig common + CPUPriorityKey = 1021, + NicehashKey = 1006, + PrintTimeKey = 1007, + + // xmrig cpu + AVKey = 'v', + CPUAffinityKey = 1020, + DryRunKey = 5000, + HugePagesKey = 1009, + MaxCPUUsageKey = 1004, + SafeKey = 1005, + ThreadsKey = 't', + + // xmrig-proxy + AccessLogFileKey = 'A', + BindKey = 'b', + CoinKey = 1104, + CustomDiffKey = 1102, + DebugKey = 1101, + ModeKey = 'm', + PoolCoinKey = 'C', + ReuseTimeoutKey = 1106, + WorkersKey = 1103, + }; + + virtual ~IConfig() {} + + virtual bool adjust() = 0; + virtual bool isValid() const = 0; + virtual bool isWatch() const = 0; + virtual bool parseBoolean(int key, bool enable) = 0; + virtual bool parseString(int key, const char *arg) = 0; + virtual bool parseUint64(int key, uint64_t arg) = 0; + virtual bool save() = 0; + virtual const char *fileName() const = 0; + virtual void getJSON(rapidjson::Document &doc) const = 0; + virtual void parseJSON(const rapidjson::Document &doc) = 0; + virtual void setFileName(const char *fileName) = 0; +}; + + +} /* namespace xmrig */ + + +#endif // __ICONFIG_H__ diff --git a/src/interfaces/IConfigCreator.h b/src/interfaces/IConfigCreator.h new file mode 100644 index 000000000..597a6b742 --- /dev/null +++ b/src/interfaces/IConfigCreator.h @@ -0,0 +1,45 @@ +/* XMRig + * Copyright 2010 Jeff Garzik + * Copyright 2012-2014 pooler + * Copyright 2014 Lucas Jones + * Copyright 2014-2016 Wolf9466 + * Copyright 2016 Jay D Dee + * 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 __ICONFIGCREATOR_H__ +#define __ICONFIGCREATOR_H__ + + +namespace xmrig { + + +class IConfig; + + +class IConfigCreator +{ +public: + virtual ~IConfigCreator() {} + + virtual IConfig *create() const = 0; +}; + + +} /* namespace xmrig */ + + +#endif // __ICONFIGCREATOR_H__ diff --git a/src/interfaces/IWatcherListener.h b/src/interfaces/IWatcherListener.h index da30b1fd3..bfafb9a01 100644 --- a/src/interfaces/IWatcherListener.h +++ b/src/interfaces/IWatcherListener.h @@ -28,7 +28,7 @@ namespace xmrig { -class Config; +class IConfig; class IWatcherListener @@ -36,7 +36,7 @@ class IWatcherListener public: virtual ~IWatcherListener() {} - virtual void onNewConfig(Config *config) = 0; + virtual void onNewConfig(IConfig *config) = 0; }; diff --git a/src/net/Url.cpp b/src/net/Url.cpp index c17ef690a..8905e9190 100644 --- a/src/net/Url.cpp +++ b/src/net/Url.cpp @@ -37,12 +37,12 @@ Url::Url() : - m_keepAlive(false), m_nicehash(false), m_host(nullptr), m_password(nullptr), m_user(nullptr), m_algo(xmrig::ALGO_CRYPTONIGHT), + m_keepAlive(0), m_variant(xmrig::VARIANT_AUTO), m_url(nullptr), m_port(kDefaultPort) @@ -62,12 +62,12 @@ Url::Url() : * @param url */ Url::Url(const char *url) : - m_keepAlive(false), m_nicehash(false), m_host(nullptr), m_password(nullptr), m_user(nullptr), m_algo(xmrig::ALGO_CRYPTONIGHT), + m_keepAlive(0), m_variant(xmrig::VARIANT_AUTO), m_url(nullptr), m_port(kDefaultPort) @@ -76,12 +76,12 @@ Url::Url(const char *url) : } -Url::Url(const char *host, uint16_t port, const char *user, const char *password, bool keepAlive, bool nicehash, int variant) : - m_keepAlive(keepAlive), +Url::Url(const char *host, uint16_t port, const char *user, const char *password, int keepAlive, bool nicehash, int variant) : m_nicehash(nicehash), m_password(password ? strdup(password) : nullptr), m_user(user ? strdup(user) : nullptr), m_algo(xmrig::ALGO_CRYPTONIGHT), + m_keepAlive(keepAlive), m_variant(variant), m_url(nullptr), m_port(port) diff --git a/src/net/Url.h b/src/net/Url.h index f861fec54..45db4457f 100644 --- a/src/net/Url.h +++ b/src/net/Url.h @@ -34,22 +34,24 @@ public: constexpr static const char *kDefaultPassword = "x"; constexpr static const char *kDefaultUser = "x"; constexpr static uint16_t kDefaultPort = 3333; + constexpr static int kKeepAliveTimeout = 60; Url(); Url(const char *url); - Url(const char *host, uint16_t port, const char *user = nullptr, const char *password = nullptr, bool keepAlive = false, bool nicehash = false, int variant = -1); + Url(const char *host, uint16_t port, const char *user = nullptr, const char *password = nullptr, int keepAlive = 0, bool nicehash = false, int variant = -1); ~Url(); - inline bool isKeepAlive() const { return m_keepAlive; } + inline bool isKeepAlive() const { return m_keepAlive > 0; } // FIXME: replace isKeepAlive to keepAlive inline bool isNicehash() const { return m_nicehash; } inline bool isValid() const { return m_host && m_port > 0; } inline const char *host() const { return m_host; } inline const char *password() const { return m_password ? m_password : kDefaultPassword; } inline const char *user() const { return m_user ? m_user : kDefaultUser; } inline int algo() const { return m_algo; } + inline int keepAlive() const { return m_keepAlive; } inline int variant() const { return m_variant; } inline uint16_t port() const { return m_port; } - inline void setKeepAlive(bool keepAlive) { m_keepAlive = keepAlive; } + inline void setKeepAlive(int keepAlive) { m_keepAlive = keepAlive >= 0 ? keepAlive : 0; } inline void setNicehash(bool nicehash) { m_nicehash = nicehash; } inline void setVariant(bool monero) { m_variant = monero; } @@ -67,12 +69,12 @@ public: private: bool parseIPv6(const char *addr); - bool m_keepAlive; bool m_nicehash; char *m_host; char *m_password; char *m_user; int m_algo; + int m_keepAlive; int m_variant; mutable char *m_url; uint16_t m_port; diff --git a/src/xmrig.h b/src/xmrig.h index 103e8a68e..9cae73c77 100644 --- a/src/xmrig.h +++ b/src/xmrig.h @@ -30,8 +30,9 @@ namespace xmrig enum Algo { - ALGO_CRYPTONIGHT, /* CryptoNight (Monero) */ - ALGO_CRYPTONIGHT_LITE, /* CryptoNight-Lite (AEON) */ + ALGO_CRYPTONIGHT, /* CryptoNight (Monero) */ + ALGO_CRYPTONIGHT_LITE, /* CryptoNight-Lite (AEON) */ + ALGO_CRYPTONIGHT_HEAVY, /* CryptoNight-Heavy (SUMO) */ };