Merge branch 'feature-httpd' into evo

This commit is contained in:
XMRig 2019-03-31 23:34:17 +07:00
commit 96f5bd32b5
79 changed files with 5918 additions and 1488 deletions

View file

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

View file

@ -1,49 +0,0 @@
# - Try to find MHD
# Once done this will define
#
# MHD_FOUND - system has MHD
# MHD_INCLUDE_DIRS - the MHD include directory
# MHD_LIBRARY - Link these to use MHD
find_path(
MHD_INCLUDE_DIR
NAMES microhttpd.h
PATHS "${XMRIG_DEPS}" ENV "XMRIG_DEPS"
PATH_SUFFIXES "include"
DOC "microhttpd include dir"
NO_DEFAULT_PATH
)
find_path(MHD_INCLUDE_DIR NAMES microhttpd.h)
find_library(
MHD_LIBRARY
NAMES libmicrohttpd.a microhttpd libmicrohttpd
PATHS "${XMRIG_DEPS}" ENV "XMRIG_DEPS"
PATH_SUFFIXES "lib"
DOC "microhttpd library"
NO_DEFAULT_PATH
)
find_library(MHD_LIBRARY NAMES microhttpd libmicrohttpd)
set(MHD_INCLUDE_DIRS ${MHD_INCLUDE_DIR})
set(MHD_LIBRARIES ${MHD_LIBRARY})
# debug library on windows
# same naming convention as in qt (appending debug library with d)
# boost is using the same "hack" as us with "optimized" and "debug"
# official MHD project actually uses _d suffix
if (${CMAKE_CXX_COMPILER_ID} STREQUAL MSVC)
find_library(
MHD_LIBRARY_DEBUG
NAMES microhttpd_d microhttpd-10_d libmicrohttpd_d libmicrohttpd-dll_d
DOC "mhd debug library"
)
set(MHD_LIBRARIES optimized ${MHD_LIBRARIES} debug ${MHD_LIBRARY_DEBUG})
endif()
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(MHD DEFAULT_MSG MHD_LIBRARY MHD_INCLUDE_DIR)
mark_as_advanced(MHD_INCLUDE_DIR MHD_LIBRARY)

View file

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

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

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

@ -0,0 +1,19 @@
Copyright Joyent, Inc. and other Node contributors.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to
deal in the Software without restriction, including without limitation the
rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
sell copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
IN THE SOFTWARE.

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

