1
0
mirror of https://github.com/xmrig/xmrig.git synced 2025-12-06 23:52:38 -05:00

Compare commits

...

53 Commits

Author SHA1 Message Date
XMRig
9f4e1ee373 Update version. 2017-07-14 21:26:22 +03:00
xmrig
ff0c6b6365 Update CHANGELOG.md 2017-07-14 21:22:48 +03:00
XMRig
7397efaf6d Merge branch 'master' of github.com:xmrig/xmrig 2017-07-14 21:16:05 +03:00
XMRig
aadc15ce66 Ignore duplicated job received from pool, with warning message. 2017-07-14 21:06:08 +03:00
XMRig
ad7c925a1a Merge branch 'dev' 2017-07-14 20:54:32 +03:00
XMRig
57be6f94bb Small code cleanup. 2017-07-13 18:02:48 +03:00
xmrig
35b188762c Update README.md 2017-07-12 14:02:07 +03:00
XMRig
7c6e429854 Improved pause/resume mechanism. 2017-07-10 21:42:28 +03:00
XMRig
c15aefd968 Merge branch 'master' into dev 2017-07-10 18:53:39 +03:00
XMRig
4a712354f1 #28 Fixed Alpine Linux support. 2017-07-07 07:15:58 +03:00
xmrig
4545c84a11 Update CHANGELOG.md 2017-07-06 10:05:36 +03:00
XMRig
a66297bed8 Merge branch 'master' into dev 2017-07-06 09:36:16 +03:00
XMRig
f4dadfd90b Improve nicehash detection. 2017-07-05 07:54:21 +03:00
XMRig
955134b162 #27 Fix possibility crash on 32bit. 2017-07-05 07:20:28 +03:00
XMRig
68795137da Merge branch 'master' into dev 2017-07-04 14:56:40 +03:00
XMRig
6ed2d61586 Probably fix OS X support. 2017-07-03 11:02:32 +03:00
xmrig
a96782218f Update README.md 2017-07-03 07:24:56 +03:00
XMRig
32e7041def Fix possibility duplicate share for short donation intervals. 2017-07-03 03:34:23 +03:00
XMRig
c16388ade3 Fix possibility crash 2017-07-02 23:35:06 +03:00
xmrig
72569a7fc7 Update README.md 2017-07-02 22:21:29 +03:00
XMRig
751be470b8 Merge branch 'dev'
# Conflicts:
#	options.c
#	src/version.h
2017-07-02 22:16:23 +03:00
XMRig
7937c814ff v2.0.0 rc 2017-07-02 21:49:56 +03:00
xmrig
8e42fb9138 Update CHANGELOG.md 2017-07-02 07:36:24 +03:00
xmrig
dbc6f26c91 Update CHANGELOG.md 2017-07-02 07:34:02 +03:00
XMRig
074db6bb72 Add nice messages for accepted and rejected shares with diff and latency. 2017-07-02 05:33:10 +03:00
XMRig
71522214ae Show resolved pool ip. 2017-07-02 01:36:33 +03:00
XMRig
8ec58a8394 Fix nicehash support, please note --nicehash option now specified per pool. 2017-07-01 22:37:27 +03:00
XMRig
263634f585 Increase major version because --backup-url option removed and added ability to specify multiple pool urls. 2017-07-01 22:14:44 +03:00
XMRig
a383eba8df Merge branch 'feature-multiple-pools' into dev
# Conflicts:
#	src/Options.cpp
2017-07-01 21:50:27 +03:00
XMRig
152b65b67c Increase response timeout to 20 seconds. 2017-07-01 21:11:41 +03:00
XMRig
970b5d1964 Add FailoverStrategy. 2017-07-01 20:53:42 +03:00
XMRig
7536663caf Remove option --backup-url. 2017-06-30 13:23:13 +03:00
XMRig
7e17f77c11 Implemented DonateStrategy. 2017-06-30 03:20:50 +03:00
XMRig
25faeabd61 Implemented SinglePoolStrategy. 2017-06-29 01:48:23 +03:00
XMRig
bd8776b7ee Add classes SinglePoolStrategy, DonateStrategy, IStrategy, IStrategyListener. 2017-06-28 06:17:02 +03:00
XMRig
b2d26eb019 Use Url inside Client. Remove onLoginCredentialsRequired from IClientListener interface. 2017-06-28 04:04:04 +03:00
XMRig
14c6f8699e Fix --cpu-affinity overflow, again. 2017-06-27 18:47:33 +03:00
XMRig
c0dcfc2a97 Initial multiple pools support [2/2]. 2017-06-27 06:32:17 +03:00
XMRig
f36b5eeaad Fix --cpu-affinity overflow. 2017-06-26 23:08:10 +03:00
XMRig
952017ae7a Initial multiple pools support [1/2]. 2017-06-26 21:13:05 +03:00
XMRig
faf793b0aa Add syslog support. 2017-06-25 02:04:59 +03:00
XMRig
e97cd98f90 Fix file log for linux. 2017-06-23 19:37:41 +03:00
XMRig
95002ead7d Merge branch 'dev' of https://github.com/xmrig/xmrig into dev 2017-06-23 12:58:56 +03:00
XMRig
c1b3802590 Add option "-l, --log-file=FILE" and stub for option "-S, --syslog". 2017-06-23 03:12:46 +03:00
XMRig
1bfbc97c7d Add FileLog class. 2017-06-23 01:38:47 +03:00
XMRig
052290d0e9 Add ConsoleLog class and ILogBackend interface. 2017-06-22 14:41:34 +03:00
XMRig
4f512c41d4 Fix linux build 2017-06-22 02:30:26 +03:00
XMRig
91ed7e36cd Temporary disable TCP keepalive for Windows, fixes Windows XP support. 2017-06-21 21:40:15 +03:00
XMRig
77d9beaf89 Rename Console class to Log. 2017-06-20 13:04:38 +03:00
XMRig
a791bc113e Adjust console output. 2017-06-20 00:55:55 +03:00
XMRig
9bfa49b7d0 Fix regression, option --no-color not fully disabled colored output. 2017-06-19 10:58:28 +03:00
XMRig
9dc02fc7f3 Fix for -a cryptonight-light. 2017-06-06 03:34:49 +03:00
XMRig
6551818610 Update libjansson to 2.10. 2017-06-06 03:31:44 +03:00
55 changed files with 1827 additions and 533 deletions

