From 5d9ebb0b917550d09e6f0f26bf5b1f02060f3427 Mon Sep 17 00:00:00 2001 From: XMRig Date: Thu, 7 Mar 2019 17:51:54 +0700 Subject: [PATCH 001/116] v2.14.2-dev --- src/version.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/version.h b/src/version.h index ff00eca3..4e8fee45 100644 --- a/src/version.h +++ b/src/version.h @@ -28,7 +28,7 @@ #define APP_ID "xmrig" #define APP_NAME "XMRig" #define APP_DESC "XMRig CPU miner" -#define APP_VERSION "2.14.1" +#define APP_VERSION "2.14.2-dev" #define APP_DOMAIN "xmrig.com" #define APP_SITE "www.xmrig.com" #define APP_COPYRIGHT "Copyright (C) 2016-2019 xmrig.com" @@ -36,7 +36,7 @@ #define APP_VER_MAJOR 2 #define APP_VER_MINOR 14 -#define APP_VER_PATCH 1 +#define APP_VER_PATCH 2 #ifdef _MSC_VER # if (_MSC_VER >= 1910) From 1bb8f77b527b02271c0645ced7063522322d628c Mon Sep 17 00:00:00 2001 From: SChernykh Date: Wed, 13 Mar 2019 22:00:44 +0100 Subject: [PATCH 002/116] Unified ASM functions signature --- src/Mem.cpp | 2 +- src/crypto/CryptoNight.h | 5 +- src/crypto/CryptoNight_x86.h | 70 +++++++++---------- .../asm/CryptonightR_soft_aes_template.inc | 2 + .../CryptonightR_soft_aes_template_win.inc | 2 + src/crypto/asm/CryptonightR_template.inc | 5 ++ src/crypto/asm/CryptonightR_template_win.inc | 5 ++ .../asm/CryptonightWOW_soft_aes_template.inc | 2 + .../CryptonightWOW_soft_aes_template_win.inc | 2 + src/crypto/asm/CryptonightWOW_template.inc | 5 ++ .../asm/CryptonightWOW_template_win.inc | 5 ++ .../cn2/cnv2_double_main_loop_sandybridge.inc | 3 + .../asm/cn2/cnv2_main_loop_bulldozer.inc | 2 + .../asm/cn2/cnv2_main_loop_ivybridge.inc | 2 + src/crypto/asm/cn2/cnv2_main_loop_ryzen.inc | 2 + .../asm/cn2/cnv2_rwz_double_main_loop.inc | 3 + src/crypto/asm/cn2/cnv2_rwz_main_loop.inc | 2 + src/crypto/asm/cn_main_loop.S | 2 - .../CryptonightR_soft_aes_template_win.inc | 2 + .../asm/win64/CryptonightR_template_win.inc | 5 ++ .../CryptonightWOW_soft_aes_template_win.inc | 2 + .../asm/win64/CryptonightWOW_template_win.inc | 5 ++ .../cn2/cnv2_double_main_loop_sandybridge.inc | 3 + .../win64/cn2/cnv2_main_loop_bulldozer.inc | 2 + .../win64/cn2/cnv2_main_loop_ivybridge.inc | 2 + .../asm/win64/cn2/cnv2_main_loop_ryzen.inc | 2 + .../win64/cn2/cnv2_rwz_double_main_loop.inc | 3 + .../asm/win64/cn2/cnv2_rwz_main_loop.inc | 2 + src/workers/CpuThread.cpp | 24 +++---- src/workers/CpuThread.h | 3 +- 30 files changed, 121 insertions(+), 55 deletions(-) diff --git a/src/Mem.cpp b/src/Mem.cpp index 4fa794d6..01a2157b 100644 --- a/src/Mem.cpp +++ b/src/Mem.cpp @@ -53,7 +53,7 @@ MemInfo Mem::create(cryptonight_ctx **ctx, xmrig::Algo algorithm, size_t count) uint8_t* p = reinterpret_cast(allocateExecutableMemory(0x4000)); c->generated_code = reinterpret_cast(p); - c->generated_code_double = reinterpret_cast(p + 0x2000); + c->generated_code_double = reinterpret_cast(p + 0x2000); c->generated_code_data.variant = xmrig::VARIANT_MAX; c->generated_code_data.height = (uint64_t)(-1); diff --git a/src/crypto/CryptoNight.h b/src/crypto/CryptoNight.h index 91a4c7b7..b1ec2371 100644 --- a/src/crypto/CryptoNight.h +++ b/src/crypto/CryptoNight.h @@ -36,8 +36,7 @@ #endif struct cryptonight_ctx; -typedef void(*cn_mainloop_fun_ms_abi)(cryptonight_ctx*) ABI_ATTRIBUTE; -typedef void(*cn_mainloop_double_fun_ms_abi)(cryptonight_ctx*, cryptonight_ctx*) ABI_ATTRIBUTE; +typedef void(*cn_mainloop_fun_ms_abi)(cryptonight_ctx**) ABI_ATTRIBUTE; struct cryptonight_r_data { int variant; @@ -54,7 +53,7 @@ struct cryptonight_ctx { const uint32_t* saes_table; cn_mainloop_fun_ms_abi generated_code; - cn_mainloop_double_fun_ms_abi generated_code_double; + cn_mainloop_fun_ms_abi generated_code_double; cryptonight_r_data generated_code_data; cryptonight_r_data generated_code_double_data; }; diff --git a/src/crypto/CryptoNight_x86.h b/src/crypto/CryptoNight_x86.h index 8b9ea783..202b662a 100644 --- a/src/crypto/CryptoNight_x86.h +++ b/src/crypto/CryptoNight_x86.h @@ -590,7 +590,7 @@ inline void cryptonight_single_hash(const uint8_t *__restrict__ input, size_t si } ctx[0]->saes_table = (const uint32_t*)saes_table; - ctx[0]->generated_code(ctx[0]); + ctx[0]->generated_code(ctx); } else { #endif @@ -750,32 +750,32 @@ inline void cryptonight_single_hash_gpu(const uint8_t *__restrict__ input, size_ #ifndef XMRIG_NO_ASM -extern "C" void cnv2_mainloop_ivybridge_asm(cryptonight_ctx *ctx); -extern "C" void cnv2_mainloop_ryzen_asm(cryptonight_ctx *ctx); -extern "C" void cnv2_mainloop_bulldozer_asm(cryptonight_ctx *ctx); -extern "C" void cnv2_double_mainloop_sandybridge_asm(cryptonight_ctx* ctx0, cryptonight_ctx* ctx1); -extern "C" void cnv2_rwz_mainloop_asm(cryptonight_ctx *ctx); -extern "C" void cnv2_rwz_double_mainloop_asm(cryptonight_ctx* ctx0, cryptonight_ctx* ctx1); +extern "C" void cnv2_mainloop_ivybridge_asm(cryptonight_ctx **ctx); +extern "C" void cnv2_mainloop_ryzen_asm(cryptonight_ctx **ctx); +extern "C" void cnv2_mainloop_bulldozer_asm(cryptonight_ctx **ctx); +extern "C" void cnv2_double_mainloop_sandybridge_asm(cryptonight_ctx **ctx); +extern "C" void cnv2_rwz_mainloop_asm(cryptonight_ctx **ctx); +extern "C" void cnv2_rwz_double_mainloop_asm(cryptonight_ctx **ctx); extern xmrig::CpuThread::cn_mainloop_fun cn_half_mainloop_ivybridge_asm; extern xmrig::CpuThread::cn_mainloop_fun cn_half_mainloop_ryzen_asm; extern xmrig::CpuThread::cn_mainloop_fun cn_half_mainloop_bulldozer_asm; -extern xmrig::CpuThread::cn_mainloop_double_fun cn_half_double_mainloop_sandybridge_asm; +extern xmrig::CpuThread::cn_mainloop_fun cn_half_double_mainloop_sandybridge_asm; extern xmrig::CpuThread::cn_mainloop_fun cn_trtl_mainloop_ivybridge_asm; extern xmrig::CpuThread::cn_mainloop_fun cn_trtl_mainloop_ryzen_asm; extern xmrig::CpuThread::cn_mainloop_fun cn_trtl_mainloop_bulldozer_asm; -extern xmrig::CpuThread::cn_mainloop_double_fun cn_trtl_double_mainloop_sandybridge_asm; +extern xmrig::CpuThread::cn_mainloop_fun cn_trtl_double_mainloop_sandybridge_asm; extern xmrig::CpuThread::cn_mainloop_fun cn_zls_mainloop_ivybridge_asm; extern xmrig::CpuThread::cn_mainloop_fun cn_zls_mainloop_ryzen_asm; extern xmrig::CpuThread::cn_mainloop_fun cn_zls_mainloop_bulldozer_asm; -extern xmrig::CpuThread::cn_mainloop_double_fun cn_zls_double_mainloop_sandybridge_asm; +extern xmrig::CpuThread::cn_mainloop_fun cn_zls_double_mainloop_sandybridge_asm; extern xmrig::CpuThread::cn_mainloop_fun cn_double_mainloop_ivybridge_asm; extern xmrig::CpuThread::cn_mainloop_fun cn_double_mainloop_ryzen_asm; extern xmrig::CpuThread::cn_mainloop_fun cn_double_mainloop_bulldozer_asm; -extern xmrig::CpuThread::cn_mainloop_double_fun cn_double_double_mainloop_sandybridge_asm; +extern xmrig::CpuThread::cn_mainloop_fun cn_double_double_mainloop_sandybridge_asm; void wow_compile_code(const V4_Instruction* code, int code_size, void* machine_code, xmrig::Assembly ASM); void v4_compile_code(const V4_Instruction* code, int code_size, void* machine_code, xmrig::Assembly ASM); @@ -824,64 +824,64 @@ inline void cryptonight_single_hash_asm(const uint8_t *__restrict__ input, size_ if (VARIANT == xmrig::VARIANT_2) { if (ASM == xmrig::ASM_INTEL) { - cnv2_mainloop_ivybridge_asm(ctx[0]); + cnv2_mainloop_ivybridge_asm(ctx); } else if (ASM == xmrig::ASM_RYZEN) { - cnv2_mainloop_ryzen_asm(ctx[0]); + cnv2_mainloop_ryzen_asm(ctx); } else { - cnv2_mainloop_bulldozer_asm(ctx[0]); + cnv2_mainloop_bulldozer_asm(ctx); } } else if (VARIANT == xmrig::VARIANT_HALF) { if (ASM == xmrig::ASM_INTEL) { - cn_half_mainloop_ivybridge_asm(ctx[0]); + cn_half_mainloop_ivybridge_asm(ctx); } else if (ASM == xmrig::ASM_RYZEN) { - cn_half_mainloop_ryzen_asm(ctx[0]); + cn_half_mainloop_ryzen_asm(ctx); } else { - cn_half_mainloop_bulldozer_asm(ctx[0]); + cn_half_mainloop_bulldozer_asm(ctx); } } else if (VARIANT == xmrig::VARIANT_TRTL) { if (ASM == xmrig::ASM_INTEL) { - cn_trtl_mainloop_ivybridge_asm(ctx[0]); + cn_trtl_mainloop_ivybridge_asm(ctx); } else if (ASM == xmrig::ASM_RYZEN) { - cn_trtl_mainloop_ryzen_asm(ctx[0]); + cn_trtl_mainloop_ryzen_asm(ctx); } else { - cn_trtl_mainloop_bulldozer_asm(ctx[0]); + cn_trtl_mainloop_bulldozer_asm(ctx); } } else if (VARIANT == xmrig::VARIANT_RWZ) { - cnv2_rwz_mainloop_asm(ctx[0]); + cnv2_rwz_mainloop_asm(ctx); } else if (VARIANT == xmrig::VARIANT_ZLS) { if (ASM == xmrig::ASM_INTEL) { - cn_zls_mainloop_ivybridge_asm(ctx[0]); + cn_zls_mainloop_ivybridge_asm(ctx); } else if (ASM == xmrig::ASM_RYZEN) { - cn_zls_mainloop_ryzen_asm(ctx[0]); + cn_zls_mainloop_ryzen_asm(ctx); } else { - cn_zls_mainloop_bulldozer_asm(ctx[0]); + cn_zls_mainloop_bulldozer_asm(ctx); } } else if (VARIANT == xmrig::VARIANT_DOUBLE) { if (ASM == xmrig::ASM_INTEL) { - cn_double_mainloop_ivybridge_asm(ctx[0]); + cn_double_mainloop_ivybridge_asm(ctx); } else if (ASM == xmrig::ASM_RYZEN) { - cn_double_mainloop_ryzen_asm(ctx[0]); + cn_double_mainloop_ryzen_asm(ctx); } else { - cn_double_mainloop_bulldozer_asm(ctx[0]); + cn_double_mainloop_bulldozer_asm(ctx); } } else if (xmrig::cn_is_cryptonight_r()) { - ctx[0]->generated_code(ctx[0]); + ctx[0]->generated_code(ctx); } cn_implode_scratchpad(reinterpret_cast<__m128i*>(ctx[0]->memory), reinterpret_cast<__m128i*>(ctx[0]->state)); @@ -910,25 +910,25 @@ inline void cryptonight_double_hash_asm(const uint8_t *__restrict__ input, size_ cn_explode_scratchpad(reinterpret_cast<__m128i*>(ctx[1]->state), reinterpret_cast<__m128i*>(ctx[1]->memory)); if (VARIANT == xmrig::VARIANT_2) { - cnv2_double_mainloop_sandybridge_asm(ctx[0], ctx[1]); + cnv2_double_mainloop_sandybridge_asm(ctx); } else if (VARIANT == xmrig::VARIANT_HALF) { - cn_half_double_mainloop_sandybridge_asm(ctx[0], ctx[1]); + cn_half_double_mainloop_sandybridge_asm(ctx); } else if (VARIANT == xmrig::VARIANT_TRTL) { - cn_trtl_double_mainloop_sandybridge_asm(ctx[0], ctx[1]); + cn_trtl_double_mainloop_sandybridge_asm(ctx); } else if (VARIANT == xmrig::VARIANT_RWZ) { - cnv2_rwz_double_mainloop_asm(ctx[0], ctx[1]); + cnv2_rwz_double_mainloop_asm(ctx); } else if (VARIANT == xmrig::VARIANT_ZLS) { - cn_zls_double_mainloop_sandybridge_asm(ctx[0], ctx[1]); + cn_zls_double_mainloop_sandybridge_asm(ctx); } else if (VARIANT == xmrig::VARIANT_DOUBLE) { - cn_double_double_mainloop_sandybridge_asm(ctx[0], ctx[1]); + cn_double_double_mainloop_sandybridge_asm(ctx); } else if (xmrig::cn_is_cryptonight_r()) { - ctx[0]->generated_code_double(ctx[0], ctx[1]); + ctx[0]->generated_code_double(ctx); } cn_implode_scratchpad(reinterpret_cast<__m128i*>(ctx[0]->memory), reinterpret_cast<__m128i*>(ctx[0]->state)); diff --git a/src/crypto/asm/CryptonightR_soft_aes_template.inc b/src/crypto/asm/CryptonightR_soft_aes_template.inc index 40c7874d..e9e1bb4f 100644 --- a/src/crypto/asm/CryptonightR_soft_aes_template.inc +++ b/src/crypto/asm/CryptonightR_soft_aes_template.inc @@ -6,6 +6,8 @@ PUBLIC FN_PREFIX(CryptonightR_soft_aes_template_end) ALIGN(64) FN_PREFIX(CryptonightR_soft_aes_template_part1): + mov rcx, [rcx] + mov QWORD PTR [rsp+8], rcx push rbx push rbp diff --git a/src/crypto/asm/CryptonightR_soft_aes_template_win.inc b/src/crypto/asm/CryptonightR_soft_aes_template_win.inc index d771f69c..589192ca 100644 --- a/src/crypto/asm/CryptonightR_soft_aes_template_win.inc +++ b/src/crypto/asm/CryptonightR_soft_aes_template_win.inc @@ -6,6 +6,8 @@ PUBLIC CryptonightR_soft_aes_template_end ALIGN(64) CryptonightR_soft_aes_template_part1: + mov rcx, [rcx] + mov QWORD PTR [rsp+8], rcx push rbx push rbp diff --git a/src/crypto/asm/CryptonightR_template.inc b/src/crypto/asm/CryptonightR_template.inc index 8ecab724..61b6b985 100644 --- a/src/crypto/asm/CryptonightR_template.inc +++ b/src/crypto/asm/CryptonightR_template.inc @@ -12,6 +12,8 @@ PUBLIC FN_PREFIX(CryptonightR_template_double_end) ALIGN(64) FN_PREFIX(CryptonightR_template_part1): + mov rcx, [rcx] + mov QWORD PTR [rsp+16], rbx mov QWORD PTR [rsp+24], rbp mov QWORD PTR [rsp+32], rsi @@ -183,6 +185,9 @@ FN_PREFIX(CryptonightR_template_end): ALIGN(64) FN_PREFIX(CryptonightR_template_double_part1): + mov rdx, [rcx+8] + mov rcx, [rcx] + mov QWORD PTR [rsp+24], rbx push rbp push rsi diff --git a/src/crypto/asm/CryptonightR_template_win.inc b/src/crypto/asm/CryptonightR_template_win.inc index a170f2d2..1bb89eb1 100644 --- a/src/crypto/asm/CryptonightR_template_win.inc +++ b/src/crypto/asm/CryptonightR_template_win.inc @@ -12,6 +12,8 @@ PUBLIC CryptonightR_template_double_end ALIGN(64) CryptonightR_template_part1: + mov rcx, [rcx] + mov QWORD PTR [rsp+16], rbx mov QWORD PTR [rsp+24], rbp mov QWORD PTR [rsp+32], rsi @@ -183,6 +185,9 @@ CryptonightR_template_end: ALIGN(64) CryptonightR_template_double_part1: + mov rdx, [rcx+8] + mov rcx, [rcx] + mov QWORD PTR [rsp+24], rbx push rbp push rsi diff --git a/src/crypto/asm/CryptonightWOW_soft_aes_template.inc b/src/crypto/asm/CryptonightWOW_soft_aes_template.inc index feea3949..53b7016a 100644 --- a/src/crypto/asm/CryptonightWOW_soft_aes_template.inc +++ b/src/crypto/asm/CryptonightWOW_soft_aes_template.inc @@ -6,6 +6,8 @@ PUBLIC FN_PREFIX(CryptonightWOW_soft_aes_template_end) ALIGN(64) FN_PREFIX(CryptonightWOW_soft_aes_template_part1): + mov rcx, [rcx] + mov QWORD PTR [rsp+8], rcx push rbx push rbp diff --git a/src/crypto/asm/CryptonightWOW_soft_aes_template_win.inc b/src/crypto/asm/CryptonightWOW_soft_aes_template_win.inc index 6ebad99f..b3202b78 100644 --- a/src/crypto/asm/CryptonightWOW_soft_aes_template_win.inc +++ b/src/crypto/asm/CryptonightWOW_soft_aes_template_win.inc @@ -6,6 +6,8 @@ PUBLIC CryptonightWOW_soft_aes_template_end ALIGN(64) CryptonightWOW_soft_aes_template_part1: + mov rcx, [rcx] + mov QWORD PTR [rsp+8], rcx push rbx push rbp diff --git a/src/crypto/asm/CryptonightWOW_template.inc b/src/crypto/asm/CryptonightWOW_template.inc index 7183a659..82d455f6 100644 --- a/src/crypto/asm/CryptonightWOW_template.inc +++ b/src/crypto/asm/CryptonightWOW_template.inc @@ -12,6 +12,8 @@ PUBLIC FN_PREFIX(CryptonightWOW_template_double_end) ALIGN(64) FN_PREFIX(CryptonightWOW_template_part1): + mov rcx, [rcx] + mov QWORD PTR [rsp+16], rbx mov QWORD PTR [rsp+24], rbp mov QWORD PTR [rsp+32], rsi @@ -165,6 +167,9 @@ FN_PREFIX(CryptonightWOW_template_end): ALIGN(64) FN_PREFIX(CryptonightWOW_template_double_part1): + mov rdx, [rcx+8] + mov rcx, [rcx] + mov QWORD PTR [rsp+24], rbx push rbp push rsi diff --git a/src/crypto/asm/CryptonightWOW_template_win.inc b/src/crypto/asm/CryptonightWOW_template_win.inc index c5652e27..644c01f1 100644 --- a/src/crypto/asm/CryptonightWOW_template_win.inc +++ b/src/crypto/asm/CryptonightWOW_template_win.inc @@ -12,6 +12,8 @@ PUBLIC CryptonightWOW_template_double_end ALIGN(64) CryptonightWOW_template_part1: + mov rcx, [rcx] + mov QWORD PTR [rsp+16], rbx mov QWORD PTR [rsp+24], rbp mov QWORD PTR [rsp+32], rsi @@ -165,6 +167,9 @@ CryptonightWOW_template_end: ALIGN(64) CryptonightWOW_template_double_part1: + mov rdx, [rcx+8] + mov rcx, [rcx] + mov QWORD PTR [rsp+24], rbx push rbp push rsi diff --git a/src/crypto/asm/cn2/cnv2_double_main_loop_sandybridge.inc b/src/crypto/asm/cn2/cnv2_double_main_loop_sandybridge.inc index aa5101a8..1710cac7 100644 --- a/src/crypto/asm/cn2/cnv2_double_main_loop_sandybridge.inc +++ b/src/crypto/asm/cn2/cnv2_double_main_loop_sandybridge.inc @@ -1,3 +1,6 @@ + mov rdx, [rcx+8] + mov rcx, [rcx] + mov rax, rsp push rbx push rbp diff --git a/src/crypto/asm/cn2/cnv2_main_loop_bulldozer.inc b/src/crypto/asm/cn2/cnv2_main_loop_bulldozer.inc index c764501d..b881b669 100644 --- a/src/crypto/asm/cn2/cnv2_main_loop_bulldozer.inc +++ b/src/crypto/asm/cn2/cnv2_main_loop_bulldozer.inc @@ -1,3 +1,5 @@ + mov rcx, [rcx] + mov QWORD PTR [rsp+16], rbx mov QWORD PTR [rsp+24], rbp mov QWORD PTR [rsp+32], rsi diff --git a/src/crypto/asm/cn2/cnv2_main_loop_ivybridge.inc b/src/crypto/asm/cn2/cnv2_main_loop_ivybridge.inc index 06f1d28b..863673de 100644 --- a/src/crypto/asm/cn2/cnv2_main_loop_ivybridge.inc +++ b/src/crypto/asm/cn2/cnv2_main_loop_ivybridge.inc @@ -1,3 +1,5 @@ + mov rcx, [rcx] + mov QWORD PTR [rsp+24], rbx push rbp push rsi diff --git a/src/crypto/asm/cn2/cnv2_main_loop_ryzen.inc b/src/crypto/asm/cn2/cnv2_main_loop_ryzen.inc index 5dbf5917..8ccc5e17 100644 --- a/src/crypto/asm/cn2/cnv2_main_loop_ryzen.inc +++ b/src/crypto/asm/cn2/cnv2_main_loop_ryzen.inc @@ -1,3 +1,5 @@ + mov rcx, [rcx] + mov QWORD PTR [rsp+16], rbx mov QWORD PTR [rsp+24], rbp mov QWORD PTR [rsp+32], rsi diff --git a/src/crypto/asm/cn2/cnv2_rwz_double_main_loop.inc b/src/crypto/asm/cn2/cnv2_rwz_double_main_loop.inc index d2d87173..d9bfc9c1 100644 --- a/src/crypto/asm/cn2/cnv2_rwz_double_main_loop.inc +++ b/src/crypto/asm/cn2/cnv2_rwz_double_main_loop.inc @@ -1,3 +1,6 @@ + mov rdx, [rcx+8] + mov rcx, [rcx] + mov rax, rsp push rbx push rbp diff --git a/src/crypto/asm/cn2/cnv2_rwz_main_loop.inc b/src/crypto/asm/cn2/cnv2_rwz_main_loop.inc index 021f787e..b59c02d6 100644 --- a/src/crypto/asm/cn2/cnv2_rwz_main_loop.inc +++ b/src/crypto/asm/cn2/cnv2_rwz_main_loop.inc @@ -1,3 +1,5 @@ + mov rcx, [rcx] + mov QWORD PTR [rsp+24], rbx push rbp push rsi diff --git a/src/crypto/asm/cn_main_loop.S b/src/crypto/asm/cn_main_loop.S index 347f0e08..7aed6c20 100644 --- a/src/crypto/asm/cn_main_loop.S +++ b/src/crypto/asm/cn_main_loop.S @@ -49,7 +49,6 @@ ALIGN(64) FN_PREFIX(cnv2_double_mainloop_sandybridge_asm): sub rsp, 48 mov rcx, rdi - mov rdx, rsi #include "cn2/cnv2_double_main_loop_sandybridge.inc" add rsp, 48 ret 0 @@ -68,7 +67,6 @@ ALIGN(64) FN_PREFIX(cnv2_rwz_double_mainloop_asm): sub rsp, 48 mov rcx, rdi - mov rdx, rsi #include "cn2/cnv2_rwz_double_main_loop.inc" add rsp, 48 ret 0 diff --git a/src/crypto/asm/win64/CryptonightR_soft_aes_template_win.inc b/src/crypto/asm/win64/CryptonightR_soft_aes_template_win.inc index d6d393a9..6898a604 100644 --- a/src/crypto/asm/win64/CryptonightR_soft_aes_template_win.inc +++ b/src/crypto/asm/win64/CryptonightR_soft_aes_template_win.inc @@ -6,6 +6,8 @@ PUBLIC CryptonightR_soft_aes_template_end ALIGN(64) CryptonightR_soft_aes_template_part1: + mov rcx, [rcx] + mov QWORD PTR [rsp+8], rcx push rbx push rbp diff --git a/src/crypto/asm/win64/CryptonightR_template_win.inc b/src/crypto/asm/win64/CryptonightR_template_win.inc index 60ee3441..d24eedaa 100644 --- a/src/crypto/asm/win64/CryptonightR_template_win.inc +++ b/src/crypto/asm/win64/CryptonightR_template_win.inc @@ -12,6 +12,8 @@ PUBLIC CryptonightR_template_double_end ALIGN(64) CryptonightR_template_part1: + mov rcx, [rcx] + mov QWORD PTR [rsp+16], rbx mov QWORD PTR [rsp+24], rbp mov QWORD PTR [rsp+32], rsi @@ -183,6 +185,9 @@ CryptonightR_template_end: ALIGN(64) CryptonightR_template_double_part1: + mov rdx, [rcx+8] + mov rcx, [rcx] + mov QWORD PTR [rsp+24], rbx push rbp push rsi diff --git a/src/crypto/asm/win64/CryptonightWOW_soft_aes_template_win.inc b/src/crypto/asm/win64/CryptonightWOW_soft_aes_template_win.inc index 68209036..1c73f77c 100644 --- a/src/crypto/asm/win64/CryptonightWOW_soft_aes_template_win.inc +++ b/src/crypto/asm/win64/CryptonightWOW_soft_aes_template_win.inc @@ -6,6 +6,8 @@ PUBLIC CryptonightWOW_soft_aes_template_end ALIGN(64) CryptonightWOW_soft_aes_template_part1: + mov rcx, [rcx] + mov QWORD PTR [rsp+8], rcx push rbx push rbp diff --git a/src/crypto/asm/win64/CryptonightWOW_template_win.inc b/src/crypto/asm/win64/CryptonightWOW_template_win.inc index 9db2cf39..55c8c8df 100644 --- a/src/crypto/asm/win64/CryptonightWOW_template_win.inc +++ b/src/crypto/asm/win64/CryptonightWOW_template_win.inc @@ -12,6 +12,8 @@ PUBLIC CryptonightWOW_template_double_end ALIGN(64) CryptonightWOW_template_part1: + mov rcx, [rcx] + mov QWORD PTR [rsp+16], rbx mov QWORD PTR [rsp+24], rbp mov QWORD PTR [rsp+32], rsi @@ -165,6 +167,9 @@ CryptonightWOW_template_end: ALIGN(64) CryptonightWOW_template_double_part1: + mov rdx, [rcx+8] + mov rcx, [rcx] + mov QWORD PTR [rsp+24], rbx push rbp push rsi diff --git a/src/crypto/asm/win64/cn2/cnv2_double_main_loop_sandybridge.inc b/src/crypto/asm/win64/cn2/cnv2_double_main_loop_sandybridge.inc index 05af9393..85077a20 100644 --- a/src/crypto/asm/win64/cn2/cnv2_double_main_loop_sandybridge.inc +++ b/src/crypto/asm/win64/cn2/cnv2_double_main_loop_sandybridge.inc @@ -1,3 +1,6 @@ + mov rdx, [rcx+8] + mov rcx, [rcx] + mov rax, rsp push rbx push rbp diff --git a/src/crypto/asm/win64/cn2/cnv2_main_loop_bulldozer.inc b/src/crypto/asm/win64/cn2/cnv2_main_loop_bulldozer.inc index 03a36f48..f17017a0 100644 --- a/src/crypto/asm/win64/cn2/cnv2_main_loop_bulldozer.inc +++ b/src/crypto/asm/win64/cn2/cnv2_main_loop_bulldozer.inc @@ -1,3 +1,5 @@ + mov rcx, [rcx] + mov QWORD PTR [rsp+16], rbx mov QWORD PTR [rsp+24], rbp mov QWORD PTR [rsp+32], rsi diff --git a/src/crypto/asm/win64/cn2/cnv2_main_loop_ivybridge.inc b/src/crypto/asm/win64/cn2/cnv2_main_loop_ivybridge.inc index 77e28f80..a12ac35c 100644 --- a/src/crypto/asm/win64/cn2/cnv2_main_loop_ivybridge.inc +++ b/src/crypto/asm/win64/cn2/cnv2_main_loop_ivybridge.inc @@ -1,3 +1,5 @@ + mov rcx, [rcx] + mov QWORD PTR [rsp+24], rbx push rbp push rsi diff --git a/src/crypto/asm/win64/cn2/cnv2_main_loop_ryzen.inc b/src/crypto/asm/win64/cn2/cnv2_main_loop_ryzen.inc index 7e5c127f..044235d8 100644 --- a/src/crypto/asm/win64/cn2/cnv2_main_loop_ryzen.inc +++ b/src/crypto/asm/win64/cn2/cnv2_main_loop_ryzen.inc @@ -1,3 +1,5 @@ + mov rcx, [rcx] + mov QWORD PTR [rsp+16], rbx mov QWORD PTR [rsp+24], rbp mov QWORD PTR [rsp+32], rsi diff --git a/src/crypto/asm/win64/cn2/cnv2_rwz_double_main_loop.inc b/src/crypto/asm/win64/cn2/cnv2_rwz_double_main_loop.inc index 69ca8793..97fb691b 100644 --- a/src/crypto/asm/win64/cn2/cnv2_rwz_double_main_loop.inc +++ b/src/crypto/asm/win64/cn2/cnv2_rwz_double_main_loop.inc @@ -1,3 +1,6 @@ + mov rdx, [rcx+8] + mov rcx, [rcx] + mov rax, rsp push rbx push rbp diff --git a/src/crypto/asm/win64/cn2/cnv2_rwz_main_loop.inc b/src/crypto/asm/win64/cn2/cnv2_rwz_main_loop.inc index 99317730..e2b7a5fc 100644 --- a/src/crypto/asm/win64/cn2/cnv2_rwz_main_loop.inc +++ b/src/crypto/asm/win64/cn2/cnv2_rwz_main_loop.inc @@ -1,3 +1,5 @@ + mov rcx, [rcx] + mov QWORD PTR [rsp+24], rbx push rbp push rsi diff --git a/src/workers/CpuThread.cpp b/src/workers/CpuThread.cpp index c98b730a..6548b461 100644 --- a/src/workers/CpuThread.cpp +++ b/src/workers/CpuThread.cpp @@ -90,31 +90,31 @@ static void patchCode(T dst, U src, const uint32_t iterations, const uint32_t ma } -extern "C" void cnv2_mainloop_ivybridge_asm(cryptonight_ctx *ctx); -extern "C" void cnv2_mainloop_ryzen_asm(cryptonight_ctx *ctx); -extern "C" void cnv2_mainloop_bulldozer_asm(cryptonight_ctx *ctx); -extern "C" void cnv2_double_mainloop_sandybridge_asm(cryptonight_ctx *ctx0, cryptonight_ctx *ctx1); +extern "C" void cnv2_mainloop_ivybridge_asm(cryptonight_ctx **ctx); +extern "C" void cnv2_mainloop_ryzen_asm(cryptonight_ctx **ctx); +extern "C" void cnv2_mainloop_bulldozer_asm(cryptonight_ctx **ctx); +extern "C" void cnv2_double_mainloop_sandybridge_asm(cryptonight_ctx **ctx); xmrig::CpuThread::cn_mainloop_fun cn_half_mainloop_ivybridge_asm = nullptr; xmrig::CpuThread::cn_mainloop_fun cn_half_mainloop_ryzen_asm = nullptr; xmrig::CpuThread::cn_mainloop_fun cn_half_mainloop_bulldozer_asm = nullptr; -xmrig::CpuThread::cn_mainloop_double_fun cn_half_double_mainloop_sandybridge_asm = nullptr; +xmrig::CpuThread::cn_mainloop_fun cn_half_double_mainloop_sandybridge_asm = nullptr; xmrig::CpuThread::cn_mainloop_fun cn_trtl_mainloop_ivybridge_asm = nullptr; xmrig::CpuThread::cn_mainloop_fun cn_trtl_mainloop_ryzen_asm = nullptr; xmrig::CpuThread::cn_mainloop_fun cn_trtl_mainloop_bulldozer_asm = nullptr; -xmrig::CpuThread::cn_mainloop_double_fun cn_trtl_double_mainloop_sandybridge_asm = nullptr; +xmrig::CpuThread::cn_mainloop_fun cn_trtl_double_mainloop_sandybridge_asm = nullptr; xmrig::CpuThread::cn_mainloop_fun cn_zls_mainloop_ivybridge_asm = nullptr; xmrig::CpuThread::cn_mainloop_fun cn_zls_mainloop_ryzen_asm = nullptr; xmrig::CpuThread::cn_mainloop_fun cn_zls_mainloop_bulldozer_asm = nullptr; -xmrig::CpuThread::cn_mainloop_double_fun cn_zls_double_mainloop_sandybridge_asm = nullptr; +xmrig::CpuThread::cn_mainloop_fun cn_zls_double_mainloop_sandybridge_asm = nullptr; xmrig::CpuThread::cn_mainloop_fun cn_double_mainloop_ivybridge_asm = nullptr; xmrig::CpuThread::cn_mainloop_fun cn_double_mainloop_ryzen_asm = nullptr; xmrig::CpuThread::cn_mainloop_fun cn_double_mainloop_bulldozer_asm = nullptr; -xmrig::CpuThread::cn_mainloop_double_fun cn_double_double_mainloop_sandybridge_asm = nullptr; +xmrig::CpuThread::cn_mainloop_fun cn_double_double_mainloop_sandybridge_asm = nullptr; void xmrig::CpuThread::patchAsmVariants() @@ -125,22 +125,22 @@ void xmrig::CpuThread::patchAsmVariants() cn_half_mainloop_ivybridge_asm = reinterpret_cast (base + 0x0000); cn_half_mainloop_ryzen_asm = reinterpret_cast (base + 0x1000); cn_half_mainloop_bulldozer_asm = reinterpret_cast (base + 0x2000); - cn_half_double_mainloop_sandybridge_asm = reinterpret_cast (base + 0x3000); + cn_half_double_mainloop_sandybridge_asm = reinterpret_cast (base + 0x3000); cn_trtl_mainloop_ivybridge_asm = reinterpret_cast (base + 0x4000); cn_trtl_mainloop_ryzen_asm = reinterpret_cast (base + 0x5000); cn_trtl_mainloop_bulldozer_asm = reinterpret_cast (base + 0x6000); - cn_trtl_double_mainloop_sandybridge_asm = reinterpret_cast (base + 0x7000); + cn_trtl_double_mainloop_sandybridge_asm = reinterpret_cast (base + 0x7000); cn_zls_mainloop_ivybridge_asm = reinterpret_cast (base + 0x8000); cn_zls_mainloop_ryzen_asm = reinterpret_cast (base + 0x9000); cn_zls_mainloop_bulldozer_asm = reinterpret_cast (base + 0xA000); - cn_zls_double_mainloop_sandybridge_asm = reinterpret_cast (base + 0xB000); + cn_zls_double_mainloop_sandybridge_asm = reinterpret_cast (base + 0xB000); cn_double_mainloop_ivybridge_asm = reinterpret_cast (base + 0xC000); cn_double_mainloop_ryzen_asm = reinterpret_cast (base + 0xD000); cn_double_mainloop_bulldozer_asm = reinterpret_cast (base + 0xE000); - cn_double_double_mainloop_sandybridge_asm = reinterpret_cast (base + 0xF000); + cn_double_double_mainloop_sandybridge_asm = reinterpret_cast (base + 0xF000); patchCode(cn_half_mainloop_ivybridge_asm, cnv2_mainloop_ivybridge_asm, xmrig::CRYPTONIGHT_HALF_ITER, xmrig::CRYPTONIGHT_MASK); patchCode(cn_half_mainloop_ryzen_asm, cnv2_mainloop_ryzen_asm, xmrig::CRYPTONIGHT_HALF_ITER, xmrig::CRYPTONIGHT_MASK); diff --git a/src/workers/CpuThread.h b/src/workers/CpuThread.h index 54e98cde..05d4a066 100644 --- a/src/workers/CpuThread.h +++ b/src/workers/CpuThread.h @@ -61,8 +61,7 @@ public: CpuThread(size_t index, Algo algorithm, AlgoVariant av, Multiway multiway, int64_t affinity, int priority, bool softAES, bool prefetch, Assembly assembly); typedef void (*cn_hash_fun)(const uint8_t *input, size_t size, uint8_t *output, cryptonight_ctx **ctx, uint64_t height); - typedef void (*cn_mainloop_fun)(cryptonight_ctx *ctx); - typedef void (*cn_mainloop_double_fun)(cryptonight_ctx *ctx1, cryptonight_ctx *ctx2); + typedef void (*cn_mainloop_fun)(cryptonight_ctx **ctx); # ifndef XMRIG_NO_ASM static void patchAsmVariants(); From d57b41c67303b39e390a2a4d657d51dc22a8b9cc Mon Sep 17 00:00:00 2001 From: XMRig Date: Thu, 14 Mar 2019 18:42:27 +0700 Subject: [PATCH 003/116] Sync changes. --- CMakeLists.txt | 1 + src/base/net/Pool.cpp | 2 +- src/base/tools/Chrono.h | 60 +++++++++++++++++++ src/common/interfaces/IClientListener.h | 6 +- src/common/interfaces/IConfig.h | 2 + src/common/net/Client.cpp | 8 ++- src/common/net/Job.h | 8 ++- .../net/strategies/FailoverStrategy.cpp | 2 +- src/common/net/strategies/FailoverStrategy.h | 4 +- .../net/strategies/SinglePoolStrategy.cpp | 2 +- .../net/strategies/SinglePoolStrategy.h | 4 +- src/crypto/CryptoNight_constants.h | 26 ++++++++ 12 files changed, 113 insertions(+), 12 deletions(-) create mode 100644 src/base/tools/Chrono.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 14dcc931..94bf61b6 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -32,6 +32,7 @@ set(HEADERS src/base/net/Pool.h src/base/net/Pools.h src/base/tools/Arguments.h + src/base/tools/Chrono.h src/base/tools/Handle.h src/base/tools/String.h src/common/config/CommonConfig.h diff --git a/src/base/net/Pool.cpp b/src/base/net/Pool.cpp index 9d4f2bde..de02be92 100644 --- a/src/base/net/Pool.cpp +++ b/src/base/net/Pool.cpp @@ -165,7 +165,7 @@ bool xmrig::Pool::isCompatible(const Algorithm &algorithm) const # ifdef XMRIG_PROXY_PROJECT if (m_algorithm.algo() == xmrig::CRYPTONIGHT && algorithm.algo() == xmrig::CRYPTONIGHT) { - return m_algorithm.variant() == xmrig::VARIANT_XTL || m_algorithm.variant() == xmrig::VARIANT_MSR; + return m_algorithm.variant() == xmrig::VARIANT_RWZ || m_algorithm.variant() == xmrig::VARIANT_ZLS; } # endif diff --git a/src/base/tools/Chrono.h b/src/base/tools/Chrono.h new file mode 100644 index 00000000..d3c14602 --- /dev/null +++ b/src/base/tools/Chrono.h @@ -0,0 +1,60 @@ +/* XMRig + * Copyright 2010 Jeff Garzik + * Copyright 2012-2014 pooler + * Copyright 2014 Lucas Jones + * Copyright 2014-2016 Wolf9466 + * Copyright 2016 Jay D Dee + * Copyright 2017-2018 XMR-Stak , + * Copyright 2018-2019 SChernykh + * Copyright 2016-2019 XMRig , + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef XMRIG_CHRONO_H +#define XMRIG_CHRONO_H + + +#include + + +namespace xmrig { + + +class Chrono +{ +public: + static inline uint64_t steadyMSecs() + { + using namespace std::chrono; + if (high_resolution_clock::is_steady) { + return static_cast(time_point_cast(high_resolution_clock::now()).time_since_epoch().count()); + } + + return static_cast(time_point_cast(steady_clock::now()).time_since_epoch().count()); + } + + + static inline uint64_t currentMSecsSinceEpoch() + { + using namespace std::chrono; + + return static_cast(time_point_cast(system_clock::now()).time_since_epoch().count()); + } +}; + + +} /* namespace xmrig */ + +#endif /* XMRIG_CHRONO_H */ diff --git a/src/common/interfaces/IClientListener.h b/src/common/interfaces/IClientListener.h index 70a3d1d0..753847ee 100644 --- a/src/common/interfaces/IClientListener.h +++ b/src/common/interfaces/IClientListener.h @@ -29,6 +29,9 @@ #include +#include "rapidjson/fwd.h" + + namespace xmrig { @@ -43,7 +46,8 @@ public: virtual ~IClientListener() = default; virtual void onClose(Client *client, int failures) = 0; - virtual void onJobReceived(Client *client, const Job &job) = 0; + virtual void onJobReceived(Client *client, const Job &job, const rapidjson::Value ¶ms) = 0; + virtual void onLogin(Client *client, rapidjson::Document &doc, rapidjson::Value ¶ms) = 0; virtual void onLoginSuccess(Client *client) = 0; virtual void onResultAccepted(Client *client, const SubmitResult &result, const char *error) = 0; }; diff --git a/src/common/interfaces/IConfig.h b/src/common/interfaces/IConfig.h index 7e6931a8..41a2f01c 100644 --- a/src/common/interfaces/IConfig.h +++ b/src/common/interfaces/IConfig.h @@ -117,6 +117,8 @@ public: TlsCiphersKey = 1112, TlsCipherSuitesKey = 1113, TlsProtocolsKey = 1114, + AlgoExtKey = 1115, + ProxyPasswordKey = 1116, // xmrig nvidia CudaMaxThreadsKey = 1200, diff --git a/src/common/net/Client.cpp b/src/common/net/Client.cpp index 7cd09d46..c0810927 100644 --- a/src/common/net/Client.cpp +++ b/src/common/net/Client.cpp @@ -252,7 +252,7 @@ int64_t xmrig::Client::submit(const JobResult &result) params.AddMember("nonce", StringRef(nonce), allocator); params.AddMember("result", StringRef(data), allocator); - if (m_extensions & AlgoExt) { + if ((m_extensions & AlgoExt) && result.algorithm.isValid()) { params.AddMember("algo", StringRef(result.algorithm.shortName()), allocator); } @@ -643,6 +643,8 @@ void xmrig::Client::login() params.AddMember("algo", algo, allocator); } + m_listener->onLogin(this, doc, params); + doc.AddMember("params", params, allocator); send(doc); @@ -750,7 +752,7 @@ void xmrig::Client::parseNotification(const char *method, const rapidjson::Value if (strcmp(method, "job") == 0) { int code = -1; if (parseJob(params, &code)) { - m_listener->onJobReceived(this, m_job); + m_listener->onJobReceived(this, m_job, params); } return; @@ -799,7 +801,7 @@ void xmrig::Client::parseResponse(int64_t id, const rapidjson::Value &result, co m_failures = 0; m_listener->onLoginSuccess(this); - m_listener->onJobReceived(this, m_job); + m_listener->onJobReceived(this, m_job, result["job"]); return; } diff --git a/src/common/net/Job.h b/src/common/net/Job.h index 49ddc7da..a6e1ec25 100644 --- a/src/common/net/Job.h +++ b/src/common/net/Job.h @@ -58,18 +58,19 @@ public: inline bool isNicehash() const { return m_nicehash; } inline bool isValid() const { return m_size > 0 && m_diff > 0; } inline bool setId(const char *id) { return m_id.setId(id); } - inline const uint32_t *nonce() const { return reinterpret_cast(m_blob + 39); } - inline const uint8_t *blob() const { return m_blob; } inline const Algorithm &algorithm() const { return m_algorithm; } inline const Id &clientId() const { return m_clientId; } inline const Id &id() const { return m_id; } + inline const uint32_t *nonce() const { return reinterpret_cast(m_blob + 39); } + inline const uint8_t *blob() const { return m_blob; } inline int poolId() const { return m_poolId; } inline int threadId() const { return m_threadId; } inline size_t size() const { return m_size; } inline uint32_t *nonce() { return reinterpret_cast(m_blob + 39); } inline uint32_t diff() const { return static_cast(m_diff); } - inline uint64_t target() const { return m_target; } inline uint64_t height() const { return m_height; } + inline uint64_t target() const { return m_target; } + inline uint8_t fixedByte() const { return *(m_blob + 42); } inline void reset() { m_size = 0; m_diff = 0; } inline void setClientId(const Id &id) { m_clientId = id; } inline void setPoolId(int poolId) { m_poolId = poolId; } @@ -79,6 +80,7 @@ public: # ifdef XMRIG_PROXY_PROJECT inline char *rawBlob() { return m_rawBlob; } + inline const char *rawBlob() const { return m_rawBlob; } inline const char *rawTarget() const { return m_rawTarget; } # endif diff --git a/src/common/net/strategies/FailoverStrategy.cpp b/src/common/net/strategies/FailoverStrategy.cpp index c833f6e6..1ec7449f 100644 --- a/src/common/net/strategies/FailoverStrategy.cpp +++ b/src/common/net/strategies/FailoverStrategy.cpp @@ -150,7 +150,7 @@ void xmrig::FailoverStrategy::onClose(Client *client, int failures) } -void xmrig::FailoverStrategy::onJobReceived(Client *client, const Job &job) +void xmrig::FailoverStrategy::onJobReceived(Client *client, const Job &job, const rapidjson::Value &) { if (m_active == client->id()) { m_listener->onJob(this, client, job); diff --git a/src/common/net/strategies/FailoverStrategy.h b/src/common/net/strategies/FailoverStrategy.h index d2231a30..a02b590e 100644 --- a/src/common/net/strategies/FailoverStrategy.h +++ b/src/common/net/strategies/FailoverStrategy.h @@ -61,8 +61,10 @@ public: void tick(uint64_t now) override; protected: + inline void onLogin(Client *, rapidjson::Document &, rapidjson::Value &) override {} + void onClose(Client *client, int failures) override; - void onJobReceived(Client *client, const Job &job) override; + void onJobReceived(Client *client, const Job &job, const rapidjson::Value ¶ms) override; void onLoginSuccess(Client *client) override; void onResultAccepted(Client *client, const SubmitResult &result, const char *error) override; diff --git a/src/common/net/strategies/SinglePoolStrategy.cpp b/src/common/net/strategies/SinglePoolStrategy.cpp index d17a43da..ca5d45f7 100644 --- a/src/common/net/strategies/SinglePoolStrategy.cpp +++ b/src/common/net/strategies/SinglePoolStrategy.cpp @@ -98,7 +98,7 @@ void xmrig::SinglePoolStrategy::onClose(Client *, int) } -void xmrig::SinglePoolStrategy::onJobReceived(Client *client, const Job &job) +void xmrig::SinglePoolStrategy::onJobReceived(Client *client, const Job &job, const rapidjson::Value &) { m_listener->onJob(this, client, job); } diff --git a/src/common/net/strategies/SinglePoolStrategy.h b/src/common/net/strategies/SinglePoolStrategy.h index eeb6903e..7d864263 100644 --- a/src/common/net/strategies/SinglePoolStrategy.h +++ b/src/common/net/strategies/SinglePoolStrategy.h @@ -55,8 +55,10 @@ public: void tick(uint64_t now) override; protected: + inline void onLogin(Client *, rapidjson::Document &, rapidjson::Value &) override {} + void onClose(Client *client, int failures) override; - void onJobReceived(Client *client, const Job &job) override; + void onJobReceived(Client *client, const Job &job, const rapidjson::Value ¶ms) override; void onLoginSuccess(Client *client) override; void onResultAccepted(Client *client, const SubmitResult &result, const char *error) override; diff --git a/src/crypto/CryptoNight_constants.h b/src/crypto/CryptoNight_constants.h index 58a3915f..1bc06a3b 100644 --- a/src/crypto/CryptoNight_constants.h +++ b/src/crypto/CryptoNight_constants.h @@ -215,6 +215,32 @@ template<> inline constexpr Variant cn_base_variant() { return V template<> inline constexpr Variant cn_base_variant() { return VARIANT_2; } +inline Variant cn_base_variant(Variant variant) +{ + switch (variant) { + case VARIANT_0: + case VARIANT_XHV: + case VARIANT_XAO: + return VARIANT_0; + + case VARIANT_1: + case VARIANT_TUBE: + case VARIANT_XTL: + case VARIANT_MSR: + case VARIANT_RTO: + return VARIANT_1; + + case VARIANT_GPU: + return VARIANT_GPU; + + default: + break; + } + + return VARIANT_2; +} + + template inline constexpr bool cn_is_cryptonight_r() { return false; } template<> inline constexpr bool cn_is_cryptonight_r() { return true; } template<> inline constexpr bool cn_is_cryptonight_r() { return true; } From be5d609856f1db604f8b3203b10d7c7c9f630a32 Mon Sep 17 00:00:00 2001 From: XMRig Date: Fri, 15 Mar 2019 01:06:10 +0700 Subject: [PATCH 004/116] Client refactoring. --- src/api/NetworkState.cpp | 18 ++++++----- src/api/NetworkState.h | 2 +- src/base/kernel/Process.cpp | 3 ++ src/common/net/Client.cpp | 59 +++++++++++++++++++++---------------- src/common/net/Client.h | 34 ++++++++++++++------- src/net/Network.cpp | 3 +- 6 files changed, 72 insertions(+), 47 deletions(-) diff --git a/src/api/NetworkState.cpp b/src/api/NetworkState.cpp index 0d60cbd2..6ccc0d0f 100644 --- a/src/api/NetworkState.cpp +++ b/src/api/NetworkState.cpp @@ -5,7 +5,8 @@ * Copyright 2014-2016 Wolf9466 * Copyright 2016 Jay D Dee * Copyright 2017-2018 XMR-Stak , - * Copyright 2016-2018 XMRig , + * Copyright 2018-2019 SChernykh + * Copyright 2016-2019 XMRig , * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -29,6 +30,7 @@ #include "api/NetworkState.h" +#include "base/tools/Chrono.h" #include "common/net/SubmitResult.h" @@ -44,12 +46,6 @@ xmrig::NetworkState::NetworkState() : } -int xmrig::NetworkState::connectionTime() const -{ - return m_active ? (int)((uv_now(uv_default_loop()) - m_connectionTime) / 1000) : 0; -} - - uint32_t xmrig::NetworkState::avgTime() const { if (m_latency.empty()) { @@ -74,6 +70,12 @@ uint32_t xmrig::NetworkState::latency() const } +uint64_t xmrig::NetworkState::connectionTime() const +{ + return m_active ? ((Chrono::steadyMSecs() - m_connectionTime) / 1000) : 0; +} + + void xmrig::NetworkState::add(const SubmitResult &result, const char *error) { if (error) { @@ -99,7 +101,7 @@ void xmrig::NetworkState::setPool(const char *host, int port, const char *ip) snprintf(pool, sizeof(pool) - 1, "%s:%d", host, port); m_active = true; - m_connectionTime = uv_now(uv_default_loop()); + m_connectionTime = Chrono::steadyMSecs(); } diff --git a/src/api/NetworkState.h b/src/api/NetworkState.h index c45761fb..2f88d9b3 100644 --- a/src/api/NetworkState.h +++ b/src/api/NetworkState.h @@ -41,9 +41,9 @@ class NetworkState public: NetworkState(); - int connectionTime() const; uint32_t avgTime() const; uint32_t latency() const; + uint64_t connectionTime() const; void add(const SubmitResult &result, const char *error); void setPool(const char *host, int port, const char *ip); void stop(); diff --git a/src/base/kernel/Process.cpp b/src/base/kernel/Process.cpp index 0bc40e2d..7feec481 100644 --- a/src/base/kernel/Process.cpp +++ b/src/base/kernel/Process.cpp @@ -28,6 +28,7 @@ #include "base/kernel/Process.h" +#include "version.h" static size_t location(xmrig::Process::Location location, char *buf, size_t max) @@ -51,6 +52,8 @@ xmrig::Process::Process(int argc, char **argv) : m_arguments(argc, argv) { srand(static_cast(static_cast(time(nullptr)) ^ reinterpret_cast(this))); + + uv_set_process_title(APP_DESC " " APP_VERSION); } diff --git a/src/common/net/Client.cpp b/src/common/net/Client.cpp index c0810927..59ad69b0 100644 --- a/src/common/net/Client.cpp +++ b/src/common/net/Client.cpp @@ -37,6 +37,7 @@ #endif +#include "base/tools/Chrono.h" #include "common/interfaces/IClientListener.h" #include "common/log/Log.h" #include "common/net/Client.h" @@ -72,12 +73,11 @@ static const char *states[] = { xmrig::Client::Client(int id, const char *agent, IClientListener *listener) : + m_enabled(true), m_ipv6(false), - m_nicehash(false), m_quiet(false), m_agent(agent), m_listener(listener), - m_extensions(0), m_id(id), m_retries(5), m_retryPause(5000), @@ -252,7 +252,7 @@ int64_t xmrig::Client::submit(const JobResult &result) params.AddMember("nonce", StringRef(nonce), allocator); params.AddMember("result", StringRef(data), allocator); - if ((m_extensions & AlgoExt) && result.algorithm.isValid()) { + if (has() && result.algorithm.isValid()) { params.AddMember("algo", StringRef(result.algorithm.shortName()), allocator); } @@ -327,7 +327,7 @@ bool xmrig::Client::parseJob(const rapidjson::Value ¶ms, int *code) return false; } - Job job(m_id, m_nicehash, m_pool.algorithm(), m_rpcId); + Job job(m_id, has(), m_pool.algorithm(), m_rpcId); if (!job.setId(params["job_id"].GetString())) { *code = 3; @@ -402,11 +402,7 @@ bool xmrig::Client::parseLogin(const rapidjson::Value &result, int *code) return false; } - m_nicehash = m_pool.isNicehash(); - - if (result.HasMember("extensions")) { - parseExtensions(result["extensions"]); - } + parseExtensions(result); const bool rc = parseJob(result["job"], code); m_jobs = 0; @@ -547,7 +543,7 @@ int64_t xmrig::Client::send(size_t size) } } - m_expire = uv_now(uv_default_loop()) + kResponseTimeout; + m_expire = Chrono::steadyMSecs() + kResponseTimeout; return m_sequence++; } @@ -597,7 +593,7 @@ void xmrig::Client::handshake() { # ifndef XMRIG_NO_TLS if (isTLS()) { - m_expire = uv_now(uv_default_loop()) + kResponseTimeout; + m_expire = Chrono::steadyMSecs() + kResponseTimeout; m_tls->handshake(); } @@ -709,28 +705,37 @@ void xmrig::Client::parse(char *line, size_t len) } -void xmrig::Client::parseExtensions(const rapidjson::Value &value) +void xmrig::Client::parseExtensions(const rapidjson::Value &result) { - m_extensions = 0; + m_extensions.reset(); - if (!value.IsArray()) { + if (!result.HasMember("extensions")) { return; } - for (const rapidjson::Value &ext : value.GetArray()) { + const rapidjson::Value &extensions = result["extensions"]; + if (!extensions.IsArray()) { + return; + } + + for (const rapidjson::Value &ext : extensions.GetArray()) { if (!ext.IsString()) { continue; } - if (strcmp(ext.GetString(), "algo") == 0) { - m_extensions |= AlgoExt; - continue; - } + const char *name = ext.GetString(); - if (strcmp(ext.GetString(), "nicehash") == 0) { - m_extensions |= NicehashExt; - m_nicehash = true; - continue; + if (strcmp(name, "algo") == 0) { + setExtension(EXT_ALGO, true); + } + else if (strcmp(name, "nicehash") == 0) { + setExtension(EXT_NICEHASH, true); + } + else if (strcmp(name, "connect") == 0) { + setExtension(EXT_CONNECT, true); + } + else if (strcmp(name, "keepalive") == 0) { + setExtension(EXT_KEEPALIVE, true); } } } @@ -868,7 +873,7 @@ void xmrig::Client::reconnect() m_failures++; m_listener->onClose(this, (int) m_failures); - m_expire = uv_now(uv_default_loop()) + m_retryPause; + m_expire = Chrono::steadyMSecs() + m_retryPause; } @@ -888,8 +893,10 @@ void xmrig::Client::startTimeout() { m_expire = 0; - if (m_pool.keepAlive()) { - m_keepAlive = uv_now(uv_default_loop()) + (m_pool.keepAlive() * 1000); + if (has()) { + const uint64_t ms = static_cast(m_pool.keepAlive() > 0 ? m_pool.keepAlive() : Pool::kKeepAliveTimeout) * 1000; + + m_keepAlive = Chrono::steadyMSecs() + ms; } } diff --git a/src/common/net/Client.h b/src/common/net/Client.h index 9314739a..c4639519 100644 --- a/src/common/net/Client.h +++ b/src/common/net/Client.h @@ -26,6 +26,7 @@ #define XMRIG_CLIENT_H +#include #include #include #include @@ -61,6 +62,14 @@ public: ClosingState }; + enum Extension { + EXT_ALGO, + EXT_NICEHASH, + EXT_CONNECT, + EXT_KEEPALIVE, + EXT_MAX + }; + constexpr static int kResponseTimeout = 20 * 1000; # ifndef XMRIG_NO_TLS @@ -82,6 +91,7 @@ public: void setPool(const Pool &pool); void tick(uint64_t now); + inline bool isEnabled() const { return m_enabled; } inline bool isReady() const { return m_state == ConnectedState && m_failures == 0; } inline const char *host() const { return m_pool.host(); } inline const char *ip() const { return m_ip; } @@ -90,19 +100,16 @@ public: inline SocketState state() const { return m_state; } inline uint16_t port() const { return m_pool.port(); } inline void setAlgo(const Algorithm &algo) { m_pool.setAlgo(algo); } + inline void setEnabled(bool enabled) { m_enabled = enabled; } inline void setQuiet(bool quiet) { m_quiet = quiet; } inline void setRetries(int retries) { m_retries = retries; } inline void setRetryPause(int ms) { m_retryPause = ms; } + template inline bool has() const noexcept { return m_extensions.test(ext); } + private: class Tls; - - enum Extensions { - NicehashExt = 1, - AlgoExt = 2 - }; - bool close(); bool isCriticalError(const char *message); bool isTLS() const; @@ -119,7 +126,7 @@ private: void login(); void onClose(); void parse(char *line, size_t len); - void parseExtensions(const rapidjson::Value &value); + void parseExtensions(const rapidjson::Value &result); void parseNotification(const char *method, const rapidjson::Value ¶ms, const rapidjson::Value &error); void parseResponse(int64_t id, const rapidjson::Value &result, const rapidjson::Value &error); void ping(); @@ -128,7 +135,8 @@ private: void setState(SocketState state); void startTimeout(); - inline bool isQuiet() const { return m_quiet || m_failures >= m_retries; } + inline bool isQuiet() const { return m_quiet || m_failures >= m_retries; } + inline void setExtension(Extension ext, bool enable) noexcept { m_extensions.set(ext, enable); } static void onAllocBuffer(uv_handle_t *handle, size_t suggested_size, uv_buf_t *buf); static void onClose(uv_handle_t *handle); @@ -139,15 +147,15 @@ private: static inline Client *getClient(void *data) { return m_storage.get(data); } addrinfo m_hints; + bool m_enabled; bool m_ipv6; - bool m_nicehash; bool m_quiet; char m_buf[kInputBufferSize]; char m_ip[46]; char m_sendBuf[2048]; const char *m_agent; IClientListener *m_listener; - int m_extensions; + Id m_rpcId; int m_id; int m_retries; int m_retryPause; @@ -156,6 +164,7 @@ private: Pool m_pool; size_t m_recvBufPos; SocketState m_state; + std::bitset m_extensions; std::map m_results; Tls *m_tls; uint64_t m_expire; @@ -166,13 +175,16 @@ private: uv_getaddrinfo_t m_resolver; uv_stream_t *m_stream; uv_tcp_t *m_socket; - Id m_rpcId; static int64_t m_sequence; static Storage m_storage; }; +template<> inline bool Client::has() const noexcept { return m_extensions.test(EXT_NICEHASH) || m_pool.isNicehash(); } +template<> inline bool Client::has() const noexcept { return m_extensions.test(EXT_KEEPALIVE) || m_pool.keepAlive() > 0; } + + } /* namespace xmrig */ diff --git a/src/net/Network.cpp b/src/net/Network.cpp index 34714c8a..6822ad32 100644 --- a/src/net/Network.cpp +++ b/src/net/Network.cpp @@ -32,6 +32,7 @@ #include "api/Api.h" +#include "base/tools/Chrono.h" #include "common/log/Log.h" #include "common/net/Client.h" #include "common/net/SubmitResult.h" @@ -204,7 +205,7 @@ void xmrig::Network::setJob(Client *client, const Job &job, bool donate) void xmrig::Network::tick() { - const uint64_t now = uv_now(uv_default_loop()); + const uint64_t now = Chrono::steadyMSecs(); m_strategy->tick(now); From ba01f2a9c4cf0acd8cc4c868d616d2782bb8d126 Mon Sep 17 00:00:00 2001 From: XMRig Date: Fri, 15 Mar 2019 01:50:35 +0700 Subject: [PATCH 005/116] Rename files. --- CMakeLists.txt | 42 +++++++++---------- cmake/OpenSSL.cmake | 2 +- src/Summary.cpp | 2 +- src/api/ApiRouter.cpp | 2 +- src/api/NetworkState.cpp | 2 +- .../kernel}/interfaces/IClientListener.h | 0 .../kernel}/interfaces/IStrategy.h | 0 .../kernel}/interfaces/IStrategyListener.h | 0 .../net => base/net/stratum}/Client.cpp | 6 +-- src/{common/net => base/net/stratum}/Client.h | 10 ++--- src/{common/net => base/net/stratum}/Id.h | 0 src/{common/net => base/net/stratum}/Job.cpp | 2 +- src/{common/net => base/net/stratum}/Job.h | 2 +- src/base/net/{ => stratum}/Pool.cpp | 2 +- src/base/net/{ => stratum}/Pool.h | 0 src/base/net/{ => stratum}/Pools.cpp | 6 +-- src/base/net/{ => stratum}/Pools.h | 2 +- .../net => base/net/stratum}/SubmitResult.cpp | 2 +- .../net => base/net/stratum}/SubmitResult.h | 0 src/{common/net => base/net/stratum}/Tls.cpp | 4 +- src/{common/net => base/net/stratum}/Tls.h | 2 +- .../stratum}/strategies/FailoverStrategy.cpp | 6 +-- .../stratum}/strategies/FailoverStrategy.h | 6 +-- .../strategies/SinglePoolStrategy.cpp | 6 +-- .../stratum}/strategies/SinglePoolStrategy.h | 4 +- src/{common/net => base/net/tools}/Storage.h | 34 ++++++++------- src/common/config/CommonConfig.h | 2 +- src/net/JobResult.h | 2 +- src/net/Network.cpp | 4 +- src/net/Network.h | 2 +- src/net/strategies/DonateStrategy.cpp | 9 ++-- src/net/strategies/DonateStrategy.h | 8 ++-- src/workers/MultiWorker.h | 2 +- src/workers/Workers.h | 2 +- 34 files changed, 88 insertions(+), 87 deletions(-) rename src/{common => base/kernel}/interfaces/IClientListener.h (100%) rename src/{common => base/kernel}/interfaces/IStrategy.h (100%) rename src/{common => base/kernel}/interfaces/IStrategyListener.h (100%) rename src/{common/net => base/net/stratum}/Client.cpp (99%) rename src/{common/net => base/net/stratum}/Client.h (97%) rename src/{common/net => base/net/stratum}/Id.h (100%) rename src/{common/net => base/net/stratum}/Job.cpp (99%) rename src/{common/net => base/net/stratum}/Job.h (99%) rename src/base/net/{ => stratum}/Pool.cpp (99%) rename src/base/net/{ => stratum}/Pool.h (100%) rename src/base/net/{ => stratum}/Pools.cpp (97%) rename src/base/net/{ => stratum}/Pools.h (98%) rename src/{common/net => base/net/stratum}/SubmitResult.cpp (97%) rename src/{common/net => base/net/stratum}/SubmitResult.h (100%) rename src/{common/net => base/net/stratum}/Tls.cpp (98%) rename src/{common/net => base/net/stratum}/Tls.h (98%) rename src/{common/net => base/net/stratum}/strategies/FailoverStrategy.cpp (96%) rename src/{common/net => base/net/stratum}/strategies/FailoverStrategy.h (95%) rename src/{common/net => base/net/stratum}/strategies/SinglePoolStrategy.cpp (95%) rename src/{common/net => base/net/stratum}/strategies/SinglePoolStrategy.h (96%) rename src/{common/net => base/net/tools}/Storage.h (70%) diff --git a/CMakeLists.txt b/CMakeLists.txt index 94bf61b6..188f595c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -23,14 +23,24 @@ set(HEADERS src/App.h src/base/io/Json.h src/base/io/Watcher.h + src/base/kernel/Entry.h + src/base/kernel/interfaces/IClientListener.h src/base/kernel/interfaces/IConfigListener.h src/base/kernel/interfaces/ISignalListener.h + src/base/kernel/interfaces/IStrategy.h + src/base/kernel/interfaces/IStrategyListener.h src/base/kernel/interfaces/IWatcherListener.h - src/base/kernel/Entry.h src/base/kernel/Process.h src/base/kernel/Signals.h - src/base/net/Pool.h - src/base/net/Pools.h + src/base/net/stratum/Client.h + src/base/net/stratum/Id.h + src/base/net/stratum/Job.h + src/base/net/stratum/Pool.h + src/base/net/stratum/Pools.h + src/base/net/stratum/strategies/FailoverStrategy.h + src/base/net/stratum/strategies/SinglePoolStrategy.h + src/base/net/stratum/SubmitResult.h + src/base/net/tools/Storage.h src/base/tools/Arguments.h src/base/tools/Chrono.h src/base/tools/Handle.h @@ -42,32 +52,22 @@ set(HEADERS src/common/cpu/Cpu.h src/common/crypto/Algorithm.h src/common/crypto/keccak.h - src/common/interfaces/IClientListener.h src/common/interfaces/IConfig.h src/common/interfaces/IConfigCreator.h src/common/interfaces/IConsoleListener.h src/common/interfaces/IControllerListener.h src/common/interfaces/ICpuInfo.h src/common/interfaces/ILogBackend.h - src/common/interfaces/IStrategy.h - src/common/interfaces/IStrategyListener.h src/common/log/BasicLog.h src/common/log/ConsoleLog.h src/common/log/FileLog.h src/common/log/Log.h - src/common/net/Client.h - src/common/net/Id.h - src/common/net/Job.h - src/common/net/Storage.h - src/common/net/strategies/FailoverStrategy.h - src/common/net/strategies/SinglePoolStrategy.h - src/common/net/SubmitResult.h src/common/Platform.h src/common/utils/c_str.h src/common/utils/mm_malloc.h src/common/xmrig.h - src/core/ConfigLoader_platform.h src/core/ConfigLoader_default.h + src/core/ConfigLoader_platform.h src/core/Controller.h src/interfaces/IJobResultListener.h src/interfaces/IThread.h @@ -116,8 +116,13 @@ set(SOURCES src/base/kernel/Entry.cpp src/base/kernel/Process.cpp src/base/kernel/Signals.cpp - src/base/net/Pool.cpp - src/base/net/Pools.cpp + src/base/net/stratum/Client.cpp + src/base/net/stratum/Job.cpp + src/base/net/stratum/Pool.cpp + src/base/net/stratum/Pools.cpp + src/base/net/stratum/strategies/FailoverStrategy.cpp + src/base/net/stratum/strategies/SinglePoolStrategy.cpp + src/base/net/stratum/SubmitResult.cpp src/base/tools/Arguments.cpp src/base/tools/Handle.cpp src/base/tools/String.cpp @@ -131,11 +136,6 @@ set(SOURCES src/common/log/ConsoleLog.cpp src/common/log/FileLog.cpp src/common/log/Log.cpp - src/common/net/Client.cpp - src/common/net/Job.cpp - src/common/net/strategies/FailoverStrategy.cpp - src/common/net/strategies/SinglePoolStrategy.cpp - src/common/net/SubmitResult.cpp src/common/Platform.cpp src/core/Config.cpp src/core/Controller.cpp diff --git a/cmake/OpenSSL.cmake b/cmake/OpenSSL.cmake index 79731d6f..5761f99f 100644 --- a/cmake/OpenSSL.cmake +++ b/cmake/OpenSSL.cmake @@ -11,7 +11,7 @@ if (WITH_TLS) find_package(OpenSSL) if (OPENSSL_FOUND) - set(TLS_SOURCES src/common/net/Tls.h src/common/net/Tls.cpp) + set(TLS_SOURCES src/base/net/stratum/Tls.h src/base/net/stratum/Tls.cpp) include_directories(${OPENSSL_INCLUDE_DIR}) else() message(FATAL_ERROR "OpenSSL NOT found: use `-DWITH_TLS=OFF` to build without TLS support") diff --git a/src/Summary.cpp b/src/Summary.cpp index 60a9278f..7a52d1b1 100644 --- a/src/Summary.cpp +++ b/src/Summary.cpp @@ -28,7 +28,7 @@ #include -#include "base/net/Pool.h" +#include "base/net/stratum/Pool.h" #include "common/cpu/Cpu.h" #include "common/log/Log.h" #include "core/Config.h" diff --git a/src/api/ApiRouter.cpp b/src/api/ApiRouter.cpp index bdedac4d..ff99c047 100644 --- a/src/api/ApiRouter.cpp +++ b/src/api/ApiRouter.cpp @@ -34,11 +34,11 @@ #include "api/ApiRouter.h" +#include "base/net/stratum/Job.h" #include "common/api/HttpReply.h" #include "common/api/HttpRequest.h" #include "common/cpu/Cpu.h" #include "common/crypto/keccak.h" -#include "common/net/Job.h" #include "common/Platform.h" #include "core/Config.h" #include "core/Controller.h" diff --git a/src/api/NetworkState.cpp b/src/api/NetworkState.cpp index 6ccc0d0f..8a541eaa 100644 --- a/src/api/NetworkState.cpp +++ b/src/api/NetworkState.cpp @@ -30,8 +30,8 @@ #include "api/NetworkState.h" +#include "base/net/stratum/SubmitResult.h" #include "base/tools/Chrono.h" -#include "common/net/SubmitResult.h" xmrig::NetworkState::NetworkState() : diff --git a/src/common/interfaces/IClientListener.h b/src/base/kernel/interfaces/IClientListener.h similarity index 100% rename from src/common/interfaces/IClientListener.h rename to src/base/kernel/interfaces/IClientListener.h diff --git a/src/common/interfaces/IStrategy.h b/src/base/kernel/interfaces/IStrategy.h similarity index 100% rename from src/common/interfaces/IStrategy.h rename to src/base/kernel/interfaces/IStrategy.h diff --git a/src/common/interfaces/IStrategyListener.h b/src/base/kernel/interfaces/IStrategyListener.h similarity index 100% rename from src/common/interfaces/IStrategyListener.h rename to src/base/kernel/interfaces/IStrategyListener.h diff --git a/src/common/net/Client.cpp b/src/base/net/stratum/Client.cpp similarity index 99% rename from src/common/net/Client.cpp rename to src/base/net/stratum/Client.cpp index 59ad69b0..1dfbc7fd 100644 --- a/src/common/net/Client.cpp +++ b/src/base/net/stratum/Client.cpp @@ -33,14 +33,14 @@ #ifndef XMRIG_NO_TLS # include # include -# include "common/net/Tls.h" +# include "base/net/stratum/Tls.h" #endif +#include "base/kernel/interfaces/IClientListener.h" +#include "base/net/stratum/Client.h" #include "base/tools/Chrono.h" -#include "common/interfaces/IClientListener.h" #include "common/log/Log.h" -#include "common/net/Client.h" #include "net/JobResult.h" #include "rapidjson/document.h" #include "rapidjson/error/en.h" diff --git a/src/common/net/Client.h b/src/base/net/stratum/Client.h similarity index 97% rename from src/common/net/Client.h rename to src/base/net/stratum/Client.h index c4639519..977a3681 100644 --- a/src/common/net/Client.h +++ b/src/base/net/stratum/Client.h @@ -32,12 +32,12 @@ #include -#include "base/net/Pool.h" +#include "base/net/stratum/Id.h" +#include "base/net/stratum/Job.h" +#include "base/net/stratum/Pool.h" +#include "base/net/stratum/SubmitResult.h" +#include "base/net/tools/Storage.h" #include "common/crypto/Algorithm.h" -#include "common/net/Id.h" -#include "common/net/Job.h" -#include "common/net/Storage.h" -#include "common/net/SubmitResult.h" #include "rapidjson/fwd.h" diff --git a/src/common/net/Id.h b/src/base/net/stratum/Id.h similarity index 100% rename from src/common/net/Id.h rename to src/base/net/stratum/Id.h diff --git a/src/common/net/Job.cpp b/src/base/net/stratum/Job.cpp similarity index 99% rename from src/common/net/Job.cpp rename to src/base/net/stratum/Job.cpp index 851507ad..3fb691ce 100644 --- a/src/common/net/Job.cpp +++ b/src/base/net/stratum/Job.cpp @@ -28,7 +28,7 @@ #include -#include "common/net/Job.h" +#include "base/net/stratum/Job.h" unsigned char hf_hex2bin(char c, bool &err) diff --git a/src/common/net/Job.h b/src/base/net/stratum/Job.h similarity index 99% rename from src/common/net/Job.h rename to src/base/net/stratum/Job.h index a6e1ec25..426a64de 100644 --- a/src/common/net/Job.h +++ b/src/base/net/stratum/Job.h @@ -32,7 +32,7 @@ #include "common/crypto/Algorithm.h" -#include "common/net/Id.h" +#include "base/net/stratum/Id.h" namespace xmrig { diff --git a/src/base/net/Pool.cpp b/src/base/net/stratum/Pool.cpp similarity index 99% rename from src/base/net/Pool.cpp rename to src/base/net/stratum/Pool.cpp index de02be92..f371b4c0 100644 --- a/src/base/net/Pool.cpp +++ b/src/base/net/stratum/Pool.cpp @@ -30,7 +30,7 @@ #include "base/io/Json.h" -#include "base/net/Pool.h" +#include "base/net/stratum/Pool.h" #include "rapidjson/document.h" diff --git a/src/base/net/Pool.h b/src/base/net/stratum/Pool.h similarity index 100% rename from src/base/net/Pool.h rename to src/base/net/stratum/Pool.h diff --git a/src/base/net/Pools.cpp b/src/base/net/stratum/Pools.cpp similarity index 97% rename from src/base/net/Pools.cpp rename to src/base/net/stratum/Pools.cpp index e3b86aca..ba55e94b 100644 --- a/src/base/net/Pools.cpp +++ b/src/base/net/stratum/Pools.cpp @@ -23,10 +23,10 @@ */ -#include "base/net/Pools.h" +#include "base/net/stratum/Pools.h" +#include "base/net/stratum/strategies/FailoverStrategy.h" +#include "base/net/stratum/strategies/SinglePoolStrategy.h" #include "common/log/Log.h" -#include "common/net/strategies/FailoverStrategy.h" -#include "common/net/strategies/SinglePoolStrategy.h" #include "rapidjson/document.h" diff --git a/src/base/net/Pools.h b/src/base/net/stratum/Pools.h similarity index 98% rename from src/base/net/Pools.h rename to src/base/net/stratum/Pools.h index a6038a04..0f856c69 100644 --- a/src/base/net/Pools.h +++ b/src/base/net/stratum/Pools.h @@ -29,7 +29,7 @@ #include -#include "base/net/Pool.h" +#include "base/net/stratum/Pool.h" namespace xmrig { diff --git a/src/common/net/SubmitResult.cpp b/src/base/net/stratum/SubmitResult.cpp similarity index 97% rename from src/common/net/SubmitResult.cpp rename to src/base/net/stratum/SubmitResult.cpp index d14bbb40..ad8a48af 100644 --- a/src/common/net/SubmitResult.cpp +++ b/src/base/net/stratum/SubmitResult.cpp @@ -26,7 +26,7 @@ #include -#include "common/net/SubmitResult.h" +#include "base/net/stratum/SubmitResult.h" xmrig::SubmitResult::SubmitResult(int64_t seq, uint32_t diff, uint64_t actualDiff, int64_t reqId) : diff --git a/src/common/net/SubmitResult.h b/src/base/net/stratum/SubmitResult.h similarity index 100% rename from src/common/net/SubmitResult.h rename to src/base/net/stratum/SubmitResult.h diff --git a/src/common/net/Tls.cpp b/src/base/net/stratum/Tls.cpp similarity index 98% rename from src/common/net/Tls.cpp rename to src/base/net/stratum/Tls.cpp index a9b3fa7d..04aeae92 100644 --- a/src/common/net/Tls.cpp +++ b/src/base/net/stratum/Tls.cpp @@ -27,8 +27,8 @@ #include -#include "common/net/Client.h" -#include "common/net/Tls.h" +#include "base/net/stratum/Client.h" +#include "base/net/stratum/Tls.h" #include "common/log/Log.h" diff --git a/src/common/net/Tls.h b/src/base/net/stratum/Tls.h similarity index 98% rename from src/common/net/Tls.h rename to src/base/net/stratum/Tls.h index cce78eeb..e070be52 100644 --- a/src/common/net/Tls.h +++ b/src/base/net/stratum/Tls.h @@ -29,7 +29,7 @@ #include -#include "common/net/Client.h" +#include "base/net/stratum/Client.h" namespace xmrig { diff --git a/src/common/net/strategies/FailoverStrategy.cpp b/src/base/net/stratum/strategies/FailoverStrategy.cpp similarity index 96% rename from src/common/net/strategies/FailoverStrategy.cpp rename to src/base/net/stratum/strategies/FailoverStrategy.cpp index 1ec7449f..d2e4a6da 100644 --- a/src/common/net/strategies/FailoverStrategy.cpp +++ b/src/base/net/stratum/strategies/FailoverStrategy.cpp @@ -23,9 +23,9 @@ */ -#include "common/interfaces/IStrategyListener.h" -#include "common/net/Client.h" -#include "common/net/strategies/FailoverStrategy.h" +#include "base/kernel/interfaces/IStrategyListener.h" +#include "base/net/stratum/Client.h" +#include "base/net/stratum/strategies/FailoverStrategy.h" #include "common/Platform.h" diff --git a/src/common/net/strategies/FailoverStrategy.h b/src/base/net/stratum/strategies/FailoverStrategy.h similarity index 95% rename from src/common/net/strategies/FailoverStrategy.h rename to src/base/net/stratum/strategies/FailoverStrategy.h index a02b590e..3517de9d 100644 --- a/src/common/net/strategies/FailoverStrategy.h +++ b/src/base/net/stratum/strategies/FailoverStrategy.h @@ -29,9 +29,9 @@ #include -#include "base/net/Pool.h" -#include "common/interfaces/IClientListener.h" -#include "common/interfaces/IStrategy.h" +#include "base/kernel/interfaces/IClientListener.h" +#include "base/kernel/interfaces/IStrategy.h" +#include "base/net/stratum/Pool.h" namespace xmrig { diff --git a/src/common/net/strategies/SinglePoolStrategy.cpp b/src/base/net/stratum/strategies/SinglePoolStrategy.cpp similarity index 95% rename from src/common/net/strategies/SinglePoolStrategy.cpp rename to src/base/net/stratum/strategies/SinglePoolStrategy.cpp index ca5d45f7..b81594e1 100644 --- a/src/common/net/strategies/SinglePoolStrategy.cpp +++ b/src/base/net/stratum/strategies/SinglePoolStrategy.cpp @@ -23,9 +23,9 @@ */ -#include "common/interfaces/IStrategyListener.h" -#include "common/net/Client.h" -#include "common/net/strategies/SinglePoolStrategy.h" +#include "base/kernel/interfaces/IStrategyListener.h" +#include "base/net/stratum/Client.h" +#include "base/net/stratum/strategies/SinglePoolStrategy.h" #include "common/Platform.h" diff --git a/src/common/net/strategies/SinglePoolStrategy.h b/src/base/net/stratum/strategies/SinglePoolStrategy.h similarity index 96% rename from src/common/net/strategies/SinglePoolStrategy.h rename to src/base/net/stratum/strategies/SinglePoolStrategy.h index 7d864263..5b3016c1 100644 --- a/src/common/net/strategies/SinglePoolStrategy.h +++ b/src/base/net/stratum/strategies/SinglePoolStrategy.h @@ -26,8 +26,8 @@ #define XMRIG_SINGLEPOOLSTRATEGY_H -#include "common/interfaces/IClientListener.h" -#include "common/interfaces/IStrategy.h" +#include "base/kernel/interfaces/IClientListener.h" +#include "base/kernel/interfaces/IStrategy.h" namespace xmrig { diff --git a/src/common/net/Storage.h b/src/base/net/tools/Storage.h similarity index 70% rename from src/common/net/Storage.h rename to src/base/net/tools/Storage.h index f36ce594..aff62481 100644 --- a/src/common/net/Storage.h +++ b/src/base/net/tools/Storage.h @@ -5,7 +5,8 @@ * Copyright 2014-2016 Wolf9466 * Copyright 2016 Jay D Dee * Copyright 2017-2018 XMR-Stak , - * Copyright 2016-2018 XMRig , + * Copyright 2018-2019 SChernykh + * Copyright 2016-2019 XMRig , * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -21,8 +22,8 @@ * along with this program. If not, see . */ -#ifndef __STORAGE_H__ -#define __STORAGE_H__ +#ifndef XMRIG_STORAGE_H +#define XMRIG_STORAGE_H #include @@ -53,11 +54,10 @@ public: inline static void *ptr(uintptr_t id) { return reinterpret_cast(id); } - inline TYPE *get(void *id) const { return get(reinterpret_cast(id)); } + inline TYPE *get(const void *id) const { return get(reinterpret_cast(id)); } inline TYPE *get(uintptr_t id) const { assert(m_data.count(id) > 0); - if (m_data.count(id) == 0) { return nullptr; } @@ -66,20 +66,22 @@ public: } - inline void remove(void *id) { remove(reinterpret_cast(id)); } - inline void remove(uintptr_t id) + inline void remove(const void *id) { delete release(reinterpret_cast(id)); } + inline void remove(uintptr_t id) { delete release(id); } + + + inline TYPE *release(const void *id) { release(reinterpret_cast(id)); } + inline TYPE *release(uintptr_t id) { TYPE *obj = get(id); - if (obj == nullptr) { - return; + if (obj != nullptr) { + auto it = m_data.find(id); + if (it != m_data.end()) { + m_data.erase(it); + } } - auto it = m_data.find(id); - if (it != m_data.end()) { - m_data.erase(it); - } - - delete obj; + return obj; } @@ -92,4 +94,4 @@ private: } /* namespace xmrig */ -#endif /* __STORAGE_H__ */ +#endif /* XMRIG_STORAGE_H */ diff --git a/src/common/config/CommonConfig.h b/src/common/config/CommonConfig.h index 103e69d2..729c2451 100644 --- a/src/common/config/CommonConfig.h +++ b/src/common/config/CommonConfig.h @@ -26,7 +26,7 @@ #define XMRIG_COMMONCONFIG_H -#include "base/net/Pools.h" +#include "base/net/stratum/Pools.h" #include "base/tools/String.h" #include "common/interfaces/IConfig.h" #include "common/xmrig.h" diff --git a/src/net/JobResult.h b/src/net/JobResult.h index 5ab4d294..2e5b0868 100644 --- a/src/net/JobResult.h +++ b/src/net/JobResult.h @@ -31,7 +31,7 @@ #include -#include "common/net/Job.h" +#include "base/net/stratum/Job.h" namespace xmrig { diff --git a/src/net/Network.cpp b/src/net/Network.cpp index 6822ad32..b8f4f05e 100644 --- a/src/net/Network.cpp +++ b/src/net/Network.cpp @@ -32,10 +32,10 @@ #include "api/Api.h" +#include "base/net/stratum/Client.h" +#include "base/net/stratum/SubmitResult.h" #include "base/tools/Chrono.h" #include "common/log/Log.h" -#include "common/net/Client.h" -#include "common/net/SubmitResult.h" #include "core/Config.h" #include "core/Controller.h" #include "net/Network.h" diff --git a/src/net/Network.h b/src/net/Network.h index 5a5cbc3e..8796045a 100644 --- a/src/net/Network.h +++ b/src/net/Network.h @@ -31,8 +31,8 @@ #include "api/NetworkState.h" +#include "base/kernel/interfaces/IStrategyListener.h" #include "common/interfaces/IControllerListener.h" -#include "common/interfaces/IStrategyListener.h" #include "interfaces/IJobResultListener.h" diff --git a/src/net/strategies/DonateStrategy.cpp b/src/net/strategies/DonateStrategy.cpp index 9593dc9a..f056d498 100644 --- a/src/net/strategies/DonateStrategy.cpp +++ b/src/net/strategies/DonateStrategy.cpp @@ -23,12 +23,11 @@ */ +#include "base/net/stratum/Client.h" +#include "base/net/stratum/Job.h" +#include "base/net/stratum/strategies/FailoverStrategy.h" +#include "base/net/stratum/strategies/SinglePoolStrategy.h" #include "common/crypto/keccak.h" -#include "common/interfaces/IStrategyListener.h" -#include "common/net/Client.h" -#include "common/net/Job.h" -#include "common/net/strategies/FailoverStrategy.h" -#include "common/net/strategies/SinglePoolStrategy.h" #include "common/Platform.h" #include "common/xmrig.h" #include "net/strategies/DonateStrategy.h" diff --git a/src/net/strategies/DonateStrategy.h b/src/net/strategies/DonateStrategy.h index 76702ef3..8c350097 100644 --- a/src/net/strategies/DonateStrategy.h +++ b/src/net/strategies/DonateStrategy.h @@ -30,10 +30,10 @@ #include -#include "base/net/Pool.h" -#include "common/interfaces/IClientListener.h" -#include "common/interfaces/IStrategy.h" -#include "common/interfaces/IStrategyListener.h" +#include "base/kernel/interfaces/IClientListener.h" +#include "base/kernel/interfaces/IStrategy.h" +#include "base/kernel/interfaces/IStrategyListener.h" +#include "base/net/stratum/Pool.h" namespace xmrig { diff --git a/src/workers/MultiWorker.h b/src/workers/MultiWorker.h index b7e4c8ca..525eee18 100644 --- a/src/workers/MultiWorker.h +++ b/src/workers/MultiWorker.h @@ -27,7 +27,7 @@ #define XMRIG_MULTIWORKER_H -#include "common/net/Job.h" +#include "base/net/stratum/Job.h" #include "Mem.h" #include "net/JobResult.h" #include "workers/Worker.h" diff --git a/src/workers/Workers.h b/src/workers/Workers.h index a9b8e695..0760c98f 100644 --- a/src/workers/Workers.h +++ b/src/workers/Workers.h @@ -31,7 +31,7 @@ #include #include -#include "common/net/Job.h" +#include "base/net/stratum/Job.h" #include "net/JobResult.h" #include "rapidjson/fwd.h" From 8c362411efddd796aa74746605c40777a1eaa2f0 Mon Sep 17 00:00:00 2001 From: XMRig Date: Fri, 15 Mar 2019 02:03:01 +0700 Subject: [PATCH 006/116] Removed class Id. --- CMakeLists.txt | 1 - src/base/net/stratum/Client.cpp | 5 +- src/base/net/stratum/Client.h | 3 +- src/base/net/stratum/Id.h | 98 --------------------------------- src/base/net/stratum/Job.cpp | 14 ++--- src/base/net/stratum/Job.h | 20 +++---- src/net/JobResult.h | 9 +-- 7 files changed, 26 insertions(+), 124 deletions(-) delete mode 100644 src/base/net/stratum/Id.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 188f595c..f8304589 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -33,7 +33,6 @@ set(HEADERS src/base/kernel/Process.h src/base/kernel/Signals.h src/base/net/stratum/Client.h - src/base/net/stratum/Id.h src/base/net/stratum/Job.h src/base/net/stratum/Pool.h src/base/net/stratum/Pools.h diff --git a/src/base/net/stratum/Client.cpp b/src/base/net/stratum/Client.cpp index 1dfbc7fd..cffbe543 100644 --- a/src/base/net/stratum/Client.cpp +++ b/src/base/net/stratum/Client.cpp @@ -397,7 +397,8 @@ bool xmrig::Client::parseJob(const rapidjson::Value ¶ms, int *code) bool xmrig::Client::parseLogin(const rapidjson::Value &result, int *code) { - if (!m_rpcId.setId(result["id"].GetString())) { + m_rpcId = result["id"].GetString(); + if (m_rpcId.isNull()) { *code = 1; return false; } @@ -498,7 +499,7 @@ int64_t xmrig::Client::send(const rapidjson::Document &doc) { using namespace rapidjson; - StringBuffer buffer(0, 512); + StringBuffer buffer(nullptr, 512); Writer writer(buffer); doc.Accept(writer); diff --git a/src/base/net/stratum/Client.h b/src/base/net/stratum/Client.h index 977a3681..ed433ff9 100644 --- a/src/base/net/stratum/Client.h +++ b/src/base/net/stratum/Client.h @@ -32,7 +32,6 @@ #include -#include "base/net/stratum/Id.h" #include "base/net/stratum/Job.h" #include "base/net/stratum/Pool.h" #include "base/net/stratum/SubmitResult.h" @@ -155,7 +154,6 @@ private: char m_sendBuf[2048]; const char *m_agent; IClientListener *m_listener; - Id m_rpcId; int m_id; int m_retries; int m_retryPause; @@ -166,6 +164,7 @@ private: SocketState m_state; std::bitset m_extensions; std::map m_results; + String m_rpcId; Tls *m_tls; uint64_t m_expire; uint64_t m_jobs; diff --git a/src/base/net/stratum/Id.h b/src/base/net/stratum/Id.h deleted file mode 100644 index 999e7837..00000000 --- a/src/base/net/stratum/Id.h +++ /dev/null @@ -1,98 +0,0 @@ -/* XMRig - * Copyright 2010 Jeff Garzik - * Copyright 2012-2014 pooler - * Copyright 2014 Lucas Jones - * Copyright 2014-2016 Wolf9466 - * Copyright 2016 Jay D Dee - * Copyright 2017-2018 XMR-Stak , - * Copyright 2016-2019 XMRig , - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#ifndef XMRIG_ID_H -#define XMRIG_ID_H - - -#include - - -namespace xmrig { - - -class Id -{ -public: - inline Id() : - m_data() - { - } - - - inline Id(const char *id, size_t sizeFix = 0) - { - setId(id, sizeFix); - } - - - inline bool operator==(const Id &other) const - { - return memcmp(m_data, other.m_data, sizeof(m_data)) == 0; - } - - - inline bool operator!=(const Id &other) const - { - return memcmp(m_data, other.m_data, sizeof(m_data)) != 0; - } - - - Id &operator=(const Id &other) - { - memcpy(m_data, other.m_data, sizeof(m_data)); - - return *this; - } - - - inline bool setId(const char *id, size_t sizeFix = 0) - { - memset(m_data, 0, sizeof(m_data)); - if (!id) { - return false; - } - - const size_t size = strlen(id); - if (size >= sizeof(m_data)) { - return false; - } - - memcpy(m_data, id, size - sizeFix); - return true; - } - - - inline const char *data() const { return m_data; } - inline bool isValid() const { return *m_data != '\0'; } - - -private: - char m_data[64]; -}; - - -} /* namespace xmrig */ - - -#endif /* XMRIG_ID_H */ diff --git a/src/base/net/stratum/Job.cpp b/src/base/net/stratum/Job.cpp index 3fb691ce..c9902f49 100644 --- a/src/base/net/stratum/Job.cpp +++ b/src/base/net/stratum/Job.cpp @@ -65,25 +65,25 @@ xmrig::Job::Job() : m_threadId(-1), m_size(0), m_diff(0), + m_height(0), m_target(0), - m_blob(), - m_height(0) + m_blob() { } -xmrig::Job::Job(int poolId, bool nicehash, const Algorithm &algorithm, const Id &clientId) : +xmrig::Job::Job(int poolId, bool nicehash, const Algorithm &algorithm, const String &clientId) : + m_algorithm(algorithm), m_autoVariant(algorithm.variant() == VARIANT_AUTO), m_nicehash(nicehash), m_poolId(poolId), m_threadId(-1), m_size(0), + m_clientId(clientId), m_diff(0), - m_target(0), - m_blob(), m_height(0), - m_algorithm(algorithm), - m_clientId(clientId) + m_target(0), + m_blob() { } diff --git a/src/base/net/stratum/Job.h b/src/base/net/stratum/Job.h index 426a64de..878274e8 100644 --- a/src/base/net/stratum/Job.h +++ b/src/base/net/stratum/Job.h @@ -31,8 +31,8 @@ #include +#include "base/tools/String.h" #include "common/crypto/Algorithm.h" -#include "base/net/stratum/Id.h" namespace xmrig { @@ -46,7 +46,7 @@ public: static constexpr const size_t kMaxBlobSize = 128; Job(); - Job(int poolId, bool nicehash, const Algorithm &algorithm, const Id &clientId); + Job(int poolId, bool nicehash, const Algorithm &algorithm, const String &clientId); ~Job(); bool isEqual(const Job &other) const; @@ -57,10 +57,10 @@ public: inline bool isNicehash() const { return m_nicehash; } inline bool isValid() const { return m_size > 0 && m_diff > 0; } - inline bool setId(const char *id) { return m_id.setId(id); } + inline bool setId(const char *id) { return m_id = id; } inline const Algorithm &algorithm() const { return m_algorithm; } - inline const Id &clientId() const { return m_clientId; } - inline const Id &id() const { return m_id; } + inline const String &clientId() const { return m_clientId; } + inline const String &id() const { return m_id; } inline const uint32_t *nonce() const { return reinterpret_cast(m_blob + 39); } inline const uint8_t *blob() const { return m_blob; } inline int poolId() const { return m_poolId; } @@ -72,7 +72,7 @@ public: inline uint64_t target() const { return m_target; } inline uint8_t fixedByte() const { return *(m_blob + 42); } inline void reset() { m_size = 0; m_diff = 0; } - inline void setClientId(const Id &id) { m_clientId = id; } + inline void setClientId(const String &id) { m_clientId = id; } inline void setPoolId(int poolId) { m_poolId = poolId; } inline void setThreadId(int threadId) { m_threadId = threadId; } inline void setVariant(const char *variant) { m_algorithm.parseVariant(variant); } @@ -99,18 +99,18 @@ public: private: Variant variant() const; + Algorithm m_algorithm; bool m_autoVariant; bool m_nicehash; int m_poolId; int m_threadId; size_t m_size; + String m_clientId; + String m_id; uint64_t m_diff; + uint64_t m_height; uint64_t m_target; uint8_t m_blob[kMaxBlobSize]; - uint64_t m_height; - xmrig::Algorithm m_algorithm; - xmrig::Id m_clientId; - xmrig::Id m_id; # ifdef XMRIG_PROXY_PROJECT char m_rawBlob[kMaxBlobSize * 2 + 8]; diff --git a/src/net/JobResult.h b/src/net/JobResult.h index 2e5b0868..9d2300b5 100644 --- a/src/net/JobResult.h +++ b/src/net/JobResult.h @@ -31,6 +31,7 @@ #include +#include "base/tools/String.h" #include "base/net/stratum/Job.h" @@ -41,11 +42,11 @@ class JobResult { public: inline JobResult() : poolId(0), diff(0), nonce(0) {} - inline JobResult(int poolId, const Id &jobId, const Id &clientId, uint32_t nonce, const uint8_t *result, uint32_t diff, const Algorithm &algorithm) : + inline JobResult(int poolId, const String &jobId, const String &clientId, uint32_t nonce, const uint8_t *result, uint32_t diff, const Algorithm &algorithm) : algorithm(algorithm), + poolId(poolId), clientId(clientId), jobId(jobId), - poolId(poolId), diff(diff), nonce(nonce) { @@ -71,9 +72,9 @@ public: Algorithm algorithm; - Id clientId; - Id jobId; int poolId; + String clientId; + String jobId; uint32_t diff; uint32_t nonce; uint8_t result[32]; From 9808fbe3963dc1af389d2b632e4bec215aeae85a Mon Sep 17 00:00:00 2001 From: XMRig Date: Fri, 15 Mar 2019 02:25:38 +0700 Subject: [PATCH 007/116] Added class Buffer. --- CMakeLists.txt | 2 + src/api/ApiRouter.cpp | 4 +- src/base/net/stratum/Client.cpp | 5 +- src/base/net/stratum/Job.cpp | 68 +-------- src/base/net/stratum/Job.h | 6 - src/base/net/stratum/Tls.cpp | 3 +- src/base/tools/Buffer.cpp | 201 ++++++++++++++++++++++++++ src/base/tools/Buffer.h | 88 +++++++++++ src/net/strategies/DonateStrategy.cpp | 3 +- 9 files changed, 304 insertions(+), 76 deletions(-) create mode 100644 src/base/tools/Buffer.cpp create mode 100644 src/base/tools/Buffer.h diff --git a/CMakeLists.txt b/CMakeLists.txt index f8304589..81ad18f6 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -41,6 +41,7 @@ set(HEADERS src/base/net/stratum/SubmitResult.h src/base/net/tools/Storage.h src/base/tools/Arguments.h + src/base/tools/Buffer.h src/base/tools/Chrono.h src/base/tools/Handle.h src/base/tools/String.h @@ -123,6 +124,7 @@ set(SOURCES src/base/net/stratum/strategies/SinglePoolStrategy.cpp src/base/net/stratum/SubmitResult.cpp src/base/tools/Arguments.cpp + src/base/tools/Buffer.cpp src/base/tools/Handle.cpp src/base/tools/String.cpp src/common/config/CommonConfig.cpp diff --git a/src/api/ApiRouter.cpp b/src/api/ApiRouter.cpp index ff99c047..5f3b1f63 100644 --- a/src/api/ApiRouter.cpp +++ b/src/api/ApiRouter.cpp @@ -34,7 +34,7 @@ #include "api/ApiRouter.h" -#include "base/net/stratum/Job.h" +#include "base/tools/Buffer.h" #include "common/api/HttpReply.h" #include "common/api/HttpRequest.h" #include "common/cpu/Cpu.h" @@ -174,7 +174,7 @@ void ApiRouter::genId(const char *id) memcpy(input + sizeof(uint16_t) + addrSize, APP_KIND, strlen(APP_KIND)); xmrig::keccak(input, inSize, hash); - xmrig::Job::toHex(hash, 8, m_id); + xmrig::Buffer::toHex(hash, 8, m_id); delete [] input; break; diff --git a/src/base/net/stratum/Client.cpp b/src/base/net/stratum/Client.cpp index cffbe543..5b330311 100644 --- a/src/base/net/stratum/Client.cpp +++ b/src/base/net/stratum/Client.cpp @@ -39,6 +39,7 @@ #include "base/kernel/interfaces/IClientListener.h" #include "base/net/stratum/Client.h" +#include "base/tools/Buffer.h" #include "base/tools/Chrono.h" #include "common/log/Log.h" #include "net/JobResult.h" @@ -232,10 +233,10 @@ int64_t xmrig::Client::submit(const JobResult &result) char *nonce = m_sendBuf; char *data = m_sendBuf + 16; - Job::toHex(reinterpret_cast(&result.nonce), 4, nonce); + Buffer::toHex(reinterpret_cast(&result.nonce), 4, nonce); nonce[8] = '\0'; - Job::toHex(result.result, 32, data); + Buffer::toHex(result.result, 32, data); data[64] = '\0'; # endif diff --git a/src/base/net/stratum/Job.cpp b/src/base/net/stratum/Job.cpp index c9902f49..f8239459 100644 --- a/src/base/net/stratum/Job.cpp +++ b/src/base/net/stratum/Job.cpp @@ -29,33 +29,7 @@ #include "base/net/stratum/Job.h" - - -unsigned char hf_hex2bin(char c, bool &err) -{ - if (c >= '0' && c <= '9') { - return c - '0'; - } - else if (c >= 'a' && c <= 'f') { - return c - 'a' + 0xA; - } - else if (c >= 'A' && c <= 'F') { - return c - 'A' + 0xA; - } - - err = true; - return 0; -} - - -char hf_bin2hex(unsigned char c) -{ - if (c <= 0x9) { - return '0' + c; - } - - return 'a' - 0xA + c; -} +#include "base/tools/Buffer.h" xmrig::Job::Job() : @@ -115,7 +89,7 @@ bool xmrig::Job::setBlob(const char *blob) return false; } - if (!fromHex(blob, (int) m_size * 2, m_blob)) { + if (!Buffer::fromHex(blob, m_size * 2, m_blob)) { return false; } @@ -167,7 +141,7 @@ bool xmrig::Job::setTarget(const char *target) char str[8]; memcpy(str, target, len); - if (!fromHex(str, 8, reinterpret_cast(&tmp)) || tmp == 0) { + if (!Buffer::fromHex(str, 8, reinterpret_cast(&tmp)) || tmp == 0) { return false; } @@ -178,7 +152,7 @@ bool xmrig::Job::setTarget(const char *target) char str[16]; memcpy(str, target, len); - if (!fromHex(str, 16, reinterpret_cast(&m_target)) || m_target == 0) { + if (!Buffer::fromHex(str, 16, reinterpret_cast(&m_target)) || m_target == 0) { return false; } } @@ -212,40 +186,6 @@ void xmrig::Job::setHeight(uint64_t height) } -bool xmrig::Job::fromHex(const char* in, unsigned int len, unsigned char* out) -{ - bool error = false; - for (unsigned int i = 0; i < len; i += 2) { - out[i / 2] = (hf_hex2bin(in[i], error) << 4) | hf_hex2bin(in[i + 1], error); - - if (error) { - return false; - } - } - return true; -} - - -void xmrig::Job::toHex(const unsigned char* in, unsigned int len, char* out) -{ - for (unsigned int i = 0; i < len; i++) { - out[i * 2] = hf_bin2hex((in[i] & 0xF0) >> 4); - out[i * 2 + 1] = hf_bin2hex(in[i] & 0x0F); - } -} - - -#ifdef APP_DEBUG -char *xmrig::Job::toHex(const unsigned char* in, unsigned int len) -{ - char *out = new char[len * 2 + 1](); - toHex(in, len, out); - - return out; -} -#endif - - xmrig::Variant xmrig::Job::variant() const { switch (m_algorithm.algo()) { diff --git a/src/base/net/stratum/Job.h b/src/base/net/stratum/Job.h index 878274e8..8fc3d709 100644 --- a/src/base/net/stratum/Job.h +++ b/src/base/net/stratum/Job.h @@ -84,14 +84,8 @@ public: 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(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); - -# ifdef APP_DEBUG - static char *toHex(const unsigned char* in, unsigned int len); -# endif inline bool operator==(const Job &other) const { return isEqual(other); } inline bool operator!=(const Job &other) const { return !isEqual(other); } diff --git a/src/base/net/stratum/Tls.cpp b/src/base/net/stratum/Tls.cpp index 04aeae92..e8948f34 100644 --- a/src/base/net/stratum/Tls.cpp +++ b/src/base/net/stratum/Tls.cpp @@ -29,6 +29,7 @@ #include "base/net/stratum/Client.h" #include "base/net/stratum/Tls.h" +#include "base/tools/Buffer.h" #include "common/log/Log.h" @@ -183,7 +184,7 @@ bool xmrig::Client::Tls::verifyFingerprint(X509 *cert) return false; } - Job::toHex(md, 32, m_fingerprint); + Buffer::toHex(md, 32, m_fingerprint); const char *fingerprint = m_client->m_pool.fingerprint(); return fingerprint == nullptr || strncasecmp(m_fingerprint, fingerprint, 64) == 0; diff --git a/src/base/tools/Buffer.cpp b/src/base/tools/Buffer.cpp new file mode 100644 index 00000000..05a68cb4 --- /dev/null +++ b/src/base/tools/Buffer.cpp @@ -0,0 +1,201 @@ +/* XMRig + * Copyright 2010 Jeff Garzik + * Copyright 2012-2014 pooler + * Copyright 2014 Lucas Jones + * Copyright 2014-2016 Wolf9466 + * Copyright 2016 Jay D Dee + * Copyright 2017-2018 XMR-Stak , + * Copyright 2018-2019 SChernykh + * Copyright 2016-2019 XMRig , + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + + +#include "base/tools/Buffer.h" + + +static inline uint8_t hf_hex2bin(uint8_t c, bool &err) +{ + if (c >= '0' && c <= '9') { + return c - '0'; + } + else if (c >= 'a' && c <= 'f') { + return c - 'a' + 0xA; + } + else if (c >= 'A' && c <= 'F') { + return c - 'A' + 0xA; + } + + err = true; + return 0; +} + + +static inline uint8_t hf_bin2hex(uint8_t c) +{ + if (c <= 0x9) { + return '0' + c; + } + + return 'a' - 0xA + c; +} + + +xmrig::Buffer::Buffer() : + m_data(nullptr), + m_size(0) +{ +} + + +xmrig::Buffer::Buffer(Buffer &&other) : + m_data(other.m_data), + m_size(other.m_size) +{ + other.m_data = nullptr; + other.m_size = 0; +} + + +xmrig::Buffer::Buffer(const Buffer &other) +{ + copy(other.data(), other.size()); +} + + +xmrig::Buffer::Buffer(const char *data, size_t size) +{ + copy(data, size); +} + + +xmrig::Buffer::Buffer(size_t size) : + m_size(size) +{ + m_data = new char[size](); +} + + +xmrig::Buffer::~Buffer() +{ + delete [] m_data; +} + + +void xmrig::Buffer::from(const char *data, size_t size) +{ + if (m_size > 0) { + if (m_size == size) { + memcpy(m_data, data, m_size); + + return; + } + + delete [] m_data; + } + + copy(data, size); +} + + +xmrig::Buffer xmrig::Buffer::allocUnsafe(size_t size) +{ + Buffer buf; + buf.m_size = size; + buf.m_data = new char[size]; + + return buf; +} + + +bool xmrig::Buffer::fromHex(const uint8_t *in, size_t size, uint8_t *out) +{ + bool error = false; + for (size_t i = 0; i < size; i += 2) { + out[i / 2] = static_cast((hf_hex2bin(in[i], error) << 4) | hf_hex2bin(in[i + 1], error)); + + if (error) { + return false; + } + } + + return true; +} + + +xmrig::Buffer xmrig::Buffer::fromHex(const char *data, size_t size) +{ + if (data == nullptr || size % 2 != 0) { + return Buffer(); + } + + Buffer buf(size / 2); + fromHex(data, size, buf.data()); + + return buf; +} + + +void xmrig::Buffer::toHex(const uint8_t *in, size_t size, uint8_t *out) +{ + for (size_t i = 0; i < size; i++) { + out[i * 2] = hf_bin2hex((in[i] & 0xF0) >> 4); + out[i * 2 + 1] = hf_bin2hex(in[i] & 0x0F); + } +} + + +xmrig::String xmrig::Buffer::toHex(const uint8_t *in, size_t size) +{ + return Buffer(reinterpret_cast(in), size).toHex(); +} + + +xmrig::String xmrig::Buffer::toHex() const +{ + if (m_size == 0) { + return String(); + } + + char *buf = new char[m_size * 2 + 1]; + buf[m_size * 2] = '\0'; + + toHex(m_data, m_size, buf); + + return String(buf); +} + + +void xmrig::Buffer::copy(const char *data, size_t size) +{ + m_data = new char[size]; + m_size = size; + + memcpy(m_data, data, m_size); +} + + +void xmrig::Buffer::move(Buffer &&other) +{ + if (m_size > 0) { + delete [] m_data; + } + + m_data = other.m_data; + m_size = other.m_size; + + other.m_data = nullptr; + other.m_size = 0; +} diff --git a/src/base/tools/Buffer.h b/src/base/tools/Buffer.h new file mode 100644 index 00000000..6b720357 --- /dev/null +++ b/src/base/tools/Buffer.h @@ -0,0 +1,88 @@ +/* XMRig + * Copyright 2010 Jeff Garzik + * Copyright 2012-2014 pooler + * Copyright 2014 Lucas Jones + * Copyright 2014-2016 Wolf9466 + * Copyright 2016 Jay D Dee + * Copyright 2017-2018 XMR-Stak , + * Copyright 2018-2019 SChernykh + * Copyright 2016-2019 XMRig , + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef XMRIG_BUFFER_H +#define XMRIG_BUFFER_H + + +#include "base/tools/String.h" + + +namespace xmrig { + + +class Buffer +{ +public: + Buffer(); + Buffer(Buffer &&other); + Buffer(const Buffer &other); + Buffer(const char *data, size_t size); + Buffer(size_t size); + ~Buffer(); + + + inline char *data() { return m_data; } + inline const char *data() const { return m_data; } + inline size_t size() const { return m_size; } + inline void from(const Buffer &other) { from(other.data(), other.size()); } + + + void from(const char *data, size_t size); + + + inline Buffer &operator=(const Buffer &other) { from(other); return *this; } + inline Buffer &operator=(Buffer &&other) { move(std::move(other)); return *this; } + + + static Buffer allocUnsafe(size_t size); + static inline Buffer alloc(size_t size) { return Buffer(size); } + + + inline static bool fromHex(const char *in, size_t size, char *out) { return fromHex(reinterpret_cast(in), size, reinterpret_cast(out)); } + inline static bool fromHex(const char *in, size_t size, uint8_t *out) { return fromHex(reinterpret_cast(in), size, out); } + inline static Buffer fromHex(const char *data) { return fromHex(data, strlen(data)); } + inline static Buffer fromHex(const String &str) { return fromHex(str.data(), str.size()); } + inline static void toHex(const char *in, size_t size, char *out) { return toHex(reinterpret_cast(in), size, reinterpret_cast(out)); } + inline static void toHex(const uint8_t *in, size_t size, char *out) { return toHex(in, size, reinterpret_cast(out)); } + + static bool fromHex(const uint8_t *in, size_t size, uint8_t *out); + static Buffer fromHex(const char *data, size_t size); + static String toHex(const uint8_t *in, size_t size); + static void toHex(const uint8_t *in, size_t size, uint8_t *out); + String toHex() const; + +private: + void copy(const char *data, size_t size); + void move(Buffer &&other); + + char *m_data; + size_t m_size; +}; + + +} /* namespace xmrig */ + + +#endif /* XMRIG_BUFFER_H */ diff --git a/src/net/strategies/DonateStrategy.cpp b/src/net/strategies/DonateStrategy.cpp index f056d498..ba544c4b 100644 --- a/src/net/strategies/DonateStrategy.cpp +++ b/src/net/strategies/DonateStrategy.cpp @@ -27,6 +27,7 @@ #include "base/net/stratum/Job.h" #include "base/net/stratum/strategies/FailoverStrategy.h" #include "base/net/stratum/strategies/SinglePoolStrategy.h" +#include "base/tools/Buffer.h" #include "common/crypto/keccak.h" #include "common/Platform.h" #include "common/xmrig.h" @@ -51,7 +52,7 @@ xmrig::DonateStrategy::DonateStrategy(int level, const char *user, Algo algo, IS char userId[65] = { 0 }; keccak(reinterpret_cast(user), strlen(user), hash); - Job::toHex(hash, 32, userId); + Buffer::toHex(hash, 32, userId); # ifndef XMRIG_NO_TLS m_pools.push_back(Pool("donate.ssl.xmrig.com", 443, userId, nullptr, false, true, true)); From f5077cadbd48d5009b270e9d12ad44d68d5cbe91 Mon Sep 17 00:00:00 2001 From: XMRig Date: Fri, 15 Mar 2019 03:44:02 +0700 Subject: [PATCH 008/116] Added class RecvBuf. --- CMakeLists.txt | 2 + src/base/kernel/interfaces/ILineListener.h | 50 ++++++++++ src/base/net/stratum/Client.cpp | 107 ++++++++------------- src/base/net/stratum/Client.h | 15 +-- src/base/net/stratum/Tls.cpp | 3 +- src/base/net/tools/RecvBuf.h | 99 +++++++++++++++++++ 6 files changed, 203 insertions(+), 73 deletions(-) create mode 100644 src/base/kernel/interfaces/ILineListener.h create mode 100644 src/base/net/tools/RecvBuf.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 81ad18f6..42bb51f8 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -26,6 +26,7 @@ set(HEADERS src/base/kernel/Entry.h src/base/kernel/interfaces/IClientListener.h src/base/kernel/interfaces/IConfigListener.h + src/base/kernel/interfaces/ILineListener.h src/base/kernel/interfaces/ISignalListener.h src/base/kernel/interfaces/IStrategy.h src/base/kernel/interfaces/IStrategyListener.h @@ -39,6 +40,7 @@ set(HEADERS src/base/net/stratum/strategies/FailoverStrategy.h src/base/net/stratum/strategies/SinglePoolStrategy.h src/base/net/stratum/SubmitResult.h + src/base/net/tools/RecvBuf.h src/base/net/tools/Storage.h src/base/tools/Arguments.h src/base/tools/Buffer.h diff --git a/src/base/kernel/interfaces/ILineListener.h b/src/base/kernel/interfaces/ILineListener.h new file mode 100644 index 00000000..1a6d4914 --- /dev/null +++ b/src/base/kernel/interfaces/ILineListener.h @@ -0,0 +1,50 @@ +/* XMRig + * Copyright 2010 Jeff Garzik + * Copyright 2012-2014 pooler + * Copyright 2014 Lucas Jones + * Copyright 2014-2016 Wolf9466 + * Copyright 2016 Jay D Dee + * Copyright 2017-2018 XMR-Stak , + * Copyright 2018-2019 SChernykh + * Copyright 2016-2019 XMRig , + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef XMRIG_ILINELISTENER_H +#define XMRIG_ILINELISTENER_H + + +#include + + +namespace xmrig { + + +class String; + + +class ILineListener +{ +public: + virtual ~ILineListener() = default; + + virtual void onLine(char *line, size_t size) = 0; +}; + + +} /* namespace xmrig */ + + +#endif // XMRIG_ILINELISTENER_H diff --git a/src/base/net/stratum/Client.cpp b/src/base/net/stratum/Client.cpp index 5b330311..313f4ec3 100644 --- a/src/base/net/stratum/Client.cpp +++ b/src/base/net/stratum/Client.cpp @@ -83,7 +83,6 @@ xmrig::Client::Client(int id, const char *agent, IClientListener *listener) : m_retries(5), m_retryPause(5000), m_failures(0), - m_recvBufPos(0), m_state(UnconnectedState), m_tls(nullptr), m_expire(0), @@ -103,9 +102,6 @@ xmrig::Client::Client(int id, const char *agent, IClientListener *listener) : m_hints.ai_family = AF_UNSPEC; m_hints.ai_socktype = SOCK_STREAM; m_hints.ai_protocol = IPPROTO_TCP; - - m_recvBuf.base = m_buf; - m_recvBuf.len = sizeof(m_buf); } @@ -477,8 +473,8 @@ int xmrig::Client::resolve(const char *host) { setState(HostLookupState); - m_expire = 0; - m_recvBufPos = 0; + m_expire = 0; + m_recvBuf.reset(); if (m_failures == -1) { m_failures = 0; @@ -672,8 +668,6 @@ void xmrig::Client::parse(char *line, size_t len) { startTimeout(); - line[len - 1] = '\0'; - LOG_DEBUG("[%s] received (%d bytes): \"%s\"", m_pool.url(), len, line); if (len < 32 || line[0] != '{') { @@ -827,32 +821,42 @@ void xmrig::Client::ping() } -void xmrig::Client::read() +void xmrig::Client::read(ssize_t nread) { - char* end; - char* start = m_recvBuf.base; - size_t remaining = m_recvBufPos; + const size_t size = static_cast(nread); - while ((end = static_cast(memchr(start, '\n', remaining))) != nullptr) { - end++; - size_t len = end - start; - parse(start, len); - - remaining -= len; - start = end; + if (nread > 0 && size > m_recvBuf.available()) { + nread = UV_ENOBUFS; } - if (remaining == 0) { - m_recvBufPos = 0; + if (nread < 0) { + if (!isQuiet()) { + LOG_ERR("[%s] read error: \"%s\"", m_pool.url(), uv_strerror(static_cast(nread))); + } + + close(); return; } - if (start == m_recvBuf.base) { - return; + assert(client->m_listener != nullptr); + if (!m_listener) { + return reconnect(); } - memcpy(m_recvBuf.base, start, remaining); - m_recvBufPos = remaining; + m_recvBuf.nread(size); + +# ifndef XMRIG_NO_TLS + if (isTLS()) { + LOG_DEBUG("[%s] TLS received (%d bytes)", m_pool.url(), static_cast(nread)); + + m_tls->read(m_recvBuf.base(), m_recvBuf.pos()); + m_recvBuf.reset(); + } + else +# endif + { + m_recvBuf.getline(this); + } } @@ -873,7 +877,7 @@ void xmrig::Client::reconnect() setState(ConnectingState); m_failures++; - m_listener->onClose(this, (int) m_failures); + m_listener->onClose(this, static_cast(m_failures)); m_expire = Chrono::steadyMSecs() + m_retryPause; } @@ -903,15 +907,20 @@ void xmrig::Client::startTimeout() } -void xmrig::Client::onAllocBuffer(uv_handle_t *handle, size_t suggested_size, uv_buf_t *buf) +void xmrig::Client::onAllocBuffer(uv_handle_t *handle, size_t, uv_buf_t *buf) { auto client = getClient(handle->data); if (!client) { return; } - buf->base = &client->m_recvBuf.base[client->m_recvBufPos]; - buf->len = client->m_recvBuf.len - client->m_recvBufPos; + buf->base = client->m_recvBuf.current(); + +# ifdef _WIN32 + buf->len = static_cast(client->m_recvBuf.available()); +# else + buf->len = client->m_recvBuf.available(); +# endif } @@ -955,45 +964,11 @@ void xmrig::Client::onConnect(uv_connect_t *req, int status) } -void xmrig::Client::onRead(uv_stream_t *stream, ssize_t nread, const uv_buf_t *buf) +void xmrig::Client::onRead(uv_stream_t *stream, ssize_t nread, const uv_buf_t *) { auto client = getClient(stream->data); - if (!client) { - return; - } - - if (nread < 0) { - if (!client->isQuiet()) { - LOG_ERR("[%s] read error: \"%s\"", client->m_pool.url(), uv_strerror((int) nread)); - } - - client->close(); - return; - } - - if ((size_t) nread > (sizeof(m_buf) - 8 - client->m_recvBufPos)) { - client->close(); - return; - } - - assert(client->m_listener != nullptr); - if (!client->m_listener) { - return client->reconnect(); - } - - client->m_recvBufPos += nread; - -# ifndef XMRIG_NO_TLS - if (client->isTLS()) { - LOG_DEBUG("[%s] TLS received (%d bytes)", client->m_pool.url(), static_cast(nread)); - - client->m_tls->read(client->m_recvBuf.base, client->m_recvBufPos); - client->m_recvBufPos = 0; - } - else -# endif - { - client->read(); + if (client) { + client->read(nread); } } diff --git a/src/base/net/stratum/Client.h b/src/base/net/stratum/Client.h index ed433ff9..07c82a8f 100644 --- a/src/base/net/stratum/Client.h +++ b/src/base/net/stratum/Client.h @@ -32,9 +32,11 @@ #include +#include "base/kernel/interfaces/ILineListener.h" #include "base/net/stratum/Job.h" #include "base/net/stratum/Pool.h" #include "base/net/stratum/SubmitResult.h" +#include "base/net/tools/RecvBuf.h" #include "base/net/tools/Storage.h" #include "common/crypto/Algorithm.h" #include "rapidjson/fwd.h" @@ -50,7 +52,7 @@ class IClientListener; class JobResult; -class Client +class Client : public ILineListener { public: enum SocketState { @@ -78,7 +80,7 @@ public: # endif Client(int id, const char *agent, IClientListener *listener); - ~Client(); + ~Client() override; bool disconnect(); const char *tlsFingerprint() const; @@ -106,6 +108,9 @@ public: template inline bool has() const noexcept { return m_extensions.test(ext); } +protected: + inline void onLine(char *line, size_t size) override { parse(line, size); } + private: class Tls; @@ -129,7 +134,7 @@ private: void parseNotification(const char *method, const rapidjson::Value ¶ms, const rapidjson::Value &error); void parseResponse(int64_t id, const rapidjson::Value &result, const rapidjson::Value &error); void ping(); - void read(); + void read(ssize_t nread); void reconnect(); void setState(SocketState state); void startTimeout(); @@ -149,7 +154,6 @@ private: bool m_enabled; bool m_ipv6; bool m_quiet; - char m_buf[kInputBufferSize]; char m_ip[46]; char m_sendBuf[2048]; const char *m_agent; @@ -160,7 +164,7 @@ private: int64_t m_failures; Job m_job; Pool m_pool; - size_t m_recvBufPos; + RecvBuf m_recvBuf; SocketState m_state; std::bitset m_extensions; std::map m_results; @@ -170,7 +174,6 @@ private: uint64_t m_jobs; uint64_t m_keepAlive; uintptr_t m_key; - uv_buf_t m_recvBuf; uv_getaddrinfo_t m_resolver; uv_stream_t *m_stream; uv_tcp_t *m_socket; diff --git a/src/base/net/stratum/Tls.cpp b/src/base/net/stratum/Tls.cpp index e8948f34..e96d9946 100644 --- a/src/base/net/stratum/Tls.cpp +++ b/src/base/net/stratum/Tls.cpp @@ -135,7 +135,8 @@ void xmrig::Client::Tls::read(const char *data, size_t size) int bytes_read = 0; while ((bytes_read = SSL_read(m_ssl, m_buf, sizeof(m_buf))) > 0) { - m_client->parse(m_buf, bytes_read); + m_buf[bytes_read - 1] = '\0'; + m_client->parse(m_buf, static_cast(bytes_read)); } } diff --git a/src/base/net/tools/RecvBuf.h b/src/base/net/tools/RecvBuf.h new file mode 100644 index 00000000..5122c980 --- /dev/null +++ b/src/base/net/tools/RecvBuf.h @@ -0,0 +1,99 @@ +/* XMRig + * Copyright 2010 Jeff Garzik + * Copyright 2012-2014 pooler + * Copyright 2014 Lucas Jones + * Copyright 2014-2016 Wolf9466 + * Copyright 2016 Jay D Dee + * Copyright 2017-2018 XMR-Stak , + * Copyright 2018-2019 SChernykh + * Copyright 2016-2019 XMRig , + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef XMRIG_RECVBUF_H +#define XMRIG_RECVBUF_H + + +#include + + +#include "base/kernel/interfaces/ILineListener.h" + + +namespace xmrig { + + +template +class RecvBuf +{ +public: + inline RecvBuf() : + m_buf(), + m_pos(0) + { + } + + inline char *base() { return m_buf; } + inline char *current() { return m_buf + m_pos; } + inline const char *base() const { return m_buf; } + inline const char *current() const { return m_buf + m_pos; } + inline size_t available() const { return N - m_pos; } + inline size_t pos() const { return m_pos; } + inline void nread(size_t size) { m_pos += size; } + inline void reset() { m_pos = 0; } + + constexpr inline size_t size() const { return N; } + + inline void getline(ILineListener *listener) + { + char *end; + char *start = m_buf; + size_t remaining = m_pos; + + while ((end = static_cast(memchr(start, '\n', remaining))) != nullptr) { + *end = '\0'; + + end++; + const size_t len = static_cast(end - start); + + listener->onLine(start, len - 1); + + remaining -= len; + start = end; + } + + if (remaining == 0) { + m_pos = 0; + return; + } + + if (start == m_buf) { + return; + } + + memcpy(m_buf, start, remaining); + m_pos = remaining; + } + +private: + char m_buf[N]; + size_t m_pos; +}; + + +} /* namespace xmrig */ + + +#endif /* XMRIG_RECVBUF_H */ From 3094741c64f3d08e5c4425123cdfb4035612d2f8 Mon Sep 17 00:00:00 2001 From: XMRig Date: Fri, 15 Mar 2019 12:54:00 +0700 Subject: [PATCH 009/116] Remove file SubmitResult.cpp. --- CMakeLists.txt | 1 - src/base/net/stratum/SubmitResult.cpp | 46 --------------------------- src/base/net/stratum/SubmitResult.h | 25 ++++++++++++--- 3 files changed, 20 insertions(+), 52 deletions(-) delete mode 100644 src/base/net/stratum/SubmitResult.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 42bb51f8..00dd8577 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -124,7 +124,6 @@ set(SOURCES src/base/net/stratum/Pools.cpp src/base/net/stratum/strategies/FailoverStrategy.cpp src/base/net/stratum/strategies/SinglePoolStrategy.cpp - src/base/net/stratum/SubmitResult.cpp src/base/tools/Arguments.cpp src/base/tools/Buffer.cpp src/base/tools/Handle.cpp diff --git a/src/base/net/stratum/SubmitResult.cpp b/src/base/net/stratum/SubmitResult.cpp deleted file mode 100644 index ad8a48af..00000000 --- a/src/base/net/stratum/SubmitResult.cpp +++ /dev/null @@ -1,46 +0,0 @@ -/* XMRig - * Copyright 2010 Jeff Garzik - * Copyright 2012-2014 pooler - * Copyright 2014 Lucas Jones - * Copyright 2014-2016 Wolf9466 - * Copyright 2016 Jay D Dee - * Copyright 2017-2018 XMR-Stak , - * Copyright 2018-2019 SChernykh - * Copyright 2016-2019 XMRig , - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - - -#include - - -#include "base/net/stratum/SubmitResult.h" - - -xmrig::SubmitResult::SubmitResult(int64_t seq, uint32_t diff, uint64_t actualDiff, int64_t reqId) : - reqId(reqId), - seq(seq), - diff(diff), - actualDiff(actualDiff), - elapsed(0) -{ - start = uv_hrtime(); -} - - -void xmrig::SubmitResult::done() -{ - elapsed = (uv_hrtime() - start) / 1000000; -} diff --git a/src/base/net/stratum/SubmitResult.h b/src/base/net/stratum/SubmitResult.h index db97ac38..583d426f 100644 --- a/src/base/net/stratum/SubmitResult.h +++ b/src/base/net/stratum/SubmitResult.h @@ -26,7 +26,7 @@ #define XMRIG_SUBMITRESULT_H -#include +#include "base/tools/Chrono.h" namespace xmrig { @@ -35,10 +35,25 @@ namespace xmrig { class SubmitResult { public: - inline SubmitResult() : reqId(0), seq(0), diff(0), actualDiff(0), elapsed(0), start(0) {} - SubmitResult(int64_t seq, uint32_t diff, uint64_t actualDiff, int64_t reqId = 0); + inline SubmitResult() : + reqId(0), + seq(0), + diff(0), + actualDiff(0), + elapsed(0), + m_start(0) + {} - void done(); + inline SubmitResult(int64_t seq, uint32_t diff, uint64_t actualDiff, int64_t reqId = 0) : + reqId(reqId), + seq(seq), + diff(diff), + actualDiff(actualDiff), + elapsed(0), + m_start(Chrono::steadyMSecs()) + {} + + inline void done() { elapsed = Chrono::steadyMSecs() - m_start; } int64_t reqId; int64_t seq; @@ -47,7 +62,7 @@ public: uint64_t elapsed; private: - uint64_t start; + uint64_t m_start; }; From af3655c27e53d0b4c703584ee1c1b22a2f43553a Mon Sep 17 00:00:00 2001 From: XMRig Date: Fri, 15 Mar 2019 18:14:25 +0700 Subject: [PATCH 010/116] Add classes Dns, DnsRecord, IDnsListener. --- CMakeLists.txt | 5 + src/base/kernel/interfaces/IDnsListener.h | 47 +++++++ src/base/net/dns/Dns.cpp | 158 +++++++++++++++++++++ src/base/net/dns/Dns.h | 80 +++++++++++ src/base/net/dns/DnsRecord.cpp | 66 +++++++++ src/base/net/dns/DnsRecord.h | 66 +++++++++ src/base/net/stratum/Client.cpp | 162 ++++++++-------------- src/base/net/stratum/Client.h | 17 +-- src/base/net/stratum/Pool.cpp | 23 +-- src/base/net/stratum/Pool.h | 21 +-- 10 files changed, 514 insertions(+), 131 deletions(-) create mode 100644 src/base/kernel/interfaces/IDnsListener.h create mode 100644 src/base/net/dns/Dns.cpp create mode 100644 src/base/net/dns/Dns.h create mode 100644 src/base/net/dns/DnsRecord.cpp create mode 100644 src/base/net/dns/DnsRecord.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 00dd8577..f0d2e64f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -26,6 +26,7 @@ set(HEADERS src/base/kernel/Entry.h src/base/kernel/interfaces/IClientListener.h src/base/kernel/interfaces/IConfigListener.h + src/base/kernel/interfaces/IDnsListener.h src/base/kernel/interfaces/ILineListener.h src/base/kernel/interfaces/ISignalListener.h src/base/kernel/interfaces/IStrategy.h @@ -33,6 +34,8 @@ set(HEADERS src/base/kernel/interfaces/IWatcherListener.h src/base/kernel/Process.h src/base/kernel/Signals.h + src/base/net/dns/Dns.h + src/base/net/dns/DnsRecord.h src/base/net/stratum/Client.h src/base/net/stratum/Job.h src/base/net/stratum/Pool.h @@ -118,6 +121,8 @@ set(SOURCES src/base/kernel/Entry.cpp src/base/kernel/Process.cpp src/base/kernel/Signals.cpp + src/base/net/dns/Dns.cpp + src/base/net/dns/DnsRecord.cpp src/base/net/stratum/Client.cpp src/base/net/stratum/Job.cpp src/base/net/stratum/Pool.cpp diff --git a/src/base/kernel/interfaces/IDnsListener.h b/src/base/kernel/interfaces/IDnsListener.h new file mode 100644 index 00000000..3683ea51 --- /dev/null +++ b/src/base/kernel/interfaces/IDnsListener.h @@ -0,0 +1,47 @@ +/* XMRig + * Copyright 2010 Jeff Garzik + * Copyright 2012-2014 pooler + * Copyright 2014 Lucas Jones + * Copyright 2014-2016 Wolf9466 + * Copyright 2016 Jay D Dee + * Copyright 2017-2018 XMR-Stak , + * Copyright 2018-2019 SChernykh + * Copyright 2016-2019 XMRig , + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef XMRIG_IDNSLISTENER_H +#define XMRIG_IDNSLISTENER_H + + +namespace xmrig { + + +class Dns; + + +class IDnsListener +{ +public: + virtual ~IDnsListener() = default; + + virtual void onResolved(const Dns &dns, int status) = 0; +}; + + +} /* namespace xmrig */ + + +#endif // XMRIG_IDNSLISTENER_H diff --git a/src/base/net/dns/Dns.cpp b/src/base/net/dns/Dns.cpp new file mode 100644 index 00000000..1e285fb4 --- /dev/null +++ b/src/base/net/dns/Dns.cpp @@ -0,0 +1,158 @@ +/* XMRig + * Copyright 2010 Jeff Garzik + * Copyright 2012-2014 pooler + * Copyright 2014 Lucas Jones + * Copyright 2014-2016 Wolf9466 + * Copyright 2016 Jay D Dee + * Copyright 2017-2018 XMR-Stak , + * Copyright 2018-2019 SChernykh + * Copyright 2016-2019 XMRig , + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + + +#include "base/kernel/interfaces/IDnsListener.h" +#include "base/net/dns/Dns.h" +#include "base/tools/Handle.h" + + +namespace xmrig { + Storage Dns::m_storage; + static const DnsRecord defaultRecord; +} + + +xmrig::Dns::Dns(IDnsListener *listener) : + m_hints(), + m_listener(listener), + m_status(0) +{ + m_key = m_storage.add(this); + + m_resolver = new uv_getaddrinfo_t; + m_resolver->data = m_storage.ptr(m_key); + + m_hints.ai_family = AF_UNSPEC; + m_hints.ai_socktype = SOCK_STREAM; + m_hints.ai_protocol = IPPROTO_TCP; +} + + +xmrig::Dns::~Dns() +{ + Handle::close(m_resolver); + + m_storage.release(m_key); +} + + +bool xmrig::Dns::resolve(const String &host) +{ + if (m_host != host) { + m_host = host; + + clear(); + } + + m_status = uv_getaddrinfo(uv_default_loop(), m_resolver, Dns::onResolved, m_host.data(), nullptr, &m_hints); + + return m_status == 0; +} + + +const char *xmrig::Dns::error() const +{ + return uv_strerror(m_status); +} + + +const xmrig::DnsRecord &xmrig::Dns::get(DnsRecord::Type prefered) const +{ + if (count() == 0) { + return defaultRecord; + } + + const size_t ipv4 = m_ipv4.size(); + const size_t ipv6 = m_ipv6.size(); + + if (ipv6 && (prefered == DnsRecord::AAAA || !ipv4)) { + return m_ipv6[ipv6 == 1 ? 0 : static_cast(rand()) % ipv6]; + } + + if (ipv4) { + return m_ipv4[ipv4 == 1 ? 0 : static_cast(rand()) % ipv4]; + } + + return defaultRecord; +} + + +size_t xmrig::Dns::count(DnsRecord::Type type) const +{ + if (type == DnsRecord::A) { + return m_ipv4.size(); + } + + if (type == DnsRecord::AAAA) { + return m_ipv6.size(); + } + + return m_ipv4.size() + m_ipv6.size(); +} + + +void xmrig::Dns::clear() +{ + m_ipv4.clear(); + m_ipv6.clear(); +} + + +void xmrig::Dns::onResolved(int status, addrinfo *res) +{ + m_status = status; + + if (m_status < 0) { + return m_listener->onResolved(*this, status); + } + + clear(); + + addrinfo *ptr = res; + while (ptr != nullptr) { + if (ptr->ai_family == AF_INET) { + m_ipv4.push_back(ptr); + } + + if (ptr->ai_family == AF_INET6) { + m_ipv6.push_back(ptr); + } + + ptr = ptr->ai_next; + } + + m_listener->onResolved(*this, status); +} + + +void xmrig::Dns::onResolved(uv_getaddrinfo_t *req, int status, addrinfo *res) +{ + Dns *dns = m_storage.get(req->data); + if (dns) { + dns->onResolved(status, res); + } + + uv_freeaddrinfo(res); +} diff --git a/src/base/net/dns/Dns.h b/src/base/net/dns/Dns.h new file mode 100644 index 00000000..73c47cdd --- /dev/null +++ b/src/base/net/dns/Dns.h @@ -0,0 +1,80 @@ +/* XMRig + * Copyright 2010 Jeff Garzik + * Copyright 2012-2014 pooler + * Copyright 2014 Lucas Jones + * Copyright 2014-2016 Wolf9466 + * Copyright 2016 Jay D Dee + * Copyright 2017-2018 XMR-Stak , + * Copyright 2018-2019 SChernykh + * Copyright 2016-2019 XMRig , + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef XMRIG_DNS_H +#define XMRIG_DNS_H + + +#include +#include + + +#include "base/net/dns/DnsRecord.h" +#include "base/net/tools/Storage.h" +#include "base/tools/String.h" + + +namespace xmrig { + + +class IDnsListener; + + +class Dns +{ +public: + Dns(IDnsListener *listener); + ~Dns(); + + inline bool isEmpty() const { return m_ipv4.empty() && m_ipv6.empty(); } + inline int status() const { return m_status; } + + bool resolve(const String &host); + const char *error() const; + const DnsRecord &get(DnsRecord::Type prefered = DnsRecord::A) const; + size_t count(DnsRecord::Type type = DnsRecord::Unknown) const; + +private: + void clear(); + void onResolved(int status, addrinfo *res); + + static void onResolved(uv_getaddrinfo_t *req, int status, addrinfo *res); + + addrinfo m_hints; + IDnsListener *m_listener; + int m_status; + std::vector m_ipv4; + std::vector m_ipv6; + String m_host; + uintptr_t m_key; + uv_getaddrinfo_t *m_resolver; + + static Storage m_storage; +}; + + +} /* namespace xmrig */ + + +#endif /* XMRIG_DNS_H */ diff --git a/src/base/net/dns/DnsRecord.cpp b/src/base/net/dns/DnsRecord.cpp new file mode 100644 index 00000000..7a85799b --- /dev/null +++ b/src/base/net/dns/DnsRecord.cpp @@ -0,0 +1,66 @@ +/* XMRig + * Copyright 2010 Jeff Garzik + * Copyright 2012-2014 pooler + * Copyright 2014 Lucas Jones + * Copyright 2014-2016 Wolf9466 + * Copyright 2016 Jay D Dee + * Copyright 2017-2018 XMR-Stak , + * Copyright 2018-2019 SChernykh + * Copyright 2016-2019 XMRig , + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + + +#include + + +#include "base/net/dns/DnsRecord.h" + + +xmrig::DnsRecord::DnsRecord(const addrinfo *addr) : + m_type(addr->ai_family == AF_INET6 ? AAAA : A) +{ + char *buf = nullptr; + + if (m_type == AAAA) { + buf = new char[45](); + uv_ip6_name(reinterpret_cast(addr->ai_addr), buf, 45); + } + else { + buf = new char[16](); + uv_ip4_name(reinterpret_cast(addr->ai_addr), buf, 16); + } + + m_ip = buf; +} + + +sockaddr *xmrig::DnsRecord::addr(uint16_t port) const +{ + if (m_type == A) { + sockaddr_in *addr = new sockaddr_in(); + uv_ip4_addr(m_ip.data(), port, addr); + + return reinterpret_cast(addr); + } + else if (m_type == AAAA) { + sockaddr_in6 *addr = new sockaddr_in6(); + uv_ip6_addr(m_ip.data(), port, addr); + + return reinterpret_cast(addr); + } + + return nullptr; +} diff --git a/src/base/net/dns/DnsRecord.h b/src/base/net/dns/DnsRecord.h new file mode 100644 index 00000000..71d1e9c8 --- /dev/null +++ b/src/base/net/dns/DnsRecord.h @@ -0,0 +1,66 @@ +/* XMRig + * Copyright 2010 Jeff Garzik + * Copyright 2012-2014 pooler + * Copyright 2014 Lucas Jones + * Copyright 2014-2016 Wolf9466 + * Copyright 2016 Jay D Dee + * Copyright 2017-2018 XMR-Stak , + * Copyright 2018-2019 SChernykh + * Copyright 2016-2019 XMRig , + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef XMRIG_DNSRECORD_H +#define XMRIG_DNSRECORD_H + + +struct addrinfo; +struct sockaddr; + + +#include "base/tools/String.h" + + +namespace xmrig { + + +class DnsRecord +{ +public: + enum Type { + Unknown, + A, + AAAA + }; + + inline DnsRecord() : m_type(Unknown) {} + DnsRecord(const addrinfo *addr); + + sockaddr *addr(uint16_t port = 0) const; + + inline bool isValid() const { return m_type != Unknown; } + inline const String &ip() const { return m_ip; } + inline Type type() const { return m_type; } + +private: + Type m_type; + String m_ip; +}; + + +} /* namespace xmrig */ + + +#endif /* XMRIG_DNSRECORD_H */ diff --git a/src/base/net/stratum/Client.cpp b/src/base/net/stratum/Client.cpp index 313f4ec3..c892b999 100644 --- a/src/base/net/stratum/Client.cpp +++ b/src/base/net/stratum/Client.cpp @@ -38,6 +38,7 @@ #include "base/kernel/interfaces/IClientListener.h" +#include "base/net/dns/Dns.h" #include "base/net/stratum/Client.h" #include "base/tools/Buffer.h" #include "base/tools/Chrono.h" @@ -93,20 +94,13 @@ xmrig::Client::Client(int id, const char *agent, IClientListener *listener) : m_socket(nullptr) { m_key = m_storage.add(this); - - memset(m_ip, 0, sizeof(m_ip)); - memset(&m_hints, 0, sizeof(m_hints)); - - m_resolver.data = m_storage.ptr(m_key); - - m_hints.ai_family = AF_UNSPEC; - m_hints.ai_socktype = SOCK_STREAM; - m_hints.ai_protocol = IPPROTO_TCP; + m_dns = new Dns(this); } xmrig::Client::~Client() { + delete m_dns; delete m_socket; } @@ -164,7 +158,7 @@ void xmrig::Client::tick(uint64_t now) { if (m_state == ConnectedState) { if (m_expire && now > m_expire) { - LOG_DEBUG_ERR("[%s] timeout", m_pool.url()); + LOG_DEBUG_ERR("[%s] timeout", url()); close(); } else if (m_keepAlive && now > m_keepAlive) { @@ -265,6 +259,36 @@ int64_t xmrig::Client::submit(const JobResult &result) } +void xmrig::Client::onResolved(const Dns &dns, int status) +{ + assert(client->m_listener != nullptr); + if (!m_listener) { + return reconnect(); + } + + if (status < 0 && dns.isEmpty()) { + if (!isQuiet()) { + LOG_ERR("[%s] DNS error: \"%s\"", url(), uv_strerror(status)); + } + + return reconnect(); + } + + if (dns.isEmpty()) { + if (!isQuiet()) { + LOG_ERR("[%s] DNS error: \"No IPv4 (A) or IPv6 (AAAA) records found\"", url()); + } + + return reconnect(); + } + + const DnsRecord &record = dns.get(); + m_ip = record.ip(); + + connect(record.addr(m_pool.port())); +} + + bool xmrig::Client::close() { if (m_state == ClosingState) { @@ -384,7 +408,7 @@ bool xmrig::Client::parseJob(const rapidjson::Value ¶ms, int *code) } if (!isQuiet()) { - LOG_WARN("[%s] duplicate job received, reconnect", m_pool.url()); + LOG_WARN("[%s] duplicate job received, reconnect", url()); } close(); @@ -419,7 +443,7 @@ bool xmrig::Client::send(BIO *bio) return true; } - LOG_DEBUG("[%s] TLS send (%d bytes)", m_pool.url(), static_cast(buf.len)); + LOG_DEBUG("[%s] TLS send (%d bytes)", url(), static_cast(buf.len)); bool result = false; if (state() == ConnectedState && uv_is_writable(m_stream)) { @@ -430,7 +454,7 @@ bool xmrig::Client::send(BIO *bio) } } else { - LOG_DEBUG_ERR("[%s] send failed, invalid state: %d", m_pool.url(), m_state); + LOG_DEBUG_ERR("[%s] send failed, invalid state: %d", url(), m_state); } (void) BIO_reset(bio); @@ -469,7 +493,7 @@ bool xmrig::Client::verifyAlgorithm(const Algorithm &algorithm) const } -int xmrig::Client::resolve(const char *host) +int xmrig::Client::resolve(const String &host) { setState(HostLookupState); @@ -480,11 +504,11 @@ int xmrig::Client::resolve(const char *host) m_failures = 0; } - const int r = uv_getaddrinfo(uv_default_loop(), &m_resolver, Client::onResolved, host, nullptr, &m_hints); - if (r) { + if (!m_dns->resolve(host)) { if (!isQuiet()) { - LOG_ERR("[%s:%u] getaddrinfo error: \"%s\"", host, m_pool.port(), uv_strerror(r)); + LOG_ERR("[%s:%u] getaddrinfo error: \"%s\"", host.data(), m_pool.port(), uv_strerror(m_dns->status())); } + return 1; } @@ -502,7 +526,7 @@ int64_t xmrig::Client::send(const rapidjson::Document &doc) const size_t size = buffer.GetSize(); if (size > (sizeof(m_sendBuf) - 2)) { - LOG_ERR("[%s] send failed: \"send buffer overflow: %zu > %zu\"", m_pool.url(), size, (sizeof(m_sendBuf) - 2)); + LOG_ERR("[%s] send failed: \"send buffer overflow: %zu > %zu\"", url(), size, (sizeof(m_sendBuf) - 2)); close(); return -1; } @@ -517,7 +541,7 @@ int64_t xmrig::Client::send(const rapidjson::Document &doc) int64_t xmrig::Client::send(size_t size) { - LOG_DEBUG("[%s] send (%d bytes): \"%s\"", m_pool.url(), size, m_sendBuf); + LOG_DEBUG("[%s] send (%d bytes): \"%s\"", url(), size, m_sendBuf); # ifndef XMRIG_NO_TLS if (isTLS()) { @@ -529,7 +553,7 @@ int64_t xmrig::Client::send(size_t size) # endif { if (state() != ConnectedState || !uv_is_writable(m_stream)) { - LOG_DEBUG_ERR("[%s] send failed, invalid state: %d", m_pool.url(), m_state); + LOG_DEBUG_ERR("[%s] send failed, invalid state: %d", url(), m_state); return -1; } @@ -546,24 +570,6 @@ int64_t xmrig::Client::send(size_t size) } -void xmrig::Client::connect(const std::vector &ipv4, const std::vector &ipv6) -{ - addrinfo *addr = nullptr; - m_ipv6 = ipv4.empty() && !ipv6.empty(); - - if (m_ipv6) { - addr = ipv6[ipv6.size() == 1 ? 0 : rand() % ipv6.size()]; - uv_ip6_name(reinterpret_cast(addr->ai_addr), m_ip, 45); - } - else { - addr = ipv4[ipv4.size() == 1 ? 0 : rand() % ipv4.size()]; - uv_ip4_name(reinterpret_cast(addr->ai_addr), m_ip, 16); - } - - connect(addr->ai_addr); -} - - void xmrig::Client::connect(sockaddr *addr) { setState(ConnectingState); @@ -616,12 +622,12 @@ void xmrig::Client::login() doc.AddMember("method", "login", allocator); Value params(kObjectType); - params.AddMember("login", StringRef(m_pool.user()), allocator); - params.AddMember("pass", StringRef(m_pool.password()), allocator); + params.AddMember("login", m_pool.user().toJSON(), allocator); + params.AddMember("pass", m_pool.password().toJSON(), allocator); params.AddMember("agent", StringRef(m_agent), allocator); - if (m_pool.rigId()) { - params.AddMember("rigid", StringRef(m_pool.rigId()), allocator); + if (!m_pool.rigId().isNull()) { + params.AddMember("rigid", m_pool.rigId().toJSON(), allocator); } # ifdef XMRIG_PROXY_PROJECT @@ -668,11 +674,11 @@ void xmrig::Client::parse(char *line, size_t len) { startTimeout(); - LOG_DEBUG("[%s] received (%d bytes): \"%s\"", m_pool.url(), len, line); + LOG_DEBUG("[%s] received (%d bytes): \"%s\"", url(), len, line); if (len < 32 || line[0] != '{') { if (!isQuiet()) { - LOG_ERR("[%s] JSON decode failed", m_pool.url()); + LOG_ERR("[%s] JSON decode failed", url()); } return; @@ -681,7 +687,7 @@ void xmrig::Client::parse(char *line, size_t len) rapidjson::Document doc; if (doc.ParseInsitu(line).HasParseError()) { if (!isQuiet()) { - LOG_ERR("[%s] JSON decode failed: \"%s\"", m_pool.url(), rapidjson::GetParseError_En(doc.GetParseError())); + LOG_ERR("[%s] JSON decode failed: \"%s\"", url(), rapidjson::GetParseError_En(doc.GetParseError())); } return; @@ -741,7 +747,7 @@ void xmrig::Client::parseNotification(const char *method, const rapidjson::Value { if (error.IsObject()) { if (!isQuiet()) { - LOG_ERR("[%s] error: \"%s\", code: %d", m_pool.url(), error["message"].GetString(), error["code"].GetInt()); + LOG_ERR("[%s] error: \"%s\", code: %d", url(), error["message"].GetString(), error["code"].GetInt()); } return; } @@ -759,7 +765,7 @@ void xmrig::Client::parseNotification(const char *method, const rapidjson::Value return; } - LOG_WARN("[%s] unsupported method: \"%s\"", m_pool.url(), method); + LOG_WARN("[%s] unsupported method: \"%s\"", url(), method); } @@ -775,7 +781,7 @@ void xmrig::Client::parseResponse(int64_t id, const rapidjson::Value &result, co m_results.erase(it); } else if (!isQuiet()) { - LOG_ERR("[%s] error: \"%s\", code: %d", m_pool.url(), message, error["code"].GetInt()); + LOG_ERR("[%s] error: \"%s\", code: %d", url(), message, error["code"].GetInt()); } if (isCriticalError(message)) { @@ -793,7 +799,7 @@ void xmrig::Client::parseResponse(int64_t id, const rapidjson::Value &result, co int code = -1; if (!parseLogin(result, &code)) { if (!isQuiet()) { - LOG_ERR("[%s] login error code: %d", m_pool.url(), code); + LOG_ERR("[%s] login error code: %d", url(), code); } close(); @@ -831,7 +837,7 @@ void xmrig::Client::read(ssize_t nread) if (nread < 0) { if (!isQuiet()) { - LOG_ERR("[%s] read error: \"%s\"", m_pool.url(), uv_strerror(static_cast(nread))); + LOG_ERR("[%s] read error: \"%s\"", url(), uv_strerror(static_cast(nread))); } close(); @@ -847,7 +853,7 @@ void xmrig::Client::read(ssize_t nread) # ifndef XMRIG_NO_TLS if (isTLS()) { - LOG_DEBUG("[%s] TLS received (%d bytes)", m_pool.url(), static_cast(nread)); + LOG_DEBUG("[%s] TLS received (%d bytes)", url(), static_cast(nread)); m_tls->read(m_recvBuf.base(), m_recvBuf.pos()); m_recvBuf.reset(); @@ -885,7 +891,7 @@ void xmrig::Client::reconnect() void xmrig::Client::setState(SocketState state) { - LOG_DEBUG("[%s] state: \"%s\"", m_pool.url(), states[state]); + LOG_DEBUG("[%s] state: \"%s\"", url(), states[state]); if (m_state == state) { return; @@ -945,7 +951,7 @@ void xmrig::Client::onConnect(uv_connect_t *req, int status) if (status < 0) { if (!client->isQuiet()) { - LOG_ERR("[%s] connect error: \"%s\"", client->m_pool.url(), uv_strerror(status)); + LOG_ERR("[%s] connect error: \"%s\"", client->url(), uv_strerror(status)); } delete req; @@ -971,53 +977,3 @@ void xmrig::Client::onRead(uv_stream_t *stream, ssize_t nread, const uv_buf_t *) client->read(nread); } } - - -void xmrig::Client::onResolved(uv_getaddrinfo_t *req, int status, struct addrinfo *res) -{ - auto client = getClient(req->data); - if (!client) { - return; - } - - assert(client->m_listener != nullptr); - if (!client->m_listener) { - return client->reconnect(); - } - - if (status < 0) { - if (!client->isQuiet()) { - LOG_ERR("[%s] DNS error: \"%s\"", client->m_pool.url(), uv_strerror(status)); - } - - return client->reconnect(); - } - - addrinfo *ptr = res; - std::vector ipv4; - std::vector ipv6; - - while (ptr != nullptr) { - if (ptr->ai_family == AF_INET) { - ipv4.push_back(ptr); - } - - if (ptr->ai_family == AF_INET6) { - ipv6.push_back(ptr); - } - - ptr = ptr->ai_next; - } - - if (ipv4.empty() && ipv6.empty()) { - if (!client->isQuiet()) { - LOG_ERR("[%s] DNS error: \"No IPv4 (A) or IPv6 (AAAA) records found\"", client->m_pool.url()); - } - - uv_freeaddrinfo(res); - return client->reconnect(); - } - - client->connect(ipv4, ipv6); - uv_freeaddrinfo(res); -} diff --git a/src/base/net/stratum/Client.h b/src/base/net/stratum/Client.h index 07c82a8f..ce2b0276 100644 --- a/src/base/net/stratum/Client.h +++ b/src/base/net/stratum/Client.h @@ -32,6 +32,7 @@ #include +#include "base/kernel/interfaces/IDnsListener.h" #include "base/kernel/interfaces/ILineListener.h" #include "base/net/stratum/Job.h" #include "base/net/stratum/Pool.h" @@ -39,7 +40,7 @@ #include "base/net/tools/RecvBuf.h" #include "base/net/tools/Storage.h" #include "common/crypto/Algorithm.h" -#include "rapidjson/fwd.h" + typedef struct bio_st BIO; @@ -52,7 +53,7 @@ class IClientListener; class JobResult; -class Client : public ILineListener +class Client : public IDnsListener, public ILineListener { public: enum SocketState { @@ -111,6 +112,8 @@ public: protected: inline void onLine(char *line, size_t size) override { parse(line, size); } + void onResolved(const Dns &dns, int status) override; + private: class Tls; @@ -121,10 +124,9 @@ private: bool parseLogin(const rapidjson::Value &result, int *code); bool send(BIO *bio); bool verifyAlgorithm(const Algorithm &algorithm) const; - int resolve(const char *host); + int resolve(const String &host); int64_t send(const rapidjson::Document &doc); int64_t send(size_t size); - void connect(const std::vector &ipv4, const std::vector &ipv6); void connect(sockaddr *addr); void handshake(); void login(); @@ -140,23 +142,22 @@ private: void startTimeout(); inline bool isQuiet() const { return m_quiet || m_failures >= m_retries; } + inline const char *url() const { return m_pool.url(); } inline void setExtension(Extension ext, bool enable) noexcept { m_extensions.set(ext, enable); } static void onAllocBuffer(uv_handle_t *handle, size_t suggested_size, uv_buf_t *buf); static void onClose(uv_handle_t *handle); static void onConnect(uv_connect_t *req, int status); static void onRead(uv_stream_t *stream, ssize_t nread, const uv_buf_t *buf); - static void onResolved(uv_getaddrinfo_t *req, int status, struct addrinfo *res); static inline Client *getClient(void *data) { return m_storage.get(data); } - addrinfo m_hints; bool m_enabled; bool m_ipv6; bool m_quiet; - char m_ip[46]; char m_sendBuf[2048]; const char *m_agent; + Dns *m_dns; IClientListener *m_listener; int m_id; int m_retries; @@ -168,13 +169,13 @@ private: SocketState m_state; std::bitset m_extensions; std::map m_results; + String m_ip; String m_rpcId; Tls *m_tls; uint64_t m_expire; uint64_t m_jobs; uint64_t m_keepAlive; uintptr_t m_key; - uv_getaddrinfo_t m_resolver; uv_stream_t *m_stream; uv_tcp_t *m_socket; diff --git a/src/base/net/stratum/Pool.cpp b/src/base/net/stratum/Pool.cpp index f371b4c0..c5f16f4f 100644 --- a/src/base/net/stratum/Pool.cpp +++ b/src/base/net/stratum/Pool.cpp @@ -47,16 +47,19 @@ namespace xmrig { -static const char *kEnabled = "enabled"; -static const char *kFingerprint = "tls-fingerprint"; -static const char *kKeepalive = "keepalive"; -static const char *kNicehash = "nicehash"; -static const char *kPass = "pass"; -static const char *kRigId = "rig-id"; -static const char *kTls = "tls"; -static const char *kUrl = "url"; -static const char *kUser = "user"; -static const char *kVariant = "variant"; +static const char *kEnabled = "enabled"; +static const char *kFingerprint = "tls-fingerprint"; +static const char *kKeepalive = "keepalive"; +static const char *kNicehash = "nicehash"; +static const char *kPass = "pass"; +static const char *kRigId = "rig-id"; +static const char *kTls = "tls"; +static const char *kUrl = "url"; +static const char *kUser = "user"; +static const char *kVariant = "variant"; + +const String Pool::kDefaultPassword = "x"; +const String Pool::kDefaultUser = "x"; } diff --git a/src/base/net/stratum/Pool.h b/src/base/net/stratum/Pool.h index a16cc15b..f681f0c4 100644 --- a/src/base/net/stratum/Pool.h +++ b/src/base/net/stratum/Pool.h @@ -40,8 +40,9 @@ namespace xmrig { class Pool { public: - constexpr static const char *kDefaultPassword = "x"; - constexpr static const char *kDefaultUser = "x"; + static const String kDefaultPassword; + static const String kDefaultUser; + constexpr static uint16_t kDefaultPort = 3333; constexpr static int kKeepAliveTimeout = 60; @@ -57,28 +58,28 @@ public: bool tls = false ); + inline Algorithm &algorithm() { return m_algorithm; } inline bool isNicehash() const { return m_nicehash; } inline bool isTLS() const { return m_tls; } inline bool isValid() const { return !m_host.isNull() && m_port > 0; } - inline const char *fingerprint() const { return m_fingerprint.data(); } - inline const char *host() const { return m_host.data(); } - inline const char *password() const { return !m_password.isNull() ? m_password.data() : kDefaultPassword; } - inline const char *rigId() const { return m_rigId.data(); } - inline const char *url() const { return m_url.data(); } - inline const char *user() const { return !m_user.isNull() ? m_user.data() : kDefaultUser; } inline const Algorithm &algorithm() const { return m_algorithm; } inline const Algorithms &algorithms() const { return m_algorithms; } + inline const String &fingerprint() const { return m_fingerprint; } + inline const String &host() const { return m_host; } + inline const String &password() const { return !m_password.isNull() ? m_password : kDefaultPassword; } + inline const String &rigId() const { return m_rigId; } + inline const String &url() const { return m_url; } + inline const String &user() const { return !m_user.isNull() ? m_user : kDefaultUser; } inline int keepAlive() const { return m_keepAlive; } inline uint16_t port() const { return m_port; } inline void setFingerprint(const char *fingerprint) { m_fingerprint = fingerprint; } - inline void setKeepAlive(int keepAlive) { m_keepAlive = keepAlive >= 0 ? keepAlive : 0; } inline void setKeepAlive(bool enable) { setKeepAlive(enable ? kKeepAliveTimeout : 0); } + inline void setKeepAlive(int keepAlive) { m_keepAlive = keepAlive >= 0 ? keepAlive : 0; } inline void setNicehash(bool nicehash) { m_nicehash = nicehash; } inline void setPassword(const char *password) { m_password = password; } inline void setRigId(const char *rigId) { m_rigId = rigId; } inline void setTLS(bool tls) { m_tls = tls; } inline void setUser(const char *user) { m_user = user; } - inline Algorithm &algorithm() { return m_algorithm; } inline bool operator!=(const Pool &other) const { return !isEqual(other); } inline bool operator==(const Pool &other) const { return isEqual(other); } From 1e62943010a6dd10effe5342f2bf21cbff4a3edc Mon Sep 17 00:00:00 2001 From: XMRig Date: Fri, 15 Mar 2019 18:54:45 +0700 Subject: [PATCH 011/116] Fix memory leak. --- src/base/net/stratum/Client.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/base/net/stratum/Client.cpp b/src/base/net/stratum/Client.cpp index c892b999..0693afb7 100644 --- a/src/base/net/stratum/Client.cpp +++ b/src/base/net/stratum/Client.cpp @@ -590,6 +590,8 @@ void xmrig::Client::connect(sockaddr *addr) # endif uv_tcp_connect(req, m_socket, reinterpret_cast(addr), Client::onConnect); + + delete addr; } From 29373c4226dbd72b37be63e77cadb90d1f129b55 Mon Sep 17 00:00:00 2001 From: Tony Butler Date: Fri, 15 Mar 2019 07:13:14 -0600 Subject: [PATCH 012/116] Fix compilation with Clang 3.5 for those with limited compiler choices Performance similar to gcc7+ on systems where gcc4 is the only alternative --- src/crypto/cn_gpu_avx.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/crypto/cn_gpu_avx.cpp b/src/crypto/cn_gpu_avx.cpp index 3dc7cacb..9f801c80 100644 --- a/src/crypto/cn_gpu_avx.cpp +++ b/src/crypto/cn_gpu_avx.cpp @@ -30,6 +30,12 @@ # include # define __restrict__ __restrict #endif +#ifndef _mm256_bslli_epi128 + #define _mm256_bslli_epi128(a, count) _mm256_slli_si256((a), (count)) +#endif +#ifndef _mm256_bsrli_epi128 + #define _mm256_bsrli_epi128(a, count) _mm256_srli_si256((a), (count)) +#endif inline void prep_dv_avx(__m256i* idx, __m256i& v, __m256& n01) { From ba68fb6c538b3a86592023a823f2010f5637cad7 Mon Sep 17 00:00:00 2001 From: XMRig Date: Sat, 16 Mar 2019 00:44:15 +0700 Subject: [PATCH 013/116] Added real graceful exit. --- CMakeLists.txt | 5 +- src/App.cpp | 12 ++- src/App.h | 2 +- src/Summary.cpp | 16 ++-- src/base/kernel/Signals.cpp | 19 ++++- src/base/kernel/Signals.h | 2 + src/base/net/dns/Dns.cpp | 4 +- src/base/tools/Handle.cpp | 79 -------------------- src/base/tools/Handle.h | 68 ++++++++++++++--- src/common/Console.cpp | 35 ++++++--- src/common/Console.h | 21 ++++-- src/common/api/Httpd.cpp | 26 +++++-- src/common/api/Httpd.h | 12 +-- src/common/interfaces/IConsoleListener.h | 19 +++-- src/common/interfaces/ILogBackend.h | 17 +++-- src/common/log/BasicLog.cpp | 11 +-- src/common/log/BasicLog.h | 14 ++-- src/common/log/ConsoleLog.cpp | 41 +++++----- src/common/log/ConsoleLog.h | 22 +++--- src/common/log/FileLog.cpp | 22 +++--- src/common/log/FileLog.h | 18 +++-- src/common/log/Log.cpp | 18 +++-- src/common/log/Log.h | 20 +++-- src/common/log/SysLog.cpp | 9 ++- src/common/log/SysLog.h | 16 +++- src/core/Controller.cpp | 15 +++- src/core/Controller.h | 1 + src/net/Network.cpp | 28 ++++--- src/net/Network.h | 3 +- src/net/strategies/DonateStrategy.cpp | 13 ++-- src/net/strategies/DonateStrategy.h | 2 +- src/workers/Hashrate.cpp | 15 ++-- src/workers/Hashrate.h | 11 +-- src/workers/MultiWorker.cpp | 2 +- src/workers/MultiWorker.h | 2 +- src/workers/{Handle.cpp => ThreadHandle.cpp} | 11 +-- src/workers/{Handle.h => ThreadHandle.h} | 13 ++-- src/workers/Worker.cpp | 4 +- src/workers/Worker.h | 4 +- src/workers/Workers.cpp | 34 +++++---- src/workers/Workers.h | 8 +- 41 files changed, 391 insertions(+), 303 deletions(-) delete mode 100644 src/base/tools/Handle.cpp rename src/workers/{Handle.cpp => ThreadHandle.cpp} (79%) rename src/workers/{Handle.h => ThreadHandle.h} (85%) diff --git a/CMakeLists.txt b/CMakeLists.txt index f0d2e64f..1f87a85d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -84,7 +84,7 @@ set(HEADERS src/Summary.h src/version.h src/workers/CpuThread.h - src/workers/Handle.h + src/workers/ThreadHandle.h src/workers/Hashrate.h src/workers/MultiWorker.h src/workers/Worker.h @@ -131,7 +131,6 @@ set(SOURCES src/base/net/stratum/strategies/SinglePoolStrategy.cpp src/base/tools/Arguments.cpp src/base/tools/Buffer.cpp - src/base/tools/Handle.cpp src/base/tools/String.cpp src/common/config/CommonConfig.cpp src/common/config/ConfigLoader.cpp @@ -151,7 +150,7 @@ set(SOURCES src/net/strategies/DonateStrategy.cpp src/Summary.cpp src/workers/CpuThread.cpp - src/workers/Handle.cpp + src/workers/ThreadHandle.cpp src/workers/Hashrate.cpp src/workers/MultiWorker.cpp src/workers/Worker.cpp diff --git a/src/App.cpp b/src/App.cpp index e75766ac..62dd3814 100644 --- a/src/App.cpp +++ b/src/App.cpp @@ -187,8 +187,14 @@ void xmrig::App::onSignal(int signum) void xmrig::App::close() { - m_controller->network()->stop(); - Workers::stop(); +# ifndef XMRIG_NO_HTTPD + m_httpd->stop(); +# endif - uv_stop(uv_default_loop()); + m_signals->stop(); + m_console->stop(); + m_controller->stop(); + + Workers::stop(); + Log::release(); } diff --git a/src/App.h b/src/App.h index fc944967..02cc61a2 100644 --- a/src/App.h +++ b/src/App.h @@ -31,13 +31,13 @@ #include "common/interfaces/IConsoleListener.h" -class Console; class Httpd; namespace xmrig { +class Console; class Controller; class Network; class Process; diff --git a/src/Summary.cpp b/src/Summary.cpp index 7a52d1b1..61638019 100644 --- a/src/Summary.cpp +++ b/src/Summary.cpp @@ -59,11 +59,11 @@ inline static const char *asmName(xmrig::Assembly assembly, bool colors) static void print_memory(xmrig::Config *config) { # ifdef _WIN32 if (config->isColors()) { - Log::i()->text(GREEN_BOLD(" * ") WHITE_BOLD("%-13s") "%s", + xmrig::Log::i()->text(GREEN_BOLD(" * ") WHITE_BOLD("%-13s") "%s", "HUGE PAGES", Mem::isHugepagesAvailable() ? "\x1B[1;32mavailable" : "\x1B[01;31munavailable"); } else { - Log::i()->text(" * %-13s%s", "HUGE PAGES", Mem::isHugepagesAvailable() ? "available" : "unavailable"); + xmrig::Log::i()->text(" * %-13s%s", "HUGE PAGES", Mem::isHugepagesAvailable() ? "available" : "unavailable"); } # endif } @@ -108,7 +108,7 @@ static void print_threads(xmrig::Config *config) snprintf(buf, sizeof buf, ", affinity=0x%" PRIX64, config->affinity()); } - Log::i()->text(config->isColors() ? GREEN_BOLD(" * ") WHITE_BOLD("%-13s") CYAN_BOLD("%d") WHITE_BOLD(", %s, av=%d, %sdonate=%d%%") WHITE_BOLD("%s") + xmrig::Log::i()->text(config->isColors() ? GREEN_BOLD(" * ") WHITE_BOLD("%-13s") CYAN_BOLD("%d") WHITE_BOLD(", %s, av=%d, %sdonate=%d%%") WHITE_BOLD("%s") : " * %-13s%d, %s, av=%d, %sdonate=%d%%%s", "THREADS", config->threadsCount(), @@ -119,7 +119,7 @@ static void print_threads(xmrig::Config *config) buf); } else { - Log::i()->text(config->isColors() ? GREEN_BOLD(" * ") WHITE_BOLD("%-13s") CYAN_BOLD("%d") WHITE_BOLD(", %s, %sdonate=%d%%") + xmrig::Log::i()->text(config->isColors() ? GREEN_BOLD(" * ") WHITE_BOLD("%-13s") CYAN_BOLD("%d") WHITE_BOLD(", %s, %sdonate=%d%%") : " * %-13s%d, %s, %sdonate=%d%%", "THREADS", config->threadsCount(), @@ -132,11 +132,11 @@ static void print_threads(xmrig::Config *config) if (config->assembly() == xmrig::ASM_AUTO) { const xmrig::Assembly assembly = xmrig::Cpu::info()->assembly(); - Log::i()->text(config->isColors() ? GREEN_BOLD(" * ") WHITE_BOLD("%-13sauto:%s") + xmrig::Log::i()->text(config->isColors() ? GREEN_BOLD(" * ") WHITE_BOLD("%-13sauto:%s") : " * %-13sauto:%s", "ASSEMBLY", asmName(assembly, config->isColors())); } else { - Log::i()->text(config->isColors() ? GREEN_BOLD(" * ") WHITE_BOLD("%-13s%s") : " * %-13s%s", "ASSEMBLY", asmName(config->assembly(), config->isColors())); + xmrig::Log::i()->text(config->isColors() ? GREEN_BOLD(" * ") WHITE_BOLD("%-13s%s") : " * %-13s%s", "ASSEMBLY", asmName(config->assembly(), config->isColors())); } # endif } @@ -145,12 +145,12 @@ static void print_threads(xmrig::Config *config) static void print_commands(xmrig::Config *config) { if (config->isColors()) { - Log::i()->text(GREEN_BOLD(" * ") WHITE_BOLD("COMMANDS ") MAGENTA_BOLD("h") WHITE_BOLD("ashrate, ") + xmrig::Log::i()->text(GREEN_BOLD(" * ") WHITE_BOLD("COMMANDS ") MAGENTA_BOLD("h") WHITE_BOLD("ashrate, ") MAGENTA_BOLD("p") WHITE_BOLD("ause, ") MAGENTA_BOLD("r") WHITE_BOLD("esume")); } else { - Log::i()->text(" * COMMANDS 'h' hashrate, 'p' pause, 'r' resume"); + xmrig::Log::i()->text(" * COMMANDS 'h' hashrate, 'p' pause, 'r' resume"); } } diff --git a/src/base/kernel/Signals.cpp b/src/base/kernel/Signals.cpp index a37c49c6..87825b83 100644 --- a/src/base/kernel/Signals.cpp +++ b/src/base/kernel/Signals.cpp @@ -5,8 +5,8 @@ * Copyright 2014-2016 Wolf9466 * Copyright 2016 Jay D Dee * Copyright 2017-2018 XMR-Stak , - * Copyright 2018 SChernykh - * Copyright 2016-2018 XMRig , + * Copyright 2018-2019 SChernykh + * Copyright 2016-2019 XMRig , * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -44,20 +44,31 @@ xmrig::Signals::Signals(ISignalListener *listener) m_signals[i] = signal; uv_signal_init(uv_default_loop(), signal); - uv_signal_start(signal, xmrig::Signals::onSignal, signums[i]); + uv_signal_start(signal, Signals::onSignal, signums[i]); } } xmrig::Signals::~Signals() { + stop(); +} + + +void xmrig::Signals::stop() +{ + if (!m_signals[0]) { + return; + } + for (size_t i = 0; i < kSignalsCount; ++i) { Handle::close(m_signals[i]); + m_signals[i] = nullptr; } } void xmrig::Signals::onSignal(uv_signal_t *handle, int signum) { - static_cast(handle->data)->m_listener->onSignal(signum); + static_cast(handle->data)->m_listener->onSignal(signum); } diff --git a/src/base/kernel/Signals.h b/src/base/kernel/Signals.h index 8ef4a4bb..9b4a870a 100644 --- a/src/base/kernel/Signals.h +++ b/src/base/kernel/Signals.h @@ -46,6 +46,8 @@ public: Signals(ISignalListener *listener); ~Signals(); + void stop(); + private: void close(int signum); diff --git a/src/base/net/dns/Dns.cpp b/src/base/net/dns/Dns.cpp index 1e285fb4..f2402124 100644 --- a/src/base/net/dns/Dns.cpp +++ b/src/base/net/dns/Dns.cpp @@ -52,9 +52,9 @@ xmrig::Dns::Dns(IDnsListener *listener) : xmrig::Dns::~Dns() { - Handle::close(m_resolver); - m_storage.release(m_key); + + Handle::close(m_resolver); } diff --git a/src/base/tools/Handle.cpp b/src/base/tools/Handle.cpp deleted file mode 100644 index d486ab39..00000000 --- a/src/base/tools/Handle.cpp +++ /dev/null @@ -1,79 +0,0 @@ -/* XMRig - * Copyright 2010 Jeff Garzik - * Copyright 2012-2014 pooler - * Copyright 2014 Lucas Jones - * Copyright 2014-2016 Wolf9466 - * Copyright 2016 Jay D Dee - * Copyright 2017-2018 XMR-Stak , - * Copyright 2018-2019 SChernykh - * Copyright 2016-2019 XMRig , - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - - -#include - - -#include "base/tools/Handle.h" - - -void xmrig::Handle::close(uv_fs_event_t *handle) -{ - if (handle) { - uv_fs_event_stop(handle); - close(reinterpret_cast(handle)); - } -} - - -void xmrig::Handle::close(uv_getaddrinfo_t *handle) -{ - if (handle) { - uv_cancel(reinterpret_cast(handle)); - close(reinterpret_cast(handle)); - } -} - - -void xmrig::Handle::close(uv_handle_t *handle) -{ - uv_close(handle, [](uv_handle_t *handle) { delete handle; }); -} - - -void xmrig::Handle::close(uv_signal_t *handle) -{ - if (handle) { - uv_signal_stop(handle); - close(reinterpret_cast(handle)); - } -} - - -void xmrig::Handle::close(uv_tcp_t *handle) -{ - if (handle) { - close(reinterpret_cast(handle)); - } -} - - -void xmrig::Handle::close(uv_timer_s *handle) -{ - if (handle) { - uv_timer_stop(handle); - close(reinterpret_cast(handle)); - } -} diff --git a/src/base/tools/Handle.h b/src/base/tools/Handle.h index 547c9202..980d4500 100644 --- a/src/base/tools/Handle.h +++ b/src/base/tools/Handle.h @@ -26,12 +26,7 @@ #define XMRIG_HANDLE_H -typedef struct uv_fs_event_s uv_fs_event_t; -typedef struct uv_getaddrinfo_s uv_getaddrinfo_t; -typedef struct uv_handle_s uv_handle_t; -typedef struct uv_signal_s uv_signal_t; -typedef struct uv_tcp_s uv_tcp_t; -typedef struct uv_timer_s uv_timer_t; +#include namespace xmrig { @@ -40,15 +35,64 @@ namespace xmrig { class Handle { public: - static void close(uv_fs_event_t *handle); - static void close(uv_getaddrinfo_t *handle); - static void close(uv_handle_t *handle); - static void close(uv_signal_t *handle); - static void close(uv_tcp_t *handle); - static void close(uv_timer_t *handle); + template + static inline void close(T handle) + { + if (handle) { + deleteLater(handle); + } + } + + + template + static inline void deleteLater(T handle) + { + uv_close(reinterpret_cast(handle), [](uv_handle_t *handle) { delete handle; }); + } }; +template<> +inline void Handle::close(uv_timer_t *handle) +{ + if (handle) { + uv_timer_stop(handle); + deleteLater(handle); + } +} + + +template<> +inline void Handle::close(uv_signal_t *handle) +{ + if (handle) { + uv_signal_stop(handle); + deleteLater(handle); + } +} + + +template<> +inline void Handle::close(uv_getaddrinfo_t *handle) +{ + if (handle) { + uv_cancel(reinterpret_cast(handle)); + + delete handle; + } +} + + +template<> +inline void Handle::close(uv_fs_event_t *handle) +{ + if (handle) { + uv_fs_event_stop(handle); + deleteLater(handle); + } +} + + } /* namespace xmrig */ diff --git a/src/common/Console.cpp b/src/common/Console.cpp index 350fb139..8e5d7285 100644 --- a/src/common/Console.cpp +++ b/src/common/Console.cpp @@ -5,7 +5,8 @@ * Copyright 2014-2016 Wolf9466 * Copyright 2016 Jay D Dee * Copyright 2017-2018 XMR-Stak , - * Copyright 2016-2018 XMRig , + * Copyright 2018-2019 SChernykh + * Copyright 2016-2019 XMRig , * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -22,26 +23,42 @@ */ +#include "base/tools/Handle.h" #include "common/Console.h" #include "interfaces/IConsoleListener.h" -Console::Console(IConsoleListener *listener) +xmrig::Console::Console(IConsoleListener *listener) : m_listener(listener) { - m_tty.data = this; - uv_tty_init(uv_default_loop(), &m_tty, 0, 1); + m_tty = new uv_tty_t; - if (!uv_is_readable(reinterpret_cast(&m_tty))) { + m_tty->data = this; + uv_tty_init(uv_default_loop(), m_tty, 0, 1); + + if (!uv_is_readable(reinterpret_cast(m_tty))) { return; } - uv_tty_set_mode(&m_tty, UV_TTY_MODE_RAW); - uv_read_start(reinterpret_cast(&m_tty), Console::onAllocBuffer, Console::onRead); + uv_tty_set_mode(m_tty, UV_TTY_MODE_RAW); + uv_read_start(reinterpret_cast(m_tty), Console::onAllocBuffer, Console::onRead); } -void Console::onAllocBuffer(uv_handle_t *handle, size_t suggested_size, uv_buf_t *buf) +xmrig::Console::~Console() +{ + stop(); +} + + +void xmrig::Console::stop() +{ + Handle::close(m_tty); + m_tty = nullptr; +} + + +void xmrig::Console::onAllocBuffer(uv_handle_t *handle, size_t, uv_buf_t *buf) { auto console = static_cast(handle->data); buf->len = 1; @@ -49,7 +66,7 @@ void Console::onAllocBuffer(uv_handle_t *handle, size_t suggested_size, uv_buf_t } -void Console::onRead(uv_stream_t *stream, ssize_t nread, const uv_buf_t *buf) +void xmrig::Console::onRead(uv_stream_t *stream, ssize_t nread, const uv_buf_t *buf) { if (nread < 0) { return uv_close(reinterpret_cast(stream), nullptr); diff --git a/src/common/Console.h b/src/common/Console.h index 7f2e3cc9..c0a36ec4 100644 --- a/src/common/Console.h +++ b/src/common/Console.h @@ -5,7 +5,8 @@ * Copyright 2014-2016 Wolf9466 * Copyright 2016 Jay D Dee * Copyright 2017-2018 XMR-Stak , - * Copyright 2016-2018 XMRig , + * Copyright 2018-2019 SChernykh + * Copyright 2016-2019 XMRig , * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -21,13 +22,17 @@ * along with this program. If not, see . */ -#ifndef __CONSOLE_H__ -#define __CONSOLE_H__ +#ifndef XMRIG_CONSOLE_H +#define XMRIG_CONSOLE_H #include + +namespace xmrig { + + class IConsoleListener; @@ -35,6 +40,9 @@ class Console { public: Console(IConsoleListener *listener); + ~Console(); + + void stop(); private: static void onAllocBuffer(uv_handle_t *handle, size_t suggested_size, uv_buf_t *buf); @@ -42,8 +50,11 @@ private: char m_buf[1]; IConsoleListener *m_listener; - uv_tty_t m_tty; + uv_tty_t *m_tty; }; -#endif /* __CONSOLE_H__ */ +} /* namespace xmrig */ + + +#endif /* XMRIG_CONSOLE_H */ diff --git a/src/common/api/Httpd.cpp b/src/common/api/Httpd.cpp index eb6a4ba6..cca2b056 100644 --- a/src/common/api/Httpd.cpp +++ b/src/common/api/Httpd.cpp @@ -5,7 +5,8 @@ * Copyright 2014-2016 Wolf9466 * Copyright 2016 Jay D Dee * Copyright 2017-2018 XMR-Stak , - * Copyright 2016-2018 XMRig , + * Copyright 2018-2019 SChernykh + * Copyright 2016-2019 XMRig , * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -27,6 +28,7 @@ #include "api/Api.h" +#include "base/tools/Handle.h" #include "common/api/Httpd.h" #include "common/api/HttpReply.h" #include "common/api/HttpRequest.h" @@ -41,14 +43,15 @@ Httpd::Httpd(int port, const char *accessToken, bool IPv6, bool restricted) : m_port(port), m_daemon(nullptr) { - uv_timer_init(uv_default_loop(), &m_timer); - m_timer.data = this; + m_timer = new uv_timer_t; + uv_timer_init(uv_default_loop(), m_timer); + m_timer->data = this; } Httpd::~Httpd() { - uv_timer_stop(&m_timer); + stop(); if (m_daemon) { MHD_stop_daemon(m_daemon); @@ -82,15 +85,22 @@ bool Httpd::start() } # if MHD_VERSION >= 0x00093900 - uv_timer_start(&m_timer, Httpd::onTimer, kIdleInterval, kIdleInterval); + uv_timer_start(m_timer, Httpd::onTimer, kIdleInterval, kIdleInterval); # else - uv_timer_start(&m_timer, Httpd::onTimer, kActiveInterval, kActiveInterval); + uv_timer_start(m_timer, Httpd::onTimer, kActiveInterval, kActiveInterval); # endif return true; } +void Httpd::stop() +{ + xmrig::Handle::close(m_timer); + m_timer = nullptr; +} + + int Httpd::process(xmrig::HttpRequest &req) { xmrig::HttpReply reply; @@ -115,11 +125,11 @@ void Httpd::run() # if MHD_VERSION >= 0x00093900 const MHD_DaemonInfo *info = MHD_get_daemon_info(m_daemon, MHD_DAEMON_INFO_CURRENT_CONNECTIONS); if (m_idle && info->num_connections) { - uv_timer_set_repeat(&m_timer, kActiveInterval); + uv_timer_set_repeat(m_timer, kActiveInterval); m_idle = false; } else if (!m_idle && !info->num_connections) { - uv_timer_set_repeat(&m_timer, kIdleInterval); + uv_timer_set_repeat(m_timer, kIdleInterval); m_idle = true; } # endif diff --git a/src/common/api/Httpd.h b/src/common/api/Httpd.h index adec1d71..82ca1541 100644 --- a/src/common/api/Httpd.h +++ b/src/common/api/Httpd.h @@ -5,7 +5,8 @@ * Copyright 2014-2016 Wolf9466 * Copyright 2016 Jay D Dee * Copyright 2017-2018 XMR-Stak , - * Copyright 2016-2018 XMRig , + * Copyright 2018-2019 SChernykh + * Copyright 2016-2019 XMRig , * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -21,8 +22,8 @@ * along with this program. If not, see . */ -#ifndef __HTTPD_H__ -#define __HTTPD_H__ +#ifndef XMRIG_HTTPD_H +#define XMRIG_HTTPD_H #include @@ -47,6 +48,7 @@ public: Httpd(int port, const char *accessToken, bool IPv6, bool restricted); ~Httpd(); bool start(); + void stop(); private: constexpr static const int kIdleInterval = 200; @@ -64,7 +66,7 @@ private: const char *m_accessToken; const int m_port; MHD_Daemon *m_daemon; - uv_timer_t m_timer; + uv_timer_t *m_timer; }; -#endif /* __HTTPD_H__ */ +#endif /* XMRIG_HTTPD_H */ diff --git a/src/common/interfaces/IConsoleListener.h b/src/common/interfaces/IConsoleListener.h index 723f87df..88972f05 100644 --- a/src/common/interfaces/IConsoleListener.h +++ b/src/common/interfaces/IConsoleListener.h @@ -4,8 +4,9 @@ * Copyright 2014 Lucas Jones * Copyright 2014-2016 Wolf9466 * Copyright 2016 Jay D Dee - * Copyright 2016-2017 XMRig - * + * Copyright 2017-2018 XMR-Stak , + * Copyright 2018-2019 SChernykh + * Copyright 2016-2019 XMRig , * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -21,17 +22,23 @@ * along with this program. If not, see . */ -#ifndef __ICONSOLELISTENER_H__ -#define __ICONSOLELISTENER_H__ +#ifndef XMRIG_ICONSOLELISTENER_H +#define XMRIG_ICONSOLELISTENER_H + + +namespace xmrig { class IConsoleListener { public: - virtual ~IConsoleListener() {} + virtual ~IConsoleListener() = default; virtual void onConsoleCommand(char command) = 0; }; -#endif // __ICONSOLELISTENER_H__ +} /* namespace xmrig */ + + +#endif // XMRIG_ICONSOLELISTENER_H diff --git a/src/common/interfaces/ILogBackend.h b/src/common/interfaces/ILogBackend.h index 85a04e93..2299fc67 100644 --- a/src/common/interfaces/ILogBackend.h +++ b/src/common/interfaces/ILogBackend.h @@ -5,7 +5,8 @@ * Copyright 2014-2016 Wolf9466 * Copyright 2016 Jay D Dee * Copyright 2017-2018 XMR-Stak , - * Copyright 2016-2018 XMRig , + * Copyright 2018-2019 SChernykh + * Copyright 2016-2019 XMRig , * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -21,14 +22,17 @@ * along with this program. If not, see . */ -#ifndef __ILOGBACKEND_H__ -#define __ILOGBACKEND_H__ +#ifndef XMRIG_ILOGBACKEND_H +#define XMRIG_ILOGBACKEND_H #include #include +namespace xmrig { + + class ILogBackend { public: @@ -46,11 +50,14 @@ public: constexpr static const size_t kBufferSize = 512; # endif - virtual ~ILogBackend() {} + virtual ~ILogBackend() = default; virtual void message(Level level, const char* fmt, va_list args) = 0; virtual void text(const char* fmt, va_list args) = 0; }; -#endif // __ILOGBACKEND_H__ +} /* namespace xmrig */ + + +#endif // XMRIG_ILOGBACKEND_H diff --git a/src/common/log/BasicLog.cpp b/src/common/log/BasicLog.cpp index cb4defcd..b048dd6e 100644 --- a/src/common/log/BasicLog.cpp +++ b/src/common/log/BasicLog.cpp @@ -5,7 +5,8 @@ * Copyright 2014-2016 Wolf9466 * Copyright 2016 Jay D Dee * Copyright 2017-2018 XMR-Stak , - * Copyright 2016-2018 XMRig , + * Copyright 2018-2019 SChernykh + * Copyright 2016-2019 XMRig , * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -38,12 +39,12 @@ #include "common/log/Log.h" -BasicLog::BasicLog() +xmrig::BasicLog::BasicLog() { } -void BasicLog::message(Level level, const char* fmt, va_list args) +void xmrig::BasicLog::message(Level level, const char* fmt, va_list args) { time_t now = time(nullptr); tm stime; @@ -70,7 +71,7 @@ void BasicLog::message(Level level, const char* fmt, va_list args) } -void BasicLog::text(const char* fmt, va_list args) +void xmrig::BasicLog::text(const char* fmt, va_list args) { snprintf(m_fmt, sizeof(m_fmt) - 1, "%s%s", fmt, Log::endl(false)); @@ -78,7 +79,7 @@ void BasicLog::text(const char* fmt, va_list args) } -void BasicLog::print(va_list args) +void xmrig::BasicLog::print(va_list args) { if (vsnprintf(m_buf, sizeof(m_buf) - 1, m_fmt, args) <= 0) { return; diff --git a/src/common/log/BasicLog.h b/src/common/log/BasicLog.h index 523538e9..bddbe07c 100644 --- a/src/common/log/BasicLog.h +++ b/src/common/log/BasicLog.h @@ -5,7 +5,8 @@ * Copyright 2014-2016 Wolf9466 * Copyright 2016 Jay D Dee * Copyright 2017-2018 XMR-Stak , - * Copyright 2016-2018 XMRig , + * Copyright 2018-2019 SChernykh + * Copyright 2016-2019 XMRig , * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -21,8 +22,8 @@ * along with this program. If not, see . */ -#ifndef __BASICLOG_H__ -#define __BASICLOG_H__ +#ifndef XMRIG_BASICLOG_H +#define XMRIG_BASICLOG_H #include @@ -32,8 +33,6 @@ namespace xmrig { - class Controller; -} class BasicLog : public ILogBackend @@ -52,4 +51,7 @@ private: char m_fmt[256]; }; -#endif /* __BASICLOG_H__ */ + +} /* namespace xmrig */ + +#endif /* XMRIG_BASICLOG_H */ diff --git a/src/common/log/ConsoleLog.cpp b/src/common/log/ConsoleLog.cpp index b10812a6..e0ac01ea 100644 --- a/src/common/log/ConsoleLog.cpp +++ b/src/common/log/ConsoleLog.cpp @@ -5,7 +5,8 @@ * Copyright 2014-2016 Wolf9466 * Copyright 2016 Jay D Dee * Copyright 2017-2018 XMR-Stak , - * Copyright 2016-2018 XMRig , + * Copyright 2018-2019 SChernykh + * Copyright 2016-2019 XMRig , * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -34,24 +35,24 @@ #endif +#include "base/tools/Handle.h" #include "common/log/ConsoleLog.h" #include "common/log/Log.h" -#include "core/Config.h" -#include "core/Controller.h" -ConsoleLog::ConsoleLog(xmrig::Controller *controller) : - m_stream(nullptr), - m_controller(controller) +xmrig::ConsoleLog::ConsoleLog() : + m_stream(nullptr) { - if (uv_tty_init(uv_default_loop(), &m_tty, 1, 0) < 0) { + m_tty = new uv_tty_t; + + if (uv_tty_init(uv_default_loop(), m_tty, 1, 0) < 0) { Log::colors = false; return; } - uv_tty_set_mode(&m_tty, UV_TTY_MODE_NORMAL); + uv_tty_set_mode(m_tty, UV_TTY_MODE_NORMAL); m_uvBuf.base = m_buf; - m_stream = reinterpret_cast(&m_tty); + m_stream = reinterpret_cast(m_tty); # ifdef WIN32 HANDLE handle = GetStdHandle(STD_INPUT_HANDLE); @@ -66,7 +67,13 @@ ConsoleLog::ConsoleLog(xmrig::Controller *controller) : } -void ConsoleLog::message(Level level, const char* fmt, va_list args) +xmrig::ConsoleLog::~ConsoleLog() +{ + Handle::close(m_tty); +} + + +void xmrig::ConsoleLog::message(Level level, const char* fmt, va_list args) { time_t now = time(nullptr); tm stime; @@ -77,8 +84,6 @@ void ConsoleLog::message(Level level, const char* fmt, va_list args) localtime_r(&now, &stime); # endif - const bool isColors = m_controller->config()->isColors(); - snprintf(m_fmt, sizeof(m_fmt) - 1, "[%d-%02d-%02d %02d:%02d:%02d]%s %s%s", stime.tm_year + 1900, stime.tm_mon + 1, @@ -86,24 +91,24 @@ void ConsoleLog::message(Level level, const char* fmt, va_list args) stime.tm_hour, stime.tm_min, stime.tm_sec, - Log::colorByLevel(level, isColors), + Log::colorByLevel(level, Log::colors), fmt, - Log::endl(isColors) + Log::endl(Log::colors) ); print(args); } -void ConsoleLog::text(const char* fmt, va_list args) +void xmrig::ConsoleLog::text(const char* fmt, va_list args) { - snprintf(m_fmt, sizeof(m_fmt) - 1, "%s%s", fmt, Log::endl(m_controller->config()->isColors())); + snprintf(m_fmt, sizeof(m_fmt) - 1, "%s%s", fmt, Log::endl(Log::colors)); print(args); } -bool ConsoleLog::isWritable() const +bool xmrig::ConsoleLog::isWritable() const { if (!m_stream || uv_is_writable(m_stream) != 1) { return false; @@ -114,7 +119,7 @@ bool ConsoleLog::isWritable() const } -void ConsoleLog::print(va_list args) +void xmrig::ConsoleLog::print(va_list args) { m_uvBuf.len = vsnprintf(m_buf, sizeof(m_buf) - 1, m_fmt, args); if (m_uvBuf.len <= 0) { diff --git a/src/common/log/ConsoleLog.h b/src/common/log/ConsoleLog.h index bac09a53..73a701e6 100644 --- a/src/common/log/ConsoleLog.h +++ b/src/common/log/ConsoleLog.h @@ -5,7 +5,8 @@ * Copyright 2014-2016 Wolf9466 * Copyright 2016 Jay D Dee * Copyright 2017-2018 XMR-Stak , - * Copyright 2016-2018 XMRig , + * Copyright 2018-2019 SChernykh + * Copyright 2016-2019 XMRig , * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -21,8 +22,8 @@ * along with this program. If not, see . */ -#ifndef __CONSOLELOG_H__ -#define __CONSOLELOG_H__ +#ifndef XMRIG_CONSOLELOG_H +#define XMRIG_CONSOLELOG_H #include @@ -32,15 +33,15 @@ namespace xmrig { - class Controller; -} class ConsoleLog : public ILogBackend { public: - ConsoleLog(xmrig::Controller *controller); + ConsoleLog(); + ~ConsoleLog() override; +protected: void message(Level level, const char *fmt, va_list args) override; void text(const char *fmt, va_list args) override; @@ -52,8 +53,11 @@ private: char m_fmt[256]; uv_buf_t m_uvBuf; uv_stream_t *m_stream; - uv_tty_t m_tty; - xmrig::Controller *m_controller; + uv_tty_t *m_tty; }; -#endif /* __CONSOLELOG_H__ */ + +} /* namespace xmrig */ + + +#endif /* XMRIG_CONSOLELOG_H */ diff --git a/src/common/log/FileLog.cpp b/src/common/log/FileLog.cpp index 9134c7c7..71eeb18c 100644 --- a/src/common/log/FileLog.cpp +++ b/src/common/log/FileLog.cpp @@ -5,7 +5,8 @@ * Copyright 2014-2016 Wolf9466 * Copyright 2016 Jay D Dee * Copyright 2017-2018 XMR-Stak , - * Copyright 2016-2018 XMRig , + * Copyright 2018-2019 SChernykh + * Copyright 2016-2019 XMRig , * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -31,12 +32,9 @@ #include "common/log/FileLog.h" #include "common/log/Log.h" -#include "core/Config.h" -#include "core/Controller.h" -FileLog::FileLog(xmrig::Controller *controller, const char *fileName) : - m_controller(controller) +xmrig::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); @@ -44,7 +42,7 @@ FileLog::FileLog(xmrig::Controller *controller, const char *fileName) : } -void FileLog::message(Level level, const char* fmt, va_list args) +void xmrig::FileLog::message(Level level, const char* fmt, va_list args) { if (m_file < 0) { return; @@ -59,8 +57,6 @@ void FileLog::message(Level level, const char* fmt, va_list args) localtime_r(&now, &stime); # endif - const bool isColors = m_controller->config()->isColors(); - snprintf(m_fmt, sizeof(m_fmt) - 1, "[%d-%02d-%02d %02d:%02d:%02d]%s %s%s", stime.tm_year + 1900, stime.tm_mon + 1, @@ -68,9 +64,9 @@ void FileLog::message(Level level, const char* fmt, va_list args) stime.tm_hour, stime.tm_min, stime.tm_sec, - Log::colorByLevel(level, isColors), + Log::colorByLevel(level, Log::colors), fmt, - Log::endl(isColors) + Log::endl(Log::colors) ); char *buf = new char[kBufferSize]; @@ -80,13 +76,13 @@ void FileLog::message(Level level, const char* fmt, va_list args) } -void FileLog::text(const char* fmt, va_list args) +void xmrig::FileLog::text(const char* fmt, va_list args) { message(INFO, fmt, args); } -void FileLog::onWrite(uv_fs_t *req) +void xmrig::FileLog::onWrite(uv_fs_t *req) { delete [] static_cast(req->data); @@ -95,7 +91,7 @@ void FileLog::onWrite(uv_fs_t *req) } -void FileLog::write(char *data, size_t size) +void xmrig::FileLog::write(char *data, size_t size) { uv_buf_t buf = uv_buf_init(data, (unsigned int) size); uv_fs_t *req = new uv_fs_t; diff --git a/src/common/log/FileLog.h b/src/common/log/FileLog.h index 8a58d4e4..da80acb2 100644 --- a/src/common/log/FileLog.h +++ b/src/common/log/FileLog.h @@ -5,7 +5,8 @@ * Copyright 2014-2016 Wolf9466 * Copyright 2016 Jay D Dee * Copyright 2017-2018 XMR-Stak , - * Copyright 2016-2018 XMRig , + * Copyright 2018-2019 SChernykh + * Copyright 2016-2019 XMRig , * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -21,8 +22,8 @@ * along with this program. If not, see . */ -#ifndef __FILELOG_H__ -#define __FILELOG_H__ +#ifndef XMRIG_FILELOG_H +#define XMRIG_FILELOG_H #include @@ -32,14 +33,12 @@ namespace xmrig { - class Controller; -} class FileLog : public ILogBackend { public: - FileLog(xmrig::Controller *controller, const char *fileName); + FileLog(const char *fileName); void message(Level level, const char* fmt, va_list args) override; void text(const char* fmt, va_list args) override; @@ -51,7 +50,10 @@ private: char m_fmt[256]; int m_file; - xmrig::Controller *m_controller; }; -#endif /* __FILELOG_H__ */ + +} /* namespace xmrig */ + + +#endif /* XMRIG_FILELOG_H */ diff --git a/src/common/log/Log.cpp b/src/common/log/Log.cpp index 07e4f299..4ef1e14a 100644 --- a/src/common/log/Log.cpp +++ b/src/common/log/Log.cpp @@ -35,6 +35,8 @@ #include "common/log/Log.h" +namespace xmrig { + Log *Log::m_self = nullptr; bool Log::colors = true; @@ -51,8 +53,10 @@ static const char *color[5] = { # endif }; +} /* namespace xmrig */ -void Log::message(ILogBackend::Level level, const char* fmt, ...) + +void xmrig::Log::message(ILogBackend::Level level, const char* fmt, ...) { uv_mutex_lock(&m_mutex); @@ -72,7 +76,7 @@ void Log::message(ILogBackend::Level level, const char* fmt, ...) } -void Log::text(const char* fmt, ...) +void xmrig::Log::text(const char* fmt, ...) { uv_mutex_lock(&m_mutex); @@ -92,7 +96,7 @@ void Log::text(const char* fmt, ...) } -const char *Log::colorByLevel(ILogBackend::Level level, bool isColors) +const char *xmrig::Log::colorByLevel(ILogBackend::Level level, bool isColors) { if (!isColors) { return ""; @@ -102,7 +106,7 @@ const char *Log::colorByLevel(ILogBackend::Level level, bool isColors) } -const char *Log::endl(bool isColors) +const char *xmrig::Log::endl(bool isColors) { # ifdef _WIN32 return isColors ? "\x1B[0m\r\n" : "\r\n"; @@ -112,7 +116,7 @@ const char *Log::endl(bool isColors) } -void Log::defaultInit() +void xmrig::Log::defaultInit() { m_self = new Log(); @@ -120,8 +124,10 @@ void Log::defaultInit() } -Log::~Log() +xmrig::Log::~Log() { + m_self = nullptr; + for (auto backend : m_backends) { delete backend; } diff --git a/src/common/log/Log.h b/src/common/log/Log.h index c32edddd..9a0ba2a9 100644 --- a/src/common/log/Log.h +++ b/src/common/log/Log.h @@ -34,6 +34,9 @@ #include "common/interfaces/ILogBackend.h" +namespace xmrig { + + class Log { public: @@ -68,6 +71,9 @@ private: }; +} /* namespace xmrig */ + + #define RED_BOLD(x) "\x1B[1;31m" x "\x1B[0m" #define RED(x) "\x1B[0;31m" x "\x1B[0m" #define GREEN_BOLD(x) "\x1B[1;32m" x "\x1B[0m" @@ -83,20 +89,20 @@ private: #define GRAY(x) "\x1B[1;30m" x "\x1B[0m" -#define LOG_ERR(x, ...) Log::i()->message(ILogBackend::ERR, x, ##__VA_ARGS__) -#define LOG_WARN(x, ...) Log::i()->message(ILogBackend::WARNING, x, ##__VA_ARGS__) -#define LOG_NOTICE(x, ...) Log::i()->message(ILogBackend::NOTICE, x, ##__VA_ARGS__) -#define LOG_INFO(x, ...) Log::i()->message(ILogBackend::INFO, x, ##__VA_ARGS__) +#define LOG_ERR(x, ...) xmrig::Log::i()->message(xmrig::ILogBackend::ERR, x, ##__VA_ARGS__) +#define LOG_WARN(x, ...) xmrig::Log::i()->message(xmrig::ILogBackend::WARNING, x, ##__VA_ARGS__) +#define LOG_NOTICE(x, ...) xmrig::Log::i()->message(xmrig::ILogBackend::NOTICE, x, ##__VA_ARGS__) +#define LOG_INFO(x, ...) xmrig::Log::i()->message(xmrig::ILogBackend::INFO, x, ##__VA_ARGS__) #ifdef APP_DEBUG -# define LOG_DEBUG(x, ...) Log::i()->message(ILogBackend::DEBUG, x, ##__VA_ARGS__) +# define LOG_DEBUG(x, ...) xmrig::Log::i()->message(xmrig::ILogBackend::DEBUG, x, ##__VA_ARGS__) #else # define LOG_DEBUG(x, ...) #endif #if defined(APP_DEBUG) || defined(APP_DEVEL) -# define LOG_DEBUG_ERR(x, ...) Log::i()->message(ILogBackend::ERR, x, ##__VA_ARGS__) -# define LOG_DEBUG_WARN(x, ...) Log::i()->message(ILogBackend::WARNING, x, ##__VA_ARGS__) +# define LOG_DEBUG_ERR(x, ...) xmrig::Log::i()->message(xmrig::ILogBackend::ERR, x, ##__VA_ARGS__) +# define LOG_DEBUG_WARN(x, ...) xmrig::Log::i()->message(xmrig::ILogBackend::WARNING, x, ##__VA_ARGS__) #else # define LOG_DEBUG_ERR(x, ...) # define LOG_DEBUG_WARN(x, ...) diff --git a/src/common/log/SysLog.cpp b/src/common/log/SysLog.cpp index bcb96394..1a8ffbd2 100644 --- a/src/common/log/SysLog.cpp +++ b/src/common/log/SysLog.cpp @@ -5,7 +5,8 @@ * Copyright 2014-2016 Wolf9466 * Copyright 2016 Jay D Dee * Copyright 2017-2018 XMR-Stak , - * Copyright 2016-2018 XMRig , + * Copyright 2018-2019 SChernykh + * Copyright 2016-2019 XMRig , * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -29,19 +30,19 @@ #include "version.h" -SysLog::SysLog() +xmrig::SysLog::SysLog() { openlog(APP_ID, LOG_PID, LOG_USER); } -void SysLog::message(Level level, const char *fmt, va_list args) +void xmrig::SysLog::message(Level level, const char *fmt, va_list args) { vsyslog(static_cast(level), fmt, args); } -void SysLog::text(const char *fmt, va_list args) +void xmrig::SysLog::text(const char *fmt, va_list args) { vsyslog(LOG_INFO, fmt, args); } diff --git a/src/common/log/SysLog.h b/src/common/log/SysLog.h index 5cfeefcd..3e64cf8b 100644 --- a/src/common/log/SysLog.h +++ b/src/common/log/SysLog.h @@ -5,7 +5,8 @@ * Copyright 2014-2016 Wolf9466 * Copyright 2016 Jay D Dee * Copyright 2017-2018 XMR-Stak , - * Copyright 2016-2018 XMRig , + * Copyright 2018-2019 SChernykh + * Copyright 2016-2019 XMRig , * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -21,13 +22,16 @@ * along with this program. If not, see . */ -#ifndef __SYSLOG_H__ -#define __SYSLOG_H__ +#ifndef XMRIG_SYSLOG_H +#define XMRIG_SYSLOG_H #include "common/interfaces/ILogBackend.h" +namespace xmrig { + + class SysLog : public ILogBackend { public: @@ -37,4 +41,8 @@ public: void text(const char *fmt, va_list args) override; }; -#endif /* __SYSLOG_BACKEND_H__ */ + +} /* namespace xmrig */ + + +#endif /* XMRIG_SYSLOG_H */ diff --git a/src/core/Controller.cpp b/src/core/Controller.cpp index 7639bfaa..cfd132dd 100644 --- a/src/core/Controller.cpp +++ b/src/core/Controller.cpp @@ -75,8 +75,6 @@ xmrig::Controller::Controller(Process *process) xmrig::Controller::~Controller() { - ConfigLoader::release(); - delete d_ptr; } @@ -109,11 +107,11 @@ int xmrig::Controller::init() Platform::setProcessPriority(d_ptr->config->priority()); if (!config()->isBackground()) { - Log::add(new ConsoleLog(this)); + Log::add(new ConsoleLog()); } if (config()->logFile()) { - Log::add(new FileLog(this, config()->logFile())); + Log::add(new FileLog(config()->logFile())); } # ifdef HAVE_SYSLOG_H @@ -166,3 +164,12 @@ void xmrig::Controller::onNewConfig(IConfig *config) delete previousConfig; } + + +void xmrig::Controller::stop() +{ + ConfigLoader::release(); + + delete d_ptr->network; + d_ptr->network = nullptr; +} diff --git a/src/core/Controller.h b/src/core/Controller.h index 8d2f2674..7c74b53c 100644 --- a/src/core/Controller.h +++ b/src/core/Controller.h @@ -54,6 +54,7 @@ public: Network *network() const; void addListener(IControllerListener *listener); void save(); + void stop(); protected: void onNewConfig(IConfig *config) override; diff --git a/src/net/Network.cpp b/src/net/Network.cpp index b8f4f05e..efadb365 100644 --- a/src/net/Network.cpp +++ b/src/net/Network.cpp @@ -35,6 +35,7 @@ #include "base/net/stratum/Client.h" #include "base/net/stratum/SubmitResult.h" #include "base/tools/Chrono.h" +#include "base/tools/Handle.h" #include "common/log/Log.h" #include "core/Config.h" #include "core/Controller.h" @@ -44,7 +45,8 @@ xmrig::Network::Network(Controller *controller) : - m_donate(nullptr) + m_donate(nullptr), + m_timer(nullptr) { Workers::setListener(this); controller->addListener(this); @@ -56,15 +58,21 @@ xmrig::Network::Network(Controller *controller) : m_donate = new DonateStrategy(controller->config()->donateLevel(), pools.data().front().user(), controller->config()->algorithm().algo(), this); } - m_timer.data = this; - uv_timer_init(uv_default_loop(), &m_timer); - - uv_timer_start(&m_timer, Network::onTick, kTickInterval, kTickInterval); + m_timer = new uv_timer_t; + m_timer->data = this; + uv_timer_init(uv_default_loop(), m_timer); + uv_timer_start(m_timer, Network::onTick, kTickInterval, kTickInterval); } xmrig::Network::~Network() { + Handle::close(m_timer); + + if (m_donate) { + delete m_donate; + } + delete m_strategy; } @@ -75,16 +83,6 @@ void xmrig::Network::connect() } -void xmrig::Network::stop() -{ - if (m_donate) { - m_donate->stop(); - } - - m_strategy->stop(); -} - - void xmrig::Network::onActive(IStrategy *strategy, Client *client) { if (m_donate && m_donate == strategy) { diff --git a/src/net/Network.h b/src/net/Network.h index 8796045a..e83e60e2 100644 --- a/src/net/Network.h +++ b/src/net/Network.h @@ -50,7 +50,6 @@ public: ~Network() override; void connect(); - void stop(); protected: void onActive(IStrategy *strategy, Client *client) override; @@ -72,7 +71,7 @@ private: IStrategy *m_donate; IStrategy *m_strategy; NetworkState m_state; - uv_timer_t m_timer; + uv_timer_t *m_timer; }; diff --git a/src/net/strategies/DonateStrategy.cpp b/src/net/strategies/DonateStrategy.cpp index ba544c4b..7d08fb33 100644 --- a/src/net/strategies/DonateStrategy.cpp +++ b/src/net/strategies/DonateStrategy.cpp @@ -28,6 +28,7 @@ #include "base/net/stratum/strategies/FailoverStrategy.h" #include "base/net/stratum/strategies/SinglePoolStrategy.h" #include "base/tools/Buffer.h" +#include "base/tools/Handle.h" #include "common/crypto/keccak.h" #include "common/Platform.h" #include "common/xmrig.h" @@ -71,8 +72,9 @@ xmrig::DonateStrategy::DonateStrategy(int level, const char *user, Algo algo, IS m_strategy = new SinglePoolStrategy(m_pools.front(), 1, 2, this, true); } - m_timer.data = this; - uv_timer_init(uv_default_loop(), &m_timer); + m_timer = new uv_timer_t; + m_timer->data = this; + uv_timer_init(uv_default_loop(), m_timer); idle(m_idleTime * randomf(0.5, 1.5)); } @@ -80,6 +82,7 @@ xmrig::DonateStrategy::DonateStrategy(int level, const char *user, Algo algo, IS xmrig::DonateStrategy::~DonateStrategy() { + Handle::close(m_timer); delete m_strategy; } @@ -104,7 +107,7 @@ void xmrig::DonateStrategy::setAlgo(const xmrig::Algorithm &algo) void xmrig::DonateStrategy::stop() { - uv_timer_stop(&m_timer); + uv_timer_stop(m_timer); m_strategy->stop(); } @@ -125,7 +128,7 @@ void xmrig::DonateStrategy::tick(uint64_t now) void xmrig::DonateStrategy::onActive(IStrategy *strategy, Client *client) { if (!isActive()) { - uv_timer_start(&m_timer, DonateStrategy::onTimer, m_donateTime, 0); + uv_timer_start(m_timer, DonateStrategy::onTimer, m_donateTime, 0); } m_active = true; @@ -154,7 +157,7 @@ void xmrig::DonateStrategy::onResultAccepted(IStrategy *strategy, Client *client void xmrig::DonateStrategy::idle(uint64_t timeout) { - uv_timer_start(&m_timer, DonateStrategy::onTimer, timeout, 0); + uv_timer_start(m_timer, DonateStrategy::onTimer, timeout, 0); } diff --git a/src/net/strategies/DonateStrategy.h b/src/net/strategies/DonateStrategy.h index 8c350097..ab898332 100644 --- a/src/net/strategies/DonateStrategy.h +++ b/src/net/strategies/DonateStrategy.h @@ -79,7 +79,7 @@ private: std::vector m_pools; uint64_t m_now; uint64_t m_stop; - uv_timer_t m_timer; + uv_timer_t *m_timer; }; diff --git a/src/workers/Hashrate.cpp b/src/workers/Hashrate.cpp index 2a750318..591b719a 100644 --- a/src/workers/Hashrate.cpp +++ b/src/workers/Hashrate.cpp @@ -5,7 +5,8 @@ * Copyright 2014-2016 Wolf9466 * Copyright 2016 Jay D Dee * Copyright 2017-2018 XMR-Stak , - * Copyright 2016-2018 XMRig , + * Copyright 2018-2019 SChernykh + * Copyright 2016-2019 XMRig , * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -29,6 +30,7 @@ #include +#include "base/tools/Handle.h" #include "common/log/Log.h" #include "core/Config.h" #include "core/Controller.h" @@ -49,6 +51,7 @@ inline static const char *format(double h, char *buf, size_t size) Hashrate::Hashrate(size_t threads, xmrig::Controller *controller) : m_highest(0.0), m_threads(threads), + m_timer(nullptr), m_controller(controller) { m_counts = new uint64_t*[threads]; @@ -64,10 +67,11 @@ Hashrate::Hashrate(size_t threads, xmrig::Controller *controller) : const int printTime = controller->config()->printTime(); if (printTime > 0) { - uv_timer_init(uv_default_loop(), &m_timer); - m_timer.data = this; + m_timer = new uv_timer_t; + uv_timer_init(uv_default_loop(), m_timer); + m_timer->data = this; - uv_timer_start(&m_timer, Hashrate::onReport, (printTime + 4) * 1000, printTime * 1000); + uv_timer_start(m_timer, Hashrate::onReport, (printTime + 4) * 1000, printTime * 1000); } } @@ -171,7 +175,8 @@ void Hashrate::print() const void Hashrate::stop() { - uv_timer_stop(&m_timer); + xmrig::Handle::close(m_timer); + m_timer = nullptr; } diff --git a/src/workers/Hashrate.h b/src/workers/Hashrate.h index e766f117..673c6a51 100644 --- a/src/workers/Hashrate.h +++ b/src/workers/Hashrate.h @@ -5,7 +5,8 @@ * Copyright 2014-2016 Wolf9466 * Copyright 2016 Jay D Dee * Copyright 2017-2018 XMR-Stak , - * Copyright 2016-2018 XMRig , + * Copyright 2018-2019 SChernykh + * Copyright 2016-2019 XMRig , * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -21,8 +22,8 @@ * along with this program. If not, see . */ -#ifndef __HASHRATE_H__ -#define __HASHRATE_H__ +#ifndef XMRIG_HASHRATE_H +#define XMRIG_HASHRATE_H #include @@ -67,9 +68,9 @@ private: uint32_t* m_top; uint64_t** m_counts; uint64_t** m_timestamps; - uv_timer_t m_timer; + uv_timer_t *m_timer; xmrig::Controller *m_controller; }; -#endif /* __HASHRATE_H__ */ +#endif /* XMRIG_HASHRATE_H */ diff --git a/src/workers/MultiWorker.cpp b/src/workers/MultiWorker.cpp index 02eec378..b3c4882b 100644 --- a/src/workers/MultiWorker.cpp +++ b/src/workers/MultiWorker.cpp @@ -35,7 +35,7 @@ template -MultiWorker::MultiWorker(Handle *handle) +MultiWorker::MultiWorker(ThreadHandle *handle) : Worker(handle) { m_memory = Mem::create(m_ctx, m_thread->algorithm(), N); diff --git a/src/workers/MultiWorker.h b/src/workers/MultiWorker.h index 525eee18..99d37e44 100644 --- a/src/workers/MultiWorker.h +++ b/src/workers/MultiWorker.h @@ -40,7 +40,7 @@ template class MultiWorker : public Worker { public: - MultiWorker(Handle *handle); + MultiWorker(ThreadHandle *handle); ~MultiWorker(); protected: diff --git a/src/workers/Handle.cpp b/src/workers/ThreadHandle.cpp similarity index 79% rename from src/workers/Handle.cpp rename to src/workers/ThreadHandle.cpp index d42ea368..43ff950c 100644 --- a/src/workers/Handle.cpp +++ b/src/workers/ThreadHandle.cpp @@ -5,7 +5,8 @@ * Copyright 2014-2016 Wolf9466 * Copyright 2016 Jay D Dee * Copyright 2017-2018 XMR-Stak , - * Copyright 2016-2018 XMRig , + * Copyright 2018-2019 SChernykh + * Copyright 2016-2019 XMRig , * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -22,10 +23,10 @@ */ -#include "workers/Handle.h" +#include "workers/ThreadHandle.h" -Handle::Handle(xmrig::IThread *config, uint32_t offset, size_t totalWays) : +ThreadHandle::ThreadHandle(xmrig::IThread *config, uint32_t offset, size_t totalWays) : m_worker(nullptr), m_totalWays(totalWays), m_offset(offset), @@ -34,13 +35,13 @@ Handle::Handle(xmrig::IThread *config, uint32_t offset, size_t totalWays) : } -void Handle::join() +void ThreadHandle::join() { uv_thread_join(&m_thread); } -void Handle::start(void (*callback) (void *)) +void ThreadHandle::start(void (*callback) (void *)) { uv_thread_create(&m_thread, callback, this); } diff --git a/src/workers/Handle.h b/src/workers/ThreadHandle.h similarity index 85% rename from src/workers/Handle.h rename to src/workers/ThreadHandle.h index 4bb899f9..f3e09ce5 100644 --- a/src/workers/Handle.h +++ b/src/workers/ThreadHandle.h @@ -5,7 +5,8 @@ * Copyright 2014-2016 Wolf9466 * Copyright 2016 Jay D Dee * Copyright 2017-2018 XMR-Stak , - * Copyright 2016-2018 XMRig , + * Copyright 2018-2019 SChernykh + * Copyright 2016-2019 XMRig , * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -21,8 +22,8 @@ * along with this program. If not, see . */ -#ifndef __HANDLE_H__ -#define __HANDLE_H__ +#ifndef XMRIG_THREADHANDLE_H +#define XMRIG_THREADHANDLE_H #include @@ -36,10 +37,10 @@ class IWorker; -class Handle +class ThreadHandle { public: - Handle(xmrig::IThread *config, uint32_t offset, size_t totalWays); + ThreadHandle(xmrig::IThread *config, uint32_t offset, size_t totalWays); void join(); void start(void (*callback) (void *)); @@ -59,4 +60,4 @@ private: }; -#endif /* __HANDLE_H__ */ +#endif /* XMRIG_THREADHANDLE_H */ diff --git a/src/workers/Worker.cpp b/src/workers/Worker.cpp index c569908c..234e7bfd 100644 --- a/src/workers/Worker.cpp +++ b/src/workers/Worker.cpp @@ -27,11 +27,11 @@ #include "common/cpu/Cpu.h" #include "common/Platform.h" #include "workers/CpuThread.h" -#include "workers/Handle.h" +#include "workers/ThreadHandle.h" #include "workers/Worker.h" -Worker::Worker(Handle *handle) : +Worker::Worker(ThreadHandle *handle) : m_id(handle->threadId()), m_totalWays(handle->totalWays()), m_offset(handle->offset()), diff --git a/src/workers/Worker.h b/src/workers/Worker.h index 73e25033..4710bcc5 100644 --- a/src/workers/Worker.h +++ b/src/workers/Worker.h @@ -33,7 +33,7 @@ #include "Mem.h" -class Handle; +class ThreadHandle; namespace xmrig { @@ -44,7 +44,7 @@ namespace xmrig { class Worker : public IWorker { public: - Worker(Handle *handle); + Worker(ThreadHandle *handle); inline const MemInfo &memory() const { return m_memory; } inline size_t id() const override { return m_id; } diff --git a/src/workers/Workers.cpp b/src/workers/Workers.cpp index f718a52c..5426762e 100644 --- a/src/workers/Workers.cpp +++ b/src/workers/Workers.cpp @@ -28,6 +28,7 @@ #include "api/Api.h" +#include "base/tools/Handle.h" #include "common/log/Log.h" #include "core/Config.h" #include "core/Controller.h" @@ -36,9 +37,9 @@ #include "interfaces/IThread.h" #include "Mem.h" #include "rapidjson/document.h" -#include "workers/Handle.h" #include "workers/Hashrate.h" #include "workers/MultiWorker.h" +#include "workers/ThreadHandle.h" #include "workers/Workers.h" @@ -51,12 +52,12 @@ Workers::LaunchStatus Workers::m_status; std::atomic Workers::m_paused; std::atomic Workers::m_sequence; std::list Workers::m_queue; -std::vector Workers::m_workers; +std::vector Workers::m_workers; uint64_t Workers::m_ticks = 0; -uv_async_t Workers::m_async; +uv_async_t *Workers::m_async = nullptr; uv_mutex_t Workers::m_mutex; uv_rwlock_t Workers::m_rwlock; -uv_timer_t Workers::m_timer; +uv_timer_t *Workers::m_timer = nullptr; xmrig::Controller *Workers::m_controller = nullptr; @@ -103,11 +104,11 @@ void Workers::printHashrate(bool detail) char num2[8] = { 0 }; char num3[8] = { 0 }; - Log::i()->text("%s| THREAD | AFFINITY | 10s H/s | 60s H/s | 15m H/s |", isColors ? "\x1B[1;37m" : ""); + xmrig::Log::i()->text("%s| THREAD | AFFINITY | 10s H/s | 60s H/s | 15m H/s |", isColors ? "\x1B[1;37m" : ""); size_t i = 0; for (const xmrig::IThread *thread : m_controller->config()->threads()) { - Log::i()->text("| %6zu | %8" PRId64 " | %7s | %7s | %7s |", + xmrig::Log::i()->text("| %6zu | %8" PRId64 " | %7s | %7s | %7s |", thread->index(), thread->affinity(), Hashrate::format(m_hashrate->calc(thread->index(), Hashrate::ShortInterval), num1, sizeof num1), @@ -192,14 +193,17 @@ void Workers::start(xmrig::Controller *controller) m_sequence = 1; m_paused = 1; - uv_async_init(uv_default_loop(), &m_async, Workers::onResult); - uv_timer_init(uv_default_loop(), &m_timer); - uv_timer_start(&m_timer, Workers::onTick, 500, 500); + m_async = new uv_async_t; + uv_async_init(uv_default_loop(), m_async, Workers::onResult); + + m_timer = new uv_timer_t; + uv_timer_init(uv_default_loop(), m_timer); + uv_timer_start(m_timer, Workers::onTick, 500, 500); uint32_t offset = 0; for (xmrig::IThread *thread : threads) { - Handle *handle = new Handle(thread, offset, m_status.ways); + ThreadHandle *handle = new ThreadHandle(thread, offset, m_status.ways); offset += thread->multiway(); m_workers.push_back(handle); @@ -212,10 +216,10 @@ void Workers::start(xmrig::Controller *controller) void Workers::stop() { - uv_timer_stop(&m_timer); + xmrig::Handle::close(m_timer); + xmrig::Handle::close(m_async); m_hashrate->stop(); - uv_close(reinterpret_cast(&m_async), nullptr); m_paused = 0; m_sequence = 0; @@ -231,7 +235,7 @@ void Workers::submit(const xmrig::JobResult &result) m_queue.push_back(result); uv_mutex_unlock(&m_mutex); - uv_async_send(&m_async); + uv_async_send(m_async); } @@ -257,7 +261,7 @@ void Workers::threadsSummary(rapidjson::Document &doc) void Workers::onReady(void *arg) { - auto handle = static_cast(arg); + auto handle = static_cast(arg); IWorker *worker = nullptr; @@ -319,7 +323,7 @@ void Workers::onResult(uv_async_t *handle) void Workers::onTick(uv_timer_t *handle) { - for (Handle *handle : m_workers) { + for (ThreadHandle *handle : m_workers) { if (!handle->worker()) { return; } diff --git a/src/workers/Workers.h b/src/workers/Workers.h index 0760c98f..23b0a27c 100644 --- a/src/workers/Workers.h +++ b/src/workers/Workers.h @@ -36,9 +36,9 @@ #include "rapidjson/fwd.h" -class Handle; class Hashrate; class IWorker; +class ThreadHandle; namespace xmrig { @@ -109,12 +109,12 @@ private: static std::atomic m_paused; static std::atomic m_sequence; static std::list m_queue; - static std::vector m_workers; + static std::vector m_workers; static uint64_t m_ticks; - static uv_async_t m_async; + static uv_async_t *m_async; static uv_mutex_t m_mutex; static uv_rwlock_t m_rwlock; - static uv_timer_t m_timer; + static uv_timer_t *m_timer; static xmrig::Controller *m_controller; }; From 0d86e53a32fb62e6fa177b2bc67094d0fa92b26b Mon Sep 17 00:00:00 2001 From: XMRig Date: Sat, 16 Mar 2019 02:07:26 +0700 Subject: [PATCH 014/116] Move files. --- CMakeLists.txt | 58 ++---------------- cmake/OpenSSL.cmake | 4 ++ src/App.cpp | 2 +- src/App.h | 2 +- src/base/base.cmake | 60 +++++++++++++++++++ src/{common => base/io}/Console.cpp | 4 +- src/{common => base/io}/Console.h | 0 .../kernel}/interfaces/IConsoleListener.h | 0 src/common/utils/c_str.h | 39 ------------ src/common/utils/timestamp.h | 55 ----------------- 10 files changed, 74 insertions(+), 150 deletions(-) create mode 100644 src/base/base.cmake rename src/{common => base/io}/Console.cpp (96%) rename src/{common => base/io}/Console.h (100%) rename src/{common => base/kernel}/interfaces/IConsoleListener.h (100%) delete mode 100644 src/common/utils/c_str.h delete mode 100644 src/common/utils/timestamp.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 1f87a85d..c8e68648 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -16,50 +16,21 @@ option(WITH_EMBEDDED_CONFIG "Enable internal embedded JSON config" OFF) include (CheckIncludeFile) include (cmake/cpu.cmake) +include (src/base/base.cmake) set(HEADERS + "${HEADERS_BASE}" src/api/NetworkState.h src/App.h - src/base/io/Json.h - src/base/io/Watcher.h - src/base/kernel/Entry.h - src/base/kernel/interfaces/IClientListener.h - src/base/kernel/interfaces/IConfigListener.h - src/base/kernel/interfaces/IDnsListener.h - src/base/kernel/interfaces/ILineListener.h - src/base/kernel/interfaces/ISignalListener.h - src/base/kernel/interfaces/IStrategy.h - src/base/kernel/interfaces/IStrategyListener.h - src/base/kernel/interfaces/IWatcherListener.h - src/base/kernel/Process.h - src/base/kernel/Signals.h - src/base/net/dns/Dns.h - src/base/net/dns/DnsRecord.h - src/base/net/stratum/Client.h - src/base/net/stratum/Job.h - src/base/net/stratum/Pool.h - src/base/net/stratum/Pools.h - src/base/net/stratum/strategies/FailoverStrategy.h - src/base/net/stratum/strategies/SinglePoolStrategy.h - src/base/net/stratum/SubmitResult.h - src/base/net/tools/RecvBuf.h - src/base/net/tools/Storage.h - src/base/tools/Arguments.h - src/base/tools/Buffer.h - src/base/tools/Chrono.h - src/base/tools/Handle.h - src/base/tools/String.h src/common/config/CommonConfig.h src/common/config/ConfigLoader.h src/common/config/ConfigWatcher.h - src/common/Console.h src/common/cpu/Cpu.h src/common/crypto/Algorithm.h src/common/crypto/keccak.h src/common/interfaces/IConfig.h src/common/interfaces/IConfigCreator.h - src/common/interfaces/IConsoleListener.h src/common/interfaces/IControllerListener.h src/common/interfaces/ICpuInfo.h src/common/interfaces/ILogBackend.h @@ -68,7 +39,6 @@ set(HEADERS src/common/log/FileLog.h src/common/log/Log.h src/common/Platform.h - src/common/utils/c_str.h src/common/utils/mm_malloc.h src/common/xmrig.h src/core/ConfigLoader_default.h @@ -114,28 +84,12 @@ else() endif() set(SOURCES + "${SOURCES_BASE}" src/api/NetworkState.cpp src/App.cpp - src/base/io/Json.cpp - src/base/io/Watcher.cpp - src/base/kernel/Entry.cpp - src/base/kernel/Process.cpp - src/base/kernel/Signals.cpp - src/base/net/dns/Dns.cpp - src/base/net/dns/DnsRecord.cpp - src/base/net/stratum/Client.cpp - src/base/net/stratum/Job.cpp - src/base/net/stratum/Pool.cpp - src/base/net/stratum/Pools.cpp - src/base/net/stratum/strategies/FailoverStrategy.cpp - src/base/net/stratum/strategies/SinglePoolStrategy.cpp - src/base/tools/Arguments.cpp - src/base/tools/Buffer.cpp - src/base/tools/String.cpp src/common/config/CommonConfig.cpp src/common/config/ConfigLoader.cpp src/common/config/ConfigWatcher.cpp - src/common/Console.cpp src/common/crypto/Algorithm.cpp src/common/crypto/keccak.cpp src/common/log/BasicLog.cpp @@ -167,9 +121,9 @@ set(SOURCES_CRYPTO if (WIN32) set(SOURCES_OS + "${SOURCES_OS}" res/app.rc src/App_win.cpp - src/base/io/Json_win.cpp src/common/Platform_win.cpp src/Mem_win.cpp ) @@ -178,15 +132,15 @@ if (WIN32) set(EXTRA_LIBS ws2_32 psapi iphlpapi userenv) elseif (APPLE) set(SOURCES_OS + "${SOURCES_OS}" src/App_unix.cpp - src/base/io/Json_unix.cpp src/common/Platform_mac.cpp src/Mem_unix.cpp ) else() set(SOURCES_OS + "${SOURCES_OS}" src/App_unix.cpp - src/base/io/Json_unix.cpp src/common/Platform_unix.cpp src/Mem_unix.cpp ) diff --git a/cmake/OpenSSL.cmake b/cmake/OpenSSL.cmake index 5761f99f..219d50b9 100644 --- a/cmake/OpenSSL.cmake +++ b/cmake/OpenSSL.cmake @@ -16,9 +16,13 @@ if (WITH_TLS) else() message(FATAL_ERROR "OpenSSL NOT found: use `-DWITH_TLS=OFF` to build without TLS support") endif() + + add_definitions(/DXMRIG_FEATURE_TLS) + remove_definitions(/DXMRIG_NO_TLS) else() set(TLS_SOURCES "") set(OPENSSL_LIBRARIES "") + remove_definitions(/DXMRIG_FEATURE_TLS) add_definitions(/DXMRIG_NO_TLS) set(CMAKE_PROJECT_NAME "${CMAKE_PROJECT_NAME}-notls") diff --git a/src/App.cpp b/src/App.cpp index 62dd3814..500a521d 100644 --- a/src/App.cpp +++ b/src/App.cpp @@ -30,8 +30,8 @@ #include "api/Api.h" #include "App.h" +#include "base/io/Console.h" #include "base/kernel/Signals.h" -#include "common/Console.h" #include "common/cpu/Cpu.h" #include "common/log/Log.h" #include "common/Platform.h" diff --git a/src/App.h b/src/App.h index 02cc61a2..21e57725 100644 --- a/src/App.h +++ b/src/App.h @@ -27,8 +27,8 @@ #define XMRIG_APP_H +#include "base/kernel/interfaces/IConsoleListener.h" #include "base/kernel/interfaces/ISignalListener.h" -#include "common/interfaces/IConsoleListener.h" class Httpd; diff --git a/src/base/base.cmake b/src/base/base.cmake new file mode 100644 index 00000000..79181f05 --- /dev/null +++ b/src/base/base.cmake @@ -0,0 +1,60 @@ +set(HEADERS_BASE + src/base/io/Console.h + src/base/io/Json.h + src/base/io/Watcher.h + src/base/kernel/Entry.h + src/base/kernel/interfaces/IClientListener.h + src/base/kernel/interfaces/IConfigListener.h + src/base/kernel/interfaces/IConsoleListener.h + src/base/kernel/interfaces/IDnsListener.h + src/base/kernel/interfaces/ILineListener.h + src/base/kernel/interfaces/ISignalListener.h + src/base/kernel/interfaces/IStrategy.h + src/base/kernel/interfaces/IStrategyListener.h + src/base/kernel/interfaces/IWatcherListener.h + src/base/kernel/Process.h + src/base/kernel/Signals.h + src/base/net/dns/Dns.h + src/base/net/dns/DnsRecord.h + src/base/net/stratum/Client.h + src/base/net/stratum/Job.h + src/base/net/stratum/Pool.h + src/base/net/stratum/Pools.h + src/base/net/stratum/strategies/FailoverStrategy.h + src/base/net/stratum/strategies/SinglePoolStrategy.h + src/base/net/stratum/SubmitResult.h + src/base/net/tools/RecvBuf.h + src/base/net/tools/Storage.h + src/base/tools/Arguments.h + src/base/tools/Buffer.h + src/base/tools/Chrono.h + src/base/tools/Handle.h + src/base/tools/String.h + ) + +set(SOURCES_BASE + src/base/io/Console.cpp + src/base/io/Json.cpp + src/base/io/Watcher.cpp + src/base/kernel/Entry.cpp + src/base/kernel/Process.cpp + src/base/kernel/Signals.cpp + src/base/net/dns/Dns.cpp + src/base/net/dns/DnsRecord.cpp + src/base/net/stratum/Client.cpp + src/base/net/stratum/Job.cpp + src/base/net/stratum/Pool.cpp + src/base/net/stratum/Pools.cpp + src/base/net/stratum/strategies/FailoverStrategy.cpp + src/base/net/stratum/strategies/SinglePoolStrategy.cpp + src/base/tools/Arguments.cpp + src/base/tools/Buffer.cpp + src/base/tools/String.cpp + ) + + +if (WIN32) + set(SOURCES_OS src/base/io/Json_win.cpp) +else() + set(SOURCES_OS src/base/io/Json_unix.cpp) +endif() diff --git a/src/common/Console.cpp b/src/base/io/Console.cpp similarity index 96% rename from src/common/Console.cpp rename to src/base/io/Console.cpp index 8e5d7285..cb23c4b0 100644 --- a/src/common/Console.cpp +++ b/src/base/io/Console.cpp @@ -23,9 +23,9 @@ */ +#include "base/io/Console.h" +#include "base/kernel/interfaces/IConsoleListener.h" #include "base/tools/Handle.h" -#include "common/Console.h" -#include "interfaces/IConsoleListener.h" xmrig::Console::Console(IConsoleListener *listener) diff --git a/src/common/Console.h b/src/base/io/Console.h similarity index 100% rename from src/common/Console.h rename to src/base/io/Console.h diff --git a/src/common/interfaces/IConsoleListener.h b/src/base/kernel/interfaces/IConsoleListener.h similarity index 100% rename from src/common/interfaces/IConsoleListener.h rename to src/base/kernel/interfaces/IConsoleListener.h diff --git a/src/common/utils/c_str.h b/src/common/utils/c_str.h deleted file mode 100644 index fe0164b9..00000000 --- a/src/common/utils/c_str.h +++ /dev/null @@ -1,39 +0,0 @@ -/* XMRig - * Copyright 2010 Jeff Garzik - * Copyright 2012-2014 pooler - * Copyright 2014 Lucas Jones - * Copyright 2014-2016 Wolf9466 - * Copyright 2016 Jay D Dee - * Copyright 2017-2018 XMR-Stak , - * Copyright 2016-2018 XMRig , - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#ifndef XMRIG_C_STR_H -#define XMRIG_C_STR_H - - -#include "base/tools/String.h" - - -namespace xmrig { - - -typedef String c_str; - - -} /* namespace xmrig */ - -#endif /* XMRIG_C_STR_H */ diff --git a/src/common/utils/timestamp.h b/src/common/utils/timestamp.h deleted file mode 100644 index 7fc4ab50..00000000 --- a/src/common/utils/timestamp.h +++ /dev/null @@ -1,55 +0,0 @@ -/* XMRig - * Copyright 2010 Jeff Garzik - * Copyright 2012-2014 pooler - * Copyright 2014 Lucas Jones - * Copyright 2014-2016 Wolf9466 - * Copyright 2016 Jay D Dee - * Copyright 2017-2018 XMR-Stak , - * Copyright 2016-2018 XMRig , - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#ifndef XMRIG_TIMESTAMP_H -#define XMRIG_TIMESTAMP_H - - -#include - - -namespace xmrig { - - -static inline int64_t steadyTimestamp() -{ - using namespace std::chrono; - if (high_resolution_clock::is_steady) { - return time_point_cast(high_resolution_clock::now()).time_since_epoch().count(); - } - - return time_point_cast(steady_clock::now()).time_since_epoch().count(); -} - - -static inline int64_t currentMSecsSinceEpoch() -{ - using namespace std::chrono; - - return time_point_cast(high_resolution_clock::now()).time_since_epoch().count(); -} - - -} /* namespace xmrig */ - -#endif /* XMRIG_TIMESTAMP_H */ From 1b9fbf11324a0188d631f975de11bceab1b7d83d Mon Sep 17 00:00:00 2001 From: XMRig Date: Sat, 16 Mar 2019 13:10:04 +0700 Subject: [PATCH 015/116] Fix compile issues. --- src/base/net/stratum/Client.cpp | 4 ++-- src/base/net/stratum/Pools.cpp | 4 ++-- src/base/net/stratum/Tls.cpp | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/base/net/stratum/Client.cpp b/src/base/net/stratum/Client.cpp index 0693afb7..ab4b934d 100644 --- a/src/base/net/stratum/Client.cpp +++ b/src/base/net/stratum/Client.cpp @@ -261,7 +261,7 @@ int64_t xmrig::Client::submit(const JobResult &result) void xmrig::Client::onResolved(const Dns &dns, int status) { - assert(client->m_listener != nullptr); + assert(m_listener != nullptr); if (!m_listener) { return reconnect(); } @@ -846,7 +846,7 @@ void xmrig::Client::read(ssize_t nread) return; } - assert(client->m_listener != nullptr); + assert(m_listener != nullptr); if (!m_listener) { return reconnect(); } diff --git a/src/base/net/stratum/Pools.cpp b/src/base/net/stratum/Pools.cpp index ba55e94b..7a738cf0 100644 --- a/src/base/net/stratum/Pools.cpp +++ b/src/base/net/stratum/Pools.cpp @@ -164,7 +164,7 @@ void xmrig::Pools::print() const Log::i()->text(GREEN_BOLD(" * ") WHITE_BOLD("POOL #%-7zu") "\x1B[1;%dm%s\x1B[0m variant " WHITE_BOLD("%s"), i, color, - pool.url(), + pool.url().data(), pool.algorithm().variantName() ); } @@ -172,7 +172,7 @@ void xmrig::Pools::print() const Log::i()->text(" * POOL #%-7zu%s%s variant=%s %s", i, pool.isEnabled() ? "" : "-", - pool.url(), + pool.url().data(), pool.algorithm().variantName(), pool.isTLS() ? "TLS" : "" ); diff --git a/src/base/net/stratum/Tls.cpp b/src/base/net/stratum/Tls.cpp index e96d9946..d92d7e54 100644 --- a/src/base/net/stratum/Tls.cpp +++ b/src/base/net/stratum/Tls.cpp @@ -150,13 +150,13 @@ bool xmrig::Client::Tls::send() bool xmrig::Client::Tls::verify(X509 *cert) { if (cert == nullptr) { - LOG_ERR("[%s] Failed to get server certificate", m_client->m_pool.url()); + LOG_ERR("[%s] Failed to get server certificate", m_client->url()); return false; } if (!verifyFingerprint(cert)) { - LOG_ERR("[%s] Failed to verify server certificate fingerprint", m_client->m_pool.url()); + LOG_ERR("[%s] Failed to verify server certificate fingerprint", m_client->url()); const char *fingerprint = m_client->m_pool.fingerprint(); if (strlen(m_fingerprint) == 64 && fingerprint != nullptr) { From c94c0210f74f48a5a634d4df35de11a7ddf61384 Mon Sep 17 00:00:00 2001 From: XMRig Date: Sat, 16 Mar 2019 13:32:00 +0700 Subject: [PATCH 016/116] Fix copy. --- src/base/tools/String.cpp | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/src/base/tools/String.cpp b/src/base/tools/String.cpp index 7ed61d01..9884f0ac 100644 --- a/src/base/tools/String.cpp +++ b/src/base/tools/String.cpp @@ -178,14 +178,10 @@ void xmrig::String::copy(const char *str) void xmrig::String::copy(const String &other) { - if (m_size > 0) { - if (m_size == other.m_size) { - memcpy(m_data, other.m_data, m_size + 1); + if (m_size > 0 && m_size == other.m_size) { + memcpy(m_data, other.m_data, m_size + 1); - return; - } - - delete [] m_data; + return; } delete [] m_data; From bbf0d11a513bd66dbc99fc66231c058de0780571 Mon Sep 17 00:00:00 2001 From: XMRig Date: Sun, 17 Mar 2019 16:03:45 +0700 Subject: [PATCH 017/116] Sync changes. --- src/base/kernel/Process.cpp | 3 --- src/base/tools/Handle.h | 4 ++++ 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/src/base/kernel/Process.cpp b/src/base/kernel/Process.cpp index 7feec481..0bc40e2d 100644 --- a/src/base/kernel/Process.cpp +++ b/src/base/kernel/Process.cpp @@ -28,7 +28,6 @@ #include "base/kernel/Process.h" -#include "version.h" static size_t location(xmrig::Process::Location location, char *buf, size_t max) @@ -52,8 +51,6 @@ xmrig::Process::Process(int argc, char **argv) : m_arguments(argc, argv) { srand(static_cast(static_cast(time(nullptr)) ^ reinterpret_cast(this))); - - uv_set_process_title(APP_DESC " " APP_VERSION); } diff --git a/src/base/tools/Handle.h b/src/base/tools/Handle.h index 980d4500..288c32de 100644 --- a/src/base/tools/Handle.h +++ b/src/base/tools/Handle.h @@ -47,6 +47,10 @@ public: template static inline void deleteLater(T handle) { + if (uv_is_closing(reinterpret_cast(handle))) { + return; + } + uv_close(reinterpret_cast(handle), [](uv_handle_t *handle) { delete handle; }); } }; From 9a6a5a94b5d2da0710d0d27ead53fabc8a59c861 Mon Sep 17 00:00:00 2001 From: XMRig Date: Mon, 18 Mar 2019 02:36:17 +0700 Subject: [PATCH 018/116] Add class Timer. --- src/App.h | 4 +- src/base/base.cmake | 3 + src/base/io/Watcher.cpp | 22 ++--- src/base/io/Watcher.h | 14 ++-- src/base/kernel/interfaces/ITimerListener.h | 47 +++++++++++ src/base/tools/String.cpp | 1 + src/base/tools/String.h | 3 +- src/base/tools/Timer.cpp | 91 +++++++++++++++++++++ src/base/tools/Timer.h | 66 +++++++++++++++ src/common/api/Httpd.cpp | 37 ++++----- src/common/api/Httpd.h | 31 ++++--- src/net/Network.cpp | 15 +--- src/net/Network.h | 10 +-- 13 files changed, 271 insertions(+), 73 deletions(-) create mode 100644 src/base/kernel/interfaces/ITimerListener.h create mode 100644 src/base/tools/Timer.cpp create mode 100644 src/base/tools/Timer.h diff --git a/src/App.h b/src/App.h index 21e57725..86f281e8 100644 --- a/src/App.h +++ b/src/App.h @@ -31,14 +31,12 @@ #include "base/kernel/interfaces/ISignalListener.h" -class Httpd; - - namespace xmrig { class Console; class Controller; +class Httpd; class Network; class Process; class Signals; diff --git a/src/base/base.cmake b/src/base/base.cmake index 79181f05..08d86805 100644 --- a/src/base/base.cmake +++ b/src/base/base.cmake @@ -11,6 +11,7 @@ set(HEADERS_BASE src/base/kernel/interfaces/ISignalListener.h src/base/kernel/interfaces/IStrategy.h src/base/kernel/interfaces/IStrategyListener.h + src/base/kernel/interfaces/ITimerListener.h src/base/kernel/interfaces/IWatcherListener.h src/base/kernel/Process.h src/base/kernel/Signals.h @@ -30,6 +31,7 @@ set(HEADERS_BASE src/base/tools/Chrono.h src/base/tools/Handle.h src/base/tools/String.h + src/base/tools/Timer.h ) set(SOURCES_BASE @@ -50,6 +52,7 @@ set(SOURCES_BASE src/base/tools/Arguments.cpp src/base/tools/Buffer.cpp src/base/tools/String.cpp + src/base/tools/Timer.cpp ) diff --git a/src/base/io/Watcher.cpp b/src/base/io/Watcher.cpp index b8ea4c3b..f5ce9647 100644 --- a/src/base/io/Watcher.cpp +++ b/src/base/io/Watcher.cpp @@ -29,37 +29,31 @@ #include "base/kernel/interfaces/IWatcherListener.h" #include "base/io/Watcher.h" #include "base/tools/Handle.h" +#include "base/tools/Timer.h" xmrig::Watcher::Watcher(const String &path, IWatcherListener *listener) : m_listener(listener), m_path(path) { + m_timer = new Timer(this); + m_fsEvent = new uv_fs_event_t; + m_fsEvent->data = this; uv_fs_event_init(uv_default_loop(), m_fsEvent); - m_timer = new uv_timer_t; - uv_timer_init(uv_default_loop(), m_timer); - - m_fsEvent->data = m_timer->data = this; - start(); } xmrig::Watcher::~Watcher() { - Handle::close(m_timer); + delete m_timer; + Handle::close(m_fsEvent); } -void xmrig::Watcher::onTimer(uv_timer_t *handle) -{ - static_cast(handle->data)->reload(); -} - - void xmrig::Watcher::onFsEvent(uv_fs_event_t *handle, const char *filename, int, int) { if (!filename) { @@ -72,8 +66,8 @@ void xmrig::Watcher::onFsEvent(uv_fs_event_t *handle, const char *filename, int, void xmrig::Watcher::queueUpdate() { - uv_timer_stop(m_timer); - uv_timer_start(m_timer, xmrig::Watcher::onTimer, kDelay, 0); + m_timer->stop(); + m_timer->start(kDelay, 0); } diff --git a/src/base/io/Watcher.h b/src/base/io/Watcher.h index 4fec4c68..6438cb7a 100644 --- a/src/base/io/Watcher.h +++ b/src/base/io/Watcher.h @@ -26,30 +26,33 @@ #define XMRIG_WATCHER_H +#include "base/kernel/interfaces/ITimerListener.h" #include "base/tools/String.h" typedef struct uv_fs_event_s uv_fs_event_t; -typedef struct uv_timer_s uv_timer_t; namespace xmrig { class IWatcherListener; +class Timer; -class Watcher +class Watcher : public ITimerListener { public: Watcher(const String &path, IWatcherListener *listener); - ~Watcher(); + ~Watcher() override; + +protected: + inline void onTimer(const Timer *) override { reload(); } private: constexpr static int kDelay = 500; static void onFsEvent(uv_fs_event_t *handle, const char *filename, int events, int status); - static void onTimer(uv_timer_t *handle); void queueUpdate(); void reload(); @@ -57,11 +60,12 @@ private: IWatcherListener *m_listener; String m_path; + Timer *m_timer; uv_fs_event_t *m_fsEvent; - uv_timer_t *m_timer; }; } /* namespace xmrig */ + #endif /* XMRIG_WATCHER_H */ diff --git a/src/base/kernel/interfaces/ITimerListener.h b/src/base/kernel/interfaces/ITimerListener.h new file mode 100644 index 00000000..1b6337d6 --- /dev/null +++ b/src/base/kernel/interfaces/ITimerListener.h @@ -0,0 +1,47 @@ +/* XMRig + * Copyright 2010 Jeff Garzik + * Copyright 2012-2014 pooler + * Copyright 2014 Lucas Jones + * Copyright 2014-2016 Wolf9466 + * Copyright 2016 Jay D Dee + * Copyright 2017-2018 XMR-Stak , + * Copyright 2018-2019 SChernykh + * Copyright 2016-2019 XMRig , + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef XMRIG_ITIMERLISTENER_H +#define XMRIG_ITIMERLISTENER_H + + +namespace xmrig { + + +class Timer; + + +class ITimerListener +{ +public: + virtual ~ITimerListener() = default; + + virtual void onTimer(const Timer *timer) = 0; +}; + + +} /* namespace xmrig */ + + +#endif // XMRIG_ITIMERLISTENER_H diff --git a/src/base/tools/String.cpp b/src/base/tools/String.cpp index 9884f0ac..c908fe9a 100644 --- a/src/base/tools/String.cpp +++ b/src/base/tools/String.cpp @@ -5,6 +5,7 @@ * Copyright 2014-2016 Wolf9466 * Copyright 2016 Jay D Dee * Copyright 2017-2018 XMR-Stak , + * Copyright 2018-2019 SChernykh * Copyright 2016-2019 XMRig , * * This program is free software: you can redistribute it and/or modify diff --git a/src/base/tools/String.h b/src/base/tools/String.h index 0c191dfd..a640469a 100644 --- a/src/base/tools/String.h +++ b/src/base/tools/String.h @@ -5,7 +5,8 @@ * Copyright 2014-2016 Wolf9466 * Copyright 2016 Jay D Dee * Copyright 2017-2018 XMR-Stak , - * Copyright 2016-2018 XMRig , + * Copyright 2018-2019 SChernykh + * Copyright 2016-2019 XMRig , * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/src/base/tools/Timer.cpp b/src/base/tools/Timer.cpp new file mode 100644 index 00000000..d06df163 --- /dev/null +++ b/src/base/tools/Timer.cpp @@ -0,0 +1,91 @@ +/* XMRig + * Copyright 2010 Jeff Garzik + * Copyright 2012-2014 pooler + * Copyright 2014 Lucas Jones + * Copyright 2014-2016 Wolf9466 + * Copyright 2016 Jay D Dee + * Copyright 2017-2018 XMR-Stak , + * Copyright 2018-2019 SChernykh + * Copyright 2016-2019 XMRig , + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + + +#include "base/kernel/interfaces/ITimerListener.h" +#include "base/tools/Handle.h" +#include "base/tools/Timer.h" + + +xmrig::Timer::Timer(ITimerListener *listener) : + m_listener(listener), + m_timer(nullptr) +{ + init(); +} + + +xmrig::Timer::Timer(ITimerListener *listener, uint64_t timeout, uint64_t repeat) : + m_listener(listener), + m_timer(nullptr) +{ + init(); + start(timeout, repeat); +} + + +xmrig::Timer::~Timer() +{ + Handle::close(m_timer); +} + + +uint64_t xmrig::Timer::repeat() const +{ + return uv_timer_get_repeat(m_timer); +} + + +void xmrig::Timer::setRepeat(uint64_t repeat) +{ + uv_timer_set_repeat(m_timer, repeat); +} + + +void xmrig::Timer::start(uint64_t timeout, uint64_t repeat) +{ + uv_timer_start(m_timer, onTimer, timeout, repeat); +} + + +void xmrig::Timer::stop() +{ + uv_timer_stop(m_timer); +} + + +void xmrig::Timer::init() +{ + m_timer = new uv_timer_t; + m_timer->data = this; + uv_timer_init(uv_default_loop(), m_timer); +} + + +void xmrig::Timer::onTimer(uv_timer_t *handle) +{ + const Timer *timer = static_cast(handle->data); + + timer->m_listener->onTimer(timer); +} diff --git a/src/base/tools/Timer.h b/src/base/tools/Timer.h new file mode 100644 index 00000000..e0e210f5 --- /dev/null +++ b/src/base/tools/Timer.h @@ -0,0 +1,66 @@ +/* XMRig + * Copyright 2010 Jeff Garzik + * Copyright 2012-2014 pooler + * Copyright 2014 Lucas Jones + * Copyright 2014-2016 Wolf9466 + * Copyright 2016 Jay D Dee + * Copyright 2017-2018 XMR-Stak , + * Copyright 2018-2019 SChernykh + * Copyright 2016-2019 XMRig , + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef XMRIG_TIMER_H +#define XMRIG_TIMER_H + + +#include + + +typedef struct uv_timer_s uv_timer_t; + + +namespace xmrig { + + +class ITimerListener; + + +class Timer +{ +public: + Timer(ITimerListener *listener); + Timer(ITimerListener *listener, uint64_t timeout, uint64_t repeat); + ~Timer(); + + uint64_t repeat() const; + void setRepeat(uint64_t repeat); + void start(uint64_t timeout, uint64_t repeat); + void stop(); + +private: + void init(); + + static void onTimer(uv_timer_t *handle); + + ITimerListener *m_listener; + uv_timer_t *m_timer; +}; + + +} /* namespace xmrig */ + + +#endif /* XMRIG_TIMER_H */ diff --git a/src/common/api/Httpd.cpp b/src/common/api/Httpd.cpp index cca2b056..7b5e8578 100644 --- a/src/common/api/Httpd.cpp +++ b/src/common/api/Httpd.cpp @@ -29,13 +29,14 @@ #include "api/Api.h" #include "base/tools/Handle.h" +#include "base/tools/Timer.h" #include "common/api/Httpd.h" #include "common/api/HttpReply.h" #include "common/api/HttpRequest.h" #include "common/log/Log.h" -Httpd::Httpd(int port, const char *accessToken, bool IPv6, bool restricted) : +xmrig::Httpd::Httpd(int port, const char *accessToken, bool IPv6, bool restricted) : m_idle(true), m_IPv6(IPv6), m_restricted(restricted), @@ -43,13 +44,11 @@ Httpd::Httpd(int port, const char *accessToken, bool IPv6, bool restricted) : m_port(port), m_daemon(nullptr) { - m_timer = new uv_timer_t; - uv_timer_init(uv_default_loop(), m_timer); - m_timer->data = this; + m_timer = new Timer(this); } -Httpd::~Httpd() +xmrig::Httpd::~Httpd() { stop(); @@ -61,7 +60,7 @@ Httpd::~Httpd() } -bool Httpd::start() +bool xmrig::Httpd::start() { if (!m_port) { return false; @@ -85,23 +84,23 @@ bool Httpd::start() } # if MHD_VERSION >= 0x00093900 - uv_timer_start(m_timer, Httpd::onTimer, kIdleInterval, kIdleInterval); + m_timer->start(kIdleInterval, kIdleInterval); # else - uv_timer_start(m_timer, Httpd::onTimer, kActiveInterval, kActiveInterval); + m_timer->start(kActiveInterval, kActiveInterval); # endif return true; } -void Httpd::stop() +void xmrig::Httpd::stop() { - xmrig::Handle::close(m_timer); + delete m_timer; m_timer = nullptr; } -int Httpd::process(xmrig::HttpRequest &req) +int xmrig::Httpd::process(HttpRequest &req) { xmrig::HttpReply reply; if (!req.process(m_accessToken, m_restricted, reply)) { @@ -118,27 +117,27 @@ int Httpd::process(xmrig::HttpRequest &req) } -void Httpd::run() +void xmrig::Httpd::run() { MHD_run(m_daemon); # if MHD_VERSION >= 0x00093900 const MHD_DaemonInfo *info = MHD_get_daemon_info(m_daemon, MHD_DAEMON_INFO_CURRENT_CONNECTIONS); if (m_idle && info->num_connections) { - uv_timer_set_repeat(m_timer, kActiveInterval); + m_timer->setRepeat(kActiveInterval); m_idle = false; } else if (!m_idle && !info->num_connections) { - uv_timer_set_repeat(m_timer, kIdleInterval); + m_timer->setRepeat(kIdleInterval); m_idle = true; } # endif } -int Httpd::handler(void *cls, struct MHD_Connection *connection, const char *url, const char *method, const char *version, const char *uploadData, size_t *uploadSize, void **con_cls) +int xmrig::Httpd::handler(void *cls, struct MHD_Connection *connection, const char *url, const char *method, const char *, const char *uploadData, size_t *uploadSize, void **con_cls) { - xmrig::HttpRequest req(connection, url, method, uploadData, uploadSize, con_cls); + HttpRequest req(connection, url, method, uploadData, uploadSize, con_cls); if (req.method() == xmrig::HttpRequest::Options) { return req.end(MHD_HTTP_OK, nullptr); @@ -150,9 +149,3 @@ int Httpd::handler(void *cls, struct MHD_Connection *connection, const char *url return static_cast(cls)->process(req); } - - -void Httpd::onTimer(uv_timer_t *handle) -{ - static_cast(handle->data)->run(); -} diff --git a/src/common/api/Httpd.h b/src/common/api/Httpd.h index 82ca1541..f0b6ce87 100644 --- a/src/common/api/Httpd.h +++ b/src/common/api/Httpd.h @@ -26,7 +26,10 @@ #define XMRIG_HTTPD_H -#include +#include + + +#include "base/kernel/interfaces/ITimerListener.h" struct MHD_Connection; @@ -34,31 +37,33 @@ struct MHD_Daemon; struct MHD_Response; -class UploadCtx; - - namespace xmrig { - class HttpRequest; -} -class Httpd +class HttpRequest; +class Timer; + + +class Httpd : public ITimerListener { public: Httpd(int port, const char *accessToken, bool IPv6, bool restricted); - ~Httpd(); + ~Httpd() override; + bool start(); void stop(); +protected: + void onTimer(const Timer *) override { run(); } + private: constexpr static const int kIdleInterval = 200; constexpr static const int kActiveInterval = 25; - int process(xmrig::HttpRequest &req); + int process(HttpRequest &req); void run(); static int handler(void *cls, MHD_Connection *connection, const char *url, const char *method, const char *version, const char *uploadData, size_t *uploadSize, void **con_cls); - static void onTimer(uv_timer_t *handle); bool m_idle; bool m_IPv6; @@ -66,7 +71,11 @@ private: const char *m_accessToken; const int m_port; MHD_Daemon *m_daemon; - uv_timer_t *m_timer; + Timer *m_timer; }; + +} /* namespace xmrig */ + + #endif /* XMRIG_HTTPD_H */ diff --git a/src/net/Network.cpp b/src/net/Network.cpp index efadb365..61f6080b 100644 --- a/src/net/Network.cpp +++ b/src/net/Network.cpp @@ -35,7 +35,7 @@ #include "base/net/stratum/Client.h" #include "base/net/stratum/SubmitResult.h" #include "base/tools/Chrono.h" -#include "base/tools/Handle.h" +#include "base/tools/Timer.h" #include "common/log/Log.h" #include "core/Config.h" #include "core/Controller.h" @@ -58,16 +58,13 @@ xmrig::Network::Network(Controller *controller) : m_donate = new DonateStrategy(controller->config()->donateLevel(), pools.data().front().user(), controller->config()->algorithm().algo(), this); } - m_timer = new uv_timer_t; - m_timer->data = this; - uv_timer_init(uv_default_loop(), m_timer); - uv_timer_start(m_timer, Network::onTick, kTickInterval, kTickInterval); + m_timer = new Timer(this, kTickInterval, kTickInterval); } xmrig::Network::~Network() { - Handle::close(m_timer); + delete m_timer; if (m_donate) { delete m_donate; @@ -215,9 +212,3 @@ void xmrig::Network::tick() Api::tick(m_state); # endif } - - -void xmrig::Network::onTick(uv_timer_t *handle) -{ - static_cast(handle->data)->tick(); -} diff --git a/src/net/Network.h b/src/net/Network.h index e83e60e2..8afc5492 100644 --- a/src/net/Network.h +++ b/src/net/Network.h @@ -27,11 +27,11 @@ #include -#include #include "api/NetworkState.h" #include "base/kernel/interfaces/IStrategyListener.h" +#include "base/kernel/interfaces/ITimerListener.h" #include "common/interfaces/IControllerListener.h" #include "interfaces/IJobResultListener.h" @@ -43,7 +43,7 @@ class Controller; class IStrategy; -class Network : public IJobResultListener, public IStrategyListener, public IControllerListener +class Network : public IJobResultListener, public IStrategyListener, public IControllerListener, public ITimerListener { public: Network(Controller *controller); @@ -52,6 +52,8 @@ public: void connect(); protected: + inline void onTimer(const Timer *) override { tick(); } + void onActive(IStrategy *strategy, Client *client) override; void onConfigChanged(Config *config, Config *previousConfig) override; void onJob(IStrategy *strategy, Client *client, const Job &job) override; @@ -66,12 +68,10 @@ private: void setJob(Client *client, const Job &job, bool donate); void tick(); - static void onTick(uv_timer_t *handle); - IStrategy *m_donate; IStrategy *m_strategy; NetworkState m_state; - uv_timer_t *m_timer; + Timer *m_timer; }; From 55686c7d57a7a7213f89b3aca8ae34ba769a9c21 Mon Sep 17 00:00:00 2001 From: XMRig Date: Mon, 18 Mar 2019 13:40:56 +0700 Subject: [PATCH 019/116] Use new Timer inside DonateStrategy. --- src/base/kernel/Process.cpp | 3 +- src/net/strategies/DonateStrategy.cpp | 55 +++++++++++++-------------- src/net/strategies/DonateStrategy.h | 6 ++- 3 files changed, 33 insertions(+), 31 deletions(-) diff --git a/src/base/kernel/Process.cpp b/src/base/kernel/Process.cpp index 0bc40e2d..9193d378 100644 --- a/src/base/kernel/Process.cpp +++ b/src/base/kernel/Process.cpp @@ -28,6 +28,7 @@ #include "base/kernel/Process.h" +#include "base/tools/Chrono.h" static size_t location(xmrig::Process::Location location, char *buf, size_t max) @@ -50,7 +51,7 @@ static size_t location(xmrig::Process::Location location, char *buf, size_t max) xmrig::Process::Process(int argc, char **argv) : m_arguments(argc, argv) { - srand(static_cast(static_cast(time(nullptr)) ^ reinterpret_cast(this))); + srand(static_cast(Chrono::currentMSecsSinceEpoch() ^ reinterpret_cast(this))); } diff --git a/src/net/strategies/DonateStrategy.cpp b/src/net/strategies/DonateStrategy.cpp index 7d08fb33..11fca39b 100644 --- a/src/net/strategies/DonateStrategy.cpp +++ b/src/net/strategies/DonateStrategy.cpp @@ -28,22 +28,25 @@ #include "base/net/stratum/strategies/FailoverStrategy.h" #include "base/net/stratum/strategies/SinglePoolStrategy.h" #include "base/tools/Buffer.h" -#include "base/tools/Handle.h" +#include "base/tools/Timer.h" #include "common/crypto/keccak.h" #include "common/Platform.h" #include "common/xmrig.h" #include "net/strategies/DonateStrategy.h" -static inline float randomf(float min, float max) { - return (max - min) * ((((float) rand()) / (float) RAND_MAX)) + min; -} +namespace xmrig { + +static inline double randomf(double min, double max) { return (max - min) * (((static_cast(rand())) / static_cast(RAND_MAX))) + min; } +static inline uint64_t random(uint64_t base, double min, double max) { return static_cast(base * randomf(min, max)); } + +} /* namespace xmrig */ xmrig::DonateStrategy::DonateStrategy(int level, const char *user, Algo algo, IStrategyListener *listener) : m_active(false), - m_donateTime(level * 60 * 1000), - m_idleTime((100 - level) * 60 * 1000), + m_donateTime(static_cast(level) * 60 * 1000), + m_idleTime((100 - static_cast(level)) * 60 * 1000), m_strategy(nullptr), m_listener(listener), m_now(0), @@ -55,7 +58,7 @@ xmrig::DonateStrategy::DonateStrategy(int level, const char *user, Algo algo, IS keccak(reinterpret_cast(user), strlen(user), hash); Buffer::toHex(hash, 32, userId); -# ifndef XMRIG_NO_TLS +# ifdef XMRIG_FEATURE_TLS m_pools.push_back(Pool("donate.ssl.xmrig.com", 443, userId, nullptr, false, true, true)); # endif @@ -72,17 +75,15 @@ xmrig::DonateStrategy::DonateStrategy(int level, const char *user, Algo algo, IS m_strategy = new SinglePoolStrategy(m_pools.front(), 1, 2, this, true); } - m_timer = new uv_timer_t; - m_timer->data = this; - uv_timer_init(uv_default_loop(), m_timer); + m_timer = new Timer(this); - idle(m_idleTime * randomf(0.5, 1.5)); + idle(random(m_idleTime, 0.5, 1.5)); } xmrig::DonateStrategy::~DonateStrategy() { - Handle::close(m_timer); + delete m_timer; delete m_strategy; } @@ -107,7 +108,7 @@ void xmrig::DonateStrategy::setAlgo(const xmrig::Algorithm &algo) void xmrig::DonateStrategy::stop() { - uv_timer_stop(m_timer); + m_timer->stop(); m_strategy->stop(); } @@ -128,7 +129,7 @@ void xmrig::DonateStrategy::tick(uint64_t now) void xmrig::DonateStrategy::onActive(IStrategy *strategy, Client *client) { if (!isActive()) { - uv_timer_start(m_timer, DonateStrategy::onTimer, m_donateTime, 0); + m_timer->start(m_donateTime, 0); } m_active = true; @@ -155,9 +156,19 @@ void xmrig::DonateStrategy::onResultAccepted(IStrategy *strategy, Client *client } +void xmrig::DonateStrategy::onTimer(const Timer *) +{ + if (!isActive()) { + return connect(); + } + + suspend(); +} + + void xmrig::DonateStrategy::idle(uint64_t timeout) { - uv_timer_start(m_timer, DonateStrategy::onTimer, timeout, 0); + m_timer->start(timeout, 0); } @@ -172,17 +183,5 @@ void xmrig::DonateStrategy::suspend() m_active = false; m_listener->onPause(this); - idle(m_idleTime); -} - - -void xmrig::DonateStrategy::onTimer(uv_timer_t *handle) -{ - auto strategy = static_cast(handle->data); - - if (!strategy->isActive()) { - return strategy->connect(); - } - - strategy->suspend(); + idle(random(m_idleTime, 0.8, 1.2)); } diff --git a/src/net/strategies/DonateStrategy.h b/src/net/strategies/DonateStrategy.h index ab898332..b5ea13c8 100644 --- a/src/net/strategies/DonateStrategy.h +++ b/src/net/strategies/DonateStrategy.h @@ -33,6 +33,7 @@ #include "base/kernel/interfaces/IClientListener.h" #include "base/kernel/interfaces/IStrategy.h" #include "base/kernel/interfaces/IStrategyListener.h" +#include "base/kernel/interfaces/ITimerListener.h" #include "base/net/stratum/Pool.h" @@ -43,7 +44,7 @@ class Client; class IStrategyListener; -class DonateStrategy : public IStrategy, public IStrategyListener +class DonateStrategy : public IStrategy, public IStrategyListener, public ITimerListener { public: DonateStrategy(int level, const char *user, Algo algo, IStrategyListener *listener); @@ -64,6 +65,7 @@ protected: void onJob(IStrategy *strategy, Client *client, const Job &job) override; void onPause(IStrategy *strategy) override; void onResultAccepted(IStrategy *strategy, Client *client, const SubmitResult &result, const char *error) override; + void onTimer(const Timer *timer) override; private: void idle(uint64_t timeout); @@ -79,7 +81,7 @@ private: std::vector m_pools; uint64_t m_now; uint64_t m_stop; - uv_timer_t *m_timer; + Timer *m_timer; }; From 0907d1eb0c69521b05b389ac17c376b932ae7bd8 Mon Sep 17 00:00:00 2001 From: XMRig Date: Tue, 19 Mar 2019 00:16:30 +0700 Subject: [PATCH 020/116] Added "donate-over-proxy" option. --- src/Summary.cpp | 8 +- src/api/ApiRouter.cpp | 2 +- src/base/net/stratum/Client.cpp | 5 + src/base/net/stratum/Client.h | 1 + src/base/net/stratum/Pools.cpp | 24 ++++- src/base/net/stratum/Pools.h | 12 +++ src/common/config/CommonConfig.cpp | 10 +- src/common/config/CommonConfig.h | 2 - src/common/interfaces/IConfig.h | 1 + src/config.json | 1 + src/core/Config.cpp | 23 ++--- src/core/ConfigLoader_platform.h | 134 +++++++++++++------------- src/net/Network.cpp | 4 +- src/net/strategies/DonateStrategy.cpp | 117 ++++++++++++++-------- src/net/strategies/DonateStrategy.h | 26 +++-- 15 files changed, 229 insertions(+), 141 deletions(-) diff --git a/src/Summary.cpp b/src/Summary.cpp index 61638019..78d624df 100644 --- a/src/Summary.cpp +++ b/src/Summary.cpp @@ -114,8 +114,8 @@ static void print_threads(xmrig::Config *config) config->threadsCount(), config->algorithm().name(), config->algoVariant(), - config->isColors() && config->donateLevel() == 0 ? "\x1B[1;31m" : "", - config->donateLevel(), + config->isColors() && config->pools().donateLevel() == 0 ? "\x1B[1;31m" : "", + config->pools().donateLevel(), buf); } else { @@ -124,8 +124,8 @@ static void print_threads(xmrig::Config *config) "THREADS", config->threadsCount(), config->algorithm().name(), - config->isColors() && config->donateLevel() == 0 ? "\x1B[1;31m" : "", - config->donateLevel()); + config->isColors() && config->pools().donateLevel() == 0 ? "\x1B[1;31m" : "", + config->pools().donateLevel()); } # ifndef XMRIG_NO_ASM diff --git a/src/api/ApiRouter.cpp b/src/api/ApiRouter.cpp index 5f3b1f63..69ab153c 100644 --- a/src/api/ApiRouter.cpp +++ b/src/api/ApiRouter.cpp @@ -254,7 +254,7 @@ void ApiRouter::getMiner(rapidjson::Document &doc) const doc.AddMember("cpu", cpu, allocator); doc.AddMember("algo", rapidjson::StringRef(m_controller->config()->algorithm().name()), allocator); doc.AddMember("hugepages", Workers::hugePages() > 0, allocator); - doc.AddMember("donate_level", m_controller->config()->donateLevel(), allocator); + doc.AddMember("donate_level", m_controller->config()->pools().donateLevel(), allocator); } diff --git a/src/base/net/stratum/Client.cpp b/src/base/net/stratum/Client.cpp index ab4b934d..d88acfc7 100644 --- a/src/base/net/stratum/Client.cpp +++ b/src/base/net/stratum/Client.cpp @@ -741,6 +741,11 @@ void xmrig::Client::parseExtensions(const rapidjson::Value &result) else if (strcmp(name, "keepalive") == 0) { setExtension(EXT_KEEPALIVE, true); } +# ifdef XMRIG_FEATURE_TLS + else if (strcmp(name, "tls") == 0) { + setExtension(EXT_TLS, true); + } +# endif } } diff --git a/src/base/net/stratum/Client.h b/src/base/net/stratum/Client.h index ce2b0276..e41d01ad 100644 --- a/src/base/net/stratum/Client.h +++ b/src/base/net/stratum/Client.h @@ -68,6 +68,7 @@ public: EXT_ALGO, EXT_NICEHASH, EXT_CONNECT, + EXT_TLS, EXT_KEEPALIVE, EXT_MAX }; diff --git a/src/base/net/stratum/Pools.cpp b/src/base/net/stratum/Pools.cpp index 7a738cf0..fc132dd5 100644 --- a/src/base/net/stratum/Pools.cpp +++ b/src/base/net/stratum/Pools.cpp @@ -27,12 +27,15 @@ #include "base/net/stratum/strategies/FailoverStrategy.h" #include "base/net/stratum/strategies/SinglePoolStrategy.h" #include "common/log/Log.h" +#include "donate.h" #include "rapidjson/document.h" xmrig::Pools::Pools() : + m_donateLevel(kDefaultDonateLevel), m_retries(5), - m_retryPause(5) + m_retryPause(5), + m_proxyDonate(PROXY_DONATE_AUTO) { # ifdef XMRIG_PROXY_PROJECT m_retries = 2; @@ -191,6 +194,25 @@ void xmrig::Pools::print() const } +void xmrig::Pools::setDonateLevel(int level) +{ + if (level >= kMinimumDonateLevel && level <= 99) { + m_donateLevel = level; + } +} + + +void xmrig::Pools::setProxyDonate(int value) +{ + switch (value) { + case PROXY_DONATE_NONE: + case PROXY_DONATE_AUTO: + case PROXY_DONATE_ALWAYS: + m_proxyDonate = static_cast(value); + } +} + + void xmrig::Pools::setRetries(int retries) { if (retries > 0 && retries <= 1000) { diff --git a/src/base/net/stratum/Pools.h b/src/base/net/stratum/Pools.h index 0f856c69..f563f243 100644 --- a/src/base/net/stratum/Pools.h +++ b/src/base/net/stratum/Pools.h @@ -42,12 +42,20 @@ class IStrategyListener; class Pools { public: + enum ProxyDonate { + PROXY_DONATE_NONE, + PROXY_DONATE_AUTO, + PROXY_DONATE_ALWAYS + }; + Pools(); inline bool setUserpass(const char *userpass) { return current().setUserpass(userpass); } inline const std::vector &data() const { return m_data; } + inline int donateLevel() const { return m_donateLevel; } inline int retries() const { return m_retries; } inline int retryPause() const { return m_retryPause; } + inline ProxyDonate proxyDonate() const { return m_proxyDonate; } inline void setFingerprint(const char *fingerprint) { current().setFingerprint(fingerprint); } inline void setKeepAlive(bool enable) { current().setKeepAlive(enable); } inline void setKeepAlive(int keepAlive) { current().setKeepAlive(keepAlive); } @@ -70,14 +78,18 @@ public: void adjust(const Algorithm &algorithm); void load(const rapidjson::Value &pools); void print() const; + void setDonateLevel(int level); + void setProxyDonate(int value); void setRetries(int retries); void setRetryPause(int retryPause); private: Pool ¤t(); + int m_donateLevel; int m_retries; int m_retryPause; + ProxyDonate m_proxyDonate; std::vector m_data; }; diff --git a/src/common/config/CommonConfig.cpp b/src/common/config/CommonConfig.cpp index 36d156a3..94bbd59f 100644 --- a/src/common/config/CommonConfig.cpp +++ b/src/common/config/CommonConfig.cpp @@ -57,7 +57,6 @@ #include "base/io/Json.h" #include "common/config/CommonConfig.h" #include "common/log/Log.h" -#include "donate.h" #include "rapidjson/document.h" #include "rapidjson/filewritestream.h" #include "rapidjson/prettywriter.h" @@ -75,7 +74,6 @@ xmrig::CommonConfig::CommonConfig() : m_syslog(false), m_watch(true), m_apiPort(0), - m_donateLevel(kDefaultDonateLevel), m_printTime(60), m_state(NoneState) { @@ -397,9 +395,11 @@ bool xmrig::CommonConfig::parseInt(int key, int arg) break; case DonateLevelKey: /* --donate-level */ - if (arg >= kMinimumDonateLevel && arg <= 99) { - m_donateLevel = arg; - } + m_pools.setDonateLevel(arg); + break; + + case ProxyDonateKey: /* --donate-over-proxy */ + m_pools.setProxyDonate(arg); break; case ApiPort: /* --api-port */ diff --git a/src/common/config/CommonConfig.h b/src/common/config/CommonConfig.h index 729c2451..e11069da 100644 --- a/src/common/config/CommonConfig.h +++ b/src/common/config/CommonConfig.h @@ -53,7 +53,6 @@ public: inline const char *userAgent() const { return m_userAgent.data(); } inline const Pools &pools() const { return m_pools; } inline int apiPort() const { return m_apiPort; } - inline int donateLevel() const { return m_donateLevel; } inline int printTime() const { return m_printTime; } inline bool isWatch() const override { return m_watch && !m_fileName.isNull(); } @@ -91,7 +90,6 @@ protected: bool m_syslog; bool m_watch; int m_apiPort; - int m_donateLevel; int m_printTime; Pools m_pools; State m_state; diff --git a/src/common/interfaces/IConfig.h b/src/common/interfaces/IConfig.h index 41a2f01c..e898c24c 100644 --- a/src/common/interfaces/IConfig.h +++ b/src/common/interfaces/IConfig.h @@ -69,6 +69,7 @@ public: TlsKey = 1013, FingerprintKey = 1014, AutoSaveKey = 1016, + ProxyDonateKey = 1017, // xmrig common CPUPriorityKey = 1021, diff --git a/src/config.json b/src/config.json index 5018db51..08b912a0 100644 --- a/src/config.json +++ b/src/config.json @@ -16,6 +16,7 @@ "cpu-affinity": null, "cpu-priority": null, "donate-level": 5, + "donate-over-proxy": 1, "huge-pages": true, "hw-aes": null, "log-file": null, diff --git a/src/core/Config.cpp b/src/core/Config.cpp index 82a96117..d566af26 100644 --- a/src/core/Config.cpp +++ b/src/core/Config.cpp @@ -97,17 +97,18 @@ void xmrig::Config::getJSON(rapidjson::Document &doc) const doc.AddMember("cpu-affinity", kNullType, allocator); } - doc.AddMember("cpu-priority", priority() != -1 ? Value(priority()) : Value(kNullType), allocator); - doc.AddMember("donate-level", donateLevel(), allocator); - doc.AddMember("huge-pages", isHugePages(), allocator); - doc.AddMember("hw-aes", m_aesMode == AES_AUTO ? Value(kNullType) : Value(m_aesMode == AES_HW), allocator); - doc.AddMember("log-file", logFile() ? Value(StringRef(logFile())).Move() : Value(kNullType).Move(), allocator); - doc.AddMember("max-cpu-usage", m_maxCpuUsage, allocator); - doc.AddMember("pools", m_pools.toJSON(doc), allocator); - doc.AddMember("print-time", printTime(), allocator); - doc.AddMember("retries", m_pools.retries(), allocator); - doc.AddMember("retry-pause", m_pools.retryPause(), allocator); - doc.AddMember("safe", m_safe, allocator); + doc.AddMember("cpu-priority", priority() != -1 ? Value(priority()) : Value(kNullType), allocator); + doc.AddMember("donate-level", m_pools.donateLevel(), allocator); + doc.AddMember("donate-over-proxy", m_pools.proxyDonate(), allocator); + doc.AddMember("huge-pages", isHugePages(), allocator); + doc.AddMember("hw-aes", m_aesMode == AES_AUTO ? Value(kNullType) : Value(m_aesMode == AES_HW), allocator); + doc.AddMember("log-file", m_logFile.toJSON(), allocator); + doc.AddMember("max-cpu-usage", m_maxCpuUsage, allocator); + doc.AddMember("pools", m_pools.toJSON(doc), allocator); + doc.AddMember("print-time", printTime(), allocator); + doc.AddMember("retries", m_pools.retries(), allocator); + doc.AddMember("retry-pause", m_pools.retryPause(), allocator); + doc.AddMember("safe", m_safe, allocator); if (threadsMode() != Simple) { Value threads(kArrayType); diff --git a/src/core/ConfigLoader_platform.h b/src/core/ConfigLoader_platform.h index 0b71c3fd..a13983cd 100644 --- a/src/core/ConfigLoader_platform.h +++ b/src/core/ConfigLoader_platform.h @@ -44,81 +44,83 @@ static char const short_options[] = "a:c:kBp:Px:r:R:s:t:T:o:u:O:v:l:S"; static struct option const options[] = { - { "algo", 1, nullptr, xmrig::IConfig::AlgorithmKey }, - { "api-access-token", 1, nullptr, xmrig::IConfig::ApiAccessTokenKey }, - { "api-port", 1, nullptr, xmrig::IConfig::ApiPort }, - { "api-worker-id", 1, nullptr, xmrig::IConfig::ApiWorkerIdKey }, - { "api-id", 1, nullptr, xmrig::IConfig::ApiIdKey }, - { "api-ipv6", 0, nullptr, xmrig::IConfig::ApiIPv6Key }, - { "api-no-restricted", 0, nullptr, xmrig::IConfig::ApiRestrictedKey }, - { "av", 1, nullptr, xmrig::IConfig::AVKey }, - { "background", 0, nullptr, xmrig::IConfig::BackgroundKey }, - { "config", 1, nullptr, xmrig::IConfig::ConfigKey }, - { "cpu-affinity", 1, nullptr, xmrig::IConfig::CPUAffinityKey }, - { "cpu-priority", 1, nullptr, xmrig::IConfig::CPUPriorityKey }, - { "donate-level", 1, nullptr, xmrig::IConfig::DonateLevelKey }, - { "dry-run", 0, nullptr, xmrig::IConfig::DryRunKey }, - { "keepalive", 0, nullptr, xmrig::IConfig::KeepAliveKey }, - { "log-file", 1, nullptr, xmrig::IConfig::LogFileKey }, - { "max-cpu-usage", 1, nullptr, xmrig::IConfig::MaxCPUUsageKey }, - { "nicehash", 0, nullptr, xmrig::IConfig::NicehashKey }, - { "no-color", 0, nullptr, xmrig::IConfig::ColorKey }, - { "no-watch", 0, nullptr, xmrig::IConfig::WatchKey }, - { "no-huge-pages", 0, nullptr, xmrig::IConfig::HugePagesKey }, - { "variant", 1, nullptr, xmrig::IConfig::VariantKey }, - { "pass", 1, nullptr, xmrig::IConfig::PasswordKey }, - { "print-time", 1, nullptr, xmrig::IConfig::PrintTimeKey }, - { "retries", 1, nullptr, xmrig::IConfig::RetriesKey }, - { "retry-pause", 1, nullptr, xmrig::IConfig::RetryPauseKey }, - { "safe", 0, nullptr, xmrig::IConfig::SafeKey }, - { "syslog", 0, nullptr, xmrig::IConfig::SyslogKey }, - { "threads", 1, nullptr, xmrig::IConfig::ThreadsKey }, - { "url", 1, nullptr, xmrig::IConfig::UrlKey }, - { "user", 1, nullptr, xmrig::IConfig::UserKey }, - { "user-agent", 1, nullptr, xmrig::IConfig::UserAgentKey }, - { "userpass", 1, nullptr, xmrig::IConfig::UserpassKey }, - { "rig-id", 1, nullptr, xmrig::IConfig::RigIdKey }, - { "tls", 0, nullptr, xmrig::IConfig::TlsKey }, - { "tls-fingerprint", 1, nullptr, xmrig::IConfig::FingerprintKey }, - { "asm", 1, nullptr, xmrig::IConfig::AssemblyKey }, + { "algo", 1, nullptr, IConfig::AlgorithmKey }, + { "api-access-token", 1, nullptr, IConfig::ApiAccessTokenKey }, + { "api-port", 1, nullptr, IConfig::ApiPort }, + { "api-worker-id", 1, nullptr, IConfig::ApiWorkerIdKey }, + { "api-id", 1, nullptr, IConfig::ApiIdKey }, + { "api-ipv6", 0, nullptr, IConfig::ApiIPv6Key }, + { "api-no-restricted", 0, nullptr, IConfig::ApiRestrictedKey }, + { "av", 1, nullptr, IConfig::AVKey }, + { "background", 0, nullptr, IConfig::BackgroundKey }, + { "config", 1, nullptr, IConfig::ConfigKey }, + { "cpu-affinity", 1, nullptr, IConfig::CPUAffinityKey }, + { "cpu-priority", 1, nullptr, IConfig::CPUPriorityKey }, + { "donate-level", 1, nullptr, IConfig::DonateLevelKey }, + { "donate-over-proxy", 1, nullptr, IConfig::ProxyDonateKey }, + { "dry-run", 0, nullptr, IConfig::DryRunKey }, + { "keepalive", 0, nullptr, IConfig::KeepAliveKey }, + { "log-file", 1, nullptr, IConfig::LogFileKey }, + { "max-cpu-usage", 1, nullptr, IConfig::MaxCPUUsageKey }, + { "nicehash", 0, nullptr, IConfig::NicehashKey }, + { "no-color", 0, nullptr, IConfig::ColorKey }, + { "no-watch", 0, nullptr, IConfig::WatchKey }, + { "no-huge-pages", 0, nullptr, IConfig::HugePagesKey }, + { "variant", 1, nullptr, IConfig::VariantKey }, + { "pass", 1, nullptr, IConfig::PasswordKey }, + { "print-time", 1, nullptr, IConfig::PrintTimeKey }, + { "retries", 1, nullptr, IConfig::RetriesKey }, + { "retry-pause", 1, nullptr, IConfig::RetryPauseKey }, + { "safe", 0, nullptr, IConfig::SafeKey }, + { "syslog", 0, nullptr, IConfig::SyslogKey }, + { "threads", 1, nullptr, IConfig::ThreadsKey }, + { "url", 1, nullptr, IConfig::UrlKey }, + { "user", 1, nullptr, IConfig::UserKey }, + { "user-agent", 1, nullptr, IConfig::UserAgentKey }, + { "userpass", 1, nullptr, IConfig::UserpassKey }, + { "rig-id", 1, nullptr, IConfig::RigIdKey }, + { "tls", 0, nullptr, IConfig::TlsKey }, + { "tls-fingerprint", 1, nullptr, IConfig::FingerprintKey }, + { "asm", 1, nullptr, IConfig::AssemblyKey }, { nullptr, 0, nullptr, 0 } }; static struct option const config_options[] = { - { "algo", 1, nullptr, xmrig::IConfig::AlgorithmKey }, - { "av", 1, nullptr, xmrig::IConfig::AVKey }, - { "background", 0, nullptr, xmrig::IConfig::BackgroundKey }, - { "colors", 0, nullptr, xmrig::IConfig::ColorKey }, - { "cpu-affinity", 1, nullptr, xmrig::IConfig::CPUAffinityKey }, - { "cpu-priority", 1, nullptr, xmrig::IConfig::CPUPriorityKey }, - { "donate-level", 1, nullptr, xmrig::IConfig::DonateLevelKey }, - { "dry-run", 0, nullptr, xmrig::IConfig::DryRunKey }, - { "huge-pages", 0, nullptr, xmrig::IConfig::HugePagesKey }, - { "log-file", 1, nullptr, xmrig::IConfig::LogFileKey }, - { "max-cpu-usage", 1, nullptr, xmrig::IConfig::MaxCPUUsageKey }, - { "print-time", 1, nullptr, xmrig::IConfig::PrintTimeKey }, - { "retries", 1, nullptr, xmrig::IConfig::RetriesKey }, - { "retry-pause", 1, nullptr, xmrig::IConfig::RetryPauseKey }, - { "safe", 0, nullptr, xmrig::IConfig::SafeKey }, - { "syslog", 0, nullptr, xmrig::IConfig::SyslogKey }, - { "threads", 1, nullptr, xmrig::IConfig::ThreadsKey }, - { "user-agent", 1, nullptr, xmrig::IConfig::UserAgentKey }, - { "watch", 0, nullptr, xmrig::IConfig::WatchKey }, - { "hw-aes", 0, nullptr, xmrig::IConfig::HardwareAESKey }, - { "asm", 1, nullptr, xmrig::IConfig::AssemblyKey }, - { "autosave", 0, nullptr, xmrig::IConfig::AutoSaveKey }, - { nullptr, 0, nullptr, 0 } + { "algo", 1, nullptr, IConfig::AlgorithmKey }, + { "av", 1, nullptr, IConfig::AVKey }, + { "background", 0, nullptr, IConfig::BackgroundKey }, + { "colors", 0, nullptr, IConfig::ColorKey }, + { "cpu-affinity", 1, nullptr, IConfig::CPUAffinityKey }, + { "cpu-priority", 1, nullptr, IConfig::CPUPriorityKey }, + { "donate-level", 1, nullptr, IConfig::DonateLevelKey }, + { "donate-over-proxy", 1, nullptr, IConfig::ProxyDonateKey }, + { "dry-run", 0, nullptr, IConfig::DryRunKey }, + { "huge-pages", 0, nullptr, IConfig::HugePagesKey }, + { "log-file", 1, nullptr, IConfig::LogFileKey }, + { "max-cpu-usage", 1, nullptr, IConfig::MaxCPUUsageKey }, + { "print-time", 1, nullptr, IConfig::PrintTimeKey }, + { "retries", 1, nullptr, IConfig::RetriesKey }, + { "retry-pause", 1, nullptr, IConfig::RetryPauseKey }, + { "safe", 0, nullptr, IConfig::SafeKey }, + { "syslog", 0, nullptr, IConfig::SyslogKey }, + { "threads", 1, nullptr, IConfig::ThreadsKey }, + { "user-agent", 1, nullptr, IConfig::UserAgentKey }, + { "watch", 0, nullptr, IConfig::WatchKey }, + { "hw-aes", 0, nullptr, IConfig::HardwareAESKey }, + { "asm", 1, nullptr, IConfig::AssemblyKey }, + { "autosave", 0, nullptr, IConfig::AutoSaveKey }, + { nullptr, 0, nullptr, 0 } }; static struct option const api_options[] = { - { "port", 1, nullptr, xmrig::IConfig::ApiPort }, - { "access-token", 1, nullptr, xmrig::IConfig::ApiAccessTokenKey }, - { "worker-id", 1, nullptr, xmrig::IConfig::ApiWorkerIdKey }, - { "ipv6", 0, nullptr, xmrig::IConfig::ApiIPv6Key }, - { "restricted", 0, nullptr, xmrig::IConfig::ApiRestrictedKey }, - { "id", 1, nullptr, xmrig::IConfig::ApiIdKey }, + { "port", 1, nullptr, IConfig::ApiPort }, + { "access-token", 1, nullptr, IConfig::ApiAccessTokenKey }, + { "worker-id", 1, nullptr, IConfig::ApiWorkerIdKey }, + { "ipv6", 0, nullptr, IConfig::ApiIPv6Key }, + { "restricted", 0, nullptr, IConfig::ApiRestrictedKey }, + { "id", 1, nullptr, IConfig::ApiIdKey }, { nullptr, 0, nullptr, 0 } }; diff --git a/src/net/Network.cpp b/src/net/Network.cpp index 61f6080b..f50e3f0a 100644 --- a/src/net/Network.cpp +++ b/src/net/Network.cpp @@ -54,8 +54,8 @@ xmrig::Network::Network(Controller *controller) : const Pools &pools = controller->config()->pools(); m_strategy = pools.createStrategy(this); - if (controller->config()->donateLevel() > 0) { - m_donate = new DonateStrategy(controller->config()->donateLevel(), pools.data().front().user(), controller->config()->algorithm().algo(), this); + if (pools.donateLevel() > 0) { + m_donate = new DonateStrategy(controller, this); } m_timer = new Timer(this, kTickInterval, kTickInterval); diff --git a/src/net/strategies/DonateStrategy.cpp b/src/net/strategies/DonateStrategy.cpp index 11fca39b..37a9c7c9 100644 --- a/src/net/strategies/DonateStrategy.cpp +++ b/src/net/strategies/DonateStrategy.cpp @@ -23,6 +23,9 @@ */ +#include + + #include "base/net/stratum/Client.h" #include "base/net/stratum/Job.h" #include "base/net/stratum/strategies/FailoverStrategy.h" @@ -32,40 +35,50 @@ #include "common/crypto/keccak.h" #include "common/Platform.h" #include "common/xmrig.h" +#include "core/Config.h" +#include "core/Controller.h" +#include "net/Network.h" #include "net/strategies/DonateStrategy.h" namespace xmrig { -static inline double randomf(double min, double max) { return (max - min) * (((static_cast(rand())) / static_cast(RAND_MAX))) + min; } +static inline double randomf(double min, double max) { return (max - min) * (((static_cast(rand())) / static_cast(RAND_MAX))) + min; } static inline uint64_t random(uint64_t base, double min, double max) { return static_cast(base * randomf(min, max)); } +static const char *kDonateHost = "donate.v2.xmrig.com"; +#ifdef XMRIG_FEATURE_TLS +static const char *kDonateHostTls = "donate.ssl.xmrig.com"; +#endif + } /* namespace xmrig */ -xmrig::DonateStrategy::DonateStrategy(int level, const char *user, Algo algo, IStrategyListener *listener) : - m_active(false), - m_donateTime(static_cast(level) * 60 * 1000), - m_idleTime((100 - static_cast(level)) * 60 * 1000), +xmrig::DonateStrategy::DonateStrategy(Controller *controller, IStrategyListener *listener) : + m_proxy(nullptr), + m_donateTime(static_cast(controller->config()->pools().donateLevel()) * 60 * 1000), + m_idleTime((100 - static_cast(controller->config()->pools().donateLevel())) * 60 * 1000), + m_controller(controller), m_strategy(nullptr), m_listener(listener), + m_state(STATE_NEW), m_now(0), m_stop(0) { uint8_t hash[200]; char userId[65] = { 0 }; - keccak(reinterpret_cast(user), strlen(user), hash); + const String &user = controller->config()->pools().data().front().user(); + keccak(reinterpret_cast(user.data()), user.size(), hash); Buffer::toHex(hash, 32, userId); # ifdef XMRIG_FEATURE_TLS - m_pools.push_back(Pool("donate.ssl.xmrig.com", 443, userId, nullptr, false, true, true)); + m_pools.push_back(Pool(kDonateHostTls, 443, userId, nullptr, false, true, true)); # endif - - m_pools.push_back(Pool("donate.v2.xmrig.com", 3333, userId, nullptr, false, true)); + m_pools.push_back(Pool(kDonateHost, 3333, userId, nullptr, false, true)); for (Pool &pool : m_pools) { - pool.adjust(Algorithm(algo, VARIANT_AUTO)); + pool.adjust(Algorithm(controller->config()->algorithm().algo(), VARIANT_AUTO)); } if (m_pools.size() > 1) { @@ -77,7 +90,7 @@ xmrig::DonateStrategy::DonateStrategy(int level, const char *user, Algo algo, IS m_timer = new Timer(this); - idle(random(m_idleTime, 0.5, 1.5)); + setState(STATE_IDLE); } @@ -119,20 +132,19 @@ void xmrig::DonateStrategy::tick(uint64_t now) m_strategy->tick(now); - if (m_stop && now > m_stop) { - m_strategy->stop(); - m_stop = 0; + if (state() == STATE_WAIT && now > m_stop) { + setState(STATE_IDLE); } } void xmrig::DonateStrategy::onActive(IStrategy *strategy, Client *client) { - if (!isActive()) { - m_timer->start(m_donateTime, 0); + if (isActive()) { + return; } - m_active = true; + setState(STATE_ACTIVE); m_listener->onActive(this, client); } @@ -158,30 +170,53 @@ void xmrig::DonateStrategy::onResultAccepted(IStrategy *strategy, Client *client void xmrig::DonateStrategy::onTimer(const Timer *) { - if (!isActive()) { - return connect(); + setState(isActive() ? STATE_WAIT : STATE_CONNECT); +} + + +void xmrig::DonateStrategy::idle(double min, double max) +{ + m_timer->start(random(m_idleTime, min, max), 0); +} + + +void xmrig::DonateStrategy::setState(State state) +{ + constexpr const uint64_t waitTime = 3000; + + assert(m_state != state && state != STATE_NEW); + if (m_state == state) { + return; } - suspend(); -} - - -void xmrig::DonateStrategy::idle(uint64_t timeout) -{ - m_timer->start(timeout, 0); -} - - -void xmrig::DonateStrategy::suspend() -{ -# if defined(XMRIG_AMD_PROJECT) || defined(XMRIG_NVIDIA_PROJECT) - m_stop = m_now + 5000; -# else - m_stop = m_now + 500; -# endif - - m_active = false; - m_listener->onPause(this); - - idle(random(m_idleTime, 0.8, 1.2)); + const State prev = m_state; + m_state = state; + + switch (state) { + case STATE_NEW: + break; + + case STATE_IDLE: + if (prev == STATE_NEW) { + idle(0.5, 1.5); + } + else { + m_strategy->stop(); + idle(0.8, 1.2); + } + break; + + case STATE_CONNECT: + connect(); + break; + + case STATE_ACTIVE: + m_timer->start(m_donateTime, 0); + break; + + case STATE_WAIT: + m_stop = m_now + waitTime; + m_listener->onPause(this); + break; + } } diff --git a/src/net/strategies/DonateStrategy.h b/src/net/strategies/DonateStrategy.h index b5ea13c8..a06f901f 100644 --- a/src/net/strategies/DonateStrategy.h +++ b/src/net/strategies/DonateStrategy.h @@ -26,7 +26,6 @@ #define XMRIG_DONATESTRATEGY_H -#include #include @@ -41,17 +40,18 @@ namespace xmrig { class Client; +class Controller; class IStrategyListener; class DonateStrategy : public IStrategy, public IStrategyListener, public ITimerListener { public: - DonateStrategy(int level, const char *user, Algo algo, IStrategyListener *listener); + DonateStrategy(Controller *controller, IStrategyListener *listener); ~DonateStrategy() override; public: - inline bool isActive() const override { return m_active; } + inline bool isActive() const override { return state() == STATE_ACTIVE; } inline void resume() override {} int64_t submit(const JobResult &result) override; @@ -68,20 +68,30 @@ protected: void onTimer(const Timer *timer) override; private: - void idle(uint64_t timeout); - void suspend(); + enum State { + STATE_NEW, + STATE_IDLE, + STATE_CONNECT, + STATE_ACTIVE, + STATE_WAIT + }; - static void onTimer(uv_timer_t *handle); + inline State state() const { return m_state; } - bool m_active; + void idle(double min, double max); + void setState(State state); + + Client *m_proxy; const uint64_t m_donateTime; const uint64_t m_idleTime; + Controller *m_controller; IStrategy *m_strategy; IStrategyListener *m_listener; + State m_state; std::vector m_pools; + Timer *m_timer; uint64_t m_now; uint64_t m_stop; - Timer *m_timer; }; From 4c95136e6ab8435098b33ac67e83ac25a0f12226 Mon Sep 17 00:00:00 2001 From: XMRig Date: Tue, 19 Mar 2019 21:31:54 +0700 Subject: [PATCH 021/116] Implemented donate over proxy. --- src/base/kernel/interfaces/IStrategy.h | 6 +- src/base/net/stratum/Client.cpp | 20 +-- src/base/net/stratum/Client.h | 3 +- .../stratum/strategies/FailoverStrategy.cpp | 14 +- .../net/stratum/strategies/FailoverStrategy.h | 11 +- .../stratum/strategies/SinglePoolStrategy.h | 7 +- src/net/Network.h | 2 + src/net/strategies/DonateStrategy.cpp | 125 +++++++++++++++--- src/net/strategies/DonateStrategy.h | 28 ++-- 9 files changed, 161 insertions(+), 55 deletions(-) diff --git a/src/base/kernel/interfaces/IStrategy.h b/src/base/kernel/interfaces/IStrategy.h index 1e9c19bc..31798b9c 100644 --- a/src/base/kernel/interfaces/IStrategy.h +++ b/src/base/kernel/interfaces/IStrategy.h @@ -29,13 +29,12 @@ #include -class JobResult; - - namespace xmrig { class Algorithm; +class Client; +class JobResult; class IStrategy @@ -44,6 +43,7 @@ public: virtual ~IStrategy() = default; virtual bool isActive() const = 0; + virtual Client *client() const = 0; virtual int64_t submit(const JobResult &result) = 0; virtual void connect() = 0; virtual void resume() = 0; diff --git a/src/base/net/stratum/Client.cpp b/src/base/net/stratum/Client.cpp index d88acfc7..db6f2663 100644 --- a/src/base/net/stratum/Client.cpp +++ b/src/base/net/stratum/Client.cpp @@ -182,6 +182,16 @@ bool xmrig::Client::disconnect() } +bool xmrig::Client::isTLS() const +{ +# ifndef XMRIG_NO_TLS + return m_pool.isTLS() && m_tls; +# else + return false; +# endif +} + + const char *xmrig::Client::tlsFingerprint() const { # ifndef XMRIG_NO_TLS @@ -331,16 +341,6 @@ bool xmrig::Client::isCriticalError(const char *message) } -bool xmrig::Client::isTLS() const -{ -# ifndef XMRIG_NO_TLS - return m_pool.isTLS() && m_tls; -# else - return false; -# endif -} - - bool xmrig::Client::parseJob(const rapidjson::Value ¶ms, int *code) { if (!params.IsObject()) { diff --git a/src/base/net/stratum/Client.h b/src/base/net/stratum/Client.h index e41d01ad..c0ea8a93 100644 --- a/src/base/net/stratum/Client.h +++ b/src/base/net/stratum/Client.h @@ -85,6 +85,7 @@ public: ~Client() override; bool disconnect(); + bool isTLS() const; const char *tlsFingerprint() const; const char *tlsVersion() const; int64_t submit(const JobResult &result); @@ -99,6 +100,7 @@ public: inline const char *host() const { return m_pool.host(); } inline const char *ip() const { return m_ip; } inline const Job &job() const { return m_job; } + inline const Pool &pool() const { return m_pool; } inline int id() const { return m_id; } inline SocketState state() const { return m_state; } inline uint16_t port() const { return m_pool.port(); } @@ -120,7 +122,6 @@ private: bool close(); bool isCriticalError(const char *message); - bool isTLS() const; bool parseJob(const rapidjson::Value ¶ms, int *code); bool parseLogin(const rapidjson::Value &result, int *code); bool send(BIO *bio); diff --git a/src/base/net/stratum/strategies/FailoverStrategy.cpp b/src/base/net/stratum/strategies/FailoverStrategy.cpp index d2e4a6da..7a59e2a6 100644 --- a/src/base/net/stratum/strategies/FailoverStrategy.cpp +++ b/src/base/net/stratum/strategies/FailoverStrategy.cpp @@ -34,8 +34,8 @@ xmrig::FailoverStrategy::FailoverStrategy(const std::vector &pools, int re m_retries(retries), m_retryPause(retryPause), m_active(-1), - m_index(0), - m_listener(listener) + m_listener(listener), + m_index(0) { for (const Pool &pool : pools) { add(pool); @@ -48,8 +48,8 @@ xmrig::FailoverStrategy::FailoverStrategy(int retryPause, int retries, IStrategy m_retries(retries), m_retryPause(retryPause), m_active(-1), - m_index(0), - m_listener(listener) + m_listener(listener), + m_index(0) { } @@ -86,7 +86,7 @@ int64_t xmrig::FailoverStrategy::submit(const JobResult &result) void xmrig::FailoverStrategy::connect() { - m_pools[static_cast(m_index)]->connect(); + m_pools[m_index]->connect(); } @@ -144,8 +144,8 @@ void xmrig::FailoverStrategy::onClose(Client *client, int failures) return; } - if (m_index == client->id() && (m_pools.size() - static_cast(m_index)) > 1) { - m_pools[static_cast(++m_index)]->connect(); + if (m_index == static_cast(client->id()) && (m_pools.size() - m_index) > 1) { + m_pools[++m_index]->connect(); } } diff --git a/src/base/net/stratum/strategies/FailoverStrategy.h b/src/base/net/stratum/strategies/FailoverStrategy.h index 3517de9d..fcebc52f 100644 --- a/src/base/net/stratum/strategies/FailoverStrategy.h +++ b/src/base/net/stratum/strategies/FailoverStrategy.h @@ -50,8 +50,10 @@ public: void add(const Pool &pool); -public: - inline bool isActive() const override { return m_active >= 0; } +protected: + inline bool isActive() const override { return m_active >= 0; } + inline Client *client() const override { return active(); } + inline void onLogin(Client *, rapidjson::Document &, rapidjson::Value &) override {} int64_t submit(const JobResult &result) override; void connect() override; @@ -60,9 +62,6 @@ public: void stop() override; void tick(uint64_t now) override; -protected: - inline void onLogin(Client *, rapidjson::Document &, rapidjson::Value &) override {} - void onClose(Client *client, int failures) override; void onJobReceived(Client *client, const Job &job, const rapidjson::Value ¶ms) override; void onLoginSuccess(Client *client) override; @@ -75,8 +74,8 @@ private: const int m_retries; const int m_retryPause; int m_active; - int m_index; IStrategyListener *m_listener; + size_t m_index; std::vector m_pools; }; diff --git a/src/base/net/stratum/strategies/SinglePoolStrategy.h b/src/base/net/stratum/strategies/SinglePoolStrategy.h index 5b3016c1..8d9f9fd1 100644 --- a/src/base/net/stratum/strategies/SinglePoolStrategy.h +++ b/src/base/net/stratum/strategies/SinglePoolStrategy.h @@ -44,8 +44,10 @@ public: SinglePoolStrategy(const Pool &pool, int retryPause, int retries, IStrategyListener *listener, bool quiet = false); ~SinglePoolStrategy() override; -public: +protected: inline bool isActive() const override { return m_active; } + inline Client *client() const override { return m_client; } + inline void onLogin(Client *, rapidjson::Document &, rapidjson::Value &) override {} int64_t submit(const JobResult &result) override; void connect() override; @@ -54,9 +56,6 @@ public: void stop() override; void tick(uint64_t now) override; -protected: - inline void onLogin(Client *, rapidjson::Document &, rapidjson::Value &) override {} - void onClose(Client *client, int failures) override; void onJobReceived(Client *client, const Job &job, const rapidjson::Value ¶ms) override; void onLoginSuccess(Client *client) override; diff --git a/src/net/Network.h b/src/net/Network.h index 8afc5492..ac74384e 100644 --- a/src/net/Network.h +++ b/src/net/Network.h @@ -49,6 +49,8 @@ public: Network(Controller *controller); ~Network() override; + inline IStrategy *strategy() const { return m_strategy; } + void connect(); protected: diff --git a/src/net/strategies/DonateStrategy.cpp b/src/net/strategies/DonateStrategy.cpp index 37a9c7c9..adfb9a99 100644 --- a/src/net/strategies/DonateStrategy.cpp +++ b/src/net/strategies/DonateStrategy.cpp @@ -39,6 +39,7 @@ #include "core/Controller.h" #include "net/Network.h" #include "net/strategies/DonateStrategy.h" +#include "rapidjson/document.h" namespace xmrig { @@ -55,6 +56,8 @@ static const char *kDonateHostTls = "donate.ssl.xmrig.com"; xmrig::DonateStrategy::DonateStrategy(Controller *controller, IStrategyListener *listener) : + m_tls(false), + m_userId(), m_proxy(nullptr), m_donateTime(static_cast(controller->config()->pools().donateLevel()) * 60 * 1000), m_idleTime((100 - static_cast(controller->config()->pools().donateLevel())) * 60 * 1000), @@ -63,19 +66,18 @@ xmrig::DonateStrategy::DonateStrategy(Controller *controller, IStrategyListener m_listener(listener), m_state(STATE_NEW), m_now(0), - m_stop(0) + m_timestamp(0) { uint8_t hash[200]; - char userId[65] = { 0 }; const String &user = controller->config()->pools().data().front().user(); keccak(reinterpret_cast(user.data()), user.size(), hash); - Buffer::toHex(hash, 32, userId); + Buffer::toHex(hash, 32, m_userId); # ifdef XMRIG_FEATURE_TLS - m_pools.push_back(Pool(kDonateHostTls, 443, userId, nullptr, false, true, true)); + m_pools.push_back(Pool(kDonateHostTls, 443, m_userId, nullptr, 0, true, true)); # endif - m_pools.push_back(Pool(kDonateHost, 3333, userId, nullptr, false, true)); + m_pools.push_back(Pool(kDonateHost, 3333, m_userId, nullptr, 0, true)); for (Pool &pool : m_pools) { pool.adjust(Algorithm(controller->config()->algorithm().algo(), VARIANT_AUTO)); @@ -98,18 +100,31 @@ xmrig::DonateStrategy::~DonateStrategy() { delete m_timer; delete m_strategy; + + if (m_proxy) { + m_proxy->deleteLater(); + } } int64_t xmrig::DonateStrategy::submit(const JobResult &result) { - return m_strategy->submit(result); + return m_proxy ? m_proxy->submit(result) : m_strategy->submit(result); } void xmrig::DonateStrategy::connect() { - m_strategy->connect(); + m_proxy = createProxy(); + if (m_proxy) { + m_proxy->connect(); + } + else if (m_controller->config()->pools().proxyDonate() == Pools::PROXY_DONATE_ALWAYS) { + setState(STATE_IDLE); + } + else { + m_strategy->connect(); + } } @@ -132,13 +147,17 @@ void xmrig::DonateStrategy::tick(uint64_t now) m_strategy->tick(now); - if (state() == STATE_WAIT && now > m_stop) { + if (m_proxy) { + m_proxy->tick(now); + } + + if (state() == STATE_WAIT && now > m_timestamp) { setState(STATE_IDLE); } } -void xmrig::DonateStrategy::onActive(IStrategy *strategy, Client *client) +void xmrig::DonateStrategy::onActive(IStrategy *, Client *client) { if (isActive()) { return; @@ -149,22 +168,49 @@ void xmrig::DonateStrategy::onActive(IStrategy *strategy, Client *client) } -void xmrig::DonateStrategy::onJob(IStrategy *strategy, Client *client, const Job &job) +void xmrig::DonateStrategy::onPause(IStrategy *) { - if (isActive()) { - m_listener->onJob(this, client, job); +} + + +void xmrig::DonateStrategy::onClose(Client *, int failures) +{ + if (failures == 2 && m_controller->config()->pools().proxyDonate() == Pools::PROXY_DONATE_AUTO) { + m_proxy->deleteLater(); + m_proxy = nullptr; + + m_strategy->connect(); } } -void xmrig::DonateStrategy::onPause(IStrategy *strategy) +void xmrig::DonateStrategy::onLogin(Client *, rapidjson::Document &doc, rapidjson::Value ¶ms) { + auto &allocator = doc.GetAllocator(); + +# ifdef XMRIG_FEATURE_TLS + if (m_tls) { + char buf[40] = { 0 }; + snprintf(buf, sizeof(buf), "stratum+ssl://%s", m_pools[0].url().data()); + params.AddMember("url", rapidjson::Value(buf, allocator), allocator); + } + else { + params.AddMember("url", m_pools[1].url().toJSON(), allocator); + } +# else + params.AddMember("url", m_pools[0].url().toJSON(), allocator); +# endif } -void xmrig::DonateStrategy::onResultAccepted(IStrategy *strategy, Client *client, const SubmitResult &result, const char *error) +void xmrig::DonateStrategy::onLoginSuccess(Client *client) { - m_listener->onResultAccepted(this, client, result, error); + if (isActive()) { + return; + } + + setState(STATE_ACTIVE); + m_listener->onActive(this, client); } @@ -174,12 +220,51 @@ void xmrig::DonateStrategy::onTimer(const Timer *) } +xmrig::Client *xmrig::DonateStrategy::createProxy() +{ + if (m_controller->config()->pools().proxyDonate() == Pools::PROXY_DONATE_NONE) { + return nullptr; + } + + IStrategy *strategy = m_controller->network()->strategy(); + if (!strategy->isActive() || !strategy->client()->has()) { + return nullptr; + } + + const Client *client = strategy->client(); + m_tls = client->has(); + + Pool pool(client->ip(), client->port(), m_userId, client->pool().password(), 0, true, client->isTLS()); + pool.setAlgo(client->pool().algorithm()); + + Client *proxy = new Client(-1, Platform::userAgent(), this); + proxy->setPool(pool); + proxy->setQuiet(true); + + return proxy; +} + + void xmrig::DonateStrategy::idle(double min, double max) { m_timer->start(random(m_idleTime, min, max), 0); } +void xmrig::DonateStrategy::setJob(Client *client, const Job &job) +{ + if (isActive()) { + m_listener->onJob(this, client, job); + } +} + + +void xmrig::DonateStrategy::setResult(Client *client, const SubmitResult &result, const char *error) +{ + m_listener->onResultAccepted(this, client, result, error); +} + + void xmrig::DonateStrategy::setState(State state) { constexpr const uint64_t waitTime = 3000; @@ -200,8 +285,16 @@ void xmrig::DonateStrategy::setState(State state) if (prev == STATE_NEW) { idle(0.5, 1.5); } + else if (prev == STATE_CONNECT) { + m_timer->start(20000, 0); + } else { m_strategy->stop(); + if (m_proxy) { + m_proxy->deleteLater(); + m_proxy = nullptr; + } + idle(0.8, 1.2); } break; @@ -215,7 +308,7 @@ void xmrig::DonateStrategy::setState(State state) break; case STATE_WAIT: - m_stop = m_now + waitTime; + m_timestamp = m_now + waitTime; m_listener->onPause(this); break; } diff --git a/src/net/strategies/DonateStrategy.h b/src/net/strategies/DonateStrategy.h index a06f901f..827596f3 100644 --- a/src/net/strategies/DonateStrategy.h +++ b/src/net/strategies/DonateStrategy.h @@ -44,15 +44,20 @@ class Controller; class IStrategyListener; -class DonateStrategy : public IStrategy, public IStrategyListener, public ITimerListener +class DonateStrategy : public IStrategy, public IStrategyListener, public ITimerListener, public IClientListener { public: DonateStrategy(Controller *controller, IStrategyListener *listener); ~DonateStrategy() override; -public: - inline bool isActive() const override { return state() == STATE_ACTIVE; } - inline void resume() override {} +protected: + inline bool isActive() const override { return state() == STATE_ACTIVE; } + inline Client *client() const override { return m_proxy ? m_proxy : m_strategy->client(); } + inline void onJob(IStrategy *, Client *client, const Job &job) override { setJob(client, job); } + inline void onJobReceived(Client *client, const Job &job, const rapidjson::Value &) override { setJob(client, job); } + inline void onResultAccepted(Client *client, const SubmitResult &result, const char *error) override { setResult(client, result, error); } + inline void onResultAccepted(IStrategy *, Client *client, const SubmitResult &result, const char *error) override { setResult(client, result, error); } + inline void resume() override {} int64_t submit(const JobResult &result) override; void connect() override; @@ -60,11 +65,13 @@ public: void stop() override; void tick(uint64_t now) override; -protected: void onActive(IStrategy *strategy, Client *client) override; - void onJob(IStrategy *strategy, Client *client, const Job &job) override; void onPause(IStrategy *strategy) override; - void onResultAccepted(IStrategy *strategy, Client *client, const SubmitResult &result, const char *error) override; + + void onClose(Client *client, int failures) override; + void onLogin(Client *client, rapidjson::Document &doc, rapidjson::Value ¶ms) override; + void onLoginSuccess(Client *client) override; + void onTimer(const Timer *timer) override; private: @@ -78,9 +85,14 @@ private: inline State state() const { return m_state; } + Client *createProxy(); void idle(double min, double max); + void setJob(Client *client, const Job &job); + void setResult(Client *client, const SubmitResult &result, const char *error); void setState(State state); + bool m_tls; + char m_userId[65]; Client *m_proxy; const uint64_t m_donateTime; const uint64_t m_idleTime; @@ -91,7 +103,7 @@ private: std::vector m_pools; Timer *m_timer; uint64_t m_now; - uint64_t m_stop; + uint64_t m_timestamp; }; From 8d61a47040ea3cffccf839c91340d7a606e98b07 Mon Sep 17 00:00:00 2001 From: XMRig Date: Tue, 19 Mar 2019 22:13:43 +0700 Subject: [PATCH 022/116] Fix uv_tty_reset_mode on Linux. --- src/App.cpp | 2 -- src/base/io/Console.cpp | 2 ++ 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/App.cpp b/src/App.cpp index 500a521d..db91bab5 100644 --- a/src/App.cpp +++ b/src/App.cpp @@ -68,8 +68,6 @@ xmrig::App::App(Process *process) : xmrig::App::~App() { - uv_tty_reset_mode(); - delete m_signals; delete m_console; delete m_controller; diff --git a/src/base/io/Console.cpp b/src/base/io/Console.cpp index cb23c4b0..0e5cd269 100644 --- a/src/base/io/Console.cpp +++ b/src/base/io/Console.cpp @@ -53,6 +53,8 @@ xmrig::Console::~Console() void xmrig::Console::stop() { + uv_tty_reset_mode(); + Handle::close(m_tty); m_tty = nullptr; } From cf7df3f62942198b38f3a30b4f6aaa6356810b30 Mon Sep 17 00:00:00 2001 From: XMRig Date: Wed, 20 Mar 2019 11:55:15 +0700 Subject: [PATCH 023/116] v2.15.0-evo --- src/version.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/version.h b/src/version.h index 4e8fee45..b89f47ce 100644 --- a/src/version.h +++ b/src/version.h @@ -28,15 +28,15 @@ #define APP_ID "xmrig" #define APP_NAME "XMRig" #define APP_DESC "XMRig CPU miner" -#define APP_VERSION "2.14.2-dev" +#define APP_VERSION "2.15.0-evo" #define APP_DOMAIN "xmrig.com" #define APP_SITE "www.xmrig.com" #define APP_COPYRIGHT "Copyright (C) 2016-2019 xmrig.com" #define APP_KIND "cpu" #define APP_VER_MAJOR 2 -#define APP_VER_MINOR 14 -#define APP_VER_PATCH 2 +#define APP_VER_MINOR 15 +#define APP_VER_PATCH 0 #ifdef _MSC_VER # if (_MSC_VER >= 1910) From a891d2a590ef718f3e39bb100762b1618035a6de Mon Sep 17 00:00:00 2001 From: xmrig Date: Sun, 24 Mar 2019 02:34:54 +0700 Subject: [PATCH 024/116] Update CHANGELOG.md --- CHANGELOG.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 79c8bb4a..0487457d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,8 @@ +# v2.15.0-beta +- [#314](https://github.com/xmrig/xmrig-proxy/issues/314) Added donate over proxy feature. + - Added new option `donate-over-proxy`. + - Added real graceful exit. + # v2.14.1 * [#975](https://github.com/xmrig/xmrig/issues/975) Fixed crash on Linux if double thread mode used. From 177e0c9c2616567552cc6fea57185c593235cef7 Mon Sep 17 00:00:00 2001 From: XMRig Date: Sun, 24 Mar 2019 02:35:51 +0700 Subject: [PATCH 025/116] v2.15.0-beta --- src/version.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/version.h b/src/version.h index b89f47ce..2c6eb6ef 100644 --- a/src/version.h +++ b/src/version.h @@ -28,7 +28,7 @@ #define APP_ID "xmrig" #define APP_NAME "XMRig" #define APP_DESC "XMRig CPU miner" -#define APP_VERSION "2.15.0-evo" +#define APP_VERSION "2.15.0-beta" #define APP_DOMAIN "xmrig.com" #define APP_SITE "www.xmrig.com" #define APP_COPYRIGHT "Copyright (C) 2016-2019 xmrig.com" From ced25c3fa0dee1b239d86686875f9234d8b0395b Mon Sep 17 00:00:00 2001 From: XMRig Date: Tue, 26 Mar 2019 19:56:35 +0700 Subject: [PATCH 026/116] Log subsystem rewritten, to handle both color and not color logs simultaneously and overall simplicity. --- CMakeLists.txt | 14 - src/App.cpp | 8 +- src/Summary.cpp | 24 +- src/base/base.cmake | 16 ++ src/base/io/log/Log.cpp | 245 ++++++++++++++++++ src/base/io/log/Log.h | 129 +++++++++ .../io/log/backends}/ConsoleLog.cpp | 73 ++---- .../log => base/io/log/backends}/ConsoleLog.h | 13 +- .../log => base/io/log/backends}/FileLog.cpp | 55 +--- .../log => base/io/log/backends}/FileLog.h | 13 +- .../log => base/io/log/backends}/SysLog.cpp | 15 +- .../log => base/io/log/backends}/SysLog.h | 8 +- .../kernel}/interfaces/ILogBackend.h | 18 +- src/base/net/stratum/Pools.cpp | 26 +- src/common/config/CommonConfig.cpp | 8 +- src/common/log/BasicLog.cpp | 90 ------- src/common/log/BasicLog.h | 57 ---- src/common/log/Log.cpp | 134 ---------- src/common/log/Log.h | 87 +------ src/core/Controller.cpp | 7 +- src/version.h | 4 +- src/workers/Workers.cpp | 4 +- 22 files changed, 489 insertions(+), 559 deletions(-) create mode 100644 src/base/io/log/Log.cpp create mode 100644 src/base/io/log/Log.h rename src/{common/log => base/io/log/backends}/ConsoleLog.cpp (64%) rename src/{common/log => base/io/log/backends}/ConsoleLog.h (84%) rename src/{common/log => base/io/log/backends}/FileLog.cpp (62%) rename src/{common/log => base/io/log/backends}/FileLog.h (85%) rename src/{common/log => base/io/log/backends}/SysLog.cpp (80%) rename src/{common/log => base/io/log/backends}/SysLog.h (85%) rename src/{common => base/kernel}/interfaces/ILogBackend.h (79%) delete mode 100644 src/common/log/BasicLog.cpp delete mode 100644 src/common/log/BasicLog.h delete mode 100644 src/common/log/Log.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index c8e68648..5c12f986 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -33,10 +33,6 @@ set(HEADERS src/common/interfaces/IConfigCreator.h src/common/interfaces/IControllerListener.h src/common/interfaces/ICpuInfo.h - src/common/interfaces/ILogBackend.h - src/common/log/BasicLog.h - src/common/log/ConsoleLog.h - src/common/log/FileLog.h src/common/log/Log.h src/common/Platform.h src/common/utils/mm_malloc.h @@ -92,10 +88,6 @@ set(SOURCES src/common/config/ConfigWatcher.cpp src/common/crypto/Algorithm.cpp src/common/crypto/keccak.cpp - src/common/log/BasicLog.cpp - src/common/log/ConsoleLog.cpp - src/common/log/FileLog.cpp - src/common/log/Log.cpp src/common/Platform.cpp src/core/Config.cpp src/core/Controller.cpp @@ -189,12 +181,6 @@ include(cmake/OpenSSL.cmake) include(cmake/asm.cmake) include(cmake/cn-gpu.cmake) -CHECK_INCLUDE_FILE (syslog.h HAVE_SYSLOG_H) -if (HAVE_SYSLOG_H) - add_definitions(/DHAVE_SYSLOG_H) - set(SOURCES_SYSLOG src/common/log/SysLog.h src/common/log/SysLog.cpp) -endif() - if (NOT WITH_AEON) add_definitions(/DXMRIG_NO_AEON) endif() diff --git a/src/App.cpp b/src/App.cpp index db91bab5..f33140c9 100644 --- a/src/App.cpp +++ b/src/App.cpp @@ -31,9 +31,9 @@ #include "api/Api.h" #include "App.h" #include "base/io/Console.h" +#include "base/io/log/Log.h" #include "base/kernel/Signals.h" #include "common/cpu/Cpu.h" -#include "common/log/Log.h" #include "common/Platform.h" #include "core/Config.h" #include "core/Controller.h" @@ -135,7 +135,7 @@ void xmrig::App::onConsoleCommand(char command) case 'p': case 'P': if (Workers::isEnabled()) { - LOG_INFO(m_controller->config()->isColors() ? "\x1B[01;33mpaused\x1B[0m, press \x1B[01;35mr\x1B[0m to resume" : "paused, press 'r' to resume"); + LOG_INFO(YELLOW_BOLD("paused") ", press " MAGENTA_BOLD("r") " to resume"); Workers::setEnabled(false); } break; @@ -143,7 +143,7 @@ void xmrig::App::onConsoleCommand(char command) case 'r': case 'R': if (!Workers::isEnabled()) { - LOG_INFO(m_controller->config()->isColors() ? "\x1B[01;32mresumed" : "resumed"); + LOG_INFO(GREEN_BOLD("resumed")); Workers::setEnabled(true); } break; @@ -194,5 +194,5 @@ void xmrig::App::close() m_controller->stop(); Workers::stop(); - Log::release(); + Log::destroy(); } diff --git a/src/Summary.cpp b/src/Summary.cpp index 78d624df..b5c63b59 100644 --- a/src/Summary.cpp +++ b/src/Summary.cpp @@ -59,11 +59,11 @@ inline static const char *asmName(xmrig::Assembly assembly, bool colors) static void print_memory(xmrig::Config *config) { # ifdef _WIN32 if (config->isColors()) { - xmrig::Log::i()->text(GREEN_BOLD(" * ") WHITE_BOLD("%-13s") "%s", + xmrig::Log::print(GREEN_BOLD(" * ") WHITE_BOLD("%-13s") "%s", "HUGE PAGES", Mem::isHugepagesAvailable() ? "\x1B[1;32mavailable" : "\x1B[01;31munavailable"); } else { - xmrig::Log::i()->text(" * %-13s%s", "HUGE PAGES", Mem::isHugepagesAvailable() ? "available" : "unavailable"); + xmrig::Log::print(" * %-13s%s", "HUGE PAGES", Mem::isHugepagesAvailable() ? "available" : "unavailable"); } # endif } @@ -74,7 +74,7 @@ static void print_cpu(xmrig::Config *config) using namespace xmrig; if (config->isColors()) { - Log::i()->text(GREEN_BOLD(" * ") WHITE_BOLD("%-13s%s (%d)") " %sx64 %sAES %sAVX2", + Log::print(GREEN_BOLD(" * ") WHITE_BOLD("%-13s%s (%d)") " %sx64 %sAES %sAVX2", "CPU", Cpu::info()->brand(), Cpu::info()->sockets(), @@ -82,11 +82,11 @@ static void print_cpu(xmrig::Config *config) Cpu::info()->hasAES() ? "\x1B[1;32m" : "\x1B[1;31m-", Cpu::info()->hasAVX2() ? "\x1B[1;32m" : "\x1B[1;31m-"); # ifndef XMRIG_NO_LIBCPUID - Log::i()->text(GREEN_BOLD(" * ") WHITE_BOLD("%-13s%.1f MB/%.1f MB"), "CPU L2/L3", Cpu::info()->L2() / 1024.0, Cpu::info()->L3() / 1024.0); + Log::print(GREEN_BOLD(" * ") WHITE_BOLD("%-13s%.1f MB/%.1f MB"), "CPU L2/L3", Cpu::info()->L2() / 1024.0, Cpu::info()->L3() / 1024.0); # endif } else { - Log::i()->text(" * %-13s%s (%d) %sx64 %sAES %sAVX2", + Log::print(" * %-13s%s (%d) %sx64 %sAES %sAVX2", "CPU", Cpu::info()->brand(), Cpu::info()->sockets(), @@ -94,7 +94,7 @@ static void print_cpu(xmrig::Config *config) Cpu::info()->hasAES() ? "" : "-", Cpu::info()->hasAVX2() ? "" : "-"); # ifndef XMRIG_NO_LIBCPUID - Log::i()->text(" * %-13s%.1f MB/%.1f MB", "CPU L2/L3", Cpu::info()->L2() / 1024.0, Cpu::info()->L3() / 1024.0); + Log::print(" * %-13s%.1f MB/%.1f MB", "CPU L2/L3", Cpu::info()->L2() / 1024.0, Cpu::info()->L3() / 1024.0); # endif } } @@ -108,7 +108,7 @@ static void print_threads(xmrig::Config *config) snprintf(buf, sizeof buf, ", affinity=0x%" PRIX64, config->affinity()); } - xmrig::Log::i()->text(config->isColors() ? GREEN_BOLD(" * ") WHITE_BOLD("%-13s") CYAN_BOLD("%d") WHITE_BOLD(", %s, av=%d, %sdonate=%d%%") WHITE_BOLD("%s") + xmrig::Log::print(config->isColors() ? GREEN_BOLD(" * ") WHITE_BOLD("%-13s") CYAN_BOLD("%d") WHITE_BOLD(", %s, av=%d, %sdonate=%d%%") WHITE_BOLD("%s") : " * %-13s%d, %s, av=%d, %sdonate=%d%%%s", "THREADS", config->threadsCount(), @@ -119,7 +119,7 @@ static void print_threads(xmrig::Config *config) buf); } else { - xmrig::Log::i()->text(config->isColors() ? GREEN_BOLD(" * ") WHITE_BOLD("%-13s") CYAN_BOLD("%d") WHITE_BOLD(", %s, %sdonate=%d%%") + xmrig::Log::print(config->isColors() ? GREEN_BOLD(" * ") WHITE_BOLD("%-13s") CYAN_BOLD("%d") WHITE_BOLD(", %s, %sdonate=%d%%") : " * %-13s%d, %s, %sdonate=%d%%", "THREADS", config->threadsCount(), @@ -132,11 +132,11 @@ static void print_threads(xmrig::Config *config) if (config->assembly() == xmrig::ASM_AUTO) { const xmrig::Assembly assembly = xmrig::Cpu::info()->assembly(); - xmrig::Log::i()->text(config->isColors() ? GREEN_BOLD(" * ") WHITE_BOLD("%-13sauto:%s") + xmrig::Log::print(config->isColors() ? GREEN_BOLD(" * ") WHITE_BOLD("%-13sauto:%s") : " * %-13sauto:%s", "ASSEMBLY", asmName(assembly, config->isColors())); } else { - xmrig::Log::i()->text(config->isColors() ? GREEN_BOLD(" * ") WHITE_BOLD("%-13s%s") : " * %-13s%s", "ASSEMBLY", asmName(config->assembly(), config->isColors())); + xmrig::Log::print(config->isColors() ? GREEN_BOLD(" * ") WHITE_BOLD("%-13s%s") : " * %-13s%s", "ASSEMBLY", asmName(config->assembly(), config->isColors())); } # endif } @@ -145,12 +145,12 @@ static void print_threads(xmrig::Config *config) static void print_commands(xmrig::Config *config) { if (config->isColors()) { - xmrig::Log::i()->text(GREEN_BOLD(" * ") WHITE_BOLD("COMMANDS ") MAGENTA_BOLD("h") WHITE_BOLD("ashrate, ") + xmrig::Log::print(GREEN_BOLD(" * ") WHITE_BOLD("COMMANDS ") MAGENTA_BOLD("h") WHITE_BOLD("ashrate, ") MAGENTA_BOLD("p") WHITE_BOLD("ause, ") MAGENTA_BOLD("r") WHITE_BOLD("esume")); } else { - xmrig::Log::i()->text(" * COMMANDS 'h' hashrate, 'p' pause, 'r' resume"); + xmrig::Log::print(" * COMMANDS 'h' hashrate, 'p' pause, 'r' resume"); } } diff --git a/src/base/base.cmake b/src/base/base.cmake index 08d86805..66bf74a8 100644 --- a/src/base/base.cmake +++ b/src/base/base.cmake @@ -1,6 +1,9 @@ set(HEADERS_BASE src/base/io/Console.h src/base/io/Json.h + src/base/io/log/backends/ConsoleLog.h + src/base/io/log/backends/FileLog.h + src/base/io/log/Log.h src/base/io/Watcher.h src/base/kernel/Entry.h src/base/kernel/interfaces/IClientListener.h @@ -8,6 +11,7 @@ set(HEADERS_BASE src/base/kernel/interfaces/IConsoleListener.h src/base/kernel/interfaces/IDnsListener.h src/base/kernel/interfaces/ILineListener.h + src/base/kernel/interfaces/ILogBackend.h src/base/kernel/interfaces/ISignalListener.h src/base/kernel/interfaces/IStrategy.h src/base/kernel/interfaces/IStrategyListener.h @@ -37,6 +41,9 @@ set(HEADERS_BASE set(SOURCES_BASE src/base/io/Console.cpp src/base/io/Json.cpp + src/base/io/log/backends/ConsoleLog.cpp + src/base/io/log/backends/FileLog.cpp + src/base/io/log/Log.cpp src/base/io/Watcher.cpp src/base/kernel/Entry.cpp src/base/kernel/Process.cpp @@ -61,3 +68,12 @@ if (WIN32) else() set(SOURCES_OS src/base/io/Json_unix.cpp) endif() + + +if (NOT WIN32) + CHECK_INCLUDE_FILE (syslog.h HAVE_SYSLOG_H) + if (HAVE_SYSLOG_H) + add_definitions(/DHAVE_SYSLOG_H) + set(SOURCES_SYSLOG src/base/log/backends/SysLog.h src/base/log/backends/SysLog.cpp) + endif() +endif() diff --git a/src/base/io/log/Log.cpp b/src/base/io/log/Log.cpp new file mode 100644 index 00000000..eec17760 --- /dev/null +++ b/src/base/io/log/Log.cpp @@ -0,0 +1,245 @@ +/* XMRig + * Copyright 2010 Jeff Garzik + * Copyright 2012-2014 pooler + * Copyright 2014 Lucas Jones + * Copyright 2014-2016 Wolf9466 + * Copyright 2016 Jay D Dee + * Copyright 2017-2018 XMR-Stak , + * Copyright 2019 Spudz76 + * Copyright 2018-2019 SChernykh + * Copyright 2016-2019 XMRig , + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + + +#ifdef WIN32 +# include +# include +#endif + + +#include +#include +#include +#include + + +#include "base/io/log/Log.h" +#include "base/kernel/interfaces/ILogBackend.h" + + +namespace xmrig { + + +static const char *colors_map[] = { + RED_BOLD_S, // EMERG + RED_BOLD_S, // ALERT + RED_BOLD_S, // CRIT + RED_S, // ERR + YELLOW_S, // WARNING + WHITE_BOLD_S, // NOTICE + nullptr, // INFO +# ifdef WIN32 + BLACK_BOLD_S // DEBUG +# else + BRIGHT_BLACK_S // DEBUG +# endif +}; + + + +class LogPrivate +{ +public: + inline LogPrivate() : + m_buf() + { + uv_mutex_init(&m_mutex); + } + + + inline ~LogPrivate() + { + uv_mutex_destroy(&m_mutex); + + for (ILogBackend *backend : m_backends) { + delete backend; + } + } + + + inline void add(ILogBackend *backend) { m_backends.push_back(backend); } + + + void print(Log::Level level, const char *fmt, va_list args) + { + size_t size = 0; + size_t offset = 0; + + lock(); + timestamp(level, size, offset); + color(level, size); + + int rc = vsnprintf(m_buf + size, sizeof (m_buf) - offset - 32, fmt, args); + if (rc < 0) { + return unlock(); + } + + size += static_cast(rc); + endl(size); + + std::string txt(m_buf); + size_t i; + while ((i = txt.find(CSI)) != std::string::npos) { + txt.erase(i, txt.find('m', i) - i + 1); + } + + if (!m_backends.empty()) { + for (ILogBackend *backend : m_backends) { + backend->print(level, m_buf, offset, size, true); + backend->print(level, txt.c_str(), offset, txt.size(), false); + } + } + else { + fputs(txt.c_str(), stdout); + fflush(stdout); + } + + unlock(); + } + + +private: + inline void lock() { uv_mutex_lock(&m_mutex); } + inline void unlock() { uv_mutex_unlock(&m_mutex); } + + + inline void timestamp(Log::Level level, size_t &size, size_t &offset) + { + if (level == Log::NONE) { + return; + } + + time_t now = time(nullptr); + tm stime; + +# ifdef _WIN32 + localtime_s(&stime, &now); +# else + localtime_r(&now, &stime); +# endif + + const int rc = snprintf(m_buf, sizeof(m_buf) - 1, "[%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 + ); + + if (rc > 0) { + size = offset = static_cast(rc); + } + } + + + inline void color(Log::Level level, size_t &size) + { + if (level == Log::NONE) { + return; + } + + const char *color = colors_map[level]; + if (color == nullptr) { + return; + } + + const size_t s = strlen(color); + memcpy(m_buf + size, color, s); + + size += s; + } + + + inline void endl(size_t &size) + { +# ifdef _WIN32 + memcpy(m_buf + size, CLEAR "\r\n", 7); + size += 6; +# else + memcpy(m_buf + size, CLEAR "\n", 6); + size += 5; +# endif + } + + + char m_buf[4096]; + std::vector m_backends; + uv_mutex_t m_mutex; +}; + + +bool Log::colors = true; +LogPrivate *Log::d = new LogPrivate(); + + +} /* namespace xmrig */ + + + +void xmrig::Log::add(ILogBackend *backend) +{ + if (d) { + d->add(backend); + } +} + + +void xmrig::Log::destroy() +{ + delete d; + d = nullptr; +} + + +void xmrig::Log::print(const char *fmt, ...) +{ + if (!d) { + return; + } + + va_list args; + va_start(args, fmt); + + d->print(NONE, fmt, args); + + va_end(args); +} + + +void xmrig::Log::print(Level level, const char *fmt, ...) +{ + if (!d) { + return; + } + + va_list args; + va_start(args, fmt); + + d->print(level, fmt, args); + + va_end(args); +} diff --git a/src/base/io/log/Log.h b/src/base/io/log/Log.h new file mode 100644 index 00000000..a14ffded --- /dev/null +++ b/src/base/io/log/Log.h @@ -0,0 +1,129 @@ +/* XMRig + * Copyright 2010 Jeff Garzik + * Copyright 2012-2014 pooler + * Copyright 2014 Lucas Jones + * Copyright 2014-2016 Wolf9466 + * Copyright 2016 Jay D Dee + * Copyright 2017-2018 XMR-Stak , + * Copyright 2019 Spudz76 + * Copyright 2018-2019 SChernykh + * Copyright 2016-2019 XMRig , + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef XMRIG_LOG_H +#define XMRIG_LOG_H + + +namespace xmrig { + + +class ILogBackend; +class LogPrivate; + + +class Log +{ +public: + enum Level : int { + NONE = -1, + EMERG, // system is unusable + ALERT, // action must be taken immediately + CRIT, // critical conditions + ERR, // error conditions + WARNING, // warning conditions + NOTICE, // normal but significant condition + INFO, // informational + DEBUG, // debug-level messages + }; + + static void add(ILogBackend *backend); + static void destroy(); + static void print(const char *fmt, ...); + static void print(Level level, const char *fmt, ...); + + static bool colors; + +private: + static LogPrivate *d; +}; + + +#define CSI "\x1B[" // Control Sequence Introducer (ANSI spec name) +#define CLEAR CSI "0m" // all attributes off +#define BRIGHT_BLACK_S CSI "0;90m" // somewhat MD.GRAY +#define BLACK_S CSI "0;30m" +#define BLACK_BOLD_S CSI "1;30m" // another name for GRAY +#define RED_S CSI "0;31m" +#define RED_BOLD_S CSI "1;31m" +#define GREEN_S CSI "0;32m" +#define GREEN_BOLD_S CSI "1;32m" +#define YELLOW_S CSI "0;33m" +#define YELLOW_BOLD_S CSI "1;33m" +#define BLUE_S CSI "0;34m" +#define BLUE_BOLD_S CSI "1;34m" +#define MAGENTA_S CSI "0;35m" +#define MAGENTA_BOLD_S CSI "1;35m" +#define CYAN_S CSI "0;36m" +#define CYAN_BOLD_S CSI "1;36m" +#define WHITE_S CSI "0;37m" // another name for LT.GRAY +#define WHITE_BOLD_S CSI "1;37m" // actually white + +//color wrappings +#define BLACK(x) BLACK_S x CLEAR +#define BLACK_BOLD(x) BLACK_BOLD_S x CLEAR +#define RED(x) RED_S x CLEAR +#define RED_BOLD(x) RED_BOLD_S x CLEAR +#define GREEN(x) GREEN_S x CLEAR +#define GREEN_BOLD(x) GREEN_BOLD_S x CLEAR +#define YELLOW(x) YELLOW_S x CLEAR +#define YELLOW_BOLD(x) YELLOW_BOLD_S x CLEAR +#define BLUE(x) BLUE_S x CLEAR +#define BLUE_BOLD(x) BLUE_BOLD_S x CLEAR +#define MAGENTA(x) MAGENTA_S x CLEAR +#define MAGENTA_BOLD(x) MAGENTA_BOLD_S x CLEAR +#define CYAN(x) CYAN_S x CLEAR +#define CYAN_BOLD(x) CYAN_BOLD_S x CLEAR +#define WHITE(x) WHITE_S x CLEAR +#define WHITE_BOLD(x) WHITE_BOLD_S x CLEAR + + +#define LOG_EMERG(x, ...) xmrig::Log::print(xmrig::Log::EMERG, x, ##__VA_ARGS__) +#define LOG_ALERT(x, ...) xmrig::Log::print(xmrig::Log::ALERT, x, ##__VA_ARGS__) +#define LOG_CRIT(x, ...) xmrig::Log::print(xmrig::Log::CRIT, x, ##__VA_ARGS__) +#define LOG_ERR(x, ...) xmrig::Log::print(xmrig::Log::ERR, x, ##__VA_ARGS__) +#define LOG_WARN(x, ...) xmrig::Log::print(xmrig::Log::WARNING, x, ##__VA_ARGS__) +#define LOG_NOTICE(x, ...) xmrig::Log::print(xmrig::Log::NOTICE, x, ##__VA_ARGS__) +#define LOG_INFO(x, ...) xmrig::Log::print(xmrig::Log::INFO, x, ##__VA_ARGS__) + +#ifdef APP_DEBUG +# define LOG_DEBUG(x, ...) xmrig::Log::print(xmrig::Log::DEBUG, x, ##__VA_ARGS__) +#else +# define LOG_DEBUG(x, ...) +#endif + +#if defined(APP_DEBUG) || defined(APP_DEVEL) +# define LOG_DEBUG_ERR(x, ...) xmrig::Log::print(xmrig::Log::ERR, x, ##__VA_ARGS__) +# define LOG_DEBUG_WARN(x, ...) xmrig::Log::print(xmrig::Log::WARNING, x, ##__VA_ARGS__) +#else +# define LOG_DEBUG_ERR(x, ...) +# define LOG_DEBUG_WARN(x, ...) +#endif + + +} /* namespace xmrig */ + + +#endif /* XMRIG_LOG_H */ diff --git a/src/common/log/ConsoleLog.cpp b/src/base/io/log/backends/ConsoleLog.cpp similarity index 64% rename from src/common/log/ConsoleLog.cpp rename to src/base/io/log/backends/ConsoleLog.cpp index e0ac01ea..a5b6c1a7 100644 --- a/src/common/log/ConsoleLog.cpp +++ b/src/base/io/log/backends/ConsoleLog.cpp @@ -5,6 +5,7 @@ * Copyright 2014-2016 Wolf9466 * Copyright 2016 Jay D Dee * Copyright 2017-2018 XMR-Stak , + * Copyright 2019 Spudz76 * Copyright 2018-2019 SChernykh * Copyright 2016-2019 XMRig , * @@ -23,21 +24,12 @@ */ -#include #include -#include -#include -#include - -#ifdef WIN32 -# include -# include -#endif #include "base/tools/Handle.h" -#include "common/log/ConsoleLog.h" -#include "common/log/Log.h" +#include "base/io/log/backends/ConsoleLog.h" +#include "base/io/log/Log.h" xmrig::ConsoleLog::ConsoleLog() : @@ -51,8 +43,7 @@ xmrig::ConsoleLog::ConsoleLog() : } uv_tty_set_mode(m_tty, UV_TTY_MODE_NORMAL); - m_uvBuf.base = m_buf; - m_stream = reinterpret_cast(m_tty); + m_stream = reinterpret_cast(m_tty); # ifdef WIN32 HANDLE handle = GetStdHandle(STD_INPUT_HANDLE); @@ -73,38 +64,25 @@ xmrig::ConsoleLog::~ConsoleLog() } -void xmrig::ConsoleLog::message(Level level, const char* fmt, va_list args) +void xmrig::ConsoleLog::print(int, const char *line, size_t, size_t size, bool colors) { - time_t now = time(nullptr); - tm stime; + if (Log::colors != colors) { + return; + } # ifdef _WIN32 - localtime_s(&stime, &now); + uv_buf_t buf = uv_buf_init(const_cast(line), static_cast(size)); # else - localtime_r(&now, &stime); + uv_buf_t buf = uv_buf_init(const_cast(line), size); # endif - snprintf(m_fmt, sizeof(m_fmt) - 1, "[%d-%02d-%02d %02d:%02d:%02d]%s %s%s", - stime.tm_year + 1900, - stime.tm_mon + 1, - stime.tm_mday, - stime.tm_hour, - stime.tm_min, - stime.tm_sec, - Log::colorByLevel(level, Log::colors), - fmt, - Log::endl(Log::colors) - ); - - print(args); -} - - -void xmrig::ConsoleLog::text(const char* fmt, va_list args) -{ - snprintf(m_fmt, sizeof(m_fmt) - 1, "%s%s", fmt, Log::endl(Log::colors)); - - print(args); + if (!isWritable()) { + fputs(line, stdout); + fflush(stdout); + } + else { + uv_try_write(m_stream, &buf, 1); + } } @@ -117,20 +95,3 @@ bool xmrig::ConsoleLog::isWritable() const const uv_handle_type type = uv_guess_handle(1); return type == UV_TTY || type == UV_NAMED_PIPE; } - - -void xmrig::ConsoleLog::print(va_list args) -{ - m_uvBuf.len = vsnprintf(m_buf, sizeof(m_buf) - 1, m_fmt, args); - if (m_uvBuf.len <= 0) { - return; - } - - if (!isWritable()) { - fputs(m_buf, stdout); - fflush(stdout); - } - else { - uv_try_write(m_stream, &m_uvBuf, 1); - } -} diff --git a/src/common/log/ConsoleLog.h b/src/base/io/log/backends/ConsoleLog.h similarity index 84% rename from src/common/log/ConsoleLog.h rename to src/base/io/log/backends/ConsoleLog.h index 73a701e6..90e4fa14 100644 --- a/src/common/log/ConsoleLog.h +++ b/src/base/io/log/backends/ConsoleLog.h @@ -5,6 +5,7 @@ * Copyright 2014-2016 Wolf9466 * Copyright 2016 Jay D Dee * Copyright 2017-2018 XMR-Stak , + * Copyright 2019 Spudz76 * Copyright 2018-2019 SChernykh * Copyright 2016-2019 XMRig , * @@ -26,10 +27,11 @@ #define XMRIG_CONSOLELOG_H -#include +typedef struct uv_stream_s uv_stream_t; +typedef struct uv_tty_s uv_tty_t; -#include "common/interfaces/ILogBackend.h" +#include "base/kernel/interfaces/ILogBackend.h" namespace xmrig { @@ -42,16 +44,11 @@ public: ~ConsoleLog() override; protected: - void message(Level level, const char *fmt, va_list args) override; - void text(const char *fmt, va_list args) override; + void print(int level, const char *line, size_t offset, size_t size, bool colors) override; private: bool isWritable() const; - void print(va_list args); - char m_buf[kBufferSize]; - char m_fmt[256]; - uv_buf_t m_uvBuf; uv_stream_t *m_stream; uv_tty_t *m_tty; }; diff --git a/src/common/log/FileLog.cpp b/src/base/io/log/backends/FileLog.cpp similarity index 62% rename from src/common/log/FileLog.cpp rename to src/base/io/log/backends/FileLog.cpp index 71eeb18c..82c8407e 100644 --- a/src/common/log/FileLog.cpp +++ b/src/base/io/log/backends/FileLog.cpp @@ -5,6 +5,7 @@ * Copyright 2014-2016 Wolf9466 * Copyright 2016 Jay D Dee * Copyright 2017-2018 XMR-Stak , + * Copyright 2019 Spudz76 * Copyright 2018-2019 SChernykh * Copyright 2016-2019 XMRig , * @@ -23,15 +24,10 @@ */ -#include -#include -#include -#include -#include +#include -#include "common/log/FileLog.h" -#include "common/log/Log.h" +#include "base/io/log/backends/FileLog.h" xmrig::FileLog::FileLog(const char *fileName) @@ -42,43 +38,22 @@ xmrig::FileLog::FileLog(const char *fileName) } -void xmrig::FileLog::message(Level level, const char* fmt, va_list args) +void xmrig::FileLog::print(int, const char *line, size_t, size_t size, bool colors) { - if (m_file < 0) { + if (m_file < 0 || colors) { return; } - time_t now = time(nullptr); - tm stime; - # ifdef _WIN32 - localtime_s(&stime, &now); + uv_buf_t buf = uv_buf_init(strdup(line), static_cast(size)); # else - localtime_r(&now, &stime); + uv_buf_t buf = uv_buf_init(strdup(line), size); # endif - snprintf(m_fmt, sizeof(m_fmt) - 1, "[%d-%02d-%02d %02d:%02d:%02d]%s %s%s", - stime.tm_year + 1900, - stime.tm_mon + 1, - stime.tm_mday, - stime.tm_hour, - stime.tm_min, - stime.tm_sec, - Log::colorByLevel(level, Log::colors), - fmt, - Log::endl(Log::colors) - ); + uv_fs_t *req = new uv_fs_t; + req->data = buf.base; - char *buf = new char[kBufferSize]; - const int size = vsnprintf(buf, kBufferSize - 1, m_fmt, args); - - write(buf, size); -} - - -void xmrig::FileLog::text(const char* fmt, va_list args) -{ - message(INFO, fmt, args); + uv_fs_write(uv_default_loop(), req, m_file, &buf, 1, -1, FileLog::onWrite); } @@ -89,13 +64,3 @@ void xmrig::FileLog::onWrite(uv_fs_t *req) uv_fs_req_cleanup(req); delete req; } - - -void xmrig::FileLog::write(char *data, size_t size) -{ - uv_buf_t buf = uv_buf_init(data, (unsigned int) size); - uv_fs_t *req = new uv_fs_t; - req->data = buf.base; - - uv_fs_write(uv_default_loop(), req, m_file, &buf, 1, -1, FileLog::onWrite); -} diff --git a/src/common/log/FileLog.h b/src/base/io/log/backends/FileLog.h similarity index 85% rename from src/common/log/FileLog.h rename to src/base/io/log/backends/FileLog.h index da80acb2..188a99aa 100644 --- a/src/common/log/FileLog.h +++ b/src/base/io/log/backends/FileLog.h @@ -5,6 +5,7 @@ * Copyright 2014-2016 Wolf9466 * Copyright 2016 Jay D Dee * Copyright 2017-2018 XMR-Stak , + * Copyright 2019 Spudz76 * Copyright 2018-2019 SChernykh * Copyright 2016-2019 XMRig , * @@ -26,10 +27,10 @@ #define XMRIG_FILELOG_H -#include +typedef struct uv_fs_s uv_fs_t; -#include "common/interfaces/ILogBackend.h" +#include "base/kernel/interfaces/ILogBackend.h" namespace xmrig { @@ -40,15 +41,13 @@ class FileLog : public ILogBackend public: FileLog(const char *fileName); - void message(Level level, const char* fmt, va_list args) override; - void text(const char* fmt, va_list args) override; + +protected: + void print(int level, const char *line, size_t offset, size_t size, bool colors) override; private: static void onWrite(uv_fs_t *req); - void write(char *data, size_t size); - - char m_fmt[256]; int m_file; }; diff --git a/src/common/log/SysLog.cpp b/src/base/io/log/backends/SysLog.cpp similarity index 80% rename from src/common/log/SysLog.cpp rename to src/base/io/log/backends/SysLog.cpp index 1a8ffbd2..b75973f1 100644 --- a/src/common/log/SysLog.cpp +++ b/src/base/io/log/backends/SysLog.cpp @@ -5,6 +5,7 @@ * Copyright 2014-2016 Wolf9466 * Copyright 2016 Jay D Dee * Copyright 2017-2018 XMR-Stak , + * Copyright 2019 Spudz76 * Copyright 2018-2019 SChernykh * Copyright 2016-2019 XMRig , * @@ -26,7 +27,7 @@ #include -#include "common/log/SysLog.h" +#include "base/io/log/backends/SysLog.h" #include "version.h" @@ -36,13 +37,17 @@ xmrig::SysLog::SysLog() } -void xmrig::SysLog::message(Level level, const char *fmt, va_list args) +xmrig::SysLog::~SysLog() { - vsyslog(static_cast(level), fmt, args); + closelog(); } -void xmrig::SysLog::text(const char *fmt, va_list args) +void xmrig::SysLog::print(int level, const char *line, size_t offset, size_t, bool colors) { - vsyslog(LOG_INFO, fmt, args); + if (colors) { + return; + } + + syslog(level == -1 ? LOG_INFO : level, line + offset); } diff --git a/src/common/log/SysLog.h b/src/base/io/log/backends/SysLog.h similarity index 85% rename from src/common/log/SysLog.h rename to src/base/io/log/backends/SysLog.h index 3e64cf8b..0e8d0f8e 100644 --- a/src/common/log/SysLog.h +++ b/src/base/io/log/backends/SysLog.h @@ -5,6 +5,7 @@ * Copyright 2014-2016 Wolf9466 * Copyright 2016 Jay D Dee * Copyright 2017-2018 XMR-Stak , + * Copyright 2019 Spudz76 * Copyright 2018-2019 SChernykh * Copyright 2016-2019 XMRig , * @@ -26,7 +27,7 @@ #define XMRIG_SYSLOG_H -#include "common/interfaces/ILogBackend.h" +#include "base/kernel/interfaces/ILogBackend.h" namespace xmrig { @@ -36,9 +37,10 @@ class SysLog : public ILogBackend { public: SysLog(); + ~SysLog(); - void message(Level level, const char *fmt, va_list args) override; - void text(const char *fmt, va_list args) override; +protected: + void print(int level, const char *line, size_t offset, size_t size, bool colors) override; }; diff --git a/src/common/interfaces/ILogBackend.h b/src/base/kernel/interfaces/ILogBackend.h similarity index 79% rename from src/common/interfaces/ILogBackend.h rename to src/base/kernel/interfaces/ILogBackend.h index 2299fc67..ef18da88 100644 --- a/src/common/interfaces/ILogBackend.h +++ b/src/base/kernel/interfaces/ILogBackend.h @@ -5,6 +5,7 @@ * Copyright 2014-2016 Wolf9466 * Copyright 2016 Jay D Dee * Copyright 2017-2018 XMR-Stak , + * Copyright 2019 Spudz76 * Copyright 2018-2019 SChernykh * Copyright 2016-2019 XMRig , * @@ -36,24 +37,9 @@ namespace xmrig { class ILogBackend { public: - enum Level { - ERR, - WARNING, - NOTICE, - INFO, - DEBUG - }; - -# ifdef APP_DEBUG - constexpr static const size_t kBufferSize = 1024; -# else - constexpr static const size_t kBufferSize = 512; -# endif - virtual ~ILogBackend() = default; - virtual void message(Level level, const char* fmt, va_list args) = 0; - virtual void text(const char* fmt, va_list args) = 0; + virtual void print(int level, const char *line, size_t offset, size_t size, bool colors) = 0; }; diff --git a/src/base/net/stratum/Pools.cpp b/src/base/net/stratum/Pools.cpp index fc132dd5..f2d34287 100644 --- a/src/base/net/stratum/Pools.cpp +++ b/src/base/net/stratum/Pools.cpp @@ -164,21 +164,21 @@ void xmrig::Pools::print() const if (Log::colors) { const int color = pool.isEnabled() ? (pool.isTLS() ? 32 : 36) : 31; - Log::i()->text(GREEN_BOLD(" * ") WHITE_BOLD("POOL #%-7zu") "\x1B[1;%dm%s\x1B[0m variant " WHITE_BOLD("%s"), - i, - color, - pool.url().data(), - pool.algorithm().variantName() - ); + Log::print(GREEN_BOLD(" * ") WHITE_BOLD("POOL #%-7zu") "\x1B[1;%dm%s\x1B[0m variant " WHITE_BOLD("%s"), + i, + color, + pool.url().data(), + pool.algorithm().variantName() + ); } else { - Log::i()->text(" * POOL #%-7zu%s%s variant=%s %s", - i, - pool.isEnabled() ? "" : "-", - pool.url().data(), - pool.algorithm().variantName(), - pool.isTLS() ? "TLS" : "" - ); + Log::print(" * POOL #%-7zu%s%s variant=%s %s", + i, + pool.isEnabled() ? "" : "-", + pool.url().data(), + pool.algorithm().variantName(), + pool.isTLS() ? "TLS" : "" + ); } i++; diff --git a/src/common/config/CommonConfig.cpp b/src/common/config/CommonConfig.cpp index 94bbd59f..1be36426 100644 --- a/src/common/config/CommonConfig.cpp +++ b/src/common/config/CommonConfig.cpp @@ -93,7 +93,7 @@ void xmrig::CommonConfig::printAPI() return; } - Log::i()->text(isColors() ? GREEN_BOLD(" * ") WHITE_BOLD("%-13s") CYAN("%s:") CYAN_BOLD("%d") + Log::print(isColors() ? GREEN_BOLD(" * ") WHITE_BOLD("%-13s") CYAN("%s:") CYAN_BOLD("%d") : " * %-13s%s:%d", "API BIND", isApiIPv6() ? "[::]" : "0.0.0.0", apiPort()); # endif @@ -118,7 +118,7 @@ void xmrig::CommonConfig::printVersions() snprintf(buf, sizeof buf, "MSVC/%d", MSVC_VERSION); # endif - Log::i()->text(isColors() ? GREEN_BOLD(" * ") WHITE_BOLD("%-13s") CYAN_BOLD("%s/%s") WHITE_BOLD(" %s") + Log::print(isColors() ? GREEN_BOLD(" * ") WHITE_BOLD("%-13s") CYAN_BOLD("%s/%s") WHITE_BOLD(" %s") : " * %-13s%s/%s %s", "ABOUT", APP_NAME, APP_VERSION, buf); @@ -157,8 +157,8 @@ void xmrig::CommonConfig::printVersions() length += snprintf(buf + length, (sizeof buf) - length, "microhttpd/%s ", MHD_get_version()); # endif - Log::i()->text(isColors() ? GREEN_BOLD(" * ") WHITE_BOLD("%-13slibuv/%s %s") - : " * %-13slibuv/%s %s", + Log::print(isColors() ? GREEN_BOLD(" * ") WHITE_BOLD("%-13slibuv/%s %s") + : " * %-13slibuv/%s %s", "LIBS", uv_version_string(), buf); } diff --git a/src/common/log/BasicLog.cpp b/src/common/log/BasicLog.cpp deleted file mode 100644 index b048dd6e..00000000 --- a/src/common/log/BasicLog.cpp +++ /dev/null @@ -1,90 +0,0 @@ -/* XMRig - * Copyright 2010 Jeff Garzik - * Copyright 2012-2014 pooler - * Copyright 2014 Lucas Jones - * Copyright 2014-2016 Wolf9466 - * Copyright 2016 Jay D Dee - * Copyright 2017-2018 XMR-Stak , - * Copyright 2018-2019 SChernykh - * Copyright 2016-2019 XMRig , - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - - -#include -#include -#include -#include -#include - -#ifdef WIN32 -# include -# include -#endif - - -#include "common/log/BasicLog.h" -#include "common/log/Log.h" - - -xmrig::BasicLog::BasicLog() -{ -} - - -void xmrig::BasicLog::message(Level level, const char* fmt, va_list args) -{ - time_t now = time(nullptr); - tm stime; - -# ifdef _WIN32 - localtime_s(&stime, &now); -# else - localtime_r(&now, &stime); -# endif - - snprintf(m_fmt, sizeof(m_fmt) - 1, "[%d-%02d-%02d %02d:%02d:%02d]%s %s%s", - stime.tm_year + 1900, - stime.tm_mon + 1, - stime.tm_mday, - stime.tm_hour, - stime.tm_min, - stime.tm_sec, - Log::colorByLevel(level, false), - fmt, - Log::endl(false) - ); - - print(args); -} - - -void xmrig::BasicLog::text(const char* fmt, va_list args) -{ - snprintf(m_fmt, sizeof(m_fmt) - 1, "%s%s", fmt, Log::endl(false)); - - print(args); -} - - -void xmrig::BasicLog::print(va_list args) -{ - if (vsnprintf(m_buf, sizeof(m_buf) - 1, m_fmt, args) <= 0) { - return; - } - - fputs(m_buf, stdout); - fflush(stdout); -} diff --git a/src/common/log/BasicLog.h b/src/common/log/BasicLog.h deleted file mode 100644 index bddbe07c..00000000 --- a/src/common/log/BasicLog.h +++ /dev/null @@ -1,57 +0,0 @@ -/* XMRig - * Copyright 2010 Jeff Garzik - * Copyright 2012-2014 pooler - * Copyright 2014 Lucas Jones - * Copyright 2014-2016 Wolf9466 - * Copyright 2016 Jay D Dee - * Copyright 2017-2018 XMR-Stak , - * Copyright 2018-2019 SChernykh - * Copyright 2016-2019 XMRig , - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#ifndef XMRIG_BASICLOG_H -#define XMRIG_BASICLOG_H - - -#include - - -#include "common/interfaces/ILogBackend.h" - - -namespace xmrig { - - -class BasicLog : public ILogBackend -{ -public: - BasicLog(); - - void message(Level level, const char *fmt, va_list args) override; - void text(const char *fmt, va_list args) override; - -private: - bool isWritable() const; - void print(va_list args); - - char m_buf[kBufferSize]; - char m_fmt[256]; -}; - - -} /* namespace xmrig */ - -#endif /* XMRIG_BASICLOG_H */ diff --git a/src/common/log/Log.cpp b/src/common/log/Log.cpp deleted file mode 100644 index 4ef1e14a..00000000 --- a/src/common/log/Log.cpp +++ /dev/null @@ -1,134 +0,0 @@ -/* XMRig - * Copyright 2010 Jeff Garzik - * Copyright 2012-2014 pooler - * Copyright 2014 Lucas Jones - * Copyright 2014-2016 Wolf9466 - * Copyright 2016 Jay D Dee - * Copyright 2017-2018 XMR-Stak , - * Copyright 2018-2019 SChernykh - * Copyright 2016-2019 XMRig , - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - - -#include -#include -#include -#include -#include - - -#include "common/interfaces/ILogBackend.h" -#include "common/log/BasicLog.h" -#include "common/log/Log.h" - - -namespace xmrig { - -Log *Log::m_self = nullptr; -bool Log::colors = true; - - -static const char *color[5] = { - "\x1B[0;31m", /* ERR */ - "\x1B[0;33m", /* WARNING */ - "\x1B[1;37m", /* NOTICE */ - "", /* INFO */ -# ifdef WIN32 - "\x1B[1;30m" /* DEBUG */ -# else - "\x1B[90m" /* DEBUG */ -# endif -}; - -} /* namespace xmrig */ - - -void xmrig::Log::message(ILogBackend::Level level, const char* fmt, ...) -{ - uv_mutex_lock(&m_mutex); - - 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); - } - - va_end(args); - - uv_mutex_unlock(&m_mutex); -} - - -void xmrig::Log::text(const char* fmt, ...) -{ - uv_mutex_lock(&m_mutex); - - 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); - - uv_mutex_unlock(&m_mutex); -} - - -const char *xmrig::Log::colorByLevel(ILogBackend::Level level, bool isColors) -{ - if (!isColors) { - return ""; - } - - return color[level]; -} - - -const char *xmrig::Log::endl(bool isColors) -{ -# ifdef _WIN32 - return isColors ? "\x1B[0m\r\n" : "\r\n"; -# else - return isColors ? "\x1B[0m\n" : "\n"; -# endif -} - - -void xmrig::Log::defaultInit() -{ - m_self = new Log(); - - add(new BasicLog()); -} - - -xmrig::Log::~Log() -{ - m_self = nullptr; - - for (auto backend : m_backends) { - delete backend; - } -} diff --git a/src/common/log/Log.h b/src/common/log/Log.h index 9a0ba2a9..f393b1da 100644 --- a/src/common/log/Log.h +++ b/src/common/log/Log.h @@ -22,90 +22,11 @@ * along with this program. If not, see . */ -#ifndef XMRIG_LOG_H -#define XMRIG_LOG_H +#ifndef XMRIG_LOG_LEGACY_H +#define XMRIG_LOG_LEGACY_H -#include -#include -#include +#include "base/io/log/Log.h" -#include "common/interfaces/ILogBackend.h" - - -namespace xmrig { - - -class Log -{ -public: - static inline Log* i() { if (!m_self) { defaultInit(); } return m_self; } - static inline void add(ILogBackend *backend) { i()->m_backends.push_back(backend); } - static inline void init() { if (!m_self) { new Log(); } } - static inline void release() { delete m_self; } - - void message(ILogBackend::Level level, const char* fmt, ...); - void text(const char* fmt, ...); - - static const char *colorByLevel(ILogBackend::Level level, bool isColors = true); - static const char *endl(bool isColors = true); - static void defaultInit(); - - static bool colors; - -private: - inline Log() { - assert(m_self == nullptr); - - uv_mutex_init(&m_mutex); - - m_self = this; - } - - ~Log(); - - static Log *m_self; - std::vector m_backends; - uv_mutex_t m_mutex; -}; - - -} /* namespace xmrig */ - - -#define RED_BOLD(x) "\x1B[1;31m" x "\x1B[0m" -#define RED(x) "\x1B[0;31m" x "\x1B[0m" -#define GREEN_BOLD(x) "\x1B[1;32m" x "\x1B[0m" -#define GREEN(x) "\x1B[0;32m" x "\x1B[0m" -#define YELLOW(x) "\x1B[0;33m" x "\x1B[0m" -#define YELLOW_BOLD(x) "\x1B[1;33m" x "\x1B[0m" -#define MAGENTA_BOLD(x) "\x1B[1;35m" x "\x1B[0m" -#define MAGENTA(x) "\x1B[0;35m" x "\x1B[0m" -#define CYAN_BOLD(x) "\x1B[1;36m" x "\x1B[0m" -#define CYAN(x) "\x1B[0;36m" x "\x1B[0m" -#define WHITE_BOLD(x) "\x1B[1;37m" x "\x1B[0m" -#define WHITE(x) "\x1B[0;37m" x "\x1B[0m" -#define GRAY(x) "\x1B[1;30m" x "\x1B[0m" - - -#define LOG_ERR(x, ...) xmrig::Log::i()->message(xmrig::ILogBackend::ERR, x, ##__VA_ARGS__) -#define LOG_WARN(x, ...) xmrig::Log::i()->message(xmrig::ILogBackend::WARNING, x, ##__VA_ARGS__) -#define LOG_NOTICE(x, ...) xmrig::Log::i()->message(xmrig::ILogBackend::NOTICE, x, ##__VA_ARGS__) -#define LOG_INFO(x, ...) xmrig::Log::i()->message(xmrig::ILogBackend::INFO, x, ##__VA_ARGS__) - -#ifdef APP_DEBUG -# define LOG_DEBUG(x, ...) xmrig::Log::i()->message(xmrig::ILogBackend::DEBUG, x, ##__VA_ARGS__) -#else -# define LOG_DEBUG(x, ...) -#endif - -#if defined(APP_DEBUG) || defined(APP_DEVEL) -# define LOG_DEBUG_ERR(x, ...) xmrig::Log::i()->message(xmrig::ILogBackend::ERR, x, ##__VA_ARGS__) -# define LOG_DEBUG_WARN(x, ...) xmrig::Log::i()->message(xmrig::ILogBackend::WARNING, x, ##__VA_ARGS__) -#else -# define LOG_DEBUG_ERR(x, ...) -# define LOG_DEBUG_WARN(x, ...) -#endif - -#endif /* XMRIG_LOG_H */ +#endif /* XMRIG_LOG_LEGACY_H */ diff --git a/src/core/Controller.cpp b/src/core/Controller.cpp index cfd132dd..6088034b 100644 --- a/src/core/Controller.cpp +++ b/src/core/Controller.cpp @@ -26,11 +26,11 @@ #include +#include "base/io/log/backends/ConsoleLog.h" +#include "base/io/log/backends/FileLog.h" #include "common/config/ConfigLoader.h" #include "common/cpu/Cpu.h" #include "common/interfaces/IControllerListener.h" -#include "common/log/ConsoleLog.h" -#include "common/log/FileLog.h" #include "common/log/Log.h" #include "common/Platform.h" #include "core/Config.h" @@ -39,7 +39,7 @@ #ifdef HAVE_SYSLOG_H -# include "common/log/SysLog.h" +# include "base/io/log/backends/SysLog.h" #endif @@ -102,7 +102,6 @@ int xmrig::Controller::init() return 1; } - Log::init(); Platform::init(config()->userAgent()); Platform::setProcessPriority(d_ptr->config->priority()); diff --git a/src/version.h b/src/version.h index 2c6eb6ef..117f1d6a 100644 --- a/src/version.h +++ b/src/version.h @@ -28,7 +28,7 @@ #define APP_ID "xmrig" #define APP_NAME "XMRig" #define APP_DESC "XMRig CPU miner" -#define APP_VERSION "2.15.0-beta" +#define APP_VERSION "2.15.1-evo" #define APP_DOMAIN "xmrig.com" #define APP_SITE "www.xmrig.com" #define APP_COPYRIGHT "Copyright (C) 2016-2019 xmrig.com" @@ -36,7 +36,7 @@ #define APP_VER_MAJOR 2 #define APP_VER_MINOR 15 -#define APP_VER_PATCH 0 +#define APP_VER_PATCH 1 #ifdef _MSC_VER # if (_MSC_VER >= 1910) diff --git a/src/workers/Workers.cpp b/src/workers/Workers.cpp index 5426762e..4adf349f 100644 --- a/src/workers/Workers.cpp +++ b/src/workers/Workers.cpp @@ -104,11 +104,11 @@ void Workers::printHashrate(bool detail) char num2[8] = { 0 }; char num3[8] = { 0 }; - xmrig::Log::i()->text("%s| THREAD | AFFINITY | 10s H/s | 60s H/s | 15m H/s |", isColors ? "\x1B[1;37m" : ""); + xmrig::Log::print("%s| THREAD | AFFINITY | 10s H/s | 60s H/s | 15m H/s |", isColors ? "\x1B[1;37m" : ""); size_t i = 0; for (const xmrig::IThread *thread : m_controller->config()->threads()) { - xmrig::Log::i()->text("| %6zu | %8" PRId64 " | %7s | %7s | %7s |", + xmrig::Log::print("| %6zu | %8" PRId64 " | %7s | %7s | %7s |", thread->index(), thread->affinity(), Hashrate::format(m_hashrate->calc(thread->index(), Hashrate::ShortInterval), num1, sizeof num1), From 17e9e036f135dc415d979c4b672d7afa79b0aa35 Mon Sep 17 00:00:00 2001 From: XMRig Date: Tue, 26 Mar 2019 22:05:56 +0700 Subject: [PATCH 027/116] Fix Linux build. --- src/base/base.cmake | 2 +- src/base/io/log/Log.cpp | 1 + src/base/io/log/backends/FileLog.cpp | 1 + src/base/io/log/backends/SysLog.cpp | 2 +- 4 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/base/base.cmake b/src/base/base.cmake index 66bf74a8..7ab88d98 100644 --- a/src/base/base.cmake +++ b/src/base/base.cmake @@ -74,6 +74,6 @@ if (NOT WIN32) CHECK_INCLUDE_FILE (syslog.h HAVE_SYSLOG_H) if (HAVE_SYSLOG_H) add_definitions(/DHAVE_SYSLOG_H) - set(SOURCES_SYSLOG src/base/log/backends/SysLog.h src/base/log/backends/SysLog.cpp) + set(SOURCES_SYSLOG src/base/io/log/backends/SysLog.h src/base/io/log/backends/SysLog.cpp) endif() endif() diff --git a/src/base/io/log/Log.cpp b/src/base/io/log/Log.cpp index eec17760..4a2a8de6 100644 --- a/src/base/io/log/Log.cpp +++ b/src/base/io/log/Log.cpp @@ -30,6 +30,7 @@ #endif +#include #include #include #include diff --git a/src/base/io/log/backends/FileLog.cpp b/src/base/io/log/backends/FileLog.cpp index 82c8407e..1ff01637 100644 --- a/src/base/io/log/backends/FileLog.cpp +++ b/src/base/io/log/backends/FileLog.cpp @@ -24,6 +24,7 @@ */ +#include #include diff --git a/src/base/io/log/backends/SysLog.cpp b/src/base/io/log/backends/SysLog.cpp index b75973f1..e66f2e35 100644 --- a/src/base/io/log/backends/SysLog.cpp +++ b/src/base/io/log/backends/SysLog.cpp @@ -49,5 +49,5 @@ void xmrig::SysLog::print(int level, const char *line, size_t offset, size_t, bo return; } - syslog(level == -1 ? LOG_INFO : level, line + offset); + syslog(level == -1 ? LOG_INFO : level, "%s", line + offset); } From f43929db98bdd24d3f79d04b94f5ba5fd926e4ad Mon Sep 17 00:00:00 2001 From: XMRig Date: Wed, 27 Mar 2019 01:29:37 +0700 Subject: [PATCH 028/116] New log support. --- CMakeLists.txt | 1 - src/App_unix.cpp | 2 +- src/Mem_unix.cpp | 2 +- src/Mem_win.cpp | 14 ++-- src/Summary.cpp | 103 ++++++++++++---------------- src/base/net/stratum/Client.cpp | 2 +- src/base/net/stratum/Pool.cpp | 2 +- src/base/net/stratum/Pools.cpp | 27 ++------ src/base/net/stratum/Tls.cpp | 2 +- src/common/Platform_win.cpp | 2 +- src/common/api/Httpd.cpp | 2 +- src/common/config/CommonConfig.cpp | 20 ++---- src/common/config/CommonConfig.h | 1 - src/common/config/ConfigWatcher.cpp | 2 +- src/common/log/Log.h | 32 --------- src/config.json | 1 + src/core/Config.cpp | 13 ++-- src/core/ConfigLoader_default.h | 4 +- src/core/Controller.cpp | 2 +- src/net/Network.cpp | 25 ++----- src/net/Network.h | 1 - src/workers/CpuThread.cpp | 2 +- src/workers/Hashrate.cpp | 5 +- src/workers/MultiWorker.cpp | 1 - src/workers/Workers.cpp | 24 +++---- src/workers/Workers.h | 2 - 26 files changed, 96 insertions(+), 198 deletions(-) delete mode 100644 src/common/log/Log.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 5c12f986..698b4953 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -33,7 +33,6 @@ set(HEADERS src/common/interfaces/IConfigCreator.h src/common/interfaces/IControllerListener.h src/common/interfaces/ICpuInfo.h - src/common/log/Log.h src/common/Platform.h src/common/utils/mm_malloc.h src/common/xmrig.h diff --git a/src/App_unix.cpp b/src/App_unix.cpp index 2b598c22..b1efce83 100644 --- a/src/App_unix.cpp +++ b/src/App_unix.cpp @@ -30,7 +30,7 @@ #include "App.h" -#include "common/log/Log.h" +#include "base/io/log/Log.h" #include "core/Config.h" #include "core/Controller.h" diff --git a/src/Mem_unix.cpp b/src/Mem_unix.cpp index 833c200c..f18656e8 100644 --- a/src/Mem_unix.cpp +++ b/src/Mem_unix.cpp @@ -28,7 +28,7 @@ #include -#include "common/log/Log.h" +#include "base/io/log/Log.h" #include "common/utils/mm_malloc.h" #include "common/xmrig.h" #include "crypto/CryptoNight.h" diff --git a/src/Mem_win.cpp b/src/Mem_win.cpp index 27c1348b..e7afb5d3 100644 --- a/src/Mem_win.cpp +++ b/src/Mem_win.cpp @@ -30,7 +30,7 @@ #include -#include "common/log/Log.h" +#include "base/io/log/Log.h" #include "common/utils/mm_malloc.h" #include "common/xmrig.h" #include "crypto/CryptoNight.h" @@ -67,11 +67,11 @@ static BOOL SetLockPagesPrivilege() { tp.PrivilegeCount = 1; tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; - if (LookupPrivilegeValue(NULL, SE_LOCK_MEMORY_NAME, &(tp.Privileges[0].Luid)) != TRUE) { + if (LookupPrivilegeValue(nullptr, SE_LOCK_MEMORY_NAME, &(tp.Privileges[0].Luid)) != TRUE) { return FALSE; } - BOOL rc = AdjustTokenPrivileges(token, FALSE, (PTOKEN_PRIVILEGES) &tp, 0, NULL, NULL); + BOOL rc = AdjustTokenPrivileges(token, FALSE, (PTOKEN_PRIVILEGES) &tp, 0, nullptr, nullptr); if (rc != TRUE || GetLastError() != ERROR_SUCCESS) { return FALSE; } @@ -95,12 +95,12 @@ static LSA_UNICODE_STRING StringToLsaUnicodeString(LPCTSTR string) { static BOOL ObtainLockPagesPrivilege() { HANDLE token; - PTOKEN_USER user = NULL; + PTOKEN_USER user = nullptr; if (OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &token) == TRUE) { DWORD size = 0; - GetTokenInformation(token, TokenUser, NULL, 0, &size); + GetTokenInformation(token, TokenUser, nullptr, 0, &size); if (size) { user = (PTOKEN_USER) LocalAlloc(LPTR, size); } @@ -118,7 +118,7 @@ static BOOL ObtainLockPagesPrivilege() { ZeroMemory(&attributes, sizeof(attributes)); BOOL result = FALSE; - if (LsaOpenPolicy(NULL, &attributes, POLICY_ALL_ACCESS, &handle) == 0) { + if (LsaOpenPolicy(nullptr, &attributes, POLICY_ALL_ACCESS, &handle) == 0) { LSA_UNICODE_STRING str = StringToLsaUnicodeString(_T(SE_LOCK_MEMORY_NAME)); if (LsaAddAccountRights(handle, user->User.Sid, &str, 1) == 0) { @@ -187,7 +187,7 @@ void Mem::release(MemInfo &info) void *Mem::allocateExecutableMemory(size_t size) { - return VirtualAlloc(0, size, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE); + return VirtualAlloc(nullptr, size, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE); } diff --git a/src/Summary.cpp b/src/Summary.cpp index b5c63b59..cc4b67e2 100644 --- a/src/Summary.cpp +++ b/src/Summary.cpp @@ -28,9 +28,9 @@ #include +#include "base/io/log/Log.h" #include "base/net/stratum/Pool.h" #include "common/cpu/Cpu.h" -#include "common/log/Log.h" #include "core/Config.h" #include "core/Controller.h" #include "crypto/Asm.h" @@ -41,62 +41,44 @@ #ifndef XMRIG_NO_ASM static const char *coloredAsmNames[] = { - "\x1B[1;31mnone\x1B[0m", + RED_BOLD("none"), "auto", - "\x1B[1;32mintel\x1B[0m", - "\x1B[1;32mryzen\x1B[0m", - "\x1B[1;32mbulldozer\x1B[0m" + GREEN_BOLD("intel"), + GREEN_BOLD("ryzen"), + GREEN_BOLD("bulldozer") }; -inline static const char *asmName(xmrig::Assembly assembly, bool colors) +inline static const char *asmName(xmrig::Assembly assembly) { - return colors ? coloredAsmNames[assembly] : xmrig::Asm::toString(assembly); + return coloredAsmNames[assembly]; } #endif -static void print_memory(xmrig::Config *config) { +static void print_memory(xmrig::Config *) { # ifdef _WIN32 - if (config->isColors()) { - xmrig::Log::print(GREEN_BOLD(" * ") WHITE_BOLD("%-13s") "%s", - "HUGE PAGES", Mem::isHugepagesAvailable() ? "\x1B[1;32mavailable" : "\x1B[01;31munavailable"); - } - else { - xmrig::Log::print(" * %-13s%s", "HUGE PAGES", Mem::isHugepagesAvailable() ? "available" : "unavailable"); - } + xmrig::Log::print(GREEN_BOLD(" * ") WHITE_BOLD("%-13s") "%s", + "HUGE PAGES", Mem::isHugepagesAvailable() ? GREEN_BOLD("available") : RED_BOLD("unavailable")); # endif } -static void print_cpu(xmrig::Config *config) +static void print_cpu(xmrig::Config *) { using namespace xmrig; - if (config->isColors()) { - Log::print(GREEN_BOLD(" * ") WHITE_BOLD("%-13s%s (%d)") " %sx64 %sAES %sAVX2", - "CPU", - Cpu::info()->brand(), - Cpu::info()->sockets(), - Cpu::info()->isX64() ? "\x1B[1;32m" : "\x1B[1;31m-", - Cpu::info()->hasAES() ? "\x1B[1;32m" : "\x1B[1;31m-", - Cpu::info()->hasAVX2() ? "\x1B[1;32m" : "\x1B[1;31m-"); -# ifndef XMRIG_NO_LIBCPUID - Log::print(GREEN_BOLD(" * ") WHITE_BOLD("%-13s%.1f MB/%.1f MB"), "CPU L2/L3", Cpu::info()->L2() / 1024.0, Cpu::info()->L3() / 1024.0); -# endif - } - else { - Log::print(" * %-13s%s (%d) %sx64 %sAES %sAVX2", - "CPU", - Cpu::info()->brand(), - Cpu::info()->sockets(), - Cpu::info()->isX64() ? "" : "-", - Cpu::info()->hasAES() ? "" : "-", - Cpu::info()->hasAVX2() ? "" : "-"); -# ifndef XMRIG_NO_LIBCPUID - Log::print(" * %-13s%.1f MB/%.1f MB", "CPU L2/L3", Cpu::info()->L2() / 1024.0, Cpu::info()->L3() / 1024.0); -# endif - } + Log::print(GREEN_BOLD(" * ") WHITE_BOLD("%-13s%s (%d)") " %sx64 %sAES %sAVX2", + "CPU", + Cpu::info()->brand(), + Cpu::info()->sockets(), + Cpu::info()->isX64() ? GREEN_BOLD_S : RED_BOLD("-"), + Cpu::info()->hasAES() ? GREEN_BOLD_S : RED_BOLD("-"), + Cpu::info()->hasAVX2() ? GREEN_BOLD_S : RED_BOLD("-") + ); +# ifndef XMRIG_NO_LIBCPUID + Log::print(GREEN_BOLD(" * ") WHITE_BOLD("%-13s%.1f MB/%.1f MB"), "CPU L2/L3", Cpu::info()->L2() / 1024.0, Cpu::info()->L3() / 1024.0); +# endif } @@ -108,43 +90,42 @@ static void print_threads(xmrig::Config *config) snprintf(buf, sizeof buf, ", affinity=0x%" PRIX64, config->affinity()); } - xmrig::Log::print(config->isColors() ? GREEN_BOLD(" * ") WHITE_BOLD("%-13s") CYAN_BOLD("%d") WHITE_BOLD(", %s, av=%d, %sdonate=%d%%") WHITE_BOLD("%s") - : " * %-13s%d, %s, av=%d, %sdonate=%d%%%s", - "THREADS", - config->threadsCount(), - config->algorithm().name(), - config->algoVariant(), - config->isColors() && config->pools().donateLevel() == 0 ? "\x1B[1;31m" : "", - config->pools().donateLevel(), - buf); + xmrig::Log::print(GREEN_BOLD(" * ") WHITE_BOLD("%-13s") CYAN_BOLD("%d") WHITE_BOLD(", %s, av=%d, %sdonate=%d%%") WHITE_BOLD("%s"), + "THREADS", + config->threadsCount(), + config->algorithm().shortName(), + config->algoVariant(), + config->pools().donateLevel() == 0 ? RED_BOLD_S : "", + config->pools().donateLevel(), + buf + ); } else { - xmrig::Log::print(config->isColors() ? GREEN_BOLD(" * ") WHITE_BOLD("%-13s") CYAN_BOLD("%d") WHITE_BOLD(", %s, %sdonate=%d%%") - : " * %-13s%d, %s, %sdonate=%d%%", - "THREADS", - config->threadsCount(), - config->algorithm().name(), - config->isColors() && config->pools().donateLevel() == 0 ? "\x1B[1;31m" : "", - config->pools().donateLevel()); + xmrig::Log::print(GREEN_BOLD(" * ") WHITE_BOLD("%-13s") CYAN_BOLD("%d") WHITE_BOLD(", %s, %sdonate=%d%%"), + "THREADS", + config->threadsCount(), + config->algorithm().shortName(), + config->pools().donateLevel() == 0 ? RED_BOLD_S : "", + config->pools().donateLevel() + ); } # ifndef XMRIG_NO_ASM if (config->assembly() == xmrig::ASM_AUTO) { const xmrig::Assembly assembly = xmrig::Cpu::info()->assembly(); - xmrig::Log::print(config->isColors() ? GREEN_BOLD(" * ") WHITE_BOLD("%-13sauto:%s") - : " * %-13sauto:%s", "ASSEMBLY", asmName(assembly, config->isColors())); + xmrig::Log::print(GREEN_BOLD(" * ") WHITE_BOLD("%-13sauto:%s"), asmName(assembly)); } else { - xmrig::Log::print(config->isColors() ? GREEN_BOLD(" * ") WHITE_BOLD("%-13s%s") : " * %-13s%s", "ASSEMBLY", asmName(config->assembly(), config->isColors())); + xmrig::Log::print(GREEN_BOLD(" * ") WHITE_BOLD("%-13s%s"), asmName(config->assembly())); } # endif } -static void print_commands(xmrig::Config *config) +static void print_commands(xmrig::Config *) { - if (config->isColors()) { + if (xmrig::Log::colors) { xmrig::Log::print(GREEN_BOLD(" * ") WHITE_BOLD("COMMANDS ") MAGENTA_BOLD("h") WHITE_BOLD("ashrate, ") MAGENTA_BOLD("p") WHITE_BOLD("ause, ") MAGENTA_BOLD("r") WHITE_BOLD("esume")); diff --git a/src/base/net/stratum/Client.cpp b/src/base/net/stratum/Client.cpp index db6f2663..88d96871 100644 --- a/src/base/net/stratum/Client.cpp +++ b/src/base/net/stratum/Client.cpp @@ -37,12 +37,12 @@ #endif +#include "base/io/log/Log.h" #include "base/kernel/interfaces/IClientListener.h" #include "base/net/dns/Dns.h" #include "base/net/stratum/Client.h" #include "base/tools/Buffer.h" #include "base/tools/Chrono.h" -#include "common/log/Log.h" #include "net/JobResult.h" #include "rapidjson/document.h" #include "rapidjson/error/en.h" diff --git a/src/base/net/stratum/Pool.cpp b/src/base/net/stratum/Pool.cpp index c5f16f4f..64543a95 100644 --- a/src/base/net/stratum/Pool.cpp +++ b/src/base/net/stratum/Pool.cpp @@ -35,7 +35,7 @@ #ifdef APP_DEBUG -# include "common/log/Log.h" +# include "base/io/log/Log.h" #endif diff --git a/src/base/net/stratum/Pools.cpp b/src/base/net/stratum/Pools.cpp index f2d34287..63102c00 100644 --- a/src/base/net/stratum/Pools.cpp +++ b/src/base/net/stratum/Pools.cpp @@ -23,10 +23,10 @@ */ +#include "base/io/log/Log.h" #include "base/net/stratum/Pools.h" #include "base/net/stratum/strategies/FailoverStrategy.h" #include "base/net/stratum/strategies/SinglePoolStrategy.h" -#include "common/log/Log.h" #include "donate.h" #include "rapidjson/document.h" @@ -161,25 +161,12 @@ void xmrig::Pools::print() const { size_t i = 1; for (const Pool &pool : m_data) { - if (Log::colors) { - const int color = pool.isEnabled() ? (pool.isTLS() ? 32 : 36) : 31; - - Log::print(GREEN_BOLD(" * ") WHITE_BOLD("POOL #%-7zu") "\x1B[1;%dm%s\x1B[0m variant " WHITE_BOLD("%s"), - i, - color, - pool.url().data(), - pool.algorithm().variantName() - ); - } - else { - Log::print(" * POOL #%-7zu%s%s variant=%s %s", - i, - pool.isEnabled() ? "" : "-", - pool.url().data(), - pool.algorithm().variantName(), - pool.isTLS() ? "TLS" : "" - ); - } + Log::print(GREEN_BOLD(" * ") WHITE_BOLD("POOL #%-7zu") CSI "1;%dm%s" CLEAR " variant " WHITE_BOLD("%s"), + i, + (pool.isEnabled() ? (pool.isTLS() ? 32 : 36) : 31), + pool.url().data(), + pool.algorithm().variantName() + ); i++; } diff --git a/src/base/net/stratum/Tls.cpp b/src/base/net/stratum/Tls.cpp index d92d7e54..8916579b 100644 --- a/src/base/net/stratum/Tls.cpp +++ b/src/base/net/stratum/Tls.cpp @@ -27,10 +27,10 @@ #include +#include "base/io/log/Log.h" #include "base/net/stratum/Client.h" #include "base/net/stratum/Tls.h" #include "base/tools/Buffer.h" -#include "common/log/Log.h" #ifdef _MSC_VER diff --git a/src/common/Platform_win.cpp b/src/common/Platform_win.cpp index 9e9b772d..f2363cd0 100644 --- a/src/common/Platform_win.cpp +++ b/src/common/Platform_win.cpp @@ -29,7 +29,7 @@ #include -#include "log/Log.h" +#include "base/io/log/Log.h" #include "Platform.h" #include "version.h" diff --git a/src/common/api/Httpd.cpp b/src/common/api/Httpd.cpp index 7b5e8578..b80e920e 100644 --- a/src/common/api/Httpd.cpp +++ b/src/common/api/Httpd.cpp @@ -28,12 +28,12 @@ #include "api/Api.h" +#include "base/io/log/Log.h" #include "base/tools/Handle.h" #include "base/tools/Timer.h" #include "common/api/Httpd.h" #include "common/api/HttpReply.h" #include "common/api/HttpRequest.h" -#include "common/log/Log.h" xmrig::Httpd::Httpd(int port, const char *accessToken, bool IPv6, bool restricted) : diff --git a/src/common/config/CommonConfig.cpp b/src/common/config/CommonConfig.cpp index 1be36426..cde55304 100644 --- a/src/common/config/CommonConfig.cpp +++ b/src/common/config/CommonConfig.cpp @@ -55,8 +55,8 @@ #include "base/io/Json.h" +#include "base/io/log/Log.h" #include "common/config/CommonConfig.h" -#include "common/log/Log.h" #include "rapidjson/document.h" #include "rapidjson/filewritestream.h" #include "rapidjson/prettywriter.h" @@ -80,12 +80,6 @@ xmrig::CommonConfig::CommonConfig() : } -bool xmrig::CommonConfig::isColors() const -{ - return Log::colors; -} - - void xmrig::CommonConfig::printAPI() { # ifndef XMRIG_NO_API @@ -93,9 +87,7 @@ void xmrig::CommonConfig::printAPI() return; } - Log::print(isColors() ? GREEN_BOLD(" * ") WHITE_BOLD("%-13s") CYAN("%s:") CYAN_BOLD("%d") - : " * %-13s%s:%d", - "API BIND", isApiIPv6() ? "[::]" : "0.0.0.0", apiPort()); + Log::print(GREEN_BOLD(" * ") WHITE_BOLD("%-13s") CYAN("%s:") CYAN_BOLD("%d"), "API BIND", isApiIPv6() ? "[::]" : "0.0.0.0", apiPort()); # endif } @@ -118,9 +110,7 @@ void xmrig::CommonConfig::printVersions() snprintf(buf, sizeof buf, "MSVC/%d", MSVC_VERSION); # endif - Log::print(isColors() ? GREEN_BOLD(" * ") WHITE_BOLD("%-13s") CYAN_BOLD("%s/%s") WHITE_BOLD(" %s") - : " * %-13s%s/%s %s", - "ABOUT", APP_NAME, APP_VERSION, buf); + Log::print(GREEN_BOLD(" * ") WHITE_BOLD("%-13s") CYAN_BOLD("%s/%s") WHITE_BOLD(" %s"), "ABOUT", APP_NAME, APP_VERSION, buf); # if defined(XMRIG_AMD_PROJECT) # if CL_VERSION_2_0 @@ -157,9 +147,7 @@ void xmrig::CommonConfig::printVersions() length += snprintf(buf + length, (sizeof buf) - length, "microhttpd/%s ", MHD_get_version()); # endif - Log::print(isColors() ? GREEN_BOLD(" * ") WHITE_BOLD("%-13slibuv/%s %s") - : " * %-13slibuv/%s %s", - "LIBS", uv_version_string(), buf); + Log::print(GREEN_BOLD(" * ") WHITE_BOLD("%-13slibuv/%s %s"), "LIBS", uv_version_string(), buf); } diff --git a/src/common/config/CommonConfig.h b/src/common/config/CommonConfig.h index e11069da..b2ec56ea 100644 --- a/src/common/config/CommonConfig.h +++ b/src/common/config/CommonConfig.h @@ -61,7 +61,6 @@ public: bool save() override; - bool isColors() const; void printAPI(); void printPools(); void printVersions(); diff --git a/src/common/config/ConfigWatcher.cpp b/src/common/config/ConfigWatcher.cpp index 1e35bc9b..c3168ac9 100644 --- a/src/common/config/ConfigWatcher.cpp +++ b/src/common/config/ConfigWatcher.cpp @@ -23,11 +23,11 @@ */ +#include "base/io/log/Log.h" #include "base/io/Watcher.h" #include "base/kernel/interfaces/IConfigListener.h" #include "common/config/ConfigLoader.h" #include "common/config/ConfigWatcher.h" -#include "common/log/Log.h" #include "core/ConfigCreator.h" diff --git a/src/common/log/Log.h b/src/common/log/Log.h deleted file mode 100644 index f393b1da..00000000 --- a/src/common/log/Log.h +++ /dev/null @@ -1,32 +0,0 @@ -/* XMRig - * Copyright 2010 Jeff Garzik - * Copyright 2012-2014 pooler - * Copyright 2014 Lucas Jones - * Copyright 2014-2016 Wolf9466 - * Copyright 2016 Jay D Dee - * Copyright 2017-2018 XMR-Stak , - * Copyright 2018-2019 SChernykh - * Copyright 2016-2019 XMRig , - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#ifndef XMRIG_LOG_LEGACY_H -#define XMRIG_LOG_LEGACY_H - - -#include "base/io/log/Log.h" - - -#endif /* XMRIG_LOG_LEGACY_H */ diff --git a/src/config.json b/src/config.json index 08b912a0..e95c2400 100644 --- a/src/config.json +++ b/src/config.json @@ -40,5 +40,6 @@ "safe": false, "threads": null, "user-agent": null, + "syslog": false, "watch": true } \ No newline at end of file diff --git a/src/core/Config.cpp b/src/core/Config.cpp index d566af26..2593ef64 100644 --- a/src/core/Config.cpp +++ b/src/core/Config.cpp @@ -27,6 +27,7 @@ #include +#include "base/io/log/Log.h" #include "common/config/ConfigLoader.h" #include "common/cpu/Cpu.h" #include "core/Config.h" @@ -87,7 +88,7 @@ void xmrig::Config::getJSON(rapidjson::Document &doc) const doc.AddMember("autosave", isAutoSave(), allocator); doc.AddMember("av", algoVariant(), allocator); doc.AddMember("background", isBackground(), allocator); - doc.AddMember("colors", isColors(), allocator); + doc.AddMember("colors", Log::colors, allocator); if (affinity() != -1L) { snprintf(affinity_tmp, sizeof(affinity_tmp) - 1, "0x%" PRIX64, affinity()); @@ -123,13 +124,9 @@ void xmrig::Config::getJSON(rapidjson::Document &doc) const doc.AddMember("threads", threadsCount(), allocator); } - doc.AddMember("user-agent", userAgent() ? Value(StringRef(userAgent())).Move() : Value(kNullType).Move(), allocator); - -# ifdef HAVE_SYSLOG_H - doc.AddMember("syslog", isSyslog(), allocator); -# endif - - doc.AddMember("watch", m_watch, allocator); + doc.AddMember("user-agent", m_userAgent.toJSON(), allocator); + doc.AddMember("syslog", isSyslog(), allocator); + doc.AddMember("watch", m_watch, allocator); } diff --git a/src/core/ConfigLoader_default.h b/src/core/ConfigLoader_default.h index 8fd0502b..f2aababd 100644 --- a/src/core/ConfigLoader_default.h +++ b/src/core/ConfigLoader_default.h @@ -50,6 +50,7 @@ R"===( "cpu-affinity": null, "cpu-priority": null, "donate-level": 5, + "donate-over-proxy": 1, "huge-pages": true, "hw-aes": null, "log-file": null, @@ -73,7 +74,8 @@ R"===( "safe": false, "threads": null, "user-agent": null, - "watch": false + "syslog": false, + "watch": true } )==="; #endif diff --git a/src/core/Controller.cpp b/src/core/Controller.cpp index 6088034b..83c96570 100644 --- a/src/core/Controller.cpp +++ b/src/core/Controller.cpp @@ -28,10 +28,10 @@ #include "base/io/log/backends/ConsoleLog.h" #include "base/io/log/backends/FileLog.h" +#include "base/io/log/Log.h" #include "common/config/ConfigLoader.h" #include "common/cpu/Cpu.h" #include "common/interfaces/IControllerListener.h" -#include "common/log/Log.h" #include "common/Platform.h" #include "core/Config.h" #include "core/Controller.h" diff --git a/src/net/Network.cpp b/src/net/Network.cpp index f50e3f0a..fbb6d8a1 100644 --- a/src/net/Network.cpp +++ b/src/net/Network.cpp @@ -32,11 +32,11 @@ #include "api/Api.h" +#include "base/io/log/Log.h" #include "base/net/stratum/Client.h" #include "base/net/stratum/SubmitResult.h" #include "base/tools/Chrono.h" #include "base/tools/Timer.h" -#include "common/log/Log.h" #include "core/Config.h" #include "core/Controller.h" #include "net/Network.h" @@ -90,13 +90,12 @@ void xmrig::Network::onActive(IStrategy *strategy, Client *client) m_state.setPool(client->host(), client->port(), client->ip()); const char *tlsVersion = client->tlsVersion(); - LOG_INFO(isColors() ? WHITE_BOLD("use pool ") CYAN_BOLD("%s:%d ") GREEN_BOLD("%s") " \x1B[1;30m%s " - : "use pool %s:%d %s %s", + LOG_INFO(WHITE_BOLD("use pool ") CYAN_BOLD("%s:%d ") GREEN_BOLD("%s") " " BLACK_BOLD("%s"), client->host(), client->port(), tlsVersion ? tlsVersion : "", client->ip()); const char *fingerprint = client->tlsFingerprint(); if (fingerprint != nullptr) { - LOG_INFO("%sfingerprint (SHA-256): \"%s\"", isColors() ? "\x1B[1;30m" : "", fingerprint); + LOG_INFO(BLACK_BOLD("fingerprint (SHA-256): \"%s\""), fingerprint); } } @@ -158,34 +157,24 @@ void xmrig::Network::onResultAccepted(IStrategy *, Client *, const SubmitResult m_state.add(result, error); if (error) { - LOG_INFO(isColors() ? "\x1B[1;31mrejected\x1B[0m (%" PRId64 "/%" PRId64 ") diff \x1B[1;37m%u\x1B[0m \x1B[31m\"%s\"\x1B[0m \x1B[1;30m(%" PRIu64 " ms)" - : "rejected (%" PRId64 "/%" PRId64 ") diff %u \"%s\" (%" PRIu64 " ms)", + LOG_INFO(RED_BOLD("rejected") " (%" PRId64 "/%" PRId64 ") diff " WHITE_BOLD("%u") " " RED("\"%s\"") " " BLACK_BOLD("(%" PRIu64 " ms)"), m_state.accepted, m_state.rejected, result.diff, error, result.elapsed); } else { - LOG_INFO(isColors() ? "\x1B[1;32maccepted\x1B[0m (%" PRId64 "/%" PRId64 ") diff \x1B[1;37m%u\x1B[0m \x1B[1;30m(%" PRIu64 " ms)" - : "accepted (%" PRId64 "/%" PRId64 ") diff %u (%" PRIu64 " ms)", + LOG_INFO(GREEN_BOLD("accepted") " (%" PRId64 "/%" PRId64 ") diff " WHITE_BOLD("%u") " " BLACK_BOLD("(%" PRIu64 " ms)"), m_state.accepted, m_state.rejected, result.diff, result.elapsed); } } -bool xmrig::Network::isColors() const -{ - return Log::colors; -} - - void xmrig::Network::setJob(Client *client, const Job &job, bool donate) { if (job.height()) { - LOG_INFO(isColors() ? MAGENTA_BOLD("new job") " from " WHITE_BOLD("%s:%d") " diff " WHITE_BOLD("%d") " algo " WHITE_BOLD("%s") " height " WHITE_BOLD("%" PRIu64) - : "new job from %s:%d diff %d algo %s height %" PRIu64, + LOG_INFO(MAGENTA_BOLD("new job") " from " WHITE_BOLD("%s:%d") " diff " WHITE_BOLD("%d") " algo " WHITE_BOLD("%s") " height " WHITE_BOLD("%" PRIu64), client->host(), client->port(), job.diff(), job.algorithm().shortName(), job.height()); } else { - LOG_INFO(isColors() ? MAGENTA_BOLD("new job") " from " WHITE_BOLD("%s:%d") " diff " WHITE_BOLD("%d") " algo " WHITE_BOLD("%s") - : "new job from %s:%d diff %d algo %s", + LOG_INFO(MAGENTA_BOLD("new job") " from " WHITE_BOLD("%s:%d") " diff " WHITE_BOLD("%d") " algo " WHITE_BOLD("%s"), client->host(), client->port(), job.diff(), job.algorithm().shortName()); } diff --git a/src/net/Network.h b/src/net/Network.h index ac74384e..1a558341 100644 --- a/src/net/Network.h +++ b/src/net/Network.h @@ -66,7 +66,6 @@ protected: private: constexpr static int kTickInterval = 1 * 1000; - bool isColors() const; void setJob(Client *client, const Job &job, bool donate); void tick(); diff --git a/src/workers/CpuThread.cpp b/src/workers/CpuThread.cpp index 6548b461..529027f5 100644 --- a/src/workers/CpuThread.cpp +++ b/src/workers/CpuThread.cpp @@ -25,8 +25,8 @@ #include +#include "base/io/log/Log.h" #include "common/cpu/Cpu.h" -#include "common/log/Log.h" #include "crypto/Asm.h" #include "Mem.h" #include "rapidjson/document.h" diff --git a/src/workers/Hashrate.cpp b/src/workers/Hashrate.cpp index 591b719a..dcf58b84 100644 --- a/src/workers/Hashrate.cpp +++ b/src/workers/Hashrate.cpp @@ -30,8 +30,8 @@ #include +#include "base/io/log/Log.h" #include "base/tools/Handle.h" -#include "common/log/Log.h" #include "core/Config.h" #include "core/Controller.h" #include "workers/Hashrate.h" @@ -163,8 +163,7 @@ void Hashrate::print() const char num3[8] = { 0 }; char num4[8] = { 0 }; - LOG_INFO(m_controller->config()->isColors() ? WHITE_BOLD("speed") " 10s/60s/15m " CYAN_BOLD("%s") CYAN(" %s %s ") CYAN_BOLD("H/s") " max " CYAN_BOLD("%s H/s") - : "speed 10s/60s/15m %s %s %s H/s max %s H/s", + LOG_INFO(WHITE_BOLD("speed") " 10s/60s/15m " CYAN_BOLD("%s") CYAN(" %s %s ") CYAN_BOLD("H/s") " max " CYAN_BOLD("%s H/s"), format(calc(ShortInterval), num1, sizeof(num1)), format(calc(MediumInterval), num2, sizeof(num2)), format(calc(LargeInterval), num3, sizeof(num3)), diff --git a/src/workers/MultiWorker.cpp b/src/workers/MultiWorker.cpp index b3c4882b..8b9e0881 100644 --- a/src/workers/MultiWorker.cpp +++ b/src/workers/MultiWorker.cpp @@ -28,7 +28,6 @@ #include "crypto/CryptoNight_test.h" -#include "common/log/Log.h" #include "workers/CpuThread.h" #include "workers/MultiWorker.h" #include "workers/Workers.h" diff --git a/src/workers/Workers.cpp b/src/workers/Workers.cpp index 4adf349f..08c16828 100644 --- a/src/workers/Workers.cpp +++ b/src/workers/Workers.cpp @@ -28,8 +28,8 @@ #include "api/Api.h" +#include "base/io/log/Log.h" #include "base/tools/Handle.h" -#include "common/log/Log.h" #include "core/Config.h" #include "core/Controller.h" #include "crypto/CryptoNight_constants.h" @@ -99,12 +99,11 @@ void Workers::printHashrate(bool detail) } if (detail) { - const bool isColors = m_controller->config()->isColors(); char num1[8] = { 0 }; char num2[8] = { 0 }; char num3[8] = { 0 }; - xmrig::Log::print("%s| THREAD | AFFINITY | 10s H/s | 60s H/s | 15m H/s |", isColors ? "\x1B[1;37m" : ""); + xmrig::Log::print(WHITE_BOLD_S "| THREAD | AFFINITY | 10s H/s | 60s H/s | 15m H/s |"); size_t i = 0; for (const xmrig::IThread *thread : m_controller->config()->threads()) { @@ -178,7 +177,6 @@ void Workers::start(xmrig::Controller *controller) const std::vector &threads = controller->config()->threads(); m_status.algo = controller->config()->algorithm().algo(); - m_status.colors = controller->config()->isColors(); m_status.threads = threads.size(); for (const xmrig::IThread *thread : threads) { @@ -302,7 +300,7 @@ void Workers::onReady(void *arg) } -void Workers::onResult(uv_async_t *handle) +void Workers::onResult(uv_async_t *) { std::list results; @@ -321,7 +319,7 @@ void Workers::onResult(uv_async_t *handle) } -void Workers::onTick(uv_timer_t *handle) +void Workers::onTick(uv_timer_t *) { for (ThreadHandle *handle : m_workers) { if (!handle->worker()) { @@ -350,16 +348,10 @@ void Workers::start(IWorker *worker) const double percent = (double) m_status.hugePages / m_status.pages * 100.0; const size_t memory = m_status.ways * xmrig::cn_select_memory(m_status.algo) / 1024; - if (m_status.colors) { - LOG_INFO(GREEN_BOLD("READY (CPU)") " threads " CYAN_BOLD("%zu(%zu)") " huge pages %s%zu/%zu %1.0f%%\x1B[0m memory " CYAN_BOLD("%zu KB") "", - m_status.threads, m_status.ways, - (m_status.hugePages == m_status.pages ? "\x1B[1;32m" : (m_status.hugePages == 0 ? "\x1B[1;31m" : "\x1B[1;33m")), - m_status.hugePages, m_status.pages, percent, memory); - } - else { - LOG_INFO("READY (CPU) threads %zu(%zu) huge pages %zu/%zu %1.0f%% memory %zu KB", - m_status.threads, m_status.ways, m_status.hugePages, m_status.pages, percent, memory); - } + LOG_INFO(GREEN_BOLD("READY (CPU)") " threads " CYAN_BOLD("%zu(%zu)") " huge pages %s%zu/%zu %1.0f%%\x1B[0m memory " CYAN_BOLD("%zu KB") "", + m_status.threads, m_status.ways, + (m_status.hugePages == m_status.pages ? GREEN_BOLD_S : (m_status.hugePages == 0 ? RED_BOLD_S : YELLOW_BOLD_S)), + m_status.hugePages, m_status.pages, percent, memory); } uv_mutex_unlock(&m_mutex); diff --git a/src/workers/Workers.h b/src/workers/Workers.h index 23b0a27c..4b6fc9cf 100644 --- a/src/workers/Workers.h +++ b/src/workers/Workers.h @@ -82,7 +82,6 @@ private: { public: inline LaunchStatus() : - colors(true), hugePages(0), pages(0), started(0), @@ -91,7 +90,6 @@ private: algo(xmrig::CRYPTONIGHT) {} - bool colors; size_t hugePages; size_t pages; size_t started; From ba910a46ba29f30236b363ac9df0a79556ef859f Mon Sep 17 00:00:00 2001 From: XMRig Date: Wed, 27 Mar 2019 15:56:31 +0700 Subject: [PATCH 029/116] Fix accidentally removed code. --- src/Summary.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Summary.cpp b/src/Summary.cpp index cc4b67e2..83a3eac6 100644 --- a/src/Summary.cpp +++ b/src/Summary.cpp @@ -114,10 +114,10 @@ static void print_threads(xmrig::Config *config) if (config->assembly() == xmrig::ASM_AUTO) { const xmrig::Assembly assembly = xmrig::Cpu::info()->assembly(); - xmrig::Log::print(GREEN_BOLD(" * ") WHITE_BOLD("%-13sauto:%s"), asmName(assembly)); + xmrig::Log::print(GREEN_BOLD(" * ") WHITE_BOLD("%-13sauto:%s"), "ASSEMBLY", asmName(assembly)); } else { - xmrig::Log::print(GREEN_BOLD(" * ") WHITE_BOLD("%-13s%s"), asmName(config->assembly())); + xmrig::Log::print(GREEN_BOLD(" * ") WHITE_BOLD("%-13s%s"), "ASSEMBLY", asmName(config->assembly())); } # endif } From d7795ca990a46ee9b506608150e2d5ac48571d26 Mon Sep 17 00:00:00 2001 From: XMRig Date: Wed, 27 Mar 2019 17:22:04 +0700 Subject: [PATCH 030/116] Remove uv_cancel for DNS requests. --- src/base/net/dns/Dns.cpp | 5 +++-- src/base/tools/Handle.h | 11 ----------- 2 files changed, 3 insertions(+), 13 deletions(-) diff --git a/src/base/net/dns/Dns.cpp b/src/base/net/dns/Dns.cpp index f2402124..f57278c4 100644 --- a/src/base/net/dns/Dns.cpp +++ b/src/base/net/dns/Dns.cpp @@ -37,7 +37,8 @@ namespace xmrig { xmrig::Dns::Dns(IDnsListener *listener) : m_hints(), m_listener(listener), - m_status(0) + m_status(0), + m_resolver(nullptr) { m_key = m_storage.add(this); @@ -54,7 +55,7 @@ xmrig::Dns::~Dns() { m_storage.release(m_key); - Handle::close(m_resolver); + delete m_resolver; } diff --git a/src/base/tools/Handle.h b/src/base/tools/Handle.h index 288c32de..1a7d08f1 100644 --- a/src/base/tools/Handle.h +++ b/src/base/tools/Handle.h @@ -76,17 +76,6 @@ inline void Handle::close(uv_signal_t *handle) } -template<> -inline void Handle::close(uv_getaddrinfo_t *handle) -{ - if (handle) { - uv_cancel(reinterpret_cast(handle)); - - delete handle; - } -} - - template<> inline void Handle::close(uv_fs_event_t *handle) { From cad3e7a101cf98a4417a4f36bd4272b016cb2297 Mon Sep 17 00:00:00 2001 From: XMRig Date: Wed, 27 Mar 2019 19:18:54 +0700 Subject: [PATCH 031/116] Sync changes. --- src/common/config/CommonConfig.cpp | 6 ------ 1 file changed, 6 deletions(-) diff --git a/src/common/config/CommonConfig.cpp b/src/common/config/CommonConfig.cpp index cde55304..0de10b1e 100644 --- a/src/common/config/CommonConfig.cpp +++ b/src/common/config/CommonConfig.cpp @@ -326,12 +326,6 @@ bool xmrig::CommonConfig::parseString(int key, const char *arg) return parseBoolean(key, false); case DonateLevelKey: /* --donate-level */ -# ifdef XMRIG_PROXY_PROJECT - if (strncmp(arg, "minemonero.pro", 14) == 0) { - m_donateLevel = 0; - return true; - } -# endif return parseUint64(key, strtol(arg, nullptr, 10)); default: From 82bbef614efef3551b34f55d340feac9bdd89877 Mon Sep 17 00:00:00 2001 From: XMRig Date: Wed, 27 Mar 2019 19:27:29 +0700 Subject: [PATCH 032/116] Remove unused field. --- src/workers/Hashrate.cpp | 3 +-- src/workers/Hashrate.h | 1 - 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/src/workers/Hashrate.cpp b/src/workers/Hashrate.cpp index dcf58b84..b2abdf29 100644 --- a/src/workers/Hashrate.cpp +++ b/src/workers/Hashrate.cpp @@ -51,8 +51,7 @@ inline static const char *format(double h, char *buf, size_t size) Hashrate::Hashrate(size_t threads, xmrig::Controller *controller) : m_highest(0.0), m_threads(threads), - m_timer(nullptr), - m_controller(controller) + m_timer(nullptr) { m_counts = new uint64_t*[threads]; m_timestamps = new uint64_t*[threads]; diff --git a/src/workers/Hashrate.h b/src/workers/Hashrate.h index 673c6a51..d27b289e 100644 --- a/src/workers/Hashrate.h +++ b/src/workers/Hashrate.h @@ -69,7 +69,6 @@ private: uint64_t** m_counts; uint64_t** m_timestamps; uv_timer_t *m_timer; - xmrig::Controller *m_controller; }; From 3f4886bb8606063492caeb89ecaedab216e72d71 Mon Sep 17 00:00:00 2001 From: XMRig Date: Wed, 27 Mar 2019 19:29:29 +0700 Subject: [PATCH 033/116] Fix CPU info colors. --- src/Summary.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Summary.cpp b/src/Summary.cpp index 83a3eac6..6c7b7bfa 100644 --- a/src/Summary.cpp +++ b/src/Summary.cpp @@ -72,9 +72,9 @@ static void print_cpu(xmrig::Config *) "CPU", Cpu::info()->brand(), Cpu::info()->sockets(), - Cpu::info()->isX64() ? GREEN_BOLD_S : RED_BOLD("-"), - Cpu::info()->hasAES() ? GREEN_BOLD_S : RED_BOLD("-"), - Cpu::info()->hasAVX2() ? GREEN_BOLD_S : RED_BOLD("-") + Cpu::info()->isX64() ? GREEN_BOLD_S : RED_BOLD_S "-", + Cpu::info()->hasAES() ? GREEN_BOLD_S : RED_BOLD_S "-", + Cpu::info()->hasAVX2() ? GREEN_BOLD_S : RED_BOLD_S "-" ); # ifndef XMRIG_NO_LIBCPUID Log::print(GREEN_BOLD(" * ") WHITE_BOLD("%-13s%.1f MB/%.1f MB"), "CPU L2/L3", Cpu::info()->L2() / 1024.0, Cpu::info()->L3() / 1024.0); From 5db458efd4af5fae78d3cdb96e15f4815219c508 Mon Sep 17 00:00:00 2001 From: XMRig Date: Wed, 27 Mar 2019 20:03:15 +0700 Subject: [PATCH 034/116] Fix macOS build. --- src/Mem_unix.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/Mem_unix.cpp b/src/Mem_unix.cpp index f18656e8..3506c2d1 100644 --- a/src/Mem_unix.cpp +++ b/src/Mem_unix.cpp @@ -35,6 +35,11 @@ #include "Mem.h" +#if defined(__APPLE__) +# include +#endif + + void Mem::init(bool enabled) { m_enabled = enabled; From 22483dd23173f4c42bd87805f4963cff8c9af61c Mon Sep 17 00:00:00 2001 From: xmrig Date: Wed, 27 Mar 2019 21:18:48 +0700 Subject: [PATCH 035/116] Update CHANGELOG.md --- CHANGELOG.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0487457d..a158b3b9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,6 @@ +# v2.15.1-beta +- [#257](https://github.com/xmrig/xmrig-nvidia/pull/257) New logging subsystem, file and syslog now always without colors. + # v2.15.0-beta - [#314](https://github.com/xmrig/xmrig-proxy/issues/314) Added donate over proxy feature. - Added new option `donate-over-proxy`. From 034720e888b6d772723916d6f0d040bd20f04c8a Mon Sep 17 00:00:00 2001 From: XMRig Date: Thu, 28 Mar 2019 22:13:27 +0700 Subject: [PATCH 036/116] Use XMRIG_FEATURE_TLS instead of XMRIG_NO_TLS --- cmake/OpenSSL.cmake | 2 -- src/base/kernel/Entry.cpp | 4 ++-- src/base/net/stratum/Client.cpp | 20 ++++++++++---------- src/base/net/stratum/Client.h | 2 +- src/base/net/stratum/Pool.cpp | 2 +- src/common/Platform.cpp | 4 ++-- src/common/config/CommonConfig.cpp | 6 +++--- src/common/config/ConfigLoader.cpp | 10 ---------- 8 files changed, 19 insertions(+), 31 deletions(-) diff --git a/cmake/OpenSSL.cmake b/cmake/OpenSSL.cmake index 219d50b9..bcdea0c6 100644 --- a/cmake/OpenSSL.cmake +++ b/cmake/OpenSSL.cmake @@ -18,12 +18,10 @@ if (WITH_TLS) endif() add_definitions(/DXMRIG_FEATURE_TLS) - remove_definitions(/DXMRIG_NO_TLS) else() set(TLS_SOURCES "") set(OPENSSL_LIBRARIES "") remove_definitions(/DXMRIG_FEATURE_TLS) - add_definitions(/DXMRIG_NO_TLS) set(CMAKE_PROJECT_NAME "${CMAKE_PROJECT_NAME}-notls") endif() diff --git a/src/base/kernel/Entry.cpp b/src/base/kernel/Entry.cpp index 84c4c971..5b335453 100644 --- a/src/base/kernel/Entry.cpp +++ b/src/base/kernel/Entry.cpp @@ -32,7 +32,7 @@ #endif -#ifndef XMRIG_NO_TLS +#ifdef XMRIG_FEATURE_TLS # include #endif @@ -77,7 +77,7 @@ static int showVersion() printf("microhttpd/%s\n", MHD_get_version()); # endif -# if !defined(XMRIG_NO_TLS) && defined(OPENSSL_VERSION_TEXT) +# if defined(XMRIG_FEATURE_TLS) && defined(OPENSSL_VERSION_TEXT) { constexpr const char *v = OPENSSL_VERSION_TEXT + 8; printf("OpenSSL/%.*s\n", static_cast(strchr(v, ' ') - v), v); diff --git a/src/base/net/stratum/Client.cpp b/src/base/net/stratum/Client.cpp index 88d96871..667dd448 100644 --- a/src/base/net/stratum/Client.cpp +++ b/src/base/net/stratum/Client.cpp @@ -30,7 +30,7 @@ #include -#ifndef XMRIG_NO_TLS +#ifdef XMRIG_FEATURE_TLS # include # include # include "base/net/stratum/Tls.h" @@ -107,7 +107,7 @@ xmrig::Client::~Client() void xmrig::Client::connect() { -# ifndef XMRIG_NO_TLS +# ifdef XMRIG_FEATURE_TLS if (m_pool.isTLS()) { m_tls = new Tls(this); } @@ -184,7 +184,7 @@ bool xmrig::Client::disconnect() bool xmrig::Client::isTLS() const { -# ifndef XMRIG_NO_TLS +# ifdef XMRIG_FEATURE_TLS return m_pool.isTLS() && m_tls; # else return false; @@ -194,7 +194,7 @@ bool xmrig::Client::isTLS() const const char *xmrig::Client::tlsFingerprint() const { -# ifndef XMRIG_NO_TLS +# ifdef XMRIG_FEATURE_TLS if (isTLS() && m_pool.fingerprint() == nullptr) { return m_tls->fingerprint(); } @@ -206,7 +206,7 @@ const char *xmrig::Client::tlsFingerprint() const const char *xmrig::Client::tlsVersion() const { -# ifndef XMRIG_NO_TLS +# ifdef XMRIG_FEATURE_TLS if (isTLS()) { return m_tls->version(); } @@ -435,7 +435,7 @@ bool xmrig::Client::parseLogin(const rapidjson::Value &result, int *code) bool xmrig::Client::send(BIO *bio) { -# ifndef XMRIG_NO_TLS +# ifdef XMRIG_FEATURE_TLS uv_buf_t buf; buf.len = BIO_get_mem_data(bio, &buf.base); @@ -543,7 +543,7 @@ int64_t xmrig::Client::send(size_t size) { LOG_DEBUG("[%s] send (%d bytes): \"%s\"", url(), size, m_sendBuf); -# ifndef XMRIG_NO_TLS +# ifdef XMRIG_FEATURE_TLS if (isTLS()) { if (!m_tls->send(m_sendBuf, size)) { return -1; @@ -597,7 +597,7 @@ void xmrig::Client::connect(sockaddr *addr) void xmrig::Client::handshake() { -# ifndef XMRIG_NO_TLS +# ifdef XMRIG_FEATURE_TLS if (isTLS()) { m_expire = Chrono::steadyMSecs() + kResponseTimeout; @@ -661,7 +661,7 @@ void xmrig::Client::onClose() m_socket = nullptr; setState(UnconnectedState); -# ifndef XMRIG_NO_TLS +# ifdef XMRIG_FEATURE_TLS if (m_tls) { delete m_tls; m_tls = nullptr; @@ -858,7 +858,7 @@ void xmrig::Client::read(ssize_t nread) m_recvBuf.nread(size); -# ifndef XMRIG_NO_TLS +# ifdef XMRIG_FEATURE_TLS if (isTLS()) { LOG_DEBUG("[%s] TLS received (%d bytes)", url(), static_cast(nread)); diff --git a/src/base/net/stratum/Client.h b/src/base/net/stratum/Client.h index c0ea8a93..65b44a5b 100644 --- a/src/base/net/stratum/Client.h +++ b/src/base/net/stratum/Client.h @@ -75,7 +75,7 @@ public: constexpr static int kResponseTimeout = 20 * 1000; -# ifndef XMRIG_NO_TLS +# ifdef XMRIG_FEATURE_TLS constexpr static int kInputBufferSize = 1024 * 16; # else constexpr static int kInputBufferSize = 1024 * 2; diff --git a/src/base/net/stratum/Pool.cpp b/src/base/net/stratum/Pool.cpp index 64543a95..2c48ab0b 100644 --- a/src/base/net/stratum/Pool.cpp +++ b/src/base/net/stratum/Pool.cpp @@ -178,7 +178,7 @@ bool xmrig::Pool::isCompatible(const Algorithm &algorithm) const bool xmrig::Pool::isEnabled() const { -# ifdef XMRIG_NO_TLS +# ifndef XMRIG_FEATURE_TLS if (isTLS()) { return false; } diff --git a/src/common/Platform.cpp b/src/common/Platform.cpp index 6bd0ac80..a74f1978 100644 --- a/src/common/Platform.cpp +++ b/src/common/Platform.cpp @@ -27,7 +27,7 @@ #include -#ifndef XMRIG_NO_TLS +#ifdef XMRIG_FEATURE_TLS # include # include #endif @@ -41,7 +41,7 @@ xmrig::String Platform::m_userAgent; void Platform::init(const char *userAgent) { -# ifndef XMRIG_NO_TLS +# ifdef XMRIG_FEATURE_TLS SSL_library_init(); SSL_load_error_strings(); ERR_load_BIO_strings(); diff --git a/src/common/config/CommonConfig.cpp b/src/common/config/CommonConfig.cpp index 0de10b1e..94a20f80 100644 --- a/src/common/config/CommonConfig.cpp +++ b/src/common/config/CommonConfig.cpp @@ -35,7 +35,7 @@ #endif -#ifndef XMRIG_NO_TLS +#ifdef XMRIG_FEATURE_TLS # include #endif @@ -131,12 +131,12 @@ void xmrig::CommonConfig::printVersions() # else memset(buf, 0, 16); -# if !defined(XMRIG_NO_HTTPD) || !defined(XMRIG_NO_TLS) +# if !defined(XMRIG_NO_HTTPD) || defined(XMRIG_FEATURE_TLS) int length = 0; # endif # endif -# if !defined(XMRIG_NO_TLS) && defined(OPENSSL_VERSION_TEXT) +# if defined(XMRIG_FEATURE_TLS) && defined(OPENSSL_VERSION_TEXT) { constexpr const char *v = OPENSSL_VERSION_TEXT + 8; length += snprintf(buf + length, (sizeof buf) - length, "OpenSSL/%.*s ", static_cast(strchr(v, ' ') - v), v); diff --git a/src/common/config/ConfigLoader.cpp b/src/common/config/ConfigLoader.cpp index 26742e5f..4b251fa2 100644 --- a/src/common/config/ConfigLoader.cpp +++ b/src/common/config/ConfigLoader.cpp @@ -29,16 +29,6 @@ #include -#ifndef XMRIG_NO_HTTPD -# include -#endif - - -#ifndef XMRIG_NO_TLS -# include -#endif - - #include "base/io/Json.h" #include "base/kernel/interfaces/IConfigListener.h" #include "base/kernel/Process.h" From 1e0c410eea141a93838147c8272c74afc19e1bdc Mon Sep 17 00:00:00 2001 From: XMRig Date: Thu, 28 Mar 2019 22:54:27 +0700 Subject: [PATCH 037/116] XMRIG_FEATURE_HTTP & XMRIG_FEATURE_API --- CMakeLists.txt | 7 +++++-- src/App.cpp | 10 +++++----- src/base/kernel/Entry.cpp | 9 --------- src/common/config/CommonConfig.cpp | 8 ++++---- src/interfaces/IThread.h | 4 ++-- src/net/Network.cpp | 2 +- src/workers/CpuThread.cpp | 2 +- src/workers/CpuThread.h | 2 +- src/workers/Workers.cpp | 2 +- src/workers/Workers.h | 2 +- 10 files changed, 21 insertions(+), 27 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 698b4953..d5baa764 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -220,11 +220,14 @@ if (WITH_HTTPD) else() message(FATAL_ERROR "microhttpd NOT found: use `-DWITH_HTTPD=OFF` to build without http deamon support") endif() + + add_definitions(/DXMRIG_FEATURE_HTTP) + add_definitions(/DXMRIG_FEATURE_API) else() set(HTTPD_SOURCES "") set(MHD_LIBRARY "") - add_definitions(/DXMRIG_NO_HTTPD) - add_definitions(/DXMRIG_NO_API) + remove_definitions(/DXMRIG_FEATURE_HTTP) + remove_definitions(/DXMRIG_FEATURE_API) endif() include_directories(src) diff --git a/src/App.cpp b/src/App.cpp index f33140c9..b404c831 100644 --- a/src/App.cpp +++ b/src/App.cpp @@ -45,7 +45,7 @@ #include "workers/Workers.h" -#ifndef XMRIG_NO_HTTPD +#ifdef XMRIG_FEATURE_HTTP # include "common/api/Httpd.h" #endif @@ -72,7 +72,7 @@ xmrig::App::~App() delete m_console; delete m_controller; -# ifndef XMRIG_NO_HTTPD +# ifdef XMRIG_FEATURE_HTTP delete m_httpd; # endif } @@ -98,11 +98,11 @@ int xmrig::App::exec() return 0; } -# ifndef XMRIG_NO_API +# ifdef XMRIG_FEATURE_API Api::start(m_controller); # endif -# ifndef XMRIG_NO_HTTPD +# ifdef XMRIG_FEATURE_HTTP m_httpd = new Httpd( m_controller->config()->apiPort(), m_controller->config()->apiToken(), @@ -185,7 +185,7 @@ void xmrig::App::onSignal(int signum) void xmrig::App::close() { -# ifndef XMRIG_NO_HTTPD +# ifdef XMRIG_FEATURE_HTTP m_httpd->stop(); # endif diff --git a/src/base/kernel/Entry.cpp b/src/base/kernel/Entry.cpp index 5b335453..5af4db78 100644 --- a/src/base/kernel/Entry.cpp +++ b/src/base/kernel/Entry.cpp @@ -27,11 +27,6 @@ #include -#ifndef XMRIG_NO_HTTPD -# include -#endif - - #ifdef XMRIG_FEATURE_TLS # include #endif @@ -73,10 +68,6 @@ static int showVersion() printf("\nlibuv/%s\n", uv_version_string()); -# ifndef XMRIG_NO_HTTPD - printf("microhttpd/%s\n", MHD_get_version()); -# endif - # if defined(XMRIG_FEATURE_TLS) && defined(OPENSSL_VERSION_TEXT) { constexpr const char *v = OPENSSL_VERSION_TEXT + 8; diff --git a/src/common/config/CommonConfig.cpp b/src/common/config/CommonConfig.cpp index 94a20f80..e42402d4 100644 --- a/src/common/config/CommonConfig.cpp +++ b/src/common/config/CommonConfig.cpp @@ -30,7 +30,7 @@ #include -#ifndef XMRIG_NO_HTTPD +#ifdef XMRIG_FEATURE_HTTP # include #endif @@ -82,7 +82,7 @@ xmrig::CommonConfig::CommonConfig() : void xmrig::CommonConfig::printAPI() { -# ifndef XMRIG_NO_API +# ifdef XMRIG_FEATURE_API if (apiPort() == 0) { return; } @@ -131,7 +131,7 @@ void xmrig::CommonConfig::printVersions() # else memset(buf, 0, 16); -# if !defined(XMRIG_NO_HTTPD) || defined(XMRIG_FEATURE_TLS) +# if defined(XMRIG_FEATURE_HTTP) || defined(XMRIG_FEATURE_TLS) int length = 0; # endif # endif @@ -143,7 +143,7 @@ void xmrig::CommonConfig::printVersions() } # endif -# ifndef XMRIG_NO_HTTPD +# ifdef XMRIG_FEATURE_HTTP length += snprintf(buf + length, (sizeof buf) - length, "microhttpd/%s ", MHD_get_version()); # endif diff --git a/src/interfaces/IThread.h b/src/interfaces/IThread.h index 3a8708e6..e74b5bca 100644 --- a/src/interfaces/IThread.h +++ b/src/interfaces/IThread.h @@ -51,7 +51,7 @@ public: PentaWay }; - virtual ~IThread() {} + virtual ~IThread() = default; virtual Algo algorithm() const = 0; virtual int priority() const = 0; @@ -61,7 +61,7 @@ public: virtual size_t index() const = 0; virtual Type type() const = 0; -# ifndef XMRIG_NO_API +# ifdef XMRIG_FEATURE_API virtual rapidjson::Value toAPI(rapidjson::Document &doc) const = 0; # endif diff --git a/src/net/Network.cpp b/src/net/Network.cpp index fbb6d8a1..b8e2e012 100644 --- a/src/net/Network.cpp +++ b/src/net/Network.cpp @@ -197,7 +197,7 @@ void xmrig::Network::tick() m_donate->tick(now); } -# ifndef XMRIG_NO_API +# ifdef XMRIG_FEATURE_API Api::tick(m_state); # endif } diff --git a/src/workers/CpuThread.cpp b/src/workers/CpuThread.cpp index 529027f5..2481162c 100644 --- a/src/workers/CpuThread.cpp +++ b/src/workers/CpuThread.cpp @@ -706,7 +706,7 @@ void xmrig::CpuThread::print() const #endif -#ifndef XMRIG_NO_API +#ifdef XMRIG_FEATURE_API rapidjson::Value xmrig::CpuThread::toAPI(rapidjson::Document &doc) const { using namespace rapidjson; diff --git a/src/workers/CpuThread.h b/src/workers/CpuThread.h index 05d4a066..2af421be 100644 --- a/src/workers/CpuThread.h +++ b/src/workers/CpuThread.h @@ -90,7 +90,7 @@ protected: void print() const override; # endif -# ifndef XMRIG_NO_API +# ifdef XMRIG_FEATURE_API rapidjson::Value toAPI(rapidjson::Document &doc) const override; # endif diff --git a/src/workers/Workers.cpp b/src/workers/Workers.cpp index 08c16828..79045df7 100644 --- a/src/workers/Workers.cpp +++ b/src/workers/Workers.cpp @@ -237,7 +237,7 @@ void Workers::submit(const xmrig::JobResult &result) } -#ifndef XMRIG_NO_API +#ifdef XMRIG_FEATURE_API void Workers::threadsSummary(rapidjson::Document &doc) { uv_mutex_lock(&m_mutex); diff --git a/src/workers/Workers.h b/src/workers/Workers.h index 4b6fc9cf..5b084fc2 100644 --- a/src/workers/Workers.h +++ b/src/workers/Workers.h @@ -68,7 +68,7 @@ public: static inline void pause() { m_active = false; m_paused = 1; m_sequence++; } static inline void setListener(xmrig::IJobResultListener *listener) { m_listener = listener; } -# ifndef XMRIG_NO_API +# ifdef XMRIG_FEATURE_API static void threadsSummary(rapidjson::Document &doc); # endif From 725796a1abee5c114c3e3e8240fec9e7d21c823e Mon Sep 17 00:00:00 2001 From: XMRig Date: Fri, 29 Mar 2019 02:31:56 +0700 Subject: [PATCH 038/116] New API settings. --- CMakeLists.txt | 7 +- src/App.cpp | 8 +- src/Summary.cpp | 4 +- src/api/ApiRouter.cpp | 2 +- src/base/base.cmake | 23 ++++ src/base/net/http/Http.cpp | 112 ++++++++++++++++++++ src/base/net/http/Http.h | 73 +++++++++++++ src/common/config/CommonConfig.cpp | 111 +++++++++++-------- src/common/config/CommonConfig.h | 19 ++-- src/common/interfaces/IConfig.h | 164 +++++++++++++++-------------- src/core/Config.cpp | 11 +- src/core/Config.h | 2 +- src/core/ConfigLoader_platform.h | 91 ++++++++-------- src/core/usage.h | 83 +++++++-------- 14 files changed, 474 insertions(+), 236 deletions(-) create mode 100644 src/base/net/http/Http.cpp create mode 100644 src/base/net/http/Http.h diff --git a/CMakeLists.txt b/CMakeLists.txt index d5baa764..c0e55b5f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -21,6 +21,7 @@ include (src/base/base.cmake) set(HEADERS "${HEADERS_BASE}" + "${HEADERS_BASE_HTTP}" src/api/NetworkState.h src/App.h src/common/config/CommonConfig.h @@ -80,6 +81,7 @@ endif() set(SOURCES "${SOURCES_BASE}" + "${SOURCES_BASE_HTTP}" src/api/NetworkState.cpp src/App.cpp src/common/config/CommonConfig.cpp @@ -220,14 +222,9 @@ if (WITH_HTTPD) else() message(FATAL_ERROR "microhttpd NOT found: use `-DWITH_HTTPD=OFF` to build without http deamon support") endif() - - add_definitions(/DXMRIG_FEATURE_HTTP) - add_definitions(/DXMRIG_FEATURE_API) else() set(HTTPD_SOURCES "") set(MHD_LIBRARY "") - remove_definitions(/DXMRIG_FEATURE_HTTP) - remove_definitions(/DXMRIG_FEATURE_API) endif() include_directories(src) diff --git a/src/App.cpp b/src/App.cpp index b404c831..093b9ceb 100644 --- a/src/App.cpp +++ b/src/App.cpp @@ -104,10 +104,10 @@ int xmrig::App::exec() # ifdef XMRIG_FEATURE_HTTP m_httpd = new Httpd( - m_controller->config()->apiPort(), - m_controller->config()->apiToken(), - m_controller->config()->isApiIPv6(), - m_controller->config()->isApiRestricted() + m_controller->config()->http().port(), + m_controller->config()->http().token(), + false, + m_controller->config()->http().isRestricted() ); m_httpd->start(); diff --git a/src/Summary.cpp b/src/Summary.cpp index 6c7b7bfa..7b47b2c6 100644 --- a/src/Summary.cpp +++ b/src/Summary.cpp @@ -142,8 +142,8 @@ void Summary::print(xmrig::Controller *controller) print_memory(controller->config()); print_cpu(controller->config()); print_threads(controller->config()); - controller->config()->printPools(); - controller->config()->printAPI(); + controller->config()->pools().print(); + controller->config()->http().print(); print_commands(controller->config()); } diff --git a/src/api/ApiRouter.cpp b/src/api/ApiRouter.cpp index 69ab153c..20752f0c 100644 --- a/src/api/ApiRouter.cpp +++ b/src/api/ApiRouter.cpp @@ -166,7 +166,7 @@ void ApiRouter::genId(const char *id) uint8_t hash[200]; const size_t addrSize = sizeof(interfaces[i].phys_addr); const size_t inSize = strlen(APP_KIND) + addrSize + sizeof(uint16_t); - const uint16_t port = static_cast(m_controller->config()->apiPort()); + const uint16_t port = static_cast(m_controller->config()->http().port()); uint8_t *input = new uint8_t[inSize](); memcpy(input, &port, sizeof(uint16_t)); diff --git a/src/base/base.cmake b/src/base/base.cmake index 7ab88d98..ffbd8454 100644 --- a/src/base/base.cmake +++ b/src/base/base.cmake @@ -21,6 +21,7 @@ set(HEADERS_BASE src/base/kernel/Signals.h src/base/net/dns/Dns.h src/base/net/dns/DnsRecord.h + src/base/net/http/Http.h src/base/net/stratum/Client.h src/base/net/stratum/Job.h src/base/net/stratum/Pool.h @@ -50,6 +51,7 @@ set(SOURCES_BASE src/base/kernel/Signals.cpp src/base/net/dns/Dns.cpp src/base/net/dns/DnsRecord.cpp + src/base/net/http/Http.cpp src/base/net/stratum/Client.cpp src/base/net/stratum/Job.cpp src/base/net/stratum/Pool.cpp @@ -77,3 +79,24 @@ if (NOT WIN32) set(SOURCES_SYSLOG src/base/io/log/backends/SysLog.h src/base/io/log/backends/SysLog.cpp) endif() endif() + + +if (WITH_HTTPD) + set(HEADERS_BASE_HTTP +# src/base/net/http/Http.h + ) + + set(SOURCES_BASE_HTTP +# src/base/net/http/Http.cpp + ) + + add_definitions(/DXMRIG_FEATURE_HTTP) + add_definitions(/DXMRIG_FEATURE_API) +else() + set(HEADERS_BASE_HTTP "") + set(SOURCES_BASE_HTTP "") + remove_definitions(/DXMRIG_FEATURE_HTTP) + remove_definitions(/DXMRIG_FEATURE_API) +endif() + +add_definitions(/DXMRIG_DEPRECATED) diff --git a/src/base/net/http/Http.cpp b/src/base/net/http/Http.cpp new file mode 100644 index 00000000..177eebde --- /dev/null +++ b/src/base/net/http/Http.cpp @@ -0,0 +1,112 @@ +/* XMRig + * Copyright 2010 Jeff Garzik + * Copyright 2012-2014 pooler + * Copyright 2014 Lucas Jones + * Copyright 2014-2016 Wolf9466 + * Copyright 2016 Jay D Dee + * Copyright 2017-2018 XMR-Stak , + * Copyright 2018-2019 SChernykh + * Copyright 2016-2019 XMRig , + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + + +#include "3rdparty/rapidjson/document.h" +#include "base/io/Json.h" +#include "base/io/log/Log.h" +#include "base/net/http/Http.h" + + +namespace xmrig { + +static const char *kEnabled = "enabled"; +static const char *kHost = "host"; +static const char *kLocalhost = "127.0.0.1"; +static const char *kPort = "port"; +static const char *kRestricted = "restricted"; +static const char *kToken = "access-token"; + +} + + +xmrig::Http::Http() : + m_enabled(false), + m_restricted(true), + m_host(kLocalhost), + m_port(0) +{ +} + + +bool xmrig::Http::isEqual(const Http &other) const +{ + return other.m_enabled == m_enabled && + other.m_restricted == m_restricted && + other.m_host == m_host && + other.m_token == m_token && + other.m_port == m_port; +} + + +rapidjson::Value xmrig::Http::toJSON(rapidjson::Document &doc) const +{ + using namespace rapidjson; + auto &allocator = doc.GetAllocator(); + + Value obj(kObjectType); + + obj.AddMember(StringRef(kEnabled), m_enabled, allocator); + obj.AddMember(StringRef(kHost), m_host.toJSON(), allocator); + obj.AddMember(StringRef(kPort), m_port, allocator); + obj.AddMember(StringRef(kToken), m_token.toJSON(), allocator); + obj.AddMember(StringRef(kRestricted), m_restricted, allocator); + + return obj; +} + + +void xmrig::Http::load(const rapidjson::Value &http) +{ + if (!http.IsObject()) { + return; + } + + m_enabled = Json::getBool(http, kEnabled); + m_restricted = Json::getBool(http, kRestricted, true); + m_host = Json::getString(http, kHost, kLocalhost); + m_token = Json::getString(http, kToken); + + setPort(Json::getInt(http, kPort)); +} + + +void xmrig::Http::print() const +{ +# ifdef XMRIG_FEATURE_API + if (!isEnabled()) { + return; + } + + Log::print(GREEN_BOLD(" * ") WHITE_BOLD("%-13s") BLUE_BOLD("http://%s:%d"), "HTTP API", host().data(), port()); +# endif +} + + +void xmrig::Http::setPort(int port) +{ + if (port >= 0 && port <= 65536) { + m_port = static_cast(port); + } +} diff --git a/src/base/net/http/Http.h b/src/base/net/http/Http.h new file mode 100644 index 00000000..ebdf6765 --- /dev/null +++ b/src/base/net/http/Http.h @@ -0,0 +1,73 @@ +/* XMRig + * Copyright 2010 Jeff Garzik + * Copyright 2012-2014 pooler + * Copyright 2014 Lucas Jones + * Copyright 2014-2016 Wolf9466 + * Copyright 2016 Jay D Dee + * Copyright 2017-2018 XMR-Stak , + * Copyright 2018-2019 SChernykh + * Copyright 2016-2019 XMRig , + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + + +#ifndef XMRIG_HTTP_H +#define XMRIG_HTTP_H + + +#include "base/tools/String.h" + + +namespace xmrig { + + +class Http +{ +public: + Http(); + + inline bool isEnabled() const { return m_enabled; } + inline bool isRestricted() const { return m_restricted; } + inline const String &host() const { return m_host; } + inline const String &token() const { return m_token; } + inline uint16_t port() const { return m_port; } + inline void setEnabled(bool enabled) { m_enabled = enabled; } + inline void setHost(const char *host) { m_host = host; } + inline void setRestricted(bool restricted) { m_restricted = restricted; } + inline void setToken(const char *token) { m_token = token; } + + inline bool operator!=(const Http &other) const { return !isEqual(other); } + inline bool operator==(const Http &other) const { return isEqual(other); } + + bool isEqual(const Http &other) const; + rapidjson::Value toJSON(rapidjson::Document &doc) const; + void load(const rapidjson::Value &http); + void print() const; + void setPort(int port); + +private: + bool m_enabled; + bool m_restricted; + String m_host; + String m_token; + uint16_t m_port; +}; + + +} // namespace xmrig + + +#endif // XMRIG_HTTP_H + diff --git a/src/common/config/CommonConfig.cpp b/src/common/config/CommonConfig.cpp index e42402d4..04518400 100644 --- a/src/common/config/CommonConfig.cpp +++ b/src/common/config/CommonConfig.cpp @@ -66,38 +66,18 @@ xmrig::CommonConfig::CommonConfig() : m_algorithm(CRYPTONIGHT, VARIANT_AUTO), m_adjusted(false), - m_apiIPv6(false), - m_apiRestricted(true), m_autoSave(true), m_background(false), m_dryRun(false), m_syslog(false), + m_upgrade(false), m_watch(true), - m_apiPort(0), m_printTime(60), m_state(NoneState) { } -void xmrig::CommonConfig::printAPI() -{ -# ifdef XMRIG_FEATURE_API - if (apiPort() == 0) { - return; - } - - Log::print(GREEN_BOLD(" * ") WHITE_BOLD("%-13s") CYAN("%s:") CYAN_BOLD("%d"), "API BIND", isApiIPv6() ? "[::]" : "0.0.0.0", apiPort()); -# endif -} - - -void xmrig::CommonConfig::printPools() -{ - m_pools.print(); -} - - void xmrig::CommonConfig::printVersions() { char buf[256] = { 0 }; @@ -228,12 +208,23 @@ bool xmrig::CommonConfig::parseBoolean(int key, bool enable) m_watch = enable; break; - case ApiIPv6Key: /* ipv6 */ - m_apiIPv6 = enable; +# ifdef XMRIG_DEPRECATED + case ApiIPv6Key: /* --api-ipv6 */ break; - case ApiRestrictedKey: /* restricted */ - m_apiRestricted = enable; + case ApiRestrictedKey: /* --api-no-restricted */ + fputs("option \"--api-no-restricted\" deprecated, use \"--http-no-restricted\" instead.\n", stderr); + fflush(stdout); + m_http.setRestricted(enable); + break; +# endif + + case HttpRestrictedKey: /* --http-no-restricted */ + m_http.setRestricted(enable); + break; + + case HttpEnabledKey: /* --http-enabled */ + m_http.setEnabled(enable); break; case DryRunKey: /* --dry-run */ @@ -289,8 +280,20 @@ bool xmrig::CommonConfig::parseString(int key, const char *arg) m_logFile = arg; break; +# ifdef XMRIG_DEPRECATED case ApiAccessTokenKey: /* --api-access-token */ - m_apiToken = arg; + fputs("option \"--api-access-token\" deprecated, use \"--http-access-token\" instead.\n", stderr); + fflush(stdout); + m_http.setToken(arg); + break; +# endif + + case HttpAccessTokenKey: /* --http-access-token */ + m_http.setToken(arg); + break; + + case HttpHostKey: /* --http-host */ + m_http.setHost(arg); break; case ApiWorkerIdKey: /* --api-worker-id */ @@ -307,26 +310,33 @@ bool xmrig::CommonConfig::parseString(int key, const char *arg) case RetriesKey: /* --retries */ case RetryPauseKey: /* --retry-pause */ - case ApiPort: /* --api-port */ case PrintTimeKey: /* --print-time */ - return parseUint64(key, strtol(arg, nullptr, 10)); + case HttpPort: /* --http-port */ +# ifdef XMRIG_DEPRECATED + case ApiPort: /* --api-port */ +# endif + return parseUint64(key, static_cast(strtol(arg, nullptr, 10))); - case BackgroundKey: /* --background */ - case SyslogKey: /* --syslog */ - case KeepAliveKey: /* --keepalive */ - case NicehashKey: /* --nicehash */ - case TlsKey: /* --tls */ - case ApiIPv6Key: /* --api-ipv6 */ - case DryRunKey: /* --dry-run */ + case BackgroundKey: /* --background */ + case SyslogKey: /* --syslog */ + case KeepAliveKey: /* --keepalive */ + case NicehashKey: /* --nicehash */ + case TlsKey: /* --tls */ + case DryRunKey: /* --dry-run */ + case HttpEnabledKey: /* --http-enabled */ return parseBoolean(key, true); - case ColorKey: /* --no-color */ - case WatchKey: /* --no-watch */ + case ColorKey: /* --no-color */ + case WatchKey: /* --no-watch */ + case HttpRestrictedKey: /* --http-no-restricted */ +# ifdef XMRIG_DEPRECATED case ApiRestrictedKey: /* --api-no-restricted */ + case ApiIPv6Key: /* --api-ipv6 */ +# endif return parseBoolean(key, false); case DonateLevelKey: /* --donate-level */ - return parseUint64(key, strtol(arg, nullptr, 10)); + return parseUint64(key, static_cast(strtol(arg, nullptr, 10))); default: break; @@ -348,6 +358,19 @@ void xmrig::CommonConfig::parseJSON(const rapidjson::Document &doc) if (pools.IsArray()) { m_pools.load(pools); } + +# ifdef XMRIG_DEPRECATED + const rapidjson::Value &api = doc["api"]; + if (api.IsObject() && api.HasMember("port")) { + m_upgrade = true; + m_http.load(api); + } + else { + m_http.load(doc["http"]); + } +# else + m_http.load(doc["http"]); +# endif } @@ -384,10 +407,16 @@ bool xmrig::CommonConfig::parseInt(int key, int arg) m_pools.setProxyDonate(arg); break; +# ifdef XMRIG_DEPRECATED case ApiPort: /* --api-port */ - if (arg > 0 && arg <= 65536) { - m_apiPort = arg; - } + fputs("option \"--api-port\" deprecated, use \"--http-port\" instead.\n", stderr); + fflush(stdout); + m_http.setPort(arg); + break; +# endif + + case HttpPort: /* --http-port */ + m_http.setPort(arg); break; case PrintTimeKey: /* --print-time */ diff --git a/src/common/config/CommonConfig.h b/src/common/config/CommonConfig.h index b2ec56ea..e3331fe0 100644 --- a/src/common/config/CommonConfig.h +++ b/src/common/config/CommonConfig.h @@ -26,8 +26,8 @@ #define XMRIG_COMMONCONFIG_H +#include "base/net/http/Http.h" #include "base/net/stratum/Pools.h" -#include "base/tools/String.h" #include "common/interfaces/IConfig.h" #include "common/xmrig.h" @@ -40,19 +40,16 @@ class CommonConfig : public IConfig public: CommonConfig(); - inline bool isApiIPv6() const { return m_apiIPv6; } - inline bool isApiRestricted() const { return m_apiRestricted; } inline bool isAutoSave() const { return m_autoSave; } inline bool isBackground() const { return m_background; } inline bool isDryRun() const { return m_dryRun; } inline bool isSyslog() const { return m_syslog; } - inline const char *apiId() const { return m_apiId.data(); } - inline const char *apiToken() const { return m_apiToken.data(); } - inline const char *apiWorkerId() const { return m_apiWorkerId.data(); } + inline const String &apiId() const { return m_apiId; } + inline const String &apiWorkerId() const { return m_apiWorkerId; } inline const char *logFile() const { return m_logFile.data(); } inline const char *userAgent() const { return m_userAgent.data(); } + inline const Http &http() const { return m_http; } inline const Pools &pools() const { return m_pools; } - inline int apiPort() const { return m_apiPort; } inline int printTime() const { return m_printTime; } inline bool isWatch() const override { return m_watch && !m_fileName.isNull(); } @@ -61,8 +58,6 @@ public: bool save() override; - void printAPI(); - void printPools(); void printVersions(); protected: @@ -81,19 +76,17 @@ protected: Algorithm m_algorithm; bool m_adjusted; - bool m_apiIPv6; - bool m_apiRestricted; bool m_autoSave; bool m_background; bool m_dryRun; bool m_syslog; + bool m_upgrade; bool m_watch; - int m_apiPort; + Http m_http; int m_printTime; Pools m_pools; State m_state; String m_apiId; - String m_apiToken; String m_apiWorkerId; String m_fileName; String m_logFile; diff --git a/src/common/interfaces/IConfig.h b/src/common/interfaces/IConfig.h index e898c24c..d7b7944a 100644 --- a/src/common/interfaces/IConfig.h +++ b/src/common/interfaces/IConfig.h @@ -41,94 +41,102 @@ class IConfig public: enum Keys { // common - AlgorithmKey = 'a', - ApiAccessTokenKey = 4001, - ApiIPv6Key = 4003, - ApiPort = 4000, - ApiRestrictedKey = 4004, - ApiWorkerIdKey = 4002, - ApiIdKey = 4005, - BackgroundKey = 'B', - ColorKey = 1002, - ConfigKey = 'c', - DonateLevelKey = 1003, - KeepAliveKey = 'k', - LogFileKey = 'l', - PasswordKey = 'p', - RetriesKey = 'r', - RetryPauseKey = 'R', - RigIdKey = 1012, - SyslogKey = 'S', - UrlKey = 'o', - UserAgentKey = 1008, - UserKey = 'u', - UserpassKey = 'O', - VariantKey = 1010, - VerboseKey = 1100, - WatchKey = 1105, - TlsKey = 1013, - FingerprintKey = 1014, - AutoSaveKey = 1016, - ProxyDonateKey = 1017, + AlgorithmKey = 'a', + ApiWorkerIdKey = 4002, + ApiIdKey = 4005, + HttpPort = 4100, + HttpAccessTokenKey = 4101, + HttpRestrictedKey = 4104, + HttpEnabledKey = 4106, + HttpHostKey = 4107, + BackgroundKey = 'B', + ColorKey = 1002, + ConfigKey = 'c', + DonateLevelKey = 1003, + KeepAliveKey = 'k', + LogFileKey = 'l', + PasswordKey = 'p', + RetriesKey = 'r', + RetryPauseKey = 'R', + RigIdKey = 1012, + SyslogKey = 'S', + UrlKey = 'o', + UserAgentKey = 1008, + UserKey = 'u', + UserpassKey = 'O', + VariantKey = 1010, + VerboseKey = 1100, + WatchKey = 1105, + TlsKey = 1013, + FingerprintKey = 1014, + AutoSaveKey = 1016, + ProxyDonateKey = 1017, + +# ifdef XMRIG_DEPRECATED + ApiPort = 4000, + ApiAccessTokenKey = 4001, + ApiIPv6Key = 4003, + ApiRestrictedKey = 4004, +# endif // xmrig common - CPUPriorityKey = 1021, - NicehashKey = 1006, - PrintTimeKey = 1007, + CPUPriorityKey = 1021, + NicehashKey = 1006, + PrintTimeKey = 1007, // xmrig cpu - AVKey = 'v', - CPUAffinityKey = 1020, - DryRunKey = 5000, - HugePagesKey = 1009, - MaxCPUUsageKey = 1004, - SafeKey = 1005, - ThreadsKey = 't', - HardwareAESKey = 1011, - AssemblyKey = 1015, + AVKey = 'v', + CPUAffinityKey = 1020, + DryRunKey = 5000, + HugePagesKey = 1009, + MaxCPUUsageKey = 1004, + SafeKey = 1005, + ThreadsKey = 't', + HardwareAESKey = 1011, + AssemblyKey = 1015, // xmrig amd - OclPlatformKey = 1400, - OclAffinityKey = 1401, - OclDevicesKey = 1402, - OclLaunchKey = 1403, - OclCacheKey = 1404, - OclPrintKey = 1405, - OclLoaderKey = 1406, - OclSridedIndexKey = 1407, - OclMemChunkKey = 1408, - OclUnrollKey = 1409, - OclCompModeKey = 1410, + OclPlatformKey = 1400, + OclAffinityKey = 1401, + OclDevicesKey = 1402, + OclLaunchKey = 1403, + OclCacheKey = 1404, + OclPrintKey = 1405, + OclLoaderKey = 1406, + OclSridedIndexKey = 1407, + OclMemChunkKey = 1408, + OclUnrollKey = 1409, + OclCompModeKey = 1410, // xmrig-proxy - AccessLogFileKey = 'A', - BindKey = 'b', - CoinKey = 1104, - CustomDiffKey = 1102, - DebugKey = 1101, - ModeKey = 'm', - PoolCoinKey = 'C', - ReuseTimeoutKey = 1106, - WorkersKey = 1103, - WorkersAdvKey = 1107, - TlsBindKey = 1108, - TlsCertKey = 1109, - TlsCertKeyKey = 1110, - TlsDHparamKey = 1111, - TlsCiphersKey = 1112, - TlsCipherSuitesKey = 1113, - TlsProtocolsKey = 1114, - AlgoExtKey = 1115, - ProxyPasswordKey = 1116, + AccessLogFileKey = 'A', + BindKey = 'b', + CoinKey = 1104, + CustomDiffKey = 1102, + DebugKey = 1101, + ModeKey = 'm', + PoolCoinKey = 'C', + ReuseTimeoutKey = 1106, + WorkersKey = 1103, + WorkersAdvKey = 1107, + TlsBindKey = 1108, + TlsCertKey = 1109, + TlsCertKeyKey = 1110, + TlsDHparamKey = 1111, + TlsCiphersKey = 1112, + TlsCipherSuitesKey = 1113, + TlsProtocolsKey = 1114, + AlgoExtKey = 1115, + ProxyPasswordKey = 1116, // xmrig nvidia - CudaMaxThreadsKey = 1200, - CudaBFactorKey = 1201, - CudaBSleepKey = 1202, - CudaDevicesKey = 1203, - CudaLaunchKey = 1204, - CudaAffinityKey = 1205, - CudaMaxUsageKey = 1206, + CudaMaxThreadsKey = 1200, + CudaBFactorKey = 1201, + CudaBSleepKey = 1202, + CudaDevicesKey = 1203, + CudaLaunchKey = 1204, + CudaAffinityKey = 1205, + CudaMaxUsageKey = 1206, }; virtual ~IConfig() = default; diff --git a/src/core/Config.cpp b/src/core/Config.cpp index 2593ef64..a1c91548 100644 --- a/src/core/Config.cpp +++ b/src/core/Config.cpp @@ -73,13 +73,10 @@ void xmrig::Config::getJSON(rapidjson::Document &doc) const doc.AddMember("algo", StringRef(algorithm().name()), allocator); Value api(kObjectType); - api.AddMember("port", apiPort(), allocator); - api.AddMember("access-token", apiToken() ? Value(StringRef(apiToken())).Move() : Value(kNullType).Move(), allocator); - api.AddMember("id", apiId() ? Value(StringRef(apiId())).Move() : Value(kNullType).Move(), allocator); - api.AddMember("worker-id", apiWorkerId() ? Value(StringRef(apiWorkerId())).Move() : Value(kNullType).Move(), allocator); - api.AddMember("ipv6", isApiIPv6(), allocator); - api.AddMember("restricted", isApiRestricted(), allocator); + api.AddMember("id", m_apiId.toJSON(), allocator); + api.AddMember("worker-id", m_apiWorkerId.toJSON(), allocator); doc.AddMember("api", api, allocator); + doc.AddMember("http", m_http.toJSON(doc), allocator); # ifndef XMRIG_NO_ASM doc.AddMember("asm", Asm::toJSON(m_assembly), allocator); @@ -269,7 +266,7 @@ bool xmrig::Config::parseUint64(int key, uint64_t arg) switch (key) { case CPUAffinityKey: /* --cpu-affinity */ if (arg) { - m_threads.mask = arg; + m_threads.mask = static_cast(arg); } break; diff --git a/src/core/Config.h b/src/core/Config.h index d2e8c166..d7df9cd9 100644 --- a/src/core/Config.h +++ b/src/core/Config.h @@ -75,7 +75,7 @@ public: inline AlgoVariant algoVariant() const { return m_algoVariant; } inline Assembly assembly() const { return m_assembly; } inline bool isHugePages() const { return m_hugePages; } - inline bool isShouldSave() const { return m_shouldSave && isAutoSave(); } + inline bool isShouldSave() const { return (m_shouldSave || m_upgrade) && isAutoSave(); } inline const std::vector &threads() const { return m_threads.list; } inline int priority() const { return m_priority; } inline int threadsCount() const { return m_threads.list.size(); } diff --git a/src/core/ConfigLoader_platform.h b/src/core/ConfigLoader_platform.h index a13983cd..5026888d 100644 --- a/src/core/ConfigLoader_platform.h +++ b/src/core/ConfigLoader_platform.h @@ -44,45 +44,54 @@ static char const short_options[] = "a:c:kBp:Px:r:R:s:t:T:o:u:O:v:l:S"; static struct option const options[] = { - { "algo", 1, nullptr, IConfig::AlgorithmKey }, - { "api-access-token", 1, nullptr, IConfig::ApiAccessTokenKey }, - { "api-port", 1, nullptr, IConfig::ApiPort }, - { "api-worker-id", 1, nullptr, IConfig::ApiWorkerIdKey }, - { "api-id", 1, nullptr, IConfig::ApiIdKey }, - { "api-ipv6", 0, nullptr, IConfig::ApiIPv6Key }, - { "api-no-restricted", 0, nullptr, IConfig::ApiRestrictedKey }, - { "av", 1, nullptr, IConfig::AVKey }, - { "background", 0, nullptr, IConfig::BackgroundKey }, - { "config", 1, nullptr, IConfig::ConfigKey }, - { "cpu-affinity", 1, nullptr, IConfig::CPUAffinityKey }, - { "cpu-priority", 1, nullptr, IConfig::CPUPriorityKey }, - { "donate-level", 1, nullptr, IConfig::DonateLevelKey }, - { "donate-over-proxy", 1, nullptr, IConfig::ProxyDonateKey }, - { "dry-run", 0, nullptr, IConfig::DryRunKey }, - { "keepalive", 0, nullptr, IConfig::KeepAliveKey }, - { "log-file", 1, nullptr, IConfig::LogFileKey }, - { "max-cpu-usage", 1, nullptr, IConfig::MaxCPUUsageKey }, - { "nicehash", 0, nullptr, IConfig::NicehashKey }, - { "no-color", 0, nullptr, IConfig::ColorKey }, - { "no-watch", 0, nullptr, IConfig::WatchKey }, - { "no-huge-pages", 0, nullptr, IConfig::HugePagesKey }, - { "variant", 1, nullptr, IConfig::VariantKey }, - { "pass", 1, nullptr, IConfig::PasswordKey }, - { "print-time", 1, nullptr, IConfig::PrintTimeKey }, - { "retries", 1, nullptr, IConfig::RetriesKey }, - { "retry-pause", 1, nullptr, IConfig::RetryPauseKey }, - { "safe", 0, nullptr, IConfig::SafeKey }, - { "syslog", 0, nullptr, IConfig::SyslogKey }, - { "threads", 1, nullptr, IConfig::ThreadsKey }, - { "url", 1, nullptr, IConfig::UrlKey }, - { "user", 1, nullptr, IConfig::UserKey }, - { "user-agent", 1, nullptr, IConfig::UserAgentKey }, - { "userpass", 1, nullptr, IConfig::UserpassKey }, - { "rig-id", 1, nullptr, IConfig::RigIdKey }, - { "tls", 0, nullptr, IConfig::TlsKey }, - { "tls-fingerprint", 1, nullptr, IConfig::FingerprintKey }, - { "asm", 1, nullptr, IConfig::AssemblyKey }, - { nullptr, 0, nullptr, 0 } + { "algo", 1, nullptr, IConfig::AlgorithmKey }, + { "api-worker-id", 1, nullptr, IConfig::ApiWorkerIdKey }, + { "api-id", 1, nullptr, IConfig::ApiIdKey }, + { "http-enabled", 0, nullptr, IConfig::HttpEnabledKey }, + { "http-host", 1, nullptr, IConfig::HttpHostKey }, + { "http-access-token", 1, nullptr, IConfig::HttpAccessTokenKey }, + { "http-port", 1, nullptr, IConfig::HttpPort }, + { "http-no-restricted", 0, nullptr, IConfig::HttpRestrictedKey }, + { "av", 1, nullptr, IConfig::AVKey }, + { "background", 0, nullptr, IConfig::BackgroundKey }, + { "config", 1, nullptr, IConfig::ConfigKey }, + { "cpu-affinity", 1, nullptr, IConfig::CPUAffinityKey }, + { "cpu-priority", 1, nullptr, IConfig::CPUPriorityKey }, + { "donate-level", 1, nullptr, IConfig::DonateLevelKey }, + { "donate-over-proxy", 1, nullptr, IConfig::ProxyDonateKey }, + { "dry-run", 0, nullptr, IConfig::DryRunKey }, + { "keepalive", 0, nullptr, IConfig::KeepAliveKey }, + { "log-file", 1, nullptr, IConfig::LogFileKey }, + { "max-cpu-usage", 1, nullptr, IConfig::MaxCPUUsageKey }, + { "nicehash", 0, nullptr, IConfig::NicehashKey }, + { "no-color", 0, nullptr, IConfig::ColorKey }, + { "no-watch", 0, nullptr, IConfig::WatchKey }, + { "no-huge-pages", 0, nullptr, IConfig::HugePagesKey }, + { "variant", 1, nullptr, IConfig::VariantKey }, + { "pass", 1, nullptr, IConfig::PasswordKey }, + { "print-time", 1, nullptr, IConfig::PrintTimeKey }, + { "retries", 1, nullptr, IConfig::RetriesKey }, + { "retry-pause", 1, nullptr, IConfig::RetryPauseKey }, + { "safe", 0, nullptr, IConfig::SafeKey }, + { "syslog", 0, nullptr, IConfig::SyslogKey }, + { "threads", 1, nullptr, IConfig::ThreadsKey }, + { "url", 1, nullptr, IConfig::UrlKey }, + { "user", 1, nullptr, IConfig::UserKey }, + { "user-agent", 1, nullptr, IConfig::UserAgentKey }, + { "userpass", 1, nullptr, IConfig::UserpassKey }, + { "rig-id", 1, nullptr, IConfig::RigIdKey }, + { "tls", 0, nullptr, IConfig::TlsKey }, + { "tls-fingerprint", 1, nullptr, IConfig::FingerprintKey }, + { "asm", 1, nullptr, IConfig::AssemblyKey }, + +# ifdef XMRIG_DEPRECATED + { "api-port", 1, nullptr, IConfig::ApiPort }, + { "api-access-token", 1, nullptr, IConfig::ApiAccessTokenKey }, + { "api-no-restricted", 0, nullptr, IConfig::ApiRestrictedKey }, + { "api-ipv6", 0, nullptr, IConfig::ApiIPv6Key }, +# endif + + { nullptr, 0, nullptr, 0 } }; @@ -115,11 +124,7 @@ static struct option const config_options[] = { static struct option const api_options[] = { - { "port", 1, nullptr, IConfig::ApiPort }, - { "access-token", 1, nullptr, IConfig::ApiAccessTokenKey }, { "worker-id", 1, nullptr, IConfig::ApiWorkerIdKey }, - { "ipv6", 0, nullptr, IConfig::ApiIPv6Key }, - { "restricted", 0, nullptr, IConfig::ApiRestrictedKey }, { "id", 1, nullptr, IConfig::ApiIdKey }, { nullptr, 0, nullptr, 0 } }; diff --git a/src/core/usage.h b/src/core/usage.h index 0d5c4781..430a60c7 100644 --- a/src/core/usage.h +++ b/src/core/usage.h @@ -35,58 +35,59 @@ namespace xmrig { static char const usage[] = "\ Usage: " APP_ID " [OPTIONS]\n\ Options:\n\ - -a, --algo=ALGO specify the algorithm to use\n\ - cryptonight\n" + -a, --algo=ALGO specify the algorithm to use\n\ + cryptonight\n" #ifndef XMRIG_NO_AEON "\ - cryptonight-lite\n" + cryptonight-lite\n" #endif #ifndef XMRIG_NO_SUMO "\ - cryptonight-heavy\n" + cryptonight-heavy\n" #endif "\ - -o, --url=URL URL of mining server\n\ - -O, --userpass=U:P username:password pair for mining server\n\ - -u, --user=USERNAME username for mining server\n\ - -p, --pass=PASSWORD password for mining server\n\ - --rig-id=ID rig identifier for pool-side statistics (needs pool support)\n\ - -t, --threads=N number of miner threads\n\ - -v, --av=N algorithm variation, 0 auto select\n\ - -k, --keepalive send keepalived packet for prevent timeout (needs pool support)\n\ - --nicehash enable nicehash.com support\n\ - --tls enable SSL/TLS support (needs pool support)\n\ - --tls-fingerprint=F pool TLS certificate fingerprint, if set enable strict certificate pinning\n\ - -r, --retries=N number of times to retry before switch to backup server (default: 5)\n\ - -R, --retry-pause=N time to pause between retries (default: 5)\n\ - --cpu-affinity set process affinity to CPU core(s), mask 0x3 for cores 0 and 1\n\ - --cpu-priority set process priority (0 idle, 2 normal to 5 highest)\n\ - --no-huge-pages disable huge pages support\n\ - --no-color disable colored output\n\ - --variant algorithm PoW variant\n\ - --donate-level=N donate level, default 5%% (5 minutes in 100 minutes)\n\ - --user-agent set custom user-agent string for pool\n\ - -B, --background run the miner in the background\n\ - -c, --config=FILE load a JSON-format configuration file\n\ - -l, --log-file=FILE log all output to a file\n" + -o, --url=URL URL of mining server\n\ + -O, --userpass=U:P username:password pair for mining server\n\ + -u, --user=USERNAME username for mining server\n\ + -p, --pass=PASSWORD password for mining server\n\ + --rig-id=ID rig identifier for pool-side statistics (needs pool support)\n\ + -t, --threads=N number of miner threads\n\ + -v, --av=N algorithm variation, 0 auto select\n\ + -k, --keepalive send keepalived packet for prevent timeout (needs pool support)\n\ + --nicehash enable nicehash.com support\n\ + --tls enable SSL/TLS support (needs pool support)\n\ + --tls-fingerprint=F pool TLS certificate fingerprint, if set enable strict certificate pinning\n\ + -r, --retries=N number of times to retry before switch to backup server (default: 5)\n\ + -R, --retry-pause=N time to pause between retries (default: 5)\n\ + --cpu-affinity set process affinity to CPU core(s), mask 0x3 for cores 0 and 1\n\ + --cpu-priority set process priority (0 idle, 2 normal to 5 highest)\n\ + --no-huge-pages disable huge pages support\n\ + --no-color disable colored output\n\ + --variant algorithm PoW variant\n\ + --donate-level=N donate level, default 5%% (5 minutes in 100 minutes)\n\ + --user-agent set custom user-agent string for pool\n\ + -B, --background run the miner in the background\n\ + -c, --config=FILE load a JSON-format configuration file\n\ + -l, --log-file=FILE log all output to a file\n" # ifdef HAVE_SYSLOG_H "\ - -S, --syslog use system log for output messages\n" + -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\ - --asm=ASM ASM code for cn/2, possible values: auto, none, intel, ryzen, bulldozer.\n\ - --print-time=N print hashrate report every N seconds\n\ - --api-port=N port for the miner API\n\ - --api-access-token=T access token for API\n\ - --api-worker-id=ID custom worker-id for API\n\ - --api-id=ID custom instance ID for API\n\ - --api-ipv6 enable IPv6 support for API\n\ - --api-no-restricted enable full remote access (only if API token set)\n\ - --dry-run test configuration and exit\n\ - -h, --help display this help and exit\n\ - -V, --version output version information and exit\n\ + --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\ + --asm=ASM ASM code for cn/2, possible values: auto, none, intel, ryzen, bulldozer.\n\ + --print-time=N print hashrate report every N seconds\n\ + --api-worker-id=ID custom worker-id for API\n\ + --api-id=ID custom instance ID for API\n\ + --http-enabled enable HTTP API\n\ + --http-host=HOST bind host for HTTP API (by default 127.0.0.1)\n\ + --http-port=N bind port for HTTP API\n\ + --http-access-token=T access token for HTTP API\n\ + --http-no-restricted enable full remote access to HTTP API (only if access token set)\n\ + --dry-run test configuration and exit\n\ + -h, --help display this help and exit\n\ + -V, --version output version information and exit\n\ "; From 01ad6bf2d93286a6fc71005058783836fb25b760 Mon Sep 17 00:00:00 2001 From: XMRig Date: Fri, 29 Mar 2019 12:33:11 +0700 Subject: [PATCH 039/116] Added new HTTP server (tiny wrapper on top of libuv + http_parser), removed libmicrohttpd support. --- CMakeLists.txt | 35 +- src/3rdparty/http-parser/AUTHORS | 68 + src/3rdparty/http-parser/LICENSE-MIT | 19 + src/3rdparty/http-parser/README.md | 246 ++ src/3rdparty/http-parser/http_parser.c | 2501 +++++++++++++++++ src/3rdparty/http-parser/http_parser.h | 439 +++ src/App.cpp | 10 +- src/Summary.cpp | 1 - src/api/Httpd.cpp | 109 + src/{common => }/api/Httpd.h | 41 +- src/base/base.cmake | 17 +- .../kernel}/interfaces/IControllerListener.h | 0 src/base/kernel/interfaces/IHttpListener.h | 48 + .../kernel/interfaces/ITcpServerListener.h | 53 + src/base/net/http/Http.cpp | 13 - src/base/net/http/Http.h | 1 - src/base/net/http/HttpContext.cpp | 142 + src/base/net/http/HttpContext.h | 81 + src/base/net/http/HttpRequest.h | 53 + src/base/net/http/HttpResponse.cpp | 97 + src/base/net/http/HttpResponse.h | 70 + src/base/net/http/HttpServer.cpp | 108 + src/base/net/http/HttpServer.h | 65 + src/base/net/tools/TcpServer.cpp | 102 + src/base/net/tools/TcpServer.h | 64 + src/common/api/Httpd.cpp | 151 - src/common/config/CommonConfig.cpp | 9 - src/core/Controller.cpp | 4 +- src/net/Network.h | 2 +- 29 files changed, 4312 insertions(+), 237 deletions(-) create mode 100644 src/3rdparty/http-parser/AUTHORS create mode 100644 src/3rdparty/http-parser/LICENSE-MIT create mode 100644 src/3rdparty/http-parser/README.md create mode 100644 src/3rdparty/http-parser/http_parser.c create mode 100644 src/3rdparty/http-parser/http_parser.h create mode 100644 src/api/Httpd.cpp rename src/{common => }/api/Httpd.h (63%) rename src/{common => base/kernel}/interfaces/IControllerListener.h (100%) create mode 100644 src/base/kernel/interfaces/IHttpListener.h create mode 100644 src/base/kernel/interfaces/ITcpServerListener.h create mode 100644 src/base/net/http/HttpContext.cpp create mode 100644 src/base/net/http/HttpContext.h create mode 100644 src/base/net/http/HttpRequest.h create mode 100644 src/base/net/http/HttpResponse.cpp create mode 100644 src/base/net/http/HttpResponse.h create mode 100644 src/base/net/http/HttpServer.cpp create mode 100644 src/base/net/http/HttpServer.h create mode 100644 src/base/net/tools/TcpServer.cpp create mode 100644 src/base/net/tools/TcpServer.h delete mode 100644 src/common/api/Httpd.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index c0e55b5f..eb0c8936 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -32,7 +32,6 @@ set(HEADERS src/common/crypto/keccak.h src/common/interfaces/IConfig.h src/common/interfaces/IConfigCreator.h - src/common/interfaces/IControllerListener.h src/common/interfaces/ICpuInfo.h src/common/Platform.h src/common/utils/mm_malloc.h @@ -203,28 +202,20 @@ if (WITH_EMBEDDED_CONFIG) endif() if (WITH_HTTPD) - find_package(MHD) - - if (MHD_FOUND) - include_directories(${MHD_INCLUDE_DIRS}) - set(HTTPD_SOURCES - src/api/Api.h - src/api/ApiRouter.h - src/common/api/HttpBody.h - src/common/api/Httpd.h - src/common/api/HttpReply.h - src/common/api/HttpRequest.h - src/api/Api.cpp - src/api/ApiRouter.cpp - src/common/api/Httpd.cpp - src/common/api/HttpRequest.cpp - ) - else() - message(FATAL_ERROR "microhttpd NOT found: use `-DWITH_HTTPD=OFF` to build without http deamon support") - endif() + set(HTTPD_SOURCES +# src/api/Api.h +# src/api/ApiRouter.h +# src/common/api/HttpBody.h + src/api/Httpd.h +# src/common/api/HttpReply.h +# src/common/api/HttpRequest.h +# src/api/Api.cpp +# src/api/ApiRouter.cpp + src/api/Httpd.cpp +# src/common/api/HttpRequest.cpp + ) else() set(HTTPD_SOURCES "") - set(MHD_LIBRARY "") endif() include_directories(src) @@ -240,4 +231,4 @@ if (WITH_DEBUG_LOG) endif() add_executable(${CMAKE_PROJECT_NAME} ${HEADERS} ${SOURCES} ${SOURCES_OS} ${SOURCES_CPUID} ${HEADERS_CRYPTO} ${SOURCES_CRYPTO} ${SOURCES_SYSLOG} ${HTTPD_SOURCES} ${TLS_SOURCES} ${XMRIG_ASM_SOURCES} ${CN_GPU_SOURCES}) -target_link_libraries(${CMAKE_PROJECT_NAME} ${XMRIG_ASM_LIBRARY} ${OPENSSL_LIBRARIES} ${UV_LIBRARIES} ${MHD_LIBRARY} ${EXTRA_LIBS} ${CPUID_LIB}) +target_link_libraries(${CMAKE_PROJECT_NAME} ${XMRIG_ASM_LIBRARY} ${OPENSSL_LIBRARIES} ${UV_LIBRARIES} ${EXTRA_LIBS} ${CPUID_LIB}) diff --git a/src/3rdparty/http-parser/AUTHORS b/src/3rdparty/http-parser/AUTHORS new file mode 100644 index 00000000..5323b685 --- /dev/null +++ b/src/3rdparty/http-parser/AUTHORS @@ -0,0 +1,68 @@ +# Authors ordered by first contribution. +Ryan Dahl +Jeremy Hinegardner +Sergey Shepelev +Joe Damato +tomika +Phoenix Sol +Cliff Frey +Ewen Cheslack-Postava +Santiago Gala +Tim Becker +Jeff Terrace +Ben Noordhuis +Nathan Rajlich +Mark Nottingham +Aman Gupta +Tim Becker +Sean Cunningham +Peter Griess +Salman Haq +Cliff Frey +Jon Kolb +Fouad Mardini +Paul Querna +Felix Geisendörfer +koichik +Andre Caron +Ivo Raisr +James McLaughlin +David Gwynne +Thomas LE ROUX +Randy Rizun +Andre Louis Caron +Simon Zimmermann +Erik Dubbelboer +Martell Malone +Bertrand Paquet +BogDan Vatra +Peter Faiman +Corey Richardson +Tóth Tamás +Cam Swords +Chris Dickinson +Uli Köhler +Charlie Somerville +Patrik Stutz +Fedor Indutny +runner +Alexis Campailla +David Wragg +Vinnie Falco +Alex Butum +Rex Feng +Alex Kocharin +Mark Koopman +Helge Heß +Alexis La Goutte +George Miroshnykov +Maciej MaÅ‚ecki +Marc O'Morain +Jeff Pinner +Timothy J Fontaine +Akagi201 +Romain Giraud +Jay Satiro +Arne Steen +Kjell Schubert +Olivier Mengué diff --git a/src/3rdparty/http-parser/LICENSE-MIT b/src/3rdparty/http-parser/LICENSE-MIT new file mode 100644 index 00000000..1ec0ab4e --- /dev/null +++ b/src/3rdparty/http-parser/LICENSE-MIT @@ -0,0 +1,19 @@ +Copyright Joyent, Inc. and other Node contributors. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to +deal in the Software without restriction, including without limitation the +rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +sell copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +IN THE SOFTWARE. diff --git a/src/3rdparty/http-parser/README.md b/src/3rdparty/http-parser/README.md new file mode 100644 index 00000000..b265d717 --- /dev/null +++ b/src/3rdparty/http-parser/README.md @@ -0,0 +1,246 @@ +HTTP Parser +=========== + +[![Build Status](https://api.travis-ci.org/nodejs/http-parser.svg?branch=master)](https://travis-ci.org/nodejs/http-parser) + +This is a parser for HTTP messages written in C. It parses both requests and +responses. The parser is designed to be used in performance HTTP +applications. It does not make any syscalls nor allocations, it does not +buffer data, it can be interrupted at anytime. Depending on your +architecture, it only requires about 40 bytes of data per message +stream (in a web server that is per connection). + +Features: + + * No dependencies + * Handles persistent streams (keep-alive). + * Decodes chunked encoding. + * Upgrade support + * Defends against buffer overflow attacks. + +The parser extracts the following information from HTTP messages: + + * Header fields and values + * Content-Length + * Request method + * Response status code + * Transfer-Encoding + * HTTP version + * Request URL + * Message body + + +Usage +----- + +One `http_parser` object is used per TCP connection. Initialize the struct +using `http_parser_init()` and set the callbacks. That might look something +like this for a request parser: +```c +http_parser_settings settings; +settings.on_url = my_url_callback; +settings.on_header_field = my_header_field_callback; +/* ... */ + +http_parser *parser = malloc(sizeof(http_parser)); +http_parser_init(parser, HTTP_REQUEST); +parser->data = my_socket; +``` + +When data is received on the socket execute the parser and check for errors. + +```c +size_t len = 80*1024, nparsed; +char buf[len]; +ssize_t recved; + +recved = recv(fd, buf, len, 0); + +if (recved < 0) { + /* Handle error. */ +} + +/* Start up / continue the parser. + * Note we pass recved==0 to signal that EOF has been received. + */ +nparsed = http_parser_execute(parser, &settings, buf, recved); + +if (parser->upgrade) { + /* handle new protocol */ +} else if (nparsed != recved) { + /* Handle error. Usually just close the connection. */ +} +``` + +`http_parser` needs to know where the end of the stream is. For example, sometimes +servers send responses without Content-Length and expect the client to +consume input (for the body) until EOF. To tell `http_parser` about EOF, give +`0` as the fourth parameter to `http_parser_execute()`. Callbacks and errors +can still be encountered during an EOF, so one must still be prepared +to receive them. + +Scalar valued message information such as `status_code`, `method`, and the +HTTP version are stored in the parser structure. This data is only +temporally stored in `http_parser` and gets reset on each new message. If +this information is needed later, copy it out of the structure during the +`headers_complete` callback. + +The parser decodes the transfer-encoding for both requests and responses +transparently. That is, a chunked encoding is decoded before being sent to +the on_body callback. + + +The Special Problem of Upgrade +------------------------------ + +`http_parser` supports upgrading the connection to a different protocol. An +increasingly common example of this is the WebSocket protocol which sends +a request like + + GET /demo HTTP/1.1 + Upgrade: WebSocket + Connection: Upgrade + Host: example.com + Origin: http://example.com + WebSocket-Protocol: sample + +followed by non-HTTP data. + +(See [RFC6455](https://tools.ietf.org/html/rfc6455) for more information the +WebSocket protocol.) + +To support this, the parser will treat this as a normal HTTP message without a +body, issuing both on_headers_complete and on_message_complete callbacks. However +http_parser_execute() will stop parsing at the end of the headers and return. + +The user is expected to check if `parser->upgrade` has been set to 1 after +`http_parser_execute()` returns. Non-HTTP data begins at the buffer supplied +offset by the return value of `http_parser_execute()`. + + +Callbacks +--------- + +During the `http_parser_execute()` call, the callbacks set in +`http_parser_settings` will be executed. The parser maintains state and +never looks behind, so buffering the data is not necessary. If you need to +save certain data for later usage, you can do that from the callbacks. + +There are two types of callbacks: + +* notification `typedef int (*http_cb) (http_parser*);` + Callbacks: on_message_begin, on_headers_complete, on_message_complete. +* data `typedef int (*http_data_cb) (http_parser*, const char *at, size_t length);` + Callbacks: (requests only) on_url, + (common) on_header_field, on_header_value, on_body; + +Callbacks must return 0 on success. Returning a non-zero value indicates +error to the parser, making it exit immediately. + +For cases where it is necessary to pass local information to/from a callback, +the `http_parser` object's `data` field can be used. +An example of such a case is when using threads to handle a socket connection, +parse a request, and then give a response over that socket. By instantiation +of a thread-local struct containing relevant data (e.g. accepted socket, +allocated memory for callbacks to write into, etc), a parser's callbacks are +able to communicate data between the scope of the thread and the scope of the +callback in a threadsafe manner. This allows `http_parser` to be used in +multi-threaded contexts. + +Example: +```c + typedef struct { + socket_t sock; + void* buffer; + int buf_len; + } custom_data_t; + + +int my_url_callback(http_parser* parser, const char *at, size_t length) { + /* access to thread local custom_data_t struct. + Use this access save parsed data for later use into thread local + buffer, or communicate over socket + */ + parser->data; + ... + return 0; +} + +... + +void http_parser_thread(socket_t sock) { + int nparsed = 0; + /* allocate memory for user data */ + custom_data_t *my_data = malloc(sizeof(custom_data_t)); + + /* some information for use by callbacks. + * achieves thread -> callback information flow */ + my_data->sock = sock; + + /* instantiate a thread-local parser */ + http_parser *parser = malloc(sizeof(http_parser)); + http_parser_init(parser, HTTP_REQUEST); /* initialise parser */ + /* this custom data reference is accessible through the reference to the + parser supplied to callback functions */ + parser->data = my_data; + + http_parser_settings settings; /* set up callbacks */ + settings.on_url = my_url_callback; + + /* execute parser */ + nparsed = http_parser_execute(parser, &settings, buf, recved); + + ... + /* parsed information copied from callback. + can now perform action on data copied into thread-local memory from callbacks. + achieves callback -> thread information flow */ + my_data->buffer; + ... +} + +``` + +In case you parse HTTP message in chunks (i.e. `read()` request line +from socket, parse, read half headers, parse, etc) your data callbacks +may be called more than once. `http_parser` guarantees that data pointer is only +valid for the lifetime of callback. You can also `read()` into a heap allocated +buffer to avoid copying memory around if this fits your application. + +Reading headers may be a tricky task if you read/parse headers partially. +Basically, you need to remember whether last header callback was field or value +and apply the following logic: + + (on_header_field and on_header_value shortened to on_h_*) + ------------------------ ------------ -------------------------------------------- + | State (prev. callback) | Callback | Description/action | + ------------------------ ------------ -------------------------------------------- + | nothing (first call) | on_h_field | Allocate new buffer and copy callback data | + | | | into it | + ------------------------ ------------ -------------------------------------------- + | value | on_h_field | New header started. | + | | | Copy current name,value buffers to headers | + | | | list and allocate new buffer for new name | + ------------------------ ------------ -------------------------------------------- + | field | on_h_field | Previous name continues. Reallocate name | + | | | buffer and append callback data to it | + ------------------------ ------------ -------------------------------------------- + | field | on_h_value | Value for current header started. Allocate | + | | | new buffer and copy callback data to it | + ------------------------ ------------ -------------------------------------------- + | value | on_h_value | Value continues. Reallocate value buffer | + | | | and append callback data to it | + ------------------------ ------------ -------------------------------------------- + + +Parsing URLs +------------ + +A simplistic zero-copy URL parser is provided as `http_parser_parse_url()`. +Users of this library may wish to use it to parse URLs constructed from +consecutive `on_url` callbacks. + +See examples of reading in headers: + +* [partial example](http://gist.github.com/155877) in C +* [from http-parser tests](http://github.com/joyent/http-parser/blob/37a0ff8/test.c#L403) in C +* [from Node library](http://github.com/joyent/node/blob/842eaf4/src/http.js#L284) in Javascript diff --git a/src/3rdparty/http-parser/http_parser.c b/src/3rdparty/http-parser/http_parser.c new file mode 100644 index 00000000..e2fc5d2e --- /dev/null +++ b/src/3rdparty/http-parser/http_parser.c @@ -0,0 +1,2501 @@ +/* Copyright Joyent, Inc. and other Node contributors. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to + * deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ +#include "http_parser.h" +#include +#include +#include +#include +#include + +static uint32_t max_header_size = HTTP_MAX_HEADER_SIZE; + +#ifndef ULLONG_MAX +# define ULLONG_MAX ((uint64_t) -1) /* 2^64-1 */ +#endif + +#ifndef MIN +# define MIN(a,b) ((a) < (b) ? (a) : (b)) +#endif + +#ifndef ARRAY_SIZE +# define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0])) +#endif + +#ifndef BIT_AT +# define BIT_AT(a, i) \ + (!!((unsigned int) (a)[(unsigned int) (i) >> 3] & \ + (1 << ((unsigned int) (i) & 7)))) +#endif + +#ifndef ELEM_AT +# define ELEM_AT(a, i, v) ((unsigned int) (i) < ARRAY_SIZE(a) ? (a)[(i)] : (v)) +#endif + +#define SET_ERRNO(e) \ +do { \ + parser->nread = nread; \ + parser->http_errno = (e); \ +} while(0) + +#define CURRENT_STATE() p_state +#define UPDATE_STATE(V) p_state = (enum state) (V); +#define RETURN(V) \ +do { \ + parser->nread = nread; \ + parser->state = CURRENT_STATE(); \ + return (V); \ +} while (0); +#define REEXECUTE() \ + goto reexecute; \ + + +#ifdef __GNUC__ +# define LIKELY(X) __builtin_expect(!!(X), 1) +# define UNLIKELY(X) __builtin_expect(!!(X), 0) +#else +# define LIKELY(X) (X) +# define UNLIKELY(X) (X) +#endif + + +/* Run the notify callback FOR, returning ER if it fails */ +#define CALLBACK_NOTIFY_(FOR, ER) \ +do { \ + assert(HTTP_PARSER_ERRNO(parser) == HPE_OK); \ + \ + if (LIKELY(settings->on_##FOR)) { \ + parser->state = CURRENT_STATE(); \ + if (UNLIKELY(0 != settings->on_##FOR(parser))) { \ + SET_ERRNO(HPE_CB_##FOR); \ + } \ + UPDATE_STATE(parser->state); \ + \ + /* We either errored above or got paused; get out */ \ + if (UNLIKELY(HTTP_PARSER_ERRNO(parser) != HPE_OK)) { \ + return (ER); \ + } \ + } \ +} while (0) + +/* Run the notify callback FOR and consume the current byte */ +#define CALLBACK_NOTIFY(FOR) CALLBACK_NOTIFY_(FOR, p - data + 1) + +/* Run the notify callback FOR and don't consume the current byte */ +#define CALLBACK_NOTIFY_NOADVANCE(FOR) CALLBACK_NOTIFY_(FOR, p - data) + +/* Run data callback FOR with LEN bytes, returning ER if it fails */ +#define CALLBACK_DATA_(FOR, LEN, ER) \ +do { \ + assert(HTTP_PARSER_ERRNO(parser) == HPE_OK); \ + \ + if (FOR##_mark) { \ + if (LIKELY(settings->on_##FOR)) { \ + parser->state = CURRENT_STATE(); \ + if (UNLIKELY(0 != \ + settings->on_##FOR(parser, FOR##_mark, (LEN)))) { \ + SET_ERRNO(HPE_CB_##FOR); \ + } \ + UPDATE_STATE(parser->state); \ + \ + /* We either errored above or got paused; get out */ \ + if (UNLIKELY(HTTP_PARSER_ERRNO(parser) != HPE_OK)) { \ + return (ER); \ + } \ + } \ + FOR##_mark = NULL; \ + } \ +} while (0) + +/* Run the data callback FOR and consume the current byte */ +#define CALLBACK_DATA(FOR) \ + CALLBACK_DATA_(FOR, p - FOR##_mark, p - data + 1) + +/* Run the data callback FOR and don't consume the current byte */ +#define CALLBACK_DATA_NOADVANCE(FOR) \ + CALLBACK_DATA_(FOR, p - FOR##_mark, p - data) + +/* Set the mark FOR; non-destructive if mark is already set */ +#define MARK(FOR) \ +do { \ + if (!FOR##_mark) { \ + FOR##_mark = p; \ + } \ +} while (0) + +/* Don't allow the total size of the HTTP headers (including the status + * line) to exceed max_header_size. This check is here to protect + * embedders against denial-of-service attacks where the attacker feeds + * us a never-ending header that the embedder keeps buffering. + * + * This check is arguably the responsibility of embedders but we're doing + * it on the embedder's behalf because most won't bother and this way we + * make the web a little safer. max_header_size is still far bigger + * than any reasonable request or response so this should never affect + * day-to-day operation. + */ +#define COUNT_HEADER_SIZE(V) \ +do { \ + nread += (uint32_t)(V); \ + if (UNLIKELY(nread > max_header_size)) { \ + SET_ERRNO(HPE_HEADER_OVERFLOW); \ + goto error; \ + } \ +} while (0) + + +#define PROXY_CONNECTION "proxy-connection" +#define CONNECTION "connection" +#define CONTENT_LENGTH "content-length" +#define TRANSFER_ENCODING "transfer-encoding" +#define UPGRADE "upgrade" +#define CHUNKED "chunked" +#define KEEP_ALIVE "keep-alive" +#define CLOSE "close" + + +static const char *method_strings[] = + { +#define XX(num, name, string) #string, + HTTP_METHOD_MAP(XX) +#undef XX + }; + + +/* Tokens as defined by rfc 2616. Also lowercases them. + * token = 1* + * separators = "(" | ")" | "<" | ">" | "@" + * | "," | ";" | ":" | "\" | <"> + * | "/" | "[" | "]" | "?" | "=" + * | "{" | "}" | SP | HT + */ +static const char tokens[256] = { +/* 0 nul 1 soh 2 stx 3 etx 4 eot 5 enq 6 ack 7 bel */ + 0, 0, 0, 0, 0, 0, 0, 0, +/* 8 bs 9 ht 10 nl 11 vt 12 np 13 cr 14 so 15 si */ + 0, 0, 0, 0, 0, 0, 0, 0, +/* 16 dle 17 dc1 18 dc2 19 dc3 20 dc4 21 nak 22 syn 23 etb */ + 0, 0, 0, 0, 0, 0, 0, 0, +/* 24 can 25 em 26 sub 27 esc 28 fs 29 gs 30 rs 31 us */ + 0, 0, 0, 0, 0, 0, 0, 0, +/* 32 sp 33 ! 34 " 35 # 36 $ 37 % 38 & 39 ' */ + ' ', '!', 0, '#', '$', '%', '&', '\'', +/* 40 ( 41 ) 42 * 43 + 44 , 45 - 46 . 47 / */ + 0, 0, '*', '+', 0, '-', '.', 0, +/* 48 0 49 1 50 2 51 3 52 4 53 5 54 6 55 7 */ + '0', '1', '2', '3', '4', '5', '6', '7', +/* 56 8 57 9 58 : 59 ; 60 < 61 = 62 > 63 ? */ + '8', '9', 0, 0, 0, 0, 0, 0, +/* 64 @ 65 A 66 B 67 C 68 D 69 E 70 F 71 G */ + 0, 'a', 'b', 'c', 'd', 'e', 'f', 'g', +/* 72 H 73 I 74 J 75 K 76 L 77 M 78 N 79 O */ + 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', +/* 80 P 81 Q 82 R 83 S 84 T 85 U 86 V 87 W */ + 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', +/* 88 X 89 Y 90 Z 91 [ 92 \ 93 ] 94 ^ 95 _ */ + 'x', 'y', 'z', 0, 0, 0, '^', '_', +/* 96 ` 97 a 98 b 99 c 100 d 101 e 102 f 103 g */ + '`', 'a', 'b', 'c', 'd', 'e', 'f', 'g', +/* 104 h 105 i 106 j 107 k 108 l 109 m 110 n 111 o */ + 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', +/* 112 p 113 q 114 r 115 s 116 t 117 u 118 v 119 w */ + 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', +/* 120 x 121 y 122 z 123 { 124 | 125 } 126 ~ 127 del */ + 'x', 'y', 'z', 0, '|', 0, '~', 0 }; + + +static const int8_t unhex[256] = + {-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1 + ,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1 + ,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1 + , 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,-1,-1,-1,-1,-1,-1 + ,-1,10,11,12,13,14,15,-1,-1,-1,-1,-1,-1,-1,-1,-1 + ,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1 + ,-1,10,11,12,13,14,15,-1,-1,-1,-1,-1,-1,-1,-1,-1 + ,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1 + }; + + +#if HTTP_PARSER_STRICT +# define T(v) 0 +#else +# define T(v) v +#endif + + +static const uint8_t normal_url_char[32] = { +/* 0 nul 1 soh 2 stx 3 etx 4 eot 5 enq 6 ack 7 bel */ + 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0, +/* 8 bs 9 ht 10 nl 11 vt 12 np 13 cr 14 so 15 si */ + 0 | T(2) | 0 | 0 | T(16) | 0 | 0 | 0, +/* 16 dle 17 dc1 18 dc2 19 dc3 20 dc4 21 nak 22 syn 23 etb */ + 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0, +/* 24 can 25 em 26 sub 27 esc 28 fs 29 gs 30 rs 31 us */ + 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0, +/* 32 sp 33 ! 34 " 35 # 36 $ 37 % 38 & 39 ' */ + 0 | 2 | 4 | 0 | 16 | 32 | 64 | 128, +/* 40 ( 41 ) 42 * 43 + 44 , 45 - 46 . 47 / */ + 1 | 2 | 4 | 8 | 16 | 32 | 64 | 128, +/* 48 0 49 1 50 2 51 3 52 4 53 5 54 6 55 7 */ + 1 | 2 | 4 | 8 | 16 | 32 | 64 | 128, +/* 56 8 57 9 58 : 59 ; 60 < 61 = 62 > 63 ? */ + 1 | 2 | 4 | 8 | 16 | 32 | 64 | 0, +/* 64 @ 65 A 66 B 67 C 68 D 69 E 70 F 71 G */ + 1 | 2 | 4 | 8 | 16 | 32 | 64 | 128, +/* 72 H 73 I 74 J 75 K 76 L 77 M 78 N 79 O */ + 1 | 2 | 4 | 8 | 16 | 32 | 64 | 128, +/* 80 P 81 Q 82 R 83 S 84 T 85 U 86 V 87 W */ + 1 | 2 | 4 | 8 | 16 | 32 | 64 | 128, +/* 88 X 89 Y 90 Z 91 [ 92 \ 93 ] 94 ^ 95 _ */ + 1 | 2 | 4 | 8 | 16 | 32 | 64 | 128, +/* 96 ` 97 a 98 b 99 c 100 d 101 e 102 f 103 g */ + 1 | 2 | 4 | 8 | 16 | 32 | 64 | 128, +/* 104 h 105 i 106 j 107 k 108 l 109 m 110 n 111 o */ + 1 | 2 | 4 | 8 | 16 | 32 | 64 | 128, +/* 112 p 113 q 114 r 115 s 116 t 117 u 118 v 119 w */ + 1 | 2 | 4 | 8 | 16 | 32 | 64 | 128, +/* 120 x 121 y 122 z 123 { 124 | 125 } 126 ~ 127 del */ + 1 | 2 | 4 | 8 | 16 | 32 | 64 | 0, }; + +#undef T + +enum state + { s_dead = 1 /* important that this is > 0 */ + + , s_start_req_or_res + , s_res_or_resp_H + , s_start_res + , s_res_H + , s_res_HT + , s_res_HTT + , s_res_HTTP + , s_res_http_major + , s_res_http_dot + , s_res_http_minor + , s_res_http_end + , s_res_first_status_code + , s_res_status_code + , s_res_status_start + , s_res_status + , s_res_line_almost_done + + , s_start_req + + , s_req_method + , s_req_spaces_before_url + , s_req_schema + , s_req_schema_slash + , s_req_schema_slash_slash + , s_req_server_start + , s_req_server + , s_req_server_with_at + , s_req_path + , s_req_query_string_start + , s_req_query_string + , s_req_fragment_start + , s_req_fragment + , s_req_http_start + , s_req_http_H + , s_req_http_HT + , s_req_http_HTT + , s_req_http_HTTP + , s_req_http_I + , s_req_http_IC + , s_req_http_major + , s_req_http_dot + , s_req_http_minor + , s_req_http_end + , s_req_line_almost_done + + , s_header_field_start + , s_header_field + , s_header_value_discard_ws + , s_header_value_discard_ws_almost_done + , s_header_value_discard_lws + , s_header_value_start + , s_header_value + , s_header_value_lws + + , s_header_almost_done + + , s_chunk_size_start + , s_chunk_size + , s_chunk_parameters + , s_chunk_size_almost_done + + , s_headers_almost_done + , s_headers_done + + /* Important: 's_headers_done' must be the last 'header' state. All + * states beyond this must be 'body' states. It is used for overflow + * checking. See the PARSING_HEADER() macro. + */ + + , s_chunk_data + , s_chunk_data_almost_done + , s_chunk_data_done + + , s_body_identity + , s_body_identity_eof + + , s_message_done + }; + + +#define PARSING_HEADER(state) (state <= s_headers_done) + + +enum header_states + { h_general = 0 + , h_C + , h_CO + , h_CON + + , h_matching_connection + , h_matching_proxy_connection + , h_matching_content_length + , h_matching_transfer_encoding + , h_matching_upgrade + + , h_connection + , h_content_length + , h_content_length_num + , h_content_length_ws + , h_transfer_encoding + , h_upgrade + + , h_matching_transfer_encoding_chunked + , h_matching_connection_token_start + , h_matching_connection_keep_alive + , h_matching_connection_close + , h_matching_connection_upgrade + , h_matching_connection_token + + , h_transfer_encoding_chunked + , h_connection_keep_alive + , h_connection_close + , h_connection_upgrade + }; + +enum http_host_state + { + s_http_host_dead = 1 + , s_http_userinfo_start + , s_http_userinfo + , s_http_host_start + , s_http_host_v6_start + , s_http_host + , s_http_host_v6 + , s_http_host_v6_end + , s_http_host_v6_zone_start + , s_http_host_v6_zone + , s_http_host_port_start + , s_http_host_port +}; + +/* Macros for character classes; depends on strict-mode */ +#define CR '\r' +#define LF '\n' +#define LOWER(c) (unsigned char)(c | 0x20) +#define IS_ALPHA(c) (LOWER(c) >= 'a' && LOWER(c) <= 'z') +#define IS_NUM(c) ((c) >= '0' && (c) <= '9') +#define IS_ALPHANUM(c) (IS_ALPHA(c) || IS_NUM(c)) +#define IS_HEX(c) (IS_NUM(c) || (LOWER(c) >= 'a' && LOWER(c) <= 'f')) +#define IS_MARK(c) ((c) == '-' || (c) == '_' || (c) == '.' || \ + (c) == '!' || (c) == '~' || (c) == '*' || (c) == '\'' || (c) == '(' || \ + (c) == ')') +#define IS_USERINFO_CHAR(c) (IS_ALPHANUM(c) || IS_MARK(c) || (c) == '%' || \ + (c) == ';' || (c) == ':' || (c) == '&' || (c) == '=' || (c) == '+' || \ + (c) == '$' || (c) == ',') + +#define STRICT_TOKEN(c) ((c == ' ') ? 0 : tokens[(unsigned char)c]) + +#if HTTP_PARSER_STRICT +#define TOKEN(c) STRICT_TOKEN(c) +#define IS_URL_CHAR(c) (BIT_AT(normal_url_char, (unsigned char)c)) +#define IS_HOST_CHAR(c) (IS_ALPHANUM(c) || (c) == '.' || (c) == '-') +#else +#define TOKEN(c) tokens[(unsigned char)c] +#define IS_URL_CHAR(c) \ + (BIT_AT(normal_url_char, (unsigned char)c) || ((c) & 0x80)) +#define IS_HOST_CHAR(c) \ + (IS_ALPHANUM(c) || (c) == '.' || (c) == '-' || (c) == '_') +#endif + +/** + * Verify that a char is a valid visible (printable) US-ASCII + * character or %x80-FF + **/ +#define IS_HEADER_CHAR(ch) \ + (ch == CR || ch == LF || ch == 9 || ((unsigned char)ch > 31 && ch != 127)) + +#define start_state (parser->type == HTTP_REQUEST ? s_start_req : s_start_res) + + +#if HTTP_PARSER_STRICT +# define STRICT_CHECK(cond) \ +do { \ + if (cond) { \ + SET_ERRNO(HPE_STRICT); \ + goto error; \ + } \ +} while (0) +# define NEW_MESSAGE() (http_should_keep_alive(parser) ? start_state : s_dead) +#else +# define STRICT_CHECK(cond) +# define NEW_MESSAGE() start_state +#endif + + +/* Map errno values to strings for human-readable output */ +#define HTTP_STRERROR_GEN(n, s) { "HPE_" #n, s }, +static struct { + const char *name; + const char *description; +} http_strerror_tab[] = { + HTTP_ERRNO_MAP(HTTP_STRERROR_GEN) +}; +#undef HTTP_STRERROR_GEN + +int http_message_needs_eof(const http_parser *parser); + +/* Our URL parser. + * + * This is designed to be shared by http_parser_execute() for URL validation, + * hence it has a state transition + byte-for-byte interface. In addition, it + * is meant to be embedded in http_parser_parse_url(), which does the dirty + * work of turning state transitions URL components for its API. + * + * This function should only be invoked with non-space characters. It is + * assumed that the caller cares about (and can detect) the transition between + * URL and non-URL states by looking for these. + */ +static enum state +parse_url_char(enum state s, const char ch) +{ + if (ch == ' ' || ch == '\r' || ch == '\n') { + return s_dead; + } + +#if HTTP_PARSER_STRICT + if (ch == '\t' || ch == '\f') { + return s_dead; + } +#endif + + switch (s) { + case s_req_spaces_before_url: + /* Proxied requests are followed by scheme of an absolute URI (alpha). + * All methods except CONNECT are followed by '/' or '*'. + */ + + if (ch == '/' || ch == '*') { + return s_req_path; + } + + if (IS_ALPHA(ch)) { + return s_req_schema; + } + + break; + + case s_req_schema: + if (IS_ALPHA(ch)) { + return s; + } + + if (ch == ':') { + return s_req_schema_slash; + } + + break; + + case s_req_schema_slash: + if (ch == '/') { + return s_req_schema_slash_slash; + } + + break; + + case s_req_schema_slash_slash: + if (ch == '/') { + return s_req_server_start; + } + + break; + + case s_req_server_with_at: + if (ch == '@') { + return s_dead; + } + + /* fall through */ + case s_req_server_start: + case s_req_server: + if (ch == '/') { + return s_req_path; + } + + if (ch == '?') { + return s_req_query_string_start; + } + + if (ch == '@') { + return s_req_server_with_at; + } + + if (IS_USERINFO_CHAR(ch) || ch == '[' || ch == ']') { + return s_req_server; + } + + break; + + case s_req_path: + if (IS_URL_CHAR(ch)) { + return s; + } + + switch (ch) { + case '?': + return s_req_query_string_start; + + case '#': + return s_req_fragment_start; + } + + break; + + case s_req_query_string_start: + case s_req_query_string: + if (IS_URL_CHAR(ch)) { + return s_req_query_string; + } + + switch (ch) { + case '?': + /* allow extra '?' in query string */ + return s_req_query_string; + + case '#': + return s_req_fragment_start; + } + + break; + + case s_req_fragment_start: + if (IS_URL_CHAR(ch)) { + return s_req_fragment; + } + + switch (ch) { + case '?': + return s_req_fragment; + + case '#': + return s; + } + + break; + + case s_req_fragment: + if (IS_URL_CHAR(ch)) { + return s; + } + + switch (ch) { + case '?': + case '#': + return s; + } + + break; + + default: + break; + } + + /* We should never fall out of the switch above unless there's an error */ + return s_dead; +} + +size_t http_parser_execute (http_parser *parser, + const http_parser_settings *settings, + const char *data, + size_t len) +{ + char c, ch; + int8_t unhex_val; + const char *p = data; + const char *header_field_mark = 0; + const char *header_value_mark = 0; + const char *url_mark = 0; + const char *body_mark = 0; + const char *status_mark = 0; + enum state p_state = (enum state) parser->state; + const unsigned int lenient = parser->lenient_http_headers; + uint32_t nread = parser->nread; + + /* We're in an error state. Don't bother doing anything. */ + if (HTTP_PARSER_ERRNO(parser) != HPE_OK) { + return 0; + } + + if (len == 0) { + switch (CURRENT_STATE()) { + case s_body_identity_eof: + /* Use of CALLBACK_NOTIFY() here would erroneously return 1 byte read if + * we got paused. + */ + CALLBACK_NOTIFY_NOADVANCE(message_complete); + return 0; + + case s_dead: + case s_start_req_or_res: + case s_start_res: + case s_start_req: + return 0; + + default: + SET_ERRNO(HPE_INVALID_EOF_STATE); + return 1; + } + } + + + if (CURRENT_STATE() == s_header_field) + header_field_mark = data; + if (CURRENT_STATE() == s_header_value) + header_value_mark = data; + switch (CURRENT_STATE()) { + case s_req_path: + case s_req_schema: + case s_req_schema_slash: + case s_req_schema_slash_slash: + case s_req_server_start: + case s_req_server: + case s_req_server_with_at: + case s_req_query_string_start: + case s_req_query_string: + case s_req_fragment_start: + case s_req_fragment: + url_mark = data; + break; + case s_res_status: + status_mark = data; + break; + default: + break; + } + + for (p=data; p != data + len; p++) { + ch = *p; + + if (PARSING_HEADER(CURRENT_STATE())) + COUNT_HEADER_SIZE(1); + +reexecute: + switch (CURRENT_STATE()) { + + case s_dead: + /* this state is used after a 'Connection: close' message + * the parser will error out if it reads another message + */ + if (LIKELY(ch == CR || ch == LF)) + break; + + SET_ERRNO(HPE_CLOSED_CONNECTION); + goto error; + + case s_start_req_or_res: + { + if (ch == CR || ch == LF) + break; + parser->flags = 0; + parser->content_length = ULLONG_MAX; + + if (ch == 'H') { + UPDATE_STATE(s_res_or_resp_H); + + CALLBACK_NOTIFY(message_begin); + } else { + parser->type = HTTP_REQUEST; + UPDATE_STATE(s_start_req); + REEXECUTE(); + } + + break; + } + + case s_res_or_resp_H: + if (ch == 'T') { + parser->type = HTTP_RESPONSE; + UPDATE_STATE(s_res_HT); + } else { + if (UNLIKELY(ch != 'E')) { + SET_ERRNO(HPE_INVALID_CONSTANT); + goto error; + } + + parser->type = HTTP_REQUEST; + parser->method = HTTP_HEAD; + parser->index = 2; + UPDATE_STATE(s_req_method); + } + break; + + case s_start_res: + { + if (ch == CR || ch == LF) + break; + parser->flags = 0; + parser->content_length = ULLONG_MAX; + + if (ch == 'H') { + UPDATE_STATE(s_res_H); + } else { + SET_ERRNO(HPE_INVALID_CONSTANT); + goto error; + } + + CALLBACK_NOTIFY(message_begin); + break; + } + + case s_res_H: + STRICT_CHECK(ch != 'T'); + UPDATE_STATE(s_res_HT); + break; + + case s_res_HT: + STRICT_CHECK(ch != 'T'); + UPDATE_STATE(s_res_HTT); + break; + + case s_res_HTT: + STRICT_CHECK(ch != 'P'); + UPDATE_STATE(s_res_HTTP); + break; + + case s_res_HTTP: + STRICT_CHECK(ch != '/'); + UPDATE_STATE(s_res_http_major); + break; + + case s_res_http_major: + if (UNLIKELY(!IS_NUM(ch))) { + SET_ERRNO(HPE_INVALID_VERSION); + goto error; + } + + parser->http_major = ch - '0'; + UPDATE_STATE(s_res_http_dot); + break; + + case s_res_http_dot: + { + if (UNLIKELY(ch != '.')) { + SET_ERRNO(HPE_INVALID_VERSION); + goto error; + } + + UPDATE_STATE(s_res_http_minor); + break; + } + + case s_res_http_minor: + if (UNLIKELY(!IS_NUM(ch))) { + SET_ERRNO(HPE_INVALID_VERSION); + goto error; + } + + parser->http_minor = ch - '0'; + UPDATE_STATE(s_res_http_end); + break; + + case s_res_http_end: + { + if (UNLIKELY(ch != ' ')) { + SET_ERRNO(HPE_INVALID_VERSION); + goto error; + } + + UPDATE_STATE(s_res_first_status_code); + break; + } + + case s_res_first_status_code: + { + if (!IS_NUM(ch)) { + if (ch == ' ') { + break; + } + + SET_ERRNO(HPE_INVALID_STATUS); + goto error; + } + parser->status_code = ch - '0'; + UPDATE_STATE(s_res_status_code); + break; + } + + case s_res_status_code: + { + if (!IS_NUM(ch)) { + switch (ch) { + case ' ': + UPDATE_STATE(s_res_status_start); + break; + case CR: + case LF: + UPDATE_STATE(s_res_status_start); + REEXECUTE(); + break; + default: + SET_ERRNO(HPE_INVALID_STATUS); + goto error; + } + break; + } + + parser->status_code *= 10; + parser->status_code += ch - '0'; + + if (UNLIKELY(parser->status_code > 999)) { + SET_ERRNO(HPE_INVALID_STATUS); + goto error; + } + + break; + } + + case s_res_status_start: + { + MARK(status); + UPDATE_STATE(s_res_status); + parser->index = 0; + + if (ch == CR || ch == LF) + REEXECUTE(); + + break; + } + + case s_res_status: + if (ch == CR) { + UPDATE_STATE(s_res_line_almost_done); + CALLBACK_DATA(status); + break; + } + + if (ch == LF) { + UPDATE_STATE(s_header_field_start); + CALLBACK_DATA(status); + break; + } + + break; + + case s_res_line_almost_done: + STRICT_CHECK(ch != LF); + UPDATE_STATE(s_header_field_start); + break; + + case s_start_req: + { + if (ch == CR || ch == LF) + break; + parser->flags = 0; + parser->content_length = ULLONG_MAX; + + if (UNLIKELY(!IS_ALPHA(ch))) { + SET_ERRNO(HPE_INVALID_METHOD); + goto error; + } + + parser->method = (enum http_method) 0; + parser->index = 1; + switch (ch) { + case 'A': parser->method = HTTP_ACL; break; + case 'B': parser->method = HTTP_BIND; break; + case 'C': parser->method = HTTP_CONNECT; /* or COPY, CHECKOUT */ break; + case 'D': parser->method = HTTP_DELETE; break; + case 'G': parser->method = HTTP_GET; break; + case 'H': parser->method = HTTP_HEAD; break; + case 'L': parser->method = HTTP_LOCK; /* or LINK */ break; + case 'M': parser->method = HTTP_MKCOL; /* or MOVE, MKACTIVITY, MERGE, M-SEARCH, MKCALENDAR */ break; + case 'N': parser->method = HTTP_NOTIFY; break; + case 'O': parser->method = HTTP_OPTIONS; break; + case 'P': parser->method = HTTP_POST; + /* or PROPFIND|PROPPATCH|PUT|PATCH|PURGE */ + break; + case 'R': parser->method = HTTP_REPORT; /* or REBIND */ break; + case 'S': parser->method = HTTP_SUBSCRIBE; /* or SEARCH, SOURCE */ break; + case 'T': parser->method = HTTP_TRACE; break; + case 'U': parser->method = HTTP_UNLOCK; /* or UNSUBSCRIBE, UNBIND, UNLINK */ break; + default: + SET_ERRNO(HPE_INVALID_METHOD); + goto error; + } + UPDATE_STATE(s_req_method); + + CALLBACK_NOTIFY(message_begin); + + break; + } + + case s_req_method: + { + const char *matcher; + if (UNLIKELY(ch == '\0')) { + SET_ERRNO(HPE_INVALID_METHOD); + goto error; + } + + matcher = method_strings[parser->method]; + if (ch == ' ' && matcher[parser->index] == '\0') { + UPDATE_STATE(s_req_spaces_before_url); + } else if (ch == matcher[parser->index]) { + ; /* nada */ + } else if ((ch >= 'A' && ch <= 'Z') || ch == '-') { + + switch (parser->method << 16 | parser->index << 8 | ch) { +#define XX(meth, pos, ch, new_meth) \ + case (HTTP_##meth << 16 | pos << 8 | ch): \ + parser->method = HTTP_##new_meth; break; + + XX(POST, 1, 'U', PUT) + XX(POST, 1, 'A', PATCH) + XX(POST, 1, 'R', PROPFIND) + XX(PUT, 2, 'R', PURGE) + XX(CONNECT, 1, 'H', CHECKOUT) + XX(CONNECT, 2, 'P', COPY) + XX(MKCOL, 1, 'O', MOVE) + XX(MKCOL, 1, 'E', MERGE) + XX(MKCOL, 1, '-', MSEARCH) + XX(MKCOL, 2, 'A', MKACTIVITY) + XX(MKCOL, 3, 'A', MKCALENDAR) + XX(SUBSCRIBE, 1, 'E', SEARCH) + XX(SUBSCRIBE, 1, 'O', SOURCE) + XX(REPORT, 2, 'B', REBIND) + XX(PROPFIND, 4, 'P', PROPPATCH) + XX(LOCK, 1, 'I', LINK) + XX(UNLOCK, 2, 'S', UNSUBSCRIBE) + XX(UNLOCK, 2, 'B', UNBIND) + XX(UNLOCK, 3, 'I', UNLINK) +#undef XX + default: + SET_ERRNO(HPE_INVALID_METHOD); + goto error; + } + } else { + SET_ERRNO(HPE_INVALID_METHOD); + goto error; + } + + ++parser->index; + break; + } + + case s_req_spaces_before_url: + { + if (ch == ' ') break; + + MARK(url); + if (parser->method == HTTP_CONNECT) { + UPDATE_STATE(s_req_server_start); + } + + UPDATE_STATE(parse_url_char(CURRENT_STATE(), ch)); + if (UNLIKELY(CURRENT_STATE() == s_dead)) { + SET_ERRNO(HPE_INVALID_URL); + goto error; + } + + break; + } + + case s_req_schema: + case s_req_schema_slash: + case s_req_schema_slash_slash: + case s_req_server_start: + { + switch (ch) { + /* No whitespace allowed here */ + case ' ': + case CR: + case LF: + SET_ERRNO(HPE_INVALID_URL); + goto error; + default: + UPDATE_STATE(parse_url_char(CURRENT_STATE(), ch)); + if (UNLIKELY(CURRENT_STATE() == s_dead)) { + SET_ERRNO(HPE_INVALID_URL); + goto error; + } + } + + break; + } + + case s_req_server: + case s_req_server_with_at: + case s_req_path: + case s_req_query_string_start: + case s_req_query_string: + case s_req_fragment_start: + case s_req_fragment: + { + switch (ch) { + case ' ': + UPDATE_STATE(s_req_http_start); + CALLBACK_DATA(url); + break; + case CR: + case LF: + parser->http_major = 0; + parser->http_minor = 9; + UPDATE_STATE((ch == CR) ? + s_req_line_almost_done : + s_header_field_start); + CALLBACK_DATA(url); + break; + default: + UPDATE_STATE(parse_url_char(CURRENT_STATE(), ch)); + if (UNLIKELY(CURRENT_STATE() == s_dead)) { + SET_ERRNO(HPE_INVALID_URL); + goto error; + } + } + break; + } + + case s_req_http_start: + switch (ch) { + case ' ': + break; + case 'H': + UPDATE_STATE(s_req_http_H); + break; + case 'I': + if (parser->method == HTTP_SOURCE) { + UPDATE_STATE(s_req_http_I); + break; + } + /* fall through */ + default: + SET_ERRNO(HPE_INVALID_CONSTANT); + goto error; + } + break; + + case s_req_http_H: + STRICT_CHECK(ch != 'T'); + UPDATE_STATE(s_req_http_HT); + break; + + case s_req_http_HT: + STRICT_CHECK(ch != 'T'); + UPDATE_STATE(s_req_http_HTT); + break; + + case s_req_http_HTT: + STRICT_CHECK(ch != 'P'); + UPDATE_STATE(s_req_http_HTTP); + break; + + case s_req_http_I: + STRICT_CHECK(ch != 'C'); + UPDATE_STATE(s_req_http_IC); + break; + + case s_req_http_IC: + STRICT_CHECK(ch != 'E'); + UPDATE_STATE(s_req_http_HTTP); /* Treat "ICE" as "HTTP". */ + break; + + case s_req_http_HTTP: + STRICT_CHECK(ch != '/'); + UPDATE_STATE(s_req_http_major); + break; + + case s_req_http_major: + if (UNLIKELY(!IS_NUM(ch))) { + SET_ERRNO(HPE_INVALID_VERSION); + goto error; + } + + parser->http_major = ch - '0'; + UPDATE_STATE(s_req_http_dot); + break; + + case s_req_http_dot: + { + if (UNLIKELY(ch != '.')) { + SET_ERRNO(HPE_INVALID_VERSION); + goto error; + } + + UPDATE_STATE(s_req_http_minor); + break; + } + + case s_req_http_minor: + if (UNLIKELY(!IS_NUM(ch))) { + SET_ERRNO(HPE_INVALID_VERSION); + goto error; + } + + parser->http_minor = ch - '0'; + UPDATE_STATE(s_req_http_end); + break; + + case s_req_http_end: + { + if (ch == CR) { + UPDATE_STATE(s_req_line_almost_done); + break; + } + + if (ch == LF) { + UPDATE_STATE(s_header_field_start); + break; + } + + SET_ERRNO(HPE_INVALID_VERSION); + goto error; + break; + } + + /* end of request line */ + case s_req_line_almost_done: + { + if (UNLIKELY(ch != LF)) { + SET_ERRNO(HPE_LF_EXPECTED); + goto error; + } + + UPDATE_STATE(s_header_field_start); + break; + } + + case s_header_field_start: + { + if (ch == CR) { + UPDATE_STATE(s_headers_almost_done); + break; + } + + if (ch == LF) { + /* they might be just sending \n instead of \r\n so this would be + * the second \n to denote the end of headers*/ + UPDATE_STATE(s_headers_almost_done); + REEXECUTE(); + } + + c = TOKEN(ch); + + if (UNLIKELY(!c)) { + SET_ERRNO(HPE_INVALID_HEADER_TOKEN); + goto error; + } + + MARK(header_field); + + parser->index = 0; + UPDATE_STATE(s_header_field); + + switch (c) { + case 'c': + parser->header_state = h_C; + break; + + case 'p': + parser->header_state = h_matching_proxy_connection; + break; + + case 't': + parser->header_state = h_matching_transfer_encoding; + break; + + case 'u': + parser->header_state = h_matching_upgrade; + break; + + default: + parser->header_state = h_general; + break; + } + break; + } + + case s_header_field: + { + const char* start = p; + for (; p != data + len; p++) { + ch = *p; + c = TOKEN(ch); + + if (!c) + break; + + switch (parser->header_state) { + case h_general: { + size_t limit = data + len - p; + limit = MIN(limit, max_header_size); + while (p+1 < data + limit && TOKEN(p[1])) { + p++; + } + break; + } + + case h_C: + parser->index++; + parser->header_state = (c == 'o' ? h_CO : h_general); + break; + + case h_CO: + parser->index++; + parser->header_state = (c == 'n' ? h_CON : h_general); + break; + + case h_CON: + parser->index++; + switch (c) { + case 'n': + parser->header_state = h_matching_connection; + break; + case 't': + parser->header_state = h_matching_content_length; + break; + default: + parser->header_state = h_general; + break; + } + break; + + /* connection */ + + case h_matching_connection: + parser->index++; + if (parser->index > sizeof(CONNECTION)-1 + || c != CONNECTION[parser->index]) { + parser->header_state = h_general; + } else if (parser->index == sizeof(CONNECTION)-2) { + parser->header_state = h_connection; + } + break; + + /* proxy-connection */ + + case h_matching_proxy_connection: + parser->index++; + if (parser->index > sizeof(PROXY_CONNECTION)-1 + || c != PROXY_CONNECTION[parser->index]) { + parser->header_state = h_general; + } else if (parser->index == sizeof(PROXY_CONNECTION)-2) { + parser->header_state = h_connection; + } + break; + + /* content-length */ + + case h_matching_content_length: + parser->index++; + if (parser->index > sizeof(CONTENT_LENGTH)-1 + || c != CONTENT_LENGTH[parser->index]) { + parser->header_state = h_general; + } else if (parser->index == sizeof(CONTENT_LENGTH)-2) { + parser->header_state = h_content_length; + } + break; + + /* transfer-encoding */ + + case h_matching_transfer_encoding: + parser->index++; + if (parser->index > sizeof(TRANSFER_ENCODING)-1 + || c != TRANSFER_ENCODING[parser->index]) { + parser->header_state = h_general; + } else if (parser->index == sizeof(TRANSFER_ENCODING)-2) { + parser->header_state = h_transfer_encoding; + } + break; + + /* upgrade */ + + case h_matching_upgrade: + parser->index++; + if (parser->index > sizeof(UPGRADE)-1 + || c != UPGRADE[parser->index]) { + parser->header_state = h_general; + } else if (parser->index == sizeof(UPGRADE)-2) { + parser->header_state = h_upgrade; + } + break; + + case h_connection: + case h_content_length: + case h_transfer_encoding: + case h_upgrade: + if (ch != ' ') parser->header_state = h_general; + break; + + default: + assert(0 && "Unknown header_state"); + break; + } + } + + if (p == data + len) { + --p; + COUNT_HEADER_SIZE(p - start); + break; + } + + COUNT_HEADER_SIZE(p - start); + + if (ch == ':') { + UPDATE_STATE(s_header_value_discard_ws); + CALLBACK_DATA(header_field); + break; + } + + SET_ERRNO(HPE_INVALID_HEADER_TOKEN); + goto error; + } + + case s_header_value_discard_ws: + if (ch == ' ' || ch == '\t') break; + + if (ch == CR) { + UPDATE_STATE(s_header_value_discard_ws_almost_done); + break; + } + + if (ch == LF) { + UPDATE_STATE(s_header_value_discard_lws); + break; + } + + /* fall through */ + + case s_header_value_start: + { + MARK(header_value); + + UPDATE_STATE(s_header_value); + parser->index = 0; + + c = LOWER(ch); + + switch (parser->header_state) { + case h_upgrade: + parser->flags |= F_UPGRADE; + parser->header_state = h_general; + break; + + case h_transfer_encoding: + /* looking for 'Transfer-Encoding: chunked' */ + if ('c' == c) { + parser->header_state = h_matching_transfer_encoding_chunked; + } else { + parser->header_state = h_general; + } + break; + + case h_content_length: + if (UNLIKELY(!IS_NUM(ch))) { + SET_ERRNO(HPE_INVALID_CONTENT_LENGTH); + goto error; + } + + if (parser->flags & F_CONTENTLENGTH) { + SET_ERRNO(HPE_UNEXPECTED_CONTENT_LENGTH); + goto error; + } + + parser->flags |= F_CONTENTLENGTH; + parser->content_length = ch - '0'; + parser->header_state = h_content_length_num; + break; + + /* when obsolete line folding is encountered for content length + * continue to the s_header_value state */ + case h_content_length_ws: + break; + + case h_connection: + /* looking for 'Connection: keep-alive' */ + if (c == 'k') { + parser->header_state = h_matching_connection_keep_alive; + /* looking for 'Connection: close' */ + } else if (c == 'c') { + parser->header_state = h_matching_connection_close; + } else if (c == 'u') { + parser->header_state = h_matching_connection_upgrade; + } else { + parser->header_state = h_matching_connection_token; + } + break; + + /* Multi-value `Connection` header */ + case h_matching_connection_token_start: + break; + + default: + parser->header_state = h_general; + break; + } + break; + } + + case s_header_value: + { + const char* start = p; + enum header_states h_state = (enum header_states) parser->header_state; + for (; p != data + len; p++) { + ch = *p; + if (ch == CR) { + UPDATE_STATE(s_header_almost_done); + parser->header_state = h_state; + CALLBACK_DATA(header_value); + break; + } + + if (ch == LF) { + UPDATE_STATE(s_header_almost_done); + COUNT_HEADER_SIZE(p - start); + parser->header_state = h_state; + CALLBACK_DATA_NOADVANCE(header_value); + REEXECUTE(); + } + + if (!lenient && !IS_HEADER_CHAR(ch)) { + SET_ERRNO(HPE_INVALID_HEADER_TOKEN); + goto error; + } + + c = LOWER(ch); + + switch (h_state) { + case h_general: + { + const char* p_cr; + const char* p_lf; + size_t limit = data + len - p; + + limit = MIN(limit, max_header_size); + + p_cr = (const char*) memchr(p, CR, limit); + p_lf = (const char*) memchr(p, LF, limit); + if (p_cr != NULL) { + if (p_lf != NULL && p_cr >= p_lf) + p = p_lf; + else + p = p_cr; + } else if (UNLIKELY(p_lf != NULL)) { + p = p_lf; + } else { + p = data + len; + } + --p; + break; + } + + case h_connection: + case h_transfer_encoding: + assert(0 && "Shouldn't get here."); + break; + + case h_content_length: + if (ch == ' ') break; + h_state = h_content_length_num; + /* fall through */ + + case h_content_length_num: + { + uint64_t t; + + if (ch == ' ') { + h_state = h_content_length_ws; + break; + } + + if (UNLIKELY(!IS_NUM(ch))) { + SET_ERRNO(HPE_INVALID_CONTENT_LENGTH); + parser->header_state = h_state; + goto error; + } + + t = parser->content_length; + t *= 10; + t += ch - '0'; + + /* Overflow? Test against a conservative limit for simplicity. */ + if (UNLIKELY((ULLONG_MAX - 10) / 10 < parser->content_length)) { + SET_ERRNO(HPE_INVALID_CONTENT_LENGTH); + parser->header_state = h_state; + goto error; + } + + parser->content_length = t; + break; + } + + case h_content_length_ws: + if (ch == ' ') break; + SET_ERRNO(HPE_INVALID_CONTENT_LENGTH); + parser->header_state = h_state; + goto error; + + /* Transfer-Encoding: chunked */ + case h_matching_transfer_encoding_chunked: + parser->index++; + if (parser->index > sizeof(CHUNKED)-1 + || c != CHUNKED[parser->index]) { + h_state = h_general; + } else if (parser->index == sizeof(CHUNKED)-2) { + h_state = h_transfer_encoding_chunked; + } + break; + + case h_matching_connection_token_start: + /* looking for 'Connection: keep-alive' */ + if (c == 'k') { + h_state = h_matching_connection_keep_alive; + /* looking for 'Connection: close' */ + } else if (c == 'c') { + h_state = h_matching_connection_close; + } else if (c == 'u') { + h_state = h_matching_connection_upgrade; + } else if (STRICT_TOKEN(c)) { + h_state = h_matching_connection_token; + } else if (c == ' ' || c == '\t') { + /* Skip lws */ + } else { + h_state = h_general; + } + break; + + /* looking for 'Connection: keep-alive' */ + case h_matching_connection_keep_alive: + parser->index++; + if (parser->index > sizeof(KEEP_ALIVE)-1 + || c != KEEP_ALIVE[parser->index]) { + h_state = h_matching_connection_token; + } else if (parser->index == sizeof(KEEP_ALIVE)-2) { + h_state = h_connection_keep_alive; + } + break; + + /* looking for 'Connection: close' */ + case h_matching_connection_close: + parser->index++; + if (parser->index > sizeof(CLOSE)-1 || c != CLOSE[parser->index]) { + h_state = h_matching_connection_token; + } else if (parser->index == sizeof(CLOSE)-2) { + h_state = h_connection_close; + } + break; + + /* looking for 'Connection: upgrade' */ + case h_matching_connection_upgrade: + parser->index++; + if (parser->index > sizeof(UPGRADE) - 1 || + c != UPGRADE[parser->index]) { + h_state = h_matching_connection_token; + } else if (parser->index == sizeof(UPGRADE)-2) { + h_state = h_connection_upgrade; + } + break; + + case h_matching_connection_token: + if (ch == ',') { + h_state = h_matching_connection_token_start; + parser->index = 0; + } + break; + + case h_transfer_encoding_chunked: + if (ch != ' ') h_state = h_general; + break; + + case h_connection_keep_alive: + case h_connection_close: + case h_connection_upgrade: + if (ch == ',') { + if (h_state == h_connection_keep_alive) { + parser->flags |= F_CONNECTION_KEEP_ALIVE; + } else if (h_state == h_connection_close) { + parser->flags |= F_CONNECTION_CLOSE; + } else if (h_state == h_connection_upgrade) { + parser->flags |= F_CONNECTION_UPGRADE; + } + h_state = h_matching_connection_token_start; + parser->index = 0; + } else if (ch != ' ') { + h_state = h_matching_connection_token; + } + break; + + default: + UPDATE_STATE(s_header_value); + h_state = h_general; + break; + } + } + parser->header_state = h_state; + + if (p == data + len) + --p; + + COUNT_HEADER_SIZE(p - start); + break; + } + + case s_header_almost_done: + { + if (UNLIKELY(ch != LF)) { + SET_ERRNO(HPE_LF_EXPECTED); + goto error; + } + + UPDATE_STATE(s_header_value_lws); + break; + } + + case s_header_value_lws: + { + if (ch == ' ' || ch == '\t') { + if (parser->header_state == h_content_length_num) { + /* treat obsolete line folding as space */ + parser->header_state = h_content_length_ws; + } + UPDATE_STATE(s_header_value_start); + REEXECUTE(); + } + + /* finished the header */ + switch (parser->header_state) { + case h_connection_keep_alive: + parser->flags |= F_CONNECTION_KEEP_ALIVE; + break; + case h_connection_close: + parser->flags |= F_CONNECTION_CLOSE; + break; + case h_transfer_encoding_chunked: + parser->flags |= F_CHUNKED; + break; + case h_connection_upgrade: + parser->flags |= F_CONNECTION_UPGRADE; + break; + default: + break; + } + + UPDATE_STATE(s_header_field_start); + REEXECUTE(); + } + + case s_header_value_discard_ws_almost_done: + { + STRICT_CHECK(ch != LF); + UPDATE_STATE(s_header_value_discard_lws); + break; + } + + case s_header_value_discard_lws: + { + if (ch == ' ' || ch == '\t') { + UPDATE_STATE(s_header_value_discard_ws); + break; + } else { + switch (parser->header_state) { + case h_connection_keep_alive: + parser->flags |= F_CONNECTION_KEEP_ALIVE; + break; + case h_connection_close: + parser->flags |= F_CONNECTION_CLOSE; + break; + case h_connection_upgrade: + parser->flags |= F_CONNECTION_UPGRADE; + break; + case h_transfer_encoding_chunked: + parser->flags |= F_CHUNKED; + break; + case h_content_length: + /* do not allow empty content length */ + SET_ERRNO(HPE_INVALID_CONTENT_LENGTH); + goto error; + break; + default: + break; + } + + /* header value was empty */ + MARK(header_value); + UPDATE_STATE(s_header_field_start); + CALLBACK_DATA_NOADVANCE(header_value); + REEXECUTE(); + } + } + + case s_headers_almost_done: + { + STRICT_CHECK(ch != LF); + + if (parser->flags & F_TRAILING) { + /* End of a chunked request */ + UPDATE_STATE(s_message_done); + CALLBACK_NOTIFY_NOADVANCE(chunk_complete); + REEXECUTE(); + } + + /* Cannot use chunked encoding and a content-length header together + per the HTTP specification. */ + if ((parser->flags & F_CHUNKED) && + (parser->flags & F_CONTENTLENGTH)) { + SET_ERRNO(HPE_UNEXPECTED_CONTENT_LENGTH); + goto error; + } + + UPDATE_STATE(s_headers_done); + + /* Set this here so that on_headers_complete() callbacks can see it */ + if ((parser->flags & F_UPGRADE) && + (parser->flags & F_CONNECTION_UPGRADE)) { + /* For responses, "Upgrade: foo" and "Connection: upgrade" are + * mandatory only when it is a 101 Switching Protocols response, + * otherwise it is purely informational, to announce support. + */ + parser->upgrade = + (parser->type == HTTP_REQUEST || parser->status_code == 101); + } else { + parser->upgrade = (parser->method == HTTP_CONNECT); + } + + /* Here we call the headers_complete callback. This is somewhat + * different than other callbacks because if the user returns 1, we + * will interpret that as saying that this message has no body. This + * is needed for the annoying case of recieving a response to a HEAD + * request. + * + * We'd like to use CALLBACK_NOTIFY_NOADVANCE() here but we cannot, so + * we have to simulate it by handling a change in errno below. + */ + if (settings->on_headers_complete) { + switch (settings->on_headers_complete(parser)) { + case 0: + break; + + case 2: + parser->upgrade = 1; + + /* fall through */ + case 1: + parser->flags |= F_SKIPBODY; + break; + + default: + SET_ERRNO(HPE_CB_headers_complete); + RETURN(p - data); /* Error */ + } + } + + if (HTTP_PARSER_ERRNO(parser) != HPE_OK) { + RETURN(p - data); + } + + REEXECUTE(); + } + + case s_headers_done: + { + int hasBody; + STRICT_CHECK(ch != LF); + + parser->nread = 0; + nread = 0; + + hasBody = parser->flags & F_CHUNKED || + (parser->content_length > 0 && parser->content_length != ULLONG_MAX); + if (parser->upgrade && (parser->method == HTTP_CONNECT || + (parser->flags & F_SKIPBODY) || !hasBody)) { + /* Exit, the rest of the message is in a different protocol. */ + UPDATE_STATE(NEW_MESSAGE()); + CALLBACK_NOTIFY(message_complete); + RETURN((p - data) + 1); + } + + if (parser->flags & F_SKIPBODY) { + UPDATE_STATE(NEW_MESSAGE()); + CALLBACK_NOTIFY(message_complete); + } else if (parser->flags & F_CHUNKED) { + /* chunked encoding - ignore Content-Length header */ + UPDATE_STATE(s_chunk_size_start); + } else { + if (parser->content_length == 0) { + /* Content-Length header given but zero: Content-Length: 0\r\n */ + UPDATE_STATE(NEW_MESSAGE()); + CALLBACK_NOTIFY(message_complete); + } else if (parser->content_length != ULLONG_MAX) { + /* Content-Length header given and non-zero */ + UPDATE_STATE(s_body_identity); + } else { + if (!http_message_needs_eof(parser)) { + /* Assume content-length 0 - read the next */ + UPDATE_STATE(NEW_MESSAGE()); + CALLBACK_NOTIFY(message_complete); + } else { + /* Read body until EOF */ + UPDATE_STATE(s_body_identity_eof); + } + } + } + + break; + } + + case s_body_identity: + { + uint64_t to_read = MIN(parser->content_length, + (uint64_t) ((data + len) - p)); + + assert(parser->content_length != 0 + && parser->content_length != ULLONG_MAX); + + /* The difference between advancing content_length and p is because + * the latter will automaticaly advance on the next loop iteration. + * Further, if content_length ends up at 0, we want to see the last + * byte again for our message complete callback. + */ + MARK(body); + parser->content_length -= to_read; + p += to_read - 1; + + if (parser->content_length == 0) { + UPDATE_STATE(s_message_done); + + /* Mimic CALLBACK_DATA_NOADVANCE() but with one extra byte. + * + * The alternative to doing this is to wait for the next byte to + * trigger the data callback, just as in every other case. The + * problem with this is that this makes it difficult for the test + * harness to distinguish between complete-on-EOF and + * complete-on-length. It's not clear that this distinction is + * important for applications, but let's keep it for now. + */ + CALLBACK_DATA_(body, p - body_mark + 1, p - data); + REEXECUTE(); + } + + break; + } + + /* read until EOF */ + case s_body_identity_eof: + MARK(body); + p = data + len - 1; + + break; + + case s_message_done: + UPDATE_STATE(NEW_MESSAGE()); + CALLBACK_NOTIFY(message_complete); + if (parser->upgrade) { + /* Exit, the rest of the message is in a different protocol. */ + RETURN((p - data) + 1); + } + break; + + case s_chunk_size_start: + { + assert(nread == 1); + assert(parser->flags & F_CHUNKED); + + unhex_val = unhex[(unsigned char)ch]; + if (UNLIKELY(unhex_val == -1)) { + SET_ERRNO(HPE_INVALID_CHUNK_SIZE); + goto error; + } + + parser->content_length = unhex_val; + UPDATE_STATE(s_chunk_size); + break; + } + + case s_chunk_size: + { + uint64_t t; + + assert(parser->flags & F_CHUNKED); + + if (ch == CR) { + UPDATE_STATE(s_chunk_size_almost_done); + break; + } + + unhex_val = unhex[(unsigned char)ch]; + + if (unhex_val == -1) { + if (ch == ';' || ch == ' ') { + UPDATE_STATE(s_chunk_parameters); + break; + } + + SET_ERRNO(HPE_INVALID_CHUNK_SIZE); + goto error; + } + + t = parser->content_length; + t *= 16; + t += unhex_val; + + /* Overflow? Test against a conservative limit for simplicity. */ + if (UNLIKELY((ULLONG_MAX - 16) / 16 < parser->content_length)) { + SET_ERRNO(HPE_INVALID_CONTENT_LENGTH); + goto error; + } + + parser->content_length = t; + break; + } + + case s_chunk_parameters: + { + assert(parser->flags & F_CHUNKED); + /* just ignore this shit. TODO check for overflow */ + if (ch == CR) { + UPDATE_STATE(s_chunk_size_almost_done); + break; + } + break; + } + + case s_chunk_size_almost_done: + { + assert(parser->flags & F_CHUNKED); + STRICT_CHECK(ch != LF); + + parser->nread = 0; + nread = 0; + + if (parser->content_length == 0) { + parser->flags |= F_TRAILING; + UPDATE_STATE(s_header_field_start); + } else { + UPDATE_STATE(s_chunk_data); + } + CALLBACK_NOTIFY(chunk_header); + break; + } + + case s_chunk_data: + { + uint64_t to_read = MIN(parser->content_length, + (uint64_t) ((data + len) - p)); + + assert(parser->flags & F_CHUNKED); + assert(parser->content_length != 0 + && parser->content_length != ULLONG_MAX); + + /* See the explanation in s_body_identity for why the content + * length and data pointers are managed this way. + */ + MARK(body); + parser->content_length -= to_read; + p += to_read - 1; + + if (parser->content_length == 0) { + UPDATE_STATE(s_chunk_data_almost_done); + } + + break; + } + + case s_chunk_data_almost_done: + assert(parser->flags & F_CHUNKED); + assert(parser->content_length == 0); + STRICT_CHECK(ch != CR); + UPDATE_STATE(s_chunk_data_done); + CALLBACK_DATA(body); + break; + + case s_chunk_data_done: + assert(parser->flags & F_CHUNKED); + STRICT_CHECK(ch != LF); + parser->nread = 0; + nread = 0; + UPDATE_STATE(s_chunk_size_start); + CALLBACK_NOTIFY(chunk_complete); + break; + + default: + assert(0 && "unhandled state"); + SET_ERRNO(HPE_INVALID_INTERNAL_STATE); + goto error; + } + } + + /* Run callbacks for any marks that we have leftover after we ran out of + * bytes. There should be at most one of these set, so it's OK to invoke + * them in series (unset marks will not result in callbacks). + * + * We use the NOADVANCE() variety of callbacks here because 'p' has already + * overflowed 'data' and this allows us to correct for the off-by-one that + * we'd otherwise have (since CALLBACK_DATA() is meant to be run with a 'p' + * value that's in-bounds). + */ + + assert(((header_field_mark ? 1 : 0) + + (header_value_mark ? 1 : 0) + + (url_mark ? 1 : 0) + + (body_mark ? 1 : 0) + + (status_mark ? 1 : 0)) <= 1); + + CALLBACK_DATA_NOADVANCE(header_field); + CALLBACK_DATA_NOADVANCE(header_value); + CALLBACK_DATA_NOADVANCE(url); + CALLBACK_DATA_NOADVANCE(body); + CALLBACK_DATA_NOADVANCE(status); + + RETURN(len); + +error: + if (HTTP_PARSER_ERRNO(parser) == HPE_OK) { + SET_ERRNO(HPE_UNKNOWN); + } + + RETURN(p - data); +} + + +/* Does the parser need to see an EOF to find the end of the message? */ +int +http_message_needs_eof (const http_parser *parser) +{ + if (parser->type == HTTP_REQUEST) { + return 0; + } + + /* See RFC 2616 section 4.4 */ + if (parser->status_code / 100 == 1 || /* 1xx e.g. Continue */ + parser->status_code == 204 || /* No Content */ + parser->status_code == 304 || /* Not Modified */ + parser->flags & F_SKIPBODY) { /* response to a HEAD request */ + return 0; + } + + if ((parser->flags & F_CHUNKED) || parser->content_length != ULLONG_MAX) { + return 0; + } + + return 1; +} + + +int +http_should_keep_alive (const http_parser *parser) +{ + if (parser->http_major > 0 && parser->http_minor > 0) { + /* HTTP/1.1 */ + if (parser->flags & F_CONNECTION_CLOSE) { + return 0; + } + } else { + /* HTTP/1.0 or earlier */ + if (!(parser->flags & F_CONNECTION_KEEP_ALIVE)) { + return 0; + } + } + + return !http_message_needs_eof(parser); +} + + +const char * +http_method_str (enum http_method m) +{ + return ELEM_AT(method_strings, m, ""); +} + +const char * +http_status_str (enum http_status s) +{ + switch (s) { +#define XX(num, name, string) case HTTP_STATUS_##name: return #string; + HTTP_STATUS_MAP(XX) +#undef XX + default: return ""; + } +} + +void +http_parser_init (http_parser *parser, enum http_parser_type t) +{ + void *data = parser->data; /* preserve application data */ + memset(parser, 0, sizeof(*parser)); + parser->data = data; + parser->type = t; + parser->state = (t == HTTP_REQUEST ? s_start_req : (t == HTTP_RESPONSE ? s_start_res : s_start_req_or_res)); + parser->http_errno = HPE_OK; +} + +void +http_parser_settings_init(http_parser_settings *settings) +{ + memset(settings, 0, sizeof(*settings)); +} + +const char * +http_errno_name(enum http_errno err) { + assert(((size_t) err) < ARRAY_SIZE(http_strerror_tab)); + return http_strerror_tab[err].name; +} + +const char * +http_errno_description(enum http_errno err) { + assert(((size_t) err) < ARRAY_SIZE(http_strerror_tab)); + return http_strerror_tab[err].description; +} + +static enum http_host_state +http_parse_host_char(enum http_host_state s, const char ch) { + switch(s) { + case s_http_userinfo: + case s_http_userinfo_start: + if (ch == '@') { + return s_http_host_start; + } + + if (IS_USERINFO_CHAR(ch)) { + return s_http_userinfo; + } + break; + + case s_http_host_start: + if (ch == '[') { + return s_http_host_v6_start; + } + + if (IS_HOST_CHAR(ch)) { + return s_http_host; + } + + break; + + case s_http_host: + if (IS_HOST_CHAR(ch)) { + return s_http_host; + } + + /* fall through */ + case s_http_host_v6_end: + if (ch == ':') { + return s_http_host_port_start; + } + + break; + + case s_http_host_v6: + if (ch == ']') { + return s_http_host_v6_end; + } + + /* fall through */ + case s_http_host_v6_start: + if (IS_HEX(ch) || ch == ':' || ch == '.') { + return s_http_host_v6; + } + + if (s == s_http_host_v6 && ch == '%') { + return s_http_host_v6_zone_start; + } + break; + + case s_http_host_v6_zone: + if (ch == ']') { + return s_http_host_v6_end; + } + + /* fall through */ + case s_http_host_v6_zone_start: + /* RFC 6874 Zone ID consists of 1*( unreserved / pct-encoded) */ + if (IS_ALPHANUM(ch) || ch == '%' || ch == '.' || ch == '-' || ch == '_' || + ch == '~') { + return s_http_host_v6_zone; + } + break; + + case s_http_host_port: + case s_http_host_port_start: + if (IS_NUM(ch)) { + return s_http_host_port; + } + + break; + + default: + break; + } + return s_http_host_dead; +} + +static int +http_parse_host(const char * buf, struct http_parser_url *u, int found_at) { + enum http_host_state s; + + const char *p; + size_t buflen = u->field_data[UF_HOST].off + u->field_data[UF_HOST].len; + + assert(u->field_set & (1 << UF_HOST)); + + u->field_data[UF_HOST].len = 0; + + s = found_at ? s_http_userinfo_start : s_http_host_start; + + for (p = buf + u->field_data[UF_HOST].off; p < buf + buflen; p++) { + enum http_host_state new_s = http_parse_host_char(s, *p); + + if (new_s == s_http_host_dead) { + return 1; + } + + switch(new_s) { + case s_http_host: + if (s != s_http_host) { + u->field_data[UF_HOST].off = (uint16_t)(p - buf); + } + u->field_data[UF_HOST].len++; + break; + + case s_http_host_v6: + if (s != s_http_host_v6) { + u->field_data[UF_HOST].off = (uint16_t)(p - buf); + } + u->field_data[UF_HOST].len++; + break; + + case s_http_host_v6_zone_start: + case s_http_host_v6_zone: + u->field_data[UF_HOST].len++; + break; + + case s_http_host_port: + if (s != s_http_host_port) { + u->field_data[UF_PORT].off = (uint16_t)(p - buf); + u->field_data[UF_PORT].len = 0; + u->field_set |= (1 << UF_PORT); + } + u->field_data[UF_PORT].len++; + break; + + case s_http_userinfo: + if (s != s_http_userinfo) { + u->field_data[UF_USERINFO].off = (uint16_t)(p - buf); + u->field_data[UF_USERINFO].len = 0; + u->field_set |= (1 << UF_USERINFO); + } + u->field_data[UF_USERINFO].len++; + break; + + default: + break; + } + s = new_s; + } + + /* Make sure we don't end somewhere unexpected */ + switch (s) { + case s_http_host_start: + case s_http_host_v6_start: + case s_http_host_v6: + case s_http_host_v6_zone_start: + case s_http_host_v6_zone: + case s_http_host_port_start: + case s_http_userinfo: + case s_http_userinfo_start: + return 1; + default: + break; + } + + return 0; +} + +void +http_parser_url_init(struct http_parser_url *u) { + memset(u, 0, sizeof(*u)); +} + +int +http_parser_parse_url(const char *buf, size_t buflen, int is_connect, + struct http_parser_url *u) +{ + enum state s; + const char *p; + enum http_parser_url_fields uf, old_uf; + int found_at = 0; + + if (buflen == 0) { + return 1; + } + + u->port = u->field_set = 0; + s = is_connect ? s_req_server_start : s_req_spaces_before_url; + old_uf = UF_MAX; + + for (p = buf; p < buf + buflen; p++) { + s = parse_url_char(s, *p); + + /* Figure out the next field that we're operating on */ + switch (s) { + case s_dead: + return 1; + + /* Skip delimeters */ + case s_req_schema_slash: + case s_req_schema_slash_slash: + case s_req_server_start: + case s_req_query_string_start: + case s_req_fragment_start: + continue; + + case s_req_schema: + uf = UF_SCHEMA; + break; + + case s_req_server_with_at: + found_at = 1; + + /* fall through */ + case s_req_server: + uf = UF_HOST; + break; + + case s_req_path: + uf = UF_PATH; + break; + + case s_req_query_string: + uf = UF_QUERY; + break; + + case s_req_fragment: + uf = UF_FRAGMENT; + break; + + default: + assert(!"Unexpected state"); + return 1; + } + + /* Nothing's changed; soldier on */ + if (uf == old_uf) { + u->field_data[uf].len++; + continue; + } + + u->field_data[uf].off = (uint16_t)(p - buf); + u->field_data[uf].len = 1; + + u->field_set |= (1 << uf); + old_uf = uf; + } + + /* host must be present if there is a schema */ + /* parsing http:///toto will fail */ + if ((u->field_set & (1 << UF_SCHEMA)) && + (u->field_set & (1 << UF_HOST)) == 0) { + return 1; + } + + if (u->field_set & (1 << UF_HOST)) { + if (http_parse_host(buf, u, found_at) != 0) { + return 1; + } + } + + /* CONNECT requests can only contain "hostname:port" */ + if (is_connect && u->field_set != ((1 << UF_HOST)|(1 << UF_PORT))) { + return 1; + } + + if (u->field_set & (1 << UF_PORT)) { + uint16_t off; + uint16_t len; + const char* p; + const char* end; + unsigned long v; + + off = u->field_data[UF_PORT].off; + len = u->field_data[UF_PORT].len; + end = buf + off + len; + + /* NOTE: The characters are already validated and are in the [0-9] range */ + assert(off + len <= buflen && "Port number overflow"); + v = 0; + for (p = buf + off; p < end; p++) { + v *= 10; + v += *p - '0'; + + /* Ports have a max value of 2^16 */ + if (v > 0xffff) { + return 1; + } + } + + u->port = (uint16_t) v; + } + + return 0; +} + +void +http_parser_pause(http_parser *parser, int paused) { + /* Users should only be pausing/unpausing a parser that is not in an error + * state. In non-debug builds, there's not much that we can do about this + * other than ignore it. + */ + if (HTTP_PARSER_ERRNO(parser) == HPE_OK || + HTTP_PARSER_ERRNO(parser) == HPE_PAUSED) { + uint32_t nread = parser->nread; /* used by the SET_ERRNO macro */ + SET_ERRNO((paused) ? HPE_PAUSED : HPE_OK); + } else { + assert(0 && "Attempting to pause parser in error state"); + } +} + +int +http_body_is_final(const struct http_parser *parser) { + return parser->state == s_message_done; +} + +unsigned long +http_parser_version(void) { + return HTTP_PARSER_VERSION_MAJOR * 0x10000 | + HTTP_PARSER_VERSION_MINOR * 0x00100 | + HTTP_PARSER_VERSION_PATCH * 0x00001; +} + +void +http_parser_set_max_header_size(uint32_t size) { + max_header_size = size; +} diff --git a/src/3rdparty/http-parser/http_parser.h b/src/3rdparty/http-parser/http_parser.h new file mode 100644 index 00000000..880ed278 --- /dev/null +++ b/src/3rdparty/http-parser/http_parser.h @@ -0,0 +1,439 @@ +/* Copyright Joyent, Inc. and other Node contributors. All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to + * deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ +#ifndef http_parser_h +#define http_parser_h +#ifdef __cplusplus +extern "C" { +#endif + +/* Also update SONAME in the Makefile whenever you change these. */ +#define HTTP_PARSER_VERSION_MAJOR 2 +#define HTTP_PARSER_VERSION_MINOR 9 +#define HTTP_PARSER_VERSION_PATCH 0 + +#include +#if defined(_WIN32) && !defined(__MINGW32__) && \ + (!defined(_MSC_VER) || _MSC_VER<1600) && !defined(__WINE__) +#include +typedef __int8 int8_t; +typedef unsigned __int8 uint8_t; +typedef __int16 int16_t; +typedef unsigned __int16 uint16_t; +typedef __int32 int32_t; +typedef unsigned __int32 uint32_t; +typedef __int64 int64_t; +typedef unsigned __int64 uint64_t; +#else +#include +#endif + +/* Compile with -DHTTP_PARSER_STRICT=0 to make less checks, but run + * faster + */ +#ifndef HTTP_PARSER_STRICT +# define HTTP_PARSER_STRICT 1 +#endif + +/* Maximium header size allowed. If the macro is not defined + * before including this header then the default is used. To + * change the maximum header size, define the macro in the build + * environment (e.g. -DHTTP_MAX_HEADER_SIZE=). To remove + * the effective limit on the size of the header, define the macro + * to a very large number (e.g. -DHTTP_MAX_HEADER_SIZE=0x7fffffff) + */ +#ifndef HTTP_MAX_HEADER_SIZE +# define HTTP_MAX_HEADER_SIZE (80*1024) +#endif + +typedef struct http_parser http_parser; +typedef struct http_parser_settings http_parser_settings; + + +/* Callbacks should return non-zero to indicate an error. The parser will + * then halt execution. + * + * The one exception is on_headers_complete. In a HTTP_RESPONSE parser + * returning '1' from on_headers_complete will tell the parser that it + * should not expect a body. This is used when receiving a response to a + * HEAD request which may contain 'Content-Length' or 'Transfer-Encoding: + * chunked' headers that indicate the presence of a body. + * + * Returning `2` from on_headers_complete will tell parser that it should not + * expect neither a body nor any futher responses on this connection. This is + * useful for handling responses to a CONNECT request which may not contain + * `Upgrade` or `Connection: upgrade` headers. + * + * http_data_cb does not return data chunks. It will be called arbitrarily + * many times for each string. E.G. you might get 10 callbacks for "on_url" + * each providing just a few characters more data. + */ +typedef int (*http_data_cb) (http_parser*, const char *at, size_t length); +typedef int (*http_cb) (http_parser*); + + +/* Status Codes */ +#define HTTP_STATUS_MAP(XX) \ + XX(100, CONTINUE, Continue) \ + XX(101, SWITCHING_PROTOCOLS, Switching Protocols) \ + XX(102, PROCESSING, Processing) \ + XX(200, OK, OK) \ + XX(201, CREATED, Created) \ + XX(202, ACCEPTED, Accepted) \ + XX(203, NON_AUTHORITATIVE_INFORMATION, Non-Authoritative Information) \ + XX(204, NO_CONTENT, No Content) \ + XX(205, RESET_CONTENT, Reset Content) \ + XX(206, PARTIAL_CONTENT, Partial Content) \ + XX(207, MULTI_STATUS, Multi-Status) \ + XX(208, ALREADY_REPORTED, Already Reported) \ + XX(226, IM_USED, IM Used) \ + XX(300, MULTIPLE_CHOICES, Multiple Choices) \ + XX(301, MOVED_PERMANENTLY, Moved Permanently) \ + XX(302, FOUND, Found) \ + XX(303, SEE_OTHER, See Other) \ + XX(304, NOT_MODIFIED, Not Modified) \ + XX(305, USE_PROXY, Use Proxy) \ + XX(307, TEMPORARY_REDIRECT, Temporary Redirect) \ + XX(308, PERMANENT_REDIRECT, Permanent Redirect) \ + XX(400, BAD_REQUEST, Bad Request) \ + XX(401, UNAUTHORIZED, Unauthorized) \ + XX(402, PAYMENT_REQUIRED, Payment Required) \ + XX(403, FORBIDDEN, Forbidden) \ + XX(404, NOT_FOUND, Not Found) \ + XX(405, METHOD_NOT_ALLOWED, Method Not Allowed) \ + XX(406, NOT_ACCEPTABLE, Not Acceptable) \ + XX(407, PROXY_AUTHENTICATION_REQUIRED, Proxy Authentication Required) \ + XX(408, REQUEST_TIMEOUT, Request Timeout) \ + XX(409, CONFLICT, Conflict) \ + XX(410, GONE, Gone) \ + XX(411, LENGTH_REQUIRED, Length Required) \ + XX(412, PRECONDITION_FAILED, Precondition Failed) \ + XX(413, PAYLOAD_TOO_LARGE, Payload Too Large) \ + XX(414, URI_TOO_LONG, URI Too Long) \ + XX(415, UNSUPPORTED_MEDIA_TYPE, Unsupported Media Type) \ + XX(416, RANGE_NOT_SATISFIABLE, Range Not Satisfiable) \ + XX(417, EXPECTATION_FAILED, Expectation Failed) \ + XX(421, MISDIRECTED_REQUEST, Misdirected Request) \ + XX(422, UNPROCESSABLE_ENTITY, Unprocessable Entity) \ + XX(423, LOCKED, Locked) \ + XX(424, FAILED_DEPENDENCY, Failed Dependency) \ + XX(426, UPGRADE_REQUIRED, Upgrade Required) \ + XX(428, PRECONDITION_REQUIRED, Precondition Required) \ + XX(429, TOO_MANY_REQUESTS, Too Many Requests) \ + XX(431, REQUEST_HEADER_FIELDS_TOO_LARGE, Request Header Fields Too Large) \ + XX(451, UNAVAILABLE_FOR_LEGAL_REASONS, Unavailable For Legal Reasons) \ + XX(500, INTERNAL_SERVER_ERROR, Internal Server Error) \ + XX(501, NOT_IMPLEMENTED, Not Implemented) \ + XX(502, BAD_GATEWAY, Bad Gateway) \ + XX(503, SERVICE_UNAVAILABLE, Service Unavailable) \ + XX(504, GATEWAY_TIMEOUT, Gateway Timeout) \ + XX(505, HTTP_VERSION_NOT_SUPPORTED, HTTP Version Not Supported) \ + XX(506, VARIANT_ALSO_NEGOTIATES, Variant Also Negotiates) \ + XX(507, INSUFFICIENT_STORAGE, Insufficient Storage) \ + XX(508, LOOP_DETECTED, Loop Detected) \ + XX(510, NOT_EXTENDED, Not Extended) \ + XX(511, NETWORK_AUTHENTICATION_REQUIRED, Network Authentication Required) \ + +enum http_status + { +#define XX(num, name, string) HTTP_STATUS_##name = num, + HTTP_STATUS_MAP(XX) +#undef XX + }; + + +/* Request Methods */ +#define HTTP_METHOD_MAP(XX) \ + XX(0, DELETE, DELETE) \ + XX(1, GET, GET) \ + XX(2, HEAD, HEAD) \ + XX(3, POST, POST) \ + XX(4, PUT, PUT) \ + /* pathological */ \ + XX(5, CONNECT, CONNECT) \ + XX(6, OPTIONS, OPTIONS) \ + XX(7, TRACE, TRACE) \ + /* WebDAV */ \ + XX(8, COPY, COPY) \ + XX(9, LOCK, LOCK) \ + XX(10, MKCOL, MKCOL) \ + XX(11, MOVE, MOVE) \ + XX(12, PROPFIND, PROPFIND) \ + XX(13, PROPPATCH, PROPPATCH) \ + XX(14, SEARCH, SEARCH) \ + XX(15, UNLOCK, UNLOCK) \ + XX(16, BIND, BIND) \ + XX(17, REBIND, REBIND) \ + XX(18, UNBIND, UNBIND) \ + XX(19, ACL, ACL) \ + /* subversion */ \ + XX(20, REPORT, REPORT) \ + XX(21, MKACTIVITY, MKACTIVITY) \ + XX(22, CHECKOUT, CHECKOUT) \ + XX(23, MERGE, MERGE) \ + /* upnp */ \ + XX(24, MSEARCH, M-SEARCH) \ + XX(25, NOTIFY, NOTIFY) \ + XX(26, SUBSCRIBE, SUBSCRIBE) \ + XX(27, UNSUBSCRIBE, UNSUBSCRIBE) \ + /* RFC-5789 */ \ + XX(28, PATCH, PATCH) \ + XX(29, PURGE, PURGE) \ + /* CalDAV */ \ + XX(30, MKCALENDAR, MKCALENDAR) \ + /* RFC-2068, section 19.6.1.2 */ \ + XX(31, LINK, LINK) \ + XX(32, UNLINK, UNLINK) \ + /* icecast */ \ + XX(33, SOURCE, SOURCE) \ + +enum http_method + { +#define XX(num, name, string) HTTP_##name = num, + HTTP_METHOD_MAP(XX) +#undef XX + }; + + +enum http_parser_type { HTTP_REQUEST, HTTP_RESPONSE, HTTP_BOTH }; + + +/* Flag values for http_parser.flags field */ +enum flags + { F_CHUNKED = 1 << 0 + , F_CONNECTION_KEEP_ALIVE = 1 << 1 + , F_CONNECTION_CLOSE = 1 << 2 + , F_CONNECTION_UPGRADE = 1 << 3 + , F_TRAILING = 1 << 4 + , F_UPGRADE = 1 << 5 + , F_SKIPBODY = 1 << 6 + , F_CONTENTLENGTH = 1 << 7 + }; + + +/* Map for errno-related constants + * + * The provided argument should be a macro that takes 2 arguments. + */ +#define HTTP_ERRNO_MAP(XX) \ + /* No error */ \ + XX(OK, "success") \ + \ + /* Callback-related errors */ \ + XX(CB_message_begin, "the on_message_begin callback failed") \ + XX(CB_url, "the on_url callback failed") \ + XX(CB_header_field, "the on_header_field callback failed") \ + XX(CB_header_value, "the on_header_value callback failed") \ + XX(CB_headers_complete, "the on_headers_complete callback failed") \ + XX(CB_body, "the on_body callback failed") \ + XX(CB_message_complete, "the on_message_complete callback failed") \ + XX(CB_status, "the on_status callback failed") \ + XX(CB_chunk_header, "the on_chunk_header callback failed") \ + XX(CB_chunk_complete, "the on_chunk_complete callback failed") \ + \ + /* Parsing-related errors */ \ + XX(INVALID_EOF_STATE, "stream ended at an unexpected time") \ + XX(HEADER_OVERFLOW, \ + "too many header bytes seen; overflow detected") \ + XX(CLOSED_CONNECTION, \ + "data received after completed connection: close message") \ + XX(INVALID_VERSION, "invalid HTTP version") \ + XX(INVALID_STATUS, "invalid HTTP status code") \ + XX(INVALID_METHOD, "invalid HTTP method") \ + XX(INVALID_URL, "invalid URL") \ + XX(INVALID_HOST, "invalid host") \ + XX(INVALID_PORT, "invalid port") \ + XX(INVALID_PATH, "invalid path") \ + XX(INVALID_QUERY_STRING, "invalid query string") \ + XX(INVALID_FRAGMENT, "invalid fragment") \ + XX(LF_EXPECTED, "LF character expected") \ + XX(INVALID_HEADER_TOKEN, "invalid character in header") \ + XX(INVALID_CONTENT_LENGTH, \ + "invalid character in content-length header") \ + XX(UNEXPECTED_CONTENT_LENGTH, \ + "unexpected content-length header") \ + XX(INVALID_CHUNK_SIZE, \ + "invalid character in chunk size header") \ + XX(INVALID_CONSTANT, "invalid constant string") \ + XX(INVALID_INTERNAL_STATE, "encountered unexpected internal state")\ + XX(STRICT, "strict mode assertion failed") \ + XX(PAUSED, "parser is paused") \ + XX(UNKNOWN, "an unknown error occurred") + + +/* Define HPE_* values for each errno value above */ +#define HTTP_ERRNO_GEN(n, s) HPE_##n, +enum http_errno { + HTTP_ERRNO_MAP(HTTP_ERRNO_GEN) +}; +#undef HTTP_ERRNO_GEN + + +/* Get an http_errno value from an http_parser */ +#define HTTP_PARSER_ERRNO(p) ((enum http_errno) (p)->http_errno) + + +struct http_parser { + /** PRIVATE **/ + unsigned int type : 2; /* enum http_parser_type */ + unsigned int flags : 8; /* F_* values from 'flags' enum; semi-public */ + unsigned int state : 7; /* enum state from http_parser.c */ + unsigned int header_state : 7; /* enum header_state from http_parser.c */ + unsigned int index : 7; /* index into current matcher */ + unsigned int lenient_http_headers : 1; + + uint32_t nread; /* # bytes read in various scenarios */ + uint64_t content_length; /* # bytes in body (0 if no Content-Length header) */ + + /** READ-ONLY **/ + unsigned short http_major; + unsigned short http_minor; + unsigned int status_code : 16; /* responses only */ + unsigned int method : 8; /* requests only */ + unsigned int http_errno : 7; + + /* 1 = Upgrade header was present and the parser has exited because of that. + * 0 = No upgrade header present. + * Should be checked when http_parser_execute() returns in addition to + * error checking. + */ + unsigned int upgrade : 1; + + /** PUBLIC **/ + void *data; /* A pointer to get hook to the "connection" or "socket" object */ +}; + + +struct http_parser_settings { + http_cb on_message_begin; + http_data_cb on_url; + http_data_cb on_status; + http_data_cb on_header_field; + http_data_cb on_header_value; + http_cb on_headers_complete; + http_data_cb on_body; + http_cb on_message_complete; + /* When on_chunk_header is called, the current chunk length is stored + * in parser->content_length. + */ + http_cb on_chunk_header; + http_cb on_chunk_complete; +}; + + +enum http_parser_url_fields + { UF_SCHEMA = 0 + , UF_HOST = 1 + , UF_PORT = 2 + , UF_PATH = 3 + , UF_QUERY = 4 + , UF_FRAGMENT = 5 + , UF_USERINFO = 6 + , UF_MAX = 7 + }; + + +/* Result structure for http_parser_parse_url(). + * + * Callers should index into field_data[] with UF_* values iff field_set + * has the relevant (1 << UF_*) bit set. As a courtesy to clients (and + * because we probably have padding left over), we convert any port to + * a uint16_t. + */ +struct http_parser_url { + uint16_t field_set; /* Bitmask of (1 << UF_*) values */ + uint16_t port; /* Converted UF_PORT string */ + + struct { + uint16_t off; /* Offset into buffer in which field starts */ + uint16_t len; /* Length of run in buffer */ + } field_data[UF_MAX]; +}; + + +/* Returns the library version. Bits 16-23 contain the major version number, + * bits 8-15 the minor version number and bits 0-7 the patch level. + * Usage example: + * + * unsigned long version = http_parser_version(); + * unsigned major = (version >> 16) & 255; + * unsigned minor = (version >> 8) & 255; + * unsigned patch = version & 255; + * printf("http_parser v%u.%u.%u\n", major, minor, patch); + */ +unsigned long http_parser_version(void); + +void http_parser_init(http_parser *parser, enum http_parser_type type); + + +/* Initialize http_parser_settings members to 0 + */ +void http_parser_settings_init(http_parser_settings *settings); + + +/* Executes the parser. Returns number of parsed bytes. Sets + * `parser->http_errno` on error. */ +size_t http_parser_execute(http_parser *parser, + const http_parser_settings *settings, + const char *data, + size_t len); + + +/* If http_should_keep_alive() in the on_headers_complete or + * on_message_complete callback returns 0, then this should be + * the last message on the connection. + * If you are the server, respond with the "Connection: close" header. + * If you are the client, close the connection. + */ +int http_should_keep_alive(const http_parser *parser); + +/* Returns a string version of the HTTP method. */ +const char *http_method_str(enum http_method m); + +/* Returns a string version of the HTTP status code. */ +const char *http_status_str(enum http_status s); + +/* Return a string name of the given error */ +const char *http_errno_name(enum http_errno err); + +/* Return a string description of the given error */ +const char *http_errno_description(enum http_errno err); + +/* Initialize all http_parser_url members to 0 */ +void http_parser_url_init(struct http_parser_url *u); + +/* Parse a URL; return nonzero on failure */ +int http_parser_parse_url(const char *buf, size_t buflen, + int is_connect, + struct http_parser_url *u); + +/* Pause or un-pause the parser; a nonzero value pauses */ +void http_parser_pause(http_parser *parser, int paused); + +/* Checks if this is the final chunk of the body. */ +int http_body_is_final(const http_parser *parser); + +/* Change the maximum header size provided at compile time. */ +void http_parser_set_max_header_size(uint32_t size); + +#ifdef __cplusplus +} +#endif +#endif diff --git a/src/App.cpp b/src/App.cpp index 093b9ceb..08597eda 100644 --- a/src/App.cpp +++ b/src/App.cpp @@ -46,7 +46,7 @@ #ifdef XMRIG_FEATURE_HTTP -# include "common/api/Httpd.h" +# include "api/Httpd.h" #endif @@ -103,13 +103,7 @@ int xmrig::App::exec() # endif # ifdef XMRIG_FEATURE_HTTP - m_httpd = new Httpd( - m_controller->config()->http().port(), - m_controller->config()->http().token(), - false, - m_controller->config()->http().isRestricted() - ); - + m_httpd = new Httpd(m_controller); m_httpd->start(); # endif diff --git a/src/Summary.cpp b/src/Summary.cpp index 7b47b2c6..b7c5d7df 100644 --- a/src/Summary.cpp +++ b/src/Summary.cpp @@ -143,7 +143,6 @@ void Summary::print(xmrig::Controller *controller) print_cpu(controller->config()); print_threads(controller->config()); controller->config()->pools().print(); - controller->config()->http().print(); print_commands(controller->config()); } diff --git a/src/api/Httpd.cpp b/src/api/Httpd.cpp new file mode 100644 index 00000000..f3cd7d9f --- /dev/null +++ b/src/api/Httpd.cpp @@ -0,0 +1,109 @@ +/* XMRig + * Copyright 2010 Jeff Garzik + * Copyright 2012-2014 pooler + * Copyright 2014 Lucas Jones + * Copyright 2014-2016 Wolf9466 + * Copyright 2016 Jay D Dee + * Copyright 2017-2018 XMR-Stak , + * Copyright 2018-2019 SChernykh + * Copyright 2016-2019 XMRig , + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + + +#include "api/Httpd.h" +#include "base/io/log/Log.h" +#include "base/net/http/HttpRequest.h" +#include "base/net/http/HttpResponse.h" +#include "base/net/http/HttpServer.h" +#include "base/net/tools/TcpServer.h" +#include "core/Config.h" +#include "core/Controller.h" + + +xmrig::Httpd::Httpd(Controller *controller) : + m_controller(controller), + m_http(nullptr), + m_server(nullptr), + m_port(0) +{ + controller->addListener(this); +} + + +xmrig::Httpd::~Httpd() +{ +} + + +bool xmrig::Httpd::start() +{ + const Http &config = m_controller->config()->http(); + + if (!config.isEnabled()) { + return true; + } + + m_http = new HttpServer(this); + m_server = new TcpServer(config.host(), config.port(), m_http); + + const int rc = m_server->bind(); + Log::print(GREEN_BOLD(" * ") WHITE_BOLD("%-13s") BLUE_BOLD("%s:%d") " " RED_BOLD("%s"), + "HTTP API", + config.host().data(), + rc < 0 ? config.port() : rc, + rc < 0 ? uv_strerror(rc) : "" + ); + + if (rc < 0) { + stop(); + + return false; + } + + m_port = static_cast(rc); + + return true; +} + + +void xmrig::Httpd::stop() +{ + delete m_server; + delete m_http; + + m_server = nullptr; + m_http = nullptr; + m_port = 0; +} + + + +void xmrig::Httpd::onConfigChanged(Config *config, Config *previousConfig) +{ + if (config->http() == previousConfig->http()) { + return; + } + + stop(); + start(); +} + + +void xmrig::Httpd::onHttp(const HttpRequest &req, HttpResponse &res) +{ + LOG_INFO(GREEN_BOLD_S "OK"); + res.end(); +} diff --git a/src/common/api/Httpd.h b/src/api/Httpd.h similarity index 63% rename from src/common/api/Httpd.h rename to src/api/Httpd.h index f0b6ce87..1c01fbdd 100644 --- a/src/common/api/Httpd.h +++ b/src/api/Httpd.h @@ -26,52 +26,39 @@ #define XMRIG_HTTPD_H -#include +#include -#include "base/kernel/interfaces/ITimerListener.h" - - -struct MHD_Connection; -struct MHD_Daemon; -struct MHD_Response; +#include "base/kernel/interfaces/IControllerListener.h" +#include "base/kernel/interfaces/IHttpListener.h" namespace xmrig { -class HttpRequest; -class Timer; +class Controller; +class HttpServer; +class TcpServer; -class Httpd : public ITimerListener +class Httpd : public IControllerListener, public IHttpListener { public: - Httpd(int port, const char *accessToken, bool IPv6, bool restricted); + Httpd(Controller *controller); ~Httpd() override; bool start(); void stop(); protected: - void onTimer(const Timer *) override { run(); } + void onConfigChanged(Config *config, Config *previousConfig) override; + void onHttp(const HttpRequest &req, HttpResponse &res) override; private: - constexpr static const int kIdleInterval = 200; - constexpr static const int kActiveInterval = 25; - - int process(HttpRequest &req); - void run(); - - static int handler(void *cls, MHD_Connection *connection, const char *url, const char *method, const char *version, const char *uploadData, size_t *uploadSize, void **con_cls); - - bool m_idle; - bool m_IPv6; - bool m_restricted; - const char *m_accessToken; - const int m_port; - MHD_Daemon *m_daemon; - Timer *m_timer; + Controller *m_controller; + HttpServer *m_http; + TcpServer *m_server; + uint16_t m_port; }; diff --git a/src/base/base.cmake b/src/base/base.cmake index ffbd8454..5bc3fd2d 100644 --- a/src/base/base.cmake +++ b/src/base/base.cmake @@ -9,6 +9,7 @@ set(HEADERS_BASE src/base/kernel/interfaces/IClientListener.h src/base/kernel/interfaces/IConfigListener.h src/base/kernel/interfaces/IConsoleListener.h + src/base/kernel/interfaces/IControllerListener.h src/base/kernel/interfaces/IDnsListener.h src/base/kernel/interfaces/ILineListener.h src/base/kernel/interfaces/ILogBackend.h @@ -83,15 +84,27 @@ endif() if (WITH_HTTPD) set(HEADERS_BASE_HTTP -# src/base/net/http/Http.h + src/3rdparty/http-parser/http_parser.h + src/base/kernel/interfaces/IHttpListener.h + src/base/kernel/interfaces/ITcpServerListener.h + src/base/net/http/HttpContext.h + src/base/net/http/HttpRequest.h + src/base/net/http/HttpResponse.h + src/base/net/http/HttpServer.h + src/base/net/tools/TcpServer.h ) set(SOURCES_BASE_HTTP -# src/base/net/http/Http.cpp + src/3rdparty/http-parser/http_parser.c + src/base/net/http/HttpContext.cpp + src/base/net/http/HttpResponse.cpp + src/base/net/http/HttpServer.cpp + src/base/net/tools/TcpServer.cpp ) add_definitions(/DXMRIG_FEATURE_HTTP) add_definitions(/DXMRIG_FEATURE_API) + remove_definitions(/DXMRIG_FEATURE_API) else() set(HEADERS_BASE_HTTP "") set(SOURCES_BASE_HTTP "") diff --git a/src/common/interfaces/IControllerListener.h b/src/base/kernel/interfaces/IControllerListener.h similarity index 100% rename from src/common/interfaces/IControllerListener.h rename to src/base/kernel/interfaces/IControllerListener.h diff --git a/src/base/kernel/interfaces/IHttpListener.h b/src/base/kernel/interfaces/IHttpListener.h new file mode 100644 index 00000000..73feff54 --- /dev/null +++ b/src/base/kernel/interfaces/IHttpListener.h @@ -0,0 +1,48 @@ +/* XMRig + * Copyright 2010 Jeff Garzik + * Copyright 2012-2014 pooler + * Copyright 2014 Lucas Jones + * Copyright 2014-2016 Wolf9466 + * Copyright 2016 Jay D Dee + * Copyright 2017-2018 XMR-Stak , + * Copyright 2018-2019 SChernykh + * Copyright 2016-2019 XMRig , + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef XMRIG_IHTTPLISTENER_H +#define XMRIG_IHTTPLISTENER_H + + +namespace xmrig { + + +class HttpRequest; +class HttpResponse; + + +class IHttpListener +{ +public: + virtual ~IHttpListener() = default; + + virtual void onHttp(const HttpRequest &req, HttpResponse &res) = 0; +}; + + +} /* namespace xmrig */ + + +#endif // XMRIG_IHTTPLISTENER_H diff --git a/src/base/kernel/interfaces/ITcpServerListener.h b/src/base/kernel/interfaces/ITcpServerListener.h new file mode 100644 index 00000000..3cb1576e --- /dev/null +++ b/src/base/kernel/interfaces/ITcpServerListener.h @@ -0,0 +1,53 @@ +/* XMRig + * Copyright 2010 Jeff Garzik + * Copyright 2012-2014 pooler + * Copyright 2014 Lucas Jones + * Copyright 2014-2016 Wolf9466 + * Copyright 2016 Jay D Dee + * Copyright 2017-2018 XMR-Stak , + * Copyright 2018-2019 SChernykh + * Copyright 2016-2019 XMRig , + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef XMRIG_ITCPSERVERLISTENER_H +#define XMRIG_ITCPSERVERLISTENER_H + + +#include + + +typedef struct uv_stream_s uv_stream_t; + + +namespace xmrig { + + +class String; + + +class ITcpServerListener +{ +public: + virtual ~ITcpServerListener() = default; + + virtual void onConnection(uv_stream_t *stream, uint16_t port) = 0; +}; + + +} /* namespace xmrig */ + + +#endif // XMRIG_ITCPSERVERLISTENER_H diff --git a/src/base/net/http/Http.cpp b/src/base/net/http/Http.cpp index 177eebde..597260cf 100644 --- a/src/base/net/http/Http.cpp +++ b/src/base/net/http/Http.cpp @@ -25,7 +25,6 @@ #include "3rdparty/rapidjson/document.h" #include "base/io/Json.h" -#include "base/io/log/Log.h" #include "base/net/http/Http.h" @@ -92,18 +91,6 @@ void xmrig::Http::load(const rapidjson::Value &http) } -void xmrig::Http::print() const -{ -# ifdef XMRIG_FEATURE_API - if (!isEnabled()) { - return; - } - - Log::print(GREEN_BOLD(" * ") WHITE_BOLD("%-13s") BLUE_BOLD("http://%s:%d"), "HTTP API", host().data(), port()); -# endif -} - - void xmrig::Http::setPort(int port) { if (port >= 0 && port <= 65536) { diff --git a/src/base/net/http/Http.h b/src/base/net/http/Http.h index ebdf6765..f8aa15bb 100644 --- a/src/base/net/http/Http.h +++ b/src/base/net/http/Http.h @@ -54,7 +54,6 @@ public: bool isEqual(const Http &other) const; rapidjson::Value toJSON(rapidjson::Document &doc) const; void load(const rapidjson::Value &http); - void print() const; void setPort(int port); private: diff --git a/src/base/net/http/HttpContext.cpp b/src/base/net/http/HttpContext.cpp new file mode 100644 index 00000000..e125b5b9 --- /dev/null +++ b/src/base/net/http/HttpContext.cpp @@ -0,0 +1,142 @@ +/* XMRig + * Copyright 2010 Jeff Garzik + * Copyright 2012-2014 pooler + * Copyright 2014 Lucas Jones + * Copyright 2014-2016 Wolf9466 + * Copyright 2016 Jay D Dee + * Copyright 2017-2018 XMR-Stak , + * Copyright 2014-2019 heapwolf + * Copyright 2018-2019 SChernykh + * Copyright 2016-2019 XMRig , + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + + +#include +#include + + +#include "3rdparty/http-parser/http_parser.h" +#include "base/net/http/HttpContext.h" + + +xmrig::HttpContext::HttpContext(int parser_type, IHttpListener *listener) : + listener(listener), + connect(nullptr), + m_wasHeaderValue(false) +{ + parser = new http_parser; + tcp = new uv_tcp_t; + + uv_tcp_init(uv_default_loop(), tcp); + http_parser_init(parser, static_cast(parser_type)); + + parser->data = tcp->data = this; +} + + +xmrig::HttpContext::~HttpContext() +{ + delete connect; + delete tcp; + delete parser; +} + + +void xmrig::HttpContext::attach(http_parser_settings *settings) +{ + settings->on_message_begin = nullptr; + settings->on_status = nullptr; + settings->on_chunk_header = nullptr; + settings->on_chunk_complete = nullptr; + + settings->on_url = [](http_parser *parser, const char *at, size_t length) -> int + { + static_cast(parser->data)->url = std::string(at, length); + return 0; + }; + + settings->on_header_field = onHeaderField; + settings->on_header_value = onHeaderValue; + + settings->on_headers_complete = [](http_parser* parser) -> int { + HttpContext *ctx = static_cast(parser->data); + ctx->method = std::string(http_method_str(static_cast(parser->method))); + + if (!ctx->m_lastHeaderField.empty()) { + ctx->setHeader(); + } + + return 0; + }; + + settings->on_body = [](http_parser *parser, const char *at, size_t len) -> int + { + static_cast(parser->data)->body << std::string(at, len); + + return 0; + }; +} + + +void xmrig::HttpContext::close(uv_handle_t* handle) +{ + delete reinterpret_cast(handle->data); +} + + +int xmrig::HttpContext::onHeaderField(http_parser *parser, const char *at, size_t length) +{ + HttpContext *ctx = static_cast(parser->data); + + if (ctx->m_wasHeaderValue) { + if (!ctx->m_lastHeaderField.empty()) { + ctx->setHeader(); + } + + ctx->m_lastHeaderField = std::string(at, length); + ctx->m_wasHeaderValue = false; + } else { + ctx->m_lastHeaderField += std::string(at, length); + } + + return 0; +} + + +int xmrig::HttpContext::onHeaderValue(http_parser *parser, const char *at, size_t length) +{ + HttpContext *ctx = static_cast(parser->data); + + if (!ctx->m_wasHeaderValue) { + ctx->m_lastHeaderValue = std::string(at, length); + ctx->m_wasHeaderValue = true; + } else { + ctx->m_lastHeaderValue += std::string(at, length); + } + + return 0; +} + + +void xmrig::HttpContext::setHeader() +{ + std::transform(m_lastHeaderField.begin(), m_lastHeaderField.end(), m_lastHeaderField.begin(), ::tolower); + headers.insert({ m_lastHeaderField, m_lastHeaderValue }); + + m_lastHeaderField.clear(); + m_lastHeaderValue.clear(); +} + diff --git a/src/base/net/http/HttpContext.h b/src/base/net/http/HttpContext.h new file mode 100644 index 00000000..06c66e3b --- /dev/null +++ b/src/base/net/http/HttpContext.h @@ -0,0 +1,81 @@ +/* XMRig + * Copyright 2010 Jeff Garzik + * Copyright 2012-2014 pooler + * Copyright 2014 Lucas Jones + * Copyright 2014-2016 Wolf9466 + * Copyright 2016 Jay D Dee + * Copyright 2017-2018 XMR-Stak , + * Copyright 2014-2019 heapwolf + * Copyright 2018-2019 SChernykh + * Copyright 2016-2019 XMRig , + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + + +#ifndef XMRIG_HTTPCONTEXT_H +#define XMRIG_HTTPCONTEXT_H + + +typedef struct http_parser http_parser; +typedef struct http_parser_settings http_parser_settings; +typedef struct uv_connect_s uv_connect_t; +typedef struct uv_handle_s uv_handle_t; +typedef struct uv_stream_s uv_stream_t; +typedef struct uv_tcp_s uv_tcp_t; + + +#include "base/net/http/HttpRequest.h" + + +namespace xmrig { + + +class IHttpListener; + + +class HttpContext : public HttpRequest +{ +public: + HttpContext(int parser_type, IHttpListener *listener); + ~HttpContext(); + + inline uv_stream_t *stream() const { return reinterpret_cast(tcp); } + inline uv_handle_t *handle() const { return reinterpret_cast(tcp); } + + static void attach(http_parser_settings *settings); + static void close(uv_handle_t* handle); + + http_parser *parser; + IHttpListener *listener; + uv_connect_t *connect; + uv_tcp_t *tcp; + +private: + static int onHeaderField(http_parser *parser, const char *at, size_t length); + static int onHeaderValue(http_parser *parser, const char *at, size_t length); + + void setHeader(); + + bool m_wasHeaderValue; + std::string m_lastHeaderField; + std::string m_lastHeaderValue; +}; + + +} // namespace xmrig + + +#endif // XMRIG_HTTPCONTEXT_H + diff --git a/src/base/net/http/HttpRequest.h b/src/base/net/http/HttpRequest.h new file mode 100644 index 00000000..2f2f22a8 --- /dev/null +++ b/src/base/net/http/HttpRequest.h @@ -0,0 +1,53 @@ +/* XMRig + * Copyright 2010 Jeff Garzik + * Copyright 2012-2014 pooler + * Copyright 2014 Lucas Jones + * Copyright 2014-2016 Wolf9466 + * Copyright 2016 Jay D Dee + * Copyright 2017-2018 XMR-Stak , + * Copyright 2014-2019 heapwolf + * Copyright 2018-2019 SChernykh + * Copyright 2016-2019 XMRig , + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + + +#ifndef XMRIG_HTTPREQUEST_H +#define XMRIG_HTTPREQUEST_H + + +#include +#include +#include + + +namespace xmrig { + + +class HttpRequest +{ +public: + std::string url; + std::string method; + std::stringstream body; + std::map headers; +}; + + +} // namespace xmrig + + +#endif // XMRIG_HTTPREQUEST_H + diff --git a/src/base/net/http/HttpResponse.cpp b/src/base/net/http/HttpResponse.cpp new file mode 100644 index 00000000..ffccf1c9 --- /dev/null +++ b/src/base/net/http/HttpResponse.cpp @@ -0,0 +1,97 @@ +/* XMRig + * Copyright 2010 Jeff Garzik + * Copyright 2012-2014 pooler + * Copyright 2014 Lucas Jones + * Copyright 2014-2016 Wolf9466 + * Copyright 2016 Jay D Dee + * Copyright 2017-2018 XMR-Stak , + * Copyright 2014-2019 heapwolf + * Copyright 2018-2019 SChernykh + * Copyright 2016-2019 XMRig , + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + + +#include + + +#include "3rdparty/http-parser/http_parser.h" +#include "base/net/http/HttpContext.h" +#include "base/net/http/HttpResponse.h" + + +namespace xmrig { + +static const char *kCRLF = "\r\n"; +static const char *kTransferEncoding = "Transfer-Encoding"; + +} // namespace xmrig + + +xmrig::HttpResponse::HttpResponse() : + parser(nullptr), + statusCode(HTTP_STATUS_OK), + body(""), + statusAdjective("OK"), // FIXME + m_writtenOrEnded(false) +{ +} + + +void xmrig::HttpResponse::writeOrEnd(const std::string &str, bool end) +{ + std::stringstream ss; + + if (!m_writtenOrEnded) { + ss << "HTTP/1.1 " << statusCode << " " << statusAdjective << kCRLF; + + for (auto &header : headers) { + ss << header.first << ": " << header.second << kCRLF; + } + + ss << kCRLF; + m_writtenOrEnded = true; + } + + if (headers.count(kTransferEncoding) && headers[kTransferEncoding] == "chunked") { + ss << std::hex << str.size() << std::dec << kCRLF << str << kCRLF; + + if (end) { + ss << "0" << kCRLF << kCRLF; + } + } + else { + ss << str; + } + + const std::string out = ss.str(); + +# ifdef _WIN32 + uv_buf_t resbuf = uv_buf_init(const_cast(out.c_str()), static_cast(out.size())); +# else + uv_buf_t resbuf = uv_buf_init(const_cast(out.c_str()), out.size()); +# endif + + HttpContext* context = static_cast(parser->data); + + uv_try_write(context->stream(), &resbuf, 1); + + if (end) { + if (!uv_is_closing(context->handle())) { + uv_close(context->handle(), HttpContext::close); + } + } +} + diff --git a/src/base/net/http/HttpResponse.h b/src/base/net/http/HttpResponse.h new file mode 100644 index 00000000..09a5b6fa --- /dev/null +++ b/src/base/net/http/HttpResponse.h @@ -0,0 +1,70 @@ +/* XMRig + * Copyright 2010 Jeff Garzik + * Copyright 2012-2014 pooler + * Copyright 2014 Lucas Jones + * Copyright 2014-2016 Wolf9466 + * Copyright 2016 Jay D Dee + * Copyright 2017-2018 XMR-Stak , + * Copyright 2014-2019 heapwolf + * Copyright 2018-2019 SChernykh + * Copyright 2016-2019 XMRig , + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + + +#ifndef XMRIG_HTTPRESPONSE_H +#define XMRIG_HTTPRESPONSE_H + + +#include +#include +#include + + +typedef struct http_parser http_parser; + + +namespace xmrig { + + +class HttpResponse +{ +public: + HttpResponse(); + + inline void end() { writeOrEnd("", true); } + inline void end(const std::string &str) { writeOrEnd(str, true); } + inline void setHeader(const std::string &key, const std::string &value) { headers.insert({ key, value }); } + inline void setStatus(int code) { statusCode = code; } + inline void write(const std::string &str) { writeOrEnd(str, false); } + + http_parser *parser; + int statusCode; + std::map headers; + std::string body; + std::string statusAdjective; // FIXME + +private: + void writeOrEnd(const std::string &str, bool end); + + bool m_writtenOrEnded = false; +}; + + +} // namespace xmrig + + +#endif // XMRIG_HTTPRESPONSE_H + diff --git a/src/base/net/http/HttpServer.cpp b/src/base/net/http/HttpServer.cpp new file mode 100644 index 00000000..818b212e --- /dev/null +++ b/src/base/net/http/HttpServer.cpp @@ -0,0 +1,108 @@ +/* XMRig + * Copyright 2010 Jeff Garzik + * Copyright 2012-2014 pooler + * Copyright 2014 Lucas Jones + * Copyright 2014-2016 Wolf9466 + * Copyright 2016 Jay D Dee + * Copyright 2017-2018 XMR-Stak , + * Copyright 2014-2019 heapwolf + * Copyright 2018-2019 SChernykh + * Copyright 2016-2019 XMRig , + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + + +#include +#include + + +#include "3rdparty/http-parser/http_parser.h" +#include "base/kernel/interfaces/IHttpListener.h" +#include "base/net/http/HttpContext.h" +#include "base/net/http/HttpResponse.h" +#include "base/net/http/HttpServer.h" + + +xmrig::HttpServer::HttpServer(IHttpListener *listener) : + m_listener(listener) +{ + m_settings = new http_parser_settings(); + + HttpContext::attach(m_settings); + m_settings->on_message_complete = HttpServer::onComplete; +} + + +xmrig::HttpServer::~HttpServer() +{ + delete m_settings; +} + + +void xmrig::HttpServer::onConnection(uv_stream_t *stream, uint16_t) +{ + static std::function onConnect; + static std::function onRead; + + HttpContext *context = new HttpContext(HTTP_REQUEST, m_listener); + uv_accept(stream, context->stream()); + + onRead = [&](uv_stream_t *tcp, ssize_t nread, const uv_buf_t *buf) { + HttpContext* context = static_cast(tcp->data); + + if (nread >= 0) { + const size_t size = static_cast(nread); + const size_t parsed = http_parser_execute(context->parser, m_settings, buf->base, size); + + if (parsed < size) { + uv_close(context->handle(), HttpContext::close); + } + } else { + uv_close(context->handle(), HttpContext::close); + } + + delete [] buf->base; + }; + + uv_read_start(context->stream(), + [](uv_handle_t *, size_t suggested_size, uv_buf_t *buf) + { + buf->base = new char[suggested_size]; + +# ifdef _WIN32 + buf->len = static_cast(suggested_size); +# else + buf->len = suggested_size; +# endif + }, + [](uv_stream_t *tcp, ssize_t nread, const uv_buf_t *buf) + { + onRead(tcp, nread, buf); + }); +} + + +int xmrig::HttpServer::onComplete(http_parser *parser) +{ + HttpContext *context = reinterpret_cast(parser->data); + + HttpResponse res; + res.parser = parser; + + context->listener->onHttp(*context, res); + + return 0; +} + diff --git a/src/base/net/http/HttpServer.h b/src/base/net/http/HttpServer.h new file mode 100644 index 00000000..651be467 --- /dev/null +++ b/src/base/net/http/HttpServer.h @@ -0,0 +1,65 @@ +/* XMRig + * Copyright 2010 Jeff Garzik + * Copyright 2012-2014 pooler + * Copyright 2014 Lucas Jones + * Copyright 2014-2016 Wolf9466 + * Copyright 2016 Jay D Dee + * Copyright 2017-2018 XMR-Stak , + * Copyright 2014-2019 heapwolf + * Copyright 2018-2019 SChernykh + * Copyright 2016-2019 XMRig , + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + + +#ifndef XMRIG_HTTPSERVER_H +#define XMRIG_HTTPSERVER_H + + +typedef struct http_parser http_parser; +typedef struct http_parser_settings http_parser_settings; + + +#include "base/kernel/interfaces/ITcpServerListener.h" + + +namespace xmrig { + + +class IHttpListener; + + +class HttpServer : public ITcpServerListener +{ +public: + HttpServer(IHttpListener *listener); + ~HttpServer() override; + +protected: + void onConnection(uv_stream_t *stream, uint16_t port) override; + +private: + static int onComplete(http_parser *parser); + + http_parser_settings *m_settings; + IHttpListener *m_listener; +}; + + +} // namespace xmrig + + +#endif // XMRIG_HTTPSERVER_H + diff --git a/src/base/net/tools/TcpServer.cpp b/src/base/net/tools/TcpServer.cpp new file mode 100644 index 00000000..e5e6e4e1 --- /dev/null +++ b/src/base/net/tools/TcpServer.cpp @@ -0,0 +1,102 @@ +/* XMRig + * Copyright 2010 Jeff Garzik + * Copyright 2012-2014 pooler + * Copyright 2014 Lucas Jones + * Copyright 2014-2016 Wolf9466 + * Copyright 2016 Jay D Dee + * Copyright 2017-2018 XMR-Stak , + * Copyright 2018-2019 SChernykh + * Copyright 2016-2019 XMRig , + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + + +#include "base/kernel/interfaces/ITcpServerListener.h" +#include "base/net/tools/TcpServer.h" +#include "base/tools/Handle.h" +#include "base/tools/String.h" + + +static const xmrig::String kLocalHost("127.0.0.1"); + + +xmrig::TcpServer::TcpServer(const String &host, uint16_t port, ITcpServerListener *listener) : + m_host(host.isNull() ? kLocalHost : host), + m_version(0), + m_listener(listener), + m_addr(), + m_port(port) +{ + m_tcp = new uv_tcp_t; + uv_tcp_init(uv_default_loop(), m_tcp); + m_tcp->data = this; + + uv_tcp_nodelay(m_tcp, 1); + + if (m_host.contains(":") && uv_ip6_addr(m_host.data(), m_port, reinterpret_cast(&m_addr)) == 0) { + m_version = 6; + } + else if (uv_ip4_addr(m_host.data(), m_port, reinterpret_cast(&m_addr)) == 0) { + m_version = 4; + } +} + + +xmrig::TcpServer::~TcpServer() +{ + Handle::close(m_tcp); +} + + +int xmrig::TcpServer::bind() +{ + if (!m_version) { + return UV_EAI_ADDRFAMILY; + } + + uv_tcp_bind(m_tcp, reinterpret_cast(&m_addr), 0); + + const int rc = uv_listen(reinterpret_cast(m_tcp), 511, TcpServer::onConnection); + if (rc != 0) { + return rc; + } + + if (!m_port) { + sockaddr_storage storage = {}; + int size = sizeof(storage); + + uv_tcp_getsockname(m_tcp, reinterpret_cast(&storage), &size); + + m_port = ntohs(reinterpret_cast(&storage)->sin_port); + } + + return m_port; +} + + +void xmrig::TcpServer::create(uv_stream_t *stream, int status) +{ + if (status < 0) { + return; + } + + m_listener->onConnection(stream, m_port); +} + + +void xmrig::TcpServer::onConnection(uv_stream_t *stream, int status) +{ + static_cast(stream->data)->create(stream, status); +} diff --git a/src/base/net/tools/TcpServer.h b/src/base/net/tools/TcpServer.h new file mode 100644 index 00000000..fc29fa2d --- /dev/null +++ b/src/base/net/tools/TcpServer.h @@ -0,0 +1,64 @@ +/* XMRig + * Copyright 2010 Jeff Garzik + * Copyright 2012-2014 pooler + * Copyright 2014 Lucas Jones + * Copyright 2014-2016 Wolf9466 + * Copyright 2016 Jay D Dee + * Copyright 2017-2018 XMR-Stak , + * Copyright 2018-2019 SChernykh + * Copyright 2016-2019 XMRig , + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef XMRIG_TCPSERVER_H +#define XMRIG_TCPSERVER_H + + +#include + + +namespace xmrig { + + +class ITcpServerListener; +class String; + + +class TcpServer +{ +public: + TcpServer(const String &host, uint16_t port, ITcpServerListener *listener); + ~TcpServer(); + + int bind(); + +private: + void create(uv_stream_t *stream, int status); + + static void onConnection(uv_stream_t *stream, int status); + + const String &m_host; + int m_version; + ITcpServerListener *m_listener; + sockaddr_storage m_addr; + uint16_t m_port; + uv_tcp_t *m_tcp; +}; + + +} /* namespace xmrig */ + + +#endif /* XMRIG_TCPSERVER_H */ diff --git a/src/common/api/Httpd.cpp b/src/common/api/Httpd.cpp deleted file mode 100644 index b80e920e..00000000 --- a/src/common/api/Httpd.cpp +++ /dev/null @@ -1,151 +0,0 @@ -/* XMRig - * Copyright 2010 Jeff Garzik - * Copyright 2012-2014 pooler - * Copyright 2014 Lucas Jones - * Copyright 2014-2016 Wolf9466 - * Copyright 2016 Jay D Dee - * Copyright 2017-2018 XMR-Stak , - * Copyright 2018-2019 SChernykh - * Copyright 2016-2019 XMRig , - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - - -#include -#include - - -#include "api/Api.h" -#include "base/io/log/Log.h" -#include "base/tools/Handle.h" -#include "base/tools/Timer.h" -#include "common/api/Httpd.h" -#include "common/api/HttpReply.h" -#include "common/api/HttpRequest.h" - - -xmrig::Httpd::Httpd(int port, const char *accessToken, bool IPv6, bool restricted) : - m_idle(true), - m_IPv6(IPv6), - m_restricted(restricted), - m_accessToken(accessToken ? strdup(accessToken) : nullptr), - m_port(port), - m_daemon(nullptr) -{ - m_timer = new Timer(this); -} - - -xmrig::Httpd::~Httpd() -{ - stop(); - - if (m_daemon) { - MHD_stop_daemon(m_daemon); - } - - delete m_accessToken; -} - - -bool xmrig::Httpd::start() -{ - if (!m_port) { - return false; - } - - unsigned int flags = 0; -# if MHD_VERSION >= 0x00093500 - if (m_IPv6 && MHD_is_feature_supported(MHD_FEATURE_IPv6)) { - flags |= MHD_USE_DUAL_STACK; - } - - if (MHD_is_feature_supported(MHD_FEATURE_EPOLL)) { - flags |= MHD_USE_EPOLL_LINUX_ONLY; - } -# endif - - m_daemon = MHD_start_daemon(flags, m_port, nullptr, nullptr, &Httpd::handler, this, MHD_OPTION_END); - if (!m_daemon) { - LOG_ERR("HTTP Daemon failed to start."); - return false; - } - -# if MHD_VERSION >= 0x00093900 - m_timer->start(kIdleInterval, kIdleInterval); -# else - m_timer->start(kActiveInterval, kActiveInterval); -# endif - - return true; -} - - -void xmrig::Httpd::stop() -{ - delete m_timer; - m_timer = nullptr; -} - - -int xmrig::Httpd::process(HttpRequest &req) -{ - xmrig::HttpReply reply; - if (!req.process(m_accessToken, m_restricted, reply)) { - return req.end(reply); - } - - if (!req.isFulfilled()) { - return MHD_YES; - } - - Api::exec(req, reply); - - return req.end(reply); -} - - -void xmrig::Httpd::run() -{ - MHD_run(m_daemon); - -# if MHD_VERSION >= 0x00093900 - const MHD_DaemonInfo *info = MHD_get_daemon_info(m_daemon, MHD_DAEMON_INFO_CURRENT_CONNECTIONS); - if (m_idle && info->num_connections) { - m_timer->setRepeat(kActiveInterval); - m_idle = false; - } - else if (!m_idle && !info->num_connections) { - m_timer->setRepeat(kIdleInterval); - m_idle = true; - } -# endif -} - - -int xmrig::Httpd::handler(void *cls, struct MHD_Connection *connection, const char *url, const char *method, const char *, const char *uploadData, size_t *uploadSize, void **con_cls) -{ - HttpRequest req(connection, url, method, uploadData, uploadSize, con_cls); - - if (req.method() == xmrig::HttpRequest::Options) { - return req.end(MHD_HTTP_OK, nullptr); - } - - if (req.method() == xmrig::HttpRequest::Unsupported) { - return req.end(MHD_HTTP_METHOD_NOT_ALLOWED, nullptr); - } - - return static_cast(cls)->process(req); -} diff --git a/src/common/config/CommonConfig.cpp b/src/common/config/CommonConfig.cpp index 04518400..b7ad520f 100644 --- a/src/common/config/CommonConfig.cpp +++ b/src/common/config/CommonConfig.cpp @@ -30,11 +30,6 @@ #include -#ifdef XMRIG_FEATURE_HTTP -# include -#endif - - #ifdef XMRIG_FEATURE_TLS # include #endif @@ -123,10 +118,6 @@ void xmrig::CommonConfig::printVersions() } # endif -# ifdef XMRIG_FEATURE_HTTP - length += snprintf(buf + length, (sizeof buf) - length, "microhttpd/%s ", MHD_get_version()); -# endif - Log::print(GREEN_BOLD(" * ") WHITE_BOLD("%-13slibuv/%s %s"), "LIBS", uv_version_string(), buf); } diff --git a/src/core/Controller.cpp b/src/core/Controller.cpp index 83c96570..26034988 100644 --- a/src/core/Controller.cpp +++ b/src/core/Controller.cpp @@ -29,9 +29,9 @@ #include "base/io/log/backends/ConsoleLog.h" #include "base/io/log/backends/FileLog.h" #include "base/io/log/Log.h" +#include "base/kernel/interfaces/IControllerListener.h" #include "common/config/ConfigLoader.h" #include "common/cpu/Cpu.h" -#include "common/interfaces/IControllerListener.h" #include "common/Platform.h" #include "core/Config.h" #include "core/Controller.h" @@ -157,7 +157,7 @@ void xmrig::Controller::onNewConfig(IConfig *config) Config *previousConfig = d_ptr->config; d_ptr->config = static_cast(config); - for (xmrig::IControllerListener *listener : d_ptr->listeners) { + for (IControllerListener *listener : d_ptr->listeners) { listener->onConfigChanged(d_ptr->config, previousConfig); } diff --git a/src/net/Network.h b/src/net/Network.h index 1a558341..9fa7564d 100644 --- a/src/net/Network.h +++ b/src/net/Network.h @@ -30,9 +30,9 @@ #include "api/NetworkState.h" +#include "base/kernel/interfaces/IControllerListener.h" #include "base/kernel/interfaces/IStrategyListener.h" #include "base/kernel/interfaces/ITimerListener.h" -#include "common/interfaces/IControllerListener.h" #include "interfaces/IJobResultListener.h" From 9daa5874f53989d884db0830d482c6251f66c0d8 Mon Sep 17 00:00:00 2001 From: XMRig Date: Fri, 29 Mar 2019 12:56:34 +0700 Subject: [PATCH 040/116] Change HttpResponse creation method. --- src/api/Httpd.cpp | 4 ++- src/api/Httpd.h | 2 +- src/base/kernel/interfaces/IHttpListener.h | 2 +- src/base/net/http/HttpContext.cpp | 29 +++++++++++++++++++++- src/base/net/http/HttpContext.h | 3 +++ src/base/net/http/HttpRequest.h | 7 ++++++ src/base/net/http/HttpResponse.cpp | 13 ++++++---- src/base/net/http/HttpResponse.h | 7 ++---- src/base/net/http/HttpServer.cpp | 6 ++--- 9 files changed, 55 insertions(+), 18 deletions(-) diff --git a/src/api/Httpd.cpp b/src/api/Httpd.cpp index f3cd7d9f..c1ad1151 100644 --- a/src/api/Httpd.cpp +++ b/src/api/Httpd.cpp @@ -102,8 +102,10 @@ void xmrig::Httpd::onConfigChanged(Config *config, Config *previousConfig) } -void xmrig::Httpd::onHttp(const HttpRequest &req, HttpResponse &res) +void xmrig::Httpd::onHttpRequest(const HttpRequest &req) { + HttpResponse res(req.id()); + LOG_INFO(GREEN_BOLD_S "OK"); res.end(); } diff --git a/src/api/Httpd.h b/src/api/Httpd.h index 1c01fbdd..6a6a1bae 100644 --- a/src/api/Httpd.h +++ b/src/api/Httpd.h @@ -52,7 +52,7 @@ public: protected: void onConfigChanged(Config *config, Config *previousConfig) override; - void onHttp(const HttpRequest &req, HttpResponse &res) override; + void onHttpRequest(const HttpRequest &req) override; private: Controller *m_controller; diff --git a/src/base/kernel/interfaces/IHttpListener.h b/src/base/kernel/interfaces/IHttpListener.h index 73feff54..d4d905ca 100644 --- a/src/base/kernel/interfaces/IHttpListener.h +++ b/src/base/kernel/interfaces/IHttpListener.h @@ -38,7 +38,7 @@ class IHttpListener public: virtual ~IHttpListener() = default; - virtual void onHttp(const HttpRequest &req, HttpResponse &res) = 0; + virtual void onHttpRequest(const HttpRequest &req) = 0; }; diff --git a/src/base/net/http/HttpContext.cpp b/src/base/net/http/HttpContext.cpp index e125b5b9..29dfde7a 100644 --- a/src/base/net/http/HttpContext.cpp +++ b/src/base/net/http/HttpContext.cpp @@ -32,11 +32,22 @@ #include "base/net/http/HttpContext.h" +namespace xmrig { + +static uint64_t SEQUENCE = 0; +std::map HttpContext::m_storage; + +} // namespace xmrig + + xmrig::HttpContext::HttpContext(int parser_type, IHttpListener *listener) : + HttpRequest(SEQUENCE++), listener(listener), connect(nullptr), m_wasHeaderValue(false) { + m_storage[id()] = this; + parser = new http_parser; tcp = new uv_tcp_t; @@ -55,6 +66,16 @@ xmrig::HttpContext::~HttpContext() } +xmrig::HttpContext *xmrig::HttpContext::get(uint64_t id) +{ + if (m_storage.count(id) == 0) { + return nullptr; + } + + return m_storage[id]; +} + + void xmrig::HttpContext::attach(http_parser_settings *settings) { settings->on_message_begin = nullptr; @@ -93,7 +114,13 @@ void xmrig::HttpContext::attach(http_parser_settings *settings) void xmrig::HttpContext::close(uv_handle_t* handle) { - delete reinterpret_cast(handle->data); + HttpContext *ctx = reinterpret_cast(handle->data); + auto it = m_storage.find(ctx->id()); + if (it != m_storage.end()) { + m_storage.erase(it); + } + + delete ctx; } diff --git a/src/base/net/http/HttpContext.h b/src/base/net/http/HttpContext.h index 06c66e3b..5e9c234a 100644 --- a/src/base/net/http/HttpContext.h +++ b/src/base/net/http/HttpContext.h @@ -54,6 +54,7 @@ public: inline uv_stream_t *stream() const { return reinterpret_cast(tcp); } inline uv_handle_t *handle() const { return reinterpret_cast(tcp); } + static HttpContext *get(uint64_t id); static void attach(http_parser_settings *settings); static void close(uv_handle_t* handle); @@ -71,6 +72,8 @@ private: bool m_wasHeaderValue; std::string m_lastHeaderField; std::string m_lastHeaderValue; + + static std::map m_storage; }; diff --git a/src/base/net/http/HttpRequest.h b/src/base/net/http/HttpRequest.h index 2f2f22a8..25f77aa5 100644 --- a/src/base/net/http/HttpRequest.h +++ b/src/base/net/http/HttpRequest.h @@ -39,10 +39,17 @@ namespace xmrig { class HttpRequest { public: + inline HttpRequest(uint64_t id) : m_id(id) {} + + inline uint64_t id() const { return m_id; } + std::string url; std::string method; std::stringstream body; std::map headers; + +private: + const uint64_t m_id; }; diff --git a/src/base/net/http/HttpResponse.cpp b/src/base/net/http/HttpResponse.cpp index ffccf1c9..f53eb894 100644 --- a/src/base/net/http/HttpResponse.cpp +++ b/src/base/net/http/HttpResponse.cpp @@ -40,18 +40,23 @@ static const char *kTransferEncoding = "Transfer-Encoding"; } // namespace xmrig -xmrig::HttpResponse::HttpResponse() : - parser(nullptr), +xmrig::HttpResponse::HttpResponse(uint64_t id) : statusCode(HTTP_STATUS_OK), body(""), statusAdjective("OK"), // FIXME - m_writtenOrEnded(false) + m_writtenOrEnded(false), + m_id(id) { } void xmrig::HttpResponse::writeOrEnd(const std::string &str, bool end) { + HttpContext *context = HttpContext::get(m_id); + if (!context) { + return; + } + std::stringstream ss; if (!m_writtenOrEnded) { @@ -84,8 +89,6 @@ void xmrig::HttpResponse::writeOrEnd(const std::string &str, bool end) uv_buf_t resbuf = uv_buf_init(const_cast(out.c_str()), out.size()); # endif - HttpContext* context = static_cast(parser->data); - uv_try_write(context->stream(), &resbuf, 1); if (end) { diff --git a/src/base/net/http/HttpResponse.h b/src/base/net/http/HttpResponse.h index 09a5b6fa..4757bd89 100644 --- a/src/base/net/http/HttpResponse.h +++ b/src/base/net/http/HttpResponse.h @@ -33,16 +33,13 @@ #include -typedef struct http_parser http_parser; - - namespace xmrig { class HttpResponse { public: - HttpResponse(); + HttpResponse(uint64_t id); inline void end() { writeOrEnd("", true); } inline void end(const std::string &str) { writeOrEnd(str, true); } @@ -50,7 +47,6 @@ public: inline void setStatus(int code) { statusCode = code; } inline void write(const std::string &str) { writeOrEnd(str, false); } - http_parser *parser; int statusCode; std::map headers; std::string body; @@ -60,6 +56,7 @@ private: void writeOrEnd(const std::string &str, bool end); bool m_writtenOrEnded = false; + const uint64_t m_id; }; diff --git a/src/base/net/http/HttpServer.cpp b/src/base/net/http/HttpServer.cpp index 818b212e..245451c2 100644 --- a/src/base/net/http/HttpServer.cpp +++ b/src/base/net/http/HttpServer.cpp @@ -97,11 +97,9 @@ void xmrig::HttpServer::onConnection(uv_stream_t *stream, uint16_t) int xmrig::HttpServer::onComplete(http_parser *parser) { HttpContext *context = reinterpret_cast(parser->data); + HttpResponse res(context->id()); - HttpResponse res; - res.parser = parser; - - context->listener->onHttp(*context, res); + context->listener->onHttpRequest(*context); return 0; } From 202b74367ae1fd210b26bef5b589e081e1daa4ed Mon Sep 17 00:00:00 2001 From: XMRig Date: Fri, 29 Mar 2019 14:22:10 +0700 Subject: [PATCH 041/116] Optimize HttpResponse for fixed size API responses. --- src/api/Httpd.cpp | 3 +- src/base/net/http/HttpResponse.cpp | 85 +++++++++++++++++------------- src/base/net/http/HttpResponse.h | 20 +++---- 3 files changed, 56 insertions(+), 52 deletions(-) diff --git a/src/api/Httpd.cpp b/src/api/Httpd.cpp index c1ad1151..ea5bd252 100644 --- a/src/api/Httpd.cpp +++ b/src/api/Httpd.cpp @@ -105,7 +105,8 @@ void xmrig::Httpd::onConfigChanged(Config *config, Config *previousConfig) void xmrig::Httpd::onHttpRequest(const HttpRequest &req) { HttpResponse res(req.id()); + res.setStatus(200); LOG_INFO(GREEN_BOLD_S "OK"); - res.end(); + res.end("{}"); } diff --git a/src/base/net/http/HttpResponse.cpp b/src/base/net/http/HttpResponse.cpp index f53eb894..c9c51de7 100644 --- a/src/base/net/http/HttpResponse.cpp +++ b/src/base/net/http/HttpResponse.cpp @@ -25,6 +25,7 @@ #include +#include #include "3rdparty/http-parser/http_parser.h" @@ -34,67 +35,75 @@ namespace xmrig { -static const char *kCRLF = "\r\n"; -static const char *kTransferEncoding = "Transfer-Encoding"; +static const char *kCRLF = "\r\n"; } // namespace xmrig xmrig::HttpResponse::HttpResponse(uint64_t id) : - statusCode(HTTP_STATUS_OK), - body(""), - statusAdjective("OK"), // FIXME - m_writtenOrEnded(false), - m_id(id) + m_id(id), + m_statusCode(HTTP_STATUS_OK) { } -void xmrig::HttpResponse::writeOrEnd(const std::string &str, bool end) +bool xmrig::HttpResponse::isAlive() const { - HttpContext *context = HttpContext::get(m_id); - if (!context) { + HttpContext *ctx = HttpContext::get(m_id); + + return ctx && uv_is_writable(ctx->stream()); +} + + +void xmrig::HttpResponse::end(const char *data, size_t size) +{ + if (!isAlive()) { return; } + if (data && !size) { + size = strlen(data); + } + + if (size) { + setHeader("Content-Length", std::to_string(size)); + } + + setHeader("Connection", "close"); + std::stringstream ss; + ss << "HTTP/1.1 " << statusCode() << " " << http_status_str(static_cast(statusCode())) << kCRLF; - if (!m_writtenOrEnded) { - ss << "HTTP/1.1 " << statusCode << " " << statusAdjective << kCRLF; - - for (auto &header : headers) { - ss << header.first << ": " << header.second << kCRLF; - } - - ss << kCRLF; - m_writtenOrEnded = true; + for (auto &header : m_headers) { + ss << header.first << ": " << header.second << kCRLF; } - if (headers.count(kTransferEncoding) && headers[kTransferEncoding] == "chunked") { - ss << std::hex << str.size() << std::dec << kCRLF << str << kCRLF; + ss << kCRLF; + const std::string header = ss.str(); - if (end) { - ss << "0" << kCRLF << kCRLF; - } - } - else { - ss << str; - } - - const std::string out = ss.str(); + uv_buf_t bufs[2]; + bufs[0].base = const_cast(header.c_str()); # ifdef _WIN32 - uv_buf_t resbuf = uv_buf_init(const_cast(out.c_str()), static_cast(out.size())); + bufs[0].len = static_cast(header.size()); # else - uv_buf_t resbuf = uv_buf_init(const_cast(out.c_str()), out.size()); + bufs[0].len = header.size(); # endif - uv_try_write(context->stream(), &resbuf, 1); + if (data) { + bufs[1].base = const_cast(data); - if (end) { - if (!uv_is_closing(context->handle())) { - uv_close(context->handle(), HttpContext::close); - } +# ifdef _WIN32 + bufs[1].len = static_cast(size); +# else + bufs[0].len = size; +# endif + } + + HttpContext *ctx = HttpContext::get(m_id); + uv_try_write(ctx->stream(), bufs, data ? 2 : 1); + + if (!uv_is_closing(ctx->handle())) { + uv_close(ctx->handle(), HttpContext::close); } } - diff --git a/src/base/net/http/HttpResponse.h b/src/base/net/http/HttpResponse.h index 4757bd89..f8296b89 100644 --- a/src/base/net/http/HttpResponse.h +++ b/src/base/net/http/HttpResponse.h @@ -29,7 +29,6 @@ #include -#include #include @@ -41,22 +40,17 @@ class HttpResponse public: HttpResponse(uint64_t id); - inline void end() { writeOrEnd("", true); } - inline void end(const std::string &str) { writeOrEnd(str, true); } - inline void setHeader(const std::string &key, const std::string &value) { headers.insert({ key, value }); } - inline void setStatus(int code) { statusCode = code; } - inline void write(const std::string &str) { writeOrEnd(str, false); } + inline int statusCode() const { return m_statusCode; } + inline void setHeader(const std::string &key, const std::string &value) { m_headers.insert({ key, value }); } + inline void setStatus(int code) { m_statusCode = code; } - int statusCode; - std::map headers; - std::string body; - std::string statusAdjective; // FIXME + bool isAlive() const; + void end(const char *data = nullptr, size_t size = 0); private: - void writeOrEnd(const std::string &str, bool end); - - bool m_writtenOrEnded = false; const uint64_t m_id; + int m_statusCode; + std::map m_headers; }; From 3f1eefb131656f647e160a8433189de43622ec7c Mon Sep 17 00:00:00 2001 From: XMRig Date: Fri, 29 Mar 2019 17:14:30 +0700 Subject: [PATCH 042/116] HTTP layer ready for API calls. --- src/api/Httpd.cpp | 62 +++++++++++++++++++++-- src/api/Httpd.h | 2 + src/base/base.cmake | 2 + src/base/net/http/Http.h | 1 + src/base/net/http/HttpApiResponse.cpp | 73 +++++++++++++++++++++++++++ src/base/net/http/HttpApiResponse.h | 57 +++++++++++++++++++++ src/base/net/http/HttpContext.cpp | 4 +- src/base/net/http/HttpRequest.h | 8 +-- 8 files changed, 198 insertions(+), 11 deletions(-) create mode 100644 src/base/net/http/HttpApiResponse.cpp create mode 100644 src/base/net/http/HttpApiResponse.h diff --git a/src/api/Httpd.cpp b/src/api/Httpd.cpp index ea5bd252..2e3194e6 100644 --- a/src/api/Httpd.cpp +++ b/src/api/Httpd.cpp @@ -23,16 +23,25 @@ */ +#include "3rdparty/http-parser/http_parser.h" #include "api/Httpd.h" #include "base/io/log/Log.h" #include "base/net/http/HttpRequest.h" -#include "base/net/http/HttpResponse.h" +#include "base/net/http/HttpApiResponse.h" #include "base/net/http/HttpServer.h" #include "base/net/tools/TcpServer.h" #include "core/Config.h" #include "core/Controller.h" +namespace xmrig { + +static const char *kAuthorization = "authorization"; +static const char *kContentType = "content-type"; + +} // namespace xmrig + + xmrig::Httpd::Httpd(Controller *controller) : m_controller(controller), m_http(nullptr), @@ -104,9 +113,52 @@ void xmrig::Httpd::onConfigChanged(Config *config, Config *previousConfig) void xmrig::Httpd::onHttpRequest(const HttpRequest &req) { - HttpResponse res(req.id()); - res.setStatus(200); + if (req.method == HTTP_OPTIONS) { + return HttpApiResponse(req.id()).end(); + } - LOG_INFO(GREEN_BOLD_S "OK"); - res.end("{}"); + if (req.method > 4) { + return HttpApiResponse(req.id(), HTTP_STATUS_METHOD_NOT_ALLOWED).end(); + } + + const int status = auth(req); + if (status != HTTP_STATUS_OK) { + return HttpApiResponse(req.id(), status).end(); + } + + if (req.method != HTTP_GET) { + if (m_controller->config()->http().isRestricted()) { + return HttpApiResponse(req.id(), HTTP_STATUS_FORBIDDEN).end(); + } + + if (!req.headers.count(kContentType) || req.headers.at(kContentType) != "application/json") { + return HttpApiResponse(req.id(), HTTP_STATUS_UNSUPPORTED_MEDIA_TYPE).end(); + } + } + + HttpApiResponse res(req.id()); + res.end(); +} + + +int xmrig::Httpd::auth(const HttpRequest &req) const +{ + const Http &config = m_controller->config()->http(); + + if (!req.headers.count(kAuthorization)) { + return config.isAuthRequired() ? HTTP_STATUS_UNAUTHORIZED : HTTP_STATUS_OK; + } + + if (config.token().isNull()) { + return HTTP_STATUS_UNAUTHORIZED; + } + + const std::string &token = req.headers.at(kAuthorization); + const size_t size = token.size(); + + if (token.size() < 8 || config.token().size() != size - 7 || memcmp("Bearer ", token.c_str(), 7) != 0) { + return HTTP_STATUS_FORBIDDEN; + } + + return strncmp(config.token().data(), token.c_str() + 7, config.token().size()) == 0 ? HTTP_STATUS_OK : HTTP_STATUS_FORBIDDEN; } diff --git a/src/api/Httpd.h b/src/api/Httpd.h index 6a6a1bae..99ee2e88 100644 --- a/src/api/Httpd.h +++ b/src/api/Httpd.h @@ -55,6 +55,8 @@ protected: void onHttpRequest(const HttpRequest &req) override; private: + int auth(const HttpRequest &req) const; + Controller *m_controller; HttpServer *m_http; TcpServer *m_server; diff --git a/src/base/base.cmake b/src/base/base.cmake index 5bc3fd2d..09c28d0e 100644 --- a/src/base/base.cmake +++ b/src/base/base.cmake @@ -87,6 +87,7 @@ if (WITH_HTTPD) src/3rdparty/http-parser/http_parser.h src/base/kernel/interfaces/IHttpListener.h src/base/kernel/interfaces/ITcpServerListener.h + src/base/net/http/HttpApiResponse.h src/base/net/http/HttpContext.h src/base/net/http/HttpRequest.h src/base/net/http/HttpResponse.h @@ -96,6 +97,7 @@ if (WITH_HTTPD) set(SOURCES_BASE_HTTP src/3rdparty/http-parser/http_parser.c + src/base/net/http/HttpApiResponse.cpp src/base/net/http/HttpContext.cpp src/base/net/http/HttpResponse.cpp src/base/net/http/HttpServer.cpp diff --git a/src/base/net/http/Http.h b/src/base/net/http/Http.h index f8aa15bb..21eb581a 100644 --- a/src/base/net/http/Http.h +++ b/src/base/net/http/Http.h @@ -38,6 +38,7 @@ class Http public: Http(); + inline bool isAuthRequired() const { return m_restricted == false || !m_token.isNull(); } inline bool isEnabled() const { return m_enabled; } inline bool isRestricted() const { return m_restricted; } inline const String &host() const { return m_host; } diff --git a/src/base/net/http/HttpApiResponse.cpp b/src/base/net/http/HttpApiResponse.cpp new file mode 100644 index 00000000..56dd9bb8 --- /dev/null +++ b/src/base/net/http/HttpApiResponse.cpp @@ -0,0 +1,73 @@ +/* XMRig + * Copyright 2010 Jeff Garzik + * Copyright 2012-2014 pooler + * Copyright 2014 Lucas Jones + * Copyright 2014-2016 Wolf9466 + * Copyright 2016 Jay D Dee + * Copyright 2017-2018 XMR-Stak , + * Copyright 2014-2019 heapwolf + * Copyright 2018-2019 SChernykh + * Copyright 2016-2019 XMRig , + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + + +#include "3rdparty/http-parser/http_parser.h" +#include "base/net/http/HttpApiResponse.h" +#include "rapidjson/prettywriter.h" +#include "rapidjson/stringbuffer.h" + + +xmrig::HttpApiResponse::HttpApiResponse(uint64_t id) : + HttpResponse(id), + m_doc(rapidjson::kObjectType) +{ +} + + +xmrig::HttpApiResponse::HttpApiResponse(uint64_t id, int status) : + HttpResponse(id), + m_doc(rapidjson::kObjectType) +{ + setStatus(status); +} + + +void xmrig::HttpApiResponse::end() +{ + using namespace rapidjson; + + setHeader("Access-Control-Allow-Origin", "*"); + setHeader("Access-Control-Allow-Methods", "GET, PUT, POST, DELETE"); + setHeader("Access-Control-Allow-Headers", "Authorization, Content-Type"); + + if (statusCode() >= 400 && !m_doc.MemberCount()) { + m_doc.AddMember("status", statusCode(), m_doc.GetAllocator()); + m_doc.AddMember("error", StringRef(http_status_str(static_cast(statusCode()))), m_doc.GetAllocator()); + } + + if (!m_doc.MemberCount()) { + return HttpResponse::end(); + } + + setHeader("Content-Type", "application/json"); + + StringBuffer buffer(nullptr, 4096); + PrettyWriter writer(buffer); + writer.SetMaxDecimalPlaces(10); + m_doc.Accept(writer); + + HttpResponse::end(buffer.GetString(), buffer.GetSize()); +} diff --git a/src/base/net/http/HttpApiResponse.h b/src/base/net/http/HttpApiResponse.h new file mode 100644 index 00000000..bbaf132e --- /dev/null +++ b/src/base/net/http/HttpApiResponse.h @@ -0,0 +1,57 @@ +/* XMRig + * Copyright 2010 Jeff Garzik + * Copyright 2012-2014 pooler + * Copyright 2014 Lucas Jones + * Copyright 2014-2016 Wolf9466 + * Copyright 2016 Jay D Dee + * Copyright 2017-2018 XMR-Stak , + * Copyright 2014-2019 heapwolf + * Copyright 2018-2019 SChernykh + * Copyright 2016-2019 XMRig , + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + + +#ifndef XMRIG_HTTPAPIRESPONSE_H +#define XMRIG_HTTPAPIRESPONSE_H + + +#include "base/net/http/HttpResponse.h" +#include "rapidjson/document.h" + + +namespace xmrig { + + +class HttpApiResponse : public HttpResponse +{ +public: + HttpApiResponse(uint64_t id); + HttpApiResponse(uint64_t id, int status); + + inline rapidjson::Document &doc() { return m_doc; } + + void end(); + +private: + rapidjson::Document m_doc; +}; + + +} // namespace xmrig + + +#endif // XMRIG_HTTPAPIRESPONSE_H + diff --git a/src/base/net/http/HttpContext.cpp b/src/base/net/http/HttpContext.cpp index 29dfde7a..e0a1e83c 100644 --- a/src/base/net/http/HttpContext.cpp +++ b/src/base/net/http/HttpContext.cpp @@ -94,7 +94,7 @@ void xmrig::HttpContext::attach(http_parser_settings *settings) settings->on_headers_complete = [](http_parser* parser) -> int { HttpContext *ctx = static_cast(parser->data); - ctx->method = std::string(http_method_str(static_cast(parser->method))); + ctx->method = parser->method; if (!ctx->m_lastHeaderField.empty()) { ctx->setHeader(); @@ -105,7 +105,7 @@ void xmrig::HttpContext::attach(http_parser_settings *settings) settings->on_body = [](http_parser *parser, const char *at, size_t len) -> int { - static_cast(parser->data)->body << std::string(at, len); + static_cast(parser->data)->body += std::string(at, len); return 0; }; diff --git a/src/base/net/http/HttpRequest.h b/src/base/net/http/HttpRequest.h index 25f77aa5..b97f0b8d 100644 --- a/src/base/net/http/HttpRequest.h +++ b/src/base/net/http/HttpRequest.h @@ -39,14 +39,14 @@ namespace xmrig { class HttpRequest { public: - inline HttpRequest(uint64_t id) : m_id(id) {} + inline HttpRequest(uint64_t id) : method(0), m_id(id) {} inline uint64_t id() const { return m_id; } - std::string url; - std::string method; - std::stringstream body; + int method; std::map headers; + std::string body; + std::string url; private: const uint64_t m_id; From 9cb43f988327984a98d7a72c8ab32a72996f71f0 Mon Sep 17 00:00:00 2001 From: XMRig Date: Fri, 29 Mar 2019 17:22:25 +0700 Subject: [PATCH 043/116] Fix log. --- src/base/io/log/Log.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/base/io/log/Log.cpp b/src/base/io/log/Log.cpp index 4a2a8de6..487cd9b8 100644 --- a/src/base/io/log/Log.cpp +++ b/src/base/io/log/Log.cpp @@ -93,12 +93,12 @@ public: timestamp(level, size, offset); color(level, size); - int rc = vsnprintf(m_buf + size, sizeof (m_buf) - offset - 32, fmt, args); + const int rc = vsnprintf(m_buf + size, sizeof (m_buf) - offset - 32, fmt, args); if (rc < 0) { return unlock(); } - size += static_cast(rc); + size += std::min(static_cast(rc), sizeof (m_buf) - offset - 32); endl(size); std::string txt(m_buf); From dd036368e2f9c9c48bd2eaf63f2c156afeb2f801 Mon Sep 17 00:00:00 2001 From: XMRig Date: Sat, 30 Mar 2019 00:16:01 +0700 Subject: [PATCH 044/116] New API class. --- CMakeLists.txt | 4 +- src/App.cpp | 25 +------- src/App.h | 2 - src/api/Api.cpp | 124 ++++++++++++++++++++++++++++++++-------- src/api/Api.h | 46 +++++++++------ src/api/ApiRouter.h | 2 +- src/api/Httpd.cpp | 6 +- src/base/base.cmake | 1 - src/core/Controller.cpp | 37 ++++++++++++ src/core/Controller.h | 3 + src/net/Network.cpp | 2 +- 11 files changed, 178 insertions(+), 74 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index eb0c8936..1522da86 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -203,13 +203,13 @@ endif() if (WITH_HTTPD) set(HTTPD_SOURCES -# src/api/Api.h + src/api/Api.h # src/api/ApiRouter.h # src/common/api/HttpBody.h src/api/Httpd.h # src/common/api/HttpReply.h # src/common/api/HttpRequest.h -# src/api/Api.cpp + src/api/Api.cpp # src/api/ApiRouter.cpp src/api/Httpd.cpp # src/common/api/HttpRequest.cpp diff --git a/src/App.cpp b/src/App.cpp index 08597eda..f7e80ef7 100644 --- a/src/App.cpp +++ b/src/App.cpp @@ -45,14 +45,8 @@ #include "workers/Workers.h" -#ifdef XMRIG_FEATURE_HTTP -# include "api/Httpd.h" -#endif - - xmrig::App::App(Process *process) : m_console(nullptr), - m_httpd(nullptr), m_signals(nullptr) { m_controller = new Controller(process); @@ -71,10 +65,6 @@ xmrig::App::~App() delete m_signals; delete m_console; delete m_controller; - -# ifdef XMRIG_FEATURE_HTTP - delete m_httpd; -# endif } @@ -98,18 +88,9 @@ int xmrig::App::exec() return 0; } -# ifdef XMRIG_FEATURE_API - Api::start(m_controller); -# endif - -# ifdef XMRIG_FEATURE_HTTP - m_httpd = new Httpd(m_controller); - m_httpd->start(); -# endif - Workers::start(m_controller); - m_controller->network()->connect(); + m_controller->start(); const int r = uv_run(uv_default_loop(), UV_RUN_DEFAULT); uv_loop_close(uv_default_loop()); @@ -179,10 +160,6 @@ void xmrig::App::onSignal(int signum) void xmrig::App::close() { -# ifdef XMRIG_FEATURE_HTTP - m_httpd->stop(); -# endif - m_signals->stop(); m_console->stop(); m_controller->stop(); diff --git a/src/App.h b/src/App.h index 86f281e8..aa534aad 100644 --- a/src/App.h +++ b/src/App.h @@ -36,7 +36,6 @@ namespace xmrig { class Console; class Controller; -class Httpd; class Network; class Process; class Signals; @@ -60,7 +59,6 @@ private: Console *m_console; Controller *m_controller; - Httpd *m_httpd; Signals *m_signals; }; diff --git a/src/api/Api.cpp b/src/api/Api.cpp index 2abdf4be..84463922 100644 --- a/src/api/Api.cpp +++ b/src/api/Api.cpp @@ -22,52 +22,128 @@ * along with this program. If not, see . */ -#include + +#include #include "api/Api.h" -#include "api/ApiRouter.h" -#include "common/api/HttpReply.h" -#include "common/api/HttpRequest.h" +#include "base/tools/Buffer.h" +#include "common/crypto/keccak.h" +#include "core/Config.h" +#include "core/Controller.h" +#include "version.h" -ApiRouter *Api::m_router = nullptr; +#ifdef XMRIG_FEATURE_HTTP +# include "api/Httpd.h" +#endif -bool Api::start(xmrig::Controller *controller) +xmrig::Api::Api(Controller *controller) : + m_id(), + m_workerId(), + m_controller(controller), + m_httpd(nullptr) { - m_router = new ApiRouter(controller); + controller->addListener(this); - return true; + genId(m_controller->config()->apiId()); } -void Api::release() +xmrig::Api::~Api() { - delete m_router; +# ifdef XMRIG_FEATURE_HTTP + delete m_httpd; +# endif } -void Api::exec(const xmrig::HttpRequest &req, xmrig::HttpReply &reply) +void xmrig::Api::request(const HttpRequest &req) { - if (!m_router) { - reply.status = 500; + +} + + +void xmrig::Api::start() +{ + genWorkerId(m_controller->config()->apiWorkerId()); + +# ifdef XMRIG_FEATURE_HTTP + m_httpd = new Httpd(m_controller); + m_httpd->start(); +# endif +} + + +void xmrig::Api::stop() +{ +# ifdef XMRIG_FEATURE_HTTP + m_httpd->stop(); +# endif +} + + +void xmrig::Api::onConfigChanged(Config *config, Config *previousConfig) +{ + if (config->apiId() != previousConfig->apiId()) { + genId(config->apiId()); + } + + if (config->apiWorkerId() != previousConfig->apiWorkerId()) { + genWorkerId(config->apiWorkerId()); + } +} + + +void xmrig::Api::genId(const String &id) +{ + memset(m_id, 0, sizeof(m_id)); + + if (id.size() > 0) { + strncpy(m_id, id.data(), sizeof(m_id) - 1); return; } - if (req.method() == xmrig::HttpRequest::Get) { - return m_router->get(req, reply); - } + uv_interface_address_t *interfaces; + int count = 0; - m_router->exec(req, reply); -} - - -void Api::tick(const xmrig::NetworkState &network) -{ - if (!m_router) { + if (uv_interface_addresses(&interfaces, &count) < 0) { return; } - m_router->tick(network); + for (int i = 0; i < count; i++) { + if (!interfaces[i].is_internal && interfaces[i].address.address4.sin_family == AF_INET) { + uint8_t hash[200]; + const size_t addrSize = sizeof(interfaces[i].phys_addr); + const size_t inSize = strlen(APP_KIND) + addrSize + sizeof(uint16_t); + const uint16_t port = static_cast(m_controller->config()->http().port()); + + uint8_t *input = new uint8_t[inSize](); + memcpy(input, &port, sizeof(uint16_t)); + memcpy(input + sizeof(uint16_t), interfaces[i].phys_addr, addrSize); + memcpy(input + sizeof(uint16_t) + addrSize, APP_KIND, strlen(APP_KIND)); + + xmrig::keccak(input, inSize, hash); + xmrig::Buffer::toHex(hash, 8, m_id); + + delete [] input; + break; + } + } + + uv_free_interface_addresses(interfaces, count); +} + + +void xmrig::Api::genWorkerId(const String &id) +{ + memset(m_workerId, 0, sizeof(m_workerId)); + + if (id.size() > 0) { + strncpy(m_workerId, id.data(), sizeof(m_workerId) - 1); + } + else { + gethostname(m_workerId, sizeof(m_workerId) - 1); + } } diff --git a/src/api/Api.h b/src/api/Api.h index caee887a..a46e95c1 100644 --- a/src/api/Api.h +++ b/src/api/Api.h @@ -26,32 +26,46 @@ #define XMRIG_API_H -#include - - -class ApiRouter; -class Hashrate; +#include "base/kernel/interfaces/IControllerListener.h" namespace xmrig { - class Controller; - class HttpReply; - class HttpRequest; - class NetworkState; -} -class Api +class Controller; +class Httpd; +class HttpRequest; +class String; + + +class Api : public IControllerListener { public: - static bool start(xmrig::Controller *controller); - static void release(); + Api(Controller *controller); + ~Api() override; - static void exec(const xmrig::HttpRequest &req, xmrig::HttpReply &reply); - static void tick(const xmrig::NetworkState &results); + inline const char *id() const { return m_id; } + inline const char *workerId() const { return m_workerId; } + + void request(const HttpRequest &req); + void start(); + void stop(); + +protected: + void onConfigChanged(Config *config, Config *previousConfig) override; private: - static ApiRouter *m_router; + void genId(const String &id); + void genWorkerId(const String &id); + + char m_id[32]; + char m_workerId[128]; + Controller *m_controller; + Httpd *m_httpd; }; + +} // namespace xmrig + + #endif /* XMRIG_API_H */ diff --git a/src/api/ApiRouter.h b/src/api/ApiRouter.h index a92173ce..61c05201 100644 --- a/src/api/ApiRouter.h +++ b/src/api/ApiRouter.h @@ -27,7 +27,7 @@ #include "api/NetworkState.h" -#include "common/interfaces/IControllerListener.h" +#include "base/kernel/interfaces/IControllerListener.h" #include "rapidjson/fwd.h" diff --git a/src/api/Httpd.cpp b/src/api/Httpd.cpp index 2e3194e6..444fdb3e 100644 --- a/src/api/Httpd.cpp +++ b/src/api/Httpd.cpp @@ -24,10 +24,11 @@ #include "3rdparty/http-parser/http_parser.h" +#include "api/Api.h" #include "api/Httpd.h" #include "base/io/log/Log.h" -#include "base/net/http/HttpRequest.h" #include "base/net/http/HttpApiResponse.h" +#include "base/net/http/HttpRequest.h" #include "base/net/http/HttpServer.h" #include "base/net/tools/TcpServer.h" #include "core/Config.h" @@ -136,8 +137,7 @@ void xmrig::Httpd::onHttpRequest(const HttpRequest &req) } } - HttpApiResponse res(req.id()); - res.end(); + m_controller->api()->request(req); } diff --git a/src/base/base.cmake b/src/base/base.cmake index 09c28d0e..5f32f425 100644 --- a/src/base/base.cmake +++ b/src/base/base.cmake @@ -106,7 +106,6 @@ if (WITH_HTTPD) add_definitions(/DXMRIG_FEATURE_HTTP) add_definitions(/DXMRIG_FEATURE_API) - remove_definitions(/DXMRIG_FEATURE_API) else() set(HEADERS_BASE_HTTP "") set(SOURCES_BASE_HTTP "") diff --git a/src/core/Controller.cpp b/src/core/Controller.cpp index 26034988..fe1537f3 100644 --- a/src/core/Controller.cpp +++ b/src/core/Controller.cpp @@ -43,10 +43,16 @@ #endif +#ifdef XMRIG_FEATURE_API +# include "api/Api.h" +#endif + + class xmrig::ControllerPrivate { public: inline ControllerPrivate(Process *process) : + api(nullptr), config(nullptr), network(nullptr), process(process) @@ -55,11 +61,16 @@ public: inline ~ControllerPrivate() { +# ifdef XMRIG_FEATURE_API + delete api; +# endif + delete network; delete config; } + Api *api; Config *config; Network *network; Process *process; @@ -79,6 +90,14 @@ xmrig::Controller::~Controller() } +xmrig::Api *xmrig::Controller::api() const +{ + assert(d_ptr->api != nullptr); + + return d_ptr->api; +} + + bool xmrig::Controller::isReady() const { return d_ptr->config && d_ptr->network; @@ -102,6 +121,10 @@ int xmrig::Controller::init() return 1; } +# ifdef XMRIG_FEATURE_API + d_ptr->api = new Api(this); +# endif + Platform::init(config()->userAgent()); Platform::setProcessPriority(d_ptr->config->priority()); @@ -165,8 +188,22 @@ void xmrig::Controller::onNewConfig(IConfig *config) } +void xmrig::Controller::start() +{ + network()->connect(); + +# ifdef XMRIG_FEATURE_API + api()->start(); +# endif +} + + void xmrig::Controller::stop() { +# ifdef XMRIG_FEATURE_API + api()->stop(); +# endif + ConfigLoader::release(); delete d_ptr->network; diff --git a/src/core/Controller.h b/src/core/Controller.h index 7c74b53c..82a90b84 100644 --- a/src/core/Controller.h +++ b/src/core/Controller.h @@ -35,6 +35,7 @@ class StatsData; namespace xmrig { +class Api; class Config; class ControllerPrivate; class IControllerListener; @@ -48,12 +49,14 @@ public: Controller(Process *process); ~Controller() override; + Api *api() const; bool isReady() const; Config *config() const; int init(); Network *network() const; void addListener(IControllerListener *listener); void save(); + void start(); void stop(); protected: diff --git a/src/net/Network.cpp b/src/net/Network.cpp index b8e2e012..7f3f81d3 100644 --- a/src/net/Network.cpp +++ b/src/net/Network.cpp @@ -198,6 +198,6 @@ void xmrig::Network::tick() } # ifdef XMRIG_FEATURE_API - Api::tick(m_state); + //Api::tick(m_state); # endif } From 9c66c9b30f184169da764d12d8726cd6f6b0c57f Mon Sep 17 00:00:00 2001 From: XMRig Date: Sat, 30 Mar 2019 02:26:30 +0700 Subject: [PATCH 045/116] Added classes IApiRequest, ApiRequest, HttpApiRequest. --- CMakeLists.txt | 11 ++-- src/api/Api.cpp | 12 +++++ src/api/Api.h | 2 + src/api/interfaces/IApiRequest.h | 72 +++++++++++++++++++++++++++ src/api/requests/ApiRequest.cpp | 39 +++++++++++++++ src/api/requests/ApiRequest.h | 67 +++++++++++++++++++++++++ src/api/requests/HttpApiRequest.cpp | 55 ++++++++++++++++++++ src/api/requests/HttpApiRequest.h | 67 +++++++++++++++++++++++++ src/base/net/http/HttpApiResponse.cpp | 19 +++++-- 9 files changed, 335 insertions(+), 9 deletions(-) create mode 100644 src/api/interfaces/IApiRequest.h create mode 100644 src/api/requests/ApiRequest.cpp create mode 100644 src/api/requests/ApiRequest.h create mode 100644 src/api/requests/HttpApiRequest.cpp create mode 100644 src/api/requests/HttpApiRequest.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 1522da86..57df6d59 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -204,15 +204,14 @@ endif() if (WITH_HTTPD) set(HTTPD_SOURCES src/api/Api.h -# src/api/ApiRouter.h -# src/common/api/HttpBody.h + src/api/interfaces/IApiRequest.h + src/api/requests/ApiRequest.h + src/api/requests/ApiRequest.cpp + src/api/requests/HttpApiRequest.h src/api/Httpd.h -# src/common/api/HttpReply.h -# src/common/api/HttpRequest.h src/api/Api.cpp -# src/api/ApiRouter.cpp + src/api/requests/HttpApiRequest.cpp src/api/Httpd.cpp -# src/common/api/HttpRequest.cpp ) else() set(HTTPD_SOURCES "") diff --git a/src/api/Api.cpp b/src/api/Api.cpp index 84463922..01309002 100644 --- a/src/api/Api.cpp +++ b/src/api/Api.cpp @@ -26,7 +26,9 @@ #include +#include "3rdparty/http-parser/http_parser.h" #include "api/Api.h" +#include "api/requests/HttpApiRequest.h" #include "base/tools/Buffer.h" #include "common/crypto/keccak.h" #include "core/Config.h" @@ -61,7 +63,9 @@ xmrig::Api::~Api() void xmrig::Api::request(const HttpRequest &req) { + HttpApiRequest request(req, m_controller->config()->http().isRestricted()); + exec(request); } @@ -96,6 +100,14 @@ void xmrig::Api::onConfigChanged(Config *config, Config *previousConfig) } +void xmrig::Api::exec(IApiRequest &request) +{ + if (request.isNew()) { + request.done(HTTP_STATUS_NOT_FOUND); + } +} + + void xmrig::Api::genId(const String &id) { memset(m_id, 0, sizeof(m_id)); diff --git a/src/api/Api.h b/src/api/Api.h index a46e95c1..04d92393 100644 --- a/src/api/Api.h +++ b/src/api/Api.h @@ -35,6 +35,7 @@ namespace xmrig { class Controller; class Httpd; class HttpRequest; +class IApiRequest; class String; @@ -55,6 +56,7 @@ protected: void onConfigChanged(Config *config, Config *previousConfig) override; private: + void exec(IApiRequest &request); void genId(const String &id); void genWorkerId(const String &id); diff --git a/src/api/interfaces/IApiRequest.h b/src/api/interfaces/IApiRequest.h new file mode 100644 index 00000000..2c2f5634 --- /dev/null +++ b/src/api/interfaces/IApiRequest.h @@ -0,0 +1,72 @@ +/* XMRig + * Copyright 2010 Jeff Garzik + * Copyright 2012-2014 pooler + * Copyright 2014 Lucas Jones + * Copyright 2014-2016 Wolf9466 + * Copyright 2016 Jay D Dee + * Copyright 2016-2018 XMRig + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef XMRIG_IAPIREQUEST_H +#define XMRIG_IAPIREQUEST_H + + +#include "rapidjson/fwd.h" + + +namespace xmrig { + + +class String; + + +class IApiRequest +{ +public: + enum Method { + METHOD_DELETE, + METHOD_GET, + METHOD_HEAD, + METHOD_POST, + METHOD_PUT + }; + + + enum Source { + SOURCE_HTTP + }; + + + virtual ~IApiRequest() = default; + + virtual bool isDone() const = 0; + virtual bool isNew() const = 0; + virtual bool isRestricted() const = 0; + virtual const rapidjson::Value &json() const = 0; + virtual const String &url() const = 0; + virtual Method method() const = 0; + virtual rapidjson::Document &doc() = 0; + virtual rapidjson::Value &reply() = 0; + virtual Source source() const = 0; + virtual void accept() = 0; + virtual void done(int status) = 0; +}; + + +} /* namespace xmrig */ + + +#endif // XMRIG_IAPIREQUEST_H diff --git a/src/api/requests/ApiRequest.cpp b/src/api/requests/ApiRequest.cpp new file mode 100644 index 00000000..c092a334 --- /dev/null +++ b/src/api/requests/ApiRequest.cpp @@ -0,0 +1,39 @@ +/* XMRig + * Copyright 2010 Jeff Garzik + * Copyright 2012-2014 pooler + * Copyright 2014 Lucas Jones + * Copyright 2014-2016 Wolf9466 + * Copyright 2016 Jay D Dee + * Copyright 2017-2018 XMR-Stak , + * Copyright 2018-2019 SChernykh + * Copyright 2016-2019 XMRig , + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + + +#include "api/requests/ApiRequest.h" + + +xmrig::ApiRequest::ApiRequest(Source source, bool restricted) : + m_restricted(restricted), + m_source(source), + m_state(STATE_NEW) +{ +} + + +xmrig::ApiRequest::~ApiRequest() +{ +} diff --git a/src/api/requests/ApiRequest.h b/src/api/requests/ApiRequest.h new file mode 100644 index 00000000..1754aa9c --- /dev/null +++ b/src/api/requests/ApiRequest.h @@ -0,0 +1,67 @@ +/* XMRig + * Copyright 2010 Jeff Garzik + * Copyright 2012-2014 pooler + * Copyright 2014 Lucas Jones + * Copyright 2014-2016 Wolf9466 + * Copyright 2016 Jay D Dee + * Copyright 2017-2018 XMR-Stak , + * Copyright 2018-2019 SChernykh + * Copyright 2016-2019 XMRig , + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + + +#ifndef XMRIG_APIREQUEST_H +#define XMRIG_APIREQUEST_H + + +#include "api/interfaces/IApiRequest.h" + + +namespace xmrig { + + +class ApiRequest : public IApiRequest +{ +public: + ApiRequest(Source source, bool restricted); + ~ApiRequest() override; + +protected: + inline bool isDone() const override { return m_state == STATE_DONE; } + inline bool isNew() const override { return m_state == STATE_NEW; } + inline bool isRestricted() const override { return m_restricted; } + inline Source source() const override { return m_source; } + inline void accept() override { m_state = STATE_ACCEPTED; } + inline void done(int) override { m_state = STATE_DONE; } + +private: + enum State { + STATE_NEW, + STATE_ACCEPTED, + STATE_DONE + }; + + bool m_restricted; + Source m_source; + State m_state; +}; + + +} // namespace xmrig + + +#endif // XMRIG_APIREQUEST_H + diff --git a/src/api/requests/HttpApiRequest.cpp b/src/api/requests/HttpApiRequest.cpp new file mode 100644 index 00000000..fac69f51 --- /dev/null +++ b/src/api/requests/HttpApiRequest.cpp @@ -0,0 +1,55 @@ +/* XMRig + * Copyright 2010 Jeff Garzik + * Copyright 2012-2014 pooler + * Copyright 2014 Lucas Jones + * Copyright 2014-2016 Wolf9466 + * Copyright 2016 Jay D Dee + * Copyright 2017-2018 XMR-Stak , + * Copyright 2018-2019 SChernykh + * Copyright 2016-2019 XMRig , + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + + +#include "api/requests/HttpApiRequest.h" +#include "base/net/http/HttpRequest.h" + + +xmrig::HttpApiRequest::HttpApiRequest(const HttpRequest &req, bool restricted) : + ApiRequest(SOURCE_HTTP, restricted), + m_req(req), + m_res(req.id()), + m_url(req.url.c_str()) +{ +} + + +xmrig::IApiRequest::Method xmrig::HttpApiRequest::method() const +{ + return static_cast(m_req.method); +} + + +void xmrig::HttpApiRequest::done(int status) +{ + ApiRequest::done(status); + + if (status >= 400) { + reply().AddMember("status", status, doc().GetAllocator()); + } + + m_res.setStatus(status); + m_res.end(); +} diff --git a/src/api/requests/HttpApiRequest.h b/src/api/requests/HttpApiRequest.h new file mode 100644 index 00000000..dbe640ef --- /dev/null +++ b/src/api/requests/HttpApiRequest.h @@ -0,0 +1,67 @@ +/* XMRig + * Copyright 2010 Jeff Garzik + * Copyright 2012-2014 pooler + * Copyright 2014 Lucas Jones + * Copyright 2014-2016 Wolf9466 + * Copyright 2016 Jay D Dee + * Copyright 2017-2018 XMR-Stak , + * Copyright 2018-2019 SChernykh + * Copyright 2016-2019 XMRig , + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + + +#ifndef XMRIG_HTTPAPIREQUEST_H +#define XMRIG_HTTPAPIREQUEST_H + + +#include "api/requests/ApiRequest.h" +#include "base/net/http/HttpApiResponse.h" +#include "base/tools/String.h" + + +namespace xmrig { + + +class HttpRequest; + + +class HttpApiRequest : public ApiRequest +{ +public: + HttpApiRequest(const HttpRequest &req, bool restricted); + +protected: + inline const rapidjson::Value &json() const override { return m_body; } + inline rapidjson::Document &doc() override { return m_res.doc(); } + inline rapidjson::Value &reply() override { return m_res.doc(); } + inline const String &url() const override { return m_url; } + + Method method() const override; + void done(int status) override; + +private: + const HttpRequest &m_req; + HttpApiResponse m_res; + rapidjson::Document m_body; + String m_url; +}; + + +} // namespace xmrig + + +#endif // XMRIG_HTTPAPIREQUEST_H + diff --git a/src/base/net/http/HttpApiResponse.cpp b/src/base/net/http/HttpApiResponse.cpp index 56dd9bb8..bf91445a 100644 --- a/src/base/net/http/HttpApiResponse.cpp +++ b/src/base/net/http/HttpApiResponse.cpp @@ -30,6 +30,14 @@ #include "rapidjson/stringbuffer.h" +namespace xmrig { + +static const char *kError = "error"; +static const char *kStatus = "status"; + +} // namespace xmrig + + xmrig::HttpApiResponse::HttpApiResponse(uint64_t id) : HttpResponse(id), m_doc(rapidjson::kObjectType) @@ -53,9 +61,14 @@ void xmrig::HttpApiResponse::end() setHeader("Access-Control-Allow-Methods", "GET, PUT, POST, DELETE"); setHeader("Access-Control-Allow-Headers", "Authorization, Content-Type"); - if (statusCode() >= 400 && !m_doc.MemberCount()) { - m_doc.AddMember("status", statusCode(), m_doc.GetAllocator()); - m_doc.AddMember("error", StringRef(http_status_str(static_cast(statusCode()))), m_doc.GetAllocator()); + if (statusCode() >= 400) { + if (!m_doc.HasMember(kStatus)) { + m_doc.AddMember(StringRef(kStatus), statusCode(), m_doc.GetAllocator()); + } + + if (!m_doc.HasMember(kError)) { + m_doc.AddMember(StringRef(kError), StringRef(http_status_str(static_cast(statusCode()))), m_doc.GetAllocator()); + } } if (!m_doc.MemberCount()) { From c9f9e6787cd776fec6b99e43b58d247156b83c36 Mon Sep 17 00:00:00 2001 From: XMRig Date: Sat, 30 Mar 2019 03:10:27 +0700 Subject: [PATCH 046/116] Restore network API. --- CMakeLists.txt | 9 ++-- src/api/Api.cpp | 11 ++++- src/api/Api.h | 10 ++++- src/api/ApiRouter.cpp | 47 -------------------- src/api/ApiRouter.h | 5 --- src/api/interfaces/IApiListener.h | 45 ++++++++++++++++++++ src/net/Network.cpp | 71 +++++++++++++++++++++++++++++-- src/net/Network.h | 12 +++++- src/{api => net}/NetworkState.cpp | 2 +- src/{api => net}/NetworkState.h | 0 10 files changed, 145 insertions(+), 67 deletions(-) create mode 100644 src/api/interfaces/IApiListener.h rename src/{api => net}/NetworkState.cpp (98%) rename src/{api => net}/NetworkState.h (100%) diff --git a/CMakeLists.txt b/CMakeLists.txt index 57df6d59..dc8a82d8 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -22,7 +22,7 @@ include (src/base/base.cmake) set(HEADERS "${HEADERS_BASE}" "${HEADERS_BASE_HTTP}" - src/api/NetworkState.h + src/api/interfaces/IApiListener.h src/App.h src/common/config/CommonConfig.h src/common/config/ConfigLoader.h @@ -45,13 +45,14 @@ set(HEADERS src/Mem.h src/net/JobResult.h src/net/Network.h + src/net/NetworkState.h src/net/strategies/DonateStrategy.h src/Summary.h src/version.h src/workers/CpuThread.h - src/workers/ThreadHandle.h src/workers/Hashrate.h src/workers/MultiWorker.h + src/workers/ThreadHandle.h src/workers/Worker.h src/workers/Workers.h ) @@ -81,7 +82,6 @@ endif() set(SOURCES "${SOURCES_BASE}" "${SOURCES_BASE_HTTP}" - src/api/NetworkState.cpp src/App.cpp src/common/config/CommonConfig.cpp src/common/config/ConfigLoader.cpp @@ -93,12 +93,13 @@ set(SOURCES src/core/Controller.cpp src/Mem.cpp src/net/Network.cpp + src/net/NetworkState.cpp src/net/strategies/DonateStrategy.cpp src/Summary.cpp src/workers/CpuThread.cpp - src/workers/ThreadHandle.cpp src/workers/Hashrate.cpp src/workers/MultiWorker.cpp + src/workers/ThreadHandle.cpp src/workers/Worker.cpp src/workers/Workers.cpp src/xmrig.cpp diff --git a/src/api/Api.cpp b/src/api/Api.cpp index 01309002..c9f0fd9a 100644 --- a/src/api/Api.cpp +++ b/src/api/Api.cpp @@ -28,6 +28,7 @@ #include "3rdparty/http-parser/http_parser.h" #include "api/Api.h" +#include "api/interfaces/IApiListener.h" #include "api/requests/HttpApiRequest.h" #include "base/tools/Buffer.h" #include "common/crypto/keccak.h" @@ -102,9 +103,15 @@ void xmrig::Api::onConfigChanged(Config *config, Config *previousConfig) void xmrig::Api::exec(IApiRequest &request) { - if (request.isNew()) { - request.done(HTTP_STATUS_NOT_FOUND); + for (IApiListener *listener : m_listeners) { + listener->onRequest(request); + + if (request.isDone()) { + return; + } } + + request.done(request.isNew() ? HTTP_STATUS_NOT_FOUND : HTTP_STATUS_OK); } diff --git a/src/api/Api.h b/src/api/Api.h index 04d92393..dc4e8e21 100644 --- a/src/api/Api.h +++ b/src/api/Api.h @@ -26,6 +26,9 @@ #define XMRIG_API_H +#include + + #include "base/kernel/interfaces/IControllerListener.h" @@ -35,6 +38,7 @@ namespace xmrig { class Controller; class Httpd; class HttpRequest; +class IApiListener; class IApiRequest; class String; @@ -45,8 +49,9 @@ public: Api(Controller *controller); ~Api() override; - inline const char *id() const { return m_id; } - inline const char *workerId() const { return m_workerId; } + inline const char *id() const { return m_id; } + inline const char *workerId() const { return m_workerId; } + inline void addListener(IApiListener *listener) { m_listeners.push_back(listener); } void request(const HttpRequest &req); void start(); @@ -64,6 +69,7 @@ private: char m_workerId[128]; Controller *m_controller; Httpd *m_httpd; + std::vector m_listeners; }; diff --git a/src/api/ApiRouter.cpp b/src/api/ApiRouter.cpp index 20752f0c..30597f46 100644 --- a/src/api/ApiRouter.cpp +++ b/src/api/ApiRouter.cpp @@ -102,8 +102,6 @@ void ApiRouter::ApiRouter::get(const xmrig::HttpRequest &req, xmrig::HttpReply & getIdentify(doc); getMiner(doc); getHashrate(doc); - getResults(doc); - getConnection(doc); return finalize(reply, doc); } @@ -120,12 +118,6 @@ void ApiRouter::exec(const xmrig::HttpRequest &req, xmrig::HttpReply &reply) } -void ApiRouter::tick(const xmrig::NetworkState &network) -{ - m_network = network; -} - - void ApiRouter::onConfigChanged(xmrig::Config *config, xmrig::Config *previousConfig) { updateWorkerId(config->apiWorkerId(), previousConfig->apiWorkerId()); @@ -185,21 +177,6 @@ void ApiRouter::genId(const char *id) } -void ApiRouter::getConnection(rapidjson::Document &doc) const -{ - auto &allocator = doc.GetAllocator(); - - rapidjson::Value connection(rapidjson::kObjectType); - connection.AddMember("pool", rapidjson::StringRef(m_network.pool), allocator); - connection.AddMember("uptime", m_network.connectionTime(), allocator); - connection.AddMember("ping", m_network.latency(), allocator); - connection.AddMember("failures", m_network.failures, allocator); - connection.AddMember("error_log", rapidjson::Value(rapidjson::kArrayType), allocator); - - doc.AddMember("connection", connection, allocator); -} - - void ApiRouter::getHashrate(rapidjson::Document &doc) const { auto &allocator = doc.GetAllocator(); @@ -258,30 +235,6 @@ void ApiRouter::getMiner(rapidjson::Document &doc) const } -void ApiRouter::getResults(rapidjson::Document &doc) const -{ - auto &allocator = doc.GetAllocator(); - - rapidjson::Value results(rapidjson::kObjectType); - - results.AddMember("diff_current", m_network.diff, allocator); - results.AddMember("shares_good", m_network.accepted, allocator); - results.AddMember("shares_total", m_network.accepted + m_network.rejected, allocator); - results.AddMember("avg_time", m_network.avgTime(), allocator); - results.AddMember("hashes_total", m_network.total, allocator); - - rapidjson::Value best(rapidjson::kArrayType); - for (size_t i = 0; i < m_network.topDiff.size(); ++i) { - best.PushBack(m_network.topDiff[i], allocator); - } - - results.AddMember("best", best, allocator); - results.AddMember("error_log", rapidjson::Value(rapidjson::kArrayType), allocator); - - doc.AddMember("results", results, allocator); -} - - void ApiRouter::getThreads(rapidjson::Document &doc) const { doc.SetObject(); diff --git a/src/api/ApiRouter.h b/src/api/ApiRouter.h index 61c05201..fd9baea8 100644 --- a/src/api/ApiRouter.h +++ b/src/api/ApiRouter.h @@ -50,26 +50,21 @@ public: void get(const xmrig::HttpRequest &req, xmrig::HttpReply &reply) const; void exec(const xmrig::HttpRequest &req, xmrig::HttpReply &reply); - void tick(const xmrig::NetworkState &results); - protected: void onConfigChanged(xmrig::Config *config, xmrig::Config *previousConfig) override; private: void finalize(xmrig::HttpReply &reply, rapidjson::Document &doc) const; void genId(const char *id); - void getConnection(rapidjson::Document &doc) const; void getHashrate(rapidjson::Document &doc) const; void getIdentify(rapidjson::Document &doc) const; void getMiner(rapidjson::Document &doc) const; - void getResults(rapidjson::Document &doc) const; void getThreads(rapidjson::Document &doc) const; void setWorkerId(const char *id); void updateWorkerId(const char *id, const char *previousId); char m_id[32]; char m_workerId[128]; - xmrig::NetworkState m_network; xmrig::Controller *m_controller; }; diff --git a/src/api/interfaces/IApiListener.h b/src/api/interfaces/IApiListener.h new file mode 100644 index 00000000..7897e375 --- /dev/null +++ b/src/api/interfaces/IApiListener.h @@ -0,0 +1,45 @@ +/* XMRig + * Copyright 2010 Jeff Garzik + * Copyright 2012-2014 pooler + * Copyright 2014 Lucas Jones + * Copyright 2014-2016 Wolf9466 + * Copyright 2016 Jay D Dee + * Copyright 2016-2018 XMRig + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef XMRIG_IAPILISTENER_H +#define XMRIG_IAPILISTENER_H + + +namespace xmrig { + + +class IApiRequest; + + +class IApiListener +{ +public: + virtual ~IApiListener() = default; + + virtual void onRequest(IApiRequest &request) = 0; +}; + + +} /* namespace xmrig */ + + +#endif // XMRIG_IAPILISTENER_H diff --git a/src/net/Network.cpp b/src/net/Network.cpp index 7f3f81d3..fa0d00a4 100644 --- a/src/net/Network.cpp +++ b/src/net/Network.cpp @@ -41,9 +41,16 @@ #include "core/Controller.h" #include "net/Network.h" #include "net/strategies/DonateStrategy.h" +#include "rapidjson/document.h" #include "workers/Workers.h" +#ifdef XMRIG_FEATURE_API +# include "api/Api.h" +# include "api/interfaces/IApiRequest.h" +#endif + + xmrig::Network::Network(Controller *controller) : m_donate(nullptr), m_timer(nullptr) @@ -51,6 +58,10 @@ xmrig::Network::Network(Controller *controller) : Workers::setListener(this); controller->addListener(this); +# ifdef XMRIG_FEATURE_API + controller->api()->addListener(this); +# endif + const Pools &pools = controller->config()->pools(); m_strategy = pools.createStrategy(this); @@ -152,6 +163,19 @@ void xmrig::Network::onPause(IStrategy *strategy) } +void xmrig::Network::onRequest(IApiRequest &request) +{ +# ifdef XMRIG_FEATURE_API + if (request.method() == IApiRequest::METHOD_GET && request.url() == "/1/summary") { + request.accept(); + + getResults(request.reply(), request.doc()); + getConnection(request.reply(), request.doc()); + } +# endif +} + + void xmrig::Network::onResultAccepted(IStrategy *, Client *, const SubmitResult &result, const char *error) { m_state.add(result, error); @@ -196,8 +220,47 @@ void xmrig::Network::tick() if (m_donate) { m_donate->tick(now); } - -# ifdef XMRIG_FEATURE_API - //Api::tick(m_state); -# endif } + + +#ifdef XMRIG_FEATURE_API +void xmrig::Network::getConnection(rapidjson::Value &reply, rapidjson::Document &doc) const +{ + using namespace rapidjson; + auto &allocator = doc.GetAllocator(); + + Value connection(kObjectType); + connection.AddMember("pool", StringRef(m_state.pool), allocator); + connection.AddMember("uptime", m_state.connectionTime(), allocator); + connection.AddMember("ping", m_state.latency(), allocator); + connection.AddMember("failures", m_state.failures, allocator); + connection.AddMember("error_log", Value(kArrayType), allocator); + + reply.AddMember("connection", connection, allocator); +} + + +void xmrig::Network::getResults(rapidjson::Value &reply, rapidjson::Document &doc) const +{ + using namespace rapidjson; + auto &allocator = doc.GetAllocator(); + + Value results(kObjectType); + + results.AddMember("diff_current", m_state.diff, allocator); + results.AddMember("shares_good", m_state.accepted, allocator); + results.AddMember("shares_total", m_state.accepted + m_state.rejected, allocator); + results.AddMember("avg_time", m_state.avgTime(), allocator); + results.AddMember("hashes_total", m_state.total, allocator); + + Value best(kArrayType); + for (size_t i = 0; i < m_state.topDiff.size(); ++i) { + best.PushBack(m_state.topDiff[i], allocator); + } + + results.AddMember("best", best, allocator); + results.AddMember("error_log", Value(kArrayType), allocator); + + reply.AddMember("results", results, allocator); +} +#endif diff --git a/src/net/Network.h b/src/net/Network.h index 9fa7564d..09e7c815 100644 --- a/src/net/Network.h +++ b/src/net/Network.h @@ -29,11 +29,13 @@ #include -#include "api/NetworkState.h" +#include "api/interfaces/IApiListener.h" #include "base/kernel/interfaces/IControllerListener.h" #include "base/kernel/interfaces/IStrategyListener.h" #include "base/kernel/interfaces/ITimerListener.h" #include "interfaces/IJobResultListener.h" +#include "net/NetworkState.h" +#include "rapidjson/fwd.h" namespace xmrig { @@ -43,7 +45,7 @@ class Controller; class IStrategy; -class Network : public IJobResultListener, public IStrategyListener, public IControllerListener, public ITimerListener +class Network : public IJobResultListener, public IStrategyListener, public IControllerListener, public ITimerListener, public IApiListener { public: Network(Controller *controller); @@ -61,6 +63,7 @@ protected: void onJob(IStrategy *strategy, Client *client, const Job &job) override; void onJobResult(const JobResult &result) override; void onPause(IStrategy *strategy) override; + void onRequest(IApiRequest &request) override; void onResultAccepted(IStrategy *strategy, Client *client, const SubmitResult &result, const char *error) override; private: @@ -69,6 +72,11 @@ private: void setJob(Client *client, const Job &job, bool donate); void tick(); +# ifdef XMRIG_FEATURE_API + void getConnection(rapidjson::Value &reply, rapidjson::Document &doc) const; + void getResults(rapidjson::Value &reply, rapidjson::Document &doc) const; +# endif + IStrategy *m_donate; IStrategy *m_strategy; NetworkState m_state; diff --git a/src/api/NetworkState.cpp b/src/net/NetworkState.cpp similarity index 98% rename from src/api/NetworkState.cpp rename to src/net/NetworkState.cpp index 8a541eaa..df248602 100644 --- a/src/api/NetworkState.cpp +++ b/src/net/NetworkState.cpp @@ -29,9 +29,9 @@ #include -#include "api/NetworkState.h" #include "base/net/stratum/SubmitResult.h" #include "base/tools/Chrono.h" +#include "net/NetworkState.h" xmrig::NetworkState::NetworkState() : diff --git a/src/api/NetworkState.h b/src/net/NetworkState.h similarity index 100% rename from src/api/NetworkState.h rename to src/net/NetworkState.h From 106e149324c1e0deb8980400a3a9e097770bc8cf Mon Sep 17 00:00:00 2001 From: XMRig Date: Sat, 30 Mar 2019 15:27:09 +0700 Subject: [PATCH 047/116] Use static http_parser_settings. --- src/base/net/http/HttpContext.cpp | 13 ++++++ src/base/net/http/HttpServer.cpp | 67 ++++++++++++------------------- src/base/net/http/HttpServer.h | 3 -- 3 files changed, 39 insertions(+), 44 deletions(-) diff --git a/src/base/net/http/HttpContext.cpp b/src/base/net/http/HttpContext.cpp index e0a1e83c..65331d3a 100644 --- a/src/base/net/http/HttpContext.cpp +++ b/src/base/net/http/HttpContext.cpp @@ -29,6 +29,7 @@ #include "3rdparty/http-parser/http_parser.h" +#include "base/kernel/interfaces/IHttpListener.h" #include "base/net/http/HttpContext.h" @@ -78,6 +79,10 @@ xmrig::HttpContext *xmrig::HttpContext::get(uint64_t id) void xmrig::HttpContext::attach(http_parser_settings *settings) { + if (settings->on_message_complete != nullptr) { + return; + } + settings->on_message_begin = nullptr; settings->on_status = nullptr; settings->on_chunk_header = nullptr; @@ -109,6 +114,14 @@ void xmrig::HttpContext::attach(http_parser_settings *settings) return 0; }; + + settings->on_message_complete = [](http_parser *parser) -> int + { + const HttpContext *ctx = reinterpret_cast(parser->data); + ctx->listener->onHttpRequest(*ctx); + + return 0; + }; } diff --git a/src/base/net/http/HttpServer.cpp b/src/base/net/http/HttpServer.cpp index 245451c2..4addee3b 100644 --- a/src/base/net/http/HttpServer.cpp +++ b/src/base/net/http/HttpServer.cpp @@ -35,48 +35,32 @@ #include "base/net/http/HttpServer.h" +namespace xmrig { + +static http_parser_settings http_settings; + +} // namespace xmrig + + xmrig::HttpServer::HttpServer(IHttpListener *listener) : m_listener(listener) { - m_settings = new http_parser_settings(); - - HttpContext::attach(m_settings); - m_settings->on_message_complete = HttpServer::onComplete; + HttpContext::attach(&http_settings); } xmrig::HttpServer::~HttpServer() { - delete m_settings; + memset(&http_settings, 0, sizeof (http_settings)); } void xmrig::HttpServer::onConnection(uv_stream_t *stream, uint16_t) { - static std::function onConnect; - static std::function onRead; + HttpContext *ctx = new HttpContext(HTTP_REQUEST, m_listener); + uv_accept(stream, ctx->stream()); - HttpContext *context = new HttpContext(HTTP_REQUEST, m_listener); - uv_accept(stream, context->stream()); - - onRead = [&](uv_stream_t *tcp, ssize_t nread, const uv_buf_t *buf) { - HttpContext* context = static_cast(tcp->data); - - if (nread >= 0) { - const size_t size = static_cast(nread); - const size_t parsed = http_parser_execute(context->parser, m_settings, buf->base, size); - - if (parsed < size) { - uv_close(context->handle(), HttpContext::close); - } - } else { - uv_close(context->handle(), HttpContext::close); - } - - delete [] buf->base; - }; - - uv_read_start(context->stream(), + uv_read_start(ctx->stream(), [](uv_handle_t *, size_t suggested_size, uv_buf_t *buf) { buf->base = new char[suggested_size]; @@ -89,18 +73,19 @@ void xmrig::HttpServer::onConnection(uv_stream_t *stream, uint16_t) }, [](uv_stream_t *tcp, ssize_t nread, const uv_buf_t *buf) { - onRead(tcp, nread, buf); + HttpContext *ctx = static_cast(tcp->data); + + if (nread >= 0) { + const size_t size = static_cast(nread); + const size_t parsed = http_parser_execute(ctx->parser, &http_settings, buf->base, size); + + if (parsed < size) { + uv_close(ctx->handle(), HttpContext::close); + } + } else { + uv_close(ctx->handle(), HttpContext::close); + } + + delete [] buf->base; }); } - - -int xmrig::HttpServer::onComplete(http_parser *parser) -{ - HttpContext *context = reinterpret_cast(parser->data); - HttpResponse res(context->id()); - - context->listener->onHttpRequest(*context); - - return 0; -} - diff --git a/src/base/net/http/HttpServer.h b/src/base/net/http/HttpServer.h index 651be467..45f3843d 100644 --- a/src/base/net/http/HttpServer.h +++ b/src/base/net/http/HttpServer.h @@ -51,9 +51,6 @@ protected: void onConnection(uv_stream_t *stream, uint16_t port) override; private: - static int onComplete(http_parser *parser); - - http_parser_settings *m_settings; IHttpListener *m_listener; }; From bd6c7c64aa347f52c1d0b58c0ada396ecda3de56 Mon Sep 17 00:00:00 2001 From: XMRig Date: Sat, 30 Mar 2019 15:51:35 +0700 Subject: [PATCH 048/116] Added workaround, Google Chrome create extra dummy connections for future speed up. --- src/base/net/http/HttpContext.cpp | 25 ++++++++++++++++++------- src/base/net/http/HttpContext.h | 4 +++- src/base/net/http/HttpResponse.cpp | 4 +--- src/base/net/http/HttpServer.cpp | 6 +++--- 4 files changed, 25 insertions(+), 14 deletions(-) diff --git a/src/base/net/http/HttpContext.cpp b/src/base/net/http/HttpContext.cpp index 65331d3a..de32f34d 100644 --- a/src/base/net/http/HttpContext.cpp +++ b/src/base/net/http/HttpContext.cpp @@ -67,6 +67,19 @@ xmrig::HttpContext::~HttpContext() } +void xmrig::HttpContext::close() +{ + auto it = m_storage.find(id()); + if (it != m_storage.end()) { + m_storage.erase(it); + } + + if (!uv_is_closing(handle())) { + uv_close(handle(), [](uv_handle_t *handle) -> void { delete reinterpret_cast(handle->data); }); + } +} + + xmrig::HttpContext *xmrig::HttpContext::get(uint64_t id) { if (m_storage.count(id) == 0) { @@ -125,15 +138,13 @@ void xmrig::HttpContext::attach(http_parser_settings *settings) } -void xmrig::HttpContext::close(uv_handle_t* handle) +void xmrig::HttpContext::closeAll() { - HttpContext *ctx = reinterpret_cast(handle->data); - auto it = m_storage.find(ctx->id()); - if (it != m_storage.end()) { - m_storage.erase(it); + for (auto kv : m_storage) { + if (!uv_is_closing(kv.second->handle())) { + uv_close(kv.second->handle(), [](uv_handle_t *handle) -> void { delete reinterpret_cast(handle->data); }); + } } - - delete ctx; } diff --git a/src/base/net/http/HttpContext.h b/src/base/net/http/HttpContext.h index 5e9c234a..3b2dead3 100644 --- a/src/base/net/http/HttpContext.h +++ b/src/base/net/http/HttpContext.h @@ -54,9 +54,11 @@ public: inline uv_stream_t *stream() const { return reinterpret_cast(tcp); } inline uv_handle_t *handle() const { return reinterpret_cast(tcp); } + void close(); + static HttpContext *get(uint64_t id); static void attach(http_parser_settings *settings); - static void close(uv_handle_t* handle); + static void closeAll(); http_parser *parser; IHttpListener *listener; diff --git a/src/base/net/http/HttpResponse.cpp b/src/base/net/http/HttpResponse.cpp index c9c51de7..77431a62 100644 --- a/src/base/net/http/HttpResponse.cpp +++ b/src/base/net/http/HttpResponse.cpp @@ -103,7 +103,5 @@ void xmrig::HttpResponse::end(const char *data, size_t size) HttpContext *ctx = HttpContext::get(m_id); uv_try_write(ctx->stream(), bufs, data ? 2 : 1); - if (!uv_is_closing(ctx->handle())) { - uv_close(ctx->handle(), HttpContext::close); - } + ctx->close(); } diff --git a/src/base/net/http/HttpServer.cpp b/src/base/net/http/HttpServer.cpp index 4addee3b..c6e02e44 100644 --- a/src/base/net/http/HttpServer.cpp +++ b/src/base/net/http/HttpServer.cpp @@ -51,7 +51,7 @@ xmrig::HttpServer::HttpServer(IHttpListener *listener) : xmrig::HttpServer::~HttpServer() { - memset(&http_settings, 0, sizeof (http_settings)); + HttpContext::closeAll(); } @@ -80,10 +80,10 @@ void xmrig::HttpServer::onConnection(uv_stream_t *stream, uint16_t) const size_t parsed = http_parser_execute(ctx->parser, &http_settings, buf->base, size); if (parsed < size) { - uv_close(ctx->handle(), HttpContext::close); + ctx->close(); } } else { - uv_close(ctx->handle(), HttpContext::close); + ctx->close(); } delete [] buf->base; From d8aba7da7dd6b2355fb81efb01924ea7989bbcab Mon Sep 17 00:00:00 2001 From: XMRig Date: Sat, 30 Mar 2019 20:46:08 +0700 Subject: [PATCH 049/116] Revert id and worker_id. --- src/api/Api.cpp | 6 ++++++ src/api/ApiRouter.h | 2 +- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/src/api/Api.cpp b/src/api/Api.cpp index c9f0fd9a..b29a6454 100644 --- a/src/api/Api.cpp +++ b/src/api/Api.cpp @@ -103,6 +103,12 @@ void xmrig::Api::onConfigChanged(Config *config, Config *previousConfig) void xmrig::Api::exec(IApiRequest &request) { + if (request.method() == IApiRequest::METHOD_GET && request.url() == "/1/summary") { + request.accept(); + request.reply().AddMember("id", rapidjson::StringRef(m_id), request.doc().GetAllocator()); + request.reply().AddMember("worker_id", rapidjson::StringRef(m_workerId), request.doc().GetAllocator());; + } + for (IApiListener *listener : m_listeners) { listener->onRequest(request); diff --git a/src/api/ApiRouter.h b/src/api/ApiRouter.h index fd9baea8..cbdc04b8 100644 --- a/src/api/ApiRouter.h +++ b/src/api/ApiRouter.h @@ -26,7 +26,7 @@ #define XMRIG_APIROUTER_H -#include "api/NetworkState.h" +#include "net/NetworkState.h" #include "base/kernel/interfaces/IControllerListener.h" #include "rapidjson/fwd.h" From e39ddeeea2fda5a823e71b63117a6184ba505cc7 Mon Sep 17 00:00:00 2001 From: XMRig Date: Sat, 30 Mar 2019 21:27:54 +0700 Subject: [PATCH 050/116] Removed IConfigCreator/ConfigCreator and changed file structure. --- CMakeLists.txt | 9 ++-- src/App.cpp | 2 +- src/App_win.cpp | 2 +- src/Summary.cpp | 2 +- src/api/Api.cpp | 2 +- src/api/Httpd.cpp | 2 +- src/base/kernel/Entry.cpp | 2 +- src/common/config/ConfigLoader.cpp | 22 ++++---- src/common/config/ConfigLoader.h | 4 +- src/common/config/ConfigWatcher.cpp | 7 ++- src/common/config/ConfigWatcher.h | 4 +- src/common/interfaces/IConfig.h | 2 + src/common/interfaces/IConfigCreator.h | 47 ----------------- src/core/ConfigCreator.h | 50 ------------------- src/core/Controller.cpp | 2 +- src/core/{ => config}/Config.cpp | 5 +- src/core/{ => config}/Config.h | 3 +- src/core/{ => config}/ConfigLoader_default.h | 0 src/core/{ => config}/ConfigLoader_platform.h | 0 src/core/{ => config}/usage.h | 0 src/net/Network.cpp | 2 +- src/net/strategies/DonateStrategy.cpp | 2 +- src/workers/Hashrate.cpp | 2 +- src/workers/Workers.cpp | 2 +- 24 files changed, 36 insertions(+), 139 deletions(-) delete mode 100644 src/common/interfaces/IConfigCreator.h delete mode 100644 src/core/ConfigCreator.h rename src/core/{ => config}/Config.cpp (98%) rename src/core/{ => config}/Config.h (96%) rename src/core/{ => config}/ConfigLoader_default.h (100%) rename src/core/{ => config}/ConfigLoader_platform.h (100%) rename src/core/{ => config}/usage.h (100%) diff --git a/CMakeLists.txt b/CMakeLists.txt index dc8a82d8..f1eeeeef 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -31,13 +31,14 @@ set(HEADERS src/common/crypto/Algorithm.h src/common/crypto/keccak.h src/common/interfaces/IConfig.h - src/common/interfaces/IConfigCreator.h src/common/interfaces/ICpuInfo.h src/common/Platform.h src/common/utils/mm_malloc.h src/common/xmrig.h - src/core/ConfigLoader_default.h - src/core/ConfigLoader_platform.h + src/core/config/Config.h + src/core/config/ConfigLoader_default.h + src/core/config/ConfigLoader_platform.h + src/core/config/usage.h src/core/Controller.h src/interfaces/IJobResultListener.h src/interfaces/IThread.h @@ -89,7 +90,7 @@ set(SOURCES src/common/crypto/Algorithm.cpp src/common/crypto/keccak.cpp src/common/Platform.cpp - src/core/Config.cpp + src/core/config/Config.cpp src/core/Controller.cpp src/Mem.cpp src/net/Network.cpp diff --git a/src/App.cpp b/src/App.cpp index f7e80ef7..38e335c2 100644 --- a/src/App.cpp +++ b/src/App.cpp @@ -35,7 +35,7 @@ #include "base/kernel/Signals.h" #include "common/cpu/Cpu.h" #include "common/Platform.h" -#include "core/Config.h" +#include "core/config/Config.h" #include "core/Controller.h" #include "crypto/CryptoNight.h" #include "Mem.h" diff --git a/src/App_win.cpp b/src/App_win.cpp index 57f57a6d..a41ed505 100644 --- a/src/App_win.cpp +++ b/src/App_win.cpp @@ -29,7 +29,7 @@ #include "App.h" #include "core/Controller.h" -#include "core/Config.h" +#include "core/config/Config.h" void xmrig::App::background() diff --git a/src/Summary.cpp b/src/Summary.cpp index b7c5d7df..697e2373 100644 --- a/src/Summary.cpp +++ b/src/Summary.cpp @@ -31,7 +31,7 @@ #include "base/io/log/Log.h" #include "base/net/stratum/Pool.h" #include "common/cpu/Cpu.h" -#include "core/Config.h" +#include "core/config/Config.h" #include "core/Controller.h" #include "crypto/Asm.h" #include "Mem.h" diff --git a/src/api/Api.cpp b/src/api/Api.cpp index b29a6454..527565ed 100644 --- a/src/api/Api.cpp +++ b/src/api/Api.cpp @@ -32,7 +32,7 @@ #include "api/requests/HttpApiRequest.h" #include "base/tools/Buffer.h" #include "common/crypto/keccak.h" -#include "core/Config.h" +#include "core/config/Config.h" #include "core/Controller.h" #include "version.h" diff --git a/src/api/Httpd.cpp b/src/api/Httpd.cpp index 444fdb3e..38b477aa 100644 --- a/src/api/Httpd.cpp +++ b/src/api/Httpd.cpp @@ -31,7 +31,7 @@ #include "base/net/http/HttpRequest.h" #include "base/net/http/HttpServer.h" #include "base/net/tools/TcpServer.h" -#include "core/Config.h" +#include "core/config/Config.h" #include "core/Controller.h" diff --git a/src/base/kernel/Entry.cpp b/src/base/kernel/Entry.cpp index 5af4db78..1834cb82 100644 --- a/src/base/kernel/Entry.cpp +++ b/src/base/kernel/Entry.cpp @@ -34,7 +34,7 @@ #include "base/kernel/Entry.h" #include "base/kernel/Process.h" -#include "core/usage.h" +#include "core/config/usage.h" #include "version.h" diff --git a/src/common/config/ConfigLoader.cpp b/src/common/config/ConfigLoader.cpp index 4b251fa2..6f145440 100644 --- a/src/common/config/ConfigLoader.cpp +++ b/src/common/config/ConfigLoader.cpp @@ -36,20 +36,19 @@ #include "common/config/ConfigWatcher.h" #include "common/interfaces/IConfig.h" #include "common/Platform.h" -#include "core/ConfigCreator.h" -#include "core/ConfigLoader_platform.h" +#include "core/config/Config.h" +#include "core/config/ConfigLoader_platform.h" #include "rapidjson/document.h" #include "rapidjson/error/en.h" #include "rapidjson/fwd.h" #ifdef XMRIG_FEATURE_EMBEDDED_CONFIG -# include "core/ConfigLoader_default.h" +# include "core/config/ConfigLoader_default.h" #endif xmrig::ConfigWatcher *xmrig::ConfigLoader::m_watcher = nullptr; -xmrig::IConfigCreator *xmrig::ConfigLoader::m_creator = nullptr; xmrig::IConfigListener *xmrig::ConfigLoader::m_listener = nullptr; @@ -106,7 +105,7 @@ bool xmrig::ConfigLoader::loadFromJSON(xmrig::IConfig *config, const rapidjson:: bool xmrig::ConfigLoader::reload(xmrig::IConfig *oldConfig, const char *json) { - xmrig::IConfig *config = m_creator->create(); + IConfig *config = Config::create(); if (!loadFromJSON(config, json)) { delete config; @@ -135,17 +134,16 @@ bool xmrig::ConfigLoader::watch(IConfig *config) assert(m_watcher == nullptr); - m_watcher = new xmrig::ConfigWatcher(config->fileName(), m_creator, m_listener); + m_watcher = new xmrig::ConfigWatcher(config->fileName(), m_listener); return true; } -xmrig::IConfig *xmrig::ConfigLoader::load(Process *process, IConfigCreator *creator, IConfigListener *listener) +xmrig::IConfig *xmrig::ConfigLoader::load(Process *process, IConfigListener *listener) { - m_creator = creator; m_listener = listener; - xmrig::IConfig *config = m_creator->create(); + IConfig *config = Config::create(); int key; int argc = process->arguments().argc(); char **argv = process->arguments().argv(); @@ -171,7 +169,7 @@ xmrig::IConfig *xmrig::ConfigLoader::load(Process *process, IConfigCreator *crea if (!config->finalize()) { delete config; - config = m_creator->create(); + config = Config::create(); loadFromFile(config, process->location(Process::ExeLocation, "config.json")); } @@ -179,7 +177,7 @@ xmrig::IConfig *xmrig::ConfigLoader::load(Process *process, IConfigCreator *crea if (!config->finalize()) { delete config; - config = m_creator->create(); + config = Config::create(); loadFromJSON(config, default_config); } # endif @@ -203,10 +201,8 @@ xmrig::IConfig *xmrig::ConfigLoader::load(Process *process, IConfigCreator *crea void xmrig::ConfigLoader::release() { delete m_watcher; - delete m_creator; m_watcher = nullptr; - m_creator = nullptr; } diff --git a/src/common/config/ConfigLoader.h b/src/common/config/ConfigLoader.h index 99d6143f..322aafcf 100644 --- a/src/common/config/ConfigLoader.h +++ b/src/common/config/ConfigLoader.h @@ -39,7 +39,6 @@ namespace xmrig { class ConfigWatcher; -class IConfigCreator; class IConfigListener; class IConfig; class Process; @@ -53,7 +52,7 @@ public: static bool loadFromJSON(IConfig *config, const rapidjson::Document &doc); static bool reload(IConfig *oldConfig, const char *json); static bool watch(IConfig *config); - static IConfig *load(Process *process, IConfigCreator *creator, IConfigListener *listener); + static IConfig *load(Process *process, IConfigListener *listener); static void release(); private: @@ -62,7 +61,6 @@ private: static void parseJSON(IConfig *config, const struct option *option, const rapidjson::Value &object); static ConfigWatcher *m_watcher; - static IConfigCreator *m_creator; static IConfigListener *m_listener; }; diff --git a/src/common/config/ConfigWatcher.cpp b/src/common/config/ConfigWatcher.cpp index c3168ac9..1c70547e 100644 --- a/src/common/config/ConfigWatcher.cpp +++ b/src/common/config/ConfigWatcher.cpp @@ -28,11 +28,10 @@ #include "base/kernel/interfaces/IConfigListener.h" #include "common/config/ConfigLoader.h" #include "common/config/ConfigWatcher.h" -#include "core/ConfigCreator.h" +#include "core/config/Config.h" -xmrig::ConfigWatcher::ConfigWatcher(const String &path, IConfigCreator *creator, IConfigListener *listener) : - m_creator(creator), +xmrig::ConfigWatcher::ConfigWatcher(const String &path, IConfigListener *listener) : m_listener(listener) { m_watcher = new Watcher(path, this); @@ -50,7 +49,7 @@ void xmrig::ConfigWatcher::onFileChanged(const String &fileName) { LOG_WARN("\"%s\" was changed, reloading configuration", fileName.data()); - IConfig *config = m_creator->create(); + IConfig *config = Config::create(); ConfigLoader::loadFromFile(config, fileName); if (!config->finalize()) { diff --git a/src/common/config/ConfigWatcher.h b/src/common/config/ConfigWatcher.h index c2c3ee29..77b41cf5 100644 --- a/src/common/config/ConfigWatcher.h +++ b/src/common/config/ConfigWatcher.h @@ -37,7 +37,6 @@ struct option; namespace xmrig { -class IConfigCreator; class IConfigListener; class Watcher; @@ -45,14 +44,13 @@ class Watcher; class ConfigWatcher : public IWatcherListener { public: - ConfigWatcher(const String &path, IConfigCreator *creator, IConfigListener *listener); + ConfigWatcher(const String &path, IConfigListener *listener); ~ConfigWatcher() override; protected: void onFileChanged(const String &fileName) override; private: - IConfigCreator *m_creator; IConfigListener *m_listener; Watcher *m_watcher; }; diff --git a/src/common/interfaces/IConfig.h b/src/common/interfaces/IConfig.h index d7b7944a..2228d2c9 100644 --- a/src/common/interfaces/IConfig.h +++ b/src/common/interfaces/IConfig.h @@ -152,6 +152,8 @@ public: virtual void getJSON(rapidjson::Document &doc) const = 0; virtual void parseJSON(const rapidjson::Document &doc) = 0; virtual void setFileName(const char *fileName) = 0; + + static IConfig *create(); }; diff --git a/src/common/interfaces/IConfigCreator.h b/src/common/interfaces/IConfigCreator.h deleted file mode 100644 index c2e0e62e..00000000 --- a/src/common/interfaces/IConfigCreator.h +++ /dev/null @@ -1,47 +0,0 @@ -/* XMRig - * Copyright 2010 Jeff Garzik - * Copyright 2012-2014 pooler - * Copyright 2014 Lucas Jones - * Copyright 2014-2016 Wolf9466 - * Copyright 2016 Jay D Dee - * Copyright 2017-2018 XMR-Stak , - * Copyright 2018-2019 SChernykh - * Copyright 2016-2019 XMRig , - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#ifndef XMRIG_ICONFIGCREATOR_H -#define XMRIG_ICONFIGCREATOR_H - - -namespace xmrig { - - -class IConfig; - - -class IConfigCreator -{ -public: - virtual ~IConfigCreator() = default; - - virtual IConfig *create() const = 0; -}; - - -} /* namespace xmrig */ - - -#endif // XMRIG_ICONFIGCREATOR_H diff --git a/src/core/ConfigCreator.h b/src/core/ConfigCreator.h deleted file mode 100644 index 054eb78c..00000000 --- a/src/core/ConfigCreator.h +++ /dev/null @@ -1,50 +0,0 @@ -/* XMRig - * Copyright 2010 Jeff Garzik - * Copyright 2012-2014 pooler - * Copyright 2014 Lucas Jones - * Copyright 2014-2016 Wolf9466 - * Copyright 2016 Jay D Dee - * Copyright 2016-2018 XMRig - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#ifndef __CONFIGCREATOR_H__ -#define __CONFIGCREATOR_H__ - - -#include "common/interfaces/IConfigCreator.h" -#include "core/Config.h" - - -namespace xmrig { - - -class IConfig; - - -class ConfigCreator : public IConfigCreator -{ -public: - inline IConfig *create() const override - { - return new Config(); - } -}; - - -} /* namespace xmrig */ - - -#endif // __CONFIGCREATOR_H__ diff --git a/src/core/Controller.cpp b/src/core/Controller.cpp index fe1537f3..fbe4a427 100644 --- a/src/core/Controller.cpp +++ b/src/core/Controller.cpp @@ -33,7 +33,7 @@ #include "common/config/ConfigLoader.h" #include "common/cpu/Cpu.h" #include "common/Platform.h" -#include "core/Config.h" +#include "core/config/Config.h" #include "core/Controller.h" #include "net/Network.h" diff --git a/src/core/Config.cpp b/src/core/config/Config.cpp similarity index 98% rename from src/core/Config.cpp rename to src/core/config/Config.cpp index a1c91548..5b337197 100644 --- a/src/core/Config.cpp +++ b/src/core/config/Config.cpp @@ -30,8 +30,7 @@ #include "base/io/log/Log.h" #include "common/config/ConfigLoader.h" #include "common/cpu/Cpu.h" -#include "core/Config.h" -#include "core/ConfigCreator.h" +#include "core/config/Config.h" #include "crypto/Asm.h" #include "crypto/CryptoNight_constants.h" #include "rapidjson/document.h" @@ -129,7 +128,7 @@ void xmrig::Config::getJSON(rapidjson::Document &doc) const xmrig::Config *xmrig::Config::load(Process *process, IConfigListener *listener) { - return static_cast(ConfigLoader::load(process, new ConfigCreator(), listener)); + return static_cast(ConfigLoader::load(process, listener)); } diff --git a/src/core/Config.h b/src/core/config/Config.h similarity index 96% rename from src/core/Config.h rename to src/core/config/Config.h index d7df9cd9..261955c5 100644 --- a/src/core/Config.h +++ b/src/core/config/Config.h @@ -78,8 +78,9 @@ public: inline bool isShouldSave() const { return (m_shouldSave || m_upgrade) && isAutoSave(); } inline const std::vector &threads() const { return m_threads.list; } inline int priority() const { return m_priority; } - inline int threadsCount() const { return m_threads.list.size(); } + inline int threadsCount() const { return static_cast(m_threads.list.size()); } inline int64_t affinity() const { return m_threads.mask; } + inline static IConfig *create() { return new Config(); } inline ThreadsMode threadsMode() const { return m_threads.mode; } static Config *load(Process *process, IConfigListener *listener); diff --git a/src/core/ConfigLoader_default.h b/src/core/config/ConfigLoader_default.h similarity index 100% rename from src/core/ConfigLoader_default.h rename to src/core/config/ConfigLoader_default.h diff --git a/src/core/ConfigLoader_platform.h b/src/core/config/ConfigLoader_platform.h similarity index 100% rename from src/core/ConfigLoader_platform.h rename to src/core/config/ConfigLoader_platform.h diff --git a/src/core/usage.h b/src/core/config/usage.h similarity index 100% rename from src/core/usage.h rename to src/core/config/usage.h diff --git a/src/net/Network.cpp b/src/net/Network.cpp index fa0d00a4..02489b8d 100644 --- a/src/net/Network.cpp +++ b/src/net/Network.cpp @@ -37,7 +37,7 @@ #include "base/net/stratum/SubmitResult.h" #include "base/tools/Chrono.h" #include "base/tools/Timer.h" -#include "core/Config.h" +#include "core/config/Config.h" #include "core/Controller.h" #include "net/Network.h" #include "net/strategies/DonateStrategy.h" diff --git a/src/net/strategies/DonateStrategy.cpp b/src/net/strategies/DonateStrategy.cpp index adfb9a99..9275bde9 100644 --- a/src/net/strategies/DonateStrategy.cpp +++ b/src/net/strategies/DonateStrategy.cpp @@ -35,7 +35,7 @@ #include "common/crypto/keccak.h" #include "common/Platform.h" #include "common/xmrig.h" -#include "core/Config.h" +#include "core/config/Config.h" #include "core/Controller.h" #include "net/Network.h" #include "net/strategies/DonateStrategy.h" diff --git a/src/workers/Hashrate.cpp b/src/workers/Hashrate.cpp index b2abdf29..568817cd 100644 --- a/src/workers/Hashrate.cpp +++ b/src/workers/Hashrate.cpp @@ -32,7 +32,7 @@ #include "base/io/log/Log.h" #include "base/tools/Handle.h" -#include "core/Config.h" +#include "core/config/Config.h" #include "core/Controller.h" #include "workers/Hashrate.h" diff --git a/src/workers/Workers.cpp b/src/workers/Workers.cpp index 79045df7..1e22f403 100644 --- a/src/workers/Workers.cpp +++ b/src/workers/Workers.cpp @@ -30,7 +30,7 @@ #include "api/Api.h" #include "base/io/log/Log.h" #include "base/tools/Handle.h" -#include "core/Config.h" +#include "core/config/Config.h" #include "core/Controller.h" #include "crypto/CryptoNight_constants.h" #include "interfaces/IJobResultListener.h" From f8f9d6c0ef63feebd595d2009f6b0c26ef1fc183 Mon Sep 17 00:00:00 2001 From: XMRig Date: Sun, 31 Mar 2019 01:31:40 +0700 Subject: [PATCH 051/116] Restored API. --- CMakeLists.txt | 16 +- src/api/Api.cpp | 14 +- src/api/Api.h | 2 + src/api/ApiRouter.cpp | 292 ---------------------------- src/api/requests/HttpApiRequest.cpp | 29 ++- src/api/requests/HttpApiRequest.h | 4 +- src/api/v1/ApiRouter.cpp | 179 +++++++++++++++++ src/api/{ => v1}/ApiRouter.h | 35 ++-- src/common/config/CommonConfig.cpp | 8 +- src/common/config/CommonConfig.h | 2 +- src/common/config/ConfigLoader.cpp | 22 ++- src/common/config/ConfigLoader.h | 5 +- src/common/interfaces/IConfig.h | 2 +- src/core/config/Config.cpp | 8 +- src/core/config/Config.h | 4 +- src/net/Network.cpp | 2 +- 16 files changed, 272 insertions(+), 352 deletions(-) delete mode 100644 src/api/ApiRouter.cpp create mode 100644 src/api/v1/ApiRouter.cpp rename src/api/{ => v1}/ApiRouter.h (63%) diff --git a/CMakeLists.txt b/CMakeLists.txt index f1eeeeef..c9513258 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -205,15 +205,17 @@ endif() if (WITH_HTTPD) set(HTTPD_SOURCES - src/api/Api.h - src/api/interfaces/IApiRequest.h - src/api/requests/ApiRequest.h - src/api/requests/ApiRequest.cpp - src/api/requests/HttpApiRequest.h - src/api/Httpd.h src/api/Api.cpp - src/api/requests/HttpApiRequest.cpp + src/api/Api.h src/api/Httpd.cpp + src/api/Httpd.h + src/api/interfaces/IApiRequest.h + src/api/requests/ApiRequest.cpp + src/api/requests/ApiRequest.h + src/api/requests/HttpApiRequest.cpp + src/api/requests/HttpApiRequest.h + src/api/v1/ApiRouter.cpp + src/api/v1/ApiRouter.h ) else() set(HTTPD_SOURCES "") diff --git a/src/api/Api.cpp b/src/api/Api.cpp index 527565ed..f6b5ba01 100644 --- a/src/api/Api.cpp +++ b/src/api/Api.cpp @@ -30,6 +30,7 @@ #include "api/Api.h" #include "api/interfaces/IApiListener.h" #include "api/requests/HttpApiRequest.h" +#include "api/v1/ApiRouter.h" #include "base/tools/Buffer.h" #include "common/crypto/keccak.h" #include "core/config/Config.h" @@ -51,11 +52,16 @@ xmrig::Api::Api(Controller *controller) : controller->addListener(this); genId(m_controller->config()->apiId()); + + m_v1 = new ApiRouter(controller); + addListener(m_v1); } xmrig::Api::~Api() { + delete m_v1; + # ifdef XMRIG_FEATURE_HTTP delete m_httpd; # endif @@ -103,10 +109,12 @@ void xmrig::Api::onConfigChanged(Config *config, Config *previousConfig) void xmrig::Api::exec(IApiRequest &request) { - if (request.method() == IApiRequest::METHOD_GET && request.url() == "/1/summary") { + using namespace rapidjson; + + if (request.method() == IApiRequest::METHOD_GET && (request.url() == "/1/summary" || request.url() == "/api.json")) { request.accept(); - request.reply().AddMember("id", rapidjson::StringRef(m_id), request.doc().GetAllocator()); - request.reply().AddMember("worker_id", rapidjson::StringRef(m_workerId), request.doc().GetAllocator());; + request.reply().AddMember("id", StringRef(m_id), request.doc().GetAllocator()); + request.reply().AddMember("worker_id", StringRef(m_workerId), request.doc().GetAllocator());; } for (IApiListener *listener : m_listeners) { diff --git a/src/api/Api.h b/src/api/Api.h index dc4e8e21..d76e3105 100644 --- a/src/api/Api.h +++ b/src/api/Api.h @@ -35,6 +35,7 @@ namespace xmrig { +class ApiRouter; class Controller; class Httpd; class HttpRequest; @@ -65,6 +66,7 @@ private: void genId(const String &id); void genWorkerId(const String &id); + ApiRouter *m_v1; char m_id[32]; char m_workerId[128]; Controller *m_controller; diff --git a/src/api/ApiRouter.cpp b/src/api/ApiRouter.cpp deleted file mode 100644 index 30597f46..00000000 --- a/src/api/ApiRouter.cpp +++ /dev/null @@ -1,292 +0,0 @@ -/* XMRig - * Copyright 2010 Jeff Garzik - * Copyright 2012-2014 pooler - * Copyright 2014 Lucas Jones - * Copyright 2014-2016 Wolf9466 - * Copyright 2016 Jay D Dee - * Copyright 2017-2018 XMR-Stak , - * Copyright 2018-2019 SChernykh - * Copyright 2016-2019 XMRig , - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#include -#include -#include - -#if _WIN32 -# include "winsock2.h" -#else -# include "unistd.h" -#endif - - -#include "api/ApiRouter.h" -#include "base/tools/Buffer.h" -#include "common/api/HttpReply.h" -#include "common/api/HttpRequest.h" -#include "common/cpu/Cpu.h" -#include "common/crypto/keccak.h" -#include "common/Platform.h" -#include "core/Config.h" -#include "core/Controller.h" -#include "interfaces/IThread.h" -#include "rapidjson/document.h" -#include "rapidjson/prettywriter.h" -#include "rapidjson/stringbuffer.h" -#include "version.h" -#include "workers/Hashrate.h" -#include "workers/Workers.h" - - -static inline double normalize(double d) -{ - if (!isnormal(d)) { - return 0.0; - } - - return floor(d * 100.0) / 100.0; -} - - -ApiRouter::ApiRouter(xmrig::Controller *controller) : - m_controller(controller) -{ - memset(m_workerId, 0, sizeof(m_workerId)); - - setWorkerId(controller->config()->apiWorkerId()); - genId(controller->config()->apiId()); -} - - -ApiRouter::~ApiRouter() -{ -} - - -void ApiRouter::ApiRouter::get(const xmrig::HttpRequest &req, xmrig::HttpReply &reply) const -{ - rapidjson::Document doc; - - if (req.match("/1/config")) { - if (req.isRestricted()) { - reply.status = 403; - return; - } - - m_controller->config()->getJSON(doc); - - return finalize(reply, doc); - } - - if (req.match("/1/threads")) { - getThreads(doc); - - return finalize(reply, doc); - } - - doc.SetObject(); - - getIdentify(doc); - getMiner(doc); - getHashrate(doc); - - return finalize(reply, doc); -} - - -void ApiRouter::exec(const xmrig::HttpRequest &req, xmrig::HttpReply &reply) -{ - if (req.method() == xmrig::HttpRequest::Put && req.match("/1/config")) { - m_controller->config()->reload(req.body()); - return; - } - - reply.status = 404; -} - - -void ApiRouter::onConfigChanged(xmrig::Config *config, xmrig::Config *previousConfig) -{ - updateWorkerId(config->apiWorkerId(), previousConfig->apiWorkerId()); -} - - -void ApiRouter::finalize(xmrig::HttpReply &reply, rapidjson::Document &doc) const -{ - rapidjson::StringBuffer buffer(nullptr, 4096); - rapidjson::PrettyWriter writer(buffer); - writer.SetMaxDecimalPlaces(10); - doc.Accept(writer); - - reply.status = 200; - reply.buf = strdup(buffer.GetString()); - reply.size = buffer.GetSize(); -} - - -void ApiRouter::genId(const char *id) -{ - memset(m_id, 0, sizeof(m_id)); - - if (id && strlen(id) > 0) { - strncpy(m_id, id, sizeof(m_id) - 1); - return; - } - - uv_interface_address_t *interfaces; - int count = 0; - - if (uv_interface_addresses(&interfaces, &count) < 0) { - return; - } - - for (int i = 0; i < count; i++) { - if (!interfaces[i].is_internal && interfaces[i].address.address4.sin_family == AF_INET) { - uint8_t hash[200]; - const size_t addrSize = sizeof(interfaces[i].phys_addr); - const size_t inSize = strlen(APP_KIND) + addrSize + sizeof(uint16_t); - const uint16_t port = static_cast(m_controller->config()->http().port()); - - uint8_t *input = new uint8_t[inSize](); - memcpy(input, &port, sizeof(uint16_t)); - memcpy(input + sizeof(uint16_t), interfaces[i].phys_addr, addrSize); - memcpy(input + sizeof(uint16_t) + addrSize, APP_KIND, strlen(APP_KIND)); - - xmrig::keccak(input, inSize, hash); - xmrig::Buffer::toHex(hash, 8, m_id); - - delete [] input; - break; - } - } - - uv_free_interface_addresses(interfaces, count); -} - - -void ApiRouter::getHashrate(rapidjson::Document &doc) const -{ - auto &allocator = doc.GetAllocator(); - - rapidjson::Value hashrate(rapidjson::kObjectType); - rapidjson::Value total(rapidjson::kArrayType); - rapidjson::Value threads(rapidjson::kArrayType); - - const Hashrate *hr = Workers::hashrate(); - - total.PushBack(normalize(hr->calc(Hashrate::ShortInterval)), allocator); - total.PushBack(normalize(hr->calc(Hashrate::MediumInterval)), allocator); - total.PushBack(normalize(hr->calc(Hashrate::LargeInterval)), allocator); - - for (size_t i = 0; i < Workers::threads(); i++) { - rapidjson::Value thread(rapidjson::kArrayType); - thread.PushBack(normalize(hr->calc(i, Hashrate::ShortInterval)), allocator); - thread.PushBack(normalize(hr->calc(i, Hashrate::MediumInterval)), allocator); - thread.PushBack(normalize(hr->calc(i, Hashrate::LargeInterval)), allocator); - - threads.PushBack(thread, allocator); - } - - hashrate.AddMember("total", total, allocator); - hashrate.AddMember("highest", normalize(hr->highest()), allocator); - hashrate.AddMember("threads", threads, allocator); - doc.AddMember("hashrate", hashrate, allocator); -} - - -void ApiRouter::getIdentify(rapidjson::Document &doc) const -{ - doc.AddMember("id", rapidjson::StringRef(m_id), doc.GetAllocator()); - doc.AddMember("worker_id", rapidjson::StringRef(m_workerId), doc.GetAllocator()); -} - - -void ApiRouter::getMiner(rapidjson::Document &doc) const -{ - using namespace xmrig; - auto &allocator = doc.GetAllocator(); - - rapidjson::Value cpu(rapidjson::kObjectType); - cpu.AddMember("brand", rapidjson::StringRef(Cpu::info()->brand()), allocator); - cpu.AddMember("aes", Cpu::info()->hasAES(), allocator); - cpu.AddMember("x64", Cpu::info()->isX64(), allocator); - cpu.AddMember("sockets", Cpu::info()->sockets(), allocator); - - doc.AddMember("version", APP_VERSION, allocator); - doc.AddMember("kind", APP_KIND, allocator); - doc.AddMember("ua", rapidjson::StringRef(Platform::userAgent()), allocator); - doc.AddMember("cpu", cpu, allocator); - doc.AddMember("algo", rapidjson::StringRef(m_controller->config()->algorithm().name()), allocator); - doc.AddMember("hugepages", Workers::hugePages() > 0, allocator); - doc.AddMember("donate_level", m_controller->config()->pools().donateLevel(), allocator); -} - - -void ApiRouter::getThreads(rapidjson::Document &doc) const -{ - doc.SetObject(); - auto &allocator = doc.GetAllocator(); - const Hashrate *hr = Workers::hashrate(); - - Workers::threadsSummary(doc); - - const std::vector &threads = m_controller->config()->threads(); - rapidjson::Value list(rapidjson::kArrayType); - - size_t i = 0; - for (const xmrig::IThread *thread : threads) { - rapidjson::Value value = thread->toAPI(doc); - - rapidjson::Value hashrate(rapidjson::kArrayType); - hashrate.PushBack(normalize(hr->calc(i, Hashrate::ShortInterval)), allocator); - hashrate.PushBack(normalize(hr->calc(i, Hashrate::MediumInterval)), allocator); - hashrate.PushBack(normalize(hr->calc(i, Hashrate::LargeInterval)), allocator); - - i++; - - value.AddMember("hashrate", hashrate, allocator); - list.PushBack(value, allocator); - } - - doc.AddMember("threads", list, allocator); -} - - -void ApiRouter::setWorkerId(const char *id) -{ - memset(m_workerId, 0, sizeof(m_workerId)); - - if (id && strlen(id) > 0) { - strncpy(m_workerId, id, sizeof(m_workerId) - 1); - } - else { - gethostname(m_workerId, sizeof(m_workerId) - 1); - } -} - - -void ApiRouter::updateWorkerId(const char *id, const char *previousId) -{ - if (id == previousId) { - return; - } - - if (id != nullptr && previousId != nullptr && strcmp(id, previousId) == 0) { - return; - } - - setWorkerId(id); -} diff --git a/src/api/requests/HttpApiRequest.cpp b/src/api/requests/HttpApiRequest.cpp index fac69f51..a61dde8d 100644 --- a/src/api/requests/HttpApiRequest.cpp +++ b/src/api/requests/HttpApiRequest.cpp @@ -25,10 +25,12 @@ #include "api/requests/HttpApiRequest.h" #include "base/net/http/HttpRequest.h" +#include "rapidjson/error/en.h" xmrig::HttpApiRequest::HttpApiRequest(const HttpRequest &req, bool restricted) : ApiRequest(SOURCE_HTTP, restricted), + m_parsed(false), m_req(req), m_res(req.id()), m_url(req.url.c_str()) @@ -36,20 +38,39 @@ xmrig::HttpApiRequest::HttpApiRequest(const HttpRequest &req, bool restricted) : } +const rapidjson::Value &xmrig::HttpApiRequest::json() const +{ + return m_body; +} + + xmrig::IApiRequest::Method xmrig::HttpApiRequest::method() const { return static_cast(m_req.method); } +void xmrig::HttpApiRequest::accept() +{ + using namespace rapidjson; + + ApiRequest::accept(); + + if (!m_parsed && !m_req.body.empty()) { + m_parsed = true; + m_body.Parse(m_req.body.c_str()); + + if (m_body.HasParseError()) { + reply().AddMember("error", StringRef(GetParseError_En(m_body.GetParseError())), doc().GetAllocator());; + } + } +} + + void xmrig::HttpApiRequest::done(int status) { ApiRequest::done(status); - if (status >= 400) { - reply().AddMember("status", status, doc().GetAllocator()); - } - m_res.setStatus(status); m_res.end(); } diff --git a/src/api/requests/HttpApiRequest.h b/src/api/requests/HttpApiRequest.h index dbe640ef..26f26f39 100644 --- a/src/api/requests/HttpApiRequest.h +++ b/src/api/requests/HttpApiRequest.h @@ -44,15 +44,17 @@ public: HttpApiRequest(const HttpRequest &req, bool restricted); protected: - inline const rapidjson::Value &json() const override { return m_body; } inline rapidjson::Document &doc() override { return m_res.doc(); } inline rapidjson::Value &reply() override { return m_res.doc(); } inline const String &url() const override { return m_url; } + const rapidjson::Value &json() const override; Method method() const override; + void accept() override; void done(int status) override; private: + bool m_parsed; const HttpRequest &m_req; HttpApiResponse m_res; rapidjson::Document m_body; diff --git a/src/api/v1/ApiRouter.cpp b/src/api/v1/ApiRouter.cpp new file mode 100644 index 00000000..2914b755 --- /dev/null +++ b/src/api/v1/ApiRouter.cpp @@ -0,0 +1,179 @@ +/* XMRig + * Copyright 2010 Jeff Garzik + * Copyright 2012-2014 pooler + * Copyright 2014 Lucas Jones + * Copyright 2014-2016 Wolf9466 + * Copyright 2016 Jay D Dee + * Copyright 2017-2018 XMR-Stak , + * Copyright 2018-2019 SChernykh + * Copyright 2016-2019 XMRig , + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include +#include +#include + + +#include "api/interfaces/IApiRequest.h" +#include "api/v1/ApiRouter.h" +#include "common/cpu/Cpu.h" +#include "common/Platform.h" +#include "core/config/Config.h" +#include "core/Controller.h" +#include "interfaces/IThread.h" +#include "rapidjson/document.h" +#include "version.h" +#include "workers/Hashrate.h" +#include "workers/Workers.h" + + +static inline double normalize(double d) +{ + if (!isnormal(d)) { + return 0.0; + } + + return floor(d * 100.0) / 100.0; +} + + +xmrig::ApiRouter::ApiRouter(xmrig::Controller *controller) : + m_controller(controller) +{ +} + + +xmrig::ApiRouter::~ApiRouter() +{ +} + + +void xmrig::ApiRouter::onRequest(IApiRequest &request) +{ + printf("xmrig::ApiRouter::onRequest\n %d", request.method()); + + if (request.method() == IApiRequest::METHOD_GET) { + if (request.url() == "/1/summary" || request.url() == "/api.json") { + request.accept(); + getMiner(request.reply(), request.doc()); + getHashrate(request.reply(), request.doc()); + } + else if (request.url() == "/1/threads") { + request.accept(); + getThreads(request.reply(), request.doc()); + } + else if (request.url() == "/1/config") { + if (request.isRestricted()) { + return request.done(403); + } + + m_controller->config()->getJSON(request.doc()); + } + } + else if (request.method() == IApiRequest::METHOD_PUT || request.method() == IApiRequest::METHOD_POST) { + if (request.url() == "/1/config") { + request.accept(); + + if (!m_controller->config()->reload(request.json())) { + return request.done(400); + } + + request.done(204); + } + } +} + + +void xmrig::ApiRouter::getHashrate(rapidjson::Value &reply, rapidjson::Document &doc) const +{ + using namespace rapidjson; + auto &allocator = doc.GetAllocator(); + + Value hashrate(kObjectType); + Value total(kArrayType); + Value threads(kArrayType); + + const Hashrate *hr = Workers::hashrate(); + + total.PushBack(normalize(hr->calc(Hashrate::ShortInterval)), allocator); + total.PushBack(normalize(hr->calc(Hashrate::MediumInterval)), allocator); + total.PushBack(normalize(hr->calc(Hashrate::LargeInterval)), allocator); + + for (size_t i = 0; i < Workers::threads(); i++) { + Value thread(kArrayType); + thread.PushBack(normalize(hr->calc(i, Hashrate::ShortInterval)), allocator); + thread.PushBack(normalize(hr->calc(i, Hashrate::MediumInterval)), allocator); + thread.PushBack(normalize(hr->calc(i, Hashrate::LargeInterval)), allocator); + + threads.PushBack(thread, allocator); + } + + hashrate.AddMember("total", total, allocator); + hashrate.AddMember("highest", normalize(hr->highest()), allocator); + hashrate.AddMember("threads", threads, allocator); + reply.AddMember("hashrate", hashrate, allocator); +} + + +void xmrig::ApiRouter::getMiner(rapidjson::Value &reply, rapidjson::Document &doc) const +{ + using namespace rapidjson; + auto &allocator = doc.GetAllocator(); + + Value cpu(kObjectType); + cpu.AddMember("brand", StringRef(Cpu::info()->brand()), allocator); + cpu.AddMember("aes", Cpu::info()->hasAES(), allocator); + cpu.AddMember("x64", Cpu::info()->isX64(), allocator); + cpu.AddMember("sockets", Cpu::info()->sockets(), allocator); + + reply.AddMember("version", APP_VERSION, allocator); + reply.AddMember("kind", APP_KIND, allocator); + reply.AddMember("ua", StringRef(Platform::userAgent()), allocator); + reply.AddMember("cpu", cpu, allocator); + reply.AddMember("algo", StringRef(m_controller->config()->algorithm().name()), allocator); + reply.AddMember("hugepages", Workers::hugePages() > 0, allocator); + reply.AddMember("donate_level", m_controller->config()->pools().donateLevel(), allocator); +} + + +void xmrig::ApiRouter::getThreads(rapidjson::Value &reply, rapidjson::Document &doc) const +{ + using namespace rapidjson; + auto &allocator = doc.GetAllocator(); + const Hashrate *hr = Workers::hashrate(); + + Workers::threadsSummary(doc); + + const std::vector &threads = m_controller->config()->threads(); + Value list(kArrayType); + + size_t i = 0; + for (const xmrig::IThread *thread : threads) { + Value value = thread->toAPI(doc); + + Value hashrate(kArrayType); + hashrate.PushBack(normalize(hr->calc(i, Hashrate::ShortInterval)), allocator); + hashrate.PushBack(normalize(hr->calc(i, Hashrate::MediumInterval)), allocator); + hashrate.PushBack(normalize(hr->calc(i, Hashrate::LargeInterval)), allocator); + + i++; + + value.AddMember("hashrate", hashrate, allocator); + list.PushBack(value, allocator); + } + + reply.AddMember("threads", list, allocator); +} diff --git a/src/api/ApiRouter.h b/src/api/v1/ApiRouter.h similarity index 63% rename from src/api/ApiRouter.h rename to src/api/v1/ApiRouter.h index cbdc04b8..02be91e2 100644 --- a/src/api/ApiRouter.h +++ b/src/api/v1/ApiRouter.h @@ -27,7 +27,7 @@ #include "net/NetworkState.h" -#include "base/kernel/interfaces/IControllerListener.h" +#include "api/interfaces/IApiListener.h" #include "rapidjson/fwd.h" @@ -35,37 +35,30 @@ class Hashrate; namespace xmrig { - class Controller; - class HttpReply; - class HttpRequest; -} -class ApiRouter : public xmrig::IControllerListener +class Controller; + + +class ApiRouter : public xmrig::IApiListener { public: ApiRouter(xmrig::Controller *controller); ~ApiRouter() override; - void get(const xmrig::HttpRequest &req, xmrig::HttpReply &reply) const; - void exec(const xmrig::HttpRequest &req, xmrig::HttpReply &reply); - protected: - void onConfigChanged(xmrig::Config *config, xmrig::Config *previousConfig) override; + void onRequest(IApiRequest &request) override; private: - void finalize(xmrig::HttpReply &reply, rapidjson::Document &doc) const; - void genId(const char *id); - void getHashrate(rapidjson::Document &doc) const; - void getIdentify(rapidjson::Document &doc) const; - void getMiner(rapidjson::Document &doc) const; - void getThreads(rapidjson::Document &doc) const; - void setWorkerId(const char *id); - void updateWorkerId(const char *id, const char *previousId); + void getHashrate(rapidjson::Value &reply, rapidjson::Document &doc) const; + void getMiner(rapidjson::Value &reply, rapidjson::Document &doc) const; + void getThreads(rapidjson::Value &reply, rapidjson::Document &doc) const; - char m_id[32]; - char m_workerId[128]; - xmrig::Controller *m_controller; + Controller *m_controller; }; + +} // namespace xmrig + + #endif /* XMRIG_APIROUTER_H */ diff --git a/src/common/config/CommonConfig.cpp b/src/common/config/CommonConfig.cpp index b7ad520f..55bb0a49 100644 --- a/src/common/config/CommonConfig.cpp +++ b/src/common/config/CommonConfig.cpp @@ -343,21 +343,21 @@ bool xmrig::CommonConfig::parseUint64(int key, uint64_t arg) } -void xmrig::CommonConfig::parseJSON(const rapidjson::Document &doc) +void xmrig::CommonConfig::parseJSON(const rapidjson::Value &json) { - const rapidjson::Value &pools = doc["pools"]; + const rapidjson::Value &pools = json["pools"]; if (pools.IsArray()) { m_pools.load(pools); } # ifdef XMRIG_DEPRECATED - const rapidjson::Value &api = doc["api"]; + const rapidjson::Value &api = json["api"]; if (api.IsObject() && api.HasMember("port")) { m_upgrade = true; m_http.load(api); } else { - m_http.load(doc["http"]); + m_http.load(json["http"]); } # else m_http.load(doc["http"]); diff --git a/src/common/config/CommonConfig.h b/src/common/config/CommonConfig.h index e3331fe0..55f36d0d 100644 --- a/src/common/config/CommonConfig.h +++ b/src/common/config/CommonConfig.h @@ -71,7 +71,7 @@ protected: bool parseBoolean(int key, bool enable) override; bool parseString(int key, const char *arg) override; bool parseUint64(int key, uint64_t arg) override; - void parseJSON(const rapidjson::Document &doc) override; + void parseJSON(const rapidjson::Value &json) override; void setFileName(const char *fileName) override; Algorithm m_algorithm; diff --git a/src/common/config/ConfigLoader.cpp b/src/common/config/ConfigLoader.cpp index 6f145440..2b7f50ce 100644 --- a/src/common/config/ConfigLoader.cpp +++ b/src/common/config/ConfigLoader.cpp @@ -48,8 +48,12 @@ #endif -xmrig::ConfigWatcher *xmrig::ConfigLoader::m_watcher = nullptr; -xmrig::IConfigListener *xmrig::ConfigLoader::m_listener = nullptr; +namespace xmrig { + +ConfigWatcher *ConfigLoader::m_watcher = nullptr; +IConfigListener *ConfigLoader::m_listener = nullptr; + +} // namespace xmrig #ifndef ARRAY_SIZE @@ -84,26 +88,26 @@ bool xmrig::ConfigLoader::loadFromJSON(xmrig::IConfig *config, const char *json) } -bool xmrig::ConfigLoader::loadFromJSON(xmrig::IConfig *config, const rapidjson::Document &doc) +bool xmrig::ConfigLoader::loadFromJSON(xmrig::IConfig *config, const rapidjson::Value &json) { for (size_t i = 0; i < ARRAY_SIZE(config_options); i++) { - parseJSON(config, &config_options[i], doc); + parseJSON(config, &config_options[i], json); } - const rapidjson::Value &api = doc["api"]; + const rapidjson::Value &api = json["api"]; if (api.IsObject()) { for (size_t i = 0; i < ARRAY_SIZE(api_options); i++) { parseJSON(config, &api_options[i], api); } } - config->parseJSON(doc); + config->parseJSON(json); return config->finalize(); } -bool xmrig::ConfigLoader::reload(xmrig::IConfig *oldConfig, const char *json) +bool xmrig::ConfigLoader::reload(xmrig::IConfig *oldConfig, const rapidjson::Value &json) { IConfig *config = Config::create(); if (!loadFromJSON(config, json)) { @@ -134,7 +138,7 @@ bool xmrig::ConfigLoader::watch(IConfig *config) assert(m_watcher == nullptr); - m_watcher = new xmrig::ConfigWatcher(config->fileName(), m_listener); + m_watcher = new ConfigWatcher(config->fileName(), m_listener); return true; } @@ -225,7 +229,7 @@ bool xmrig::ConfigLoader::getJSON(const char *fileName, rapidjson::Document &doc bool xmrig::ConfigLoader::parseArg(xmrig::IConfig *config, int key, const char *arg) { - if (key == xmrig::IConfig::ConfigKey) { + if (key == IConfig::ConfigKey) { return loadFromFile(config, arg); } diff --git a/src/common/config/ConfigLoader.h b/src/common/config/ConfigLoader.h index 322aafcf..f03de711 100644 --- a/src/common/config/ConfigLoader.h +++ b/src/common/config/ConfigLoader.h @@ -49,8 +49,8 @@ class ConfigLoader public: static bool loadFromFile(IConfig *config, const char *fileName); static bool loadFromJSON(IConfig *config, const char *json); - static bool loadFromJSON(IConfig *config, const rapidjson::Document &doc); - static bool reload(IConfig *oldConfig, const char *json); + static bool loadFromJSON(IConfig *config, const rapidjson::Value &json); + static bool reload(IConfig *oldConfig, const rapidjson::Value &json); static bool watch(IConfig *config); static IConfig *load(Process *process, IConfigListener *listener); static void release(); @@ -67,4 +67,5 @@ private: } /* namespace xmrig */ + #endif /* XMRIG_CONFIGLOADER_H */ diff --git a/src/common/interfaces/IConfig.h b/src/common/interfaces/IConfig.h index 2228d2c9..c897ee37 100644 --- a/src/common/interfaces/IConfig.h +++ b/src/common/interfaces/IConfig.h @@ -150,7 +150,7 @@ public: virtual const Algorithm &algorithm() const = 0; virtual const String &fileName() const = 0; virtual void getJSON(rapidjson::Document &doc) const = 0; - virtual void parseJSON(const rapidjson::Document &doc) = 0; + virtual void parseJSON(const rapidjson::Value &json) = 0; virtual void setFileName(const char *fileName) = 0; static IConfig *create(); diff --git a/src/core/config/Config.cpp b/src/core/config/Config.cpp index 5b337197..2b706d74 100644 --- a/src/core/config/Config.cpp +++ b/src/core/config/Config.cpp @@ -55,7 +55,7 @@ xmrig::Config::Config() : xmrig::CommonConfig(), } -bool xmrig::Config::reload(const char *json) +bool xmrig::Config::reload(const rapidjson::Value &json) { return xmrig::ConfigLoader::reload(this, json); } @@ -277,11 +277,11 @@ bool xmrig::Config::parseUint64(int key, uint64_t arg) } -void xmrig::Config::parseJSON(const rapidjson::Document &doc) +void xmrig::Config::parseJSON(const rapidjson::Value &json) { - CommonConfig::parseJSON(doc); + CommonConfig::parseJSON(json); - const rapidjson::Value &threads = doc["threads"]; + const rapidjson::Value &threads = json["threads"]; if (threads.IsArray()) { for (const rapidjson::Value &value : threads.GetArray()) { diff --git a/src/core/config/Config.h b/src/core/config/Config.h index 261955c5..2a8ca11d 100644 --- a/src/core/config/Config.h +++ b/src/core/config/Config.h @@ -67,7 +67,7 @@ public: Config(); - bool reload(const char *json); + bool reload(const rapidjson::Value &json); void getJSON(rapidjson::Document &doc) const override; @@ -90,7 +90,7 @@ protected: bool parseBoolean(int key, bool enable) override; bool parseString(int key, const char *arg) override; bool parseUint64(int key, uint64_t arg) override; - void parseJSON(const rapidjson::Document &doc) override; + void parseJSON(const rapidjson::Value &json) override; private: bool parseInt(int key, int arg); diff --git a/src/net/Network.cpp b/src/net/Network.cpp index 02489b8d..5de840ea 100644 --- a/src/net/Network.cpp +++ b/src/net/Network.cpp @@ -166,7 +166,7 @@ void xmrig::Network::onPause(IStrategy *strategy) void xmrig::Network::onRequest(IApiRequest &request) { # ifdef XMRIG_FEATURE_API - if (request.method() == IApiRequest::METHOD_GET && request.url() == "/1/summary") { + if (request.method() == IApiRequest::METHOD_GET && (request.url() == "/1/summary" || request.url() == "/api.json")) { request.accept(); getResults(request.reply(), request.doc()); From ca249f1f1ca84701daa0e2ac6dc65f1f9e5fc540 Mon Sep 17 00:00:00 2001 From: XMRig Date: Sun, 31 Mar 2019 01:44:53 +0700 Subject: [PATCH 052/116] Cleanup. --- cmake/FindMHD.cmake | 49 --------- src/api/v1/ApiRouter.cpp | 2 - src/common/api/HttpBody.h | 69 ------------- src/common/api/HttpReply.h | 53 ---------- src/common/api/HttpRequest.cpp | 175 --------------------------------- src/common/api/HttpRequest.h | 84 ---------------- 6 files changed, 432 deletions(-) delete mode 100644 cmake/FindMHD.cmake delete mode 100644 src/common/api/HttpBody.h delete mode 100644 src/common/api/HttpReply.h delete mode 100644 src/common/api/HttpRequest.cpp delete mode 100644 src/common/api/HttpRequest.h diff --git a/cmake/FindMHD.cmake b/cmake/FindMHD.cmake deleted file mode 100644 index 7a598e02..00000000 --- a/cmake/FindMHD.cmake +++ /dev/null @@ -1,49 +0,0 @@ -# - Try to find MHD -# Once done this will define -# -# MHD_FOUND - system has MHD -# MHD_INCLUDE_DIRS - the MHD include directory -# MHD_LIBRARY - Link these to use MHD - -find_path( - MHD_INCLUDE_DIR - NAMES microhttpd.h - PATHS "${XMRIG_DEPS}" ENV "XMRIG_DEPS" - PATH_SUFFIXES "include" - DOC "microhttpd include dir" - NO_DEFAULT_PATH -) - -find_path(MHD_INCLUDE_DIR NAMES microhttpd.h) - -find_library( - MHD_LIBRARY - NAMES libmicrohttpd.a microhttpd libmicrohttpd - PATHS "${XMRIG_DEPS}" ENV "XMRIG_DEPS" - PATH_SUFFIXES "lib" - DOC "microhttpd library" - NO_DEFAULT_PATH -) - -find_library(MHD_LIBRARY NAMES microhttpd libmicrohttpd) - -set(MHD_INCLUDE_DIRS ${MHD_INCLUDE_DIR}) -set(MHD_LIBRARIES ${MHD_LIBRARY}) - -# debug library on windows -# same naming convention as in qt (appending debug library with d) -# boost is using the same "hack" as us with "optimized" and "debug" -# official MHD project actually uses _d suffix -if (${CMAKE_CXX_COMPILER_ID} STREQUAL MSVC) - find_library( - MHD_LIBRARY_DEBUG - NAMES microhttpd_d microhttpd-10_d libmicrohttpd_d libmicrohttpd-dll_d - DOC "mhd debug library" - ) - set(MHD_LIBRARIES optimized ${MHD_LIBRARIES} debug ${MHD_LIBRARY_DEBUG}) -endif() - -include(FindPackageHandleStandardArgs) -find_package_handle_standard_args(MHD DEFAULT_MSG MHD_LIBRARY MHD_INCLUDE_DIR) -mark_as_advanced(MHD_INCLUDE_DIR MHD_LIBRARY) - diff --git a/src/api/v1/ApiRouter.cpp b/src/api/v1/ApiRouter.cpp index 2914b755..029d0a3b 100644 --- a/src/api/v1/ApiRouter.cpp +++ b/src/api/v1/ApiRouter.cpp @@ -63,8 +63,6 @@ xmrig::ApiRouter::~ApiRouter() void xmrig::ApiRouter::onRequest(IApiRequest &request) { - printf("xmrig::ApiRouter::onRequest\n %d", request.method()); - if (request.method() == IApiRequest::METHOD_GET) { if (request.url() == "/1/summary" || request.url() == "/api.json") { request.accept(); diff --git a/src/common/api/HttpBody.h b/src/common/api/HttpBody.h deleted file mode 100644 index 0b143fb7..00000000 --- a/src/common/api/HttpBody.h +++ /dev/null @@ -1,69 +0,0 @@ -/* XMRig - * Copyright 2010 Jeff Garzik - * Copyright 2012-2014 pooler - * Copyright 2014 Lucas Jones - * Copyright 2014-2016 Wolf9466 - * Copyright 2016 Jay D Dee - * Copyright 2017-2018 XMR-Stak , - * Copyright 2016-2018 XMRig , - * - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#ifndef __HTTPBODY_H__ -#define __HTTPBODY_H__ - - -#include - - -namespace xmrig { - - -class HttpBody -{ -public: - inline HttpBody() : - m_pos(0) - {} - - - inline bool write(const char *data, size_t size) - { - if (size > (sizeof(m_data) - m_pos - 1)) { - return false; - } - - memcpy(m_data + m_pos, data, size); - - m_pos += size; - m_data[m_pos] = '\0'; - - return true; - } - - - inline const char *data() const { return m_data; } - -private: - char m_data[32768]; - size_t m_pos; -}; - - -} /* namespace xmrig */ - - -#endif /* __HTTPBODY_H__ */ diff --git a/src/common/api/HttpReply.h b/src/common/api/HttpReply.h deleted file mode 100644 index 6a6cb802..00000000 --- a/src/common/api/HttpReply.h +++ /dev/null @@ -1,53 +0,0 @@ -/* XMRig - * Copyright 2010 Jeff Garzik - * Copyright 2012-2014 pooler - * Copyright 2014 Lucas Jones - * Copyright 2014-2016 Wolf9466 - * Copyright 2016 Jay D Dee - * Copyright 2017-2018 XMR-Stak , - * Copyright 2016-2018 XMRig , - * - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#ifndef __HTTPREPLY_H__ -#define __HTTPREPLY_H__ - - -#include - - -namespace xmrig { - - -class HttpReply -{ -public: - HttpReply() : - buf(nullptr), - status(200), - size(0) - {} - - char *buf; - int status; - size_t size; -}; - - -} /* namespace xmrig */ - - -#endif /* __HTTPREPLY_H__ */ diff --git a/src/common/api/HttpRequest.cpp b/src/common/api/HttpRequest.cpp deleted file mode 100644 index 6898a385..00000000 --- a/src/common/api/HttpRequest.cpp +++ /dev/null @@ -1,175 +0,0 @@ -/* XMRig - * Copyright 2010 Jeff Garzik - * Copyright 2012-2014 pooler - * Copyright 2014 Lucas Jones - * Copyright 2014-2016 Wolf9466 - * Copyright 2016 Jay D Dee - * Copyright 2017-2018 XMR-Stak , - * Copyright 2016-2018 XMRig , - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - - -#include -#include - -#include "common/api/HttpBody.h" -#include "common/api/HttpRequest.h" -#include "common/api/HttpReply.h" - - -#ifndef MHD_HTTP_PAYLOAD_TOO_LARGE -# define MHD_HTTP_PAYLOAD_TOO_LARGE 413 -#endif - - -xmrig::HttpRequest::HttpRequest(MHD_Connection *connection, const char *url, const char *method, const char *uploadData, size_t *uploadSize, void **cls) : - m_fulfilled(true), - m_restricted(true), - m_uploadData(uploadData), - m_url(url), - m_body(static_cast(*cls)), - m_method(Unsupported), - m_connection(connection), - m_uploadSize(uploadSize), - m_cls(cls) -{ - if (strcmp(method, MHD_HTTP_METHOD_OPTIONS) == 0) { - m_method = Options; - } - else if (strcmp(method, MHD_HTTP_METHOD_GET) == 0) { - m_method = Get; - } - else if (strcmp(method, MHD_HTTP_METHOD_PUT) == 0) { - m_method = Put; - } -} - - -xmrig::HttpRequest::~HttpRequest() -{ - if (m_fulfilled) { - delete m_body; - } -} - - -bool xmrig::HttpRequest::match(const char *path) const -{ - return strcmp(m_url, path) == 0; -} - - -bool xmrig::HttpRequest::process(const char *accessToken, bool restricted, xmrig::HttpReply &reply) -{ - m_restricted = restricted || !accessToken; - - if (m_body) { - if (*m_uploadSize != 0) { - if (!m_body->write(m_uploadData, *m_uploadSize)) { - *m_cls = nullptr; - m_fulfilled = true; - reply.status = MHD_HTTP_PAYLOAD_TOO_LARGE; - return false; - } - - *m_uploadSize = 0; - m_fulfilled = false; - return true; - } - - m_fulfilled = true; - return true; - } - - reply.status = auth(accessToken); - if (reply.status != MHD_HTTP_OK) { - return false; - } - - if (m_restricted && m_method != Get) { - reply.status = MHD_HTTP_FORBIDDEN; - return false; - } - - if (m_method == Get) { - return true; - } - - const char *contentType = MHD_lookup_connection_value(m_connection, MHD_HEADER_KIND, "Content-Type"); - if (!contentType || strcmp(contentType, "application/json") != 0) { - reply.status = MHD_HTTP_UNSUPPORTED_MEDIA_TYPE; - return false; - } - - m_body = new xmrig::HttpBody(); - m_fulfilled = false; - *m_cls = m_body; - - return true; -} - - -const char *xmrig::HttpRequest::body() const -{ - return m_body ? m_body->data() : nullptr; -} - - -int xmrig::HttpRequest::end(const HttpReply &reply) -{ - if (reply.buf) { - return end(reply.status, MHD_create_response_from_buffer(reply.size ? reply.size : strlen(reply.buf), (void*) reply.buf, MHD_RESPMEM_MUST_FREE)); - } - - return end(reply.status, nullptr); -} - - -int xmrig::HttpRequest::end(int status, MHD_Response *rsp) -{ - if (!rsp) { - rsp = MHD_create_response_from_buffer(0, nullptr, MHD_RESPMEM_PERSISTENT); - } - - MHD_add_response_header(rsp, "Content-Type", "application/json"); - MHD_add_response_header(rsp, "Access-Control-Allow-Origin", "*"); - MHD_add_response_header(rsp, "Access-Control-Allow-Methods", "GET, PUT"); - MHD_add_response_header(rsp, "Access-Control-Allow-Headers", "Authorization, Content-Type"); - - const int ret = MHD_queue_response(m_connection, status, rsp); - MHD_destroy_response(rsp); - return ret; -} - - -int xmrig::HttpRequest::auth(const char *accessToken) -{ - if (!accessToken) { - return MHD_HTTP_OK; - } - - const char *header = MHD_lookup_connection_value(m_connection, MHD_HEADER_KIND, "Authorization"); - if (accessToken && !header) { - return MHD_HTTP_UNAUTHORIZED; - } - - const size_t size = strlen(header); - if (size < 8 || strlen(accessToken) != size - 7 || memcmp("Bearer ", header, 7) != 0) { - return MHD_HTTP_FORBIDDEN; - } - - return strncmp(accessToken, header + 7, strlen(accessToken)) == 0 ? MHD_HTTP_OK : MHD_HTTP_FORBIDDEN; -} diff --git a/src/common/api/HttpRequest.h b/src/common/api/HttpRequest.h deleted file mode 100644 index f6ff9a40..00000000 --- a/src/common/api/HttpRequest.h +++ /dev/null @@ -1,84 +0,0 @@ -/* XMRig - * Copyright 2010 Jeff Garzik - * Copyright 2012-2014 pooler - * Copyright 2014 Lucas Jones - * Copyright 2014-2016 Wolf9466 - * Copyright 2016 Jay D Dee - * Copyright 2017-2018 XMR-Stak , - * Copyright 2016-2018 XMRig , - * - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#ifndef __HTTPREQUEST_H__ -#define __HTTPREQUEST_H__ - - -#include - - -struct MHD_Connection; -struct MHD_Response; - - -namespace xmrig { - - -class HttpBody; -class HttpReply; - - -class HttpRequest -{ -public: - enum Method { - Unsupported, - Options, - Get, - Put - }; - - HttpRequest(MHD_Connection *connection, const char *url, const char *method, const char *uploadData, size_t *uploadSize, void **cls); - ~HttpRequest(); - - inline bool isFulfilled() const { return m_fulfilled; } - inline bool isRestricted() const { return m_restricted; } - inline Method method() const { return m_method; } - - bool match(const char *path) const; - bool process(const char *accessToken, bool restricted, xmrig::HttpReply &reply); - const char *body() const; - int end(const HttpReply &reply); - int end(int status, MHD_Response *rsp); - -private: - int auth(const char *accessToken); - - bool m_fulfilled; - bool m_restricted; - const char *m_uploadData; - const char *m_url; - HttpBody *m_body; - Method m_method; - MHD_Connection *m_connection; - size_t *m_uploadSize; - void **m_cls; -}; - - -} /* namespace xmrig */ - - -#endif /* __HTTPREQUEST_H__ */ From e759ccf3857ceb428f69f0e8f0d44014f52f6012 Mon Sep 17 00:00:00 2001 From: XMRig Date: Sun, 31 Mar 2019 23:22:36 +0700 Subject: [PATCH 053/116] Sync changes. --- src/App_unix.cpp | 2 +- src/api/Api.cpp | 5 +++++ src/api/v1/ApiRouter.h | 3 +-- src/base/net/http/HttpResponse.cpp | 3 ++- src/core/Controller.cpp | 2 ++ src/core/Controller.h | 3 --- src/workers/Workers.cpp | 2 -- 7 files changed, 11 insertions(+), 9 deletions(-) diff --git a/src/App_unix.cpp b/src/App_unix.cpp index b1efce83..5149513c 100644 --- a/src/App_unix.cpp +++ b/src/App_unix.cpp @@ -31,7 +31,7 @@ #include "App.h" #include "base/io/log/Log.h" -#include "core/Config.h" +#include "core/config/Config.h" #include "core/Controller.h" diff --git a/src/api/Api.cpp b/src/api/Api.cpp index f6b5ba01..fc82ac9c 100644 --- a/src/api/Api.cpp +++ b/src/api/Api.cpp @@ -26,6 +26,11 @@ #include +#ifndef _WIN32 +# include +#endif + + #include "3rdparty/http-parser/http_parser.h" #include "api/Api.h" #include "api/interfaces/IApiListener.h" diff --git a/src/api/v1/ApiRouter.h b/src/api/v1/ApiRouter.h index 02be91e2..9bb99244 100644 --- a/src/api/v1/ApiRouter.h +++ b/src/api/v1/ApiRouter.h @@ -26,7 +26,6 @@ #define XMRIG_APIROUTER_H -#include "net/NetworkState.h" #include "api/interfaces/IApiListener.h" #include "rapidjson/fwd.h" @@ -43,7 +42,7 @@ class Controller; class ApiRouter : public xmrig::IApiListener { public: - ApiRouter(xmrig::Controller *controller); + ApiRouter(Controller *controller); ~ApiRouter() override; protected: diff --git a/src/base/net/http/HttpResponse.cpp b/src/base/net/http/HttpResponse.cpp index 77431a62..bfb4e1ba 100644 --- a/src/base/net/http/HttpResponse.cpp +++ b/src/base/net/http/HttpResponse.cpp @@ -24,8 +24,9 @@ */ -#include #include +#include +#include #include "3rdparty/http-parser/http_parser.h" diff --git a/src/core/Controller.cpp b/src/core/Controller.cpp index fbe4a427..32507e90 100644 --- a/src/core/Controller.cpp +++ b/src/core/Controller.cpp @@ -195,6 +195,8 @@ void xmrig::Controller::start() # ifdef XMRIG_FEATURE_API api()->start(); # endif + + save(); } diff --git a/src/core/Controller.h b/src/core/Controller.h index 82a90b84..c1ca3da3 100644 --- a/src/core/Controller.h +++ b/src/core/Controller.h @@ -29,9 +29,6 @@ #include "base/kernel/interfaces/IConfigListener.h" -class StatsData; - - namespace xmrig { diff --git a/src/workers/Workers.cpp b/src/workers/Workers.cpp index 1e22f403..53990135 100644 --- a/src/workers/Workers.cpp +++ b/src/workers/Workers.cpp @@ -207,8 +207,6 @@ void Workers::start(xmrig::Controller *controller) m_workers.push_back(handle); handle->start(Workers::onReady); } - - controller->save(); } From 0245ce5f3550c642f17207052f425382a760c57b Mon Sep 17 00:00:00 2001 From: XMRig Date: Mon, 1 Apr 2019 00:00:40 +0700 Subject: [PATCH 054/116] Fix compile issue. --- src/base/io/log/Log.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/base/io/log/Log.cpp b/src/base/io/log/Log.cpp index 487cd9b8..fe5aa205 100644 --- a/src/base/io/log/Log.cpp +++ b/src/base/io/log/Log.cpp @@ -30,6 +30,7 @@ #endif +#include #include #include #include From 24e432891550abb8867159e1c9ecb460f92c29ae Mon Sep 17 00:00:00 2001 From: XMRig Date: Mon, 1 Apr 2019 00:21:15 +0700 Subject: [PATCH 055/116] Fixed malformed HTTP response on Linux. --- src/base/net/http/HttpResponse.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/base/net/http/HttpResponse.cpp b/src/base/net/http/HttpResponse.cpp index bfb4e1ba..65c0eb04 100644 --- a/src/base/net/http/HttpResponse.cpp +++ b/src/base/net/http/HttpResponse.cpp @@ -97,7 +97,7 @@ void xmrig::HttpResponse::end(const char *data, size_t size) # ifdef _WIN32 bufs[1].len = static_cast(size); # else - bufs[0].len = size; + bufs[1].len = size; # endif } From 40d9f537431186d0302addc2477533a53ca11611 Mon Sep 17 00:00:00 2001 From: XMRig Date: Mon, 1 Apr 2019 00:31:46 +0700 Subject: [PATCH 056/116] Sync changes. --- src/common/config/CommonConfig.cpp | 2 ++ src/common/interfaces/IConfig.h | 2 -- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/common/config/CommonConfig.cpp b/src/common/config/CommonConfig.cpp index 55bb0a49..b0b716c1 100644 --- a/src/common/config/CommonConfig.cpp +++ b/src/common/config/CommonConfig.cpp @@ -355,6 +355,8 @@ void xmrig::CommonConfig::parseJSON(const rapidjson::Value &json) if (api.IsObject() && api.HasMember("port")) { m_upgrade = true; m_http.load(api); + m_http.setEnabled(Json::getUint(api, "port") > 0); + m_http.setHost("0.0.0.0"); } else { m_http.load(json["http"]); diff --git a/src/common/interfaces/IConfig.h b/src/common/interfaces/IConfig.h index c897ee37..071b3478 100644 --- a/src/common/interfaces/IConfig.h +++ b/src/common/interfaces/IConfig.h @@ -152,8 +152,6 @@ public: virtual void getJSON(rapidjson::Document &doc) const = 0; virtual void parseJSON(const rapidjson::Value &json) = 0; virtual void setFileName(const char *fileName) = 0; - - static IConfig *create(); }; From 44570895026eeb1b20df9f14aa685301f834b08c Mon Sep 17 00:00:00 2001 From: XMRig Date: Mon, 1 Apr 2019 02:46:41 +0700 Subject: [PATCH 057/116] Added error log to http responses. --- src/base/net/http/HttpResponse.cpp | 33 +++++++++++++++++++++++++++++- 1 file changed, 32 insertions(+), 1 deletion(-) diff --git a/src/base/net/http/HttpResponse.cpp b/src/base/net/http/HttpResponse.cpp index 65c0eb04..06b61879 100644 --- a/src/base/net/http/HttpResponse.cpp +++ b/src/base/net/http/HttpResponse.cpp @@ -30,13 +30,15 @@ #include "3rdparty/http-parser/http_parser.h" +#include "base/io/log/Log.h" #include "base/net/http/HttpContext.h" #include "base/net/http/HttpResponse.h" namespace xmrig { -static const char *kCRLF = "\r\n"; +static const char *kCRLF = "\r\n"; +static const char *kUserAgent = "user-agent"; } // namespace xmrig @@ -102,6 +104,35 @@ void xmrig::HttpResponse::end(const char *data, size_t size) } HttpContext *ctx = HttpContext::get(m_id); + +# ifndef APP_DEBUG + if (statusCode() >= 400) +# endif + { + const bool err = statusCode() >= 400; + char ip[46] = {}; + sockaddr_storage addr = {}; + int aSize = sizeof(addr); + + uv_tcp_getpeername(ctx->tcp, reinterpret_cast(&addr), &aSize); + if (reinterpret_cast(&addr)->sin_family == AF_INET6) { + uv_ip6_name(reinterpret_cast(&addr), ip, 45); + } + else { + uv_ip4_name(reinterpret_cast(&addr), ip, 16); + } + + Log::print(err ? Log::ERR : Log::INFO, CYAN("%s ") CLEAR MAGENTA_BOLD("%s") WHITE_BOLD(" %s ") CSI "1;%dm%d " CLEAR WHITE_BOLD("%zu ") BLACK_BOLD("\"%s\""), + ip, + http_method_str(static_cast(ctx->method)), + ctx->url.c_str(), + err ? 31 : 32, + statusCode(), + header.size() + size, + ctx->headers.count(kUserAgent) ? ctx->headers.at(kUserAgent).c_str() : nullptr + ); + } + uv_try_write(ctx->stream(), bufs, data ? 2 : 1); ctx->close(); From 3b91817caf4920301a17df89786349d8ca4bd831 Mon Sep 17 00:00:00 2001 From: XMRig Date: Mon, 1 Apr 2019 11:50:28 +0700 Subject: [PATCH 058/116] Special handle for favicon.ico --- res/app.rc | 2 +- src/api/Httpd.cpp | 29 +++++++++++++++++++++++++++++ src/base/net/http/HttpResponse.cpp | 4 ++-- src/base/net/http/HttpResponse.h | 2 +- 4 files changed, 33 insertions(+), 4 deletions(-) diff --git a/res/app.rc b/res/app.rc index 037d842a..fb41b8b1 100644 --- a/res/app.rc +++ b/res/app.rc @@ -1,7 +1,7 @@ #include #include "../src/version.h" -IDI_ICON1 ICON DISCARDABLE "app.ico" +101 ICON "app.ico" VS_VERSION_INFO VERSIONINFO FILEVERSION APP_VER_MAJOR,APP_VER_MINOR,APP_VER_PATCH,0 diff --git a/src/api/Httpd.cpp b/src/api/Httpd.cpp index 38b477aa..726f75e0 100644 --- a/src/api/Httpd.cpp +++ b/src/api/Httpd.cpp @@ -40,6 +40,11 @@ namespace xmrig { static const char *kAuthorization = "authorization"; static const char *kContentType = "content-type"; +#ifdef _WIN32 +static const char *favicon = nullptr; +static size_t faviconSize = 0; +#endif + } // namespace xmrig @@ -85,6 +90,17 @@ bool xmrig::Httpd::start() m_port = static_cast(rc); +# ifdef _WIN32 + HRSRC src = FindResource(nullptr, MAKEINTRESOURCE(1), RT_ICON); + if (src != nullptr) { + HGLOBAL res = LoadResource(nullptr, src); + if (res != nullptr) { + favicon = static_cast(LockResource(res)); + faviconSize = SizeofResource(nullptr, src); + } + } +# endif + return true; } @@ -118,6 +134,19 @@ void xmrig::Httpd::onHttpRequest(const HttpRequest &req) return HttpApiResponse(req.id()).end(); } + if (req.method == HTTP_GET && req.url == "/favicon.ico") { +# ifdef _WIN32 + if (favicon != nullptr) { + HttpResponse response(req.id()); + response.setHeader("Content-Type", "image/x-icon"); + + return response.end(favicon, faviconSize); + } +# endif + + return HttpResponse(req.id(), 404).end(); + } + if (req.method > 4) { return HttpApiResponse(req.id(), HTTP_STATUS_METHOD_NOT_ALLOWED).end(); } diff --git a/src/base/net/http/HttpResponse.cpp b/src/base/net/http/HttpResponse.cpp index 06b61879..3b88e29b 100644 --- a/src/base/net/http/HttpResponse.cpp +++ b/src/base/net/http/HttpResponse.cpp @@ -43,9 +43,9 @@ static const char *kUserAgent = "user-agent"; } // namespace xmrig -xmrig::HttpResponse::HttpResponse(uint64_t id) : +xmrig::HttpResponse::HttpResponse(uint64_t id, int statusCode) : m_id(id), - m_statusCode(HTTP_STATUS_OK) + m_statusCode(statusCode) { } diff --git a/src/base/net/http/HttpResponse.h b/src/base/net/http/HttpResponse.h index f8296b89..c2bc9001 100644 --- a/src/base/net/http/HttpResponse.h +++ b/src/base/net/http/HttpResponse.h @@ -38,7 +38,7 @@ namespace xmrig { class HttpResponse { public: - HttpResponse(uint64_t id); + HttpResponse(uint64_t id, int statusCode = 200); inline int statusCode() const { return m_statusCode; } inline void setHeader(const std::string &key, const std::string &value) { m_headers.insert({ key, value }); } From cf7245b469771c4ba78f654d709722182054b840 Mon Sep 17 00:00:00 2001 From: XMRig Date: Mon, 1 Apr 2019 11:54:09 +0700 Subject: [PATCH 059/116] Update default config. --- src/config.json | 10 +++++++--- src/core/config/ConfigLoader_default.h | 10 +++++++--- 2 files changed, 14 insertions(+), 6 deletions(-) diff --git a/src/config.json b/src/config.json index e95c2400..dbb980d0 100644 --- a/src/config.json +++ b/src/config.json @@ -1,11 +1,14 @@ { "algo": "cryptonight", "api": { + "id": null, + "worker-id": null + }, + "http": { + "enabled": false, + "host": "127.0.0.1", "port": 0, "access-token": null, - "id": null, - "worker-id": null, - "ipv6": false, "restricted": true }, "asm": true, @@ -30,6 +33,7 @@ "nicehash": false, "keepalive": false, "variant": -1, + "enabled": true, "tls": false, "tls-fingerprint": null } diff --git a/src/core/config/ConfigLoader_default.h b/src/core/config/ConfigLoader_default.h index f2aababd..9ef81fd2 100644 --- a/src/core/config/ConfigLoader_default.h +++ b/src/core/config/ConfigLoader_default.h @@ -35,11 +35,14 @@ R"===( { "algo": "cryptonight", "api": { + "id": null, + "worker-id": null + }, + "http": { + "enabled": false, + "host": "127.0.0.1", "port": 0, "access-token": null, - "id": null, - "worker-id": null, - "ipv6": false, "restricted": true }, "asm": true, @@ -64,6 +67,7 @@ R"===( "nicehash": false, "keepalive": false, "variant": -1, + "enabled": true, "tls": false, "tls-fingerprint": null } From 1f45e77848fd0852d03e70cb5c533943b9dd5e52 Mon Sep 17 00:00:00 2001 From: XMRig Date: Mon, 1 Apr 2019 18:56:42 +0700 Subject: [PATCH 060/116] Fixed wrong status code for "GET /1/config" --- src/api/v1/ApiRouter.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/api/v1/ApiRouter.cpp b/src/api/v1/ApiRouter.cpp index 029d0a3b..cef4b7fc 100644 --- a/src/api/v1/ApiRouter.cpp +++ b/src/api/v1/ApiRouter.cpp @@ -78,6 +78,7 @@ void xmrig::ApiRouter::onRequest(IApiRequest &request) return request.done(403); } + request.accept(); m_controller->config()->getJSON(request.doc()); } } From 1e3e8df43cdae935a73e0f78e5c1824f62fd9c14 Mon Sep 17 00:00:00 2001 From: xmrig Date: Mon, 1 Apr 2019 19:01:34 +0700 Subject: [PATCH 061/116] Update CHANGELOG.md --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index a158b3b9..ada15bed 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,4 +1,5 @@ # v2.15.1-beta +- [#1007](https://github.com/xmrig/xmrig/issues/1007) Old HTTP API backend based on libmicrohttpd, replaced to custom HTTP server (libuv + http_parser). - [#257](https://github.com/xmrig/xmrig-nvidia/pull/257) New logging subsystem, file and syslog now always without colors. # v2.15.0-beta From 89d7e84f8890bbb91090811f2efde7f6221a2d5d Mon Sep 17 00:00:00 2001 From: XMRig Date: Mon, 1 Apr 2019 19:04:48 +0700 Subject: [PATCH 062/116] v2.15.1-beta --- src/version.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/version.h b/src/version.h index 117f1d6a..c90a12fa 100644 --- a/src/version.h +++ b/src/version.h @@ -28,7 +28,7 @@ #define APP_ID "xmrig" #define APP_NAME "XMRig" #define APP_DESC "XMRig CPU miner" -#define APP_VERSION "2.15.1-evo" +#define APP_VERSION "2.15.1-beta" #define APP_DOMAIN "xmrig.com" #define APP_SITE "www.xmrig.com" #define APP_COPYRIGHT "Copyright (C) 2016-2019 xmrig.com" From 4aa7f01f137034ba7e7c59f1d6c443f24e1d22ff Mon Sep 17 00:00:00 2001 From: XMRig Date: Mon, 1 Apr 2019 23:45:23 +0700 Subject: [PATCH 063/116] v2.15.2-evo --- src/version.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/version.h b/src/version.h index c90a12fa..0f5a456a 100644 --- a/src/version.h +++ b/src/version.h @@ -28,7 +28,7 @@ #define APP_ID "xmrig" #define APP_NAME "XMRig" #define APP_DESC "XMRig CPU miner" -#define APP_VERSION "2.15.1-beta" +#define APP_VERSION "2.15.2-evo" #define APP_DOMAIN "xmrig.com" #define APP_SITE "www.xmrig.com" #define APP_COPYRIGHT "Copyright (C) 2016-2019 xmrig.com" @@ -36,7 +36,7 @@ #define APP_VER_MAJOR 2 #define APP_VER_MINOR 15 -#define APP_VER_PATCH 1 +#define APP_VER_PATCH 2 #ifdef _MSC_VER # if (_MSC_VER >= 1910) From 85ee55f309a534d97fdd402f6bb90dcf775bc857 Mon Sep 17 00:00:00 2001 From: XMRig Date: Tue, 2 Apr 2019 17:46:26 +0700 Subject: [PATCH 064/116] Fixed, big HTTP responses was truncated. --- src/base/base.cmake | 1 + src/base/net/http/HttpResponse.cpp | 76 ++++++++++++++++++++---------- src/base/tools/Baton.h | 45 ++++++++++++++++++ 3 files changed, 97 insertions(+), 25 deletions(-) create mode 100644 src/base/tools/Baton.h diff --git a/src/base/base.cmake b/src/base/base.cmake index 5f32f425..688f3ef8 100644 --- a/src/base/base.cmake +++ b/src/base/base.cmake @@ -33,6 +33,7 @@ set(HEADERS_BASE src/base/net/tools/RecvBuf.h src/base/net/tools/Storage.h src/base/tools/Arguments.h + src/base/tools/Baton.h src/base/tools/Buffer.h src/base/tools/Chrono.h src/base/tools/Handle.h diff --git a/src/base/net/http/HttpResponse.cpp b/src/base/net/http/HttpResponse.cpp index 3b88e29b..d782217b 100644 --- a/src/base/net/http/HttpResponse.cpp +++ b/src/base/net/http/HttpResponse.cpp @@ -33,6 +33,7 @@ #include "base/io/log/Log.h" #include "base/net/http/HttpContext.h" #include "base/net/http/HttpResponse.h" +#include "base/tools/Baton.h" namespace xmrig { @@ -40,6 +41,52 @@ namespace xmrig { static const char *kCRLF = "\r\n"; static const char *kUserAgent = "user-agent"; + +class WriteBaton : public Baton +{ +public: + inline WriteBaton(const std::stringstream &ss, const char *data, size_t size, HttpContext *ctx) : + m_ctx(ctx), + m_header(ss.str()) + { + req.data = this; + bufs[0].len = m_header.size(); + bufs[0].base = const_cast(m_header.c_str()); + + if (data) { + bufs[1].len = size; + bufs[1].base = new char[size]; + memcpy(bufs[1].base, data, size); + } + else { + bufs[1].base = nullptr; + bufs[1].len = 0; + } + } + + + inline ~WriteBaton() + { + if (count() == 2) { + delete [] bufs[1].base; + } + + m_ctx->close(); + } + + + inline size_t count() const { return bufs[1].base == nullptr ? 1 : 2; } + inline size_t size() const { return bufs[0].len + bufs[1].len; } + inline static void onWrite(uv_write_t *req, int) { delete reinterpret_cast(req->data); } + + + uv_buf_t bufs[2]; + +private: + HttpContext *m_ctx; + std::string m_header; +}; + } // namespace xmrig @@ -82,28 +129,9 @@ void xmrig::HttpResponse::end(const char *data, size_t size) } ss << kCRLF; - const std::string header = ss.str(); - uv_buf_t bufs[2]; - bufs[0].base = const_cast(header.c_str()); - -# ifdef _WIN32 - bufs[0].len = static_cast(header.size()); -# else - bufs[0].len = header.size(); -# endif - - if (data) { - bufs[1].base = const_cast(data); - -# ifdef _WIN32 - bufs[1].len = static_cast(size); -# else - bufs[1].len = size; -# endif - } - - HttpContext *ctx = HttpContext::get(m_id); + HttpContext *ctx = HttpContext::get(m_id); + WriteBaton *baton = new WriteBaton(ss, data, size, ctx); # ifndef APP_DEBUG if (statusCode() >= 400) @@ -128,12 +156,10 @@ void xmrig::HttpResponse::end(const char *data, size_t size) ctx->url.c_str(), err ? 31 : 32, statusCode(), - header.size() + size, + baton->size(), ctx->headers.count(kUserAgent) ? ctx->headers.at(kUserAgent).c_str() : nullptr ); } - uv_try_write(ctx->stream(), bufs, data ? 2 : 1); - - ctx->close(); + uv_write(&baton->req, ctx->stream(), baton->bufs, baton->count(), WriteBaton::onWrite); } diff --git a/src/base/tools/Baton.h b/src/base/tools/Baton.h new file mode 100644 index 00000000..7bea0af0 --- /dev/null +++ b/src/base/tools/Baton.h @@ -0,0 +1,45 @@ +/* XMRig + * Copyright 2010 Jeff Garzik + * Copyright 2012-2014 pooler + * Copyright 2014 Lucas Jones + * Copyright 2014-2016 Wolf9466 + * Copyright 2016 Jay D Dee + * Copyright 2017-2018 XMR-Stak , + * Copyright 2018-2019 SChernykh + * Copyright 2016-2019 XMRig , + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef XMRIG_BATON_H +#define XMRIG_BATON_H + + +namespace xmrig { + + +template +class Baton +{ +public: + inline Baton() { req.data = this; } + + T req; +}; + + +} /* namespace xmrig */ + + +#endif /* XMRIG_BATON_H */ From fa2a0b9b7911ec02c18bde7fbd875f031f449b5b Mon Sep 17 00:00:00 2001 From: XMRig Date: Fri, 5 Apr 2019 22:14:01 +0700 Subject: [PATCH 065/116] New config subsystem --- CMakeLists.txt | 13 +- src/api/Api.cpp | 19 +- src/api/Api.h | 10 +- src/api/Httpd.cpp | 14 +- src/api/Httpd.h | 10 +- src/api/v1/ApiRouter.cpp | 16 +- src/api/v1/ApiRouter.h | 6 +- src/base/base.cmake | 13 +- src/base/io/Json.cpp | 46 ++ src/base/io/Json.h | 26 ++ src/base/io/JsonChain.cpp | 201 +++++++++ src/base/io/JsonChain.h | 74 +++ src/base/io/Json_win.cpp | 2 +- src/base/kernel/Base.cpp | 283 ++++++++++++ .../ConfigWatcher.cpp => base/kernel/Base.h} | 68 +-- src/base/kernel/config/BaseConfig.cpp | 195 ++++++++ .../kernel/config/BaseConfig.h} | 54 +-- src/base/kernel/config/BaseTransform.cpp | 255 +++++++++++ src/base/kernel/config/BaseTransform.h | 123 +++++ ...{IControllerListener.h => IBaseListener.h} | 10 +- .../kernel}/interfaces/IConfig.h | 23 +- .../kernel/interfaces/IConfigTransform.h} | 29 +- .../kernel/interfaces/IJsonReader.h} | 45 +- src/base/net/stratum/Pools.cpp | 33 +- src/base/net/stratum/Pools.h | 14 - src/common/config/CommonConfig.cpp | 426 ------------------ src/common/config/ConfigLoader.cpp | 262 ----------- src/common/crypto/Algorithm.cpp | 2 +- src/core/Controller.cpp | 167 +------ src/core/Controller.h | 28 +- src/core/config/Config.cpp | 196 +++----- src/core/config/Config.h | 25 +- src/core/config/ConfigTransform.cpp | 106 +++++ src/core/config/ConfigTransform.h | 51 +++ ...onfigLoader_default.h => Config_default.h} | 9 +- ...figLoader_platform.h => Config_platform.h} | 24 +- src/net/Network.h | 4 +- 37 files changed, 1628 insertions(+), 1254 deletions(-) create mode 100644 src/base/io/JsonChain.cpp create mode 100644 src/base/io/JsonChain.h create mode 100644 src/base/kernel/Base.cpp rename src/{common/config/ConfigWatcher.cpp => base/kernel/Base.h} (62%) create mode 100644 src/base/kernel/config/BaseConfig.cpp rename src/{common/config/CommonConfig.h => base/kernel/config/BaseConfig.h} (71%) create mode 100644 src/base/kernel/config/BaseTransform.cpp create mode 100644 src/base/kernel/config/BaseTransform.h rename src/base/kernel/interfaces/{IControllerListener.h => IBaseListener.h} (88%) rename src/{common => base/kernel}/interfaces/IConfig.h (85%) rename src/{common/config/ConfigWatcher.h => base/kernel/interfaces/IConfigTransform.h} (72%) rename src/{common/config/ConfigLoader.h => base/kernel/interfaces/IJsonReader.h} (53%) delete mode 100644 src/common/config/CommonConfig.cpp delete mode 100644 src/common/config/ConfigLoader.cpp create mode 100644 src/core/config/ConfigTransform.cpp create mode 100644 src/core/config/ConfigTransform.h rename src/core/config/{ConfigLoader_default.h => Config_default.h} (94%) rename src/core/config/{ConfigLoader_platform.h => Config_platform.h} (88%) diff --git a/CMakeLists.txt b/CMakeLists.txt index c9513258..550de480 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -24,20 +24,17 @@ set(HEADERS "${HEADERS_BASE_HTTP}" src/api/interfaces/IApiListener.h src/App.h - src/common/config/CommonConfig.h - src/common/config/ConfigLoader.h - src/common/config/ConfigWatcher.h src/common/cpu/Cpu.h src/common/crypto/Algorithm.h src/common/crypto/keccak.h - src/common/interfaces/IConfig.h src/common/interfaces/ICpuInfo.h src/common/Platform.h src/common/utils/mm_malloc.h src/common/xmrig.h src/core/config/Config.h - src/core/config/ConfigLoader_default.h - src/core/config/ConfigLoader_platform.h + src/core/config/ConfigTransform.h + src/core/config/Config_default.h + src/core/config/Config_platform.h src/core/config/usage.h src/core/Controller.h src/interfaces/IJobResultListener.h @@ -84,13 +81,11 @@ set(SOURCES "${SOURCES_BASE}" "${SOURCES_BASE_HTTP}" src/App.cpp - src/common/config/CommonConfig.cpp - src/common/config/ConfigLoader.cpp - src/common/config/ConfigWatcher.cpp src/common/crypto/Algorithm.cpp src/common/crypto/keccak.cpp src/common/Platform.cpp src/core/config/Config.cpp + src/core/config/ConfigTransform.cpp src/core/Controller.cpp src/Mem.cpp src/net/Network.cpp diff --git a/src/api/Api.cpp b/src/api/Api.cpp index fc82ac9c..1b7210f6 100644 --- a/src/api/Api.cpp +++ b/src/api/Api.cpp @@ -36,6 +36,7 @@ #include "api/interfaces/IApiListener.h" #include "api/requests/HttpApiRequest.h" #include "api/v1/ApiRouter.h" +#include "base/kernel/Base.h" #include "base/tools/Buffer.h" #include "common/crypto/keccak.h" #include "core/config/Config.h" @@ -48,17 +49,17 @@ #endif -xmrig::Api::Api(Controller *controller) : +xmrig::Api::Api(Base *base) : + m_base(base), m_id(), m_workerId(), - m_controller(controller), m_httpd(nullptr) { - controller->addListener(this); + base->addListener(this); - genId(m_controller->config()->apiId()); + genId(base->config()->apiId()); - m_v1 = new ApiRouter(controller); + m_v1 = new ApiRouter(base); addListener(m_v1); } @@ -75,7 +76,7 @@ xmrig::Api::~Api() void xmrig::Api::request(const HttpRequest &req) { - HttpApiRequest request(req, m_controller->config()->http().isRestricted()); + HttpApiRequest request(req, m_base->config()->http().isRestricted()); exec(request); } @@ -83,10 +84,10 @@ void xmrig::Api::request(const HttpRequest &req) void xmrig::Api::start() { - genWorkerId(m_controller->config()->apiWorkerId()); + genWorkerId(m_base->config()->apiWorkerId()); # ifdef XMRIG_FEATURE_HTTP - m_httpd = new Httpd(m_controller); + m_httpd = new Httpd(m_base); m_httpd->start(); # endif } @@ -155,7 +156,7 @@ void xmrig::Api::genId(const String &id) uint8_t hash[200]; const size_t addrSize = sizeof(interfaces[i].phys_addr); const size_t inSize = strlen(APP_KIND) + addrSize + sizeof(uint16_t); - const uint16_t port = static_cast(m_controller->config()->http().port()); + const uint16_t port = static_cast(m_base->config()->http().port()); uint8_t *input = new uint8_t[inSize](); memcpy(input, &port, sizeof(uint16_t)); diff --git a/src/api/Api.h b/src/api/Api.h index d76e3105..9d391901 100644 --- a/src/api/Api.h +++ b/src/api/Api.h @@ -29,14 +29,14 @@ #include -#include "base/kernel/interfaces/IControllerListener.h" +#include "base/kernel/interfaces/IBaseListener.h" namespace xmrig { class ApiRouter; -class Controller; +class Base; class Httpd; class HttpRequest; class IApiListener; @@ -44,10 +44,10 @@ class IApiRequest; class String; -class Api : public IControllerListener +class Api : public IBaseListener { public: - Api(Controller *controller); + Api(Base *base); ~Api() override; inline const char *id() const { return m_id; } @@ -67,9 +67,9 @@ private: void genWorkerId(const String &id); ApiRouter *m_v1; + Base *m_base; char m_id[32]; char m_workerId[128]; - Controller *m_controller; Httpd *m_httpd; std::vector m_listeners; }; diff --git a/src/api/Httpd.cpp b/src/api/Httpd.cpp index 726f75e0..0aba6072 100644 --- a/src/api/Httpd.cpp +++ b/src/api/Httpd.cpp @@ -48,13 +48,13 @@ static size_t faviconSize = 0; } // namespace xmrig -xmrig::Httpd::Httpd(Controller *controller) : - m_controller(controller), +xmrig::Httpd::Httpd(Base *base) : + m_base(base), m_http(nullptr), m_server(nullptr), m_port(0) { - controller->addListener(this); + base->addListener(this); } @@ -65,7 +65,7 @@ xmrig::Httpd::~Httpd() bool xmrig::Httpd::start() { - const Http &config = m_controller->config()->http(); + const Http &config = m_base->config()->http(); if (!config.isEnabled()) { return true; @@ -157,7 +157,7 @@ void xmrig::Httpd::onHttpRequest(const HttpRequest &req) } if (req.method != HTTP_GET) { - if (m_controller->config()->http().isRestricted()) { + if (m_base->config()->http().isRestricted()) { return HttpApiResponse(req.id(), HTTP_STATUS_FORBIDDEN).end(); } @@ -166,13 +166,13 @@ void xmrig::Httpd::onHttpRequest(const HttpRequest &req) } } - m_controller->api()->request(req); + m_base->api()->request(req); } int xmrig::Httpd::auth(const HttpRequest &req) const { - const Http &config = m_controller->config()->http(); + const Http &config = m_base->config()->http(); if (!req.headers.count(kAuthorization)) { return config.isAuthRequired() ? HTTP_STATUS_UNAUTHORIZED : HTTP_STATUS_OK; diff --git a/src/api/Httpd.h b/src/api/Httpd.h index 99ee2e88..ae6cbfc8 100644 --- a/src/api/Httpd.h +++ b/src/api/Httpd.h @@ -29,22 +29,22 @@ #include -#include "base/kernel/interfaces/IControllerListener.h" +#include "base/kernel/interfaces/IBaseListener.h" #include "base/kernel/interfaces/IHttpListener.h" namespace xmrig { -class Controller; +class Base; class HttpServer; class TcpServer; -class Httpd : public IControllerListener, public IHttpListener +class Httpd : public IBaseListener, public IHttpListener { public: - Httpd(Controller *controller); + Httpd(Base *base); ~Httpd() override; bool start(); @@ -57,7 +57,7 @@ protected: private: int auth(const HttpRequest &req) const; - Controller *m_controller; + Base *m_base; HttpServer *m_http; TcpServer *m_server; uint16_t m_port; diff --git a/src/api/v1/ApiRouter.cpp b/src/api/v1/ApiRouter.cpp index cef4b7fc..1f3641c3 100644 --- a/src/api/v1/ApiRouter.cpp +++ b/src/api/v1/ApiRouter.cpp @@ -29,10 +29,10 @@ #include "api/interfaces/IApiRequest.h" #include "api/v1/ApiRouter.h" +#include "base/kernel/Base.h" #include "common/cpu/Cpu.h" #include "common/Platform.h" #include "core/config/Config.h" -#include "core/Controller.h" #include "interfaces/IThread.h" #include "rapidjson/document.h" #include "version.h" @@ -50,8 +50,8 @@ static inline double normalize(double d) } -xmrig::ApiRouter::ApiRouter(xmrig::Controller *controller) : - m_controller(controller) +xmrig::ApiRouter::ApiRouter(Base *base) : + m_base(base) { } @@ -79,14 +79,14 @@ void xmrig::ApiRouter::onRequest(IApiRequest &request) } request.accept(); - m_controller->config()->getJSON(request.doc()); + m_base->config()->getJSON(request.doc()); } } else if (request.method() == IApiRequest::METHOD_PUT || request.method() == IApiRequest::METHOD_POST) { if (request.url() == "/1/config") { request.accept(); - if (!m_controller->config()->reload(request.json())) { + if (!m_base->reload(request.json())) { return request.done(400); } @@ -142,9 +142,9 @@ void xmrig::ApiRouter::getMiner(rapidjson::Value &reply, rapidjson::Document &do reply.AddMember("kind", APP_KIND, allocator); reply.AddMember("ua", StringRef(Platform::userAgent()), allocator); reply.AddMember("cpu", cpu, allocator); - reply.AddMember("algo", StringRef(m_controller->config()->algorithm().name()), allocator); + reply.AddMember("algo", StringRef(m_base->config()->algorithm().shortName()), allocator); reply.AddMember("hugepages", Workers::hugePages() > 0, allocator); - reply.AddMember("donate_level", m_controller->config()->pools().donateLevel(), allocator); + reply.AddMember("donate_level", m_base->config()->pools().donateLevel(), allocator); } @@ -156,7 +156,7 @@ void xmrig::ApiRouter::getThreads(rapidjson::Value &reply, rapidjson::Document & Workers::threadsSummary(doc); - const std::vector &threads = m_controller->config()->threads(); + const std::vector &threads = m_base->config()->threads(); Value list(kArrayType); size_t i = 0; diff --git a/src/api/v1/ApiRouter.h b/src/api/v1/ApiRouter.h index 9bb99244..bdbbaea4 100644 --- a/src/api/v1/ApiRouter.h +++ b/src/api/v1/ApiRouter.h @@ -36,13 +36,13 @@ class Hashrate; namespace xmrig { -class Controller; +class Base; class ApiRouter : public xmrig::IApiListener { public: - ApiRouter(Controller *controller); + ApiRouter(Base *base); ~ApiRouter() override; protected: @@ -53,7 +53,7 @@ private: void getMiner(rapidjson::Value &reply, rapidjson::Document &doc) const; void getThreads(rapidjson::Value &reply, rapidjson::Document &doc) const; - Controller *m_controller; + Base *m_base; }; diff --git a/src/base/base.cmake b/src/base/base.cmake index 688f3ef8..04016f01 100644 --- a/src/base/base.cmake +++ b/src/base/base.cmake @@ -1,15 +1,21 @@ set(HEADERS_BASE src/base/io/Console.h src/base/io/Json.h + src/base/io/JsonChain.h src/base/io/log/backends/ConsoleLog.h src/base/io/log/backends/FileLog.h src/base/io/log/Log.h src/base/io/Watcher.h + src/base/kernel/Base.h + src/base/kernel/config/BaseConfig.h + src/base/kernel/config/BaseTransform.h src/base/kernel/Entry.h + src/base/kernel/interfaces/IBaseListener.h src/base/kernel/interfaces/IClientListener.h + src/base/kernel/interfaces/IConfig.h src/base/kernel/interfaces/IConfigListener.h + src/base/kernel/interfaces/IConfigTransform.h src/base/kernel/interfaces/IConsoleListener.h - src/base/kernel/interfaces/IControllerListener.h src/base/kernel/interfaces/IDnsListener.h src/base/kernel/interfaces/ILineListener.h src/base/kernel/interfaces/ILogBackend.h @@ -44,11 +50,15 @@ set(HEADERS_BASE set(SOURCES_BASE src/base/io/Console.cpp src/base/io/Json.cpp + src/base/io/JsonChain.cpp src/base/io/log/backends/ConsoleLog.cpp src/base/io/log/backends/FileLog.cpp src/base/io/log/Log.cpp src/base/io/Watcher.cpp + src/base/kernel/config/BaseConfig.cpp + src/base/kernel/config/BaseTransform.cpp src/base/kernel/Entry.cpp + src/base/kernel/Base.cpp src/base/kernel/Process.cpp src/base/kernel/Signals.cpp src/base/net/dns/Dns.cpp @@ -87,6 +97,7 @@ if (WITH_HTTPD) set(HEADERS_BASE_HTTP src/3rdparty/http-parser/http_parser.h src/base/kernel/interfaces/IHttpListener.h + src/base/kernel/interfaces/IJsonReader.h src/base/kernel/interfaces/ITcpServerListener.h src/base/net/http/HttpApiResponse.h src/base/net/http/HttpContext.h diff --git a/src/base/io/Json.cpp b/src/base/io/Json.cpp index b95994e4..91646453 100644 --- a/src/base/io/Json.cpp +++ b/src/base/io/Json.cpp @@ -27,6 +27,13 @@ #include "rapidjson/document.h" +namespace xmrig { + +static const rapidjson::Value kNullValue; + +} + + bool xmrig::Json::getBool(const rapidjson::Value &obj, const char *key, bool defaultValue) { auto i = obj.FindMember(key); @@ -49,6 +56,39 @@ const char *xmrig::Json::getString(const rapidjson::Value &obj, const char *key, } +const rapidjson::Value &xmrig::Json::getArray(const rapidjson::Value &obj, const char *key) +{ + auto i = obj.FindMember(key); + if (i != obj.MemberEnd() && i->value.IsArray()) { + return i->value; + } + + return kNullValue; +} + + +const rapidjson::Value &xmrig::Json::getObject(const rapidjson::Value &obj, const char *key) +{ + auto i = obj.FindMember(key); + if (i != obj.MemberEnd() && i->value.IsObject()) { + return i->value; + } + + return kNullValue; +} + + +const rapidjson::Value &xmrig::Json::getValue(const rapidjson::Value &obj, const char *key) +{ + auto i = obj.FindMember(key); + if (i != obj.MemberEnd()) { + return i->value; + } + + return kNullValue; +} + + int xmrig::Json::getInt(const rapidjson::Value &obj, const char *key, int defaultValue) { auto i = obj.FindMember(key); @@ -91,3 +131,9 @@ unsigned xmrig::Json::getUint(const rapidjson::Value &obj, const char *key, unsi return defaultValue; } + + +bool xmrig::JsonReader::isEmpty() const +{ + return !m_obj.IsObject() || m_obj.ObjectEmpty(); +} diff --git a/src/base/io/Json.h b/src/base/io/Json.h index 28dcf9a3..80fe5dc2 100644 --- a/src/base/io/Json.h +++ b/src/base/io/Json.h @@ -26,6 +26,7 @@ #define XMRIG_JSON_H +#include "base/kernel/interfaces/IJsonReader.h" #include "rapidjson/fwd.h" @@ -37,6 +38,9 @@ class Json public: static bool getBool(const rapidjson::Value &obj, const char *key, bool defaultValue = false); static const char *getString(const rapidjson::Value &obj, const char *key, const char *defaultValue = nullptr); + static const rapidjson::Value &getArray(const rapidjson::Value &obj, const char *key); + static const rapidjson::Value &getObject(const rapidjson::Value &obj, const char *key); + static const rapidjson::Value &getValue(const rapidjson::Value &obj, const char *key); static int getInt(const rapidjson::Value &obj, const char *key, int defaultValue = 0); static int64_t getInt64(const rapidjson::Value &obj, const char *key, int64_t defaultValue = 0); static uint64_t getUint64(const rapidjson::Value &obj, const char *key, uint64_t defaultValue = 0); @@ -47,6 +51,28 @@ public: }; +class JsonReader : public IJsonReader +{ +public: + inline JsonReader(const rapidjson::Value &obj) : m_obj(obj) {} + + inline bool getBool(const char *key, bool defaultValue = false) const override { return Json::getBool(m_obj, key, defaultValue); } + inline const char *getString(const char *key, const char *defaultValue = nullptr) const override { return Json::getString(m_obj, key, defaultValue); } + inline const rapidjson::Value &getArray(const char *key) const override { return Json::getArray(m_obj, key); } + inline const rapidjson::Value &getObject(const char *key) const override { return Json::getObject(m_obj, key); } + inline const rapidjson::Value &getValue(const char *key) const override { return Json::getValue(m_obj, key); } + inline int getInt(const char *key, int defaultValue = 0) const override { return Json::getInt(m_obj, key, defaultValue); } + inline int64_t getInt64(const char *key, int64_t defaultValue = 0) const override { return Json::getInt64(m_obj, key, defaultValue); } + inline uint64_t getUint64(const char *key, uint64_t defaultValue = 0) const override { return Json::getUint64(m_obj, key, defaultValue); } + inline unsigned getUint(const char *key, unsigned defaultValue = 0) const override { return Json::getUint(m_obj, key, defaultValue); } + + bool isEmpty() const override; + +private: + const rapidjson::Value &m_obj; +}; + + } /* namespace xmrig */ diff --git a/src/base/io/JsonChain.cpp b/src/base/io/JsonChain.cpp new file mode 100644 index 00000000..d65427cc --- /dev/null +++ b/src/base/io/JsonChain.cpp @@ -0,0 +1,201 @@ +/* XMRig + * Copyright 2010 Jeff Garzik + * Copyright 2012-2014 pooler + * Copyright 2014 Lucas Jones + * Copyright 2014-2016 Wolf9466 + * Copyright 2016 Jay D Dee + * Copyright 2017-2018 XMR-Stak , + * Copyright 2018-2019 SChernykh + * Copyright 2016-2019 XMRig , + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + + +#include "base/io/Json.h" +#include "base/io/JsonChain.h" +#include "base/io/log/Log.h" +#include "rapidjson/error/en.h" + + +namespace xmrig { + +static const rapidjson::Value kNullValue; + +} + + +xmrig::JsonChain::JsonChain() +{ +} + + +bool xmrig::JsonChain::add(rapidjson::Document &&doc) +{ + if (doc.HasParseError() || !doc.IsObject() || doc.ObjectEmpty()) { + return false; + } + + m_chain.push_back(std::move(doc)); + + return true; +} + + +bool xmrig::JsonChain::addFile(const char *fileName) +{ + using namespace rapidjson; + Document doc; + if (Json::get(fileName, doc)) { + m_fileName = fileName; + + return add(std::move(doc)); + } + + if (doc.HasParseError()) { + LOG_ERR("%s: \"%s\"", fileName, doc.GetErrorOffset(), GetParseError_En(doc.GetParseError())); + } + else { + LOG_ERR("unable to open \"%s\".", fileName); + } + + return false; +} + + +bool xmrig::JsonChain::addRaw(const char *json) +{ + using namespace rapidjson; + Document doc; + doc.Parse(json); + + return add(std::move(doc)); +} + + +bool xmrig::JsonChain::getBool(const char *key, bool defaultValue) const +{ + for (auto it = m_chain.rbegin(); it != m_chain.rend(); ++it) { + auto i = it->FindMember(key); + if (i != it->MemberEnd() && i->value.IsBool()) { + return i->value.GetBool(); + } + } + + return defaultValue; +} + + +const char *xmrig::JsonChain::getString(const char *key, const char *defaultValue) const +{ + for (auto it = m_chain.rbegin(); it != m_chain.rend(); ++it) { + auto i = it->FindMember(key); + if (i != it->MemberEnd() && i->value.IsString()) { + return i->value.GetString(); + } + } + + return defaultValue; +} + + +const rapidjson::Value &xmrig::JsonChain::getArray(const char *key) const +{ + for (auto it = m_chain.rbegin(); it != m_chain.rend(); ++it) { + auto i = it->FindMember(key); + if (i != it->MemberEnd() && i->value.IsArray()) { + return i->value; + } + } + + return kNullValue; +} + + +const rapidjson::Value &xmrig::JsonChain::getObject(const char *key) const +{ + for (auto it = m_chain.rbegin(); it != m_chain.rend(); ++it) { + auto i = it->FindMember(key); + if (i != it->MemberEnd() && i->value.IsObject()) { + return i->value; + } + } + + return kNullValue; +} + + +const rapidjson::Value &xmrig::JsonChain::getValue(const char *key) const +{ + for (auto it = m_chain.rbegin(); it != m_chain.rend(); ++it) { + auto i = it->FindMember(key); + if (i != it->MemberEnd()) { + return i->value; + } + } + + return kNullValue; +} + + +int xmrig::JsonChain::getInt(const char *key, int defaultValue) const +{ + for (auto it = m_chain.rbegin(); it != m_chain.rend(); ++it) { + auto i = it->FindMember(key); + if (i != it->MemberEnd() && i->value.IsInt()) { + return i->value.GetInt(); + } + } + + return defaultValue; +} + + +int64_t xmrig::JsonChain::getInt64(const char *key, int64_t defaultValue) const +{ + for (auto it = m_chain.rbegin(); it != m_chain.rend(); ++it) { + auto i = it->FindMember(key); + if (i != it->MemberEnd() && i->value.IsInt64()) { + return i->value.GetInt64(); + } + } + + return defaultValue; +} + + +uint64_t xmrig::JsonChain::getUint64(const char *key, uint64_t defaultValue) const +{ + for (auto it = m_chain.rbegin(); it != m_chain.rend(); ++it) { + auto i = it->FindMember(key); + if (i != it->MemberEnd() && i->value.IsUint64()) { + return i->value.GetUint64(); + } + } + + return defaultValue; +} + + +unsigned xmrig::JsonChain::getUint(const char *key, unsigned defaultValue) const +{ + for (auto it = m_chain.rbegin(); it != m_chain.rend(); ++it) { + auto i = it->FindMember(key); + if (i != it->MemberEnd() && i->value.IsUint()) { + return i->value.GetUint(); + } + } + + return defaultValue; +} diff --git a/src/base/io/JsonChain.h b/src/base/io/JsonChain.h new file mode 100644 index 00000000..dab01218 --- /dev/null +++ b/src/base/io/JsonChain.h @@ -0,0 +1,74 @@ +/* XMRig + * Copyright 2010 Jeff Garzik + * Copyright 2012-2014 pooler + * Copyright 2014 Lucas Jones + * Copyright 2014-2016 Wolf9466 + * Copyright 2016 Jay D Dee + * Copyright 2017-2018 XMR-Stak , + * Copyright 2018-2019 SChernykh + * Copyright 2016-2019 XMRig , + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef XMRIG_JSONCHAIN_H +#define XMRIG_JSONCHAIN_H + + +#include + + +#include "base/kernel/interfaces/IJsonReader.h" +#include "base/tools/String.h" +#include "rapidjson/document.h" + + +namespace xmrig { + + +class JsonChain : public IJsonReader +{ +public: + JsonChain(); + + bool add(rapidjson::Document &&doc); + bool addFile(const char *fileName); + bool addRaw(const char *json); + + inline const String &fileName() const { return m_fileName; } + inline size_t size() const { return m_chain.size(); } + +protected: + inline bool isEmpty() const override { return m_chain.empty(); } + + bool getBool(const char *key, bool defaultValue = false) const override; + const char *getString(const char *key, const char *defaultValue = nullptr) const override; + const rapidjson::Value &getArray(const char *key) const override; + const rapidjson::Value &getObject(const char *key) const override; + const rapidjson::Value &getValue(const char *key) const override; + int getInt(const char *key, int defaultValue = 0) const override; + int64_t getInt64(const char *key, int64_t defaultValue = 0) const override; + uint64_t getUint64(const char *key, uint64_t defaultValue = 0) const override; + unsigned getUint(const char *key, unsigned defaultValue = 0) const override; + +private: + std::vector m_chain; + String m_fileName; +}; + + +} /* namespace xmrig */ + + +#endif /* XMRIG_JSONCHAIN_H */ diff --git a/src/base/io/Json_win.cpp b/src/base/io/Json_win.cpp index 4a1c5266..58ee26b7 100644 --- a/src/base/io/Json_win.cpp +++ b/src/base/io/Json_win.cpp @@ -102,7 +102,7 @@ bool xmrig::Json::save(const char *fileName, const rapidjson::Document &doc) return false; } # elif defined(__GNUC__) - const int fd = _wopen(toUtf16(fileName).c_str(), _O_WRONLY | _O_BINARY | _O_TRUNC); + const int fd = _wopen(toUtf16(fileName).c_str(), _O_WRONLY | _O_BINARY | _O_CREAT | _O_TRUNC); if (fd == -1) { return false; } diff --git a/src/base/kernel/Base.cpp b/src/base/kernel/Base.cpp new file mode 100644 index 00000000..84152441 --- /dev/null +++ b/src/base/kernel/Base.cpp @@ -0,0 +1,283 @@ +/* XMRig + * Copyright 2010 Jeff Garzik + * Copyright 2012-2014 pooler + * Copyright 2014 Lucas Jones + * Copyright 2014-2016 Wolf9466 + * Copyright 2016 Jay D Dee + * Copyright 2017-2018 XMR-Stak , + * Copyright 2018-2019 SChernykh + * Copyright 2016-2019 XMRig , + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + + +#include +#include + + +#include "base/io/Json.h" +#include "base/io/JsonChain.h" +#include "base/io/log/backends/ConsoleLog.h" +#include "base/io/log/backends/FileLog.h" +#include "base/io/log/Log.h" +#include "base/io/Watcher.h" +#include "base/kernel/Base.h" +#include "base/kernel/interfaces/IBaseListener.h" +#include "base/kernel/Process.h" +#include "common/Platform.h" +#include "core/config/Config_default.h" +#include "core/config/Config.h" +#include "core/config/ConfigTransform.h" + + +#ifdef HAVE_SYSLOG_H +# include "base/io/log/backends/SysLog.h" +#endif + + +#ifdef XMRIG_FEATURE_API +# include "api/Api.h" +#endif + + +class xmrig::BasePrivate +{ +public: + inline BasePrivate(Process *process) : + api(nullptr), + config(nullptr), + process(process), + watcher(nullptr) + {} + + + inline ~BasePrivate() + { +# ifdef XMRIG_FEATURE_API + delete api; +# endif + + delete config; + delete watcher; + } + + + inline bool read(const JsonChain &chain, std::unique_ptr &config) + { + config = std::unique_ptr(new Config()); + + return config->read(chain, chain.fileName()); + } + + + inline Config *load() + { + JsonChain chain; + ConfigTransform transform; + std::unique_ptr config; + + transform.load(chain, process, transform); + + if (read(chain, config)) { + return config.release(); + } + + chain.addFile(process->location(Process::ExeLocation, "config.json")); + + if (read(chain, config)) { + return config.release(); + } + +# ifdef XMRIG_FEATURE_EMBEDDED_CONFIG + chain.addRaw(default_config); + + if (read(chain, config)) { + return config.release(); + } +# endif + + return nullptr; + } + + + inline void replace(Config *newConfig) + { + Config *previousConfig = config; + config = newConfig; + + for (IBaseListener *listener : listeners) { + listener->onConfigChanged(config, previousConfig); + } + + delete previousConfig; + } + + + Api *api; + Config *config; + Process *process; + std::vector listeners; + Watcher *watcher; +}; + + +xmrig::Base::Base(Process *process) + : d_ptr(new BasePrivate(process)) +{ +} + + +xmrig::Base::~Base() +{ + delete d_ptr; +} + + +bool xmrig::Base::isReady() const +{ + return d_ptr->config != nullptr; +} + + +int xmrig::Base::init() +{ + d_ptr->config = d_ptr->load(); + + if (!d_ptr->config) { + LOG_EMERG("No valid configuration found. Exiting."); + + return 1; + } + +# ifdef XMRIG_FEATURE_API + d_ptr->api = new Api(this); +# endif + + Platform::init(config()->userAgent()); + Platform::setProcessPriority(config()->priority()); + + if (!config()->isBackground()) { + Log::add(new ConsoleLog()); + } + + if (config()->logFile()) { + Log::add(new FileLog(config()->logFile())); + } + +# ifdef HAVE_SYSLOG_H + if (config()->isSyslog()) { + Log::add(new SysLog()); + } +# endif + + return 0; +} + + +void xmrig::Base::start() +{ +# ifdef XMRIG_FEATURE_API + api()->start(); +# endif + + if (config()->isShouldSave()) { + config()->save(); + } + + if (config()->isWatch()) { + d_ptr->watcher = new Watcher(config()->fileName(), this); + } +} + + +void xmrig::Base::stop() +{ +# ifdef XMRIG_FEATURE_API + api()->stop(); +# endif + + delete d_ptr->watcher; + d_ptr->watcher = nullptr; +} + + +xmrig::Api *xmrig::Base::api() const +{ + assert(d_ptr->api != nullptr); + + return d_ptr->api; +} + + +bool xmrig::Base::reload(const rapidjson::Value &json) +{ + JsonReader reader(json); + if (reader.isEmpty()) { + return false; + } + + Config *config = new Config(); + if (!config->read(reader, d_ptr->config->fileName())) { + delete config; + + return false; + } + + const bool saved = config->save(); + + if (config->isWatch() && d_ptr->watcher && saved) { + delete config; + + return true; + } + + d_ptr->replace(config); + + return true; +} + + +xmrig::Config *xmrig::Base::config() const +{ + assert(d_ptr->config != nullptr); + + return d_ptr->config; +} + + +void xmrig::Base::addListener(IBaseListener *listener) +{ + d_ptr->listeners.push_back(listener); +} + + +void xmrig::Base::onFileChanged(const String &fileName) +{ + LOG_WARN("\"%s\" was changed, reloading configuration", fileName.data()); + + JsonChain chain; + chain.addFile(fileName); + + Config *config = new Config(); + + if (!config->read(chain, chain.fileName())) { + LOG_ERR("reloading failed"); + + delete config; + return; + } + + d_ptr->replace(config); +} diff --git a/src/common/config/ConfigWatcher.cpp b/src/base/kernel/Base.h similarity index 62% rename from src/common/config/ConfigWatcher.cpp rename to src/base/kernel/Base.h index 1c70547e..592d3a37 100644 --- a/src/common/config/ConfigWatcher.cpp +++ b/src/base/kernel/Base.h @@ -22,42 +22,50 @@ * along with this program. If not, see . */ +#ifndef XMRIG_BASE_H +#define XMRIG_BASE_H + -#include "base/io/log/Log.h" -#include "base/io/Watcher.h" #include "base/kernel/interfaces/IConfigListener.h" -#include "common/config/ConfigLoader.h" -#include "common/config/ConfigWatcher.h" -#include "core/config/Config.h" +#include "base/kernel/interfaces/IWatcherListener.h" +#include "rapidjson/fwd.h" -xmrig::ConfigWatcher::ConfigWatcher(const String &path, IConfigListener *listener) : - m_listener(listener) +namespace xmrig { + + +class Api; +class Config; +class BasePrivate; +class IBaseListener; +class Process; + + +class Base : public IWatcherListener { - m_watcher = new Watcher(path, this); -} +public: + Base(Process *process); + ~Base() override; + + virtual bool isReady() const; + virtual int init(); + virtual void start(); + virtual void stop(); + + Api *api() const; + bool reload(const rapidjson::Value &json); + Config *config() const; + void addListener(IBaseListener *listener); + +protected: + void onFileChanged(const String &fileName) override; + +private: + BasePrivate *d_ptr; +}; -xmrig::ConfigWatcher::~ConfigWatcher() -{ - delete m_watcher; -} +} /* namespace xmrig */ - -void xmrig::ConfigWatcher::onFileChanged(const String &fileName) -{ - LOG_WARN("\"%s\" was changed, reloading configuration", fileName.data()); - - IConfig *config = Config::create(); - ConfigLoader::loadFromFile(config, fileName); - - if (!config->finalize()) { - LOG_ERR("reloading failed"); - - delete config; - return; - } - - m_listener->onNewConfig(config); -} +#endif /* XMRIG_BASE_H */ diff --git a/src/base/kernel/config/BaseConfig.cpp b/src/base/kernel/config/BaseConfig.cpp new file mode 100644 index 00000000..7284c263 --- /dev/null +++ b/src/base/kernel/config/BaseConfig.cpp @@ -0,0 +1,195 @@ +/* XMRig + * Copyright 2010 Jeff Garzik + * Copyright 2012-2014 pooler + * Copyright 2014 Lucas Jones + * Copyright 2014-2016 Wolf9466 + * Copyright 2016 Jay D Dee + * Copyright 2017-2018 XMR-Stak , + * Copyright 2018-2019 SChernykh + * Copyright 2016-2019 XMRig , + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + + +#include +#include +#include +#include +#include + + +#ifdef XMRIG_FEATURE_TLS +# include +#endif + + +#ifdef XMRIG_AMD_PROJECT +# if defined(__APPLE__) +# include +# else +# include "3rdparty/CL/cl.h" +# endif +#endif + + +#ifdef XMRIG_NVIDIA_PROJECT +# include "nvidia/cryptonight.h" +#endif + + +#include "base/io/Json.h" +#include "base/io/log/Log.h" +#include "base/kernel/config/BaseConfig.h" +#include "base/kernel/interfaces/IJsonReader.h" +#include "donate.h" +#include "rapidjson/document.h" +#include "rapidjson/filewritestream.h" +#include "rapidjson/prettywriter.h" +#include "version.h" + + +xmrig::BaseConfig::BaseConfig() : + m_algorithm(CRYPTONIGHT, VARIANT_AUTO), + m_autoSave(true), + m_background(false), + m_dryRun(false), + m_syslog(false), + m_upgrade(false), + m_watch(true) +{ +} + + +void xmrig::BaseConfig::printVersions() +{ + char buf[256] = { 0 }; + +# if defined(__clang__) + snprintf(buf, sizeof buf, "clang/%d.%d.%d", __clang_major__, __clang_minor__, __clang_patchlevel__); +# elif defined(__GNUC__) + snprintf(buf, sizeof buf, "gcc/%d.%d.%d", __GNUC__, __GNUC_MINOR__, __GNUC_PATCHLEVEL__); +# elif defined(_MSC_VER) + snprintf(buf, sizeof buf, "MSVC/%d", MSVC_VERSION); +# endif + + Log::print(GREEN_BOLD(" * ") WHITE_BOLD("%-13s") CYAN_BOLD("%s/%s") WHITE_BOLD(" %s"), "ABOUT", APP_NAME, APP_VERSION, buf); + +# if defined(XMRIG_AMD_PROJECT) +# if CL_VERSION_2_0 + const char *ocl = "2.0"; +# elif CL_VERSION_1_2 + const char *ocl = "1.2"; +# elif CL_VERSION_1_1 + const char *ocl = "1.1"; +# elif CL_VERSION_1_0 + const char *ocl = "1.0"; +# else + const char *ocl = "0.0"; +# endif + int length = snprintf(buf, sizeof buf, "OpenCL/%s ", ocl); +# elif defined(XMRIG_NVIDIA_PROJECT) + const int cudaVersion = cuda_get_runtime_version(); + int length = snprintf(buf, sizeof buf, "CUDA/%d.%d ", cudaVersion / 1000, cudaVersion % 100); +# else + memset(buf, 0, 16); + +# if defined(XMRIG_FEATURE_HTTP) || defined(XMRIG_FEATURE_TLS) + int length = 0; +# endif +# endif + +# if defined(XMRIG_FEATURE_TLS) && defined(OPENSSL_VERSION_TEXT) + { + constexpr const char *v = OPENSSL_VERSION_TEXT + 8; + length += snprintf(buf + length, (sizeof buf) - length, "OpenSSL/%.*s ", static_cast(strchr(v, ' ') - v), v); + } +# endif + + Log::print(GREEN_BOLD(" * ") WHITE_BOLD("%-13slibuv/%s %s"), "LIBS", uv_version_string(), buf); +} + + +bool xmrig::BaseConfig::read(const IJsonReader &reader, const char *fileName) +{ + m_fileName = fileName; + + if (reader.isEmpty()) { + return false; + } + + m_autoSave = reader.getBool("autosave", m_autoSave); + m_background = reader.getBool("background", m_background); + m_dryRun = reader.getBool("dry-run", m_dryRun); + m_syslog = reader.getBool("syslog", m_syslog); + m_watch = reader.getBool("watch", m_watch); + m_logFile = reader.getString("log-file"); + m_userAgent = reader.getString("user-agent"); + + setPrintTime(reader.getUint("print-time", 60)); + + const rapidjson::Value &api = reader.getObject("api"); + if (api.IsObject()) { + m_apiId = Json::getString(api, "id"); + m_apiWorkerId = Json::getString(api, "worker-id"); + } + +# ifdef XMRIG_DEPRECATED + if (api.IsObject() && api.HasMember("port")) { + m_upgrade = true; + m_http.load(api); + m_http.setEnabled(Json::getUint(api, "port") > 0); + m_http.setHost("0.0.0.0"); + } + else { + m_http.load(reader.getObject("http")); + } +# else + m_http.load(chain.getObject("http")); +# endif + + m_algorithm.parseAlgorithm(reader.getString("algo")); + + m_pools.load(reader.getArray("pools")); + m_pools.setDonateLevel(reader.getInt("donate-level", kDefaultDonateLevel)); + m_pools.setProxyDonate(reader.getInt("donate-over-proxy", Pools::PROXY_DONATE_AUTO)); + m_pools.setRetries(reader.getInt("retries")); + m_pools.setRetryPause(reader.getInt("retry-pause")); + + if (!m_algorithm.isValid()) { + return false; + } + + m_pools.adjust(m_algorithm); + + return m_pools.active() > 0; +} + + +bool xmrig::BaseConfig::save() +{ + if (m_fileName.isNull()) { + return false; + } + + rapidjson::Document doc; + getJSON(doc); + + if (Json::save(m_fileName, doc)) { + LOG_NOTICE("configuration saved to: \"%s\"", m_fileName.data()); + return true; + } + + return false; +} diff --git a/src/common/config/CommonConfig.h b/src/base/kernel/config/BaseConfig.h similarity index 71% rename from src/common/config/CommonConfig.h rename to src/base/kernel/config/BaseConfig.h index 55f36d0d..f0c52536 100644 --- a/src/common/config/CommonConfig.h +++ b/src/base/kernel/config/BaseConfig.h @@ -22,60 +22,54 @@ * along with this program. If not, see . */ -#ifndef XMRIG_COMMONCONFIG_H -#define XMRIG_COMMONCONFIG_H +#ifndef XMRIG_BASECONFIG_H +#define XMRIG_BASECONFIG_H +#include "base/kernel/interfaces/IConfig.h" #include "base/net/http/Http.h" #include "base/net/stratum/Pools.h" -#include "common/interfaces/IConfig.h" #include "common/xmrig.h" +struct option; + + namespace xmrig { -class CommonConfig : public IConfig +class IJsonReader; + + +class BaseConfig : public IConfig { public: - CommonConfig(); + BaseConfig(); inline bool isAutoSave() const { return m_autoSave; } inline bool isBackground() const { return m_background; } inline bool isDryRun() const { return m_dryRun; } inline bool isSyslog() const { return m_syslog; } - inline const String &apiId() const { return m_apiId; } - inline const String &apiWorkerId() const { return m_apiWorkerId; } inline const char *logFile() const { return m_logFile.data(); } inline const char *userAgent() const { return m_userAgent.data(); } inline const Http &http() const { return m_http; } inline const Pools &pools() const { return m_pools; } - inline int printTime() const { return m_printTime; } + inline const String &apiId() const { return m_apiId; } + inline const String &apiWorkerId() const { return m_apiWorkerId; } + inline uint32_t printTime() const { return m_printTime; } - inline bool isWatch() const override { return m_watch && !m_fileName.isNull(); } - inline const Algorithm &algorithm() const override { return m_algorithm; } - inline const String &fileName() const override { return m_fileName; } + inline bool isWatch() const override { return m_watch && !m_fileName.isNull(); } + inline const Algorithm &algorithm() const override { return m_algorithm; } + inline const String &fileName() const override { return m_fileName; } + inline void setFileName(const char *fileName) override { m_fileName = fileName; } + bool read(const IJsonReader &reader, const char *fileName) override; bool save() override; void printVersions(); protected: - enum State { - NoneState, - ReadyState, - ErrorState - }; - - bool finalize() override; - bool parseBoolean(int key, bool enable) override; - bool parseString(int key, const char *arg) override; - bool parseUint64(int key, uint64_t arg) override; - void parseJSON(const rapidjson::Value &json) override; - void setFileName(const char *fileName) override; - Algorithm m_algorithm; - bool m_adjusted; bool m_autoSave; bool m_background; bool m_dryRun; @@ -83,20 +77,20 @@ protected: bool m_upgrade; bool m_watch; Http m_http; - int m_printTime; Pools m_pools; - State m_state; String m_apiId; String m_apiWorkerId; String m_fileName; String m_logFile; String m_userAgent; + uint32_t m_printTime; private: - bool parseInt(int key, int arg); + inline void setPrintTime(uint32_t printTime) { if (printTime <= 3600) { m_printTime = printTime; } } }; -} /* namespace xmrig */ +} // namespace xmrig -#endif /* XMRIG_COMMONCONFIG_H */ + +#endif /* XMRIG_BASECONFIG_H */ diff --git a/src/base/kernel/config/BaseTransform.cpp b/src/base/kernel/config/BaseTransform.cpp new file mode 100644 index 00000000..c676330e --- /dev/null +++ b/src/base/kernel/config/BaseTransform.cpp @@ -0,0 +1,255 @@ +/* XMRig + * Copyright 2010 Jeff Garzik + * Copyright 2012-2014 pooler + * Copyright 2014 Lucas Jones + * Copyright 2014-2016 Wolf9466 + * Copyright 2016 Jay D Dee + * Copyright 2017-2018 XMR-Stak , + * Copyright 2018-2019 SChernykh + * Copyright 2016-2019 XMRig , + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + + +#ifdef _MSC_VER +# include "getopt/getopt.h" +#else +# include +#endif + + +#include "base/kernel/config/BaseTransform.h" +#include "base/kernel/Process.h" +#include "base/io/log/Log.h" +#include "base/kernel/interfaces/IConfig.h" +#include "base/io/JsonChain.h" +#include "core/config/Config_platform.h" + + +namespace xmrig +{ + +static const char *kApi = "api"; +static const char *kHttp = "http"; +static const char *kPools = "pools"; + +} + + +xmrig::BaseTransform::BaseTransform() +{ +} + + +void xmrig::BaseTransform::load(JsonChain &chain, Process *process, IConfigTransform &transform) +{ + using namespace rapidjson; + + int key; + int argc = process->arguments().argc(); + char **argv = process->arguments().argv(); + + Document doc(kObjectType); + + while (1) { + key = getopt_long(argc, argv, short_options, options, nullptr); + if (key < 0) { + break; + } + + if (key == IConfig::ConfigKey) { + chain.add(std::move(doc)); + chain.addFile(optarg); + + doc = Document(kObjectType); + } + else { + transform.transform(doc, key, optarg); + } + } + + if (optind < argc) { + LOG_WARN("%s: unsupported non-option argument '%s'", argv[0], argv[optind]); + } + + chain.add(std::move(doc)); +} + + +void xmrig::BaseTransform::transform(rapidjson::Document &doc, int key, const char *arg) +{ + switch (key) { + case IConfig::AlgorithmKey: /* --algo */ + return set(doc, "algo", arg); + + case IConfig::UserpassKey: /* --userpass */ + return add(doc, kPools, "userpass", arg); + + case IConfig::UrlKey: /* --url */ + return add(doc, kPools, "url", arg, true); + + case IConfig::UserKey: /* --user */ + return add(doc, kPools, "user", arg); + + case IConfig::PasswordKey: /* --pass */ + return add(doc, kPools, "pass", arg); + + case IConfig::RigIdKey: /* --rig-id */ + return add(doc, kPools, "rig-id", arg); + + case IConfig::FingerprintKey: /* --tls-fingerprint */ + return add(doc, kPools, "tls-fingerprint", arg); + + case IConfig::VariantKey: /* --variant */ + return add(doc, kPools, "variant", arg); + + case IConfig::LogFileKey: /* --log-file */ + return set(doc, "log-file", arg); + +# ifdef XMRIG_DEPRECATED + case IConfig::ApiAccessTokenKey: /* --api-access-token */ + fputs("option \"--api-access-token\" deprecated, use \"--http-access-token\" instead.\n", stderr); + fflush(stdout); + return set(doc, kHttp, "access-token", arg); +# endif + + case IConfig::HttpAccessTokenKey: /* --http-access-token */ + return set(doc, kHttp, "access-token", arg); + + case IConfig::HttpHostKey: /* --http-host */ + return set(doc, kHttp, "host", arg); + + case IConfig::ApiWorkerIdKey: /* --api-worker-id */ + return set(doc, kApi, "worker-id", arg); + + case IConfig::ApiIdKey: /* --api-id */ + return set(doc, kApi, "id", arg); + + case IConfig::UserAgentKey: /* --user-agent */ + return set(doc, "user-agent", arg); + + case IConfig::RetriesKey: /* --retries */ + case IConfig::RetryPauseKey: /* --retry-pause */ + case IConfig::PrintTimeKey: /* --print-time */ + case IConfig::HttpPort: /* --http-port */ + case IConfig::DonateLevelKey: /* --donate-level */ +# ifdef XMRIG_DEPRECATED + case IConfig::ApiPort: /* --api-port */ +# endif + return transformUint64(doc, key, static_cast(strtol(arg, nullptr, 10))); + + case IConfig::BackgroundKey: /* --background */ + case IConfig::SyslogKey: /* --syslog */ + case IConfig::KeepAliveKey: /* --keepalive */ + case IConfig::NicehashKey: /* --nicehash */ + case IConfig::TlsKey: /* --tls */ + case IConfig::DryRunKey: /* --dry-run */ + case IConfig::HttpEnabledKey: /* --http-enabled */ + return transformBoolean(doc, key, true); + + case IConfig::ColorKey: /* --no-color */ + case IConfig::HttpRestrictedKey: /* --http-no-restricted */ +# ifdef XMRIG_DEPRECATED + case IConfig::ApiRestrictedKey: /* --api-no-restricted */ + case IConfig::ApiIPv6Key: /* --api-ipv6 */ +# endif + return transformBoolean(doc, key, false); + + default: + break; + } +} + + +void xmrig::BaseTransform::transformBoolean(rapidjson::Document &doc, int key, bool enable) +{ + switch (key) { + case IConfig::BackgroundKey: /* --background */ + return set(doc, "background", enable); + + case IConfig::SyslogKey: /* --syslog */ + return set(doc, "syslog", enable); + + case IConfig::KeepAliveKey: /* --keepalive */ + return add(doc, kPools, "keepalive", enable); + + case IConfig::TlsKey: /* --tls */ + return add(doc, kPools, "tls", enable); + +# ifndef XMRIG_PROXY_PROJECT + case IConfig::NicehashKey: /* --nicehash */ + return add(doc, kPools, "nicehash", enable); +# endif + + case IConfig::ColorKey: /* --no-color */ + return set(doc, "colors", enable); + +# ifdef XMRIG_DEPRECATED + case IConfig::ApiIPv6Key: /* --api-ipv6 */ + break; + + case IConfig::ApiRestrictedKey: /* --api-no-restricted */ + fputs("option \"--api-no-restricted\" deprecated, use \"--http-no-restricted\" instead.\n", stderr); + fflush(stdout); + return set(doc, kHttp, "restricted", enable); +# endif + + case IConfig::HttpRestrictedKey: /* --http-no-restricted */ + return set(doc, kHttp, "restricted", enable); + + case IConfig::HttpEnabledKey: /* --http-enabled */ + return set(doc, kHttp, "enabled", enable); + + case IConfig::DryRunKey: /* --dry-run */ + return set(doc, "dry-run", enable); + + default: + break; + } +} + + +void xmrig::BaseTransform::transformUint64(rapidjson::Document &doc, int key, uint64_t arg) +{ + switch (key) { + case IConfig::RetriesKey: /* --retries */ + return set(doc, "retries", arg); + + case IConfig::RetryPauseKey: /* --retry-pause */ + return set(doc, "retry-pause", arg); + + case IConfig::DonateLevelKey: /* --donate-level */ + return set(doc, "donate-level", arg); + + case IConfig::ProxyDonateKey: /* --donate-over-proxy */ + return set(doc, "donate-over-proxy", arg); + +# ifdef XMRIG_DEPRECATED + case IConfig::ApiPort: /* --api-port */ + fputs("option \"--api-port\" deprecated, use \"--http-port\" instead.\n", stderr); + fflush(stdout); + return set(doc, kHttp, "port", arg); +# endif + + case IConfig::HttpPort: /* --http-port */ + return set(doc, kHttp, "port", arg); + + case IConfig::PrintTimeKey: /* --print-time */ + return set(doc, "print-time", arg); + + default: + break; + } +} diff --git a/src/base/kernel/config/BaseTransform.h b/src/base/kernel/config/BaseTransform.h new file mode 100644 index 00000000..3952e22b --- /dev/null +++ b/src/base/kernel/config/BaseTransform.h @@ -0,0 +1,123 @@ +/* XMRig + * Copyright 2010 Jeff Garzik + * Copyright 2012-2014 pooler + * Copyright 2014 Lucas Jones + * Copyright 2014-2016 Wolf9466 + * Copyright 2016 Jay D Dee + * Copyright 2017-2018 XMR-Stak , + * Copyright 2018-2019 SChernykh + * Copyright 2016-2019 XMRig , + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef XMRIG_BASETRANSFORM_H +#define XMRIG_BASETRANSFORM_H + + +#include "base/kernel/interfaces/IConfigTransform.h" +#include "rapidjson/document.h" + + +struct option; + + +namespace xmrig { + + +class IConfigTransform; +class JsonChain; +class Process; + + +class BaseTransform : public IConfigTransform +{ +public: + BaseTransform(); + + static void load(JsonChain &chain, Process *process, IConfigTransform &transform); + +protected: + void transform(rapidjson::Document &doc, int key, const char *arg) override; + + + template + inline void set(rapidjson::Document &doc, const char *key, T value) { set(doc, doc, key, value); } + + + template + inline void set(rapidjson::Document &doc, const char *objKey, const char *key, T value) + { + if (!doc.HasMember(objKey)) { + doc.AddMember(rapidjson::StringRef(objKey), rapidjson::kObjectType, doc.GetAllocator()); + } + + set(doc, doc[objKey], key, value); + } + + + template + inline void add(rapidjson::Document &doc, const char *arrayKey, const char *key, T value, bool force = false) + { + auto &allocator = doc.GetAllocator(); + + if (!doc.HasMember(arrayKey)) { + doc.AddMember(rapidjson::StringRef(arrayKey), rapidjson::kArrayType, allocator); + } + + rapidjson::Value &array = doc[arrayKey]; + if (force || array.Size() == 0) { + array.PushBack(rapidjson::kObjectType, allocator); + } + + set(doc, array[array.Size() - 1], key, value); + } + + + template + inline void set(rapidjson::Document &doc, rapidjson::Value &obj, const char *key, T value) + { + if (obj.HasMember(key)) { + obj[key] = value; + } + else { + obj.AddMember(rapidjson::StringRef(key), value, doc.GetAllocator()); + } + } + + +private: + void transformBoolean(rapidjson::Document &doc, int key, bool enable); + void transformUint64(rapidjson::Document &doc, int key, uint64_t arg); +}; + + +template<> +inline void BaseTransform::set(rapidjson::Document &doc, rapidjson::Value &obj, const char *key, const char *value) +{ + auto &allocator = doc.GetAllocator(); + + if (obj.HasMember(key)) { + obj[key] = rapidjson::Value(value, allocator); + } + else { + obj.AddMember(rapidjson::StringRef(key), rapidjson::Value(value, allocator), allocator); + } +} + + +} // namespace xmrig + + +#endif /* XMRIG_BASETRANSFORM_H */ diff --git a/src/base/kernel/interfaces/IControllerListener.h b/src/base/kernel/interfaces/IBaseListener.h similarity index 88% rename from src/base/kernel/interfaces/IControllerListener.h rename to src/base/kernel/interfaces/IBaseListener.h index c6157408..1f212369 100644 --- a/src/base/kernel/interfaces/IControllerListener.h +++ b/src/base/kernel/interfaces/IBaseListener.h @@ -22,8 +22,8 @@ * along with this program. If not, see . */ -#ifndef XMRIG_ICONTROLLERLISTENER_H -#define XMRIG_ICONTROLLERLISTENER_H +#ifndef XMRIG_IBASELISTENER_H +#define XMRIG_IBASELISTENER_H namespace xmrig { @@ -32,10 +32,10 @@ namespace xmrig { class Config; -class IControllerListener +class IBaseListener { public: - virtual ~IControllerListener() = default; + virtual ~IBaseListener() = default; virtual void onConfigChanged(Config *config, Config *previousConfig) = 0; }; @@ -44,4 +44,4 @@ public: } /* namespace xmrig */ -#endif // XMRIG_ICONTROLLERLISTENER_H +#endif // XMRIG_IBASELISTENER_H diff --git a/src/common/interfaces/IConfig.h b/src/base/kernel/interfaces/IConfig.h similarity index 85% rename from src/common/interfaces/IConfig.h rename to src/base/kernel/interfaces/IConfig.h index 071b3478..44628129 100644 --- a/src/common/interfaces/IConfig.h +++ b/src/base/kernel/interfaces/IConfig.h @@ -33,6 +33,7 @@ namespace xmrig { +class IJsonReader; class String; @@ -66,10 +67,8 @@ public: UserpassKey = 'O', VariantKey = 1010, VerboseKey = 1100, - WatchKey = 1105, TlsKey = 1013, FingerprintKey = 1014, - AutoSaveKey = 1016, ProxyDonateKey = 1017, # ifdef XMRIG_DEPRECATED @@ -92,7 +91,7 @@ public: MaxCPUUsageKey = 1004, SafeKey = 1005, ThreadsKey = 't', - HardwareAESKey = 1011, +// HardwareAESKey = 1011, AssemblyKey = 1015, // xmrig amd @@ -141,17 +140,13 @@ public: virtual ~IConfig() = default; - virtual bool finalize() = 0; - virtual bool isWatch() const = 0; - virtual bool parseBoolean(int key, bool enable) = 0; - virtual bool parseString(int key, const char *arg) = 0; - virtual bool parseUint64(int key, uint64_t arg) = 0; - virtual bool save() = 0; - virtual const Algorithm &algorithm() const = 0; - virtual const String &fileName() const = 0; - virtual void getJSON(rapidjson::Document &doc) const = 0; - virtual void parseJSON(const rapidjson::Value &json) = 0; - virtual void setFileName(const char *fileName) = 0; + virtual bool isWatch() const = 0; + virtual bool read(const IJsonReader &reader, const char *fileName) = 0; + virtual bool save() = 0; + virtual const Algorithm &algorithm() const = 0; + virtual const String &fileName() const = 0; + virtual void getJSON(rapidjson::Document &doc) const = 0; + virtual void setFileName(const char *fileName) = 0; }; diff --git a/src/common/config/ConfigWatcher.h b/src/base/kernel/interfaces/IConfigTransform.h similarity index 72% rename from src/common/config/ConfigWatcher.h rename to src/base/kernel/interfaces/IConfigTransform.h index 77b41cf5..37ceaba1 100644 --- a/src/common/config/ConfigWatcher.h +++ b/src/base/kernel/interfaces/IConfigTransform.h @@ -22,40 +22,31 @@ * along with this program. If not, see . */ -#ifndef XMRIG_CONFIGWATCHER_H -#define XMRIG_CONFIGWATCHER_H +#ifndef XMRIG_ICONFIGTRANSFORM_H +#define XMRIG_ICONFIGTRANSFORM_H -#include "base/kernel/interfaces/IWatcherListener.h" -#include "base/tools/String.h" +#include "common/crypto/Algorithm.h" #include "rapidjson/fwd.h" -struct option; - - namespace xmrig { -class IConfigListener; -class Watcher; +class IJsonReader; +class String; -class ConfigWatcher : public IWatcherListener +class IConfigTransform { public: - ConfigWatcher(const String &path, IConfigListener *listener); - ~ConfigWatcher() override; + virtual ~IConfigTransform() = default; -protected: - void onFileChanged(const String &fileName) override; - -private: - IConfigListener *m_listener; - Watcher *m_watcher; + virtual void transform(rapidjson::Document &doc, int key, const char *arg) = 0; }; } /* namespace xmrig */ -#endif /* __CONFIGWATCHER_H__ */ + +#endif // XMRIG_ICONFIGTRANSFORM_H diff --git a/src/common/config/ConfigLoader.h b/src/base/kernel/interfaces/IJsonReader.h similarity index 53% rename from src/common/config/ConfigLoader.h rename to src/base/kernel/interfaces/IJsonReader.h index f03de711..c0fe09cb 100644 --- a/src/common/config/ConfigLoader.h +++ b/src/base/kernel/interfaces/IJsonReader.h @@ -22,50 +22,35 @@ * along with this program. If not, see . */ -#ifndef XMRIG_CONFIGLOADER_H -#define XMRIG_CONFIGLOADER_H - - -#include +#ifndef XMRIG_IJSONREADER_H +#define XMRIG_IJSONREADER_H #include "rapidjson/fwd.h" -struct option; - - namespace xmrig { -class ConfigWatcher; -class IConfigListener; -class IConfig; -class Process; - - -class ConfigLoader +class IJsonReader { public: - static bool loadFromFile(IConfig *config, const char *fileName); - static bool loadFromJSON(IConfig *config, const char *json); - static bool loadFromJSON(IConfig *config, const rapidjson::Value &json); - static bool reload(IConfig *oldConfig, const rapidjson::Value &json); - static bool watch(IConfig *config); - static IConfig *load(Process *process, IConfigListener *listener); - static void release(); + virtual ~IJsonReader() = default; -private: - static bool getJSON(const char *fileName, rapidjson::Document &doc); - static bool parseArg(IConfig *config, int key, const char *arg); - static void parseJSON(IConfig *config, const struct option *option, const rapidjson::Value &object); - - static ConfigWatcher *m_watcher; - static IConfigListener *m_listener; + virtual bool getBool(const char *key, bool defaultValue = false) const = 0; + virtual bool isEmpty() const = 0; + virtual const char *getString(const char *key, const char *defaultValue = nullptr) const = 0; + virtual const rapidjson::Value &getArray(const char *key) const = 0; + virtual const rapidjson::Value &getObject(const char *key) const = 0; + virtual const rapidjson::Value &getValue(const char *key) const = 0; + virtual int getInt(const char *key, int defaultValue = 0) const = 0; + virtual int64_t getInt64(const char *key, int64_t defaultValue = 0) const = 0; + virtual uint64_t getUint64(const char *key, uint64_t defaultValue = 0) const = 0; + virtual unsigned getUint(const char *key, unsigned defaultValue = 0) const = 0; }; } /* namespace xmrig */ -#endif /* XMRIG_CONFIGLOADER_H */ +#endif // XMRIG_IJSONREADER_H diff --git a/src/base/net/stratum/Pools.cpp b/src/base/net/stratum/Pools.cpp index 63102c00..638ba5ea 100644 --- a/src/base/net/stratum/Pools.cpp +++ b/src/base/net/stratum/Pools.cpp @@ -44,16 +44,6 @@ xmrig::Pools::Pools() : } -xmrig::Pool &xmrig::Pools::current() -{ - if (m_data.empty()) { - m_data.push_back(Pool()); - } - - return m_data.back(); -} - - bool xmrig::Pools::isEqual(const Pools &other) const { if (m_data.size() != other.m_data.size() || m_retries != other.m_retries || m_retryPause != other.m_retryPause) { @@ -64,25 +54,6 @@ bool xmrig::Pools::isEqual(const Pools &other) const } -bool xmrig::Pools::setUrl(const char *url) -{ - if (m_data.empty() || m_data.back().isValid()) { - Pool pool(url); - - if (pool.isValid()) { - m_data.push_back(std::move(pool)); - return true; - } - - return false; - } - - current().parse(url); - - return m_data.back().isValid(); -} - - xmrig::IStrategy *xmrig::Pools::createStrategy(IStrategyListener *listener) const { if (active() == 1) { @@ -144,6 +115,10 @@ void xmrig::Pools::load(const rapidjson::Value &pools) { m_data.clear(); + if (!pools.IsArray()) { + return; + } + for (const rapidjson::Value &value : pools.GetArray()) { if (!value.IsObject()) { continue; diff --git a/src/base/net/stratum/Pools.h b/src/base/net/stratum/Pools.h index f563f243..6a63f166 100644 --- a/src/base/net/stratum/Pools.h +++ b/src/base/net/stratum/Pools.h @@ -50,28 +50,16 @@ public: Pools(); - inline bool setUserpass(const char *userpass) { return current().setUserpass(userpass); } inline const std::vector &data() const { return m_data; } inline int donateLevel() const { return m_donateLevel; } inline int retries() const { return m_retries; } inline int retryPause() const { return m_retryPause; } inline ProxyDonate proxyDonate() const { return m_proxyDonate; } - inline void setFingerprint(const char *fingerprint) { current().setFingerprint(fingerprint); } - inline void setKeepAlive(bool enable) { current().setKeepAlive(enable); } - inline void setKeepAlive(int keepAlive) { current().setKeepAlive(keepAlive); } - inline void setNicehash(bool enable) { current().setNicehash(enable); } - inline void setPassword(const char *password) { current().setPassword(password); } - inline void setRigId(const char *rigId) { current().setRigId(rigId); } - inline void setTLS(bool enable) { current().setTLS(enable); } - inline void setUser(const char *user) { current().setUser(user); } - inline void setVariant(const char *variant) { current().algorithm().parseVariant(variant); } - inline void setVariant(int variant) { current().algorithm().parseVariant(variant); } inline bool operator!=(const Pools &other) const { return !isEqual(other); } inline bool operator==(const Pools &other) const { return isEqual(other); } bool isEqual(const Pools &other) const; - bool setUrl(const char *url); IStrategy *createStrategy(IStrategyListener *listener) const; rapidjson::Value toJSON(rapidjson::Document &doc) const; size_t active() const; @@ -84,8 +72,6 @@ public: void setRetryPause(int retryPause); private: - Pool ¤t(); - int m_donateLevel; int m_retries; int m_retryPause; diff --git a/src/common/config/CommonConfig.cpp b/src/common/config/CommonConfig.cpp deleted file mode 100644 index b0b716c1..00000000 --- a/src/common/config/CommonConfig.cpp +++ /dev/null @@ -1,426 +0,0 @@ -/* XMRig - * Copyright 2010 Jeff Garzik - * Copyright 2012-2014 pooler - * Copyright 2014 Lucas Jones - * Copyright 2014-2016 Wolf9466 - * Copyright 2016 Jay D Dee - * Copyright 2017-2018 XMR-Stak , - * Copyright 2018-2019 SChernykh - * Copyright 2016-2019 XMRig , - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - - -#include -#include -#include -#include -#include - - -#ifdef XMRIG_FEATURE_TLS -# include -#endif - - -#ifdef XMRIG_AMD_PROJECT -# if defined(__APPLE__) -# include -# else -# include "3rdparty/CL/cl.h" -# endif -#endif - - -#ifdef XMRIG_NVIDIA_PROJECT -# include "nvidia/cryptonight.h" -#endif - - -#include "base/io/Json.h" -#include "base/io/log/Log.h" -#include "common/config/CommonConfig.h" -#include "rapidjson/document.h" -#include "rapidjson/filewritestream.h" -#include "rapidjson/prettywriter.h" -#include "version.h" - - -xmrig::CommonConfig::CommonConfig() : - m_algorithm(CRYPTONIGHT, VARIANT_AUTO), - m_adjusted(false), - m_autoSave(true), - m_background(false), - m_dryRun(false), - m_syslog(false), - m_upgrade(false), - m_watch(true), - m_printTime(60), - m_state(NoneState) -{ -} - - -void xmrig::CommonConfig::printVersions() -{ - char buf[256] = { 0 }; - -# if defined(__clang__) - snprintf(buf, sizeof buf, "clang/%d.%d.%d", __clang_major__, __clang_minor__, __clang_patchlevel__); -# elif defined(__GNUC__) - snprintf(buf, sizeof buf, "gcc/%d.%d.%d", __GNUC__, __GNUC_MINOR__, __GNUC_PATCHLEVEL__); -# elif defined(_MSC_VER) - snprintf(buf, sizeof buf, "MSVC/%d", MSVC_VERSION); -# endif - - Log::print(GREEN_BOLD(" * ") WHITE_BOLD("%-13s") CYAN_BOLD("%s/%s") WHITE_BOLD(" %s"), "ABOUT", APP_NAME, APP_VERSION, buf); - -# if defined(XMRIG_AMD_PROJECT) -# if CL_VERSION_2_0 - const char *ocl = "2.0"; -# elif CL_VERSION_1_2 - const char *ocl = "1.2"; -# elif CL_VERSION_1_1 - const char *ocl = "1.1"; -# elif CL_VERSION_1_0 - const char *ocl = "1.0"; -# else - const char *ocl = "0.0"; -# endif - int length = snprintf(buf, sizeof buf, "OpenCL/%s ", ocl); -# elif defined(XMRIG_NVIDIA_PROJECT) - const int cudaVersion = cuda_get_runtime_version(); - int length = snprintf(buf, sizeof buf, "CUDA/%d.%d ", cudaVersion / 1000, cudaVersion % 100); -# else - memset(buf, 0, 16); - -# if defined(XMRIG_FEATURE_HTTP) || defined(XMRIG_FEATURE_TLS) - int length = 0; -# endif -# endif - -# if defined(XMRIG_FEATURE_TLS) && defined(OPENSSL_VERSION_TEXT) - { - constexpr const char *v = OPENSSL_VERSION_TEXT + 8; - length += snprintf(buf + length, (sizeof buf) - length, "OpenSSL/%.*s ", static_cast(strchr(v, ' ') - v), v); - } -# endif - - Log::print(GREEN_BOLD(" * ") WHITE_BOLD("%-13slibuv/%s %s"), "LIBS", uv_version_string(), buf); -} - - -bool xmrig::CommonConfig::save() -{ - if (m_fileName.isNull()) { - return false; - } - - rapidjson::Document doc; - getJSON(doc); - - if (Json::save(m_fileName, doc)) { - LOG_NOTICE("configuration saved to: \"%s\"", m_fileName.data()); - return true; - } - - return false; -} - - -bool xmrig::CommonConfig::finalize() -{ - if (m_state == ReadyState) { - return true; - } - - if (m_state == ErrorState) { - return false; - } - - if (!m_algorithm.isValid()) { - return false; - } - - m_pools.adjust(m_algorithm); - - if (!m_pools.active()) { - m_state = ErrorState; - return false; - } - - m_state = ReadyState; - return true; -} - - -bool xmrig::CommonConfig::parseBoolean(int key, bool enable) -{ - switch (key) { - case BackgroundKey: /* --background */ - m_background = enable; - break; - - case SyslogKey: /* --syslog */ - m_syslog = enable; - break; - - case KeepAliveKey: /* --keepalive */ - m_pools.setKeepAlive(enable); - break; - - case TlsKey: /* --tls */ - m_pools.setTLS(enable); - break; - -# ifndef XMRIG_PROXY_PROJECT - case NicehashKey: /* --nicehash */ - m_pools.setNicehash(enable); - break; -# endif - - case ColorKey: /* --no-color */ - Log::colors = enable; - break; - - case WatchKey: /* watch */ - m_watch = enable; - break; - -# ifdef XMRIG_DEPRECATED - case ApiIPv6Key: /* --api-ipv6 */ - break; - - case ApiRestrictedKey: /* --api-no-restricted */ - fputs("option \"--api-no-restricted\" deprecated, use \"--http-no-restricted\" instead.\n", stderr); - fflush(stdout); - m_http.setRestricted(enable); - break; -# endif - - case HttpRestrictedKey: /* --http-no-restricted */ - m_http.setRestricted(enable); - break; - - case HttpEnabledKey: /* --http-enabled */ - m_http.setEnabled(enable); - break; - - case DryRunKey: /* --dry-run */ - m_dryRun = enable; - break; - - case AutoSaveKey: - m_autoSave = enable; - break; - - default: - break; - } - - return true; -} - - -bool xmrig::CommonConfig::parseString(int key, const char *arg) -{ - switch (key) { - case AlgorithmKey: /* --algo */ - m_algorithm.parseAlgorithm(arg); - break; - - case UserpassKey: /* --userpass */ - return m_pools.setUserpass(arg); - - case UrlKey: /* --url */ - return m_pools.setUrl(arg); - - case UserKey: /* --user */ - m_pools.setUser(arg); - break; - - case PasswordKey: /* --pass */ - m_pools.setPassword(arg); - break; - - case RigIdKey: /* --rig-id */ - m_pools.setRigId(arg); - break; - - case FingerprintKey: /* --tls-fingerprint */ - m_pools.setFingerprint(arg); - break; - - case VariantKey: /* --variant */ - m_pools.setVariant(arg); - break; - - case LogFileKey: /* --log-file */ - m_logFile = arg; - break; - -# ifdef XMRIG_DEPRECATED - case ApiAccessTokenKey: /* --api-access-token */ - fputs("option \"--api-access-token\" deprecated, use \"--http-access-token\" instead.\n", stderr); - fflush(stdout); - m_http.setToken(arg); - break; -# endif - - case HttpAccessTokenKey: /* --http-access-token */ - m_http.setToken(arg); - break; - - case HttpHostKey: /* --http-host */ - m_http.setHost(arg); - break; - - case ApiWorkerIdKey: /* --api-worker-id */ - m_apiWorkerId = arg; - break; - - case ApiIdKey: /* --api-id */ - m_apiId = arg; - break; - - case UserAgentKey: /* --user-agent */ - m_userAgent = arg; - break; - - case RetriesKey: /* --retries */ - case RetryPauseKey: /* --retry-pause */ - case PrintTimeKey: /* --print-time */ - case HttpPort: /* --http-port */ -# ifdef XMRIG_DEPRECATED - case ApiPort: /* --api-port */ -# endif - return parseUint64(key, static_cast(strtol(arg, nullptr, 10))); - - case BackgroundKey: /* --background */ - case SyslogKey: /* --syslog */ - case KeepAliveKey: /* --keepalive */ - case NicehashKey: /* --nicehash */ - case TlsKey: /* --tls */ - case DryRunKey: /* --dry-run */ - case HttpEnabledKey: /* --http-enabled */ - return parseBoolean(key, true); - - case ColorKey: /* --no-color */ - case WatchKey: /* --no-watch */ - case HttpRestrictedKey: /* --http-no-restricted */ -# ifdef XMRIG_DEPRECATED - case ApiRestrictedKey: /* --api-no-restricted */ - case ApiIPv6Key: /* --api-ipv6 */ -# endif - return parseBoolean(key, false); - - case DonateLevelKey: /* --donate-level */ - return parseUint64(key, static_cast(strtol(arg, nullptr, 10))); - - default: - break; - } - - return true; -} - - -bool xmrig::CommonConfig::parseUint64(int key, uint64_t arg) -{ - return parseInt(key, static_cast(arg)); -} - - -void xmrig::CommonConfig::parseJSON(const rapidjson::Value &json) -{ - const rapidjson::Value &pools = json["pools"]; - if (pools.IsArray()) { - m_pools.load(pools); - } - -# ifdef XMRIG_DEPRECATED - const rapidjson::Value &api = json["api"]; - if (api.IsObject() && api.HasMember("port")) { - m_upgrade = true; - m_http.load(api); - m_http.setEnabled(Json::getUint(api, "port") > 0); - m_http.setHost("0.0.0.0"); - } - else { - m_http.load(json["http"]); - } -# else - m_http.load(doc["http"]); -# endif -} - - -void xmrig::CommonConfig::setFileName(const char *fileName) -{ - m_fileName = fileName; -} - - -bool xmrig::CommonConfig::parseInt(int key, int arg) -{ - switch (key) { - case RetriesKey: /* --retries */ - m_pools.setRetries(arg); - break; - - case RetryPauseKey: /* --retry-pause */ - m_pools.setRetryPause(arg); - break; - - case KeepAliveKey: /* --keepalive */ - m_pools.setKeepAlive(arg); - break; - - case VariantKey: /* --variant */ - m_pools.setVariant(arg); - break; - - case DonateLevelKey: /* --donate-level */ - m_pools.setDonateLevel(arg); - break; - - case ProxyDonateKey: /* --donate-over-proxy */ - m_pools.setProxyDonate(arg); - break; - -# ifdef XMRIG_DEPRECATED - case ApiPort: /* --api-port */ - fputs("option \"--api-port\" deprecated, use \"--http-port\" instead.\n", stderr); - fflush(stdout); - m_http.setPort(arg); - break; -# endif - - case HttpPort: /* --http-port */ - m_http.setPort(arg); - break; - - case PrintTimeKey: /* --print-time */ - if (arg >= 0 && arg <= 3600) { - m_printTime = arg; - } - break; - - default: - break; - } - - return true; -} diff --git a/src/common/config/ConfigLoader.cpp b/src/common/config/ConfigLoader.cpp deleted file mode 100644 index 2b7f50ce..00000000 --- a/src/common/config/ConfigLoader.cpp +++ /dev/null @@ -1,262 +0,0 @@ -/* XMRig - * Copyright 2010 Jeff Garzik - * Copyright 2012-2014 pooler - * Copyright 2014 Lucas Jones - * Copyright 2014-2016 Wolf9466 - * Copyright 2016 Jay D Dee - * Copyright 2017-2018 XMR-Stak , - * Copyright 2018-2019 SChernykh - * Copyright 2016-2019 XMRig , - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - - -#include -#include -#include -#include - - -#include "base/io/Json.h" -#include "base/kernel/interfaces/IConfigListener.h" -#include "base/kernel/Process.h" -#include "common/config/ConfigLoader.h" -#include "common/config/ConfigWatcher.h" -#include "common/interfaces/IConfig.h" -#include "common/Platform.h" -#include "core/config/Config.h" -#include "core/config/ConfigLoader_platform.h" -#include "rapidjson/document.h" -#include "rapidjson/error/en.h" -#include "rapidjson/fwd.h" - - -#ifdef XMRIG_FEATURE_EMBEDDED_CONFIG -# include "core/config/ConfigLoader_default.h" -#endif - - -namespace xmrig { - -ConfigWatcher *ConfigLoader::m_watcher = nullptr; -IConfigListener *ConfigLoader::m_listener = nullptr; - -} // namespace xmrig - - -#ifndef ARRAY_SIZE -# define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0])) -#endif - - -bool xmrig::ConfigLoader::loadFromFile(xmrig::IConfig *config, const char *fileName) -{ - rapidjson::Document doc; - if (!getJSON(fileName, doc)) { - return false; - } - - config->setFileName(fileName); - - return loadFromJSON(config, doc); -} - - -bool xmrig::ConfigLoader::loadFromJSON(xmrig::IConfig *config, const char *json) -{ - using namespace rapidjson; - Document doc; - doc.Parse(json); - - if (doc.HasParseError() || !doc.IsObject()) { - return false; - } - - return loadFromJSON(config, doc); -} - - -bool xmrig::ConfigLoader::loadFromJSON(xmrig::IConfig *config, const rapidjson::Value &json) -{ - for (size_t i = 0; i < ARRAY_SIZE(config_options); i++) { - parseJSON(config, &config_options[i], json); - } - - const rapidjson::Value &api = json["api"]; - if (api.IsObject()) { - for (size_t i = 0; i < ARRAY_SIZE(api_options); i++) { - parseJSON(config, &api_options[i], api); - } - } - - config->parseJSON(json); - - return config->finalize(); -} - - -bool xmrig::ConfigLoader::reload(xmrig::IConfig *oldConfig, const rapidjson::Value &json) -{ - IConfig *config = Config::create(); - if (!loadFromJSON(config, json)) { - delete config; - - return false; - } - - config->setFileName(oldConfig->fileName()); - const bool saved = config->save(); - - if (config->isWatch() && m_watcher && saved) { - delete config; - - return true; - } - - m_listener->onNewConfig(config); - return true; -} - - -bool xmrig::ConfigLoader::watch(IConfig *config) -{ - if (!config->isWatch()) { - return false; - } - - assert(m_watcher == nullptr); - - m_watcher = new ConfigWatcher(config->fileName(), m_listener); - return true; -} - - -xmrig::IConfig *xmrig::ConfigLoader::load(Process *process, IConfigListener *listener) -{ - m_listener = listener; - - IConfig *config = Config::create(); - int key; - int argc = process->arguments().argc(); - char **argv = process->arguments().argv(); - - while (1) { - key = getopt_long(argc, argv, short_options, options, nullptr); - if (key < 0) { - break; - } - - if (!parseArg(config, key, optarg)) { - delete config; - return nullptr; - } - } - - if (optind < argc) { - fprintf(stderr, "%s: unsupported non-option argument '%s'\n", argv[0], argv[optind]); - delete config; - return nullptr; - } - - if (!config->finalize()) { - delete config; - - config = Config::create(); - loadFromFile(config, process->location(Process::ExeLocation, "config.json")); - } - -# ifdef XMRIG_FEATURE_EMBEDDED_CONFIG - if (!config->finalize()) { - delete config; - - config = Config::create(); - loadFromJSON(config, default_config); - } -# endif - - if (!config->finalize()) { - if (!config->algorithm().isValid()) { - fprintf(stderr, "No valid algorithm specified. Exiting.\n"); - } - else { - fprintf(stderr, "No valid configuration found. Exiting.\n"); - } - - delete config; - return nullptr; - } - - return config; -} - - -void xmrig::ConfigLoader::release() -{ - delete m_watcher; - - m_watcher = nullptr; -} - - -bool xmrig::ConfigLoader::getJSON(const char *fileName, rapidjson::Document &doc) -{ - if (Json::get(fileName, doc)) { - return true; - } - - if (doc.HasParseError()) { - printf("%s: \"%s\"\n", fileName, doc.GetErrorOffset(), rapidjson::GetParseError_En(doc.GetParseError())); - } - else { - fprintf(stderr, "unable to open \"%s\".\n", fileName); - } - - return false; -} - - -bool xmrig::ConfigLoader::parseArg(xmrig::IConfig *config, int key, const char *arg) -{ - if (key == IConfig::ConfigKey) { - return loadFromFile(config, arg); - } - - return config->parseString(key, arg); -} - - -void xmrig::ConfigLoader::parseJSON(xmrig::IConfig *config, const struct option *option, const rapidjson::Value &object) -{ - if (!option->name || !object.HasMember(option->name)) { - return; - } - - const rapidjson::Value &value = object[option->name]; - - if (option->has_arg) { - if (value.IsString()) { - config->parseString(option->val, value.GetString()); - } - else if (value.IsInt64()) { - config->parseUint64(option->val, value.GetUint64()); - } - else if (value.IsBool()) { - config->parseBoolean(option->val, value.IsTrue()); - } - } - else if (value.IsBool()) { - config->parseBoolean(option->val, value.IsTrue()); - } -} diff --git a/src/common/crypto/Algorithm.cpp b/src/common/crypto/Algorithm.cpp index f14d034d..d9d3ead9 100644 --- a/src/common/crypto/Algorithm.cpp +++ b/src/common/crypto/Algorithm.cpp @@ -176,7 +176,7 @@ void xmrig::Algorithm::parseAlgorithm(const char *algo) m_algo = INVALID_ALGO; m_variant = VARIANT_AUTO; - assert(algo != nullptr); +// assert(algo != nullptr); if (algo == nullptr || strlen(algo) < 1) { return; } diff --git a/src/core/Controller.cpp b/src/core/Controller.cpp index 32507e90..493b3e11 100644 --- a/src/core/Controller.cpp +++ b/src/core/Controller.cpp @@ -26,89 +26,28 @@ #include -#include "base/io/log/backends/ConsoleLog.h" -#include "base/io/log/backends/FileLog.h" -#include "base/io/log/Log.h" -#include "base/kernel/interfaces/IControllerListener.h" -#include "common/config/ConfigLoader.h" #include "common/cpu/Cpu.h" #include "common/Platform.h" -#include "core/config/Config.h" #include "core/Controller.h" #include "net/Network.h" -#ifdef HAVE_SYSLOG_H -# include "base/io/log/backends/SysLog.h" -#endif - - -#ifdef XMRIG_FEATURE_API -# include "api/Api.h" -#endif - - -class xmrig::ControllerPrivate -{ -public: - inline ControllerPrivate(Process *process) : - api(nullptr), - config(nullptr), - network(nullptr), - process(process) - {} - - - inline ~ControllerPrivate() - { -# ifdef XMRIG_FEATURE_API - delete api; -# endif - - delete network; - delete config; - } - - - Api *api; - Config *config; - Network *network; - Process *process; - std::vector listeners; -}; - - -xmrig::Controller::Controller(Process *process) - : d_ptr(new ControllerPrivate(process)) +xmrig::Controller::Controller(Process *process) : + Base(process), + m_network(nullptr) { } xmrig::Controller::~Controller() { - delete d_ptr; -} - - -xmrig::Api *xmrig::Controller::api() const -{ - assert(d_ptr->api != nullptr); - - return d_ptr->api; + delete m_network; } bool xmrig::Controller::isReady() const { - return d_ptr->config && d_ptr->network; -} - - -xmrig::Config *xmrig::Controller::config() const -{ - assert(d_ptr->config != nullptr); - - return d_ptr->config; + return Base::isReady() && m_network; } @@ -116,98 +55,36 @@ int xmrig::Controller::init() { Cpu::init(); - d_ptr->config = Config::load(d_ptr->process, this); - if (!d_ptr->config) { - return 1; + const int rc = Base::init(); + if (rc != 0) { + return rc; } -# ifdef XMRIG_FEATURE_API - d_ptr->api = new Api(this); -# endif - - Platform::init(config()->userAgent()); - Platform::setProcessPriority(d_ptr->config->priority()); - - if (!config()->isBackground()) { - Log::add(new ConsoleLog()); - } - - if (config()->logFile()) { - Log::add(new FileLog(config()->logFile())); - } - -# ifdef HAVE_SYSLOG_H - if (config()->isSyslog()) { - Log::add(new SysLog()); - } -# endif - - d_ptr->network = new Network(this); + m_network = new Network(this); return 0; } -xmrig::Network *xmrig::Controller::network() const -{ - assert(d_ptr->network != nullptr); - - return d_ptr->network; -} - - -void xmrig::Controller::addListener(IControllerListener *listener) -{ - d_ptr->listeners.push_back(listener); -} - - -void xmrig::Controller::save() -{ - if (!config()) { - return; - } - - if (d_ptr->config->isShouldSave()) { - d_ptr->config->save(); - } - - ConfigLoader::watch(d_ptr->config); -} - - -void xmrig::Controller::onNewConfig(IConfig *config) -{ - Config *previousConfig = d_ptr->config; - d_ptr->config = static_cast(config); - - for (IControllerListener *listener : d_ptr->listeners) { - listener->onConfigChanged(d_ptr->config, previousConfig); - } - - delete previousConfig; -} - - void xmrig::Controller::start() { + Base::start(); + network()->connect(); - -# ifdef XMRIG_FEATURE_API - api()->start(); -# endif - - save(); } void xmrig::Controller::stop() { -# ifdef XMRIG_FEATURE_API - api()->stop(); -# endif + Base::stop(); - ConfigLoader::release(); - - delete d_ptr->network; - d_ptr->network = nullptr; + delete m_network; + m_network = nullptr; +} + + +xmrig::Network *xmrig::Controller::network() const +{ + assert(m_network != nullptr); + + return m_network; } diff --git a/src/core/Controller.h b/src/core/Controller.h index c1ca3da3..10e12147 100644 --- a/src/core/Controller.h +++ b/src/core/Controller.h @@ -26,45 +26,35 @@ #define XMRIG_CONTROLLER_H -#include "base/kernel/interfaces/IConfigListener.h" +#include "base/kernel/Base.h" namespace xmrig { -class Api; -class Config; -class ControllerPrivate; -class IControllerListener; class Network; class Process; -class Controller : public IConfigListener +class Controller : public Base { public: Controller(Process *process); ~Controller() override; - Api *api() const; - bool isReady() const; - Config *config() const; - int init(); - Network *network() const; - void addListener(IControllerListener *listener); - void save(); - void start(); - void stop(); + bool isReady() const override; + int init() override; + void start() override; + void stop() override; -protected: - void onNewConfig(IConfig *config) override; + Network *network() const; private: - ControllerPrivate *d_ptr; + Network *m_network; }; -} /* namespace xmrig */ +} // namespace xmrig #endif /* XMRIG_CONTROLLER_H */ diff --git a/src/core/config/Config.cpp b/src/core/config/Config.cpp index 2b706d74..1249b8ba 100644 --- a/src/core/config/Config.cpp +++ b/src/core/config/Config.cpp @@ -28,7 +28,7 @@ #include "base/io/log/Log.h" -#include "common/config/ConfigLoader.h" +#include "base/kernel/interfaces/IJsonReader.h" #include "common/cpu/Cpu.h" #include "core/config/Config.h" #include "crypto/Asm.h" @@ -42,7 +42,7 @@ static char affinity_tmp[20] = { 0 }; -xmrig::Config::Config() : xmrig::CommonConfig(), +xmrig::Config::Config() : m_aesMode(AES_AUTO), m_algoVariant(AV_AUTO), m_assembly(ASM_AUTO), @@ -55,9 +55,23 @@ xmrig::Config::Config() : xmrig::CommonConfig(), } -bool xmrig::Config::reload(const rapidjson::Value &json) +bool xmrig::Config::read(const IJsonReader &reader, const char *fileName) { - return xmrig::ConfigLoader::reload(this, json); + if (!BaseConfig::read(reader, fileName)) { + return false; + } + + m_hugePages = reader.getBool("huge-pages", true); + m_safe = reader.getBool("safe"); + + setAesMode(reader.getValue("hw-aes")); + setAlgoVariant(reader.getInt("av")); + setAssembly(reader.getValue("asm")); + setMaxCpuUsage(reader.getInt("max-cpu-usage", 100)); + setPriority(reader.getInt("cpu-priority", -1)); + setThreads(reader.getValue("threads")); + + return finalize(); } @@ -126,22 +140,8 @@ void xmrig::Config::getJSON(rapidjson::Document &doc) const } -xmrig::Config *xmrig::Config::load(Process *process, IConfigListener *listener) -{ - return static_cast(ConfigLoader::load(process, listener)); -} - - bool xmrig::Config::finalize() { - if (m_state != NoneState) { - return CommonConfig::finalize(); - } - - if (!CommonConfig::finalize()) { - return false; - } - if (!m_threads.cpu.empty()) { m_threads.mode = Advanced; const bool softAES = (m_aesMode == AES_AUTO ? (Cpu::info()->hasAES() ? AES_HW : AES_SOFT) : m_aesMode) == AES_SOFT; @@ -153,7 +153,7 @@ bool xmrig::Config::finalize() return true; } - const AlgoVariant av = getAlgoVariant(); + const AlgoVariant av = getAlgoVariant(); m_threads.mode = m_threads.count ? Simple : Automatic; const size_t size = CpuThread::multiway(av) * cn_select_memory(m_algorithm.algo()) / 1024; @@ -173,117 +173,54 @@ bool xmrig::Config::finalize() } m_shouldSave = m_threads.mode == Automatic; - return true; -} - - -bool xmrig::Config::parseBoolean(int key, bool enable) -{ - if (!CommonConfig::parseBoolean(key, enable)) { - return false; - } - - switch (key) { - case SafeKey: /* --safe */ - m_safe = enable; - break; - - case HugePagesKey: /* --no-huge-pages */ - m_hugePages = enable; - break; - - case HardwareAESKey: /* hw-aes config only */ - m_aesMode = enable ? AES_HW : AES_SOFT; - break; - -# ifndef XMRIG_NO_ASM - case AssemblyKey: - m_assembly = Asm::parse(enable); - break; -# endif - - default: - break; - } return true; } -bool xmrig::Config::parseString(int key, const char *arg) +void xmrig::Config::setAesMode(const rapidjson::Value &aesMode) { - if (!CommonConfig::parseString(key, arg)) { - return false; + if (aesMode.IsBool()) { + m_aesMode = aesMode.GetBool() ? AES_HW : AES_SOFT; } - - switch (key) { - case AVKey: /* --av */ - case MaxCPUUsageKey: /* --max-cpu-usage */ - case CPUPriorityKey: /* --cpu-priority */ - return parseUint64(key, strtol(arg, nullptr, 10)); - - case SafeKey: /* --safe */ - return parseBoolean(key, true); - - case HugePagesKey: /* --no-huge-pages */ - return parseBoolean(key, false); - - case ThreadsKey: /* --threads */ - if (strncmp(arg, "all", 3) == 0) { - m_threads.count = Cpu::info()->threads(); - return true; - } - - return parseUint64(key, strtol(arg, nullptr, 10)); - - case CPUAffinityKey: /* --cpu-affinity */ - { - const char *p = strstr(arg, "0x"); - return parseUint64(key, p ? strtoull(p, nullptr, 16) : strtoull(arg, nullptr, 10)); - } - -# ifndef XMRIG_NO_ASM - case AssemblyKey: /* --asm */ - m_assembly = Asm::parse(arg); - break; -# endif - - default: - break; - } - - return true; } -bool xmrig::Config::parseUint64(int key, uint64_t arg) +void xmrig::Config::setAlgoVariant(int av) { - if (!CommonConfig::parseUint64(key, arg)) { - return false; + if (av >= AV_AUTO && av < AV_MAX) { + m_algoVariant = static_cast(av); } - - switch (key) { - case CPUAffinityKey: /* --cpu-affinity */ - if (arg) { - m_threads.mask = static_cast(arg); - } - break; - - default: - return parseInt(key, static_cast(arg)); - } - - return true; } -void xmrig::Config::parseJSON(const rapidjson::Value &json) +void xmrig::Config::setAssembly(const rapidjson::Value &assembly) { - CommonConfig::parseJSON(json); + m_assembly = Asm::parse(assembly); +} - const rapidjson::Value &threads = json["threads"]; +void xmrig::Config::setMaxCpuUsage(int max) +{ + if (max > 0 && max <= 100) { + m_maxCpuUsage = max; + } +} + + +void xmrig::Config::setPriority(int priority) +{ + if (priority >= 0 && priority <= 5) { + m_priority = priority; + } +} + + +void xmrig::Config::setThreads(const rapidjson::Value &threads) +{ if (threads.IsArray()) { + m_threads.cpu.clear(); + for (const rapidjson::Value &value : threads.GetArray()) { if (!value.IsObject()) { continue; @@ -298,41 +235,12 @@ void xmrig::Config::parseJSON(const rapidjson::Value &json) } } } -} - - -bool xmrig::Config::parseInt(int key, int arg) -{ - switch (key) { - case ThreadsKey: /* --threads */ - if (arg >= 0 && arg < 1024) { - m_threads.count = arg; + else if (threads.IsUint()) { + const unsigned count = threads.GetUint(); + if (count < 1024) { + m_threads.count = count; } - break; - - case AVKey: /* --av */ - if (arg >= AV_AUTO && arg < AV_MAX) { - m_algoVariant = static_cast(arg); - } - break; - - case MaxCPUUsageKey: /* --max-cpu-usage */ - if (m_maxCpuUsage > 0 && arg <= 100) { - m_maxCpuUsage = arg; - } - break; - - case CPUPriorityKey: /* --cpu-priority */ - if (arg >= 0 && arg <= 5) { - m_priority = arg; - } - break; - - default: - break; } - - return true; } diff --git a/src/core/config/Config.h b/src/core/config/Config.h index 2a8ca11d..19c70cf1 100644 --- a/src/core/config/Config.h +++ b/src/core/config/Config.h @@ -29,7 +29,7 @@ #include -#include "common/config/CommonConfig.h" +#include "base/kernel/config/BaseConfig.h" #include "common/xmrig.h" #include "rapidjson/fwd.h" #include "workers/CpuThread.h" @@ -55,7 +55,7 @@ class Process; * api/worker-id * pools/ */ -class Config : public CommonConfig +class Config : public BaseConfig { public: enum ThreadsMode { @@ -67,8 +67,7 @@ public: Config(); - bool reload(const rapidjson::Value &json); - + bool read(const IJsonReader &reader, const char *fileName) override; void getJSON(rapidjson::Document &doc) const override; inline AesMode aesMode() const { return m_aesMode; } @@ -80,20 +79,16 @@ public: inline int priority() const { return m_priority; } inline int threadsCount() const { return static_cast(m_threads.list.size()); } inline int64_t affinity() const { return m_threads.mask; } - inline static IConfig *create() { return new Config(); } inline ThreadsMode threadsMode() const { return m_threads.mode; } - static Config *load(Process *process, IConfigListener *listener); - -protected: - bool finalize() override; - bool parseBoolean(int key, bool enable) override; - bool parseString(int key, const char *arg) override; - bool parseUint64(int key, uint64_t arg) override; - void parseJSON(const rapidjson::Value &json) override; - private: - bool parseInt(int key, int arg); + bool finalize(); + void setAesMode(const rapidjson::Value &aesMode); + void setAlgoVariant(int av); + void setAssembly(const rapidjson::Value &assembly); + void setMaxCpuUsage(int max); + void setPriority(int priority); + void setThreads(const rapidjson::Value &threads); AlgoVariant getAlgoVariant() const; # ifndef XMRIG_NO_AEON diff --git a/src/core/config/ConfigTransform.cpp b/src/core/config/ConfigTransform.cpp new file mode 100644 index 00000000..7c9afc17 --- /dev/null +++ b/src/core/config/ConfigTransform.cpp @@ -0,0 +1,106 @@ +/* XMRig + * Copyright 2010 Jeff Garzik + * Copyright 2012-2014 pooler + * Copyright 2014 Lucas Jones + * Copyright 2014-2016 Wolf9466 + * Copyright 2016 Jay D Dee + * Copyright 2017-2018 XMR-Stak , + * Copyright 2018-2019 SChernykh + * Copyright 2016-2019 XMRig , + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + + +#include "core/config/ConfigTransform.h" +#include "base/kernel/interfaces/IConfig.h" + + +xmrig::ConfigTransform::ConfigTransform() +{ + +} + + +void xmrig::ConfigTransform::transform(rapidjson::Document &doc, int key, const char *arg) +{ + BaseTransform::transform(doc, key, arg); + + switch (key) { + case IConfig::AVKey: /* --av */ + case IConfig::MaxCPUUsageKey: /* --max-cpu-usage */ + case IConfig::CPUPriorityKey: /* --cpu-priority */ + case IConfig::ThreadsKey: /* --threads */ + return transformUint64(doc, key, static_cast(strtol(arg, nullptr, 10))); + + case IConfig::SafeKey: /* --safe */ + return transformBoolean(doc, key, true); + + case IConfig::HugePagesKey: /* --no-huge-pages */ + return transformBoolean(doc, key, false); + + case IConfig::CPUAffinityKey: /* --cpu-affinity */ + { + const char *p = strstr(arg, "0x"); + return transformUint64(doc, key, p ? strtoull(p, nullptr, 16) : strtoull(arg, nullptr, 10)); + } + +# ifndef XMRIG_NO_ASM + case IConfig::AssemblyKey: /* --asm */ + return set(doc, "asm", arg); +# endif + + default: + break; + } +} + + +void xmrig::ConfigTransform::transformBoolean(rapidjson::Document &doc, int key, bool enable) +{ + switch (key) { + case IConfig::SafeKey: /* --safe */ + return set(doc, "safe", enable); + + case IConfig::HugePagesKey: /* --no-huge-pages */ + return set(doc, "huge-pages", enable); + + default: + break; + } +} + + +void xmrig::ConfigTransform::transformUint64(rapidjson::Document &doc, int key, uint64_t arg) +{ + switch (key) { + case IConfig::CPUAffinityKey: /* --cpu-affinity */ + return set(doc, "cpu-affinity", static_cast(arg)); + + case IConfig::ThreadsKey: /* --threads */ + return set(doc, "threads", arg); + + case IConfig::AVKey: /* --av */ + return set(doc, "av", arg); + + case IConfig::MaxCPUUsageKey: /* --max-cpu-usage */ + return set(doc, "max-cpu-usage", arg); + + case IConfig::CPUPriorityKey: /* --cpu-priority */ + return set(doc, "cpu-priority", arg); + + default: + break; + } +} diff --git a/src/core/config/ConfigTransform.h b/src/core/config/ConfigTransform.h new file mode 100644 index 00000000..2d291d8f --- /dev/null +++ b/src/core/config/ConfigTransform.h @@ -0,0 +1,51 @@ +/* XMRig + * Copyright 2010 Jeff Garzik + * Copyright 2012-2014 pooler + * Copyright 2014 Lucas Jones + * Copyright 2014-2016 Wolf9466 + * Copyright 2016 Jay D Dee + * Copyright 2017-2018 XMR-Stak , + * Copyright 2016-2018 XMRig , + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef XMRIG_CONFIGTRANSFORM_H +#define XMRIG_CONFIGTRANSFORM_H + + +#include "base/kernel/config/BaseTransform.h" + + +namespace xmrig { + + +class ConfigTransform : public BaseTransform +{ +public: + ConfigTransform(); + +protected: + void transform(rapidjson::Document &doc, int key, const char *arg) override; + +private: + void transformBoolean(rapidjson::Document &doc, int key, bool enable); + void transformUint64(rapidjson::Document &doc, int key, uint64_t arg); +}; + + +} // namespace xmrig + + +#endif /* XMRIG_CONFIGTRANSFORM_H */ diff --git a/src/core/config/ConfigLoader_default.h b/src/core/config/Config_default.h similarity index 94% rename from src/core/config/ConfigLoader_default.h rename to src/core/config/Config_default.h index 9ef81fd2..3462ad19 100644 --- a/src/core/config/ConfigLoader_default.h +++ b/src/core/config/Config_default.h @@ -22,8 +22,8 @@ * along with this program. If not, see . */ -#ifndef XMRIG_CONFIGLOADER_DEFAULT_H -#define XMRIG_CONFIGLOADER_DEFAULT_H +#ifndef XMRIG_CONFIG_DEFAULT_H +#define XMRIG_CONFIG_DEFAULT_H namespace xmrig { @@ -85,6 +85,7 @@ R"===( #endif -} /* namespace xmrig */ +} // namespace xmrig -#endif /* XMRIG_CONFIGLOADER_DEFAULT_H */ + +#endif /* XMRIG_CONFIG_DEFAULT_H */ diff --git a/src/core/config/ConfigLoader_platform.h b/src/core/config/Config_platform.h similarity index 88% rename from src/core/config/ConfigLoader_platform.h rename to src/core/config/Config_platform.h index 5026888d..8ece4105 100644 --- a/src/core/config/ConfigLoader_platform.h +++ b/src/core/config/Config_platform.h @@ -22,8 +22,8 @@ * along with this program. If not, see . */ -#ifndef XMRIG_CONFIGLOADER_PLATFORM_H -#define XMRIG_CONFIGLOADER_PLATFORM_H +#ifndef XMRIG_CONFIG_PLATFORM_H +#define XMRIG_CONFIG_PLATFORM_H #ifdef _MSC_VER @@ -33,17 +33,17 @@ #endif -#include "common/interfaces/IConfig.h" +#include "base/kernel/interfaces/IConfig.h" #include "version.h" namespace xmrig { -static char const short_options[] = "a:c:kBp:Px:r:R:s:t:T:o:u:O:v:l:S"; +static const char short_options[] = "a:c:kBp:Px:r:R:s:t:T:o:u:O:v:l:S"; -static struct option const options[] = { +static const option options[] = { { "algo", 1, nullptr, IConfig::AlgorithmKey }, { "api-worker-id", 1, nullptr, IConfig::ApiWorkerIdKey }, { "api-id", 1, nullptr, IConfig::ApiIdKey }, @@ -65,7 +65,6 @@ static struct option const options[] = { { "max-cpu-usage", 1, nullptr, IConfig::MaxCPUUsageKey }, { "nicehash", 0, nullptr, IConfig::NicehashKey }, { "no-color", 0, nullptr, IConfig::ColorKey }, - { "no-watch", 0, nullptr, IConfig::WatchKey }, { "no-huge-pages", 0, nullptr, IConfig::HugePagesKey }, { "variant", 1, nullptr, IConfig::VariantKey }, { "pass", 1, nullptr, IConfig::PasswordKey }, @@ -115,21 +114,12 @@ static struct option const config_options[] = { { "syslog", 0, nullptr, IConfig::SyslogKey }, { "threads", 1, nullptr, IConfig::ThreadsKey }, { "user-agent", 1, nullptr, IConfig::UserAgentKey }, - { "watch", 0, nullptr, IConfig::WatchKey }, - { "hw-aes", 0, nullptr, IConfig::HardwareAESKey }, { "asm", 1, nullptr, IConfig::AssemblyKey }, - { "autosave", 0, nullptr, IConfig::AutoSaveKey }, { nullptr, 0, nullptr, 0 } }; -static struct option const api_options[] = { - { "worker-id", 1, nullptr, IConfig::ApiWorkerIdKey }, - { "id", 1, nullptr, IConfig::ApiIdKey }, - { nullptr, 0, nullptr, 0 } -}; +} // namespace xmrig -} /* namespace xmrig */ - -#endif /* XMRIG_CONFIGLOADER_PLATFORM_H */ +#endif /* XMRIG_CONFIG_PLATFORM_H */ diff --git a/src/net/Network.h b/src/net/Network.h index 09e7c815..1b8f4934 100644 --- a/src/net/Network.h +++ b/src/net/Network.h @@ -30,7 +30,7 @@ #include "api/interfaces/IApiListener.h" -#include "base/kernel/interfaces/IControllerListener.h" +#include "base/kernel/interfaces/IBaseListener.h" #include "base/kernel/interfaces/IStrategyListener.h" #include "base/kernel/interfaces/ITimerListener.h" #include "interfaces/IJobResultListener.h" @@ -45,7 +45,7 @@ class Controller; class IStrategy; -class Network : public IJobResultListener, public IStrategyListener, public IControllerListener, public ITimerListener, public IApiListener +class Network : public IJobResultListener, public IStrategyListener, public IBaseListener, public ITimerListener, public IApiListener { public: Network(Controller *controller); From 1774b423456838a6b5dafb0d3cb001080d0bc0b9 Mon Sep 17 00:00:00 2001 From: XMRig Date: Sat, 6 Apr 2019 02:10:08 +0700 Subject: [PATCH 066/116] Fix "colors" option. --- src/base/kernel/config/BaseConfig.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/base/kernel/config/BaseConfig.cpp b/src/base/kernel/config/BaseConfig.cpp index 7284c263..e5fa7293 100644 --- a/src/base/kernel/config/BaseConfig.cpp +++ b/src/base/kernel/config/BaseConfig.cpp @@ -134,6 +134,7 @@ bool xmrig::BaseConfig::read(const IJsonReader &reader, const char *fileName) m_dryRun = reader.getBool("dry-run", m_dryRun); m_syslog = reader.getBool("syslog", m_syslog); m_watch = reader.getBool("watch", m_watch); + Log::colors = reader.getBool("colors", Log::colors); m_logFile = reader.getString("log-file"); m_userAgent = reader.getString("user-agent"); From 5d9648956bfcb3b1d2cb1edb099bb2dd0ee55d6b Mon Sep 17 00:00:00 2001 From: XMRig Date: Sat, 6 Apr 2019 02:11:02 +0700 Subject: [PATCH 067/116] Add milliseconds to log. --- src/base/io/log/Log.cpp | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/base/io/log/Log.cpp b/src/base/io/log/Log.cpp index fe5aa205..22972a7e 100644 --- a/src/base/io/log/Log.cpp +++ b/src/base/io/log/Log.cpp @@ -40,6 +40,7 @@ #include "base/io/log/Log.h" #include "base/kernel/interfaces/ILogBackend.h" +#include "base/tools/Chrono.h" namespace xmrig { @@ -134,7 +135,8 @@ private: return; } - time_t now = time(nullptr); + const uint64_t ms = Chrono::currentMSecsSinceEpoch(); + time_t now = ms / 1000; tm stime; # ifdef _WIN32 @@ -143,13 +145,14 @@ private: localtime_r(&now, &stime); # endif - const int rc = snprintf(m_buf, sizeof(m_buf) - 1, "[%d-%02d-%02d %02d:%02d:%02d] ", + const int rc = snprintf(m_buf, sizeof(m_buf) - 1, "[%d-%02d-%02d %02d:%02d:%02d" BLACK_BOLD(".%03d") "] ", stime.tm_year + 1900, stime.tm_mon + 1, stime.tm_mday, stime.tm_hour, stime.tm_min, - stime.tm_sec + stime.tm_sec, + static_cast(ms % 1000) ); if (rc > 0) { From 09df8c38462f02cd8b397c609641b05c824e60d4 Mon Sep 17 00:00:00 2001 From: XMRig Date: Sat, 6 Apr 2019 18:32:24 +0700 Subject: [PATCH 068/116] Sync changes. --- CMakeLists.txt | 4 +- src/base/io/JsonChain.cpp | 12 +++++ src/base/io/JsonChain.h | 2 + src/base/kernel/Base.cpp | 9 +++- src/base/kernel/config/BaseTransform.cpp | 62 ++++++++++++------------ src/base/kernel/interfaces/IConfig.h | 1 - src/core/Controller.h | 1 - src/core/config/ConfigTransform.cpp | 57 ---------------------- 8 files changed, 55 insertions(+), 93 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 550de480..2bc90d43 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -31,10 +31,10 @@ set(HEADERS src/common/Platform.h src/common/utils/mm_malloc.h src/common/xmrig.h - src/core/config/Config.h - src/core/config/ConfigTransform.h src/core/config/Config_default.h src/core/config/Config_platform.h + src/core/config/Config.h + src/core/config/ConfigTransform.h src/core/config/usage.h src/core/Controller.h src/interfaces/IJobResultListener.h diff --git a/src/base/io/JsonChain.cpp b/src/base/io/JsonChain.cpp index d65427cc..4dd75f0b 100644 --- a/src/base/io/JsonChain.cpp +++ b/src/base/io/JsonChain.cpp @@ -84,6 +84,18 @@ bool xmrig::JsonChain::addRaw(const char *json) } +void xmrig::JsonChain::dump(const char *fileName) +{ + rapidjson::Document doc(rapidjson::kArrayType); + + for (rapidjson::Document &value : m_chain) { + doc.PushBack(value, doc.GetAllocator()); + } + + Json::save(fileName, doc); +} + + bool xmrig::JsonChain::getBool(const char *key, bool defaultValue) const { for (auto it = m_chain.rbegin(); it != m_chain.rend(); ++it) { diff --git a/src/base/io/JsonChain.h b/src/base/io/JsonChain.h index dab01218..275f789e 100644 --- a/src/base/io/JsonChain.h +++ b/src/base/io/JsonChain.h @@ -46,6 +46,8 @@ public: bool addFile(const char *fileName); bool addRaw(const char *json); + void dump(const char *fileName); + inline const String &fileName() const { return m_fileName; } inline size_t size() const { return m_chain.size(); } diff --git a/src/base/kernel/Base.cpp b/src/base/kernel/Base.cpp index 84152441..157363f0 100644 --- a/src/base/kernel/Base.cpp +++ b/src/base/kernel/Base.cpp @@ -37,7 +37,6 @@ #include "base/kernel/interfaces/IBaseListener.h" #include "base/kernel/Process.h" #include "common/Platform.h" -#include "core/config/Config_default.h" #include "core/config/Config.h" #include "core/config/ConfigTransform.h" @@ -52,6 +51,11 @@ #endif +#ifdef XMRIG_FEATURE_EMBEDDED_CONFIG +# include "core/config/Config_default.h" +#endif + + class xmrig::BasePrivate { public: @@ -166,7 +170,10 @@ int xmrig::Base::init() # endif Platform::init(config()->userAgent()); + +# ifndef XMRIG_PROXY_PROJECT Platform::setProcessPriority(config()->priority()); +# endif if (!config()->isBackground()) { Log::add(new ConsoleLog()); diff --git a/src/base/kernel/config/BaseTransform.cpp b/src/base/kernel/config/BaseTransform.cpp index c676330e..c794d071 100644 --- a/src/base/kernel/config/BaseTransform.cpp +++ b/src/base/kernel/config/BaseTransform.cpp @@ -92,53 +92,53 @@ void xmrig::BaseTransform::transform(rapidjson::Document &doc, int key, const ch { switch (key) { case IConfig::AlgorithmKey: /* --algo */ - return set(doc, "algo", arg); + return set(doc, "algo", arg); case IConfig::UserpassKey: /* --userpass */ - return add(doc, kPools, "userpass", arg); + return add(doc, kPools, "userpass", arg); case IConfig::UrlKey: /* --url */ - return add(doc, kPools, "url", arg, true); + return add(doc, kPools, "url", arg, true); case IConfig::UserKey: /* --user */ - return add(doc, kPools, "user", arg); + return add(doc, kPools, "user", arg); case IConfig::PasswordKey: /* --pass */ - return add(doc, kPools, "pass", arg); + return add(doc, kPools, "pass", arg); case IConfig::RigIdKey: /* --rig-id */ - return add(doc, kPools, "rig-id", arg); + return add(doc, kPools, "rig-id", arg); case IConfig::FingerprintKey: /* --tls-fingerprint */ - return add(doc, kPools, "tls-fingerprint", arg); + return add(doc, kPools, "tls-fingerprint", arg); case IConfig::VariantKey: /* --variant */ - return add(doc, kPools, "variant", arg); + return add(doc, kPools, "variant", arg); case IConfig::LogFileKey: /* --log-file */ - return set(doc, "log-file", arg); + return set(doc, "log-file", arg); # ifdef XMRIG_DEPRECATED case IConfig::ApiAccessTokenKey: /* --api-access-token */ fputs("option \"--api-access-token\" deprecated, use \"--http-access-token\" instead.\n", stderr); fflush(stdout); - return set(doc, kHttp, "access-token", arg); + return set(doc, kHttp, "access-token", arg); # endif case IConfig::HttpAccessTokenKey: /* --http-access-token */ - return set(doc, kHttp, "access-token", arg); + return set(doc, kHttp, "access-token", arg); case IConfig::HttpHostKey: /* --http-host */ - return set(doc, kHttp, "host", arg); + return set(doc, kHttp, "host", arg); case IConfig::ApiWorkerIdKey: /* --api-worker-id */ - return set(doc, kApi, "worker-id", arg); + return set(doc, kApi, "worker-id", arg); case IConfig::ApiIdKey: /* --api-id */ - return set(doc, kApi, "id", arg); + return set(doc, kApi, "id", arg); case IConfig::UserAgentKey: /* --user-agent */ - return set(doc, "user-agent", arg); + return set(doc, "user-agent", arg); case IConfig::RetriesKey: /* --retries */ case IConfig::RetryPauseKey: /* --retry-pause */ @@ -177,16 +177,16 @@ void xmrig::BaseTransform::transformBoolean(rapidjson::Document &doc, int key, b { switch (key) { case IConfig::BackgroundKey: /* --background */ - return set(doc, "background", enable); + return set(doc, "background", enable); case IConfig::SyslogKey: /* --syslog */ - return set(doc, "syslog", enable); + return set(doc, "syslog", enable); case IConfig::KeepAliveKey: /* --keepalive */ - return add(doc, kPools, "keepalive", enable); + return add(doc, kPools, "keepalive", enable); case IConfig::TlsKey: /* --tls */ - return add(doc, kPools, "tls", enable); + return add(doc, kPools, "tls", enable); # ifndef XMRIG_PROXY_PROJECT case IConfig::NicehashKey: /* --nicehash */ @@ -194,7 +194,7 @@ void xmrig::BaseTransform::transformBoolean(rapidjson::Document &doc, int key, b # endif case IConfig::ColorKey: /* --no-color */ - return set(doc, "colors", enable); + return set(doc, "colors", enable); # ifdef XMRIG_DEPRECATED case IConfig::ApiIPv6Key: /* --api-ipv6 */ @@ -203,17 +203,17 @@ void xmrig::BaseTransform::transformBoolean(rapidjson::Document &doc, int key, b case IConfig::ApiRestrictedKey: /* --api-no-restricted */ fputs("option \"--api-no-restricted\" deprecated, use \"--http-no-restricted\" instead.\n", stderr); fflush(stdout); - return set(doc, kHttp, "restricted", enable); + return set(doc, kHttp, "restricted", enable); # endif case IConfig::HttpRestrictedKey: /* --http-no-restricted */ - return set(doc, kHttp, "restricted", enable); + return set(doc, kHttp, "restricted", enable); case IConfig::HttpEnabledKey: /* --http-enabled */ - return set(doc, kHttp, "enabled", enable); + return set(doc, kHttp, "enabled", enable); case IConfig::DryRunKey: /* --dry-run */ - return set(doc, "dry-run", enable); + return set(doc, "dry-run", enable); default: break; @@ -225,29 +225,29 @@ void xmrig::BaseTransform::transformUint64(rapidjson::Document &doc, int key, ui { switch (key) { case IConfig::RetriesKey: /* --retries */ - return set(doc, "retries", arg); + return set(doc, "retries", arg); case IConfig::RetryPauseKey: /* --retry-pause */ - return set(doc, "retry-pause", arg); + return set(doc, "retry-pause", arg); case IConfig::DonateLevelKey: /* --donate-level */ - return set(doc, "donate-level", arg); + return set(doc, "donate-level", arg); case IConfig::ProxyDonateKey: /* --donate-over-proxy */ - return set(doc, "donate-over-proxy", arg); + return set(doc, "donate-over-proxy", arg); # ifdef XMRIG_DEPRECATED case IConfig::ApiPort: /* --api-port */ fputs("option \"--api-port\" deprecated, use \"--http-port\" instead.\n", stderr); fflush(stdout); - return set(doc, kHttp, "port", arg); + return set(doc, kHttp, "port", arg); # endif case IConfig::HttpPort: /* --http-port */ - return set(doc, kHttp, "port", arg); + return set(doc, kHttp, "port", arg); case IConfig::PrintTimeKey: /* --print-time */ - return set(doc, "print-time", arg); + return set(doc, "print-time", arg); default: break; diff --git a/src/base/kernel/interfaces/IConfig.h b/src/base/kernel/interfaces/IConfig.h index 44628129..d592c4cb 100644 --- a/src/base/kernel/interfaces/IConfig.h +++ b/src/base/kernel/interfaces/IConfig.h @@ -110,7 +110,6 @@ public: // xmrig-proxy AccessLogFileKey = 'A', BindKey = 'b', - CoinKey = 1104, CustomDiffKey = 1102, DebugKey = 1101, ModeKey = 'm', diff --git a/src/core/Controller.h b/src/core/Controller.h index 10e12147..02f9ca92 100644 --- a/src/core/Controller.h +++ b/src/core/Controller.h @@ -33,7 +33,6 @@ namespace xmrig { class Network; -class Process; class Controller : public Base diff --git a/src/core/config/ConfigTransform.cpp b/src/core/config/ConfigTransform.cpp index 7c9afc17..7d313726 100644 --- a/src/core/config/ConfigTransform.cpp +++ b/src/core/config/ConfigTransform.cpp @@ -36,71 +36,14 @@ xmrig::ConfigTransform::ConfigTransform() void xmrig::ConfigTransform::transform(rapidjson::Document &doc, int key, const char *arg) { BaseTransform::transform(doc, key, arg); - - switch (key) { - case IConfig::AVKey: /* --av */ - case IConfig::MaxCPUUsageKey: /* --max-cpu-usage */ - case IConfig::CPUPriorityKey: /* --cpu-priority */ - case IConfig::ThreadsKey: /* --threads */ - return transformUint64(doc, key, static_cast(strtol(arg, nullptr, 10))); - - case IConfig::SafeKey: /* --safe */ - return transformBoolean(doc, key, true); - - case IConfig::HugePagesKey: /* --no-huge-pages */ - return transformBoolean(doc, key, false); - - case IConfig::CPUAffinityKey: /* --cpu-affinity */ - { - const char *p = strstr(arg, "0x"); - return transformUint64(doc, key, p ? strtoull(p, nullptr, 16) : strtoull(arg, nullptr, 10)); - } - -# ifndef XMRIG_NO_ASM - case IConfig::AssemblyKey: /* --asm */ - return set(doc, "asm", arg); -# endif - - default: - break; - } } void xmrig::ConfigTransform::transformBoolean(rapidjson::Document &doc, int key, bool enable) { - switch (key) { - case IConfig::SafeKey: /* --safe */ - return set(doc, "safe", enable); - - case IConfig::HugePagesKey: /* --no-huge-pages */ - return set(doc, "huge-pages", enable); - - default: - break; - } } void xmrig::ConfigTransform::transformUint64(rapidjson::Document &doc, int key, uint64_t arg) { - switch (key) { - case IConfig::CPUAffinityKey: /* --cpu-affinity */ - return set(doc, "cpu-affinity", static_cast(arg)); - - case IConfig::ThreadsKey: /* --threads */ - return set(doc, "threads", arg); - - case IConfig::AVKey: /* --av */ - return set(doc, "av", arg); - - case IConfig::MaxCPUUsageKey: /* --max-cpu-usage */ - return set(doc, "max-cpu-usage", arg); - - case IConfig::CPUPriorityKey: /* --cpu-priority */ - return set(doc, "cpu-priority", arg); - - default: - break; - } } From 466aad8543d810edf3817a99ac87f95660b98a46 Mon Sep 17 00:00:00 2001 From: XMRig Date: Sat, 6 Apr 2019 20:07:20 +0700 Subject: [PATCH 069/116] Fix build without ASM. --- src/core/config/Config.cpp | 19 ++++++++++++------- src/core/config/Config.h | 5 ++++- 2 files changed, 16 insertions(+), 8 deletions(-) diff --git a/src/core/config/Config.cpp b/src/core/config/Config.cpp index 1249b8ba..f49ba05d 100644 --- a/src/core/config/Config.cpp +++ b/src/core/config/Config.cpp @@ -66,11 +66,14 @@ bool xmrig::Config::read(const IJsonReader &reader, const char *fileName) setAesMode(reader.getValue("hw-aes")); setAlgoVariant(reader.getInt("av")); - setAssembly(reader.getValue("asm")); setMaxCpuUsage(reader.getInt("max-cpu-usage", 100)); setPriority(reader.getInt("cpu-priority", -1)); setThreads(reader.getValue("threads")); +# ifndef XMRIG_NO_ASM + setAssembly(reader.getValue("asm")); +# endif + return finalize(); } @@ -194,12 +197,6 @@ void xmrig::Config::setAlgoVariant(int av) } -void xmrig::Config::setAssembly(const rapidjson::Value &assembly) -{ - m_assembly = Asm::parse(assembly); -} - - void xmrig::Config::setMaxCpuUsage(int max) { if (max > 0 && max <= 100) { @@ -278,3 +275,11 @@ xmrig::AlgoVariant xmrig::Config::getAlgoVariantLite() const return m_algoVariant; } #endif + + +#ifndef XMRIG_NO_ASM +void xmrig::Config::setAssembly(const rapidjson::Value &assembly) +{ + m_assembly = Asm::parse(assembly); +} +#endif diff --git a/src/core/config/Config.h b/src/core/config/Config.h index 19c70cf1..861840c7 100644 --- a/src/core/config/Config.h +++ b/src/core/config/Config.h @@ -85,7 +85,6 @@ private: bool finalize(); void setAesMode(const rapidjson::Value &aesMode); void setAlgoVariant(int av); - void setAssembly(const rapidjson::Value &assembly); void setMaxCpuUsage(int max); void setPriority(int priority); void setThreads(const rapidjson::Value &threads); @@ -95,6 +94,10 @@ private: AlgoVariant getAlgoVariantLite() const; # endif +# ifndef XMRIG_NO_ASM + void setAssembly(const rapidjson::Value &assembly); +# endif + struct Threads { From 9561570c50179cc08ca8c4944ae25c8db0fbc964 Mon Sep 17 00:00:00 2001 From: XMRig Date: Sat, 6 Apr 2019 21:10:26 +0700 Subject: [PATCH 070/116] Fix build on FreeBSD. --- src/base/kernel/config/BaseTransform.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/base/kernel/config/BaseTransform.cpp b/src/base/kernel/config/BaseTransform.cpp index c794d071..5a05111b 100644 --- a/src/base/kernel/config/BaseTransform.cpp +++ b/src/base/kernel/config/BaseTransform.cpp @@ -23,6 +23,9 @@ */ +#include + + #ifdef _MSC_VER # include "getopt/getopt.h" #else From d6da0652ceae8aa02284ab4d5d7e91153b244350 Mon Sep 17 00:00:00 2001 From: XMRig Date: Sun, 7 Apr 2019 21:31:32 +0700 Subject: [PATCH 071/116] Removed unused setters in Pool class. --- src/base/net/stratum/Pool.cpp | 54 ++++++++++++++++------------------- src/base/net/stratum/Pool.h | 31 ++++++++++---------- src/base/tools/String.cpp | 14 +++++++++ src/base/tools/String.h | 1 + 4 files changed, 55 insertions(+), 45 deletions(-) diff --git a/src/base/net/stratum/Pool.cpp b/src/base/net/stratum/Pool.cpp index 2c48ab0b..c618707a 100644 --- a/src/base/net/stratum/Pool.cpp +++ b/src/base/net/stratum/Pool.cpp @@ -65,10 +65,8 @@ const String Pool::kDefaultUser = "x"; xmrig::Pool::Pool() : - m_enabled(true), - m_nicehash(false), - m_tls(false), m_keepAlive(0), + m_flags(0), m_port(kDefaultPort) { } @@ -86,10 +84,8 @@ xmrig::Pool::Pool() : * @param url */ xmrig::Pool::Pool(const char *url) : - m_enabled(true), - m_nicehash(false), - m_tls(false), m_keepAlive(0), + m_flags(1), m_port(kDefaultPort) { parse(url); @@ -97,22 +93,24 @@ xmrig::Pool::Pool(const char *url) : xmrig::Pool::Pool(const rapidjson::Value &object) : - m_enabled(true), - m_nicehash(false), - m_tls(false), m_keepAlive(0), + m_flags(1), m_port(kDefaultPort) { if (!parse(Json::getString(object, kUrl))) { return; } - setUser(Json::getString(object, kUser)); - setPassword(Json::getString(object, kPass)); - setRigId(Json::getString(object, kRigId)); - setNicehash(Json::getBool(object, kNicehash)); + m_user = Json::getString(object, kUser); + m_password = Json::getString(object, kPass); + m_rigId = Json::getString(object, kRigId); + m_fingerprint = Json::getString(object, kFingerprint); - const rapidjson::Value &keepalive = object[kKeepalive]; + m_flags.set(FLAG_ENABLED, Json::getBool(object, kEnabled, true)); + m_flags.set(FLAG_NICEHASH, Json::getBool(object, kNicehash)); + m_flags.set(FLAG_TLS, Json::getBool(object, kTls, m_flags.test(FLAG_TLS))); + + const rapidjson::Value &keepalive = Json::getValue(object, kKeepalive); if (keepalive.IsInt()) { setKeepAlive(keepalive.GetInt()); } @@ -120,7 +118,7 @@ xmrig::Pool::Pool(const rapidjson::Value &object) : setKeepAlive(keepalive.GetBool()); } - const rapidjson::Value &variant = object[kVariant]; + const rapidjson::Value &variant = Json::getValue(object, kVariant); if (variant.IsString()) { algorithm().parseVariant(variant.GetString()); } @@ -128,17 +126,12 @@ xmrig::Pool::Pool(const rapidjson::Value &object) : algorithm().parseVariant(variant.GetInt()); } - m_enabled = Json::getBool(object, kEnabled, true); - m_tls = Json::getBool(object, kTls); - m_fingerprint = Json::getString(object, kFingerprint); } xmrig::Pool::Pool(const char *host, uint16_t port, const char *user, const char *password, int keepAlive, bool nicehash, bool tls) : - m_enabled(true), - m_nicehash(nicehash), - m_tls(tls), m_keepAlive(keepAlive), + m_flags(1), m_host(host), m_password(password), m_user(user), @@ -151,6 +144,9 @@ xmrig::Pool::Pool(const char *host, uint16_t port, const char *user, const char snprintf(url, size - 1, "%s:%d", m_host.data(), m_port); m_url = url; + + m_flags.set(FLAG_NICEHASH, nicehash); + m_flags.set(FLAG_TLS, tls); } @@ -184,15 +180,13 @@ bool xmrig::Pool::isEnabled() const } # endif - return m_enabled && isValid() && algorithm().isValid(); + return m_flags.test(FLAG_ENABLED) && isValid() && algorithm().isValid(); } bool xmrig::Pool::isEqual(const Pool &other) const { - return (m_nicehash == other.m_nicehash - && m_enabled == other.m_enabled - && m_tls == other.m_tls + return (m_flags == other.m_flags && m_keepAlive == other.m_keepAlive && m_port == other.m_port && m_algorithm == other.m_algorithm @@ -214,10 +208,10 @@ bool xmrig::Pool::parse(const char *url) if (p) { if (strncasecmp(url, "stratum+tcp://", 14) == 0) { - m_tls = false; + m_flags.set(FLAG_TLS, false); } else if (strncasecmp(url, "stratum+ssl://", 14) == 0) { - m_tls = true; + m_flags.set(FLAG_TLS, true); } else { return false; @@ -309,7 +303,7 @@ rapidjson::Value xmrig::Pool::toJSON(rapidjson::Document &doc) const break; } - obj.AddMember(StringRef(kEnabled), m_enabled, allocator); + obj.AddMember(StringRef(kEnabled), m_flags.test(FLAG_ENABLED), allocator); obj.AddMember(StringRef(kTls), isTLS(), allocator); obj.AddMember(StringRef(kFingerprint), m_fingerprint.toJSON(), allocator); @@ -396,8 +390,8 @@ void xmrig::Pool::adjustVariant(const xmrig::Variant variantHint) using namespace xmrig; if (m_host.contains(".nicehash.com")) { + m_flags.set(FLAG_NICEHASH, true); m_keepAlive = false; - m_nicehash = true; bool valid = true; switch (m_port) { @@ -432,7 +426,7 @@ void xmrig::Pool::adjustVariant(const xmrig::Variant variantHint) m_algorithm.setAlgo(INVALID_ALGO); } - m_tls = m_port > 33000; + m_flags.set(FLAG_TLS, m_port > 33000); return; } diff --git a/src/base/net/stratum/Pool.h b/src/base/net/stratum/Pool.h index f681f0c4..d933bb86 100644 --- a/src/base/net/stratum/Pool.h +++ b/src/base/net/stratum/Pool.h @@ -26,6 +26,7 @@ #define XMRIG_POOL_H +#include #include @@ -40,6 +41,13 @@ namespace xmrig { class Pool { public: + enum Flags { + FLAG_ENABLED, + FLAG_NICEHASH, + FLAG_TLS, + FLAG_MAX + }; + static const String kDefaultPassword; static const String kDefaultUser; @@ -59,8 +67,8 @@ public: ); inline Algorithm &algorithm() { return m_algorithm; } - inline bool isNicehash() const { return m_nicehash; } - inline bool isTLS() const { return m_tls; } + inline bool isNicehash() const { return m_flags.test(FLAG_NICEHASH); } + inline bool isTLS() const { return m_flags.test(FLAG_TLS); } inline bool isValid() const { return !m_host.isNull() && m_port > 0; } inline const Algorithm &algorithm() const { return m_algorithm; } inline const Algorithms &algorithms() const { return m_algorithms; } @@ -72,17 +80,9 @@ public: inline const String &user() const { return !m_user.isNull() ? m_user : kDefaultUser; } inline int keepAlive() const { return m_keepAlive; } inline uint16_t port() const { return m_port; } - inline void setFingerprint(const char *fingerprint) { m_fingerprint = fingerprint; } - inline void setKeepAlive(bool enable) { setKeepAlive(enable ? kKeepAliveTimeout : 0); } - inline void setKeepAlive(int keepAlive) { m_keepAlive = keepAlive >= 0 ? keepAlive : 0; } - inline void setNicehash(bool nicehash) { m_nicehash = nicehash; } - inline void setPassword(const char *password) { m_password = password; } - inline void setRigId(const char *rigId) { m_rigId = rigId; } - inline void setTLS(bool tls) { m_tls = tls; } - inline void setUser(const char *user) { m_user = user; } - inline bool operator!=(const Pool &other) const { return !isEqual(other); } - inline bool operator==(const Pool &other) const { return isEqual(other); } + inline bool operator!=(const Pool &other) const { return !isEqual(other); } + inline bool operator==(const Pool &other) const { return isEqual(other); } bool isCompatible(const Algorithm &algorithm) const; bool isEnabled() const; @@ -98,6 +98,9 @@ public: # endif private: + inline void setKeepAlive(bool enable) { setKeepAlive(enable ? kKeepAliveTimeout : 0); } + inline void setKeepAlive(int keepAlive) { m_keepAlive = keepAlive >= 0 ? keepAlive : 0; } + bool parseIPv6(const char *addr); void addVariant(Variant variant); void adjustVariant(const Variant variantHint); @@ -105,10 +108,8 @@ private: Algorithm m_algorithm; Algorithms m_algorithms; - bool m_enabled; - bool m_nicehash; - bool m_tls; int m_keepAlive; + std::bitset m_flags; String m_fingerprint; String m_host; String m_password; diff --git a/src/base/tools/String.cpp b/src/base/tools/String.cpp index c908fe9a..c7bc3d1b 100644 --- a/src/base/tools/String.cpp +++ b/src/base/tools/String.cpp @@ -129,6 +129,20 @@ std::vector xmrig::String::split(char sep) const } +xmrig::String &xmrig::String::toLower() +{ + if (isNull() || isEmpty()) { + return *this; + } + + for (size_t i = 0; i < size(); ++i) { + m_data[i] = static_cast(tolower(m_data[i])); + } + + return *this; +} + + xmrig::String xmrig::String::join(const std::vector &vec, char sep) { if (vec.empty()) { diff --git a/src/base/tools/String.h b/src/base/tools/String.h index a640469a..eb0a1820 100644 --- a/src/base/tools/String.h +++ b/src/base/tools/String.h @@ -85,6 +85,7 @@ public: rapidjson::Value toJSON() const; rapidjson::Value toJSON(rapidjson::Document &doc) const; std::vector split(char sep) const; + String &toLower(); static String join(const std::vector &vec, char sep); From 35d868fb48a29a5954300e31fd02853eb08cf97b Mon Sep 17 00:00:00 2001 From: XMRig Date: Mon, 8 Apr 2019 02:16:54 +0700 Subject: [PATCH 072/116] Fix --userpass option. --- src/base/kernel/config/BaseTransform.cpp | 15 ++++++++++++++- src/base/net/stratum/Client.cpp | 4 ++-- src/base/net/stratum/Pool.cpp | 19 +------------------ src/base/net/stratum/Pool.h | 1 - 4 files changed, 17 insertions(+), 22 deletions(-) diff --git a/src/base/kernel/config/BaseTransform.cpp b/src/base/kernel/config/BaseTransform.cpp index 5a05111b..3b6b6d82 100644 --- a/src/base/kernel/config/BaseTransform.cpp +++ b/src/base/kernel/config/BaseTransform.cpp @@ -98,7 +98,20 @@ void xmrig::BaseTransform::transform(rapidjson::Document &doc, int key, const ch return set(doc, "algo", arg); case IConfig::UserpassKey: /* --userpass */ - return add(doc, kPools, "userpass", arg); + { + const char *p = strrchr(arg, ':'); + if (!p) { + return; + } + + char *user = new char[p - arg + 1](); + strncpy(user, arg, static_cast(p - arg)); + + add(doc, kPools, "user", user); + add(doc, kPools, "pass", p + 1); + delete [] user; + } + break; case IConfig::UrlKey: /* --url */ return add(doc, kPools, "url", arg, true); diff --git a/src/base/net/stratum/Client.cpp b/src/base/net/stratum/Client.cpp index 667dd448..62c15f5a 100644 --- a/src/base/net/stratum/Client.cpp +++ b/src/base/net/stratum/Client.cpp @@ -541,7 +541,7 @@ int64_t xmrig::Client::send(const rapidjson::Document &doc) int64_t xmrig::Client::send(size_t size) { - LOG_DEBUG("[%s] send (%d bytes): \"%s\"", url(), size, m_sendBuf); + LOG_DEBUG("[%s] send (%d bytes): \"%.*s\"", url(), size, static_cast(size) - 1, m_sendBuf); # ifdef XMRIG_FEATURE_TLS if (isTLS()) { @@ -676,7 +676,7 @@ void xmrig::Client::parse(char *line, size_t len) { startTimeout(); - LOG_DEBUG("[%s] received (%d bytes): \"%s\"", url(), len, line); + LOG_DEBUG("[%s] received (%d bytes): \"%.*s\"", url(), len, static_cast(len), line); if (len < 32 || line[0] != '{') { if (!isQuiet()) { diff --git a/src/base/net/stratum/Pool.cpp b/src/base/net/stratum/Pool.cpp index c618707a..25fd13aa 100644 --- a/src/base/net/stratum/Pool.cpp +++ b/src/base/net/stratum/Pool.cpp @@ -246,23 +246,6 @@ bool xmrig::Pool::parse(const char *url) } -bool xmrig::Pool::setUserpass(const char *userpass) -{ - const char *p = strchr(userpass, ':'); - if (!p) { - return false; - } - - char *user = new char[p - userpass + 1](); - strncpy(user, userpass, static_cast(p - userpass)); - - m_user = user; - m_password = p + 1; - - return true; -} - - rapidjson::Value xmrig::Pool::toJSON(rapidjson::Document &doc) const { using namespace rapidjson; @@ -344,7 +327,7 @@ void xmrig::Pool::print() const LOG_DEBUG ("pass: %s", m_password.data()); LOG_DEBUG ("rig-id %s", m_rigId.data()); LOG_DEBUG ("algo: %s", m_algorithm.name()); - LOG_DEBUG ("nicehash: %d", static_cast(m_nicehash)); + LOG_DEBUG ("nicehash: %d", static_cast(m_flags.test(FLAG_NICEHASH))); LOG_DEBUG ("keepAlive: %d", m_keepAlive); } #endif diff --git a/src/base/net/stratum/Pool.h b/src/base/net/stratum/Pool.h index d933bb86..c8a7c44b 100644 --- a/src/base/net/stratum/Pool.h +++ b/src/base/net/stratum/Pool.h @@ -88,7 +88,6 @@ public: bool isEnabled() const; bool isEqual(const Pool &other) const; bool parse(const char *url); - bool setUserpass(const char *userpass); rapidjson::Value toJSON(rapidjson::Document &doc) const; void adjust(const Algorithm &algorithm); void setAlgo(const Algorithm &algorithm); From 241383068c29bad2d691ba95e6f8893ae9034875 Mon Sep 17 00:00:00 2001 From: XMRig Date: Tue, 9 Apr 2019 01:59:22 +0700 Subject: [PATCH 073/116] Added HttpClient class. --- src/api/Httpd.cpp | 34 +-- src/api/Httpd.h | 4 +- src/api/requests/HttpApiRequest.cpp | 4 +- src/api/requests/HttpApiRequest.h | 6 +- src/base/base.cmake | 4 +- src/base/kernel/interfaces/IHttpListener.h | 4 +- src/base/net/dns/Dns.cpp | 6 +- src/base/net/dns/Dns.h | 5 +- src/base/net/http/HttpClient.cpp | 198 ++++++++++++++++++ src/base/net/http/HttpClient.h | 64 ++++++ src/base/net/http/HttpContext.cpp | 165 +++++++++------ src/base/net/http/HttpContext.h | 24 +-- .../net/http/{HttpRequest.h => HttpData.h} | 12 +- src/base/net/http/HttpResponse.cpp | 16 +- src/base/net/http/HttpServer.cpp | 10 +- src/base/net/stratum/Client.cpp | 14 +- src/base/tools/Baton.h | 4 +- 17 files changed, 421 insertions(+), 153 deletions(-) create mode 100644 src/base/net/http/HttpClient.cpp create mode 100644 src/base/net/http/HttpClient.h rename src/base/net/http/{HttpRequest.h => HttpData.h} (89%) diff --git a/src/api/Httpd.cpp b/src/api/Httpd.cpp index 0aba6072..57a112e9 100644 --- a/src/api/Httpd.cpp +++ b/src/api/Httpd.cpp @@ -28,7 +28,7 @@ #include "api/Httpd.h" #include "base/io/log/Log.h" #include "base/net/http/HttpApiResponse.h" -#include "base/net/http/HttpRequest.h" +#include "base/net/http/HttpData.h" #include "base/net/http/HttpServer.h" #include "base/net/tools/TcpServer.h" #include "core/config/Config.h" @@ -128,49 +128,49 @@ void xmrig::Httpd::onConfigChanged(Config *config, Config *previousConfig) } -void xmrig::Httpd::onHttpRequest(const HttpRequest &req) +void xmrig::Httpd::onHttpData(const HttpData &data) { - if (req.method == HTTP_OPTIONS) { - return HttpApiResponse(req.id()).end(); + if (data.method == HTTP_OPTIONS) { + return HttpApiResponse(data.id()).end(); } - if (req.method == HTTP_GET && req.url == "/favicon.ico") { + if (data.method == HTTP_GET && data.url == "/favicon.ico") { # ifdef _WIN32 if (favicon != nullptr) { - HttpResponse response(req.id()); + HttpResponse response(data.id()); response.setHeader("Content-Type", "image/x-icon"); return response.end(favicon, faviconSize); } # endif - return HttpResponse(req.id(), 404).end(); + return HttpResponse(data.id(), 404).end(); } - if (req.method > 4) { - return HttpApiResponse(req.id(), HTTP_STATUS_METHOD_NOT_ALLOWED).end(); + if (data.method > 4) { + return HttpApiResponse(data.id(), HTTP_STATUS_METHOD_NOT_ALLOWED).end(); } - const int status = auth(req); + const int status = auth(data); if (status != HTTP_STATUS_OK) { - return HttpApiResponse(req.id(), status).end(); + return HttpApiResponse(data.id(), status).end(); } - if (req.method != HTTP_GET) { + if (data.method != HTTP_GET) { if (m_base->config()->http().isRestricted()) { - return HttpApiResponse(req.id(), HTTP_STATUS_FORBIDDEN).end(); + return HttpApiResponse(data.id(), HTTP_STATUS_FORBIDDEN).end(); } - if (!req.headers.count(kContentType) || req.headers.at(kContentType) != "application/json") { - return HttpApiResponse(req.id(), HTTP_STATUS_UNSUPPORTED_MEDIA_TYPE).end(); + if (!data.headers.count(kContentType) || data.headers.at(kContentType) != "application/json") { + return HttpApiResponse(data.id(), HTTP_STATUS_UNSUPPORTED_MEDIA_TYPE).end(); } } - m_base->api()->request(req); + m_base->api()->request(data); } -int xmrig::Httpd::auth(const HttpRequest &req) const +int xmrig::Httpd::auth(const HttpData &req) const { const Http &config = m_base->config()->http(); diff --git a/src/api/Httpd.h b/src/api/Httpd.h index ae6cbfc8..220bb7f5 100644 --- a/src/api/Httpd.h +++ b/src/api/Httpd.h @@ -52,10 +52,10 @@ public: protected: void onConfigChanged(Config *config, Config *previousConfig) override; - void onHttpRequest(const HttpRequest &req) override; + void onHttpData(const HttpData &data) override; private: - int auth(const HttpRequest &req) const; + int auth(const HttpData &req) const; Base *m_base; HttpServer *m_http; diff --git a/src/api/requests/HttpApiRequest.cpp b/src/api/requests/HttpApiRequest.cpp index a61dde8d..e4f2de1e 100644 --- a/src/api/requests/HttpApiRequest.cpp +++ b/src/api/requests/HttpApiRequest.cpp @@ -24,11 +24,11 @@ #include "api/requests/HttpApiRequest.h" -#include "base/net/http/HttpRequest.h" +#include "base/net/http/HttpData.h" #include "rapidjson/error/en.h" -xmrig::HttpApiRequest::HttpApiRequest(const HttpRequest &req, bool restricted) : +xmrig::HttpApiRequest::HttpApiRequest(const HttpData &req, bool restricted) : ApiRequest(SOURCE_HTTP, restricted), m_parsed(false), m_req(req), diff --git a/src/api/requests/HttpApiRequest.h b/src/api/requests/HttpApiRequest.h index 26f26f39..f34d4be5 100644 --- a/src/api/requests/HttpApiRequest.h +++ b/src/api/requests/HttpApiRequest.h @@ -35,13 +35,13 @@ namespace xmrig { -class HttpRequest; +class HttpData; class HttpApiRequest : public ApiRequest { public: - HttpApiRequest(const HttpRequest &req, bool restricted); + HttpApiRequest(const HttpData &req, bool restricted); protected: inline rapidjson::Document &doc() override { return m_res.doc(); } @@ -55,7 +55,7 @@ protected: private: bool m_parsed; - const HttpRequest &m_req; + const HttpData &m_req; HttpApiResponse m_res; rapidjson::Document m_body; String m_url; diff --git a/src/base/base.cmake b/src/base/base.cmake index 04016f01..886d4c11 100644 --- a/src/base/base.cmake +++ b/src/base/base.cmake @@ -100,8 +100,9 @@ if (WITH_HTTPD) src/base/kernel/interfaces/IJsonReader.h src/base/kernel/interfaces/ITcpServerListener.h src/base/net/http/HttpApiResponse.h + src/base/net/http/HttpClient.h src/base/net/http/HttpContext.h - src/base/net/http/HttpRequest.h + src/base/net/http/HttpData.h src/base/net/http/HttpResponse.h src/base/net/http/HttpServer.h src/base/net/tools/TcpServer.h @@ -110,6 +111,7 @@ if (WITH_HTTPD) set(SOURCES_BASE_HTTP src/3rdparty/http-parser/http_parser.c src/base/net/http/HttpApiResponse.cpp + src/base/net/http/HttpClient.cpp src/base/net/http/HttpContext.cpp src/base/net/http/HttpResponse.cpp src/base/net/http/HttpServer.cpp diff --git a/src/base/kernel/interfaces/IHttpListener.h b/src/base/kernel/interfaces/IHttpListener.h index d4d905ca..94fd1d18 100644 --- a/src/base/kernel/interfaces/IHttpListener.h +++ b/src/base/kernel/interfaces/IHttpListener.h @@ -29,7 +29,7 @@ namespace xmrig { -class HttpRequest; +class HttpData; class HttpResponse; @@ -38,7 +38,7 @@ class IHttpListener public: virtual ~IHttpListener() = default; - virtual void onHttpRequest(const HttpRequest &req) = 0; + virtual void onHttpData(const HttpData &data) = 0; }; diff --git a/src/base/net/dns/Dns.cpp b/src/base/net/dns/Dns.cpp index f57278c4..40d2a6e3 100644 --- a/src/base/net/dns/Dns.cpp +++ b/src/base/net/dns/Dns.cpp @@ -144,7 +144,11 @@ void xmrig::Dns::onResolved(int status, addrinfo *res) ptr = ptr->ai_next; } - m_listener->onResolved(*this, status); + if (isEmpty()) { + m_status = UV_EAI_NONAME; + } + + m_listener->onResolved(*this, m_status); } diff --git a/src/base/net/dns/Dns.h b/src/base/net/dns/Dns.h index 73c47cdd..11f5bf80 100644 --- a/src/base/net/dns/Dns.h +++ b/src/base/net/dns/Dns.h @@ -47,8 +47,9 @@ public: Dns(IDnsListener *listener); ~Dns(); - inline bool isEmpty() const { return m_ipv4.empty() && m_ipv6.empty(); } - inline int status() const { return m_status; } + inline bool isEmpty() const { return m_ipv4.empty() && m_ipv6.empty(); } + inline const String &host() const { return m_host; } + inline int status() const { return m_status; } bool resolve(const String &host); const char *error() const; diff --git a/src/base/net/http/HttpClient.cpp b/src/base/net/http/HttpClient.cpp new file mode 100644 index 00000000..d33daf2c --- /dev/null +++ b/src/base/net/http/HttpClient.cpp @@ -0,0 +1,198 @@ +/* XMRig + * Copyright 2010 Jeff Garzik + * Copyright 2012-2014 pooler + * Copyright 2014 Lucas Jones + * Copyright 2014-2016 Wolf9466 + * Copyright 2016 Jay D Dee + * Copyright 2017-2018 XMR-Stak , + * Copyright 2014-2019 heapwolf + * Copyright 2018-2019 SChernykh + * Copyright 2016-2019 XMRig , + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + + +#include + + +#include "3rdparty/http-parser/http_parser.h" +#include "base/io/log/Log.h" +#include "base/net/dns/Dns.h" +#include "base/net/http/HttpClient.h" +#include "base/tools/Baton.h" +#include "common/Platform.h" + + +namespace xmrig { + +static const char *kCRLF = "\r\n"; + + +class WriteBaton : public Baton +{ +public: + inline WriteBaton(const std::stringstream &ss, std::string &&body) : + m_body(body), + m_header(ss.str()) + { + bufs[0].len = m_header.size(); + bufs[0].base = const_cast(m_header.c_str()); + + if (!m_body.empty()) { + bufs[1].len = m_body.size(); + bufs[1].base = const_cast(m_body.c_str()); + } + else { + bufs[1].base = nullptr; + bufs[1].len = 0; + } + } + + + inline size_t count() const { return bufs[1].base == nullptr ? 1 : 2; } + inline size_t size() const { return bufs[0].len + bufs[1].len; } + inline static void onWrite(uv_write_t *req, int) { delete reinterpret_cast(req->data); } + + + uv_buf_t bufs[2]; + +private: + std::string m_body; + std::string m_header; +}; + + +} // namespace xmrig + + +xmrig::HttpClient::HttpClient(const String &host, uint16_t port, int method, const String &url, IHttpListener *listener, const char *data, size_t size) : + HttpContext(HTTP_RESPONSE, listener), + m_port(port) +{ + this->method = method; + this->url = url; + + if (data) { + body = size ? std::string(data, size) : data; + } + + m_dns = new Dns(this); + + status = m_dns->resolve(host); +} + + +xmrig::HttpClient::~HttpClient() +{ + delete m_dns; +} + + +void xmrig::HttpClient::onResolved(const Dns &dns, int status) +{ + this->status = status; + + if (status < 0 && dns.isEmpty()) { + LOG_ERR("[%s:%d] DNS error: \"%s\"", dns.host().data(), m_port, uv_strerror(status)); + + return; + } + + sockaddr *addr = dns.get().addr(m_port); + + uv_connect_t *req = new uv_connect_t; + req->data = this; + + uv_tcp_connect(req, m_tcp, addr, onConnect); +} + + +void xmrig::HttpClient::send() +{ + headers.insert({ "Host", m_dns->host().data() }); + headers.insert({ "Connection", "close" }); + headers.insert({ "User-Agent", Platform::userAgent() }); + + if (body.size()) { + headers.insert({ "Content-Length", std::to_string(body.size()) }); + } + + std::stringstream ss; + ss << http_method_str(static_cast(method)) << " " << url << " HTTP/1.1" << kCRLF; + + for (auto &header : headers) { + ss << header.first << ": " << header.second << kCRLF; + } + + ss << kCRLF; + + headers.clear(); + + WriteBaton *baton = new WriteBaton(ss, std::move(body)); + uv_write(&baton->req, stream(), baton->bufs, baton->count(), WriteBaton::onWrite); +} + + +void xmrig::HttpClient::onConnect(uv_connect_t *req, int status) +{ + HttpClient *client = static_cast(req->data); + if (!client) { + delete req; + return; + } + + if (status < 0) { + LOG_ERR("[%s:%d] connect error: \"%s\"", client->m_dns->host().data(), client->m_port, uv_strerror(status)); + + delete req; + client->close(); + return; + } + + uv_read_start(client->stream(), + [](uv_handle_t *, size_t suggested_size, uv_buf_t *buf) + { + buf->base = new char[suggested_size]; + +# ifdef _WIN32 + buf->len = static_cast(suggested_size); +# else + buf->len = suggested_size; +# endif + }, + [](uv_stream_t *tcp, ssize_t nread, const uv_buf_t *buf) + { + HttpClient *client = static_cast(tcp->data); + + if (nread >= 0) { + const size_t size = static_cast(nread); + const size_t parsed = client->parse(buf->base, size); + + if (parsed < size) { + client->close(); + } + } else { + if (nread != UV_EOF) { + LOG_ERR("[%s:%d] read error: \"%s\"", client->m_dns->host().data(), client->m_port, uv_strerror(static_cast(nread))); + } + + client->close(); + } + + delete [] buf->base; + }); + + client->send(); +} diff --git a/src/base/net/http/HttpClient.h b/src/base/net/http/HttpClient.h new file mode 100644 index 00000000..c31b9a3e --- /dev/null +++ b/src/base/net/http/HttpClient.h @@ -0,0 +1,64 @@ +/* XMRig + * Copyright 2010 Jeff Garzik + * Copyright 2012-2014 pooler + * Copyright 2014 Lucas Jones + * Copyright 2014-2016 Wolf9466 + * Copyright 2016 Jay D Dee + * Copyright 2017-2018 XMR-Stak , + * Copyright 2014-2019 heapwolf + * Copyright 2018-2019 SChernykh + * Copyright 2016-2019 XMRig , + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + + +#ifndef XMRIG_HTTPCLIENT_H +#define XMRIG_HTTPCLIENT_H + + +#include "base/net/http/HttpContext.h" +#include "base/kernel/interfaces/IDnsListener.h" + + +namespace xmrig { + + +class String; + + +class HttpClient : public HttpContext, public IDnsListener +{ +public: + HttpClient(const String &host, uint16_t port, int method, const String &url, IHttpListener *listener, const char *data = nullptr, size_t size = 0); + ~HttpClient(); + +protected: + void onResolved(const Dns &dns, int status); + +private: + void send(); + + static void onConnect(uv_connect_t *req, int status); + + Dns *m_dns; + uint16_t m_port; +}; + + +} // namespace xmrig + + +#endif // XMRIG_HTTPCLIENT_H + diff --git a/src/base/net/http/HttpContext.cpp b/src/base/net/http/HttpContext.cpp index de32f34d..c98b4ad2 100644 --- a/src/base/net/http/HttpContext.cpp +++ b/src/base/net/http/HttpContext.cpp @@ -35,43 +35,72 @@ namespace xmrig { +static http_parser_settings http_settings; +static std::map storage; static uint64_t SEQUENCE = 0; -std::map HttpContext::m_storage; } // namespace xmrig xmrig::HttpContext::HttpContext(int parser_type, IHttpListener *listener) : - HttpRequest(SEQUENCE++), - listener(listener), - connect(nullptr), - m_wasHeaderValue(false) + HttpData(SEQUENCE++), + m_wasHeaderValue(false), + m_listener(listener) { - m_storage[id()] = this; + storage[id()] = this; - parser = new http_parser; - tcp = new uv_tcp_t; + m_parser = new http_parser; + m_tcp = new uv_tcp_t; - uv_tcp_init(uv_default_loop(), tcp); - http_parser_init(parser, static_cast(parser_type)); + uv_tcp_init(uv_default_loop(), m_tcp); + uv_tcp_nodelay(m_tcp, 1); - parser->data = tcp->data = this; + http_parser_init(m_parser, static_cast(parser_type)); + + m_parser->data = m_tcp->data = this; + + if (http_settings.on_message_complete == nullptr) { + attach(&http_settings); + } } xmrig::HttpContext::~HttpContext() { - delete connect; - delete tcp; - delete parser; + delete m_tcp; + delete m_parser; +} + + +size_t xmrig::HttpContext::parse(const char *data, size_t size) +{ + return http_parser_execute(m_parser, &http_settings, data, size); +} + + +std::string xmrig::HttpContext::ip() const +{ + char ip[46] = {}; + sockaddr_storage addr = {}; + int size = sizeof(addr); + + uv_tcp_getpeername(m_tcp, reinterpret_cast(&addr), &size); + if (reinterpret_cast(&addr)->sin_family == AF_INET6) { + uv_ip6_name(reinterpret_cast(&addr), ip, 45); + } + else { + uv_ip4_name(reinterpret_cast(&addr), ip, 16); + } + + return ip; } void xmrig::HttpContext::close() { - auto it = m_storage.find(id()); - if (it != m_storage.end()) { - m_storage.erase(it); + auto it = storage.find(id()); + if (it != storage.end()) { + storage.erase(it); } if (!uv_is_closing(handle())) { @@ -82,65 +111,17 @@ void xmrig::HttpContext::close() xmrig::HttpContext *xmrig::HttpContext::get(uint64_t id) { - if (m_storage.count(id) == 0) { + if (storage.count(id) == 0) { return nullptr; } - return m_storage[id]; -} - - -void xmrig::HttpContext::attach(http_parser_settings *settings) -{ - if (settings->on_message_complete != nullptr) { - return; - } - - settings->on_message_begin = nullptr; - settings->on_status = nullptr; - settings->on_chunk_header = nullptr; - settings->on_chunk_complete = nullptr; - - settings->on_url = [](http_parser *parser, const char *at, size_t length) -> int - { - static_cast(parser->data)->url = std::string(at, length); - return 0; - }; - - settings->on_header_field = onHeaderField; - settings->on_header_value = onHeaderValue; - - settings->on_headers_complete = [](http_parser* parser) -> int { - HttpContext *ctx = static_cast(parser->data); - ctx->method = parser->method; - - if (!ctx->m_lastHeaderField.empty()) { - ctx->setHeader(); - } - - return 0; - }; - - settings->on_body = [](http_parser *parser, const char *at, size_t len) -> int - { - static_cast(parser->data)->body += std::string(at, len); - - return 0; - }; - - settings->on_message_complete = [](http_parser *parser) -> int - { - const HttpContext *ctx = reinterpret_cast(parser->data); - ctx->listener->onHttpRequest(*ctx); - - return 0; - }; + return storage[id]; } void xmrig::HttpContext::closeAll() { - for (auto kv : m_storage) { + for (auto kv : storage) { if (!uv_is_closing(kv.second->handle())) { uv_close(kv.second->handle(), [](uv_handle_t *handle) -> void { delete reinterpret_cast(handle->data); }); } @@ -182,6 +163,54 @@ int xmrig::HttpContext::onHeaderValue(http_parser *parser, const char *at, size_ } +void xmrig::HttpContext::attach(http_parser_settings *settings) +{ + settings->on_message_begin = nullptr; + settings->on_status = nullptr; + settings->on_chunk_header = nullptr; + settings->on_chunk_complete = nullptr; + + settings->on_url = [](http_parser *parser, const char *at, size_t length) -> int + { + static_cast(parser->data)->url = std::string(at, length); + return 0; + }; + + settings->on_header_field = onHeaderField; + settings->on_header_value = onHeaderValue; + + settings->on_headers_complete = [](http_parser* parser) -> int { + HttpContext *ctx = static_cast(parser->data); + ctx->status = parser->status_code; + + if (parser->type == HTTP_REQUEST) { + ctx->method = parser->method; + } + + if (!ctx->m_lastHeaderField.empty()) { + ctx->setHeader(); + } + + return 0; + }; + + settings->on_body = [](http_parser *parser, const char *at, size_t len) -> int + { + static_cast(parser->data)->body += std::string(at, len); + + return 0; + }; + + settings->on_message_complete = [](http_parser *parser) -> int + { + const HttpContext *ctx = static_cast(parser->data); + ctx->m_listener->onHttpData(*ctx); + + return 0; + }; +} + + void xmrig::HttpContext::setHeader() { std::transform(m_lastHeaderField.begin(), m_lastHeaderField.end(), m_lastHeaderField.begin(), ::tolower); diff --git a/src/base/net/http/HttpContext.h b/src/base/net/http/HttpContext.h index 3b2dead3..ee11a072 100644 --- a/src/base/net/http/HttpContext.h +++ b/src/base/net/http/HttpContext.h @@ -36,7 +36,7 @@ typedef struct uv_stream_s uv_stream_t; typedef struct uv_tcp_s uv_tcp_t; -#include "base/net/http/HttpRequest.h" +#include "base/net/http/HttpData.h" namespace xmrig { @@ -45,37 +45,37 @@ namespace xmrig { class IHttpListener; -class HttpContext : public HttpRequest +class HttpContext : public HttpData { public: HttpContext(int parser_type, IHttpListener *listener); - ~HttpContext(); + virtual ~HttpContext(); - inline uv_stream_t *stream() const { return reinterpret_cast(tcp); } - inline uv_handle_t *handle() const { return reinterpret_cast(tcp); } + inline uv_stream_t *stream() const { return reinterpret_cast(m_tcp); } + inline uv_handle_t *handle() const { return reinterpret_cast(m_tcp); } + size_t parse(const char *data, size_t size); + std::string ip() const; void close(); static HttpContext *get(uint64_t id); - static void attach(http_parser_settings *settings); static void closeAll(); - http_parser *parser; - IHttpListener *listener; - uv_connect_t *connect; - uv_tcp_t *tcp; +protected: + uv_tcp_t *m_tcp; private: static int onHeaderField(http_parser *parser, const char *at, size_t length); static int onHeaderValue(http_parser *parser, const char *at, size_t length); + static void attach(http_parser_settings *settings); void setHeader(); bool m_wasHeaderValue; + http_parser *m_parser; + IHttpListener *m_listener; std::string m_lastHeaderField; std::string m_lastHeaderValue; - - static std::map m_storage; }; diff --git a/src/base/net/http/HttpRequest.h b/src/base/net/http/HttpData.h similarity index 89% rename from src/base/net/http/HttpRequest.h rename to src/base/net/http/HttpData.h index b97f0b8d..ceb19b8e 100644 --- a/src/base/net/http/HttpRequest.h +++ b/src/base/net/http/HttpData.h @@ -24,26 +24,26 @@ */ -#ifndef XMRIG_HTTPREQUEST_H -#define XMRIG_HTTPREQUEST_H +#ifndef XMRIG_HTTPDATA_H +#define XMRIG_HTTPDATA_H #include -#include #include namespace xmrig { -class HttpRequest +class HttpData { public: - inline HttpRequest(uint64_t id) : method(0), m_id(id) {} + inline HttpData(uint64_t id) : method(0), status(0), m_id(id) {} inline uint64_t id() const { return m_id; } int method; + int status; std::map headers; std::string body; std::string url; @@ -56,5 +56,5 @@ private: } // namespace xmrig -#endif // XMRIG_HTTPREQUEST_H +#endif // XMRIG_HTTPDATA_H diff --git a/src/base/net/http/HttpResponse.cpp b/src/base/net/http/HttpResponse.cpp index d782217b..7a4af838 100644 --- a/src/base/net/http/HttpResponse.cpp +++ b/src/base/net/http/HttpResponse.cpp @@ -49,7 +49,6 @@ public: m_ctx(ctx), m_header(ss.str()) { - req.data = this; bufs[0].len = m_header.size(); bufs[0].base = const_cast(m_header.c_str()); @@ -137,21 +136,10 @@ void xmrig::HttpResponse::end(const char *data, size_t size) if (statusCode() >= 400) # endif { - const bool err = statusCode() >= 400; - char ip[46] = {}; - sockaddr_storage addr = {}; - int aSize = sizeof(addr); - - uv_tcp_getpeername(ctx->tcp, reinterpret_cast(&addr), &aSize); - if (reinterpret_cast(&addr)->sin_family == AF_INET6) { - uv_ip6_name(reinterpret_cast(&addr), ip, 45); - } - else { - uv_ip4_name(reinterpret_cast(&addr), ip, 16); - } + const bool err = statusCode() >= 400; Log::print(err ? Log::ERR : Log::INFO, CYAN("%s ") CLEAR MAGENTA_BOLD("%s") WHITE_BOLD(" %s ") CSI "1;%dm%d " CLEAR WHITE_BOLD("%zu ") BLACK_BOLD("\"%s\""), - ip, + ctx->ip().c_str(), http_method_str(static_cast(ctx->method)), ctx->url.c_str(), err ? 31 : 32, diff --git a/src/base/net/http/HttpServer.cpp b/src/base/net/http/HttpServer.cpp index c6e02e44..60db31f6 100644 --- a/src/base/net/http/HttpServer.cpp +++ b/src/base/net/http/HttpServer.cpp @@ -35,17 +35,9 @@ #include "base/net/http/HttpServer.h" -namespace xmrig { - -static http_parser_settings http_settings; - -} // namespace xmrig - - xmrig::HttpServer::HttpServer(IHttpListener *listener) : m_listener(listener) { - HttpContext::attach(&http_settings); } @@ -77,7 +69,7 @@ void xmrig::HttpServer::onConnection(uv_stream_t *stream, uint16_t) if (nread >= 0) { const size_t size = static_cast(nread); - const size_t parsed = http_parser_execute(ctx->parser, &http_settings, buf->base, size); + const size_t parsed = ctx->parse(buf->base, size); if (parsed < size) { ctx->close(); diff --git a/src/base/net/stratum/Client.cpp b/src/base/net/stratum/Client.cpp index 62c15f5a..dba84cb1 100644 --- a/src/base/net/stratum/Client.cpp +++ b/src/base/net/stratum/Client.cpp @@ -284,14 +284,6 @@ void xmrig::Client::onResolved(const Dns &dns, int status) return reconnect(); } - if (dns.isEmpty()) { - if (!isQuiet()) { - LOG_ERR("[%s] DNS error: \"No IPv4 (A) or IPv6 (AAAA) records found\"", url()); - } - - return reconnect(); - } - const DnsRecord &record = dns.get(); m_ip = record.ip(); @@ -574,8 +566,6 @@ void xmrig::Client::connect(sockaddr *addr) { setState(ConnectingState); - reinterpret_cast(addr)->sin_port = htons(m_pool.port()); - uv_connect_t *req = new uv_connect_t; req->data = m_storage.ptr(m_key); @@ -589,7 +579,7 @@ void xmrig::Client::connect(sockaddr *addr) uv_tcp_keepalive(m_socket, 1, 60); # endif - uv_tcp_connect(req, m_socket, reinterpret_cast(addr), Client::onConnect); + uv_tcp_connect(req, m_socket, addr, onConnect); delete addr; } @@ -970,7 +960,7 @@ void xmrig::Client::onConnect(uv_connect_t *req, int status) client->m_stream->data = req->data; client->setState(ConnectedState); - uv_read_start(client->m_stream, Client::onAllocBuffer, Client::onRead); + uv_read_start(client->m_stream, onAllocBuffer, onRead); delete req; client->handshake(); diff --git a/src/base/tools/Baton.h b/src/base/tools/Baton.h index 7bea0af0..646dc0b8 100644 --- a/src/base/tools/Baton.h +++ b/src/base/tools/Baton.h @@ -29,13 +29,13 @@ namespace xmrig { -template +template class Baton { public: inline Baton() { req.data = this; } - T req; + REQ req; }; From 6812d22d63f02be97dc25327c79fe7abe263c136 Mon Sep 17 00:00:00 2001 From: XMRig Date: Tue, 9 Apr 2019 02:27:19 +0700 Subject: [PATCH 074/116] Rename cmake option WITH_HTTPD to WITH_HTTP. --- CMakeLists.txt | 10 +++++----- src/base/base.cmake | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 2bc90d43..c7098f37 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -6,7 +6,7 @@ option(WITH_AEON "CryptoNight-Lite support" ON) option(WITH_SUMO "CryptoNight-Heavy support" ON) option(WITH_CN_PICO "CryptoNight-Pico support" ON) option(WITH_CN_GPU "CryptoNight-GPU support" ON) -option(WITH_HTTPD "HTTP REST API" ON) +option(WITH_HTTP "HTTP protocol support (client/server)" ON) option(WITH_DEBUG_LOG "Enable debug log output" OFF) option(WITH_TLS "Enable OpenSSL support" ON) option(WITH_ASM "Enable ASM PoW implementations" ON) @@ -198,8 +198,8 @@ if (WITH_EMBEDDED_CONFIG) add_definitions(/DXMRIG_FEATURE_EMBEDDED_CONFIG) endif() -if (WITH_HTTPD) - set(HTTPD_SOURCES +if (WITH_HTTP) + set(HTTP_SOURCES src/api/Api.cpp src/api/Api.h src/api/Httpd.cpp @@ -213,7 +213,7 @@ if (WITH_HTTPD) src/api/v1/ApiRouter.h ) else() - set(HTTPD_SOURCES "") + set(HTTP_SOURCES "") endif() include_directories(src) @@ -228,5 +228,5 @@ if (WITH_DEBUG_LOG) add_definitions(/DAPP_DEBUG) endif() -add_executable(${CMAKE_PROJECT_NAME} ${HEADERS} ${SOURCES} ${SOURCES_OS} ${SOURCES_CPUID} ${HEADERS_CRYPTO} ${SOURCES_CRYPTO} ${SOURCES_SYSLOG} ${HTTPD_SOURCES} ${TLS_SOURCES} ${XMRIG_ASM_SOURCES} ${CN_GPU_SOURCES}) +add_executable(${CMAKE_PROJECT_NAME} ${HEADERS} ${SOURCES} ${SOURCES_OS} ${SOURCES_CPUID} ${HEADERS_CRYPTO} ${SOURCES_CRYPTO} ${SOURCES_SYSLOG} ${HTTP_SOURCES} ${TLS_SOURCES} ${XMRIG_ASM_SOURCES} ${CN_GPU_SOURCES}) target_link_libraries(${CMAKE_PROJECT_NAME} ${XMRIG_ASM_LIBRARY} ${OPENSSL_LIBRARIES} ${UV_LIBRARIES} ${EXTRA_LIBS} ${CPUID_LIB}) diff --git a/src/base/base.cmake b/src/base/base.cmake index 886d4c11..5263ed92 100644 --- a/src/base/base.cmake +++ b/src/base/base.cmake @@ -93,7 +93,7 @@ if (NOT WIN32) endif() -if (WITH_HTTPD) +if (WITH_HTTP) set(HEADERS_BASE_HTTP src/3rdparty/http-parser/http_parser.h src/base/kernel/interfaces/IHttpListener.h From c823c54f9bd39d9e67f53c558add72fabc31bd35 Mon Sep 17 00:00:00 2001 From: XMRig Date: Tue, 9 Apr 2019 14:06:56 +0700 Subject: [PATCH 075/116] Added HttpsClient. --- cmake/OpenSSL.cmake | 4 + src/base/net/http/HttpClient.cpp | 51 +++++++--- src/base/net/http/HttpClient.h | 17 +++- src/base/net/http/HttpsClient.cpp | 150 ++++++++++++++++++++++++++++++ src/base/net/http/HttpsClient.h | 70 ++++++++++++++ 5 files changed, 272 insertions(+), 20 deletions(-) create mode 100644 src/base/net/http/HttpsClient.cpp create mode 100644 src/base/net/http/HttpsClient.h diff --git a/cmake/OpenSSL.cmake b/cmake/OpenSSL.cmake index bcdea0c6..ea46081c 100644 --- a/cmake/OpenSSL.cmake +++ b/cmake/OpenSSL.cmake @@ -13,6 +13,10 @@ if (WITH_TLS) if (OPENSSL_FOUND) set(TLS_SOURCES src/base/net/stratum/Tls.h src/base/net/stratum/Tls.cpp) include_directories(${OPENSSL_INCLUDE_DIR}) + + if (WITH_HTTP) + set(TLS_SOURCES ${TLS_SOURCES} src/base/net/http/HttpsClient.h src/base/net/http/HttpsClient.cpp) + endif() else() message(FATAL_ERROR "OpenSSL NOT found: use `-DWITH_TLS=OFF` to build without TLS support") endif() diff --git a/src/base/net/http/HttpClient.cpp b/src/base/net/http/HttpClient.cpp index d33daf2c..a512989c 100644 --- a/src/base/net/http/HttpClient.cpp +++ b/src/base/net/http/HttpClient.cpp @@ -43,9 +43,9 @@ static const char *kCRLF = "\r\n"; class WriteBaton : public Baton { public: - inline WriteBaton(const std::stringstream &ss, std::string &&body) : + inline WriteBaton(const std::string &header, std::string &&body) : m_body(body), - m_header(ss.str()) + m_header(header) { bufs[0].len = m_header.size(); bufs[0].base = const_cast(m_header.c_str()); @@ -77,9 +77,9 @@ private: } // namespace xmrig -xmrig::HttpClient::HttpClient(const String &host, uint16_t port, int method, const String &url, IHttpListener *listener, const char *data, size_t size) : +xmrig::HttpClient::HttpClient(int method, const String &url, IHttpListener *listener, const char *data, size_t size) : HttpContext(HTTP_RESPONSE, listener), - m_port(port) + m_port(0) { this->method = method; this->url = url; @@ -89,8 +89,6 @@ xmrig::HttpClient::HttpClient(const String &host, uint16_t port, int method, con } m_dns = new Dns(this); - - status = m_dns->resolve(host); } @@ -100,6 +98,20 @@ xmrig::HttpClient::~HttpClient() } +bool xmrig::HttpClient::connect(const String &host, uint16_t port) +{ + m_port = port; + + return m_dns->resolve(host); +} + + +const xmrig::String &xmrig::HttpClient::host() const +{ + return m_dns->host(); +} + + void xmrig::HttpClient::onResolved(const Dns &dns, int status) { this->status = status; @@ -119,7 +131,7 @@ void xmrig::HttpClient::onResolved(const Dns &dns, int status) } -void xmrig::HttpClient::send() +void xmrig::HttpClient::handshake() { headers.insert({ "Host", m_dns->host().data() }); headers.insert({ "Connection", "close" }); @@ -140,7 +152,21 @@ void xmrig::HttpClient::send() headers.clear(); - WriteBaton *baton = new WriteBaton(ss, std::move(body)); + write(ss.str()); +} + + +void xmrig::HttpClient::read(const char *data, size_t size) +{ + if (parse(data, size) < size) { + close(); + } +} + + +void xmrig::HttpClient::write(const std::string &header) +{ + WriteBaton *baton = new WriteBaton(header, std::move(body)); uv_write(&baton->req, stream(), baton->bufs, baton->count(), WriteBaton::onWrite); } @@ -177,12 +203,7 @@ void xmrig::HttpClient::onConnect(uv_connect_t *req, int status) HttpClient *client = static_cast(tcp->data); if (nread >= 0) { - const size_t size = static_cast(nread); - const size_t parsed = client->parse(buf->base, size); - - if (parsed < size) { - client->close(); - } + client->read(buf->base, static_cast(nread)); } else { if (nread != UV_EOF) { LOG_ERR("[%s:%d] read error: \"%s\"", client->m_dns->host().data(), client->m_port, uv_strerror(static_cast(nread))); @@ -194,5 +215,5 @@ void xmrig::HttpClient::onConnect(uv_connect_t *req, int status) delete [] buf->base; }); - client->send(); + client->handshake(); } diff --git a/src/base/net/http/HttpClient.h b/src/base/net/http/HttpClient.h index c31b9a3e..b92c4733 100644 --- a/src/base/net/http/HttpClient.h +++ b/src/base/net/http/HttpClient.h @@ -41,15 +41,22 @@ class String; class HttpClient : public HttpContext, public IDnsListener { public: - HttpClient(const String &host, uint16_t port, int method, const String &url, IHttpListener *listener, const char *data = nullptr, size_t size = 0); - ~HttpClient(); + HttpClient(int method, const String &url, IHttpListener *listener, const char *data = nullptr, size_t size = 0); + ~HttpClient() override; + + inline uint16_t port() const { return m_port; } + + bool connect(const String &host, uint16_t port); + const String &host() const; protected: - void onResolved(const Dns &dns, int status); + void onResolved(const Dns &dns, int status) override; + + virtual void handshake(); + virtual void read(const char *data, size_t size); + virtual void write(const std::string &header); private: - void send(); - static void onConnect(uv_connect_t *req, int status); Dns *m_dns; diff --git a/src/base/net/http/HttpsClient.cpp b/src/base/net/http/HttpsClient.cpp new file mode 100644 index 00000000..8fd26a2e --- /dev/null +++ b/src/base/net/http/HttpsClient.cpp @@ -0,0 +1,150 @@ +/* XMRig + * Copyright 2010 Jeff Garzik + * Copyright 2012-2014 pooler + * Copyright 2014 Lucas Jones + * Copyright 2014-2016 Wolf9466 + * Copyright 2016 Jay D Dee + * Copyright 2017-2018 XMR-Stak , + * Copyright 2014-2019 heapwolf + * Copyright 2018-2019 SChernykh + * Copyright 2016-2019 XMRig , + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + + +#include +#include +#include + + +#include "base/net/http/HttpsClient.h" +#include "base/tools/String.h" + + +xmrig::HttpsClient::HttpsClient(int method, const String &url, IHttpListener *listener, const char *data, size_t size) : + HttpClient(method, url, listener, data, size), + m_ready(false), + m_buf(), + m_ssl(nullptr) +{ + m_ctx = SSL_CTX_new(SSLv23_method()); + assert(m_ctx != nullptr); + + if (!m_ctx) { + return; + } + + m_writeBio = BIO_new(BIO_s_mem()); + m_readBio = BIO_new(BIO_s_mem()); + SSL_CTX_set_options(m_ctx, SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3); +} + + +xmrig::HttpsClient::~HttpsClient() +{ + if (m_ctx) { + SSL_CTX_free(m_ctx); + } + + if (m_ssl) { + SSL_free(m_ssl); + } +} + + +void xmrig::HttpsClient::handshake() +{ + m_ssl = SSL_new(m_ctx); + assert(m_ssl != nullptr); + + if (!m_ssl) { + return; + } + + SSL_set_connect_state(m_ssl); + SSL_set_bio(m_ssl, m_readBio, m_writeBio); + SSL_set_tlsext_host_name(m_ssl, host().data()); + + SSL_do_handshake(m_ssl); + + flush(); +} + + +void xmrig::HttpsClient::read(const char *data, size_t size) +{ + BIO_write(m_readBio, data, size); + + if (!SSL_is_init_finished(m_ssl)) { + const int rc = SSL_connect(m_ssl); + + if (rc < 0 && SSL_get_error(m_ssl, rc) == SSL_ERROR_WANT_READ) { + flush(); + } else if (rc == 1) { + X509 *cert = SSL_get_peer_certificate(m_ssl); + if (!verify(cert)) { + X509_free(cert); + return close(); + } + + X509_free(cert); + m_ready = true; + + HttpClient::handshake(); + } + + return; + } + + int bytes_read = 0; + while ((bytes_read = SSL_read(m_ssl, m_buf, sizeof(m_buf))) > 0) { + HttpClient::read(m_buf, static_cast(bytes_read)); + } +} + + +void xmrig::HttpsClient::write(const std::string &header) +{ + SSL_write(m_ssl, (header + body).c_str(), header.size() + body.size()); + flush(); +} + + +bool xmrig::HttpsClient::verify(X509 *cert) const +{ + return cert != nullptr; +} + + +void xmrig::HttpsClient::flush() +{ + uv_buf_t buf; + buf.len = BIO_get_mem_data(m_writeBio, &buf.base); + + if (buf.len == 0) { + return; + } + + bool result = false; + if (uv_is_writable(stream())) { + result = uv_try_write(stream(), &buf, 1) == buf.len; + + if (!result) { + close(); + } + } + + (void) BIO_reset(m_writeBio); +} diff --git a/src/base/net/http/HttpsClient.h b/src/base/net/http/HttpsClient.h new file mode 100644 index 00000000..76b90c66 --- /dev/null +++ b/src/base/net/http/HttpsClient.h @@ -0,0 +1,70 @@ +/* XMRig + * Copyright 2010 Jeff Garzik + * Copyright 2012-2014 pooler + * Copyright 2014 Lucas Jones + * Copyright 2014-2016 Wolf9466 + * Copyright 2016 Jay D Dee + * Copyright 2017-2018 XMR-Stak , + * Copyright 2014-2019 heapwolf + * Copyright 2018-2019 SChernykh + * Copyright 2016-2019 XMRig , + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + + +#ifndef XMRIG_HTTPSCLIENT_H +#define XMRIG_HTTPSCLIENT_H + + +typedef struct bio_st BIO; +typedef struct ssl_ctx_st SSL_CTX; +typedef struct ssl_st SSL; +typedef struct x509_st X509; + + +#include "base/net/http/HttpClient.h" + + +namespace xmrig { + + +class HttpsClient : public HttpClient +{ +public: + HttpsClient(int method, const String &url, IHttpListener *listener, const char *data = nullptr, size_t size = 0); + ~HttpsClient() override; + +protected: + void handshake() override; + void read(const char *data, size_t size) override; + void write(const std::string &header) override; + +private: + bool verify(X509 *cert) const; + void flush(); + + BIO *m_readBio; + BIO *m_writeBio; + bool m_ready; + char m_buf[1024 * 2]; + SSL *m_ssl; + SSL_CTX *m_ctx; +}; + + +} // namespace xmrig + + +#endif // XMRIG_HTTPSCLIENT_H From c41889477cf4be49d96abf17223476717877005c Mon Sep 17 00:00:00 2001 From: XMRig Date: Wed, 10 Apr 2019 00:10:02 +0700 Subject: [PATCH 076/116] Fix build. --- src/api/Api.cpp | 2 +- src/api/Api.h | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/api/Api.cpp b/src/api/Api.cpp index 1b7210f6..d1bac212 100644 --- a/src/api/Api.cpp +++ b/src/api/Api.cpp @@ -74,7 +74,7 @@ xmrig::Api::~Api() } -void xmrig::Api::request(const HttpRequest &req) +void xmrig::Api::request(const HttpData &req) { HttpApiRequest request(req, m_base->config()->http().isRestricted()); diff --git a/src/api/Api.h b/src/api/Api.h index 9d391901..0c7fac52 100644 --- a/src/api/Api.h +++ b/src/api/Api.h @@ -38,7 +38,7 @@ namespace xmrig { class ApiRouter; class Base; class Httpd; -class HttpRequest; +class HttpData; class IApiListener; class IApiRequest; class String; @@ -54,7 +54,7 @@ public: inline const char *workerId() const { return m_workerId; } inline void addListener(IApiListener *listener) { m_listeners.push_back(listener); } - void request(const HttpRequest &req); + void request(const HttpData &req); void start(); void stop(); From 1bd8d6350842c73153758db06023c163eff34f39 Mon Sep 17 00:00:00 2001 From: XMRig Date: Wed, 10 Apr 2019 03:42:00 +0700 Subject: [PATCH 077/116] 64bit diff support. --- src/base/net/stratum/Job.h | 2 +- src/base/net/stratum/SubmitResult.h | 8 ++++---- src/net/JobResult.h | 12 ++++++------ src/net/Network.cpp | 8 ++++---- src/net/NetworkState.cpp | 4 ++-- src/net/NetworkState.h | 2 +- 6 files changed, 18 insertions(+), 18 deletions(-) diff --git a/src/base/net/stratum/Job.h b/src/base/net/stratum/Job.h index 8fc3d709..c8dced4b 100644 --- a/src/base/net/stratum/Job.h +++ b/src/base/net/stratum/Job.h @@ -67,7 +67,7 @@ public: inline int threadId() const { return m_threadId; } inline size_t size() const { return m_size; } inline uint32_t *nonce() { return reinterpret_cast(m_blob + 39); } - inline uint32_t diff() const { return static_cast(m_diff); } + inline uint64_t diff() const { return m_diff; } inline uint64_t height() const { return m_height; } inline uint64_t target() const { return m_target; } inline uint8_t fixedByte() const { return *(m_blob + 42); } diff --git a/src/base/net/stratum/SubmitResult.h b/src/base/net/stratum/SubmitResult.h index 583d426f..5abd3e4b 100644 --- a/src/base/net/stratum/SubmitResult.h +++ b/src/base/net/stratum/SubmitResult.h @@ -38,17 +38,17 @@ public: inline SubmitResult() : reqId(0), seq(0), - diff(0), actualDiff(0), + diff(0), elapsed(0), m_start(0) {} - inline SubmitResult(int64_t seq, uint32_t diff, uint64_t actualDiff, int64_t reqId = 0) : + inline SubmitResult(int64_t seq, uint64_t diff, uint64_t actualDiff, int64_t reqId = 0) : reqId(reqId), seq(seq), - diff(diff), actualDiff(actualDiff), + diff(diff), elapsed(0), m_start(Chrono::steadyMSecs()) {} @@ -57,8 +57,8 @@ public: int64_t reqId; int64_t seq; - uint32_t diff; uint64_t actualDiff; + uint64_t diff; uint64_t elapsed; private: diff --git a/src/net/JobResult.h b/src/net/JobResult.h index 9d2300b5..9fe1238e 100644 --- a/src/net/JobResult.h +++ b/src/net/JobResult.h @@ -41,20 +41,20 @@ namespace xmrig { class JobResult { public: - inline JobResult() : poolId(0), diff(0), nonce(0) {} - inline JobResult(int poolId, const String &jobId, const String &clientId, uint32_t nonce, const uint8_t *result, uint32_t diff, const Algorithm &algorithm) : + inline JobResult() : poolId(0), nonce(0), diff(0) {} + inline JobResult(int poolId, const String &jobId, const String &clientId, uint32_t nonce, const uint8_t *result, uint64_t diff, const Algorithm &algorithm) : algorithm(algorithm), poolId(poolId), clientId(clientId), jobId(jobId), - diff(diff), - nonce(nonce) + nonce(nonce), + diff(diff) { memcpy(this->result, result, sizeof(this->result)); } - inline JobResult(const Job &job) : poolId(0), diff(0), nonce(0) + inline JobResult(const Job &job) : poolId(0), nonce(0), diff(0) { jobId = job.id(); clientId = job.clientId(); @@ -75,8 +75,8 @@ public: int poolId; String clientId; String jobId; - uint32_t diff; uint32_t nonce; + uint64_t diff; uint8_t result[32]; }; diff --git a/src/net/Network.cpp b/src/net/Network.cpp index 5de840ea..be853cfa 100644 --- a/src/net/Network.cpp +++ b/src/net/Network.cpp @@ -181,11 +181,11 @@ void xmrig::Network::onResultAccepted(IStrategy *, Client *, const SubmitResult m_state.add(result, error); if (error) { - LOG_INFO(RED_BOLD("rejected") " (%" PRId64 "/%" PRId64 ") diff " WHITE_BOLD("%u") " " RED("\"%s\"") " " BLACK_BOLD("(%" PRIu64 " ms)"), + LOG_INFO(RED_BOLD("rejected") " (%" PRId64 "/%" PRId64 ") diff " WHITE_BOLD("%" PRIu64) " " RED("\"%s\"") " " BLACK_BOLD("(%" PRIu64 " ms)"), m_state.accepted, m_state.rejected, result.diff, error, result.elapsed); } else { - LOG_INFO(GREEN_BOLD("accepted") " (%" PRId64 "/%" PRId64 ") diff " WHITE_BOLD("%u") " " BLACK_BOLD("(%" PRIu64 " ms)"), + LOG_INFO(GREEN_BOLD("accepted") " (%" PRId64 "/%" PRId64 ") diff " WHITE_BOLD("%" PRIu64) " " BLACK_BOLD("(%" PRIu64 " ms)"), m_state.accepted, m_state.rejected, result.diff, result.elapsed); } } @@ -194,11 +194,11 @@ void xmrig::Network::onResultAccepted(IStrategy *, Client *, const SubmitResult void xmrig::Network::setJob(Client *client, const Job &job, bool donate) { if (job.height()) { - LOG_INFO(MAGENTA_BOLD("new job") " from " WHITE_BOLD("%s:%d") " diff " WHITE_BOLD("%d") " algo " WHITE_BOLD("%s") " height " WHITE_BOLD("%" PRIu64), + LOG_INFO(MAGENTA_BOLD("new job") " from " WHITE_BOLD("%s:%d") " diff " WHITE_BOLD("%" PRIu64) " algo " WHITE_BOLD("%s") " height " WHITE_BOLD("%" PRIu64), client->host(), client->port(), job.diff(), job.algorithm().shortName(), job.height()); } else { - LOG_INFO(MAGENTA_BOLD("new job") " from " WHITE_BOLD("%s:%d") " diff " WHITE_BOLD("%d") " algo " WHITE_BOLD("%s"), + LOG_INFO(MAGENTA_BOLD("new job") " from " WHITE_BOLD("%s:%d") " diff " WHITE_BOLD("%" PRIu64) " algo " WHITE_BOLD("%s"), client->host(), client->port(), job.diff(), job.algorithm().shortName()); } diff --git a/src/net/NetworkState.cpp b/src/net/NetworkState.cpp index df248602..c55422db 100644 --- a/src/net/NetworkState.cpp +++ b/src/net/NetworkState.cpp @@ -35,14 +35,14 @@ xmrig::NetworkState::NetworkState() : - diff(0), + pool(), accepted(0), + diff(0), failures(0), rejected(0), total(0), m_active(false) { - memset(pool, 0, sizeof(pool)); } diff --git a/src/net/NetworkState.h b/src/net/NetworkState.h index 2f88d9b3..cf9a649a 100644 --- a/src/net/NetworkState.h +++ b/src/net/NetworkState.h @@ -50,8 +50,8 @@ public: char pool[256]; std::array topDiff { { } }; - uint32_t diff; uint64_t accepted; + uint64_t diff; uint64_t failures; uint64_t rejected; uint64_t total; From 9a6944d6949d38e5911a0483f781594bcfa4d6a3 Mon Sep 17 00:00:00 2001 From: XMRig Date: Wed, 10 Apr 2019 18:29:33 +0700 Subject: [PATCH 078/116] Add IClient and BaseClient. --- src/base/base.cmake | 3 + src/base/kernel/interfaces/IClient.h | 84 +++++++++++++++++++ src/base/kernel/interfaces/IClientListener.h | 12 +-- .../kernel/interfaces/IStrategyListener.h | 10 +-- src/base/net/stratum/BaseClient.cpp | 37 ++++++++ src/base/net/stratum/BaseClient.h | 75 +++++++++++++++++ src/base/net/stratum/Client.cpp | 28 +------ src/base/net/stratum/Client.h | 76 +++++------------ .../stratum/strategies/FailoverStrategy.cpp | 8 +- .../net/stratum/strategies/FailoverStrategy.h | 14 ++-- .../stratum/strategies/SinglePoolStrategy.cpp | 8 +- .../stratum/strategies/SinglePoolStrategy.h | 14 ++-- src/net/Network.cpp | 16 ++-- src/net/Network.h | 8 +- src/net/strategies/DonateStrategy.cpp | 18 ++-- src/net/strategies/DonateStrategy.h | 26 +++--- 16 files changed, 291 insertions(+), 146 deletions(-) create mode 100644 src/base/kernel/interfaces/IClient.h create mode 100644 src/base/net/stratum/BaseClient.cpp create mode 100644 src/base/net/stratum/BaseClient.h diff --git a/src/base/base.cmake b/src/base/base.cmake index 5263ed92..3c7ee1b3 100644 --- a/src/base/base.cmake +++ b/src/base/base.cmake @@ -11,6 +11,7 @@ set(HEADERS_BASE src/base/kernel/config/BaseTransform.h src/base/kernel/Entry.h src/base/kernel/interfaces/IBaseListener.h + src/base/kernel/interfaces/IClient.h src/base/kernel/interfaces/IClientListener.h src/base/kernel/interfaces/IConfig.h src/base/kernel/interfaces/IConfigListener.h @@ -29,6 +30,7 @@ set(HEADERS_BASE src/base/net/dns/Dns.h src/base/net/dns/DnsRecord.h src/base/net/http/Http.h + src/base/net/stratum/BaseClient.h src/base/net/stratum/Client.h src/base/net/stratum/Job.h src/base/net/stratum/Pool.h @@ -64,6 +66,7 @@ set(SOURCES_BASE src/base/net/dns/Dns.cpp src/base/net/dns/DnsRecord.cpp src/base/net/http/Http.cpp + src/base/net/stratum/BaseClient.cpp src/base/net/stratum/Client.cpp src/base/net/stratum/Job.cpp src/base/net/stratum/Pool.cpp diff --git a/src/base/kernel/interfaces/IClient.h b/src/base/kernel/interfaces/IClient.h new file mode 100644 index 00000000..52ef83a1 --- /dev/null +++ b/src/base/kernel/interfaces/IClient.h @@ -0,0 +1,84 @@ +/* XMRig + * Copyright 2010 Jeff Garzik + * Copyright 2012-2014 pooler + * Copyright 2014 Lucas Jones + * Copyright 2014-2016 Wolf9466 + * Copyright 2016 Jay D Dee + * Copyright 2017-2018 XMR-Stak , + * Copyright 2018-2019 SChernykh + * Copyright 2016-2019 XMRig , + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef XMRIG_ICLIENT_H +#define XMRIG_ICLIENT_H + + +#include + + +namespace xmrig { + + +class Algorithm; +class Job; +class JobResult; +class Pool; +class String; + + +class IClient +{ +public: + enum Extension { + EXT_ALGO, + EXT_NICEHASH, + EXT_CONNECT, + EXT_TLS, + EXT_KEEPALIVE, + EXT_MAX + }; + + virtual ~IClient() = default; + + virtual bool disconnect() = 0; + virtual bool hasExtension(Extension extension) const noexcept = 0; + virtual bool isEnabled() const = 0; + virtual bool isTLS() const = 0; + virtual const char *tlsFingerprint() const = 0; + virtual const char *tlsVersion() const = 0; + virtual const Job &job() const = 0; + virtual const Pool &pool() const = 0; + virtual const String &ip() const = 0; + virtual int id() const = 0; + virtual int64_t submit(const JobResult &result) = 0; + virtual void connect() = 0; + virtual void connect(const Pool &pool) = 0; + virtual void deleteLater() = 0; + virtual void setAlgo(const Algorithm &algo) = 0; + virtual void setEnabled(bool enabled) = 0; + virtual void setPool(const Pool &pool) = 0; + virtual void setQuiet(bool quiet) = 0; + virtual void setRetries(int retries) = 0; + virtual void setRetryPause(uint64_t ms) = 0; + virtual void tick(uint64_t now) = 0; + +}; + + +} /* namespace xmrig */ + + +#endif // XMRIG_ICLIENT_H diff --git a/src/base/kernel/interfaces/IClientListener.h b/src/base/kernel/interfaces/IClientListener.h index 753847ee..de4dd81d 100644 --- a/src/base/kernel/interfaces/IClientListener.h +++ b/src/base/kernel/interfaces/IClientListener.h @@ -35,7 +35,7 @@ namespace xmrig { -class Client; +class IClient; class Job; class SubmitResult; @@ -45,11 +45,11 @@ class IClientListener public: virtual ~IClientListener() = default; - virtual void onClose(Client *client, int failures) = 0; - virtual void onJobReceived(Client *client, const Job &job, const rapidjson::Value ¶ms) = 0; - virtual void onLogin(Client *client, rapidjson::Document &doc, rapidjson::Value ¶ms) = 0; - virtual void onLoginSuccess(Client *client) = 0; - virtual void onResultAccepted(Client *client, const SubmitResult &result, const char *error) = 0; + virtual void onClose(IClient *client, int failures) = 0; + virtual void onJobReceived(IClient *client, const Job &job, const rapidjson::Value ¶ms) = 0; + virtual void onLogin(IClient *client, rapidjson::Document &doc, rapidjson::Value ¶ms) = 0; + virtual void onLoginSuccess(IClient *client) = 0; + virtual void onResultAccepted(IClient *client, const SubmitResult &result, const char *error) = 0; }; diff --git a/src/base/kernel/interfaces/IStrategyListener.h b/src/base/kernel/interfaces/IStrategyListener.h index cbec7742..2e63449b 100644 --- a/src/base/kernel/interfaces/IStrategyListener.h +++ b/src/base/kernel/interfaces/IStrategyListener.h @@ -32,7 +32,7 @@ namespace xmrig { -class Client; +class IClient; class IStrategy; class Job; class SubmitResult; @@ -43,10 +43,10 @@ class IStrategyListener public: virtual ~IStrategyListener() = default; - virtual void onActive(IStrategy *strategy, Client *client) = 0; - virtual void onJob(IStrategy *strategy, Client *client, const Job &job) = 0; - virtual void onPause(IStrategy *strategy) = 0; - virtual void onResultAccepted(IStrategy *strategy, Client *client, const SubmitResult &result, const char *error) = 0; + virtual void onActive(IStrategy *strategy, IClient *client) = 0; + virtual void onJob(IStrategy *strategy, IClient *client, const Job &job) = 0; + virtual void onPause(IStrategy *strategy) = 0; + virtual void onResultAccepted(IStrategy *strategy, IClient *client, const SubmitResult &result, const char *error) = 0; }; diff --git a/src/base/net/stratum/BaseClient.cpp b/src/base/net/stratum/BaseClient.cpp new file mode 100644 index 00000000..9107116b --- /dev/null +++ b/src/base/net/stratum/BaseClient.cpp @@ -0,0 +1,37 @@ +/* XMRig + * Copyright 2010 Jeff Garzik + * Copyright 2012-2014 pooler + * Copyright 2014 Lucas Jones + * Copyright 2014-2016 Wolf9466 + * Copyright 2016 Jay D Dee + * Copyright 2017-2018 XMR-Stak , + * Copyright 2018-2019 SChernykh + * Copyright 2016-2019 XMRig , + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + + +#include "base/net/stratum/BaseClient.h" + + +xmrig::BaseClient::BaseClient(int id, IClientListener *listener) : + m_quiet(false), + m_listener(listener), + m_id(id), + m_retries(5), + m_retryPause(5000) +{ + +} diff --git a/src/base/net/stratum/BaseClient.h b/src/base/net/stratum/BaseClient.h new file mode 100644 index 00000000..27432a2f --- /dev/null +++ b/src/base/net/stratum/BaseClient.h @@ -0,0 +1,75 @@ +/* XMRig + * Copyright 2010 Jeff Garzik + * Copyright 2012-2014 pooler + * Copyright 2014 Lucas Jones + * Copyright 2014-2016 Wolf9466 + * Copyright 2016 Jay D Dee + * Copyright 2017-2018 XMR-Stak , + * Copyright 2018-2019 SChernykh + * Copyright 2016-2019 XMRig , + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef XMRIG_BASECLIENT_H +#define XMRIG_BASECLIENT_H + + +#include "base/kernel/interfaces/IClient.h" +#include "base/net/stratum/Job.h" +#include "base/net/stratum/Pool.h" + + +namespace xmrig { + + +class IClientListener; + + +class BaseClient : public IClient +{ +public: + BaseClient(int id, IClientListener *listener); + + inline bool isEnabled() const override { return m_enabled; } + inline const Job &job() const override { return m_job; } + inline const Pool &pool() const override { return m_pool; } + inline const String &ip() const override { return m_ip; } + inline int id() const override { return m_id; } + inline void setAlgo(const Algorithm &algo) override { m_pool.setAlgo(algo); } + inline void setEnabled(bool enabled) override { m_enabled = enabled; } + inline void setPool(const Pool &pool) override { if (pool.isValid()) { m_pool = pool; } } + inline void setQuiet(bool quiet) override { m_quiet = quiet; } + inline void setRetries(int retries) override { m_retries = retries; } + inline void setRetryPause(uint64_t ms) override { m_retryPause = ms; } + +protected: + bool m_quiet; + IClientListener *m_listener; + int m_id; + int m_retries; + Job m_job; + Pool m_pool; + String m_ip; + uint64_t m_retryPause; + +private: + bool m_enabled; +}; + + +} /* namespace xmrig */ + + +#endif /* XMRIG_BASECLIENT_H */ diff --git a/src/base/net/stratum/Client.cpp b/src/base/net/stratum/Client.cpp index dba84cb1..27075d48 100644 --- a/src/base/net/stratum/Client.cpp +++ b/src/base/net/stratum/Client.cpp @@ -75,14 +75,8 @@ static const char *states[] = { xmrig::Client::Client(int id, const char *agent, IClientListener *listener) : - m_enabled(true), - m_ipv6(false), - m_quiet(false), + BaseClient(id, listener), m_agent(agent), - m_listener(listener), - m_id(id), - m_retries(5), - m_retryPause(5000), m_failures(0), m_state(UnconnectedState), m_tls(nullptr), @@ -117,14 +111,9 @@ void xmrig::Client::connect() } -/** - * @brief Connect to server. - * - * @param url - */ -void xmrig::Client::connect(const Pool &url) +void xmrig::Client::connect(const Pool &pool) { - setPool(url); + setPool(pool); connect(); } @@ -143,17 +132,6 @@ void xmrig::Client::deleteLater() } - -void xmrig::Client::setPool(const Pool &pool) -{ - if (!pool.isValid()) { - return; - } - - m_pool = pool; -} - - void xmrig::Client::tick(uint64_t now) { if (m_state == ConnectedState) { diff --git a/src/base/net/stratum/Client.h b/src/base/net/stratum/Client.h index 65b44a5b..e334896c 100644 --- a/src/base/net/stratum/Client.h +++ b/src/base/net/stratum/Client.h @@ -34,6 +34,7 @@ #include "base/kernel/interfaces/IDnsListener.h" #include "base/kernel/interfaces/ILineListener.h" +#include "base/net/stratum/BaseClient.h" #include "base/net/stratum/Job.h" #include "base/net/stratum/Pool.h" #include "base/net/stratum/SubmitResult.h" @@ -53,26 +54,9 @@ class IClientListener; class JobResult; -class Client : public IDnsListener, public ILineListener +class Client : public BaseClient, public IDnsListener, public ILineListener { public: - enum SocketState { - UnconnectedState, - HostLookupState, - ConnectingState, - ConnectedState, - ClosingState - }; - - enum Extension { - EXT_ALGO, - EXT_NICEHASH, - EXT_CONNECT, - EXT_TLS, - EXT_KEEPALIVE, - EXT_MAX - }; - constexpr static int kResponseTimeout = 20 * 1000; # ifdef XMRIG_FEATURE_TLS @@ -84,33 +68,17 @@ public: Client(int id, const char *agent, IClientListener *listener); ~Client() override; - bool disconnect(); - bool isTLS() const; - const char *tlsFingerprint() const; - const char *tlsVersion() const; - int64_t submit(const JobResult &result); - void connect(); - void connect(const Pool &pool); - void deleteLater(); - void setPool(const Pool &pool); - void tick(uint64_t now); + bool disconnect() override; + bool isTLS() const override; + const char *tlsFingerprint() const override; + const char *tlsVersion() const override; + int64_t submit(const JobResult &result) override; + void connect() override; + void connect(const Pool &pool) override; + void deleteLater() override; + void tick(uint64_t now) override; - inline bool isEnabled() const { return m_enabled; } - inline bool isReady() const { return m_state == ConnectedState && m_failures == 0; } - inline const char *host() const { return m_pool.host(); } - inline const char *ip() const { return m_ip; } - inline const Job &job() const { return m_job; } - inline const Pool &pool() const { return m_pool; } - inline int id() const { return m_id; } - inline SocketState state() const { return m_state; } - inline uint16_t port() const { return m_pool.port(); } - inline void setAlgo(const Algorithm &algo) { m_pool.setAlgo(algo); } - inline void setEnabled(bool enabled) { m_enabled = enabled; } - inline void setQuiet(bool quiet) { m_quiet = quiet; } - inline void setRetries(int retries) { m_retries = retries; } - inline void setRetryPause(int ms) { m_retryPause = ms; } - - template inline bool has() const noexcept { return m_extensions.test(ext); } + inline bool hasExtension(Extension extension) const noexcept override { return m_extensions.test(extension); } protected: inline void onLine(char *line, size_t size) override { parse(line, size); } @@ -118,6 +86,14 @@ protected: void onResolved(const Dns &dns, int status) override; private: + enum SocketState { + UnconnectedState, + HostLookupState, + ConnectingState, + ConnectedState, + ClosingState + }; + class Tls; bool close(); @@ -145,7 +121,9 @@ private: inline bool isQuiet() const { return m_quiet || m_failures >= m_retries; } inline const char *url() const { return m_pool.url(); } + inline SocketState state() const { return m_state; } inline void setExtension(Extension ext, bool enable) noexcept { m_extensions.set(ext, enable); } + template inline bool has() const noexcept { return m_extensions.test(ext); } static void onAllocBuffer(uv_handle_t *handle, size_t suggested_size, uv_buf_t *buf); static void onClose(uv_handle_t *handle); @@ -154,24 +132,14 @@ private: static inline Client *getClient(void *data) { return m_storage.get(data); } - bool m_enabled; - bool m_ipv6; - bool m_quiet; char m_sendBuf[2048]; const char *m_agent; Dns *m_dns; - IClientListener *m_listener; - int m_id; - int m_retries; - int m_retryPause; int64_t m_failures; - Job m_job; - Pool m_pool; RecvBuf m_recvBuf; SocketState m_state; std::bitset m_extensions; std::map m_results; - String m_ip; String m_rpcId; Tls *m_tls; uint64_t m_expire; diff --git a/src/base/net/stratum/strategies/FailoverStrategy.cpp b/src/base/net/stratum/strategies/FailoverStrategy.cpp index 7a59e2a6..0c574a5d 100644 --- a/src/base/net/stratum/strategies/FailoverStrategy.cpp +++ b/src/base/net/stratum/strategies/FailoverStrategy.cpp @@ -129,7 +129,7 @@ void xmrig::FailoverStrategy::tick(uint64_t now) } -void xmrig::FailoverStrategy::onClose(Client *client, int failures) +void xmrig::FailoverStrategy::onClose(IClient *client, int failures) { if (failures == -1) { return; @@ -150,7 +150,7 @@ void xmrig::FailoverStrategy::onClose(Client *client, int failures) } -void xmrig::FailoverStrategy::onJobReceived(Client *client, const Job &job, const rapidjson::Value &) +void xmrig::FailoverStrategy::onJobReceived(IClient *client, const Job &job, const rapidjson::Value &) { if (m_active == client->id()) { m_listener->onJob(this, client, job); @@ -158,7 +158,7 @@ void xmrig::FailoverStrategy::onJobReceived(Client *client, const Job &job, cons } -void xmrig::FailoverStrategy::onLoginSuccess(Client *client) +void xmrig::FailoverStrategy::onLoginSuccess(IClient *client) { int active = m_active; @@ -179,7 +179,7 @@ void xmrig::FailoverStrategy::onLoginSuccess(Client *client) } -void xmrig::FailoverStrategy::onResultAccepted(Client *client, const SubmitResult &result, const char *error) +void xmrig::FailoverStrategy::onResultAccepted(IClient *client, const SubmitResult &result, const char *error) { m_listener->onResultAccepted(this, client, result, error); } diff --git a/src/base/net/stratum/strategies/FailoverStrategy.h b/src/base/net/stratum/strategies/FailoverStrategy.h index fcebc52f..748eddda 100644 --- a/src/base/net/stratum/strategies/FailoverStrategy.h +++ b/src/base/net/stratum/strategies/FailoverStrategy.h @@ -51,9 +51,9 @@ public: void add(const Pool &pool); protected: - inline bool isActive() const override { return m_active >= 0; } - inline Client *client() const override { return active(); } - inline void onLogin(Client *, rapidjson::Document &, rapidjson::Value &) override {} + inline bool isActive() const override { return m_active >= 0; } + inline Client *client() const override { return active(); } + inline void onLogin(IClient *, rapidjson::Document &, rapidjson::Value &) override {} int64_t submit(const JobResult &result) override; void connect() override; @@ -62,10 +62,10 @@ protected: void stop() override; void tick(uint64_t now) override; - void onClose(Client *client, int failures) override; - void onJobReceived(Client *client, const Job &job, const rapidjson::Value ¶ms) override; - void onLoginSuccess(Client *client) override; - void onResultAccepted(Client *client, const SubmitResult &result, const char *error) override; + void onClose(IClient *client, int failures) override; + void onJobReceived(IClient *client, const Job &job, const rapidjson::Value ¶ms) override; + void onLoginSuccess(IClient *client) override; + void onResultAccepted(IClient *client, const SubmitResult &result, const char *error) override; private: inline Client *active() const { return m_pools[static_cast(m_active)]; } diff --git a/src/base/net/stratum/strategies/SinglePoolStrategy.cpp b/src/base/net/stratum/strategies/SinglePoolStrategy.cpp index b81594e1..45dce5d9 100644 --- a/src/base/net/stratum/strategies/SinglePoolStrategy.cpp +++ b/src/base/net/stratum/strategies/SinglePoolStrategy.cpp @@ -87,7 +87,7 @@ void xmrig::SinglePoolStrategy::tick(uint64_t now) } -void xmrig::SinglePoolStrategy::onClose(Client *, int) +void xmrig::SinglePoolStrategy::onClose(IClient *, int) { if (!isActive()) { return; @@ -98,20 +98,20 @@ void xmrig::SinglePoolStrategy::onClose(Client *, int) } -void xmrig::SinglePoolStrategy::onJobReceived(Client *client, const Job &job, const rapidjson::Value &) +void xmrig::SinglePoolStrategy::onJobReceived(IClient *client, const Job &job, const rapidjson::Value &) { m_listener->onJob(this, client, job); } -void xmrig::SinglePoolStrategy::onLoginSuccess(Client *client) +void xmrig::SinglePoolStrategy::onLoginSuccess(IClient *client) { m_active = true; m_listener->onActive(this, client); } -void xmrig::SinglePoolStrategy::onResultAccepted(Client *client, const SubmitResult &result, const char *error) +void xmrig::SinglePoolStrategy::onResultAccepted(IClient *client, const SubmitResult &result, const char *error) { m_listener->onResultAccepted(this, client, result, error); } diff --git a/src/base/net/stratum/strategies/SinglePoolStrategy.h b/src/base/net/stratum/strategies/SinglePoolStrategy.h index 8d9f9fd1..b8a4fe1e 100644 --- a/src/base/net/stratum/strategies/SinglePoolStrategy.h +++ b/src/base/net/stratum/strategies/SinglePoolStrategy.h @@ -45,9 +45,9 @@ public: ~SinglePoolStrategy() override; protected: - inline bool isActive() const override { return m_active; } - inline Client *client() const override { return m_client; } - inline void onLogin(Client *, rapidjson::Document &, rapidjson::Value &) override {} + inline bool isActive() const override { return m_active; } + inline Client *client() const override { return m_client; } + inline void onLogin(IClient *, rapidjson::Document &, rapidjson::Value &) override {} int64_t submit(const JobResult &result) override; void connect() override; @@ -56,10 +56,10 @@ protected: void stop() override; void tick(uint64_t now) override; - void onClose(Client *client, int failures) override; - void onJobReceived(Client *client, const Job &job, const rapidjson::Value ¶ms) override; - void onLoginSuccess(Client *client) override; - void onResultAccepted(Client *client, const SubmitResult &result, const char *error) override; + void onClose(IClient *client, int failures) override; + void onJobReceived(IClient *client, const Job &job, const rapidjson::Value ¶ms) override; + void onLoginSuccess(IClient *client) override; + void onResultAccepted(IClient *client, const SubmitResult &result, const char *error) override; private: bool m_active; diff --git a/src/net/Network.cpp b/src/net/Network.cpp index be853cfa..9a9944eb 100644 --- a/src/net/Network.cpp +++ b/src/net/Network.cpp @@ -91,18 +91,18 @@ void xmrig::Network::connect() } -void xmrig::Network::onActive(IStrategy *strategy, Client *client) +void xmrig::Network::onActive(IStrategy *strategy, IClient *client) { if (m_donate && m_donate == strategy) { LOG_NOTICE("dev donate started"); return; } - m_state.setPool(client->host(), client->port(), client->ip()); + m_state.setPool(client->pool().host(), client->pool().port(), client->ip()); const char *tlsVersion = client->tlsVersion(); LOG_INFO(WHITE_BOLD("use pool ") CYAN_BOLD("%s:%d ") GREEN_BOLD("%s") " " BLACK_BOLD("%s"), - client->host(), client->port(), tlsVersion ? tlsVersion : "", client->ip()); + client->pool().host().data(), client->pool().port(), tlsVersion ? tlsVersion : "", client->ip().data()); const char *fingerprint = client->tlsFingerprint(); if (fingerprint != nullptr) { @@ -127,7 +127,7 @@ void xmrig::Network::onConfigChanged(Config *config, Config *previousConfig) } -void xmrig::Network::onJob(IStrategy *strategy, Client *client, const Job &job) +void xmrig::Network::onJob(IStrategy *strategy, IClient *client, const Job &job) { if (m_donate && m_donate->isActive() && m_donate != strategy) { return; @@ -176,7 +176,7 @@ void xmrig::Network::onRequest(IApiRequest &request) } -void xmrig::Network::onResultAccepted(IStrategy *, Client *, const SubmitResult &result, const char *error) +void xmrig::Network::onResultAccepted(IStrategy *, IClient *, const SubmitResult &result, const char *error) { m_state.add(result, error); @@ -191,15 +191,15 @@ void xmrig::Network::onResultAccepted(IStrategy *, Client *, const SubmitResult } -void xmrig::Network::setJob(Client *client, const Job &job, bool donate) +void xmrig::Network::setJob(IClient *client, const Job &job, bool donate) { if (job.height()) { LOG_INFO(MAGENTA_BOLD("new job") " from " WHITE_BOLD("%s:%d") " diff " WHITE_BOLD("%" PRIu64) " algo " WHITE_BOLD("%s") " height " WHITE_BOLD("%" PRIu64), - client->host(), client->port(), job.diff(), job.algorithm().shortName(), job.height()); + client->pool().host().data(), client->pool().port(), job.diff(), job.algorithm().shortName(), job.height()); } else { LOG_INFO(MAGENTA_BOLD("new job") " from " WHITE_BOLD("%s:%d") " diff " WHITE_BOLD("%" PRIu64) " algo " WHITE_BOLD("%s"), - client->host(), client->port(), job.diff(), job.algorithm().shortName()); + client->pool().host().data(), client->pool().port(), job.diff(), job.algorithm().shortName()); } if (!donate && m_donate) { diff --git a/src/net/Network.h b/src/net/Network.h index 1b8f4934..cee15f69 100644 --- a/src/net/Network.h +++ b/src/net/Network.h @@ -58,18 +58,18 @@ public: protected: inline void onTimer(const Timer *) override { tick(); } - void onActive(IStrategy *strategy, Client *client) override; + void onActive(IStrategy *strategy, IClient *client) override; void onConfigChanged(Config *config, Config *previousConfig) override; - void onJob(IStrategy *strategy, Client *client, const Job &job) override; + void onJob(IStrategy *strategy, IClient *client, const Job &job) override; void onJobResult(const JobResult &result) override; void onPause(IStrategy *strategy) override; void onRequest(IApiRequest &request) override; - void onResultAccepted(IStrategy *strategy, Client *client, const SubmitResult &result, const char *error) override; + void onResultAccepted(IStrategy *strategy, IClient *client, const SubmitResult &result, const char *error) override; private: constexpr static int kTickInterval = 1 * 1000; - void setJob(Client *client, const Job &job, bool donate); + void setJob(IClient *client, const Job &job, bool donate); void tick(); # ifdef XMRIG_FEATURE_API diff --git a/src/net/strategies/DonateStrategy.cpp b/src/net/strategies/DonateStrategy.cpp index 9275bde9..7a9f9e60 100644 --- a/src/net/strategies/DonateStrategy.cpp +++ b/src/net/strategies/DonateStrategy.cpp @@ -157,7 +157,7 @@ void xmrig::DonateStrategy::tick(uint64_t now) } -void xmrig::DonateStrategy::onActive(IStrategy *, Client *client) +void xmrig::DonateStrategy::onActive(IStrategy *, IClient *client) { if (isActive()) { return; @@ -173,7 +173,7 @@ void xmrig::DonateStrategy::onPause(IStrategy *) } -void xmrig::DonateStrategy::onClose(Client *, int failures) +void xmrig::DonateStrategy::onClose(IClient *, int failures) { if (failures == 2 && m_controller->config()->pools().proxyDonate() == Pools::PROXY_DONATE_AUTO) { m_proxy->deleteLater(); @@ -184,7 +184,7 @@ void xmrig::DonateStrategy::onClose(Client *, int failures) } -void xmrig::DonateStrategy::onLogin(Client *, rapidjson::Document &doc, rapidjson::Value ¶ms) +void xmrig::DonateStrategy::onLogin(IClient *, rapidjson::Document &doc, rapidjson::Value ¶ms) { auto &allocator = doc.GetAllocator(); @@ -203,7 +203,7 @@ void xmrig::DonateStrategy::onLogin(Client *, rapidjson::Document &doc, rapidjso } -void xmrig::DonateStrategy::onLoginSuccess(Client *client) +void xmrig::DonateStrategy::onLoginSuccess(IClient *client) { if (isActive()) { return; @@ -227,14 +227,14 @@ xmrig::Client *xmrig::DonateStrategy::createProxy() } IStrategy *strategy = m_controller->network()->strategy(); - if (!strategy->isActive() || !strategy->client()->has()) { + if (!strategy->isActive() || !strategy->client()->hasExtension(IClient::EXT_CONNECT)) { return nullptr; } const Client *client = strategy->client(); - m_tls = client->has(); + m_tls = client->hasExtension(IClient::EXT_TLS); - Pool pool(client->ip(), client->port(), m_userId, client->pool().password(), 0, true, client->isTLS()); + Pool pool(client->ip(), client->pool().port(), m_userId, client->pool().password(), 0, true, client->isTLS()); pool.setAlgo(client->pool().algorithm()); Client *proxy = new Client(-1, Platform::userAgent(), this); @@ -251,7 +251,7 @@ void xmrig::DonateStrategy::idle(double min, double max) } -void xmrig::DonateStrategy::setJob(Client *client, const Job &job) +void xmrig::DonateStrategy::setJob(IClient *client, const Job &job) { if (isActive()) { m_listener->onJob(this, client, job); @@ -259,7 +259,7 @@ void xmrig::DonateStrategy::setJob(Client *client, const Job &job) } -void xmrig::DonateStrategy::setResult(Client *client, const SubmitResult &result, const char *error) +void xmrig::DonateStrategy::setResult(IClient *client, const SubmitResult &result, const char *error) { m_listener->onResultAccepted(this, client, result, error); } diff --git a/src/net/strategies/DonateStrategy.h b/src/net/strategies/DonateStrategy.h index 827596f3..69bf8dbd 100644 --- a/src/net/strategies/DonateStrategy.h +++ b/src/net/strategies/DonateStrategy.h @@ -51,13 +51,13 @@ public: ~DonateStrategy() override; protected: - inline bool isActive() const override { return state() == STATE_ACTIVE; } - inline Client *client() const override { return m_proxy ? m_proxy : m_strategy->client(); } - inline void onJob(IStrategy *, Client *client, const Job &job) override { setJob(client, job); } - inline void onJobReceived(Client *client, const Job &job, const rapidjson::Value &) override { setJob(client, job); } - inline void onResultAccepted(Client *client, const SubmitResult &result, const char *error) override { setResult(client, result, error); } - inline void onResultAccepted(IStrategy *, Client *client, const SubmitResult &result, const char *error) override { setResult(client, result, error); } - inline void resume() override {} + inline bool isActive() const override { return state() == STATE_ACTIVE; } + inline Client *client() const override { return m_proxy ? m_proxy : m_strategy->client(); } + inline void onJob(IStrategy *, IClient *client, const Job &job) override { setJob(client, job); } + inline void onJobReceived(IClient *client, const Job &job, const rapidjson::Value &) override { setJob(client, job); } + inline void onResultAccepted(IClient *client, const SubmitResult &result, const char *error) override { setResult(client, result, error); } + inline void onResultAccepted(IStrategy *, IClient *client, const SubmitResult &result, const char *error) override { setResult(client, result, error); } + inline void resume() override {} int64_t submit(const JobResult &result) override; void connect() override; @@ -65,12 +65,12 @@ protected: void stop() override; void tick(uint64_t now) override; - void onActive(IStrategy *strategy, Client *client) override; + void onActive(IStrategy *strategy, IClient *client) override; void onPause(IStrategy *strategy) override; - void onClose(Client *client, int failures) override; - void onLogin(Client *client, rapidjson::Document &doc, rapidjson::Value ¶ms) override; - void onLoginSuccess(Client *client) override; + void onClose(IClient *client, int failures) override; + void onLogin(IClient *client, rapidjson::Document &doc, rapidjson::Value ¶ms) override; + void onLoginSuccess(IClient *client) override; void onTimer(const Timer *timer) override; @@ -87,8 +87,8 @@ private: Client *createProxy(); void idle(double min, double max); - void setJob(Client *client, const Job &job); - void setResult(Client *client, const SubmitResult &result, const char *error); + void setJob(IClient *client, const Job &job); + void setResult(IClient *client, const SubmitResult &result, const char *error); void setState(State state); bool m_tls; From 0d496aaf2f638e41937fe8358bc60f7695aeb4b3 Mon Sep 17 00:00:00 2001 From: XMRig Date: Thu, 11 Apr 2019 00:18:33 +0700 Subject: [PATCH 079/116] Prepare for daemon support. --- src/base/kernel/interfaces/IClient.h | 1 + src/base/net/stratum/Client.h | 1 + src/base/net/stratum/Job.cpp | 6 +- src/base/net/stratum/Job.h | 4 +- src/base/net/stratum/Pool.cpp | 117 ++++++++++++++++++--------- src/base/net/stratum/Pool.h | 9 ++- src/net/Network.cpp | 5 +- src/net/Network.h | 1 + 8 files changed, 97 insertions(+), 47 deletions(-) diff --git a/src/base/kernel/interfaces/IClient.h b/src/base/kernel/interfaces/IClient.h index 52ef83a1..c872a37a 100644 --- a/src/base/kernel/interfaces/IClient.h +++ b/src/base/kernel/interfaces/IClient.h @@ -57,6 +57,7 @@ public: virtual bool hasExtension(Extension extension) const noexcept = 0; virtual bool isEnabled() const = 0; virtual bool isTLS() const = 0; + virtual const char *mode() const = 0; virtual const char *tlsFingerprint() const = 0; virtual const char *tlsVersion() const = 0; virtual const Job &job() const = 0; diff --git a/src/base/net/stratum/Client.h b/src/base/net/stratum/Client.h index e334896c..b42fa613 100644 --- a/src/base/net/stratum/Client.h +++ b/src/base/net/stratum/Client.h @@ -79,6 +79,7 @@ public: void tick(uint64_t now) override; inline bool hasExtension(Extension extension) const noexcept override { return m_extensions.test(extension); } + inline const char *mode() const override { return "pool"; } protected: inline void onLine(char *line, size_t size) override { parse(line, size); } diff --git a/src/base/net/stratum/Job.cpp b/src/base/net/stratum/Job.cpp index f8239459..8ef607ad 100644 --- a/src/base/net/stratum/Job.cpp +++ b/src/base/net/stratum/Job.cpp @@ -7,6 +7,7 @@ * Copyright 2017-2018 XMR-Stak , * Copyright 2018 Lee Clagett * Copyright 2018 SChernykh + * Copyright 2019 Howard Chu * Copyright 2016-2019 XMRig , * * This program is free software: you can redistribute it and/or modify @@ -180,9 +181,10 @@ void xmrig::Job::setAlgorithm(const char *algo) } -void xmrig::Job::setHeight(uint64_t height) +void xmrig::Job::setDiff(uint64_t diff) { - m_height = height; + m_diff = diff; + m_target = toDiff(diff); } diff --git a/src/base/net/stratum/Job.h b/src/base/net/stratum/Job.h index c8dced4b..16e9a861 100644 --- a/src/base/net/stratum/Job.h +++ b/src/base/net/stratum/Job.h @@ -7,6 +7,7 @@ * Copyright 2017-2018 XMR-Stak , * Copyright 2018 Lee Clagett * Copyright 2018-2019 SChernykh + * Copyright 2019 Howard Chu * Copyright 2016-2019 XMRig , * * This program is free software: you can redistribute it and/or modify @@ -53,7 +54,7 @@ public: bool setBlob(const char *blob); bool setTarget(const char *target); void setAlgorithm(const char *algo); - void setHeight(uint64_t height); + void setDiff(uint64_t diff); inline bool isNicehash() const { return m_nicehash; } inline bool isValid() const { return m_size > 0 && m_diff > 0; } @@ -73,6 +74,7 @@ public: inline uint8_t fixedByte() const { return *(m_blob + 42); } inline void reset() { m_size = 0; m_diff = 0; } inline void setClientId(const String &id) { m_clientId = id; } + inline void setHeight(uint64_t height) { m_height = height; } inline void setPoolId(int poolId) { m_poolId = poolId; } inline void setThreadId(int threadId) { m_threadId = threadId; } inline void setVariant(const char *variant) { m_algorithm.parseVariant(variant); } diff --git a/src/base/net/stratum/Pool.cpp b/src/base/net/stratum/Pool.cpp index 25fd13aa..d23781ad 100644 --- a/src/base/net/stratum/Pool.cpp +++ b/src/base/net/stratum/Pool.cpp @@ -6,6 +6,7 @@ * Copyright 2016 Jay D Dee * Copyright 2017-2019 XMR-Stak , * Copyright 2018-2019 SChernykh + * Copyright 2019 Howard Chu * Copyright 2016-2019 XMRig , * * This program is free software: you can redistribute it and/or modify @@ -41,25 +42,34 @@ #ifdef _MSC_VER # define strncasecmp _strnicmp -# define strcasecmp _stricmp #endif namespace xmrig { -static const char *kEnabled = "enabled"; -static const char *kFingerprint = "tls-fingerprint"; -static const char *kKeepalive = "keepalive"; -static const char *kNicehash = "nicehash"; -static const char *kPass = "pass"; -static const char *kRigId = "rig-id"; -static const char *kTls = "tls"; -static const char *kUrl = "url"; -static const char *kUser = "user"; -static const char *kVariant = "variant"; +static const char *kDaemon = "daemon"; +static const char *kDaemonPollInterval = "daemon-poll-interval"; +static const char *kEnabled = "enabled"; +static const char *kFingerprint = "tls-fingerprint"; +static const char *kKeepalive = "keepalive"; +static const char *kNicehash = "nicehash"; +static const char *kPass = "pass"; +static const char *kRigId = "rig-id"; +static const char *kTls = "tls"; +static const char *kUrl = "url"; +static const char *kUser = "user"; +static const char *kVariant = "variant"; -const String Pool::kDefaultPassword = "x"; -const String Pool::kDefaultUser = "x"; +const String Pool::kDefaultPassword = "x"; +const String Pool::kDefaultUser = "x"; + +static const char kStratumTcp[] = "stratum+tcp://"; +static const char kStratumSsl[] = "stratum+ssl://"; + +#ifdef XMRIG_FEATURE_HTTP +static const char kDaemonHttp[] = "daemon+http://"; +static const char kDaemonHttps[] = "daemon+https://"; +#endif } @@ -67,7 +77,8 @@ const String Pool::kDefaultUser = "x"; xmrig::Pool::Pool() : m_keepAlive(0), m_flags(0), - m_port(kDefaultPort) + m_port(kDefaultPort), + m_pollInterval(kDefaultPollInterval) { } @@ -86,7 +97,8 @@ xmrig::Pool::Pool() : xmrig::Pool::Pool(const char *url) : m_keepAlive(0), m_flags(1), - m_port(kDefaultPort) + m_port(kDefaultPort), + m_pollInterval(kDefaultPollInterval) { parse(url); } @@ -95,20 +107,23 @@ xmrig::Pool::Pool(const char *url) : xmrig::Pool::Pool(const rapidjson::Value &object) : m_keepAlive(0), m_flags(1), - m_port(kDefaultPort) + m_port(kDefaultPort), + m_pollInterval(kDefaultPollInterval) { if (!parse(Json::getString(object, kUrl))) { return; } - m_user = Json::getString(object, kUser); - m_password = Json::getString(object, kPass); - m_rigId = Json::getString(object, kRigId); - m_fingerprint = Json::getString(object, kFingerprint); + m_user = Json::getString(object, kUser); + m_password = Json::getString(object, kPass); + m_rigId = Json::getString(object, kRigId); + m_fingerprint = Json::getString(object, kFingerprint); + m_pollInterval = Json::getUint64(object, kDaemonPollInterval, kDefaultPollInterval); m_flags.set(FLAG_ENABLED, Json::getBool(object, kEnabled, true)); m_flags.set(FLAG_NICEHASH, Json::getBool(object, kNicehash)); m_flags.set(FLAG_TLS, Json::getBool(object, kTls, m_flags.test(FLAG_TLS))); + m_flags.set(FLAG_DAEMON, Json::getBool(object, kDaemon, m_flags.test(FLAG_DAEMON))); const rapidjson::Value &keepalive = Json::getValue(object, kKeepalive); if (keepalive.IsInt()) { @@ -135,7 +150,8 @@ xmrig::Pool::Pool(const char *host, uint16_t port, const char *user, const char m_host(host), m_password(password), m_user(user), - m_port(port) + m_port(port), + m_pollInterval(kDefaultPollInterval) { const size_t size = m_host.size() + 8; assert(size > 8); @@ -180,22 +196,29 @@ bool xmrig::Pool::isEnabled() const } # endif +# ifndef XMRIG_FEATURE_HTTP + if (isDaemon()) { + return false; + } +# endif + return m_flags.test(FLAG_ENABLED) && isValid() && algorithm().isValid(); } bool xmrig::Pool::isEqual(const Pool &other) const { - return (m_flags == other.m_flags - && m_keepAlive == other.m_keepAlive - && m_port == other.m_port - && m_algorithm == other.m_algorithm - && m_fingerprint == other.m_fingerprint - && m_host == other.m_host - && m_password == other.m_password - && m_rigId == other.m_rigId - && m_url == other.m_url - && m_user == other.m_user); + return (m_flags == other.m_flags + && m_keepAlive == other.m_keepAlive + && m_port == other.m_port + && m_algorithm == other.m_algorithm + && m_fingerprint == other.m_fingerprint + && m_host == other.m_host + && m_password == other.m_password + && m_rigId == other.m_rigId + && m_url == other.m_url + && m_user == other.m_user + && m_pollInterval == other.m_pollInterval); } @@ -203,21 +226,33 @@ bool xmrig::Pool::parse(const char *url) { assert(url != nullptr); - const char *p = strstr(url, "://"); + const char *p = strstr(url, "://"); const char *base = url; if (p) { - if (strncasecmp(url, "stratum+tcp://", 14) == 0) { - m_flags.set(FLAG_TLS, false); + if (strncasecmp(url, kStratumTcp, sizeof(kStratumTcp) - 1) == 0) { + m_flags.set(FLAG_DAEMON, false); + m_flags.set(FLAG_TLS, false); } - else if (strncasecmp(url, "stratum+ssl://", 14) == 0) { - m_flags.set(FLAG_TLS, true); + else if (strncasecmp(url, kStratumSsl, sizeof(kStratumSsl) - 1) == 0) { + m_flags.set(FLAG_DAEMON, false); + m_flags.set(FLAG_TLS, true); } +# ifdef XMRIG_FEATURE_HTTP + else if (strncasecmp(url, kDaemonHttps, sizeof(kDaemonHttps) - 1) == 0) { + m_flags.set(FLAG_DAEMON, true); + m_flags.set(FLAG_TLS, true); + } + else if (strncasecmp(url, kDaemonHttp, sizeof(kDaemonHttp) - 1) == 0) { + m_flags.set(FLAG_DAEMON, true); + m_flags.set(FLAG_TLS, false); + } +# endif else { return false; } - base = url + 14; + base = p + 3; } if (!strlen(base) || *base == '/') { @@ -286,9 +321,11 @@ rapidjson::Value xmrig::Pool::toJSON(rapidjson::Document &doc) const break; } - obj.AddMember(StringRef(kEnabled), m_flags.test(FLAG_ENABLED), allocator); - obj.AddMember(StringRef(kTls), isTLS(), allocator); - obj.AddMember(StringRef(kFingerprint), m_fingerprint.toJSON(), allocator); + obj.AddMember(StringRef(kEnabled), m_flags.test(FLAG_ENABLED), allocator); + obj.AddMember(StringRef(kTls), isTLS(), allocator); + obj.AddMember(StringRef(kFingerprint), m_fingerprint.toJSON(), allocator); + obj.AddMember(StringRef(kDaemon), m_flags.test(FLAG_DAEMON), allocator); + obj.AddMember(StringRef(kDaemonPollInterval), m_pollInterval, allocator); return obj; } diff --git a/src/base/net/stratum/Pool.h b/src/base/net/stratum/Pool.h index c8a7c44b..d3c9b141 100644 --- a/src/base/net/stratum/Pool.h +++ b/src/base/net/stratum/Pool.h @@ -6,6 +6,7 @@ * Copyright 2016 Jay D Dee * Copyright 2017-2018 XMR-Stak , * Copyright 2018-2019 SChernykh + * Copyright 2019 Howard Chu * Copyright 2016-2019 XMRig , * * This program is free software: you can redistribute it and/or modify @@ -45,14 +46,16 @@ public: FLAG_ENABLED, FLAG_NICEHASH, FLAG_TLS, + FLAG_DAEMON, FLAG_MAX }; static const String kDefaultPassword; static const String kDefaultUser; - constexpr static uint16_t kDefaultPort = 3333; - constexpr static int kKeepAliveTimeout = 60; + constexpr static int kKeepAliveTimeout = 60; + constexpr static uint16_t kDefaultPort = 3333; + constexpr static uint64_t kDefaultPollInterval = 1000; Pool(); Pool(const char *url); @@ -67,6 +70,7 @@ public: ); inline Algorithm &algorithm() { return m_algorithm; } + inline bool isDaemon() const { return m_flags.test(FLAG_DAEMON); } inline bool isNicehash() const { return m_flags.test(FLAG_NICEHASH); } inline bool isTLS() const { return m_flags.test(FLAG_TLS); } inline bool isValid() const { return !m_host.isNull() && m_port > 0; } @@ -116,6 +120,7 @@ private: String m_url; String m_user; uint16_t m_port; + uint64_t m_pollInterval; }; diff --git a/src/net/Network.cpp b/src/net/Network.cpp index 9a9944eb..cc5d59e4 100644 --- a/src/net/Network.cpp +++ b/src/net/Network.cpp @@ -6,6 +6,7 @@ * Copyright 2016 Jay D Dee * Copyright 2017-2018 XMR-Stak , * Copyright 2018-2019 SChernykh + * Copyright 2019 Howard Chu * Copyright 2016-2019 XMRig , * * This program is free software: you can redistribute it and/or modify @@ -101,8 +102,8 @@ void xmrig::Network::onActive(IStrategy *strategy, IClient *client) m_state.setPool(client->pool().host(), client->pool().port(), client->ip()); const char *tlsVersion = client->tlsVersion(); - LOG_INFO(WHITE_BOLD("use pool ") CYAN_BOLD("%s:%d ") GREEN_BOLD("%s") " " BLACK_BOLD("%s"), - client->pool().host().data(), client->pool().port(), tlsVersion ? tlsVersion : "", client->ip().data()); + LOG_INFO(WHITE_BOLD("use %s ") CYAN_BOLD("%s:%d ") GREEN_BOLD("%s") " " BLACK_BOLD("%s"), + client->mode(), client->pool().host().data(), client->pool().port(), tlsVersion ? tlsVersion : "", client->ip().data()); const char *fingerprint = client->tlsFingerprint(); if (fingerprint != nullptr) { diff --git a/src/net/Network.h b/src/net/Network.h index cee15f69..079d997a 100644 --- a/src/net/Network.h +++ b/src/net/Network.h @@ -6,6 +6,7 @@ * Copyright 2016 Jay D Dee * Copyright 2017-2018 XMR-Stak , * Copyright 2018-2019 SChernykh + * Copyright 2019 Howard Chu * Copyright 2016-2019 XMRig , * * This program is free software: you can redistribute it and/or modify From cf7ce13986e81b7c359a08149bb97b4d78901c04 Mon Sep 17 00:00:00 2001 From: stoffu Date: Thu, 11 Apr 2019 14:01:07 +0900 Subject: [PATCH 080/116] Config: fix std::max issue with msvc2017 to fix the following errors: xmrig\src\core\Config.cpp(165): error C2065: 'max': undeclared identifier xmrig\src\core\Config.cpp(165): error C2275: 'size_t': illegal use of this type as an expression --- src/core/Config.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/core/Config.cpp b/src/core/Config.cpp index 82a96117..9216027a 100644 --- a/src/core/Config.cpp +++ b/src/core/Config.cpp @@ -22,6 +22,7 @@ * along with this program. If not, see . */ +#include #include #include #include From 62012a1a50a6bcddd905e60c88f330ec41e5c6e3 Mon Sep 17 00:00:00 2001 From: XMRig Date: Fri, 12 Apr 2019 03:25:21 +0700 Subject: [PATCH 081/116] Added DaemonClient. --- src/base/base.cmake | 2 + src/base/kernel/interfaces/IStrategy.h | 4 +- src/base/net/http/HttpClient.cpp | 28 +- src/base/net/http/HttpClient.h | 4 +- src/base/net/http/HttpContext.cpp | 10 +- src/base/net/http/HttpContext.h | 2 +- src/base/net/http/HttpsClient.cpp | 4 +- src/base/net/stratum/BaseClient.cpp | 27 +- src/base/net/stratum/BaseClient.h | 21 ++ src/base/net/stratum/Client.cpp | 122 +++--- src/base/net/stratum/Client.h | 25 +- src/base/net/stratum/DaemonClient.cpp | 350 ++++++++++++++++++ src/base/net/stratum/DaemonClient.h | 78 ++++ src/base/net/stratum/Pool.h | 1 + .../stratum/strategies/FailoverStrategy.cpp | 21 +- .../net/stratum/strategies/FailoverStrategy.h | 6 +- .../stratum/strategies/SinglePoolStrategy.cpp | 15 + .../stratum/strategies/SinglePoolStrategy.h | 4 +- src/net/strategies/DonateStrategy.cpp | 4 +- src/net/strategies/DonateStrategy.h | 4 +- 20 files changed, 610 insertions(+), 122 deletions(-) create mode 100644 src/base/net/stratum/DaemonClient.cpp create mode 100644 src/base/net/stratum/DaemonClient.h diff --git a/src/base/base.cmake b/src/base/base.cmake index 3c7ee1b3..6d478b39 100644 --- a/src/base/base.cmake +++ b/src/base/base.cmake @@ -108,6 +108,7 @@ if (WITH_HTTP) src/base/net/http/HttpData.h src/base/net/http/HttpResponse.h src/base/net/http/HttpServer.h + src/base/net/stratum/DaemonClient.h src/base/net/tools/TcpServer.h ) @@ -118,6 +119,7 @@ if (WITH_HTTP) src/base/net/http/HttpContext.cpp src/base/net/http/HttpResponse.cpp src/base/net/http/HttpServer.cpp + src/base/net/stratum/DaemonClient.cpp src/base/net/tools/TcpServer.cpp ) diff --git a/src/base/kernel/interfaces/IStrategy.h b/src/base/kernel/interfaces/IStrategy.h index 31798b9c..f2e58408 100644 --- a/src/base/kernel/interfaces/IStrategy.h +++ b/src/base/kernel/interfaces/IStrategy.h @@ -33,7 +33,7 @@ namespace xmrig { class Algorithm; -class Client; +class IClient; class JobResult; @@ -43,7 +43,7 @@ public: virtual ~IStrategy() = default; virtual bool isActive() const = 0; - virtual Client *client() const = 0; + virtual IClient *client() const = 0; virtual int64_t submit(const JobResult &result) = 0; virtual void connect() = 0; virtual void resume() = 0; diff --git a/src/base/net/http/HttpClient.cpp b/src/base/net/http/HttpClient.cpp index a512989c..d58e7299 100644 --- a/src/base/net/http/HttpClient.cpp +++ b/src/base/net/http/HttpClient.cpp @@ -40,11 +40,11 @@ namespace xmrig { static const char *kCRLF = "\r\n"; -class WriteBaton : public Baton +class ClientWriteBaton : public Baton { public: - inline WriteBaton(const std::string &header, std::string &&body) : - m_body(body), + inline ClientWriteBaton(const std::string &header, std::string &&body) : + m_body(std::move(body)), m_header(header) { bufs[0].len = m_header.size(); @@ -63,7 +63,7 @@ public: inline size_t count() const { return bufs[1].base == nullptr ? 1 : 2; } inline size_t size() const { return bufs[0].len + bufs[1].len; } - inline static void onWrite(uv_write_t *req, int) { delete reinterpret_cast(req->data); } + inline static void onWrite(uv_write_t *req, int) { delete reinterpret_cast(req->data); } uv_buf_t bufs[2]; @@ -117,7 +117,9 @@ void xmrig::HttpClient::onResolved(const Dns &dns, int status) this->status = status; if (status < 0 && dns.isEmpty()) { - LOG_ERR("[%s:%d] DNS error: \"%s\"", dns.host().data(), m_port, uv_strerror(status)); + if (!m_quiet) { + LOG_ERR("[%s:%d] DNS error: \"%s\"", dns.host().data(), m_port, uv_strerror(status)); + } return; } @@ -159,15 +161,15 @@ void xmrig::HttpClient::handshake() void xmrig::HttpClient::read(const char *data, size_t size) { if (parse(data, size) < size) { - close(); + close(UV_EPROTO); } } void xmrig::HttpClient::write(const std::string &header) { - WriteBaton *baton = new WriteBaton(header, std::move(body)); - uv_write(&baton->req, stream(), baton->bufs, baton->count(), WriteBaton::onWrite); + ClientWriteBaton *baton = new ClientWriteBaton(header, std::move(body)); + uv_write(&baton->req, stream(), baton->bufs, baton->count(), ClientWriteBaton::onWrite); } @@ -180,10 +182,12 @@ void xmrig::HttpClient::onConnect(uv_connect_t *req, int status) } if (status < 0) { - LOG_ERR("[%s:%d] connect error: \"%s\"", client->m_dns->host().data(), client->m_port, uv_strerror(status)); + if (!client->m_quiet) { + LOG_ERR("[%s:%d] connect error: \"%s\"", client->m_dns->host().data(), client->m_port, uv_strerror(status)); + } delete req; - client->close(); + client->close(status); return; } @@ -205,11 +209,11 @@ void xmrig::HttpClient::onConnect(uv_connect_t *req, int status) if (nread >= 0) { client->read(buf->base, static_cast(nread)); } else { - if (nread != UV_EOF) { + if (!client->m_quiet && nread != UV_EOF) { LOG_ERR("[%s:%d] read error: \"%s\"", client->m_dns->host().data(), client->m_port, uv_strerror(static_cast(nread))); } - client->close(); + client->close(static_cast(nread)); } delete [] buf->base; diff --git a/src/base/net/http/HttpClient.h b/src/base/net/http/HttpClient.h index b92c4733..e9866483 100644 --- a/src/base/net/http/HttpClient.h +++ b/src/base/net/http/HttpClient.h @@ -44,7 +44,8 @@ public: HttpClient(int method, const String &url, IHttpListener *listener, const char *data = nullptr, size_t size = 0); ~HttpClient() override; - inline uint16_t port() const { return m_port; } + inline uint16_t port() const { return m_port; } + inline void setQuiet(bool quiet) { m_quiet = quiet; } bool connect(const String &host, uint16_t port); const String &host() const; @@ -59,6 +60,7 @@ protected: private: static void onConnect(uv_connect_t *req, int status); + bool m_quiet; Dns *m_dns; uint16_t m_port; }; diff --git a/src/base/net/http/HttpContext.cpp b/src/base/net/http/HttpContext.cpp index c98b4ad2..e97f989b 100644 --- a/src/base/net/http/HttpContext.cpp +++ b/src/base/net/http/HttpContext.cpp @@ -96,8 +96,13 @@ std::string xmrig::HttpContext::ip() const } -void xmrig::HttpContext::close() +void xmrig::HttpContext::close(int status) { + if (status < 0 && m_listener) { + this->status = status; + m_listener->onHttpData(*this); + } + auto it = storage.find(id()); if (it != storage.end()) { storage.erase(it); @@ -203,8 +208,9 @@ void xmrig::HttpContext::attach(http_parser_settings *settings) settings->on_message_complete = [](http_parser *parser) -> int { - const HttpContext *ctx = static_cast(parser->data); + HttpContext *ctx = static_cast(parser->data); ctx->m_listener->onHttpData(*ctx); + ctx->m_listener = nullptr; return 0; }; diff --git a/src/base/net/http/HttpContext.h b/src/base/net/http/HttpContext.h index ee11a072..fbb453aa 100644 --- a/src/base/net/http/HttpContext.h +++ b/src/base/net/http/HttpContext.h @@ -56,7 +56,7 @@ public: size_t parse(const char *data, size_t size); std::string ip() const; - void close(); + void close(int status = 0); static HttpContext *get(uint64_t id); static void closeAll(); diff --git a/src/base/net/http/HttpsClient.cpp b/src/base/net/http/HttpsClient.cpp index 8fd26a2e..ff103a34 100644 --- a/src/base/net/http/HttpsClient.cpp +++ b/src/base/net/http/HttpsClient.cpp @@ -96,7 +96,7 @@ void xmrig::HttpsClient::read(const char *data, size_t size) X509 *cert = SSL_get_peer_certificate(m_ssl); if (!verify(cert)) { X509_free(cert); - return close(); + return close(UV_EPROTO); } X509_free(cert); @@ -142,7 +142,7 @@ void xmrig::HttpsClient::flush() result = uv_try_write(stream(), &buf, 1) == buf.len; if (!result) { - close(); + close(UV_EIO); } } diff --git a/src/base/net/stratum/BaseClient.cpp b/src/base/net/stratum/BaseClient.cpp index 9107116b..f44415d5 100644 --- a/src/base/net/stratum/BaseClient.cpp +++ b/src/base/net/stratum/BaseClient.cpp @@ -23,7 +23,16 @@ */ +#include "base/kernel/interfaces/IClientListener.h" #include "base/net/stratum/BaseClient.h" +#include "base/net/stratum/SubmitResult.h" + + +namespace xmrig { + +int64_t BaseClient::m_sequence = 1; + +} /* namespace xmrig */ xmrig::BaseClient::BaseClient(int id, IClientListener *listener) : @@ -31,7 +40,23 @@ xmrig::BaseClient::BaseClient(int id, IClientListener *listener) : m_listener(listener), m_id(id), m_retries(5), + m_failures(0), + m_state(UnconnectedState), m_retryPause(5000) { - +} + + +bool xmrig::BaseClient::handleSubmitResponse(int64_t id, const char *error) +{ + auto it = m_results.find(id); + if (it != m_results.end()) { + it->second.done(); + m_listener->onResultAccepted(this, it->second, error); + m_results.erase(it); + + return true; + } + + return false; } diff --git a/src/base/net/stratum/BaseClient.h b/src/base/net/stratum/BaseClient.h index 27432a2f..9e1c7ffb 100644 --- a/src/base/net/stratum/BaseClient.h +++ b/src/base/net/stratum/BaseClient.h @@ -26,6 +26,9 @@ #define XMRIG_BASECLIENT_H +#include + + #include "base/kernel/interfaces/IClient.h" #include "base/net/stratum/Job.h" #include "base/net/stratum/Pool.h" @@ -35,6 +38,7 @@ namespace xmrig { class IClientListener; +class SubmitResult; class BaseClient : public IClient @@ -55,15 +59,32 @@ public: inline void setRetryPause(uint64_t ms) override { m_retryPause = ms; } protected: + enum SocketState { + UnconnectedState, + HostLookupState, + ConnectingState, + ConnectedState, + ClosingState + }; + + inline bool isQuiet() const { return m_quiet || m_failures >= m_retries; } + + bool handleSubmitResponse(int64_t id, const char *error = nullptr); + bool m_quiet; IClientListener *m_listener; int m_id; int m_retries; + int64_t m_failures; Job m_job; Pool m_pool; + SocketState m_state; + std::map m_results; String m_ip; uint64_t m_retryPause; + static int64_t m_sequence; + private: bool m_enabled; }; diff --git a/src/base/net/stratum/Client.cpp b/src/base/net/stratum/Client.cpp index 27075d48..df6f4837 100644 --- a/src/base/net/stratum/Client.cpp +++ b/src/base/net/stratum/Client.cpp @@ -57,7 +57,6 @@ namespace xmrig { -int64_t Client::m_sequence = 1; Storage Client::m_storage; } /* namespace xmrig */ @@ -77,8 +76,6 @@ static const char *states[] = { xmrig::Client::Client(int id, const char *agent, IClientListener *listener) : BaseClient(id, listener), m_agent(agent), - m_failures(0), - m_state(UnconnectedState), m_tls(nullptr), m_expire(0), m_jobs(0), @@ -99,57 +96,6 @@ xmrig::Client::~Client() } -void xmrig::Client::connect() -{ -# ifdef XMRIG_FEATURE_TLS - if (m_pool.isTLS()) { - m_tls = new Tls(this); - } -# endif - - resolve(m_pool.host()); -} - - -void xmrig::Client::connect(const Pool &pool) -{ - setPool(pool); - connect(); -} - - -void xmrig::Client::deleteLater() -{ - if (!m_listener) { - return; - } - - m_listener = nullptr; - - if (!disconnect()) { - m_storage.remove(m_key); - } -} - - -void xmrig::Client::tick(uint64_t now) -{ - if (m_state == ConnectedState) { - if (m_expire && now > m_expire) { - LOG_DEBUG_ERR("[%s] timeout", url()); - close(); - } - else if (m_keepAlive && now > m_keepAlive) { - ping(); - } - } - - if (m_expire && now > m_expire && m_state == ConnectingState) { - connect(); - } -} - - bool xmrig::Client::disconnect() { m_keepAlive = 0; @@ -247,6 +193,57 @@ int64_t xmrig::Client::submit(const JobResult &result) } +void xmrig::Client::connect() +{ +# ifdef XMRIG_FEATURE_TLS + if (m_pool.isTLS()) { + m_tls = new Tls(this); + } +# endif + + resolve(m_pool.host()); +} + + +void xmrig::Client::connect(const Pool &pool) +{ + setPool(pool); + connect(); +} + + +void xmrig::Client::deleteLater() +{ + if (!m_listener) { + return; + } + + m_listener = nullptr; + + if (!disconnect()) { + m_storage.remove(m_key); + } +} + + +void xmrig::Client::tick(uint64_t now) +{ + if (m_state == ConnectedState) { + if (m_expire && now > m_expire) { + LOG_DEBUG_ERR("[%s] timeout", url()); + close(); + } + else if (m_keepAlive && now > m_keepAlive) { + ping(); + } + } + + if (m_expire && now > m_expire && m_state == ConnectingState) { + connect(); + } +} + + void xmrig::Client::onResolved(const Dns &dns, int status) { assert(m_listener != nullptr); @@ -749,14 +746,8 @@ void xmrig::Client::parseResponse(int64_t id, const rapidjson::Value &result, co if (error.IsObject()) { const char *message = error["message"].GetString(); - auto it = m_results.find(id); - if (it != m_results.end()) { - it->second.done(); - m_listener->onResultAccepted(this, it->second, message); - m_results.erase(it); - } - else if (!isQuiet()) { - LOG_ERR("[%s] error: \"%s\", code: %d", url(), message, error["code"].GetInt()); + if (!handleSubmitResponse(id, message) && !isQuiet()) { + LOG_ERR("[%s] error: " RED_BOLD("\"%s\"") RED_S ", code: %d", url(), message, error["code"].GetInt()); } if (isCriticalError(message)) { @@ -787,12 +778,7 @@ void xmrig::Client::parseResponse(int64_t id, const rapidjson::Value &result, co return; } - auto it = m_results.find(id); - if (it != m_results.end()) { - it->second.done(); - m_listener->onResultAccepted(this, it->second, nullptr); - m_results.erase(it); - } + handleSubmitResponse(id); } diff --git a/src/base/net/stratum/Client.h b/src/base/net/stratum/Client.h index b42fa613..c7aeabfe 100644 --- a/src/base/net/stratum/Client.h +++ b/src/base/net/stratum/Client.h @@ -43,7 +43,6 @@ #include "common/crypto/Algorithm.h" - typedef struct bio_st BIO; @@ -68,6 +67,7 @@ public: Client(int id, const char *agent, IClientListener *listener); ~Client() override; +protected: bool disconnect() override; bool isTLS() const override; const char *tlsFingerprint() const override; @@ -78,23 +78,13 @@ public: void deleteLater() override; void tick(uint64_t now) override; - inline bool hasExtension(Extension extension) const noexcept override { return m_extensions.test(extension); } - inline const char *mode() const override { return "pool"; } - -protected: - inline void onLine(char *line, size_t size) override { parse(line, size); } - void onResolved(const Dns &dns, int status) override; -private: - enum SocketState { - UnconnectedState, - HostLookupState, - ConnectingState, - ConnectedState, - ClosingState - }; + inline bool hasExtension(Extension extension) const noexcept override { return m_extensions.test(extension); } + inline const char *mode() const override { return "pool"; } + inline void onLine(char *line, size_t size) override { parse(line, size); } +private: class Tls; bool close(); @@ -120,7 +110,6 @@ private: void setState(SocketState state); void startTimeout(); - inline bool isQuiet() const { return m_quiet || m_failures >= m_retries; } inline const char *url() const { return m_pool.url(); } inline SocketState state() const { return m_state; } inline void setExtension(Extension ext, bool enable) noexcept { m_extensions.set(ext, enable); } @@ -136,11 +125,8 @@ private: char m_sendBuf[2048]; const char *m_agent; Dns *m_dns; - int64_t m_failures; RecvBuf m_recvBuf; - SocketState m_state; std::bitset m_extensions; - std::map m_results; String m_rpcId; Tls *m_tls; uint64_t m_expire; @@ -150,7 +136,6 @@ private: uv_stream_t *m_stream; uv_tcp_t *m_socket; - static int64_t m_sequence; static Storage m_storage; }; diff --git a/src/base/net/stratum/DaemonClient.cpp b/src/base/net/stratum/DaemonClient.cpp new file mode 100644 index 00000000..a5aef54d --- /dev/null +++ b/src/base/net/stratum/DaemonClient.cpp @@ -0,0 +1,350 @@ +/* XMRig + * Copyright 2010 Jeff Garzik + * Copyright 2012-2014 pooler + * Copyright 2014 Lucas Jones + * Copyright 2014-2016 Wolf9466 + * Copyright 2016 Jay D Dee + * Copyright 2017-2018 XMR-Stak , + * Copyright 2018-2019 SChernykh + * Copyright 2019 Howard Chu + * Copyright 2016-2019 XMRig , + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + + +#include +#include + + +#include "3rdparty/http-parser/http_parser.h" +#include "base/io/Json.h" +#include "base/io/log/Log.h" +#include "base/kernel/interfaces/IClientListener.h" +#include "base/net/http/HttpClient.h" +#include "base/net/stratum/DaemonClient.h" +#include "base/net/stratum/SubmitResult.h" +#include "base/tools/Buffer.h" +#include "base/tools/Timer.h" +#include "net/JobResult.h" +#include "rapidjson/document.h" +#include "rapidjson/error/en.h" +#include "rapidjson/stringbuffer.h" +#include "rapidjson/writer.h" + + +#ifdef XMRIG_FEATURE_TLS +# include "base/net/http/HttpsClient.h" +#endif + + +xmrig::DaemonClient::DaemonClient(int id, IClientListener *listener) : + BaseClient(id, listener) +{ + m_timer = new Timer(this); +} + + +xmrig::DaemonClient::~DaemonClient() +{ + delete m_timer; +} + + +bool xmrig::DaemonClient::disconnect() +{ + setState(UnconnectedState); + + return true; +} + + +bool xmrig::DaemonClient::isTLS() const +{ + return false; +} + + +const char *xmrig::DaemonClient::tlsFingerprint() const +{ + return nullptr; +} + + +const char *xmrig::DaemonClient::tlsVersion() const +{ + return nullptr; +} + + +int64_t xmrig::DaemonClient::submit(const JobResult &result) +{ + if (result.jobId != (m_blocktemplate.data() + m_blocktemplate.size() - 48)) { + return -1; + } + + Buffer::toHex(reinterpret_cast(&result.nonce), 4, m_blocktemplate.data() + 78); + + using namespace rapidjson; + Document doc(kObjectType); + auto &allocator = doc.GetAllocator(); + + doc.AddMember("id", m_sequence, allocator); + doc.AddMember("jsonrpc", "2.0", allocator); + doc.AddMember("method", "submitblock", allocator); + + Value params(kArrayType); + params.PushBack(m_blocktemplate.toJSON(), allocator); + + doc.AddMember("params", params, allocator); + +# ifdef XMRIG_PROXY_PROJECT + m_results[m_sequence] = SubmitResult(m_sequence, result.diff, result.actualDiff(), result.id); +# else + m_results[m_sequence] = SubmitResult(m_sequence, result.diff, result.actualDiff()); +# endif + + send(HTTP_POST, "/json_rpc", doc); + + return m_sequence++; +} + + +void xmrig::DaemonClient::connect() +{ + setState(ConnectingState); + getBlockTemplate(); +} + + +void xmrig::DaemonClient::connect(const Pool &pool) +{ + setPool(pool); + connect(); +} + + +void xmrig::DaemonClient::onHttpData(const HttpData &data) +{ + if (data.status != HTTP_STATUS_OK) { + return retry(); + } + + LOG_DEBUG("[%s:%d] received (%d bytes): \"%.*s\"", m_pool.host().data(), m_pool.port(), static_cast(data.body.size()), static_cast(data.body.size()), data.body.c_str()); + + m_ip = static_cast(data).ip().c_str(); + + rapidjson::Document doc; + if (doc.Parse(data.body.c_str()).HasParseError()) { + if (!isQuiet()) { + LOG_ERR("[%s:%d] JSON decode failed: \"%s\"", m_pool.host().data(), m_pool.port(), rapidjson::GetParseError_En(doc.GetParseError())); + } + + return retry(); + } + + if (data.method == HTTP_GET && data.url == "/getheight") { + if (m_job.height() != Json::getUint64(doc, "height")) { + getBlockTemplate(); + } + + return; + } + + if (!parseResponse(Json::getInt64(doc, "id", -1), Json::getObject(doc, "result"), Json::getObject(doc, "error"))) { + retry(); + } +} + + +void xmrig::DaemonClient::onTimer(const Timer *) +{ + if (m_state == ConnectingState) { + getBlockTemplate(); + } + else if (m_state == ConnectedState) { + send(HTTP_GET, "/getheight"); + } +} + + +bool xmrig::DaemonClient::parseJob(const rapidjson::Value ¶ms, int *code) +{ + Job job(m_id, false, m_pool.algorithm(), String()); + + String blocktemplate = Json::getString(params, "blocktemplate_blob"); + if (blocktemplate.isNull() || !job.setBlob(Json::getString(params, "blockhashing_blob"))) { + *code = 4; + return false; + } + + job.setHeight(Json::getUint64(params, "height")); + job.setDiff(Json::getUint64(params, "difficulty")); + job.setId(blocktemplate.data() + blocktemplate.size() - 48); + + m_job = std::move(job); + m_blocktemplate = std::move(blocktemplate); + + if (m_state == ConnectingState) { + setState(ConnectedState); + } + + m_listener->onJobReceived(this, m_job, params); + return true; +} + + +bool xmrig::DaemonClient::parseResponse(int64_t id, const rapidjson::Value &result, const rapidjson::Value &error) +{ + if (id == -1) { + return false; + } + + if (error.IsObject()) { + const char *message = error["message"].GetString(); + + if (!handleSubmitResponse(id, message) && !isQuiet()) { + LOG_ERR("[%s:%d] error: " RED_BOLD("\"%s\"") RED_S ", code: %d", m_pool.host().data(), m_pool.port(), message, error["code"].GetInt()); + } + + return false; + } + + if (!result.IsObject()) { + return false; + } + + int code = -1; + if (result.HasMember("blocktemplate_blob") && parseJob(result, &code)) { + return true; + } + + if (handleSubmitResponse(id)) { + getBlockTemplate(); + return true; + } + + + return false; +} + + +int64_t xmrig::DaemonClient::getBlockTemplate() +{ + using namespace rapidjson; + Document doc(kObjectType); + auto &allocator = doc.GetAllocator(); + + doc.AddMember("id", m_sequence, allocator); + doc.AddMember("jsonrpc", "2.0", allocator); + doc.AddMember("method", "getblocktemplate", allocator); + + Value params(kObjectType); + params.AddMember("wallet_address", m_pool.user().toJSON(), allocator); + params.AddMember("reserve_size", 8, allocator); + + doc.AddMember("params", params, allocator); + + send(HTTP_POST, "/json_rpc", doc); + + return m_sequence++; +} + + +void xmrig::DaemonClient::retry() +{ + m_failures++; + m_listener->onClose(this, static_cast(m_failures)); + + if (m_failures == -1) { + return; + } + + if (m_state == ConnectedState) { + setState(ConnectingState); + } + + m_timer->stop(); + m_timer->start(m_retryPause, 0); +} + + +void xmrig::DaemonClient::send(int method, const char *url, const char *data, size_t size) +{ + LOG_DEBUG("[%s:%d] " MAGENTA_BOLD("\"%s %s\"") BLACK_BOLD_S " send (%zu bytes): \"%.*s\"", + m_pool.host().data(), + m_pool.port(), + http_method_str(static_cast(method)), + url, + size, + static_cast(size), + data); + + HttpClient *client; +# ifdef XMRIG_FEATURE_TLS + if (m_pool.isTLS()) { + client = new HttpsClient(method, url, this, data, size); + } + else +# endif + { + client = new HttpClient(method, url, this, data, size); + } + + client->setQuiet(isQuiet()); + client->connect(m_pool.host(), m_pool.port()); +} + + +void xmrig::DaemonClient::send(int method, const char *url, const rapidjson::Document &doc) +{ + using namespace rapidjson; + + StringBuffer buffer(nullptr, 512); + Writer writer(buffer); + doc.Accept(writer); + + send(method, url, buffer.GetString(), buffer.GetSize()); +} + + +void xmrig::DaemonClient::setState(SocketState state) +{ + assert(m_state != state); + if (m_state == state) { + return; + } + + m_state = state; + + switch (state) { + case ConnectedState: + { + m_failures = 0; + m_listener->onLoginSuccess(this); + + const uint64_t interval = std::max(20, m_pool.pollInterval()); + m_timer->start(interval, interval); + } + break; + + case UnconnectedState: + m_failures = -1; + m_timer->stop(); + break; + + default: + break; + } +} diff --git a/src/base/net/stratum/DaemonClient.h b/src/base/net/stratum/DaemonClient.h new file mode 100644 index 00000000..740af6d0 --- /dev/null +++ b/src/base/net/stratum/DaemonClient.h @@ -0,0 +1,78 @@ +/* XMRig + * Copyright 2010 Jeff Garzik + * Copyright 2012-2014 pooler + * Copyright 2014 Lucas Jones + * Copyright 2014-2016 Wolf9466 + * Copyright 2016 Jay D Dee + * Copyright 2017-2018 XMR-Stak , + * Copyright 2018-2019 SChernykh + * Copyright 2019 Howard Chu + * Copyright 2016-2019 XMRig , + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef XMRIG_DAEMONCLIENT_H +#define XMRIG_DAEMONCLIENT_H + + +#include "base/net/stratum/BaseClient.h" +#include "base/kernel/interfaces/ITimerListener.h" +#include "base/kernel/interfaces/IHttpListener.h" + + +namespace xmrig { + + +class DaemonClient : public BaseClient, public ITimerListener, public IHttpListener +{ +public: + DaemonClient(int id, IClientListener *listener); + ~DaemonClient() override; + +protected: + bool disconnect() override; + bool isTLS() const override; + const char *tlsFingerprint() const override; + const char *tlsVersion() const override; + int64_t submit(const JobResult &result) override; + void connect() override; + void connect(const Pool &pool) override; + + void onHttpData(const HttpData &data) override; + void onTimer(const Timer *timer) override; + + inline bool hasExtension(Extension) const noexcept override { return false; } + inline const char *mode() const override { return "daemon"; } + inline void deleteLater() override { delete this; } + inline void tick(uint64_t) override {} + +private: + bool parseJob(const rapidjson::Value ¶ms, int *code); + bool parseResponse(int64_t id, const rapidjson::Value &result, const rapidjson::Value &error); + int64_t getBlockTemplate(); + void retry(); + void send(int method, const char *url, const char *data = nullptr, size_t size = 0); + void send(int method, const char *url, const rapidjson::Document &doc); + void setState(SocketState state); + + String m_blocktemplate; + Timer *m_timer; +}; + + +} /* namespace xmrig */ + + +#endif /* XMRIG_DAEMONCLIENT_H */ diff --git a/src/base/net/stratum/Pool.h b/src/base/net/stratum/Pool.h index d3c9b141..6eec7aa5 100644 --- a/src/base/net/stratum/Pool.h +++ b/src/base/net/stratum/Pool.h @@ -84,6 +84,7 @@ public: inline const String &user() const { return !m_user.isNull() ? m_user : kDefaultUser; } inline int keepAlive() const { return m_keepAlive; } inline uint16_t port() const { return m_port; } + inline uint64_t pollInterval() const { return m_pollInterval; } inline bool operator!=(const Pool &other) const { return !isEqual(other); } inline bool operator==(const Pool &other) const { return isEqual(other); } diff --git a/src/base/net/stratum/strategies/FailoverStrategy.cpp b/src/base/net/stratum/strategies/FailoverStrategy.cpp index 0c574a5d..b89cd955 100644 --- a/src/base/net/stratum/strategies/FailoverStrategy.cpp +++ b/src/base/net/stratum/strategies/FailoverStrategy.cpp @@ -29,6 +29,11 @@ #include "common/Platform.h" +#ifdef XMRIG_FEATURE_HTTP +# include "base/net/stratum/DaemonClient.h" +#endif + + xmrig::FailoverStrategy::FailoverStrategy(const std::vector &pools, int retryPause, int retries, IStrategyListener *listener, bool quiet) : m_quiet(quiet), m_retries(retries), @@ -56,7 +61,7 @@ xmrig::FailoverStrategy::FailoverStrategy(int retryPause, int retries, IStrategy xmrig::FailoverStrategy::~FailoverStrategy() { - for (Client *client : m_pools) { + for (IClient *client : m_pools) { client->deleteLater(); } } @@ -64,7 +69,15 @@ xmrig::FailoverStrategy::~FailoverStrategy() void xmrig::FailoverStrategy::add(const Pool &pool) { - Client *client = new Client(static_cast(m_pools.size()), Platform::userAgent(), this); + const int id = static_cast(m_pools.size()); + +# ifdef XMRIG_FEATURE_HTTP + IClient *client = !pool.isDaemon() ? static_cast(new Client(id, Platform::userAgent(), this)) + : static_cast(new DaemonClient(id, this)); +# else + IClient *client = new Client(id, Platform::userAgent(), this); +# endif + client->setPool(pool); client->setRetries(m_retries); client->setRetryPause(m_retryPause * 1000); @@ -102,7 +115,7 @@ void xmrig::FailoverStrategy::resume() void xmrig::FailoverStrategy::setAlgo(const xmrig::Algorithm &algo) { - for (Client *client : m_pools) { + for (IClient *client : m_pools) { client->setAlgo(algo); } } @@ -123,7 +136,7 @@ void xmrig::FailoverStrategy::stop() void xmrig::FailoverStrategy::tick(uint64_t now) { - for (Client *client : m_pools) { + for (IClient *client : m_pools) { client->tick(now); } } diff --git a/src/base/net/stratum/strategies/FailoverStrategy.h b/src/base/net/stratum/strategies/FailoverStrategy.h index 748eddda..344d815c 100644 --- a/src/base/net/stratum/strategies/FailoverStrategy.h +++ b/src/base/net/stratum/strategies/FailoverStrategy.h @@ -52,7 +52,7 @@ public: protected: inline bool isActive() const override { return m_active >= 0; } - inline Client *client() const override { return active(); } + inline IClient *client() const override { return active(); } inline void onLogin(IClient *, rapidjson::Document &, rapidjson::Value &) override {} int64_t submit(const JobResult &result) override; @@ -68,7 +68,7 @@ protected: void onResultAccepted(IClient *client, const SubmitResult &result, const char *error) override; private: - inline Client *active() const { return m_pools[static_cast(m_active)]; } + inline IClient *active() const { return m_pools[static_cast(m_active)]; } const bool m_quiet; const int m_retries; @@ -76,7 +76,7 @@ private: int m_active; IStrategyListener *m_listener; size_t m_index; - std::vector m_pools; + std::vector m_pools; }; diff --git a/src/base/net/stratum/strategies/SinglePoolStrategy.cpp b/src/base/net/stratum/strategies/SinglePoolStrategy.cpp index 45dce5d9..f432514e 100644 --- a/src/base/net/stratum/strategies/SinglePoolStrategy.cpp +++ b/src/base/net/stratum/strategies/SinglePoolStrategy.cpp @@ -29,11 +29,26 @@ #include "common/Platform.h" +#ifdef XMRIG_FEATURE_HTTP +# include "base/net/stratum/DaemonClient.h" +#endif + + xmrig::SinglePoolStrategy::SinglePoolStrategy(const Pool &pool, int retryPause, int retries, IStrategyListener *listener, bool quiet) : m_active(false), m_listener(listener) { +# ifdef XMRIG_FEATURE_HTTP + if (!pool.isDaemon()) { + m_client = new Client(0, Platform::userAgent(), this); + } + else { + m_client = new DaemonClient(0, this); + } +# else m_client = new Client(0, Platform::userAgent(), this); +# endif + m_client->setPool(pool); m_client->setRetries(retries); m_client->setRetryPause(retryPause * 1000); diff --git a/src/base/net/stratum/strategies/SinglePoolStrategy.h b/src/base/net/stratum/strategies/SinglePoolStrategy.h index b8a4fe1e..af0bd7d6 100644 --- a/src/base/net/stratum/strategies/SinglePoolStrategy.h +++ b/src/base/net/stratum/strategies/SinglePoolStrategy.h @@ -46,7 +46,7 @@ public: protected: inline bool isActive() const override { return m_active; } - inline Client *client() const override { return m_client; } + inline IClient *client() const override { return m_client; } inline void onLogin(IClient *, rapidjson::Document &, rapidjson::Value &) override {} int64_t submit(const JobResult &result) override; @@ -63,7 +63,7 @@ protected: private: bool m_active; - Client *m_client; + IClient *m_client; IStrategyListener *m_listener; }; diff --git a/src/net/strategies/DonateStrategy.cpp b/src/net/strategies/DonateStrategy.cpp index 7a9f9e60..fb958a4c 100644 --- a/src/net/strategies/DonateStrategy.cpp +++ b/src/net/strategies/DonateStrategy.cpp @@ -231,8 +231,8 @@ xmrig::Client *xmrig::DonateStrategy::createProxy() return nullptr; } - const Client *client = strategy->client(); - m_tls = client->hasExtension(IClient::EXT_TLS); + const IClient *client = strategy->client(); + m_tls = client->hasExtension(IClient::EXT_TLS); Pool pool(client->ip(), client->pool().port(), m_userId, client->pool().password(), 0, true, client->isTLS()); pool.setAlgo(client->pool().algorithm()); diff --git a/src/net/strategies/DonateStrategy.h b/src/net/strategies/DonateStrategy.h index 69bf8dbd..c9fc312d 100644 --- a/src/net/strategies/DonateStrategy.h +++ b/src/net/strategies/DonateStrategy.h @@ -52,7 +52,7 @@ public: protected: inline bool isActive() const override { return state() == STATE_ACTIVE; } - inline Client *client() const override { return m_proxy ? m_proxy : m_strategy->client(); } + inline IClient *client() const override { return m_proxy ? m_proxy : m_strategy->client(); } inline void onJob(IStrategy *, IClient *client, const Job &job) override { setJob(client, job); } inline void onJobReceived(IClient *client, const Job &job, const rapidjson::Value &) override { setJob(client, job); } inline void onResultAccepted(IClient *client, const SubmitResult &result, const char *error) override { setResult(client, result, error); } @@ -93,7 +93,7 @@ private: bool m_tls; char m_userId[65]; - Client *m_proxy; + IClient *m_proxy; const uint64_t m_donateTime; const uint64_t m_idleTime; Controller *m_controller; From 5e369a5af85b9cf6b72c0b205d5a5bc878a6160e Mon Sep 17 00:00:00 2001 From: XMRig Date: Fri, 12 Apr 2019 04:25:47 +0700 Subject: [PATCH 082/116] Fixed daemon support over HTTPS. --- src/base/net/http/HttpClient.cpp | 1 + src/base/net/http/HttpClient.h | 3 +- src/base/net/http/HttpsClient.cpp | 70 ++++++++++++++++++++++++--- src/base/net/http/HttpsClient.h | 11 ++++- src/base/net/stratum/DaemonClient.cpp | 23 ++++----- src/base/net/stratum/DaemonClient.h | 6 ++- 6 files changed, 90 insertions(+), 24 deletions(-) diff --git a/src/base/net/http/HttpClient.cpp b/src/base/net/http/HttpClient.cpp index d58e7299..319bb4dd 100644 --- a/src/base/net/http/HttpClient.cpp +++ b/src/base/net/http/HttpClient.cpp @@ -79,6 +79,7 @@ private: xmrig::HttpClient::HttpClient(int method, const String &url, IHttpListener *listener, const char *data, size_t size) : HttpContext(HTTP_RESPONSE, listener), + m_quiet(false), m_port(0) { this->method = method; diff --git a/src/base/net/http/HttpClient.h b/src/base/net/http/HttpClient.h index e9866483..c5dfc43d 100644 --- a/src/base/net/http/HttpClient.h +++ b/src/base/net/http/HttpClient.h @@ -57,10 +57,11 @@ protected: virtual void read(const char *data, size_t size); virtual void write(const std::string &header); + bool m_quiet; + private: static void onConnect(uv_connect_t *req, int status); - bool m_quiet; Dns *m_dns; uint16_t m_port; }; diff --git a/src/base/net/http/HttpsClient.cpp b/src/base/net/http/HttpsClient.cpp index ff103a34..2c287330 100644 --- a/src/base/net/http/HttpsClient.cpp +++ b/src/base/net/http/HttpsClient.cpp @@ -29,15 +29,22 @@ #include +#include "base/io/log/Log.h" #include "base/net/http/HttpsClient.h" -#include "base/tools/String.h" +#include "base/tools/Buffer.h" -xmrig::HttpsClient::HttpsClient(int method, const String &url, IHttpListener *listener, const char *data, size_t size) : +#ifdef _MSC_VER +# define strncasecmp(x,y,z) _strnicmp(x,y,z) +#endif + + +xmrig::HttpsClient::HttpsClient(int method, const String &url, IHttpListener *listener, const char *data, size_t size, const String &fingerprint) : HttpClient(method, url, listener, data, size), m_ready(false), m_buf(), - m_ssl(nullptr) + m_ssl(nullptr), + m_fp(fingerprint) { m_ctx = SSL_CTX_new(SSLv23_method()); assert(m_ctx != nullptr); @@ -64,6 +71,18 @@ xmrig::HttpsClient::~HttpsClient() } +const char *xmrig::HttpsClient::fingerprint() const +{ + return m_ready ? m_fingerprint : nullptr; +} + + +const char *xmrig::HttpsClient::version() const +{ + return m_ready ? SSL_get_version(m_ssl) : nullptr; +} + + void xmrig::HttpsClient::handshake() { m_ssl = SSL_new(m_ctx); @@ -118,13 +137,52 @@ void xmrig::HttpsClient::read(const char *data, size_t size) void xmrig::HttpsClient::write(const std::string &header) { SSL_write(m_ssl, (header + body).c_str(), header.size() + body.size()); + body.clear(); + flush(); } -bool xmrig::HttpsClient::verify(X509 *cert) const +bool xmrig::HttpsClient::verify(X509 *cert) { - return cert != nullptr; + if (cert == nullptr) { + return false; + } + + if (!verifyFingerprint(cert)) { + if (!m_quiet) { + LOG_ERR("[%s:%d] Failed to verify server certificate fingerprint", host().data(), port()); + + if (strlen(m_fingerprint) == 64 && !m_fp.isNull()) { + LOG_ERR("\"%s\" was given", m_fingerprint); + LOG_ERR("\"%s\" was configured", m_fp.data()); + } + } + + return false; + } + + return true; +} + + +bool xmrig::HttpsClient::verifyFingerprint(X509 *cert) +{ + const EVP_MD *digest = EVP_get_digestbyname("sha256"); + if (digest == nullptr) { + return false; + } + + unsigned char md[EVP_MAX_MD_SIZE]; + unsigned int dlen; + + if (X509_digest(cert, digest, md, &dlen) != 1) { + return false; + } + + Buffer::toHex(md, 32, m_fingerprint); + + return m_fp.isNull() || strncasecmp(m_fingerprint, m_fp.data(), 64) == 0; } @@ -139,7 +197,7 @@ void xmrig::HttpsClient::flush() bool result = false; if (uv_is_writable(stream())) { - result = uv_try_write(stream(), &buf, 1) == buf.len; + result = uv_try_write(stream(), &buf, 1) == static_cast(buf.len); if (!result) { close(UV_EIO); diff --git a/src/base/net/http/HttpsClient.h b/src/base/net/http/HttpsClient.h index 76b90c66..c6a22809 100644 --- a/src/base/net/http/HttpsClient.h +++ b/src/base/net/http/HttpsClient.h @@ -35,6 +35,7 @@ typedef struct x509_st X509; #include "base/net/http/HttpClient.h" +#include "base/tools/String.h" namespace xmrig { @@ -43,24 +44,30 @@ namespace xmrig { class HttpsClient : public HttpClient { public: - HttpsClient(int method, const String &url, IHttpListener *listener, const char *data = nullptr, size_t size = 0); + HttpsClient(int method, const String &url, IHttpListener *listener, const char *data, size_t size, const String &fingerprint); ~HttpsClient() override; + const char *fingerprint() const; + const char *version() const; + protected: void handshake() override; void read(const char *data, size_t size) override; void write(const std::string &header) override; private: - bool verify(X509 *cert) const; + bool verify(X509 *cert); + bool verifyFingerprint(X509 *cert); void flush(); BIO *m_readBio; BIO *m_writeBio; bool m_ready; char m_buf[1024 * 2]; + char m_fingerprint[32 * 2 + 8]; SSL *m_ssl; SSL_CTX *m_ctx; + String m_fp; }; diff --git a/src/base/net/stratum/DaemonClient.cpp b/src/base/net/stratum/DaemonClient.cpp index a5aef54d..251c5fd5 100644 --- a/src/base/net/stratum/DaemonClient.cpp +++ b/src/base/net/stratum/DaemonClient.cpp @@ -72,19 +72,11 @@ bool xmrig::DaemonClient::disconnect() bool xmrig::DaemonClient::isTLS() const { +# ifdef XMRIG_FEATURE_TLS + return m_pool.isTLS(); +# else return false; -} - - -const char *xmrig::DaemonClient::tlsFingerprint() const -{ - return nullptr; -} - - -const char *xmrig::DaemonClient::tlsVersion() const -{ - return nullptr; +# endif } @@ -145,6 +137,11 @@ void xmrig::DaemonClient::onHttpData(const HttpData &data) m_ip = static_cast(data).ip().c_str(); + if (isTLS()) { + m_tlsVersion = static_cast(data).version(); + m_tlsFingerprint = static_cast(data).fingerprint(); + } + rapidjson::Document doc; if (doc.Parse(data.body.c_str()).HasParseError()) { if (!isQuiet()) { @@ -294,7 +291,7 @@ void xmrig::DaemonClient::send(int method, const char *url, const char *data, si HttpClient *client; # ifdef XMRIG_FEATURE_TLS if (m_pool.isTLS()) { - client = new HttpsClient(method, url, this, data, size); + client = new HttpsClient(method, url, this, data, size, m_pool.fingerprint()); } else # endif diff --git a/src/base/net/stratum/DaemonClient.h b/src/base/net/stratum/DaemonClient.h index 740af6d0..f9438f67 100644 --- a/src/base/net/stratum/DaemonClient.h +++ b/src/base/net/stratum/DaemonClient.h @@ -44,8 +44,6 @@ public: protected: bool disconnect() override; bool isTLS() const override; - const char *tlsFingerprint() const override; - const char *tlsVersion() const override; int64_t submit(const JobResult &result) override; void connect() override; void connect(const Pool &pool) override; @@ -55,6 +53,8 @@ protected: inline bool hasExtension(Extension) const noexcept override { return false; } inline const char *mode() const override { return "daemon"; } + inline const char *tlsFingerprint() const override { return m_tlsFingerprint; } + inline const char *tlsVersion() const override { return m_tlsVersion; } inline void deleteLater() override { delete this; } inline void tick(uint64_t) override {} @@ -68,6 +68,8 @@ private: void setState(SocketState state); String m_blocktemplate; + String m_tlsFingerprint; + String m_tlsVersion; Timer *m_timer; }; From 867478b983a6a8b8bbd853e5a9f14cc8c447cfe3 Mon Sep 17 00:00:00 2001 From: XMRig Date: Fri, 12 Apr 2019 18:30:08 +0700 Subject: [PATCH 083/116] Added command line option --daemon and --daemon-poll-interval --- src/base/kernel/config/BaseTransform.cpp | 8 ++ src/base/kernel/interfaces/IConfig.h | 2 + src/core/config/Config_platform.h | 2 + src/core/config/usage.h | 101 +++++++++++++---------- 4 files changed, 71 insertions(+), 42 deletions(-) diff --git a/src/base/kernel/config/BaseTransform.cpp b/src/base/kernel/config/BaseTransform.cpp index 3b6b6d82..e4165a4c 100644 --- a/src/base/kernel/config/BaseTransform.cpp +++ b/src/base/kernel/config/BaseTransform.cpp @@ -161,6 +161,7 @@ void xmrig::BaseTransform::transform(rapidjson::Document &doc, int key, const ch case IConfig::PrintTimeKey: /* --print-time */ case IConfig::HttpPort: /* --http-port */ case IConfig::DonateLevelKey: /* --donate-level */ + case IConfig::DaemonPollKey: /* --daemon-poll-interval */ # ifdef XMRIG_DEPRECATED case IConfig::ApiPort: /* --api-port */ # endif @@ -173,6 +174,7 @@ void xmrig::BaseTransform::transform(rapidjson::Document &doc, int key, const ch case IConfig::TlsKey: /* --tls */ case IConfig::DryRunKey: /* --dry-run */ case IConfig::HttpEnabledKey: /* --http-enabled */ + case IConfig::DaemonKey: /* --daemon */ return transformBoolean(doc, key, true); case IConfig::ColorKey: /* --no-color */ @@ -204,6 +206,9 @@ void xmrig::BaseTransform::transformBoolean(rapidjson::Document &doc, int key, b case IConfig::TlsKey: /* --tls */ return add(doc, kPools, "tls", enable); + case IConfig::DaemonKey: /* --daemon */ + return add(doc, kPools, "daemon", enable); + # ifndef XMRIG_PROXY_PROJECT case IConfig::NicehashKey: /* --nicehash */ return add(doc, kPools, "nicehash", enable); @@ -265,6 +270,9 @@ void xmrig::BaseTransform::transformUint64(rapidjson::Document &doc, int key, ui case IConfig::PrintTimeKey: /* --print-time */ return set(doc, "print-time", arg); + case IConfig::DaemonPollKey: /* --daemon-poll-interval */ + return add(doc, kPools, "daemon-poll-interval", arg); + default: break; } diff --git a/src/base/kernel/interfaces/IConfig.h b/src/base/kernel/interfaces/IConfig.h index d592c4cb..07849e35 100644 --- a/src/base/kernel/interfaces/IConfig.h +++ b/src/base/kernel/interfaces/IConfig.h @@ -70,6 +70,8 @@ public: TlsKey = 1013, FingerprintKey = 1014, ProxyDonateKey = 1017, + DaemonKey = 1018, + DaemonPollKey = 1019, # ifdef XMRIG_DEPRECATED ApiPort = 4000, diff --git a/src/core/config/Config_platform.h b/src/core/config/Config_platform.h index 8ece4105..ca06a703 100644 --- a/src/core/config/Config_platform.h +++ b/src/core/config/Config_platform.h @@ -82,6 +82,8 @@ static const option options[] = { { "tls", 0, nullptr, IConfig::TlsKey }, { "tls-fingerprint", 1, nullptr, IConfig::FingerprintKey }, { "asm", 1, nullptr, IConfig::AssemblyKey }, + { "daemon", 0, nullptr, IConfig::DaemonKey }, + { "daemon-poll-interval", 1, nullptr, IConfig::DaemonPollKey }, # ifdef XMRIG_DEPRECATED { "api-port", 1, nullptr, IConfig::ApiPort }, diff --git a/src/core/config/usage.h b/src/core/config/usage.h index 430a60c7..ce172778 100644 --- a/src/core/config/usage.h +++ b/src/core/config/usage.h @@ -35,59 +35,76 @@ namespace xmrig { static char const usage[] = "\ Usage: " APP_ID " [OPTIONS]\n\ Options:\n\ - -a, --algo=ALGO specify the algorithm to use\n\ - cryptonight\n" + -a, --algo=ALGO specify the algorithm to use\n\ + cryptonight\n" #ifndef XMRIG_NO_AEON "\ - cryptonight-lite\n" + cryptonight-lite\n" #endif #ifndef XMRIG_NO_SUMO "\ - cryptonight-heavy\n" + cryptonight-heavy\n" +#endif +#ifndef XMRIG_NO_CN_PICO +"\ + cryptonight-pico\n" #endif "\ - -o, --url=URL URL of mining server\n\ - -O, --userpass=U:P username:password pair for mining server\n\ - -u, --user=USERNAME username for mining server\n\ - -p, --pass=PASSWORD password for mining server\n\ - --rig-id=ID rig identifier for pool-side statistics (needs pool support)\n\ - -t, --threads=N number of miner threads\n\ - -v, --av=N algorithm variation, 0 auto select\n\ - -k, --keepalive send keepalived packet for prevent timeout (needs pool support)\n\ - --nicehash enable nicehash.com support\n\ - --tls enable SSL/TLS support (needs pool support)\n\ - --tls-fingerprint=F pool TLS certificate fingerprint, if set enable strict certificate pinning\n\ - -r, --retries=N number of times to retry before switch to backup server (default: 5)\n\ - -R, --retry-pause=N time to pause between retries (default: 5)\n\ - --cpu-affinity set process affinity to CPU core(s), mask 0x3 for cores 0 and 1\n\ - --cpu-priority set process priority (0 idle, 2 normal to 5 highest)\n\ - --no-huge-pages disable huge pages support\n\ - --no-color disable colored output\n\ - --variant algorithm PoW variant\n\ - --donate-level=N donate level, default 5%% (5 minutes in 100 minutes)\n\ - --user-agent set custom user-agent string for pool\n\ - -B, --background run the miner in the background\n\ - -c, --config=FILE load a JSON-format configuration file\n\ - -l, --log-file=FILE log all output to a file\n" + -o, --url=URL URL of mining server\n\ + -O, --userpass=U:P username:password pair for mining server\n\ + -u, --user=USERNAME username for mining server\n\ + -p, --pass=PASSWORD password for mining server\n\ + --rig-id=ID rig identifier for pool-side statistics (needs pool support)\n\ + -t, --threads=N number of miner threads\n\ + -v, --av=N algorithm variation, 0 auto select\n\ + -k, --keepalive send keepalived packet for prevent timeout (needs pool support)\n\ + --nicehash enable nicehash.com support\n" +#ifdef XMRIG_FEATURE_TLS +"\ + --tls enable SSL/TLS support (needs pool support)\n\ + --tls-fingerprint=F pool TLS certificate fingerprint, if set enable strict certificate pinning\n" +#endif +#ifdef XMRIG_FEATURE_HTTP +"\ + --daemon use daemon RPC instead of pool for solo mining\n\ + --daemon-poll-interval=N daemon poll interval in milliseconds (default: 1000)\n" +#endif +"\ + -r, --retries=N number of times to retry before switch to backup server (default: 5)\n\ + -R, --retry-pause=N time to pause between retries (default: 5)\n\ + --cpu-affinity set process affinity to CPU core(s), mask 0x3 for cores 0 and 1\n\ + --cpu-priority set process priority (0 idle, 2 normal to 5 highest)\n\ + --no-huge-pages disable huge pages support\n\ + --no-color disable colored output\n\ + --variant algorithm PoW variant\n\ + --donate-level=N donate level, default 5%% (5 minutes in 100 minutes)\n\ + --user-agent set custom user-agent string for pool\n\ + -B, --background run the miner in the background\n\ + -c, --config=FILE load a JSON-format configuration file\n\ + -l, --log-file=FILE log all output to a file\n" # ifdef HAVE_SYSLOG_H "\ - -S, --syslog use system log for output messages\n" + -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\ - --asm=ASM ASM code for cn/2, possible values: auto, none, intel, ryzen, bulldozer.\n\ - --print-time=N print hashrate report every N seconds\n\ - --api-worker-id=ID custom worker-id for API\n\ - --api-id=ID custom instance ID for API\n\ - --http-enabled enable HTTP API\n\ - --http-host=HOST bind host for HTTP API (by default 127.0.0.1)\n\ - --http-port=N bind port for HTTP API\n\ - --http-access-token=T access token for HTTP API\n\ - --http-no-restricted enable full remote access to HTTP API (only if access token set)\n\ - --dry-run test configuration and exit\n\ - -h, --help display this help and exit\n\ - -V, --version output version information and exit\n\ + --max-cpu-usage=N maximum CPU usage for automatic threads mode (default: 100)\n\ + --safe safe adjust threads and av settings for current CPU\n\ + --asm=ASM ASM optimizations, possible values: auto, none, intel, ryzen, bulldozer.\n\ + --print-time=N print hashrate report every N seconds\n" +#ifdef XMRIG_FEATURE_HTTP +"\ + --api-worker-id=ID custom worker-id for API\n\ + --api-id=ID custom instance ID for API\n\ + --http-enabled enable HTTP API\n\ + --http-host=HOST bind host for HTTP API (default: 127.0.0.1)\n\ + --http-port=N bind port for HTTP API\n\ + --http-access-token=T access token for HTTP API\n\ + --http-no-restricted enable full remote access to HTTP API (only if access token set)\n" +#endif +"\ + --dry-run test configuration and exit\n\ + -h, --help display this help and exit\n\ + -V, --version output version information and exit\n\ "; From 83a7a88b11a31f1a1a3056e5d2565bcef38fc0a2 Mon Sep 17 00:00:00 2001 From: XMRig Date: Fri, 12 Apr 2019 19:25:03 +0700 Subject: [PATCH 084/116] Fixed build without TLS support. --- src/base/net/stratum/DaemonClient.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/base/net/stratum/DaemonClient.cpp b/src/base/net/stratum/DaemonClient.cpp index 251c5fd5..a6826e67 100644 --- a/src/base/net/stratum/DaemonClient.cpp +++ b/src/base/net/stratum/DaemonClient.cpp @@ -137,10 +137,12 @@ void xmrig::DaemonClient::onHttpData(const HttpData &data) m_ip = static_cast(data).ip().c_str(); +# ifdef XMRIG_FEATURE_TLS if (isTLS()) { m_tlsVersion = static_cast(data).version(); m_tlsFingerprint = static_cast(data).fingerprint(); } +# endif rapidjson::Document doc; if (doc.Parse(data.body.c_str()).HasParseError()) { From 23b0e3799e9e6874ff9f47450478d4a00fc2376a Mon Sep 17 00:00:00 2001 From: XMRig Date: Fri, 12 Apr 2019 22:32:45 +0700 Subject: [PATCH 085/116] Fixed build on some systems. --- src/base/tools/String.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/base/tools/String.cpp b/src/base/tools/String.cpp index c7bc3d1b..7778c6da 100644 --- a/src/base/tools/String.cpp +++ b/src/base/tools/String.cpp @@ -23,6 +23,9 @@ */ +#include + + #include "base/tools/String.h" #include "rapidjson/document.h" From 21798edb8bfb4f86daa63befff970b171ef09c09 Mon Sep 17 00:00:00 2001 From: XMRig Date: Sat, 13 Apr 2019 19:09:22 +0700 Subject: [PATCH 086/116] Sync changes. --- src/base/net/stratum/DaemonClient.cpp | 12 +++++++++--- src/base/net/stratum/Job.cpp | 5 +++++ src/base/net/stratum/Pool.h | 3 +++ 3 files changed, 17 insertions(+), 3 deletions(-) diff --git a/src/base/net/stratum/DaemonClient.cpp b/src/base/net/stratum/DaemonClient.cpp index a6826e67..0944b6e6 100644 --- a/src/base/net/stratum/DaemonClient.cpp +++ b/src/base/net/stratum/DaemonClient.cpp @@ -64,7 +64,9 @@ xmrig::DaemonClient::~DaemonClient() bool xmrig::DaemonClient::disconnect() { - setState(UnconnectedState); + if (m_state != UnconnectedState) { + setState(UnconnectedState); + } return true; } @@ -82,11 +84,15 @@ bool xmrig::DaemonClient::isTLS() const int64_t xmrig::DaemonClient::submit(const JobResult &result) { - if (result.jobId != (m_blocktemplate.data() + m_blocktemplate.size() - 48)) { + if (result.jobId != (m_blocktemplate.data() + m_blocktemplate.size() - 32)) { return -1; } +# ifdef XMRIG_PROXY_PROJECT + memcpy(m_blocktemplate.data() + 78, result.nonce, 8); +# else Buffer::toHex(reinterpret_cast(&result.nonce), 4, m_blocktemplate.data() + 78); +# endif using namespace rapidjson; Document doc(kObjectType); @@ -190,7 +196,7 @@ bool xmrig::DaemonClient::parseJob(const rapidjson::Value ¶ms, int *code) job.setHeight(Json::getUint64(params, "height")); job.setDiff(Json::getUint64(params, "difficulty")); - job.setId(blocktemplate.data() + blocktemplate.size() - 48); + job.setId(blocktemplate.data() + blocktemplate.size() - 32); m_job = std::move(job); m_blocktemplate = std::move(blocktemplate); diff --git a/src/base/net/stratum/Job.cpp b/src/base/net/stratum/Job.cpp index 8ef607ad..663818e2 100644 --- a/src/base/net/stratum/Job.cpp +++ b/src/base/net/stratum/Job.cpp @@ -185,6 +185,11 @@ void xmrig::Job::setDiff(uint64_t diff) { m_diff = diff; m_target = toDiff(diff); + +# ifdef XMRIG_PROXY_PROJECT + Buffer::toHex(reinterpret_cast(&m_target), 8, m_rawTarget); + m_rawTarget[16] = '\0'; +# endif } diff --git a/src/base/net/stratum/Pool.h b/src/base/net/stratum/Pool.h index 6eec7aa5..f7987707 100644 --- a/src/base/net/stratum/Pool.h +++ b/src/base/net/stratum/Pool.h @@ -85,6 +85,9 @@ public: inline int keepAlive() const { return m_keepAlive; } inline uint16_t port() const { return m_port; } inline uint64_t pollInterval() const { return m_pollInterval; } + inline void setPassword(const String &password) { m_password = password; } + inline void setRigId(const String &rigId) { m_rigId = rigId; } + inline void setUser(const String &user) { m_user = user; } inline bool operator!=(const Pool &other) const { return !isEqual(other); } inline bool operator==(const Pool &other) const { return isEqual(other); } From c0e668f36f04414eab011cfa0e607b3781640136 Mon Sep 17 00:00:00 2001 From: XMRig Date: Sat, 13 Apr 2019 23:58:58 +0700 Subject: [PATCH 087/116] Move files. --- src/base/base.cmake | 12 ++++++------ src/base/io/{ => json}/Json.cpp | 2 +- src/base/io/{ => json}/Json.h | 0 src/base/io/{ => json}/JsonChain.cpp | 4 ++-- src/base/io/{ => json}/JsonChain.h | 0 src/base/io/{ => json}/Json_unix.cpp | 0 src/base/io/{ => json}/Json_win.cpp | 2 +- src/base/kernel/Base.cpp | 4 ++-- src/base/kernel/config/BaseConfig.cpp | 2 +- src/base/kernel/config/BaseTransform.cpp | 2 +- src/base/net/http/Http.cpp | 2 +- src/base/net/stratum/DaemonClient.cpp | 2 +- src/base/net/stratum/Pool.cpp | 2 +- 13 files changed, 17 insertions(+), 17 deletions(-) rename src/base/io/{ => json}/Json.cpp (99%) rename src/base/io/{ => json}/Json.h (100%) rename src/base/io/{ => json}/JsonChain.cpp (98%) rename src/base/io/{ => json}/JsonChain.h (100%) rename src/base/io/{ => json}/Json_unix.cpp (100%) rename src/base/io/{ => json}/Json_win.cpp (99%) diff --git a/src/base/base.cmake b/src/base/base.cmake index 6d478b39..c1718316 100644 --- a/src/base/base.cmake +++ b/src/base/base.cmake @@ -1,7 +1,7 @@ set(HEADERS_BASE src/base/io/Console.h - src/base/io/Json.h - src/base/io/JsonChain.h + src/base/io/json/Json.h + src/base/io/json/JsonChain.h src/base/io/log/backends/ConsoleLog.h src/base/io/log/backends/FileLog.h src/base/io/log/Log.h @@ -51,8 +51,8 @@ set(HEADERS_BASE set(SOURCES_BASE src/base/io/Console.cpp - src/base/io/Json.cpp - src/base/io/JsonChain.cpp + src/base/io/json/Json.cpp + src/base/io/json/JsonChain.cpp src/base/io/log/backends/ConsoleLog.cpp src/base/io/log/backends/FileLog.cpp src/base/io/log/Log.cpp @@ -81,9 +81,9 @@ set(SOURCES_BASE if (WIN32) - set(SOURCES_OS src/base/io/Json_win.cpp) + set(SOURCES_OS src/base/io/json/Json_win.cpp) else() - set(SOURCES_OS src/base/io/Json_unix.cpp) + set(SOURCES_OS src/base/io/json/Json_unix.cpp) endif() diff --git a/src/base/io/Json.cpp b/src/base/io/json/Json.cpp similarity index 99% rename from src/base/io/Json.cpp rename to src/base/io/json/Json.cpp index 91646453..07986c4a 100644 --- a/src/base/io/Json.cpp +++ b/src/base/io/json/Json.cpp @@ -23,7 +23,7 @@ */ -#include "base/io/Json.h" +#include "base/io/json/Json.h" #include "rapidjson/document.h" diff --git a/src/base/io/Json.h b/src/base/io/json/Json.h similarity index 100% rename from src/base/io/Json.h rename to src/base/io/json/Json.h diff --git a/src/base/io/JsonChain.cpp b/src/base/io/json/JsonChain.cpp similarity index 98% rename from src/base/io/JsonChain.cpp rename to src/base/io/json/JsonChain.cpp index 4dd75f0b..bbaabbde 100644 --- a/src/base/io/JsonChain.cpp +++ b/src/base/io/json/JsonChain.cpp @@ -23,8 +23,8 @@ */ -#include "base/io/Json.h" -#include "base/io/JsonChain.h" +#include "base/io/json/Json.h" +#include "base/io/json/JsonChain.h" #include "base/io/log/Log.h" #include "rapidjson/error/en.h" diff --git a/src/base/io/JsonChain.h b/src/base/io/json/JsonChain.h similarity index 100% rename from src/base/io/JsonChain.h rename to src/base/io/json/JsonChain.h diff --git a/src/base/io/Json_unix.cpp b/src/base/io/json/Json_unix.cpp similarity index 100% rename from src/base/io/Json_unix.cpp rename to src/base/io/json/Json_unix.cpp diff --git a/src/base/io/Json_win.cpp b/src/base/io/json/Json_win.cpp similarity index 99% rename from src/base/io/Json_win.cpp rename to src/base/io/json/Json_win.cpp index 58ee26b7..0faccdea 100644 --- a/src/base/io/Json_win.cpp +++ b/src/base/io/json/Json_win.cpp @@ -35,7 +35,7 @@ #include -#include "base/io/Json.h" +#include "base/io/json/Json.h" #include "rapidjson/document.h" #include "rapidjson/istreamwrapper.h" #include "rapidjson/ostreamwrapper.h" diff --git a/src/base/kernel/Base.cpp b/src/base/kernel/Base.cpp index 157363f0..1083efe9 100644 --- a/src/base/kernel/Base.cpp +++ b/src/base/kernel/Base.cpp @@ -27,8 +27,8 @@ #include -#include "base/io/Json.h" -#include "base/io/JsonChain.h" +#include "base/io/json/Json.h" +#include "base/io/json/JsonChain.h" #include "base/io/log/backends/ConsoleLog.h" #include "base/io/log/backends/FileLog.h" #include "base/io/log/Log.h" diff --git a/src/base/kernel/config/BaseConfig.cpp b/src/base/kernel/config/BaseConfig.cpp index e5fa7293..b2166240 100644 --- a/src/base/kernel/config/BaseConfig.cpp +++ b/src/base/kernel/config/BaseConfig.cpp @@ -49,7 +49,7 @@ #endif -#include "base/io/Json.h" +#include "base/io/json/Json.h" #include "base/io/log/Log.h" #include "base/kernel/config/BaseConfig.h" #include "base/kernel/interfaces/IJsonReader.h" diff --git a/src/base/kernel/config/BaseTransform.cpp b/src/base/kernel/config/BaseTransform.cpp index e4165a4c..615342b9 100644 --- a/src/base/kernel/config/BaseTransform.cpp +++ b/src/base/kernel/config/BaseTransform.cpp @@ -37,7 +37,7 @@ #include "base/kernel/Process.h" #include "base/io/log/Log.h" #include "base/kernel/interfaces/IConfig.h" -#include "base/io/JsonChain.h" +#include "base/io/json/JsonChain.h" #include "core/config/Config_platform.h" diff --git a/src/base/net/http/Http.cpp b/src/base/net/http/Http.cpp index 597260cf..3c275824 100644 --- a/src/base/net/http/Http.cpp +++ b/src/base/net/http/Http.cpp @@ -24,7 +24,7 @@ #include "3rdparty/rapidjson/document.h" -#include "base/io/Json.h" +#include "base/io/json/Json.h" #include "base/net/http/Http.h" diff --git a/src/base/net/stratum/DaemonClient.cpp b/src/base/net/stratum/DaemonClient.cpp index 0944b6e6..0b2a2ec1 100644 --- a/src/base/net/stratum/DaemonClient.cpp +++ b/src/base/net/stratum/DaemonClient.cpp @@ -29,7 +29,7 @@ #include "3rdparty/http-parser/http_parser.h" -#include "base/io/Json.h" +#include "base/io/json/Json.h" #include "base/io/log/Log.h" #include "base/kernel/interfaces/IClientListener.h" #include "base/net/http/HttpClient.h" diff --git a/src/base/net/stratum/Pool.cpp b/src/base/net/stratum/Pool.cpp index d23781ad..f441ba63 100644 --- a/src/base/net/stratum/Pool.cpp +++ b/src/base/net/stratum/Pool.cpp @@ -30,7 +30,7 @@ #include -#include "base/io/Json.h" +#include "base/io/json/Json.h" #include "base/net/stratum/Pool.h" #include "rapidjson/document.h" From 074b3869d2648101a9ffeb2bde1f1682686da31e Mon Sep 17 00:00:00 2001 From: XMRig Date: Sun, 14 Apr 2019 01:10:24 +0700 Subject: [PATCH 088/116] Added JsonRequest. --- src/base/base.cmake | 4 ++- src/base/io/json/JsonRequest.cpp | 38 ++++++++++++++++++++++ src/base/io/json/JsonRequest.h | 45 +++++++++++++++++++++++++++ src/base/net/stratum/Client.cpp | 15 +++------ src/base/net/stratum/DaemonClient.cpp | 16 +++------- 5 files changed, 94 insertions(+), 24 deletions(-) create mode 100644 src/base/io/json/JsonRequest.cpp create mode 100644 src/base/io/json/JsonRequest.h diff --git a/src/base/base.cmake b/src/base/base.cmake index c1718316..dcc10495 100644 --- a/src/base/base.cmake +++ b/src/base/base.cmake @@ -2,6 +2,7 @@ set(HEADERS_BASE src/base/io/Console.h src/base/io/json/Json.h src/base/io/json/JsonChain.h + src/base/io/json/JsonRequest.h src/base/io/log/backends/ConsoleLog.h src/base/io/log/backends/FileLog.h src/base/io/log/Log.h @@ -53,14 +54,15 @@ set(SOURCES_BASE src/base/io/Console.cpp src/base/io/json/Json.cpp src/base/io/json/JsonChain.cpp + src/base/io/json/JsonRequest.cpp src/base/io/log/backends/ConsoleLog.cpp src/base/io/log/backends/FileLog.cpp src/base/io/log/Log.cpp src/base/io/Watcher.cpp + src/base/kernel/Base.cpp src/base/kernel/config/BaseConfig.cpp src/base/kernel/config/BaseTransform.cpp src/base/kernel/Entry.cpp - src/base/kernel/Base.cpp src/base/kernel/Process.cpp src/base/kernel/Signals.cpp src/base/net/dns/Dns.cpp diff --git a/src/base/io/json/JsonRequest.cpp b/src/base/io/json/JsonRequest.cpp new file mode 100644 index 00000000..4556f3f0 --- /dev/null +++ b/src/base/io/json/JsonRequest.cpp @@ -0,0 +1,38 @@ +/* XMRig + * Copyright 2010 Jeff Garzik + * Copyright 2012-2014 pooler + * Copyright 2014 Lucas Jones + * Copyright 2014-2016 Wolf9466 + * Copyright 2016 Jay D Dee + * Copyright 2017-2018 XMR-Stak , + * Copyright 2018-2019 SChernykh + * Copyright 2016-2019 XMRig , + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + + +#include "base/io/json/JsonRequest.h" +#include "rapidjson/document.h" + + +void xmrig::JsonRequest::create(rapidjson::Document &doc, int64_t id, const char *method, rapidjson::Value ¶ms) +{ + auto &allocator = doc.GetAllocator(); + + doc.AddMember("id", id, allocator); + doc.AddMember("jsonrpc", "2.0", allocator); + doc.AddMember("method", rapidjson::StringRef(method), allocator); + doc.AddMember("params", params, allocator); +} diff --git a/src/base/io/json/JsonRequest.h b/src/base/io/json/JsonRequest.h new file mode 100644 index 00000000..e98c0bae --- /dev/null +++ b/src/base/io/json/JsonRequest.h @@ -0,0 +1,45 @@ +/* XMRig + * Copyright 2010 Jeff Garzik + * Copyright 2012-2014 pooler + * Copyright 2014 Lucas Jones + * Copyright 2014-2016 Wolf9466 + * Copyright 2016 Jay D Dee + * Copyright 2017-2018 XMR-Stak , + * Copyright 2018-2019 SChernykh + * Copyright 2016-2019 XMRig , + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef XMRIG_JSONREQUEST_H +#define XMRIG_JSONREQUEST_H + + +#include "rapidjson/fwd.h" + + +namespace xmrig { + + +class JsonRequest +{ +public: + static void create(rapidjson::Document &doc, int64_t id, const char *method, rapidjson::Value ¶ms); +}; + + +} /* namespace xmrig */ + + +#endif /* XMRIG_JSONREQUEST_H */ diff --git a/src/base/net/stratum/Client.cpp b/src/base/net/stratum/Client.cpp index df6f4837..1d448ddf 100644 --- a/src/base/net/stratum/Client.cpp +++ b/src/base/net/stratum/Client.cpp @@ -37,6 +37,7 @@ #endif +#include "base/io/json/JsonRequest.h" #include "base/io/log/Log.h" #include "base/kernel/interfaces/IClientListener.h" #include "base/net/dns/Dns.h" @@ -167,10 +168,6 @@ int64_t xmrig::Client::submit(const JobResult &result) Document doc(kObjectType); auto &allocator = doc.GetAllocator(); - doc.AddMember("id", m_sequence, allocator); - doc.AddMember("jsonrpc", "2.0", allocator); - doc.AddMember("method", "submit", allocator); - Value params(kObjectType); params.AddMember("id", StringRef(m_rpcId.data()), allocator); params.AddMember("job_id", StringRef(result.jobId.data()), allocator); @@ -181,7 +178,7 @@ int64_t xmrig::Client::submit(const JobResult &result) params.AddMember("algo", StringRef(result.algorithm.shortName()), allocator); } - doc.AddMember("params", params, allocator); + JsonRequest::create(doc, m_sequence, "submit", params); # ifdef XMRIG_PROXY_PROJECT m_results[m_sequence] = SubmitResult(m_sequence, result.diff, result.actualDiff(), result.id); @@ -584,14 +581,10 @@ void xmrig::Client::login() Document doc(kObjectType); auto &allocator = doc.GetAllocator(); - doc.AddMember("id", 1, allocator); - doc.AddMember("jsonrpc", "2.0", allocator); - doc.AddMember("method", "login", allocator); - Value params(kObjectType); params.AddMember("login", m_pool.user().toJSON(), allocator); params.AddMember("pass", m_pool.password().toJSON(), allocator); - params.AddMember("agent", StringRef(m_agent), allocator); + params.AddMember("agent", StringRef(m_agent), allocator); if (!m_pool.rigId().isNull()) { params.AddMember("rigid", m_pool.rigId().toJSON(), allocator); @@ -612,7 +605,7 @@ void xmrig::Client::login() m_listener->onLogin(this, doc, params); - doc.AddMember("params", params, allocator); + JsonRequest::create(doc, 1, "login", params); send(doc); } diff --git a/src/base/net/stratum/DaemonClient.cpp b/src/base/net/stratum/DaemonClient.cpp index 0b2a2ec1..b4492e7e 100644 --- a/src/base/net/stratum/DaemonClient.cpp +++ b/src/base/net/stratum/DaemonClient.cpp @@ -30,6 +30,7 @@ #include "3rdparty/http-parser/http_parser.h" #include "base/io/json/Json.h" +#include "base/io/json/JsonRequest.h" #include "base/io/log/Log.h" #include "base/kernel/interfaces/IClientListener.h" #include "base/net/http/HttpClient.h" @@ -96,16 +97,11 @@ int64_t xmrig::DaemonClient::submit(const JobResult &result) using namespace rapidjson; Document doc(kObjectType); - auto &allocator = doc.GetAllocator(); - - doc.AddMember("id", m_sequence, allocator); - doc.AddMember("jsonrpc", "2.0", allocator); - doc.AddMember("method", "submitblock", allocator); Value params(kArrayType); - params.PushBack(m_blocktemplate.toJSON(), allocator); + params.PushBack(m_blocktemplate.toJSON(), doc.GetAllocator()); - doc.AddMember("params", params, allocator); + JsonRequest::create(doc, m_sequence, "submitblock", params); # ifdef XMRIG_PROXY_PROJECT m_results[m_sequence] = SubmitResult(m_sequence, result.diff, result.actualDiff(), result.id); @@ -251,15 +247,11 @@ int64_t xmrig::DaemonClient::getBlockTemplate() Document doc(kObjectType); auto &allocator = doc.GetAllocator(); - doc.AddMember("id", m_sequence, allocator); - doc.AddMember("jsonrpc", "2.0", allocator); - doc.AddMember("method", "getblocktemplate", allocator); - Value params(kObjectType); params.AddMember("wallet_address", m_pool.user().toJSON(), allocator); params.AddMember("reserve_size", 8, allocator); - doc.AddMember("params", params, allocator); + JsonRequest::create(doc, m_sequence, "getblocktemplate", params); send(HTTP_POST, "/json_rpc", doc); From a3b303e885acbf79240c200e92659674a30720ec Mon Sep 17 00:00:00 2001 From: XMRig Date: Sun, 14 Apr 2019 03:21:23 +0700 Subject: [PATCH 089/116] Added checking for top_block_hash/hash. --- src/base/net/stratum/DaemonClient.cpp | 49 ++++++++++++++++++++++----- src/base/net/stratum/DaemonClient.h | 3 ++ 2 files changed, 43 insertions(+), 9 deletions(-) diff --git a/src/base/net/stratum/DaemonClient.cpp b/src/base/net/stratum/DaemonClient.cpp index b4492e7e..769e2116 100644 --- a/src/base/net/stratum/DaemonClient.cpp +++ b/src/base/net/stratum/DaemonClient.cpp @@ -50,8 +50,21 @@ #endif +namespace xmrig { + +static const char *kBlocktemplateBlob = "blocktemplate_blob"; +static const char *kGetHeight = "/getheight"; +static const char *kGetInfo = "/getinfo"; +static const char *kHash = "hash"; +static const char *kHeight = "height"; +static const char *kJsonRPC = "/json_rpc"; + +} + + xmrig::DaemonClient::DaemonClient(int id, IClientListener *listener) : - BaseClient(id, listener) + BaseClient(id, listener), + m_monero(true) { m_timer = new Timer(this); } @@ -109,7 +122,7 @@ int64_t xmrig::DaemonClient::submit(const JobResult &result) m_results[m_sequence] = SubmitResult(m_sequence, result.diff, result.actualDiff()); # endif - send(HTTP_POST, "/json_rpc", doc); + send(HTTP_POST, kJsonRPC, doc); return m_sequence++; } @@ -155,8 +168,19 @@ void xmrig::DaemonClient::onHttpData(const HttpData &data) return retry(); } - if (data.method == HTTP_GET && data.url == "/getheight") { - if (m_job.height() != Json::getUint64(doc, "height")) { + if (data.method == HTTP_GET) { + if (data.url == kGetHeight) { + if (!doc.HasMember(kHash)) { + m_monero = false; + + return send(HTTP_GET, kGetInfo); + } + + if (isOutdated(Json::getUint64(doc, kHeight), Json::getString(doc, kHash))) { + getBlockTemplate(); + } + } + else if (data.url == kGetInfo && isOutdated(Json::getUint64(doc, kHeight), Json::getString(doc, "top_block_hash"))) { getBlockTemplate(); } @@ -175,27 +199,34 @@ void xmrig::DaemonClient::onTimer(const Timer *) getBlockTemplate(); } else if (m_state == ConnectedState) { - send(HTTP_GET, "/getheight"); + send(HTTP_GET, m_monero ? kGetHeight : kGetInfo); } } +bool xmrig::DaemonClient::isOutdated(uint64_t height, const char *hash) const +{ + return m_job.height() != height || m_prevHash != hash; +} + + bool xmrig::DaemonClient::parseJob(const rapidjson::Value ¶ms, int *code) { Job job(m_id, false, m_pool.algorithm(), String()); - String blocktemplate = Json::getString(params, "blocktemplate_blob"); + String blocktemplate = Json::getString(params, kBlocktemplateBlob); if (blocktemplate.isNull() || !job.setBlob(Json::getString(params, "blockhashing_blob"))) { *code = 4; return false; } - job.setHeight(Json::getUint64(params, "height")); + job.setHeight(Json::getUint64(params, kHeight)); job.setDiff(Json::getUint64(params, "difficulty")); job.setId(blocktemplate.data() + blocktemplate.size() - 32); m_job = std::move(job); m_blocktemplate = std::move(blocktemplate); + m_prevHash = Json::getString(params, "prev_hash"); if (m_state == ConnectingState) { setState(ConnectedState); @@ -227,7 +258,7 @@ bool xmrig::DaemonClient::parseResponse(int64_t id, const rapidjson::Value &resu } int code = -1; - if (result.HasMember("blocktemplate_blob") && parseJob(result, &code)) { + if (result.HasMember(kBlocktemplateBlob) && parseJob(result, &code)) { return true; } @@ -253,7 +284,7 @@ int64_t xmrig::DaemonClient::getBlockTemplate() JsonRequest::create(doc, m_sequence, "getblocktemplate", params); - send(HTTP_POST, "/json_rpc", doc); + send(HTTP_POST, kJsonRPC, doc); return m_sequence++; } diff --git a/src/base/net/stratum/DaemonClient.h b/src/base/net/stratum/DaemonClient.h index f9438f67..00b62e39 100644 --- a/src/base/net/stratum/DaemonClient.h +++ b/src/base/net/stratum/DaemonClient.h @@ -59,6 +59,7 @@ protected: inline void tick(uint64_t) override {} private: + bool isOutdated(uint64_t height, const char *hash) const; bool parseJob(const rapidjson::Value ¶ms, int *code); bool parseResponse(int64_t id, const rapidjson::Value &result, const rapidjson::Value &error); int64_t getBlockTemplate(); @@ -67,7 +68,9 @@ private: void send(int method, const char *url, const rapidjson::Document &doc); void setState(SocketState state); + bool m_monero; String m_blocktemplate; + String m_prevHash; String m_tlsFingerprint; String m_tlsVersion; Timer *m_timer; From ee1d61d117efcfc591691c9936921a621bac65e4 Mon Sep 17 00:00:00 2001 From: XMRig Date: Sun, 14 Apr 2019 03:24:14 +0700 Subject: [PATCH 090/116] Fix Linux build. --- src/base/io/json/Json_unix.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/base/io/json/Json_unix.cpp b/src/base/io/json/Json_unix.cpp index da3902d8..eeef9564 100644 --- a/src/base/io/json/Json_unix.cpp +++ b/src/base/io/json/Json_unix.cpp @@ -26,7 +26,7 @@ #include -#include "base/io/Json.h" +#include "base/io/json/Json.h" #include "rapidjson/document.h" #include "rapidjson/istreamwrapper.h" #include "rapidjson/ostreamwrapper.h" From 32c3d4b9f6469d57ab4d5fbbb007f3463c2ccac5 Mon Sep 17 00:00:00 2001 From: Tony Butler Date: Mon, 15 Apr 2019 10:39:16 -0600 Subject: [PATCH 091/116] Repair compilation with Clang 9.0.0 (which now includes its own _rotr intrinsic) --- src/crypto/soft_aes.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/crypto/soft_aes.h b/src/crypto/soft_aes.h index 26c1b06a..52fd9b7a 100644 --- a/src/crypto/soft_aes.h +++ b/src/crypto/soft_aes.h @@ -130,7 +130,7 @@ static inline uint32_t sub_word(uint32_t key) saes_sbox[key & 0xff]; } -#if defined(__clang__) || defined(XMRIG_ARM) +#if (defined(__clang__) && __clang_major__ != 9) || defined(XMRIG_ARM) static inline uint32_t _rotr(uint32_t value, uint32_t amount) { return (value >> amount) | (value << ((32 - amount) & 31)); From f9f7ef26b8c9757bb5e6733f420f880fbdb0464a Mon Sep 17 00:00:00 2001 From: XMRig Date: Tue, 16 Apr 2019 01:20:50 +0700 Subject: [PATCH 092/116] #1012 Added checks for _rotr. --- cmake/flags.cmake | 7 +++++++ src/crypto/soft_aes.h | 2 +- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/cmake/flags.cmake b/cmake/flags.cmake index 3989cb71..2f3eb208 100644 --- a/cmake/flags.cmake +++ b/cmake/flags.cmake @@ -10,6 +10,8 @@ if (CMAKE_BUILD_TYPE STREQUAL "Release") add_definitions(/DNDEBUG) endif() +include(CheckSymbolExists) + if (CMAKE_CXX_COMPILER_ID MATCHES GNU) set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Wno-strict-aliasing") @@ -27,6 +29,8 @@ if (CMAKE_CXX_COMPILER_ID MATCHES GNU) else() set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -maes") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -maes") + + add_definitions(/DHAVE_ROTR) endif() if (WIN32) @@ -50,6 +54,7 @@ elseif (CMAKE_CXX_COMPILER_ID MATCHES MSVC) add_definitions(/D_CRT_SECURE_NO_WARNINGS) add_definitions(/D_CRT_NONSTDC_NO_WARNINGS) add_definitions(/DNOMINMAX) + add_definitions(/DHAVE_ROTR) elseif (CMAKE_CXX_COMPILER_ID MATCHES Clang) @@ -68,6 +73,8 @@ elseif (CMAKE_CXX_COMPILER_ID MATCHES Clang) else() set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -maes") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -maes") + + check_symbol_exists("_rotr" "x86intrin.h" HAVE_ROTR) endif() endif() diff --git a/src/crypto/soft_aes.h b/src/crypto/soft_aes.h index 26c1b06a..4ad9bdd9 100644 --- a/src/crypto/soft_aes.h +++ b/src/crypto/soft_aes.h @@ -130,7 +130,7 @@ static inline uint32_t sub_word(uint32_t key) saes_sbox[key & 0xff]; } -#if defined(__clang__) || defined(XMRIG_ARM) +#ifndef HAVE_ROTR static inline uint32_t _rotr(uint32_t value, uint32_t amount) { return (value >> amount) | (value << ((32 - amount) & 31)); From 9137f59ec1216ceef8e4569640748d8bdc452593 Mon Sep 17 00:00:00 2001 From: XMRig Date: Tue, 16 Apr 2019 02:00:27 +0700 Subject: [PATCH 093/116] #1012 Fixed _rotr detection. --- cmake/flags.cmake | 3 +++ 1 file changed, 3 insertions(+) diff --git a/cmake/flags.cmake b/cmake/flags.cmake index 2f3eb208..d50b5c84 100644 --- a/cmake/flags.cmake +++ b/cmake/flags.cmake @@ -75,6 +75,9 @@ elseif (CMAKE_CXX_COMPILER_ID MATCHES Clang) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -maes") check_symbol_exists("_rotr" "x86intrin.h" HAVE_ROTR) + if (HAVE_ROTR) + add_definitions(/DHAVE_ROTR) + endif() endif() endif() From 699269bbae408001f19c53f5e130d93f67d06e0b Mon Sep 17 00:00:00 2001 From: Tony Butler Date: Mon, 15 Apr 2019 13:26:55 -0600 Subject: [PATCH 094/116] Upstream fixed it for good with [Added checks for _rotr.] and [Fixed _rotr detection.] --- cmake/flags.cmake | 10 ++++++++++ src/crypto/soft_aes.h | 2 +- 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/cmake/flags.cmake b/cmake/flags.cmake index 3989cb71..d50b5c84 100644 --- a/cmake/flags.cmake +++ b/cmake/flags.cmake @@ -10,6 +10,8 @@ if (CMAKE_BUILD_TYPE STREQUAL "Release") add_definitions(/DNDEBUG) endif() +include(CheckSymbolExists) + if (CMAKE_CXX_COMPILER_ID MATCHES GNU) set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Wno-strict-aliasing") @@ -27,6 +29,8 @@ if (CMAKE_CXX_COMPILER_ID MATCHES GNU) else() set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -maes") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -maes") + + add_definitions(/DHAVE_ROTR) endif() if (WIN32) @@ -50,6 +54,7 @@ elseif (CMAKE_CXX_COMPILER_ID MATCHES MSVC) add_definitions(/D_CRT_SECURE_NO_WARNINGS) add_definitions(/D_CRT_NONSTDC_NO_WARNINGS) add_definitions(/DNOMINMAX) + add_definitions(/DHAVE_ROTR) elseif (CMAKE_CXX_COMPILER_ID MATCHES Clang) @@ -68,6 +73,11 @@ elseif (CMAKE_CXX_COMPILER_ID MATCHES Clang) else() set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -maes") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -maes") + + check_symbol_exists("_rotr" "x86intrin.h" HAVE_ROTR) + if (HAVE_ROTR) + add_definitions(/DHAVE_ROTR) + endif() endif() endif() diff --git a/src/crypto/soft_aes.h b/src/crypto/soft_aes.h index 52fd9b7a..4ad9bdd9 100644 --- a/src/crypto/soft_aes.h +++ b/src/crypto/soft_aes.h @@ -130,7 +130,7 @@ static inline uint32_t sub_word(uint32_t key) saes_sbox[key & 0xff]; } -#if (defined(__clang__) && __clang_major__ != 9) || defined(XMRIG_ARM) +#ifndef HAVE_ROTR static inline uint32_t _rotr(uint32_t value, uint32_t amount) { return (value >> amount) | (value << ((32 - amount) & 31)); From ff6544a14c07fc0849909878a591d3233e8c99f6 Mon Sep 17 00:00:00 2001 From: XMRig Date: Wed, 17 Apr 2019 19:03:15 +0700 Subject: [PATCH 095/116] Updated default config. --- src/config.json | 4 +++- src/core/config/Config_default.h | 4 +++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/src/config.json b/src/config.json index dbb980d0..53df5486 100644 --- a/src/config.json +++ b/src/config.json @@ -35,7 +35,9 @@ "variant": -1, "enabled": true, "tls": false, - "tls-fingerprint": null + "tls-fingerprint": null, + "daemon": false, + "daemon-poll-interval": 1000 } ], "print-time": 60, diff --git a/src/core/config/Config_default.h b/src/core/config/Config_default.h index 3462ad19..d6145cf4 100644 --- a/src/core/config/Config_default.h +++ b/src/core/config/Config_default.h @@ -69,7 +69,9 @@ R"===( "variant": -1, "enabled": true, "tls": false, - "tls-fingerprint": null + "tls-fingerprint": null, + "daemon": false, + "daemon-poll-interval": 1000 } ], "print-time": 60, From 552858b9e331601a9aa04a17f1d06a505473a3b9 Mon Sep 17 00:00:00 2001 From: xmrig Date: Wed, 17 Apr 2019 23:59:21 +0700 Subject: [PATCH 096/116] Update CHANGELOG.md --- CHANGELOG.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index ada15bed..a4eb3a07 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,9 @@ +# v2.15.2-beta +- [#1010](https://github.com/xmrig/xmrig/pull/1010#issuecomment-482632107) Added daemon support (solo mining). +- [#1012](https://github.com/xmrig/xmrig/pull/1012) Fixed compatibility with clang 9. +- Config subsystem was rewritten, internally JSON is primary format now. +- Fixed regression, big HTTP responses was truncated. + # v2.15.1-beta - [#1007](https://github.com/xmrig/xmrig/issues/1007) Old HTTP API backend based on libmicrohttpd, replaced to custom HTTP server (libuv + http_parser). - [#257](https://github.com/xmrig/xmrig-nvidia/pull/257) New logging subsystem, file and syslog now always without colors. From e46a2a508a9686429f2661a4338a38b32fc29c95 Mon Sep 17 00:00:00 2001 From: XMRig Date: Thu, 18 Apr 2019 00:25:37 +0700 Subject: [PATCH 097/116] v2.15.2-beta --- src/version.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/version.h b/src/version.h index 0f5a456a..60080720 100644 --- a/src/version.h +++ b/src/version.h @@ -28,7 +28,7 @@ #define APP_ID "xmrig" #define APP_NAME "XMRig" #define APP_DESC "XMRig CPU miner" -#define APP_VERSION "2.15.2-evo" +#define APP_VERSION "2.15.2-beta" #define APP_DOMAIN "xmrig.com" #define APP_SITE "www.xmrig.com" #define APP_COPYRIGHT "Copyright (C) 2016-2019 xmrig.com" From 8b0d35b61922c28651a239360298c5a890edf66e Mon Sep 17 00:00:00 2001 From: XMRig Date: Thu, 18 Apr 2019 15:23:36 +0700 Subject: [PATCH 098/116] #1014 Fixed regression, default value for `algo` option was not applied. --- CHANGELOG.md | 3 +++ src/base/kernel/config/BaseConfig.cpp | 2 +- src/version.h | 4 ++-- 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a4eb3a07..4655cf34 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,6 @@ +# v2.15.3-beta +- [#1014](https://github.com/xmrig/xmrig/issues/1014) Fixed regression, default value for `algo` option was not applied. + # v2.15.2-beta - [#1010](https://github.com/xmrig/xmrig/pull/1010#issuecomment-482632107) Added daemon support (solo mining). - [#1012](https://github.com/xmrig/xmrig/pull/1012) Fixed compatibility with clang 9. diff --git a/src/base/kernel/config/BaseConfig.cpp b/src/base/kernel/config/BaseConfig.cpp index b2166240..af2418aa 100644 --- a/src/base/kernel/config/BaseConfig.cpp +++ b/src/base/kernel/config/BaseConfig.cpp @@ -160,7 +160,7 @@ bool xmrig::BaseConfig::read(const IJsonReader &reader, const char *fileName) m_http.load(chain.getObject("http")); # endif - m_algorithm.parseAlgorithm(reader.getString("algo")); + m_algorithm.parseAlgorithm(reader.getString("algo", "cn")); m_pools.load(reader.getArray("pools")); m_pools.setDonateLevel(reader.getInt("donate-level", kDefaultDonateLevel)); diff --git a/src/version.h b/src/version.h index 60080720..0c9b970a 100644 --- a/src/version.h +++ b/src/version.h @@ -28,7 +28,7 @@ #define APP_ID "xmrig" #define APP_NAME "XMRig" #define APP_DESC "XMRig CPU miner" -#define APP_VERSION "2.15.2-beta" +#define APP_VERSION "2.15.3-beta" #define APP_DOMAIN "xmrig.com" #define APP_SITE "www.xmrig.com" #define APP_COPYRIGHT "Copyright (C) 2016-2019 xmrig.com" @@ -36,7 +36,7 @@ #define APP_VER_MAJOR 2 #define APP_VER_MINOR 15 -#define APP_VER_PATCH 2 +#define APP_VER_PATCH 3 #ifdef _MSC_VER # if (_MSC_VER >= 1910) From 304d7bd09aceab34f156c6e488ae38f7fbba2378 Mon Sep 17 00:00:00 2001 From: XMRig Date: Thu, 18 Apr 2019 20:59:14 +0700 Subject: [PATCH 099/116] v2.15.4-evo --- src/version.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/version.h b/src/version.h index 0c9b970a..f91a812f 100644 --- a/src/version.h +++ b/src/version.h @@ -28,7 +28,7 @@ #define APP_ID "xmrig" #define APP_NAME "XMRig" #define APP_DESC "XMRig CPU miner" -#define APP_VERSION "2.15.3-beta" +#define APP_VERSION "2.15.4-evo" #define APP_DOMAIN "xmrig.com" #define APP_SITE "www.xmrig.com" #define APP_COPYRIGHT "Copyright (C) 2016-2019 xmrig.com" @@ -36,7 +36,7 @@ #define APP_VER_MAJOR 2 #define APP_VER_MINOR 15 -#define APP_VER_PATCH 3 +#define APP_VER_PATCH 4 #ifdef _MSC_VER # if (_MSC_VER >= 1910) From 378bc504fcc3ea8634d1eda9925599060f1fe209 Mon Sep 17 00:00:00 2001 From: XMRig Date: Thu, 25 Apr 2019 02:22:53 +0700 Subject: [PATCH 100/116] Use null for unknown hashrate in API. --- src/api/v1/ApiRouter.cpp | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/api/v1/ApiRouter.cpp b/src/api/v1/ApiRouter.cpp index 1f3641c3..91395939 100644 --- a/src/api/v1/ApiRouter.cpp +++ b/src/api/v1/ApiRouter.cpp @@ -40,13 +40,15 @@ #include "workers/Workers.h" -static inline double normalize(double d) +static inline rapidjson::Value normalize(double d) { + using namespace rapidjson; + if (!isnormal(d)) { - return 0.0; + return Value(kNullType); } - return floor(d * 100.0) / 100.0; + return Value(floor(d * 100.0) / 100.0); } From a000544fdc37943650dd2db378d3cf0ab40bb0a4 Mon Sep 17 00:00:00 2001 From: XMRig Date: Wed, 1 May 2019 22:07:13 +0700 Subject: [PATCH 101/116] Return current algorithm in API response. --- src/api/v1/ApiRouter.cpp | 1 - src/base/net/stratum/strategies/FailoverStrategy.cpp | 2 +- src/base/net/stratum/strategies/FailoverStrategy.h | 2 +- src/net/Network.cpp | 4 ++++ src/net/Network.h | 1 + src/net/NetworkState.cpp | 2 +- 6 files changed, 8 insertions(+), 4 deletions(-) diff --git a/src/api/v1/ApiRouter.cpp b/src/api/v1/ApiRouter.cpp index 91395939..d066b0b1 100644 --- a/src/api/v1/ApiRouter.cpp +++ b/src/api/v1/ApiRouter.cpp @@ -144,7 +144,6 @@ void xmrig::ApiRouter::getMiner(rapidjson::Value &reply, rapidjson::Document &do reply.AddMember("kind", APP_KIND, allocator); reply.AddMember("ua", StringRef(Platform::userAgent()), allocator); reply.AddMember("cpu", cpu, allocator); - reply.AddMember("algo", StringRef(m_base->config()->algorithm().shortName()), allocator); reply.AddMember("hugepages", Workers::hugePages() > 0, allocator); reply.AddMember("donate_level", m_base->config()->pools().donateLevel(), allocator); } diff --git a/src/base/net/stratum/strategies/FailoverStrategy.cpp b/src/base/net/stratum/strategies/FailoverStrategy.cpp index b89cd955..d5247229 100644 --- a/src/base/net/stratum/strategies/FailoverStrategy.cpp +++ b/src/base/net/stratum/strategies/FailoverStrategy.cpp @@ -89,7 +89,7 @@ void xmrig::FailoverStrategy::add(const Pool &pool) int64_t xmrig::FailoverStrategy::submit(const JobResult &result) { - if (m_active == -1) { + if (!isActive()) { return -1; } diff --git a/src/base/net/stratum/strategies/FailoverStrategy.h b/src/base/net/stratum/strategies/FailoverStrategy.h index 344d815c..b1fe8bac 100644 --- a/src/base/net/stratum/strategies/FailoverStrategy.h +++ b/src/base/net/stratum/strategies/FailoverStrategy.h @@ -52,7 +52,7 @@ public: protected: inline bool isActive() const override { return m_active >= 0; } - inline IClient *client() const override { return active(); } + inline IClient *client() const override { return isActive() ? active() : m_pools[m_index]; } inline void onLogin(IClient *, rapidjson::Document &, rapidjson::Value &) override {} int64_t submit(const JobResult &result) override; diff --git a/src/net/Network.cpp b/src/net/Network.cpp index cc5d59e4..32cad6a6 100644 --- a/src/net/Network.cpp +++ b/src/net/Network.cpp @@ -53,6 +53,7 @@ xmrig::Network::Network(Controller *controller) : + m_controller(controller), m_donate(nullptr), m_timer(nullptr) { @@ -230,6 +231,9 @@ void xmrig::Network::getConnection(rapidjson::Value &reply, rapidjson::Document using namespace rapidjson; auto &allocator = doc.GetAllocator(); + const Algorithm &algo = m_strategy->client()->job().algorithm(); + reply.AddMember("algo", StringRef((algo.isValid() ? algo : m_controller->config()->algorithm()).shortName()), allocator); + Value connection(kObjectType); connection.AddMember("pool", StringRef(m_state.pool), allocator); connection.AddMember("uptime", m_state.connectionTime(), allocator); diff --git a/src/net/Network.h b/src/net/Network.h index 079d997a..eaec9472 100644 --- a/src/net/Network.h +++ b/src/net/Network.h @@ -78,6 +78,7 @@ private: void getResults(rapidjson::Value &reply, rapidjson::Document &doc) const; # endif + Controller *m_controller; IStrategy *m_donate; IStrategy *m_strategy; NetworkState m_state; diff --git a/src/net/NetworkState.cpp b/src/net/NetworkState.cpp index c55422db..e495773a 100644 --- a/src/net/NetworkState.cpp +++ b/src/net/NetworkState.cpp @@ -92,7 +92,7 @@ void xmrig::NetworkState::add(const SubmitResult &result, const char *error) std::sort(topDiff.rbegin(), topDiff.rend()); } - m_latency.push_back(result.elapsed > 0xFFFF ? 0xFFFF : (uint16_t) result.elapsed); + m_latency.push_back(result.elapsed > 0xFFFF ? 0xFFFF : static_cast(result.elapsed)); } From ffb282a11ad47ac399b60a44ba21ef43b33c5071 Mon Sep 17 00:00:00 2001 From: XMRig Date: Mon, 13 May 2019 00:11:57 +0700 Subject: [PATCH 102/116] Added global uptime and extended connection information for API. --- src/api/Api.cpp | 11 ++++++++--- src/api/Api.h | 2 ++ src/base/tools/String.h | 1 + src/net/Network.cpp | 15 +++++++++------ src/net/NetworkState.cpp | 18 +++++++++++++----- src/net/NetworkState.h | 13 ++++++++++++- 6 files changed, 45 insertions(+), 15 deletions(-) diff --git a/src/api/Api.cpp b/src/api/Api.cpp index d1bac212..a11325f3 100644 --- a/src/api/Api.cpp +++ b/src/api/Api.cpp @@ -38,6 +38,7 @@ #include "api/v1/ApiRouter.h" #include "base/kernel/Base.h" #include "base/tools/Buffer.h" +#include "base/tools/Chrono.h" #include "common/crypto/keccak.h" #include "core/config/Config.h" #include "core/Controller.h" @@ -53,7 +54,8 @@ xmrig::Api::Api(Base *base) : m_base(base), m_id(), m_workerId(), - m_httpd(nullptr) + m_httpd(nullptr), + m_timestamp(Chrono::steadyMSecs()) { base->addListener(this); @@ -118,9 +120,12 @@ void xmrig::Api::exec(IApiRequest &request) using namespace rapidjson; if (request.method() == IApiRequest::METHOD_GET && (request.url() == "/1/summary" || request.url() == "/api.json")) { + auto &allocator = request.doc().GetAllocator(); + request.accept(); - request.reply().AddMember("id", StringRef(m_id), request.doc().GetAllocator()); - request.reply().AddMember("worker_id", StringRef(m_workerId), request.doc().GetAllocator());; + request.reply().AddMember("id", StringRef(m_id), allocator); + request.reply().AddMember("worker_id", StringRef(m_workerId), allocator); + request.reply().AddMember("uptime", (Chrono::steadyMSecs() - m_timestamp) / 1000, allocator); } for (IApiListener *listener : m_listeners) { diff --git a/src/api/Api.h b/src/api/Api.h index 0c7fac52..eef57c3a 100644 --- a/src/api/Api.h +++ b/src/api/Api.h @@ -27,6 +27,7 @@ #include +#include #include "base/kernel/interfaces/IBaseListener.h" @@ -72,6 +73,7 @@ private: char m_workerId[128]; Httpd *m_httpd; std::vector m_listeners; + uint64_t m_timestamp; }; diff --git a/src/base/tools/String.h b/src/base/tools/String.h index eb0a1820..2c47d850 100644 --- a/src/base/tools/String.h +++ b/src/base/tools/String.h @@ -80,6 +80,7 @@ public: inline String &operator=(char *str) { move(str); return *this; } inline String &operator=(const char *str) { copy(str); return *this; } inline String &operator=(const String &str) { copy(str); return *this; } + inline String &operator=(std::nullptr_t) { delete [] m_data; m_data = nullptr; m_size = 0; return *this; } inline String &operator=(String &&other) { move(std::move(other)); return *this; } rapidjson::Value toJSON() const; diff --git a/src/net/Network.cpp b/src/net/Network.cpp index 32cad6a6..1ab42236 100644 --- a/src/net/Network.cpp +++ b/src/net/Network.cpp @@ -100,7 +100,7 @@ void xmrig::Network::onActive(IStrategy *strategy, IClient *client) return; } - m_state.setPool(client->pool().host(), client->pool().port(), client->ip()); + m_state.onActive(client); const char *tlsVersion = client->tlsVersion(); LOG_INFO(WHITE_BOLD("use %s ") CYAN_BOLD("%s:%d ") GREEN_BOLD("%s") " " BLACK_BOLD("%s"), @@ -235,11 +235,14 @@ void xmrig::Network::getConnection(rapidjson::Value &reply, rapidjson::Document reply.AddMember("algo", StringRef((algo.isValid() ? algo : m_controller->config()->algorithm()).shortName()), allocator); Value connection(kObjectType); - connection.AddMember("pool", StringRef(m_state.pool), allocator); - connection.AddMember("uptime", m_state.connectionTime(), allocator); - connection.AddMember("ping", m_state.latency(), allocator); - connection.AddMember("failures", m_state.failures, allocator); - connection.AddMember("error_log", Value(kArrayType), allocator); + connection.AddMember("pool", StringRef(m_state.pool), allocator); + connection.AddMember("ip", m_state.ip().toJSON(), allocator); + connection.AddMember("uptime", m_state.connectionTime(), allocator); + connection.AddMember("ping", m_state.latency(), allocator); + connection.AddMember("failures", m_state.failures, allocator); + connection.AddMember("tls", m_state.tls().toJSON(), allocator); + connection.AddMember("tls-fingerprint", m_state.fingerprint().toJSON(), allocator); + connection.AddMember("error_log", Value(kArrayType), allocator); reply.AddMember("connection", connection, allocator); } diff --git a/src/net/NetworkState.cpp b/src/net/NetworkState.cpp index e495773a..6868f57e 100644 --- a/src/net/NetworkState.cpp +++ b/src/net/NetworkState.cpp @@ -29,6 +29,8 @@ #include +#include "base/kernel/interfaces/IClient.h" +#include "base/net/stratum/Pool.h" #include "base/net/stratum/SubmitResult.h" #include "base/tools/Chrono.h" #include "net/NetworkState.h" @@ -96,19 +98,25 @@ void xmrig::NetworkState::add(const SubmitResult &result, const char *error) } -void xmrig::NetworkState::setPool(const char *host, int port, const char *ip) +void xmrig::NetworkState::onActive(IClient *client) { - snprintf(pool, sizeof(pool) - 1, "%s:%d", host, port); + snprintf(pool, sizeof(pool) - 1, "%s:%d", client->pool().host().data(), client->pool().port()); - m_active = true; + m_ip = client->ip(); + m_tls = client->tlsVersion(); + m_fingerprint = client->tlsFingerprint(); + m_active = true; m_connectionTime = Chrono::steadyMSecs(); } void xmrig::NetworkState::stop() { - m_active = false; - diff = 0; + m_active = false; + diff = 0; + m_ip = nullptr; + m_tls = nullptr; + m_fingerprint = nullptr; failures++; m_latency.clear(); diff --git a/src/net/NetworkState.h b/src/net/NetworkState.h index cf9a649a..ce56ec72 100644 --- a/src/net/NetworkState.h +++ b/src/net/NetworkState.h @@ -30,9 +30,13 @@ #include +#include "base/tools/String.h" + + namespace xmrig { +class IClient; class SubmitResult; @@ -41,11 +45,15 @@ class NetworkState public: NetworkState(); + inline const String &fingerprint() const { return m_fingerprint; } + inline const String &ip() const { return m_ip; } + inline const String &tls() const { return m_tls; } + uint32_t avgTime() const; uint32_t latency() const; uint64_t connectionTime() const; void add(const SubmitResult &result, const char *error); - void setPool(const char *host, int port, const char *ip); + void onActive(IClient *client); void stop(); char pool[256]; @@ -59,6 +67,9 @@ public: private: bool m_active; std::vector m_latency; + String m_fingerprint; + String m_ip; + String m_tls; uint64_t m_connectionTime; }; From 6fb014d0b135ba961bc3c04a5c89cb26fcf902ba Mon Sep 17 00:00:00 2001 From: XMRig Date: Tue, 21 May 2019 12:14:20 +0700 Subject: [PATCH 103/116] Fixed MSVC 2019 version detection. --- src/version.h | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/version.h b/src/version.h index f91a812f..384c2513 100644 --- a/src/version.h +++ b/src/version.h @@ -39,7 +39,9 @@ #define APP_VER_PATCH 4 #ifdef _MSC_VER -# if (_MSC_VER >= 1910) +# if (_MSC_VER >= 1920) +# define MSVC_VERSION 2019 +# elif (_MSC_VER >= 1910 && _MSC_VER < 1920) # define MSVC_VERSION 2017 # elif _MSC_VER == 1900 # define MSVC_VERSION 2015 From 51b92f66cfddf151570c643cb0407dd3720cdc65 Mon Sep 17 00:00:00 2001 From: XMRig Date: Sat, 25 May 2019 10:58:35 +0700 Subject: [PATCH 104/116] Sync changes. --- src/api/ApiRouter.cpp | 8 +++++--- src/version.h | 4 +++- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/src/api/ApiRouter.cpp b/src/api/ApiRouter.cpp index bdedac4d..beee8fd3 100644 --- a/src/api/ApiRouter.cpp +++ b/src/api/ApiRouter.cpp @@ -51,13 +51,15 @@ #include "workers/Workers.h" -static inline double normalize(double d) +static inline rapidjson::Value normalize(double d) { + using namespace rapidjson; + if (!isnormal(d)) { - return 0.0; + return Value(kNullType); } - return floor(d * 100.0) / 100.0; + return Value(floor(d * 100.0) / 100.0); } diff --git a/src/version.h b/src/version.h index 4e8fee45..b6ae7102 100644 --- a/src/version.h +++ b/src/version.h @@ -39,7 +39,9 @@ #define APP_VER_PATCH 2 #ifdef _MSC_VER -# if (_MSC_VER >= 1910) +# if (_MSC_VER >= 1920) +# define MSVC_VERSION 2019 +# elif (_MSC_VER >= 1910 && _MSC_VER < 1920) # define MSVC_VERSION 2017 # elif _MSC_VER == 1900 # define MSVC_VERSION 2015 From 10165da53efcad10c3d9a56f01b58f9471ac5172 Mon Sep 17 00:00:00 2001 From: XMRig Date: Sun, 26 May 2019 18:54:47 +0700 Subject: [PATCH 105/116] Removed obsolete automatic variants. --- src/common/net/Job.cpp | 18 ------------------ 1 file changed, 18 deletions(-) diff --git a/src/common/net/Job.cpp b/src/common/net/Job.cpp index 851507ad..cb6be4e6 100644 --- a/src/common/net/Job.cpp +++ b/src/common/net/Job.cpp @@ -127,24 +127,6 @@ bool xmrig::Job::setBlob(const char *blob) m_algorithm.setVariant(variant()); } - if (!m_algorithm.isForced()) { - if (m_algorithm.variant() == VARIANT_XTL && m_blob[0] >= 9) { - m_algorithm.setVariant(VARIANT_HALF); - } - else if (m_algorithm.variant() == VARIANT_MSR && m_blob[0] >= 8) { - m_algorithm.setVariant(VARIANT_HALF); - } - else if (m_algorithm.variant() == VARIANT_WOW && m_blob[0] < 11) { - m_algorithm.setVariant(VARIANT_2); - } - else if (m_algorithm.variant() == VARIANT_RWZ && m_blob[0] < 12) { - m_algorithm.setVariant(VARIANT_2); - } - else if (m_algorithm.variant() == VARIANT_ZLS && m_blob[0] < 8) { - m_algorithm.setVariant(VARIANT_2); - } - } - # ifdef XMRIG_PROXY_PROJECT memset(m_rawBlob, 0, sizeof(m_rawBlob)); memcpy(m_rawBlob, blob, m_size * 2); From 809efb4700dc9f14e78eea7f7f1a5c38c6d37cfa Mon Sep 17 00:00:00 2001 From: xmrig Date: Sun, 26 May 2019 19:21:13 +0700 Subject: [PATCH 106/116] Update CHANGELOG.md --- CHANGELOG.md | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 79c8bb4a..be30f774 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,10 @@ +# v2.14.4 +- [#992](https://github.com/xmrig/xmrig/pull/992) Fixed compilation with Clang 3.5. +- [#1012](https://github.com/xmrig/xmrig/pull/1012) Fixed compilation with Clang 9.0. +- In HTTP API for unknown hashrate now used `null` instead of `0.0`. +- Fixed MSVC 2019 version detection. +- Removed obsolete automatic variants. + # v2.14.1 * [#975](https://github.com/xmrig/xmrig/issues/975) Fixed crash on Linux if double thread mode used. From 1d4bc030fb4ccb366765cd4feb31b95ebd9db9a5 Mon Sep 17 00:00:00 2001 From: XMRig Date: Sun, 26 May 2019 19:28:28 +0700 Subject: [PATCH 107/116] v2.14.4-dev --- src/version.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/version.h b/src/version.h index b6ae7102..33be0af8 100644 --- a/src/version.h +++ b/src/version.h @@ -28,7 +28,7 @@ #define APP_ID "xmrig" #define APP_NAME "XMRig" #define APP_DESC "XMRig CPU miner" -#define APP_VERSION "2.14.2-dev" +#define APP_VERSION "2.14.4-dev" #define APP_DOMAIN "xmrig.com" #define APP_SITE "www.xmrig.com" #define APP_COPYRIGHT "Copyright (C) 2016-2019 xmrig.com" @@ -36,7 +36,7 @@ #define APP_VER_MAJOR 2 #define APP_VER_MINOR 14 -#define APP_VER_PATCH 2 +#define APP_VER_PATCH 4 #ifdef _MSC_VER # if (_MSC_VER >= 1920) From 2d8e8c92ab031745e2d26596ca2b0b395a420d24 Mon Sep 17 00:00:00 2001 From: XMRig Date: Thu, 30 May 2019 12:16:19 +0700 Subject: [PATCH 108/116] v2.14.4 --- src/version.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/version.h b/src/version.h index 33be0af8..6a5ecb02 100644 --- a/src/version.h +++ b/src/version.h @@ -28,7 +28,7 @@ #define APP_ID "xmrig" #define APP_NAME "XMRig" #define APP_DESC "XMRig CPU miner" -#define APP_VERSION "2.14.4-dev" +#define APP_VERSION "2.14.4" #define APP_DOMAIN "xmrig.com" #define APP_SITE "www.xmrig.com" #define APP_COPYRIGHT "Copyright (C) 2016-2019 xmrig.com" From 3dde8cacff0e30dd1c265d7b5ddae858885ad707 Mon Sep 17 00:00:00 2001 From: XMRig Date: Fri, 31 May 2019 22:50:39 +0700 Subject: [PATCH 109/116] v2.14.5-dev --- src/version.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/version.h b/src/version.h index 6a5ecb02..7ba9c776 100644 --- a/src/version.h +++ b/src/version.h @@ -28,7 +28,7 @@ #define APP_ID "xmrig" #define APP_NAME "XMRig" #define APP_DESC "XMRig CPU miner" -#define APP_VERSION "2.14.4" +#define APP_VERSION "2.14.5-dev" #define APP_DOMAIN "xmrig.com" #define APP_SITE "www.xmrig.com" #define APP_COPYRIGHT "Copyright (C) 2016-2019 xmrig.com" @@ -36,7 +36,7 @@ #define APP_VER_MAJOR 2 #define APP_VER_MINOR 14 -#define APP_VER_PATCH 4 +#define APP_VER_PATCH 5 #ifdef _MSC_VER # if (_MSC_VER >= 1920) From 9726f8cf9d3f2cf6a4b584a9a820eaa68bb0c5dc Mon Sep 17 00:00:00 2001 From: xmrig Date: Sun, 2 Jun 2019 14:16:45 +0700 Subject: [PATCH 110/116] Update CHANGELOG.md --- CHANGELOG.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 48ec8acb..dd7dc888 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,7 @@ +# v2.15.4-beta +- Added global uptime and extended connection information in API. +- API now return current algorithm instead of global algorithm specified in config. + # v2.15.3-beta - [#1014](https://github.com/xmrig/xmrig/issues/1014) Fixed regression, default value for `algo` option was not applied. From 5dde5dbf4e43a8a5c0cc6d1fcdece4d42d9e495e Mon Sep 17 00:00:00 2001 From: xmrig Date: Sun, 2 Jun 2019 14:18:13 +0700 Subject: [PATCH 111/116] Update CHANGELOG.md --- CHANGELOG.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index dd7dc888..11b82cbf 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,7 @@ # v2.15.4-beta - Added global uptime and extended connection information in API. -- API now return current algorithm instead of global algorithm specified in config. +- API now return current algorithm instead of global algorithm specified in config. +- This version also include all changes from stable version v2.14.4. # v2.15.3-beta - [#1014](https://github.com/xmrig/xmrig/issues/1014) Fixed regression, default value for `algo` option was not applied. From 277f188cd5a0a1f42cf1a84abf4760cff055ab14 Mon Sep 17 00:00:00 2001 From: XMRig Date: Sun, 2 Jun 2019 14:30:09 +0700 Subject: [PATCH 112/116] v2.15.4-beta --- src/version.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/version.h b/src/version.h index 384c2513..35831361 100644 --- a/src/version.h +++ b/src/version.h @@ -28,7 +28,7 @@ #define APP_ID "xmrig" #define APP_NAME "XMRig" #define APP_DESC "XMRig CPU miner" -#define APP_VERSION "2.15.4-evo" +#define APP_VERSION "2.15.4-beta" #define APP_DOMAIN "xmrig.com" #define APP_SITE "www.xmrig.com" #define APP_COPYRIGHT "Copyright (C) 2016-2019 xmrig.com" From ac1b554282ae1cc8b432f6e625334300781920fc Mon Sep 17 00:00:00 2001 From: SChernykh Date: Sat, 15 Jun 2019 22:53:03 +0200 Subject: [PATCH 113/116] RandomWOW support --- CMakeLists.txt | 4 +- cmake/FindRandomWOW.cmake | 25 +++++++++++ src/base/net/stratum/Client.cpp | 8 ++++ src/base/net/stratum/DaemonClient.cpp | 2 + src/base/net/stratum/Job.cpp | 11 +++++ src/base/net/stratum/Job.h | 3 ++ src/base/net/stratum/Pool.cpp | 1 + src/common/crypto/Algorithm.cpp | 4 +- src/common/xmrig.h | 1 + src/workers/CpuThread.cpp | 8 ++++ src/workers/MultiWorker.cpp | 16 ++++++- src/workers/MultiWorker.h | 3 ++ src/workers/Workers.cpp | 64 +++++++++++++++++++++++++++ src/workers/Workers.h | 10 +++++ 14 files changed, 157 insertions(+), 3 deletions(-) create mode 100644 cmake/FindRandomWOW.cmake diff --git a/CMakeLists.txt b/CMakeLists.txt index c7098f37..8f6e9226 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -154,6 +154,7 @@ add_definitions(/DUNICODE) set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}/cmake") find_package(UV REQUIRED) +find_package(RANDOMWOW REQUIRED) include(cmake/flags.cmake) @@ -219,6 +220,7 @@ endif() include_directories(src) include_directories(src/3rdparty) include_directories(${UV_INCLUDE_DIR}) +include_directories(${RANDOMWOW_INCLUDE_DIR}) if (BUILD_STATIC) set(CMAKE_EXE_LINKER_FLAGS " -static") @@ -229,4 +231,4 @@ if (WITH_DEBUG_LOG) endif() add_executable(${CMAKE_PROJECT_NAME} ${HEADERS} ${SOURCES} ${SOURCES_OS} ${SOURCES_CPUID} ${HEADERS_CRYPTO} ${SOURCES_CRYPTO} ${SOURCES_SYSLOG} ${HTTP_SOURCES} ${TLS_SOURCES} ${XMRIG_ASM_SOURCES} ${CN_GPU_SOURCES}) -target_link_libraries(${CMAKE_PROJECT_NAME} ${XMRIG_ASM_LIBRARY} ${OPENSSL_LIBRARIES} ${UV_LIBRARIES} ${EXTRA_LIBS} ${CPUID_LIB}) +target_link_libraries(${CMAKE_PROJECT_NAME} ${XMRIG_ASM_LIBRARY} ${OPENSSL_LIBRARIES} ${UV_LIBRARIES} ${RANDOMWOW_LIBRARIES} ${EXTRA_LIBS} ${CPUID_LIB}) diff --git a/cmake/FindRandomWOW.cmake b/cmake/FindRandomWOW.cmake new file mode 100644 index 00000000..c1db649f --- /dev/null +++ b/cmake/FindRandomWOW.cmake @@ -0,0 +1,25 @@ +find_path( + RANDOMWOW_INCLUDE_DIR + NAMES randomwow.h + PATHS "${XMRIG_DEPS}" ENV "XMRIG_DEPS" + PATH_SUFFIXES "include" + NO_DEFAULT_PATH +) + +find_path(RANDOMWOW_INCLUDE_DIR NAMES randomwow.h) + +find_library( + RANDOMWOW_LIBRARY + NAMES librandomwow.a randomwow librandomwow + PATHS "${XMRIG_DEPS}" ENV "XMRIG_DEPS" + PATH_SUFFIXES "lib" + NO_DEFAULT_PATH +) + +find_library(RANDOMWOW_LIBRARY NAMES librandomwow.a randomwow librandomwow) + +set(RANDOMWOW_LIBRARIES ${RANDOMWOW_LIBRARY}) +set(RANDOMWOW_INCLUDE_DIRS ${RANDOMWOW_INCLUDE_DIR}) + +include(FindPackageHandleStandardArgs) +find_package_handle_standard_args(RANDOMWOW DEFAULT_MSG RANDOMWOW_LIBRARY RANDOMWOW_INCLUDE_DIR) diff --git a/src/base/net/stratum/Client.cpp b/src/base/net/stratum/Client.cpp index 1d448ddf..4941ca3a 100644 --- a/src/base/net/stratum/Client.cpp +++ b/src/base/net/stratum/Client.cpp @@ -344,6 +344,14 @@ bool xmrig::Client::parseJob(const rapidjson::Value ¶ms, int *code) } } + if (params.HasMember("seed_hash")) { + const rapidjson::Value &variant = params["seed_hash"]; + + if (variant.IsString()) { + job.setSeedHash(variant.GetString()); + } + } + if (params.HasMember("height")) { const rapidjson::Value &variant = params["height"]; diff --git a/src/base/net/stratum/DaemonClient.cpp b/src/base/net/stratum/DaemonClient.cpp index 769e2116..e63c3271 100644 --- a/src/base/net/stratum/DaemonClient.cpp +++ b/src/base/net/stratum/DaemonClient.cpp @@ -220,6 +220,8 @@ bool xmrig::DaemonClient::parseJob(const rapidjson::Value ¶ms, int *code) return false; } + job.setSeedHash(Json::getString(params, "seed_hash")); + job.setHeight(Json::getUint64(params, kHeight)); job.setDiff(Json::getUint64(params, "difficulty")); job.setId(blocktemplate.data() + blocktemplate.size() - 32); diff --git a/src/base/net/stratum/Job.cpp b/src/base/net/stratum/Job.cpp index 1f1cd413..36098bfe 100644 --- a/src/base/net/stratum/Job.cpp +++ b/src/base/net/stratum/Job.cpp @@ -42,6 +42,7 @@ xmrig::Job::Job() : m_diff(0), m_height(0), m_target(0), + m_seedHash(), m_blob() { } @@ -58,6 +59,7 @@ xmrig::Job::Job(int poolId, bool nicehash, const Algorithm &algorithm, const Str m_diff(0), m_height(0), m_target(0), + m_seedHash(), m_blob() { } @@ -175,6 +177,15 @@ void xmrig::Job::setDiff(uint64_t diff) } +bool xmrig::Job::setSeedHash(const char *hash) +{ + if (!hash || (strlen(hash) != sizeof(m_seedHash) * 2)) + return false; + + return Buffer::fromHex(hash, sizeof(m_seedHash) * 2, m_seedHash); +} + + xmrig::Variant xmrig::Job::variant() const { switch (m_algorithm.algo()) { diff --git a/src/base/net/stratum/Job.h b/src/base/net/stratum/Job.h index 16e9a861..1c1b078b 100644 --- a/src/base/net/stratum/Job.h +++ b/src/base/net/stratum/Job.h @@ -55,6 +55,7 @@ public: bool setTarget(const char *target); void setAlgorithm(const char *algo); void setDiff(uint64_t diff); + bool setSeedHash(const char *hash); inline bool isNicehash() const { return m_nicehash; } inline bool isValid() const { return m_size > 0 && m_diff > 0; } @@ -64,6 +65,7 @@ public: inline const String &id() const { return m_id; } inline const uint32_t *nonce() const { return reinterpret_cast(m_blob + 39); } inline const uint8_t *blob() const { return m_blob; } + inline const uint8_t *seed_hash() const { return m_seedHash; } inline int poolId() const { return m_poolId; } inline int threadId() const { return m_threadId; } inline size_t size() const { return m_size; } @@ -106,6 +108,7 @@ private: uint64_t m_diff; uint64_t m_height; uint64_t m_target; + uint8_t m_seedHash[32]; uint8_t m_blob[kMaxBlobSize]; # ifdef XMRIG_PROXY_PROJECT diff --git a/src/base/net/stratum/Pool.cpp b/src/base/net/stratum/Pool.cpp index f441ba63..d3b4b4a3 100644 --- a/src/base/net/stratum/Pool.cpp +++ b/src/base/net/stratum/Pool.cpp @@ -517,6 +517,7 @@ void xmrig::Pool::rebuild() addVariant(VARIANT_RWZ); addVariant(VARIANT_ZLS); addVariant(VARIANT_DOUBLE); + addVariant(VARIANT_RX_WOW); addVariant(VARIANT_AUTO); # endif } diff --git a/src/common/crypto/Algorithm.cpp b/src/common/crypto/Algorithm.cpp index d9d3ead9..af139ae3 100644 --- a/src/common/crypto/Algorithm.cpp +++ b/src/common/crypto/Algorithm.cpp @@ -69,6 +69,7 @@ static AlgoData const algorithms[] = { { "cryptonight/rwz", "cn/rwz", xmrig::CRYPTONIGHT, xmrig::VARIANT_RWZ }, { "cryptonight/zls", "cn/zls", xmrig::CRYPTONIGHT, xmrig::VARIANT_ZLS }, { "cryptonight/double", "cn/double", xmrig::CRYPTONIGHT, xmrig::VARIANT_DOUBLE }, + { "randomx/wow", "rx/wow", xmrig::CRYPTONIGHT, xmrig::VARIANT_RX_WOW }, # ifndef XMRIG_NO_AEON { "cryptonight-lite", "cn-lite", xmrig::CRYPTONIGHT_LITE, xmrig::VARIANT_AUTO }, @@ -138,7 +139,8 @@ static const char *variants[] = { "r", "rwz", "zls", - "double" + "double", + "rx/wow", }; diff --git a/src/common/xmrig.h b/src/common/xmrig.h index e8ca8857..49a8d1f7 100644 --- a/src/common/xmrig.h +++ b/src/common/xmrig.h @@ -79,6 +79,7 @@ enum Variant { VARIANT_RWZ = 14, // CryptoNight variant 2 with 3/4 iterations and reversed shuffle operation (Graft) VARIANT_ZLS = 15, // CryptoNight variant 2 with 3/4 iterations (Zelerius) VARIANT_DOUBLE = 16, // CryptoNight variant 2 with double iterations (X-CASH) + VARIANT_RX_WOW = 17, // RandomX (Wownero) VARIANT_MAX }; diff --git a/src/workers/CpuThread.cpp b/src/workers/CpuThread.cpp index 2481162c..3bce832e 100644 --- a/src/workers/CpuThread.cpp +++ b/src/workers/CpuThread.cpp @@ -390,6 +390,8 @@ xmrig::CpuThread::cn_hash_fun xmrig::CpuThread::fn(Algo algorithm, AlgoVariant a cryptonight_quad_hash, cryptonight_penta_hash, + nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, // VARIANT_RX_WOW + # ifndef XMRIG_NO_AEON cryptonight_single_hash, cryptonight_double_hash, @@ -428,6 +430,7 @@ xmrig::CpuThread::cn_hash_fun xmrig::CpuThread::fn(Algo algorithm, AlgoVariant a nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, // VARIANT_RWZ nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, // VARIANT_ZLS nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, // VARIANT_DOUBLE + nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, // VARIANT_RX_WOW # else nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, // VARIANT_0 nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, // VARIANT_1 @@ -446,6 +449,7 @@ xmrig::CpuThread::cn_hash_fun xmrig::CpuThread::fn(Algo algorithm, AlgoVariant a nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, // VARIANT_RWZ nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, // VARIANT_ZLS nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, // VARIANT_DOUBLE + nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, // VARIANT_RX_WOW # endif # ifndef XMRIG_NO_SUMO @@ -498,6 +502,7 @@ xmrig::CpuThread::cn_hash_fun xmrig::CpuThread::fn(Algo algorithm, AlgoVariant a nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, // VARIANT_RWZ nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, // VARIANT_ZLS nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, // VARIANT_DOUBLE + nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, // VARIANT_RX_WOW # else nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, // VARIANT_0 nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, // VARIANT_1 @@ -516,6 +521,7 @@ xmrig::CpuThread::cn_hash_fun xmrig::CpuThread::fn(Algo algorithm, AlgoVariant a nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, // VARIANT_RWZ nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, // VARIANT_ZLS nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, // VARIANT_DOUBLE + nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, // VARIANT_RX_WOW # endif # ifndef XMRIG_NO_CN_PICO @@ -547,6 +553,7 @@ xmrig::CpuThread::cn_hash_fun xmrig::CpuThread::fn(Algo algorithm, AlgoVariant a nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, // VARIANT_RWZ nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, // VARIANT_ZLS nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, // VARIANT_DOUBLE + nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, // VARIANT_RX_WOW # else nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, // VARIANT_0 nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, // VARIANT_1 @@ -565,6 +572,7 @@ xmrig::CpuThread::cn_hash_fun xmrig::CpuThread::fn(Algo algorithm, AlgoVariant a nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, // VARIANT_RWZ nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, // VARIANT_ZLS nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, // VARIANT_DOUBLE + nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, // VARIANT_RX_WOW # endif }; diff --git a/src/workers/MultiWorker.cpp b/src/workers/MultiWorker.cpp index 8b9e0881..40caf380 100644 --- a/src/workers/MultiWorker.cpp +++ b/src/workers/MultiWorker.cpp @@ -38,6 +38,12 @@ MultiWorker::MultiWorker(ThreadHandle *handle) : Worker(handle) { m_memory = Mem::create(m_ctx, m_thread->algorithm(), N); + + const int flags = RANDOMX_FLAG_LARGE_PAGES | RANDOMX_FLAG_HARD_AES | RANDOMX_FLAG_FULL_MEM | RANDOMX_FLAG_JIT; + m_rx_vm = randomx_create_vm(static_cast(flags), nullptr, Workers::getDataset()); + if (!m_rx_vm) { + m_rx_vm = randomx_create_vm(static_cast(flags - RANDOMX_FLAG_LARGE_PAGES), nullptr, Workers::getDataset()); + } } @@ -45,6 +51,7 @@ template MultiWorker::~MultiWorker() { Mem::release(m_ctx, N, m_memory); + randomx_destroy_vm(m_rx_vm); } @@ -126,7 +133,14 @@ void MultiWorker::start() storeStats(); } - m_thread->fn(m_state.job.algorithm().variant())(m_state.blob, m_state.job.size(), m_hash, m_ctx, m_state.job.height()); + const xmrig::Variant v = m_state.job.algorithm().variant(); + if (v == xmrig::VARIANT_RX_WOW) { + Workers::updateDataset(m_state.job.seed_hash(), m_totalWays); + randomx_calculate_hash(m_rx_vm, m_state.blob, m_state.job.size(), m_hash); + } + else { + m_thread->fn(v)(m_state.blob, m_state.job.size(), m_hash, m_ctx, m_state.job.height()); + } for (size_t i = 0; i < N; ++i) { if (*reinterpret_cast(m_hash + (i * 32) + 24) < m_state.job.target()) { diff --git a/src/workers/MultiWorker.h b/src/workers/MultiWorker.h index 99d37e44..98acded9 100644 --- a/src/workers/MultiWorker.h +++ b/src/workers/MultiWorker.h @@ -31,6 +31,7 @@ #include "Mem.h" #include "net/JobResult.h" #include "workers/Worker.h" +#include "randomwow.h" class Handle; @@ -70,6 +71,8 @@ private: State m_pausedState; State m_state; uint8_t m_hash[N * 32]; + + randomx_vm* m_rx_vm; }; diff --git a/src/workers/Workers.cpp b/src/workers/Workers.cpp index 53990135..54373cc9 100644 --- a/src/workers/Workers.cpp +++ b/src/workers/Workers.cpp @@ -59,6 +59,11 @@ uv_mutex_t Workers::m_mutex; uv_rwlock_t Workers::m_rwlock; uv_timer_t *Workers::m_timer = nullptr; xmrig::Controller *Workers::m_controller = nullptr; +uv_rwlock_t Workers::m_rx_dataset_lock; +randomx_cache *Workers::m_rx_cache = nullptr; +randomx_dataset *Workers::m_rx_dataset = nullptr; +uint8_t Workers::m_rx_seed_hash[32] = {}; +std::atomic Workers::m_rx_dataset_init_thread_counter = 0; xmrig::Job Workers::job() @@ -187,6 +192,7 @@ void Workers::start(xmrig::Controller *controller) uv_mutex_init(&m_mutex); uv_rwlock_init(&m_rwlock); + uv_rwlock_init(&m_rx_dataset_lock); m_sequence = 1; m_paused = 1; @@ -356,3 +362,61 @@ void Workers::start(IWorker *worker) worker->start(); } + +void Workers::updateDataset(const uint8_t* seed_hash, const uint32_t num_threads) +{ + // Check if we need to update cache and dataset + if (memcmp(m_rx_seed_hash, seed_hash, sizeof(m_rx_seed_hash)) == 0) + return; + + const uint32_t thread_id = m_rx_dataset_init_thread_counter++; + LOG_NOTICE("Thread %u started updating RandomX dataset", thread_id); + + // Wait for all threads to get here + do { + std::this_thread::yield(); + } while (m_rx_dataset_init_thread_counter.load() != num_threads); + + // One of the threads updates cache + uv_rwlock_wrlock(&m_rx_dataset_lock); + if (memcmp(m_rx_seed_hash, seed_hash, sizeof(m_rx_seed_hash)) != 0) { + memcpy(m_rx_seed_hash, seed_hash, sizeof(m_rx_seed_hash)); + randomx_init_cache(m_rx_cache, m_rx_seed_hash, sizeof(m_rx_seed_hash)); + } + uv_rwlock_wrunlock(&m_rx_dataset_lock); + + // All threads update dataset + const uint32_t a = (randomx_dataset_item_count() * thread_id) / num_threads; + const uint32_t b = (randomx_dataset_item_count() * (thread_id + 1)) / num_threads; + randomx_init_dataset(m_rx_dataset, m_rx_cache, a, b - a); + + LOG_NOTICE("Thread %u finished updating RandomX dataset", thread_id); + + // Wait for all threads to complete + --m_rx_dataset_init_thread_counter; + do { + std::this_thread::yield(); + } while (m_rx_dataset_init_thread_counter.load() != 0); +} + +randomx_dataset* Workers::getDataset() +{ + if (m_rx_dataset) + return m_rx_dataset; + + uv_rwlock_wrlock(&m_rx_dataset_lock); + if (!m_rx_dataset) { + randomx_dataset* dataset = randomx_alloc_dataset(RANDOMX_FLAG_LARGE_PAGES); + if (!dataset) { + dataset = randomx_alloc_dataset(RANDOMX_FLAG_DEFAULT); + } + m_rx_cache = randomx_alloc_cache(static_cast(RANDOMX_FLAG_JIT | RANDOMX_FLAG_LARGE_PAGES)); + if (!m_rx_cache) { + m_rx_cache = randomx_alloc_cache(RANDOMX_FLAG_JIT); + } + m_rx_dataset = dataset; + } + uv_rwlock_wrunlock(&m_rx_dataset_lock); + + return m_rx_dataset; +} diff --git a/src/workers/Workers.h b/src/workers/Workers.h index 5b084fc2..3f6e307d 100644 --- a/src/workers/Workers.h +++ b/src/workers/Workers.h @@ -34,6 +34,7 @@ #include "base/net/stratum/Job.h" #include "net/JobResult.h" #include "rapidjson/fwd.h" +#include "randomwow.h" class Hashrate; @@ -72,6 +73,9 @@ public: static void threadsSummary(rapidjson::Document &doc); # endif + static void updateDataset(const uint8_t* seed_hash, uint32_t num_threads); + static randomx_dataset* getDataset(); + private: static void onReady(void *arg); static void onResult(uv_async_t *handle); @@ -114,6 +118,12 @@ private: static uv_rwlock_t m_rwlock; static uv_timer_t *m_timer; static xmrig::Controller *m_controller; + + static uv_rwlock_t m_rx_dataset_lock; + static randomx_cache *m_rx_cache; + static randomx_dataset *m_rx_dataset; + static uint8_t m_rx_seed_hash[32]; + static std::atomic m_rx_dataset_init_thread_counter; }; From 202d44c14704329c41edc194e1b11ec2e6644071 Mon Sep 17 00:00:00 2001 From: SChernykh Date: Sat, 15 Jun 2019 23:29:13 +0200 Subject: [PATCH 114/116] Fixed gcc compilation --- src/workers/Workers.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/workers/Workers.cpp b/src/workers/Workers.cpp index 54373cc9..591f92d0 100644 --- a/src/workers/Workers.cpp +++ b/src/workers/Workers.cpp @@ -63,7 +63,7 @@ uv_rwlock_t Workers::m_rx_dataset_lock; randomx_cache *Workers::m_rx_cache = nullptr; randomx_dataset *Workers::m_rx_dataset = nullptr; uint8_t Workers::m_rx_seed_hash[32] = {}; -std::atomic Workers::m_rx_dataset_init_thread_counter = 0; +std::atomic Workers::m_rx_dataset_init_thread_counter = {}; xmrig::Job Workers::job() From d0ce60a73aa103dcc00da85d6b19b73c263b116a Mon Sep 17 00:00:00 2001 From: SChernykh Date: Sat, 15 Jun 2019 23:50:31 +0200 Subject: [PATCH 115/116] Fixed auto-config --- src/core/config/Config.cpp | 3 ++- src/crypto/CryptoNight_constants.h | 4 ++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/src/core/config/Config.cpp b/src/core/config/Config.cpp index 88ddbb72..fb3fefac 100644 --- a/src/core/config/Config.cpp +++ b/src/core/config/Config.cpp @@ -160,7 +160,8 @@ bool xmrig::Config::finalize() const AlgoVariant av = getAlgoVariant(); m_threads.mode = m_threads.count ? Simple : Automatic; - const size_t size = CpuThread::multiway(av) * cn_select_memory(m_algorithm.algo()) / 1024; + const Variant v = m_algorithm.variant(); + const size_t size = CpuThread::multiway(av) * cn_select_memory(m_algorithm.algo(), v) / 1024; if (!m_threads.count) { m_threads.count = Cpu::info()->optimalThreadsCount(size, m_maxCpuUsage); diff --git a/src/crypto/CryptoNight_constants.h b/src/crypto/CryptoNight_constants.h index 1bc06a3b..4a66c16b 100644 --- a/src/crypto/CryptoNight_constants.h +++ b/src/crypto/CryptoNight_constants.h @@ -70,12 +70,12 @@ template<> inline constexpr size_t cn_select_memory() { retur template<> inline constexpr size_t cn_select_memory() { return CRYPTONIGHT_PICO_MEMORY; } -inline size_t cn_select_memory(Algo algorithm) +inline size_t cn_select_memory(Algo algorithm, Variant v = VARIANT_AUTO) { switch(algorithm) { case CRYPTONIGHT: - return CRYPTONIGHT_MEMORY; + return (v == VARIANT_RX_WOW) ? CRYPTONIGHT_LITE_MEMORY : CRYPTONIGHT_MEMORY; case CRYPTONIGHT_LITE: return CRYPTONIGHT_LITE_MEMORY; From 50ace41766743b3462fe0d02ba982782c1aa2c3b Mon Sep 17 00:00:00 2001 From: SChernykh Date: Sat, 15 Jun 2019 23:52:39 +0200 Subject: [PATCH 116/116] Fixed cmake for Linux --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 8f6e9226..0724cfdb 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -154,7 +154,7 @@ add_definitions(/DUNICODE) set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}/cmake") find_package(UV REQUIRED) -find_package(RANDOMWOW REQUIRED) +find_package(RandomWOW REQUIRED) include(cmake/flags.cmake)