mirror of
https://github.com/xmrig/xmrig.git
synced 2024-11-05 16:07:42 +00:00
Merge branch 'feature-httpd' into evo
This commit is contained in:
commit
96f5bd32b5
79 changed files with 5918 additions and 1488 deletions
|
@ -21,7 +21,8 @@ include (src/base/base.cmake)
|
||||||
|
|
||||||
set(HEADERS
|
set(HEADERS
|
||||||
"${HEADERS_BASE}"
|
"${HEADERS_BASE}"
|
||||||
src/api/NetworkState.h
|
"${HEADERS_BASE_HTTP}"
|
||||||
|
src/api/interfaces/IApiListener.h
|
||||||
src/App.h
|
src/App.h
|
||||||
src/common/config/CommonConfig.h
|
src/common/config/CommonConfig.h
|
||||||
src/common/config/ConfigLoader.h
|
src/common/config/ConfigLoader.h
|
||||||
|
@ -30,14 +31,14 @@ set(HEADERS
|
||||||
src/common/crypto/Algorithm.h
|
src/common/crypto/Algorithm.h
|
||||||
src/common/crypto/keccak.h
|
src/common/crypto/keccak.h
|
||||||
src/common/interfaces/IConfig.h
|
src/common/interfaces/IConfig.h
|
||||||
src/common/interfaces/IConfigCreator.h
|
|
||||||
src/common/interfaces/IControllerListener.h
|
|
||||||
src/common/interfaces/ICpuInfo.h
|
src/common/interfaces/ICpuInfo.h
|
||||||
src/common/Platform.h
|
src/common/Platform.h
|
||||||
src/common/utils/mm_malloc.h
|
src/common/utils/mm_malloc.h
|
||||||
src/common/xmrig.h
|
src/common/xmrig.h
|
||||||
src/core/ConfigLoader_default.h
|
src/core/config/Config.h
|
||||||
src/core/ConfigLoader_platform.h
|
src/core/config/ConfigLoader_default.h
|
||||||
|
src/core/config/ConfigLoader_platform.h
|
||||||
|
src/core/config/usage.h
|
||||||
src/core/Controller.h
|
src/core/Controller.h
|
||||||
src/interfaces/IJobResultListener.h
|
src/interfaces/IJobResultListener.h
|
||||||
src/interfaces/IThread.h
|
src/interfaces/IThread.h
|
||||||
|
@ -45,13 +46,14 @@ set(HEADERS
|
||||||
src/Mem.h
|
src/Mem.h
|
||||||
src/net/JobResult.h
|
src/net/JobResult.h
|
||||||
src/net/Network.h
|
src/net/Network.h
|
||||||
|
src/net/NetworkState.h
|
||||||
src/net/strategies/DonateStrategy.h
|
src/net/strategies/DonateStrategy.h
|
||||||
src/Summary.h
|
src/Summary.h
|
||||||
src/version.h
|
src/version.h
|
||||||
src/workers/CpuThread.h
|
src/workers/CpuThread.h
|
||||||
src/workers/ThreadHandle.h
|
|
||||||
src/workers/Hashrate.h
|
src/workers/Hashrate.h
|
||||||
src/workers/MultiWorker.h
|
src/workers/MultiWorker.h
|
||||||
|
src/workers/ThreadHandle.h
|
||||||
src/workers/Worker.h
|
src/workers/Worker.h
|
||||||
src/workers/Workers.h
|
src/workers/Workers.h
|
||||||
)
|
)
|
||||||
|
@ -80,7 +82,7 @@ endif()
|
||||||
|
|
||||||
set(SOURCES
|
set(SOURCES
|
||||||
"${SOURCES_BASE}"
|
"${SOURCES_BASE}"
|
||||||
src/api/NetworkState.cpp
|
"${SOURCES_BASE_HTTP}"
|
||||||
src/App.cpp
|
src/App.cpp
|
||||||
src/common/config/CommonConfig.cpp
|
src/common/config/CommonConfig.cpp
|
||||||
src/common/config/ConfigLoader.cpp
|
src/common/config/ConfigLoader.cpp
|
||||||
|
@ -88,16 +90,17 @@ set(SOURCES
|
||||||
src/common/crypto/Algorithm.cpp
|
src/common/crypto/Algorithm.cpp
|
||||||
src/common/crypto/keccak.cpp
|
src/common/crypto/keccak.cpp
|
||||||
src/common/Platform.cpp
|
src/common/Platform.cpp
|
||||||
src/core/Config.cpp
|
src/core/config/Config.cpp
|
||||||
src/core/Controller.cpp
|
src/core/Controller.cpp
|
||||||
src/Mem.cpp
|
src/Mem.cpp
|
||||||
src/net/Network.cpp
|
src/net/Network.cpp
|
||||||
|
src/net/NetworkState.cpp
|
||||||
src/net/strategies/DonateStrategy.cpp
|
src/net/strategies/DonateStrategy.cpp
|
||||||
src/Summary.cpp
|
src/Summary.cpp
|
||||||
src/workers/CpuThread.cpp
|
src/workers/CpuThread.cpp
|
||||||
src/workers/ThreadHandle.cpp
|
|
||||||
src/workers/Hashrate.cpp
|
src/workers/Hashrate.cpp
|
||||||
src/workers/MultiWorker.cpp
|
src/workers/MultiWorker.cpp
|
||||||
|
src/workers/ThreadHandle.cpp
|
||||||
src/workers/Worker.cpp
|
src/workers/Worker.cpp
|
||||||
src/workers/Workers.cpp
|
src/workers/Workers.cpp
|
||||||
src/xmrig.cpp
|
src/xmrig.cpp
|
||||||
|
@ -201,30 +204,21 @@ if (WITH_EMBEDDED_CONFIG)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if (WITH_HTTPD)
|
if (WITH_HTTPD)
|
||||||
find_package(MHD)
|
|
||||||
|
|
||||||
if (MHD_FOUND)
|
|
||||||
include_directories(${MHD_INCLUDE_DIRS})
|
|
||||||
set(HTTPD_SOURCES
|
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/Api.cpp
|
||||||
src/api/ApiRouter.cpp
|
src/api/Api.h
|
||||||
src/common/api/Httpd.cpp
|
src/api/Httpd.cpp
|
||||||
src/common/api/HttpRequest.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()
|
|
||||||
message(FATAL_ERROR "microhttpd NOT found: use `-DWITH_HTTPD=OFF` to build without http deamon support")
|
|
||||||
endif()
|
|
||||||
else()
|
else()
|
||||||
set(HTTPD_SOURCES "")
|
set(HTTPD_SOURCES "")
|
||||||
set(MHD_LIBRARY "")
|
|
||||||
add_definitions(/DXMRIG_NO_HTTPD)
|
|
||||||
add_definitions(/DXMRIG_NO_API)
|
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
include_directories(src)
|
include_directories(src)
|
||||||
|
@ -240,4 +234,4 @@ if (WITH_DEBUG_LOG)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
add_executable(${CMAKE_PROJECT_NAME} ${HEADERS} ${SOURCES} ${SOURCES_OS} ${SOURCES_CPUID} ${HEADERS_CRYPTO} ${SOURCES_CRYPTO} ${SOURCES_SYSLOG} ${HTTPD_SOURCES} ${TLS_SOURCES} ${XMRIG_ASM_SOURCES} ${CN_GPU_SOURCES})
|
add_executable(${CMAKE_PROJECT_NAME} ${HEADERS} ${SOURCES} ${SOURCES_OS} ${SOURCES_CPUID} ${HEADERS_CRYPTO} ${SOURCES_CRYPTO} ${SOURCES_SYSLOG} ${HTTPD_SOURCES} ${TLS_SOURCES} ${XMRIG_ASM_SOURCES} ${CN_GPU_SOURCES})
|
||||||
target_link_libraries(${CMAKE_PROJECT_NAME} ${XMRIG_ASM_LIBRARY} ${OPENSSL_LIBRARIES} ${UV_LIBRARIES} ${MHD_LIBRARY} ${EXTRA_LIBS} ${CPUID_LIB})
|
target_link_libraries(${CMAKE_PROJECT_NAME} ${XMRIG_ASM_LIBRARY} ${OPENSSL_LIBRARIES} ${UV_LIBRARIES} ${EXTRA_LIBS} ${CPUID_LIB})
|
||||||
|
|
|
@ -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)
|
|
||||||
|
|
|
@ -18,12 +18,10 @@ if (WITH_TLS)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
add_definitions(/DXMRIG_FEATURE_TLS)
|
add_definitions(/DXMRIG_FEATURE_TLS)
|
||||||
remove_definitions(/DXMRIG_NO_TLS)
|
|
||||||
else()
|
else()
|
||||||
set(TLS_SOURCES "")
|
set(TLS_SOURCES "")
|
||||||
set(OPENSSL_LIBRARIES "")
|
set(OPENSSL_LIBRARIES "")
|
||||||
remove_definitions(/DXMRIG_FEATURE_TLS)
|
remove_definitions(/DXMRIG_FEATURE_TLS)
|
||||||
add_definitions(/DXMRIG_NO_TLS)
|
|
||||||
|
|
||||||
set(CMAKE_PROJECT_NAME "${CMAKE_PROJECT_NAME}-notls")
|
set(CMAKE_PROJECT_NAME "${CMAKE_PROJECT_NAME}-notls")
|
||||||
endif()
|
endif()
|
||||||
|
|
68
src/3rdparty/http-parser/AUTHORS
vendored
Normal file
68
src/3rdparty/http-parser/AUTHORS
vendored
Normal 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
19
src/3rdparty/http-parser/LICENSE-MIT
vendored
Normal 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
246
src/3rdparty/http-parser/README.md
vendored
Normal 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
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
439
src/3rdparty/http-parser/http_parser.h
vendored
Normal 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
|
33
src/App.cpp
33
src/App.cpp
|
@ -35,7 +35,7 @@
|
||||||
#include "base/kernel/Signals.h"
|
#include "base/kernel/Signals.h"
|
||||||
#include "common/cpu/Cpu.h"
|
#include "common/cpu/Cpu.h"
|
||||||
#include "common/Platform.h"
|
#include "common/Platform.h"
|
||||||
#include "core/Config.h"
|
#include "core/config/Config.h"
|
||||||
#include "core/Controller.h"
|
#include "core/Controller.h"
|
||||||
#include "crypto/CryptoNight.h"
|
#include "crypto/CryptoNight.h"
|
||||||
#include "Mem.h"
|
#include "Mem.h"
|
||||||
|
@ -45,14 +45,8 @@
|
||||||
#include "workers/Workers.h"
|
#include "workers/Workers.h"
|
||||||
|
|
||||||
|
|
||||||
#ifndef XMRIG_NO_HTTPD
|
|
||||||
# include "common/api/Httpd.h"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
xmrig::App::App(Process *process) :
|
xmrig::App::App(Process *process) :
|
||||||
m_console(nullptr),
|
m_console(nullptr),
|
||||||
m_httpd(nullptr),
|
|
||||||
m_signals(nullptr)
|
m_signals(nullptr)
|
||||||
{
|
{
|
||||||
m_controller = new Controller(process);
|
m_controller = new Controller(process);
|
||||||
|
@ -71,10 +65,6 @@ xmrig::App::~App()
|
||||||
delete m_signals;
|
delete m_signals;
|
||||||
delete m_console;
|
delete m_console;
|
||||||
delete m_controller;
|
delete m_controller;
|
||||||
|
|
||||||
# ifndef XMRIG_NO_HTTPD
|
|
||||||
delete m_httpd;
|
|
||||||
# endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -98,24 +88,9 @@ int xmrig::App::exec()
|
||||||
return 0;
|
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);
|
Workers::start(m_controller);
|
||||||
|
|
||||||
m_controller->network()->connect();
|
m_controller->start();
|
||||||
|
|
||||||
const int r = uv_run(uv_default_loop(), UV_RUN_DEFAULT);
|
const int r = uv_run(uv_default_loop(), UV_RUN_DEFAULT);
|
||||||
uv_loop_close(uv_default_loop());
|
uv_loop_close(uv_default_loop());
|
||||||
|
@ -185,10 +160,6 @@ void xmrig::App::onSignal(int signum)
|
||||||
|
|
||||||
void xmrig::App::close()
|
void xmrig::App::close()
|
||||||
{
|
{
|
||||||
# ifndef XMRIG_NO_HTTPD
|
|
||||||
m_httpd->stop();
|
|
||||||
# endif
|
|
||||||
|
|
||||||
m_signals->stop();
|
m_signals->stop();
|
||||||
m_console->stop();
|
m_console->stop();
|
||||||
m_controller->stop();
|
m_controller->stop();
|
||||||
|
|
|
@ -36,7 +36,6 @@ namespace xmrig {
|
||||||
|
|
||||||
class Console;
|
class Console;
|
||||||
class Controller;
|
class Controller;
|
||||||
class Httpd;
|
|
||||||
class Network;
|
class Network;
|
||||||
class Process;
|
class Process;
|
||||||
class Signals;
|
class Signals;
|
||||||
|
@ -60,7 +59,6 @@ private:
|
||||||
|
|
||||||
Console *m_console;
|
Console *m_console;
|
||||||
Controller *m_controller;
|
Controller *m_controller;
|
||||||
Httpd *m_httpd;
|
|
||||||
Signals *m_signals;
|
Signals *m_signals;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -31,7 +31,7 @@
|
||||||
|
|
||||||
#include "App.h"
|
#include "App.h"
|
||||||
#include "base/io/log/Log.h"
|
#include "base/io/log/Log.h"
|
||||||
#include "core/Config.h"
|
#include "core/config/Config.h"
|
||||||
#include "core/Controller.h"
|
#include "core/Controller.h"
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -29,7 +29,7 @@
|
||||||
|
|
||||||
#include "App.h"
|
#include "App.h"
|
||||||
#include "core/Controller.h"
|
#include "core/Controller.h"
|
||||||
#include "core/Config.h"
|
#include "core/config/Config.h"
|
||||||
|
|
||||||
|
|
||||||
void xmrig::App::background()
|
void xmrig::App::background()
|
||||||
|
|
|
@ -31,7 +31,7 @@
|
||||||
#include "base/io/log/Log.h"
|
#include "base/io/log/Log.h"
|
||||||
#include "base/net/stratum/Pool.h"
|
#include "base/net/stratum/Pool.h"
|
||||||
#include "common/cpu/Cpu.h"
|
#include "common/cpu/Cpu.h"
|
||||||
#include "core/Config.h"
|
#include "core/config/Config.h"
|
||||||
#include "core/Controller.h"
|
#include "core/Controller.h"
|
||||||
#include "crypto/Asm.h"
|
#include "crypto/Asm.h"
|
||||||
#include "Mem.h"
|
#include "Mem.h"
|
||||||
|
@ -142,8 +142,7 @@ void Summary::print(xmrig::Controller *controller)
|
||||||
print_memory(controller->config());
|
print_memory(controller->config());
|
||||||
print_cpu(controller->config());
|
print_cpu(controller->config());
|
||||||
print_threads(controller->config());
|
print_threads(controller->config());
|
||||||
controller->config()->printPools();
|
controller->config()->pools().print();
|
||||||
controller->config()->printAPI();
|
|
||||||
|
|
||||||
print_commands(controller->config());
|
print_commands(controller->config());
|
||||||
}
|
}
|
||||||
|
|
162
src/api/Api.cpp
162
src/api/Api.cpp
|
@ -22,52 +22,166 @@
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
* 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/Api.h"
|
||||||
#include "api/ApiRouter.h"
|
#include "api/interfaces/IApiListener.h"
|
||||||
#include "common/api/HttpReply.h"
|
#include "api/requests/HttpApiRequest.h"
|
||||||
#include "common/api/HttpRequest.h"
|
#include "api/v1/ApiRouter.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(Controller *controller) :
|
||||||
|
m_id(),
|
||||||
|
m_workerId(),
|
||||||
|
m_controller(controller),
|
||||||
|
m_httpd(nullptr)
|
||||||
{
|
{
|
||||||
m_router = new ApiRouter(controller);
|
controller->addListener(this);
|
||||||
|
|
||||||
return true;
|
genId(m_controller->config()->apiId());
|
||||||
|
|
||||||
|
m_v1 = new ApiRouter(controller);
|
||||||
|
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 HttpRequest &req)
|
||||||
{
|
{
|
||||||
if (!m_router) {
|
HttpApiRequest request(req, m_controller->config()->http().isRestricted());
|
||||||
reply.status = 500;
|
|
||||||
|
exec(request);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void xmrig::Api::start()
|
||||||
|
{
|
||||||
|
genWorkerId(m_controller->config()->apiWorkerId());
|
||||||
|
|
||||||
|
# ifdef XMRIG_FEATURE_HTTP
|
||||||
|
m_httpd = new Httpd(m_controller);
|
||||||
|
m_httpd->start();
|
||||||
|
# endif
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void xmrig::Api::stop()
|
||||||
|
{
|
||||||
|
# ifdef XMRIG_FEATURE_HTTP
|
||||||
|
m_httpd->stop();
|
||||||
|
# endif
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void xmrig::Api::onConfigChanged(Config *config, Config *previousConfig)
|
||||||
|
{
|
||||||
|
if (config->apiId() != previousConfig->apiId()) {
|
||||||
|
genId(config->apiId());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (config->apiWorkerId() != previousConfig->apiWorkerId()) {
|
||||||
|
genWorkerId(config->apiWorkerId());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void xmrig::Api::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;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (req.method() == xmrig::HttpRequest::Get) {
|
uv_interface_address_t *interfaces;
|
||||||
return m_router->get(req, reply);
|
int count = 0;
|
||||||
}
|
|
||||||
|
|
||||||
m_router->exec(req, reply);
|
if (uv_interface_addresses(&interfaces, &count) < 0) {
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void Api::tick(const xmrig::NetworkState &network)
|
|
||||||
{
|
|
||||||
if (!m_router) {
|
|
||||||
return;
|
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_controller->config()->http().port());
|
||||||
|
|
||||||
|
uint8_t *input = new uint8_t[inSize]();
|
||||||
|
memcpy(input, &port, sizeof(uint16_t));
|
||||||
|
memcpy(input + sizeof(uint16_t), interfaces[i].phys_addr, addrSize);
|
||||||
|
memcpy(input + sizeof(uint16_t) + addrSize, APP_KIND, strlen(APP_KIND));
|
||||||
|
|
||||||
|
xmrig::keccak(input, inSize, hash);
|
||||||
|
xmrig::Buffer::toHex(hash, 8, m_id);
|
||||||
|
|
||||||
|
delete [] input;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
uv_free_interface_addresses(interfaces, count);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void xmrig::Api::genWorkerId(const String &id)
|
||||||
|
{
|
||||||
|
memset(m_workerId, 0, sizeof(m_workerId));
|
||||||
|
|
||||||
|
if (id.size() > 0) {
|
||||||
|
strncpy(m_workerId, id.data(), sizeof(m_workerId) - 1);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
gethostname(m_workerId, sizeof(m_workerId) - 1);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,32 +26,56 @@
|
||||||
#define XMRIG_API_H
|
#define XMRIG_API_H
|
||||||
|
|
||||||
|
|
||||||
#include <uv.h>
|
#include <vector>
|
||||||
|
|
||||||
|
|
||||||
class ApiRouter;
|
#include "base/kernel/interfaces/IControllerListener.h"
|
||||||
class Hashrate;
|
|
||||||
|
|
||||||
|
|
||||||
namespace xmrig {
|
namespace xmrig {
|
||||||
|
|
||||||
|
|
||||||
|
class ApiRouter;
|
||||||
class Controller;
|
class Controller;
|
||||||
class HttpReply;
|
class Httpd;
|
||||||
class HttpRequest;
|
class HttpRequest;
|
||||||
class NetworkState;
|
class IApiListener;
|
||||||
}
|
class IApiRequest;
|
||||||
|
class String;
|
||||||
|
|
||||||
|
|
||||||
class Api
|
class Api : public IControllerListener
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
static bool start(xmrig::Controller *controller);
|
Api(Controller *controller);
|
||||||
static void release();
|
~Api() override;
|
||||||
|
|
||||||
static void exec(const xmrig::HttpRequest &req, xmrig::HttpReply &reply);
|
inline const char *id() const { return m_id; }
|
||||||
static void tick(const xmrig::NetworkState &results);
|
inline const char *workerId() const { return m_workerId; }
|
||||||
|
inline void addListener(IApiListener *listener) { m_listeners.push_back(listener); }
|
||||||
|
|
||||||
|
void request(const HttpRequest &req);
|
||||||
|
void start();
|
||||||
|
void stop();
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void onConfigChanged(Config *config, Config *previousConfig) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static ApiRouter *m_router;
|
void exec(IApiRequest &request);
|
||||||
|
void genId(const String &id);
|
||||||
|
void genWorkerId(const String &id);
|
||||||
|
|
||||||
|
ApiRouter *m_v1;
|
||||||
|
char m_id[32];
|
||||||
|
char m_workerId[128];
|
||||||
|
Controller *m_controller;
|
||||||
|
Httpd *m_httpd;
|
||||||
|
std::vector<IApiListener *> m_listeners;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
} // namespace xmrig
|
||||||
|
|
||||||
|
|
||||||
#endif /* XMRIG_API_H */
|
#endif /* XMRIG_API_H */
|
||||||
|
|
|
@ -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);
|
|
||||||
}
|
|
|
@ -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 */
|
|
164
src/api/Httpd.cpp
Normal file
164
src/api/Httpd.cpp
Normal file
|
@ -0,0 +1,164 @@
|
||||||
|
/* 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/HttpRequest.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";
|
||||||
|
|
||||||
|
} // namespace xmrig
|
||||||
|
|
||||||
|
|
||||||
|
xmrig::Httpd::Httpd(Controller *controller) :
|
||||||
|
m_controller(controller),
|
||||||
|
m_http(nullptr),
|
||||||
|
m_server(nullptr),
|
||||||
|
m_port(0)
|
||||||
|
{
|
||||||
|
controller->addListener(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
xmrig::Httpd::~Httpd()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool xmrig::Httpd::start()
|
||||||
|
{
|
||||||
|
const Http &config = m_controller->config()->http();
|
||||||
|
|
||||||
|
if (!config.isEnabled()) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_http = new HttpServer(this);
|
||||||
|
m_server = new TcpServer(config.host(), config.port(), m_http);
|
||||||
|
|
||||||
|
const int rc = m_server->bind();
|
||||||
|
Log::print(GREEN_BOLD(" * ") WHITE_BOLD("%-13s") BLUE_BOLD("%s:%d") " " RED_BOLD("%s"),
|
||||||
|
"HTTP API",
|
||||||
|
config.host().data(),
|
||||||
|
rc < 0 ? config.port() : rc,
|
||||||
|
rc < 0 ? uv_strerror(rc) : ""
|
||||||
|
);
|
||||||
|
|
||||||
|
if (rc < 0) {
|
||||||
|
stop();
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_port = static_cast<uint16_t>(rc);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void xmrig::Httpd::stop()
|
||||||
|
{
|
||||||
|
delete m_server;
|
||||||
|
delete m_http;
|
||||||
|
|
||||||
|
m_server = nullptr;
|
||||||
|
m_http = nullptr;
|
||||||
|
m_port = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void xmrig::Httpd::onConfigChanged(Config *config, Config *previousConfig)
|
||||||
|
{
|
||||||
|
if (config->http() == previousConfig->http()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
stop();
|
||||||
|
start();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void xmrig::Httpd::onHttpRequest(const HttpRequest &req)
|
||||||
|
{
|
||||||
|
if (req.method == HTTP_OPTIONS) {
|
||||||
|
return HttpApiResponse(req.id()).end();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (req.method > 4) {
|
||||||
|
return HttpApiResponse(req.id(), HTTP_STATUS_METHOD_NOT_ALLOWED).end();
|
||||||
|
}
|
||||||
|
|
||||||
|
const int status = auth(req);
|
||||||
|
if (status != HTTP_STATUS_OK) {
|
||||||
|
return HttpApiResponse(req.id(), status).end();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (req.method != HTTP_GET) {
|
||||||
|
if (m_controller->config()->http().isRestricted()) {
|
||||||
|
return HttpApiResponse(req.id(), HTTP_STATUS_FORBIDDEN).end();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!req.headers.count(kContentType) || req.headers.at(kContentType) != "application/json") {
|
||||||
|
return HttpApiResponse(req.id(), HTTP_STATUS_UNSUPPORTED_MEDIA_TYPE).end();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
m_controller->api()->request(req);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int xmrig::Httpd::auth(const HttpRequest &req) const
|
||||||
|
{
|
||||||
|
const Http &config = m_controller->config()->http();
|
||||||
|
|
||||||
|
if (!req.headers.count(kAuthorization)) {
|
||||||
|
return config.isAuthRequired() ? HTTP_STATUS_UNAUTHORIZED : HTTP_STATUS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (config.token().isNull()) {
|
||||||
|
return HTTP_STATUS_UNAUTHORIZED;
|
||||||
|
}
|
||||||
|
|
||||||
|
const std::string &token = req.headers.at(kAuthorization);
|
||||||
|
const size_t size = token.size();
|
||||||
|
|
||||||
|
if (token.size() < 8 || config.token().size() != size - 7 || memcmp("Bearer ", token.c_str(), 7) != 0) {
|
||||||
|
return HTTP_STATUS_FORBIDDEN;
|
||||||
|
}
|
||||||
|
|
||||||
|
return strncmp(config.token().data(), token.c_str() + 7, config.token().size()) == 0 ? HTTP_STATUS_OK : HTTP_STATUS_FORBIDDEN;
|
||||||
|
}
|
|
@ -26,52 +26,41 @@
|
||||||
#define XMRIG_HTTPD_H
|
#define XMRIG_HTTPD_H
|
||||||
|
|
||||||
|
|
||||||
#include <stddef.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
|
|
||||||
#include "base/kernel/interfaces/ITimerListener.h"
|
#include "base/kernel/interfaces/IControllerListener.h"
|
||||||
|
#include "base/kernel/interfaces/IHttpListener.h"
|
||||||
|
|
||||||
struct MHD_Connection;
|
|
||||||
struct MHD_Daemon;
|
|
||||||
struct MHD_Response;
|
|
||||||
|
|
||||||
|
|
||||||
namespace xmrig {
|
namespace xmrig {
|
||||||
|
|
||||||
|
|
||||||
class HttpRequest;
|
class Controller;
|
||||||
class Timer;
|
class HttpServer;
|
||||||
|
class TcpServer;
|
||||||
|
|
||||||
|
|
||||||
class Httpd : public ITimerListener
|
class Httpd : public IControllerListener, public IHttpListener
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
Httpd(int port, const char *accessToken, bool IPv6, bool restricted);
|
Httpd(Controller *controller);
|
||||||
~Httpd() override;
|
~Httpd() override;
|
||||||
|
|
||||||
bool start();
|
bool start();
|
||||||
void stop();
|
void stop();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void onTimer(const Timer *) override { run(); }
|
void onConfigChanged(Config *config, Config *previousConfig) override;
|
||||||
|
void onHttpRequest(const HttpRequest &req) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
constexpr static const int kIdleInterval = 200;
|
int auth(const HttpRequest &req) const;
|
||||||
constexpr static const int kActiveInterval = 25;
|
|
||||||
|
|
||||||
int process(HttpRequest &req);
|
Controller *m_controller;
|
||||||
void run();
|
HttpServer *m_http;
|
||||||
|
TcpServer *m_server;
|
||||||
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);
|
uint16_t m_port;
|
||||||
|
|
||||||
bool m_idle;
|
|
||||||
bool m_IPv6;
|
|
||||||
bool m_restricted;
|
|
||||||
const char *m_accessToken;
|
|
||||||
const int m_port;
|
|
||||||
MHD_Daemon *m_daemon;
|
|
||||||
Timer *m_timer;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -20,31 +20,26 @@
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef __CONFIGCREATOR_H__
|
#ifndef XMRIG_IAPILISTENER_H
|
||||||
#define __CONFIGCREATOR_H__
|
#define XMRIG_IAPILISTENER_H
|
||||||
|
|
||||||
|
|
||||||
#include "common/interfaces/IConfigCreator.h"
|
|
||||||
#include "core/Config.h"
|
|
||||||
|
|
||||||
|
|
||||||
namespace xmrig {
|
namespace xmrig {
|
||||||
|
|
||||||
|
|
||||||
class IConfig;
|
class IApiRequest;
|
||||||
|
|
||||||
|
|
||||||
class ConfigCreator : public IConfigCreator
|
class IApiListener
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
inline IConfig *create() const override
|
virtual ~IApiListener() = default;
|
||||||
{
|
|
||||||
return new Config();
|
virtual void onRequest(IApiRequest &request) = 0;
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
} /* namespace xmrig */
|
} /* namespace xmrig */
|
||||||
|
|
||||||
|
|
||||||
#endif // __CONFIGCREATOR_H__
|
#endif // XMRIG_IAPILISTENER_H
|
72
src/api/interfaces/IApiRequest.h
Normal file
72
src/api/interfaces/IApiRequest.h
Normal 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
|
|
@ -5,8 +5,8 @@
|
||||||
* Copyright 2014-2016 Wolf9466 <https://github.com/OhGodAPet>
|
* Copyright 2014-2016 Wolf9466 <https://github.com/OhGodAPet>
|
||||||
* Copyright 2016 Jay D Dee <jayddee246@gmail.com>
|
* Copyright 2016 Jay D Dee <jayddee246@gmail.com>
|
||||||
* Copyright 2017-2018 XMR-Stak <https://github.com/fireice-uk>, <https://github.com/psychocrypt>
|
* 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
|
* 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
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
@ -22,32 +22,18 @@
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef __HTTPREPLY_H__
|
|
||||||
#define __HTTPREPLY_H__
|
#include "api/requests/ApiRequest.h"
|
||||||
|
|
||||||
|
|
||||||
#include <stdint.h>
|
xmrig::ApiRequest::ApiRequest(Source source, bool restricted) :
|
||||||
|
m_restricted(restricted),
|
||||||
|
m_source(source),
|
||||||
namespace xmrig {
|
m_state(STATE_NEW)
|
||||||
|
|
||||||
|
|
||||||
class HttpReply
|
|
||||||
{
|
{
|
||||||
public:
|
}
|
||||||
HttpReply() :
|
|
||||||
buf(nullptr),
|
|
||||||
status(200),
|
|
||||||
size(0)
|
|
||||||
{}
|
|
||||||
|
|
||||||
char *buf;
|
|
||||||
int status;
|
|
||||||
size_t size;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
} /* namespace xmrig */
|
xmrig::ApiRequest::~ApiRequest()
|
||||||
|
{
|
||||||
|
}
|
||||||
#endif /* __HTTPREPLY_H__ */
|
|
67
src/api/requests/ApiRequest.h
Normal file
67
src/api/requests/ApiRequest.h
Normal file
|
@ -0,0 +1,67 @@
|
||||||
|
/* XMRig
|
||||||
|
* Copyright 2010 Jeff Garzik <jgarzik@pobox.com>
|
||||||
|
* Copyright 2012-2014 pooler <pooler@litecoinpool.org>
|
||||||
|
* Copyright 2014 Lucas Jones <https://github.com/lucasjones>
|
||||||
|
* Copyright 2014-2016 Wolf9466 <https://github.com/OhGodAPet>
|
||||||
|
* Copyright 2016 Jay D Dee <jayddee246@gmail.com>
|
||||||
|
* Copyright 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_APIREQUEST_H
|
||||||
|
#define XMRIG_APIREQUEST_H
|
||||||
|
|
||||||
|
|
||||||
|
#include "api/interfaces/IApiRequest.h"
|
||||||
|
|
||||||
|
|
||||||
|
namespace xmrig {
|
||||||
|
|
||||||
|
|
||||||
|
class ApiRequest : public IApiRequest
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
ApiRequest(Source source, bool restricted);
|
||||||
|
~ApiRequest() override;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
inline bool isDone() const override { return m_state == STATE_DONE; }
|
||||||
|
inline bool isNew() const override { return m_state == STATE_NEW; }
|
||||||
|
inline bool isRestricted() const override { return m_restricted; }
|
||||||
|
inline Source source() const override { return m_source; }
|
||||||
|
inline void accept() override { m_state = STATE_ACCEPTED; }
|
||||||
|
inline void done(int) override { m_state = STATE_DONE; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
enum State {
|
||||||
|
STATE_NEW,
|
||||||
|
STATE_ACCEPTED,
|
||||||
|
STATE_DONE
|
||||||
|
};
|
||||||
|
|
||||||
|
bool m_restricted;
|
||||||
|
Source m_source;
|
||||||
|
State m_state;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
} // namespace xmrig
|
||||||
|
|
||||||
|
|
||||||
|
#endif // XMRIG_APIREQUEST_H
|
||||||
|
|
76
src/api/requests/HttpApiRequest.cpp
Normal file
76
src/api/requests/HttpApiRequest.cpp
Normal 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/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#include "api/requests/HttpApiRequest.h"
|
||||||
|
#include "base/net/http/HttpRequest.h"
|
||||||
|
#include "rapidjson/error/en.h"
|
||||||
|
|
||||||
|
|
||||||
|
xmrig::HttpApiRequest::HttpApiRequest(const HttpRequest &req, bool restricted) :
|
||||||
|
ApiRequest(SOURCE_HTTP, restricted),
|
||||||
|
m_parsed(false),
|
||||||
|
m_req(req),
|
||||||
|
m_res(req.id()),
|
||||||
|
m_url(req.url.c_str())
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const rapidjson::Value &xmrig::HttpApiRequest::json() const
|
||||||
|
{
|
||||||
|
return m_body;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
xmrig::IApiRequest::Method xmrig::HttpApiRequest::method() const
|
||||||
|
{
|
||||||
|
return static_cast<IApiRequest::Method>(m_req.method);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void xmrig::HttpApiRequest::accept()
|
||||||
|
{
|
||||||
|
using namespace rapidjson;
|
||||||
|
|
||||||
|
ApiRequest::accept();
|
||||||
|
|
||||||
|
if (!m_parsed && !m_req.body.empty()) {
|
||||||
|
m_parsed = true;
|
||||||
|
m_body.Parse<kParseCommentsFlag | kParseTrailingCommasFlag>(m_req.body.c_str());
|
||||||
|
|
||||||
|
if (m_body.HasParseError()) {
|
||||||
|
reply().AddMember("error", StringRef(GetParseError_En(m_body.GetParseError())), doc().GetAllocator());;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void xmrig::HttpApiRequest::done(int status)
|
||||||
|
{
|
||||||
|
ApiRequest::done(status);
|
||||||
|
|
||||||
|
m_res.setStatus(status);
|
||||||
|
m_res.end();
|
||||||
|
}
|
69
src/api/requests/HttpApiRequest.h
Normal file
69
src/api/requests/HttpApiRequest.h
Normal 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 HttpRequest;
|
||||||
|
|
||||||
|
|
||||||
|
class HttpApiRequest : public ApiRequest
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
HttpApiRequest(const HttpRequest &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 HttpRequest &m_req;
|
||||||
|
HttpApiResponse m_res;
|
||||||
|
rapidjson::Document m_body;
|
||||||
|
String m_url;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
} // namespace xmrig
|
||||||
|
|
||||||
|
|
||||||
|
#endif // XMRIG_HTTPAPIREQUEST_H
|
||||||
|
|
177
src/api/v1/ApiRouter.cpp
Normal file
177
src/api/v1/ApiRouter.cpp
Normal file
|
@ -0,0 +1,177 @@
|
||||||
|
/* 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 "common/cpu/Cpu.h"
|
||||||
|
#include "common/Platform.h"
|
||||||
|
#include "core/config/Config.h"
|
||||||
|
#include "core/Controller.h"
|
||||||
|
#include "interfaces/IThread.h"
|
||||||
|
#include "rapidjson/document.h"
|
||||||
|
#include "version.h"
|
||||||
|
#include "workers/Hashrate.h"
|
||||||
|
#include "workers/Workers.h"
|
||||||
|
|
||||||
|
|
||||||
|
static inline double normalize(double d)
|
||||||
|
{
|
||||||
|
if (!isnormal(d)) {
|
||||||
|
return 0.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return floor(d * 100.0) / 100.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
xmrig::ApiRouter::ApiRouter(xmrig::Controller *controller) :
|
||||||
|
m_controller(controller)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
xmrig::ApiRouter::~ApiRouter()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void xmrig::ApiRouter::onRequest(IApiRequest &request)
|
||||||
|
{
|
||||||
|
if (request.method() == IApiRequest::METHOD_GET) {
|
||||||
|
if (request.url() == "/1/summary" || request.url() == "/api.json") {
|
||||||
|
request.accept();
|
||||||
|
getMiner(request.reply(), request.doc());
|
||||||
|
getHashrate(request.reply(), request.doc());
|
||||||
|
}
|
||||||
|
else if (request.url() == "/1/threads") {
|
||||||
|
request.accept();
|
||||||
|
getThreads(request.reply(), request.doc());
|
||||||
|
}
|
||||||
|
else if (request.url() == "/1/config") {
|
||||||
|
if (request.isRestricted()) {
|
||||||
|
return request.done(403);
|
||||||
|
}
|
||||||
|
|
||||||
|
m_controller->config()->getJSON(request.doc());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (request.method() == IApiRequest::METHOD_PUT || request.method() == IApiRequest::METHOD_POST) {
|
||||||
|
if (request.url() == "/1/config") {
|
||||||
|
request.accept();
|
||||||
|
|
||||||
|
if (!m_controller->config()->reload(request.json())) {
|
||||||
|
return request.done(400);
|
||||||
|
}
|
||||||
|
|
||||||
|
request.done(204);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void xmrig::ApiRouter::getHashrate(rapidjson::Value &reply, rapidjson::Document &doc) const
|
||||||
|
{
|
||||||
|
using namespace rapidjson;
|
||||||
|
auto &allocator = doc.GetAllocator();
|
||||||
|
|
||||||
|
Value hashrate(kObjectType);
|
||||||
|
Value total(kArrayType);
|
||||||
|
Value threads(kArrayType);
|
||||||
|
|
||||||
|
const Hashrate *hr = Workers::hashrate();
|
||||||
|
|
||||||
|
total.PushBack(normalize(hr->calc(Hashrate::ShortInterval)), allocator);
|
||||||
|
total.PushBack(normalize(hr->calc(Hashrate::MediumInterval)), allocator);
|
||||||
|
total.PushBack(normalize(hr->calc(Hashrate::LargeInterval)), allocator);
|
||||||
|
|
||||||
|
for (size_t i = 0; i < Workers::threads(); i++) {
|
||||||
|
Value thread(kArrayType);
|
||||||
|
thread.PushBack(normalize(hr->calc(i, Hashrate::ShortInterval)), allocator);
|
||||||
|
thread.PushBack(normalize(hr->calc(i, Hashrate::MediumInterval)), allocator);
|
||||||
|
thread.PushBack(normalize(hr->calc(i, Hashrate::LargeInterval)), allocator);
|
||||||
|
|
||||||
|
threads.PushBack(thread, allocator);
|
||||||
|
}
|
||||||
|
|
||||||
|
hashrate.AddMember("total", total, allocator);
|
||||||
|
hashrate.AddMember("highest", normalize(hr->highest()), allocator);
|
||||||
|
hashrate.AddMember("threads", threads, allocator);
|
||||||
|
reply.AddMember("hashrate", hashrate, allocator);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void xmrig::ApiRouter::getMiner(rapidjson::Value &reply, rapidjson::Document &doc) const
|
||||||
|
{
|
||||||
|
using namespace rapidjson;
|
||||||
|
auto &allocator = doc.GetAllocator();
|
||||||
|
|
||||||
|
Value cpu(kObjectType);
|
||||||
|
cpu.AddMember("brand", StringRef(Cpu::info()->brand()), allocator);
|
||||||
|
cpu.AddMember("aes", Cpu::info()->hasAES(), allocator);
|
||||||
|
cpu.AddMember("x64", Cpu::info()->isX64(), allocator);
|
||||||
|
cpu.AddMember("sockets", Cpu::info()->sockets(), allocator);
|
||||||
|
|
||||||
|
reply.AddMember("version", APP_VERSION, allocator);
|
||||||
|
reply.AddMember("kind", APP_KIND, allocator);
|
||||||
|
reply.AddMember("ua", StringRef(Platform::userAgent()), allocator);
|
||||||
|
reply.AddMember("cpu", cpu, allocator);
|
||||||
|
reply.AddMember("algo", StringRef(m_controller->config()->algorithm().name()), allocator);
|
||||||
|
reply.AddMember("hugepages", Workers::hugePages() > 0, allocator);
|
||||||
|
reply.AddMember("donate_level", m_controller->config()->pools().donateLevel(), allocator);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void xmrig::ApiRouter::getThreads(rapidjson::Value &reply, rapidjson::Document &doc) const
|
||||||
|
{
|
||||||
|
using namespace rapidjson;
|
||||||
|
auto &allocator = doc.GetAllocator();
|
||||||
|
const Hashrate *hr = Workers::hashrate();
|
||||||
|
|
||||||
|
Workers::threadsSummary(doc);
|
||||||
|
|
||||||
|
const std::vector<xmrig::IThread *> &threads = m_controller->config()->threads();
|
||||||
|
Value list(kArrayType);
|
||||||
|
|
||||||
|
size_t i = 0;
|
||||||
|
for (const xmrig::IThread *thread : threads) {
|
||||||
|
Value value = thread->toAPI(doc);
|
||||||
|
|
||||||
|
Value hashrate(kArrayType);
|
||||||
|
hashrate.PushBack(normalize(hr->calc(i, Hashrate::ShortInterval)), allocator);
|
||||||
|
hashrate.PushBack(normalize(hr->calc(i, Hashrate::MediumInterval)), allocator);
|
||||||
|
hashrate.PushBack(normalize(hr->calc(i, Hashrate::LargeInterval)), allocator);
|
||||||
|
|
||||||
|
i++;
|
||||||
|
|
||||||
|
value.AddMember("hashrate", hashrate, allocator);
|
||||||
|
list.PushBack(value, allocator);
|
||||||
|
}
|
||||||
|
|
||||||
|
reply.AddMember("threads", list, allocator);
|
||||||
|
}
|
63
src/api/v1/ApiRouter.h
Normal file
63
src/api/v1/ApiRouter.h
Normal 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 Controller;
|
||||||
|
|
||||||
|
|
||||||
|
class ApiRouter : public xmrig::IApiListener
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
ApiRouter(Controller *controller);
|
||||||
|
~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;
|
||||||
|
|
||||||
|
Controller *m_controller;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
} // namespace xmrig
|
||||||
|
|
||||||
|
|
||||||
|
#endif /* XMRIG_APIROUTER_H */
|
|
@ -9,6 +9,7 @@ set(HEADERS_BASE
|
||||||
src/base/kernel/interfaces/IClientListener.h
|
src/base/kernel/interfaces/IClientListener.h
|
||||||
src/base/kernel/interfaces/IConfigListener.h
|
src/base/kernel/interfaces/IConfigListener.h
|
||||||
src/base/kernel/interfaces/IConsoleListener.h
|
src/base/kernel/interfaces/IConsoleListener.h
|
||||||
|
src/base/kernel/interfaces/IControllerListener.h
|
||||||
src/base/kernel/interfaces/IDnsListener.h
|
src/base/kernel/interfaces/IDnsListener.h
|
||||||
src/base/kernel/interfaces/ILineListener.h
|
src/base/kernel/interfaces/ILineListener.h
|
||||||
src/base/kernel/interfaces/ILogBackend.h
|
src/base/kernel/interfaces/ILogBackend.h
|
||||||
|
@ -21,6 +22,7 @@ set(HEADERS_BASE
|
||||||
src/base/kernel/Signals.h
|
src/base/kernel/Signals.h
|
||||||
src/base/net/dns/Dns.h
|
src/base/net/dns/Dns.h
|
||||||
src/base/net/dns/DnsRecord.h
|
src/base/net/dns/DnsRecord.h
|
||||||
|
src/base/net/http/Http.h
|
||||||
src/base/net/stratum/Client.h
|
src/base/net/stratum/Client.h
|
||||||
src/base/net/stratum/Job.h
|
src/base/net/stratum/Job.h
|
||||||
src/base/net/stratum/Pool.h
|
src/base/net/stratum/Pool.h
|
||||||
|
@ -50,6 +52,7 @@ set(SOURCES_BASE
|
||||||
src/base/kernel/Signals.cpp
|
src/base/kernel/Signals.cpp
|
||||||
src/base/net/dns/Dns.cpp
|
src/base/net/dns/Dns.cpp
|
||||||
src/base/net/dns/DnsRecord.cpp
|
src/base/net/dns/DnsRecord.cpp
|
||||||
|
src/base/net/http/Http.cpp
|
||||||
src/base/net/stratum/Client.cpp
|
src/base/net/stratum/Client.cpp
|
||||||
src/base/net/stratum/Job.cpp
|
src/base/net/stratum/Job.cpp
|
||||||
src/base/net/stratum/Pool.cpp
|
src/base/net/stratum/Pool.cpp
|
||||||
|
@ -77,3 +80,37 @@ if (NOT WIN32)
|
||||||
set(SOURCES_SYSLOG src/base/io/log/backends/SysLog.h src/base/io/log/backends/SysLog.cpp)
|
set(SOURCES_SYSLOG src/base/io/log/backends/SysLog.h src/base/io/log/backends/SysLog.cpp)
|
||||||
endif()
|
endif()
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
|
||||||
|
if (WITH_HTTPD)
|
||||||
|
set(HEADERS_BASE_HTTP
|
||||||
|
src/3rdparty/http-parser/http_parser.h
|
||||||
|
src/base/kernel/interfaces/IHttpListener.h
|
||||||
|
src/base/kernel/interfaces/ITcpServerListener.h
|
||||||
|
src/base/net/http/HttpApiResponse.h
|
||||||
|
src/base/net/http/HttpContext.h
|
||||||
|
src/base/net/http/HttpRequest.h
|
||||||
|
src/base/net/http/HttpResponse.h
|
||||||
|
src/base/net/http/HttpServer.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/HttpContext.cpp
|
||||||
|
src/base/net/http/HttpResponse.cpp
|
||||||
|
src/base/net/http/HttpServer.cpp
|
||||||
|
src/base/net/tools/TcpServer.cpp
|
||||||
|
)
|
||||||
|
|
||||||
|
add_definitions(/DXMRIG_FEATURE_HTTP)
|
||||||
|
add_definitions(/DXMRIG_FEATURE_API)
|
||||||
|
else()
|
||||||
|
set(HEADERS_BASE_HTTP "")
|
||||||
|
set(SOURCES_BASE_HTTP "")
|
||||||
|
remove_definitions(/DXMRIG_FEATURE_HTTP)
|
||||||
|
remove_definitions(/DXMRIG_FEATURE_API)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
add_definitions(/DXMRIG_DEPRECATED)
|
||||||
|
|
|
@ -93,12 +93,12 @@ public:
|
||||||
timestamp(level, size, offset);
|
timestamp(level, size, offset);
|
||||||
color(level, size);
|
color(level, size);
|
||||||
|
|
||||||
int rc = vsnprintf(m_buf + size, sizeof (m_buf) - offset - 32, fmt, args);
|
const int rc = vsnprintf(m_buf + size, sizeof (m_buf) - offset - 32, fmt, args);
|
||||||
if (rc < 0) {
|
if (rc < 0) {
|
||||||
return unlock();
|
return unlock();
|
||||||
}
|
}
|
||||||
|
|
||||||
size += static_cast<size_t>(rc);
|
size += std::min(static_cast<size_t>(rc), sizeof (m_buf) - offset - 32);
|
||||||
endl(size);
|
endl(size);
|
||||||
|
|
||||||
std::string txt(m_buf);
|
std::string txt(m_buf);
|
||||||
|
|
|
@ -27,19 +27,14 @@
|
||||||
#include <uv.h>
|
#include <uv.h>
|
||||||
|
|
||||||
|
|
||||||
#ifndef XMRIG_NO_HTTPD
|
#ifdef XMRIG_FEATURE_TLS
|
||||||
# include <microhttpd.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
#ifndef XMRIG_NO_TLS
|
|
||||||
# include <openssl/opensslv.h>
|
# include <openssl/opensslv.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
#include "base/kernel/Entry.h"
|
#include "base/kernel/Entry.h"
|
||||||
#include "base/kernel/Process.h"
|
#include "base/kernel/Process.h"
|
||||||
#include "core/usage.h"
|
#include "core/config/usage.h"
|
||||||
#include "version.h"
|
#include "version.h"
|
||||||
|
|
||||||
|
|
||||||
|
@ -73,11 +68,7 @@ static int showVersion()
|
||||||
|
|
||||||
printf("\nlibuv/%s\n", uv_version_string());
|
printf("\nlibuv/%s\n", uv_version_string());
|
||||||
|
|
||||||
# ifndef XMRIG_NO_HTTPD
|
# if defined(XMRIG_FEATURE_TLS) && defined(OPENSSL_VERSION_TEXT)
|
||||||
printf("microhttpd/%s\n", MHD_get_version());
|
|
||||||
# endif
|
|
||||||
|
|
||||||
# if !defined(XMRIG_NO_TLS) && defined(OPENSSL_VERSION_TEXT)
|
|
||||||
{
|
{
|
||||||
constexpr const char *v = OPENSSL_VERSION_TEXT + 8;
|
constexpr const char *v = OPENSSL_VERSION_TEXT + 8;
|
||||||
printf("OpenSSL/%.*s\n", static_cast<int>(strchr(v, ' ') - v), v);
|
printf("OpenSSL/%.*s\n", static_cast<int>(strchr(v, ' ') - v), v);
|
||||||
|
|
|
@ -22,26 +22,27 @@
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef XMRIG_ICONFIGCREATOR_H
|
#ifndef XMRIG_IHTTPLISTENER_H
|
||||||
#define XMRIG_ICONFIGCREATOR_H
|
#define XMRIG_IHTTPLISTENER_H
|
||||||
|
|
||||||
|
|
||||||
namespace xmrig {
|
namespace xmrig {
|
||||||
|
|
||||||
|
|
||||||
class IConfig;
|
class HttpRequest;
|
||||||
|
class HttpResponse;
|
||||||
|
|
||||||
|
|
||||||
class IConfigCreator
|
class IHttpListener
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
virtual ~IConfigCreator() = default;
|
virtual ~IHttpListener() = default;
|
||||||
|
|
||||||
virtual IConfig *create() const = 0;
|
virtual void onHttpRequest(const HttpRequest &req) = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
} /* namespace xmrig */
|
} /* namespace xmrig */
|
||||||
|
|
||||||
|
|
||||||
#endif // XMRIG_ICONFIGCREATOR_H
|
#endif // XMRIG_IHTTPLISTENER_H
|
|
@ -5,8 +5,8 @@
|
||||||
* Copyright 2014-2016 Wolf9466 <https://github.com/OhGodAPet>
|
* Copyright 2014-2016 Wolf9466 <https://github.com/OhGodAPet>
|
||||||
* Copyright 2016 Jay D Dee <jayddee246@gmail.com>
|
* Copyright 2016 Jay D Dee <jayddee246@gmail.com>
|
||||||
* Copyright 2017-2018 XMR-Stak <https://github.com/fireice-uk>, <https://github.com/psychocrypt>
|
* 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
|
* 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
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
@ -22,48 +22,32 @@
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef __HTTPBODY_H__
|
#ifndef XMRIG_ITCPSERVERLISTENER_H
|
||||||
#define __HTTPBODY_H__
|
#define XMRIG_ITCPSERVERLISTENER_H
|
||||||
|
|
||||||
|
|
||||||
#include <string.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
|
|
||||||
|
typedef struct uv_stream_s uv_stream_t;
|
||||||
|
|
||||||
|
|
||||||
namespace xmrig {
|
namespace xmrig {
|
||||||
|
|
||||||
|
|
||||||
class HttpBody
|
class String;
|
||||||
|
|
||||||
|
|
||||||
|
class ITcpServerListener
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
inline HttpBody() :
|
virtual ~ITcpServerListener() = default;
|
||||||
m_pos(0)
|
|
||||||
{}
|
|
||||||
|
|
||||||
|
virtual void onConnection(uv_stream_t *stream, uint16_t port) = 0;
|
||||||
inline bool write(const char *data, size_t size)
|
|
||||||
{
|
|
||||||
if (size > (sizeof(m_data) - m_pos - 1)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
memcpy(m_data + m_pos, data, size);
|
|
||||||
|
|
||||||
m_pos += size;
|
|
||||||
m_data[m_pos] = '\0';
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
inline const char *data() const { return m_data; }
|
|
||||||
|
|
||||||
private:
|
|
||||||
char m_data[32768];
|
|
||||||
size_t m_pos;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
} /* namespace xmrig */
|
} /* namespace xmrig */
|
||||||
|
|
||||||
|
|
||||||
#endif /* __HTTPBODY_H__ */
|
#endif // XMRIG_ITCPSERVERLISTENER_H
|
99
src/base/net/http/Http.cpp
Normal file
99
src/base/net/http/Http.cpp
Normal 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.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
73
src/base/net/http/Http.h
Normal file
|
@ -0,0 +1,73 @@
|
||||||
|
/* XMRig
|
||||||
|
* Copyright 2010 Jeff Garzik <jgarzik@pobox.com>
|
||||||
|
* Copyright 2012-2014 pooler <pooler@litecoinpool.org>
|
||||||
|
* Copyright 2014 Lucas Jones <https://github.com/lucasjones>
|
||||||
|
* Copyright 2014-2016 Wolf9466 <https://github.com/OhGodAPet>
|
||||||
|
* Copyright 2016 Jay D Dee <jayddee246@gmail.com>
|
||||||
|
* Copyright 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
|
||||||
|
|
86
src/base/net/http/HttpApiResponse.cpp
Normal file
86
src/base/net/http/HttpApiResponse.cpp
Normal 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());
|
||||||
|
}
|
57
src/base/net/http/HttpApiResponse.h
Normal file
57
src/base/net/http/HttpApiResponse.h
Normal 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
|
||||||
|
|
193
src/base/net/http/HttpContext.cpp
Normal file
193
src/base/net/http/HttpContext.cpp
Normal 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 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 uint64_t SEQUENCE = 0;
|
||||||
|
std::map<uint64_t, HttpContext *> HttpContext::m_storage;
|
||||||
|
|
||||||
|
} // namespace xmrig
|
||||||
|
|
||||||
|
|
||||||
|
xmrig::HttpContext::HttpContext(int parser_type, IHttpListener *listener) :
|
||||||
|
HttpRequest(SEQUENCE++),
|
||||||
|
listener(listener),
|
||||||
|
connect(nullptr),
|
||||||
|
m_wasHeaderValue(false)
|
||||||
|
{
|
||||||
|
m_storage[id()] = this;
|
||||||
|
|
||||||
|
parser = new http_parser;
|
||||||
|
tcp = new uv_tcp_t;
|
||||||
|
|
||||||
|
uv_tcp_init(uv_default_loop(), tcp);
|
||||||
|
http_parser_init(parser, static_cast<http_parser_type>(parser_type));
|
||||||
|
|
||||||
|
parser->data = tcp->data = this;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
xmrig::HttpContext::~HttpContext()
|
||||||
|
{
|
||||||
|
delete connect;
|
||||||
|
delete tcp;
|
||||||
|
delete parser;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void xmrig::HttpContext::close()
|
||||||
|
{
|
||||||
|
auto it = m_storage.find(id());
|
||||||
|
if (it != m_storage.end()) {
|
||||||
|
m_storage.erase(it);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!uv_is_closing(handle())) {
|
||||||
|
uv_close(handle(), [](uv_handle_t *handle) -> void { delete reinterpret_cast<HttpContext*>(handle->data); });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
xmrig::HttpContext *xmrig::HttpContext::get(uint64_t id)
|
||||||
|
{
|
||||||
|
if (m_storage.count(id) == 0) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
return m_storage[id];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void xmrig::HttpContext::attach(http_parser_settings *settings)
|
||||||
|
{
|
||||||
|
if (settings->on_message_complete != nullptr) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
settings->on_message_begin = nullptr;
|
||||||
|
settings->on_status = nullptr;
|
||||||
|
settings->on_chunk_header = nullptr;
|
||||||
|
settings->on_chunk_complete = nullptr;
|
||||||
|
|
||||||
|
settings->on_url = [](http_parser *parser, const char *at, size_t length) -> int
|
||||||
|
{
|
||||||
|
static_cast<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->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
|
||||||
|
{
|
||||||
|
const HttpContext *ctx = reinterpret_cast<const HttpContext*>(parser->data);
|
||||||
|
ctx->listener->onHttpRequest(*ctx);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void xmrig::HttpContext::closeAll()
|
||||||
|
{
|
||||||
|
for (auto kv : m_storage) {
|
||||||
|
if (!uv_is_closing(kv.second->handle())) {
|
||||||
|
uv_close(kv.second->handle(), [](uv_handle_t *handle) -> void { delete reinterpret_cast<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::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();
|
||||||
|
}
|
||||||
|
|
86
src/base/net/http/HttpContext.h
Normal file
86
src/base/net/http/HttpContext.h
Normal 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/HttpRequest.h"
|
||||||
|
|
||||||
|
|
||||||
|
namespace xmrig {
|
||||||
|
|
||||||
|
|
||||||
|
class IHttpListener;
|
||||||
|
|
||||||
|
|
||||||
|
class HttpContext : public HttpRequest
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
HttpContext(int parser_type, IHttpListener *listener);
|
||||||
|
~HttpContext();
|
||||||
|
|
||||||
|
inline uv_stream_t *stream() const { return reinterpret_cast<uv_stream_t *>(tcp); }
|
||||||
|
inline uv_handle_t *handle() const { return reinterpret_cast<uv_handle_t *>(tcp); }
|
||||||
|
|
||||||
|
void close();
|
||||||
|
|
||||||
|
static HttpContext *get(uint64_t id);
|
||||||
|
static void attach(http_parser_settings *settings);
|
||||||
|
static void closeAll();
|
||||||
|
|
||||||
|
http_parser *parser;
|
||||||
|
IHttpListener *listener;
|
||||||
|
uv_connect_t *connect;
|
||||||
|
uv_tcp_t *tcp;
|
||||||
|
|
||||||
|
private:
|
||||||
|
static int onHeaderField(http_parser *parser, const char *at, size_t length);
|
||||||
|
static int onHeaderValue(http_parser *parser, const char *at, size_t length);
|
||||||
|
|
||||||
|
void setHeader();
|
||||||
|
|
||||||
|
bool m_wasHeaderValue;
|
||||||
|
std::string m_lastHeaderField;
|
||||||
|
std::string m_lastHeaderValue;
|
||||||
|
|
||||||
|
static std::map<uint64_t, HttpContext *> m_storage;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
} // namespace xmrig
|
||||||
|
|
||||||
|
|
||||||
|
#endif // XMRIG_HTTPCONTEXT_H
|
||||||
|
|
60
src/base/net/http/HttpRequest.h
Normal file
60
src/base/net/http/HttpRequest.h
Normal 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_HTTPREQUEST_H
|
||||||
|
#define XMRIG_HTTPREQUEST_H
|
||||||
|
|
||||||
|
|
||||||
|
#include <map>
|
||||||
|
#include <sstream>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
|
||||||
|
namespace xmrig {
|
||||||
|
|
||||||
|
|
||||||
|
class HttpRequest
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
inline HttpRequest(uint64_t id) : method(0), m_id(id) {}
|
||||||
|
|
||||||
|
inline uint64_t id() const { return m_id; }
|
||||||
|
|
||||||
|
int method;
|
||||||
|
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_HTTPREQUEST_H
|
||||||
|
|
108
src/base/net/http/HttpResponse.cpp
Normal file
108
src/base/net/http/HttpResponse.cpp
Normal file
|
@ -0,0 +1,108 @@
|
||||||
|
/* 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/net/http/HttpContext.h"
|
||||||
|
#include "base/net/http/HttpResponse.h"
|
||||||
|
|
||||||
|
|
||||||
|
namespace xmrig {
|
||||||
|
|
||||||
|
static const char *kCRLF = "\r\n";
|
||||||
|
|
||||||
|
} // namespace xmrig
|
||||||
|
|
||||||
|
|
||||||
|
xmrig::HttpResponse::HttpResponse(uint64_t id) :
|
||||||
|
m_id(id),
|
||||||
|
m_statusCode(HTTP_STATUS_OK)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
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;
|
||||||
|
const std::string header = ss.str();
|
||||||
|
|
||||||
|
uv_buf_t bufs[2];
|
||||||
|
bufs[0].base = const_cast<char *>(header.c_str());
|
||||||
|
|
||||||
|
# ifdef _WIN32
|
||||||
|
bufs[0].len = static_cast<unsigned int>(header.size());
|
||||||
|
# else
|
||||||
|
bufs[0].len = header.size();
|
||||||
|
# endif
|
||||||
|
|
||||||
|
if (data) {
|
||||||
|
bufs[1].base = const_cast<char *>(data);
|
||||||
|
|
||||||
|
# ifdef _WIN32
|
||||||
|
bufs[1].len = static_cast<unsigned int>(size);
|
||||||
|
# else
|
||||||
|
bufs[0].len = size;
|
||||||
|
# endif
|
||||||
|
}
|
||||||
|
|
||||||
|
HttpContext *ctx = HttpContext::get(m_id);
|
||||||
|
uv_try_write(ctx->stream(), bufs, data ? 2 : 1);
|
||||||
|
|
||||||
|
ctx->close();
|
||||||
|
}
|
61
src/base/net/http/HttpResponse.h
Normal file
61
src/base/net/http/HttpResponse.h
Normal 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);
|
||||||
|
|
||||||
|
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
|
||||||
|
|
91
src/base/net/http/HttpServer.cpp
Normal file
91
src/base/net/http/HttpServer.cpp
Normal file
|
@ -0,0 +1,91 @@
|
||||||
|
/* 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"
|
||||||
|
|
||||||
|
|
||||||
|
namespace xmrig {
|
||||||
|
|
||||||
|
static http_parser_settings http_settings;
|
||||||
|
|
||||||
|
} // namespace xmrig
|
||||||
|
|
||||||
|
|
||||||
|
xmrig::HttpServer::HttpServer(IHttpListener *listener) :
|
||||||
|
m_listener(listener)
|
||||||
|
{
|
||||||
|
HttpContext::attach(&http_settings);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
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 = http_parser_execute(ctx->parser, &http_settings, buf->base, size);
|
||||||
|
|
||||||
|
if (parsed < size) {
|
||||||
|
ctx->close();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
ctx->close();
|
||||||
|
}
|
||||||
|
|
||||||
|
delete [] buf->base;
|
||||||
|
});
|
||||||
|
}
|
62
src/base/net/http/HttpServer.h
Normal file
62
src/base/net/http/HttpServer.h
Normal file
|
@ -0,0 +1,62 @@
|
||||||
|
/* XMRig
|
||||||
|
* Copyright 2010 Jeff Garzik <jgarzik@pobox.com>
|
||||||
|
* Copyright 2012-2014 pooler <pooler@litecoinpool.org>
|
||||||
|
* Copyright 2014 Lucas Jones <https://github.com/lucasjones>
|
||||||
|
* Copyright 2014-2016 Wolf9466 <https://github.com/OhGodAPet>
|
||||||
|
* Copyright 2016 Jay D Dee <jayddee246@gmail.com>
|
||||||
|
* Copyright 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
|
||||||
|
|
|
@ -30,7 +30,7 @@
|
||||||
#include <utility>
|
#include <utility>
|
||||||
|
|
||||||
|
|
||||||
#ifndef XMRIG_NO_TLS
|
#ifdef XMRIG_FEATURE_TLS
|
||||||
# include <openssl/ssl.h>
|
# include <openssl/ssl.h>
|
||||||
# include <openssl/err.h>
|
# include <openssl/err.h>
|
||||||
# include "base/net/stratum/Tls.h"
|
# include "base/net/stratum/Tls.h"
|
||||||
|
@ -107,7 +107,7 @@ xmrig::Client::~Client()
|
||||||
|
|
||||||
void xmrig::Client::connect()
|
void xmrig::Client::connect()
|
||||||
{
|
{
|
||||||
# ifndef XMRIG_NO_TLS
|
# ifdef XMRIG_FEATURE_TLS
|
||||||
if (m_pool.isTLS()) {
|
if (m_pool.isTLS()) {
|
||||||
m_tls = new Tls(this);
|
m_tls = new Tls(this);
|
||||||
}
|
}
|
||||||
|
@ -184,7 +184,7 @@ bool xmrig::Client::disconnect()
|
||||||
|
|
||||||
bool xmrig::Client::isTLS() const
|
bool xmrig::Client::isTLS() const
|
||||||
{
|
{
|
||||||
# ifndef XMRIG_NO_TLS
|
# ifdef XMRIG_FEATURE_TLS
|
||||||
return m_pool.isTLS() && m_tls;
|
return m_pool.isTLS() && m_tls;
|
||||||
# else
|
# else
|
||||||
return false;
|
return false;
|
||||||
|
@ -194,7 +194,7 @@ bool xmrig::Client::isTLS() const
|
||||||
|
|
||||||
const char *xmrig::Client::tlsFingerprint() const
|
const char *xmrig::Client::tlsFingerprint() const
|
||||||
{
|
{
|
||||||
# ifndef XMRIG_NO_TLS
|
# ifdef XMRIG_FEATURE_TLS
|
||||||
if (isTLS() && m_pool.fingerprint() == nullptr) {
|
if (isTLS() && m_pool.fingerprint() == nullptr) {
|
||||||
return m_tls->fingerprint();
|
return m_tls->fingerprint();
|
||||||
}
|
}
|
||||||
|
@ -206,7 +206,7 @@ const char *xmrig::Client::tlsFingerprint() const
|
||||||
|
|
||||||
const char *xmrig::Client::tlsVersion() const
|
const char *xmrig::Client::tlsVersion() const
|
||||||
{
|
{
|
||||||
# ifndef XMRIG_NO_TLS
|
# ifdef XMRIG_FEATURE_TLS
|
||||||
if (isTLS()) {
|
if (isTLS()) {
|
||||||
return m_tls->version();
|
return m_tls->version();
|
||||||
}
|
}
|
||||||
|
@ -435,7 +435,7 @@ bool xmrig::Client::parseLogin(const rapidjson::Value &result, int *code)
|
||||||
|
|
||||||
bool xmrig::Client::send(BIO *bio)
|
bool xmrig::Client::send(BIO *bio)
|
||||||
{
|
{
|
||||||
# ifndef XMRIG_NO_TLS
|
# ifdef XMRIG_FEATURE_TLS
|
||||||
uv_buf_t buf;
|
uv_buf_t buf;
|
||||||
buf.len = BIO_get_mem_data(bio, &buf.base);
|
buf.len = BIO_get_mem_data(bio, &buf.base);
|
||||||
|
|
||||||
|
@ -543,7 +543,7 @@ int64_t xmrig::Client::send(size_t size)
|
||||||
{
|
{
|
||||||
LOG_DEBUG("[%s] send (%d bytes): \"%s\"", url(), size, m_sendBuf);
|
LOG_DEBUG("[%s] send (%d bytes): \"%s\"", url(), size, m_sendBuf);
|
||||||
|
|
||||||
# ifndef XMRIG_NO_TLS
|
# ifdef XMRIG_FEATURE_TLS
|
||||||
if (isTLS()) {
|
if (isTLS()) {
|
||||||
if (!m_tls->send(m_sendBuf, size)) {
|
if (!m_tls->send(m_sendBuf, size)) {
|
||||||
return -1;
|
return -1;
|
||||||
|
@ -597,7 +597,7 @@ void xmrig::Client::connect(sockaddr *addr)
|
||||||
|
|
||||||
void xmrig::Client::handshake()
|
void xmrig::Client::handshake()
|
||||||
{
|
{
|
||||||
# ifndef XMRIG_NO_TLS
|
# ifdef XMRIG_FEATURE_TLS
|
||||||
if (isTLS()) {
|
if (isTLS()) {
|
||||||
m_expire = Chrono::steadyMSecs() + kResponseTimeout;
|
m_expire = Chrono::steadyMSecs() + kResponseTimeout;
|
||||||
|
|
||||||
|
@ -661,7 +661,7 @@ void xmrig::Client::onClose()
|
||||||
m_socket = nullptr;
|
m_socket = nullptr;
|
||||||
setState(UnconnectedState);
|
setState(UnconnectedState);
|
||||||
|
|
||||||
# ifndef XMRIG_NO_TLS
|
# ifdef XMRIG_FEATURE_TLS
|
||||||
if (m_tls) {
|
if (m_tls) {
|
||||||
delete m_tls;
|
delete m_tls;
|
||||||
m_tls = nullptr;
|
m_tls = nullptr;
|
||||||
|
@ -858,7 +858,7 @@ void xmrig::Client::read(ssize_t nread)
|
||||||
|
|
||||||
m_recvBuf.nread(size);
|
m_recvBuf.nread(size);
|
||||||
|
|
||||||
# ifndef XMRIG_NO_TLS
|
# ifdef XMRIG_FEATURE_TLS
|
||||||
if (isTLS()) {
|
if (isTLS()) {
|
||||||
LOG_DEBUG("[%s] TLS received (%d bytes)", url(), static_cast<int>(nread));
|
LOG_DEBUG("[%s] TLS received (%d bytes)", url(), static_cast<int>(nread));
|
||||||
|
|
||||||
|
|
|
@ -75,7 +75,7 @@ public:
|
||||||
|
|
||||||
constexpr static int kResponseTimeout = 20 * 1000;
|
constexpr static int kResponseTimeout = 20 * 1000;
|
||||||
|
|
||||||
# ifndef XMRIG_NO_TLS
|
# ifdef XMRIG_FEATURE_TLS
|
||||||
constexpr static int kInputBufferSize = 1024 * 16;
|
constexpr static int kInputBufferSize = 1024 * 16;
|
||||||
# else
|
# else
|
||||||
constexpr static int kInputBufferSize = 1024 * 2;
|
constexpr static int kInputBufferSize = 1024 * 2;
|
||||||
|
|
|
@ -178,7 +178,7 @@ bool xmrig::Pool::isCompatible(const Algorithm &algorithm) const
|
||||||
|
|
||||||
bool xmrig::Pool::isEnabled() const
|
bool xmrig::Pool::isEnabled() const
|
||||||
{
|
{
|
||||||
# ifdef XMRIG_NO_TLS
|
# ifndef XMRIG_FEATURE_TLS
|
||||||
if (isTLS()) {
|
if (isTLS()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
102
src/base/net/tools/TcpServer.cpp
Normal file
102
src/base/net/tools/TcpServer.cpp
Normal file
|
@ -0,0 +1,102 @@
|
||||||
|
/* 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/ITcpServerListener.h"
|
||||||
|
#include "base/net/tools/TcpServer.h"
|
||||||
|
#include "base/tools/Handle.h"
|
||||||
|
#include "base/tools/String.h"
|
||||||
|
|
||||||
|
|
||||||
|
static const xmrig::String kLocalHost("127.0.0.1");
|
||||||
|
|
||||||
|
|
||||||
|
xmrig::TcpServer::TcpServer(const String &host, uint16_t port, ITcpServerListener *listener) :
|
||||||
|
m_host(host.isNull() ? kLocalHost : host),
|
||||||
|
m_version(0),
|
||||||
|
m_listener(listener),
|
||||||
|
m_addr(),
|
||||||
|
m_port(port)
|
||||||
|
{
|
||||||
|
m_tcp = new uv_tcp_t;
|
||||||
|
uv_tcp_init(uv_default_loop(), m_tcp);
|
||||||
|
m_tcp->data = this;
|
||||||
|
|
||||||
|
uv_tcp_nodelay(m_tcp, 1);
|
||||||
|
|
||||||
|
if (m_host.contains(":") && uv_ip6_addr(m_host.data(), m_port, reinterpret_cast<sockaddr_in6 *>(&m_addr)) == 0) {
|
||||||
|
m_version = 6;
|
||||||
|
}
|
||||||
|
else if (uv_ip4_addr(m_host.data(), m_port, reinterpret_cast<sockaddr_in *>(&m_addr)) == 0) {
|
||||||
|
m_version = 4;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
xmrig::TcpServer::~TcpServer()
|
||||||
|
{
|
||||||
|
Handle::close(m_tcp);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int xmrig::TcpServer::bind()
|
||||||
|
{
|
||||||
|
if (!m_version) {
|
||||||
|
return UV_EAI_ADDRFAMILY;
|
||||||
|
}
|
||||||
|
|
||||||
|
uv_tcp_bind(m_tcp, reinterpret_cast<const sockaddr*>(&m_addr), 0);
|
||||||
|
|
||||||
|
const int rc = uv_listen(reinterpret_cast<uv_stream_t*>(m_tcp), 511, TcpServer::onConnection);
|
||||||
|
if (rc != 0) {
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!m_port) {
|
||||||
|
sockaddr_storage storage = {};
|
||||||
|
int size = sizeof(storage);
|
||||||
|
|
||||||
|
uv_tcp_getsockname(m_tcp, reinterpret_cast<sockaddr*>(&storage), &size);
|
||||||
|
|
||||||
|
m_port = ntohs(reinterpret_cast<sockaddr_in *>(&storage)->sin_port);
|
||||||
|
}
|
||||||
|
|
||||||
|
return m_port;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void xmrig::TcpServer::create(uv_stream_t *stream, int status)
|
||||||
|
{
|
||||||
|
if (status < 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_listener->onConnection(stream, m_port);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void xmrig::TcpServer::onConnection(uv_stream_t *stream, int status)
|
||||||
|
{
|
||||||
|
static_cast<TcpServer *>(stream->data)->create(stream, status);
|
||||||
|
}
|
64
src/base/net/tools/TcpServer.h
Normal file
64
src/base/net/tools/TcpServer.h
Normal file
|
@ -0,0 +1,64 @@
|
||||||
|
/* 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_TCPSERVER_H
|
||||||
|
#define XMRIG_TCPSERVER_H
|
||||||
|
|
||||||
|
|
||||||
|
#include <uv.h>
|
||||||
|
|
||||||
|
|
||||||
|
namespace xmrig {
|
||||||
|
|
||||||
|
|
||||||
|
class ITcpServerListener;
|
||||||
|
class String;
|
||||||
|
|
||||||
|
|
||||||
|
class TcpServer
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
TcpServer(const String &host, uint16_t port, ITcpServerListener *listener);
|
||||||
|
~TcpServer();
|
||||||
|
|
||||||
|
int bind();
|
||||||
|
|
||||||
|
private:
|
||||||
|
void create(uv_stream_t *stream, int status);
|
||||||
|
|
||||||
|
static void onConnection(uv_stream_t *stream, int status);
|
||||||
|
|
||||||
|
const String &m_host;
|
||||||
|
int m_version;
|
||||||
|
ITcpServerListener *m_listener;
|
||||||
|
sockaddr_storage m_addr;
|
||||||
|
uint16_t m_port;
|
||||||
|
uv_tcp_t *m_tcp;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
} /* namespace xmrig */
|
||||||
|
|
||||||
|
|
||||||
|
#endif /* XMRIG_TCPSERVER_H */
|
|
@ -27,7 +27,7 @@
|
||||||
#include <uv.h>
|
#include <uv.h>
|
||||||
|
|
||||||
|
|
||||||
#ifndef XMRIG_NO_TLS
|
#ifdef XMRIG_FEATURE_TLS
|
||||||
# include <openssl/ssl.h>
|
# include <openssl/ssl.h>
|
||||||
# include <openssl/err.h>
|
# include <openssl/err.h>
|
||||||
#endif
|
#endif
|
||||||
|
@ -41,7 +41,7 @@ xmrig::String Platform::m_userAgent;
|
||||||
|
|
||||||
void Platform::init(const char *userAgent)
|
void Platform::init(const char *userAgent)
|
||||||
{
|
{
|
||||||
# ifndef XMRIG_NO_TLS
|
# ifdef XMRIG_FEATURE_TLS
|
||||||
SSL_library_init();
|
SSL_library_init();
|
||||||
SSL_load_error_strings();
|
SSL_load_error_strings();
|
||||||
ERR_load_BIO_strings();
|
ERR_load_BIO_strings();
|
||||||
|
|
|
@ -1,175 +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 2016-2018 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 <microhttpd.h>
|
|
||||||
#include <string.h>
|
|
||||||
|
|
||||||
#include "common/api/HttpBody.h"
|
|
||||||
#include "common/api/HttpRequest.h"
|
|
||||||
#include "common/api/HttpReply.h"
|
|
||||||
|
|
||||||
|
|
||||||
#ifndef MHD_HTTP_PAYLOAD_TOO_LARGE
|
|
||||||
# define MHD_HTTP_PAYLOAD_TOO_LARGE 413
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
xmrig::HttpRequest::HttpRequest(MHD_Connection *connection, const char *url, const char *method, const char *uploadData, size_t *uploadSize, void **cls) :
|
|
||||||
m_fulfilled(true),
|
|
||||||
m_restricted(true),
|
|
||||||
m_uploadData(uploadData),
|
|
||||||
m_url(url),
|
|
||||||
m_body(static_cast<HttpBody*>(*cls)),
|
|
||||||
m_method(Unsupported),
|
|
||||||
m_connection(connection),
|
|
||||||
m_uploadSize(uploadSize),
|
|
||||||
m_cls(cls)
|
|
||||||
{
|
|
||||||
if (strcmp(method, MHD_HTTP_METHOD_OPTIONS) == 0) {
|
|
||||||
m_method = Options;
|
|
||||||
}
|
|
||||||
else if (strcmp(method, MHD_HTTP_METHOD_GET) == 0) {
|
|
||||||
m_method = Get;
|
|
||||||
}
|
|
||||||
else if (strcmp(method, MHD_HTTP_METHOD_PUT) == 0) {
|
|
||||||
m_method = Put;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
xmrig::HttpRequest::~HttpRequest()
|
|
||||||
{
|
|
||||||
if (m_fulfilled) {
|
|
||||||
delete m_body;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
bool xmrig::HttpRequest::match(const char *path) const
|
|
||||||
{
|
|
||||||
return strcmp(m_url, path) == 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
bool xmrig::HttpRequest::process(const char *accessToken, bool restricted, xmrig::HttpReply &reply)
|
|
||||||
{
|
|
||||||
m_restricted = restricted || !accessToken;
|
|
||||||
|
|
||||||
if (m_body) {
|
|
||||||
if (*m_uploadSize != 0) {
|
|
||||||
if (!m_body->write(m_uploadData, *m_uploadSize)) {
|
|
||||||
*m_cls = nullptr;
|
|
||||||
m_fulfilled = true;
|
|
||||||
reply.status = MHD_HTTP_PAYLOAD_TOO_LARGE;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
*m_uploadSize = 0;
|
|
||||||
m_fulfilled = false;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
m_fulfilled = true;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
reply.status = auth(accessToken);
|
|
||||||
if (reply.status != MHD_HTTP_OK) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (m_restricted && m_method != Get) {
|
|
||||||
reply.status = MHD_HTTP_FORBIDDEN;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (m_method == Get) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
const char *contentType = MHD_lookup_connection_value(m_connection, MHD_HEADER_KIND, "Content-Type");
|
|
||||||
if (!contentType || strcmp(contentType, "application/json") != 0) {
|
|
||||||
reply.status = MHD_HTTP_UNSUPPORTED_MEDIA_TYPE;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
m_body = new xmrig::HttpBody();
|
|
||||||
m_fulfilled = false;
|
|
||||||
*m_cls = m_body;
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
const char *xmrig::HttpRequest::body() const
|
|
||||||
{
|
|
||||||
return m_body ? m_body->data() : nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
int xmrig::HttpRequest::end(const HttpReply &reply)
|
|
||||||
{
|
|
||||||
if (reply.buf) {
|
|
||||||
return end(reply.status, MHD_create_response_from_buffer(reply.size ? reply.size : strlen(reply.buf), (void*) reply.buf, MHD_RESPMEM_MUST_FREE));
|
|
||||||
}
|
|
||||||
|
|
||||||
return end(reply.status, nullptr);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
int xmrig::HttpRequest::end(int status, MHD_Response *rsp)
|
|
||||||
{
|
|
||||||
if (!rsp) {
|
|
||||||
rsp = MHD_create_response_from_buffer(0, nullptr, MHD_RESPMEM_PERSISTENT);
|
|
||||||
}
|
|
||||||
|
|
||||||
MHD_add_response_header(rsp, "Content-Type", "application/json");
|
|
||||||
MHD_add_response_header(rsp, "Access-Control-Allow-Origin", "*");
|
|
||||||
MHD_add_response_header(rsp, "Access-Control-Allow-Methods", "GET, PUT");
|
|
||||||
MHD_add_response_header(rsp, "Access-Control-Allow-Headers", "Authorization, Content-Type");
|
|
||||||
|
|
||||||
const int ret = MHD_queue_response(m_connection, status, rsp);
|
|
||||||
MHD_destroy_response(rsp);
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
int xmrig::HttpRequest::auth(const char *accessToken)
|
|
||||||
{
|
|
||||||
if (!accessToken) {
|
|
||||||
return MHD_HTTP_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
const char *header = MHD_lookup_connection_value(m_connection, MHD_HEADER_KIND, "Authorization");
|
|
||||||
if (accessToken && !header) {
|
|
||||||
return MHD_HTTP_UNAUTHORIZED;
|
|
||||||
}
|
|
||||||
|
|
||||||
const size_t size = strlen(header);
|
|
||||||
if (size < 8 || strlen(accessToken) != size - 7 || memcmp("Bearer ", header, 7) != 0) {
|
|
||||||
return MHD_HTTP_FORBIDDEN;
|
|
||||||
}
|
|
||||||
|
|
||||||
return strncmp(accessToken, header + 7, strlen(accessToken)) == 0 ? MHD_HTTP_OK : MHD_HTTP_FORBIDDEN;
|
|
||||||
}
|
|
|
@ -1,84 +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 2016-2018 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 __HTTPREQUEST_H__
|
|
||||||
#define __HTTPREQUEST_H__
|
|
||||||
|
|
||||||
|
|
||||||
#include <stdint.h>
|
|
||||||
|
|
||||||
|
|
||||||
struct MHD_Connection;
|
|
||||||
struct MHD_Response;
|
|
||||||
|
|
||||||
|
|
||||||
namespace xmrig {
|
|
||||||
|
|
||||||
|
|
||||||
class HttpBody;
|
|
||||||
class HttpReply;
|
|
||||||
|
|
||||||
|
|
||||||
class HttpRequest
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
enum Method {
|
|
||||||
Unsupported,
|
|
||||||
Options,
|
|
||||||
Get,
|
|
||||||
Put
|
|
||||||
};
|
|
||||||
|
|
||||||
HttpRequest(MHD_Connection *connection, const char *url, const char *method, const char *uploadData, size_t *uploadSize, void **cls);
|
|
||||||
~HttpRequest();
|
|
||||||
|
|
||||||
inline bool isFulfilled() const { return m_fulfilled; }
|
|
||||||
inline bool isRestricted() const { return m_restricted; }
|
|
||||||
inline Method method() const { return m_method; }
|
|
||||||
|
|
||||||
bool match(const char *path) const;
|
|
||||||
bool process(const char *accessToken, bool restricted, xmrig::HttpReply &reply);
|
|
||||||
const char *body() const;
|
|
||||||
int end(const HttpReply &reply);
|
|
||||||
int end(int status, MHD_Response *rsp);
|
|
||||||
|
|
||||||
private:
|
|
||||||
int auth(const char *accessToken);
|
|
||||||
|
|
||||||
bool m_fulfilled;
|
|
||||||
bool m_restricted;
|
|
||||||
const char *m_uploadData;
|
|
||||||
const char *m_url;
|
|
||||||
HttpBody *m_body;
|
|
||||||
Method m_method;
|
|
||||||
MHD_Connection *m_connection;
|
|
||||||
size_t *m_uploadSize;
|
|
||||||
void **m_cls;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
} /* namespace xmrig */
|
|
||||||
|
|
||||||
|
|
||||||
#endif /* __HTTPREQUEST_H__ */
|
|
|
@ -1,151 +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 <microhttpd.h>
|
|
||||||
#include <string.h>
|
|
||||||
|
|
||||||
|
|
||||||
#include "api/Api.h"
|
|
||||||
#include "base/io/log/Log.h"
|
|
||||||
#include "base/tools/Handle.h"
|
|
||||||
#include "base/tools/Timer.h"
|
|
||||||
#include "common/api/Httpd.h"
|
|
||||||
#include "common/api/HttpReply.h"
|
|
||||||
#include "common/api/HttpRequest.h"
|
|
||||||
|
|
||||||
|
|
||||||
xmrig::Httpd::Httpd(int port, const char *accessToken, bool IPv6, bool restricted) :
|
|
||||||
m_idle(true),
|
|
||||||
m_IPv6(IPv6),
|
|
||||||
m_restricted(restricted),
|
|
||||||
m_accessToken(accessToken ? strdup(accessToken) : nullptr),
|
|
||||||
m_port(port),
|
|
||||||
m_daemon(nullptr)
|
|
||||||
{
|
|
||||||
m_timer = new Timer(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
xmrig::Httpd::~Httpd()
|
|
||||||
{
|
|
||||||
stop();
|
|
||||||
|
|
||||||
if (m_daemon) {
|
|
||||||
MHD_stop_daemon(m_daemon);
|
|
||||||
}
|
|
||||||
|
|
||||||
delete m_accessToken;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
bool xmrig::Httpd::start()
|
|
||||||
{
|
|
||||||
if (!m_port) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned int flags = 0;
|
|
||||||
# if MHD_VERSION >= 0x00093500
|
|
||||||
if (m_IPv6 && MHD_is_feature_supported(MHD_FEATURE_IPv6)) {
|
|
||||||
flags |= MHD_USE_DUAL_STACK;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (MHD_is_feature_supported(MHD_FEATURE_EPOLL)) {
|
|
||||||
flags |= MHD_USE_EPOLL_LINUX_ONLY;
|
|
||||||
}
|
|
||||||
# endif
|
|
||||||
|
|
||||||
m_daemon = MHD_start_daemon(flags, m_port, nullptr, nullptr, &Httpd::handler, this, MHD_OPTION_END);
|
|
||||||
if (!m_daemon) {
|
|
||||||
LOG_ERR("HTTP Daemon failed to start.");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
# if MHD_VERSION >= 0x00093900
|
|
||||||
m_timer->start(kIdleInterval, kIdleInterval);
|
|
||||||
# else
|
|
||||||
m_timer->start(kActiveInterval, kActiveInterval);
|
|
||||||
# endif
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void xmrig::Httpd::stop()
|
|
||||||
{
|
|
||||||
delete m_timer;
|
|
||||||
m_timer = nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
int xmrig::Httpd::process(HttpRequest &req)
|
|
||||||
{
|
|
||||||
xmrig::HttpReply reply;
|
|
||||||
if (!req.process(m_accessToken, m_restricted, reply)) {
|
|
||||||
return req.end(reply);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!req.isFulfilled()) {
|
|
||||||
return MHD_YES;
|
|
||||||
}
|
|
||||||
|
|
||||||
Api::exec(req, reply);
|
|
||||||
|
|
||||||
return req.end(reply);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void xmrig::Httpd::run()
|
|
||||||
{
|
|
||||||
MHD_run(m_daemon);
|
|
||||||
|
|
||||||
# if MHD_VERSION >= 0x00093900
|
|
||||||
const MHD_DaemonInfo *info = MHD_get_daemon_info(m_daemon, MHD_DAEMON_INFO_CURRENT_CONNECTIONS);
|
|
||||||
if (m_idle && info->num_connections) {
|
|
||||||
m_timer->setRepeat(kActiveInterval);
|
|
||||||
m_idle = false;
|
|
||||||
}
|
|
||||||
else if (!m_idle && !info->num_connections) {
|
|
||||||
m_timer->setRepeat(kIdleInterval);
|
|
||||||
m_idle = true;
|
|
||||||
}
|
|
||||||
# endif
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
int xmrig::Httpd::handler(void *cls, struct MHD_Connection *connection, const char *url, const char *method, const char *, const char *uploadData, size_t *uploadSize, void **con_cls)
|
|
||||||
{
|
|
||||||
HttpRequest req(connection, url, method, uploadData, uploadSize, con_cls);
|
|
||||||
|
|
||||||
if (req.method() == xmrig::HttpRequest::Options) {
|
|
||||||
return req.end(MHD_HTTP_OK, nullptr);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (req.method() == xmrig::HttpRequest::Unsupported) {
|
|
||||||
return req.end(MHD_HTTP_METHOD_NOT_ALLOWED, nullptr);
|
|
||||||
}
|
|
||||||
|
|
||||||
return static_cast<Httpd*>(cls)->process(req);
|
|
||||||
}
|
|
|
@ -30,12 +30,7 @@
|
||||||
#include <uv.h>
|
#include <uv.h>
|
||||||
|
|
||||||
|
|
||||||
#ifndef XMRIG_NO_HTTPD
|
#ifdef XMRIG_FEATURE_TLS
|
||||||
# include <microhttpd.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
#ifndef XMRIG_NO_TLS
|
|
||||||
# include <openssl/opensslv.h>
|
# include <openssl/opensslv.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -66,38 +61,18 @@
|
||||||
xmrig::CommonConfig::CommonConfig() :
|
xmrig::CommonConfig::CommonConfig() :
|
||||||
m_algorithm(CRYPTONIGHT, VARIANT_AUTO),
|
m_algorithm(CRYPTONIGHT, VARIANT_AUTO),
|
||||||
m_adjusted(false),
|
m_adjusted(false),
|
||||||
m_apiIPv6(false),
|
|
||||||
m_apiRestricted(true),
|
|
||||||
m_autoSave(true),
|
m_autoSave(true),
|
||||||
m_background(false),
|
m_background(false),
|
||||||
m_dryRun(false),
|
m_dryRun(false),
|
||||||
m_syslog(false),
|
m_syslog(false),
|
||||||
|
m_upgrade(false),
|
||||||
m_watch(true),
|
m_watch(true),
|
||||||
m_apiPort(0),
|
|
||||||
m_printTime(60),
|
m_printTime(60),
|
||||||
m_state(NoneState)
|
m_state(NoneState)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void xmrig::CommonConfig::printAPI()
|
|
||||||
{
|
|
||||||
# ifndef XMRIG_NO_API
|
|
||||||
if (apiPort() == 0) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
Log::print(GREEN_BOLD(" * ") WHITE_BOLD("%-13s") CYAN("%s:") CYAN_BOLD("%d"), "API BIND", isApiIPv6() ? "[::]" : "0.0.0.0", apiPort());
|
|
||||||
# endif
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void xmrig::CommonConfig::printPools()
|
|
||||||
{
|
|
||||||
m_pools.print();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void xmrig::CommonConfig::printVersions()
|
void xmrig::CommonConfig::printVersions()
|
||||||
{
|
{
|
||||||
char buf[256] = { 0 };
|
char buf[256] = { 0 };
|
||||||
|
@ -131,22 +106,18 @@ void xmrig::CommonConfig::printVersions()
|
||||||
# else
|
# else
|
||||||
memset(buf, 0, 16);
|
memset(buf, 0, 16);
|
||||||
|
|
||||||
# if !defined(XMRIG_NO_HTTPD) || !defined(XMRIG_NO_TLS)
|
# if defined(XMRIG_FEATURE_HTTP) || defined(XMRIG_FEATURE_TLS)
|
||||||
int length = 0;
|
int length = 0;
|
||||||
# endif
|
# endif
|
||||||
# endif
|
# endif
|
||||||
|
|
||||||
# if !defined(XMRIG_NO_TLS) && defined(OPENSSL_VERSION_TEXT)
|
# if defined(XMRIG_FEATURE_TLS) && defined(OPENSSL_VERSION_TEXT)
|
||||||
{
|
{
|
||||||
constexpr const char *v = OPENSSL_VERSION_TEXT + 8;
|
constexpr const char *v = OPENSSL_VERSION_TEXT + 8;
|
||||||
length += snprintf(buf + length, (sizeof buf) - length, "OpenSSL/%.*s ", static_cast<int>(strchr(v, ' ') - v), v);
|
length += snprintf(buf + length, (sizeof buf) - length, "OpenSSL/%.*s ", static_cast<int>(strchr(v, ' ') - v), v);
|
||||||
}
|
}
|
||||||
# endif
|
# endif
|
||||||
|
|
||||||
# ifndef XMRIG_NO_HTTPD
|
|
||||||
length += snprintf(buf + length, (sizeof buf) - length, "microhttpd/%s ", MHD_get_version());
|
|
||||||
# endif
|
|
||||||
|
|
||||||
Log::print(GREEN_BOLD(" * ") WHITE_BOLD("%-13slibuv/%s %s"), "LIBS", uv_version_string(), buf);
|
Log::print(GREEN_BOLD(" * ") WHITE_BOLD("%-13slibuv/%s %s"), "LIBS", uv_version_string(), buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -228,12 +199,23 @@ bool xmrig::CommonConfig::parseBoolean(int key, bool enable)
|
||||||
m_watch = enable;
|
m_watch = enable;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case ApiIPv6Key: /* ipv6 */
|
# ifdef XMRIG_DEPRECATED
|
||||||
m_apiIPv6 = enable;
|
case ApiIPv6Key: /* --api-ipv6 */
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case ApiRestrictedKey: /* restricted */
|
case ApiRestrictedKey: /* --api-no-restricted */
|
||||||
m_apiRestricted = enable;
|
fputs("option \"--api-no-restricted\" deprecated, use \"--http-no-restricted\" instead.\n", stderr);
|
||||||
|
fflush(stdout);
|
||||||
|
m_http.setRestricted(enable);
|
||||||
|
break;
|
||||||
|
# endif
|
||||||
|
|
||||||
|
case HttpRestrictedKey: /* --http-no-restricted */
|
||||||
|
m_http.setRestricted(enable);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case HttpEnabledKey: /* --http-enabled */
|
||||||
|
m_http.setEnabled(enable);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case DryRunKey: /* --dry-run */
|
case DryRunKey: /* --dry-run */
|
||||||
|
@ -289,8 +271,20 @@ bool xmrig::CommonConfig::parseString(int key, const char *arg)
|
||||||
m_logFile = arg;
|
m_logFile = arg;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
# ifdef XMRIG_DEPRECATED
|
||||||
case ApiAccessTokenKey: /* --api-access-token */
|
case ApiAccessTokenKey: /* --api-access-token */
|
||||||
m_apiToken = arg;
|
fputs("option \"--api-access-token\" deprecated, use \"--http-access-token\" instead.\n", stderr);
|
||||||
|
fflush(stdout);
|
||||||
|
m_http.setToken(arg);
|
||||||
|
break;
|
||||||
|
# endif
|
||||||
|
|
||||||
|
case HttpAccessTokenKey: /* --http-access-token */
|
||||||
|
m_http.setToken(arg);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case HttpHostKey: /* --http-host */
|
||||||
|
m_http.setHost(arg);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case ApiWorkerIdKey: /* --api-worker-id */
|
case ApiWorkerIdKey: /* --api-worker-id */
|
||||||
|
@ -307,26 +301,33 @@ bool xmrig::CommonConfig::parseString(int key, const char *arg)
|
||||||
|
|
||||||
case RetriesKey: /* --retries */
|
case RetriesKey: /* --retries */
|
||||||
case RetryPauseKey: /* --retry-pause */
|
case RetryPauseKey: /* --retry-pause */
|
||||||
case ApiPort: /* --api-port */
|
|
||||||
case PrintTimeKey: /* --print-time */
|
case PrintTimeKey: /* --print-time */
|
||||||
return parseUint64(key, strtol(arg, nullptr, 10));
|
case HttpPort: /* --http-port */
|
||||||
|
# ifdef XMRIG_DEPRECATED
|
||||||
|
case ApiPort: /* --api-port */
|
||||||
|
# endif
|
||||||
|
return parseUint64(key, static_cast<uint64_t>(strtol(arg, nullptr, 10)));
|
||||||
|
|
||||||
case BackgroundKey: /* --background */
|
case BackgroundKey: /* --background */
|
||||||
case SyslogKey: /* --syslog */
|
case SyslogKey: /* --syslog */
|
||||||
case KeepAliveKey: /* --keepalive */
|
case KeepAliveKey: /* --keepalive */
|
||||||
case NicehashKey: /* --nicehash */
|
case NicehashKey: /* --nicehash */
|
||||||
case TlsKey: /* --tls */
|
case TlsKey: /* --tls */
|
||||||
case ApiIPv6Key: /* --api-ipv6 */
|
|
||||||
case DryRunKey: /* --dry-run */
|
case DryRunKey: /* --dry-run */
|
||||||
|
case HttpEnabledKey: /* --http-enabled */
|
||||||
return parseBoolean(key, true);
|
return parseBoolean(key, true);
|
||||||
|
|
||||||
case ColorKey: /* --no-color */
|
case ColorKey: /* --no-color */
|
||||||
case WatchKey: /* --no-watch */
|
case WatchKey: /* --no-watch */
|
||||||
|
case HttpRestrictedKey: /* --http-no-restricted */
|
||||||
|
# ifdef XMRIG_DEPRECATED
|
||||||
case ApiRestrictedKey: /* --api-no-restricted */
|
case ApiRestrictedKey: /* --api-no-restricted */
|
||||||
|
case ApiIPv6Key: /* --api-ipv6 */
|
||||||
|
# endif
|
||||||
return parseBoolean(key, false);
|
return parseBoolean(key, false);
|
||||||
|
|
||||||
case DonateLevelKey: /* --donate-level */
|
case DonateLevelKey: /* --donate-level */
|
||||||
return parseUint64(key, strtol(arg, nullptr, 10));
|
return parseUint64(key, static_cast<uint64_t>(strtol(arg, nullptr, 10)));
|
||||||
|
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
|
@ -342,12 +343,25 @@ bool xmrig::CommonConfig::parseUint64(int key, uint64_t arg)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void xmrig::CommonConfig::parseJSON(const rapidjson::Document &doc)
|
void xmrig::CommonConfig::parseJSON(const rapidjson::Value &json)
|
||||||
{
|
{
|
||||||
const rapidjson::Value &pools = doc["pools"];
|
const rapidjson::Value &pools = json["pools"];
|
||||||
if (pools.IsArray()) {
|
if (pools.IsArray()) {
|
||||||
m_pools.load(pools);
|
m_pools.load(pools);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# ifdef XMRIG_DEPRECATED
|
||||||
|
const rapidjson::Value &api = json["api"];
|
||||||
|
if (api.IsObject() && api.HasMember("port")) {
|
||||||
|
m_upgrade = true;
|
||||||
|
m_http.load(api);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
m_http.load(json["http"]);
|
||||||
|
}
|
||||||
|
# else
|
||||||
|
m_http.load(doc["http"]);
|
||||||
|
# endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -384,10 +398,16 @@ bool xmrig::CommonConfig::parseInt(int key, int arg)
|
||||||
m_pools.setProxyDonate(arg);
|
m_pools.setProxyDonate(arg);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
# ifdef XMRIG_DEPRECATED
|
||||||
case ApiPort: /* --api-port */
|
case ApiPort: /* --api-port */
|
||||||
if (arg > 0 && arg <= 65536) {
|
fputs("option \"--api-port\" deprecated, use \"--http-port\" instead.\n", stderr);
|
||||||
m_apiPort = arg;
|
fflush(stdout);
|
||||||
}
|
m_http.setPort(arg);
|
||||||
|
break;
|
||||||
|
# endif
|
||||||
|
|
||||||
|
case HttpPort: /* --http-port */
|
||||||
|
m_http.setPort(arg);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case PrintTimeKey: /* --print-time */
|
case PrintTimeKey: /* --print-time */
|
||||||
|
|
|
@ -26,8 +26,8 @@
|
||||||
#define XMRIG_COMMONCONFIG_H
|
#define XMRIG_COMMONCONFIG_H
|
||||||
|
|
||||||
|
|
||||||
|
#include "base/net/http/Http.h"
|
||||||
#include "base/net/stratum/Pools.h"
|
#include "base/net/stratum/Pools.h"
|
||||||
#include "base/tools/String.h"
|
|
||||||
#include "common/interfaces/IConfig.h"
|
#include "common/interfaces/IConfig.h"
|
||||||
#include "common/xmrig.h"
|
#include "common/xmrig.h"
|
||||||
|
|
||||||
|
@ -40,19 +40,16 @@ class CommonConfig : public IConfig
|
||||||
public:
|
public:
|
||||||
CommonConfig();
|
CommonConfig();
|
||||||
|
|
||||||
inline bool isApiIPv6() const { return m_apiIPv6; }
|
|
||||||
inline bool isApiRestricted() const { return m_apiRestricted; }
|
|
||||||
inline bool isAutoSave() const { return m_autoSave; }
|
inline bool isAutoSave() const { return m_autoSave; }
|
||||||
inline bool isBackground() const { return m_background; }
|
inline bool isBackground() const { return m_background; }
|
||||||
inline bool isDryRun() const { return m_dryRun; }
|
inline bool isDryRun() const { return m_dryRun; }
|
||||||
inline bool isSyslog() const { return m_syslog; }
|
inline bool isSyslog() const { return m_syslog; }
|
||||||
inline const char *apiId() const { return m_apiId.data(); }
|
inline const String &apiId() const { return m_apiId; }
|
||||||
inline const char *apiToken() const { return m_apiToken.data(); }
|
inline const String &apiWorkerId() const { return m_apiWorkerId; }
|
||||||
inline const char *apiWorkerId() const { return m_apiWorkerId.data(); }
|
|
||||||
inline const char *logFile() const { return m_logFile.data(); }
|
inline const char *logFile() const { return m_logFile.data(); }
|
||||||
inline const char *userAgent() const { return m_userAgent.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 const Pools &pools() const { return m_pools; }
|
||||||
inline int apiPort() const { return m_apiPort; }
|
|
||||||
inline int printTime() const { return m_printTime; }
|
inline int printTime() const { return m_printTime; }
|
||||||
|
|
||||||
inline bool isWatch() const override { return m_watch && !m_fileName.isNull(); }
|
inline bool isWatch() const override { return m_watch && !m_fileName.isNull(); }
|
||||||
|
@ -61,8 +58,6 @@ public:
|
||||||
|
|
||||||
bool save() override;
|
bool save() override;
|
||||||
|
|
||||||
void printAPI();
|
|
||||||
void printPools();
|
|
||||||
void printVersions();
|
void printVersions();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
@ -76,24 +71,22 @@ protected:
|
||||||
bool parseBoolean(int key, bool enable) override;
|
bool parseBoolean(int key, bool enable) override;
|
||||||
bool parseString(int key, const char *arg) override;
|
bool parseString(int key, const char *arg) override;
|
||||||
bool parseUint64(int key, uint64_t arg) override;
|
bool parseUint64(int key, uint64_t arg) override;
|
||||||
void parseJSON(const rapidjson::Document &doc) override;
|
void parseJSON(const rapidjson::Value &json) override;
|
||||||
void setFileName(const char *fileName) override;
|
void setFileName(const char *fileName) override;
|
||||||
|
|
||||||
Algorithm m_algorithm;
|
Algorithm m_algorithm;
|
||||||
bool m_adjusted;
|
bool m_adjusted;
|
||||||
bool m_apiIPv6;
|
|
||||||
bool m_apiRestricted;
|
|
||||||
bool m_autoSave;
|
bool m_autoSave;
|
||||||
bool m_background;
|
bool m_background;
|
||||||
bool m_dryRun;
|
bool m_dryRun;
|
||||||
bool m_syslog;
|
bool m_syslog;
|
||||||
|
bool m_upgrade;
|
||||||
bool m_watch;
|
bool m_watch;
|
||||||
int m_apiPort;
|
Http m_http;
|
||||||
int m_printTime;
|
int m_printTime;
|
||||||
Pools m_pools;
|
Pools m_pools;
|
||||||
State m_state;
|
State m_state;
|
||||||
String m_apiId;
|
String m_apiId;
|
||||||
String m_apiToken;
|
|
||||||
String m_apiWorkerId;
|
String m_apiWorkerId;
|
||||||
String m_fileName;
|
String m_fileName;
|
||||||
String m_logFile;
|
String m_logFile;
|
||||||
|
|
|
@ -29,16 +29,6 @@
|
||||||
#include <uv.h>
|
#include <uv.h>
|
||||||
|
|
||||||
|
|
||||||
#ifndef XMRIG_NO_HTTPD
|
|
||||||
# include <microhttpd.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
#ifndef XMRIG_NO_TLS
|
|
||||||
# include <openssl/opensslv.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
#include "base/io/Json.h"
|
#include "base/io/Json.h"
|
||||||
#include "base/kernel/interfaces/IConfigListener.h"
|
#include "base/kernel/interfaces/IConfigListener.h"
|
||||||
#include "base/kernel/Process.h"
|
#include "base/kernel/Process.h"
|
||||||
|
@ -46,21 +36,24 @@
|
||||||
#include "common/config/ConfigWatcher.h"
|
#include "common/config/ConfigWatcher.h"
|
||||||
#include "common/interfaces/IConfig.h"
|
#include "common/interfaces/IConfig.h"
|
||||||
#include "common/Platform.h"
|
#include "common/Platform.h"
|
||||||
#include "core/ConfigCreator.h"
|
#include "core/config/Config.h"
|
||||||
#include "core/ConfigLoader_platform.h"
|
#include "core/config/ConfigLoader_platform.h"
|
||||||
#include "rapidjson/document.h"
|
#include "rapidjson/document.h"
|
||||||
#include "rapidjson/error/en.h"
|
#include "rapidjson/error/en.h"
|
||||||
#include "rapidjson/fwd.h"
|
#include "rapidjson/fwd.h"
|
||||||
|
|
||||||
|
|
||||||
#ifdef XMRIG_FEATURE_EMBEDDED_CONFIG
|
#ifdef XMRIG_FEATURE_EMBEDDED_CONFIG
|
||||||
# include "core/ConfigLoader_default.h"
|
# include "core/config/ConfigLoader_default.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
xmrig::ConfigWatcher *xmrig::ConfigLoader::m_watcher = nullptr;
|
namespace xmrig {
|
||||||
xmrig::IConfigCreator *xmrig::ConfigLoader::m_creator = nullptr;
|
|
||||||
xmrig::IConfigListener *xmrig::ConfigLoader::m_listener = nullptr;
|
ConfigWatcher *ConfigLoader::m_watcher = nullptr;
|
||||||
|
IConfigListener *ConfigLoader::m_listener = nullptr;
|
||||||
|
|
||||||
|
} // namespace xmrig
|
||||||
|
|
||||||
|
|
||||||
#ifndef ARRAY_SIZE
|
#ifndef ARRAY_SIZE
|
||||||
|
@ -95,28 +88,28 @@ bool xmrig::ConfigLoader::loadFromJSON(xmrig::IConfig *config, const char *json)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool xmrig::ConfigLoader::loadFromJSON(xmrig::IConfig *config, const rapidjson::Document &doc)
|
bool xmrig::ConfigLoader::loadFromJSON(xmrig::IConfig *config, const rapidjson::Value &json)
|
||||||
{
|
{
|
||||||
for (size_t i = 0; i < ARRAY_SIZE(config_options); i++) {
|
for (size_t i = 0; i < ARRAY_SIZE(config_options); i++) {
|
||||||
parseJSON(config, &config_options[i], doc);
|
parseJSON(config, &config_options[i], json);
|
||||||
}
|
}
|
||||||
|
|
||||||
const rapidjson::Value &api = doc["api"];
|
const rapidjson::Value &api = json["api"];
|
||||||
if (api.IsObject()) {
|
if (api.IsObject()) {
|
||||||
for (size_t i = 0; i < ARRAY_SIZE(api_options); i++) {
|
for (size_t i = 0; i < ARRAY_SIZE(api_options); i++) {
|
||||||
parseJSON(config, &api_options[i], api);
|
parseJSON(config, &api_options[i], api);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
config->parseJSON(doc);
|
config->parseJSON(json);
|
||||||
|
|
||||||
return config->finalize();
|
return config->finalize();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool xmrig::ConfigLoader::reload(xmrig::IConfig *oldConfig, const char *json)
|
bool xmrig::ConfigLoader::reload(xmrig::IConfig *oldConfig, const rapidjson::Value &json)
|
||||||
{
|
{
|
||||||
xmrig::IConfig *config = m_creator->create();
|
IConfig *config = Config::create();
|
||||||
if (!loadFromJSON(config, json)) {
|
if (!loadFromJSON(config, json)) {
|
||||||
delete config;
|
delete config;
|
||||||
|
|
||||||
|
@ -145,17 +138,16 @@ bool xmrig::ConfigLoader::watch(IConfig *config)
|
||||||
|
|
||||||
assert(m_watcher == nullptr);
|
assert(m_watcher == nullptr);
|
||||||
|
|
||||||
m_watcher = new xmrig::ConfigWatcher(config->fileName(), m_creator, m_listener);
|
m_watcher = new ConfigWatcher(config->fileName(), m_listener);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
xmrig::IConfig *xmrig::ConfigLoader::load(Process *process, IConfigCreator *creator, IConfigListener *listener)
|
xmrig::IConfig *xmrig::ConfigLoader::load(Process *process, IConfigListener *listener)
|
||||||
{
|
{
|
||||||
m_creator = creator;
|
|
||||||
m_listener = listener;
|
m_listener = listener;
|
||||||
|
|
||||||
xmrig::IConfig *config = m_creator->create();
|
IConfig *config = Config::create();
|
||||||
int key;
|
int key;
|
||||||
int argc = process->arguments().argc();
|
int argc = process->arguments().argc();
|
||||||
char **argv = process->arguments().argv();
|
char **argv = process->arguments().argv();
|
||||||
|
@ -181,7 +173,7 @@ xmrig::IConfig *xmrig::ConfigLoader::load(Process *process, IConfigCreator *crea
|
||||||
if (!config->finalize()) {
|
if (!config->finalize()) {
|
||||||
delete config;
|
delete config;
|
||||||
|
|
||||||
config = m_creator->create();
|
config = Config::create();
|
||||||
loadFromFile(config, process->location(Process::ExeLocation, "config.json"));
|
loadFromFile(config, process->location(Process::ExeLocation, "config.json"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -189,7 +181,7 @@ xmrig::IConfig *xmrig::ConfigLoader::load(Process *process, IConfigCreator *crea
|
||||||
if (!config->finalize()) {
|
if (!config->finalize()) {
|
||||||
delete config;
|
delete config;
|
||||||
|
|
||||||
config = m_creator->create();
|
config = Config::create();
|
||||||
loadFromJSON(config, default_config);
|
loadFromJSON(config, default_config);
|
||||||
}
|
}
|
||||||
# endif
|
# endif
|
||||||
|
@ -213,10 +205,8 @@ xmrig::IConfig *xmrig::ConfigLoader::load(Process *process, IConfigCreator *crea
|
||||||
void xmrig::ConfigLoader::release()
|
void xmrig::ConfigLoader::release()
|
||||||
{
|
{
|
||||||
delete m_watcher;
|
delete m_watcher;
|
||||||
delete m_creator;
|
|
||||||
|
|
||||||
m_watcher = nullptr;
|
m_watcher = nullptr;
|
||||||
m_creator = nullptr;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -239,7 +229,7 @@ bool xmrig::ConfigLoader::getJSON(const char *fileName, rapidjson::Document &doc
|
||||||
|
|
||||||
bool xmrig::ConfigLoader::parseArg(xmrig::IConfig *config, int key, const char *arg)
|
bool xmrig::ConfigLoader::parseArg(xmrig::IConfig *config, int key, const char *arg)
|
||||||
{
|
{
|
||||||
if (key == xmrig::IConfig::ConfigKey) {
|
if (key == IConfig::ConfigKey) {
|
||||||
return loadFromFile(config, arg);
|
return loadFromFile(config, arg);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -39,7 +39,6 @@ namespace xmrig {
|
||||||
|
|
||||||
|
|
||||||
class ConfigWatcher;
|
class ConfigWatcher;
|
||||||
class IConfigCreator;
|
|
||||||
class IConfigListener;
|
class IConfigListener;
|
||||||
class IConfig;
|
class IConfig;
|
||||||
class Process;
|
class Process;
|
||||||
|
@ -50,10 +49,10 @@ class ConfigLoader
|
||||||
public:
|
public:
|
||||||
static bool loadFromFile(IConfig *config, const char *fileName);
|
static bool loadFromFile(IConfig *config, const char *fileName);
|
||||||
static bool loadFromJSON(IConfig *config, const char *json);
|
static bool loadFromJSON(IConfig *config, const char *json);
|
||||||
static bool loadFromJSON(IConfig *config, const rapidjson::Document &doc);
|
static bool loadFromJSON(IConfig *config, const rapidjson::Value &json);
|
||||||
static bool reload(IConfig *oldConfig, const char *json);
|
static bool reload(IConfig *oldConfig, const rapidjson::Value &json);
|
||||||
static bool watch(IConfig *config);
|
static bool watch(IConfig *config);
|
||||||
static IConfig *load(Process *process, IConfigCreator *creator, IConfigListener *listener);
|
static IConfig *load(Process *process, IConfigListener *listener);
|
||||||
static void release();
|
static void release();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
@ -62,11 +61,11 @@ private:
|
||||||
static void parseJSON(IConfig *config, const struct option *option, const rapidjson::Value &object);
|
static void parseJSON(IConfig *config, const struct option *option, const rapidjson::Value &object);
|
||||||
|
|
||||||
static ConfigWatcher *m_watcher;
|
static ConfigWatcher *m_watcher;
|
||||||
static IConfigCreator *m_creator;
|
|
||||||
static IConfigListener *m_listener;
|
static IConfigListener *m_listener;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
} /* namespace xmrig */
|
} /* namespace xmrig */
|
||||||
|
|
||||||
|
|
||||||
#endif /* XMRIG_CONFIGLOADER_H */
|
#endif /* XMRIG_CONFIGLOADER_H */
|
||||||
|
|
|
@ -28,11 +28,10 @@
|
||||||
#include "base/kernel/interfaces/IConfigListener.h"
|
#include "base/kernel/interfaces/IConfigListener.h"
|
||||||
#include "common/config/ConfigLoader.h"
|
#include "common/config/ConfigLoader.h"
|
||||||
#include "common/config/ConfigWatcher.h"
|
#include "common/config/ConfigWatcher.h"
|
||||||
#include "core/ConfigCreator.h"
|
#include "core/config/Config.h"
|
||||||
|
|
||||||
|
|
||||||
xmrig::ConfigWatcher::ConfigWatcher(const String &path, IConfigCreator *creator, IConfigListener *listener) :
|
xmrig::ConfigWatcher::ConfigWatcher(const String &path, IConfigListener *listener) :
|
||||||
m_creator(creator),
|
|
||||||
m_listener(listener)
|
m_listener(listener)
|
||||||
{
|
{
|
||||||
m_watcher = new Watcher(path, this);
|
m_watcher = new Watcher(path, this);
|
||||||
|
@ -50,7 +49,7 @@ void xmrig::ConfigWatcher::onFileChanged(const String &fileName)
|
||||||
{
|
{
|
||||||
LOG_WARN("\"%s\" was changed, reloading configuration", fileName.data());
|
LOG_WARN("\"%s\" was changed, reloading configuration", fileName.data());
|
||||||
|
|
||||||
IConfig *config = m_creator->create();
|
IConfig *config = Config::create();
|
||||||
ConfigLoader::loadFromFile(config, fileName);
|
ConfigLoader::loadFromFile(config, fileName);
|
||||||
|
|
||||||
if (!config->finalize()) {
|
if (!config->finalize()) {
|
||||||
|
|
|
@ -37,7 +37,6 @@ struct option;
|
||||||
namespace xmrig {
|
namespace xmrig {
|
||||||
|
|
||||||
|
|
||||||
class IConfigCreator;
|
|
||||||
class IConfigListener;
|
class IConfigListener;
|
||||||
class Watcher;
|
class Watcher;
|
||||||
|
|
||||||
|
@ -45,14 +44,13 @@ class Watcher;
|
||||||
class ConfigWatcher : public IWatcherListener
|
class ConfigWatcher : public IWatcherListener
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
ConfigWatcher(const String &path, IConfigCreator *creator, IConfigListener *listener);
|
ConfigWatcher(const String &path, IConfigListener *listener);
|
||||||
~ConfigWatcher() override;
|
~ConfigWatcher() override;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void onFileChanged(const String &fileName) override;
|
void onFileChanged(const String &fileName) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
IConfigCreator *m_creator;
|
|
||||||
IConfigListener *m_listener;
|
IConfigListener *m_listener;
|
||||||
Watcher *m_watcher;
|
Watcher *m_watcher;
|
||||||
};
|
};
|
||||||
|
|
|
@ -42,12 +42,13 @@ public:
|
||||||
enum Keys {
|
enum Keys {
|
||||||
// common
|
// common
|
||||||
AlgorithmKey = 'a',
|
AlgorithmKey = 'a',
|
||||||
ApiAccessTokenKey = 4001,
|
|
||||||
ApiIPv6Key = 4003,
|
|
||||||
ApiPort = 4000,
|
|
||||||
ApiRestrictedKey = 4004,
|
|
||||||
ApiWorkerIdKey = 4002,
|
ApiWorkerIdKey = 4002,
|
||||||
ApiIdKey = 4005,
|
ApiIdKey = 4005,
|
||||||
|
HttpPort = 4100,
|
||||||
|
HttpAccessTokenKey = 4101,
|
||||||
|
HttpRestrictedKey = 4104,
|
||||||
|
HttpEnabledKey = 4106,
|
||||||
|
HttpHostKey = 4107,
|
||||||
BackgroundKey = 'B',
|
BackgroundKey = 'B',
|
||||||
ColorKey = 1002,
|
ColorKey = 1002,
|
||||||
ConfigKey = 'c',
|
ConfigKey = 'c',
|
||||||
|
@ -71,6 +72,13 @@ public:
|
||||||
AutoSaveKey = 1016,
|
AutoSaveKey = 1016,
|
||||||
ProxyDonateKey = 1017,
|
ProxyDonateKey = 1017,
|
||||||
|
|
||||||
|
# ifdef XMRIG_DEPRECATED
|
||||||
|
ApiPort = 4000,
|
||||||
|
ApiAccessTokenKey = 4001,
|
||||||
|
ApiIPv6Key = 4003,
|
||||||
|
ApiRestrictedKey = 4004,
|
||||||
|
# endif
|
||||||
|
|
||||||
// xmrig common
|
// xmrig common
|
||||||
CPUPriorityKey = 1021,
|
CPUPriorityKey = 1021,
|
||||||
NicehashKey = 1006,
|
NicehashKey = 1006,
|
||||||
|
@ -142,8 +150,10 @@ public:
|
||||||
virtual const Algorithm &algorithm() const = 0;
|
virtual const Algorithm &algorithm() const = 0;
|
||||||
virtual const String &fileName() const = 0;
|
virtual const String &fileName() const = 0;
|
||||||
virtual void getJSON(rapidjson::Document &doc) const = 0;
|
virtual void getJSON(rapidjson::Document &doc) const = 0;
|
||||||
virtual void parseJSON(const rapidjson::Document &doc) = 0;
|
virtual void parseJSON(const rapidjson::Value &json) = 0;
|
||||||
virtual void setFileName(const char *fileName) = 0;
|
virtual void setFileName(const char *fileName) = 0;
|
||||||
|
|
||||||
|
static IConfig *create();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -29,11 +29,11 @@
|
||||||
#include "base/io/log/backends/ConsoleLog.h"
|
#include "base/io/log/backends/ConsoleLog.h"
|
||||||
#include "base/io/log/backends/FileLog.h"
|
#include "base/io/log/backends/FileLog.h"
|
||||||
#include "base/io/log/Log.h"
|
#include "base/io/log/Log.h"
|
||||||
|
#include "base/kernel/interfaces/IControllerListener.h"
|
||||||
#include "common/config/ConfigLoader.h"
|
#include "common/config/ConfigLoader.h"
|
||||||
#include "common/cpu/Cpu.h"
|
#include "common/cpu/Cpu.h"
|
||||||
#include "common/interfaces/IControllerListener.h"
|
|
||||||
#include "common/Platform.h"
|
#include "common/Platform.h"
|
||||||
#include "core/Config.h"
|
#include "core/config/Config.h"
|
||||||
#include "core/Controller.h"
|
#include "core/Controller.h"
|
||||||
#include "net/Network.h"
|
#include "net/Network.h"
|
||||||
|
|
||||||
|
@ -43,10 +43,16 @@
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef XMRIG_FEATURE_API
|
||||||
|
# include "api/Api.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
class xmrig::ControllerPrivate
|
class xmrig::ControllerPrivate
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
inline ControllerPrivate(Process *process) :
|
inline ControllerPrivate(Process *process) :
|
||||||
|
api(nullptr),
|
||||||
config(nullptr),
|
config(nullptr),
|
||||||
network(nullptr),
|
network(nullptr),
|
||||||
process(process)
|
process(process)
|
||||||
|
@ -55,11 +61,16 @@ public:
|
||||||
|
|
||||||
inline ~ControllerPrivate()
|
inline ~ControllerPrivate()
|
||||||
{
|
{
|
||||||
|
# ifdef XMRIG_FEATURE_API
|
||||||
|
delete api;
|
||||||
|
# endif
|
||||||
|
|
||||||
delete network;
|
delete network;
|
||||||
delete config;
|
delete config;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Api *api;
|
||||||
Config *config;
|
Config *config;
|
||||||
Network *network;
|
Network *network;
|
||||||
Process *process;
|
Process *process;
|
||||||
|
@ -79,6 +90,14 @@ xmrig::Controller::~Controller()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
xmrig::Api *xmrig::Controller::api() const
|
||||||
|
{
|
||||||
|
assert(d_ptr->api != nullptr);
|
||||||
|
|
||||||
|
return d_ptr->api;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
bool xmrig::Controller::isReady() const
|
bool xmrig::Controller::isReady() const
|
||||||
{
|
{
|
||||||
return d_ptr->config && d_ptr->network;
|
return d_ptr->config && d_ptr->network;
|
||||||
|
@ -102,6 +121,10 @@ int xmrig::Controller::init()
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# ifdef XMRIG_FEATURE_API
|
||||||
|
d_ptr->api = new Api(this);
|
||||||
|
# endif
|
||||||
|
|
||||||
Platform::init(config()->userAgent());
|
Platform::init(config()->userAgent());
|
||||||
Platform::setProcessPriority(d_ptr->config->priority());
|
Platform::setProcessPriority(d_ptr->config->priority());
|
||||||
|
|
||||||
|
@ -157,7 +180,7 @@ void xmrig::Controller::onNewConfig(IConfig *config)
|
||||||
Config *previousConfig = d_ptr->config;
|
Config *previousConfig = d_ptr->config;
|
||||||
d_ptr->config = static_cast<Config*>(config);
|
d_ptr->config = static_cast<Config*>(config);
|
||||||
|
|
||||||
for (xmrig::IControllerListener *listener : d_ptr->listeners) {
|
for (IControllerListener *listener : d_ptr->listeners) {
|
||||||
listener->onConfigChanged(d_ptr->config, previousConfig);
|
listener->onConfigChanged(d_ptr->config, previousConfig);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -165,8 +188,24 @@ void xmrig::Controller::onNewConfig(IConfig *config)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void xmrig::Controller::start()
|
||||||
|
{
|
||||||
|
network()->connect();
|
||||||
|
|
||||||
|
# ifdef XMRIG_FEATURE_API
|
||||||
|
api()->start();
|
||||||
|
# endif
|
||||||
|
|
||||||
|
save();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void xmrig::Controller::stop()
|
void xmrig::Controller::stop()
|
||||||
{
|
{
|
||||||
|
# ifdef XMRIG_FEATURE_API
|
||||||
|
api()->stop();
|
||||||
|
# endif
|
||||||
|
|
||||||
ConfigLoader::release();
|
ConfigLoader::release();
|
||||||
|
|
||||||
delete d_ptr->network;
|
delete d_ptr->network;
|
||||||
|
|
|
@ -29,12 +29,10 @@
|
||||||
#include "base/kernel/interfaces/IConfigListener.h"
|
#include "base/kernel/interfaces/IConfigListener.h"
|
||||||
|
|
||||||
|
|
||||||
class StatsData;
|
|
||||||
|
|
||||||
|
|
||||||
namespace xmrig {
|
namespace xmrig {
|
||||||
|
|
||||||
|
|
||||||
|
class Api;
|
||||||
class Config;
|
class Config;
|
||||||
class ControllerPrivate;
|
class ControllerPrivate;
|
||||||
class IControllerListener;
|
class IControllerListener;
|
||||||
|
@ -48,12 +46,14 @@ public:
|
||||||
Controller(Process *process);
|
Controller(Process *process);
|
||||||
~Controller() override;
|
~Controller() override;
|
||||||
|
|
||||||
|
Api *api() const;
|
||||||
bool isReady() const;
|
bool isReady() const;
|
||||||
Config *config() const;
|
Config *config() const;
|
||||||
int init();
|
int init();
|
||||||
Network *network() const;
|
Network *network() const;
|
||||||
void addListener(IControllerListener *listener);
|
void addListener(IControllerListener *listener);
|
||||||
void save();
|
void save();
|
||||||
|
void start();
|
||||||
void stop();
|
void stop();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
|
@ -30,8 +30,7 @@
|
||||||
#include "base/io/log/Log.h"
|
#include "base/io/log/Log.h"
|
||||||
#include "common/config/ConfigLoader.h"
|
#include "common/config/ConfigLoader.h"
|
||||||
#include "common/cpu/Cpu.h"
|
#include "common/cpu/Cpu.h"
|
||||||
#include "core/Config.h"
|
#include "core/config/Config.h"
|
||||||
#include "core/ConfigCreator.h"
|
|
||||||
#include "crypto/Asm.h"
|
#include "crypto/Asm.h"
|
||||||
#include "crypto/CryptoNight_constants.h"
|
#include "crypto/CryptoNight_constants.h"
|
||||||
#include "rapidjson/document.h"
|
#include "rapidjson/document.h"
|
||||||
|
@ -56,7 +55,7 @@ xmrig::Config::Config() : xmrig::CommonConfig(),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool xmrig::Config::reload(const char *json)
|
bool xmrig::Config::reload(const rapidjson::Value &json)
|
||||||
{
|
{
|
||||||
return xmrig::ConfigLoader::reload(this, json);
|
return xmrig::ConfigLoader::reload(this, json);
|
||||||
}
|
}
|
||||||
|
@ -73,13 +72,10 @@ void xmrig::Config::getJSON(rapidjson::Document &doc) const
|
||||||
doc.AddMember("algo", StringRef(algorithm().name()), allocator);
|
doc.AddMember("algo", StringRef(algorithm().name()), allocator);
|
||||||
|
|
||||||
Value api(kObjectType);
|
Value api(kObjectType);
|
||||||
api.AddMember("port", apiPort(), allocator);
|
api.AddMember("id", m_apiId.toJSON(), allocator);
|
||||||
api.AddMember("access-token", apiToken() ? Value(StringRef(apiToken())).Move() : Value(kNullType).Move(), allocator);
|
api.AddMember("worker-id", m_apiWorkerId.toJSON(), allocator);
|
||||||
api.AddMember("id", apiId() ? Value(StringRef(apiId())).Move() : Value(kNullType).Move(), allocator);
|
|
||||||
api.AddMember("worker-id", apiWorkerId() ? Value(StringRef(apiWorkerId())).Move() : Value(kNullType).Move(), allocator);
|
|
||||||
api.AddMember("ipv6", isApiIPv6(), allocator);
|
|
||||||
api.AddMember("restricted", isApiRestricted(), allocator);
|
|
||||||
doc.AddMember("api", api, allocator);
|
doc.AddMember("api", api, allocator);
|
||||||
|
doc.AddMember("http", m_http.toJSON(doc), allocator);
|
||||||
|
|
||||||
# ifndef XMRIG_NO_ASM
|
# ifndef XMRIG_NO_ASM
|
||||||
doc.AddMember("asm", Asm::toJSON(m_assembly), allocator);
|
doc.AddMember("asm", Asm::toJSON(m_assembly), allocator);
|
||||||
|
@ -132,7 +128,7 @@ void xmrig::Config::getJSON(rapidjson::Document &doc) const
|
||||||
|
|
||||||
xmrig::Config *xmrig::Config::load(Process *process, IConfigListener *listener)
|
xmrig::Config *xmrig::Config::load(Process *process, IConfigListener *listener)
|
||||||
{
|
{
|
||||||
return static_cast<Config*>(ConfigLoader::load(process, new ConfigCreator(), listener));
|
return static_cast<Config*>(ConfigLoader::load(process, listener));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -269,7 +265,7 @@ bool xmrig::Config::parseUint64(int key, uint64_t arg)
|
||||||
switch (key) {
|
switch (key) {
|
||||||
case CPUAffinityKey: /* --cpu-affinity */
|
case CPUAffinityKey: /* --cpu-affinity */
|
||||||
if (arg) {
|
if (arg) {
|
||||||
m_threads.mask = arg;
|
m_threads.mask = static_cast<int64_t>(arg);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -281,11 +277,11 @@ bool xmrig::Config::parseUint64(int key, uint64_t arg)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void xmrig::Config::parseJSON(const rapidjson::Document &doc)
|
void xmrig::Config::parseJSON(const rapidjson::Value &json)
|
||||||
{
|
{
|
||||||
CommonConfig::parseJSON(doc);
|
CommonConfig::parseJSON(json);
|
||||||
|
|
||||||
const rapidjson::Value &threads = doc["threads"];
|
const rapidjson::Value &threads = json["threads"];
|
||||||
|
|
||||||
if (threads.IsArray()) {
|
if (threads.IsArray()) {
|
||||||
for (const rapidjson::Value &value : threads.GetArray()) {
|
for (const rapidjson::Value &value : threads.GetArray()) {
|
|
@ -67,7 +67,7 @@ public:
|
||||||
|
|
||||||
Config();
|
Config();
|
||||||
|
|
||||||
bool reload(const char *json);
|
bool reload(const rapidjson::Value &json);
|
||||||
|
|
||||||
void getJSON(rapidjson::Document &doc) const override;
|
void getJSON(rapidjson::Document &doc) const override;
|
||||||
|
|
||||||
|
@ -75,11 +75,12 @@ public:
|
||||||
inline AlgoVariant algoVariant() const { return m_algoVariant; }
|
inline AlgoVariant algoVariant() const { return m_algoVariant; }
|
||||||
inline Assembly assembly() const { return m_assembly; }
|
inline Assembly assembly() const { return m_assembly; }
|
||||||
inline bool isHugePages() const { return m_hugePages; }
|
inline bool isHugePages() const { return m_hugePages; }
|
||||||
inline bool isShouldSave() const { return m_shouldSave && isAutoSave(); }
|
inline bool isShouldSave() const { return (m_shouldSave || m_upgrade) && isAutoSave(); }
|
||||||
inline const std::vector<IThread *> &threads() const { return m_threads.list; }
|
inline const std::vector<IThread *> &threads() const { return m_threads.list; }
|
||||||
inline int priority() const { return m_priority; }
|
inline int priority() const { return m_priority; }
|
||||||
inline int threadsCount() const { return m_threads.list.size(); }
|
inline int threadsCount() const { return static_cast<int>(m_threads.list.size()); }
|
||||||
inline int64_t affinity() const { return m_threads.mask; }
|
inline int64_t affinity() const { return m_threads.mask; }
|
||||||
|
inline static IConfig *create() { return new Config(); }
|
||||||
inline ThreadsMode threadsMode() const { return m_threads.mode; }
|
inline ThreadsMode threadsMode() const { return m_threads.mode; }
|
||||||
|
|
||||||
static Config *load(Process *process, IConfigListener *listener);
|
static Config *load(Process *process, IConfigListener *listener);
|
||||||
|
@ -89,7 +90,7 @@ protected:
|
||||||
bool parseBoolean(int key, bool enable) override;
|
bool parseBoolean(int key, bool enable) override;
|
||||||
bool parseString(int key, const char *arg) override;
|
bool parseString(int key, const char *arg) override;
|
||||||
bool parseUint64(int key, uint64_t arg) override;
|
bool parseUint64(int key, uint64_t arg) override;
|
||||||
void parseJSON(const rapidjson::Document &doc) override;
|
void parseJSON(const rapidjson::Value &json) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool parseInt(int key, int arg);
|
bool parseInt(int key, int arg);
|
|
@ -45,12 +45,13 @@ static char const short_options[] = "a:c:kBp:Px:r:R:s:t:T:o:u:O:v:l:S";
|
||||||
|
|
||||||
static struct option const options[] = {
|
static struct option const options[] = {
|
||||||
{ "algo", 1, nullptr, IConfig::AlgorithmKey },
|
{ "algo", 1, nullptr, IConfig::AlgorithmKey },
|
||||||
{ "api-access-token", 1, nullptr, IConfig::ApiAccessTokenKey },
|
|
||||||
{ "api-port", 1, nullptr, IConfig::ApiPort },
|
|
||||||
{ "api-worker-id", 1, nullptr, IConfig::ApiWorkerIdKey },
|
{ "api-worker-id", 1, nullptr, IConfig::ApiWorkerIdKey },
|
||||||
{ "api-id", 1, nullptr, IConfig::ApiIdKey },
|
{ "api-id", 1, nullptr, IConfig::ApiIdKey },
|
||||||
{ "api-ipv6", 0, nullptr, IConfig::ApiIPv6Key },
|
{ "http-enabled", 0, nullptr, IConfig::HttpEnabledKey },
|
||||||
{ "api-no-restricted", 0, nullptr, IConfig::ApiRestrictedKey },
|
{ "http-host", 1, nullptr, IConfig::HttpHostKey },
|
||||||
|
{ "http-access-token", 1, nullptr, IConfig::HttpAccessTokenKey },
|
||||||
|
{ "http-port", 1, nullptr, IConfig::HttpPort },
|
||||||
|
{ "http-no-restricted", 0, nullptr, IConfig::HttpRestrictedKey },
|
||||||
{ "av", 1, nullptr, IConfig::AVKey },
|
{ "av", 1, nullptr, IConfig::AVKey },
|
||||||
{ "background", 0, nullptr, IConfig::BackgroundKey },
|
{ "background", 0, nullptr, IConfig::BackgroundKey },
|
||||||
{ "config", 1, nullptr, IConfig::ConfigKey },
|
{ "config", 1, nullptr, IConfig::ConfigKey },
|
||||||
|
@ -82,6 +83,14 @@ static struct option const options[] = {
|
||||||
{ "tls", 0, nullptr, IConfig::TlsKey },
|
{ "tls", 0, nullptr, IConfig::TlsKey },
|
||||||
{ "tls-fingerprint", 1, nullptr, IConfig::FingerprintKey },
|
{ "tls-fingerprint", 1, nullptr, IConfig::FingerprintKey },
|
||||||
{ "asm", 1, nullptr, IConfig::AssemblyKey },
|
{ "asm", 1, nullptr, IConfig::AssemblyKey },
|
||||||
|
|
||||||
|
# ifdef XMRIG_DEPRECATED
|
||||||
|
{ "api-port", 1, nullptr, IConfig::ApiPort },
|
||||||
|
{ "api-access-token", 1, nullptr, IConfig::ApiAccessTokenKey },
|
||||||
|
{ "api-no-restricted", 0, nullptr, IConfig::ApiRestrictedKey },
|
||||||
|
{ "api-ipv6", 0, nullptr, IConfig::ApiIPv6Key },
|
||||||
|
# endif
|
||||||
|
|
||||||
{ nullptr, 0, nullptr, 0 }
|
{ nullptr, 0, nullptr, 0 }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -115,11 +124,7 @@ static struct option const config_options[] = {
|
||||||
|
|
||||||
|
|
||||||
static struct option const api_options[] = {
|
static struct option const api_options[] = {
|
||||||
{ "port", 1, nullptr, IConfig::ApiPort },
|
|
||||||
{ "access-token", 1, nullptr, IConfig::ApiAccessTokenKey },
|
|
||||||
{ "worker-id", 1, nullptr, IConfig::ApiWorkerIdKey },
|
{ "worker-id", 1, nullptr, IConfig::ApiWorkerIdKey },
|
||||||
{ "ipv6", 0, nullptr, IConfig::ApiIPv6Key },
|
|
||||||
{ "restricted", 0, nullptr, IConfig::ApiRestrictedKey },
|
|
||||||
{ "id", 1, nullptr, IConfig::ApiIdKey },
|
{ "id", 1, nullptr, IConfig::ApiIdKey },
|
||||||
{ nullptr, 0, nullptr, 0 }
|
{ nullptr, 0, nullptr, 0 }
|
||||||
};
|
};
|
96
src/core/config/usage.h
Normal file
96
src/core/config/usage.h
Normal file
|
@ -0,0 +1,96 @@
|
||||||
|
/* XMRig
|
||||||
|
* Copyright 2010 Jeff Garzik <jgarzik@pobox.com>
|
||||||
|
* Copyright 2012-2014 pooler <pooler@litecoinpool.org>
|
||||||
|
* Copyright 2014 Lucas Jones <https://github.com/lucasjones>
|
||||||
|
* Copyright 2014-2016 Wolf9466 <https://github.com/OhGodAPet>
|
||||||
|
* Copyright 2016 Jay D Dee <jayddee246@gmail.com>
|
||||||
|
* Copyright 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_USAGE_H
|
||||||
|
#define XMRIG_USAGE_H
|
||||||
|
|
||||||
|
|
||||||
|
#include "version.h"
|
||||||
|
|
||||||
|
|
||||||
|
namespace xmrig {
|
||||||
|
|
||||||
|
|
||||||
|
static char const usage[] = "\
|
||||||
|
Usage: " APP_ID " [OPTIONS]\n\
|
||||||
|
Options:\n\
|
||||||
|
-a, --algo=ALGO specify the algorithm to use\n\
|
||||||
|
cryptonight\n"
|
||||||
|
#ifndef XMRIG_NO_AEON
|
||||||
|
"\
|
||||||
|
cryptonight-lite\n"
|
||||||
|
#endif
|
||||||
|
#ifndef XMRIG_NO_SUMO
|
||||||
|
"\
|
||||||
|
cryptonight-heavy\n"
|
||||||
|
#endif
|
||||||
|
"\
|
||||||
|
-o, --url=URL URL of mining server\n\
|
||||||
|
-O, --userpass=U:P username:password pair for mining server\n\
|
||||||
|
-u, --user=USERNAME username for mining server\n\
|
||||||
|
-p, --pass=PASSWORD password for mining server\n\
|
||||||
|
--rig-id=ID rig identifier for pool-side statistics (needs pool support)\n\
|
||||||
|
-t, --threads=N number of miner threads\n\
|
||||||
|
-v, --av=N algorithm variation, 0 auto select\n\
|
||||||
|
-k, --keepalive send keepalived packet for prevent timeout (needs pool support)\n\
|
||||||
|
--nicehash enable nicehash.com support\n\
|
||||||
|
--tls enable SSL/TLS support (needs pool support)\n\
|
||||||
|
--tls-fingerprint=F pool TLS certificate fingerprint, if set enable strict certificate pinning\n\
|
||||||
|
-r, --retries=N number of times to retry before switch to backup server (default: 5)\n\
|
||||||
|
-R, --retry-pause=N time to pause between retries (default: 5)\n\
|
||||||
|
--cpu-affinity set process affinity to CPU core(s), mask 0x3 for cores 0 and 1\n\
|
||||||
|
--cpu-priority set process priority (0 idle, 2 normal to 5 highest)\n\
|
||||||
|
--no-huge-pages disable huge pages support\n\
|
||||||
|
--no-color disable colored output\n\
|
||||||
|
--variant algorithm PoW variant\n\
|
||||||
|
--donate-level=N donate level, default 5%% (5 minutes in 100 minutes)\n\
|
||||||
|
--user-agent set custom user-agent string for pool\n\
|
||||||
|
-B, --background run the miner in the background\n\
|
||||||
|
-c, --config=FILE load a JSON-format configuration file\n\
|
||||||
|
-l, --log-file=FILE log all output to a file\n"
|
||||||
|
# ifdef HAVE_SYSLOG_H
|
||||||
|
"\
|
||||||
|
-S, --syslog use system log for output messages\n"
|
||||||
|
# endif
|
||||||
|
"\
|
||||||
|
--max-cpu-usage=N maximum CPU usage for automatic threads mode (default 75)\n\
|
||||||
|
--safe safe adjust threads and av settings for current CPU\n\
|
||||||
|
--asm=ASM ASM code for cn/2, possible values: auto, none, intel, ryzen, bulldozer.\n\
|
||||||
|
--print-time=N print hashrate report every N seconds\n\
|
||||||
|
--api-worker-id=ID custom worker-id for API\n\
|
||||||
|
--api-id=ID custom instance ID for API\n\
|
||||||
|
--http-enabled enable HTTP API\n\
|
||||||
|
--http-host=HOST bind host for HTTP API (by default 127.0.0.1)\n\
|
||||||
|
--http-port=N bind port for HTTP API\n\
|
||||||
|
--http-access-token=T access token for HTTP API\n\
|
||||||
|
--http-no-restricted enable full remote access to HTTP API (only if access token set)\n\
|
||||||
|
--dry-run test configuration and exit\n\
|
||||||
|
-h, --help display this help and exit\n\
|
||||||
|
-V, --version output version information and exit\n\
|
||||||
|
";
|
||||||
|
|
||||||
|
|
||||||
|
} /* namespace xmrig */
|
||||||
|
|
||||||
|
#endif /* XMRIG_USAGE_H */
|
|
@ -1,95 +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_USAGE_H
|
|
||||||
#define XMRIG_USAGE_H
|
|
||||||
|
|
||||||
|
|
||||||
#include "version.h"
|
|
||||||
|
|
||||||
|
|
||||||
namespace xmrig {
|
|
||||||
|
|
||||||
|
|
||||||
static char const usage[] = "\
|
|
||||||
Usage: " APP_ID " [OPTIONS]\n\
|
|
||||||
Options:\n\
|
|
||||||
-a, --algo=ALGO specify the algorithm to use\n\
|
|
||||||
cryptonight\n"
|
|
||||||
#ifndef XMRIG_NO_AEON
|
|
||||||
"\
|
|
||||||
cryptonight-lite\n"
|
|
||||||
#endif
|
|
||||||
#ifndef XMRIG_NO_SUMO
|
|
||||||
"\
|
|
||||||
cryptonight-heavy\n"
|
|
||||||
#endif
|
|
||||||
"\
|
|
||||||
-o, --url=URL URL of mining server\n\
|
|
||||||
-O, --userpass=U:P username:password pair for mining server\n\
|
|
||||||
-u, --user=USERNAME username for mining server\n\
|
|
||||||
-p, --pass=PASSWORD password for mining server\n\
|
|
||||||
--rig-id=ID rig identifier for pool-side statistics (needs pool support)\n\
|
|
||||||
-t, --threads=N number of miner threads\n\
|
|
||||||
-v, --av=N algorithm variation, 0 auto select\n\
|
|
||||||
-k, --keepalive send keepalived packet for prevent timeout (needs pool support)\n\
|
|
||||||
--nicehash enable nicehash.com support\n\
|
|
||||||
--tls enable SSL/TLS support (needs pool support)\n\
|
|
||||||
--tls-fingerprint=F pool TLS certificate fingerprint, if set enable strict certificate pinning\n\
|
|
||||||
-r, --retries=N number of times to retry before switch to backup server (default: 5)\n\
|
|
||||||
-R, --retry-pause=N time to pause between retries (default: 5)\n\
|
|
||||||
--cpu-affinity set process affinity to CPU core(s), mask 0x3 for cores 0 and 1\n\
|
|
||||||
--cpu-priority set process priority (0 idle, 2 normal to 5 highest)\n\
|
|
||||||
--no-huge-pages disable huge pages support\n\
|
|
||||||
--no-color disable colored output\n\
|
|
||||||
--variant algorithm PoW variant\n\
|
|
||||||
--donate-level=N donate level, default 5%% (5 minutes in 100 minutes)\n\
|
|
||||||
--user-agent set custom user-agent string for pool\n\
|
|
||||||
-B, --background run the miner in the background\n\
|
|
||||||
-c, --config=FILE load a JSON-format configuration file\n\
|
|
||||||
-l, --log-file=FILE log all output to a file\n"
|
|
||||||
# ifdef HAVE_SYSLOG_H
|
|
||||||
"\
|
|
||||||
-S, --syslog use system log for output messages\n"
|
|
||||||
# endif
|
|
||||||
"\
|
|
||||||
--max-cpu-usage=N maximum CPU usage for automatic threads mode (default 75)\n\
|
|
||||||
--safe safe adjust threads and av settings for current CPU\n\
|
|
||||||
--asm=ASM ASM code for cn/2, possible values: auto, none, intel, ryzen, bulldozer.\n\
|
|
||||||
--print-time=N print hashrate report every N seconds\n\
|
|
||||||
--api-port=N port for the miner API\n\
|
|
||||||
--api-access-token=T access token for API\n\
|
|
||||||
--api-worker-id=ID custom worker-id for API\n\
|
|
||||||
--api-id=ID custom instance ID for API\n\
|
|
||||||
--api-ipv6 enable IPv6 support for API\n\
|
|
||||||
--api-no-restricted enable full remote access (only if API token set)\n\
|
|
||||||
--dry-run test configuration and exit\n\
|
|
||||||
-h, --help display this help and exit\n\
|
|
||||||
-V, --version output version information and exit\n\
|
|
||||||
";
|
|
||||||
|
|
||||||
|
|
||||||
} /* namespace xmrig */
|
|
||||||
|
|
||||||
#endif /* XMRIG_USAGE_H */
|
|
|
@ -51,7 +51,7 @@ public:
|
||||||
PentaWay
|
PentaWay
|
||||||
};
|
};
|
||||||
|
|
||||||
virtual ~IThread() {}
|
virtual ~IThread() = default;
|
||||||
|
|
||||||
virtual Algo algorithm() const = 0;
|
virtual Algo algorithm() const = 0;
|
||||||
virtual int priority() const = 0;
|
virtual int priority() const = 0;
|
||||||
|
@ -61,7 +61,7 @@ public:
|
||||||
virtual size_t index() const = 0;
|
virtual size_t index() const = 0;
|
||||||
virtual Type type() const = 0;
|
virtual Type type() const = 0;
|
||||||
|
|
||||||
# ifndef XMRIG_NO_API
|
# ifdef XMRIG_FEATURE_API
|
||||||
virtual rapidjson::Value toAPI(rapidjson::Document &doc) const = 0;
|
virtual rapidjson::Value toAPI(rapidjson::Document &doc) const = 0;
|
||||||
# endif
|
# endif
|
||||||
|
|
||||||
|
|
|
@ -37,13 +37,20 @@
|
||||||
#include "base/net/stratum/SubmitResult.h"
|
#include "base/net/stratum/SubmitResult.h"
|
||||||
#include "base/tools/Chrono.h"
|
#include "base/tools/Chrono.h"
|
||||||
#include "base/tools/Timer.h"
|
#include "base/tools/Timer.h"
|
||||||
#include "core/Config.h"
|
#include "core/config/Config.h"
|
||||||
#include "core/Controller.h"
|
#include "core/Controller.h"
|
||||||
#include "net/Network.h"
|
#include "net/Network.h"
|
||||||
#include "net/strategies/DonateStrategy.h"
|
#include "net/strategies/DonateStrategy.h"
|
||||||
|
#include "rapidjson/document.h"
|
||||||
#include "workers/Workers.h"
|
#include "workers/Workers.h"
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef XMRIG_FEATURE_API
|
||||||
|
# include "api/Api.h"
|
||||||
|
# include "api/interfaces/IApiRequest.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
xmrig::Network::Network(Controller *controller) :
|
xmrig::Network::Network(Controller *controller) :
|
||||||
m_donate(nullptr),
|
m_donate(nullptr),
|
||||||
m_timer(nullptr)
|
m_timer(nullptr)
|
||||||
|
@ -51,6 +58,10 @@ xmrig::Network::Network(Controller *controller) :
|
||||||
Workers::setListener(this);
|
Workers::setListener(this);
|
||||||
controller->addListener(this);
|
controller->addListener(this);
|
||||||
|
|
||||||
|
# ifdef XMRIG_FEATURE_API
|
||||||
|
controller->api()->addListener(this);
|
||||||
|
# endif
|
||||||
|
|
||||||
const Pools &pools = controller->config()->pools();
|
const Pools &pools = controller->config()->pools();
|
||||||
m_strategy = pools.createStrategy(this);
|
m_strategy = pools.createStrategy(this);
|
||||||
|
|
||||||
|
@ -152,6 +163,19 @@ void xmrig::Network::onPause(IStrategy *strategy)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void xmrig::Network::onRequest(IApiRequest &request)
|
||||||
|
{
|
||||||
|
# ifdef XMRIG_FEATURE_API
|
||||||
|
if (request.method() == IApiRequest::METHOD_GET && (request.url() == "/1/summary" || request.url() == "/api.json")) {
|
||||||
|
request.accept();
|
||||||
|
|
||||||
|
getResults(request.reply(), request.doc());
|
||||||
|
getConnection(request.reply(), request.doc());
|
||||||
|
}
|
||||||
|
# endif
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void xmrig::Network::onResultAccepted(IStrategy *, Client *, const SubmitResult &result, const char *error)
|
void xmrig::Network::onResultAccepted(IStrategy *, Client *, const SubmitResult &result, const char *error)
|
||||||
{
|
{
|
||||||
m_state.add(result, error);
|
m_state.add(result, error);
|
||||||
|
@ -196,8 +220,47 @@ void xmrig::Network::tick()
|
||||||
if (m_donate) {
|
if (m_donate) {
|
||||||
m_donate->tick(now);
|
m_donate->tick(now);
|
||||||
}
|
}
|
||||||
|
|
||||||
# ifndef XMRIG_NO_API
|
|
||||||
Api::tick(m_state);
|
|
||||||
# endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef XMRIG_FEATURE_API
|
||||||
|
void xmrig::Network::getConnection(rapidjson::Value &reply, rapidjson::Document &doc) const
|
||||||
|
{
|
||||||
|
using namespace rapidjson;
|
||||||
|
auto &allocator = doc.GetAllocator();
|
||||||
|
|
||||||
|
Value connection(kObjectType);
|
||||||
|
connection.AddMember("pool", StringRef(m_state.pool), allocator);
|
||||||
|
connection.AddMember("uptime", m_state.connectionTime(), allocator);
|
||||||
|
connection.AddMember("ping", m_state.latency(), allocator);
|
||||||
|
connection.AddMember("failures", m_state.failures, allocator);
|
||||||
|
connection.AddMember("error_log", Value(kArrayType), allocator);
|
||||||
|
|
||||||
|
reply.AddMember("connection", connection, allocator);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void xmrig::Network::getResults(rapidjson::Value &reply, rapidjson::Document &doc) const
|
||||||
|
{
|
||||||
|
using namespace rapidjson;
|
||||||
|
auto &allocator = doc.GetAllocator();
|
||||||
|
|
||||||
|
Value results(kObjectType);
|
||||||
|
|
||||||
|
results.AddMember("diff_current", m_state.diff, allocator);
|
||||||
|
results.AddMember("shares_good", m_state.accepted, allocator);
|
||||||
|
results.AddMember("shares_total", m_state.accepted + m_state.rejected, allocator);
|
||||||
|
results.AddMember("avg_time", m_state.avgTime(), allocator);
|
||||||
|
results.AddMember("hashes_total", m_state.total, allocator);
|
||||||
|
|
||||||
|
Value best(kArrayType);
|
||||||
|
for (size_t i = 0; i < m_state.topDiff.size(); ++i) {
|
||||||
|
best.PushBack(m_state.topDiff[i], allocator);
|
||||||
|
}
|
||||||
|
|
||||||
|
results.AddMember("best", best, allocator);
|
||||||
|
results.AddMember("error_log", Value(kArrayType), allocator);
|
||||||
|
|
||||||
|
reply.AddMember("results", results, allocator);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
|
@ -29,11 +29,13 @@
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
|
|
||||||
#include "api/NetworkState.h"
|
#include "api/interfaces/IApiListener.h"
|
||||||
|
#include "base/kernel/interfaces/IControllerListener.h"
|
||||||
#include "base/kernel/interfaces/IStrategyListener.h"
|
#include "base/kernel/interfaces/IStrategyListener.h"
|
||||||
#include "base/kernel/interfaces/ITimerListener.h"
|
#include "base/kernel/interfaces/ITimerListener.h"
|
||||||
#include "common/interfaces/IControllerListener.h"
|
|
||||||
#include "interfaces/IJobResultListener.h"
|
#include "interfaces/IJobResultListener.h"
|
||||||
|
#include "net/NetworkState.h"
|
||||||
|
#include "rapidjson/fwd.h"
|
||||||
|
|
||||||
|
|
||||||
namespace xmrig {
|
namespace xmrig {
|
||||||
|
@ -43,7 +45,7 @@ class Controller;
|
||||||
class IStrategy;
|
class IStrategy;
|
||||||
|
|
||||||
|
|
||||||
class Network : public IJobResultListener, public IStrategyListener, public IControllerListener, public ITimerListener
|
class Network : public IJobResultListener, public IStrategyListener, public IControllerListener, public ITimerListener, public IApiListener
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
Network(Controller *controller);
|
Network(Controller *controller);
|
||||||
|
@ -61,6 +63,7 @@ protected:
|
||||||
void onJob(IStrategy *strategy, Client *client, const Job &job) override;
|
void onJob(IStrategy *strategy, Client *client, const Job &job) override;
|
||||||
void onJobResult(const JobResult &result) override;
|
void onJobResult(const JobResult &result) override;
|
||||||
void onPause(IStrategy *strategy) override;
|
void onPause(IStrategy *strategy) override;
|
||||||
|
void onRequest(IApiRequest &request) override;
|
||||||
void onResultAccepted(IStrategy *strategy, Client *client, const SubmitResult &result, const char *error) override;
|
void onResultAccepted(IStrategy *strategy, Client *client, const SubmitResult &result, const char *error) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
@ -69,6 +72,11 @@ private:
|
||||||
void setJob(Client *client, const Job &job, bool donate);
|
void setJob(Client *client, const Job &job, bool donate);
|
||||||
void tick();
|
void tick();
|
||||||
|
|
||||||
|
# ifdef XMRIG_FEATURE_API
|
||||||
|
void getConnection(rapidjson::Value &reply, rapidjson::Document &doc) const;
|
||||||
|
void getResults(rapidjson::Value &reply, rapidjson::Document &doc) const;
|
||||||
|
# endif
|
||||||
|
|
||||||
IStrategy *m_donate;
|
IStrategy *m_donate;
|
||||||
IStrategy *m_strategy;
|
IStrategy *m_strategy;
|
||||||
NetworkState m_state;
|
NetworkState m_state;
|
||||||
|
|
|
@ -29,9 +29,9 @@
|
||||||
#include <uv.h>
|
#include <uv.h>
|
||||||
|
|
||||||
|
|
||||||
#include "api/NetworkState.h"
|
|
||||||
#include "base/net/stratum/SubmitResult.h"
|
#include "base/net/stratum/SubmitResult.h"
|
||||||
#include "base/tools/Chrono.h"
|
#include "base/tools/Chrono.h"
|
||||||
|
#include "net/NetworkState.h"
|
||||||
|
|
||||||
|
|
||||||
xmrig::NetworkState::NetworkState() :
|
xmrig::NetworkState::NetworkState() :
|
|
@ -35,7 +35,7 @@
|
||||||
#include "common/crypto/keccak.h"
|
#include "common/crypto/keccak.h"
|
||||||
#include "common/Platform.h"
|
#include "common/Platform.h"
|
||||||
#include "common/xmrig.h"
|
#include "common/xmrig.h"
|
||||||
#include "core/Config.h"
|
#include "core/config/Config.h"
|
||||||
#include "core/Controller.h"
|
#include "core/Controller.h"
|
||||||
#include "net/Network.h"
|
#include "net/Network.h"
|
||||||
#include "net/strategies/DonateStrategy.h"
|
#include "net/strategies/DonateStrategy.h"
|
||||||
|
|
|
@ -706,7 +706,7 @@ void xmrig::CpuThread::print() const
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
#ifndef XMRIG_NO_API
|
#ifdef XMRIG_FEATURE_API
|
||||||
rapidjson::Value xmrig::CpuThread::toAPI(rapidjson::Document &doc) const
|
rapidjson::Value xmrig::CpuThread::toAPI(rapidjson::Document &doc) const
|
||||||
{
|
{
|
||||||
using namespace rapidjson;
|
using namespace rapidjson;
|
||||||
|
|
|
@ -90,7 +90,7 @@ protected:
|
||||||
void print() const override;
|
void print() const override;
|
||||||
# endif
|
# endif
|
||||||
|
|
||||||
# ifndef XMRIG_NO_API
|
# ifdef XMRIG_FEATURE_API
|
||||||
rapidjson::Value toAPI(rapidjson::Document &doc) const override;
|
rapidjson::Value toAPI(rapidjson::Document &doc) const override;
|
||||||
# endif
|
# endif
|
||||||
|
|
||||||
|
|
|
@ -32,7 +32,7 @@
|
||||||
|
|
||||||
#include "base/io/log/Log.h"
|
#include "base/io/log/Log.h"
|
||||||
#include "base/tools/Handle.h"
|
#include "base/tools/Handle.h"
|
||||||
#include "core/Config.h"
|
#include "core/config/Config.h"
|
||||||
#include "core/Controller.h"
|
#include "core/Controller.h"
|
||||||
#include "workers/Hashrate.h"
|
#include "workers/Hashrate.h"
|
||||||
|
|
||||||
|
|
|
@ -30,7 +30,7 @@
|
||||||
#include "api/Api.h"
|
#include "api/Api.h"
|
||||||
#include "base/io/log/Log.h"
|
#include "base/io/log/Log.h"
|
||||||
#include "base/tools/Handle.h"
|
#include "base/tools/Handle.h"
|
||||||
#include "core/Config.h"
|
#include "core/config/Config.h"
|
||||||
#include "core/Controller.h"
|
#include "core/Controller.h"
|
||||||
#include "crypto/CryptoNight_constants.h"
|
#include "crypto/CryptoNight_constants.h"
|
||||||
#include "interfaces/IJobResultListener.h"
|
#include "interfaces/IJobResultListener.h"
|
||||||
|
@ -207,8 +207,6 @@ void Workers::start(xmrig::Controller *controller)
|
||||||
m_workers.push_back(handle);
|
m_workers.push_back(handle);
|
||||||
handle->start(Workers::onReady);
|
handle->start(Workers::onReady);
|
||||||
}
|
}
|
||||||
|
|
||||||
controller->save();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -237,7 +235,7 @@ void Workers::submit(const xmrig::JobResult &result)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#ifndef XMRIG_NO_API
|
#ifdef XMRIG_FEATURE_API
|
||||||
void Workers::threadsSummary(rapidjson::Document &doc)
|
void Workers::threadsSummary(rapidjson::Document &doc)
|
||||||
{
|
{
|
||||||
uv_mutex_lock(&m_mutex);
|
uv_mutex_lock(&m_mutex);
|
||||||
|
|
|
@ -68,7 +68,7 @@ public:
|
||||||
static inline void pause() { m_active = false; m_paused = 1; m_sequence++; }
|
static inline void pause() { m_active = false; m_paused = 1; m_sequence++; }
|
||||||
static inline void setListener(xmrig::IJobResultListener *listener) { m_listener = listener; }
|
static inline void setListener(xmrig::IJobResultListener *listener) { m_listener = listener; }
|
||||||
|
|
||||||
# ifndef XMRIG_NO_API
|
# ifdef XMRIG_FEATURE_API
|
||||||
static void threadsSummary(rapidjson::Document &doc);
|
static void threadsSummary(rapidjson::Document &doc);
|
||||||
# endif
|
# endif
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue