1
0
mirror of https://github.com/xmrig/xmrig.git synced 2025-12-07 07:55:04 -05:00

Compare commits

..

85 Commits

Author SHA1 Message Date
XMRig
e46a2a508a v2.15.2-beta 2019-04-18 00:25:37 +07:00
XMRig
fe9aa9f3c4 Merge branch 'evo' into beta 2019-04-18 00:25:06 +07:00
xmrig
552858b9e3 Update CHANGELOG.md 2019-04-17 23:59:21 +07:00
XMRig
ff6544a14c Updated default config. 2019-04-17 19:03:15 +07:00
XMRig
d77e404439 Merge branch 'dev' into evo 2019-04-17 17:42:22 +07:00
xmrig
ff4d54dc4c Merge pull request #1012 from Spudz76/dev-fixClang9
Repair compilation with Clang 9.0.0
2019-04-16 02:37:19 +07:00
Tony Butler
699269bbae Upstream fixed it for good with [Added checks for _rotr.] and [Fixed _rotr detection.] 2019-04-15 13:26:55 -06:00
XMRig
9137f59ec1 #1012 Fixed _rotr detection. 2019-04-16 02:00:27 +07:00
XMRig
f9f7ef26b8 #1012 Added checks for _rotr. 2019-04-16 01:20:50 +07:00
Tony Butler
32c3d4b9f6 Repair compilation with Clang 9.0.0 (which now includes its own _rotr intrinsic) 2019-04-15 10:39:16 -06:00
XMRig
ee1d61d117 Fix Linux build. 2019-04-14 03:24:14 +07:00
XMRig
a3b303e885 Added checking for top_block_hash/hash. 2019-04-14 03:21:23 +07:00
XMRig
074b3869d2 Added JsonRequest. 2019-04-14 01:10:24 +07:00
XMRig
c0e668f36f Move files. 2019-04-13 23:58:58 +07:00
XMRig
21798edb8b Sync changes. 2019-04-13 19:09:22 +07:00
XMRig
23b0e3799e Fixed build on some systems. 2019-04-12 22:32:45 +07:00
XMRig
83a7a88b11 Fixed build without TLS support. 2019-04-12 19:25:03 +07:00
XMRig
60f6817d21 Merge branch 'feature-daemon' into evo 2019-04-12 19:08:30 +07:00
XMRig
867478b983 Added command line option --daemon and --daemon-poll-interval 2019-04-12 18:30:08 +07:00
XMRig
5e369a5af8 Fixed daemon support over HTTPS. 2019-04-12 04:25:47 +07:00
XMRig
62012a1a50 Added DaemonClient. 2019-04-12 03:25:21 +07:00
xmrig
54a1c614f7 Merge pull request #1011 from stoffu/config-max-msvc2017
Config: fix std::max issue with msvc2017
2019-04-11 14:08:45 +07:00
stoffu
cf7ce13986 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
2019-04-11 14:01:07 +09:00
XMRig
0d496aaf2f Prepare for daemon support. 2019-04-11 00:18:33 +07:00
XMRig
9a6944d694 Add IClient and BaseClient. 2019-04-10 18:29:33 +07:00
XMRig
1bd8d63508 64bit diff support. 2019-04-10 03:42:00 +07:00
XMRig
c41889477c Fix build. 2019-04-10 00:10:02 +07:00
XMRig
c823c54f9b Added HttpsClient. 2019-04-09 14:06:56 +07:00
XMRig
6812d22d63 Rename cmake option WITH_HTTPD to WITH_HTTP. 2019-04-09 02:27:19 +07:00
XMRig
241383068c Added HttpClient class. 2019-04-09 01:59:22 +07:00
XMRig
35d868fb48 Fix --userpass option. 2019-04-08 02:16:54 +07:00
XMRig
d6da0652ce Removed unused setters in Pool class. 2019-04-07 21:31:32 +07:00
XMRig
9561570c50 Fix build on FreeBSD. 2019-04-06 21:10:26 +07:00
XMRig
466aad8543 Fix build without ASM. 2019-04-06 20:07:20 +07:00
XMRig
db456a3e63 Merge branch 'feature-json-centric-config' into evo 2019-04-06 18:34:38 +07:00
XMRig
09df8c3846 Sync changes. 2019-04-06 18:32:24 +07:00
XMRig
5d9648956b Add milliseconds to log. 2019-04-06 02:11:02 +07:00
XMRig
1774b42345 Fix "colors" option. 2019-04-06 02:10:08 +07:00
XMRig
fa2a0b9b79 New config subsystem 2019-04-05 22:14:01 +07:00
XMRig
85ee55f309 Fixed, big HTTP responses was truncated. 2019-04-02 17:46:26 +07:00
XMRig
4aa7f01f13 v2.15.2-evo 2019-04-01 23:45:23 +07:00
XMRig
496870a59d Merge branch 'beta' into evo 2019-04-01 23:41:38 +07:00
XMRig
89d7e84f88 v2.15.1-beta 2019-04-01 19:04:48 +07:00
XMRig
29f683b01f Merge branch 'evo' into beta 2019-04-01 19:04:20 +07:00
xmrig
1e3e8df43c Update CHANGELOG.md 2019-04-01 19:01:34 +07:00
XMRig
1f45e77848 Fixed wrong status code for "GET /1/config" 2019-04-01 18:56:42 +07:00
XMRig
cf7245b469 Update default config. 2019-04-01 11:54:09 +07:00
XMRig
3b91817caf Special handle for favicon.ico 2019-04-01 11:50:28 +07:00
XMRig
4457089502 Added error log to http responses. 2019-04-01 02:46:41 +07:00
XMRig
40d9f53743 Sync changes. 2019-04-01 00:31:46 +07:00
XMRig
24e4328915 Fixed malformed HTTP response on Linux. 2019-04-01 00:21:15 +07:00
XMRig
0245ce5f35 Fix compile issue. 2019-04-01 00:00:40 +07:00
XMRig
96f5bd32b5 Merge branch 'feature-httpd' into evo 2019-03-31 23:34:17 +07:00
XMRig
e759ccf385 Sync changes. 2019-03-31 23:22:36 +07:00
XMRig
ca249f1f1c Cleanup. 2019-03-31 01:44:53 +07:00
XMRig
f8f9d6c0ef Restored API. 2019-03-31 01:31:40 +07:00
XMRig
e39ddeeea2 Removed IConfigCreator/ConfigCreator and changed file structure. 2019-03-30 21:27:54 +07:00
XMRig
d8aba7da7d Revert id and worker_id. 2019-03-30 20:46:08 +07:00
XMRig
bd6c7c64aa Added workaround, Google Chrome create extra dummy connections for future speed up. 2019-03-30 15:51:35 +07:00
XMRig
106e149324 Use static http_parser_settings. 2019-03-30 15:27:09 +07:00
XMRig
c9f9e6787c Restore network API. 2019-03-30 03:10:27 +07:00
XMRig
9c66c9b30f Added classes IApiRequest, ApiRequest, HttpApiRequest. 2019-03-30 02:26:30 +07:00
XMRig
dd036368e2 New API class. 2019-03-30 00:16:01 +07:00
XMRig
9cb43f9883 Fix log. 2019-03-29 17:22:25 +07:00
XMRig
3f1eefb131 HTTP layer ready for API calls. 2019-03-29 17:14:30 +07:00
XMRig
202b74367a Optimize HttpResponse for fixed size API responses. 2019-03-29 14:22:10 +07:00
XMRig
9daa5874f5 Change HttpResponse creation method. 2019-03-29 12:56:34 +07:00
XMRig
01ad6bf2d9 Added new HTTP server (tiny wrapper on top of libuv + http_parser), removed libmicrohttpd support. 2019-03-29 12:33:11 +07:00
XMRig
725796a1ab New API settings. 2019-03-29 02:31:56 +07:00
XMRig
1e0c410eea XMRIG_FEATURE_HTTP & XMRIG_FEATURE_API 2019-03-28 22:54:27 +07:00
XMRig
034720e888 Use XMRIG_FEATURE_TLS instead of XMRIG_NO_TLS 2019-03-28 22:13:27 +07:00
xmrig
22483dd231 Update CHANGELOG.md 2019-03-27 21:18:48 +07:00
XMRig
5db458efd4 Fix macOS build. 2019-03-27 20:03:15 +07:00
XMRig
3f4886bb86 Fix CPU info colors. 2019-03-27 19:29:29 +07:00
XMRig
82bbef614e Remove unused field. 2019-03-27 19:27:29 +07:00
XMRig
933c0d40b7 Merge branch 'dev' into evo 2019-03-27 19:20:12 +07:00
XMRig
cad3e7a101 Sync changes. 2019-03-27 19:18:54 +07:00
XMRig
d7795ca990 Remove uv_cancel for DNS requests. 2019-03-27 17:22:04 +07:00
XMRig
ba910a46ba Fix accidentally removed code. 2019-03-27 15:56:31 +07:00
XMRig
f43929db98 New log support. 2019-03-27 01:29:37 +07:00
XMRig
17e9e036f1 Fix Linux build. 2019-03-26 22:05:56 +07:00
XMRig
ced25c3fa0 Log subsystem rewritten, to handle both color and not color logs simultaneously and overall simplicity. 2019-03-26 19:56:35 +07:00
XMRig
0a893c2172 Merge branch 'beta' into evo 2019-03-24 21:33:06 +07:00
xmrig
1f77b049e3 Merge pull request #992 from Spudz76/dev-clang35fix
Fix compilation with Clang 3.5
2019-03-16 01:30:13 +07:00
Tony Butler
29373c4226 Fix compilation with Clang 3.5 for those with limited compiler choices
Performance similar to gcc7+ on systems where gcc4 is the only alternative
2019-03-15 07:19:47 -06:00
150 changed files with 9956 additions and 3759 deletions

View File

@@ -1,3 +1,13 @@
# 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.
# v2.15.0-beta
- [#314](https://github.com/xmrig/xmrig-proxy/issues/314) Added donate over proxy feature.
- Added new option `donate-over-proxy`.

View File

@@ -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)
@@ -21,28 +21,21 @@ include (src/base/base.cmake)
set(HEADERS
"${HEADERS_BASE}"
src/api/NetworkState.h
"${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/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
src/common/xmrig.h
src/core/ConfigLoader_default.h
src/core/ConfigLoader_platform.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
src/interfaces/IThread.h
@@ -50,13 +43,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
)
@@ -85,28 +79,23 @@ endif()
set(SOURCES
"${SOURCES_BASE}"
src/api/NetworkState.cpp
"${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/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/config/Config.cpp
src/core/config/ConfigTransform.cpp
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
@@ -189,12 +178,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()
@@ -215,31 +198,22 @@ if (WITH_EMBEDDED_CONFIG)
add_definitions(/DXMRIG_FEATURE_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()
if (WITH_HTTP)
set(HTTP_SOURCES
src/api/Api.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 "")
set(MHD_LIBRARY "")
add_definitions(/DXMRIG_NO_HTTPD)
add_definitions(/DXMRIG_NO_API)
set(HTTP_SOURCES "")
endif()
include_directories(src)
@@ -254,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})
target_link_libraries(${CMAKE_PROJECT_NAME} ${XMRIG_ASM_LIBRARY} ${OPENSSL_LIBRARIES} ${UV_LIBRARIES} ${MHD_LIBRARY} ${EXTRA_LIBS} ${CPUID_LIB})
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})

View File

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

View File

@@ -13,17 +13,19 @@ 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()
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()

View File

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

View File

@@ -1,7 +1,7 @@
#include <windows.h>
#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

68
src/3rdparty/http-parser/AUTHORS vendored Normal file
View File

@@ -0,0 +1,68 @@
# Authors ordered by first contribution.
Ryan Dahl <ry@tinyclouds.org>
Jeremy Hinegardner <jeremy@hinegardner.org>
Sergey Shepelev <temotor@gmail.com>
Joe Damato <ice799@gmail.com>
tomika <tomika_nospam@freemail.hu>
Phoenix Sol <phoenix@burninglabs.com>
Cliff Frey <cliff@meraki.com>
Ewen Cheslack-Postava <ewencp@cs.stanford.edu>
Santiago Gala <sgala@apache.org>
Tim Becker <tim.becker@syngenio.de>
Jeff Terrace <jterrace@gmail.com>
Ben Noordhuis <info@bnoordhuis.nl>
Nathan Rajlich <nathan@tootallnate.net>
Mark Nottingham <mnot@mnot.net>
Aman Gupta <aman@tmm1.net>
Tim Becker <tim.becker@kuriositaet.de>
Sean Cunningham <sean.cunningham@mandiant.com>
Peter Griess <pg@std.in>
Salman Haq <salman.haq@asti-usa.com>
Cliff Frey <clifffrey@gmail.com>
Jon Kolb <jon@b0g.us>
Fouad Mardini <f.mardini@gmail.com>
Paul Querna <pquerna@apache.org>
Felix Geisendörfer <felix@debuggable.com>
koichik <koichik@improvement.jp>
Andre Caron <andre.l.caron@gmail.com>
Ivo Raisr <ivosh@ivosh.net>
James McLaughlin <jamie@lacewing-project.org>
David Gwynne <loki@animata.net>
Thomas LE ROUX <thomas@november-eleven.fr>
Randy Rizun <rrizun@ortivawireless.com>
Andre Louis Caron <andre.louis.caron@usherbrooke.ca>
Simon Zimmermann <simonz05@gmail.com>
Erik Dubbelboer <erik@dubbelboer.com>
Martell Malone <martellmalone@gmail.com>
Bertrand Paquet <bpaquet@octo.com>
BogDan Vatra <bogdan@kde.org>
Peter Faiman <peter@thepicard.org>
Corey Richardson <corey@octayn.net>
Tóth Tamás <tomika_nospam@freemail.hu>
Cam Swords <cam.swords@gmail.com>
Chris Dickinson <christopher.s.dickinson@gmail.com>
Uli Köhler <ukoehler@btronik.de>
Charlie Somerville <charlie@charliesomerville.com>
Patrik Stutz <patrik.stutz@gmail.com>
Fedor Indutny <fedor.indutny@gmail.com>
runner <runner.mei@gmail.com>
Alexis Campailla <alexis@janeasystems.com>
David Wragg <david@wragg.org>
Vinnie Falco <vinnie.falco@gmail.com>
Alex Butum <alexbutum@linux.com>
Rex Feng <rexfeng@gmail.com>
Alex Kocharin <alex@kocharin.ru>
Mark Koopman <markmontymark@yahoo.com>
Helge Heß <me@helgehess.eu>
Alexis La Goutte <alexis.lagoutte@gmail.com>
George Miroshnykov <george.miroshnykov@gmail.com>
Maciej Małecki <me@mmalecki.com>
Marc O'Morain <github.com@marcomorain.com>
Jeff Pinner <jpinner@twitter.com>
Timothy J Fontaine <tjfontaine@gmail.com>
Akagi201 <akagi201@gmail.com>
Romain Giraud <giraud.romain@gmail.com>
Jay Satiro <raysatiro@yahoo.com>
Arne Steen <Arne.Steen@gmx.de>
Kjell Schubert <kjell.schubert@gmail.com>
Olivier Mengué <dolmen@cpan.org>

19
src/3rdparty/http-parser/LICENSE-MIT vendored Normal file
View File

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

246
src/3rdparty/http-parser/README.md vendored Normal file
View File

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

2501
src/3rdparty/http-parser/http_parser.c vendored Normal file

File diff suppressed because it is too large Load Diff

439
src/3rdparty/http-parser/http_parser.h vendored Normal file
View File

@@ -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 <stddef.h>
#if defined(_WIN32) && !defined(__MINGW32__) && \
(!defined(_MSC_VER) || _MSC_VER<1600) && !defined(__WINE__)
#include <BaseTsd.h>
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 <stdint.h>
#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=<value>). 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

View File

@@ -31,11 +31,11 @@
#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/config/Config.h"
#include "core/Controller.h"
#include "crypto/CryptoNight.h"
#include "Mem.h"
@@ -45,14 +45,8 @@
#include "workers/Workers.h"
#ifndef XMRIG_NO_HTTPD
# include "common/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;
# ifndef XMRIG_NO_HTTPD
delete m_httpd;
# endif
}
@@ -98,24 +88,9 @@ int xmrig::App::exec()
return 0;
}
# ifndef XMRIG_NO_API
Api::start(m_controller);
# endif
# ifndef XMRIG_NO_HTTPD
m_httpd = new Httpd(
m_controller->config()->apiPort(),
m_controller->config()->apiToken(),
m_controller->config()->isApiIPv6(),
m_controller->config()->isApiRestricted()
);
m_httpd->start();
# endif
Workers::start(m_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());
@@ -135,7 +110,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 +118,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;
@@ -185,14 +160,10 @@ void xmrig::App::onSignal(int signum)
void xmrig::App::close()
{
# ifndef XMRIG_NO_HTTPD
m_httpd->stop();
# endif
m_signals->stop();
m_console->stop();
m_controller->stop();
Workers::stop();
Log::release();
Log::destroy();
}

View File

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

View File

@@ -30,8 +30,8 @@
#include "App.h"
#include "common/log/Log.h"
#include "core/Config.h"
#include "base/io/log/Log.h"
#include "core/config/Config.h"
#include "core/Controller.h"

View File

@@ -29,7 +29,7 @@
#include "App.h"
#include "core/Controller.h"
#include "core/Config.h"
#include "core/config/Config.h"
void xmrig::App::background()

View File

@@ -28,13 +28,18 @@
#include <sys/mman.h>
#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"
#include "Mem.h"
#if defined(__APPLE__)
# include <mach/vm_statistics.h>
#endif
void Mem::init(bool enabled)
{
m_enabled = enabled;

View File

@@ -30,7 +30,7 @@
#include <tchar.h>
#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);
}

View File

@@ -28,10 +28,10 @@
#include <uv.h>
#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/config/Config.h"
#include "core/Controller.h"
#include "crypto/Asm.h"
#include "Mem.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::i()->text(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(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::i()->text(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::i()->text(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",
"CPU",
Cpu::info()->brand(),
Cpu::info()->sockets(),
Cpu::info()->isX64() ? "" : "-",
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);
# 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_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);
# endif
}
@@ -108,49 +90,48 @@ 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")
: " * %-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::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(),
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::i()->text(config->isColors() ? GREEN_BOLD(" * ") WHITE_BOLD("%-13sauto:%s")
: " * %-13sauto:%s", "ASSEMBLY", asmName(assembly, config->isColors()));
xmrig::Log::print(GREEN_BOLD(" * ") WHITE_BOLD("%-13sauto:%s"), "ASSEMBLY", asmName(assembly));
}
else {
xmrig::Log::i()->text(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"), "ASSEMBLY", asmName(config->assembly()));
}
# endif
}
static void print_commands(xmrig::Config *config)
static void print_commands(xmrig::Config *)
{
if (config->isColors()) {
xmrig::Log::i()->text(GREEN_BOLD(" * ") WHITE_BOLD("COMMANDS ") MAGENTA_BOLD("h") WHITE_BOLD("ashrate, ")
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"));
}
else {
xmrig::Log::i()->text(" * COMMANDS 'h' hashrate, 'p' pause, 'r' resume");
xmrig::Log::print(" * COMMANDS 'h' hashrate, 'p' pause, 'r' resume");
}
}
@@ -161,8 +142,7 @@ 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();
print_commands(controller->config());
}

View File

@@ -22,52 +22,167 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <string.h>
#include <uv.h>
#ifndef _WIN32
# include <unistd.h>
#endif
#include "3rdparty/http-parser/http_parser.h"
#include "api/Api.h"
#include "api/ApiRouter.h"
#include "common/api/HttpReply.h"
#include "common/api/HttpRequest.h"
#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"
#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(Base *base) :
m_base(base),
m_id(),
m_workerId(),
m_httpd(nullptr)
{
m_router = new ApiRouter(controller);
base->addListener(this);
return true;
genId(base->config()->apiId());
m_v1 = new ApiRouter(base);
addListener(m_v1);
}
void Api::release()
xmrig::Api::~Api()
{
delete m_router;
delete m_v1;
# ifdef XMRIG_FEATURE_HTTP
delete m_httpd;
# endif
}
void Api::exec(const xmrig::HttpRequest &req, xmrig::HttpReply &reply)
void xmrig::Api::request(const HttpData &req)
{
if (!m_router) {
reply.status = 500;
HttpApiRequest request(req, m_base->config()->http().isRestricted());
exec(request);
}
void xmrig::Api::start()
{
genWorkerId(m_base->config()->apiWorkerId());
# ifdef XMRIG_FEATURE_HTTP
m_httpd = new Httpd(m_base);
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::exec(IApiRequest &request)
{
using namespace rapidjson;
if (request.method() == IApiRequest::METHOD_GET && (request.url() == "/1/summary" || request.url() == "/api.json")) {
request.accept();
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) {
listener->onRequest(request);
if (request.isDone()) {
return;
}
}
request.done(request.isNew() ? HTTP_STATUS_NOT_FOUND : HTTP_STATUS_OK);
}
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<uint16_t>(m_base->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);
}
}

View File

@@ -26,32 +26,56 @@
#define XMRIG_API_H
#include <uv.h>
#include <vector>
class ApiRouter;
class Hashrate;
#include "base/kernel/interfaces/IBaseListener.h"
namespace xmrig {
class Controller;
class HttpReply;
class HttpRequest;
class NetworkState;
}
class Api
class ApiRouter;
class Base;
class Httpd;
class HttpData;
class IApiListener;
class IApiRequest;
class String;
class Api : public IBaseListener
{
public:
static bool start(xmrig::Controller *controller);
static void release();
Api(Base *base);
~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; }
inline void addListener(IApiListener *listener) { m_listeners.push_back(listener); }
void request(const HttpData &req);
void start();
void stop();
protected:
void onConfigChanged(Config *config, Config *previousConfig) override;
private:
static ApiRouter *m_router;
void exec(IApiRequest &request);
void genId(const String &id);
void genWorkerId(const String &id);
ApiRouter *m_v1;
Base *m_base;
char m_id[32];
char m_workerId[128];
Httpd *m_httpd;
std::vector<IApiListener *> m_listeners;
};
} // namespace xmrig
#endif /* XMRIG_API_H */

View File

@@ -1,339 +0,0 @@
/* XMRig
* Copyright 2010 Jeff Garzik <jgarzik@pobox.com>
* Copyright 2012-2014 pooler <pooler@litecoinpool.org>
* Copyright 2014 Lucas Jones <https://github.com/lucasjones>
* Copyright 2014-2016 Wolf9466 <https://github.com/OhGodAPet>
* Copyright 2016 Jay D Dee <jayddee246@gmail.com>
* Copyright 2017-2018 XMR-Stak <https://github.com/fireice-uk>, <https://github.com/psychocrypt>
* Copyright 2018-2019 SChernykh <https://github.com/SChernykh>
* Copyright 2016-2019 XMRig <https://github.com/xmrig>, <support@xmrig.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <math.h>
#include <string.h>
#include <uv.h>
#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);
getResults(doc);
getConnection(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::tick(const xmrig::NetworkState &network)
{
m_network = network;
}
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<rapidjson::StringBuffer> 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<uint16_t>(m_controller->config()->apiPort());
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::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();
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::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();
auto &allocator = doc.GetAllocator();
const Hashrate *hr = Workers::hashrate();
Workers::threadsSummary(doc);
const std::vector<xmrig::IThread *> &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);
}

View File

@@ -1,76 +0,0 @@
/* XMRig
* Copyright 2010 Jeff Garzik <jgarzik@pobox.com>
* Copyright 2012-2014 pooler <pooler@litecoinpool.org>
* Copyright 2014 Lucas Jones <https://github.com/lucasjones>
* Copyright 2014-2016 Wolf9466 <https://github.com/OhGodAPet>
* Copyright 2016 Jay D Dee <jayddee246@gmail.com>
* Copyright 2017-2018 XMR-Stak <https://github.com/fireice-uk>, <https://github.com/psychocrypt>
* Copyright 2018-2019 SChernykh <https://github.com/SChernykh>
* Copyright 2016-2019 XMRig <https://github.com/xmrig>, <support@xmrig.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef XMRIG_APIROUTER_H
#define XMRIG_APIROUTER_H
#include "api/NetworkState.h"
#include "common/interfaces/IControllerListener.h"
#include "rapidjson/fwd.h"
class Hashrate;
namespace xmrig {
class Controller;
class HttpReply;
class HttpRequest;
}
class ApiRouter : public xmrig::IControllerListener
{
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);
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;
};
#endif /* XMRIG_APIROUTER_H */

193
src/api/Httpd.cpp Normal file
View File

@@ -0,0 +1,193 @@
/* XMRig
* Copyright 2010 Jeff Garzik <jgarzik@pobox.com>
* Copyright 2012-2014 pooler <pooler@litecoinpool.org>
* Copyright 2014 Lucas Jones <https://github.com/lucasjones>
* Copyright 2014-2016 Wolf9466 <https://github.com/OhGodAPet>
* Copyright 2016 Jay D Dee <jayddee246@gmail.com>
* Copyright 2017-2018 XMR-Stak <https://github.com/fireice-uk>, <https://github.com/psychocrypt>
* Copyright 2018-2019 SChernykh <https://github.com/SChernykh>
* Copyright 2016-2019 XMRig <https://github.com/xmrig>, <support@xmrig.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "3rdparty/http-parser/http_parser.h"
#include "api/Api.h"
#include "api/Httpd.h"
#include "base/io/log/Log.h"
#include "base/net/http/HttpApiResponse.h"
#include "base/net/http/HttpData.h"
#include "base/net/http/HttpServer.h"
#include "base/net/tools/TcpServer.h"
#include "core/config/Config.h"
#include "core/Controller.h"
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
xmrig::Httpd::Httpd(Base *base) :
m_base(base),
m_http(nullptr),
m_server(nullptr),
m_port(0)
{
base->addListener(this);
}
xmrig::Httpd::~Httpd()
{
}
bool xmrig::Httpd::start()
{
const Http &config = m_base->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<uint16_t>(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<const char *>(LockResource(res));
faviconSize = SizeofResource(nullptr, src);
}
}
# endif
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::onHttpData(const HttpData &data)
{
if (data.method == HTTP_OPTIONS) {
return HttpApiResponse(data.id()).end();
}
if (data.method == HTTP_GET && data.url == "/favicon.ico") {
# ifdef _WIN32
if (favicon != nullptr) {
HttpResponse response(data.id());
response.setHeader("Content-Type", "image/x-icon");
return response.end(favicon, faviconSize);
}
# endif
return HttpResponse(data.id(), 404).end();
}
if (data.method > 4) {
return HttpApiResponse(data.id(), HTTP_STATUS_METHOD_NOT_ALLOWED).end();
}
const int status = auth(data);
if (status != HTTP_STATUS_OK) {
return HttpApiResponse(data.id(), status).end();
}
if (data.method != HTTP_GET) {
if (m_base->config()->http().isRestricted()) {
return HttpApiResponse(data.id(), HTTP_STATUS_FORBIDDEN).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(data);
}
int xmrig::Httpd::auth(const HttpData &req) const
{
const Http &config = m_base->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;
}

70
src/api/Httpd.h Normal file
View File

@@ -0,0 +1,70 @@
/* XMRig
* Copyright 2010 Jeff Garzik <jgarzik@pobox.com>
* Copyright 2012-2014 pooler <pooler@litecoinpool.org>
* Copyright 2014 Lucas Jones <https://github.com/lucasjones>
* Copyright 2014-2016 Wolf9466 <https://github.com/OhGodAPet>
* Copyright 2016 Jay D Dee <jayddee246@gmail.com>
* Copyright 2017-2018 XMR-Stak <https://github.com/fireice-uk>, <https://github.com/psychocrypt>
* Copyright 2018-2019 SChernykh <https://github.com/SChernykh>
* Copyright 2016-2019 XMRig <https://github.com/xmrig>, <support@xmrig.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef XMRIG_HTTPD_H
#define XMRIG_HTTPD_H
#include <stdint.h>
#include "base/kernel/interfaces/IBaseListener.h"
#include "base/kernel/interfaces/IHttpListener.h"
namespace xmrig {
class Base;
class HttpServer;
class TcpServer;
class Httpd : public IBaseListener, public IHttpListener
{
public:
Httpd(Base *base);
~Httpd() override;
bool start();
void stop();
protected:
void onConfigChanged(Config *config, Config *previousConfig) override;
void onHttpData(const HttpData &data) override;
private:
int auth(const HttpData &req) const;
Base *m_base;
HttpServer *m_http;
TcpServer *m_server;
uint16_t m_port;
};
} /* namespace xmrig */
#endif /* XMRIG_HTTPD_H */

