diff --git a/CMakeLists.txt b/CMakeLists.txt index 1be15601..1f42950e 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 @@ -35,12 +43,12 @@ set(HEADERS src/net/Job.h src/net/JobResult.h src/net/Network.h + src/net/Storage.h src/net/strategies/DonateStrategy.h src/net/strategies/FailoverStrategy.h src/net/strategies/SinglePoolStrategy.h src/net/SubmitResult.h src/net/Url.h - src/Options.h src/Platform.h src/Summary.h src/version.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 @@ -92,7 +104,6 @@ set(SOURCES src/net/strategies/SinglePoolStrategy.cpp src/net/SubmitResult.cpp src/net/Url.cpp - src/Options.cpp src/Platform.cpp src/Summary.cpp src/workers/DoubleWorker.cpp diff --git a/src/App.cpp b/src/App.cpp index ed425f90..9bdd381e 100644 --- a/src/App.cpp +++ b/src/App.cpp @@ -29,6 +29,7 @@ #include "api/Api.h" #include "App.h" #include "Console.h" +#include "core/Config.h" #include "core/Controller.h" #include "Cpu.h" #include "crypto/CryptoNight.h" @@ -37,17 +38,12 @@ #include "log/Log.h" #include "Mem.h" #include "net/Network.h" -#include "Options.h" #include "Platform.h" #include "Summary.h" #include "version.h" #include "workers/Workers.h" -#ifdef HAVE_SYSLOG_H -# include "log/SysLog.h" -#endif - #ifndef XMRIG_NO_HTTPD # include "api/Httpd.h" #endif @@ -59,42 +55,19 @@ App *App::m_self = nullptr; App::App(int argc, char **argv) : m_console(nullptr), - m_httpd(nullptr), - m_network(nullptr), - m_options(nullptr) + m_httpd(nullptr) { m_self = this; m_controller = new xmrig::Controller(); - - Cpu::init(); - m_options = Options::parse(argc, argv); - if (!m_options) { + if (m_controller->init(argc, argv) != 0) { return; } - Log::init(); - - if (!m_options->background()) { - Log::add(new ConsoleLog(m_options->colors())); + if (!m_controller->config()->isBackground()) { m_console = new Console(this); } - if (m_options->logFile()) { - Log::add(new FileLog(m_options->logFile())); - } - -# ifdef HAVE_SYSLOG_H - if (m_options->syslog()) { - Log::add(new SysLog()); - } -# endif - - Platform::init(m_options->userAgent()); - Platform::setProcessPriority(m_options->priority()); - - m_network = new Network(m_options); - uv_signal_init(uv_default_loop(), &m_sigHUP); uv_signal_init(uv_default_loop(), &m_sigINT); uv_signal_init(uv_default_loop(), &m_sigTERM); @@ -103,19 +76,22 @@ App::App(int argc, char **argv) : App::~App() { + Mem::release(); + uv_tty_reset_mode(); + delete m_console; + delete m_controller; + # ifndef XMRIG_NO_HTTPD delete m_httpd; # endif - - delete m_console; } int App::exec() { - if (!m_options) { + if (!m_controller->isReady()) { return 2; } @@ -125,15 +101,20 @@ int App::exec() background(); - if (!CryptoNight::init(m_options->algo(), m_options->algoVariant())) { - LOG_ERR("\"%s\" hash self-test failed.", m_options->algoName()); + if (!CryptoNight::init(m_controller->config()->algorithm(), m_controller->config()->algoVariant(), m_controller->config()->isDoubleHash())) { + LOG_ERR("\"%s\" hash self-test failed.", m_controller->config()->algoName()); return 1; } - Mem::allocate(m_options->algo(), m_options->threads(), m_options->doubleHash(), m_options->hugePages()); - Summary::print(); + Mem::allocate(m_controller->config()->algorithm(), + m_controller->config()->threads(), + m_controller->config()->isDoubleHash(), + m_controller->config()->isHugePages() + ); - if (m_options->dryRun()) { + Summary::print(m_controller); + + if (m_controller->config()->isDryRun()) { LOG_NOTICE("OK"); release(); @@ -145,13 +126,19 @@ int App::exec() # endif # ifndef XMRIG_NO_HTTPD - m_httpd = new Httpd(m_options->apiPort(), m_options->apiToken(), true, true); + m_httpd = new Httpd( + m_controller->config()->apiPort(), + m_controller->config()->apiToken(), + m_controller->config()->isApiIPv6(), + m_controller->config()->isApiRestricted() + ); + m_httpd->start(); # endif - Workers::start(m_options->affinity(), m_options->priority()); + Workers::start(m_controller->config()->affinity(), m_controller->config()->priority(), m_controller); - m_network->connect(); + m_controller->network()->connect(); const int r = uv_run(uv_default_loop(), UV_RUN_DEFAULT); uv_loop_close(uv_default_loop()); @@ -172,7 +159,7 @@ void App::onConsoleCommand(char command) case 'p': case 'P': if (Workers::isEnabled()) { - LOG_INFO(m_options->colors() ? "\x1B[01;33mpaused\x1B[0m, press \x1B[01;35mr\x1B[0m to resume" : "paused, press 'r' to resume"); + LOG_INFO(m_controller->config()->isColors() ? "\x1B[01;33mpaused\x1B[0m, press \x1B[01;35mr\x1B[0m to resume" : "paused, press 'r' to resume"); Workers::setEnabled(false); } break; @@ -180,7 +167,7 @@ void App::onConsoleCommand(char command) case 'r': case 'R': if (!Workers::isEnabled()) { - LOG_INFO(m_options->colors() ? "\x1B[01;32mresumed" : "resumed"); + LOG_INFO(m_controller->config()->isColors() ? "\x1B[01;32mresumed" : "resumed"); Workers::setEnabled(true); } break; @@ -198,7 +185,7 @@ void App::onConsoleCommand(char command) void App::close() { - m_network->stop(); + m_controller->network()->stop(); Workers::stop(); uv_stop(uv_default_loop()); @@ -207,13 +194,6 @@ void App::close() void App::release() { - if (m_network) { - delete m_network; - } - - Options::release(); - Mem::release(); - Platform::release(); } diff --git a/src/App.h b/src/App.h index 9116a79a..22269f67 100644 --- a/src/App.h +++ b/src/App.h @@ -64,8 +64,6 @@ private: Console *m_console; Httpd *m_httpd; - Network *m_network; - Options *m_options; uv_signal_t m_sigHUP; uv_signal_t m_sigINT; uv_signal_t m_sigTERM; diff --git a/src/App_unix.cpp b/src/App_unix.cpp index 674a53e6..fdb2b124 100644 --- a/src/App_unix.cpp +++ b/src/App_unix.cpp @@ -29,20 +29,22 @@ #include "App.h" +#include "core/Config.h" +#include "core/Controller.h" #include "Cpu.h" #include "log/Log.h" -#include "Options.h" void App::background() { signal(SIGPIPE, SIG_IGN); - if (m_options->affinity() != -1L) { - Cpu::setAffinity(-1, m_options->affinity()); + const int64_t affinity = m_controller->config()->affinity(); + if (affinity != -1L) { + Cpu::setAffinity(-1, affinity); } - if (!m_options->background()) { + if (!m_controller->config()->isBackground()) { return; } diff --git a/src/App_win.cpp b/src/App_win.cpp index 895f3bdf..b3a2c4cf 100644 --- a/src/App_win.cpp +++ b/src/App_win.cpp @@ -4,8 +4,8 @@ * Copyright 2014 Lucas Jones * Copyright 2014-2016 Wolf9466 * Copyright 2016 Jay D Dee - * Copyright 2016-2017 XMRig - * + * 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 @@ -27,17 +27,19 @@ #include "App.h" -#include "Options.h" #include "Cpu.h" +#include "core/Controller.h" +#include "core/Config.h" void App::background() { - if (m_options->affinity() != -1L) { - Cpu::setAffinity(-1, m_options->affinity()); + const int64_t affinity = m_controller->config()->affinity(); + if (affinity != -1L) { + Cpu::setAffinity(-1, affinity); } - if (!m_options->background()) { + if (!m_controller->config()->isBackground()) { return; } diff --git a/src/Mem.cpp b/src/Mem.cpp index b32d2196..991f4398 100644 --- a/src/Mem.cpp +++ b/src/Mem.cpp @@ -28,7 +28,6 @@ #include "crypto/CryptoNight.h" #include "Mem.h" -#include "Options.h" #include "xmrig.h" diff --git a/src/Mem_unix.cpp b/src/Mem_unix.cpp index 3e699544..3b69f267 100644 --- a/src/Mem_unix.cpp +++ b/src/Mem_unix.cpp @@ -37,7 +37,6 @@ #include "crypto/CryptoNight.h" #include "log/Log.h" #include "Mem.h" -#include "Options.h" #include "xmrig.h" diff --git a/src/Mem_win.cpp b/src/Mem_win.cpp index 239bda7d..1b35c704 100644 --- a/src/Mem_win.cpp +++ b/src/Mem_win.cpp @@ -37,7 +37,6 @@ #include "log/Log.h" #include "crypto/CryptoNight.h" #include "Mem.h" -#include "Options.h" #include "xmrig.h" diff --git a/src/Options.cpp b/src/Options.cpp deleted file mode 100644 index 939075f8..00000000 --- a/src/Options.cpp +++ /dev/null @@ -1,761 +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 . - */ - - -#include -#include - - -#ifdef _MSC_VER -# include "getopt/getopt.h" -#else -# include -#endif - - -#ifndef XMRIG_NO_HTTPD -# include -#endif - - -#include "Cpu.h" -#include "donate.h" -#include "net/Url.h" -#include "Options.h" -#include "Platform.h" -#include "rapidjson/document.h" -#include "rapidjson/error/en.h" -#include "rapidjson/filereadstream.h" -#include "version.h" -#include "xmrig.h" - - -#ifndef ARRAY_SIZE -# define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0])) -#endif - - -Options *Options::m_self = nullptr; - - -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, 'a' }, - { "api-access-token", 1, nullptr, 4001 }, - { "api-port", 1, nullptr, 4000 }, - { "api-worker-id", 1, nullptr, 4002 }, - { "av", 1, nullptr, 'v' }, - { "background", 0, nullptr, 'B' }, - { "config", 1, nullptr, 'c' }, - { "cpu-affinity", 1, nullptr, 1020 }, - { "cpu-priority", 1, nullptr, 1021 }, - { "donate-level", 1, nullptr, 1003 }, - { "dry-run", 0, nullptr, 5000 }, - { "help", 0, nullptr, 'h' }, - { "keepalive", 0, nullptr ,'k' }, - { "log-file", 1, nullptr, 'l' }, - { "max-cpu-usage", 1, nullptr, 1004 }, - { "nicehash", 0, nullptr, 1006 }, - { "no-color", 0, nullptr, 1002 }, - { "no-huge-pages", 0, nullptr, 1009 }, - { "variant", 1, nullptr, 1010 }, - { "pass", 1, nullptr, 'p' }, - { "print-time", 1, nullptr, 1007 }, - { "retries", 1, nullptr, 'r' }, - { "retry-pause", 1, nullptr, 'R' }, - { "safe", 0, nullptr, 1005 }, - { "syslog", 0, nullptr, 'S' }, - { "threads", 1, nullptr, 't' }, - { "url", 1, nullptr, 'o' }, - { "user", 1, nullptr, 'u' }, - { "user-agent", 1, nullptr, 1008 }, - { "userpass", 1, nullptr, 'O' }, - { "version", 0, nullptr, 'V' }, - { 0, 0, 0, 0 } -}; - - -static struct option const config_options[] = { - { "algo", 1, nullptr, 'a' }, - { "av", 1, nullptr, 'v' }, - { "background", 0, nullptr, 'B' }, - { "colors", 0, nullptr, 2000 }, - { "cpu-affinity", 1, nullptr, 1020 }, - { "cpu-priority", 1, nullptr, 1021 }, - { "donate-level", 1, nullptr, 1003 }, - { "dry-run", 0, nullptr, 5000 }, - { "huge-pages", 0, nullptr, 1009 }, - { "log-file", 1, nullptr, 'l' }, - { "max-cpu-usage", 1, nullptr, 1004 }, - { "print-time", 1, nullptr, 1007 }, - { "retries", 1, nullptr, 'r' }, - { "retry-pause", 1, nullptr, 'R' }, - { "safe", 0, nullptr, 1005 }, - { "syslog", 0, nullptr, 'S' }, - { "threads", 1, nullptr, 't' }, - { "user-agent", 1, nullptr, 1008 }, - { 0, 0, 0, 0 } -}; - - -static struct option const pool_options[] = { - { "url", 1, nullptr, 'o' }, - { "pass", 1, nullptr, 'p' }, - { "user", 1, nullptr, 'u' }, - { "userpass", 1, nullptr, 'O' }, - { "keepalive", 0, nullptr ,'k' }, - { "variant", 1, nullptr, 1010 }, - { "nicehash", 0, nullptr, 1006 }, - { 0, 0, 0, 0 } -}; - - -static struct option const api_options[] = { - { "port", 1, nullptr, 4000 }, - { "access-token", 1, nullptr, 4001 }, - { "worker-id", 1, nullptr, 4002 }, - { 0, 0, 0, 0 } -}; - - -static const char *algo_names[] = { - "cryptonight", -# ifndef XMRIG_NO_AEON - "cryptonight-lite" -# endif -}; - - -Options *Options::parse(int argc, char **argv) -{ - Options *options = new Options(argc, argv); - if (options->isReady()) { - m_self = options; - return m_self; - } - - delete options; - return nullptr; -} - - -const char *Options::algoName() const -{ - return algo_names[m_algo]; -} - - -Options::Options(int argc, char **argv) : - m_background(false), - m_colors(true), - m_doubleHash(false), - m_dryRun(false), - m_hugePages(true), - m_ready(false), - m_safe(false), - m_syslog(false), - m_apiToken(nullptr), - m_apiWorkerId(nullptr), - m_logFile(nullptr), - m_userAgent(nullptr), - m_algo(0), - m_algoVariant(0), - m_apiPort(0), - m_donateLevel(kDonateLevel), - m_maxCpuUsage(75), - m_printTime(60), - m_priority(-1), - m_retries(5), - m_retryPause(5), - m_threads(0), - m_affinity(-1L) -{ - m_pools.push_back(new Url()); - - int key; - - while (1) { - key = getopt_long(argc, argv, short_options, options, NULL); - if (key < 0) { - break; - } - - if (!parseArg(key, optarg)) { - return; - } - } - - if (optind < argc) { - fprintf(stderr, "%s: unsupported non-option argument '%s'\n", argv[0], argv[optind]); - return; - } - - if (!m_pools[0]->isValid()) { - parseConfig(Platform::defaultConfigName()); - } - - if (!m_pools[0]->isValid()) { - fprintf(stderr, "No pool URL supplied. Exiting.\n"); - return; - } - - 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; - } - } - - adjust(); - - m_ready = true; -} - - -Options::~Options() -{ -} - - -bool Options::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 Options::parseArg(int key, const char *arg) -{ - switch (key) { - case 'a': /* --algo */ - if (!setAlgo(arg)) { - return false; - } - break; - - case 'o': /* --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 'O': /* --userpass */ - if (!m_pools.back()->setUserpass(arg)) { - return false; - } - break; - - case 'u': /* --user */ - m_pools.back()->setUser(arg); - break; - - case 'p': /* --pass */ - m_pools.back()->setPassword(arg); - break; - - case 'l': /* --log-file */ - free(m_logFile); - m_logFile = strdup(arg); - m_colors = false; - break; - - case 4001: /* --access-token */ - free(m_apiToken); - m_apiToken = strdup(arg); - break; - - case 4002: /* --worker-id */ - free(m_apiWorkerId); - m_apiWorkerId = strdup(arg); - break; - - case 'r': /* --retries */ - case 'R': /* --retry-pause */ - case 'v': /* --av */ - case 1003: /* --donate-level */ - case 1004: /* --max-cpu-usage */ - case 1007: /* --print-time */ - case 1021: /* --cpu-priority */ - case 4000: /* --api-port */ - case 1010: /* --variant */ - return parseArg(key, strtol(arg, nullptr, 10)); - - case 'B': /* --background */ - case 'k': /* --keepalive */ - case 'S': /* --syslog */ - case 1005: /* --safe */ - case 1006: /* --nicehash */ - case 5000: /* --dry-run */ - return parseBoolean(key, true); - - case 1002: /* --no-color */ - case 1009: /* --no-huge-pages */ - return parseBoolean(key, false); - - case 't': /* --threads */ - if (strncmp(arg, "all", 3) == 0) { - m_threads = Cpu::threads(); - return true; - } - - return parseArg(key, strtol(arg, nullptr, 10)); - - case 'V': /* --version */ - showVersion(); - return false; - - case 'h': /* --help */ - showUsage(0); - return false; - - case 'c': /* --config */ - parseConfig(arg); - break; - - case 1020: { /* --cpu-affinity */ - const char *p = strstr(arg, "0x"); - return parseArg(key, p ? strtoull(p, nullptr, 16) : strtoull(arg, nullptr, 10)); - } - - case 1008: /* --user-agent */ - free(m_userAgent); - m_userAgent = strdup(arg); - break; - - default: - showUsage(1); - return false; - } - - return true; -} - - -bool Options::parseArg(int key, uint64_t arg) -{ - switch (key) { - case 'r': /* --retries */ - if (arg < 1 || arg > 1000) { - showUsage(1); - return false; - } - - m_retries = (int) arg; - break; - - case 'R': /* --retry-pause */ - if (arg < 1 || arg > 3600) { - showUsage(1); - return false; - } - - m_retryPause = (int) arg; - break; - - case 't': /* --threads */ - if (arg < 1 || arg > 1024) { - showUsage(1); - return false; - } - - m_threads = (int) arg; - break; - - case 'v': /* --av */ - if (arg > 1000) { - showUsage(1); - return false; - } - - m_algoVariant = (int) arg; - break; - - case 1003: /* --donate-level */ - if (arg < 1 || arg > 99) { - return true; - } - - m_donateLevel = (int) arg; - break; - - case 1004: /* --max-cpu-usage */ - if (arg < 1 || arg > 100) { - showUsage(1); - return false; - } - - m_maxCpuUsage = (int) arg; - break; - - case 1007: /* --print-time */ - if (arg > 1000) { - showUsage(1); - return false; - } - - m_printTime = (int) arg; - break; - - case 1010: /* --variant */ - m_pools.back()->setVariant((int) arg); - break; - - case 1020: /* --cpu-affinity */ - if (arg) { - m_affinity = arg; - } - break; - - case 1021: /* --cpu-priority */ - if (arg <= 5) { - m_priority = (int) arg; - } - break; - - case 4000: /* --api-port */ - if (arg <= 65536) { - m_apiPort = (int) arg; - } - break; - - default: - break; - } - - return true; -} - - -bool Options::parseBoolean(int key, bool enable) -{ - switch (key) { - case 'k': /* --keepalive */ - m_pools.back()->setKeepAlive(enable); - break; - - case 'B': /* --background */ - m_background = enable; - m_colors = enable ? false : m_colors; - break; - - case 'S': /* --syslog */ - m_syslog = enable; - m_colors = enable ? false : m_colors; - break; - - case 1002: /* --no-color */ - m_colors = enable; - break; - - case 1005: /* --safe */ - m_safe = enable; - break; - - case 1006: /* --nicehash */ - m_pools.back()->setNicehash(enable); - break; - - case 1009: /* --no-huge-pages */ - m_hugePages = enable; - break; - - case 2000: /* colors */ - m_colors = enable; - break; - - case 5000: /* --dry-run */ - m_dryRun = enable; - break; - - default: - break; - } - - return true; -} - - -Url *Options::parseUrl(const char *arg) const -{ - auto url = new Url(arg); - if (!url->isValid()) { - delete url; - return nullptr; - } - - return url; -} - - -void Options::adjust() -{ - for (Url *url : m_pools) { - url->adjust(m_algo); - } -} - - -void Options::parseConfig(const char *fileName) -{ - rapidjson::Document doc; - if (!getJSON(fileName, doc)) { - return; - } - - for (size_t i = 0; i < ARRAY_SIZE(config_options); i++) { - parseJSON(&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(&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(&api_options[i], api); - } - } -} - - -void Options::parseJSON(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 && value.IsString()) { - parseArg(option->val, value.GetString()); - } - else if (option->has_arg && value.IsInt64()) { - parseArg(option->val, value.GetUint64()); - } - else if (!option->has_arg && value.IsBool()) { - parseBoolean(option->val, value.IsTrue()); - } -} - - -void Options::showUsage(int status) const -{ - if (status) { - fprintf(stderr, "Try \"" APP_ID "\" --help' for more information.\n"); - } - else { - printf(usage); - } -} - - -void Options::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 -} - - -bool Options::setAlgo(const char *algo) -{ - for (size_t i = 0; i < ARRAY_SIZE(algo_names); i++) { - if (algo_names[i] && !strcmp(algo, algo_names[i])) { - m_algo = (int) i; - break; - } - -# ifndef XMRIG_NO_AEON - if (i == ARRAY_SIZE(algo_names) - 1 && !strcmp(algo, "cryptonight-light")) { - m_algo = xmrig::ALGO_CRYPTONIGHT_LITE; - break; - } -# endif - - if (i == ARRAY_SIZE(algo_names) - 1) { - showUsage(1); - return false; - } - } - - return true; -} - - -int Options::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 Options::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/Options.h b/src/Options.h deleted file mode 100644 index e29059ec..00000000 --- a/src/Options.h +++ /dev/null @@ -1,133 +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 __OPTIONS_H__ -#define __OPTIONS_H__ - - -#include -#include - - -#include "rapidjson/fwd.h" - - -class Url; -struct option; - - -class Options -{ -public: - enum AlgoVariant { - AV0_AUTO, - AV1_AESNI, - AV2_AESNI_DOUBLE, - AV3_SOFT_AES, - AV4_SOFT_AES_DOUBLE, - AV_MAX - }; - - static inline Options* i() { return m_self; } - static Options *parse(int argc, char **argv); - - inline bool background() const { return m_background; } - inline bool colors() const { return m_colors; } - inline bool doubleHash() const { return m_doubleHash; } - inline bool dryRun() const { return m_dryRun; } - inline bool hugePages() const { return m_hugePages; } - inline bool syslog() 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 algo() const { return m_algo; } - inline int algoVariant() const { return m_algoVariant; } - inline int apiPort() const { return m_apiPort; } - inline int donateLevel() const { return m_donateLevel; } - inline int printTime() const { return m_printTime; } - inline int priority() const { return m_priority; } - inline int retries() const { return m_retries; } - inline int retryPause() const { return m_retryPause; } - inline int threads() const { return m_threads; } - inline int64_t affinity() const { return m_affinity; } - inline void setColors(bool colors) { m_colors = colors; } - - inline static void release() { delete m_self; } - - const char *algoName() const; - -private: - Options(int argc, char **argv); - ~Options(); - - inline bool isReady() const { return m_ready; } - - static Options *m_self; - - bool getJSON(const char *fileName, rapidjson::Document &doc); - bool parseArg(int key, const char *arg); - bool parseArg(int key, uint64_t arg); - bool parseBoolean(int key, bool enable); - Url *parseUrl(const char *arg) const; - void adjust(); - void parseConfig(const char *fileName); - void parseJSON(const struct option *option, const rapidjson::Value &object); - void showUsage(int status) const; - void showVersion(void); - - bool setAlgo(const char *algo); - - int getAlgoVariant() const; -# ifndef XMRIG_NO_AEON - int getAlgoVariantLite() const; -# endif - - bool m_background; - bool m_colors; - bool m_doubleHash; - bool m_dryRun; - bool m_hugePages; - bool m_ready; - bool m_safe; - bool m_syslog; - char *m_apiToken; - char *m_apiWorkerId; - char *m_logFile; - char *m_userAgent; - int m_algo; - int m_algoVariant; - int m_apiPort; - int m_donateLevel; - int m_maxCpuUsage; - int m_printTime; - int m_priority; - int m_retries; - int m_retryPause; - int m_threads; - int64_t m_affinity; - std::vector m_pools; -}; - -#endif /* __OPTIONS_H__ */ diff --git a/src/Summary.cpp b/src/Summary.cpp index 2d93f429..6aa42b74 100644 --- a/src/Summary.cpp +++ b/src/Summary.cpp @@ -4,8 +4,8 @@ * Copyright 2014 Lucas Jones * Copyright 2014-2016 Wolf9466 * Copyright 2016 Jay D Dee - * Copyright 2016-2017 XMRig - * + * 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 @@ -27,16 +27,17 @@ #include +#include "core/Config.h" +#include "core/Controller.h" #include "Cpu.h" #include "log/Log.h" #include "Mem.h" #include "net/Url.h" -#include "Options.h" #include "Summary.h" #include "version.h" -static void print_versions() +static void print_versions(xmrig::Config *config) { char buf[16]; @@ -51,13 +52,13 @@ static void print_versions() # endif - Log::i()->text(Options::i()->colors() ? "\x1B[01;32m * \x1B[01;37mVERSIONS: \x1B[01;36mXMRig/%s\x1B[01;37m libuv/%s%s" : " * VERSIONS: XMRig/%s libuv/%s%s", + Log::i()->text(config->isColors() ? "\x1B[01;32m * \x1B[01;37mVERSIONS: \x1B[01;36mXMRig/%s\x1B[01;37m libuv/%s%s" : " * VERSIONS: XMRig/%s libuv/%s%s", APP_VERSION, uv_version_string(), buf); } -static void print_memory() { - if (Options::i()->colors()) { +static void print_memory(xmrig::Config *config) { + if (config->isColors()) { Log::i()->text("\x1B[01;32m * \x1B[01;37mHUGE PAGES: %s, %s", Mem::isHugepagesAvailable() ? "\x1B[01;32mavailable" : "\x1B[01;31munavailable", Mem::isHugepagesEnabled() ? "\x1B[01;32menabled" : "\x1B[01;31mdisabled"); @@ -68,9 +69,9 @@ static void print_memory() { } -static void print_cpu() +static void print_cpu(xmrig::Config *config) { - if (Options::i()->colors()) { + if (config->isColors()) { Log::i()->text("\x1B[01;32m * \x1B[01;37mCPU: %s (%d) %sx64 %sAES-NI", Cpu::brand(), Cpu::sockets(), @@ -89,32 +90,32 @@ static void print_cpu() } -static void print_threads() +static void print_threads(xmrig::Config *config) { char buf[32]; - if (Options::i()->affinity() != -1L) { - snprintf(buf, 32, ", affinity=0x%" PRIX64, Options::i()->affinity()); + if (config->affinity() != -1L) { + snprintf(buf, 32, ", affinity=0x%" PRIX64, config->affinity()); } else { buf[0] = '\0'; } - Log::i()->text(Options::i()->colors() ? "\x1B[01;32m * \x1B[01;37mTHREADS: \x1B[01;36m%d\x1B[01;37m, %s, av=%d, %sdonate=%d%%%s" : " * THREADS: %d, %s, av=%d, %sdonate=%d%%%s", - Options::i()->threads(), - Options::i()->algoName(), - Options::i()->algoVariant(), - Options::i()->colors() && Options::i()->donateLevel() == 0 ? "\x1B[01;31m" : "", - Options::i()->donateLevel(), + Log::i()->text(config->isColors() ? "\x1B[01;32m * \x1B[01;37mTHREADS: \x1B[01;36m%d\x1B[01;37m, %s, av=%d, %sdonate=%d%%%s" : " * THREADS: %d, %s, av=%d, %sdonate=%d%%%s", + config->threads(), + config->algoName(), + config->algoVariant(), + config->isColors() && config->donateLevel() == 0 ? "\x1B[01;31m" : "", + config->donateLevel(), buf); } -static void print_pools() +static void print_pools(xmrig::Config *config) { - const std::vector &pools = Options::i()->pools(); + const std::vector &pools = config->pools(); for (size_t i = 0; i < pools.size(); ++i) { - Log::i()->text(Options::i()->colors() ? "\x1B[01;32m * \x1B[01;37mPOOL #%d: \x1B[01;36m%s:%d" : " * POOL #%d: %s:%d", + Log::i()->text(config->isColors() ? "\x1B[01;32m * \x1B[01;37mPOOL #%d: \x1B[01;36m%s:%d" : " * POOL #%d: %s:%d", i + 1, pools[i]->host(), pools[i]->port()); @@ -129,20 +130,22 @@ static void print_pools() #ifndef XMRIG_NO_API -static void print_api() +static void print_api(xmrig::Config *config) { - if (Options::i()->apiPort() == 0) { + const int port = config->apiPort(); + if (port == 0) { return; } - Log::i()->text(Options::i()->colors() ? "\x1B[01;32m * \x1B[01;37mAPI PORT: \x1B[01;36m%d" : " * API PORT: %d", Options::i()->apiPort()); + Log::i()->text(config->isColors() ? "\x1B[01;32m * \x1B[01;37mAPI BIND: \x1B[01;36m%s:%d" : " * API BIND: %s:%d", + config->isApiIPv6() ? "[::]" : "0.0.0.0", port); } #endif -static void print_commands() +static void print_commands(xmrig::Config *config) { - if (Options::i()->colors()) { + if (config->isColors()) { Log::i()->text("\x1B[01;32m * \x1B[01;37mCOMMANDS: \x1B[01;35mh\x1B[01;37mashrate, \x1B[01;35mp\x1B[01;37mause, \x1B[01;35mr\x1B[01;37mesume"); } else { @@ -151,19 +154,19 @@ static void print_commands() } -void Summary::print() +void Summary::print(xmrig::Controller *controller) { - print_versions(); - print_memory(); - print_cpu(); - print_threads(); - print_pools(); + print_versions(controller->config()); + print_memory(controller->config()); + print_cpu(controller->config()); + print_threads(controller->config()); + print_pools(controller->config()); # ifndef XMRIG_NO_API - print_api(); + print_api(controller->config()); # endif - print_commands(); + print_commands(controller->config()); } diff --git a/src/Summary.h b/src/Summary.h index 3f64fd60..f07dba35 100644 --- a/src/Summary.h +++ b/src/Summary.h @@ -4,8 +4,8 @@ * Copyright 2014 Lucas Jones * Copyright 2014-2016 Wolf9466 * Copyright 2016 Jay D Dee - * Copyright 2016-2017 XMRig - * + * 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 @@ -25,10 +25,15 @@ #define __SUMMARY_H__ +namespace xmrig { + class Controller; +} + + class Summary { public: - static void print(); + static void print(xmrig::Controller *controller); }; diff --git a/src/api/ApiRouter.cpp b/src/api/ApiRouter.cpp index 6ee8e7a4..e1ba9e17 100644 --- a/src/api/ApiRouter.cpp +++ b/src/api/ApiRouter.cpp @@ -35,14 +35,15 @@ #include "api/ApiRouter.h" #include "api/HttpReply.h" #include "api/HttpRequest.h" +#include "core/Config.h" +#include "core/Controller.h" #include "Cpu.h" #include "Mem.h" #include "net/Job.h" -#include "Options.h" #include "Platform.h" #include "rapidjson/document.h" -#include "rapidjson/stringbuffer.h" #include "rapidjson/prettywriter.h" +#include "rapidjson/stringbuffer.h" #include "version.h" #include "workers/Hashrate.h" @@ -66,13 +67,13 @@ static inline double normalize(double d) ApiRouter::ApiRouter(xmrig::Controller *controller) : m_controller(controller) { - m_threads = Options::i()->threads(); + m_threads = controller->config()->threads(); m_hashrate = new double[m_threads * 3](); memset(m_totalHashrate, 0, sizeof(m_totalHashrate)); memset(m_workerId, 0, sizeof(m_workerId)); - setWorkerId(Options::i()->apiWorkerId()); + setWorkerId(controller->config()->apiWorkerId()); genId(); } @@ -88,6 +89,17 @@ void ApiRouter::ApiRouter::get(const xmrig::HttpRequest &req, xmrig::HttpReply & rapidjson::Document doc; doc.SetObject(); + if (req.match("/1/config")) { + if (req.isRestricted()) { + reply.status = 403; + return; + } + + m_controller->config()->getJSON(doc); + + return finalize(reply, doc); + } + getIdentify(doc); getMiner(doc); getHashrate(doc); @@ -100,10 +112,10 @@ void ApiRouter::ApiRouter::get(const xmrig::HttpRequest &req, xmrig::HttpReply & void ApiRouter::exec(const xmrig::HttpRequest &req, xmrig::HttpReply &reply) { -// if (req.method() == xmrig::HttpRequest::Put && req.match("/1/config")) { -// m_controller->config()->reload(req.body()); -// return; -// } + if (req.method() == xmrig::HttpRequest::Put && req.match("/1/config")) { + m_controller->config()->reload(req.body()); + return; + } reply.status = 404; } @@ -246,9 +258,9 @@ void ApiRouter::getMiner(rapidjson::Document &doc) const doc.AddMember("kind", APP_KIND, allocator); doc.AddMember("ua", rapidjson::StringRef(Platform::userAgent()), allocator); doc.AddMember("cpu", cpu, allocator); - doc.AddMember("algo", rapidjson::StringRef(Options::i()->algoName()), allocator); + doc.AddMember("algo", rapidjson::StringRef(m_controller->config()->algoName()), allocator); doc.AddMember("hugepages", Mem::isHugepagesEnabled(), allocator); - doc.AddMember("donate_level", Options::i()->donateLevel(), allocator); + doc.AddMember("donate_level", m_controller->config()->donateLevel(), allocator); } diff --git a/src/core/CommonConfig.cpp b/src/core/CommonConfig.cpp new file mode 100644 index 00000000..ea17342c --- /dev/null +++ b/src/core/CommonConfig.cpp @@ -0,0 +1,382 @@ +/* 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_syslog(false), + m_watch(false), // TODO: enable config file watch by default when this feature propertly handled and tested. + 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 00000000..ab840a48 --- /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 00000000..ec7e5de1 --- /dev/null +++ b/src/core/Config.cpp @@ -0,0 +1,342 @@ +/* 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 "core/Config.h" +#include "core/ConfigCreator.h" +#include "core/ConfigLoader.h" +#include "Cpu.h" +#include "net/Url.h" +#include "rapidjson/document.h" +#include "rapidjson/filewritestream.h" +#include "rapidjson/prettywriter.h" +#include "xmrig.h" + + +static char affinity_tmp[20] = { 0 }; + + +xmrig::Config::Config() : xmrig::CommonConfig(), + m_doubleHash(false), + m_dryRun(false), + m_hugePages(true), + m_safe(false), + 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("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("av", algoVariant(), allocator); + doc.AddMember("background", isBackground(), allocator); + + doc.AddMember("colors", isColors(), allocator); + + if (affinity() != -1L) { + snprintf(affinity_tmp, sizeof(affinity_tmp) - 1, "0x%" PRIX64, affinity()); + doc.AddMember("cpu-affinity", rapidjson::StringRef(affinity_tmp), allocator); + } + else { + doc.AddMember("cpu-affinity", rapidjson::kNullType, allocator); + } + + if (priority() != -1) { + doc.AddMember("cpu-priority", priority(), allocator); + } + else { + doc.AddMember("cpu-priority", rapidjson::kNullType, allocator); + } + + doc.AddMember("donate-level", donateLevel(), allocator); + doc.AddMember("huge-pages", isHugePages(), allocator); + doc.AddMember("log-file", logFile() ? rapidjson::Value(rapidjson::StringRef(logFile())).Move() : rapidjson::Value(rapidjson::kNullType).Move(), allocator); + doc.AddMember("max-cpu-usage", m_maxCpuUsage, 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); + + if (url->keepAlive() == 0 || url->keepAlive() == Url::kKeepAliveTimeout) { + obj.AddMember("keepalive", url->keepAlive() > 0, allocator); + } + else { + obj.AddMember("keepalive", url->keepAlive(), allocator); + } + + obj.AddMember("nicehash", url->isNicehash(), allocator); + obj.AddMember("variant", url->variant(), allocator); + + pools.PushBack(obj, allocator); + } + + doc.AddMember("pools", pools, allocator); + doc.AddMember("print-time", printTime(), allocator); + doc.AddMember("retries", retries(), allocator); + doc.AddMember("retry-pause", retryPause(), allocator); + doc.AddMember("safe", m_safe, allocator); + doc.AddMember("threads", threads(), 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("watch", m_watch, 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_algorithm, m_doubleHash, m_maxCpuUsage); + } + else if (m_safe) { + const int count = Cpu::optimalThreadsCount(m_algorithm, 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_algorithm == 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 00000000..110c61a7 --- /dev/null +++ b/src/core/Config.h @@ -0,0 +1,120 @@ +/* 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 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_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 00000000..fcc6c596 --- /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 00000000..1dec4eca --- /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 00000000..64638af3 --- /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 00000000..68eef639 --- /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::ThreadsKey }, + { "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 00000000..b934b52b --- /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 00000000..74526e90 --- /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 af8a27d5..805861ef 100644 --- a/src/core/Controller.cpp +++ b/src/core/Controller.cpp @@ -22,15 +22,19 @@ */ -//#include "core/Config.h" -//#include "core/ConfigLoader.h" +#include + + +#include "core/Config.h" +#include "core/ConfigLoader.h" #include "core/Controller.h" +#include "Cpu.h" +#include "interfaces/IControllerListener.h" #include "log/ConsoleLog.h" #include "log/FileLog.h" #include "log/Log.h" +#include "net/Network.h" #include "Platform.h" -//#include "proxy/Proxy.h" -#include "interfaces/IControllerListener.h" #ifdef HAVE_SYSLOG_H @@ -42,18 +46,21 @@ class xmrig::ControllerPrivate { public: inline ControllerPrivate() : + network(nullptr), config(nullptr) {} inline ~ControllerPrivate() { -// delete config; + delete network; + delete config; } - xmrig::Config *config; + Network *network; std::vector listeners; + xmrig::Config *config; }; @@ -65,61 +72,81 @@ xmrig::Controller::Controller() xmrig::Controller::~Controller() { -// ConfigLoader::release(); + ConfigLoader::release(); + Platform::release(); delete d_ptr; } +bool xmrig::Controller::isReady() const +{ + return d_ptr->config && d_ptr->network; +} + + xmrig::Config *xmrig::Controller::config() const { + assert(d_ptr->config != nullptr); + return d_ptr->config; } int xmrig::Controller::init(int argc, char **argv) { -// d_ptr->config = xmrig::Config::load(argc, argv, this); -// if (!d_ptr->config) { -// return 1; -// } + Cpu::init(); -// Log::init(); -// Platform::init(config()->userAgent()); + d_ptr->config = xmrig::Config::load(argc, argv, this); + if (!d_ptr->config) { + return 1; + } -// if (!config()->background()) { -// Log::add(new ConsoleLog(this)); -// } + Log::init(); + Platform::init(config()->userAgent()); + Platform::setProcessPriority(d_ptr->config->priority()); -// if (config()->logFile()) { -// Log::add(new FileLog(config()->logFile())); -// } + if (!config()->isBackground()) { + Log::add(new ConsoleLog(this)); + } -//# ifdef HAVE_SYSLOG_H -// if (config()->syslog()) { -// Log::add(new SysLog()); -// } -//# endif + if (config()->logFile()) { + Log::add(new FileLog(config()->logFile())); + } -// d_ptr->proxy = new Proxy(this); +# ifdef HAVE_SYSLOG_H + if (config()->isSyslog()) { + Log::add(new SysLog()); + } +# endif + + d_ptr->network = new Network(this); return 0; } +Network *xmrig::Controller::network() const +{ + assert(d_ptr->network != nullptr); + + return d_ptr->network; +} + + void xmrig::Controller::addListener(IControllerListener *listener) { d_ptr->listeners.push_back(listener); } -void xmrig::Controller::onNewConfig(Config *config) +void xmrig::Controller::onNewConfig(IConfig *config) { -// xmrig::Config *previousConfig = d_ptr->config; -// d_ptr->config = config; + Config *previousConfig = d_ptr->config; + d_ptr->config = static_cast(config); -// for (xmrig::IControllerListener *listener : d_ptr->listeners) { -// listener->onConfigChanged(config, previousConfig); -// } + for (xmrig::IControllerListener *listener : d_ptr->listeners) { + listener->onConfigChanged(d_ptr->config, previousConfig); + } -// delete previousConfig; + delete previousConfig; } diff --git a/src/core/Controller.h b/src/core/Controller.h index 2fe37c15..25f91843 100644 --- a/src/core/Controller.h +++ b/src/core/Controller.h @@ -28,7 +28,7 @@ #include "interfaces/IWatcherListener.h" -class Proxy; +class Network; class StatsData; @@ -46,13 +46,14 @@ public: Controller(); ~Controller(); + bool isReady() const; Config *config() const; int init(int argc, char **argv); - Proxy *proxy() const; + Network *network() const; void addListener(IControllerListener *listener); protected: - void onNewConfig(Config *config) override; + void onNewConfig(IConfig *config) override; private: ControllerPrivate *d_ptr; diff --git a/src/crypto/CryptoNight.cpp b/src/crypto/CryptoNight.cpp index b605bfb8..c9a2e499 100644 --- a/src/crypto/CryptoNight.cpp +++ b/src/crypto/CryptoNight.cpp @@ -35,7 +35,6 @@ #include "crypto/CryptoNight_test.h" #include "net/Job.h" #include "net/JobResult.h" -#include "Options.h" #include "xmrig.h" @@ -131,7 +130,7 @@ bool CryptoNight::hash(const Job &job, JobResult &result, cryptonight_ctx *ctx) } -bool CryptoNight::init(int algo, int variant) +bool CryptoNight::init(int algo, int variant, bool doubleHash) { if (variant < 1 || variant > 4) { return false; @@ -145,7 +144,7 @@ bool CryptoNight::init(int algo, int variant) cryptonight_hash_ctx = cryptonight_variations[index]; - return selfTest(algo); + return selfTest(algo, doubleHash); } @@ -155,7 +154,7 @@ void CryptoNight::hash(const uint8_t *input, size_t size, uint8_t *output, crypt } -bool CryptoNight::selfTest(int algo) { +bool CryptoNight::selfTest(int algo, bool doubleHash) { if (cryptonight_hash_ctx == nullptr) { return false; } @@ -167,8 +166,6 @@ bool CryptoNight::selfTest(int algo) { cryptonight_hash_ctx(test_input, 76, output, ctx, 0); - const bool doubleHash = Options::i()->doubleHash(); - # ifndef XMRIG_NO_AEON bool rc = memcmp(output, algo == xmrig::ALGO_CRYPTONIGHT_LITE ? test_output_v0_lite : test_output_v0, (doubleHash ? 64 : 32)) == 0; # else diff --git a/src/crypto/CryptoNight.h b/src/crypto/CryptoNight.h index 13e9c8e8..eb17719e 100644 --- a/src/crypto/CryptoNight.h +++ b/src/crypto/CryptoNight.h @@ -54,11 +54,11 @@ class CryptoNight { public: static bool hash(const Job &job, JobResult &result, cryptonight_ctx *ctx); - static bool init(int algo, int variant); + static bool init(int algo, int variant, bool doubleHash); static void hash(const uint8_t *input, size_t size, uint8_t *output, cryptonight_ctx *ctx, int variant); private: - static bool selfTest(int algo); + static bool selfTest(int algo, bool doubleHash); }; #endif /* __CRYPTONIGHT_H__ */ diff --git a/src/donate.h b/src/donate.h index e8230b87..bdf7a00d 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 00000000..89aa6217 --- /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 00000000..597a6b74 --- /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 da30b1fd..bfafb9a0 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/log/ConsoleLog.cpp b/src/log/ConsoleLog.cpp index 3656d48c..eeed7355 100644 --- a/src/log/ConsoleLog.cpp +++ b/src/log/ConsoleLog.cpp @@ -4,8 +4,8 @@ * Copyright 2014 Lucas Jones * Copyright 2014-2016 Wolf9466 * Copyright 2016 Jay D Dee - * Copyright 2016-2017 XMRig - * + * 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 @@ -34,18 +34,18 @@ #endif +#include "core/Config.h" +#include "core/Controller.h" #include "log/ConsoleLog.h" #include "log/Log.h" -#include "Options.h" -ConsoleLog::ConsoleLog(bool colors) : - m_colors(colors), - m_stream(nullptr) +ConsoleLog::ConsoleLog(xmrig::Controller *controller) : + m_stream(nullptr), + m_controller(controller) { if (uv_tty_init(uv_default_loop(), &m_tty, 1, 0) < 0) { - Options::i()->setColors(false); - m_colors = false; + controller->config()->setColors(false); return; } @@ -78,7 +78,9 @@ void ConsoleLog::message(int level, const char* fmt, va_list args) # endif const char* color = nullptr; - if (m_colors) { + const bool colors = m_controller->config()->isColors(); + + if (colors) { switch (level) { case Log::ERR: color = Log::kCL_RED; @@ -109,9 +111,9 @@ void ConsoleLog::message(int level, const char* fmt, va_list args) stime.tm_hour, stime.tm_min, stime.tm_sec, - m_colors ? color : "", + colors ? color : "", fmt, - m_colors ? Log::kCL_N : "" + colors ? Log::kCL_N : "" ); print(args); @@ -120,7 +122,7 @@ void ConsoleLog::message(int level, const char* fmt, va_list args) void ConsoleLog::text(const char* fmt, va_list args) { - snprintf(m_fmt, sizeof(m_fmt) - 1, "%s%s\n", fmt, m_colors ? Log::kCL_N : ""); + snprintf(m_fmt, sizeof(m_fmt) - 1, "%s%s\n", fmt, m_controller->config()->isColors() ? Log::kCL_N : ""); print(args); } diff --git a/src/log/ConsoleLog.h b/src/log/ConsoleLog.h index a04a27c5..6649be84 100644 --- a/src/log/ConsoleLog.h +++ b/src/log/ConsoleLog.h @@ -4,8 +4,8 @@ * Copyright 2014 Lucas Jones * Copyright 2014-2016 Wolf9466 * Copyright 2016 Jay D Dee - * Copyright 2016-2017 XMRig - * + * 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 @@ -31,10 +31,15 @@ #include "interfaces/ILogBackend.h" +namespace xmrig { + class Controller; +} + + class ConsoleLog : public ILogBackend { public: - ConsoleLog(bool colors); + ConsoleLog(xmrig::Controller *controller); void message(int level, const char *fmt, va_list args) override; void text(const char *fmt, va_list args) override; @@ -43,12 +48,12 @@ private: bool isWritable() const; void print(va_list args); - bool m_colors; char m_buf[512]; char m_fmt[256]; uv_buf_t m_uvBuf; uv_stream_t *m_stream; uv_tty_t m_tty; + xmrig::Controller *m_controller; }; #endif /* __CONSOLELOG_H__ */ diff --git a/src/net/Client.cpp b/src/net/Client.cpp index c8a93f24..ec9dc863 100644 --- a/src/net/Client.cpp +++ b/src/net/Client.cpp @@ -52,6 +52,7 @@ int64_t Client::m_sequence = 1; +xmrig::Storage Client::m_storage; Client::Client(int id, const char *agent, IClientListener *listener) : @@ -67,13 +68,17 @@ Client::Client(int id, const char *agent, IClientListener *listener) : m_state(UnconnectedState), m_expire(0), m_jobs(0), + m_keepAlive(0), + m_key(0), m_stream(nullptr), m_socket(nullptr) { + m_key = m_storage.add(this); + memset(m_ip, 0, sizeof(m_ip)); memset(&m_hints, 0, sizeof(m_hints)); - m_resolver.data = this; + m_resolver.data = m_storage.ptr(m_key); m_hints.ai_family = AF_UNSPEC; m_hints.ai_socktype = SOCK_STREAM; @@ -81,11 +86,6 @@ Client::Client(int id, const char *agent, IClientListener *listener) : m_recvBuf.base = m_buf; m_recvBuf.len = sizeof(m_buf); - -# ifndef XMRIG_PROXY_PROJECT - m_keepAliveTimer.data = this; - uv_timer_init(uv_default_loop(), &m_keepAliveTimer); -# endif } @@ -121,8 +121,13 @@ void Client::deleteLater() m_listener = nullptr; - if (!disconnect()) { - delete this; + if (state() == HostLookupState) { + uv_cancel(reinterpret_cast(&m_resolver)); + return; + } + + if (!disconnect() && m_state != ClosingState) { + m_storage.remove(m_key); } } @@ -139,17 +144,17 @@ void Client::setUrl(const Url *url) void Client::tick(uint64_t now) { - if (m_expire == 0 || now < m_expire) { - return; - } - if (m_state == ConnectedState) { - LOG_DEBUG_ERR("[%s:%u] timeout", m_url.host(), m_url.port()); - close(); + if (m_expire && now > m_expire) { + LOG_DEBUG_ERR("[%s:%u] timeout", m_url.host(), m_url.port()); + close(); + } + else if (m_keepAlive && now > m_keepAlive) { + ping(); + } } - - if (m_state == ConnectingState) { + if (m_expire && now > m_expire && m_state == ConnectingState) { connect(); } } @@ -157,12 +162,9 @@ void Client::tick(uint64_t now) bool Client::disconnect() { -# ifndef XMRIG_PROXY_PROJECT - uv_timer_stop(&m_keepAliveTimer); -# endif - - m_expire = 0; - m_failures = -1; + m_keepAlive = 0; + m_expire = 0; + m_failures = -1; return close(); } @@ -404,10 +406,10 @@ void Client::connect(sockaddr *addr) delete m_socket; uv_connect_t *req = new uv_connect_t; - req->data = this; + req->data = m_storage.ptr(m_key); m_socket = new uv_tcp_t; - m_socket->data = this; + m_socket->data = m_storage.ptr(m_key); uv_tcp_init(uv_default_loop(), m_socket); uv_tcp_nodelay(m_socket, 1); @@ -567,7 +569,7 @@ void Client::parseResponse(int64_t id, const rapidjson::Value &result, const rap LOG_ERR("[%s:%u] error: \"%s\", code: %d", m_url.host(), m_url.port(), message, error["code"].GetInt()); } - if (id == 1 || isCriticalError(message)) { + if (isCriticalError(message)) { close(); } @@ -613,18 +615,13 @@ void Client::ping() void Client::reconnect() { if (!m_listener) { - delete this; + m_storage.remove(m_key); return; } setState(ConnectingState); - -# ifndef XMRIG_PROXY_PROJECT - if (m_url.isKeepAlive()) { - uv_timer_stop(&m_keepAliveTimer); - } -# endif + m_keepAlive = 0; if (m_failures == -1) { return m_listener->onClose(this, -1); @@ -653,13 +650,9 @@ void Client::startTimeout() { m_expire = 0; -# ifndef XMRIG_PROXY_PROJECT - if (!m_url.isKeepAlive()) { - return; + if (m_url.keepAlive()) { + m_keepAlive = uv_now(uv_default_loop()) + (m_url.keepAlive() * 1000); } - - uv_timer_start(&m_keepAliveTimer, [](uv_timer_t *handle) { getClient(handle->data)->ping(); }, kKeepAliveTimeout, 0); -# endif } @@ -690,6 +683,7 @@ void Client::onConnect(uv_connect_t *req, int status) { auto client = getClient(req->data); if (!client) { + delete req; return; } @@ -735,6 +729,11 @@ void Client::onRead(uv_stream_t *stream, ssize_t nread, const uv_buf_t *buf) return; } + assert(client->m_listener != nullptr); + if (!client->m_listener) { + return client->reconnect(); + } + client->m_recvBufPos += nread; char* end; @@ -771,6 +770,11 @@ void Client::onResolved(uv_getaddrinfo_t *req, int status, struct addrinfo *res) return; } + assert(client->m_listener != nullptr); + if (!client->m_listener) { + return client->reconnect(); + } + if (status < 0) { if (!client->m_quiet) { LOG_ERR("[%s:%u] DNS error: \"%s\"", client->m_url.host(), client->m_url.port(), uv_strerror(status)); diff --git a/src/net/Client.h b/src/net/Client.h index fff7a156..fc0335c6 100644 --- a/src/net/Client.h +++ b/src/net/Client.h @@ -32,6 +32,7 @@ #include "net/Id.h" #include "net/Job.h" +#include "net/Storage.h" #include "net/SubmitResult.h" #include "net/Url.h" #include "rapidjson/fwd.h" @@ -53,9 +54,9 @@ public: }; constexpr static int kResponseTimeout = 20 * 1000; - constexpr static int kKeepAliveTimeout = 60 * 1000; Client(int id, const char *agent, IClientListener *listener); + ~Client(); bool disconnect(); int64_t submit(const JobResult &result); @@ -76,8 +77,6 @@ public: inline void setRetryPause(int ms) { m_retryPause = ms; } private: - ~Client(); - bool close(); bool isCriticalError(const char *message); bool parseJob(const rapidjson::Value ¶ms, int *code); @@ -103,7 +102,7 @@ private: static void onRead(uv_stream_t *stream, ssize_t nread, const uv_buf_t *buf); static void onResolved(uv_getaddrinfo_t *req, int status, struct addrinfo *res); - static inline Client *getClient(void *data) { return static_cast(data); } + static inline Client *getClient(void *data) { return m_storage.get(data); } addrinfo m_hints; bool m_ipv6; @@ -120,10 +119,11 @@ private: Job m_job; size_t m_recvBufPos; SocketState m_state; - static int64_t m_sequence; std::map m_results; uint64_t m_expire; uint64_t m_jobs; + uint64_t m_keepAlive; + uintptr_t m_key; Url m_url; uv_buf_t m_recvBuf; uv_getaddrinfo_t m_resolver; @@ -131,9 +131,8 @@ private: uv_tcp_t *m_socket; xmrig::Id m_rpcId; -# ifndef XMRIG_PROXY_PROJECT - uv_timer_t m_keepAliveTimer; -# endif + static int64_t m_sequence; + static xmrig::Storage m_storage; }; diff --git a/src/net/Network.cpp b/src/net/Network.cpp index ede3f8b4..a8e60efa 100644 --- a/src/net/Network.cpp +++ b/src/net/Network.cpp @@ -39,29 +39,30 @@ #include "net/strategies/SinglePoolStrategy.h" #include "net/SubmitResult.h" #include "net/Url.h" -#include "Options.h" #include "workers/Workers.h" +#include "core/Controller.h" +#include "core/Config.h" -Network::Network(const Options *options) : - m_options(options), - m_donate(nullptr) +Network::Network(xmrig::Controller *controller) : + m_donate(nullptr), + m_controller(controller) { srand(time(0) ^ (uintptr_t) this); Workers::setListener(this); - const std::vector &pools = options->pools(); + const std::vector &pools = controller->config()->pools(); if (pools.size() > 1) { - m_strategy = new FailoverStrategy(pools, options->retryPause(), options->retries(), this); + m_strategy = new FailoverStrategy(pools, controller->config()->retryPause(), controller->config()->retries(), this); } else { - m_strategy = new SinglePoolStrategy(pools.front(), options->retryPause(), this); + m_strategy = new SinglePoolStrategy(pools.front(), controller->config()->retryPause(), this); } - if (m_options->donateLevel() > 0) { - m_donate = new DonateStrategy(options->donateLevel(), options->pools().front()->user(), options->algo(), this); + if (controller->config()->donateLevel() > 0) { + m_donate = new DonateStrategy(controller->config()->donateLevel(), controller->config()->pools().front()->user(), controller->config()->algorithm(), this); } m_timer.data = this; @@ -101,7 +102,7 @@ void Network::onActive(IStrategy *strategy, Client *client) m_state.setPool(client->host(), client->port(), client->ip()); - LOG_INFO(m_options->colors() ? "\x1B[01;37muse pool \x1B[01;36m%s:%d \x1B[01;30m%s" : "use pool %s:%d %s", client->host(), client->port(), client->ip()); + LOG_INFO(isColors() ? "\x1B[01;37muse pool \x1B[01;36m%s:%d \x1B[01;30m%s" : "use pool %s:%d %s", client->host(), client->port(), client->ip()); } @@ -146,21 +147,27 @@ void Network::onResultAccepted(IStrategy *strategy, Client *client, const Submit m_state.add(result, error); if (error) { - LOG_INFO(m_options->colors() ? "\x1B[01;31mrejected\x1B[0m (%" PRId64 "/%" PRId64 ") diff \x1B[01;37m%u\x1B[0m \x1B[31m\"%s\"\x1B[0m \x1B[01;30m(%" PRIu64 " ms)" - : "rejected (%" PRId64 "/%" PRId64 ") diff %u \"%s\" (%" PRIu64 " ms)", + LOG_INFO(isColors() ? "\x1B[01;31mrejected\x1B[0m (%" PRId64 "/%" PRId64 ") diff \x1B[01;37m%u\x1B[0m \x1B[31m\"%s\"\x1B[0m \x1B[01;30m(%" PRIu64 " ms)" + : "rejected (%" PRId64 "/%" PRId64 ") diff %u \"%s\" (%" PRIu64 " ms)", m_state.accepted, m_state.rejected, result.diff, error, result.elapsed); } else { - LOG_INFO(m_options->colors() ? "\x1B[01;32maccepted\x1B[0m (%" PRId64 "/%" PRId64 ") diff \x1B[01;37m%u\x1B[0m \x1B[01;30m(%" PRIu64 " ms)" - : "accepted (%" PRId64 "/%" PRId64 ") diff %u (%" PRIu64 " ms)", + LOG_INFO(isColors() ? "\x1B[01;32maccepted\x1B[0m (%" PRId64 "/%" PRId64 ") diff \x1B[01;37m%u\x1B[0m \x1B[01;30m(%" PRIu64 " ms)" + : "accepted (%" PRId64 "/%" PRId64 ") diff %u (%" PRIu64 " ms)", m_state.accepted, m_state.rejected, result.diff, result.elapsed); } } +bool Network::isColors() const +{ + return m_controller->config()->isColors(); +} + + void Network::setJob(Client *client, const Job &job, bool donate) { - if (m_options->colors()) { + if (isColors()) { LOG_INFO("\x1B[01;35mnew job\x1B[0m from \x1B[01;37m%s:%d\x1B[0m diff \x1B[01;37m%d", client->host(), client->port(), job.diff()); } else { diff --git a/src/net/Network.h b/src/net/Network.h index fae5c563..353edc77 100644 --- a/src/net/Network.h +++ b/src/net/Network.h @@ -35,14 +35,18 @@ class IStrategy; -class Options; class Url; +namespace xmrig { + class Controller; +} + + class Network : public IJobResultListener, public IStrategyListener { public: - Network(const Options *options); + Network(xmrig::Controller *controller); ~Network(); void connect(); @@ -58,16 +62,17 @@ protected: private: constexpr static int kTickInterval = 1 * 1000; + bool isColors() const; void setJob(Client *client, const Job &job, bool donate); void tick(); static void onTick(uv_timer_t *handle); - const Options *m_options; IStrategy *m_donate; IStrategy *m_strategy; NetworkState m_state; uv_timer_t m_timer; + xmrig::Controller *m_controller; }; diff --git a/src/net/Storage.h b/src/net/Storage.h new file mode 100644 index 00000000..105547ec --- /dev/null +++ b/src/net/Storage.h @@ -0,0 +1,97 @@ +/* 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 __STORAGE_H__ +#define __STORAGE_H__ + + +#include +#include + +#include "log/Log.h" + + +namespace xmrig { + + +template +class Storage +{ +public: + inline Storage() : + m_counter(0) + { + } + + + inline uintptr_t add(TYPE *ptr) + { + m_data[m_counter] = ptr; + + return m_counter++; + } + + + inline static void *ptr(uintptr_t id) { return reinterpret_cast(id); } + + + inline TYPE *get(void *id) const { return get(reinterpret_cast(id)); } + inline TYPE *get(uintptr_t id) const + { + assert(m_data.count(id) > 0); + + if (m_data.count(id) == 0) { + return nullptr; + } + + return m_data.at(id); + } + + + inline void remove(void *id) { remove(reinterpret_cast(id)); } + inline void remove(uintptr_t id) + { + TYPE *obj = get(id); + if (obj == nullptr) { + return; + } + + auto it = m_data.find(id); + if (it != m_data.end()) { + m_data.erase(it); + } + + delete obj; + } + + +private: + std::map m_data; + uint64_t m_counter; +}; + + +} /* namespace xmrig */ + + +#endif /* __STORAGE_H__ */ diff --git a/src/net/Url.cpp b/src/net/Url.cpp index c17ef690..8905e919 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 f861fec5..4c2c9435 100644 --- a/src/net/Url.h +++ b/src/net/Url.h @@ -34,22 +34,23 @@ 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 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 +68,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/workers/Hashrate.cpp b/src/workers/Hashrate.cpp index bd5b7df6..ef06eb52 100644 --- a/src/workers/Hashrate.cpp +++ b/src/workers/Hashrate.cpp @@ -4,8 +4,8 @@ * Copyright 2014 Lucas Jones * Copyright 2014-2016 Wolf9466 * Copyright 2016 Jay D Dee - * Copyright 2016-2017 XMRig - * + * 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 @@ -27,8 +27,10 @@ #include #include + +#include "core/Config.h" +#include "core/Controller.h" #include "log/Log.h" -#include "Options.h" #include "workers/Hashrate.h" @@ -43,9 +45,10 @@ inline const char *format(double h, char* buf, size_t size) } -Hashrate::Hashrate(int threads) : +Hashrate::Hashrate(int threads, xmrig::Controller *controller) : m_highest(0.0), - m_threads(threads) + m_threads(threads), + m_controller(controller) { m_counts = new uint64_t*[threads]; m_timestamps = new uint64_t*[threads]; @@ -60,7 +63,7 @@ Hashrate::Hashrate(int threads) : memset(m_timestamps[0], 0, sizeof(uint64_t) * kBucketSize); } - const int printTime = Options::i()->printTime(); + const int printTime = controller->config()->printTime(); if (printTime > 0) { uv_timer_init(uv_default_loop(), &m_timer); @@ -153,7 +156,7 @@ void Hashrate::print() char num3[8]; char num4[8]; - LOG_INFO(Options::i()->colors() ? "\x1B[01;37mspeed\x1B[0m 2.5s/60s/15m \x1B[01;36m%s \x1B[22;36m%s %s \x1B[01;36mH/s\x1B[0m max: \x1B[01;36m%s H/s" : "speed 2.5s/60s/15m %s %s %s H/s max: %s H/s", + LOG_INFO(m_controller->config()->isColors() ? "\x1B[01;37mspeed\x1B[0m 2.5s/60s/15m \x1B[01;36m%s \x1B[22;36m%s %s \x1B[01;36mH/s\x1B[0m max: \x1B[01;36m%s H/s" : "speed 2.5s/60s/15m %s %s %s H/s max: %s H/s", format(calc(ShortInterval), num1, sizeof(num1)), format(calc(MediumInterval), num2, sizeof(num2)), format(calc(LargeInterval), num3, sizeof(num3)), diff --git a/src/workers/Hashrate.h b/src/workers/Hashrate.h index 026c0cdf..5f4f0eaa 100644 --- a/src/workers/Hashrate.h +++ b/src/workers/Hashrate.h @@ -4,8 +4,8 @@ * Copyright 2014 Lucas Jones * Copyright 2014-2016 Wolf9466 * Copyright 2016 Jay D Dee - * Copyright 2016-2017 XMRig - * + * 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 @@ -29,6 +29,11 @@ #include +namespace xmrig { + class Controller; +} + + class Hashrate { public: @@ -38,7 +43,7 @@ public: LargeInterval = 900000 }; - Hashrate(int threads); + Hashrate(int threads, xmrig::Controller *controller); double calc(size_t ms) const; double calc(size_t threadId, size_t ms) const; void add(size_t threadId, uint64_t count, uint64_t timestamp); @@ -61,6 +66,7 @@ private: uint64_t** m_counts; uint64_t** m_timestamps; uv_timer_t m_timer; + xmrig::Controller *m_controller; }; diff --git a/src/workers/Workers.cpp b/src/workers/Workers.cpp index f0aef448..5642751a 100644 --- a/src/workers/Workers.cpp +++ b/src/workers/Workers.cpp @@ -4,8 +4,8 @@ * Copyright 2014 Lucas Jones * Copyright 2014-2016 Wolf9466 * Copyright 2016 Jay D Dee - * Copyright 2016-2017 XMRig - * + * 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 @@ -27,7 +27,6 @@ #include "api/Api.h" #include "interfaces/IJobResultListener.h" #include "Mem.h" -#include "Options.h" #include "workers/DoubleWorker.h" #include "workers/Handle.h" #include "workers/Hashrate.h" @@ -103,10 +102,10 @@ void Workers::setJob(const Job &job, bool donate) } -void Workers::start(int64_t affinity, int priority) +void Workers::start(int64_t affinity, int priority, xmrig::Controller *controller) { const int threads = Mem::threads(); - m_hashrate = new Hashrate(threads); + m_hashrate = new Hashrate(threads, controller); uv_mutex_init(&m_mutex); uv_rwlock_init(&m_rwlock); diff --git a/src/workers/Workers.h b/src/workers/Workers.h index 1c85089a..942a5b58 100644 --- a/src/workers/Workers.h +++ b/src/workers/Workers.h @@ -4,8 +4,8 @@ * Copyright 2014 Lucas Jones * Copyright 2014-2016 Wolf9466 * Copyright 2016 Jay D Dee - * Copyright 2016-2017 XMRig - * + * 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 @@ -39,6 +39,11 @@ class Hashrate; class IJobResultListener; +namespace xmrig { + class Controller; +} + + class Workers { public: @@ -46,7 +51,7 @@ public: static void printHashrate(bool detail); static void setEnabled(bool enabled); static void setJob(const Job &job, bool donate); - static void start(int64_t affinity, int priority); + static void start(int64_t affinity, int priority, xmrig::Controller *controller); static void stop(); static void submit(const JobResult &result); diff --git a/src/xmrig.h b/src/xmrig.h index 103e8a68..9cae73c7 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) */ };