@ -0,0 +1,246 @@
HTTP Parser
===========
[![Build Status](https://api.travis-ci.org/nodejs/http-parser.svg?branch=master)](https://travis-ci.org/nodejs/http-parser)
This is a parser for HTTP messages written in C. It parses both requests and
responses. The parser is designed to be used in performance HTTP
applications. It does not make any syscalls nor allocations, it does not
buffer data, it can be interrupted at anytime. Depending on your
architecture, it only requires about 40 bytes of data per message
stream (in a web server that is per connection).
Features:
* No dependencies
* Handles persistent streams (keep-alive).
* Decodes chunked encoding.
* Upgrade support
* Defends against buffer overflow attacks.
The parser extracts the following information from HTTP messages:
* Header fields and values
* Content-Length
* Request method
* Response status code
* Transfer-Encoding
* HTTP version
* Request URL
* Message body
Usage
-----
One `http_parser` object is used per TCP connection. Initialize the struct
using `http_parser_init()` and set the callbacks. That might look something
like this for a request parser:
```c
http_parser_settings settings;
settings.on_url = my_url_callback;
settings.on_header_field = my_header_field_callback;
/* ... */
http_parser *parser = malloc(sizeof(http_parser));
http_parser_init(parser, HTTP_REQUEST);
parser->data = my_socket;
```
When data is received on the socket execute the parser and check for errors.
```c
size_t len = 80*1024, nparsed;
char buf[len];
ssize_t recved;
recved = recv(fd, buf, len, 0);
if (recved < 0) {
/* Handle error. */
}
/* Start up / continue the parser.
* Note we pass recved==0 to signal that EOF has been received.
*/
nparsed = http_parser_execute(parser, &settings, buf, recved);
if (parser->upgrade) {
/* handle new protocol */
} else if (nparsed != recved) {
/* Handle error. Usually just close the connection. */
}
```
`http_parser` needs to know where the end of the stream is. For example, sometimes
servers send responses without Content-Length and expect the client to
consume input (for the body) until EOF. To tell `http_parser` about EOF, give
`0` as the fourth parameter to `http_parser_execute()`. Callbacks and errors
can still be encountered during an EOF, so one must still be prepared
to receive them.
Scalar valued message information such as `status_code`, `method`, and the
HTTP version are stored in the parser structure. This data is only
temporally stored in `http_parser` and gets reset on each new message. If
this information is needed later, copy it out of the structure during the
`headers_complete` callback.
The parser decodes the transfer-encoding for both requests and responses
transparently. That is, a chunked encoding is decoded before being sent to
the on_body callback.
The Special Problem of Upgrade
------------------------------
`http_parser` supports upgrading the connection to a different protocol. An
increasingly common example of this is the WebSocket protocol which sends
a request like
GET /demo HTTP/1.1
Upgrade: WebSocket
Connection: Upgrade
Host: example.com
Origin: http://example.com
WebSocket-Protocol: sample
followed by non-HTTP data.
(See [RFC6455](https://tools.ietf.org/html/rfc6455) for more information the
WebSocket protocol.)
To support this, the parser will treat this as a normal HTTP message without a
body, issuing both on_headers_complete and on_message_complete callbacks. However
http_parser_execute() will stop parsing at the end of the headers and return.
The user is expected to check if `parser->upgrade` has been set to 1 after
`http_parser_execute()` returns. Non-HTTP data begins at the buffer supplied
offset by the return value of `http_parser_execute()`.
Callbacks
---------
During the `http_parser_execute()` call, the callbacks set in
`http_parser_settings` will be executed. The parser maintains state and
never looks behind, so buffering the data is not necessary. If you need to
save certain data for later usage, you can do that from the callbacks.
There are two types of callbacks:
* notification `typedef int (*http_cb) (http_parser*);`
Callbacks: on_message_begin, on_headers_complete, on_message_complete.
* data `typedef int (*http_data_cb) (http_parser*, const char *at, size_t length);`
Callbacks: (requests only) on_url,
(common) on_header_field, on_header_value, on_body;
Callbacks must return 0 on success. Returning a non-zero value indicates
error to the parser, making it exit immediately.
For cases where it is necessary to pass local information to/from a callback,
the `http_parser` object's `data` field can be used.
An example of such a case is when using threads to handle a socket connection,
parse a request, and then give a response over that socket. By instantiation
of a thread-local struct containing relevant data (e.g. accepted socket,
allocated memory for callbacks to write into, etc), a parser's callbacks are
able to communicate data between the scope of the thread and the scope of the
callback in a threadsafe manner. This allows `http_parser` to be used in
multi-threaded contexts.
Example:
```c
typedef struct {
socket_t sock;
void* buffer;
int buf_len;
} custom_data_t;
int my_url_callback(http_parser* parser, const char *at, size_t length) {
/* access to thread local custom_data_t struct.
Use this access save parsed data for later use into thread local
buffer, or communicate over socket
*/
parser->data;
...
return 0;
}
...
void http_parser_thread(socket_t sock) {
int nparsed = 0;
/* allocate memory for user data */
custom_data_t *my_data = malloc(sizeof(custom_data_t));
/* some information for use by callbacks.
* achieves thread -> callback information flow */
my_data->sock = sock;
/* instantiate a thread-local parser */
http_parser *parser = malloc(sizeof(http_parser));
http_parser_init(parser, HTTP_REQUEST); /* initialise parser */
/* this custom data reference is accessible through the reference to the
parser supplied to callback functions */
parser->data = my_data;
http_parser_settings settings; /* set up callbacks */
settings.on_url = my_url_callback;
/* execute parser */
nparsed = http_parser_execute(parser, &settings, buf, recved);
...
/* parsed information copied from callback.
can now perform action on data copied into thread-local memory from callbacks.
achieves callback -> thread information flow */
my_data->buffer;
...
}
```
In case you parse HTTP message in chunks (i.e. `read()` request line
from socket, parse, read half headers, parse, etc) your data callbacks
may be called more than once. `http_parser` guarantees that data pointer is only
valid for the lifetime of callback. You can also `read()` into a heap allocated
buffer to avoid copying memory around if this fits your application.
Reading headers may be a tricky task if you read/parse headers partially.
Basically, you need to remember whether last header callback was field or value
and apply the following logic:
(on_header_field and on_header_value shortened to on_h_*)
------------------------ ------------ --------------------------------------------
| State (prev. callback) | Callback | Description/action |
------------------------ ------------ --------------------------------------------
| nothing (first call) | on_h_field | Allocate new buffer and copy callback data |
| | | into it |
------------------------ ------------ --------------------------------------------
| value | on_h_field | New header started. |
| | | Copy current name,value buffers to headers |
| | | list and allocate new buffer for new name |
------------------------ ------------ --------------------------------------------
| field | on_h_field | Previous name continues. Reallocate name |
| | | buffer and append callback data to it |
------------------------ ------------ --------------------------------------------
| field | on_h_value | Value for current header started. Allocate |
| | | new buffer and copy callback data to it |
------------------------ ------------ --------------------------------------------
| value | on_h_value | Value continues. Reallocate value buffer |
| | | and append callback data to it |
------------------------ ------------ --------------------------------------------
Parsing URLs
------------
A simplistic zero-copy URL parser is provided as `http_parser_parse_url()`.
Users of this library may wish to use it to parse URLs constructed from
consecutive `on_url` callbacks.
See examples of reading in headers:
* [partial example](http://gist.github.com/155877) in C
* [from http-parser tests](http://github.com/joyent/http-parser/blob/37a0ff8/test.c#L403) in C
* [from Node library](http://github.com/joyent/node/blob/842eaf4/src/http.js#L284) in Javascript

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

File diff suppressed because it is too large Load diff

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

@ -0,0 +1,439 @@
/* Copyright Joyent, Inc. and other Node contributors. All rights reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to
* deal in the Software without restriction, including without limitation the
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
* sell copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
* IN THE SOFTWARE.
*/
#ifndef http_parser_h
#define http_parser_h
#ifdef __cplusplus
extern "C" {
#endif
/* Also update SONAME in the Makefile whenever you change these. */
#define HTTP_PARSER_VERSION_MAJOR 2
#define HTTP_PARSER_VERSION_MINOR 9
#define HTTP_PARSER_VERSION_PATCH 0
#include <stddef.h>
#if defined(_WIN32) && !defined(__MINGW32__) && \
(!defined(_MSC_VER) || _MSC_VER<1600) && !defined(__WINE__)
#include <BaseTsd.h>
typedef __int8 int8_t;
typedef unsigned __int8 uint8_t;
typedef __int16 int16_t;
typedef unsigned __int16 uint16_t;
typedef __int32 int32_t;
typedef unsigned __int32 uint32_t;
typedef __int64 int64_t;
typedef unsigned __int64 uint64_t;
#else
#include <stdint.h>
#endif
/* Compile with -DHTTP_PARSER_STRICT=0 to make less checks, but run
* faster
*/
#ifndef HTTP_PARSER_STRICT
# define HTTP_PARSER_STRICT 1
#endif
/* Maximium header size allowed. If the macro is not defined
* before including this header then the default is used. To
* change the maximum header size, define the macro in the build
* environment (e.g. -DHTTP_MAX_HEADER_SIZE=<value>). To remove
* the effective limit on the size of the header, define the macro
* to a very large number (e.g. -DHTTP_MAX_HEADER_SIZE=0x7fffffff)
*/
#ifndef HTTP_MAX_HEADER_SIZE
# define HTTP_MAX_HEADER_SIZE (80*1024)
#endif
typedef struct http_parser http_parser;
typedef struct http_parser_settings http_parser_settings;
/* Callbacks should return non-zero to indicate an error. The parser will
* then halt execution.
*
* The one exception is on_headers_complete. In a HTTP_RESPONSE parser
* returning '1' from on_headers_complete will tell the parser that it
* should not expect a body. This is used when receiving a response to a
* HEAD request which may contain 'Content-Length' or 'Transfer-Encoding:
* chunked' headers that indicate the presence of a body.
*
* Returning `2` from on_headers_complete will tell parser that it should not
* expect neither a body nor any futher responses on this connection. This is
* useful for handling responses to a CONNECT request which may not contain
* `Upgrade` or `Connection: upgrade` headers.
*
* http_data_cb does not return data chunks. It will be called arbitrarily
* many times for each string. E.G. you might get 10 callbacks for "on_url"
* each providing just a few characters more data.
*/
typedef int (*http_data_cb) (http_parser*, const char *at, size_t length);
typedef int (*http_cb) (http_parser*);
/* Status Codes */
#define HTTP_STATUS_MAP(XX) \
XX(100, CONTINUE, Continue) \
XX(101, SWITCHING_PROTOCOLS, Switching Protocols) \
XX(102, PROCESSING, Processing) \
XX(200, OK, OK) \
XX(201, CREATED, Created) \
XX(202, ACCEPTED, Accepted) \
XX(203, NON_AUTHORITATIVE_INFORMATION, Non-Authoritative Information) \
XX(204, NO_CONTENT, No Content) \
XX(205, RESET_CONTENT, Reset Content) \
XX(206, PARTIAL_CONTENT, Partial Content) \
XX(207, MULTI_STATUS, Multi-Status) \
XX(208, ALREADY_REPORTED, Already Reported) \
XX(226, IM_USED, IM Used) \
XX(300, MULTIPLE_CHOICES, Multiple Choices) \
XX(301, MOVED_PERMANENTLY, Moved Permanently) \
XX(302, FOUND, Found) \
XX(303, SEE_OTHER, See Other) \
XX(304, NOT_MODIFIED, Not Modified) \
XX(305, USE_PROXY, Use Proxy) \
XX(307, TEMPORARY_REDIRECT, Temporary Redirect) \
XX(308, PERMANENT_REDIRECT, Permanent Redirect) \
XX(400, BAD_REQUEST, Bad Request) \
XX(401, UNAUTHORIZED, Unauthorized) \
XX(402, PAYMENT_REQUIRED, Payment Required) \
XX(403, FORBIDDEN, Forbidden) \
XX(404, NOT_FOUND, Not Found) \
XX(405, METHOD_NOT_ALLOWED, Method Not Allowed) \
XX(406, NOT_ACCEPTABLE, Not Acceptable) \
XX(407, PROXY_AUTHENTICATION_REQUIRED, Proxy Authentication Required) \
XX(408, REQUEST_TIMEOUT, Request Timeout) \
XX(409, CONFLICT, Conflict) \
XX(410, GONE, Gone) \
XX(411, LENGTH_REQUIRED, Length Required) \
XX(412, PRECONDITION_FAILED, Precondition Failed) \
XX(413, PAYLOAD_TOO_LARGE, Payload Too Large) \
XX(414, URI_TOO_LONG, URI Too Long) \
XX(415, UNSUPPORTED_MEDIA_TYPE, Unsupported Media Type) \
XX(416, RANGE_NOT_SATISFIABLE, Range Not Satisfiable) \
XX(417, EXPECTATION_FAILED, Expectation Failed) \
XX(421, MISDIRECTED_REQUEST, Misdirected Request) \
XX(422, UNPROCESSABLE_ENTITY, Unprocessable Entity) \
XX(423, LOCKED, Locked) \
XX(424, FAILED_DEPENDENCY, Failed Dependency) \
XX(426, UPGRADE_REQUIRED, Upgrade Required) \
XX(428, PRECONDITION_REQUIRED, Precondition Required) \
XX(429, TOO_MANY_REQUESTS, Too Many Requests) \
XX(431, REQUEST_HEADER_FIELDS_TOO_LARGE, Request Header Fields Too Large) \
XX(451, UNAVAILABLE_FOR_LEGAL_REASONS, Unavailable For Legal Reasons) \
XX(500, INTERNAL_SERVER_ERROR, Internal Server Error) \
XX(501, NOT_IMPLEMENTED, Not Implemented) \
XX(502, BAD_GATEWAY, Bad Gateway) \
XX(503, SERVICE_UNAVAILABLE, Service Unavailable) \
XX(504, GATEWAY_TIMEOUT, Gateway Timeout) \
XX(505, HTTP_VERSION_NOT_SUPPORTED, HTTP Version Not Supported) \
XX(506, VARIANT_ALSO_NEGOTIATES, Variant Also Negotiates) \
XX(507, INSUFFICIENT_STORAGE, Insufficient Storage) \
XX(508, LOOP_DETECTED, Loop Detected) \
XX(510, NOT_EXTENDED, Not Extended) \
XX(511, NETWORK_AUTHENTICATION_REQUIRED, Network Authentication Required) \
enum http_status
{
#define XX(num, name, string) HTTP_STATUS_##name = num,
HTTP_STATUS_MAP(XX)
#undef XX
};
/* Request Methods */
#define HTTP_METHOD_MAP(XX) \
XX(0, DELETE, DELETE) \
XX(1, GET, GET) \
XX(2, HEAD, HEAD) \
XX(3, POST, POST) \
XX(4, PUT, PUT) \
/* pathological */ \
XX(5, CONNECT, CONNECT) \
XX(6, OPTIONS, OPTIONS) \
XX(7, TRACE, TRACE) \
/* WebDAV */ \
XX(8, COPY, COPY) \
XX(9, LOCK, LOCK) \
XX(10, MKCOL, MKCOL) \
XX(11, MOVE, MOVE) \
XX(12, PROPFIND, PROPFIND) \
XX(13, PROPPATCH, PROPPATCH) \
XX(14, SEARCH, SEARCH) \
XX(15, UNLOCK, UNLOCK) \
XX(16, BIND, BIND) \
XX(17, REBIND, REBIND) \
XX(18, UNBIND, UNBIND) \
XX(19, ACL, ACL) \
/* subversion */ \
XX(20, REPORT, REPORT) \
XX(21, MKACTIVITY, MKACTIVITY) \
XX(22, CHECKOUT, CHECKOUT) \
XX(23, MERGE, MERGE) \
/* upnp */ \
XX(24, MSEARCH, M-SEARCH) \
XX(25, NOTIFY, NOTIFY) \
XX(26, SUBSCRIBE, SUBSCRIBE) \
XX(27, UNSUBSCRIBE, UNSUBSCRIBE) \
/* RFC-5789 */ \
XX(28, PATCH, PATCH) \
XX(29, PURGE, PURGE) \
/* CalDAV */ \
XX(30, MKCALENDAR, MKCALENDAR) \
/* RFC-2068, section 19.6.1.2 */ \
XX(31, LINK, LINK) \
XX(32, UNLINK, UNLINK) \
/* icecast */ \
XX(33, SOURCE, SOURCE) \
enum http_method
{
#define XX(num, name, string) HTTP_##name = num,
HTTP_METHOD_MAP(XX)
#undef XX
};
enum http_parser_type { HTTP_REQUEST, HTTP_RESPONSE, HTTP_BOTH };
/* Flag values for http_parser.flags field */
enum flags
{ F_CHUNKED = 1 << 0
, F_CONNECTION_KEEP_ALIVE = 1 << 1
, F_CONNECTION_CLOSE = 1 << 2
, F_CONNECTION_UPGRADE = 1 << 3
, F_TRAILING = 1 << 4
, F_UPGRADE = 1 << 5
, F_SKIPBODY = 1 << 6
, F_CONTENTLENGTH = 1 << 7
};
/* Map for errno-related constants
*
* The provided argument should be a macro that takes 2 arguments.
*/
#define HTTP_ERRNO_MAP(XX) \
/* No error */ \
XX(OK, "success") \
\
/* Callback-related errors */ \
XX(CB_message_begin, "the on_message_begin callback failed") \
XX(CB_url, "the on_url callback failed") \
XX(CB_header_field, "the on_header_field callback failed") \
XX(CB_header_value, "the on_header_value callback failed") \
XX(CB_headers_complete, "the on_headers_complete callback failed") \
XX(CB_body, "the on_body callback failed") \
XX(CB_message_complete, "the on_message_complete callback failed") \
XX(CB_status, "the on_status callback failed") \
XX(CB_chunk_header, "the on_chunk_header callback failed") \
XX(CB_chunk_complete, "the on_chunk_complete callback failed") \
\
/* Parsing-related errors */ \
XX(INVALID_EOF_STATE, "stream ended at an unexpected time") \
XX(HEADER_OVERFLOW, \
"too many header bytes seen; overflow detected") \
XX(CLOSED_CONNECTION, \
"data received after completed connection: close message") \
XX(INVALID_VERSION, "invalid HTTP version") \
XX(INVALID_STATUS, "invalid HTTP status code") \
XX(INVALID_METHOD, "invalid HTTP method") \
XX(INVALID_URL, "invalid URL") \
XX(INVALID_HOST, "invalid host") \
XX(INVALID_PORT, "invalid port") \
XX(INVALID_PATH, "invalid path") \
XX(INVALID_QUERY_STRING, "invalid query string") \
XX(INVALID_FRAGMENT, "invalid fragment") \
XX(LF_EXPECTED, "LF character expected") \
XX(INVALID_HEADER_TOKEN, "invalid character in header") \
XX(INVALID_CONTENT_LENGTH, \
"invalid character in content-length header") \
XX(UNEXPECTED_CONTENT_LENGTH, \
"unexpected content-length header") \
XX(INVALID_CHUNK_SIZE, \
"invalid character in chunk size header") \
XX(INVALID_CONSTANT, "invalid constant string") \
XX(INVALID_INTERNAL_STATE, "encountered unexpected internal state")\
XX(STRICT, "strict mode assertion failed") \
XX(PAUSED, "parser is paused") \
XX(UNKNOWN, "an unknown error occurred")
/* Define HPE_* values for each errno value above */
#define HTTP_ERRNO_GEN(n, s) HPE_##n,
enum http_errno {
HTTP_ERRNO_MAP(HTTP_ERRNO_GEN)
};
#undef HTTP_ERRNO_GEN
/* Get an http_errno value from an http_parser */
#define HTTP_PARSER_ERRNO(p) ((enum http_errno) (p)->http_errno)
struct http_parser {
/** PRIVATE **/
unsigned int type : 2; /* enum http_parser_type */
unsigned int flags : 8; /* F_* values from 'flags' enum; semi-public */
unsigned int state : 7; /* enum state from http_parser.c */
unsigned int header_state : 7; /* enum header_state from http_parser.c */
unsigned int index : 7; /* index into current matcher */
unsigned int lenient_http_headers : 1;
uint32_t nread; /* # bytes read in various scenarios */
uint64_t content_length; /* # bytes in body (0 if no Content-Length header) */
/** READ-ONLY **/
unsigned short http_major;
unsigned short http_minor;
unsigned int status_code : 16; /* responses only */
unsigned int method : 8; /* requests only */
unsigned int http_errno : 7;
/* 1 = Upgrade header was present and the parser has exited because of that.
* 0 = No upgrade header present.
* Should be checked when http_parser_execute() returns in addition to
* error checking.
*/
unsigned int upgrade : 1;
/** PUBLIC **/
void *data; /* A pointer to get hook to the "connection" or "socket" object */
};
struct http_parser_settings {
http_cb on_message_begin;
http_data_cb on_url;
http_data_cb on_status;
http_data_cb on_header_field;
http_data_cb on_header_value;
http_cb on_headers_complete;
http_data_cb on_body;
http_cb on_message_complete;
/* When on_chunk_header is called, the current chunk length is stored
* in parser->content_length.
*/
http_cb on_chunk_header;
http_cb on_chunk_complete;
};
enum http_parser_url_fields
{ UF_SCHEMA = 0
, UF_HOST = 1
, UF_PORT = 2
, UF_PATH = 3
, UF_QUERY = 4
, UF_FRAGMENT = 5
, UF_USERINFO = 6
, UF_MAX = 7
};
/* Result structure for http_parser_parse_url().
*
* Callers should index into field_data[] with UF_* values iff field_set
* has the relevant (1 << UF_*) bit set. As a courtesy to clients (and
* because we probably have padding left over), we convert any port to
* a uint16_t.
*/
struct http_parser_url {
uint16_t field_set; /* Bitmask of (1 << UF_*) values */
uint16_t port; /* Converted UF_PORT string */
struct {
uint16_t off; /* Offset into buffer in which field starts */
uint16_t len; /* Length of run in buffer */
} field_data[UF_MAX];
};
/* Returns the library version. Bits 16-23 contain the major version number,
* bits 8-15 the minor version number and bits 0-7 the patch level.
* Usage example:
*
* unsigned long version = http_parser_version();
* unsigned major = (version >> 16) & 255;
* unsigned minor = (version >> 8) & 255;
* unsigned patch = version & 255;
* printf("http_parser v%u.%u.%u\n", major, minor, patch);
*/
unsigned long http_parser_version(void);
void http_parser_init(http_parser *parser, enum http_parser_type type);
/* Initialize http_parser_settings members to 0
*/
void http_parser_settings_init(http_parser_settings *settings);
/* Executes the parser. Returns number of parsed bytes. Sets
* `parser->http_errno` on error. */
size_t http_parser_execute(http_parser *parser,
const http_parser_settings *settings,
const char *data,
size_t len);
/* If http_should_keep_alive() in the on_headers_complete or
* on_message_complete callback returns 0, then this should be
* the last message on the connection.
* If you are the server, respond with the "Connection: close" header.
* If you are the client, close the connection.
*/
int http_should_keep_alive(const http_parser *parser);
/* Returns a string version of the HTTP method. */
const char *http_method_str(enum http_method m);
/* Returns a string version of the HTTP status code. */
const char *http_status_str(enum http_status s);
/* Return a string name of the given error */
const char *http_errno_name(enum http_errno err);
/* Return a string description of the given error */
const char *http_errno_description(enum http_errno err);
/* Initialize all http_parser_url members to 0 */
void http_parser_url_init(struct http_parser_url *u);
/* Parse a URL; return nonzero on failure */
int http_parser_parse_url(const char *buf, size_t buflen,
int is_connect,
struct http_parser_url *u);
/* Pause or un-pause the parser; a nonzero value pauses */
void http_parser_pause(http_parser *parser, int paused);
/* Checks if this is the final chunk of the body. */
int http_body_is_final(const http_parser *parser);
/* Change the maximum header size provided at compile time. */
void http_parser_set_max_header_size(uint32_t size);
#ifdef __cplusplus
}
#endif
#endif

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -1,339 +0,0 @@
/* XMRig
* Copyright 2010 Jeff Garzik <jgarzik@pobox.com>
* Copyright 2012-2014 pooler <pooler@litecoinpool.org>
* Copyright 2014 Lucas Jones <https://github.com/lucasjones>
* Copyright 2014-2016 Wolf9466 <https://github.com/OhGodAPet>
* Copyright 2016 Jay D Dee <jayddee246@gmail.com>
* Copyright 2017-2018 XMR-Stak <https://github.com/fireice-uk>, <https://github.com/psychocrypt>
* Copyright 2018-2019 SChernykh <https://github.com/SChernykh>
* Copyright 2016-2019 XMRig <https://github.com/xmrig>, <support@xmrig.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <math.h>
#include <string.h>
#include <uv.h>
#if _WIN32
# include "winsock2.h"
#else
# include "unistd.h"
#endif
#include "api/ApiRouter.h"
#include "base/tools/Buffer.h"
#include "common/api/HttpReply.h"
#include "common/api/HttpRequest.h"
#include "common/cpu/Cpu.h"
#include "common/crypto/keccak.h"
#include "common/Platform.h"
#include "core/Config.h"
#include "core/Controller.h"
#include "interfaces/IThread.h"
#include "rapidjson/document.h"
#include "rapidjson/prettywriter.h"
#include "rapidjson/stringbuffer.h"
#include "version.h"
#include "workers/Hashrate.h"
#include "workers/Workers.h"
static inline double normalize(double d)
{
if (!isnormal(d)) {
return 0.0;
}
return floor(d * 100.0) / 100.0;
}
ApiRouter::ApiRouter(xmrig::Controller *controller) :
m_controller(controller)
{
memset(m_workerId, 0, sizeof(m_workerId));
setWorkerId(controller->config()->apiWorkerId());
genId(controller->config()->apiId());
}
ApiRouter::~ApiRouter()
{
}
void ApiRouter::ApiRouter::get(const xmrig::HttpRequest &req, xmrig::HttpReply &reply) const
{
rapidjson::Document doc;
if (req.match("/1/config")) {
if (req.isRestricted()) {
reply.status = 403;
return;
}
m_controller->config()->getJSON(doc);
return finalize(reply, doc);
}
if (req.match("/1/threads")) {
getThreads(doc);
return finalize(reply, doc);
}
doc.SetObject();
getIdentify(doc);
getMiner(doc);
getHashrate(doc);
getResults(doc);
getConnection(doc);
return finalize(reply, doc);
}
void ApiRouter::exec(const xmrig::HttpRequest &req, xmrig::HttpReply &reply)
{
if (req.method() == xmrig::HttpRequest::Put && req.match("/1/config")) {
m_controller->config()->reload(req.body());
return;
}
reply.status = 404;
}
void ApiRouter::tick(const xmrig::NetworkState &network)
{
m_network = network;
}
void ApiRouter::onConfigChanged(xmrig::Config *config, xmrig::Config *previousConfig)
{
updateWorkerId(config->apiWorkerId(), previousConfig->apiWorkerId());
}
void ApiRouter::finalize(xmrig::HttpReply &reply, rapidjson::Document &doc) const
{
rapidjson::StringBuffer buffer(nullptr, 4096);
rapidjson::PrettyWriter<rapidjson::StringBuffer> writer(buffer);
writer.SetMaxDecimalPlaces(10);
doc.Accept(writer);
reply.status = 200;
reply.buf = strdup(buffer.GetString());
reply.size = buffer.GetSize();
}
void ApiRouter::genId(const char *id)
{
memset(m_id, 0, sizeof(m_id));
if (id && strlen(id) > 0) {
strncpy(m_id, id, sizeof(m_id) - 1);
return;
}
uv_interface_address_t *interfaces;
int count = 0;
if (uv_interface_addresses(&interfaces, &count) < 0) {
return;
}
for (int i = 0; i < count; i++) {
if (!interfaces[i].is_internal && interfaces[i].address.address4.sin_family == AF_INET) {
uint8_t hash[200];
const size_t addrSize = sizeof(interfaces[i].phys_addr);
const size_t inSize = strlen(APP_KIND) + addrSize + sizeof(uint16_t);
const uint16_t port = static_cast<uint16_t>(m_controller->config()->apiPort());
uint8_t *input = new uint8_t[inSize]();
memcpy(input, &port, sizeof(uint16_t));
memcpy(input + sizeof(uint16_t), interfaces[i].phys_addr, addrSize);
memcpy(input + sizeof(uint16_t) + addrSize, APP_KIND, strlen(APP_KIND));
xmrig::keccak(input, inSize, hash);
xmrig::Buffer::toHex(hash, 8, m_id);
delete [] input;
break;
}
}
uv_free_interface_addresses(interfaces, count);
}
void ApiRouter::getConnection(rapidjson::Document &doc) const
{
auto &allocator = doc.GetAllocator();
rapidjson::Value connection(rapidjson::kObjectType);
connection.AddMember("pool", rapidjson::StringRef(m_network.pool), allocator);
connection.AddMember("uptime", m_network.connectionTime(), allocator);
connection.AddMember("ping", m_network.latency(), allocator);
connection.AddMember("failures", m_network.failures, allocator);
connection.AddMember("error_log", rapidjson::Value(rapidjson::kArrayType), allocator);
doc.AddMember("connection", connection, allocator);
}
void ApiRouter::getHashrate(rapidjson::Document &doc) const
{
auto &allocator = doc.GetAllocator();
rapidjson::Value hashrate(rapidjson::kObjectType);
rapidjson::Value total(rapidjson::kArrayType);
rapidjson::Value threads(rapidjson::kArrayType);
const Hashrate *hr = Workers::hashrate();
total.PushBack(normalize(hr->calc(Hashrate::ShortInterval)), allocator);
total.PushBack(normalize(hr->calc(Hashrate::MediumInterval)), allocator);
total.PushBack(normalize(hr->calc(Hashrate::LargeInterval)), allocator);
for (size_t i = 0; i < Workers::threads(); i++) {
rapidjson::Value thread(rapidjson::kArrayType);
thread.PushBack(normalize(hr->calc(i, Hashrate::ShortInterval)), allocator);
thread.PushBack(normalize(hr->calc(i, Hashrate::MediumInterval)), allocator);
thread.PushBack(normalize(hr->calc(i, Hashrate::LargeInterval)), allocator);
threads.PushBack(thread, allocator);
}
hashrate.AddMember("total", total, allocator);
hashrate.AddMember("highest", normalize(hr->highest()), allocator);
hashrate.AddMember("threads", threads, allocator);
doc.AddMember("hashrate", hashrate, allocator);
}
void ApiRouter::getIdentify(rapidjson::Document &doc) const
{
doc.AddMember("id", rapidjson::StringRef(m_id), doc.GetAllocator());
doc.AddMember("worker_id", rapidjson::StringRef(m_workerId), doc.GetAllocator());
}
void ApiRouter::getMiner(rapidjson::Document &doc) const
{
using namespace xmrig;
auto &allocator = doc.GetAllocator();
rapidjson::Value cpu(rapidjson::kObjectType);
cpu.AddMember("brand", rapidjson::StringRef(Cpu::info()->brand()), allocator);
cpu.AddMember("aes", Cpu::info()->hasAES(), allocator);
cpu.AddMember("x64", Cpu::info()->isX64(), allocator);
cpu.AddMember("sockets", Cpu::info()->sockets(), allocator);
doc.AddMember("version", APP_VERSION, allocator);
doc.AddMember("kind", APP_KIND, allocator);
doc.AddMember("ua", rapidjson::StringRef(Platform::userAgent()), allocator);
doc.AddMember("cpu", cpu, allocator);
doc.AddMember("algo", rapidjson::StringRef(m_controller->config()->algorithm().name()), allocator);
doc.AddMember("hugepages", Workers::hugePages() > 0, allocator);
doc.AddMember("donate_level", m_controller->config()->pools().donateLevel(), allocator);
}
void ApiRouter::getResults(rapidjson::Document &doc) const
{
auto &allocator = doc.GetAllocator();
rapidjson::Value results(rapidjson::kObjectType);
results.AddMember("diff_current", m_network.diff, allocator);
results.AddMember("shares_good", m_network.accepted, allocator);
results.AddMember("shares_total", m_network.accepted + m_network.rejected, allocator);
results.AddMember("avg_time", m_network.avgTime(), allocator);
results.AddMember("hashes_total", m_network.total, allocator);
rapidjson::Value best(rapidjson::kArrayType);
for (size_t i = 0; i < m_network.topDiff.size(); ++i) {
best.PushBack(m_network.topDiff[i], allocator);
}
results.AddMember("best", best, allocator);
results.AddMember("error_log", rapidjson::Value(rapidjson::kArrayType), allocator);
doc.AddMember("results", results, allocator);
}
void ApiRouter::getThreads(rapidjson::Document &doc) const
{
doc.SetObject();
auto &allocator = doc.GetAllocator();
const Hashrate *hr = Workers::hashrate();
Workers::threadsSummary(doc);
const std::vector<xmrig::IThread *> &threads = m_controller->config()->threads();
rapidjson::Value list(rapidjson::kArrayType);
size_t i = 0;
for (const xmrig::IThread *thread : threads) {
rapidjson::Value value = thread->toAPI(doc);
rapidjson::Value hashrate(rapidjson::kArrayType);
hashrate.PushBack(normalize(hr->calc(i, Hashrate::ShortInterval)), allocator);
hashrate.PushBack(normalize(hr->calc(i, Hashrate::MediumInterval)), allocator);
hashrate.PushBack(normalize(hr->calc(i, Hashrate::LargeInterval)), allocator);
i++;
value.AddMember("hashrate", hashrate, allocator);
list.PushBack(value, allocator);
}
doc.AddMember("threads", list, allocator);
}
void ApiRouter::setWorkerId(const char *id)
{
memset(m_workerId, 0, sizeof(m_workerId));
if (id && strlen(id) > 0) {
strncpy(m_workerId, id, sizeof(m_workerId) - 1);
}
else {
gethostname(m_workerId, sizeof(m_workerId) - 1);
}
}
void ApiRouter::updateWorkerId(const char *id, const char *previousId)
{
if (id == previousId) {
return;
}
if (id != nullptr && previousId != nullptr && strcmp(id, previousId) == 0) {
return;
}
setWorkerId(id);
}

View file

@ -1,76 +0,0 @@
/* XMRig
* Copyright 2010 Jeff Garzik <jgarzik@pobox.com>
* Copyright 2012-2014 pooler <pooler@litecoinpool.org>
* Copyright 2014 Lucas Jones <https://github.com/lucasjones>
* Copyright 2014-2016 Wolf9466 <https://github.com/OhGodAPet>
* Copyright 2016 Jay D Dee <jayddee246@gmail.com>
* Copyright 2017-2018 XMR-Stak <https://github.com/fireice-uk>, <https://github.com/psychocrypt>
* Copyright 2018-2019 SChernykh <https://github.com/SChernykh>
* Copyright 2016-2019 XMRig <https://github.com/xmrig>, <support@xmrig.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef XMRIG_APIROUTER_H
#define XMRIG_APIROUTER_H
#include "api/NetworkState.h"
#include "common/interfaces/IControllerListener.h"
#include "rapidjson/fwd.h"
class Hashrate;
namespace xmrig {
class Controller;
class HttpReply;
class HttpRequest;
}
class ApiRouter : public xmrig::IControllerListener
{
public:
ApiRouter(xmrig::Controller *controller);
~ApiRouter() override;
void get(const xmrig::HttpRequest &req, xmrig::HttpReply &reply) const;
void exec(const xmrig::HttpRequest &req, xmrig::HttpReply &reply);
void tick(const xmrig::NetworkState &results);
protected:
void onConfigChanged(xmrig::Config *config, xmrig::Config *previousConfig) override;
private:
void finalize(xmrig::HttpReply &reply, rapidjson::Document &doc) const;
void genId(const char *id);
void getConnection(rapidjson::Document &doc) const;
void getHashrate(rapidjson::Document &doc) const;
void getIdentify(rapidjson::Document &doc) const;
void getMiner(rapidjson::Document &doc) const;
void getResults(rapidjson::Document &doc) const;
void getThreads(rapidjson::Document &doc) const;
void setWorkerId(const char *id);
void updateWorkerId(const char *id, const char *previousId);
char m_id[32];
char m_workerId[128];
xmrig::NetworkState m_network;
xmrig::Controller *m_controller;
};
#endif /* XMRIG_APIROUTER_H */

164
src/api/Httpd.cpp Normal file
View 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;
}

View file

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

View file

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

View file

@ -0,0 +1,72 @@
/* XMRig
* Copyright 2010 Jeff Garzik <jgarzik@pobox.com>
* Copyright 2012-2014 pooler <pooler@litecoinpool.org>
* Copyright 2014 Lucas Jones <https://github.com/lucasjones>
* Copyright 2014-2016 Wolf9466 <https://github.com/OhGodAPet>
* Copyright 2016 Jay D Dee <jayddee246@gmail.com>
* Copyright 2016-2018 XMRig <support@xmrig.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef XMRIG_IAPIREQUEST_H
#define XMRIG_IAPIREQUEST_H
#include "rapidjson/fwd.h"
namespace xmrig {
class String;
class IApiRequest
{
public:
enum Method {
METHOD_DELETE,
METHOD_GET,
METHOD_HEAD,
METHOD_POST,
METHOD_PUT
};
enum Source {
SOURCE_HTTP
};
virtual ~IApiRequest() = default;
virtual bool isDone() const = 0;
virtual bool isNew() const = 0;
virtual bool isRestricted() const = 0;
virtual const rapidjson::Value &json() const = 0;
virtual const String &url() const = 0;
virtual Method method() const = 0;
virtual rapidjson::Document &doc() = 0;
virtual rapidjson::Value &reply() = 0;
virtual Source source() const = 0;
virtual void accept() = 0;
virtual void done(int status) = 0;
};
} /* namespace xmrig */
#endif // XMRIG_IAPIREQUEST_H

View file

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

View file

@ -0,0 +1,67 @@
/* XMRig
* Copyright 2010 Jeff Garzik <jgarzik@pobox.com>
* Copyright 2012-2014 pooler <pooler@litecoinpool.org>
* Copyright 2014 Lucas Jones <https://github.com/lucasjones>
* Copyright 2014-2016 Wolf9466 <https://github.com/OhGodAPet>
* Copyright 2016 Jay D Dee <jayddee246@gmail.com>
* Copyright 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

View file

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

View file

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

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -0,0 +1,99 @@
/* XMRig
* Copyright 2010 Jeff Garzik <jgarzik@pobox.com>
* Copyright 2012-2014 pooler <pooler@litecoinpool.org>
* Copyright 2014 Lucas Jones <https://github.com/lucasjones>
* Copyright 2014-2016 Wolf9466 <https://github.com/OhGodAPet>
* Copyright 2016 Jay D Dee <jayddee246@gmail.com>
* Copyright 2017-2018 XMR-Stak <https://github.com/fireice-uk>, <https://github.com/psychocrypt>
* Copyright 2018-2019 SChernykh <https://github.com/SChernykh>
* Copyright 2016-2019 XMRig <https://github.com/xmrig>, <support@xmrig.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "3rdparty/rapidjson/document.h"
#include "base/io/Json.h"
#include "base/net/http/Http.h"
namespace xmrig {
static const char *kEnabled = "enabled";
static const char *kHost = "host";
static const char *kLocalhost = "127.0.0.1";
static const char *kPort = "port";
static const char *kRestricted = "restricted";
static const char *kToken = "access-token";
}
xmrig::Http::Http() :
m_enabled(false),
m_restricted(true),
m_host(kLocalhost),
m_port(0)
{
}
bool xmrig::Http::isEqual(const Http &other) const
{
return other.m_enabled == m_enabled &&
other.m_restricted == m_restricted &&
other.m_host == m_host &&
other.m_token == m_token &&
other.m_port == m_port;
}
rapidjson::Value xmrig::Http::toJSON(rapidjson::Document &doc) const
{
using namespace rapidjson;
auto &allocator = doc.GetAllocator();
Value obj(kObjectType);
obj.AddMember(StringRef(kEnabled), m_enabled, allocator);
obj.AddMember(StringRef(kHost), m_host.toJSON(), allocator);
obj.AddMember(StringRef(kPort), m_port, allocator);
obj.AddMember(StringRef(kToken), m_token.toJSON(), allocator);
obj.AddMember(StringRef(kRestricted), m_restricted, allocator);
return obj;
}
void xmrig::Http::load(const rapidjson::Value &http)
{
if (!http.IsObject()) {
return;
}
m_enabled = Json::getBool(http, kEnabled);
m_restricted = Json::getBool(http, kRestricted, true);
m_host = Json::getString(http, kHost, kLocalhost);
m_token = Json::getString(http, kToken);
setPort(Json::getInt(http, kPort));
}
void xmrig::Http::setPort(int port)
{
if (port >= 0 && port <= 65536) {
m_port = static_cast<uint16_t>(port);
}
}

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

@ -0,0 +1,73 @@
/* XMRig
* Copyright 2010 Jeff Garzik <jgarzik@pobox.com>
* Copyright 2012-2014 pooler <pooler@litecoinpool.org>
* Copyright 2014 Lucas Jones <https://github.com/lucasjones>
* Copyright 2014-2016 Wolf9466 <https://github.com/OhGodAPet>
* Copyright 2016 Jay D Dee <jayddee246@gmail.com>
* Copyright 2017-2018 XMR-Stak <https://github.com/fireice-uk>, <https://github.com/psychocrypt>
* Copyright 2018-2019 SChernykh <https://github.com/SChernykh>
* Copyright 2016-2019 XMRig <https://github.com/xmrig>, <support@xmrig.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef XMRIG_HTTP_H
#define XMRIG_HTTP_H
#include "base/tools/String.h"
namespace xmrig {
class Http
{
public:
Http();
inline bool isAuthRequired() const { return m_restricted == false || !m_token.isNull(); }
inline bool isEnabled() const { return m_enabled; }
inline bool isRestricted() const { return m_restricted; }
inline const String &host() const { return m_host; }
inline const String &token() const { return m_token; }
inline uint16_t port() const { return m_port; }
inline void setEnabled(bool enabled) { m_enabled = enabled; }
inline void setHost(const char *host) { m_host = host; }
inline void setRestricted(bool restricted) { m_restricted = restricted; }
inline void setToken(const char *token) { m_token = token; }
inline bool operator!=(const Http &other) const { return !isEqual(other); }
inline bool operator==(const Http &other) const { return isEqual(other); }
bool isEqual(const Http &other) const;
rapidjson::Value toJSON(rapidjson::Document &doc) const;
void load(const rapidjson::Value &http);
void setPort(int port);
private:
bool m_enabled;
bool m_restricted;
String m_host;
String m_token;
uint16_t m_port;
};
} // namespace xmrig
#endif // XMRIG_HTTP_H

View file

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

View file

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

View file

@ -0,0 +1,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();
}

View file

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

View file

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

View 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();
}

View file

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

View file

@ -0,0 +1,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;
});
}

View file

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

View file

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

View file

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

View file

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

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

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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