View File

@@ -20,31 +20,26 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef __CONFIGCREATOR_H__
#define __CONFIGCREATOR_H__
#include "common/interfaces/IConfigCreator.h"
#include "core/Config.h"
#ifndef XMRIG_IAPILISTENER_H
#define XMRIG_IAPILISTENER_H
namespace xmrig {
class IConfig;
class IApiRequest;
class ConfigCreator : public IConfigCreator
class IApiListener
{
public:
inline IConfig *create() const override
{
return new Config();
}
virtual ~IApiListener() = default;
virtual void onRequest(IApiRequest &request) = 0;
};
} /* namespace xmrig */
#endif // __CONFIGCREATOR_H__
#endif // XMRIG_IAPILISTENER_H

View File

@@ -0,0 +1,72 @@
/* XMRig
* Copyright 2010 Jeff Garzik <jgarzik@pobox.com>
* Copyright 2012-2014 pooler <pooler@litecoinpool.org>
* Copyright 2014 Lucas Jones <https://github.com/lucasjones>
* Copyright 2014-2016 Wolf9466 <https://github.com/OhGodAPet>
* Copyright 2016 Jay D Dee <jayddee246@gmail.com>
* Copyright 2016-2018 XMRig <support@xmrig.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef 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

View File

@@ -0,0 +1,39 @@
/* XMRig
* Copyright 2010 Jeff Garzik <jgarzik@pobox.com>
* Copyright 2012-2014 pooler <pooler@litecoinpool.org>
* Copyright 2014 Lucas Jones <https://github.com/lucasjones>
* Copyright 2014-2016 Wolf9466 <https://github.com/OhGodAPet>
* Copyright 2016 Jay D Dee <jayddee246@gmail.com>
* Copyright 2017-2018 XMR-Stak <https://github.com/fireice-uk>, <https://github.com/psychocrypt>
* Copyright 2018-2019 SChernykh <https://github.com/SChernykh>
* Copyright 2016-2019 XMRig <https://github.com/xmrig>, <support@xmrig.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "api/requests/ApiRequest.h"
xmrig::ApiRequest::ApiRequest(Source source, bool restricted) :
m_restricted(restricted),
m_source(source),
m_state(STATE_NEW)
{
}
xmrig::ApiRequest::~ApiRequest()
{
}

View File

@@ -22,32 +22,46 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef XMRIG_JSON_H
#define XMRIG_JSON_H
#ifndef XMRIG_APIREQUEST_H
#define XMRIG_APIREQUEST_H
#include "rapidjson/fwd.h"
#include "api/interfaces/IApiRequest.h"
namespace xmrig {
class Json
class ApiRequest : public IApiRequest
{
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 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);
static unsigned getUint(const rapidjson::Value &obj, const char *key, unsigned defaultValue = 0);
ApiRequest(Source source, bool restricted);
~ApiRequest() override;
static bool get(const char *fileName, rapidjson::Document &doc);
static bool save(const char *fileName, const rapidjson::Document &doc);
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 */
} // namespace xmrig
#endif /* XMRIG_JSON_H */
#endif // XMRIG_APIREQUEST_H

View File

@@ -23,42 +23,54 @@
*/
#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"
#include "api/requests/HttpApiRequest.h"
#include "base/net/http/HttpData.h"
#include "rapidjson/error/en.h"
xmrig::ConfigWatcher::ConfigWatcher(const String &path, IConfigCreator *creator, IConfigListener *listener) :
m_creator(creator),
m_listener(listener)
xmrig::HttpApiRequest::HttpApiRequest(const HttpData &req, bool restricted) :
ApiRequest(SOURCE_HTTP, restricted),
m_parsed(false),
m_req(req),
m_res(req.id()),
m_url(req.url.c_str())
{
m_watcher = new Watcher(path, this);
}
xmrig::ConfigWatcher::~ConfigWatcher()
const rapidjson::Value &xmrig::HttpApiRequest::json() const
{
delete m_watcher;
return m_body;
}
void xmrig::ConfigWatcher::onFileChanged(const String &fileName)
xmrig::IApiRequest::Method xmrig::HttpApiRequest::method() const
{
LOG_WARN("\"%s\" was changed, reloading configuration", fileName.data());
return static_cast<IApiRequest::Method>(m_req.method);
}
IConfig *config = m_creator->create();
ConfigLoader::loadFromFile(config, fileName);
if (!config->finalize()) {
LOG_ERR("reloading failed");
void xmrig::HttpApiRequest::accept()
{
using namespace rapidjson;
delete config;
return;
ApiRequest::accept();
if (!m_parsed && !m_req.body.empty()) {
m_parsed = true;
m_body.Parse<kParseCommentsFlag | kParseTrailingCommasFlag>(m_req.body.c_str());
if (m_body.HasParseError()) {
reply().AddMember("error", StringRef(GetParseError_En(m_body.GetParseError())), doc().GetAllocator());;
}
}
m_listener->onNewConfig(config);
}
void xmrig::HttpApiRequest::done(int status)
{
ApiRequest::done(status);
m_res.setStatus(status);
m_res.end();
}

View File

@@ -0,0 +1,69 @@
/* XMRig
* Copyright 2010 Jeff Garzik <jgarzik@pobox.com>
* Copyright 2012-2014 pooler <pooler@litecoinpool.org>
* Copyright 2014 Lucas Jones <https://github.com/lucasjones>
* Copyright 2014-2016 Wolf9466 <https://github.com/OhGodAPet>
* Copyright 2016 Jay D Dee <jayddee246@gmail.com>
* Copyright 2017-2018 XMR-Stak <https://github.com/fireice-uk>, <https://github.com/psychocrypt>
* Copyright 2018-2019 SChernykh <https://github.com/SChernykh>
* Copyright 2016-2019 XMRig <https://github.com/xmrig>, <support@xmrig.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef 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 HttpData;
class HttpApiRequest : public ApiRequest
{
public:
HttpApiRequest(const HttpData &req, bool restricted);
protected:
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 HttpData &m_req;
HttpApiResponse m_res;
rapidjson::Document m_body;
String m_url;
};
} // namespace xmrig
#endif // XMRIG_HTTPAPIREQUEST_H

178
src/api/v1/ApiRouter.cpp Normal file
View File

@@ -0,0 +1,178 @@
/* XMRig
* Copyright 2010 Jeff Garzik <jgarzik@pobox.com>
* Copyright 2012-2014 pooler <pooler@litecoinpool.org>
* Copyright 2014 Lucas Jones <https://github.com/lucasjones>
* Copyright 2014-2016 Wolf9466 <https://github.com/OhGodAPet>
* Copyright 2016 Jay D Dee <jayddee246@gmail.com>
* Copyright 2017-2018 XMR-Stak <https://github.com/fireice-uk>, <https://github.com/psychocrypt>
* Copyright 2018-2019 SChernykh <https://github.com/SChernykh>
* Copyright 2016-2019 XMRig <https://github.com/xmrig>, <support@xmrig.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <math.h>
#include <string.h>
#include <uv.h>
#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 "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(Base *base) :
m_base(base)
{
}
xmrig::ApiRouter::~ApiRouter()
{
}
void xmrig::ApiRouter::onRequest(IApiRequest &request)
{
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);
}
request.accept();
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_base->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_base->config()->algorithm().shortName()), allocator);
reply.AddMember("hugepages", Workers::hugePages() > 0, allocator);
reply.AddMember("donate_level", m_base->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<IThread *> &threads = m_base->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);
}

63
src/api/v1/ApiRouter.h Normal file
View File

@@ -0,0 +1,63 @@
/* XMRig
* Copyright 2010 Jeff Garzik <jgarzik@pobox.com>
* Copyright 2012-2014 pooler <pooler@litecoinpool.org>
* Copyright 2014 Lucas Jones <https://github.com/lucasjones>
* Copyright 2014-2016 Wolf9466 <https://github.com/OhGodAPet>
* Copyright 2016 Jay D Dee <jayddee246@gmail.com>
* Copyright 2017-2018 XMR-Stak <https://github.com/fireice-uk>, <https://github.com/psychocrypt>
* Copyright 2018-2019 SChernykh <https://github.com/SChernykh>
* Copyright 2016-2019 XMRig <https://github.com/xmrig>, <support@xmrig.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef XMRIG_APIROUTER_H
#define XMRIG_APIROUTER_H
#include "api/interfaces/IApiListener.h"
#include "rapidjson/fwd.h"
class Hashrate;
namespace xmrig {
class Base;
class ApiRouter : public xmrig::IApiListener
{
public:
ApiRouter(Base *base);
~ApiRouter() override;
protected:
void onRequest(IApiRequest &request) override;
private:
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;
Base *m_base;
};
} // namespace xmrig
#endif /* XMRIG_APIROUTER_H */

View File

@@ -1,13 +1,26 @@
set(HEADERS_BASE
src/base/io/Console.h
src/base/io/Json.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
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/IClient.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/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
@@ -17,6 +30,8 @@ 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/BaseClient.h
src/base/net/stratum/Client.h
src/base/net/stratum/Job.h
src/base/net/stratum/Pool.h
@@ -27,6 +42,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
@@ -36,13 +52,23 @@ set(HEADERS_BASE
set(SOURCES_BASE
src/base/io/Console.cpp
src/base/io/Json.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/Process.cpp
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/BaseClient.cpp
src/base/net/stratum/Client.cpp
src/base/net/stratum/Job.cpp
src/base/net/stratum/Pool.cpp
@@ -57,7 +83,55 @@ 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()
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/io/log/backends/SysLog.h src/base/io/log/backends/SysLog.cpp)
endif()
endif()
if (WITH_HTTP)
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/HttpClient.h
src/base/net/http/HttpContext.h
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
)
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
src/base/net/stratum/DaemonClient.cpp
src/base/net/tools/TcpServer.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)

View File

@@ -23,10 +23,17 @@
*/
#include "base/io/Json.h"
#include "base/io/json/Json.h"
#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();
}

79
src/base/io/json/Json.h Normal file
View File

@@ -0,0 +1,79 @@
/* XMRig
* Copyright 2010 Jeff Garzik <jgarzik@pobox.com>
* Copyright 2012-2014 pooler <pooler@litecoinpool.org>
* Copyright 2014 Lucas Jones <https://github.com/lucasjones>
* Copyright 2014-2016 Wolf9466 <https://github.com/OhGodAPet>
* Copyright 2016 Jay D Dee <jayddee246@gmail.com>
* Copyright 2017-2018 XMR-Stak <https://github.com/fireice-uk>, <https://github.com/psychocrypt>
* Copyright 2018-2019 SChernykh <https://github.com/SChernykh>
* Copyright 2016-2019 XMRig <https://github.com/xmrig>, <support@xmrig.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef XMRIG_JSON_H
#define XMRIG_JSON_H
#include "base/kernel/interfaces/IJsonReader.h"
#include "rapidjson/fwd.h"
namespace xmrig {
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);
static unsigned getUint(const rapidjson::Value &obj, const char *key, unsigned defaultValue = 0);
static bool get(const char *fileName, rapidjson::Document &doc);
static bool save(const char *fileName, const rapidjson::Document &doc);
};
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 */
#endif /* XMRIG_JSON_H */

View File

@@ -0,0 +1,213 @@
/* XMRig
* Copyright 2010 Jeff Garzik <jgarzik@pobox.com>
* Copyright 2012-2014 pooler <pooler@litecoinpool.org>
* Copyright 2014 Lucas Jones <https://github.com/lucasjones>
* Copyright 2014-2016 Wolf9466 <https://github.com/OhGodAPet>
* Copyright 2016 Jay D Dee <jayddee246@gmail.com>
* Copyright 2017-2018 XMR-Stak <https://github.com/fireice-uk>, <https://github.com/psychocrypt>
* Copyright 2018-2019 SChernykh <https://github.com/SChernykh>
* Copyright 2016-2019 XMRig <https://github.com/xmrig>, <support@xmrig.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "base/io/json/Json.h"
#include "base/io/json/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<offset:%zu>: \"%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<kParseCommentsFlag | kParseTrailingCommasFlag>(json);
return add(std::move(doc));
}
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) {
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;
}

View File

@@ -0,0 +1,76 @@
/* XMRig
* Copyright 2010 Jeff Garzik <jgarzik@pobox.com>
* Copyright 2012-2014 pooler <pooler@litecoinpool.org>
* Copyright 2014 Lucas Jones <https://github.com/lucasjones>
* Copyright 2014-2016 Wolf9466 <https://github.com/OhGodAPet>
* Copyright 2016 Jay D Dee <jayddee246@gmail.com>
* Copyright 2017-2018 XMR-Stak <https://github.com/fireice-uk>, <https://github.com/psychocrypt>
* Copyright 2018-2019 SChernykh <https://github.com/SChernykh>
* Copyright 2016-2019 XMRig <https://github.com/xmrig>, <support@xmrig.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef XMRIG_JSONCHAIN_H
#define XMRIG_JSONCHAIN_H
#include <vector>
#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);
void dump(const char *fileName);
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<rapidjson::Document> m_chain;
String m_fileName;
};
} /* namespace xmrig */
#endif /* XMRIG_JSONCHAIN_H */

