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

Compare commits

...

31 Commits

Author SHA1 Message Date
xmrig
92d787c817 Update CHANGELOG.md 2017-08-04 11:51:09 +03:00
XMRig
816fc3ee43 Fixed terminal issues after exit on Linux and OS X. 2017-08-04 11:10:33 +03:00
XMRig
7004a51ce6 v2.2.0 2017-08-02 20:08:41 +03:00
XMRig
3cc18d30de Merge branch 'dev' 2017-08-02 20:01:10 +03:00
xmrig
bd3665e111 Update CHANGELOG.md 2017-08-02 19:53:10 +03:00
XMRig
a680220d28 Fixed autoconf mode for AMD FX CPUs. 2017-08-02 18:59:24 +03:00
xmrig
2d1fdec618 Update CHANGELOG.md 2017-08-01 20:20:30 +03:00
XMRig
b1a2215829 Add missing port in config.json. 2017-08-01 19:34:36 +03:00
XMRig
eb5f7c6a7b #46 Simplify config parsing 2017-08-01 12:56:30 +03:00
XMRig
1bc23354d3 #46 Add support for default config. 2017-07-31 18:38:02 +03:00
XMRig
e6a72b2f78 #46 Added config file support. 2017-07-31 16:05:16 +03:00
XMRig
5bed17a8af Fix stop for FailoverStrategy. 2017-07-27 07:36:16 +03:00
XMRig
7b21749a19 Merge branch 'feature-async-console' into dev 2017-07-23 11:08:09 +03:00
XMRig
0b5587fd6a Add commands help. 2017-07-23 10:04:23 +03:00
XMRig
776f77a8d4 Added IConsoleListener 2017-07-23 09:36:30 +03:00
XMRig
583f45e2da Add Console class. 2017-07-23 08:35:26 +03:00
XMRig
9b474f239f Disable QuickEdit mode for Windows. 2017-07-23 07:38:57 +03:00
XMRig
9665ff15ae Use uv_tty for console output and remove legacy winansi. 2017-07-23 05:59:57 +03:00
xmrig
b6bf6d9bc9 Update CHANGELOG.md 2017-07-20 02:56:07 +03:00
XMRig
3d9be9484d Merge branch 'dev'
# Conflicts:
#	src/version.h
2017-07-20 00:54:03 +03:00
XMRig
35fd43a6b4 Changed donation address, new xmrig-proxy is coming soon. 2017-07-19 23:57:03 +03:00
xmrig
294453fdc1 Update CHANGELOG.md 2017-07-19 23:54:50 +03:00
XMRig
30a7f9f7f5 Backport crypto changes from Dead2 xmr-stak-cpu fork. 2017-07-19 21:02:38 +03:00
XMRig
8f38462bbe #40 Fix crash on Linux. 2017-07-19 04:28:59 +03:00
XMRig
ebf54c6d04 Fix warnings on Linux. 2017-07-18 22:38:38 +03:00
XMRig
d7659b5093 Fixed %lld and %llu related warnings. 2017-07-18 20:20:29 +03:00
XMRig
e00c568ae9 Fix OS X build. 2017-07-18 14:09:20 +03:00
XMRig
a3988374f0 Fixed graceful shutdown. 2017-07-18 05:20:36 +03:00
XMRig
9732636155 Fixed bug, login request was contain malformed JSON if username or password has some special characters for example \. 2017-07-18 01:49:04 +03:00
XMRig
986aee4297 Better support for Round Robin DNS, related https://github.com/fireice-uk/xmr-stak-cpu/pull/220 2017-07-17 23:35:36 +03:00
XMRig
66d3e96a1a Sync changes with upcoming xmrig-proxy project. 2017-07-17 21:57:03 +03:00
49 changed files with 1011 additions and 2081 deletions

View File