View File

@@ -1,3 +1,20 @@
# 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.

View File

@@ -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")
@@ -161,6 +179,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 +192,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})

View File

@@ -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

View File

@@ -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();

View File

@@ -29,8 +29,8 @@
#include "App.h"
#include "Console.h"
#include "Cpu.h"
#include "log/Log.h"
#include "Options.h"

View File

@@ -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; }

View File

@@ -40,6 +40,6 @@ void Cpu::init()
}
void Cpu::setAffinity(int id, unsigned long mask)
void Cpu::setAffinity(int id, uint64_t mask)
{
}

View File

@@ -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);

View File

@@ -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);

View File

@@ -25,6 +25,7 @@
#define __MEM_H__
#include <stddef.h>
#include <stdint.h>

View File

@@ -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)

View File

@@ -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"

View File

@@ -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

View File

@@ -25,6 +25,7 @@
#define __OPTIONS_H__
#include <vector>
#include <stdint.h>
@@ -55,12 +56,9 @@ public:
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 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; }
@@ -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__ */

View File

@@ -25,8 +25,8 @@
#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 +50,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",
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 +72,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",
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
}
}
@@ -100,28 +100,32 @@ static void print_threads()
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",
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(),
Options::i()->nicehash() ? ", nicehash" : "", buf);
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
}

View File