View File

@@ -0,0 +1,38 @@
/* XMRig
* Copyright 2010 Jeff Garzik <jgarzik@pobox.com>
* Copyright 2012-2014 pooler <pooler@litecoinpool.org>
* Copyright 2014 Lucas Jones <https://github.com/lucasjones>
* Copyright 2014-2016 Wolf9466 <https://github.com/OhGodAPet>
* Copyright 2016 Jay D Dee <jayddee246@gmail.com>
* Copyright 2017-2018 XMR-Stak <https://github.com/fireice-uk>, <https://github.com/psychocrypt>
* Copyright 2018-2019 SChernykh <https://github.com/SChernykh>
* Copyright 2016-2019 XMRig <https://github.com/xmrig>, <support@xmrig.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "base/io/json/JsonRequest.h"
#include "rapidjson/document.h"
void xmrig::JsonRequest::create(rapidjson::Document &doc, int64_t id, const char *method, rapidjson::Value &params)
{
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);
}

View File

@@ -5,8 +5,8 @@
* Copyright 2014-2016 Wolf9466 <https://github.com/OhGodAPet>
* Copyright 2016 Jay D Dee <jayddee246@gmail.com>
* Copyright 2017-2018 XMR-Stak <https://github.com/fireice-uk>, <https://github.com/psychocrypt>
* Copyright 2016-2018 XMRig <https://github.com/xmrig>, <support@xmrig.com>
*
* Copyright 2018-2019 SChernykh <https://github.com/SChernykh>
* Copyright 2016-2019 XMRig <https://github.com/xmrig>, <support@xmrig.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -22,32 +22,24 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef __HTTPREPLY_H__
#define __HTTPREPLY_H__
#ifndef XMRIG_JSONREQUEST_H
#define XMRIG_JSONREQUEST_H
#include <stdint.h>
#include "rapidjson/fwd.h"
namespace xmrig {
class HttpReply
class JsonRequest
{
public:
HttpReply() :
buf(nullptr),
status(200),
size(0)
{}
char *buf;
int status;
size_t size;
static void create(rapidjson::Document &doc, int64_t id, const char *method, rapidjson::Value &params);
};
} /* namespace xmrig */
#endif /* __HTTPREPLY_H__ */
#endif /* XMRIG_JSONREQUEST_H */

View File

@@ -26,7 +26,7 @@
#include <fstream>
#include "base/io/Json.h"
#include "base/io/json/Json.h"
#include "rapidjson/document.h"
#include "rapidjson/istreamwrapper.h"
#include "rapidjson/ostreamwrapper.h"

View File

@@ -35,7 +35,7 @@
#include <fstream>
#include "base/io/Json.h"
#include "base/io/json/Json.h"
#include "rapidjson/document.h"
#include "rapidjson/istreamwrapper.h"
#include "rapidjson/ostreamwrapper.h"
@@ -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;
}

250
src/base/io/log/Log.cpp Normal file
View File

@@ -0,0 +1,250 @@
/* XMRig
* Copyright 2010 Jeff Garzik <jgarzik@pobox.com>
* Copyright 2012-2014 pooler <pooler@litecoinpool.org>
* Copyright 2014 Lucas Jones <https://github.com/lucasjones>
* Copyright 2014-2016 Wolf9466 <https://github.com/OhGodAPet>
* Copyright 2016 Jay D Dee <jayddee246@gmail.com>
* Copyright 2017-2018 XMR-Stak <https://github.com/fireice-uk>, <https://github.com/psychocrypt>
* Copyright 2019 Spudz76 <https://github.com/Spudz76>
* Copyright 2018-2019 SChernykh <https://github.com/SChernykh>
* Copyright 2016-2019 XMRig <https://github.com/xmrig>, <support@xmrig.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifdef WIN32
# include <winsock2.h>
# include <windows.h>
#endif
#include <algorithm>
#include <string.h>
#include <string>
#include <time.h>
#include <uv.h>
#include <vector>
#include "base/io/log/Log.h"
#include "base/kernel/interfaces/ILogBackend.h"
#include "base/tools/Chrono.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);
const int rc = vsnprintf(m_buf + size, sizeof (m_buf) - offset - 32, fmt, args);
if (rc < 0) {
return unlock();
}
size += std::min(static_cast<size_t>(rc), sizeof (m_buf) - offset - 32);
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;
}
const uint64_t ms = Chrono::currentMSecsSinceEpoch();
time_t now = ms / 1000;
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" BLACK_BOLD(".%03d") "] ",
stime.tm_year + 1900,
stime.tm_mon + 1,
stime.tm_mday,
stime.tm_hour,
stime.tm_min,
stime.tm_sec,
static_cast<int>(ms % 1000)
);
if (rc > 0) {
size = offset = static_cast<size_t>(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<ILogBackend*> 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);
}

129
src/base/io/log/Log.h Normal file
View File

@@ -0,0 +1,129 @@
/* XMRig
* Copyright 2010 Jeff Garzik <jgarzik@pobox.com>
* Copyright 2012-2014 pooler <pooler@litecoinpool.org>
* Copyright 2014 Lucas Jones <https://github.com/lucasjones>
* Copyright 2014-2016 Wolf9466 <https://github.com/OhGodAPet>
* Copyright 2016 Jay D Dee <jayddee246@gmail.com>
* Copyright 2017-2018 XMR-Stak <https://github.com/fireice-uk>, <https://github.com/psychocrypt>
* Copyright 2019 Spudz76 <https://github.com/Spudz76>
* Copyright 2018-2019 SChernykh <https://github.com/SChernykh>
* Copyright 2016-2019 XMRig <https://github.com/xmrig>, <support@xmrig.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef 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 */

View File

@@ -5,6 +5,7 @@
* Copyright 2014-2016 Wolf9466 <https://github.com/OhGodAPet>
* Copyright 2016 Jay D Dee <jayddee246@gmail.com>
* Copyright 2017-2018 XMR-Stak <https://github.com/fireice-uk>, <https://github.com/psychocrypt>
* Copyright 2019 Spudz76 <https://github.com/Spudz76>
* Copyright 2018-2019 SChernykh <https://github.com/SChernykh>
* Copyright 2016-2019 XMRig <https://github.com/xmrig>, <support@xmrig.com>
*
@@ -23,21 +24,12 @@
*/
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#ifdef WIN32
# include <winsock2.h>
# include <windows.h>
#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<uv_stream_t*>(m_tty);
m_stream = reinterpret_cast<uv_stream_t*>(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<char *>(line), static_cast<unsigned int>(size));
# else
localtime_r(&now, &stime);
uv_buf_t buf = uv_buf_init(const_cast<char *>(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);
}
}

View File

@@ -5,6 +5,7 @@
* Copyright 2014-2016 Wolf9466 <https://github.com/OhGodAPet>
* Copyright 2016 Jay D Dee <jayddee246@gmail.com>
* Copyright 2017-2018 XMR-Stak <https://github.com/fireice-uk>, <https://github.com/psychocrypt>
* Copyright 2019 Spudz76 <https://github.com/Spudz76>
* Copyright 2018-2019 SChernykh <https://github.com/SChernykh>
* Copyright 2016-2019 XMRig <https://github.com/xmrig>, <support@xmrig.com>
*
@@ -26,10 +27,11 @@
#define XMRIG_CONSOLELOG_H
#include <uv.h>
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;
};

View File

@@ -5,6 +5,7 @@
* Copyright 2014-2016 Wolf9466 <https://github.com/OhGodAPet>
* Copyright 2016 Jay D Dee <jayddee246@gmail.com>
* Copyright 2017-2018 XMR-Stak <https://github.com/fireice-uk>, <https://github.com/psychocrypt>
* Copyright 2019 Spudz76 <https://github.com/Spudz76>
* Copyright 2018-2019 SChernykh <https://github.com/SChernykh>
* Copyright 2016-2019 XMRig <https://github.com/xmrig>, <support@xmrig.com>
*
@@ -23,15 +24,11 @@
*/
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <uv.h>
#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 +39,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<unsigned int>(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 +65,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);
}

View File

@@ -5,6 +5,7 @@
* Copyright 2014-2016 Wolf9466 <https://github.com/OhGodAPet>
* Copyright 2016 Jay D Dee <jayddee246@gmail.com>
* Copyright 2017-2018 XMR-Stak <https://github.com/fireice-uk>, <https://github.com/psychocrypt>
* Copyright 2019 Spudz76 <https://github.com/Spudz76>
* Copyright 2018-2019 SChernykh <https://github.com/SChernykh>
* Copyright 2016-2019 XMRig <https://github.com/xmrig>, <support@xmrig.com>
*
@@ -26,10 +27,10 @@
#define XMRIG_FILELOG_H
#include <uv.h>
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;
};

View File

@@ -5,6 +5,7 @@
* Copyright 2014-2016 Wolf9466 <https://github.com/OhGodAPet>
* Copyright 2016 Jay D Dee <jayddee246@gmail.com>
* Copyright 2017-2018 XMR-Stak <https://github.com/fireice-uk>, <https://github.com/psychocrypt>
* Copyright 2019 Spudz76 <https://github.com/Spudz76>
* Copyright 2018-2019 SChernykh <https://github.com/SChernykh>
* Copyright 2016-2019 XMRig <https://github.com/xmrig>, <support@xmrig.com>
*
@@ -26,7 +27,7 @@
#include <syslog.h>
#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<int>(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, "%s", line + offset);
}

View File

@@ -5,6 +5,7 @@
* Copyright 2014-2016 Wolf9466 <https://github.com/OhGodAPet>
* Copyright 2016 Jay D Dee <jayddee246@gmail.com>
* Copyright 2017-2018 XMR-Stak <https://github.com/fireice-uk>, <https://github.com/psychocrypt>
* Copyright 2019 Spudz76 <https://github.com/Spudz76>
* Copyright 2018-2019 SChernykh <https://github.com/SChernykh>
* Copyright 2016-2019 XMRig <https://github.com/xmrig>, <support@xmrig.com>
*
@@ -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;
};

290
src/base/kernel/Base.cpp Normal file
View File

@@ -0,0 +1,290 @@
/* XMRig
* Copyright 2010 Jeff Garzik <jgarzik@pobox.com>
* Copyright 2012-2014 pooler <pooler@litecoinpool.org>
* Copyright 2014 Lucas Jones <https://github.com/lucasjones>
* Copyright 2014-2016 Wolf9466 <https://github.com/OhGodAPet>
* Copyright 2016 Jay D Dee <jayddee246@gmail.com>
* Copyright 2017-2018 XMR-Stak <https://github.com/fireice-uk>, <https://github.com/psychocrypt>
* Copyright 2018-2019 SChernykh <https://github.com/SChernykh>
* Copyright 2016-2019 XMRig <https://github.com/xmrig>, <support@xmrig.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <assert.h>
#include <memory>
#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"
#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.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
#ifdef XMRIG_FEATURE_EMBEDDED_CONFIG
# include "core/config/Config_default.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)
{
config = std::unique_ptr<Config>(new Config());
return config->read(chain, chain.fileName());
}
inline Config *load()
{
JsonChain chain;
ConfigTransform transform;
std::unique_ptr<Config> 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<IBaseListener *> 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());
# ifndef XMRIG_PROXY_PROJECT
Platform::setProcessPriority(config()->priority());
# endif
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);
}

View File

@@ -22,42 +22,50 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef XMRIG_CONFIGWATCHER_H
#define XMRIG_CONFIGWATCHER_H
#ifndef XMRIG_BASE_H
#define XMRIG_BASE_H
#include "base/kernel/interfaces/IConfigListener.h"
#include "base/kernel/interfaces/IWatcherListener.h"
#include "base/tools/String.h"
#include "rapidjson/fwd.h"
struct option;
namespace xmrig {
class IConfigCreator;
class IConfigListener;
class Watcher;
class Api;
class Config;
class BasePrivate;
class IBaseListener;
class Process;
class ConfigWatcher : public IWatcherListener
class Base : public IWatcherListener
{
public:
ConfigWatcher(const String &path, IConfigCreator *creator, IConfigListener *listener);
~ConfigWatcher() override;
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:
IConfigCreator *m_creator;
IConfigListener *m_listener;
Watcher *m_watcher;
BasePrivate *d_ptr;
};
} /* namespace xmrig */
#endif /* __CONFIGWATCHER_H__ */
#endif /* XMRIG_BASE_H */

View File

@@ -27,19 +27,14 @@
#include <uv.h>
#ifndef XMRIG_NO_HTTPD
# include <microhttpd.h>
#endif
#ifndef XMRIG_NO_TLS
#ifdef XMRIG_FEATURE_TLS
# include <openssl/opensslv.h>
#endif
#include "base/kernel/Entry.h"
#include "base/kernel/Process.h"
#include "core/usage.h"
#include "core/config/usage.h"
#include "version.h"
@@ -73,11 +68,7 @@ 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_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<int>(strchr(v, ' ') - v), v);