@@ -1,3 +1,20 @@
# v2.2.1
- Fixed [terminal issues](https://github.com/xmrig/xmrig-proxy/issues/2#issuecomment-319914085) after exit on Linux and OS X.
# v2.2.0
- [#46](https://github.com/xmrig/xmrig/issues/46) Restored config file support. Now possible use multiple config files and combine with command line options also added support for default config.
- Improved colors support on Windows, now used uv_tty, legacy code removed.
- QuickEdit Mode now disabled on Windows.
- Added interactive commands in console window:: **h**ashrate, **p**ause, **r**esume.
- Fixed autoconf mode for AMD FX CPUs.
# v2.1.0
- [#40](https://github.com/xmrig/xmrig/issues/40)
Improved miner shutdown, fixed crash on exit for Linux and OS X.
- Fixed, login request was contain malformed JSON if username or password has some special characters for example `\`.
- [#220](https://github.com/fireice-uk/xmr-stak-cpu/pull/220) Better support for Round Robin DNS, IP address now always chosen randomly instead of stuck on first one.
- Changed donation address, new [xmrig-proxy](https://github.com/xmrig/xmrig-proxy) is coming soon.
# v2.0.2
- Better deal with possible duplicate jobs from pool, show warning and ignore duplicates.
- For Windows builds libuv updated to version 1.13.1 and gcc to 7.1.0.

View File

@@ -11,8 +11,10 @@ include (CheckIncludeFile)
set(HEADERS
src/3rdparty/align.h
src/App.h
src/Console.h
src/Cpu.h
src/interfaces/IClientListener.h
src/interfaces/IConsoleListener.h
src/interfaces/IJobResultListener.h
src/interfaces/ILogBackend.h
src/interfaces/IStrategy.h
@@ -58,6 +60,7 @@ set(HEADERS_CRYPTO
set(SOURCES
src/App.cpp
src/Console.cpp
src/log/ConsoleLog.cpp
src/log/FileLog.cpp
src/log/Log.cpp
@@ -65,10 +68,10 @@ set(SOURCES
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/net/Url.cpp
src/Options.cpp
src/Summary.cpp
src/workers/DoubleWorker.cpp
@@ -94,8 +97,6 @@ set(SOURCES_CRYPTO
if (WIN32)
set(SOURCES_OS
res/app.rc
src/3rdparty/winansi.cpp
src/3rdparty/winansi.h
src/App_win.cpp
src/Cpu_win.cpp
src/Mem_win.cpp
@@ -145,6 +146,7 @@ if (CMAKE_CXX_COMPILER_ID MATCHES GNU)
if (WIN32)
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -static")
add_definitions(/D__STDC_FORMAT_MACROS)
else()
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -static-libgcc -static-libstdc++")
endif()

View File

@@ -1,392 +0,0 @@
/**
* Old Git implementation of windows terminal colors (2009)
* before use of a threaded wrapper.
*/
#undef NOGDI
#include <windows.h>
#include <wingdi.h>
#include <winreg.h>
#include <malloc.h>
#include <stdio.h>
#include <io.h>
#include "winansi.h"
/*
* Copyright 2008 Peter Harris <git@peter.is-a-geek.org>
*/
/*
Functions to be wrapped:
*/
#undef printf
#undef fprintf
#undef fputs
#undef vfprintf
/* TODO: write */
/*
ANSI codes used by git: m, K
This file is git-specific. Therefore, this file does not attempt
to implement any codes that are not used by git.
*/
static HANDLE console;
static WORD plain_attr;
static WORD attr;
static int negative;
static void init(void)
{
CONSOLE_SCREEN_BUFFER_INFO sbi;
static int initialized = 0;
if (initialized)
return;
console = GetStdHandle(STD_OUTPUT_HANDLE);
if (console == INVALID_HANDLE_VALUE)
console = NULL;
if (!console)
return;
GetConsoleScreenBufferInfo(console, &sbi);
attr = plain_attr = sbi.wAttributes;
negative = 0;
initialized = 1;
}
static int write_console(const char *str, int len)
{
/* convert utf-8 to utf-16, write directly to console */
int wlen = MultiByteToWideChar(CP_UTF8, 0, str, len, NULL, 0);
wchar_t *wbuf = (wchar_t *)alloca(wlen * sizeof(wchar_t));
MultiByteToWideChar(CP_UTF8, 0, str, len, wbuf, wlen);
WriteConsoleW(console, wbuf, wlen, NULL, NULL);
/* return original (utf-8 encoded) length */
return len;
}
#define FOREGROUND_ALL (FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE)
#define BACKGROUND_ALL (BACKGROUND_RED | BACKGROUND_GREEN | BACKGROUND_BLUE)
static void set_console_attr(void)
{
WORD attributes = attr;
if (negative) {
attributes &= ~FOREGROUND_ALL;
attributes &= ~BACKGROUND_ALL;
/* This could probably use a bitmask
instead of a series of ifs */
if (attr & FOREGROUND_RED)
attributes |= BACKGROUND_RED;
if (attr & FOREGROUND_GREEN)
attributes |= BACKGROUND_GREEN;
if (attr & FOREGROUND_BLUE)
attributes |= BACKGROUND_BLUE;
if (attr & BACKGROUND_RED)
attributes |= FOREGROUND_RED;
if (attr & BACKGROUND_GREEN)
attributes |= FOREGROUND_GREEN;
if (attr & BACKGROUND_BLUE)
attributes |= FOREGROUND_BLUE;
}
SetConsoleTextAttribute(console, attributes);
}
static void erase_in_line(void)
{
CONSOLE_SCREEN_BUFFER_INFO sbi;
DWORD dummy; /* Needed for Windows 7 (or Vista) regression */
if (!console)
return;
GetConsoleScreenBufferInfo(console, &sbi);
FillConsoleOutputCharacterA(console, ' ',
sbi.dwSize.X - sbi.dwCursorPosition.X, sbi.dwCursorPosition,
&dummy);
}
static const char *set_attr(const char *str)
{
const char *func;
size_t len = strspn(str, "0123456789;");
func = str + len;
switch (*func) {
case 'm':
do {
long val = strtol(str, (char **)&str, 10);
switch (val) {
case 0: /* reset */
attr = plain_attr;
negative = 0;
break;
case 1: /* bold */
attr |= FOREGROUND_INTENSITY;
break;
case 2: /* faint */
case 22: /* normal */
attr &= ~FOREGROUND_INTENSITY;
break;
case 3: /* italic */
/* Unsupported */
break;
case 4: /* underline */
case 21: /* double underline */
/* Wikipedia says this flag does nothing */
/* Furthermore, mingw doesn't define this flag
attr |= COMMON_LVB_UNDERSCORE; */
break;
case 24: /* no underline */
/* attr &= ~COMMON_LVB_UNDERSCORE; */
break;
case 5: /* slow blink */
case 6: /* fast blink */
/* We don't have blink, but we do have
background intensity */
attr |= BACKGROUND_INTENSITY;
break;
case 25: /* no blink */
attr &= ~BACKGROUND_INTENSITY;
break;
case 7: /* negative */
negative = 1;
break;
case 27: /* positive */
negative = 0;
break;
case 8: /* conceal */
case 28: /* reveal */
/* Unsupported */
break;
case 30: /* Black */
attr &= ~FOREGROUND_ALL;
break;
case 31: /* Red */
attr &= ~FOREGROUND_ALL;
attr |= FOREGROUND_RED;
break;
case 32: /* Green */
attr &= ~FOREGROUND_ALL;
attr |= FOREGROUND_GREEN;
break;
case 33: /* Yellow */
attr &= ~FOREGROUND_ALL;
attr |= FOREGROUND_RED | FOREGROUND_GREEN;
break;
case 34: /* Blue */
attr &= ~FOREGROUND_ALL;
attr |= FOREGROUND_BLUE;
break;
case 35: /* Magenta */
attr &= ~FOREGROUND_ALL;
attr |= FOREGROUND_RED | FOREGROUND_BLUE;
break;
case 36: /* Cyan */
attr &= ~FOREGROUND_ALL;
attr |= FOREGROUND_GREEN | FOREGROUND_BLUE;
break;
case 37: /* White */
attr |= FOREGROUND_RED |
FOREGROUND_GREEN |
FOREGROUND_BLUE;
break;
case 38: /* Unknown */
break;
case 39: /* reset */
attr &= ~FOREGROUND_ALL;
attr |= (plain_attr & FOREGROUND_ALL);
break;
case 40: /* Black */
attr &= ~BACKGROUND_ALL;
break;
case 41: /* Red */
attr &= ~BACKGROUND_ALL;
attr |= BACKGROUND_RED;
break;
case 42: /* Green */
attr &= ~BACKGROUND_ALL;
attr |= BACKGROUND_GREEN;
break;
case 43: /* Yellow */
attr &= ~BACKGROUND_ALL;
attr |= BACKGROUND_RED | BACKGROUND_GREEN;
break;
case 44: /* Blue */
attr &= ~BACKGROUND_ALL;
attr |= BACKGROUND_BLUE;
break;
case 45: /* Magenta */
attr &= ~BACKGROUND_ALL;
attr |= BACKGROUND_RED | BACKGROUND_BLUE;
break;
case 46: /* Cyan */
attr &= ~BACKGROUND_ALL;
attr |= BACKGROUND_GREEN | BACKGROUND_BLUE;
break;
case 47: /* White */
attr |= BACKGROUND_RED |
BACKGROUND_GREEN |
BACKGROUND_BLUE;
break;
case 48: /* Unknown */
break;
case 49: /* reset */
attr &= ~BACKGROUND_ALL;
attr |= (plain_attr & BACKGROUND_ALL);
break;
default:
/* Unsupported code */
break;
}
str++;
} while (*(str - 1) == ';');
set_console_attr();
break;
case 'K':
erase_in_line();
break;
default:
/* Unsupported code */
break;
}
return func + 1;
}
static int ansi_emulate(const char *str, FILE *stream)
{
int rv = 0;
const char *pos = str;
fflush(stream);
while (*pos) {
pos = strstr(str, "\033[");
if (pos) {
int len = (int) (pos - str);
if (len) {
int out_len = write_console(str, len);
rv += out_len;
if (out_len < len)
return rv;
}
str = pos + 2;
rv += 2;
pos = set_attr(str);
rv += (int) (pos - str);
str = pos;
}
else {
int len = (int) strlen(str);
rv += write_console(str, len);
return rv;
}
}
return rv;
}
int winansi_fputs(const char *str, FILE *stream)
{
int rv;
if (!isatty(fileno(stream)))
return fputs(str, stream);
init();
if (!console)
return fputs(str, stream);
rv = ansi_emulate(str, stream);
if (rv >= 0)
return 0;
else
return EOF;
}
int winansi_vfprintf(FILE *stream, const char *format, va_list list)
{
int len, rv;
char small_buf[256] = { 0 };
char *buf = small_buf;
va_list cp;
if (!isatty(fileno(stream)))
goto abort;
init();
if (!console)
goto abort;
va_copy(cp, list);
len = vsnprintf(small_buf, sizeof(small_buf), format, cp);
#ifdef WIN32
/* bug on long strings without that */
if (len == -1)
len = _vscprintf(format, cp);
#endif
va_end(cp);
if ((unsigned) len > sizeof(small_buf) - 1) {
buf = (char*)malloc(len + 1);
if (!buf)
goto abort;
len = vsnprintf(buf, len + 1, format, list);
#ifdef WIN32
if (len == -1)
len = _vscprintf(format, list);
#endif
}
rv = ansi_emulate(buf, stream);
if (buf != small_buf)
free(buf);
return rv;
abort:
rv = vfprintf(stream, format, list);
return rv;
}
int winansi_fprintf(FILE *stream, const char *format, ...)
{
va_list list;
int rv;
va_start(list, format);
rv = winansi_vfprintf(stream, format, list);
va_end(list);
return rv;
}
int winansi_printf(const char *format, ...)
{
va_list list;
int rv;
va_start(list, format);
rv = winansi_vfprintf(stdout, format, list);
va_end(list);
return rv;
}

View File

@@ -1,29 +0,0 @@
/*
* ANSI emulation wrappers
*/
#include <windows.h>
#include <stddef.h>
#include <stdio.h>
#define fileno(fd) _fileno(fd)
#ifdef __cplusplus
extern "C" {
#endif
int winansi_fputs(const char *str, FILE *stream);
int winansi_printf(const char *format, ...);
int winansi_fprintf(FILE *stream, const char *format, ...);
int winansi_vfprintf(FILE *stream, const char *format, va_list list);
#ifdef __cplusplus
}
#endif
#undef fputs
#undef fprintf
#undef vfprintf
#define fputs winansi_fputs
#define printf winansi_printf
#define fprintf winansi_fprintf
#define vfprintf winansi_vfprintf

View File

@@ -27,6 +27,7 @@
#include "App.h"
#include "Console.h"
#include "Cpu.h"
#include "crypto/CryptoNight.h"
#include "log/ConsoleLog.h"
@@ -50,6 +51,7 @@ App *App::m_self = nullptr;
App::App(int argc, char **argv) :
m_console(nullptr),
m_network(nullptr),
m_options(nullptr)
{
@@ -62,6 +64,7 @@ App::App(int argc, char **argv) :
if (!m_options->background()) {
Log::add(new ConsoleLog(m_options->colors()));
m_console = new Console(this);
}
if (m_options->logFile()) {
@@ -82,6 +85,7 @@ App::App(int argc, char **argv) :
App::~App()
{
delete m_console;
}
@@ -111,6 +115,7 @@ int App::exec()
const int r = uv_run(uv_default_loop(), UV_RUN_DEFAULT);
uv_loop_close(uv_default_loop());
uv_tty_reset_mode();
free(m_network);
free(m_options);
@@ -121,8 +126,44 @@ int App::exec()
}
void App::onConsoleCommand(char command)
{
switch (command) {
case 'h':
case 'H':
Workers::printHashrate(true);
break;
case 'p':
case 'P':
LOG_INFO(m_options->colors() ? "\x1B[01;33mpaused\x1B[0m, press \x1B[01;35mr\x1B[0m to resume" : "paused, press 'r' to resume");
Workers::setEnabled(false);
break;
case 'r':
case 'R':
if (!Workers::isEnabled()) {
LOG_INFO(m_options->colors() ? "\x1B[01;32mresumed" : "resumed");
Workers::setEnabled(true);
}
break;
case 3:
LOG_WARN("Ctrl+C received, exiting");
close();
break;
default:
break;
}
}
void App::close()
{
m_network->stop();
Workers::stop();
uv_stop(uv_default_loop());
}
@@ -147,5 +188,6 @@ void App::onSignal(uv_signal_t *handle, int signum)
break;
}
uv_signal_stop(handle);
m_self->close();
}

View File

@@ -28,11 +28,15 @@
#include <uv.h>
#include "interfaces/IConsoleListener.h"
class Console;
class Network;
class Options;
class App
class App : public IConsoleListener
{
public:
App(int argc, char **argv);
@@ -40,6 +44,9 @@ public:
int exec();
protected:
void onConsoleCommand(char command) override;
private:
void background();
void close();
@@ -48,6 +55,7 @@ private:
static App *m_self;
Console *m_console;
Network *m_network;
Options *m_options;
uv_signal_t m_signal;

57
src/Console.cpp Normal file
View File

@@ -0,0 +1,57 @@
/* 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 "Console.h"
#include "interfaces/IConsoleListener.h"
Console::Console(IConsoleListener *listener)
: m_listener(listener)
{
m_tty.data = this;
uv_tty_init(uv_default_loop(), &m_tty, 0, 1);
uv_tty_set_mode(&m_tty, UV_TTY_MODE_RAW);
uv_read_start(reinterpret_cast<uv_stream_t*>(&m_tty), Console::onAllocBuffer, Console::onRead);
}
void Console::onAllocBuffer(uv_handle_t *handle, size_t suggested_size, uv_buf_t *buf)
{
auto console = static_cast<Console*>(handle->data);
buf->len = 1;
buf->base = console->m_buf;
}
void Console::onRead(uv_stream_t *stream, ssize_t nread, const uv_buf_t *buf)
{
if (nread < 0) {
return uv_close(reinterpret_cast<uv_handle_t*>(stream), nullptr);
}
if (nread == 1) {
static_cast<Console*>(stream->data)->m_listener->onConsoleCommand(buf->base[0]);
}
}

49
src/Console.h Normal file
View File

@@ -0,0 +1,49 @@
/* XMRig
* Copyright 2010 Jeff Garzik <jgarzik@pobox.com>
* Copyright 2012-2014 pooler <pooler@litecoinpool.org>
* Copyright 2014 Lucas Jones <https://github.com/lucasjones>
* Copyright 2014-2016 Wolf9466 <https://github.com/OhGodAPet>
* Copyright 2016 Jay D Dee <jayddee246@gmail.com>
* Copyright 2016-2017 XMRig <support@xmrig.com>
*
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef __CONSOLE_H__
#define __CONSOLE_H__
#include <uv.h>
class IConsoleListener;
class Console
{
public:
Console(IConsoleListener *listener);
private:
static void onAllocBuffer(uv_handle_t *handle, size_t suggested_size, uv_buf_t *buf);
static void onRead(uv_stream_t *stream, ssize_t nread, const uv_buf_t *buf);
char m_buf[1];
IConsoleListener *m_listener;
uv_tty_t m_tty;
};
#endif /* __CONSOLE_H__ */

View File

@@ -29,13 +29,14 @@
#include "Cpu.h"
char Cpu::m_brand[64] = { 0 };
int Cpu::m_flags = 0;
int Cpu::m_l2_cache = 0;
int Cpu::m_l3_cache = 0;
int Cpu::m_sockets = 1;
int Cpu::m_totalCores = 0;
int Cpu::m_totalThreads = 0;
bool Cpu::m_l2_exclusive = false;
char Cpu::m_brand[64] = { 0 };
int Cpu::m_flags = 0;
int Cpu::m_l2_cache = 0;
int Cpu::m_l3_cache = 0;
int Cpu::m_sockets = 1;
int Cpu::m_totalCores = 0;
int Cpu::m_totalThreads = 0;
int Cpu::optimalThreadsCount(int algo, bool doubleHash, int maxCpuUsage)
@@ -44,7 +45,14 @@ int Cpu::optimalThreadsCount(int algo, bool doubleHash, int maxCpuUsage)
return 1;
}
int cache = m_l3_cache ? m_l3_cache : m_l2_cache;
int cache = 0;
if (m_l3_cache) {
cache = m_l2_exclusive ? (m_l2_cache + m_l3_cache) : m_l3_cache;
}
else {
cache = m_l2_cache;
}
int count = 0;
const int size = (algo ? 1024 : 2048) * (doubleHash ? 2 : 1);
@@ -84,8 +92,9 @@ void Cpu::initCommon()
m_l3_cache = data.l3_cache > 0 ? data.l3_cache * m_sockets : 0;
// Workaround for AMD CPUs https://github.com/anrieff/libcpuid/issues/97
if (data.vendor == VENDOR_AMD && data.l3_cache <= 0 && data.l2_assoc == 16 && data.ext_family >= 21) {
if (data.vendor == VENDOR_AMD && data.ext_family >= 0x15 && data.ext_family < 0x17) {
m_l2_cache = data.l2_cache * (m_totalCores / 2) * m_sockets;
m_l2_exclusive = true;
}
else {
m_l2_cache = data.l2_cache > 0 ? data.l2_cache * m_totalCores * m_sockets : 0;

View File

@@ -53,6 +53,7 @@ public:
private:
static void initCommon();
static bool m_l2_exclusive;
static char m_brand[64];
static int m_flags;
static int m_l2_cache;

View File

@@ -113,6 +113,36 @@ static struct option const options[] = {
};
static struct option const config_options[] = {
{ "algo", 1, nullptr, 'a' },
{ "av", 1, nullptr, 'v' },
{ "background", 0, nullptr, 'B' },
{ "cpu-affinity", 1, nullptr, 1020 },
{ "donate-level", 1, nullptr, 1003 },
{ "log-file", 1, nullptr, 'l' },
{ "max-cpu-usage", 1, nullptr, 1004 },
{ "print-time", 1, nullptr, 1007 },
{ "retries", 1, nullptr, 'r' },
{ "retry-pause", 1, nullptr, 'R' },
{ "safe", 0, nullptr, 1005 },
{ "syslog", 0, nullptr, 'S' },
{ "threads", 1, nullptr, 't' },
{ "colors", 0, nullptr, 2000 },
{ 0, 0, 0, 0 }
};
static struct option const pool_options[] = {
{ "url", 1, nullptr, 'o' },
{ "pass", 1, nullptr, 'p' },
{ "user", 1, nullptr, 'u' },
{ "userpass", 1, nullptr, 'O' },
{ "keepalive", 0, nullptr ,'k' },
{ "nicehash", 0, nullptr, 1006 },
{ 0, 0, 0, 0 }
};
static const char *algo_names[] = {
"cryptonight",
# ifndef XMRIG_NO_AEON
@@ -121,6 +151,34 @@ static const char *algo_names[] = {
};
static char *defaultConfigName()
{
size_t size = 512;
char *buf = new char[size];
if (uv_exepath(buf, &size) < 0) {
delete [] buf;
return nullptr;
}
if (size < 500) {
# ifdef WIN32
char *p = strrchr(buf, '\\');
# else
char *p = strrchr(buf, '/');
# endif
if (p) {
strcpy(p + 1, "config.json");
return buf;
}
}
delete [] buf;
return nullptr;
}
Options *Options::parse(int argc, char **argv)
{
if (!m_self) {
@@ -176,7 +234,13 @@ Options::Options(int argc, char **argv) :
}
if (!m_pools[0]->isValid()) {
fprintf(stderr, "No pool URL supplied. Exiting.");
char *fileName = defaultConfigName();
parseConfig(fileName);
delete [] fileName;
}
if (!m_pools[0]->isValid()) {
fprintf(stderr, "No pool URL supplied. Exiting.\n");
return;
}
@@ -204,11 +268,8 @@ Options::~Options()
}
bool Options::parseArg(int key, char *arg)
bool Options::parseArg(int key, const char *arg)
{
char *p;
int v;
switch (key) {
case 'a': /* --algo */
if (!setAlgo(arg)) {
@@ -216,13 +277,6 @@ bool Options::parseArg(int key, char *arg)
}
break;
case 'O': /* --userpass */
if (!m_pools.back()->setUserpass(arg)) {
return false;
}
break;
case 'o': /* --url */
if (m_pools.size() > 1 || m_pools[0]->isValid()) {
Url *url = new Url(arg);
@@ -240,7 +294,12 @@ bool Options::parseArg(int key, char *arg)
if (!m_pools.back()->isValid()) {
return false;
}
break;
case 'O': /* --userpass */
if (!m_pools.back()->setUserpass(arg)) {
return false;
}
break;
case 'u': /* --user */
@@ -257,53 +316,22 @@ bool Options::parseArg(int key, char *arg)
m_colors = false;
break;
case 'r': /* --retries */
v = strtol(arg, nullptr, 10);
if (v < 1 || v > 1000) {
showUsage(1);
return false;
}
m_retries = v;
break;
case 'R': /* --retry-pause */
v = strtol(arg, nullptr, 10);
if (v < 1 || v > 3600) {
showUsage(1);
return false;
}
m_retryPause = v;
break;
case 't': /* --threads */
v = strtol(arg, nullptr, 10);
if (v < 1 || v > 1024) {
showUsage(1);
return false;
}
m_threads = v;
break;
case 'r': /* --retries */
case 'R': /* --retry-pause */
case 't': /* --threads */
case 'v': /* --av */
case 1003: /* --donate-level */
case 1004: /* --max-cpu-usage */
v = strtol(arg, nullptr, 10);
if (v < 1 || v > 100) {
showUsage(1);
return false;
}
m_maxCpuUsage = v;
break;
case 1007: /* --print-time */
return parseArg(key, strtol(arg, nullptr, 10));
case 'B': /* --background */
case 'k': /* --keepalive */
case 'S': /* --syslog */
case 1002: /* --no-color */
case 1005: /* --safe */
m_safe = true;
break;
case 'k': /* --keepalive */
m_pools.back()->setKeepAlive(true);
break;
case 1006: /* --nicehash */
return parseBoolean(key, true);
case 'V': /* --version */
showVersion();
@@ -313,59 +341,15 @@ bool Options::parseArg(int key, char *arg)
showUsage(0);
return false;
case 'B': /* --background */
m_background = true;
m_colors = false;
case 'c': /* --config */
parseConfig(arg);
break;
case 'S': /* --syslog */
m_syslog = true;
m_colors = false;
break;
case 'v': /* --av */
v = strtol(arg, nullptr, 10);
if (v < 0 || v > 1000) {
showUsage(1);
return false;
case 1020: { /* --cpu-affinity */
const char *p = strstr(arg, "0x");
return parseArg(key, p ? strtoull(p, nullptr, 16) : strtoull(arg, nullptr, 10));
}
m_algoVariant = v;
break;
case 1020: /* --cpu-affinity */
p = strstr(arg, "0x");
m_affinity = p ? strtoull(p, nullptr, 16) : strtoull(arg, nullptr, 10);
break;
case 1002: /* --no-color */
m_colors = false;
break;
case 1003: /* --donate-level */
v = strtol(arg, nullptr, 10);
if (v < 1 || v > 99) {
showUsage(1);
return false;
}
m_donateLevel = v;
break;
case 1006: /* --nicehash */
m_pools.back()->setNicehash(true);
break;
case 1007: /* --print-time */
v = strtol(arg, nullptr, 10);
if (v < 0 || v > 1000) {
showUsage(1);
return false;
}
m_printTime = v;
break;
default:
showUsage(1);
return false;
@@ -375,6 +359,127 @@ bool Options::parseArg(int key, char *arg)
}
bool Options::parseArg(int key, uint64_t arg)
{
switch (key) {
case 'r': /* --retries */
if (arg < 1 || arg > 1000) {
showUsage(1);
return false;
}
m_retries = arg;
break;
case 'R': /* --retry-pause */
if (arg < 1 || arg > 3600) {
showUsage(1);
return false;
}
m_retryPause = arg;
break;
case 't': /* --threads */
if (arg < 1 || arg > 1024) {
showUsage(1);
return false;
}
m_threads = arg;
break;
case 'v': /* --av */
if (arg > 1000) {
showUsage(1);
return false;
}
m_algoVariant = arg;
break;
case 1003: /* --donate-level */
if (arg < 1 || arg > 99) {
showUsage(1);
return false;
}
m_donateLevel = arg;
break;
case 1004: /* --max-cpu-usage */
if (arg < 1 || arg > 100) {
showUsage(1);
return false;
}
m_maxCpuUsage = arg;
break;
case 1007: /* --print-time */
if (arg > 1000) {
showUsage(1);
return false;
}
m_printTime = arg;
break;
case 1020: /* --cpu-affinity */
if (arg) {
m_affinity = arg;
}
break;
default:
break;
}
return true;
}
bool Options::parseBoolean(int key, bool enable)
{
switch (key) {
case 'k': /* --keepalive */
m_pools.back()->setKeepAlive(enable);
break;
case 'B': /* --background */
m_background = enable;
m_colors = enable ? false : m_colors;
break;
case 'S': /* --syslog */
m_syslog = enable;
m_colors = enable ? false : m_colors;
break;
case 1002: /* --no-color */
m_colors = enable;
break;
case 1005: /* --safe */
m_safe = enable;
break;
case 1006: /* --nicehash */
m_pools.back()->setNicehash(enable);
break;
case 2000: /* colors */
m_colors = enable;
break;
default:
break;
}
return true;
}
Url *Options::parseUrl(const char *arg) const
{
auto url = new Url(arg);
@@ -387,6 +492,72 @@ Url *Options::parseUrl(const char *arg) const
}
void Options::parseConfig(const char *fileName)
{
json_error_t err;
json_t *config = json_load_file(fileName, 0, &err);
if (!json_is_object(config)) {
if (config) {
json_decref(config);
return;
}
if (err.line < 0) {
fprintf(stderr, "%s\n", err.text);
}
else {
fprintf(stderr, "%s:%d: %s\n", fileName, err.line, err.text);
}
return;
}
for (size_t i = 0; i < ARRAY_SIZE(config_options); i++) {
parseJSON(&config_options[i], config);
}
json_t *pools = json_object_get(config, "pools");
if (json_is_array(pools)) {
size_t index;
json_t *value;
json_array_foreach(pools, index, value) {
if (json_is_object(value)) {
for (size_t i = 0; i < ARRAY_SIZE(pool_options); i++) {
parseJSON(&pool_options[i], value);
}
}
}
}
json_decref(config);
}
void Options::parseJSON(const struct option *option, json_t *object)
{
if (!option->name) {
return;
}
json_t *val = json_object_get(object, option->name);
if (!val) {
return;
}
if (option->has_arg && json_is_string(val)) {
parseArg(option->val, json_string_value(val));
}
else if (option->has_arg && json_is_integer(val)) {
parseArg(option->val, json_integer_value(val));
}
else if (!option->has_arg && json_is_boolean(val)) {
parseBoolean(option->val, json_is_true(val));
}
}
void Options::showUsage(int status) const
{
if (status) {

View File

@@ -25,11 +25,13 @@
#define __OPTIONS_H__
#include <vector>
#include <jansson.h>
#include <stdint.h>
#include <vector>
class Url;
struct option;
class Options
@@ -76,8 +78,12 @@ private:
static Options *m_self;
bool parseArg(int key, char *arg);
bool parseArg(int key, const char *arg);
bool parseArg(int key, uint64_t arg);
bool parseBoolean(int key, bool enable);
Url *parseUrl(const char *arg) const;
void parseConfig(const char *fileName);
void parseJSON(const struct option *option, json_t *object);
void showUsage(int status) const;
void showVersion(void);

View File

@@ -22,6 +22,7 @@
*/
#include <inttypes.h>
#include <uv.h>
@@ -49,11 +50,8 @@ static void print_versions()
# endif
if (Options::i()->colors()) {
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 {
Log::i()->text(" * VERSIONS: XMRig/%s libuv/%s%s", APP_VERSION, uv_version_string(), buf);
}
Log::i()->text(Options::i()->colors() ? "\x1B[01;32m * \x1B[01;37mVERSIONS: \x1B[01;36mXMRig/%s\x1B[01;37m libuv/%s%s" : " * VERSIONS: XMRig/%s libuv/%s%s",
APP_VERSION, uv_version_string(), buf);
}
@@ -94,7 +92,7 @@ static void print_threads()
{
char buf[32];
if (Options::i()->affinity() != -1L) {
snprintf(buf, 32, ", affinity=0x%llX", Options::i()->affinity());
snprintf(buf, 32, ", affinity=0x%" PRIX64, Options::i()->affinity());
}
else {
buf[0] = '\0';
@@ -129,6 +127,17 @@ static void print_pools()
}
static void print_commands()
{
if (Options::i()->colors()) {
Log::i()->text("\x1B[01;32m * \x1B[01;37mCOMMANDS: \x1B[01;35mh\x1B[01;37mashrate, \x1B[01;35mp\x1B[01;37mause, \x1B[01;35mr\x1B[01;37mesume");
}
else {
Log::i()->text(" * COMMANDS: 'h' hashrate, 'p' pause, 'r' resume");
}
}
void Summary::print()
{
print_versions();
@@ -136,6 +145,7 @@ void Summary::print()
print_cpu();
print_threads();
print_pools();
print_commands();
}

25
src/config.json Normal file
View File

@@ -0,0 +1,25 @@
{
"algo": "cryptonight",
"av": 0,
"background": false,
"colors": true,
"cpu-affinity": null,
"donate-level": 5,
"log-file": null,
"max-cpu-usage": 75,
"print-time": 60,
"retries": 5,
"retry-pause": 5,
"safe": false,
"syslog": false,
"threads": null,
"pools": [
{
"url": "pool.minemonero.pro:5555",
"user": "",
"pass": "x",
"keepalive": true,
"nicehash": false
}
]
}

View File

@@ -65,7 +65,7 @@ static inline void do_jh_hash(const void* input, size_t len, char* output) {
static inline void do_skein_hash(const void* input, size_t len, char* output) {
skein_hash(8 * 32, static_cast<const uint8_t*>(input), 8 * len, reinterpret_cast<uint8_t*>(output));
xmr_skein(static_cast<const uint8_t*>(input), reinterpret_cast<uint8_t*>(output));
}

View File

@@ -3,7 +3,7 @@
// A baseline Keccak (3rd round) implementation.
#include <stdint.h>
#include <string.h>
#include <memory.h>
#define HASH_DATA_AREA 136
#define KECCAK_ROUNDS 24
@@ -24,18 +24,6 @@ const uint64_t keccakf_rndc[24] =
0x8000000000008080, 0x0000000080000001, 0x8000000080008008
};
const int keccakf_rotc[24] =
{
1, 3, 6, 10, 15, 21, 28, 36, 45, 55, 2, 14,
27, 41, 56, 8, 25, 43, 62, 18, 39, 61, 20, 44
};
const int keccakf_piln[24] =
{
10, 7, 11, 17, 18, 3, 5, 16, 8, 21, 24, 4,
15, 23, 19, 13, 12, 2, 20, 14, 22, 9, 6, 1
};
// update the state with given number of rounds
void keccakf(uint64_t st[25], int rounds)
@@ -63,26 +51,86 @@ void keccakf(uint64_t st[25], int rounds)
// Rho Pi
t = st[1];
for (i = 0; i < 24; ++i) {
bc[0] = st[keccakf_piln[i]];
st[keccakf_piln[i]] = ROTL64(t, keccakf_rotc[i]);
t = bc[0];
}
st[ 1] = ROTL64(st[ 6], 44);
st[ 6] = ROTL64(st[ 9], 20);
st[ 9] = ROTL64(st[22], 61);
st[22] = ROTL64(st[14], 39);
st[14] = ROTL64(st[20], 18);
st[20] = ROTL64(st[ 2], 62);
st[ 2] = ROTL64(st[12], 43);
st[12] = ROTL64(st[13], 25);
st[13] = ROTL64(st[19], 8);
st[19] = ROTL64(st[23], 56);
st[23] = ROTL64(st[15], 41);
st[15] = ROTL64(st[ 4], 27);
st[ 4] = ROTL64(st[24], 14);
st[24] = ROTL64(st[21], 2);
st[21] = ROTL64(st[ 8], 55);
st[ 8] = ROTL64(st[16], 45);
st[16] = ROTL64(st[ 5], 36);
st[ 5] = ROTL64(st[ 3], 28);
st[ 3] = ROTL64(st[18], 21);
st[18] = ROTL64(st[17], 15);
st[17] = ROTL64(st[11], 10);
st[11] = ROTL64(st[ 7], 6);
st[ 7] = ROTL64(st[10], 3);
st[10] = ROTL64(t, 1);
// Chi
for (j = 0; j < 25; j += 5) {
bc[0] = st[j ];
bc[1] = st[j + 1];
bc[2] = st[j + 2];
bc[3] = st[j + 3];
bc[4] = st[j + 4];
st[j ] ^= (~bc[1]) & bc[2];
st[j + 1] ^= (~bc[2]) & bc[3];
st[j + 2] ^= (~bc[3]) & bc[4];
st[j + 3] ^= (~bc[4]) & bc[0];
st[j + 4] ^= (~bc[0]) & bc[1];
}
// unrolled loop, where only last iteration is different
j = 0;
bc[0] = st[j ];
bc[1] = st[j + 1];
st[j ] ^= (~st[j + 1]) & st[j + 2];
st[j + 1] ^= (~st[j + 2]) & st[j + 3];
st[j + 2] ^= (~st[j + 3]) & st[j + 4];
st[j + 3] ^= (~st[j + 4]) & bc[0];
st[j + 4] ^= (~bc[0]) & bc[1];
j = 5;
bc[0] = st[j ];
bc[1] = st[j + 1];
st[j ] ^= (~st[j + 1]) & st[j + 2];
st[j + 1] ^= (~st[j + 2]) & st[j + 3];
st[j + 2] ^= (~st[j + 3]) & st[j + 4];
st[j + 3] ^= (~st[j + 4]) & bc[0];
st[j + 4] ^= (~bc[0]) & bc[1];
j = 10;
bc[0] = st[j ];
bc[1] = st[j + 1];
st[j ] ^= (~st[j + 1]) & st[j + 2];
st[j + 1] ^= (~st[j + 2]) & st[j + 3];
st[j + 2] ^= (~st[j + 3]) & st[j + 4];
st[j + 3] ^= (~st[j + 4]) & bc[0];
st[j + 4] ^= (~bc[0]) & bc[1];
j = 15;
bc[0] = st[j ];
bc[1] = st[j + 1];
st[j ] ^= (~st[j + 1]) & st[j + 2];
st[j + 1] ^= (~st[j + 2]) & st[j + 3];
st[j + 2] ^= (~st[j + 3]) & st[j + 4];
st[j + 3] ^= (~st[j + 4]) & bc[0];
st[j + 4] ^= (~bc[0]) & bc[1];
j = 20;
bc[0] = st[j ];
bc[1] = st[j + 1];
bc[2] = st[j + 2];
bc[3] = st[j + 3];
bc[4] = st[j + 4];
st[j ] ^= (~bc[1]) & bc[2];
st[j + 1] ^= (~bc[2]) & bc[3];
st[j + 2] ^= (~bc[3]) & bc[4];
st[j + 3] ^= (~bc[4]) & bc[0];
st[j + 4] ^= (~bc[0]) & bc[1];
// Iota
st[0] ^= keccakf_rndc[round];
}
@@ -121,3 +169,8 @@ void keccak(const uint8_t *in, int inlen, uint8_t *md, int mdlen)
memcpy(md, st, mdlen);
}
void keccak1600(const uint8_t *in, int inlen, uint8_t *md)
{
keccak(in, inlen, md, sizeof(state_t));
}

File diff suppressed because it is too large Load Diff

View File

@@ -44,4 +44,6 @@ typedef u08b_t SkeinBitSequence; /* bit stream type */
SkeinHashReturn skein_hash(int hashbitlen, const SkeinBitSequence *data,
SkeinDataLength databitlen, SkeinBitSequence *hashval);
void xmr_skein(const SkeinBitSequence *data, SkeinBitSequence *hashval);
#endif /* ifndef _SKEIN_H_ */

View File

@@ -37,10 +37,10 @@ class IClientListener
public:
virtual ~IClientListener() {}
virtual void onClose(Client *client, int failures) = 0;
virtual void onJobReceived(Client *client, const Job &job) = 0;
virtual void onLoginSuccess(Client *client) = 0;
virtual void onResultAccepted(Client *client, uint32_t diff, uint64_t ms, const char *error) = 0;
virtual void onClose(Client *client, int failures) = 0;
virtual void onJobReceived(Client *client, const Job &job) = 0;
virtual void onLoginSuccess(Client *client) = 0;
virtual void onResultAccepted(Client *client, int64_t seq, uint32_t diff, uint64_t ms, const char *error) = 0;
};

View File

@@ -0,0 +1,37 @@
/* 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 __ICONSOLELISTENER_H__
#define __ICONSOLELISTENER_H__
class IConsoleListener
{
public:
virtual ~IConsoleListener() {}
virtual void onConsoleCommand(char command) = 0;
};
#endif // __ICONSOLELISTENER_H__

View File

@@ -25,6 +25,9 @@
#define __ISTRATEGY_H__
#include <stdint.h>
class JobResult;
@@ -33,10 +36,11 @@ 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;
virtual bool isActive() const = 0;
virtual int64_t submit(const JobResult &result) = 0;
virtual void connect() = 0;
virtual void resume() = 0;
virtual void stop() = 0;
};

View File

@@ -38,10 +38,10 @@ 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;
virtual void onActive(Client *client) = 0;
virtual void onJob(Client *client, const Job &job) = 0;
virtual void onPause(IStrategy *strategy) = 0;
virtual void onResultAccepted(Client *client, int64_t seq, uint32_t diff, uint64_t ms, const char *error) = 0;
};

View File

@@ -27,13 +27,12 @@
#include <string.h>
#include <time.h>
#ifdef WIN32
# include <winsock2.h>
# include <malloc.h>
# include "3rdparty/winansi.h"
# include <windows.h>
#endif
#include "log/ConsoleLog.h"
#include "log/Log.h"
@@ -41,6 +40,19 @@
ConsoleLog::ConsoleLog(bool colors) :
m_colors(colors)
{
uv_tty_init(uv_default_loop(), &m_tty, 1, 0);
uv_tty_set_mode(&m_tty, UV_TTY_MODE_NORMAL);
# ifdef WIN32
HANDLE handle = GetStdHandle(STD_INPUT_HANDLE);
if (handle != INVALID_HANDLE_VALUE) {
DWORD mode = 0;
if (GetConsoleMode(handle, &mode)) {
mode &= ~ENABLE_QUICK_EDIT_MODE;
SetConsoleMode(handle, mode | ENABLE_EXTENDED_FLAGS);
}
}
# endif
}
@@ -81,7 +93,7 @@ void ConsoleLog::message(int level, const char* fmt, va_list args)
}
const size_t len = 64 + strlen(fmt) + 2;
char *buf = static_cast<char *>(alloca(len));
char *buf = new char[len];
sprintf(buf, "[%d-%02d-%02d %02d:%02d:%02d]%s %s%s\n",
stime.tm_year + 1900,
@@ -95,18 +107,35 @@ void ConsoleLog::message(int level, const char* fmt, va_list args)
m_colors ? Log::kCL_N : ""
);
vfprintf(stdout, buf, args);
fflush(stdout);
print(buf, args);
}
void ConsoleLog::text(const char* fmt, va_list args)
{
const int len = 64 + strlen(fmt) + 2;
char *buf = static_cast<char *>(alloca(len));
char *buf = new char[len];
sprintf(buf, "%s%s\n", fmt, m_colors ? Log::kCL_N : "");
vfprintf(stdout, buf, args);
fflush(stdout);
print(buf, args);
}
void ConsoleLog::print(char *fmt, va_list args)
{
vsnprintf(m_buf, sizeof(m_buf) - 1, fmt, args);
delete [] fmt;
uv_buf_t buf;
buf.base = strdup(m_buf);
buf.len = strlen(buf.base);
uv_write_t *req = new uv_write_t;
req->data = buf.base;
uv_write(req, reinterpret_cast<uv_stream_t*>(&m_tty), &buf, 1, [](uv_write_t *req, int status) {
free(req->data);
delete req;
});
}

View File

@@ -25,6 +25,9 @@
#define __CONSOLELOG_H__
#include <uv.h>
#include "interfaces/ILogBackend.h"
@@ -33,11 +36,15 @@ 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;
void message(int level, const char *fmt, va_list args) override;
void text(const char *fmt, va_list args) override;
private:
void print(char *fmt, va_list args);
bool m_colors;
char m_buf[512];
uv_tty_t m_tty;
};
#endif /* __CONSOLELOG_H__ */

View File

@@ -28,13 +28,6 @@
#include <time.h>
#ifdef WIN32
# include <winsock2.h>
# include <malloc.h>
# include "3rdparty/winansi.h"
#endif
#include "log/FileLog.h"

View File

@@ -28,12 +28,6 @@
#include <time.h>
#ifdef WIN32
# include <winsock2.h>
# include <malloc.h>
# include "3rdparty/winansi.h"
#endif
#include "interfaces/ILogBackend.h"
#include "log/Log.h"

View File

@@ -21,23 +21,32 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <inttypes.h>
#include <iterator>
#include <string.h>
#include <utility>
#include "log/Log.h"
#include "interfaces/IClientListener.h"
#include "net/Client.h"
#include "net/JobResult.h"
#include "net/Url.h"
#ifdef XMRIG_PROXY_PROJECT
# include "proxy/JobResult.h"
#else
# include "net/JobResult.h"
#endif
#ifdef _MSC_VER
# define strncasecmp(x,y,z) _strnicmp(x,y,z)
#endif
int64_t Client::m_sequence = 1;
Client::Client(int id, const char *agent, IClientListener *listener) :
m_quiet(false),
m_agent(agent),
@@ -45,7 +54,6 @@ Client::Client(int id, const char *agent, IClientListener *listener) :
m_id(id),
m_retryPause(5000),
m_failures(0),
m_sequence(1),
m_recvBufPos(0),
m_state(UnconnectedState),
m_stream(nullptr),
@@ -77,6 +85,35 @@ Client::~Client()
}
/**
* @brief Send raw data to server.
*
* @param data
*/
int64_t Client::send(char *data, size_t size)
{
LOG_DEBUG("[%s:%u] send (%d bytes): \"%s\"", m_url.host(), m_url.port(), size ? size : strlen(data), data);
if (state() != ConnectedState) {
LOG_DEBUG_ERR("[%s:%u] send failed, invalid state: %d", m_url.host(), m_url.port(), m_state);
return -1;
}
uv_buf_t buf = uv_buf_init(data, size ? size : strlen(data));
uv_write_t *req = new uv_write_t;
req->data = buf.base;
uv_write(req, m_stream, &buf, 1, [](uv_write_t *req, int status) {
free(req->data);
delete req;
});
uv_timer_start(&m_responseTimer, [](uv_timer_t *handle) { getClient(handle->data)->close(); }, kResponseTimeout, 0);
return m_sequence++;
}
void Client::connect()
{
resolve(m_url.host());
@@ -97,6 +134,8 @@ void Client::connect(const Url *url)
void Client::disconnect()
{
uv_timer_stop(&m_keepAliveTimer);
uv_timer_stop(&m_responseTimer);
uv_timer_stop(&m_retriesTimer);
m_failures = -1;
@@ -104,34 +143,6 @@ void Client::disconnect()
}
/**
* @brief Send raw data to server.
*
* @param data
*/
void Client::send(char *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_url.host(), m_url.port(), m_state);
return;
}
m_sequence++;
uv_buf_t buf = uv_buf_init(data, strlen(data));
uv_write_t *req = static_cast<uv_write_t*>(malloc(sizeof(uv_write_t)));
req->data = buf.base;
uv_write(req, m_stream, &buf, 1, [](uv_write_t *req, int status) {
free(req->data);
free(req);
});
uv_timer_start(&m_responseTimer, [](uv_timer_t *handle) { getClient(handle->data)->close(); }, kResponseTimeout, 0);
}
void Client::setUrl(const Url *url)
{
if (!url || !url->isValid()) {
@@ -142,9 +153,14 @@ void Client::setUrl(const Url *url)
}
void Client::submit(const JobResult &result)
int64_t Client::submit(const JobResult &result)
{
char *req = static_cast<char*>(malloc(345));
# ifdef XMRIG_PROXY_PROJECT
const char *nonce = result.nonce;
const char *data = result.result;
# else
char nonce[9];
char data[65];
@@ -153,12 +169,13 @@ void Client::submit(const JobResult &result)
Job::toHex(result.result, 32, data);
data[64] = '\0';
# endif
snprintf(req, 345, "{\"id\":%llu,\"jsonrpc\":\"2.0\",\"method\":\"submit\",\"params\":{\"id\":\"%s\",\"job_id\":\"%s\",\"nonce\":\"%s\",\"result\":\"%s\"}}\n",
snprintf(req, 345, "{\"id\":%" PRIu64 ",\"jsonrpc\":\"2.0\",\"method\":\"submit\",\"params\":{\"id\":\"%s\",\"job_id\":\"%s\",\"nonce\":\"%s\",\"result\":\"%s\"}}\n",
m_sequence, m_rpcId, result.jobId, nonce, data);
m_results[m_sequence] = SubmitResult(result.diff);
send(req);
m_results[m_sequence] = SubmitResult(m_sequence, result.diff);
return send(req);
}
@@ -191,8 +208,6 @@ bool Client::parseJob(const json_t *params, int *code)
}
m_job = std::move(job);
LOG_DEBUG("[%s:%u] job: \"%s\", diff: %lld", m_url.host(), m_url.port(), job.id(), job.diff());
return true;
}
@@ -241,7 +256,10 @@ void Client::close()
}
setState(ClosingState);
uv_close(reinterpret_cast<uv_handle_t*>(m_socket), Client::onClose);
if (uv_is_closing(reinterpret_cast<uv_handle_t*>(m_socket)) == 0) {
uv_close(reinterpret_cast<uv_handle_t*>(m_socket), Client::onClose);
}
}
@@ -265,20 +283,34 @@ void Client::connect(struct sockaddr *addr)
uv_tcp_keepalive(m_socket, 1, 60);
# endif
uv_tcp_connect(req, m_socket, (const sockaddr*) addr, Client::onConnect);
uv_tcp_connect(req, m_socket, reinterpret_cast<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);
json_t *req = json_object();
json_object_set(req, "id", json_integer(1));
json_object_set(req, "jsonrpc", json_string("2.0"));
json_object_set(req, "method", json_string("login"));
send(req);
json_t *params = json_object();
json_object_set(params, "login", json_string(m_url.user()));
json_object_set(params, "pass", json_string(m_url.password()));
json_object_set(params, "agent", json_string(m_agent));
json_object_set(req, "params", params);
char *buf = json_dumps(req, JSON_COMPACT);
const size_t size = strlen(buf);
buf[size] = '\n';
json_decref(req);
send(buf, size + 1);
}
@@ -316,7 +348,7 @@ void Client::parseNotification(const char *method, const json_t *params, const j
{
if (json_is_object(error)) {
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")));
LOG_ERR("[%s:%u] error: \"%s\", code: %" PRId64, m_url.host(), m_url.port(), json_string_value(json_object_get(error, "message")), json_integer_value(json_object_get(error, "code")));
}
return;
}
@@ -345,11 +377,11 @@ void Client::parseResponse(int64_t id, const json_t *result, const json_t *error
auto it = m_results.find(id);
if (it != m_results.end()) {
m_listener->onResultAccepted(this, it->second.diff, it->second.elapsed(), message);
m_listener->onResultAccepted(this, it->second.seq, it->second.diff, it->second.elapsed(), message);
m_results.erase(it);
}
else if (!m_quiet) {
LOG_ERR("[%s:%u] error: \"%s\", code: %lld", m_url.host(), m_url.port(), message, json_integer_value(json_object_get(error, "code")));
LOG_ERR("[%s:%u] error: \"%s\", code: %" PRId64, m_url.host(), m_url.port(), message, json_integer_value(json_object_get(error, "code")));
}
if (id == 1 || (message && strncasecmp(message, "Unauthenticated", 15) == 0)) {
@@ -381,7 +413,7 @@ void Client::parseResponse(int64_t id, const json_t *result, const json_t *error
auto it = m_results.find(id);
if (it != m_results.end()) {
m_listener->onResultAccepted(this, it->second.diff, it->second.elapsed(), nullptr);
m_listener->onResultAccepted(this, it->second.seq, it->second.diff, it->second.elapsed(), nullptr);
m_results.erase(it);
}
}
@@ -389,8 +421,8 @@ void Client::parseResponse(int64_t id, const json_t *result, const json_t *error
void Client::ping()
{
char *req = static_cast<char*>(malloc(128));
snprintf(req, 128, "{\"id\":%lld,\"jsonrpc\":\"2.0\",\"method\":\"keepalived\",\"params\":{\"id\":\"%s\"}}\n", m_sequence, m_rpcId);
char *req = static_cast<char*>(malloc(160));
snprintf(req, 160, "{\"id\":%" PRId64 ",\"jsonrpc\":\"2.0\",\"method\":\"keepalived\",\"params\":{\"id\":\"%s\"}}\n", m_sequence, m_rpcId);
send(req);
}
@@ -497,6 +529,10 @@ void Client::onRead(uv_stream_t *stream, ssize_t nread, const uv_buf_t *buf)
return client->close();;
}
if ((size_t) nread > (kRecvBufSize - 8 - client->m_recvBufPos)) {
return client->close();;
}
client->m_recvBufPos += nread;
char* end;
@@ -534,8 +570,26 @@ void Client::onResolved(uv_getaddrinfo_t *req, int status, struct addrinfo *res)
return client->reconnect();;
}
uv_ip4_name(reinterpret_cast<sockaddr_in*>(res->ai_addr), client->m_ip, 16);
addrinfo *ptr = res;
std::vector<addrinfo*> ipv4;
client->connect(res->ai_addr);
while (ptr != nullptr) {
if (ptr->ai_family == AF_INET) {
ipv4.push_back(ptr);
}
ptr = ptr->ai_next;
}
if (ipv4.empty()) {
LOG_ERR("[%s:%u] DNS error: \"No IPv4 records found\"", client->m_url.host(), client->m_url.port());
return client->reconnect();
}
ptr = ipv4[rand() % ipv4.size()];
uv_ip4_name(reinterpret_cast<sockaddr_in*>(ptr->ai_addr), client->m_ip, 16);
client->connect(ptr->ai_addr);
uv_freeaddrinfo(res);
}

View File

@@ -56,12 +56,12 @@ public:
Client(int id, const char *agent, IClientListener *listener);
~Client();
int64_t send(char *data, size_t size = 0);
int64_t submit(const JobResult &result);
void connect();
void connect(const Url *url);
void disconnect();
void 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_url.host(); }
@@ -98,6 +98,7 @@ private:
static inline Client *getClient(void *data) { return static_cast<Client*>(data); }
addrinfo m_hints;
bool m_quiet;
char m_ip[17];
char m_rpcId[64];
@@ -106,12 +107,11 @@ private:
int m_id;
int m_retryPause;
int64_t m_failures;
int64_t m_sequence;
Job m_job;
size_t m_recvBufPos;
SocketState m_state;
static int64_t m_sequence;
std::map<int64_t, SubmitResult> m_results;
struct addrinfo m_hints;
Url m_url;
uv_buf_t m_recvBuf;
uv_getaddrinfo_t m_resolver;

View File

@@ -90,6 +90,11 @@ bool Job::setBlob(const char *blob)
m_nicehash = true;
}
# ifdef XMRIG_PROXY_PROJECT
memset(m_rawBlob, 0, sizeof(m_rawBlob));
memcpy(m_rawBlob, blob, m_size * 2);
# endif
return true;
}
@@ -138,6 +143,11 @@ bool Job::setTarget(const char *target)
return false;
}
# ifdef XMRIG_PROXY_PROJECT
memset(m_rawTarget, 0, sizeof(m_rawTarget));
memcpy(m_rawTarget, target, len);
# endif
m_diff = toDiff(m_target);
return true;
}

View File

@@ -50,6 +50,11 @@ public:
inline uint64_t target() const { return m_target; }
inline void setNicehash(bool nicehash) { m_nicehash = nicehash; }
# ifdef XMRIG_PROXY_PROJECT
inline char *rawBlob() { return m_rawBlob; }
inline const char *rawTarget() const { return m_rawTarget; }
# endif
static bool fromHex(const char* in, unsigned int len, unsigned char* out);
static inline uint32_t *nonce(uint8_t *blob) { return reinterpret_cast<uint32_t*>(blob + 39); }
static inline uint64_t toDiff(uint64_t target) { return 0xFFFFFFFFFFFFFFFFULL / target; }
@@ -65,6 +70,11 @@ private:
uint32_t m_size;
uint64_t m_diff;
uint64_t m_target;
# ifdef XMRIG_PROXY_PROJECT
VAR_ALIGN(16, char m_rawBlob[169]);
VAR_ALIGN(16, char m_rawTarget[17]);
# endif
};
#endif /* __JOB_H__ */

View File

@@ -22,7 +22,9 @@
*/
#include <inttypes.h>
#include <memory>
#include <time.h>
#include "log/Log.h"
@@ -43,6 +45,8 @@ Network::Network(const Options *options) :
m_accepted(0),
m_rejected(0)
{
srand(time(0) ^ (uintptr_t) this);
Workers::setListener(this);
m_agent = userAgent();
@@ -73,6 +77,16 @@ void Network::connect()
}
void Network::stop()
{
if (m_donate) {
m_donate->stop();
}
m_strategy->stop();
}
void Network::onActive(Client *client)
{
if (client->id() == -1) {
@@ -97,7 +111,8 @@ void Network::onJob(Client *client, const Job &job)
void Network::onJobResult(const JobResult &result)
{
if (result.poolId == -1 && m_donate) {
return m_donate->submit(result);
m_donate->submit(result);
return;
}
m_strategy->submit(result);
@@ -112,23 +127,27 @@ void Network::onPause(IStrategy *strategy)
}
if (!m_strategy->isActive()) {
LOG_ERR("no active pools, pause mining");
LOG_ERR("no active pools, stop mining");
return Workers::pause();
}
}
void Network::onResultAccepted(Client *client, uint32_t diff, uint64_t ms, const char *error)
void Network::onResultAccepted(Client *client, int64_t seq, uint32_t diff, uint64_t ms, const char *error)
{
if (error) {
m_rejected++;
LOG_INFO(m_options->colors() ? "\x1B[01;31mrejected\x1B[0m (%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);
LOG_INFO(m_options->colors() ? "\x1B[01;31mrejected\x1B[0m (%" PRId64 "/%" PRId64 ") diff \x1B[01;37m%u\x1B[0m \x1B[31m\"%s\"\x1B[0m \x1B[01;30m(%" PRIu64 " ms)"
: "rejected (%" PRId64 "/%" PRId64 ") diff %u \"%s\" (%" PRIu64 " ms)",
m_accepted, m_rejected, diff, error, ms);
}
else {
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);
LOG_INFO(m_options->colors() ? "\x1B[01;32maccepted\x1B[0m (%" PRId64 "/%" PRId64 ") diff \x1B[01;37m%u\x1B[0m \x1B[01;30m(%" PRIu64 " ms)"
: "accepted (%" PRId64 "/%" PRId64 ") diff %u (%" PRIu64 " ms)",
m_accepted, m_rejected, diff, ms);
}
}

View File

@@ -45,6 +45,7 @@ public:
~Network();
void connect();
void stop();
static char *userAgent();
@@ -53,7 +54,7 @@ protected:
void onJob(Client *client, const Job &job) override;
void onJobResult(const JobResult &result) override;
void onPause(IStrategy *strategy) override;
void onResultAccepted(Client *client, uint32_t diff, uint64_t ms, const char *error) override;
void onResultAccepted(Client *client, int64_t seq, uint32_t diff, uint64_t ms, const char *error) override;
private:
void setJob(Client *client, const Job &job);

View File

@@ -31,8 +31,9 @@
class SubmitResult
{
public:
inline SubmitResult() : diff(0), start(0) {}
inline SubmitResult(uint32_t diff) :
inline SubmitResult() : seq(0), diff(0), start(0) {}
inline SubmitResult(int64_t seq, uint32_t diff) :
seq(seq),
diff(diff)
{
start = uv_hrtime();
@@ -40,6 +41,7 @@ public:
inline uint64_t elapsed() const { return (uv_hrtime() - start) / 1000000; }
int64_t seq;
uint32_t diff;
uint64_t start;
};

View File

@@ -34,7 +34,7 @@ DonateStrategy::DonateStrategy(const char *agent, IStrategyListener *listener) :
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());
Url *url = new Url("fee.xmrig.com", Options::i()->algo() == Options::ALGO_CRYPTONIGHT_LITE ? 3333 : 443, Options::i()->pools().front()->user(), nullptr, false, true);
m_client = new Client(-1, agent, this);
m_client->setUrl(url);
@@ -50,15 +50,22 @@ DonateStrategy::DonateStrategy(const char *agent, IStrategyListener *listener) :
}
int64_t DonateStrategy::submit(const JobResult &result)
{
return m_client->submit(result);
}
void DonateStrategy::connect()
{
m_client->connect();
}
void DonateStrategy::submit(const JobResult &result)
void DonateStrategy::stop()
{
m_client->submit(result);
uv_timer_stop(&m_timer);
m_client->disconnect();
}
@@ -84,9 +91,9 @@ void DonateStrategy::onLoginSuccess(Client *client)
}
void DonateStrategy::onResultAccepted(Client *client, uint32_t diff, uint64_t ms, const char *error)
void DonateStrategy::onResultAccepted(Client *client, int64_t seq, uint32_t diff, uint64_t ms, const char *error)
{
m_listener->onResultAccepted(client, diff, ms, error);
m_listener->onResultAccepted(client, seq, diff, ms, error);
}
@@ -96,7 +103,7 @@ void DonateStrategy::idle()
}
void DonateStrategy::stop()
void DonateStrategy::suspend()
{
m_client->disconnect();
@@ -115,5 +122,5 @@ void DonateStrategy::onTimer(uv_timer_t *handle)
return strategy->connect();
}
strategy->stop();
strategy->suspend();
}

View File

@@ -46,18 +46,19 @@ public:
inline bool isActive() const override { return m_active; }
inline void resume() override {}
int64_t submit(const JobResult &result) override;
void connect() override;
void submit(const JobResult &result) override;
void stop() override;
protected:
void onClose(Client *client, int failures) override;
void onJobReceived(Client *client, const Job &job) override;
void onLoginSuccess(Client *client) override;
void onResultAccepted(Client *client, uint32_t diff, uint64_t ms, const char *error) override;
void onResultAccepted(Client *client, int64_t seq, uint32_t diff, uint64_t ms, const char *error) override;
private:
void idle();
void stop();
void suspend();
static void onTimer(uv_timer_t *handle);

View File

@@ -39,6 +39,12 @@ FailoverStrategy::FailoverStrategy(const std::vector<Url*> &urls, const char *ag
}
int64_t FailoverStrategy::submit(const JobResult &result)
{
return m_pools[m_active]->submit(result);
}
void FailoverStrategy::connect()
{
m_pools[m_index]->connect();
@@ -55,9 +61,16 @@ void FailoverStrategy::resume()
}
void FailoverStrategy::submit(const JobResult &result)
void FailoverStrategy::stop()
{
m_pools[m_active]->submit(result);
for (size_t i = 0; i < m_pools.size(); ++i) {
m_pools[i]->disconnect();
}
m_index = 0;
m_active = -1;
m_listener->onPause(this);
}
@@ -111,9 +124,9 @@ void FailoverStrategy::onLoginSuccess(Client *client)
}
void FailoverStrategy::onResultAccepted(Client *client, uint32_t diff, uint64_t ms, const char *error)
void FailoverStrategy::onResultAccepted(Client *client, int64_t seq, uint32_t diff, uint64_t ms, const char *error)
{
m_listener->onResultAccepted(client, diff, ms, error);
m_listener->onResultAccepted(client, seq, diff, ms, error);
}

View File

@@ -45,15 +45,16 @@ public:
public:
inline bool isActive() const override { return m_active >= 0; }
int64_t submit(const JobResult &result) override;
void connect() override;
void resume() override;
void submit(const JobResult &result) override;
void stop() override;
protected:
void onClose(Client *client, int failures) override;
void onJobReceived(Client *client, const Job &job) override;
void onLoginSuccess(Client *client) override;
void onResultAccepted(Client *client, uint32_t diff, uint64_t ms, const char *error) override;
void onResultAccepted(Client *client, int64_t seq, uint32_t diff, uint64_t ms, const char *error) override;
private:
void add(const Url *url, const char *agent);

View File

@@ -38,6 +38,12 @@ SinglePoolStrategy::SinglePoolStrategy(const Url *url, const char *agent, IStrat
}
int64_t SinglePoolStrategy::submit(const JobResult &result)
{
return m_client->submit(result);
}
void SinglePoolStrategy::connect()
{
m_client->connect();
@@ -54,9 +60,9 @@ void SinglePoolStrategy::resume()
}
void SinglePoolStrategy::submit(const JobResult &result)
void SinglePoolStrategy::stop()
{
m_client->submit(result);
m_client->disconnect();
}
@@ -84,7 +90,7 @@ void SinglePoolStrategy::onLoginSuccess(Client *client)
}
void SinglePoolStrategy::onResultAccepted(Client *client, uint32_t diff, uint64_t ms, const char *error)
void SinglePoolStrategy::onResultAccepted(Client *client, int64_t seq, uint32_t diff, uint64_t ms, const char *error)
{
m_listener->onResultAccepted(client, diff, ms, error);
m_listener->onResultAccepted(client, seq, diff, ms, error);
}

View File

@@ -42,15 +42,16 @@ public:
public:
inline bool isActive() const override { return m_active; }
int64_t submit(const JobResult &result) override;
void connect() override;
void resume() override;
void submit(const JobResult &result) override;
void stop() override;
protected:
void onClose(Client *client, int failures) override;
void onJobReceived(Client *client, const Job &job) override;
void onLoginSuccess(Client *client) override;
void onResultAccepted(Client *client, uint32_t diff, uint64_t ms, const char *error) override;
void onResultAccepted(Client *client, int64_t seq, uint32_t diff, uint64_t ms, const char *error) override;
private:
bool m_active;

View File

@@ -27,14 +27,14 @@
#define APP_ID "xmrig"
#define APP_NAME "XMRig"
#define APP_DESC "Monero (XMR) CPU miner"
#define APP_VERSION "2.0.2"
#define APP_VERSION "2.2.1"
#define APP_DOMAIN "xmrig.com"
#define APP_SITE "www.xmrig.com"
#define APP_COPYRIGHT "Copyright (C) 2016-2017 xmrig.com"
#define APP_VER_MAJOR 2
#define APP_VER_MINOR 0
#define APP_VER_BUILD 2
#define APP_VER_MINOR 2
#define APP_VER_BUILD 1
#define APP_VER_REV 0
#ifdef _MSC_VER

View File

@@ -62,13 +62,17 @@ DoubleWorker::~DoubleWorker()
void DoubleWorker::start()
{
while (true) {
while (Workers::sequence() > 0) {
if (Workers::isPaused()) {
do {
std::this_thread::sleep_for(std::chrono::milliseconds(200));
}
while (Workers::isPaused());
if (Workers::sequence() == 0) {
break;
}
consumeJob();
}

View File

@@ -34,6 +34,12 @@ Handle::Handle(int threadId, int threads, int64_t affinity) :
}
void Handle::join()
{
uv_thread_join(&m_thread);
}
void Handle::start(void (*callback) (void *))
{
uv_thread_create(&m_thread, callback, this);

View File

@@ -36,6 +36,7 @@ class Handle
{
public:
Handle(int threadId, int threads, int64_t affinity);
void join();
void start(void (*callback) (void *));
inline int threadId() const { return m_threadId; }

View File

@@ -161,6 +161,12 @@ void Hashrate::print()
}
void Hashrate::stop()
{
uv_timer_stop(&m_timer);
}
void Hashrate::updateHighest()
{
double highest = calc(2500);

View File

@@ -37,6 +37,7 @@ public:
double calc(size_t threadId, size_t ms) const;
void add(size_t threadId, uint64_t count, uint64_t timestamp);
void print();
void stop();
void updateHighest();
inline double highest() const { return m_highest; }

View File

@@ -38,13 +38,17 @@ SingleWorker::SingleWorker(Handle *handle)
void SingleWorker::start()
{
while (true) {
while (Workers::sequence() > 0) {
if (Workers::isPaused()) {
do {
std::this_thread::sleep_for(std::chrono::milliseconds(200));
}
while (Workers::isPaused());
if (Workers::sequence() == 0) {
break;
}
consumeJob();
}

View File

@@ -60,6 +60,12 @@ Job Workers::job()
}
void Workers::printHashrate(bool detail)
{
m_hashrate->print();
}
void Workers::setEnabled(bool enabled)
{
if (m_enabled == enabled) {
@@ -100,7 +106,7 @@ void Workers::start(int64_t affinity)
uv_mutex_init(&m_mutex);
uv_rwlock_init(&m_rwlock);
m_sequence = 0;
m_sequence = 1;
m_paused = 1;
uv_async_init(uv_default_loop(), &m_async, Workers::onResult);
@@ -115,6 +121,21 @@ void Workers::start(int64_t affinity)
}
void Workers::stop()
{
uv_timer_stop(&m_timer);
m_hashrate->stop();
uv_close(reinterpret_cast<uv_handle_t*>(&m_async), nullptr);
m_paused = 0;
m_sequence = 0;
for (size_t i = 0; i < m_workers.size(); ++i) {
m_workers[i]->join();
}
}
void Workers::submit(const JobResult &result)
{
uv_mutex_lock(&m_mutex);

View File

@@ -43,9 +43,11 @@ class Workers
{
public:
static Job job();
static void printHashrate(bool detail);
static void setEnabled(bool enabled);
static void setJob(const Job &job);
static void start(int64_t affinity);
static void stop();
static void submit(const JobResult &result);
static inline bool isEnabled() { return m_enabled; }

View File

@@ -25,7 +25,7 @@
int main(int argc, char **argv) {
auto app = new App(argc, argv);
App app(argc, argv);
return app->exec();
return app.exec();
}