@@ -25,6 +25,9 @@
#define __ICLIENTLISTENER_H__
#include <stdint.h>
class Client;
class Job;
@@ -36,8 +39,8 @@ public:
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 onResultAccepted(Client *client, uint32_t diff, uint64_t ms, const char *error) = 0;
};

View 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__

View 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 __ISTRATEGY_H__
#define __ISTRATEGY_H__
class JobResult;
class IStrategy
{
public:
virtual ~IStrategy() {}
virtual bool isActive() const = 0;
virtual void connect() = 0;
virtual void resume() = 0;
virtual void submit(const JobResult &result) = 0;
};
#endif // __ISTRATEGY_H__

View 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, uint32_t diff, uint64_t ms, const char *error) = 0;
};
#endif // __ISTRATEGYLISTENER_H__

View File

@@ -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
View 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
View 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
View 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
View 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;
}
}

View File

@@ -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
View 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
View 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__ */

View File

@@ -22,10 +22,11 @@
*/
#include <iterator>
#include <utility>
#include "Console.h"
#include "log/Log.h"
#include "interfaces/IClientListener.h"
#include "net/Client.h"
#include "net/JobResult.h"
@@ -37,9 +38,9 @@
#endif
Client::Client(int id, IClientListener *listener) :
m_keepAlive(false),
m_host(nullptr),
Client::Client(int id, const char *agent, IClientListener *listener) :
m_quiet(false),
m_agent(agent),
m_listener(listener),
m_id(id),
m_retryPause(5000),
@@ -47,16 +48,17 @@ Client::Client(int id, IClientListener *listener) :
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 +74,12 @@ Client::~Client()
{
free(m_recvBuf.base);
free(m_socket);
free(m_host);
}
void Client::connect()
{
resolve(m_host);
resolve(m_url.host());
}
@@ -90,30 +91,19 @@ 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_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.
*
@@ -121,9 +111,9 @@ void Client::login(const char *user, const char *pass, const char *agent)
*/
void Client::send(char *data)
{
LOG_DEBUG("[%s:%u] send (%d bytes): \"%s\"", m_host, m_port, strlen(data), data);
LOG_DEBUG("[%s:%u] send (%d bytes): \"%s\"", m_url.host(), m_url.port(), strlen(data), data);
if (state() != ConnectedState) {
LOG_DEBUG_ERR("[%s:%u] send failed, invalid state: %d", m_host, m_port, m_state);
LOG_DEBUG_ERR("[%s:%u] send failed, invalid state: %d", m_url.host(), m_url.port(), m_state);
return;
}
@@ -148,9 +138,7 @@ void Client::setUrl(const Url *url)
return;
}
free(m_host);
m_host = strdup(url->host());
m_port = url->port();
m_url = url;
}
@@ -169,6 +157,7 @@ void Client::submit(const JobResult &result)
snprintf(req, 345, "{\"id\":%llu,\"jsonrpc\":\"2.0\",\"method\":\"submit\",\"params\":{\"id\":\"%s\",\"job_id\":\"%s\",\"nonce\":\"%s\",\"result\":\"%s\"}}\n",
m_sequence, m_rpcId, result.jobId, nonce, data);
m_results[m_sequence] = SubmitResult(result.diff);
send(req);
}
@@ -180,7 +169,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 +185,14 @@ bool Client::parseJob(const json_t *params, int *code)
return false;
}
job.setPoolId(m_id);
if (m_job == job) {
LOG_WARN("[%s:%u] duplicate job received, ignore", m_url.host(), m_url.port());
return false;
}
m_job = std::move(job);
LOG_DEBUG("[%s:%u] job: \"%s\", diff: %lld", m_host, m_port, job.id(), job.diff());
LOG_DEBUG("[%s:%u] job: \"%s\", diff: %lld", m_url.host(), m_url.port(), job.id(), job.diff());
return true;
}
@@ -225,9 +218,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;
}
@@ -250,7 +249,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,25 +260,43 @@ void Client::connect(struct sockaddr *addr)
uv_tcp_init(uv_default_loop(), m_socket);
uv_tcp_nodelay(m_socket, 1);
# ifndef WIN32
uv_tcp_keepalive(m_socket, 1, 60);
# endif
uv_tcp_connect(req, m_socket, (const sockaddr*) addr, Client::onConnect);
}
void Client::login()
{
m_sequence = 1;
m_results.clear();
const size_t size = 96 + strlen(m_url.user()) + strlen(m_url.password()) + strlen(m_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, m_url.user(), m_url.password(), m_agent);
send(req);
}
void Client::parse(char *line, size_t len)
{
startTimeout();
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 +315,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: %lld", 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 +334,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 +342,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.diff, it->second.elapsed(), message);
m_results.erase(it);
}
else if (!m_quiet) {
LOG_ERR("[%s:%u] error: \"%s\", code: %lld", 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 +366,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,6 +378,12 @@ 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.diff, it->second.elapsed(), nullptr);
m_results.erase(it);
}
}
@@ -362,8 +398,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 +418,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 +431,7 @@ void Client::setState(SocketState state)
void Client::startTimeout()
{
uv_timer_stop(&m_responseTimer);
if (!m_keepAlive) {
if (!m_url.isKeepAlive()) {
return;
}
@@ -428,7 +466,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 +482,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 +490,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 +530,12 @@ 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();;
}
uv_ip4_name(reinterpret_cast<sockaddr_in*>(res->ai_addr), client->m_ip, 16);
client->connect(res->ai_addr);
uv_freeaddrinfo(res);
}
Client *Client::getClient(void *data)
{
return static_cast<Client*>(data);
}