View File

@@ -0,0 +1,196 @@
/* XMRig
* Copyright 2010 Jeff Garzik <jgarzik@pobox.com>
* Copyright 2012-2014 pooler <pooler@litecoinpool.org>
* Copyright 2014 Lucas Jones <https://github.com/lucasjones>
* Copyright 2014-2016 Wolf9466 <https://github.com/OhGodAPet>
* Copyright 2016 Jay D Dee <jayddee246@gmail.com>
* Copyright 2017-2018 XMR-Stak <https://github.com/fireice-uk>, <https://github.com/psychocrypt>
* Copyright 2018-2019 SChernykh <https://github.com/SChernykh>
* Copyright 2016-2019 XMRig <https://github.com/xmrig>, <support@xmrig.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <uv.h>
#ifdef XMRIG_FEATURE_TLS
# include <openssl/opensslv.h>
#endif
#ifdef XMRIG_AMD_PROJECT
# if defined(__APPLE__)
# include <OpenCL/cl.h>
# else
# include "3rdparty/CL/cl.h"
# endif
#endif
#ifdef XMRIG_NVIDIA_PROJECT
# include "nvidia/cryptonight.h"
#endif
#include "base/io/json/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<int>(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);
Log::colors = reader.getBool("colors", Log::colors);
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;
}

View File

@@ -22,89 +22,75 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#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 "base/tools/String.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 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 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 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;
bool isColors() const;
void printAPI();
void printPools();
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::Document &doc) override;
void setFileName(const char *fileName) override;
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;
int m_printTime;
Http m_http;
Pools m_pools;
State m_state;
String m_apiId;
String m_apiToken;
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 */

View File

@@ -0,0 +1,279 @@
/* XMRig
* Copyright 2010 Jeff Garzik <jgarzik@pobox.com>
* Copyright 2012-2014 pooler <pooler@litecoinpool.org>
* Copyright 2014 Lucas Jones <https://github.com/lucasjones>
* Copyright 2014-2016 Wolf9466 <https://github.com/OhGodAPet>
* Copyright 2016 Jay D Dee <jayddee246@gmail.com>
* Copyright 2017-2018 XMR-Stak <https://github.com/fireice-uk>, <https://github.com/psychocrypt>
* Copyright 2018-2019 SChernykh <https://github.com/SChernykh>
* Copyright 2016-2019 XMRig <https://github.com/xmrig>, <support@xmrig.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <stdio.h>
#ifdef _MSC_VER
# include "getopt/getopt.h"
#else
# include <getopt.h>
#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/json/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 */
{
const char *p = strrchr(arg, ':');
if (!p) {
return;
}
char *user = new char[p - arg + 1]();
strncpy(user, arg, static_cast<size_t>(p - arg));
add<const char *>(doc, kPools, "user", user);
add(doc, kPools, "pass", p + 1);
delete [] user;
}
break;
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 */
case IConfig::DaemonPollKey: /* --daemon-poll-interval */
# ifdef XMRIG_DEPRECATED
case IConfig::ApiPort: /* --api-port */
# endif
return transformUint64(doc, key, static_cast<uint64_t>(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 */
case IConfig::DaemonKey: /* --daemon */
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);
case IConfig::DaemonKey: /* --daemon */
return add(doc, kPools, "daemon", enable);
# ifndef XMRIG_PROXY_PROJECT
case IConfig::NicehashKey: /* --nicehash */
return add<bool>(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);
case IConfig::DaemonPollKey: /* --daemon-poll-interval */
return add(doc, kPools, "daemon-poll-interval", arg);
default:
break;
}
}

View File

@@ -0,0 +1,123 @@
/* XMRig
* Copyright 2010 Jeff Garzik <jgarzik@pobox.com>
* Copyright 2012-2014 pooler <pooler@litecoinpool.org>
* Copyright 2014 Lucas Jones <https://github.com/lucasjones>
* Copyright 2014-2016 Wolf9466 <https://github.com/OhGodAPet>
* Copyright 2016 Jay D Dee <jayddee246@gmail.com>
* Copyright 2017-2018 XMR-Stak <https://github.com/fireice-uk>, <https://github.com/psychocrypt>
* Copyright 2018-2019 SChernykh <https://github.com/SChernykh>
* Copyright 2016-2019 XMRig <https://github.com/xmrig>, <support@xmrig.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef 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<typename T>
inline void set(rapidjson::Document &doc, const char *key, T value) { set<T>(doc, doc, key, value); }
template<typename T>
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<T>(doc, doc[objKey], key, value);
}
template<typename T>
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<T>(doc, array[array.Size() - 1], key, value);
}
template<typename T>
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 */

View File

@@ -22,8 +22,8 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#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

View File

@@ -0,0 +1,85 @@
/* XMRig
* Copyright 2010 Jeff Garzik <jgarzik@pobox.com>
* Copyright 2012-2014 pooler <pooler@litecoinpool.org>
* Copyright 2014 Lucas Jones <https://github.com/lucasjones>
* Copyright 2014-2016 Wolf9466 <https://github.com/OhGodAPet>
* Copyright 2016 Jay D Dee <jayddee246@gmail.com>
* Copyright 2017-2018 XMR-Stak <https://github.com/fireice-uk>, <https://github.com/psychocrypt>
* Copyright 2018-2019 SChernykh <https://github.com/SChernykh>
* Copyright 2016-2019 XMRig <https://github.com/xmrig>, <support@xmrig.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef XMRIG_ICLIENT_H
#define XMRIG_ICLIENT_H
#include <stdint.h>
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 *mode() 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

View File

@@ -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 &params) = 0;
virtual void onLogin(Client *client, rapidjson::Document &doc, rapidjson::Value &params) = 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 &params) = 0;
virtual void onLogin(IClient *client, rapidjson::Document &doc, rapidjson::Value &params) = 0;
virtual void onLoginSuccess(IClient *client) = 0;
virtual void onResultAccepted(IClient *client, const SubmitResult &result, const char *error) = 0;
};

View File

@@ -0,0 +1,157 @@
/* XMRig
* Copyright 2010 Jeff Garzik <jgarzik@pobox.com>
* Copyright 2012-2014 pooler <pooler@litecoinpool.org>
* Copyright 2014 Lucas Jones <https://github.com/lucasjones>
* Copyright 2014-2016 Wolf9466 <https://github.com/OhGodAPet>
* Copyright 2016 Jay D Dee <jayddee246@gmail.com>
* Copyright 2017-2018 XMR-Stak <https://github.com/fireice-uk>, <https://github.com/psychocrypt>
* Copyright 2018-2019 SChernykh <https://github.com/SChernykh>
* Copyright 2016-2019 XMRig <https://github.com/xmrig>, <support@xmrig.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef XMRIG_ICONFIG_H
#define XMRIG_ICONFIG_H
#include "common/crypto/Algorithm.h"
#include "rapidjson/fwd.h"
namespace xmrig {
class IJsonReader;
class String;
class IConfig
{
public:
enum Keys {
// common
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,
TlsKey = 1013,
FingerprintKey = 1014,
ProxyDonateKey = 1017,
DaemonKey = 1018,
DaemonPollKey = 1019,
# ifdef XMRIG_DEPRECATED
ApiPort = 4000,
ApiAccessTokenKey = 4001,
ApiIPv6Key = 4003,
ApiRestrictedKey = 4004,
# endif
// xmrig common
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,
// xmrig amd
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',
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,
};
virtual ~IConfig() = default;
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;
};
} /* namespace xmrig */
#endif // XMRIG_ICONFIG_H

View File

@@ -0,0 +1,52 @@
/* XMRig
* Copyright 2010 Jeff Garzik <jgarzik@pobox.com>
* Copyright 2012-2014 pooler <pooler@litecoinpool.org>
* Copyright 2014 Lucas Jones <https://github.com/lucasjones>
* Copyright 2014-2016 Wolf9466 <https://github.com/OhGodAPet>
* Copyright 2016 Jay D Dee <jayddee246@gmail.com>
* Copyright 2017-2018 XMR-Stak <https://github.com/fireice-uk>, <https://github.com/psychocrypt>
* Copyright 2018-2019 SChernykh <https://github.com/SChernykh>
* Copyright 2016-2019 XMRig <https://github.com/xmrig>, <support@xmrig.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef XMRIG_ICONFIGTRANSFORM_H
#define XMRIG_ICONFIGTRANSFORM_H
#include "common/crypto/Algorithm.h"
#include "rapidjson/fwd.h"
namespace xmrig {
class IJsonReader;
class String;
class IConfigTransform
{
public:
virtual ~IConfigTransform() = default;
virtual void transform(rapidjson::Document &doc, int key, const char *arg) = 0;
};
} /* namespace xmrig */
#endif // XMRIG_ICONFIGTRANSFORM_H

View File

@@ -0,0 +1,48 @@
/* XMRig
* Copyright 2010 Jeff Garzik <jgarzik@pobox.com>
* Copyright 2012-2014 pooler <pooler@litecoinpool.org>
* Copyright 2014 Lucas Jones <https://github.com/lucasjones>
* Copyright 2014-2016 Wolf9466 <https://github.com/OhGodAPet>
* Copyright 2016 Jay D Dee <jayddee246@gmail.com>
* Copyright 2017-2018 XMR-Stak <https://github.com/fireice-uk>, <https://github.com/psychocrypt>
* Copyright 2018-2019 SChernykh <https://github.com/SChernykh>
* Copyright 2016-2019 XMRig <https://github.com/xmrig>, <support@xmrig.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef XMRIG_IHTTPLISTENER_H
#define XMRIG_IHTTPLISTENER_H
namespace xmrig {
class HttpData;
class HttpResponse;
class IHttpListener
{
public:
virtual ~IHttpListener() = default;
virtual void onHttpData(const HttpData &data) = 0;
};
} /* namespace xmrig */
#endif // XMRIG_IHTTPLISTENER_H

View File

@@ -22,51 +22,35 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef XMRIG_CONFIGLOADER_H
#define XMRIG_CONFIGLOADER_H
#include <stdint.h>
#ifndef XMRIG_IJSONREADER_H
#define XMRIG_IJSONREADER_H
#include "rapidjson/fwd.h"
struct option;
namespace xmrig {
class ConfigWatcher;
class IConfigCreator;
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::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 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 IConfigCreator *m_creator;
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

View File

@@ -5,6 +5,7 @@
* Copyright 2014-2016 Wolf9466 <https://github.com/OhGodAPet>
* Copyright 2016 Jay D Dee <jayddee246@gmail.com>
* Copyright 2017-2018 XMR-Stak <https://github.com/fireice-uk>, <https://github.com/psychocrypt>
* Copyright 2019 Spudz76 <https://github.com/Spudz76>
* Copyright 2018-2019 SChernykh <https://github.com/SChernykh>
* Copyright 2016-2019 XMRig <https://github.com/xmrig>, <support@xmrig.com>
*
@@ -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;
};

View File

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

View File

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

View File

@@ -22,36 +22,32 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef XMRIG_BASICLOG_H
#define XMRIG_BASICLOG_H
#ifndef XMRIG_ITCPSERVERLISTENER_H
#define XMRIG_ITCPSERVERLISTENER_H
#include <uv.h>
#include <stdint.h>
#include "common/interfaces/ILogBackend.h"
typedef struct uv_stream_s uv_stream_t;
namespace xmrig {
class BasicLog : public ILogBackend
class String;
class ITcpServerListener
{
public:
BasicLog();
virtual ~ITcpServerListener() = default;
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];
virtual void onConnection(uv_stream_t *stream, uint16_t port) = 0;
};
} /* namespace xmrig */
#endif /* XMRIG_BASICLOG_H */
#endif // XMRIG_ITCPSERVERLISTENER_H

View File

@@ -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;
}
@@ -143,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);
}

View File

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

View File

