mirror of
https://github.com/xmrig/xmrig.git
synced 2025-12-06 23:52:38 -05:00
Compare commits
66 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b6bf6d9bc9 | ||
|
|
3d9be9484d | ||
|
|
35fd43a6b4 | ||
|
|
294453fdc1 | ||
|
|
30a7f9f7f5 | ||
|
|
8f38462bbe | ||
|
|
ebf54c6d04 | ||
|
|
d7659b5093 | ||
|
|
e00c568ae9 | ||
|
|
a3988374f0 | ||
|
|
9732636155 | ||
|
|
986aee4297 | ||
|
|
66d3e96a1a | ||
|
|
9f4e1ee373 | ||
|
|
ff0c6b6365 | ||
|
|
7397efaf6d | ||
|
|
aadc15ce66 | ||
|
|
ad7c925a1a | ||
|
|
57be6f94bb | ||
|
|
35b188762c | ||
|
|
7c6e429854 | ||
|
|
c15aefd968 | ||
|
|
4a712354f1 | ||
|
|
4545c84a11 | ||
|
|
a66297bed8 | ||
|
|
f4dadfd90b | ||
|
|
955134b162 | ||
|
|
68795137da | ||
|
|
6ed2d61586 | ||
|
|
a96782218f | ||
|
|
32e7041def | ||
|
|
c16388ade3 | ||
|
|
72569a7fc7 | ||
|
|
751be470b8 | ||
|
|
7937c814ff | ||
|
|
8e42fb9138 | ||
|
|
dbc6f26c91 | ||
|
|
074db6bb72 | ||
|
|
71522214ae | ||
|
|
8ec58a8394 | ||
|
|
263634f585 | ||
|
|
a383eba8df | ||
|
|
152b65b67c | ||
|
|
970b5d1964 | ||
|
|
7536663caf | ||
|
|
7e17f77c11 | ||
|
|
25faeabd61 | ||
|
|
bd8776b7ee | ||
|
|
b2d26eb019 | ||
|
|
14c6f8699e | ||
|
|
c0dcfc2a97 | ||
|
|
f36b5eeaad | ||
|
|
952017ae7a | ||
|
|
faf793b0aa | ||
|
|
e97cd98f90 | ||
|
|
95002ead7d | ||
|
|
c1b3802590 | ||
|
|
1bfbc97c7d | ||
|
|
052290d0e9 | ||
|
|
4f512c41d4 | ||
|
|
91ed7e36cd | ||
|
|
77d9beaf89 | ||
|
|
a791bc113e | ||
|
|
9bfa49b7d0 | ||
|
|
9dc02fc7f3 | ||
|
|
6551818610 |
23
CHANGELOG.md
23
CHANGELOG.md
@@ -1,3 +1,26 @@
|
||||
# v2.1.0
|
||||
- [#40](https://github.com/xmrig/xmrig/issues/40) Improved miner shutdown, fixed crash on exit for Linux and OS X.
|
||||
- Fixed, login request was contain malformed JSON if username or password has some special characters for example `\`.
|
||||
- [#220](https://github.com/fireice-uk/xmr-stak-cpu/pull/220) Better support for Round Robin DNS, IP address now always chosen randomly instead of stuck on first one.
|
||||
- Changed donation address, new [xmrig-proxy](https://github.com/xmrig/xmrig-proxy) is coming soon.
|
||||
|
||||
# v2.0.2
|
||||
- Better deal with possible duplicate jobs from pool, show warning and ignore duplicates.
|
||||
- For Windows builds libuv updated to version 1.13.1 and gcc to 7.1.0.
|
||||
|
||||
# v2.0.1
|
||||
- [#27](https://github.com/xmrig/xmrig/issues/27) Fixed possibility crash on 32bit systems.
|
||||
|
||||
# v2.0.0
|
||||
- Option `--backup-url` removed, instead now possibility specify multiple pools for example: `-o example1.com:3333 -u user1 -p password1 -k -o example2.com:5555 -u user2 -o example3.com:4444 -u user3`
|
||||
- [#15](https://github.com/xmrig/xmrig/issues/15) Added option `-l, --log-file=FILE` to write log to file.
|
||||
- [#15](https://github.com/xmrig/xmrig/issues/15) Added option `-S, --syslog` to use syslog for logging, Linux only.
|
||||
- [#18](https://github.com/xmrig/xmrig/issues/18) Added nice messages for accepted/rejected shares with diff and network latency.
|
||||
- [#20](https://github.com/xmrig/xmrig/issues/20) Fixed `--cpu-affinity` for more than 32 threads.
|
||||
- Fixed Windows XP support.
|
||||
- Fixed regression, option `--no-color` was not fully disable colored output.
|
||||
- Show resolved pool IP address in miner output.
|
||||
|
||||
# v1.0.1
|
||||
- Fix broken software AES implementation, app has crashed if CPU not support AES-NI, only version 1.0.0 affected.
|
||||
|
||||
|
||||
@@ -4,20 +4,33 @@ project(xmrig)
|
||||
option(WITH_LIBCPUID "Use Libcpuid" ON)
|
||||
option(WITH_AEON "CryptoNight-Lite support" ON)
|
||||
|
||||
|
||||
include (CheckIncludeFile)
|
||||
|
||||
|
||||
set(HEADERS
|
||||
src/3rdparty/align.h
|
||||
src/App.h
|
||||
src/Console.h
|
||||
src/Cpu.h
|
||||
src/interfaces/IClientListener.h
|
||||
src/interfaces/IJobResultListener.h
|
||||
src/interfaces/ILogBackend.h
|
||||
src/interfaces/IStrategy.h
|
||||
src/interfaces/IStrategyListener.h
|
||||
src/interfaces/IWorker.h
|
||||
src/log/ConsoleLog.h
|
||||
src/log/FileLog.h
|
||||
src/log/Log.h
|
||||
src/Mem.h
|
||||
src/net/Client.h
|
||||
src/net/Job.h
|
||||
src/net/JobResult.h
|
||||
src/net/Network.h
|
||||
src/net/SubmitResult.h
|
||||
src/net/Url.h
|
||||
src/net/strategies/DonateStrategy.h
|
||||
src/net/strategies/FailoverStrategy.h
|
||||
src/net/strategies/SinglePoolStrategy.h
|
||||
src/Options.h
|
||||
src/Summary.h
|
||||
src/version.h
|
||||
@@ -45,12 +58,17 @@ set(HEADERS_CRYPTO
|
||||
|
||||
set(SOURCES
|
||||
src/App.cpp
|
||||
src/Console.cpp
|
||||
src/log/ConsoleLog.cpp
|
||||
src/log/FileLog.cpp
|
||||
src/log/Log.cpp
|
||||
src/Mem.cpp
|
||||
src/net/Client.cpp
|
||||
src/net/Job.cpp
|
||||
src/net/Network.cpp
|
||||
src/net/Url.cpp
|
||||
src/net/strategies/DonateStrategy.cpp
|
||||
src/net/strategies/FailoverStrategy.cpp
|
||||
src/net/strategies/SinglePoolStrategy.cpp
|
||||
src/Options.cpp
|
||||
src/Summary.cpp
|
||||
src/workers/DoubleWorker.cpp
|
||||
@@ -119,7 +137,7 @@ endif()
|
||||
# https://cmake.org/cmake/help/latest/variable/CMAKE_LANG_COMPILER_ID.html
|
||||
if (CMAKE_CXX_COMPILER_ID MATCHES GNU)
|
||||
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -maes -Wall")
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -maes -Wall -Wno-strict-aliasing")
|
||||
set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} -Ofast -funroll-loops -fvariable-expansion-in-unroller -ftree-loop-if-convert-stores -fmerge-all-constants -fbranch-target-load-optimize2")
|
||||
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -maes -Wall -std=c++14 -fno-exceptions -fno-rtti")
|
||||
@@ -127,6 +145,7 @@ if (CMAKE_CXX_COMPILER_ID MATCHES GNU)
|
||||
|
||||
if (WIN32)
|
||||
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -static")
|
||||
add_definitions(/D__STDC_FORMAT_MACROS)
|
||||
else()
|
||||
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -static-libgcc -static-libstdc++")
|
||||
endif()
|
||||
@@ -161,6 +180,12 @@ else()
|
||||
set(SOURCES_CPUID src/Cpu_stub.cpp)
|
||||
endif()
|
||||
|
||||
CHECK_INCLUDE_FILE (syslog.h HAVE_SYSLOG_H)
|
||||
if (HAVE_SYSLOG_H)
|
||||
add_definitions(/DHAVE_SYSLOG_H)
|
||||
set(SOURCES_SYSLOG src/log/SysLog.h src/log/SysLog.cpp)
|
||||
endif()
|
||||
|
||||
include_directories(src)
|
||||
include_directories(src/3rdparty)
|
||||
include_directories(src/3rdparty/jansson)
|
||||
@@ -168,5 +193,5 @@ include_directories(${UV_INCLUDE_DIR})
|
||||
|
||||
add_subdirectory(src/3rdparty/jansson)
|
||||
|
||||
add_executable(xmrig ${HEADERS} ${SOURCES} ${SOURCES_OS} ${SOURCES_CPUID} ${HEADERS_CRYPTO} ${SOURCES_CRYPTO})
|
||||
add_executable(xmrig ${HEADERS} ${SOURCES} ${SOURCES_OS} ${SOURCES_CPUID} ${HEADERS_CRYPTO} ${SOURCES_CRYPTO} ${SOURCES_SYSLOG})
|
||||
target_link_libraries(xmrig jansson ${UV_LIBRARIES} ${EXTRA_LIBS} ${CPUID_LIB})
|
||||
|
||||
11
README.md
11
README.md
@@ -1,8 +1,8 @@
|
||||
# XMRig
|
||||
XMRig is high performance Monero (XMR) CPU miner, with the official full Windows support.
|
||||
Based on cpuminer-multi with heavy optimizations/rewrites and removing a lot of legacy code.
|
||||
Originally based on cpuminer-multi with heavy optimizations/rewrites and removing a lot of legacy code, since version 1.0.0 complete rewritten from scratch on C++.
|
||||
|
||||
<img src="http://i.imgur.com/GdRDnAu.png" width="596" >
|
||||
<img src="https://i.imgur.com/OXoB10D.png" width="628" >
|
||||
|
||||
#### Table of contents
|
||||
* [Features](#features)
|
||||
@@ -38,11 +38,16 @@ Based on cpuminer-multi with heavy optimizations/rewrites and removing a lot of
|
||||
xmrig.exe -o xmr-eu.dwarfpool.com:8005 -u YOUR_WALLET -p x -k
|
||||
```
|
||||
|
||||
### Failover
|
||||
```
|
||||
xmrig.exe -o pool.supportxmr.com:5555 -u YOUR_WALLET1 -k -o xmr-eu.dwarfpool.com:8005 -u YOUR_WALLET2 -p x -k
|
||||
```
|
||||
For failover you can add multiple pools, maximum count not limited.
|
||||
|
||||
### Options
|
||||
```
|
||||
-a, --algo=ALGO cryptonight (default) or cryptonight-lite
|
||||
-o, --url=URL URL of mining server
|
||||
-b, --backup-url=URL URL of backup mining server
|
||||
-O, --userpass=U:P username:password pair for mining server
|
||||
-u, --user=USERNAME username for mining server
|
||||
-p, --pass=PASSWORD password for mining server
|
||||
|
||||
44
src/App.cpp
44
src/App.cpp
@@ -27,9 +27,11 @@
|
||||
|
||||
|
||||
#include "App.h"
|
||||
#include "Console.h"
|
||||
#include "Cpu.h"
|
||||
#include "crypto/CryptoNight.h"
|
||||
#include "log/ConsoleLog.h"
|
||||
#include "log/FileLog.h"
|
||||
#include "log/Log.h"
|
||||
#include "Mem.h"
|
||||
#include "net/Network.h"
|
||||
#include "Options.h"
|
||||
@@ -38,6 +40,11 @@
|
||||
#include "workers/Workers.h"
|
||||
|
||||
|
||||
#ifdef HAVE_SYSLOG_H
|
||||
# include "log/SysLog.h"
|
||||
#endif
|
||||
|
||||
|
||||
App *App::m_self = nullptr;
|
||||
|
||||
|
||||
@@ -48,10 +55,25 @@ App::App(int argc, char **argv) :
|
||||
{
|
||||
m_self = this;
|
||||
|
||||
Console::init();
|
||||
Cpu::init();
|
||||
|
||||
m_options = Options::parse(argc, argv);
|
||||
|
||||
Log::init();
|
||||
|
||||
if (!m_options->background()) {
|
||||
Log::add(new ConsoleLog(m_options->colors()));
|
||||
}
|
||||
|
||||
if (m_options->logFile()) {
|
||||
Log::add(new FileLog(m_options->logFile()));
|
||||
}
|
||||
|
||||
# ifdef HAVE_SYSLOG_H
|
||||
if (m_options->syslog()) {
|
||||
Log::add(new SysLog());
|
||||
}
|
||||
# endif
|
||||
|
||||
m_network = new Network(m_options);
|
||||
|
||||
uv_signal_init(uv_default_loop(), &m_signal);
|
||||
@@ -69,21 +91,21 @@ int App::exec()
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!CryptoNight::init(m_options->algo(), m_options->algoVariant())) {
|
||||
LOG_ERR("\"%s\" hash self-test failed.", m_options->algoName());
|
||||
return 1;
|
||||
}
|
||||
|
||||
uv_signal_start(&m_signal, App::onSignal, SIGHUP);
|
||||
uv_signal_start(&m_signal, App::onSignal, SIGTERM);
|
||||
uv_signal_start(&m_signal, App::onSignal, SIGINT);
|
||||
|
||||
background();
|
||||
|
||||
if (!CryptoNight::init(m_options->algo(), m_options->algoVariant())) {
|
||||
LOG_ERR("\"%s\" hash self-test failed.", m_options->algoName());
|
||||
return 1;
|
||||
}
|
||||
|
||||
Mem::allocate(m_options->algo(), m_options->threads(), m_options->doubleHash());
|
||||
Summary::print();
|
||||
|
||||
Workers::start(m_options->affinity(), m_options->nicehash());
|
||||
Workers::start(m_options->affinity());
|
||||
|
||||
m_network->connect();
|
||||
|
||||
@@ -101,6 +123,9 @@ int App::exec()
|
||||
|
||||
void App::close()
|
||||
{
|
||||
m_network->stop();
|
||||
Workers::stop();
|
||||
|
||||
uv_stop(uv_default_loop());
|
||||
}
|
||||
|
||||
@@ -125,5 +150,6 @@ void App::onSignal(uv_signal_t *handle, int signum)
|
||||
break;
|
||||
}
|
||||
|
||||
uv_signal_stop(handle);
|
||||
m_self->close();
|
||||
}
|
||||
|
||||
@@ -29,8 +29,8 @@
|
||||
|
||||
|
||||
#include "App.h"
|
||||
#include "Console.h"
|
||||
#include "Cpu.h"
|
||||
#include "log/Log.h"
|
||||
#include "Options.h"
|
||||
|
||||
|
||||
|
||||
@@ -25,6 +25,9 @@
|
||||
#define __CPU_H__
|
||||
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
|
||||
class Cpu
|
||||
{
|
||||
public:
|
||||
@@ -36,7 +39,7 @@ public:
|
||||
|
||||
static int optimalThreadsCount(int algo, bool doubleHash, int maxCpuUsage);
|
||||
static void init();
|
||||
static void setAffinity(int id, unsigned long mask);
|
||||
static void setAffinity(int id, uint64_t mask);
|
||||
|
||||
static inline bool hasAES() { return m_flags & AES; }
|
||||
static inline bool isX64() { return m_flags & X86_64; }
|
||||
|
||||
@@ -40,6 +40,6 @@ void Cpu::init()
|
||||
}
|
||||
|
||||
|
||||
void Cpu::setAffinity(int id, unsigned long mask)
|
||||
void Cpu::setAffinity(int id, uint64_t mask)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -25,6 +25,7 @@
|
||||
#include <pthread.h>
|
||||
#include <sched.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
|
||||
|
||||
#include "Cpu.h"
|
||||
@@ -40,7 +41,7 @@ void Cpu::init()
|
||||
}
|
||||
|
||||
|
||||
void Cpu::setAffinity(int id, unsigned long mask)
|
||||
void Cpu::setAffinity(int id, uint64_t mask)
|
||||
{
|
||||
cpu_set_t set;
|
||||
CPU_ZERO(&set);
|
||||
|
||||
@@ -41,7 +41,7 @@ void Cpu::init()
|
||||
}
|
||||
|
||||
|
||||
void Cpu::setAffinity(int id, unsigned long mask)
|
||||
void Cpu::setAffinity(int id, uint64_t mask)
|
||||
{
|
||||
if (id == -1) {
|
||||
SetProcessAffinityMask(GetCurrentProcess(), mask);
|
||||
|
||||
@@ -28,9 +28,9 @@
|
||||
|
||||
|
||||
#include "crypto/CryptoNight.h"
|
||||
#include "log/Log.h"
|
||||
#include "Mem.h"
|
||||
#include "Options.h"
|
||||
#include "Console.h"
|
||||
|
||||
|
||||
bool Mem::allocate(int algo, int threads, bool doubleHash)
|
||||
|
||||
@@ -33,7 +33,7 @@
|
||||
# include <malloc.h>
|
||||
#endif
|
||||
|
||||
#include "Console.h"
|
||||
#include "log/Log.h"
|
||||
#include "crypto/CryptoNight.h"
|
||||
#include "Mem.h"
|
||||
#include "Options.h"
|
||||
|
||||
122
src/Options.cpp
122
src/Options.cpp
@@ -34,7 +34,6 @@
|
||||
#endif
|
||||
|
||||
|
||||
#include "Console.h"
|
||||
#include "Cpu.h"
|
||||
#include "donate.h"
|
||||
#include "net/Url.h"
|
||||
@@ -55,7 +54,6 @@ Usage: " APP_ID " [OPTIONS]\n\
|
||||
Options:\n\
|
||||
-a, --algo=ALGO cryptonight (default) or cryptonight-lite\n\
|
||||
-o, --url=URL URL of mining server\n\
|
||||
-b, --backup-url=URL URL of backup 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\
|
||||
@@ -69,6 +67,12 @@ Options:\n\
|
||||
--donate-level=N donate level, default 5%% (5 minutes in 100 minutes)\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 support\n\
|
||||
@@ -78,19 +82,19 @@ Options:\n\
|
||||
";
|
||||
|
||||
|
||||
static char const short_options[] = "a:c:khBp:Px:r:R:s:t:T:o:u:O:v:Vb:";
|
||||
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' },
|
||||
{ "av", 1, nullptr, 'v' },
|
||||
{ "background", 0, nullptr, 'B' },
|
||||
{ "backup-url", 1, nullptr, 'b' },
|
||||
{ "config", 1, nullptr, 'c' },
|
||||
{ "cpu-affinity", 1, nullptr, 1020 },
|
||||
{ "donate-level", 1, nullptr, 1003 },
|
||||
{ "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 },
|
||||
@@ -99,6 +103,7 @@ static struct option const options[] = {
|
||||
{ "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' },
|
||||
@@ -136,12 +141,10 @@ Options::Options(int argc, char **argv) :
|
||||
m_background(false),
|
||||
m_colors(true),
|
||||
m_doubleHash(false),
|
||||
m_keepAlive(false),
|
||||
m_nicehash(false),
|
||||
m_ready(false),
|
||||
m_safe(false),
|
||||
m_pass(nullptr),
|
||||
m_user(nullptr),
|
||||
m_syslog(false),
|
||||
m_logFile(nullptr),
|
||||
m_algo(0),
|
||||
m_algoVariant(0),
|
||||
m_donateLevel(kDonateLevel),
|
||||
@@ -150,10 +153,10 @@ Options::Options(int argc, char **argv) :
|
||||
m_retries(5),
|
||||
m_retryPause(5),
|
||||
m_threads(0),
|
||||
m_affinity(-1L),
|
||||
m_backupUrl(nullptr),
|
||||
m_url(nullptr)
|
||||
m_affinity(-1L)
|
||||
{
|
||||
m_pools.push_back(new Url());
|
||||
|
||||
int key;
|
||||
|
||||
while (1) {
|
||||
@@ -172,23 +175,11 @@ Options::Options(int argc, char **argv) :
|
||||
return;
|
||||
}
|
||||
|
||||
if (!m_url) {
|
||||
LOG_ERR("No pool URL supplied. Exiting.", argv[0]);
|
||||
if (!m_pools[0]->isValid()) {
|
||||
fprintf(stderr, "No pool URL supplied. Exiting.");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!m_nicehash && m_url->isNicehash()) {
|
||||
m_nicehash = true;
|
||||
}
|
||||
|
||||
if (!m_user) {
|
||||
m_user = strdup("x");
|
||||
}
|
||||
|
||||
if (!m_pass) {
|
||||
m_pass = strdup("x");
|
||||
}
|
||||
|
||||
m_algoVariant = getAlgoVariant();
|
||||
if (m_algoVariant == AV2_AESNI_DOUBLE || m_algoVariant == AV4_SOFT_AES_DOUBLE) {
|
||||
m_doubleHash = true;
|
||||
@@ -210,11 +201,6 @@ Options::Options(int argc, char **argv) :
|
||||
|
||||
Options::~Options()
|
||||
{
|
||||
delete m_url;
|
||||
delete m_backupUrl;
|
||||
|
||||
free(m_user);
|
||||
free(m_pass);
|
||||
}
|
||||
|
||||
|
||||
@@ -222,8 +208,6 @@ bool Options::parseArg(int key, char *arg)
|
||||
{
|
||||
char *p;
|
||||
int v;
|
||||
uint64_t ul;
|
||||
Url *url;
|
||||
|
||||
switch (key) {
|
||||
case 'a': /* --algo */
|
||||
@@ -233,35 +217,44 @@ bool Options::parseArg(int key, char *arg)
|
||||
break;
|
||||
|
||||
case 'O': /* --userpass */
|
||||
if (!setUserpass(arg)) {
|
||||
if (!m_pools.back()->setUserpass(arg)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case 'o': /* --url */
|
||||
url = parseUrl(arg);
|
||||
if (url) {
|
||||
free(m_url);
|
||||
m_url = 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);
|
||||
}
|
||||
break;
|
||||
|
||||
case 'b': /* --backup-url */
|
||||
url = parseUrl(arg);
|
||||
if (url) {
|
||||
free(m_backupUrl);
|
||||
m_backupUrl = url;
|
||||
if (!m_pools.back()->isValid()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case 'u': /* --user */
|
||||
free(m_user);
|
||||
m_user = strdup(arg);
|
||||
m_pools.back()->setUser(arg);
|
||||
break;
|
||||
|
||||
case 'p': /* --pass */
|
||||
free(m_pass);
|
||||
m_pass = strdup(arg);
|
||||
m_pools.back()->setPassword(arg);
|
||||
break;
|
||||
|
||||
case 'l': /* --log-file */
|
||||
free(m_logFile);
|
||||
m_logFile = strdup(arg);
|
||||
m_colors = false;
|
||||
break;
|
||||
|
||||
case 'r': /* --retries */
|
||||
@@ -309,7 +302,7 @@ bool Options::parseArg(int key, char *arg)
|
||||
break;
|
||||
|
||||
case 'k': /* --keepalive */
|
||||
m_keepAlive = true;
|
||||
m_pools.back()->setKeepAlive(true);
|
||||
break;
|
||||
|
||||
case 'V': /* --version */
|
||||
@@ -325,6 +318,11 @@ bool Options::parseArg(int key, char *arg)
|
||||
m_colors = false;
|
||||
break;
|
||||
|
||||
case 'S': /* --syslog */
|
||||
m_syslog = true;
|
||||
m_colors = false;
|
||||
break;
|
||||
|
||||
case 'v': /* --av */
|
||||
v = strtol(arg, nullptr, 10);
|
||||
if (v < 0 || v > 1000) {
|
||||
@@ -337,12 +335,7 @@ bool Options::parseArg(int key, char *arg)
|
||||
|
||||
case 1020: /* --cpu-affinity */
|
||||
p = strstr(arg, "0x");
|
||||
ul = p ? strtoul(p, NULL, 16) : atol(arg);
|
||||
if (ul > (1UL << Cpu::threads()) -1) {
|
||||
ul = -1;
|
||||
}
|
||||
|
||||
m_affinity = ul;
|
||||
m_affinity = p ? strtoull(p, nullptr, 16) : strtoull(arg, nullptr, 10);
|
||||
break;
|
||||
|
||||
case 1002: /* --no-color */
|
||||
@@ -360,7 +353,7 @@ bool Options::parseArg(int key, char *arg)
|
||||
break;
|
||||
|
||||
case 1006: /* --nicehash */
|
||||
m_nicehash = true;
|
||||
m_pools.back()->setNicehash(true);
|
||||
break;
|
||||
|
||||
case 1007: /* --print-time */
|
||||
@@ -463,25 +456,6 @@ bool Options::setAlgo(const char *algo)
|
||||
}
|
||||
|
||||
|
||||
bool Options::setUserpass(const char *userpass)
|
||||
{
|
||||
const char *p = strchr(userpass, ':');
|
||||
if (!p) {
|
||||
showUsage(1);
|
||||
return false;
|
||||
}
|
||||
|
||||
free(m_user);
|
||||
free(m_pass);
|
||||
|
||||
m_user = static_cast<char*>(calloc(p - userpass + 1, 1));
|
||||
strncpy(m_user, userpass, p - userpass);
|
||||
m_pass = strdup(p + 1);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
int Options::getAlgoVariant() const
|
||||
{
|
||||
# ifndef XMRIG_NO_AEON
|
||||
|
||||
@@ -25,6 +25,7 @@
|
||||
#define __OPTIONS_H__
|
||||
|
||||
|
||||
#include <vector>
|
||||
#include <stdint.h>
|
||||
|
||||
|
||||
@@ -51,24 +52,21 @@ public:
|
||||
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 isReady() const { return m_ready; }
|
||||
inline bool keepAlive() const { return m_keepAlive; }
|
||||
inline bool nicehash() const { return m_nicehash; }
|
||||
inline const char *pass() const { return m_pass; }
|
||||
inline const char *user() const { return m_user; }
|
||||
inline const Url *backupUrl() const { return m_backupUrl; }
|
||||
inline const Url *url() const { return m_url; }
|
||||
inline int algo() const { return m_algo; }
|
||||
inline int algoVariant() const { return m_algoVariant; }
|
||||
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 int threads() const { return m_threads; }
|
||||
inline int64_t affinity() const { return m_affinity; }
|
||||
inline bool background() const { return m_background; }
|
||||
inline bool colors() const { return m_colors; }
|
||||
inline bool doubleHash() const { return m_doubleHash; }
|
||||
inline bool isReady() const { return m_ready; }
|
||||
inline bool syslog() const { return m_syslog; }
|
||||
inline const char *logFile() const { return m_logFile; }
|
||||
inline const std::vector<Url*> &pools() const { return m_pools; }
|
||||
inline int algo() const { return m_algo; }
|
||||
inline int algoVariant() const { return m_algoVariant; }
|
||||
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 int threads() const { return m_threads; }
|
||||
inline int64_t affinity() const { return m_affinity; }
|
||||
|
||||
const char *algoName() const;
|
||||
|
||||
@@ -84,7 +82,6 @@ private:
|
||||
void showVersion(void);
|
||||
|
||||
bool setAlgo(const char *algo);
|
||||
bool setUserpass(const char *userpass);
|
||||
|
||||
int getAlgoVariant() const;
|
||||
# ifndef XMRIG_NO_AEON
|
||||
@@ -94,12 +91,10 @@ private:
|
||||
bool m_background;
|
||||
bool m_colors;
|
||||
bool m_doubleHash;
|
||||
bool m_keepAlive;
|
||||
bool m_nicehash;
|
||||
bool m_ready;
|
||||
bool m_safe;
|
||||
char *m_pass;
|
||||
char *m_user;
|
||||
bool m_syslog;
|
||||
char *m_logFile;
|
||||
int m_algo;
|
||||
int m_algoVariant;
|
||||
int m_donateLevel;
|
||||
@@ -109,8 +104,7 @@ private:
|
||||
int m_retryPause;
|
||||
int m_threads;
|
||||
int64_t m_affinity;
|
||||
Url *m_backupUrl;
|
||||
Url *m_url;
|
||||
std::vector<Url*> m_pools;
|
||||
};
|
||||
|
||||
#endif /* __OPTIONS_H__ */
|
||||
|
||||
@@ -22,11 +22,12 @@
|
||||
*/
|
||||
|
||||
|
||||
#include <inttypes.h>
|
||||
#include <uv.h>
|
||||
|
||||
|
||||
#include "Console.h"
|
||||
#include "Cpu.h"
|
||||
#include "log/Log.h"
|
||||
#include "Mem.h"
|
||||
#include "net/Url.h"
|
||||
#include "Options.h"
|
||||
@@ -50,21 +51,21 @@ static void print_versions()
|
||||
|
||||
|
||||
if (Options::i()->colors()) {
|
||||
Console::i()->text("\x1B[01;32m * \x1B[01;37mVERSIONS: \x1B[01;36mXMRig/%s\x1B[01;37m libuv/%s%s", APP_VERSION, uv_version_string(), buf);
|
||||
Log::i()->text("\x1B[01;32m * \x1B[01;37mVERSIONS: \x1B[01;36mXMRig/%s\x1B[01;37m libuv/%s%s", APP_VERSION, uv_version_string(), buf);
|
||||
} else {
|
||||
Console::i()->text(" * VERSIONS: XMRig/%s libuv/%s%s", APP_VERSION, uv_version_string(), buf);
|
||||
Log::i()->text(" * VERSIONS: XMRig/%s libuv/%s%s", APP_VERSION, uv_version_string(), buf);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void print_memory() {
|
||||
if (Options::i()->colors()) {
|
||||
Console::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");
|
||||
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");
|
||||
}
|
||||
else {
|
||||
Console::i()->text(" * HUGE PAGES: %s, %s", Mem::isHugepagesAvailable() ? "available" : "unavailable", Mem::isHugepagesEnabled() ? "enabled" : "disabled");
|
||||
Log::i()->text(" * HUGE PAGES: %s, %s", Mem::isHugepagesAvailable() ? "available" : "unavailable", Mem::isHugepagesEnabled() ? "enabled" : "disabled");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -72,19 +73,19 @@ static void print_memory() {
|
||||
static void print_cpu()
|
||||
{
|
||||
if (Options::i()->colors()) {
|
||||
Console::i()->text("\x1B[01;32m * \x1B[01;37mCPU: %s (%d) %sx64 %sAES-NI",
|
||||
Cpu::brand(),
|
||||
Cpu::sockets(),
|
||||
Cpu::isX64() ? "\x1B[01;32m" : "\x1B[01;31m-",
|
||||
Cpu::hasAES() ? "\x1B[01;32m" : "\x1B[01;31m-");
|
||||
Log::i()->text("\x1B[01;32m * \x1B[01;37mCPU: %s (%d) %sx64 %sAES-NI",
|
||||
Cpu::brand(),
|
||||
Cpu::sockets(),
|
||||
Cpu::isX64() ? "\x1B[01;32m" : "\x1B[01;31m-",
|
||||
Cpu::hasAES() ? "\x1B[01;32m" : "\x1B[01;31m-");
|
||||
# ifndef XMRIG_NO_LIBCPUID
|
||||
Console::i()->text("\x1B[01;32m * \x1B[01;37mCPU L2/L3: %.1f MB/%.1f MB", Cpu::l2() / 1024.0, Cpu::l3() / 1024.0);
|
||||
Log::i()->text("\x1B[01;32m * \x1B[01;37mCPU L2/L3: %.1f MB/%.1f MB", Cpu::l2() / 1024.0, Cpu::l3() / 1024.0);
|
||||
# endif
|
||||
}
|
||||
else {
|
||||
Console::i()->text(" * CPU: %s (%d) %sx64 %sAES-NI", Cpu::brand(), Cpu::sockets(), Cpu::isX64() ? "" : "-", Cpu::hasAES() ? "" : "-");
|
||||
Log::i()->text(" * CPU: %s (%d) %sx64 %sAES-NI", Cpu::brand(), Cpu::sockets(), Cpu::isX64() ? "" : "-", Cpu::hasAES() ? "" : "-");
|
||||
# ifndef XMRIG_NO_LIBCPUID
|
||||
Console::i()->text(" * CPU L2/L3: %.1f MB/%.1f MB", Cpu::l2() / 1024.0, Cpu::l3() / 1024.0);
|
||||
Log::i()->text(" * CPU L2/L3: %.1f MB/%.1f MB", Cpu::l2() / 1024.0, Cpu::l3() / 1024.0);
|
||||
# endif
|
||||
}
|
||||
}
|
||||
@@ -94,34 +95,38 @@ static void print_threads()
|
||||
{
|
||||
char buf[32];
|
||||
if (Options::i()->affinity() != -1L) {
|
||||
snprintf(buf, 32, ", affinity=0x%llX", Options::i()->affinity());
|
||||
snprintf(buf, 32, ", affinity=0x%" PRIX64, Options::i()->affinity());
|
||||
}
|
||||
else {
|
||||
buf[0] = '\0';
|
||||
}
|
||||
|
||||
Console::i()->text(Options::i()->colors() ? "\x1B[01;32m * \x1B[01;37mTHREADS: \x1B[01;36m%d\x1B[01;37m, %s, av=%d, donate=%d%%%s%s" : " * THREADS: %d, %s, av=%d, donate=%d%%%s%s",
|
||||
Options::i()->threads(),
|
||||
Options::i()->algoName(),
|
||||
Options::i()->algoVariant(),
|
||||
Options::i()->donateLevel(),
|
||||
Options::i()->nicehash() ? ", nicehash" : "", buf);
|
||||
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(),
|
||||
buf);
|
||||
}
|
||||
|
||||
|
||||
static void print_pools()
|
||||
{
|
||||
Console::i()->text(Options::i()->colors() ? "\x1B[01;32m * \x1B[01;37mPOOL #1: \x1B[01;36m%s:%d" : " * POOL #1: %s:%d",
|
||||
Options::i()->url()->host(),
|
||||
Options::i()->url()->port());
|
||||
const std::vector<Url*> &pools = Options::i()->pools();
|
||||
|
||||
if (!Options::i()->backupUrl()) {
|
||||
return;
|
||||
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",
|
||||
i + 1,
|
||||
pools[i]->host(),
|
||||
pools[i]->port());
|
||||
}
|
||||
|
||||
Console::i()->text(Options::i()->colors() ? "\x1B[01;32m * \x1B[01;37mPOOL #2: \x1B[01;36m%s:%d" : " * POOL #2: %s:%d",
|
||||
Options::i()->backupUrl()->host(),
|
||||
Options::i()->backupUrl()->port());
|
||||
# ifdef APP_DEBUG
|
||||
for (size_t i = 0; i < pools.size(); ++i) {
|
||||
Log::i()->text("%s:%d, user: %s, pass: %s, ka: %d, nicehash: %d", pools[i]->host(), pools[i]->port(), pools[i]->user(), pools[i]->password(), pools[i]->isKeepAlive(), pools[i]->isNicehash());
|
||||
}
|
||||
# endif
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -65,7 +65,7 @@ static inline void do_jh_hash(const void* input, size_t len, char* output) {
|
||||
|
||||
|
||||
static inline void do_skein_hash(const void* input, size_t len, char* output) {
|
||||
skein_hash(8 * 32, static_cast<const uint8_t*>(input), 8 * len, reinterpret_cast<uint8_t*>(output));
|
||||
xmr_skein(static_cast<const uint8_t*>(input), reinterpret_cast<uint8_t*>(output));
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
// A baseline Keccak (3rd round) implementation.
|
||||
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <memory.h>
|
||||
|
||||
#define HASH_DATA_AREA 136
|
||||
#define KECCAK_ROUNDS 24
|
||||
@@ -24,18 +24,6 @@ const uint64_t keccakf_rndc[24] =
|
||||
0x8000000000008080, 0x0000000080000001, 0x8000000080008008
|
||||
};
|
||||
|
||||
const int keccakf_rotc[24] =
|
||||
{
|
||||
1, 3, 6, 10, 15, 21, 28, 36, 45, 55, 2, 14,
|
||||
27, 41, 56, 8, 25, 43, 62, 18, 39, 61, 20, 44
|
||||
};
|
||||
|
||||
const int keccakf_piln[24] =
|
||||
{
|
||||
10, 7, 11, 17, 18, 3, 5, 16, 8, 21, 24, 4,
|
||||
15, 23, 19, 13, 12, 2, 20, 14, 22, 9, 6, 1
|
||||
};
|
||||
|
||||
// update the state with given number of rounds
|
||||
|
||||
void keccakf(uint64_t st[25], int rounds)
|
||||
@@ -63,26 +51,86 @@ void keccakf(uint64_t st[25], int rounds)
|
||||
|
||||
// Rho Pi
|
||||
t = st[1];
|
||||
for (i = 0; i < 24; ++i) {
|
||||
bc[0] = st[keccakf_piln[i]];
|
||||
st[keccakf_piln[i]] = ROTL64(t, keccakf_rotc[i]);
|
||||
t = bc[0];
|
||||
}
|
||||
st[ 1] = ROTL64(st[ 6], 44);
|
||||
st[ 6] = ROTL64(st[ 9], 20);
|
||||
st[ 9] = ROTL64(st[22], 61);
|
||||
st[22] = ROTL64(st[14], 39);
|
||||
st[14] = ROTL64(st[20], 18);
|
||||
st[20] = ROTL64(st[ 2], 62);
|
||||
st[ 2] = ROTL64(st[12], 43);
|
||||
st[12] = ROTL64(st[13], 25);
|
||||
st[13] = ROTL64(st[19], 8);
|
||||
st[19] = ROTL64(st[23], 56);
|
||||
st[23] = ROTL64(st[15], 41);
|
||||
st[15] = ROTL64(st[ 4], 27);
|
||||
st[ 4] = ROTL64(st[24], 14);
|
||||
st[24] = ROTL64(st[21], 2);
|
||||
st[21] = ROTL64(st[ 8], 55);
|
||||
st[ 8] = ROTL64(st[16], 45);
|
||||
st[16] = ROTL64(st[ 5], 36);
|
||||
st[ 5] = ROTL64(st[ 3], 28);
|
||||
st[ 3] = ROTL64(st[18], 21);
|
||||
st[18] = ROTL64(st[17], 15);
|
||||
st[17] = ROTL64(st[11], 10);
|
||||
st[11] = ROTL64(st[ 7], 6);
|
||||
st[ 7] = ROTL64(st[10], 3);
|
||||
st[10] = ROTL64(t, 1);
|
||||
|
||||
// Chi
|
||||
for (j = 0; j < 25; j += 5) {
|
||||
bc[0] = st[j ];
|
||||
bc[1] = st[j + 1];
|
||||
bc[2] = st[j + 2];
|
||||
bc[3] = st[j + 3];
|
||||
bc[4] = st[j + 4];
|
||||
st[j ] ^= (~bc[1]) & bc[2];
|
||||
st[j + 1] ^= (~bc[2]) & bc[3];
|
||||
st[j + 2] ^= (~bc[3]) & bc[4];
|
||||
st[j + 3] ^= (~bc[4]) & bc[0];
|
||||
st[j + 4] ^= (~bc[0]) & bc[1];
|
||||
}
|
||||
// unrolled loop, where only last iteration is different
|
||||
j = 0;
|
||||
bc[0] = st[j ];
|
||||
bc[1] = st[j + 1];
|
||||
|
||||
st[j ] ^= (~st[j + 1]) & st[j + 2];
|
||||
st[j + 1] ^= (~st[j + 2]) & st[j + 3];
|
||||
st[j + 2] ^= (~st[j + 3]) & st[j + 4];
|
||||
st[j + 3] ^= (~st[j + 4]) & bc[0];
|
||||
st[j + 4] ^= (~bc[0]) & bc[1];
|
||||
|
||||
j = 5;
|
||||
bc[0] = st[j ];
|
||||
bc[1] = st[j + 1];
|
||||
|
||||
st[j ] ^= (~st[j + 1]) & st[j + 2];
|
||||
st[j + 1] ^= (~st[j + 2]) & st[j + 3];
|
||||
st[j + 2] ^= (~st[j + 3]) & st[j + 4];
|
||||
st[j + 3] ^= (~st[j + 4]) & bc[0];
|
||||
st[j + 4] ^= (~bc[0]) & bc[1];
|
||||
|
||||
j = 10;
|
||||
bc[0] = st[j ];
|
||||
bc[1] = st[j + 1];
|
||||
|
||||
st[j ] ^= (~st[j + 1]) & st[j + 2];
|
||||
st[j + 1] ^= (~st[j + 2]) & st[j + 3];
|
||||
st[j + 2] ^= (~st[j + 3]) & st[j + 4];
|
||||
st[j + 3] ^= (~st[j + 4]) & bc[0];
|
||||
st[j + 4] ^= (~bc[0]) & bc[1];
|
||||
|
||||
j = 15;
|
||||
bc[0] = st[j ];
|
||||
bc[1] = st[j + 1];
|
||||
|
||||
st[j ] ^= (~st[j + 1]) & st[j + 2];
|
||||
st[j + 1] ^= (~st[j + 2]) & st[j + 3];
|
||||
st[j + 2] ^= (~st[j + 3]) & st[j + 4];
|
||||
st[j + 3] ^= (~st[j + 4]) & bc[0];
|
||||
st[j + 4] ^= (~bc[0]) & bc[1];
|
||||
|
||||
j = 20;
|
||||
bc[0] = st[j ];
|
||||
bc[1] = st[j + 1];
|
||||
bc[2] = st[j + 2];
|
||||
bc[3] = st[j + 3];
|
||||
bc[4] = st[j + 4];
|
||||
|
||||
st[j ] ^= (~bc[1]) & bc[2];
|
||||
st[j + 1] ^= (~bc[2]) & bc[3];
|
||||
st[j + 2] ^= (~bc[3]) & bc[4];
|
||||
st[j + 3] ^= (~bc[4]) & bc[0];
|
||||
st[j + 4] ^= (~bc[0]) & bc[1];
|
||||
|
||||
// Iota
|
||||
st[0] ^= keccakf_rndc[round];
|
||||
}
|
||||
@@ -121,3 +169,8 @@ void keccak(const uint8_t *in, int inlen, uint8_t *md, int mdlen)
|
||||
|
||||
memcpy(md, st, mdlen);
|
||||
}
|
||||
|
||||
void keccak1600(const uint8_t *in, int inlen, uint8_t *md)
|
||||
{
|
||||
keccak(in, inlen, md, sizeof(state_t));
|
||||
}
|
||||
|
||||
1409
src/crypto/c_skein.c
1409
src/crypto/c_skein.c
File diff suppressed because it is too large
Load Diff
@@ -44,4 +44,6 @@ typedef u08b_t SkeinBitSequence; /* bit stream type */
|
||||
SkeinHashReturn skein_hash(int hashbitlen, const SkeinBitSequence *data,
|
||||
SkeinDataLength databitlen, SkeinBitSequence *hashval);
|
||||
|
||||
void xmr_skein(const SkeinBitSequence *data, SkeinBitSequence *hashval);
|
||||
|
||||
#endif /* ifndef _SKEIN_H_ */
|
||||
|
||||
@@ -25,6 +25,9 @@
|
||||
#define __ICLIENTLISTENER_H__
|
||||
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
|
||||
class Client;
|
||||
class Job;
|
||||
|
||||
@@ -34,10 +37,10 @@ class IClientListener
|
||||
public:
|
||||
virtual ~IClientListener() {}
|
||||
|
||||
virtual void onClose(Client *client, int failures) = 0;
|
||||
virtual void onJobReceived(Client *client, const Job &job) = 0;
|
||||
virtual void onLoginCredentialsRequired(Client *client) = 0;
|
||||
virtual void onLoginSuccess(Client *client) = 0;
|
||||
virtual void onClose(Client *client, int failures) = 0;
|
||||
virtual void onJobReceived(Client *client, const Job &job) = 0;
|
||||
virtual void onLoginSuccess(Client *client) = 0;
|
||||
virtual void onResultAccepted(Client *client, int64_t seq, uint32_t diff, uint64_t ms, const char *error) = 0;
|
||||
};
|
||||
|
||||
|
||||
|
||||
41
src/interfaces/ILogBackend.h
Normal file
41
src/interfaces/ILogBackend.h
Normal file
@@ -0,0 +1,41 @@
|
||||
/* XMRig
|
||||
* Copyright 2010 Jeff Garzik <jgarzik@pobox.com>
|
||||
* Copyright 2012-2014 pooler <pooler@litecoinpool.org>
|
||||
* Copyright 2014 Lucas Jones <https://github.com/lucasjones>
|
||||
* Copyright 2014-2016 Wolf9466 <https://github.com/OhGodAPet>
|
||||
* Copyright 2016 Jay D Dee <jayddee246@gmail.com>
|
||||
* Copyright 2016-2017 XMRig <support@xmrig.com>
|
||||
*
|
||||
*
|
||||
* 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef __ILOGBACKEND_H__
|
||||
#define __ILOGBACKEND_H__
|
||||
|
||||
|
||||
#include <stdarg.h>
|
||||
|
||||
|
||||
class ILogBackend
|
||||
{
|
||||
public:
|
||||
virtual ~ILogBackend() {}
|
||||
|
||||
virtual void message(int level, const char* fmt, va_list args) = 0;
|
||||
virtual void text(const char* fmt, va_list args) = 0;
|
||||
};
|
||||
|
||||
|
||||
#endif // __ILOGBACKEND_H__
|
||||
47
src/interfaces/IStrategy.h
Normal file
47
src/interfaces/IStrategy.h
Normal file
@@ -0,0 +1,47 @@
|
||||
/* XMRig
|
||||
* Copyright 2010 Jeff Garzik <jgarzik@pobox.com>
|
||||
* Copyright 2012-2014 pooler <pooler@litecoinpool.org>
|
||||
* Copyright 2014 Lucas Jones <https://github.com/lucasjones>
|
||||
* Copyright 2014-2016 Wolf9466 <https://github.com/OhGodAPet>
|
||||
* Copyright 2016 Jay D Dee <jayddee246@gmail.com>
|
||||
* Copyright 2016-2017 XMRig <support@xmrig.com>
|
||||
*
|
||||
*
|
||||
* 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef __ISTRATEGY_H__
|
||||
#define __ISTRATEGY_H__
|
||||
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
|
||||
class JobResult;
|
||||
|
||||
|
||||
class IStrategy
|
||||
{
|
||||
public:
|
||||
virtual ~IStrategy() {}
|
||||
|
||||
virtual bool isActive() const = 0;
|
||||
virtual int64_t submit(const JobResult &result) = 0;
|
||||
virtual void connect() = 0;
|
||||
virtual void resume() = 0;
|
||||
virtual void stop() = 0;
|
||||
};
|
||||
|
||||
|
||||
#endif // __ISTRATEGY_H__
|
||||
48
src/interfaces/IStrategyListener.h
Normal file
48
src/interfaces/IStrategyListener.h
Normal file
@@ -0,0 +1,48 @@
|
||||
/* XMRig
|
||||
* Copyright 2010 Jeff Garzik <jgarzik@pobox.com>
|
||||
* Copyright 2012-2014 pooler <pooler@litecoinpool.org>
|
||||
* Copyright 2014 Lucas Jones <https://github.com/lucasjones>
|
||||
* Copyright 2014-2016 Wolf9466 <https://github.com/OhGodAPet>
|
||||
* Copyright 2016 Jay D Dee <jayddee246@gmail.com>
|
||||
* Copyright 2016-2017 XMRig <support@xmrig.com>
|
||||
*
|
||||
*
|
||||
* 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef __ISTRATEGYLISTENER_H__
|
||||
#define __ISTRATEGYLISTENER_H__
|
||||
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
|
||||
class Client;
|
||||
class IStrategy;
|
||||
class Job;
|
||||
|
||||
|
||||
class IStrategyListener
|
||||
{
|
||||
public:
|
||||
virtual ~IStrategyListener() {}
|
||||
|
||||
virtual void onActive(Client *client) = 0;
|
||||
virtual void onJob(Client *client, const Job &job) = 0;
|
||||
virtual void onPause(IStrategy *strategy) = 0;
|
||||
virtual void onResultAccepted(Client *client, int64_t seq, uint32_t diff, uint64_t ms, const char *error) = 0;
|
||||
};
|
||||
|
||||
|
||||
#endif // __ISTRATEGYLISTENER_H__
|
||||
@@ -34,21 +34,17 @@
|
||||
# include "3rdparty/winansi.h"
|
||||
#endif
|
||||
|
||||
#include "Console.h"
|
||||
#include "log/ConsoleLog.h"
|
||||
#include "log/Log.h"
|
||||
|
||||
|
||||
Console *Console::m_self = nullptr;
|
||||
|
||||
|
||||
void Console::init()
|
||||
ConsoleLog::ConsoleLog(bool colors) :
|
||||
m_colors(colors)
|
||||
{
|
||||
if (!m_self) {
|
||||
m_self = new Console();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Console::message(Console::Level level, const char* fmt, ...)
|
||||
void ConsoleLog::message(int level, const char* fmt, va_list args)
|
||||
{
|
||||
time_t now = time(nullptr);
|
||||
tm stime;
|
||||
@@ -59,26 +55,23 @@ void Console::message(Console::Level level, const char* fmt, ...)
|
||||
localtime_r(&now, &stime);
|
||||
# endif
|
||||
|
||||
va_list ap;
|
||||
va_start(ap, fmt);
|
||||
|
||||
const char* color = nullptr;
|
||||
if (m_colors) {
|
||||
switch (level) {
|
||||
case ERR:
|
||||
color = kCL_RED;
|
||||
case Log::ERR:
|
||||
color = Log::kCL_RED;
|
||||
break;
|
||||
|
||||
case WARNING:
|
||||
color = kCL_YELLOW;
|
||||
case Log::WARNING:
|
||||
color = Log::kCL_YELLOW;
|
||||
break;
|
||||
|
||||
case NOTICE:
|
||||
color = kCL_WHITE;
|
||||
case Log::NOTICE:
|
||||
color = Log::kCL_WHITE;
|
||||
break;
|
||||
|
||||
case DEBUG:
|
||||
color = kCL_GRAY;
|
||||
case Log::DEBUG:
|
||||
color = Log::kCL_GRAY;
|
||||
break;
|
||||
|
||||
default:
|
||||
@@ -97,48 +90,23 @@ void Console::message(Console::Level level, const char* fmt, ...)
|
||||
stime.tm_hour,
|
||||
stime.tm_min,
|
||||
stime.tm_sec,
|
||||
color,
|
||||
m_colors ? color : "",
|
||||
fmt,
|
||||
m_colors ? kCL_N : ""
|
||||
m_colors ? Log::kCL_N : ""
|
||||
);
|
||||
|
||||
uv_mutex_lock(&m_mutex);
|
||||
|
||||
vfprintf(stdout, buf, ap);
|
||||
vfprintf(stdout, buf, args);
|
||||
fflush(stdout);
|
||||
|
||||
uv_mutex_unlock(&m_mutex);
|
||||
|
||||
va_end(ap);
|
||||
}
|
||||
|
||||
|
||||
void Console::text(const char* fmt, ...)
|
||||
void ConsoleLog::text(const char* fmt, va_list args)
|
||||
{
|
||||
va_list ap;
|
||||
va_start(ap, fmt);
|
||||
|
||||
const int len = 64 + strlen(fmt) + 2;
|
||||
char *buf = static_cast<char *>(alloca(len));
|
||||
|
||||
sprintf(buf, "%s%s\n",
|
||||
fmt,
|
||||
m_colors ? kCL_N : ""
|
||||
);
|
||||
sprintf(buf, "%s%s\n", fmt, m_colors ? Log::kCL_N : "");
|
||||
|
||||
uv_mutex_lock(&m_mutex);
|
||||
|
||||
vfprintf(stdout, buf, ap);
|
||||
vfprintf(stdout, buf, args);
|
||||
fflush(stdout);
|
||||
|
||||
uv_mutex_unlock(&m_mutex);
|
||||
|
||||
va_end(ap);
|
||||
}
|
||||
|
||||
|
||||
Console::Console() :
|
||||
m_colors(true)
|
||||
{
|
||||
uv_mutex_init(&m_mutex);
|
||||
}
|
||||
43
src/log/ConsoleLog.h
Normal file
43
src/log/ConsoleLog.h
Normal file
@@ -0,0 +1,43 @@
|
||||
/* XMRig
|
||||
* Copyright 2010 Jeff Garzik <jgarzik@pobox.com>
|
||||
* Copyright 2012-2014 pooler <pooler@litecoinpool.org>
|
||||
* Copyright 2014 Lucas Jones <https://github.com/lucasjones>
|
||||
* Copyright 2014-2016 Wolf9466 <https://github.com/OhGodAPet>
|
||||
* Copyright 2016 Jay D Dee <jayddee246@gmail.com>
|
||||
* Copyright 2016-2017 XMRig <support@xmrig.com>
|
||||
*
|
||||
*
|
||||
* 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef __CONSOLELOG_H__
|
||||
#define __CONSOLELOG_H__
|
||||
|
||||
|
||||
#include "interfaces/ILogBackend.h"
|
||||
|
||||
|
||||
class ConsoleLog : public ILogBackend
|
||||
{
|
||||
public:
|
||||
ConsoleLog(bool colors);
|
||||
|
||||
void message(int level, const char* fmt, va_list args) override;
|
||||
void text(const char* fmt, va_list args) override;
|
||||
|
||||
private:
|
||||
bool m_colors;
|
||||
};
|
||||
|
||||
#endif /* __CONSOLELOG_H__ */
|
||||
103
src/log/FileLog.cpp
Normal file
103
src/log/FileLog.cpp
Normal file
@@ -0,0 +1,103 @@
|
||||
/* XMRig
|
||||
* Copyright 2010 Jeff Garzik <jgarzik@pobox.com>
|
||||
* Copyright 2012-2014 pooler <pooler@litecoinpool.org>
|
||||
* Copyright 2014 Lucas Jones <https://github.com/lucasjones>
|
||||
* Copyright 2014-2016 Wolf9466 <https://github.com/OhGodAPet>
|
||||
* Copyright 2016 Jay D Dee <jayddee246@gmail.com>
|
||||
* Copyright 2016-2017 XMRig <support@xmrig.com>
|
||||
*
|
||||
*
|
||||
* 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
|
||||
#include <stdarg.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
|
||||
|
||||
#ifdef WIN32
|
||||
# include <winsock2.h>
|
||||
# include <malloc.h>
|
||||
# include "3rdparty/winansi.h"
|
||||
#endif
|
||||
|
||||
|
||||
#include "log/FileLog.h"
|
||||
|
||||
|
||||
FileLog::FileLog(const char *fileName)
|
||||
{
|
||||
uv_fs_t req;
|
||||
m_file = uv_fs_open(uv_default_loop(), &req, fileName, O_CREAT | O_APPEND | O_WRONLY, 0644, nullptr);
|
||||
uv_fs_req_cleanup(&req);
|
||||
}
|
||||
|
||||
|
||||
void FileLog::message(int level, const char* fmt, va_list args)
|
||||
{
|
||||
if (m_file < 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
time_t now = time(nullptr);
|
||||
tm stime;
|
||||
|
||||
# ifdef _WIN32
|
||||
localtime_s(&stime, &now);
|
||||
# else
|
||||
localtime_r(&now, &stime);
|
||||
# endif
|
||||
|
||||
char *buf = static_cast<char*>(malloc(512));
|
||||
int size = snprintf(buf, 23, "[%d-%02d-%02d %02d:%02d:%02d] ",
|
||||
stime.tm_year + 1900,
|
||||
stime.tm_mon + 1,
|
||||
stime.tm_mday,
|
||||
stime.tm_hour,
|
||||
stime.tm_min,
|
||||
stime.tm_sec);
|
||||
|
||||
size = vsnprintf(buf + size, 512 - size - 1, fmt, args) + size;
|
||||
buf[size] = '\n';
|
||||
|
||||
write(buf, size + 1);
|
||||
}
|
||||
|
||||
|
||||
void FileLog::text(const char* fmt, va_list args)
|
||||
{
|
||||
message(0, fmt, args);
|
||||
}
|
||||
|
||||
|
||||
|
||||
void FileLog::onWrite(uv_fs_t *req)
|
||||
{
|
||||
free(req->data);
|
||||
|
||||
uv_fs_req_cleanup(req);
|
||||
free(req);
|
||||
}
|
||||
|
||||
|
||||
void FileLog::write(char *data, size_t size)
|
||||
{
|
||||
uv_buf_t buf = uv_buf_init(data, size);
|
||||
uv_fs_t *req = static_cast<uv_fs_t*>(malloc(sizeof(uv_fs_t)));
|
||||
req->data = buf.base;
|
||||
|
||||
uv_fs_write(uv_default_loop(), req, m_file, &buf, 1, 0, FileLog::onWrite);
|
||||
}
|
||||
50
src/log/FileLog.h
Normal file
50
src/log/FileLog.h
Normal file
@@ -0,0 +1,50 @@
|
||||
/* XMRig
|
||||
* Copyright 2010 Jeff Garzik <jgarzik@pobox.com>
|
||||
* Copyright 2012-2014 pooler <pooler@litecoinpool.org>
|
||||
* Copyright 2014 Lucas Jones <https://github.com/lucasjones>
|
||||
* Copyright 2014-2016 Wolf9466 <https://github.com/OhGodAPet>
|
||||
* Copyright 2016 Jay D Dee <jayddee246@gmail.com>
|
||||
* Copyright 2016-2017 XMRig <support@xmrig.com>
|
||||
*
|
||||
*
|
||||
* 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef __FILELOG_H__
|
||||
#define __FILELOG_H__
|
||||
|
||||
|
||||
#include <uv.h>
|
||||
|
||||
|
||||
#include "interfaces/ILogBackend.h"
|
||||
|
||||
|
||||
class FileLog : public ILogBackend
|
||||
{
|
||||
public:
|
||||
FileLog(const char *fileName);
|
||||
|
||||
void message(int level, const char* fmt, va_list args) override;
|
||||
void text(const char* fmt, va_list args) override;
|
||||
|
||||
private:
|
||||
static void onWrite(uv_fs_t *req);
|
||||
|
||||
void write(char *data, size_t size);
|
||||
|
||||
int m_file;
|
||||
};
|
||||
|
||||
#endif /* __FILELOG_H__ */
|
||||
79
src/log/Log.cpp
Normal file
79
src/log/Log.cpp
Normal file
@@ -0,0 +1,79 @@
|
||||
/* XMRig
|
||||
* Copyright 2010 Jeff Garzik <jgarzik@pobox.com>
|
||||
* Copyright 2012-2014 pooler <pooler@litecoinpool.org>
|
||||
* Copyright 2014 Lucas Jones <https://github.com/lucasjones>
|
||||
* Copyright 2014-2016 Wolf9466 <https://github.com/OhGodAPet>
|
||||
* Copyright 2016 Jay D Dee <jayddee246@gmail.com>
|
||||
* Copyright 2016-2017 XMRig <support@xmrig.com>
|
||||
*
|
||||
*
|
||||
* 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
|
||||
#include <stdarg.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
|
||||
|
||||
#ifdef WIN32
|
||||
# include <winsock2.h>
|
||||
# include <malloc.h>
|
||||
# include "3rdparty/winansi.h"
|
||||
#endif
|
||||
|
||||
#include "interfaces/ILogBackend.h"
|
||||
#include "log/Log.h"
|
||||
|
||||
|
||||
Log *Log::m_self = nullptr;
|
||||
|
||||
|
||||
void Log::message(Log::Level level, const char* fmt, ...)
|
||||
{
|
||||
va_list args;
|
||||
va_list copy;
|
||||
va_start(args, fmt);
|
||||
|
||||
for (ILogBackend *backend : m_backends) {
|
||||
va_copy(copy, args);
|
||||
backend->message(level, fmt, copy);
|
||||
va_end(copy);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Log::text(const char* fmt, ...)
|
||||
{
|
||||
va_list args;
|
||||
va_list copy;
|
||||
va_start(args, fmt);
|
||||
|
||||
for (ILogBackend *backend : m_backends) {
|
||||
va_copy(copy, args);
|
||||
backend->text(fmt, copy);
|
||||
va_end(copy);
|
||||
}
|
||||
|
||||
va_end(args);
|
||||
}
|
||||
|
||||
|
||||
Log::~Log()
|
||||
{
|
||||
for (auto backend : m_backends) {
|
||||
delete backend;
|
||||
}
|
||||
}
|
||||
@@ -21,14 +21,18 @@
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef __CONSOLE_H__
|
||||
#define __CONSOLE_H__
|
||||
#ifndef __LOG_H__
|
||||
#define __LOG_H__
|
||||
|
||||
|
||||
#include <uv.h>
|
||||
#include <vector>
|
||||
|
||||
|
||||
class Console
|
||||
class ILogBackend;
|
||||
|
||||
|
||||
class Log
|
||||
{
|
||||
public:
|
||||
enum Level {
|
||||
@@ -50,34 +54,35 @@ public:
|
||||
constexpr static const char* kCL_GRAY = "\x1B[90m";
|
||||
# endif
|
||||
|
||||
static inline Console* i() { return m_self; }
|
||||
static void init();
|
||||
static inline Log* i() { return m_self; }
|
||||
static inline void add(ILogBackend *backend) { i()->m_backends.push_back(backend); }
|
||||
static inline void init() { if (!m_self) { m_self = new Log();} }
|
||||
|
||||
void message(Level level, const char* fmt, ...);
|
||||
void text(const char* fmt, ...);
|
||||
|
||||
private:
|
||||
Console();
|
||||
inline Log() {}
|
||||
~Log();
|
||||
|
||||
static Console *m_self;
|
||||
bool m_colors;
|
||||
uv_mutex_t m_mutex;
|
||||
static Log *m_self;
|
||||
std::vector<ILogBackend*> m_backends;
|
||||
};
|
||||
|
||||
|
||||
#define LOG_ERR(x, ...) Console::i()->message(Console::ERR, x, ##__VA_ARGS__)
|
||||
#define LOG_WARN(x, ...) Console::i()->message(Console::WARNING, x, ##__VA_ARGS__)
|
||||
#define LOG_NOTICE(x, ...) Console::i()->message(Console::NOTICE, x, ##__VA_ARGS__)
|
||||
#define LOG_INFO(x, ...) Console::i()->message(Console::INFO, x, ##__VA_ARGS__)
|
||||
#define LOG_ERR(x, ...) Log::i()->message(Log::ERR, x, ##__VA_ARGS__)
|
||||
#define LOG_WARN(x, ...) Log::i()->message(Log::WARNING, x, ##__VA_ARGS__)
|
||||
#define LOG_NOTICE(x, ...) Log::i()->message(Log::NOTICE, x, ##__VA_ARGS__)
|
||||
#define LOG_INFO(x, ...) Log::i()->message(Log::INFO, x, ##__VA_ARGS__)
|
||||
|
||||
#ifdef APP_DEBUG
|
||||
# define LOG_DEBUG(x, ...) Console::i()->message(Console::DEBUG, x, ##__VA_ARGS__)
|
||||
# define LOG_DEBUG_ERR(x, ...) Console::i()->message(Console::ERR, x, ##__VA_ARGS__)
|
||||
# define LOG_DEBUG_WARN(x, ...) Console::i()->message(Console::WARNING, x, ##__VA_ARGS__)
|
||||
# define LOG_DEBUG(x, ...) Log::i()->message(Log::DEBUG, x, ##__VA_ARGS__)
|
||||
# define LOG_DEBUG_ERR(x, ...) Log::i()->message(Log::ERR, x, ##__VA_ARGS__)
|
||||
# define LOG_DEBUG_WARN(x, ...) Log::i()->message(Log::WARNING, x, ##__VA_ARGS__)
|
||||
#else
|
||||
# define LOG_DEBUG(x, ...)
|
||||
# define LOG_DEBUG_ERR(x, ...)
|
||||
# define LOG_DEBUG_WARN(x, ...)
|
||||
#endif
|
||||
|
||||
#endif /* __CONSOLE_H__ */
|
||||
#endif /* __LOG_H__ */
|
||||
47
src/log/SysLog.cpp
Normal file
47
src/log/SysLog.cpp
Normal file
@@ -0,0 +1,47 @@
|
||||
/* XMRig
|
||||
* Copyright 2010 Jeff Garzik <jgarzik@pobox.com>
|
||||
* Copyright 2012-2014 pooler <pooler@litecoinpool.org>
|
||||
* Copyright 2014 Lucas Jones <https://github.com/lucasjones>
|
||||
* Copyright 2014-2016 Wolf9466 <https://github.com/OhGodAPet>
|
||||
* Copyright 2016 Jay D Dee <jayddee246@gmail.com>
|
||||
* Copyright 2016-2017 XMRig <support@xmrig.com>
|
||||
*
|
||||
*
|
||||
* 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
|
||||
#include <syslog.h>
|
||||
|
||||
|
||||
#include "log/SysLog.h"
|
||||
#include "version.h"
|
||||
|
||||
|
||||
SysLog::SysLog()
|
||||
{
|
||||
openlog(APP_ID, LOG_PID, LOG_USER);
|
||||
}
|
||||
|
||||
|
||||
void SysLog::message(int level, const char *fmt, va_list args)
|
||||
{
|
||||
vsyslog(level, fmt, args);
|
||||
}
|
||||
|
||||
|
||||
void SysLog::text(const char *fmt, va_list args)
|
||||
{
|
||||
message(LOG_INFO, fmt, args);
|
||||
}
|
||||
40
src/log/SysLog.h
Normal file
40
src/log/SysLog.h
Normal file
@@ -0,0 +1,40 @@
|
||||
/* XMRig
|
||||
* Copyright 2010 Jeff Garzik <jgarzik@pobox.com>
|
||||
* Copyright 2012-2014 pooler <pooler@litecoinpool.org>
|
||||
* Copyright 2014 Lucas Jones <https://github.com/lucasjones>
|
||||
* Copyright 2014-2016 Wolf9466 <https://github.com/OhGodAPet>
|
||||
* Copyright 2016 Jay D Dee <jayddee246@gmail.com>
|
||||
* Copyright 2016-2017 XMRig <support@xmrig.com>
|
||||
*
|
||||
*
|
||||
* 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef __SYSLOG_H__
|
||||
#define __SYSLOG_H__
|
||||
|
||||
|
||||
#include "interfaces/ILogBackend.h"
|
||||
|
||||
|
||||
class SysLog : public ILogBackend
|
||||
{
|
||||
public:
|
||||
SysLog();
|
||||
|
||||
void message(int level, const char *fmt, va_list args) override;
|
||||
void text(const char *fmt, va_list args) override;
|
||||
};
|
||||
|
||||
#endif /* __SYSLOG_BACKEND_H__ */
|
||||
@@ -21,42 +21,52 @@
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
|
||||
#include <inttypes.h>
|
||||
#include <iterator>
|
||||
#include <string.h>
|
||||
#include <utility>
|
||||
|
||||
|
||||
#include "Console.h"
|
||||
#include "log/Log.h"
|
||||
#include "interfaces/IClientListener.h"
|
||||
#include "net/Client.h"
|
||||
#include "net/JobResult.h"
|
||||
#include "net/Url.h"
|
||||
|
||||
|
||||
#ifdef XMRIG_PROXY_PROJECT
|
||||
# include "proxy/JobResult.h"
|
||||
#else
|
||||
# include "net/JobResult.h"
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef _MSC_VER
|
||||
# define strncasecmp(x,y,z) _strnicmp(x,y,z)
|
||||
#endif
|
||||
|
||||
|
||||
Client::Client(int id, IClientListener *listener) :
|
||||
m_keepAlive(false),
|
||||
m_host(nullptr),
|
||||
int64_t Client::m_sequence = 1;
|
||||
|
||||
|
||||
Client::Client(int id, const char *agent, IClientListener *listener) :
|
||||
m_quiet(false),
|
||||
m_agent(agent),
|
||||
m_listener(listener),
|
||||
m_id(id),
|
||||
m_retryPause(5000),
|
||||
m_failures(0),
|
||||
m_sequence(1),
|
||||
m_recvBufPos(0),
|
||||
m_state(UnconnectedState),
|
||||
m_port(0),
|
||||
m_stream(nullptr),
|
||||
m_socket(nullptr)
|
||||
{
|
||||
memset(m_ip, 0, sizeof(m_ip));
|
||||
memset(&m_hints, 0, sizeof(m_hints));
|
||||
|
||||
m_resolver.data = m_responseTimer.data = m_retriesTimer.data = m_keepAliveTimer.data = this;
|
||||
|
||||
m_hints.ai_family = PF_INET;
|
||||
m_hints.ai_socktype = SOCK_STREAM;
|
||||
m_hints.ai_protocol = IPPROTO_TCP;
|
||||
m_hints.ai_flags = 0;
|
||||
|
||||
m_recvBuf.base = static_cast<char*>(malloc(kRecvBufSize));
|
||||
m_recvBuf.len = kRecvBufSize;
|
||||
@@ -72,13 +82,41 @@ Client::~Client()
|
||||
{
|
||||
free(m_recvBuf.base);
|
||||
free(m_socket);
|
||||
free(m_host);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Send raw data to server.
|
||||
*
|
||||
* @param data
|
||||
*/
|
||||
int64_t Client::send(char *data, size_t size)
|
||||
{
|
||||
LOG_DEBUG("[%s:%u] send (%d bytes): \"%s\"", m_url.host(), m_url.port(), size ? size : strlen(data), data);
|
||||
if (state() != ConnectedState) {
|
||||
LOG_DEBUG_ERR("[%s:%u] send failed, invalid state: %d", m_url.host(), m_url.port(), m_state);
|
||||
return -1;
|
||||
}
|
||||
|
||||
uv_buf_t buf = uv_buf_init(data, size ? size : strlen(data));
|
||||
|
||||
uv_write_t *req = static_cast<uv_write_t*>(malloc(sizeof(uv_write_t)));
|
||||
req->data = buf.base;
|
||||
|
||||
uv_write(req, m_stream, &buf, 1, [](uv_write_t *req, int status) {
|
||||
free(req->data);
|
||||
free(req);
|
||||
});
|
||||
|
||||
uv_timer_start(&m_responseTimer, [](uv_timer_t *handle) { getClient(handle->data)->close(); }, kResponseTimeout, 0);
|
||||
|
||||
return m_sequence++;
|
||||
}
|
||||
|
||||
|
||||
void Client::connect()
|
||||
{
|
||||
resolve(m_host);
|
||||
resolve(m_url.host());
|
||||
}
|
||||
|
||||
|
||||
@@ -90,73 +128,39 @@ void Client::connect()
|
||||
void Client::connect(const Url *url)
|
||||
{
|
||||
setUrl(url);
|
||||
resolve(m_host);
|
||||
resolve(m_url.host());
|
||||
}
|
||||
|
||||
|
||||
void Client::disconnect()
|
||||
{
|
||||
uv_timer_stop(&m_keepAliveTimer);
|
||||
uv_timer_stop(&m_responseTimer);
|
||||
uv_timer_stop(&m_retriesTimer);
|
||||
m_failures = -1;
|
||||
|
||||
close();
|
||||
}
|
||||
|
||||
|
||||
void Client::login(const char *user, const char *pass, const char *agent)
|
||||
{
|
||||
m_sequence = 1;
|
||||
|
||||
const size_t size = 96 + strlen(user) + strlen(pass) + strlen(agent);
|
||||
char *req = static_cast<char*>(malloc(size));
|
||||
snprintf(req, size, "{\"id\":%llu,\"jsonrpc\":\"2.0\",\"method\":\"login\",\"params\":{\"login\":\"%s\",\"pass\":\"%s\",\"agent\":\"%s\"}}\n", m_sequence, user, pass, agent);
|
||||
|
||||
send(req);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Send raw data to server.
|
||||
*
|
||||
* @param data
|
||||
*/
|
||||
void Client::send(char *data)
|
||||
{
|
||||
LOG_DEBUG("[%s:%u] send (%d bytes): \"%s\"", m_host, m_port, strlen(data), data);
|
||||
if (state() != ConnectedState) {
|
||||
LOG_DEBUG_ERR("[%s:%u] send failed, invalid state: %d", m_host, m_port, m_state);
|
||||
return;
|
||||
}
|
||||
|
||||
m_sequence++;
|
||||
uv_buf_t buf = uv_buf_init(data, strlen(data));
|
||||
|
||||
uv_write_t *req = static_cast<uv_write_t*>(malloc(sizeof(uv_write_t)));
|
||||
req->data = buf.base;
|
||||
|
||||
uv_write(req, m_stream, &buf, 1, [](uv_write_t *req, int status) {
|
||||
free(req->data);
|
||||
free(req);
|
||||
});
|
||||
|
||||
uv_timer_start(&m_responseTimer, [](uv_timer_t *handle) { getClient(handle->data)->close(); }, kResponseTimeout, 0);
|
||||
}
|
||||
|
||||
|
||||
void Client::setUrl(const Url *url)
|
||||
{
|
||||
if (!url || !url->isValid()) {
|
||||
return;
|
||||
}
|
||||
|
||||
free(m_host);
|
||||
m_host = strdup(url->host());
|
||||
m_port = url->port();
|
||||
m_url = url;
|
||||
}
|
||||
|
||||
|
||||
void Client::submit(const JobResult &result)
|
||||
int64_t Client::submit(const JobResult &result)
|
||||
{
|
||||
char *req = static_cast<char*>(malloc(345));
|
||||
|
||||
# ifdef XMRIG_PROXY_PROJECT
|
||||
const char *nonce = result.nonce;
|
||||
const char *data = result.result;
|
||||
# else
|
||||
char nonce[9];
|
||||
char data[65];
|
||||
|
||||
@@ -165,11 +169,13 @@ void Client::submit(const JobResult &result)
|
||||
|
||||
Job::toHex(result.result, 32, data);
|
||||
data[64] = '\0';
|
||||
# endif
|
||||
|
||||
snprintf(req, 345, "{\"id\":%llu,\"jsonrpc\":\"2.0\",\"method\":\"submit\",\"params\":{\"id\":\"%s\",\"job_id\":\"%s\",\"nonce\":\"%s\",\"result\":\"%s\"}}\n",
|
||||
snprintf(req, 345, "{\"id\":%" PRIu64 ",\"jsonrpc\":\"2.0\",\"method\":\"submit\",\"params\":{\"id\":\"%s\",\"job_id\":\"%s\",\"nonce\":\"%s\",\"result\":\"%s\"}}\n",
|
||||
m_sequence, m_rpcId, result.jobId, nonce, data);
|
||||
|
||||
send(req);
|
||||
m_results[m_sequence] = SubmitResult(m_sequence, result.diff);
|
||||
return send(req);
|
||||
}
|
||||
|
||||
|
||||
@@ -180,7 +186,7 @@ bool Client::parseJob(const json_t *params, int *code)
|
||||
return false;
|
||||
}
|
||||
|
||||
Job job;
|
||||
Job job(m_id, m_url.isNicehash());
|
||||
if (!job.setId(json_string_value(json_object_get(params, "job_id")))) {
|
||||
*code = 3;
|
||||
return false;
|
||||
@@ -196,10 +202,12 @@ bool Client::parseJob(const json_t *params, int *code)
|
||||
return false;
|
||||
}
|
||||
|
||||
job.setPoolId(m_id);
|
||||
m_job = std::move(job);
|
||||
if (m_job == job) {
|
||||
LOG_WARN("[%s:%u] duplicate job received, ignore", m_url.host(), m_url.port());
|
||||
return false;
|
||||
}
|
||||
|
||||
LOG_DEBUG("[%s:%u] job: \"%s\", diff: %lld", m_host, m_port, job.id(), job.diff());
|
||||
m_job = std::move(job);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -225,9 +233,15 @@ int Client::resolve(const char *host)
|
||||
|
||||
m_recvBufPos = 0;
|
||||
|
||||
if (m_failures == -1) {
|
||||
m_failures = 0;
|
||||
}
|
||||
|
||||
const int r = uv_getaddrinfo(uv_default_loop(), &m_resolver, Client::onResolved, host, NULL, &m_hints);
|
||||
if (r) {
|
||||
LOG_ERR("[%s:%u] getaddrinfo error: \"%s\"", host, m_port, uv_strerror(r));
|
||||
if (!m_quiet) {
|
||||
LOG_ERR("[%s:%u] getaddrinfo error: \"%s\"", host, m_url.port(), uv_strerror(r));
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -242,7 +256,10 @@ void Client::close()
|
||||
}
|
||||
|
||||
setState(ClosingState);
|
||||
uv_close(reinterpret_cast<uv_handle_t*>(m_socket), Client::onClose);
|
||||
|
||||
if (uv_is_closing(reinterpret_cast<uv_handle_t*>(m_socket)) == 0) {
|
||||
uv_close(reinterpret_cast<uv_handle_t*>(m_socket), Client::onClose);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -250,7 +267,7 @@ void Client::connect(struct sockaddr *addr)
|
||||
{
|
||||
setState(ConnectingState);
|
||||
|
||||
reinterpret_cast<struct sockaddr_in*>(addr)->sin_port = htons(m_port);
|
||||
reinterpret_cast<struct sockaddr_in*>(addr)->sin_port = htons(m_url.port());
|
||||
free(m_socket);
|
||||
|
||||
uv_connect_t *req = (uv_connect_t*) malloc(sizeof(uv_connect_t));
|
||||
@@ -261,9 +278,39 @@ void Client::connect(struct sockaddr *addr)
|
||||
|
||||
uv_tcp_init(uv_default_loop(), m_socket);
|
||||
uv_tcp_nodelay(m_socket, 1);
|
||||
uv_tcp_keepalive(m_socket, 1, 60);
|
||||
|
||||
uv_tcp_connect(req, m_socket, (const sockaddr*) addr, Client::onConnect);
|
||||
# ifndef WIN32
|
||||
uv_tcp_keepalive(m_socket, 1, 60);
|
||||
# endif
|
||||
|
||||
uv_tcp_connect(req, m_socket, reinterpret_cast<const sockaddr*>(addr), Client::onConnect);
|
||||
}
|
||||
|
||||
|
||||
void Client::login()
|
||||
{
|
||||
m_results.clear();
|
||||
|
||||
json_t *req = json_object();
|
||||
json_object_set(req, "id", json_integer(1));
|
||||
json_object_set(req, "jsonrpc", json_string("2.0"));
|
||||
json_object_set(req, "method", json_string("login"));
|
||||
|
||||
json_t *params = json_object();
|
||||
json_object_set(params, "login", json_string(m_url.user()));
|
||||
json_object_set(params, "pass", json_string(m_url.password()));
|
||||
json_object_set(params, "agent", json_string(m_agent));
|
||||
|
||||
json_object_set(req, "params", params);
|
||||
|
||||
char *buf = json_dumps(req, JSON_COMPACT);
|
||||
const size_t size = strlen(buf);
|
||||
|
||||
buf[size] = '\n';
|
||||
|
||||
json_decref(req);
|
||||
|
||||
send(buf, size + 1);
|
||||
}
|
||||
|
||||
|
||||
@@ -273,13 +320,15 @@ void Client::parse(char *line, size_t len)
|
||||
|
||||
line[len - 1] = '\0';
|
||||
|
||||
LOG_DEBUG("[%s:%u] received (%d bytes): \"%s\"", m_host, m_port, len, line);
|
||||
LOG_DEBUG("[%s:%u] received (%d bytes): \"%s\"", m_url.host(), m_url.port(), len, line);
|
||||
|
||||
json_error_t err;
|
||||
json_t *val = json_loads(line, 0, &err);
|
||||
|
||||
if (!val) {
|
||||
LOG_ERR("[%s:%u] JSON decode failed: \"%s\"", m_host, m_port, err.text);
|
||||
if (!m_quiet) {
|
||||
LOG_ERR("[%s:%u] JSON decode failed: \"%s\"", m_url.host(), m_url.port(), err.text);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -298,7 +347,9 @@ void Client::parse(char *line, size_t len)
|
||||
void Client::parseNotification(const char *method, const json_t *params, const json_t *error)
|
||||
{
|
||||
if (json_is_object(error)) {
|
||||
LOG_ERR("[%s:%u] error: \"%s\", code: %lld", m_host, m_port, json_string_value(json_object_get(error, "message")), json_integer_value(json_object_get(error, "code")));
|
||||
if (!m_quiet) {
|
||||
LOG_ERR("[%s:%u] error: \"%s\", code: %" PRId64, m_url.host(), m_url.port(), json_string_value(json_object_get(error, "message")), json_integer_value(json_object_get(error, "code")));
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -315,7 +366,7 @@ void Client::parseNotification(const char *method, const json_t *params, const j
|
||||
return;
|
||||
}
|
||||
|
||||
LOG_WARN("[%s:%u] unsupported method: \"%s\"", m_host, m_port, method);
|
||||
LOG_WARN("[%s:%u] unsupported method: \"%s\"", m_url.host(), m_url.port(), method);
|
||||
}
|
||||
|
||||
|
||||
@@ -323,7 +374,15 @@ void Client::parseResponse(int64_t id, const json_t *result, const json_t *error
|
||||
{
|
||||
if (json_is_object(error)) {
|
||||
const char *message = json_string_value(json_object_get(error, "message"));
|
||||
LOG_ERR("[%s:%u] error: \"%s\", code: %lld", m_host, m_port, message, json_integer_value(json_object_get(error, "code")));
|
||||
|
||||
auto it = m_results.find(id);
|
||||
if (it != m_results.end()) {
|
||||
m_listener->onResultAccepted(this, it->second.seq, it->second.diff, it->second.elapsed(), message);
|
||||
m_results.erase(it);
|
||||
}
|
||||
else if (!m_quiet) {
|
||||
LOG_ERR("[%s:%u] error: \"%s\", code: %" PRId64, m_url.host(), m_url.port(), message, json_integer_value(json_object_get(error, "code")));
|
||||
}
|
||||
|
||||
if (id == 1 || (message && strncasecmp(message, "Unauthenticated", 15) == 0)) {
|
||||
close();
|
||||
@@ -339,7 +398,10 @@ void Client::parseResponse(int64_t id, const json_t *result, const json_t *error
|
||||
if (id == 1) {
|
||||
int code = -1;
|
||||
if (!parseLogin(result, &code)) {
|
||||
LOG_ERR("[%s:%u] login error code: %d", m_host, m_port, code);
|
||||
if (!m_quiet) {
|
||||
LOG_ERR("[%s:%u] login error code: %d", m_url.host(), m_url.port(), code);
|
||||
}
|
||||
|
||||
return close();
|
||||
}
|
||||
|
||||
@@ -348,13 +410,19 @@ void Client::parseResponse(int64_t id, const json_t *result, const json_t *error
|
||||
m_listener->onJobReceived(this, m_job);
|
||||
return;
|
||||
}
|
||||
|
||||
auto it = m_results.find(id);
|
||||
if (it != m_results.end()) {
|
||||
m_listener->onResultAccepted(this, it->second.seq, it->second.diff, it->second.elapsed(), nullptr);
|
||||
m_results.erase(it);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Client::ping()
|
||||
{
|
||||
char *req = static_cast<char*>(malloc(128));
|
||||
snprintf(req, 128, "{\"id\":%lld,\"jsonrpc\":\"2.0\",\"method\":\"keepalived\",\"params\":{\"id\":\"%s\"}}\n", m_sequence, m_rpcId);
|
||||
char *req = static_cast<char*>(malloc(160));
|
||||
snprintf(req, 160, "{\"id\":%" PRId64 ",\"jsonrpc\":\"2.0\",\"method\":\"keepalived\",\"params\":{\"id\":\"%s\"}}\n", m_sequence, m_rpcId);
|
||||
|
||||
send(req);
|
||||
}
|
||||
@@ -362,8 +430,10 @@ void Client::ping()
|
||||
|
||||
void Client::reconnect()
|
||||
{
|
||||
setState(ConnectingState);
|
||||
|
||||
uv_timer_stop(&m_responseTimer);
|
||||
if (m_keepAlive) {
|
||||
if (m_url.isKeepAlive()) {
|
||||
uv_timer_stop(&m_keepAliveTimer);
|
||||
}
|
||||
|
||||
@@ -380,7 +450,7 @@ void Client::reconnect()
|
||||
|
||||
void Client::setState(SocketState state)
|
||||
{
|
||||
LOG_DEBUG("[%s:%u] state: %d", m_host, m_port, state);
|
||||
LOG_DEBUG("[%s:%u] state: %d", m_url.host(), m_url.port(), state);
|
||||
|
||||
if (m_state == state) {
|
||||
return;
|
||||
@@ -393,7 +463,7 @@ void Client::setState(SocketState state)
|
||||
void Client::startTimeout()
|
||||
{
|
||||
uv_timer_stop(&m_responseTimer);
|
||||
if (!m_keepAlive) {
|
||||
if (!m_url.isKeepAlive()) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -428,7 +498,10 @@ void Client::onConnect(uv_connect_t *req, int status)
|
||||
{
|
||||
auto client = getClient(req->data);
|
||||
if (status < 0) {
|
||||
LOG_ERR("[%s:%u] connect error: \"%s\"", client->m_host, client->m_port, uv_strerror(status));
|
||||
if (!client->m_quiet) {
|
||||
LOG_ERR("[%s:%u] connect error: \"%s\"", client->m_url.host(), client->m_url.port(), uv_strerror(status));
|
||||
}
|
||||
|
||||
free(req);
|
||||
client->close();
|
||||
return;
|
||||
@@ -441,7 +514,7 @@ void Client::onConnect(uv_connect_t *req, int status)
|
||||
uv_read_start(client->m_stream, Client::onAllocBuffer, Client::onRead);
|
||||
free(req);
|
||||
|
||||
client->m_listener->onLoginCredentialsRequired(client);
|
||||
client->login();
|
||||
}
|
||||
|
||||
|
||||
@@ -449,8 +522,8 @@ void Client::onRead(uv_stream_t *stream, ssize_t nread, const uv_buf_t *buf)
|
||||
{
|
||||
auto client = getClient(stream->data);
|
||||
if (nread < 0) {
|
||||
if (nread != UV_EOF) {
|
||||
LOG_ERR("[%s:%u] read error: \"%s\"", client->m_host, client->m_port, uv_strerror(nread));
|
||||
if (nread != UV_EOF && !client->m_quiet) {
|
||||
LOG_ERR("[%s:%u] read error: \"%s\"", client->m_url.host(), client->m_url.port(), uv_strerror(nread));
|
||||
}
|
||||
|
||||
return client->close();;
|
||||
@@ -489,16 +562,30 @@ void Client::onResolved(uv_getaddrinfo_t *req, int status, struct addrinfo *res)
|
||||
{
|
||||
auto client = getClient(req->data);
|
||||
if (status < 0) {
|
||||
LOG_ERR("[%s:%u] DNS error: \"%s\"", client->m_host, client->m_port, uv_strerror(status));
|
||||
LOG_ERR("[%s:%u] DNS error: \"%s\"", client->m_url.host(), client->m_url.port(), uv_strerror(status));
|
||||
return client->reconnect();;
|
||||
}
|
||||
|
||||
client->connect(res->ai_addr);
|
||||
addrinfo *ptr = res;
|
||||
std::vector<addrinfo*> ipv4;
|
||||
|
||||
while (ptr != nullptr) {
|
||||
if (ptr->ai_family == AF_INET) {
|
||||
ipv4.push_back(ptr);
|
||||
}
|
||||
|
||||
ptr = ptr->ai_next;
|
||||
}
|
||||
|
||||
if (ipv4.empty()) {
|
||||
LOG_ERR("[%s:%u] DNS error: \"No IPv4 records found\"", client->m_url.host(), client->m_url.port());
|
||||
return client->reconnect();
|
||||
}
|
||||
|
||||
ptr = ipv4[rand() % ipv4.size()];
|
||||
|
||||
uv_ip4_name(reinterpret_cast<sockaddr_in*>(ptr->ai_addr), client->m_ip, 16);
|
||||
|
||||
client->connect(ptr->ai_addr);
|
||||
uv_freeaddrinfo(res);
|
||||
}
|
||||
|
||||
|
||||
Client *Client::getClient(void *data)
|
||||
{
|
||||
return static_cast<Client*>(data);
|
||||
}
|
||||
|
||||
@@ -26,15 +26,17 @@
|
||||
|
||||
|
||||
#include <jansson.h>
|
||||
#include <map>
|
||||
#include <uv.h>
|
||||
|
||||
|
||||
#include "net/Job.h"
|
||||
#include "net/SubmitResult.h"
|
||||
#include "net/Url.h"
|
||||
|
||||
|
||||
class IClientListener;
|
||||
class JobResult;
|
||||
class Url;
|
||||
|
||||
|
||||
class Client
|
||||
@@ -48,27 +50,27 @@ public:
|
||||
ClosingState
|
||||
};
|
||||
|
||||
constexpr static int kResponseTimeout = 15 * 1000;
|
||||
constexpr static int kResponseTimeout = 20 * 1000;
|
||||
constexpr static int kKeepAliveTimeout = 60 * 1000;
|
||||
|
||||
Client(int id, IClientListener *listener);
|
||||
Client(int id, const char *agent, IClientListener *listener);
|
||||
~Client();
|
||||
|
||||
int64_t send(char *data, size_t size = 0);
|
||||
int64_t submit(const JobResult &result);
|
||||
void connect();
|
||||
void connect(const Url *url);
|
||||
void disconnect();
|
||||
void login(const char *user, const char *pass, const char *agent);
|
||||
void send(char *data);
|
||||
void setUrl(const Url *url);
|
||||
void submit(const JobResult &result);
|
||||
|
||||
inline bool isReady() const { return m_state == ConnectedState && m_failures == 0; }
|
||||
inline const char *host() const { return m_host; }
|
||||
inline const char *host() const { return m_url.host(); }
|
||||
inline const char *ip() const { return m_ip; }
|
||||
inline const Job &job() const { return m_job; }
|
||||
inline int id() const { return m_id; }
|
||||
inline SocketState state() const { return m_state; }
|
||||
inline uint16_t port() const { return m_port; }
|
||||
inline void setKeepAlive(bool keepAlive) { m_keepAlive = keepAlive; }
|
||||
inline uint16_t port() const { return m_url.port(); }
|
||||
inline void setQuiet(bool quiet) { m_quiet = quiet; }
|
||||
inline void setRetryPause(int ms) { m_retryPause = ms; }
|
||||
|
||||
private:
|
||||
@@ -79,6 +81,7 @@ private:
|
||||
int resolve(const char *host);
|
||||
void close();
|
||||
void connect(struct sockaddr *addr);
|
||||
void login();
|
||||
void parse(char *line, size_t len);
|
||||
void parseNotification(const char *method, const json_t *params, const json_t *error);
|
||||
void parseResponse(int64_t id, const json_t *result, const json_t *error);
|
||||
@@ -93,21 +96,23 @@ 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 Client *getClient(void *data);
|
||||
static inline Client *getClient(void *data) { return static_cast<Client*>(data); }
|
||||
|
||||
bool m_keepAlive;
|
||||
char *m_host;
|
||||
addrinfo m_hints;
|
||||
bool m_quiet;
|
||||
char m_ip[17];
|
||||
char m_rpcId[64];
|
||||
const char *m_agent;
|
||||
IClientListener *m_listener;
|
||||
int m_id;
|
||||
int m_retryPause;
|
||||
int64_t m_failures;
|
||||
int64_t m_sequence;
|
||||
Job m_job;
|
||||
size_t m_recvBufPos;
|
||||
SocketState m_state;
|
||||
struct addrinfo m_hints;
|
||||
uint16_t m_port;
|
||||
static int64_t m_sequence;
|
||||
std::map<int64_t, SubmitResult> m_results;
|
||||
Url m_url;
|
||||
uv_buf_t m_recvBuf;
|
||||
uv_getaddrinfo_t m_resolver;
|
||||
uv_stream_t *m_stream;
|
||||
|
||||
@@ -23,11 +23,10 @@
|
||||
|
||||
|
||||
#include <string.h>
|
||||
//#include <stdlib.h>
|
||||
|
||||
|
||||
#include "log/Log.h"
|
||||
#include "net/Job.h"
|
||||
#include "Console.h"
|
||||
|
||||
|
||||
static inline unsigned char hf_hex2bin(char c, bool &err)
|
||||
@@ -57,7 +56,8 @@ static inline char hf_bin2hex(unsigned char c)
|
||||
}
|
||||
|
||||
|
||||
Job::Job(int poolId) :
|
||||
Job::Job(int poolId, bool nicehash) :
|
||||
m_nicehash(nicehash),
|
||||
m_poolId(poolId),
|
||||
m_size(0),
|
||||
m_diff(0),
|
||||
@@ -82,7 +82,20 @@ bool Job::setBlob(const char *blob)
|
||||
return false;
|
||||
}
|
||||
|
||||
return fromHex(blob, m_size * 2, m_blob);
|
||||
if (!fromHex(blob, m_size * 2, m_blob)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (*nonce() != 0 && !m_nicehash) {
|
||||
m_nicehash = true;
|
||||
}
|
||||
|
||||
# ifdef XMRIG_PROXY_PROJECT
|
||||
memset(m_rawBlob, 0, sizeof(m_rawBlob));
|
||||
memcpy(m_rawBlob, blob, m_size * 2);
|
||||
# endif
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -130,6 +143,11 @@ bool Job::setTarget(const char *target)
|
||||
return false;
|
||||
}
|
||||
|
||||
# ifdef XMRIG_PROXY_PROJECT
|
||||
memset(m_rawTarget, 0, sizeof(m_rawTarget));
|
||||
memcpy(m_rawTarget, target, len);
|
||||
# endif
|
||||
|
||||
m_diff = toDiff(m_target);
|
||||
return true;
|
||||
}
|
||||
@@ -156,3 +174,9 @@ void Job::toHex(const unsigned char* in, unsigned int len, char* out)
|
||||
out[i * 2 + 1] = hf_bin2hex(in[i] & 0x0F);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool Job::operator==(const Job &other) const
|
||||
{
|
||||
return memcmp(m_id, other.m_id, sizeof(m_id)) == 0;
|
||||
}
|
||||
|
||||
@@ -34,33 +34,47 @@
|
||||
class Job
|
||||
{
|
||||
public:
|
||||
Job(int poolId = -2);
|
||||
Job(int poolId = -2, bool nicehash = false);
|
||||
bool setBlob(const char *blob);
|
||||
bool setId(const char *id);
|
||||
bool setTarget(const char *target);
|
||||
|
||||
inline bool isValid() const { return m_size > 0 && m_diff > 0; }
|
||||
inline const char *id() const { return m_id; }
|
||||
inline const uint8_t *blob() const { return m_blob; }
|
||||
inline int poolId() const { return m_poolId; }
|
||||
inline uint32_t *nonce() { return reinterpret_cast<uint32_t*>(m_blob + 39); }
|
||||
inline uint32_t diff() const { return m_diff; }
|
||||
inline uint32_t size() const { return m_size; }
|
||||
inline uint64_t target() const { return m_target; }
|
||||
inline void setPoolId(int poolId) { m_poolId = poolId; }
|
||||
inline bool isNicehash() const { return m_nicehash; }
|
||||
inline bool isValid() const { return m_size > 0 && m_diff > 0; }
|
||||
inline const char *id() const { return m_id; }
|
||||
inline const uint8_t *blob() const { return m_blob; }
|
||||
inline int poolId() const { return m_poolId; }
|
||||
inline uint32_t *nonce() { return reinterpret_cast<uint32_t*>(m_blob + 39); }
|
||||
inline uint32_t diff() const { return m_diff; }
|
||||
inline uint32_t size() const { return m_size; }
|
||||
inline uint64_t target() const { return m_target; }
|
||||
inline void setNicehash(bool nicehash) { m_nicehash = nicehash; }
|
||||
|
||||
# ifdef XMRIG_PROXY_PROJECT
|
||||
inline char *rawBlob() { return m_rawBlob; }
|
||||
inline const char *rawTarget() const { return m_rawTarget; }
|
||||
# endif
|
||||
|
||||
static bool fromHex(const char* in, unsigned int len, unsigned char* out);
|
||||
static inline uint32_t *nonce(uint8_t *blob) { return reinterpret_cast<uint32_t*>(blob + 39); }
|
||||
static inline uint64_t toDiff(uint64_t target) { return 0xFFFFFFFFFFFFFFFFULL / target; }
|
||||
static void toHex(const unsigned char* in, unsigned int len, char* out);
|
||||
|
||||
bool operator==(const Job &other) const;
|
||||
|
||||
private:
|
||||
bool m_nicehash;
|
||||
int m_poolId;
|
||||
VAR_ALIGN(16, char m_id[64]);
|
||||
VAR_ALIGN(16, uint8_t m_blob[84]); // Max blob size is 84 (75 fixed + 9 variable), aligned to 96. https://github.com/xmrig/xmrig/issues/1 Thanks fireice-uk.
|
||||
uint32_t m_size;
|
||||
uint64_t m_diff;
|
||||
uint64_t m_target;
|
||||
|
||||
# ifdef XMRIG_PROXY_PROJECT
|
||||
VAR_ALIGN(16, char m_rawBlob[169]);
|
||||
VAR_ALIGN(16, char m_rawTarget[17]);
|
||||
# endif
|
||||
};
|
||||
|
||||
#endif /* __JOB_H__ */
|
||||
|
||||
@@ -29,18 +29,32 @@
|
||||
#include <stdint.h>
|
||||
|
||||
|
||||
#include "Job.h"
|
||||
|
||||
|
||||
class JobResult
|
||||
{
|
||||
public:
|
||||
inline JobResult() : poolId(0), nonce(0) {}
|
||||
inline JobResult(int poolId, const char *jobId, uint32_t nonce, const uint8_t *result) : poolId(poolId), nonce(nonce)
|
||||
inline JobResult() : poolId(0), diff(0), nonce(0) {}
|
||||
inline JobResult(int poolId, const char *jobId, uint32_t nonce, const uint8_t *result, uint32_t diff) : poolId(poolId), diff(diff), nonce(nonce)
|
||||
{
|
||||
memcpy(this->jobId, jobId, sizeof(this->jobId));
|
||||
memcpy(this->result, result, sizeof(this->result));
|
||||
}
|
||||
|
||||
|
||||
inline JobResult &operator=(const Job &job) {
|
||||
memcpy(jobId, job.id(), sizeof(jobId));
|
||||
poolId = job.poolId();
|
||||
diff = job.diff();
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
char jobId[64];
|
||||
int poolId;
|
||||
uint32_t diff;
|
||||
uint32_t nonce;
|
||||
uint8_t result[32];
|
||||
};
|
||||
|
||||
@@ -22,82 +22,85 @@
|
||||
*/
|
||||
|
||||
|
||||
#include <inttypes.h>
|
||||
#include <memory>
|
||||
#include <time.h>
|
||||
|
||||
|
||||
#include "Console.h"
|
||||
#include "log/Log.h"
|
||||
#include "net/Client.h"
|
||||
#include "net/Network.h"
|
||||
#include "net/strategies/DonateStrategy.h"
|
||||
#include "net/strategies/FailoverStrategy.h"
|
||||
#include "net/strategies/SinglePoolStrategy.h"
|
||||
#include "net/Url.h"
|
||||
#include "Options.h"
|
||||
#include "workers/Workers.h"
|
||||
|
||||
|
||||
Network::Network(const Options *options) :
|
||||
m_donate(false),
|
||||
m_donateActive(false),
|
||||
m_options(options),
|
||||
m_pool(0),
|
||||
m_diff(0)
|
||||
m_donate(nullptr),
|
||||
m_accepted(0),
|
||||
m_rejected(0)
|
||||
{
|
||||
Workers::setListener(this);
|
||||
srand(time(0) ^ (uintptr_t) this);
|
||||
|
||||
m_pools.reserve(2);
|
||||
Workers::setListener(this);
|
||||
m_agent = userAgent();
|
||||
|
||||
addPool(std::make_unique<Url>().get());
|
||||
addPool(m_options->url());
|
||||
addPool(m_options->backupUrl());
|
||||
const std::vector<Url*> &pools = options->pools();
|
||||
|
||||
m_timer.data = this;
|
||||
uv_timer_init(uv_default_loop(), &m_timer);
|
||||
if (pools.size() > 1) {
|
||||
m_strategy = new FailoverStrategy(pools, m_agent, this);
|
||||
}
|
||||
else {
|
||||
m_strategy = new SinglePoolStrategy(pools.front(), m_agent, this);
|
||||
}
|
||||
|
||||
if (m_options->donateLevel() > 0) {
|
||||
m_donate = new DonateStrategy(m_agent, this);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Network::~Network()
|
||||
{
|
||||
for (auto client : m_pools) {
|
||||
delete client;
|
||||
}
|
||||
|
||||
free(m_agent);
|
||||
}
|
||||
|
||||
|
||||
void Network::connect()
|
||||
{
|
||||
m_pools[1]->connect();
|
||||
|
||||
if (m_options->donateLevel()) {
|
||||
uv_timer_start(&m_timer, Network::onTimer, (100 - m_options->donateLevel()) * 60 * 1000, 0);
|
||||
}
|
||||
m_strategy->connect();
|
||||
}
|
||||
|
||||
|
||||
void Network::onClose(Client *client, int failures)
|
||||
void Network::stop()
|
||||
{
|
||||
const int id = client->id();
|
||||
if (id == 0) {
|
||||
if (failures == -1) {
|
||||
stopDonate();
|
||||
}
|
||||
if (m_donate) {
|
||||
m_donate->stop();
|
||||
}
|
||||
|
||||
m_strategy->stop();
|
||||
}
|
||||
|
||||
|
||||
void Network::onActive(Client *client)
|
||||
{
|
||||
if (client->id() == -1) {
|
||||
LOG_NOTICE("dev donate started");
|
||||
return;
|
||||
}
|
||||
|
||||
if (m_pool == id) {
|
||||
m_pool = 0;
|
||||
Workers::pause();
|
||||
}
|
||||
|
||||
if (id == 1 && m_pools.size() > 2 && failures == m_options->retries()) {
|
||||
m_pools[2]->connect();
|
||||
}
|
||||
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());
|
||||
}
|
||||
|
||||
|
||||
void Network::onJobReceived(Client *client, const Job &job)
|
||||
void Network::onJob(Client *client, const Job &job)
|
||||
{
|
||||
if (m_donate && client->id() != 0) {
|
||||
if (m_donate && m_donate->isActive() && client->id() != -1) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -107,117 +110,57 @@ void Network::onJobReceived(Client *client, const Job &job)
|
||||
|
||||
void Network::onJobResult(const JobResult &result)
|
||||
{
|
||||
if (m_options->colors()) {
|
||||
LOG_NOTICE("\x1B[01;32mSHARE FOUND");
|
||||
if (result.poolId == -1 && m_donate) {
|
||||
m_donate->submit(result);
|
||||
return;
|
||||
}
|
||||
|
||||
m_strategy->submit(result);
|
||||
}
|
||||
|
||||
|
||||
void Network::onPause(IStrategy *strategy)
|
||||
{
|
||||
if (m_donate && m_donate == strategy) {
|
||||
LOG_NOTICE("dev donate finished");
|
||||
m_strategy->resume();
|
||||
}
|
||||
|
||||
if (!m_strategy->isActive()) {
|
||||
LOG_ERR("no active pools, stop mining");
|
||||
return Workers::pause();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Network::onResultAccepted(Client *client, int64_t seq, uint32_t diff, uint64_t ms, const char *error)
|
||||
{
|
||||
if (error) {
|
||||
m_rejected++;
|
||||
|
||||
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)",
|
||||
m_accepted, m_rejected, diff, error, ms);
|
||||
}
|
||||
else {
|
||||
LOG_NOTICE("SHARE FOUND");
|
||||
m_accepted++;
|
||||
|
||||
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)",
|
||||
m_accepted, m_rejected, diff, ms);
|
||||
}
|
||||
|
||||
m_pools[result.poolId]->submit(result);
|
||||
}
|
||||
|
||||
|
||||
void Network::onLoginCredentialsRequired(Client *client)
|
||||
{
|
||||
client->login(m_options->user(), m_options->pass(), m_agent);
|
||||
}
|
||||
|
||||
|
||||
void Network::onLoginSuccess(Client *client)
|
||||
{
|
||||
const int id = client->id();
|
||||
if (id == 0) {
|
||||
return startDonate();
|
||||
}
|
||||
|
||||
if (id == 2 && m_pool) { // primary pool is already active
|
||||
m_pools[2]->disconnect();
|
||||
return;
|
||||
}
|
||||
|
||||
LOG_NOTICE("use pool: \"%s:%d\"", client->host(), client->port());
|
||||
m_pool = id;
|
||||
|
||||
if (m_pool == 1 && m_pools.size() > 2) { // try disconnect from backup pool
|
||||
m_pools[2]->disconnect();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Network::addPool(const Url *url)
|
||||
{
|
||||
if (!url) {
|
||||
return;
|
||||
}
|
||||
|
||||
Client *client = new Client(m_pools.size(), this);
|
||||
client->setUrl(url);
|
||||
client->setRetryPause(m_options->retryPause() * 1000);
|
||||
client->setKeepAlive(m_options->keepAlive());
|
||||
|
||||
m_pools.push_back(client);
|
||||
}
|
||||
|
||||
|
||||
void Network::setJob(Client *client, const Job &job)
|
||||
{
|
||||
if (m_options->colors()) {
|
||||
LOG_INFO("\x1B[01;35mnew job\x1B[0m from \"%s:%d\", diff: %d", client->host(), client->port(), job.diff());
|
||||
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 {
|
||||
LOG_INFO("new job from \"%s:%d\", diff: %d", client->host(), client->port(), job.diff());
|
||||
LOG_INFO("new job from %s:%d diff %d", client->host(), client->port(), job.diff());
|
||||
}
|
||||
|
||||
Workers::setJob(job);
|
||||
}
|
||||
|
||||
|
||||
void Network::startDonate()
|
||||
{
|
||||
if (m_donate) {
|
||||
return;
|
||||
}
|
||||
|
||||
LOG_NOTICE("dev donate started");
|
||||
|
||||
m_donate = true;
|
||||
}
|
||||
|
||||
|
||||
void Network::stopDonate()
|
||||
{
|
||||
if (!m_donate) {
|
||||
return;
|
||||
}
|
||||
|
||||
LOG_NOTICE("dev donate finished");
|
||||
|
||||
m_donate = false;
|
||||
if (!m_pool) {
|
||||
return;
|
||||
}
|
||||
|
||||
Client *client = m_pools[m_pool];
|
||||
if (client->isReady()) {
|
||||
setJob(client, client->job());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Network::onTimer(uv_timer_t *handle)
|
||||
{
|
||||
auto net = static_cast<Network*>(handle->data);
|
||||
|
||||
if (!net->m_donate) {
|
||||
auto url = std::make_unique<Url>("donate.xmrig.com", net->m_options->algo() == Options::ALGO_CRYPTONIGHT_LITE ? 3333 : 443);
|
||||
net->m_pools[0]->connect(url.get());
|
||||
|
||||
uv_timer_start(&net->m_timer, Network::onTimer, net->m_options->donateLevel() * 60 * 1000, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
net->m_pools[0]->disconnect();
|
||||
uv_timer_start(&net->m_timer, Network::onTimer, (100 - net->m_options->donateLevel()) * 60 * 1000, 0);
|
||||
}
|
||||
|
||||
@@ -29,46 +29,43 @@
|
||||
#include <uv.h>
|
||||
|
||||
|
||||
#include "interfaces/IClientListener.h"
|
||||
#include "interfaces/IJobResultListener.h"
|
||||
#include "interfaces/IStrategyListener.h"
|
||||
|
||||
|
||||
class IStrategy;
|
||||
class Options;
|
||||
class Url;
|
||||
|
||||
|
||||
class Network : public IClientListener, public IJobResultListener
|
||||
class Network : public IJobResultListener, public IStrategyListener
|
||||
{
|
||||
public:
|
||||
Network(const Options *options);
|
||||
~Network();
|
||||
|
||||
void connect();
|
||||
void stop();
|
||||
|
||||
static char *userAgent();
|
||||
|
||||
protected:
|
||||
void onClose(Client *client, int failures) override;
|
||||
void onJobReceived(Client *client, const Job &job) override;
|
||||
void onActive(Client *client) override;
|
||||
void onJob(Client *client, const Job &job) override;
|
||||
void onJobResult(const JobResult &result) override;
|
||||
void onLoginCredentialsRequired(Client *client) override;
|
||||
void onLoginSuccess(Client *client) override;
|
||||
void onPause(IStrategy *strategy) override;
|
||||
void onResultAccepted(Client *client, int64_t seq, uint32_t diff, uint64_t ms, const char *error) override;
|
||||
|
||||
private:
|
||||
void addPool(const Url *url);
|
||||
void setJob(Client *client, const Job &job);
|
||||
void startDonate();
|
||||
void stopDonate();
|
||||
|
||||
static void onTimer(uv_timer_t *handle);
|
||||
|
||||
bool m_donate;
|
||||
bool m_donateActive;
|
||||
char *m_agent;
|
||||
const Options *m_options;
|
||||
int m_pool;
|
||||
std::vector<Client*> m_pools;
|
||||
uint64_t m_diff;
|
||||
uv_timer_t m_timer;
|
||||
IStrategy *m_donate;
|
||||
IStrategy *m_strategy;
|
||||
uint64_t m_accepted;
|
||||
uint64_t m_rejected;
|
||||
};
|
||||
|
||||
|
||||
|
||||
49
src/net/SubmitResult.h
Normal file
49
src/net/SubmitResult.h
Normal file
@@ -0,0 +1,49 @@
|
||||
/* XMRig
|
||||
* Copyright 2010 Jeff Garzik <jgarzik@pobox.com>
|
||||
* Copyright 2012-2014 pooler <pooler@litecoinpool.org>
|
||||
* Copyright 2014 Lucas Jones <https://github.com/lucasjones>
|
||||
* Copyright 2014-2016 Wolf9466 <https://github.com/OhGodAPet>
|
||||
* Copyright 2016 Jay D Dee <jayddee246@gmail.com>
|
||||
* Copyright 2016-2017 XMRig <support@xmrig.com>
|
||||
*
|
||||
*
|
||||
* 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef __SUBMITRESULT_H__
|
||||
#define __SUBMITRESULT_H__
|
||||
|
||||
|
||||
#include <uv.h>
|
||||
|
||||
|
||||
class SubmitResult
|
||||
{
|
||||
public:
|
||||
inline SubmitResult() : seq(0), diff(0), start(0) {}
|
||||
inline SubmitResult(int64_t seq, uint32_t diff) :
|
||||
seq(seq),
|
||||
diff(diff)
|
||||
{
|
||||
start = uv_hrtime();
|
||||
}
|
||||
|
||||
inline uint64_t elapsed() const { return (uv_hrtime() - start) / 1000000; }
|
||||
|
||||
int64_t seq;
|
||||
uint32_t diff;
|
||||
uint64_t start;
|
||||
};
|
||||
|
||||
#endif /* __SUBMITRESULT_H__ */
|
||||
139
src/net/Url.cpp
139
src/net/Url.cpp
@@ -35,8 +35,12 @@
|
||||
|
||||
|
||||
Url::Url() :
|
||||
m_keepAlive(false),
|
||||
m_nicehash(false),
|
||||
m_host(nullptr),
|
||||
m_port(3333)
|
||||
m_password(nullptr),
|
||||
m_user(nullptr),
|
||||
m_port(kDefaultPort)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -53,40 +57,22 @@ Url::Url() :
|
||||
* @param url
|
||||
*/
|
||||
Url::Url(const char *url) :
|
||||
m_keepAlive(false),
|
||||
m_nicehash(false),
|
||||
m_host(nullptr),
|
||||
m_port(3333)
|
||||
m_password(nullptr),
|
||||
m_user(nullptr),
|
||||
m_port(kDefaultPort)
|
||||
{
|
||||
const char *p = strstr(url, "://");
|
||||
const char *base = url;
|
||||
|
||||
if (p) {
|
||||
if (strncasecmp(url, "stratum+tcp://", 14)) {
|
||||
return;
|
||||
}
|
||||
|
||||
base = url + 14;
|
||||
}
|
||||
|
||||
if (!strlen(base) || *base == '/') {
|
||||
return;
|
||||
}
|
||||
|
||||
const char *port = strchr(base, ':');
|
||||
if (!port) {
|
||||
m_host = strdup(base);
|
||||
return;
|
||||
}
|
||||
|
||||
const size_t size = port++ - base + 1;
|
||||
m_host = static_cast<char*>(malloc(size));
|
||||
memcpy(m_host, base, size - 1);
|
||||
m_host[size - 1] = '\0';
|
||||
|
||||
m_port = strtol(port, nullptr, 10);
|
||||
parse(url);
|
||||
}
|
||||
|
||||
|
||||
Url::Url(const char *host, uint16_t port) :
|
||||
Url::Url(const char *host, uint16_t port, const char *user, const char *password, bool keepAlive, bool nicehash) :
|
||||
m_keepAlive(keepAlive),
|
||||
m_nicehash(nicehash),
|
||||
m_password(password ? strdup(password) : nullptr),
|
||||
m_user(user ? strdup(user) : nullptr),
|
||||
m_port(port)
|
||||
{
|
||||
m_host = strdup(host);
|
||||
@@ -96,10 +82,101 @@ Url::Url(const char *host, uint16_t port) :
|
||||
Url::~Url()
|
||||
{
|
||||
free(m_host);
|
||||
free(m_password);
|
||||
free(m_user);
|
||||
}
|
||||
|
||||
|
||||
bool Url::isNicehash() const
|
||||
{
|
||||
return isValid() && strstr(m_host, ".nicehash.com");
|
||||
return isValid() && (m_nicehash || strstr(m_host, ".nicehash.com"));
|
||||
}
|
||||
|
||||
|
||||
bool Url::parse(const char *url)
|
||||
{
|
||||
const char *p = strstr(url, "://");
|
||||
const char *base = url;
|
||||
|
||||
if (p) {
|
||||
if (strncasecmp(url, "stratum+tcp://", 14)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
base = url + 14;
|
||||
}
|
||||
|
||||
if (!strlen(base) || *base == '/') {
|
||||
return false;
|
||||
}
|
||||
|
||||
const char *port = strchr(base, ':');
|
||||
if (!port) {
|
||||
m_host = strdup(base);
|
||||
return false;
|
||||
}
|
||||
|
||||
const size_t size = port++ - base + 1;
|
||||
m_host = static_cast<char*>(malloc(size));
|
||||
memcpy(m_host, base, size - 1);
|
||||
m_host[size - 1] = '\0';
|
||||
|
||||
m_port = strtol(port, nullptr, 10);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool Url::setUserpass(const char *userpass)
|
||||
{
|
||||
const char *p = strchr(userpass, ':');
|
||||
if (!p) {
|
||||
return false;
|
||||
}
|
||||
|
||||
free(m_user);
|
||||
free(m_password);
|
||||
|
||||
m_user = static_cast<char*>(calloc(p - userpass + 1, 1));
|
||||
strncpy(m_user, userpass, p - userpass);
|
||||
m_password = strdup(p + 1);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
void Url::setPassword(const char *password)
|
||||
{
|
||||
if (!password) {
|
||||
return;
|
||||
}
|
||||
|
||||
free(m_password);
|
||||
m_password = strdup(password);
|
||||
}
|
||||
|
||||
|
||||
void Url::setUser(const char *user)
|
||||
{
|
||||
if (!user) {
|
||||
return;
|
||||
}
|
||||
|
||||
free(m_user);
|
||||
m_user = strdup(user);
|
||||
}
|
||||
|
||||
|
||||
Url &Url::operator=(const Url *other)
|
||||
{
|
||||
m_keepAlive = other->m_keepAlive;
|
||||
m_nicehash = other->m_nicehash;
|
||||
m_port = other->m_port;
|
||||
|
||||
free(m_host);
|
||||
m_host = strdup(other->m_host);
|
||||
|
||||
setPassword(other->m_password);
|
||||
setUser(other->m_user);
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
@@ -31,19 +31,38 @@
|
||||
class Url
|
||||
{
|
||||
public:
|
||||
constexpr static const char *kDefaultPassword = "x";
|
||||
constexpr static const char *kDefaultUser = "x";
|
||||
constexpr static uint16_t kDefaultPort = 3333;
|
||||
|
||||
Url();
|
||||
Url(const char *url);
|
||||
Url(const char *host, uint16_t port);
|
||||
Url(const char *host, uint16_t port, const char *user = nullptr, const char *password = nullptr, bool keepAlive = false, bool nicehash = false );
|
||||
~Url();
|
||||
|
||||
bool isNicehash() const;
|
||||
inline bool isKeepAlive() const { return m_keepAlive; }
|
||||
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 uint16_t port() const { return m_port; }
|
||||
inline void setKeepAlive(bool keepAlive) { m_keepAlive = keepAlive; }
|
||||
inline void setNicehash(bool nicehash) { m_nicehash = nicehash; }
|
||||
|
||||
inline bool isValid() const { return m_host && m_port > 0; }
|
||||
inline const char *host() const { return m_host; }
|
||||
inline uint16_t port() const { return m_port; }
|
||||
bool isNicehash() const;
|
||||
bool parse(const char *url);
|
||||
bool setUserpass(const char *userpass);
|
||||
void setPassword(const char *password);
|
||||
void setUser(const char *user);
|
||||
|
||||
Url &operator=(const Url *other);
|
||||
|
||||
private:
|
||||
bool m_keepAlive;
|
||||
bool m_nicehash;
|
||||
char *m_host;
|
||||
char *m_password;
|
||||
char *m_user;
|
||||
uint16_t m_port;
|
||||
};
|
||||
|
||||
|
||||
126
src/net/strategies/DonateStrategy.cpp
Normal file
126
src/net/strategies/DonateStrategy.cpp
Normal file
@@ -0,0 +1,126 @@
|
||||
/* XMRig
|
||||
* Copyright 2010 Jeff Garzik <jgarzik@pobox.com>
|
||||
* Copyright 2012-2014 pooler <pooler@litecoinpool.org>
|
||||
* Copyright 2014 Lucas Jones <https://github.com/lucasjones>
|
||||
* Copyright 2014-2016 Wolf9466 <https://github.com/OhGodAPet>
|
||||
* Copyright 2016 Jay D Dee <jayddee246@gmail.com>
|
||||
* Copyright 2016-2017 XMRig <support@xmrig.com>
|
||||
*
|
||||
*
|
||||
* 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
|
||||
#include "interfaces/IStrategyListener.h"
|
||||
#include "net/Client.h"
|
||||
#include "net/strategies/DonateStrategy.h"
|
||||
#include "Options.h"
|
||||
|
||||
|
||||
DonateStrategy::DonateStrategy(const char *agent, IStrategyListener *listener) :
|
||||
m_active(false),
|
||||
m_donateTime(Options::i()->donateLevel() * 60 * 1000),
|
||||
m_idleTime((100 - Options::i()->donateLevel()) * 60 * 1000),
|
||||
m_listener(listener)
|
||||
{
|
||||
Url *url = new Url("fee.xmrig.com", Options::i()->algo() == Options::ALGO_CRYPTONIGHT_LITE ? 3333 : 443, Options::i()->pools().front()->user(), nullptr, false, true);
|
||||
|
||||
m_client = new Client(-1, agent, this);
|
||||
m_client->setUrl(url);
|
||||
m_client->setRetryPause(Options::i()->retryPause() * 1000);
|
||||
m_client->setQuiet(true);
|
||||
|
||||
delete url;
|
||||
|
||||
m_timer.data = this;
|
||||
uv_timer_init(uv_default_loop(), &m_timer);
|
||||
|
||||
idle();
|
||||
}
|
||||
|
||||
|
||||
int64_t DonateStrategy::submit(const JobResult &result)
|
||||
{
|
||||
return m_client->submit(result);
|
||||
}
|
||||
|
||||
|
||||
void DonateStrategy::connect()
|
||||
{
|
||||
m_client->connect();
|
||||
}
|
||||
|
||||
|
||||
void DonateStrategy::stop()
|
||||
{
|
||||
uv_timer_stop(&m_timer);
|
||||
m_client->disconnect();
|
||||
}
|
||||
|
||||
|
||||
void DonateStrategy::onClose(Client *client, int failures)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
void DonateStrategy::onJobReceived(Client *client, const Job &job)
|
||||
{
|
||||
m_listener->onJob(client, job);
|
||||
}
|
||||
|
||||
|
||||
void DonateStrategy::onLoginSuccess(Client *client)
|
||||
{
|
||||
if (!isActive()) {
|
||||
uv_timer_start(&m_timer, DonateStrategy::onTimer, m_donateTime, 0);
|
||||
}
|
||||
|
||||
m_active = true;
|
||||
m_listener->onActive(client);
|
||||
}
|
||||
|
||||
|
||||
void DonateStrategy::onResultAccepted(Client *client, int64_t seq, uint32_t diff, uint64_t ms, const char *error)
|
||||
{
|
||||
m_listener->onResultAccepted(client, seq, diff, ms, error);
|
||||
}
|
||||
|
||||
|
||||
void DonateStrategy::idle()
|
||||
{
|
||||
uv_timer_start(&m_timer, DonateStrategy::onTimer, m_idleTime, 0);
|
||||
}
|
||||
|
||||
|
||||
void DonateStrategy::suspend()
|
||||
{
|
||||
m_client->disconnect();
|
||||
|
||||
m_active = false;
|
||||
m_listener->onPause(this);
|
||||
|
||||
idle();
|
||||
}
|
||||
|
||||
|
||||
void DonateStrategy::onTimer(uv_timer_t *handle)
|
||||
{
|
||||
auto strategy = static_cast<DonateStrategy*>(handle->data);
|
||||
|
||||
if (!strategy->isActive()) {
|
||||
return strategy->connect();
|
||||
}
|
||||
|
||||
strategy->suspend();
|
||||
}
|
||||
73
src/net/strategies/DonateStrategy.h
Normal file
73
src/net/strategies/DonateStrategy.h
Normal file
@@ -0,0 +1,73 @@
|
||||
/* XMRig
|
||||
* Copyright 2010 Jeff Garzik <jgarzik@pobox.com>
|
||||
* Copyright 2012-2014 pooler <pooler@litecoinpool.org>
|
||||
* Copyright 2014 Lucas Jones <https://github.com/lucasjones>
|
||||
* Copyright 2014-2016 Wolf9466 <https://github.com/OhGodAPet>
|
||||
* Copyright 2016 Jay D Dee <jayddee246@gmail.com>
|
||||
* Copyright 2016-2017 XMRig <support@xmrig.com>
|
||||
*
|
||||
*
|
||||
* 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef __DONATESTRATEGY_H__
|
||||
#define __DONATESTRATEGY_H__
|
||||
|
||||
|
||||
#include <uv.h>
|
||||
|
||||
|
||||
#include "interfaces/IClientListener.h"
|
||||
#include "interfaces/IStrategy.h"
|
||||
|
||||
|
||||
class Client;
|
||||
class IStrategyListener;
|
||||
class Url;
|
||||
|
||||
|
||||
class DonateStrategy : public IStrategy, public IClientListener
|
||||
{
|
||||
public:
|
||||
DonateStrategy(const char *agent, IStrategyListener *listener);
|
||||
|
||||
public:
|
||||
inline bool isActive() const override { return m_active; }
|
||||
inline void resume() override {}
|
||||
|
||||
int64_t submit(const JobResult &result) override;
|
||||
void connect() override;
|
||||
void stop() override;
|
||||
|
||||
protected:
|
||||
void onClose(Client *client, int failures) override;
|
||||
void onJobReceived(Client *client, const Job &job) override;
|
||||
void onLoginSuccess(Client *client) override;
|
||||
void onResultAccepted(Client *client, int64_t seq, uint32_t diff, uint64_t ms, const char *error) override;
|
||||
|
||||
private:
|
||||
void idle();
|
||||
void suspend();
|
||||
|
||||
static void onTimer(uv_timer_t *handle);
|
||||
|
||||
bool m_active;
|
||||
Client *m_client;
|
||||
const int m_donateTime;
|
||||
const int m_idleTime;
|
||||
IStrategyListener *m_listener;
|
||||
uv_timer_t m_timer;
|
||||
};
|
||||
|
||||
#endif /* __DONATESTRATEGY_H__ */
|
||||
135
src/net/strategies/FailoverStrategy.cpp
Normal file
135
src/net/strategies/FailoverStrategy.cpp
Normal file
@@ -0,0 +1,135 @@
|
||||
/* XMRig
|
||||
* Copyright 2010 Jeff Garzik <jgarzik@pobox.com>
|
||||
* Copyright 2012-2014 pooler <pooler@litecoinpool.org>
|
||||
* Copyright 2014 Lucas Jones <https://github.com/lucasjones>
|
||||
* Copyright 2014-2016 Wolf9466 <https://github.com/OhGodAPet>
|
||||
* Copyright 2016 Jay D Dee <jayddee246@gmail.com>
|
||||
* Copyright 2016-2017 XMRig <support@xmrig.com>
|
||||
*
|
||||
*
|
||||
* 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
|
||||
#include "interfaces/IStrategyListener.h"
|
||||
#include "net/Client.h"
|
||||
#include "net/strategies/FailoverStrategy.h"
|
||||
#include "Options.h"
|
||||
|
||||
|
||||
FailoverStrategy::FailoverStrategy(const std::vector<Url*> &urls, const char *agent, IStrategyListener *listener) :
|
||||
m_active(-1),
|
||||
m_index(0),
|
||||
m_listener(listener)
|
||||
{
|
||||
for (const Url *url : urls) {
|
||||
add(url, agent);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int64_t FailoverStrategy::submit(const JobResult &result)
|
||||
{
|
||||
return m_pools[m_active]->submit(result);
|
||||
}
|
||||
|
||||
|
||||
void FailoverStrategy::connect()
|
||||
{
|
||||
m_pools[m_index]->connect();
|
||||
}
|
||||
|
||||
|
||||
void FailoverStrategy::resume()
|
||||
{
|
||||
if (!isActive()) {
|
||||
return;
|
||||
}
|
||||
|
||||
m_listener->onJob( m_pools[m_active], m_pools[m_active]->job());
|
||||
}
|
||||
|
||||
|
||||
void FailoverStrategy::stop()
|
||||
{
|
||||
for (size_t i = 0; i < m_pools.size(); ++i) {
|
||||
m_pools[i]->disconnect();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void FailoverStrategy::onClose(Client *client, int failures)
|
||||
{
|
||||
if (failures == -1) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (m_active == client->id()) {
|
||||
m_active = -1;
|
||||
m_listener->onPause(this);
|
||||
}
|
||||
|
||||
if (m_index == 0 && failures < Options::i()->retries()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (m_index == client->id() && (m_pools.size() - m_index) > 1) {
|
||||
m_pools[++m_index]->connect();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void FailoverStrategy::onJobReceived(Client *client, const Job &job)
|
||||
{
|
||||
if (m_active == client->id()) {
|
||||
m_listener->onJob(client, job);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void FailoverStrategy::onLoginSuccess(Client *client)
|
||||
{
|
||||
int active = m_active;
|
||||
|
||||
if (client->id() == 0 || !isActive()) {
|
||||
active = client->id();
|
||||
}
|
||||
|
||||
for (size_t i = 1; i < m_pools.size(); ++i) {
|
||||
if (active != static_cast<int>(i)) {
|
||||
m_pools[i]->disconnect();
|
||||
}
|
||||
}
|
||||
|
||||
if (active >= 0 && active != m_active) {
|
||||
m_index = m_active = active;
|
||||
m_listener->onActive(client);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void FailoverStrategy::onResultAccepted(Client *client, int64_t seq, uint32_t diff, uint64_t ms, const char *error)
|
||||
{
|
||||
m_listener->onResultAccepted(client, seq, diff, ms, error);
|
||||
}
|
||||
|
||||
|
||||
void FailoverStrategy::add(const Url *url, const char *agent)
|
||||
{
|
||||
Client *client = new Client(m_pools.size(), agent, this);
|
||||
client->setUrl(url);
|
||||
client->setRetryPause(Options::i()->retryPause() * 1000);
|
||||
|
||||
m_pools.push_back(client);
|
||||
}
|
||||
68
src/net/strategies/FailoverStrategy.h
Normal file
68
src/net/strategies/FailoverStrategy.h
Normal file
@@ -0,0 +1,68 @@
|
||||
/* XMRig
|
||||
* Copyright 2010 Jeff Garzik <jgarzik@pobox.com>
|
||||
* Copyright 2012-2014 pooler <pooler@litecoinpool.org>
|
||||
* Copyright 2014 Lucas Jones <https://github.com/lucasjones>
|
||||
* Copyright 2014-2016 Wolf9466 <https://github.com/OhGodAPet>
|
||||
* Copyright 2016 Jay D Dee <jayddee246@gmail.com>
|
||||
* Copyright 2016-2017 XMRig <support@xmrig.com>
|
||||
*
|
||||
*
|
||||
* 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef __FAILOVERSTRATEGY_H__
|
||||
#define __FAILOVERSTRATEGY_H__
|
||||
|
||||
|
||||
#include <vector>
|
||||
|
||||
|
||||
#include "interfaces/IClientListener.h"
|
||||
#include "interfaces/IStrategy.h"
|
||||
|
||||
|
||||
class Client;
|
||||
class IStrategyListener;
|
||||
class Url;
|
||||
|
||||
|
||||
class FailoverStrategy : public IStrategy, public IClientListener
|
||||
{
|
||||
public:
|
||||
FailoverStrategy(const std::vector<Url*> &urls, const char *agent, IStrategyListener *listener);
|
||||
|
||||
public:
|
||||
inline bool isActive() const override { return m_active >= 0; }
|
||||
|
||||
int64_t submit(const JobResult &result) override;
|
||||
void connect() override;
|
||||
void resume() override;
|
||||
void stop() override;
|
||||
|
||||
protected:
|
||||
void onClose(Client *client, int failures) override;
|
||||
void onJobReceived(Client *client, const Job &job) override;
|
||||
void onLoginSuccess(Client *client) override;
|
||||
void onResultAccepted(Client *client, int64_t seq, uint32_t diff, uint64_t ms, const char *error) override;
|
||||
|
||||
private:
|
||||
void add(const Url *url, const char *agent);
|
||||
|
||||
int m_active;
|
||||
int m_index;
|
||||
IStrategyListener *m_listener;
|
||||
std::vector<Client*> m_pools;
|
||||
};
|
||||
|
||||
#endif /* __FAILOVERSTRATEGY_H__ */
|
||||
96
src/net/strategies/SinglePoolStrategy.cpp
Normal file
96
src/net/strategies/SinglePoolStrategy.cpp
Normal file
@@ -0,0 +1,96 @@
|
||||
/* XMRig
|
||||
* Copyright 2010 Jeff Garzik <jgarzik@pobox.com>
|
||||
* Copyright 2012-2014 pooler <pooler@litecoinpool.org>
|
||||
* Copyright 2014 Lucas Jones <https://github.com/lucasjones>
|
||||
* Copyright 2014-2016 Wolf9466 <https://github.com/OhGodAPet>
|
||||
* Copyright 2016 Jay D Dee <jayddee246@gmail.com>
|
||||
* Copyright 2016-2017 XMRig <support@xmrig.com>
|
||||
*
|
||||
*
|
||||
* 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
|
||||
#include "interfaces/IStrategyListener.h"
|
||||
#include "net/Client.h"
|
||||
#include "net/strategies/SinglePoolStrategy.h"
|
||||
#include "Options.h"
|
||||
|
||||
|
||||
SinglePoolStrategy::SinglePoolStrategy(const Url *url, const char *agent, IStrategyListener *listener) :
|
||||
m_active(false),
|
||||
m_listener(listener)
|
||||
{
|
||||
m_client = new Client(0, agent, this);
|
||||
m_client->setUrl(url);
|
||||
m_client->setRetryPause(Options::i()->retryPause() * 1000);
|
||||
}
|
||||
|
||||
|
||||
int64_t SinglePoolStrategy::submit(const JobResult &result)
|
||||
{
|
||||
return m_client->submit(result);
|
||||
}
|
||||
|
||||
|
||||
void SinglePoolStrategy::connect()
|
||||
{
|
||||
m_client->connect();
|
||||
}
|
||||
|
||||
|
||||
void SinglePoolStrategy::resume()
|
||||
{
|
||||
if (!isActive()) {
|
||||
return;
|
||||
}
|
||||
|
||||
m_listener->onJob(m_client, m_client->job());
|
||||
}
|
||||
|
||||
|
||||
void SinglePoolStrategy::stop()
|
||||
{
|
||||
m_client->disconnect();
|
||||
}
|
||||
|
||||
|
||||
void SinglePoolStrategy::onClose(Client *client, int failures)
|
||||
{
|
||||
if (!isActive()) {
|
||||
return;
|
||||
}
|
||||
|
||||
m_active = false;
|
||||
m_listener->onPause(this);
|
||||
}
|
||||
|
||||
|
||||
void SinglePoolStrategy::onJobReceived(Client *client, const Job &job)
|
||||
{
|
||||
m_listener->onJob(client, job);
|
||||
}
|
||||
|
||||
|
||||
void SinglePoolStrategy::onLoginSuccess(Client *client)
|
||||
{
|
||||
m_active = true;
|
||||
m_listener->onActive(client);
|
||||
}
|
||||
|
||||
|
||||
void SinglePoolStrategy::onResultAccepted(Client *client, int64_t seq, uint32_t diff, uint64_t ms, const char *error)
|
||||
{
|
||||
m_listener->onResultAccepted(client, seq, diff, ms, error);
|
||||
}
|
||||
62
src/net/strategies/SinglePoolStrategy.h
Normal file
62
src/net/strategies/SinglePoolStrategy.h
Normal file
@@ -0,0 +1,62 @@
|
||||
/* XMRig
|
||||
* Copyright 2010 Jeff Garzik <jgarzik@pobox.com>
|
||||
* Copyright 2012-2014 pooler <pooler@litecoinpool.org>
|
||||
* Copyright 2014 Lucas Jones <https://github.com/lucasjones>
|
||||
* Copyright 2014-2016 Wolf9466 <https://github.com/OhGodAPet>
|
||||
* Copyright 2016 Jay D Dee <jayddee246@gmail.com>
|
||||
* Copyright 2016-2017 XMRig <support@xmrig.com>
|
||||
*
|
||||
*
|
||||
* 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef __SINGLEPOOLSTRATEGY_H__
|
||||
#define __SINGLEPOOLSTRATEGY_H__
|
||||
|
||||
|
||||
#include "interfaces/IClientListener.h"
|
||||
#include "interfaces/IStrategy.h"
|
||||
|
||||
|
||||
class Client;
|
||||
class IStrategyListener;
|
||||
class Url;
|
||||
|
||||
|
||||
class SinglePoolStrategy : public IStrategy, public IClientListener
|
||||
{
|
||||
public:
|
||||
SinglePoolStrategy(const Url *url, const char *agent, IStrategyListener *listener);
|
||||
|
||||
public:
|
||||
inline bool isActive() const override { return m_active; }
|
||||
|
||||
int64_t submit(const JobResult &result) override;
|
||||
void connect() override;
|
||||
void resume() override;
|
||||
void stop() override;
|
||||
|
||||
protected:
|
||||
void onClose(Client *client, int failures) override;
|
||||
void onJobReceived(Client *client, const Job &job) override;
|
||||
void onLoginSuccess(Client *client) override;
|
||||
void onResultAccepted(Client *client, int64_t seq, uint32_t diff, uint64_t ms, const char *error) override;
|
||||
|
||||
private:
|
||||
bool m_active;
|
||||
Client *m_client;
|
||||
IStrategyListener *m_listener;
|
||||
};
|
||||
|
||||
#endif /* __SINGLEPOOLSTRATEGY_H__ */
|
||||
@@ -27,14 +27,14 @@
|
||||
#define APP_ID "xmrig"
|
||||
#define APP_NAME "XMRig"
|
||||
#define APP_DESC "Monero (XMR) CPU miner"
|
||||
#define APP_VERSION "1.0.1"
|
||||
#define APP_VERSION "2.1.0"
|
||||
#define APP_DOMAIN "xmrig.com"
|
||||
#define APP_SITE "www.xmrig.com"
|
||||
#define APP_COPYRIGHT "Copyright (C) 2016-2017 xmrig.com"
|
||||
|
||||
#define APP_VER_MAJOR 1
|
||||
#define APP_VER_MINOR 0
|
||||
#define APP_VER_BUILD 1
|
||||
#define APP_VER_MAJOR 2
|
||||
#define APP_VER_MINOR 1
|
||||
#define APP_VER_BUILD 0
|
||||
#define APP_VER_REV 0
|
||||
|
||||
#ifdef _MSC_VER
|
||||
|
||||
@@ -30,17 +30,39 @@
|
||||
#include "workers/Workers.h"
|
||||
|
||||
|
||||
DoubleWorker::DoubleWorker(Handle *handle)
|
||||
: Worker(handle),
|
||||
m_nonce1(0),
|
||||
m_nonce2(0)
|
||||
class DoubleWorker::State
|
||||
{
|
||||
public:
|
||||
inline State() :
|
||||
nonce1(0),
|
||||
nonce2(0)
|
||||
{}
|
||||
|
||||
Job job;
|
||||
uint32_t nonce1;
|
||||
uint32_t nonce2;
|
||||
uint8_t blob[84 * 2];
|
||||
};
|
||||
|
||||
|
||||
DoubleWorker::DoubleWorker(Handle *handle)
|
||||
: Worker(handle)
|
||||
{
|
||||
m_state = new State();
|
||||
m_pausedState = new State();
|
||||
}
|
||||
|
||||
|
||||
DoubleWorker::~DoubleWorker()
|
||||
{
|
||||
delete m_state;
|
||||
delete m_pausedState;
|
||||
}
|
||||
|
||||
|
||||
void DoubleWorker::start()
|
||||
{
|
||||
while (true) {
|
||||
while (Workers::sequence() > 0) {
|
||||
if (Workers::isPaused()) {
|
||||
do {
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(200));
|
||||
@@ -56,17 +78,17 @@ void DoubleWorker::start()
|
||||
}
|
||||
|
||||
m_count += 2;
|
||||
*Job::nonce(m_blob) = ++m_nonce1;
|
||||
*Job::nonce(m_blob + m_job.size()) = ++m_nonce2;
|
||||
*Job::nonce(m_state->blob) = ++m_state->nonce1;
|
||||
*Job::nonce(m_state->blob + m_state->job.size()) = ++m_state->nonce2;
|
||||
|
||||
CryptoNight::hash(m_blob, m_job.size(), m_hash, m_ctx);
|
||||
CryptoNight::hash(m_state->blob, m_state->job.size(), m_hash, m_ctx);
|
||||
|
||||
if (*reinterpret_cast<uint64_t*>(m_hash + 24) < m_job.target()) {
|
||||
Workers::submit(JobResult(m_job.poolId(), m_job.id(), m_nonce1, m_hash));
|
||||
if (*reinterpret_cast<uint64_t*>(m_hash + 24) < m_state->job.target()) {
|
||||
Workers::submit(JobResult(m_state->job.poolId(), m_state->job.id(), m_state->nonce1, m_hash, m_state->job.diff()));
|
||||
}
|
||||
|
||||
if (*reinterpret_cast<uint64_t*>(m_hash + 32 + 24) < m_job.target()) {
|
||||
Workers::submit(JobResult(m_job.poolId(), m_job.id(), m_nonce2, m_hash + 32));
|
||||
if (*reinterpret_cast<uint64_t*>(m_hash + 32 + 24) < m_state->job.target()) {
|
||||
Workers::submit(JobResult(m_state->job.poolId(), m_state->job.id(), m_state->nonce2, m_hash + 32, m_state->job.diff()));
|
||||
}
|
||||
|
||||
std::this_thread::yield();
|
||||
@@ -77,20 +99,49 @@ void DoubleWorker::start()
|
||||
}
|
||||
|
||||
|
||||
bool DoubleWorker::resume(const Job &job)
|
||||
{
|
||||
if (m_state->job.poolId() == -1 && job.poolId() >= 0 && memcmp(job.id(), m_pausedState->job.id(), 64) == 0) {
|
||||
*m_state = *m_pausedState;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
void DoubleWorker::consumeJob()
|
||||
{
|
||||
m_job = Workers::job();
|
||||
Job job = Workers::job();
|
||||
m_sequence = Workers::sequence();
|
||||
if (m_state->job == job) {
|
||||
return;
|
||||
}
|
||||
|
||||
memcpy(m_blob, m_job.blob(), m_job.size());
|
||||
memcpy(m_blob + m_job.size(), m_job.blob(), m_job.size());
|
||||
save(job);
|
||||
|
||||
if (m_nicehash) {
|
||||
m_nonce1 = (*Job::nonce(m_blob) & 0xff000000U) + (0xffffffU / (m_threads * 2) * m_id);
|
||||
m_nonce2 = (*Job::nonce(m_blob + m_job.size()) & 0xff000000U) + (0xffffffU / (m_threads * 2) * (m_id + m_threads));
|
||||
if (resume(job)) {
|
||||
return;
|
||||
}
|
||||
|
||||
m_state->job = std::move(job);
|
||||
memcpy(m_state->blob, m_state->job.blob(), m_state->job.size());
|
||||
memcpy(m_state->blob + m_state->job.size(), m_state->job.blob(), m_state->job.size());
|
||||
|
||||
if (m_state->job.isNicehash()) {
|
||||
m_state->nonce1 = (*Job::nonce(m_state->blob) & 0xff000000U) + (0xffffffU / (m_threads * 2) * m_id);
|
||||
m_state->nonce2 = (*Job::nonce(m_state->blob + m_state->job.size()) & 0xff000000U) + (0xffffffU / (m_threads * 2) * (m_id + m_threads));
|
||||
}
|
||||
else {
|
||||
m_nonce1 = 0xffffffffU / (m_threads * 2) * m_id;
|
||||
m_nonce2 = 0xffffffffU / (m_threads * 2) * (m_id + m_threads);
|
||||
m_state->nonce1 = 0xffffffffU / (m_threads * 2) * m_id;
|
||||
m_state->nonce2 = 0xffffffffU / (m_threads * 2) * (m_id + m_threads);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void DoubleWorker::save(const Job &job)
|
||||
{
|
||||
if (job.poolId() == -1 && m_state->job.poolId() >= 0) {
|
||||
*m_pausedState = *m_state;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -38,17 +38,20 @@ class DoubleWorker : public Worker
|
||||
{
|
||||
public:
|
||||
DoubleWorker(Handle *handle);
|
||||
~DoubleWorker();
|
||||
|
||||
void start() override;
|
||||
|
||||
private:
|
||||
bool resume(const Job &job);
|
||||
void consumeJob();
|
||||
void save(const Job &job);
|
||||
|
||||
class State;
|
||||
|
||||
Job m_job;
|
||||
uint32_t m_nonce1;
|
||||
uint32_t m_nonce2;
|
||||
uint8_t m_hash[64];
|
||||
uint8_t m_blob[84 * 2];
|
||||
State *m_state;
|
||||
State *m_pausedState;
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -25,8 +25,7 @@
|
||||
#include "workers/Handle.h"
|
||||
|
||||
|
||||
Handle::Handle(int threadId, int threads, int64_t affinity, bool nicehash) :
|
||||
m_nicehash(nicehash),
|
||||
Handle::Handle(int threadId, int threads, int64_t affinity) :
|
||||
m_threadId(threadId),
|
||||
m_threads(threads),
|
||||
m_affinity(affinity),
|
||||
@@ -35,6 +34,12 @@ Handle::Handle(int threadId, int threads, int64_t affinity, bool nicehash) :
|
||||
}
|
||||
|
||||
|
||||
void Handle::join()
|
||||
{
|
||||
uv_thread_join(&m_thread);
|
||||
}
|
||||
|
||||
|
||||
void Handle::start(void (*callback) (void *))
|
||||
{
|
||||
uv_thread_create(&m_thread, callback, this);
|
||||
|
||||
@@ -35,10 +35,10 @@ class IWorker;
|
||||
class Handle
|
||||
{
|
||||
public:
|
||||
Handle(int threadId, int threads, int64_t affinity, bool nicehash);
|
||||
Handle(int threadId, int threads, int64_t affinity);
|
||||
void join();
|
||||
void start(void (*callback) (void *));
|
||||
|
||||
inline bool nicehash() const { return m_nicehash; }
|
||||
inline int threadId() const { return m_threadId; }
|
||||
inline int threads() const { return m_threads; }
|
||||
inline int64_t affinity() const { return m_affinity; }
|
||||
@@ -46,7 +46,6 @@ public:
|
||||
inline void setWorker(IWorker *worker) { m_worker = worker; }
|
||||
|
||||
private:
|
||||
bool m_nicehash;
|
||||
int m_threadId;
|
||||
int m_threads;
|
||||
int64_t m_affinity;
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
#include <cmath>
|
||||
#include <memory.h>
|
||||
|
||||
#include "Console.h"
|
||||
#include "log/Log.h"
|
||||
#include "Options.h"
|
||||
#include "workers/Hashrate.h"
|
||||
|
||||
@@ -152,7 +152,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 highest: \x1B[01;36m%s H/s" : "speed 2.5s/60s/15m %s %s %s H/s highest: %s H/s",
|
||||
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",
|
||||
format(calc(2500), num1, sizeof(num1)),
|
||||
format(calc(60000), num2, sizeof(num2)),
|
||||
format(calc(900000), num3, sizeof(num3)),
|
||||
@@ -161,6 +161,12 @@ void Hashrate::print()
|
||||
}
|
||||
|
||||
|
||||
void Hashrate::stop()
|
||||
{
|
||||
uv_timer_stop(&m_timer);
|
||||
}
|
||||
|
||||
|
||||
void Hashrate::updateHighest()
|
||||
{
|
||||
double highest = calc(2500);
|
||||
|
||||
@@ -37,6 +37,7 @@ public:
|
||||
double calc(size_t threadId, size_t ms) const;
|
||||
void add(size_t threadId, uint64_t count, uint64_t timestamp);
|
||||
void print();
|
||||
void stop();
|
||||
void updateHighest();
|
||||
|
||||
inline double highest() const { return m_highest; }
|
||||
|
||||
@@ -38,7 +38,7 @@ SingleWorker::SingleWorker(Handle *handle)
|
||||
|
||||
void SingleWorker::start()
|
||||
{
|
||||
while (true) {
|
||||
while (Workers::sequence() > 0) {
|
||||
if (Workers::isPaused()) {
|
||||
do {
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(200));
|
||||
@@ -68,19 +68,48 @@ void SingleWorker::start()
|
||||
}
|
||||
|
||||
|
||||
bool SingleWorker::resume(const Job &job)
|
||||
{
|
||||
if (m_job.poolId() == -1 && job.poolId() >= 0 && memcmp(job.id(), m_paused.id(), 64) == 0) {
|
||||
m_job = m_paused;
|
||||
m_result = m_job;
|
||||
m_result.nonce = *m_job.nonce();
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
void SingleWorker::consumeJob()
|
||||
{
|
||||
m_job = Workers::job();
|
||||
Job job = Workers::job();
|
||||
m_sequence = Workers::sequence();
|
||||
if (m_job == job) {
|
||||
return;
|
||||
}
|
||||
|
||||
memcpy(m_result.jobId, m_job.id(), sizeof(m_result.jobId));
|
||||
m_result.poolId = m_job.poolId();
|
||||
save(job);
|
||||
|
||||
if (m_nicehash) {
|
||||
if (resume(job)) {
|
||||
return;
|
||||
}
|
||||
|
||||
m_job = std::move(job);
|
||||
m_result = m_job;
|
||||
|
||||
if (m_job.isNicehash()) {
|
||||
m_result.nonce = (*m_job.nonce() & 0xff000000U) + (0xffffffU / m_threads * m_id);
|
||||
}
|
||||
else {
|
||||
m_result.nonce = 0xffffffffU / m_threads * m_id;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void SingleWorker::save(const Job &job)
|
||||
{
|
||||
if (job.poolId() == -1 && m_job.poolId() >= 0) {
|
||||
m_paused = m_job;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -41,9 +41,12 @@ public:
|
||||
void start() override;
|
||||
|
||||
private:
|
||||
bool resume(const Job &job);
|
||||
void consumeJob();
|
||||
void save(const Job &job);
|
||||
|
||||
Job m_job;
|
||||
Job m_paused;
|
||||
JobResult m_result;
|
||||
};
|
||||
|
||||
|
||||
@@ -23,7 +23,6 @@
|
||||
|
||||
#include <chrono>
|
||||
|
||||
#include "Console.h"
|
||||
|
||||
#include "Cpu.h"
|
||||
#include "Mem.h"
|
||||
@@ -32,7 +31,6 @@
|
||||
|
||||
|
||||
Worker::Worker(Handle *handle) :
|
||||
m_nicehash(handle->nicehash()),
|
||||
m_id(handle->threadId()),
|
||||
m_threads(handle->threads()),
|
||||
m_hashCount(0),
|
||||
|
||||
@@ -48,7 +48,6 @@ public:
|
||||
protected:
|
||||
void storeStats();
|
||||
|
||||
bool m_nicehash;
|
||||
cryptonight_ctx *m_ctx;
|
||||
int m_id;
|
||||
int m_threads;
|
||||
|
||||
@@ -24,7 +24,6 @@
|
||||
#include <cmath>
|
||||
|
||||
|
||||
#include "Console.h"
|
||||
#include "interfaces/IJobResultListener.h"
|
||||
#include "Mem.h"
|
||||
#include "Options.h"
|
||||
@@ -35,6 +34,8 @@
|
||||
#include "workers/Workers.h"
|
||||
|
||||
|
||||
bool Workers::m_active = false;
|
||||
bool Workers::m_enabled = true;
|
||||
Hashrate *Workers::m_hashrate = nullptr;
|
||||
IJobResultListener *Workers::m_listener = nullptr;
|
||||
Job Workers::m_job;
|
||||
@@ -59,18 +60,39 @@ Job Workers::job()
|
||||
}
|
||||
|
||||
|
||||
void Workers::setEnabled(bool enabled)
|
||||
{
|
||||
if (m_enabled == enabled) {
|
||||
return;
|
||||
}
|
||||
|
||||
m_enabled = enabled;
|
||||
if (!m_active) {
|
||||
return;
|
||||
}
|
||||
|
||||
m_paused = enabled ? 0 : 1;
|
||||
m_sequence++;
|
||||
}
|
||||
|
||||
|
||||
void Workers::setJob(const Job &job)
|
||||
{
|
||||
uv_rwlock_wrlock(&m_rwlock);
|
||||
m_job = job;
|
||||
uv_rwlock_wrunlock(&m_rwlock);
|
||||
|
||||
m_active = true;
|
||||
if (!m_enabled) {
|
||||
return;
|
||||
}
|
||||
|
||||
m_sequence++;
|
||||
m_paused = 0;
|
||||
}
|
||||
|
||||
|
||||
void Workers::start(int64_t affinity, bool nicehash)
|
||||
void Workers::start(int64_t affinity)
|
||||
{
|
||||
const int threads = Mem::threads();
|
||||
m_hashrate = new Hashrate(threads);
|
||||
@@ -78,7 +100,7 @@ void Workers::start(int64_t affinity, bool nicehash)
|
||||
uv_mutex_init(&m_mutex);
|
||||
uv_rwlock_init(&m_rwlock);
|
||||
|
||||
m_sequence = 0;
|
||||
m_sequence = 1;
|
||||
m_paused = 1;
|
||||
|
||||
uv_async_init(uv_default_loop(), &m_async, Workers::onResult);
|
||||
@@ -86,13 +108,27 @@ void Workers::start(int64_t affinity, bool nicehash)
|
||||
uv_timer_start(&m_timer, Workers::onTick, 500, 500);
|
||||
|
||||
for (int i = 0; i < threads; ++i) {
|
||||
Handle *handle = new Handle(i, threads, affinity, nicehash);
|
||||
Handle *handle = new Handle(i, threads, affinity);
|
||||
m_workers.push_back(handle);
|
||||
handle->start(Workers::onReady);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Workers::stop()
|
||||
{
|
||||
uv_timer_stop(&m_timer);
|
||||
m_hashrate->stop();
|
||||
|
||||
uv_close(reinterpret_cast<uv_handle_t*>(&m_async), nullptr);
|
||||
m_sequence = 0;
|
||||
|
||||
for (size_t i = 0; i < m_workers.size(); ++i) {
|
||||
m_workers[i]->join();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Workers::submit(const JobResult &result)
|
||||
{
|
||||
uv_mutex_lock(&m_mutex);
|
||||
|
||||
@@ -43,14 +43,17 @@ class Workers
|
||||
{
|
||||
public:
|
||||
static Job job();
|
||||
static void setEnabled(bool enabled);
|
||||
static void setJob(const Job &job);
|
||||
static void start(int64_t affinity, bool nicehash);
|
||||
static void start(int64_t affinity);
|
||||
static void stop();
|
||||
static void submit(const JobResult &result);
|
||||
|
||||
static inline bool isEnabled() { return m_enabled; }
|
||||
static inline bool isOutdated(uint64_t sequence) { return m_sequence.load(std::memory_order_relaxed) != sequence; }
|
||||
static inline bool isPaused() { return m_paused.load(std::memory_order_relaxed) == 1; }
|
||||
static inline uint64_t sequence() { return m_sequence.load(std::memory_order_relaxed); }
|
||||
static inline void pause() { m_paused = 1; }
|
||||
static inline void pause() { m_active = false; m_paused = 1; m_sequence++; }
|
||||
static inline void setListener(IJobResultListener *listener) { m_listener = listener; }
|
||||
|
||||
private:
|
||||
@@ -58,6 +61,8 @@ private:
|
||||
static void onResult(uv_async_t *handle);
|
||||
static void onTick(uv_timer_t *handle);
|
||||
|
||||
static bool m_active;
|
||||
static bool m_enabled;
|
||||
static Hashrate *m_hashrate;
|
||||
static IJobResultListener *m_listener;
|
||||
static Job m_job;
|
||||
|
||||
@@ -25,7 +25,7 @@
|
||||
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
auto app = new App(argc, argv);
|
||||
App app(argc, argv);
|
||||
|
||||
return app->exec();
|
||||
return app.exec();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user