View File

@@ -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();
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,11 +96,12 @@ 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;
bool m_quiet;
char m_ip[17];
char m_rpcId[64];
const char *m_agent;
IClientListener *m_listener;
int m_id;
int m_retryPause;
@@ -106,8 +110,9 @@ private:
Job m_job;
size_t m_recvBufPos;
SocketState m_state;
std::map<int64_t, SubmitResult> m_results;
struct addrinfo m_hints;
uint16_t m_port;
Url m_url;
uv_buf_t m_recvBuf;
uv_getaddrinfo_t m_resolver;
uv_stream_t *m_stream;

View File

@@ -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,15 @@ 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;
}
return true;
}
@@ -156,3 +164,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;
}

View File

@@ -34,11 +34,12 @@
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 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; }
@@ -47,14 +48,17 @@ public:
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 void setNicehash(bool nicehash) { m_nicehash = nicehash; }
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.

View File

@@ -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];
};

View File

@@ -25,79 +25,68 @@
#include <memory>
#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);
m_pools.reserve(2);
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::onActive(Client *client)
{
const int id = client->id();
if (id == 0) {
if (failures == -1) {
stopDonate();
}
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 +96,52 @@ 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) {
return m_donate->submit(result);
}
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, pause mining");
return Workers::pause();
}
}
void Network::onResultAccepted(Client *client, uint32_t diff, uint64_t ms, const char *error)
{
if (error) {
m_rejected++;
LOG_INFO(m_options->colors() ? "\x1B[01;31mrejected\x1B[0m (%lld/%lld) diff \x1B[01;37m%u\x1B[0m \x1B[31m\"%s\"\x1B[0m \x1B[01;30m(%llu ms)" : "accepted (%lld/%lld) diff %u \"%s\" (%llu 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 (%lld/%lld) diff \x1B[01;37m%u\x1B[0m \x1B[01;30m(%llu ms)" : "accepted (%lld/%lld) diff %u (%llu 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);
}

View File

@@ -29,15 +29,16 @@
#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);
@@ -48,27 +49,22 @@ public:
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, 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;
};

47
src/net/SubmitResult.h Normal file
View 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 __SUBMITRESULT_H__
#define __SUBMITRESULT_H__
#include <uv.h>
class SubmitResult
{
public:
inline SubmitResult() : diff(0), start(0) {}
inline SubmitResult(uint32_t diff) :
diff(diff)
{
start = uv_hrtime();
}
inline uint64_t elapsed() const { return (uv_hrtime() - start) / 1000000; }
uint32_t diff;
uint64_t start;
};
#endif /* __SUBMITRESULT_H__ */

View File

@@ -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;
}