@@ -0,0 +1,99 @@
/* XMRig
* Copyright 2010 Jeff Garzik <jgarzik@pobox.com>
* Copyright 2012-2014 pooler <pooler@litecoinpool.org>
* Copyright 2014 Lucas Jones <https://github.com/lucasjones>
* Copyright 2014-2016 Wolf9466 <https://github.com/OhGodAPet>
* Copyright 2016 Jay D Dee <jayddee246@gmail.com>
* Copyright 2017-2018 XMR-Stak <https://github.com/fireice-uk>, <https://github.com/psychocrypt>
* Copyright 2018-2019 SChernykh <https://github.com/SChernykh>
* Copyright 2016-2019 XMRig <https://github.com/xmrig>, <support@xmrig.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "3rdparty/rapidjson/document.h"
#include "base/io/json/Json.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::setPort(int port)
{
if (port >= 0 && port <= 65536) {
m_port = static_cast<uint16_t>(port);
}
}

73
src/base/net/http/Http.h Normal file
View File

@@ -0,0 +1,73 @@
/* XMRig
* Copyright 2010 Jeff Garzik <jgarzik@pobox.com>
* Copyright 2012-2014 pooler <pooler@litecoinpool.org>
* Copyright 2014 Lucas Jones <https://github.com/lucasjones>
* Copyright 2014-2016 Wolf9466 <https://github.com/OhGodAPet>
* Copyright 2016 Jay D Dee <jayddee246@gmail.com>
* Copyright 2017-2018 XMR-Stak <https://github.com/fireice-uk>, <https://github.com/psychocrypt>
* Copyright 2018-2019 SChernykh <https://github.com/SChernykh>
* Copyright 2016-2019 XMRig <https://github.com/xmrig>, <support@xmrig.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef XMRIG_HTTP_H
#define XMRIG_HTTP_H
#include "base/tools/String.h"
namespace xmrig {
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; }
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 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

View File

@@ -0,0 +1,86 @@
/* XMRig
* Copyright 2010 Jeff Garzik <jgarzik@pobox.com>
* Copyright 2012-2014 pooler <pooler@litecoinpool.org>
* Copyright 2014 Lucas Jones <https://github.com/lucasjones>
* Copyright 2014-2016 Wolf9466 <https://github.com/OhGodAPet>
* Copyright 2016 Jay D Dee <jayddee246@gmail.com>
* Copyright 2017-2018 XMR-Stak <https://github.com/fireice-uk>, <https://github.com/psychocrypt>
* Copyright 2014-2019 heapwolf <https://github.com/heapwolf>
* Copyright 2018-2019 SChernykh <https://github.com/SChernykh>
* Copyright 2016-2019 XMRig <https://github.com/xmrig>, <support@xmrig.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "3rdparty/http-parser/http_parser.h"
#include "base/net/http/HttpApiResponse.h"
#include "rapidjson/prettywriter.h"
#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)
{
}
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) {
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<http_status>(statusCode()))), m_doc.GetAllocator());
}
}
if (!m_doc.MemberCount()) {
return HttpResponse::end();
}
setHeader("Content-Type", "application/json");
StringBuffer buffer(nullptr, 4096);
PrettyWriter<StringBuffer> writer(buffer);
writer.SetMaxDecimalPlaces(10);
m_doc.Accept(writer);
HttpResponse::end(buffer.GetString(), buffer.GetSize());
}

View File

@@ -0,0 +1,57 @@
/* XMRig
* Copyright 2010 Jeff Garzik <jgarzik@pobox.com>
* Copyright 2012-2014 pooler <pooler@litecoinpool.org>
* Copyright 2014 Lucas Jones <https://github.com/lucasjones>
* Copyright 2014-2016 Wolf9466 <https://github.com/OhGodAPet>
* Copyright 2016 Jay D Dee <jayddee246@gmail.com>
* Copyright 2017-2018 XMR-Stak <https://github.com/fireice-uk>, <https://github.com/psychocrypt>
* Copyright 2014-2019 heapwolf <https://github.com/heapwolf>
* Copyright 2018-2019 SChernykh <https://github.com/SChernykh>
* Copyright 2016-2019 XMRig <https://github.com/xmrig>, <support@xmrig.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef 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

View File

@@ -0,0 +1,224 @@
/* XMRig
* Copyright 2010 Jeff Garzik <jgarzik@pobox.com>
* Copyright 2012-2014 pooler <pooler@litecoinpool.org>
* Copyright 2014 Lucas Jones <https://github.com/lucasjones>
* Copyright 2014-2016 Wolf9466 <https://github.com/OhGodAPet>
* Copyright 2016 Jay D Dee <jayddee246@gmail.com>
* Copyright 2017-2018 XMR-Stak <https://github.com/fireice-uk>, <https://github.com/psychocrypt>
* Copyright 2014-2019 heapwolf <https://github.com/heapwolf>
* Copyright 2018-2019 SChernykh <https://github.com/SChernykh>
* Copyright 2016-2019 XMRig <https://github.com/xmrig>, <support@xmrig.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <sstream>
#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 ClientWriteBaton : public Baton<uv_write_t>
{
public:
inline ClientWriteBaton(const std::string &header, std::string &&body) :
m_body(std::move(body)),
m_header(header)
{
bufs[0].len = m_header.size();
bufs[0].base = const_cast<char *>(m_header.c_str());
if (!m_body.empty()) {
bufs[1].len = m_body.size();
bufs[1].base = const_cast<char *>(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<ClientWriteBaton *>(req->data); }
uv_buf_t bufs[2];
private:
std::string m_body;
std::string m_header;
};
} // namespace xmrig
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;
this->url = url;
if (data) {
body = size ? std::string(data, size) : data;
}
m_dns = new Dns(this);
}
xmrig::HttpClient::~HttpClient()
{
delete m_dns;
}
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;
if (status < 0 && dns.isEmpty()) {
if (!m_quiet) {
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::handshake()
{
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<http_method>(method)) << " " << url << " HTTP/1.1" << kCRLF;
for (auto &header : headers) {
ss << header.first << ": " << header.second << kCRLF;
}
ss << kCRLF;
headers.clear();
write(ss.str());
}
void xmrig::HttpClient::read(const char *data, size_t size)
{
if (parse(data, size) < size) {
close(UV_EPROTO);
}
}
void xmrig::HttpClient::write(const std::string &header)
{
ClientWriteBaton *baton = new ClientWriteBaton(header, std::move(body));
uv_write(&baton->req, stream(), baton->bufs, baton->count(), ClientWriteBaton::onWrite);
}
void xmrig::HttpClient::onConnect(uv_connect_t *req, int status)
{
HttpClient *client = static_cast<HttpClient *>(req->data);
if (!client) {
delete req;
return;
}
if (status < 0) {
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(status);
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<unsigned int>(suggested_size);
# else
buf->len = suggested_size;
# endif
},
[](uv_stream_t *tcp, ssize_t nread, const uv_buf_t *buf)
{
HttpClient *client = static_cast<HttpClient*>(tcp->data);
if (nread >= 0) {
client->read(buf->base, static_cast<size_t>(nread));
} else {
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<int>(nread)));
}
client->close(static_cast<int>(nread));
}
delete [] buf->base;
});
client->handshake();
}

View File

@@ -5,6 +5,7 @@
* Copyright 2014-2016 Wolf9466 <https://github.com/OhGodAPet>
* Copyright 2016 Jay D Dee <jayddee246@gmail.com>
* Copyright 2017-2018 XMR-Stak <https://github.com/fireice-uk>, <https://github.com/psychocrypt>
* Copyright 2014-2019 heapwolf <https://github.com/heapwolf>
* Copyright 2018-2019 SChernykh <https://github.com/SChernykh>
* Copyright 2016-2019 XMRig <https://github.com/xmrig>, <support@xmrig.com>
*
@@ -22,60 +23,52 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef XMRIG_HTTPD_H
#define XMRIG_HTTPD_H
#ifndef XMRIG_HTTPCLIENT_H
#define XMRIG_HTTPCLIENT_H
#include <stddef.h>
#include "base/kernel/interfaces/ITimerListener.h"
struct MHD_Connection;
struct MHD_Daemon;
struct MHD_Response;
#include "base/net/http/HttpContext.h"
#include "base/kernel/interfaces/IDnsListener.h"
namespace xmrig {
class HttpRequest;
class Timer;
class String;
class Httpd : public ITimerListener
class HttpClient : public HttpContext, public IDnsListener
{
public:
Httpd(int port, const char *accessToken, bool IPv6, bool restricted);
~Httpd() override;
HttpClient(int method, const String &url, IHttpListener *listener, const char *data = nullptr, size_t size = 0);
~HttpClient() override;
bool start();
void stop();
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;
protected:
void onTimer(const Timer *) override { run(); }
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);
bool m_quiet;
private:
constexpr static const int kIdleInterval = 200;
constexpr static const int kActiveInterval = 25;
static void onConnect(uv_connect_t *req, int status);
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;
Dns *m_dns;
uint16_t m_port;
};
} /* namespace xmrig */
} // namespace xmrig
#endif /* XMRIG_HTTPD_H */
#endif // XMRIG_HTTPCLIENT_H

View File

@@ -0,0 +1,228 @@
/* XMRig
* Copyright 2010 Jeff Garzik <jgarzik@pobox.com>
* Copyright 2012-2014 pooler <pooler@litecoinpool.org>
* Copyright 2014 Lucas Jones <https://github.com/lucasjones>
* Copyright 2014-2016 Wolf9466 <https://github.com/OhGodAPet>
* Copyright 2016 Jay D Dee <jayddee246@gmail.com>
* Copyright 2017-2018 XMR-Stak <https://github.com/fireice-uk>, <https://github.com/psychocrypt>
* Copyright 2014-2019 heapwolf <https://github.com/heapwolf>
* Copyright 2018-2019 SChernykh <https://github.com/SChernykh>
* Copyright 2016-2019 XMRig <https://github.com/xmrig>, <support@xmrig.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <algorithm>
#include <uv.h>
#include "3rdparty/http-parser/http_parser.h"
#include "base/kernel/interfaces/IHttpListener.h"
#include "base/net/http/HttpContext.h"
namespace xmrig {
static http_parser_settings http_settings;
static std::map<uint64_t, HttpContext *> storage;
static uint64_t SEQUENCE = 0;
} // namespace xmrig
xmrig::HttpContext::HttpContext(int parser_type, IHttpListener *listener) :
HttpData(SEQUENCE++),
m_wasHeaderValue(false),
m_listener(listener)
{
storage[id()] = this;
m_parser = new http_parser;
m_tcp = new uv_tcp_t;
uv_tcp_init(uv_default_loop(), m_tcp);
uv_tcp_nodelay(m_tcp, 1);
http_parser_init(m_parser, static_cast<http_parser_type>(parser_type));
m_parser->data = m_tcp->data = this;
if (http_settings.on_message_complete == nullptr) {
attach(&http_settings);
}
}
xmrig::HttpContext::~HttpContext()
{
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<sockaddr*>(&addr), &size);
if (reinterpret_cast<sockaddr_in *>(&addr)->sin_family == AF_INET6) {
uv_ip6_name(reinterpret_cast<sockaddr_in6*>(&addr), ip, 45);
}
else {
uv_ip4_name(reinterpret_cast<sockaddr_in*>(&addr), ip, 16);
}
return ip;
}
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);
}
if (!uv_is_closing(handle())) {
uv_close(handle(), [](uv_handle_t *handle) -> void { delete reinterpret_cast<HttpContext*>(handle->data); });
}
}
xmrig::HttpContext *xmrig::HttpContext::get(uint64_t id)
{
if (storage.count(id) == 0) {
return nullptr;
}
return storage[id];
}
void xmrig::HttpContext::closeAll()
{
for (auto kv : storage) {
if (!uv_is_closing(kv.second->handle())) {
uv_close(kv.second->handle(), [](uv_handle_t *handle) -> void { delete reinterpret_cast<HttpContext*>(handle->data); });
}
}
}
int xmrig::HttpContext::onHeaderField(http_parser *parser, const char *at, size_t length)
{
HttpContext *ctx = static_cast<HttpContext*>(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<HttpContext*>(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::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<HttpContext*>(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<HttpContext*>(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<HttpContext*>(parser->data)->body += std::string(at, len);
return 0;
};
settings->on_message_complete = [](http_parser *parser) -> int
{
HttpContext *ctx = static_cast<HttpContext*>(parser->data);
ctx->m_listener->onHttpData(*ctx);
ctx->m_listener = nullptr;
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();
}

View File

@@ -0,0 +1,86 @@
/* XMRig
* Copyright 2010 Jeff Garzik <jgarzik@pobox.com>
* Copyright 2012-2014 pooler <pooler@litecoinpool.org>
* Copyright 2014 Lucas Jones <https://github.com/lucasjones>
* Copyright 2014-2016 Wolf9466 <https://github.com/OhGodAPet>
* Copyright 2016 Jay D Dee <jayddee246@gmail.com>
* Copyright 2017-2018 XMR-Stak <https://github.com/fireice-uk>, <https://github.com/psychocrypt>
* Copyright 2014-2019 heapwolf <https://github.com/heapwolf>
* Copyright 2018-2019 SChernykh <https://github.com/SChernykh>
* Copyright 2016-2019 XMRig <https://github.com/xmrig>, <support@xmrig.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef 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/HttpData.h"
namespace xmrig {
class IHttpListener;
class HttpContext : public HttpData
{
public:
HttpContext(int parser_type, IHttpListener *listener);
virtual ~HttpContext();
inline uv_stream_t *stream() const { return reinterpret_cast<uv_stream_t *>(m_tcp); }
inline uv_handle_t *handle() const { return reinterpret_cast<uv_handle_t *>(m_tcp); }
size_t parse(const char *data, size_t size);
std::string ip() const;
void close(int status = 0);
static HttpContext *get(uint64_t id);
static void closeAll();
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;
};
} // namespace xmrig
#endif // XMRIG_HTTPCONTEXT_H

View File

@@ -0,0 +1,60 @@
/* XMRig
* Copyright 2010 Jeff Garzik <jgarzik@pobox.com>
* Copyright 2012-2014 pooler <pooler@litecoinpool.org>
* Copyright 2014 Lucas Jones <https://github.com/lucasjones>
* Copyright 2014-2016 Wolf9466 <https://github.com/OhGodAPet>
* Copyright 2016 Jay D Dee <jayddee246@gmail.com>
* Copyright 2017-2018 XMR-Stak <https://github.com/fireice-uk>, <https://github.com/psychocrypt>
* Copyright 2014-2019 heapwolf <https://github.com/heapwolf>
* Copyright 2018-2019 SChernykh <https://github.com/SChernykh>
* Copyright 2016-2019 XMRig <https://github.com/xmrig>, <support@xmrig.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef XMRIG_HTTPDATA_H
#define XMRIG_HTTPDATA_H
#include <map>
#include <string>
namespace xmrig {
class HttpData
{
public:
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<const std::string, const std::string> headers;
std::string body;
std::string url;
private:
const uint64_t m_id;
};
} // namespace xmrig
#endif // XMRIG_HTTPDATA_H

View File

@@ -0,0 +1,153 @@
/* XMRig
* Copyright 2010 Jeff Garzik <jgarzik@pobox.com>
* Copyright 2012-2014 pooler <pooler@litecoinpool.org>
* Copyright 2014 Lucas Jones <https://github.com/lucasjones>
* Copyright 2014-2016 Wolf9466 <https://github.com/OhGodAPet>
* Copyright 2016 Jay D Dee <jayddee246@gmail.com>
* Copyright 2017-2018 XMR-Stak <https://github.com/fireice-uk>, <https://github.com/psychocrypt>
* Copyright 2014-2019 heapwolf <https://github.com/heapwolf>
* Copyright 2018-2019 SChernykh <https://github.com/SChernykh>
* Copyright 2016-2019 XMRig <https://github.com/xmrig>, <support@xmrig.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <sstream>
#include <string.h>
#include <uv.h>
#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"
#include "base/tools/Baton.h"
namespace xmrig {
static const char *kCRLF = "\r\n";
static const char *kUserAgent = "user-agent";
class WriteBaton : public Baton<uv_write_t>
{
public:
inline WriteBaton(const std::stringstream &ss, const char *data, size_t size, HttpContext *ctx) :
m_ctx(ctx),
m_header(ss.str())
{
bufs[0].len = m_header.size();
bufs[0].base = const_cast<char *>(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<WriteBaton *>(req->data); }
uv_buf_t bufs[2];
private:
HttpContext *m_ctx;
std::string m_header;
};
} // namespace xmrig
xmrig::HttpResponse::HttpResponse(uint64_t id, int statusCode) :
m_id(id),
m_statusCode(statusCode)
{
}
bool xmrig::HttpResponse::isAlive() const
{
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<http_status>(statusCode())) << kCRLF;
for (auto &header : m_headers) {
ss << header.first << ": " << header.second << kCRLF;
}
ss << kCRLF;
HttpContext *ctx = HttpContext::get(m_id);
WriteBaton *baton = new WriteBaton(ss, data, size, ctx);
# ifndef APP_DEBUG
if (statusCode() >= 400)
# endif
{
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\""),
ctx->ip().c_str(),
http_method_str(static_cast<http_method>(ctx->method)),
ctx->url.c_str(),
err ? 31 : 32,
statusCode(),
baton->size(),
ctx->headers.count(kUserAgent) ? ctx->headers.at(kUserAgent).c_str() : nullptr
);
}
uv_write(&baton->req, ctx->stream(), baton->bufs, baton->count(), WriteBaton::onWrite);
}

View File

@@ -0,0 +1,61 @@
/* XMRig
* Copyright 2010 Jeff Garzik <jgarzik@pobox.com>
* Copyright 2012-2014 pooler <pooler@litecoinpool.org>
* Copyright 2014 Lucas Jones <https://github.com/lucasjones>
* Copyright 2014-2016 Wolf9466 <https://github.com/OhGodAPet>
* Copyright 2016 Jay D Dee <jayddee246@gmail.com>
* Copyright 2017-2018 XMR-Stak <https://github.com/fireice-uk>, <https://github.com/psychocrypt>
* Copyright 2014-2019 heapwolf <https://github.com/heapwolf>
* Copyright 2018-2019 SChernykh <https://github.com/SChernykh>
* Copyright 2016-2019 XMRig <https://github.com/xmrig>, <support@xmrig.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef XMRIG_HTTPRESPONSE_H
#define XMRIG_HTTPRESPONSE_H
#include <map>
#include <string>
namespace xmrig {
class HttpResponse
{
public:
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 }); }
inline void setStatus(int code) { m_statusCode = code; }
bool isAlive() const;
void end(const char *data = nullptr, size_t size = 0);
private:
const uint64_t m_id;
int m_statusCode;
std::map<const std::string, const std::string> m_headers;
};
} // namespace xmrig
#endif // XMRIG_HTTPRESPONSE_H

View File

@@ -0,0 +1,83 @@
/* XMRig
* Copyright 2010 Jeff Garzik <jgarzik@pobox.com>
* Copyright 2012-2014 pooler <pooler@litecoinpool.org>
* Copyright 2014 Lucas Jones <https://github.com/lucasjones>
* Copyright 2014-2016 Wolf9466 <https://github.com/OhGodAPet>
* Copyright 2016 Jay D Dee <jayddee246@gmail.com>
* Copyright 2017-2018 XMR-Stak <https://github.com/fireice-uk>, <https://github.com/psychocrypt>
* Copyright 2014-2019 heapwolf <https://github.com/heapwolf>
* Copyright 2018-2019 SChernykh <https://github.com/SChernykh>
* Copyright 2016-2019 XMRig <https://github.com/xmrig>, <support@xmrig.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <functional>
#include <uv.h>
#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)
{
}
xmrig::HttpServer::~HttpServer()
{
HttpContext::closeAll();
}
void xmrig::HttpServer::onConnection(uv_stream_t *stream, uint16_t)
{
HttpContext *ctx = new HttpContext(HTTP_REQUEST, m_listener);
uv_accept(stream, ctx->stream());
uv_read_start(ctx->stream(),
[](uv_handle_t *, size_t suggested_size, uv_buf_t *buf)
{
buf->base = new char[suggested_size];
# ifdef _WIN32
buf->len = static_cast<unsigned int>(suggested_size);
# else
buf->len = suggested_size;
# endif
},
[](uv_stream_t *tcp, ssize_t nread, const uv_buf_t *buf)
{
HttpContext *ctx = static_cast<HttpContext*>(tcp->data);
if (nread >= 0) {
const size_t size = static_cast<size_t>(nread);
const size_t parsed = ctx->parse(buf->base, size);
if (parsed < size) {
ctx->close();
}
} else {
ctx->close();
}
delete [] buf->base;
});
}

View File

@@ -0,0 +1,62 @@
/* XMRig
* Copyright 2010 Jeff Garzik <jgarzik@pobox.com>
* Copyright 2012-2014 pooler <pooler@litecoinpool.org>
* Copyright 2014 Lucas Jones <https://github.com/lucasjones>
* Copyright 2014-2016 Wolf9466 <https://github.com/OhGodAPet>
* Copyright 2016 Jay D Dee <jayddee246@gmail.com>
* Copyright 2017-2018 XMR-Stak <https://github.com/fireice-uk>, <https://github.com/psychocrypt>
* Copyright 2014-2019 heapwolf <https://github.com/heapwolf>
* Copyright 2018-2019 SChernykh <https://github.com/SChernykh>
* Copyright 2016-2019 XMRig <https://github.com/xmrig>, <support@xmrig.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef 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:
IHttpListener *m_listener;
};
} // namespace xmrig
#endif // XMRIG_HTTPSERVER_H

View File

@@ -0,0 +1,208 @@
/* XMRig
* Copyright 2010 Jeff Garzik <jgarzik@pobox.com>
* Copyright 2012-2014 pooler <pooler@litecoinpool.org>
* Copyright 2014 Lucas Jones <https://github.com/lucasjones>
* Copyright 2014-2016 Wolf9466 <https://github.com/OhGodAPet>
* Copyright 2016 Jay D Dee <jayddee246@gmail.com>
* Copyright 2017-2018 XMR-Stak <https://github.com/fireice-uk>, <https://github.com/psychocrypt>
* Copyright 2014-2019 heapwolf <https://github.com/heapwolf>
* Copyright 2018-2019 SChernykh <https://github.com/SChernykh>
* Copyright 2016-2019 XMRig <https://github.com/xmrig>, <support@xmrig.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <assert.h>
#include <openssl/ssl.h>
#include <uv.h>
#include "base/io/log/Log.h"
#include "base/net/http/HttpsClient.h"
#include "base/tools/Buffer.h"
#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_fp(fingerprint)
{
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);
}
}
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);
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(UV_EPROTO);
}
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<size_t>(bytes_read));
}
}
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)
{
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;
}
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) == static_cast<int>(buf.len);
if (!result) {
close(UV_EIO);
}
}
(void) BIO_reset(m_writeBio);
}

View File

@@ -0,0 +1,77 @@
/* XMRig
* Copyright 2010 Jeff Garzik <jgarzik@pobox.com>
* Copyright 2012-2014 pooler <pooler@litecoinpool.org>
* Copyright 2014 Lucas Jones <https://github.com/lucasjones>
* Copyright 2014-2016 Wolf9466 <https://github.com/OhGodAPet>
* Copyright 2016 Jay D Dee <jayddee246@gmail.com>
* Copyright 2017-2018 XMR-Stak <https://github.com/fireice-uk>, <https://github.com/psychocrypt>
* Copyright 2014-2019 heapwolf <https://github.com/heapwolf>
* Copyright 2018-2019 SChernykh <https://github.com/SChernykh>
* Copyright 2016-2019 XMRig <https://github.com/xmrig>, <support@xmrig.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef 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"
#include "base/tools/String.h"
namespace xmrig {
class HttpsClient : public HttpClient
{
public:
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);
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;
};
} // namespace xmrig
#endif // XMRIG_HTTPSCLIENT_H

View File

@@ -0,0 +1,62 @@
/* XMRig
* Copyright 2010 Jeff Garzik <jgarzik@pobox.com>
* Copyright 2012-2014 pooler <pooler@litecoinpool.org>
* Copyright 2014 Lucas Jones <https://github.com/lucasjones>
* Copyright 2014-2016 Wolf9466 <https://github.com/OhGodAPet>
* Copyright 2016 Jay D Dee <jayddee246@gmail.com>
* Copyright 2017-2018 XMR-Stak <https://github.com/fireice-uk>, <https://github.com/psychocrypt>
* Copyright 2018-2019 SChernykh <https://github.com/SChernykh>
* Copyright 2016-2019 XMRig <https://github.com/xmrig>, <support@xmrig.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "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) :
m_quiet(false),
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;
}

View File

@@ -0,0 +1,96 @@
/* XMRig
* Copyright 2010 Jeff Garzik <jgarzik@pobox.com>
* Copyright 2012-2014 pooler <pooler@litecoinpool.org>
* Copyright 2014 Lucas Jones <https://github.com/lucasjones>
* Copyright 2014-2016 Wolf9466 <https://github.com/OhGodAPet>
* Copyright 2016 Jay D Dee <jayddee246@gmail.com>
* Copyright 2017-2018 XMR-Stak <https://github.com/fireice-uk>, <https://github.com/psychocrypt>
* Copyright 2018-2019 SChernykh <https://github.com/SChernykh>
* Copyright 2016-2019 XMRig <https://github.com/xmrig>, <support@xmrig.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef XMRIG_BASECLIENT_H
#define XMRIG_BASECLIENT_H
#include <map>
#include "base/kernel/interfaces/IClient.h"
#include "base/net/stratum/Job.h"
#include "base/net/stratum/Pool.h"
namespace xmrig {
class IClientListener;
class SubmitResult;
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:
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<int64_t, SubmitResult> m_results;
String m_ip;
uint64_t m_retryPause;
static int64_t m_sequence;
private:
bool m_enabled;
};
} /* namespace xmrig */
#endif /* XMRIG_BASECLIENT_H */

View File

@@ -30,19 +30,20 @@
#include <utility>
#ifndef XMRIG_NO_TLS
#ifdef XMRIG_FEATURE_TLS
# include <openssl/ssl.h>
# include <openssl/err.h>
# include "base/net/stratum/Tls.h"
#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"
#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"
@@ -57,7 +58,6 @@
namespace xmrig {
int64_t Client::m_sequence = 1;
Storage<Client> Client::m_storage;
} /* namespace xmrig */
@@ -75,16 +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),
m_expire(0),
m_jobs(0),
@@ -105,73 +97,6 @@ xmrig::Client::~Client()
}
void xmrig::Client::connect()
{
# ifndef XMRIG_NO_TLS
if (m_pool.isTLS()) {
m_tls = new Tls(this);
}
# endif
resolve(m_pool.host());
}
/**
* @brief Connect to server.
*
* @param url
*/
void xmrig::Client::connect(const Pool &url)
{
setPool(url);
connect();
}
void xmrig::Client::deleteLater()
{
if (!m_listener) {
return;
}
m_listener = nullptr;
if (!disconnect()) {
m_storage.remove(m_key);
}
}
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) {
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;
@@ -184,7 +109,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 +119,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 +131,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();
}
@@ -243,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);
@@ -257,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);
@@ -269,6 +190,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);
@@ -284,14 +256,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();
@@ -435,7 +399,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);
@@ -541,9 +505,9 @@ 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<int>(size) - 1, m_sendBuf);
# ifndef XMRIG_NO_TLS
# ifdef XMRIG_FEATURE_TLS
if (isTLS()) {
if (!m_tls->send(m_sendBuf, size)) {
return -1;
@@ -574,8 +538,6 @@ void xmrig::Client::connect(sockaddr *addr)
{
setState(ConnectingState);
reinterpret_cast<sockaddr_in*>(addr)->sin_port = htons(m_pool.port());
uv_connect_t *req = new uv_connect_t;
req->data = m_storage.ptr(m_key);
@@ -589,7 +551,7 @@ void xmrig::Client::connect(sockaddr *addr)
uv_tcp_keepalive(m_socket, 1, 60);
# endif
uv_tcp_connect(req, m_socket, reinterpret_cast<const sockaddr*>(addr), Client::onConnect);
uv_tcp_connect(req, m_socket, addr, onConnect);
delete addr;
}
@@ -597,7 +559,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;
@@ -619,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);
@@ -647,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);
}
@@ -661,7 +619,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;
@@ -676,7 +634,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<int>(len), line);
if (len < 32 || line[0] != '{') {
if (!isQuiet()) {
@@ -781,14 +739,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)) {
@@ -819,12 +771,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);
}
@@ -858,7 +805,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<int>(nread));
@@ -970,7 +917,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();

View File