View File

@@ -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; }
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;
};

View File

@@ -0,0 +1,119 @@
/* 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("donate2.xmrig.com", Options::i()->algo() == Options::ALGO_CRYPTONIGHT_LITE ? 3333 : 443, Options::i()->pools().front()->user());
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();
}
void DonateStrategy::connect()
{
m_client->connect();
}
void DonateStrategy::submit(const JobResult &result)
{
m_client->submit(result);
}
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, uint32_t diff, uint64_t ms, const char *error)
{
m_listener->onResultAccepted(client, diff, ms, error);
}
void DonateStrategy::idle()
{
uv_timer_start(&m_timer, DonateStrategy::onTimer, m_idleTime, 0);
}
void DonateStrategy::stop()
{
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->stop();
}

View File

@@ -0,0 +1,72 @@
/* 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 {}
void connect() override;
void submit(const JobResult &result) 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, uint32_t diff, uint64_t ms, const char *error) override;
private:
void idle();
void stop();
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__ */

View File

@@ -0,0 +1,127 @@
/* 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);
}
}
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::submit(const JobResult &result)
{
m_pools[m_active]->submit(result);
}
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, uint32_t diff, uint64_t ms, const char *error)
{
m_listener->onResultAccepted(client, 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);
}

View File

@@ -0,0 +1,67 @@
/* 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; }
void connect() override;
void resume() override;
void submit(const JobResult &result) 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, 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__ */

View File

@@ -0,0 +1,90 @@
/* 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);
}
void SinglePoolStrategy::connect()
{
m_client->connect();
}
void SinglePoolStrategy::resume()
{
if (!isActive()) {
return;
}
m_listener->onJob(m_client, m_client->job());
}
void SinglePoolStrategy::submit(const JobResult &result)
{
m_client->submit(result);
}
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, uint32_t diff, uint64_t ms, const char *error)
{
m_listener->onResultAccepted(client, diff, ms, error);
}

View File

@@ -0,0 +1,61 @@
/* 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; }
void connect() override;
void resume() override;
void submit(const JobResult &result) 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, uint32_t diff, uint64_t ms, const char *error) override;
private:
bool m_active;
Client *m_client;
IStrategyListener *m_listener;
};
#endif /* __SINGLEPOOLSTRATEGY_H__ */

View File

@@ -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.0.2"
#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_MAJOR 2
#define APP_VER_MINOR 0
#define APP_VER_BUILD 1
#define APP_VER_BUILD 2
#define APP_VER_REV 0
#ifdef _MSC_VER

View File

@@ -30,11 +30,33 @@
#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;
}
@@ -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;
}
}

View File

@@ -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;
};

View File

@@ -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),

View File

@@ -35,10 +35,9 @@ class IWorker;
class Handle
{
public:
Handle(int threadId, int threads, int64_t affinity, bool nicehash);
Handle(int threadId, int threads, int64_t affinity);
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 +45,6 @@ public:
inline void setWorker(IWorker *worker) { m_worker = worker; }
private:
bool m_nicehash;
int m_threadId;
int m_threads;
int64_t m_affinity;

View File

@@ -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)),

View File

@@ -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;
}
}

View File

@@ -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;
};

View File

@@ -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),

View File

@@ -48,7 +48,6 @@ public:
protected:
void storeStats();
bool m_nicehash;
cryptonight_ctx *m_ctx;
int m_id;
int m_threads;

View File

@@ -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);
@@ -86,7 +108,7 @@ 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);
}

View File

@@ -43,14 +43,16 @@ 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 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 +60,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;