@@ -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"
@@ -42,7 +43,6 @@
#include "common/crypto/Algorithm.h"
typedef struct bio_st BIO;
@@ -53,29 +53,12 @@ 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;
# ifndef XMRIG_NO_TLS
# ifdef XMRIG_FEATURE_TLS
constexpr static int kInputBufferSize = 1024 * 16;
# else
constexpr static int kInputBufferSize = 1024 * 2;
@@ -84,39 +67,23 @@ 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);
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<Extension ext> inline bool has() const noexcept { return m_extensions.test(ext); }
protected:
inline void onLine(char *line, size_t size) override { parse(line, size); }
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;
void onResolved(const Dns &dns, int status) override;
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;
@@ -143,9 +110,10 @@ 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); }
template<Extension ext> 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 +122,11 @@ 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<kInputBufferSize> m_recvBuf;
SocketState m_state;
std::bitset<EXT_MAX> m_extensions;
std::map<int64_t, SubmitResult> m_results;
String m_ip;
String m_rpcId;
Tls *m_tls;
uint64_t m_expire;
@@ -181,7 +136,6 @@ private:
uv_stream_t *m_stream;
uv_tcp_t *m_socket;
static int64_t m_sequence;
static Storage<Client> m_storage;
};

View File

@@ -0,0 +1,378 @@
/* XMRig
* Copyright 2010 Jeff Garzik <jgarzik@pobox.com>
* Copyright 2012-2014 pooler <pooler@litecoinpool.org>
* Copyright 2014 Lucas Jones <https://github.com/lucasjones>
* Copyright 2014-2016 Wolf9466 <https://github.com/OhGodAPet>
* Copyright 2016 Jay D Dee <jayddee246@gmail.com>
* Copyright 2017-2018 XMR-Stak <https://github.com/fireice-uk>, <https://github.com/psychocrypt>
* Copyright 2018-2019 SChernykh <https://github.com/SChernykh>
* Copyright 2019 Howard Chu <https://github.com/hyc>
* Copyright 2016-2019 XMRig <https://github.com/xmrig>, <support@xmrig.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <algorithm>
#include <assert.h>
#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"
#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
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),
m_monero(true)
{
m_timer = new Timer(this);
}
xmrig::DaemonClient::~DaemonClient()
{
delete m_timer;
}
bool xmrig::DaemonClient::disconnect()
{
if (m_state != UnconnectedState) {
setState(UnconnectedState);
}
return true;
}
bool xmrig::DaemonClient::isTLS() const
{
# ifdef XMRIG_FEATURE_TLS
return m_pool.isTLS();
# else
return false;
# endif
}
int64_t xmrig::DaemonClient::submit(const JobResult &result)
{
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<const uint8_t *>(&result.nonce), 4, m_blocktemplate.data() + 78);
# endif
using namespace rapidjson;
Document doc(kObjectType);
Value params(kArrayType);
params.PushBack(m_blocktemplate.toJSON(), doc.GetAllocator());
JsonRequest::create(doc, m_sequence, "submitblock", params);
# 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, kJsonRPC, 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<int>(data.body.size()), static_cast<int>(data.body.size()), data.body.c_str());
m_ip = static_cast<const HttpContext &>(data).ip().c_str();
# ifdef XMRIG_FEATURE_TLS
if (isTLS()) {
m_tlsVersion = static_cast<const HttpsClient &>(data).version();
m_tlsFingerprint = static_cast<const HttpsClient &>(data).fingerprint();
}
# endif
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) {
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();
}
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, 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 &params, int *code)
{
Job job(m_id, false, m_pool.algorithm(), String());
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, 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);
}
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(kBlocktemplateBlob) && 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();
Value params(kObjectType);
params.AddMember("wallet_address", m_pool.user().toJSON(), allocator);
params.AddMember("reserve_size", 8, allocator);
JsonRequest::create(doc, m_sequence, "getblocktemplate", params);
send(HTTP_POST, kJsonRPC, doc);
return m_sequence++;
}
void xmrig::DaemonClient::retry()
{
m_failures++;
m_listener->onClose(this, static_cast<int>(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<http_method>(method)),
url,
size,
static_cast<int>(size),
data);
HttpClient *client;
# ifdef XMRIG_FEATURE_TLS
if (m_pool.isTLS()) {
client = new HttpsClient(method, url, this, data, size, m_pool.fingerprint());
}
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<StringBuffer> 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<uint64_t>(20, m_pool.pollInterval());
m_timer->start(interval, interval);
}
break;
case UnconnectedState:
m_failures = -1;
m_timer->stop();
break;
default:
break;
}
}

View File

@@ -0,0 +1,83 @@
/* XMRig
* Copyright 2010 Jeff Garzik <jgarzik@pobox.com>
* Copyright 2012-2014 pooler <pooler@litecoinpool.org>
* Copyright 2014 Lucas Jones <https://github.com/lucasjones>
* Copyright 2014-2016 Wolf9466 <https://github.com/OhGodAPet>
* Copyright 2016 Jay D Dee <jayddee246@gmail.com>
* Copyright 2017-2018 XMR-Stak <https://github.com/fireice-uk>, <https://github.com/psychocrypt>
* Copyright 2018-2019 SChernykh <https://github.com/SChernykh>
* Copyright 2019 Howard Chu <https://github.com/hyc>
* Copyright 2016-2019 XMRig <https://github.com/xmrig>, <support@xmrig.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef 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;
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 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 {}
private:
bool isOutdated(uint64_t height, const char *hash) const;
bool parseJob(const rapidjson::Value &params, 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);
bool m_monero;
String m_blocktemplate;
String m_prevHash;
String m_tlsFingerprint;
String m_tlsVersion;
Timer *m_timer;
};
} /* namespace xmrig */
#endif /* XMRIG_DAEMONCLIENT_H */

View File

@@ -7,6 +7,7 @@
* Copyright 2017-2018 XMR-Stak <https://github.com/fireice-uk>, <https://github.com/psychocrypt>
* Copyright 2018 Lee Clagett <https://github.com/vtnerd>
* Copyright 2018 SChernykh <https://github.com/SChernykh>
* Copyright 2019 Howard Chu <https://github.com/hyc>
* Copyright 2016-2019 XMRig <https://github.com/xmrig>, <support@xmrig.com>
*
* This program is free software: you can redistribute it and/or modify
@@ -180,9 +181,15 @@ 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);
# ifdef XMRIG_PROXY_PROJECT
Buffer::toHex(reinterpret_cast<uint8_t *>(&m_target), 8, m_rawTarget);
m_rawTarget[16] = '\0';
# endif
}

View File

@@ -7,6 +7,7 @@
* Copyright 2017-2018 XMR-Stak <https://github.com/fireice-uk>, <https://github.com/psychocrypt>
* Copyright 2018 Lee Clagett <https://github.com/vtnerd>
* Copyright 2018-2019 SChernykh <https://github.com/SChernykh>
* Copyright 2019 Howard Chu <https://github.com/hyc>
* Copyright 2016-2019 XMRig <https://github.com/xmrig>, <support@xmrig.com>
*
* 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; }
@@ -67,12 +68,13 @@ public:
inline int threadId() const { return m_threadId; }
inline size_t size() const { return m_size; }
inline uint32_t *nonce() { return reinterpret_cast<uint32_t*>(m_blob + 39); }
inline uint32_t diff() const { return static_cast<uint32_t>(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); }
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); }

View File

@@ -6,6 +6,7 @@
* Copyright 2016 Jay D Dee <jayddee246@gmail.com>
* Copyright 2017-2019 XMR-Stak <https://github.com/fireice-uk>, <https://github.com/psychocrypt>
* Copyright 2018-2019 SChernykh <https://github.com/SChernykh>
* Copyright 2019 Howard Chu <https://github.com/hyc>
* Copyright 2016-2019 XMRig <https://github.com/xmrig>, <support@xmrig.com>
*
* This program is free software: you can redistribute it and/or modify
@@ -29,47 +30,55 @@
#include <stdio.h>
#include "base/io/Json.h"
#include "base/io/json/Json.h"
#include "base/net/stratum/Pool.h"
#include "rapidjson/document.h"
#ifdef APP_DEBUG
# include "common/log/Log.h"
# include "base/io/log/Log.h"
#endif
#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
}
xmrig::Pool::Pool() :
m_enabled(true),
m_nicehash(false),
m_tls(false),
m_keepAlive(0),
m_port(kDefaultPort)
m_flags(0),
m_port(kDefaultPort),
m_pollInterval(kDefaultPollInterval)
{
}
@@ -86,33 +95,37 @@ xmrig::Pool::Pool() :
* @param url
*/
xmrig::Pool::Pool(const char *url) :
m_enabled(true),
m_nicehash(false),
m_tls(false),
m_keepAlive(0),
m_port(kDefaultPort)
m_flags(1),
m_port(kDefaultPort),
m_pollInterval(kDefaultPollInterval)
{
parse(url);
}
xmrig::Pool::Pool(const rapidjson::Value &object) :
m_enabled(true),
m_nicehash(false),
m_tls(false),
m_keepAlive(0),
m_port(kDefaultPort)
m_flags(1),
m_port(kDefaultPort),
m_pollInterval(kDefaultPollInterval)
{
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);
m_pollInterval = Json::getUint64(object, kDaemonPollInterval, kDefaultPollInterval);
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)));
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()) {
setKeepAlive(keepalive.GetInt());
}
@@ -120,7 +133,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,21 +141,17 @@ 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),
m_port(port)
m_port(port),
m_pollInterval(kDefaultPollInterval)
{
const size_t size = m_host.size() + 8;
assert(size > 8);
@@ -151,6 +160,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);
}
@@ -178,30 +190,35 @@ 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;
}
# endif
return m_enabled && isValid() && algorithm().isValid();
# 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_nicehash == other.m_nicehash
&& m_enabled == other.m_enabled
&& m_tls == other.m_tls
&& 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);
}
@@ -209,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_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_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 == '/') {
@@ -252,23 +281,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<size_t>(p - userpass));
m_user = user;
m_password = p + 1;
return true;
}
rapidjson::Value xmrig::Pool::toJSON(rapidjson::Document &doc) const
{
using namespace rapidjson;
@@ -309,9 +321,11 @@ rapidjson::Value xmrig::Pool::toJSON(rapidjson::Document &doc) const
break;
}
obj.AddMember(StringRef(kEnabled), m_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;
}
@@ -350,7 +364,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<int>(m_nicehash));
LOG_DEBUG ("nicehash: %d", static_cast<int>(m_flags.test(FLAG_NICEHASH)));
LOG_DEBUG ("keepAlive: %d", m_keepAlive);
}
#endif
@@ -396,8 +410,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 +446,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;
}

View File

@@ -6,6 +6,7 @@
* Copyright 2016 Jay D Dee <jayddee246@gmail.com>
* Copyright 2017-2018 XMR-Stak <https://github.com/fireice-uk>, <https://github.com/psychocrypt>
* Copyright 2018-2019 SChernykh <https://github.com/SChernykh>
* Copyright 2019 Howard Chu <https://github.com/hyc>
* Copyright 2016-2019 XMRig <https://github.com/xmrig>, <support@xmrig.com>
*
* This program is free software: you can redistribute it and/or modify
@@ -26,6 +27,7 @@
#define XMRIG_POOL_H
#include <bitset>
#include <vector>
@@ -40,11 +42,20 @@ namespace xmrig {
class Pool
{
public:
enum Flags {
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);
@@ -59,8 +70,9 @@ public:
);
inline Algorithm &algorithm() { return m_algorithm; }
inline bool isNicehash() const { return m_nicehash; }
inline bool isTLS() const { return m_tls; }
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; }
inline const Algorithm &algorithm() const { return m_algorithm; }
inline const Algorithms &algorithms() const { return m_algorithms; }
@@ -72,23 +84,18 @@ 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 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); }
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;
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);
@@ -98,6 +105,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 +115,8 @@ private:
Algorithm m_algorithm;
Algorithms m_algorithms;
bool m_enabled;
bool m_nicehash;
bool m_tls;
int m_keepAlive;
std::bitset<FLAG_MAX> m_flags;
String m_fingerprint;
String m_host;
String m_password;
@@ -116,6 +124,7 @@ private:
String m_url;
String m_user;
uint16_t m_port;
uint64_t m_pollInterval;
};

View File

@@ -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"
@@ -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;
@@ -161,25 +136,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::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()
);
}
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(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++;
}

View File

@@ -50,28 +50,16 @@ public:
Pools();
inline bool setUserpass(const char *userpass) { return current().setUserpass(userpass); }
inline const std::vector<Pool> &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 &current();
int m_donateLevel;
int m_retries;
int m_retryPause;

View File

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

View File

@@ -27,10 +27,10 @@
#include <assert.h>
#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

View File

@@ -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<Pool> &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<int>(m_pools.size()), Platform::userAgent(), this);
const int id = static_cast<int>(m_pools.size());
# ifdef XMRIG_FEATURE_HTTP
IClient *client = !pool.isDaemon() ? static_cast<IClient *>(new Client(id, Platform::userAgent(), this))
: static_cast<IClient *>(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,13 +136,13 @@ void xmrig::FailoverStrategy::stop()
void xmrig::FailoverStrategy::tick(uint64_t now)
{
for (Client *client : m_pools) {
for (IClient *client : m_pools) {
client->tick(now);
}
}
void xmrig::FailoverStrategy::onClose(Client *client, int failures)
void xmrig::FailoverStrategy::onClose(IClient *client, int failures)
{
if (failures == -1) {
return;
@@ -150,7 +163,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 +171,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 +192,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);
}

View File

@@ -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 IClient *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,13 +62,13 @@ 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 &params) 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 &params) 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<size_t>(m_active)]; }
inline IClient *active() const { return m_pools[static_cast<size_t>(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<Client*> m_pools;
std::vector<IClient*> m_pools;
};

Some files were not shown because too many files have changed in this diff Show More