diff --git a/CHANGELOG.md b/CHANGELOG.md index 951a3e2a1..2ae55e82b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,10 @@ +# v6.12.0 +- [#2276](https://github.com/xmrig/xmrig/pull/2276) Added support for Uplexa (`cn/upx2` algorithm). + +# v6.11.0 +- [#2196](https://github.com/xmrig/xmrig/pull/2196) Improved DNS subsystem and added new DNS specific options. +- [#2207](https://github.com/xmrig/xmrig/issues/2207) Fixed regression in HTTP parser and llhttp updated to v5.1.0. + # v6.10.1 - [#441](https://github.com/xmrig/xmrig-proxy/issues/441) Fixed send buffer overflow with custom diff. diff --git a/CMakeLists.txt b/CMakeLists.txt index 08b8951a6..f916f7542 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -148,6 +148,7 @@ add_definitions(/DXMRIG_ALGO_CN_LITE) add_definitions(/DXMRIG_ALGO_CN_HEAVY) add_definitions(/DXMRIG_ALGO_CN_PICO) add_definitions(/DXMRIG_ALGO_CN_GPU) +add_definitions(/DXMRIG_ALGO_CN_FEMTO) add_definitions(/DXMRIG_ALGO_ARGON2) add_definitions(/DXMRIG_ALGO_ASTROBWT) diff --git a/README.md b/README.md index fb3a59d79..6c734a233 100644 --- a/README.md +++ b/README.md @@ -30,45 +30,70 @@ Use [config.xmrig.com](https://config.xmrig.com/proxy) to generate, edit or shar ### Options ``` - -b, --bind=ADDR bind to specified address, example "0.0.0.0:3333" - -a, --algo=ALGO mining algorithm https://xmrig.com/docs/algorithms - --coin=COIN specify coin instead of algorithm - -m, --mode=MODE proxy mode, nicehash (default) or simple - -o, --url=URL URL of mining server - -O, --userpass=U:P username:password pair for mining server - -u, --user=USERNAME username for mining server - -p, --pass=PASSWORD password for mining server - -r, --retries=N number of times to retry before switch to backup server (default: 1) - -R, --retry-pause=N time to pause between retries (default: 1 second) - --custom-diff=N override pool diff - --reuse-timeout=N timeout in seconds for reuse pool connections in simple mode - --verbose verbose output - --user-agent=AGENT set custom user-agent string for pool - --no-color disable colored output - --no-workers disable per worker statistics - --variant algorithm PoW variant - --donate-level=N donate level, default 2% - -B, --background run the miner in the background - -c, --config=FILE load a JSON-format configuration file - --no-watch disable configuration file watching - -l, --log-file=FILE log all output to a file - -S, --syslog use system log for output messages - -A --access-log-file=N log all workers access to a file - --api-port=N port for the miner API - --api-access-token=T use Bearer access token for API - --api-worker-id=ID custom worker-id for API - --api-no-ipv6 disable IPv6 support for API - --api-no-restricted enable full remote access (only if API token set) - --tls enable SSL/TLS support for pool connection (needs pool support) - --tls-bind=ADDR bind to specified address with enabled TLS - --tls-cert=FILE load TLS certificate chain from a file in the PEM format - --tls-cert-key=FILE load TLS certificate private key from a file in the PEM format - --tls-dhparam=FILE load DH parameters for DHE ciphers from a file in the PEM format - --tls-protocols=N enable specified TLS protocols, example: "TLSv1 TLSv1.1 TLSv1.2 TLSv1.3" - --tls-ciphers=S set list of available ciphers (TLSv1.2 and below) - --tls-ciphersuites=S set list of available TLSv1.3 ciphersuites - -h, --help display this help and exit - -V, --version output version information and exit +Network: + -o, --url=URL URL of mining server + -a, --algo=ALGO mining algorithm https://xmrig.com/docs/algorithms + --coin=COIN specify coin instead of algorithm + -u, --user=USERNAME username for mining server + -p, --pass=PASSWORD password for mining server + -O, --userpass=U:P username:password pair for mining server + -x, --proxy=HOST:PORT connect through a SOCKS5 proxy + -k, --keepalive send keepalived packet for prevent timeout (needs pool support) + --rig-id=ID rig identifier for pool-side statistics (needs pool support) + --tls enable SSL/TLS support (needs pool support) + --tls-fingerprint=HEX pool TLS certificate fingerprint for strict certificate pinning + --dns-ipv6 prefer IPv6 records from DNS responses + --dns-ttl=N N seconds (default: 30) TTL for internal DNS cache + --daemon use daemon RPC instead of pool for solo mining + --daemon-poll-interval=N daemon poll interval in milliseconds (default: 1000) + --self-select=URL self-select block templates from URL + --submit-to-origin also submit solution back to self-select URL + -r, --retries=N number of times to retry before switch to backup server (default: 5) + -R, --retry-pause=N time to pause between retries (default: 5) + --user-agent set custom user-agent string for pool + --donate-level=N donate level, default 0%% + +Options: + -b, --bind=ADDR bind to specified address, example "0.0.0.0:3333" + -m, --mode=MODE proxy mode, nicehash (default) or simple + --custom-diff=N override pool diff + --custom-diff-stats calculate stats using custom diff shares instead of pool shares + --reuse-timeout=N timeout in seconds for reuse pool connections in simple mode + --no-workers disable per worker statistics + --access-password=P set password to restrict connections to the proxy + --no-algo-ext disable "algo" protocol extension + +API: + --api-worker-id=ID custom worker-id for API + --api-id=ID custom instance ID for API + --http-host=HOST bind host for HTTP API (default: 127.0.0.1) + --http-port=N bind port for HTTP API + --http-access-token=T access token for HTTP API + --http-no-restricted enable full remote access to HTTP API (only if access token set) + +TLS: + --tls-bind=ADDR bind to specified address with enabled TLS + --tls-gen=HOSTNAME generate TLS certificate for specific hostname + --tls-cert=FILE load TLS certificate chain from a file in the PEM format + --tls-cert-key=FILE load TLS certificate private key from a file in the PEM format + --tls-dhparam=FILE load DH parameters for DHE ciphers from a file in the PEM format + --tls-protocols=N enable specified TLS protocols, example: "TLSv1 TLSv1.1 TLSv1.2 TLSv1.3" + --tls-ciphers=S set list of available ciphers (TLSv1.2 and below) + --tls-ciphersuites=S set list of available TLSv1.3 ciphersuites + +Logging: + -S, --syslog use system log for output messages + -l, --log-file=FILE log all output to a file + -A --access-log-file=FILE log all workers access to a file + --no-color disable colored output + --verbose verbose output + +Misc: + -c, --config=FILE load a JSON-format configuration file + -B, --background run the proxy in the background + -V, --version output version information and exit + -h, --help display this help and exit + --dry-run test configuration and exit ``` ## Donations @@ -76,7 +101,6 @@ Use [config.xmrig.com](https://config.xmrig.com/proxy) to generate, edit or shar Default donation fee is 2% can be reduced to 1% or disabled via `donate-level` option. Donation fee applies only if you use more than 256 miners. * XMR: `48edfHu7V9Z84YzzMa6fUueoELZ9ZRXq9VetWzYGzKt52XU5xvqgzYnDK9URnRoJMk1j8nLwEVsaSWJ4fhdUyZijBGUicoD` -* BTC: `1P7ujsXeX7GxQwHNnJsRMgAdNkFZmNVqJT` ## Contacts * support@xmrig.com diff --git a/src/3rdparty/llhttp/api.c b/src/3rdparty/llhttp/api.c index 0f9b56777..8a4bdd26b 100644 --- a/src/3rdparty/llhttp/api.c +++ b/src/3rdparty/llhttp/api.c @@ -24,6 +24,70 @@ void llhttp_init(llhttp_t* parser, llhttp_type_t type, } +#if defined(__wasm__) + +extern int wasm_on_message_begin(llhttp_t * p); +extern int wasm_on_url(llhttp_t* p, const char* at, size_t length); +extern int wasm_on_status(llhttp_t* p, const char* at, size_t length); +extern int wasm_on_header_field(llhttp_t* p, const char* at, size_t length); +extern int wasm_on_header_value(llhttp_t* p, const char* at, size_t length); +extern int wasm_on_headers_complete(llhttp_t * p); +extern int wasm_on_body(llhttp_t* p, const char* at, size_t length); +extern int wasm_on_message_complete(llhttp_t * p); + +const llhttp_settings_t wasm_settings = { + wasm_on_message_begin, + wasm_on_url, + wasm_on_status, + wasm_on_header_field, + wasm_on_header_value, + wasm_on_headers_complete, + wasm_on_body, + wasm_on_message_complete, + NULL, + NULL, +}; + + +llhttp_t* llhttp_alloc(llhttp_type_t type) { + llhttp_t* parser = malloc(sizeof(llhttp_t)); + llhttp_init(parser, type, &wasm_settings); + return parser; +} + +void llhttp_free(llhttp_t* parser) { + free(parser); +} + +/* Some getters required to get stuff from the parser */ + +uint8_t llhttp_get_type(llhttp_t* parser) { + return parser->type; +} + +uint8_t llhttp_get_http_major(llhttp_t* parser) { + return parser->http_major; +} + +uint8_t llhttp_get_http_minor(llhttp_t* parser) { + return parser->http_minor; +} + +uint8_t llhttp_get_method(llhttp_t* parser) { + return parser->method; +} + +int llhttp_get_status_code(llhttp_t* parser) { + return parser->status_code; +} + +uint8_t llhttp_get_upgrade(llhttp_t* parser) { + return parser->upgrade; +} + +#endif // defined(__wasm__) + + void llhttp_reset(llhttp_t* parser) { llhttp_type_t type = parser->type; const llhttp_settings_t* settings = parser->settings; @@ -150,6 +214,7 @@ void llhttp_set_lenient_headers(llhttp_t* parser, int enabled) { } } + void llhttp_set_lenient_chunked_length(llhttp_t* parser, int enabled) { if (enabled) { parser->lenient_flags |= LENIENT_CHUNKED_LENGTH; @@ -159,6 +224,14 @@ void llhttp_set_lenient_chunked_length(llhttp_t* parser, int enabled) { } +void llhttp_set_lenient_keep_alive(llhttp_t* parser, int enabled) { + if (enabled) { + parser->lenient_flags |= LENIENT_KEEP_ALIVE; + } else { + parser->lenient_flags &= ~LENIENT_KEEP_ALIVE; + } +} + /* Callbacks */ diff --git a/src/3rdparty/llhttp/api.h b/src/3rdparty/llhttp/api.h index f62c57fee..7fdbfc10d 100644 --- a/src/3rdparty/llhttp/api.h +++ b/src/3rdparty/llhttp/api.h @@ -5,6 +5,12 @@ extern "C" { #endif #include +#if defined(__wasm__) +#define LLHTTP_EXPORT __attribute__((visibility("default"))) +#else +#define LLHTTP_EXPORT +#endif + typedef llhttp__internal_t llhttp_t; typedef struct llhttp_settings_s llhttp_settings_t; @@ -55,15 +61,46 @@ struct llhttp_settings_s { * the `parser` here. In practice, `settings` has to be either a static * variable or be allocated with `malloc`, `new`, etc. */ +LLHTTP_EXPORT void llhttp_init(llhttp_t* parser, llhttp_type_t type, const llhttp_settings_t* settings); +#if defined(__wasm__) + +LLHTTP_EXPORT +llhttp_t* llhttp_alloc(llhttp_type_t type); + +LLHTTP_EXPORT +void llhttp_free(llhttp_t* parser); + +LLHTTP_EXPORT +uint8_t llhttp_get_type(llhttp_t* parser); + +LLHTTP_EXPORT +uint8_t llhttp_get_http_major(llhttp_t* parser); + +LLHTTP_EXPORT +uint8_t llhttp_get_http_minor(llhttp_t* parser); + +LLHTTP_EXPORT +uint8_t llhttp_get_method(llhttp_t* parser); + +LLHTTP_EXPORT +int llhttp_get_status_code(llhttp_t* parser); + +LLHTTP_EXPORT +uint8_t llhttp_get_upgrade(llhttp_t* parser); + +#endif // defined(__wasm__) + /* Reset an already initialized parser back to the start state, preserving the * existing parser type, callback settings, user data, and lenient flags. */ +LLHTTP_EXPORT void llhttp_reset(llhttp_t* parser); /* Initialize the settings object */ +LLHTTP_EXPORT void llhttp_settings_init(llhttp_settings_t* settings); /* Parse full or partial request/response, invoking user callbacks along the @@ -82,6 +119,7 @@ void llhttp_settings_init(llhttp_settings_t* settings); * to return the same error upon each successive call up until `llhttp_init()` * is called. */ +LLHTTP_EXPORT llhttp_errno_t llhttp_execute(llhttp_t* parser, const char* data, size_t len); /* This method should be called when the other side has no further bytes to @@ -92,16 +130,19 @@ llhttp_errno_t llhttp_execute(llhttp_t* parser, const char* data, size_t len); * connection. This method will invoke `on_message_complete()` callback if the * request was terminated safely. Otherwise a error code would be returned. */ +LLHTTP_EXPORT llhttp_errno_t llhttp_finish(llhttp_t* parser); /* Returns `1` if the incoming message is parsed until the last byte, and has * to be completed by calling `llhttp_finish()` on EOF */ +LLHTTP_EXPORT int llhttp_message_needs_eof(const llhttp_t* parser); /* Returns `1` if there might be any other messages following the last that was * successfully parsed. */ +LLHTTP_EXPORT int llhttp_should_keep_alive(const llhttp_t* parser); /* Make further calls of `llhttp_execute()` return `HPE_PAUSED` and set @@ -110,6 +151,7 @@ int llhttp_should_keep_alive(const llhttp_t* parser); * Important: do not call this from user callbacks! User callbacks must return * `HPE_PAUSED` if pausing is required. */ +LLHTTP_EXPORT void llhttp_pause(llhttp_t* parser); /* Might be called to resume the execution after the pause in user's callback. @@ -117,6 +159,7 @@ void llhttp_pause(llhttp_t* parser); * * Call this only if `llhttp_execute()` returns `HPE_PAUSED`. */ +LLHTTP_EXPORT void llhttp_resume(llhttp_t* parser); /* Might be called to resume the execution after the pause in user's callback. @@ -124,9 +167,11 @@ void llhttp_resume(llhttp_t* parser); * * Call this only if `llhttp_execute()` returns `HPE_PAUSED_UPGRADE` */ +LLHTTP_EXPORT void llhttp_resume_after_upgrade(llhttp_t* parser); /* Returns the latest return error */ +LLHTTP_EXPORT llhttp_errno_t llhttp_get_errno(const llhttp_t* parser); /* Returns the verbal explanation of the latest returned error. @@ -134,6 +179,7 @@ llhttp_errno_t llhttp_get_errno(const llhttp_t* parser); * Note: User callback should set error reason when returning the error. See * `llhttp_set_error_reason()` for details. */ +LLHTTP_EXPORT const char* llhttp_get_error_reason(const llhttp_t* parser); /* Assign verbal description to the returned error. Must be called in user @@ -141,6 +187,7 @@ const char* llhttp_get_error_reason(const llhttp_t* parser); * * Note: `HPE_USER` error code might be useful in user callbacks. */ +LLHTTP_EXPORT void llhttp_set_error_reason(llhttp_t* parser, const char* reason); /* Returns the pointer to the last parsed byte before the returned error. The @@ -148,12 +195,15 @@ void llhttp_set_error_reason(llhttp_t* parser, const char* reason); * * Note: this method might be useful for counting the number of parsed bytes. */ +LLHTTP_EXPORT const char* llhttp_get_error_pos(const llhttp_t* parser); /* Returns textual name of error code */ +LLHTTP_EXPORT const char* llhttp_errno_name(llhttp_errno_t err); /* Returns textual name of HTTP method */ +LLHTTP_EXPORT const char* llhttp_method_name(llhttp_method_t method); @@ -166,6 +216,7 @@ const char* llhttp_method_name(llhttp_method_t method); * * **(USE AT YOUR OWN RISK)** */ +LLHTTP_EXPORT void llhttp_set_lenient_headers(llhttp_t* parser, int enabled); @@ -179,8 +230,23 @@ void llhttp_set_lenient_headers(llhttp_t* parser, int enabled); * * **(USE AT YOUR OWN RISK)** */ +LLHTTP_EXPORT void llhttp_set_lenient_chunked_length(llhttp_t* parser, int enabled); + +/* Enables/disables lenient handling of `Connection: close` and HTTP/1.0 + * requests responses. + * + * Normally `llhttp` would error on (in strict mode) or discard (in loose mode) + * the HTTP request/response after the request/response with `Connection: close` + * and `Content-Length`. This is important to prevent cache poisoning attacks, + * but might interact badly with outdated and insecure clients. With this flag + * the extra request/response will be parsed normally. + * + * **(USE AT YOUR OWN RISK)** + */ +void llhttp_set_lenient_keep_alive(llhttp_t* parser, int enabled); + #ifdef __cplusplus } /* extern "C" */ #endif diff --git a/src/3rdparty/llhttp/llhttp.c b/src/3rdparty/llhttp/llhttp.c index 33ddcb295..a8efce103 100644 --- a/src/3rdparty/llhttp/llhttp.c +++ b/src/3rdparty/llhttp/llhttp.c @@ -627,6 +627,13 @@ int llhttp__internal__c_update_finish_1( return 0; } +int llhttp__internal__c_test_lenient_flags( + llhttp__internal_t* state, + const unsigned char* p, + const unsigned char* endp) { + return (state->lenient_flags & 4) == 4; +} + int llhttp__internal__c_test_flags_1( llhttp__internal_t* state, const unsigned char* p, @@ -634,7 +641,7 @@ int llhttp__internal__c_test_flags_1( return (state->flags & 544) == 544; } -int llhttp__internal__c_test_lenient_flags( +int llhttp__internal__c_test_lenient_flags_1( llhttp__internal_t* state, const unsigned char* p, const unsigned char* endp) { @@ -802,7 +809,7 @@ int llhttp__internal__c_update_header_state_2( return 0; } -int llhttp__internal__c_test_lenient_flags_1( +int llhttp__internal__c_test_lenient_flags_2( llhttp__internal_t* state, const unsigned char* p, const unsigned char* endp) { @@ -1661,7 +1668,7 @@ static llparse_state_t llhttp__internal__run( goto s_n_llhttp__internal__n_span_end_llhttp__on_header_value_2; } default: { - goto s_n_llhttp__internal__n_invoke_test_lenient_flags_1; + goto s_n_llhttp__internal__n_invoke_test_lenient_flags_2; } } /* UNREACHABLE */; @@ -5733,10 +5740,20 @@ static llparse_state_t llhttp__internal__run( /* UNREACHABLE */; abort(); } + s_n_llhttp__internal__n_invoke_test_lenient_flags: { + switch (llhttp__internal__c_test_lenient_flags(state, p, endp)) { + case 1: + goto s_n_llhttp__internal__n_invoke_update_finish_2; + default: + goto s_n_llhttp__internal__n_closed; + } + /* UNREACHABLE */; + abort(); + } s_n_llhttp__internal__n_invoke_update_finish_1: { switch (llhttp__internal__c_update_finish_1(state, p, endp)) { default: - goto s_n_llhttp__internal__n_closed; + goto s_n_llhttp__internal__n_invoke_test_lenient_flags; } /* UNREACHABLE */; abort(); @@ -6098,8 +6115,8 @@ static llparse_state_t llhttp__internal__run( /* UNREACHABLE */; abort(); } - s_n_llhttp__internal__n_invoke_test_lenient_flags: { - switch (llhttp__internal__c_test_lenient_flags(state, p, endp)) { + s_n_llhttp__internal__n_invoke_test_lenient_flags_1: { + switch (llhttp__internal__c_test_lenient_flags_1(state, p, endp)) { case 0: goto s_n_llhttp__internal__n_error_15; default: @@ -6111,7 +6128,7 @@ static llparse_state_t llhttp__internal__run( s_n_llhttp__internal__n_invoke_test_flags_1: { switch (llhttp__internal__c_test_flags_1(state, p, endp)) { case 1: - goto s_n_llhttp__internal__n_invoke_test_lenient_flags; + goto s_n_llhttp__internal__n_invoke_test_lenient_flags_1; default: goto s_n_llhttp__internal__n_invoke_llhttp__before_headers_complete; } @@ -6365,8 +6382,8 @@ static llparse_state_t llhttp__internal__run( /* UNREACHABLE */; abort(); } - s_n_llhttp__internal__n_invoke_test_lenient_flags_1: { - switch (llhttp__internal__c_test_lenient_flags_1(state, p, endp)) { + s_n_llhttp__internal__n_invoke_test_lenient_flags_2: { + switch (llhttp__internal__c_test_lenient_flags_2(state, p, endp)) { case 1: goto s_n_llhttp__internal__n_header_value_lenient; default: @@ -6727,7 +6744,7 @@ static llparse_state_t llhttp__internal__run( abort(); } s_n_llhttp__internal__n_error_29: { - state->error = 0x16; + state->error = 0x17; state->reason = "Pause on PRI/Upgrade"; state->error_pos = (const char*) p; state->_current = (void*) (intptr_t) s_error; @@ -7906,6 +7923,7 @@ static llparse_match_t llparse__match_sequence_id( enum llparse_state_e { s_error, + s_n_llhttp__internal__n_closed, s_n_llhttp__internal__n_invoke_llhttp__after_message_complete, s_n_llhttp__internal__n_pause_1, s_n_llhttp__internal__n_invoke_is_equal_upgrade, @@ -8199,6 +8217,13 @@ int llhttp__internal__c_update_finish_1( return 0; } +int llhttp__internal__c_test_lenient_flags( + llhttp__internal_t* state, + const unsigned char* p, + const unsigned char* endp) { + return (state->lenient_flags & 4) == 4; +} + int llhttp__internal__c_test_flags_1( llhttp__internal_t* state, const unsigned char* p, @@ -8206,7 +8231,7 @@ int llhttp__internal__c_test_flags_1( return (state->flags & 544) == 544; } -int llhttp__internal__c_test_lenient_flags( +int llhttp__internal__c_test_lenient_flags_1( llhttp__internal_t* state, const unsigned char* p, const unsigned char* endp) { @@ -8278,7 +8303,7 @@ int llhttp__internal__c_or_flags( return 0; } -int llhttp__internal__c_update_finish_2( +int llhttp__internal__c_update_finish_3( llhttp__internal_t* state, const unsigned char* p, const unsigned char* endp) { @@ -8374,7 +8399,7 @@ int llhttp__internal__c_update_header_state_2( return 0; } -int llhttp__internal__c_test_lenient_flags_1( +int llhttp__internal__c_test_lenient_flags_2( llhttp__internal_t* state, const unsigned char* p, const unsigned char* endp) { @@ -8574,9 +8599,21 @@ static llparse_state_t llhttp__internal__run( const unsigned char* endp) { int match; switch ((llparse_state_t) (intptr_t) state->_current) { + case s_n_llhttp__internal__n_closed: + s_n_llhttp__internal__n_closed: { + if (p == endp) { + return s_n_llhttp__internal__n_closed; + } + p++; + goto s_n_llhttp__internal__n_closed; + /* UNREACHABLE */; + abort(); + } case s_n_llhttp__internal__n_invoke_llhttp__after_message_complete: s_n_llhttp__internal__n_invoke_llhttp__after_message_complete: { switch (llhttp__after_message_complete(state, p, endp)) { + case 1: + goto s_n_llhttp__internal__n_invoke_update_finish_2; default: goto s_n_llhttp__internal__n_invoke_update_finish_1; } @@ -9045,7 +9082,7 @@ static llparse_state_t llhttp__internal__run( case 3: goto s_n_llhttp__internal__n_span_start_llhttp__on_body_1; case 4: - goto s_n_llhttp__internal__n_invoke_update_finish_2; + goto s_n_llhttp__internal__n_invoke_update_finish_3; case 5: goto s_n_llhttp__internal__n_error_10; default: @@ -9184,7 +9221,7 @@ static llparse_state_t llhttp__internal__run( goto s_n_llhttp__internal__n_span_end_llhttp__on_header_value_2; } default: { - goto s_n_llhttp__internal__n_invoke_test_lenient_flags_1; + goto s_n_llhttp__internal__n_invoke_test_lenient_flags_2; } } /* UNREACHABLE */; @@ -13077,7 +13114,7 @@ static llparse_state_t llhttp__internal__run( /* UNREACHABLE */; abort(); } - s_n_llhttp__internal__n_invoke_update_finish_1: { + s_n_llhttp__internal__n_invoke_update_finish_2: { switch (llhttp__internal__c_update_finish_1(state, p, endp)) { default: goto s_n_llhttp__internal__n_start; @@ -13085,6 +13122,24 @@ static llparse_state_t llhttp__internal__run( /* UNREACHABLE */; abort(); } + s_n_llhttp__internal__n_invoke_test_lenient_flags: { + switch (llhttp__internal__c_test_lenient_flags(state, p, endp)) { + case 1: + goto s_n_llhttp__internal__n_invoke_update_finish_2; + default: + goto s_n_llhttp__internal__n_closed; + } + /* UNREACHABLE */; + abort(); + } + s_n_llhttp__internal__n_invoke_update_finish_1: { + switch (llhttp__internal__c_update_finish_1(state, p, endp)) { + default: + goto s_n_llhttp__internal__n_invoke_test_lenient_flags; + } + /* UNREACHABLE */; + abort(); + } s_n_llhttp__internal__n_pause_5: { state->error = 0x15; state->reason = "on_message_complete pause"; @@ -13311,8 +13366,8 @@ static llparse_state_t llhttp__internal__run( /* UNREACHABLE */; abort(); } - s_n_llhttp__internal__n_invoke_update_finish_2: { - switch (llhttp__internal__c_update_finish_2(state, p, endp)) { + s_n_llhttp__internal__n_invoke_update_finish_3: { + switch (llhttp__internal__c_update_finish_3(state, p, endp)) { default: goto s_n_llhttp__internal__n_span_start_llhttp__on_body_2; } @@ -13424,8 +13479,8 @@ static llparse_state_t llhttp__internal__run( /* UNREACHABLE */; abort(); } - s_n_llhttp__internal__n_invoke_test_lenient_flags: { - switch (llhttp__internal__c_test_lenient_flags(state, p, endp)) { + s_n_llhttp__internal__n_invoke_test_lenient_flags_1: { + switch (llhttp__internal__c_test_lenient_flags_1(state, p, endp)) { case 0: goto s_n_llhttp__internal__n_error_11; default: @@ -13437,7 +13492,7 @@ static llparse_state_t llhttp__internal__run( s_n_llhttp__internal__n_invoke_test_flags_1: { switch (llhttp__internal__c_test_flags_1(state, p, endp)) { case 1: - goto s_n_llhttp__internal__n_invoke_test_lenient_flags; + goto s_n_llhttp__internal__n_invoke_test_lenient_flags_1; default: goto s_n_llhttp__internal__n_invoke_llhttp__before_headers_complete; } @@ -13673,8 +13728,8 @@ static llparse_state_t llhttp__internal__run( /* UNREACHABLE */; abort(); } - s_n_llhttp__internal__n_invoke_test_lenient_flags_1: { - switch (llhttp__internal__c_test_lenient_flags_1(state, p, endp)) { + s_n_llhttp__internal__n_invoke_test_lenient_flags_2: { + switch (llhttp__internal__c_test_lenient_flags_2(state, p, endp)) { case 1: goto s_n_llhttp__internal__n_header_value_lenient; default: @@ -14035,7 +14090,7 @@ static llparse_state_t llhttp__internal__run( abort(); } s_n_llhttp__internal__n_error_23: { - state->error = 0x16; + state->error = 0x17; state->reason = "Pause on PRI/Upgrade"; state->error_pos = (const char*) p; state->_current = (void*) (intptr_t) s_error; diff --git a/src/3rdparty/llhttp/llhttp.h b/src/3rdparty/llhttp/llhttp.h index a7164103b..8f9590d35 100644 --- a/src/3rdparty/llhttp/llhttp.h +++ b/src/3rdparty/llhttp/llhttp.h @@ -1,8 +1,8 @@ #ifndef INCLUDE_LLHTTP_H_ #define INCLUDE_LLHTTP_H_ -#define LLHTTP_VERSION_MAJOR 4 -#define LLHTTP_VERSION_MINOR 0 +#define LLHTTP_VERSION_MAJOR 5 +#define LLHTTP_VERSION_MINOR 1 #define LLHTTP_VERSION_PATCH 0 #ifndef LLHTTP_STRICT_MODE @@ -79,7 +79,8 @@ enum llhttp_errno { HPE_CB_CHUNK_COMPLETE = 20, HPE_PAUSED = 21, HPE_PAUSED_UPGRADE = 22, - HPE_USER = 23 + HPE_PAUSED_H2_UPGRADE = 23, + HPE_USER = 24 }; typedef enum llhttp_errno llhttp_errno_t; @@ -98,7 +99,8 @@ typedef enum llhttp_flags llhttp_flags_t; enum llhttp_lenient_flags { LENIENT_HEADERS = 0x1, - LENIENT_CHUNKED_LENGTH = 0x2 + LENIENT_CHUNKED_LENGTH = 0x2, + LENIENT_KEEP_ALIVE = 0x4 }; typedef enum llhttp_lenient_flags llhttp_lenient_flags_t; @@ -190,7 +192,8 @@ typedef enum llhttp_method llhttp_method_t; XX(20, CB_CHUNK_COMPLETE, CB_CHUNK_COMPLETE) \ XX(21, PAUSED, PAUSED) \ XX(22, PAUSED_UPGRADE, PAUSED_UPGRADE) \ - XX(23, USER, USER) \ + XX(23, PAUSED_H2_UPGRADE, PAUSED_H2_UPGRADE) \ + XX(24, USER, USER) \ #define HTTP_METHOD_MAP(XX) \ @@ -255,6 +258,12 @@ extern "C" { #endif #include +#if defined(__wasm__) +#define LLHTTP_EXPORT __attribute__((visibility("default"))) +#else +#define LLHTTP_EXPORT +#endif + typedef llhttp__internal_t llhttp_t; typedef struct llhttp_settings_s llhttp_settings_t; @@ -305,15 +314,46 @@ struct llhttp_settings_s { * the `parser` here. In practice, `settings` has to be either a static * variable or be allocated with `malloc`, `new`, etc. */ +LLHTTP_EXPORT void llhttp_init(llhttp_t* parser, llhttp_type_t type, const llhttp_settings_t* settings); +#if defined(__wasm__) + +LLHTTP_EXPORT +llhttp_t* llhttp_alloc(llhttp_type_t type); + +LLHTTP_EXPORT +void llhttp_free(llhttp_t* parser); + +LLHTTP_EXPORT +uint8_t llhttp_get_type(llhttp_t* parser); + +LLHTTP_EXPORT +uint8_t llhttp_get_http_major(llhttp_t* parser); + +LLHTTP_EXPORT +uint8_t llhttp_get_http_minor(llhttp_t* parser); + +LLHTTP_EXPORT +uint8_t llhttp_get_method(llhttp_t* parser); + +LLHTTP_EXPORT +int llhttp_get_status_code(llhttp_t* parser); + +LLHTTP_EXPORT +uint8_t llhttp_get_upgrade(llhttp_t* parser); + +#endif // defined(__wasm__) + /* Reset an already initialized parser back to the start state, preserving the * existing parser type, callback settings, user data, and lenient flags. */ +LLHTTP_EXPORT void llhttp_reset(llhttp_t* parser); /* Initialize the settings object */ +LLHTTP_EXPORT void llhttp_settings_init(llhttp_settings_t* settings); /* Parse full or partial request/response, invoking user callbacks along the @@ -332,6 +372,7 @@ void llhttp_settings_init(llhttp_settings_t* settings); * to return the same error upon each successive call up until `llhttp_init()` * is called. */ +LLHTTP_EXPORT llhttp_errno_t llhttp_execute(llhttp_t* parser, const char* data, size_t len); /* This method should be called when the other side has no further bytes to @@ -342,16 +383,19 @@ llhttp_errno_t llhttp_execute(llhttp_t* parser, const char* data, size_t len); * connection. This method will invoke `on_message_complete()` callback if the * request was terminated safely. Otherwise a error code would be returned. */ +LLHTTP_EXPORT llhttp_errno_t llhttp_finish(llhttp_t* parser); /* Returns `1` if the incoming message is parsed until the last byte, and has * to be completed by calling `llhttp_finish()` on EOF */ +LLHTTP_EXPORT int llhttp_message_needs_eof(const llhttp_t* parser); /* Returns `1` if there might be any other messages following the last that was * successfully parsed. */ +LLHTTP_EXPORT int llhttp_should_keep_alive(const llhttp_t* parser); /* Make further calls of `llhttp_execute()` return `HPE_PAUSED` and set @@ -360,6 +404,7 @@ int llhttp_should_keep_alive(const llhttp_t* parser); * Important: do not call this from user callbacks! User callbacks must return * `HPE_PAUSED` if pausing is required. */ +LLHTTP_EXPORT void llhttp_pause(llhttp_t* parser); /* Might be called to resume the execution after the pause in user's callback. @@ -367,6 +412,7 @@ void llhttp_pause(llhttp_t* parser); * * Call this only if `llhttp_execute()` returns `HPE_PAUSED`. */ +LLHTTP_EXPORT void llhttp_resume(llhttp_t* parser); /* Might be called to resume the execution after the pause in user's callback. @@ -374,9 +420,11 @@ void llhttp_resume(llhttp_t* parser); * * Call this only if `llhttp_execute()` returns `HPE_PAUSED_UPGRADE` */ +LLHTTP_EXPORT void llhttp_resume_after_upgrade(llhttp_t* parser); /* Returns the latest return error */ +LLHTTP_EXPORT llhttp_errno_t llhttp_get_errno(const llhttp_t* parser); /* Returns the verbal explanation of the latest returned error. @@ -384,6 +432,7 @@ llhttp_errno_t llhttp_get_errno(const llhttp_t* parser); * Note: User callback should set error reason when returning the error. See * `llhttp_set_error_reason()` for details. */ +LLHTTP_EXPORT const char* llhttp_get_error_reason(const llhttp_t* parser); /* Assign verbal description to the returned error. Must be called in user @@ -391,6 +440,7 @@ const char* llhttp_get_error_reason(const llhttp_t* parser); * * Note: `HPE_USER` error code might be useful in user callbacks. */ +LLHTTP_EXPORT void llhttp_set_error_reason(llhttp_t* parser, const char* reason); /* Returns the pointer to the last parsed byte before the returned error. The @@ -398,12 +448,15 @@ void llhttp_set_error_reason(llhttp_t* parser, const char* reason); * * Note: this method might be useful for counting the number of parsed bytes. */ +LLHTTP_EXPORT const char* llhttp_get_error_pos(const llhttp_t* parser); /* Returns textual name of error code */ +LLHTTP_EXPORT const char* llhttp_errno_name(llhttp_errno_t err); /* Returns textual name of HTTP method */ +LLHTTP_EXPORT const char* llhttp_method_name(llhttp_method_t method); @@ -416,6 +469,7 @@ const char* llhttp_method_name(llhttp_method_t method); * * **(USE AT YOUR OWN RISK)** */ +LLHTTP_EXPORT void llhttp_set_lenient_headers(llhttp_t* parser, int enabled); @@ -429,8 +483,23 @@ void llhttp_set_lenient_headers(llhttp_t* parser, int enabled); * * **(USE AT YOUR OWN RISK)** */ +LLHTTP_EXPORT void llhttp_set_lenient_chunked_length(llhttp_t* parser, int enabled); + +/* Enables/disables lenient handling of `Connection: close` and HTTP/1.0 + * requests responses. + * + * Normally `llhttp` would error on (in strict mode) or discard (in loose mode) + * the HTTP request/response after the request/response with `Connection: close` + * and `Content-Length`. This is important to prevent cache poisoning attacks, + * but might interact badly with outdated and insecure clients. With this flag + * the extra request/response will be parsed normally. + * + * **(USE AT YOUR OWN RISK)** + */ +void llhttp_set_lenient_keep_alive(llhttp_t* parser, int enabled); + #ifdef __cplusplus } /* extern "C" */ #endif diff --git a/src/base/base.cmake b/src/base/base.cmake index 12b4ce99c..9d1410521 100644 --- a/src/base/base.cmake +++ b/src/base/base.cmake @@ -32,6 +32,7 @@ set(HEADERS_BASE src/base/kernel/interfaces/IConfigListener.h src/base/kernel/interfaces/IConfigTransform.h src/base/kernel/interfaces/IConsoleListener.h + src/base/kernel/interfaces/IDnsBackend.h src/base/kernel/interfaces/IDnsListener.h src/base/kernel/interfaces/ILineListener.h src/base/kernel/interfaces/ILogBackend.h @@ -43,7 +44,11 @@ set(HEADERS_BASE src/base/kernel/Platform.h src/base/kernel/Process.h src/base/net/dns/Dns.h + src/base/net/dns/DnsConfig.h src/base/net/dns/DnsRecord.h + src/base/net/dns/DnsRecords.h + src/base/net/dns/DnsRequest.h + src/base/net/dns/DnsUvBackend.h src/base/net/http/Http.h src/base/net/http/HttpListener.h src/base/net/stratum/BaseClient.h @@ -99,7 +104,10 @@ set(SOURCES_BASE src/base/kernel/Platform.cpp src/base/kernel/Process.cpp src/base/net/dns/Dns.cpp + src/base/net/dns/DnsConfig.cpp src/base/net/dns/DnsRecord.cpp + src/base/net/dns/DnsRecords.cpp + src/base/net/dns/DnsUvBackend.cpp src/base/net/http/Http.cpp src/base/net/stratum/AlgoSwitch.cpp src/base/net/stratum/BaseClient.cpp diff --git a/src/base/crypto/Algorithm.cpp b/src/base/crypto/Algorithm.cpp index 1a999cb74..05517ba75 100644 --- a/src/base/crypto/Algorithm.cpp +++ b/src/base/crypto/Algorithm.cpp @@ -6,8 +6,8 @@ * Copyright 2016 Jay D Dee * Copyright 2017-2018 XMR-Stak , * Copyright 2018 Lee Clagett - * Copyright 2018-2020 SChernykh - * Copyright 2016-2020 XMRig , + * Copyright 2018-2021 SChernykh + * Copyright 2016-2021 XMRig , * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -135,6 +135,11 @@ static AlgoName const algorithm_names[] = { { "cryptonight/gpu", "cn/gpu", Algorithm::CN_GPU }, { "cryptonight_gpu", nullptr, Algorithm::CN_GPU }, # endif +# ifdef XMRIG_ALGO_CN_FEMTO + { "cryptonight/upx2", "cn/upx2", Algorithm::CN_UPX2 }, + { "cn-extremelite/upx2", nullptr, Algorithm::CN_UPX2 }, + { "cryptonight-upx/2", nullptr, Algorithm::CN_UPX2 }, +# endif }; @@ -206,6 +211,9 @@ size_t xmrig::Algorithm::l3() const case CN_PICO: return oneMiB / 4; + case CN_FEMTO: + return oneMiB / 8; + default: break; } @@ -346,6 +354,11 @@ xmrig::Algorithm::Family xmrig::Algorithm::family(Id id) return CN_PICO; # endif +# ifdef XMRIG_ALGO_CN_FEMTO + case CN_UPX2: + return CN_FEMTO; +# endif + # ifdef XMRIG_ALGO_RANDOMX case RX_0: case RX_WOW: diff --git a/src/base/crypto/Algorithm.h b/src/base/crypto/Algorithm.h index 4f2d72551..76eaad532 100644 --- a/src/base/crypto/Algorithm.h +++ b/src/base/crypto/Algorithm.h @@ -6,8 +6,8 @@ * Copyright 2016 Jay D Dee * Copyright 2017-2018 XMR-Stak , * Copyright 2018 Lee Clagett - * Copyright 2018-2020 SChernykh - * Copyright 2016-2020 XMRig , + * Copyright 2018-2021 SChernykh + * Copyright 2016-2021 XMRig , * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -66,6 +66,7 @@ class Algorithm CN_PICO_TLO, // "cn-pico/tlo" CryptoNight-Pico (TLO) CN_CCX, // "cn/ccx" Conceal (CCX) CN_GPU, // "cn/gpu" CryptoNight-GPU (Ryo). + CN_UPX2, // "cn/upx2" Uplexa (UPX2) RX_0, // "rx/0" RandomX (reference configuration). RX_WOW, // "rx/wow" RandomWOW (Wownero). RX_ARQ, // "rx/arq" RandomARQ (Arqma). @@ -86,6 +87,7 @@ class Algorithm CN_LITE, CN_HEAVY, CN_PICO, + CN_FEMTO, RANDOM_X, ARGON2, ASTROBWT, @@ -97,7 +99,7 @@ class Algorithm inline Algorithm(Id id) : m_id(id) {} Algorithm(const rapidjson::Value &value); - inline bool isCN() const { auto f = family(); return f == CN || f == CN_LITE || f == CN_HEAVY || f == CN_PICO; } + inline bool isCN() const { auto f = family(); return f == CN || f == CN_LITE || f == CN_HEAVY || f == CN_PICO || f == CN_FEMTO; } inline bool isEqual(const Algorithm &other) const { return m_id == other.m_id; } inline bool isValid() const { return m_id != INVALID && family() != UNKNOWN; } inline const char *name() const { return name(false); } diff --git a/src/base/io/log/FileLogWriter.cpp b/src/base/io/log/FileLogWriter.cpp index 352dec20f..b41f7f395 100644 --- a/src/base/io/log/FileLogWriter.cpp +++ b/src/base/io/log/FileLogWriter.cpp @@ -91,7 +91,7 @@ bool xmrig::FileLogWriter::writeLine(const char *data, size_t size) { const uv_buf_t buf[2] = { uv_buf_init(new char[size], size), - uv_buf_init(m_endl, sizeof(m_endl) - 1) + uv_buf_init(const_cast(m_endl), sizeof(m_endl) - 1) }; memcpy(buf[0].base, data, size); diff --git a/src/base/io/log/FileLogWriter.h b/src/base/io/log/FileLogWriter.h index 548d235ce..f3606aa32 100644 --- a/src/base/io/log/FileLogWriter.h +++ b/src/base/io/log/FileLogWriter.h @@ -42,9 +42,9 @@ class FileLogWriter private: # ifdef XMRIG_OS_WIN - char m_endl[3] = "\r\n"; + const char m_endl[3] = {'\r', '\n', 0}; # else - char m_endl[2] = "\n"; + const char m_endl[2] = {'\n', 0}; # endif int m_file = -1; diff --git a/src/base/kernel/config/BaseConfig.cpp b/src/base/kernel/config/BaseConfig.cpp index 1f2b09cb2..37982999e 100644 --- a/src/base/kernel/config/BaseConfig.cpp +++ b/src/base/kernel/config/BaseConfig.cpp @@ -23,6 +23,7 @@ #include "base/io/log/Log.h" #include "base/io/log/Tags.h" #include "base/kernel/interfaces/IJsonReader.h" +#include "base/net/dns/Dns.h" #include "version.h" @@ -105,6 +106,8 @@ bool xmrig::BaseConfig::read(const IJsonReader &reader, const char *fileName) m_http.load(reader.getObject(kHttp)); m_pools.load(reader); + Dns::set(reader.getObject(DnsConfig::kField)); + return m_pools.active() > 0; } diff --git a/src/base/kernel/config/BaseTransform.cpp b/src/base/kernel/config/BaseTransform.cpp index 55e082b61..3cd48d5a1 100644 --- a/src/base/kernel/config/BaseTransform.cpp +++ b/src/base/kernel/config/BaseTransform.cpp @@ -33,6 +33,7 @@ #include "base/kernel/config/BaseConfig.h" #include "base/kernel/interfaces/IConfig.h" #include "base/kernel/Process.h" +#include "base/net/dns/DnsConfig.h" #include "base/net/stratum/Pool.h" #include "base/net/stratum/Pools.h" #include "core/config/Config_platform.h" @@ -244,6 +245,7 @@ void xmrig::BaseTransform::transform(rapidjson::Document &doc, int key, const ch case IConfig::HttpPort: /* --http-port */ case IConfig::DonateLevelKey: /* --donate-level */ case IConfig::DaemonPollKey: /* --daemon-poll-interval */ + case IConfig::DnsTtlKey: /* --dns-ttl */ return transformUint64(doc, key, static_cast(strtol(arg, nullptr, 10))); case IConfig::BackgroundKey: /* --background */ @@ -256,6 +258,7 @@ void xmrig::BaseTransform::transform(rapidjson::Document &doc, int key, const ch case IConfig::DaemonKey: /* --daemon */ case IConfig::SubmitToOriginKey: /* --submit-to-origin */ case IConfig::VerboseKey: /* --verbose */ + case IConfig::DnsIPv6Key: /* --dns-ipv6 */ return transformBoolean(doc, key, true); case IConfig::ColorKey: /* --no-color */ @@ -316,6 +319,9 @@ void xmrig::BaseTransform::transformBoolean(rapidjson::Document &doc, int key, b case IConfig::NoTitleKey: /* --no-title */ return set(doc, BaseConfig::kTitle, enable); + case IConfig::DnsIPv6Key: /* --dns-ipv6 */ + return set(doc, DnsConfig::kField, DnsConfig::kIPv6, enable); + default: break; } @@ -344,6 +350,9 @@ void xmrig::BaseTransform::transformUint64(rapidjson::Document &doc, int key, ui case IConfig::PrintTimeKey: /* --print-time */ return set(doc, BaseConfig::kPrintTime, arg); + case IConfig::DnsTtlKey: /* --dns-ttl */ + return set(doc, DnsConfig::kField, DnsConfig::kTTL, arg); + # ifdef XMRIG_FEATURE_HTTP case IConfig::DaemonPollKey: /* --daemon-poll-interval */ return add(doc, Pools::kPools, Pool::kDaemonPollInterval, arg); diff --git a/src/base/kernel/interfaces/IConfig.h b/src/base/kernel/interfaces/IConfig.h index adf6b083c..e0b1a7b04 100644 --- a/src/base/kernel/interfaces/IConfig.h +++ b/src/base/kernel/interfaces/IConfig.h @@ -82,6 +82,8 @@ class IConfig HugePageSizeKey = 1050, PauseOnActiveKey = 1051, SubmitToOriginKey = 1052, + DnsIPv6Key = 1053, + DnsTtlKey = 1054, // xmrig common CPUPriorityKey = 1021, diff --git a/src/base/kernel/interfaces/IDnsBackend.h b/src/base/kernel/interfaces/IDnsBackend.h new file mode 100644 index 000000000..ca676f326 --- /dev/null +++ b/src/base/kernel/interfaces/IDnsBackend.h @@ -0,0 +1,54 @@ +/* XMRig + * Copyright (c) 2018-2021 SChernykh + * Copyright (c) 2016-2021 XMRig , + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef XMRIG_IDNSBACKEND_H +#define XMRIG_IDNSBACKEND_H + + +#include "base/tools/Object.h" + + +#include + + +namespace xmrig { + + +class DnsRecords; +class DnsRequest; +class IDnsListener; +class String; + + +class IDnsBackend +{ +public: + XMRIG_DISABLE_COPY_MOVE(IDnsBackend) + + IDnsBackend() = default; + virtual ~IDnsBackend() = default; + + virtual const DnsRecords &records() const = 0; + virtual std::shared_ptr resolve(const String &host, IDnsListener *listener, uint64_t ttl) = 0; +}; + + +} /* namespace xmrig */ + + +#endif // XMRIG_IDNSBACKEND_H diff --git a/src/base/kernel/interfaces/IDnsListener.h b/src/base/kernel/interfaces/IDnsListener.h index 7d0e14e36..b9d20efa9 100644 --- a/src/base/kernel/interfaces/IDnsListener.h +++ b/src/base/kernel/interfaces/IDnsListener.h @@ -1,6 +1,6 @@ /* XMRig - * Copyright (c) 2018-2020 SChernykh - * Copyright (c) 2016-2020 XMRig , + * Copyright (c) 2018-2021 SChernykh + * Copyright (c) 2016-2021 XMRig , * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -26,7 +26,7 @@ namespace xmrig { -class Dns; +class DnsRecords; class IDnsListener @@ -37,7 +37,7 @@ class IDnsListener IDnsListener() = default; virtual ~IDnsListener() = default; - virtual void onResolved(const Dns &dns, int status) = 0; + virtual void onResolved(const DnsRecords &records, int status, const char *error) = 0; }; diff --git a/src/base/net/dns/Dns.cpp b/src/base/net/dns/Dns.cpp index ef50b20dc..85590bb7d 100644 --- a/src/base/net/dns/Dns.cpp +++ b/src/base/net/dns/Dns.cpp @@ -1,6 +1,6 @@ /* XMRig - * Copyright (c) 2018-2020 SChernykh - * Copyright (c) 2016-2020 XMRig , + * Copyright (c) 2018-2021 SChernykh + * Copyright (c) 2016-2021 XMRig , * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -18,136 +18,24 @@ #include "base/net/dns/Dns.h" -#include "base/kernel/interfaces/IDnsListener.h" +#include "base/net/dns/DnsUvBackend.h" namespace xmrig { - Storage Dns::m_storage; - static const DnsRecord defaultRecord; -} - - -xmrig::Dns::Dns(IDnsListener *listener) : - m_listener(listener) -{ - m_key = m_storage.add(this); - m_resolver = new uv_getaddrinfo_t; - m_resolver->data = m_storage.ptr(m_key); - m_hints.ai_family = AF_UNSPEC; - m_hints.ai_socktype = SOCK_STREAM; - m_hints.ai_protocol = IPPROTO_TCP; -} - - -xmrig::Dns::~Dns() -{ - m_storage.release(m_key); - - delete m_resolver; -} - - -bool xmrig::Dns::resolve(const String &host) -{ - if (m_host != host) { - m_host = host; - - clear(); - } +DnsConfig Dns::m_config; +std::map > Dns::m_backends; - m_status = uv_getaddrinfo(uv_default_loop(), m_resolver, Dns::onResolved, m_host.data(), nullptr, &m_hints); - return m_status == 0; -} - - -const char *xmrig::Dns::error() const -{ - return uv_strerror(m_status); -} - - -const xmrig::DnsRecord &xmrig::Dns::get(DnsRecord::Type prefered) const -{ - if (count() == 0) { - return defaultRecord; - } - - const size_t ipv4 = m_ipv4.size(); - const size_t ipv6 = m_ipv6.size(); - - if (ipv6 && (prefered == DnsRecord::AAAA || !ipv4)) { - return m_ipv6[ipv6 == 1 ? 0 : static_cast(rand()) % ipv6]; - } - - if (ipv4) { - return m_ipv4[ipv4 == 1 ? 0 : static_cast(rand()) % ipv4]; - } - - return defaultRecord; -} - - -size_t xmrig::Dns::count(DnsRecord::Type type) const -{ - if (type == DnsRecord::A) { - return m_ipv4.size(); - } - - if (type == DnsRecord::AAAA) { - return m_ipv6.size(); - } - - return m_ipv4.size() + m_ipv6.size(); -} - - -void xmrig::Dns::clear() -{ - m_ipv4.clear(); - m_ipv6.clear(); -} - - -void xmrig::Dns::onResolved(int status, addrinfo *res) -{ - m_status = status; - - if (m_status < 0) { - return m_listener->onResolved(*this, status); - } - - clear(); - - addrinfo *ptr = res; - while (ptr != nullptr) { - if (ptr->ai_family == AF_INET) { - m_ipv4.emplace_back(ptr); - } - - if (ptr->ai_family == AF_INET6) { - m_ipv6.emplace_back(ptr); - } - - ptr = ptr->ai_next; - } - - if (isEmpty()) { - m_status = UV_EAI_NONAME; - } - - m_listener->onResolved(*this, m_status); -} +} // namespace xmrig -void xmrig::Dns::onResolved(uv_getaddrinfo_t *req, int status, addrinfo *res) +std::shared_ptr xmrig::Dns::resolve(const String &host, IDnsListener *listener, uint64_t ttl) { - Dns *dns = m_storage.get(req->data); - if (dns) { - dns->onResolved(status, res); + if (m_backends.find(host) == m_backends.end()) { + m_backends.insert({ host, std::make_shared() }); } - uv_freeaddrinfo(res); + return m_backends.at(host)->resolve(host, listener, ttl == 0 ? m_config.ttl() : ttl); } diff --git a/src/base/net/dns/Dns.h b/src/base/net/dns/Dns.h index 86f901451..cf054390f 100644 --- a/src/base/net/dns/Dns.h +++ b/src/base/net/dns/Dns.h @@ -1,6 +1,6 @@ /* XMRig - * Copyright (c) 2018-2020 SChernykh - * Copyright (c) 2016-2020 XMRig , + * Copyright (c) 2018-2021 SChernykh + * Copyright (c) 2016-2021 XMRig , * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -20,55 +20,34 @@ #define XMRIG_DNS_H -#include -#include +#include "base/net/dns/DnsConfig.h" +#include "base/tools/String.h" -#include "base/net/dns/DnsRecord.h" -#include "base/net/tools/Storage.h" -#include "base/tools/Object.h" -#include "base/tools/String.h" +#include +#include namespace xmrig { +class DnsConfig; +class DnsRequest; +class IDnsBackend; class IDnsListener; class Dns { public: - XMRIG_DISABLE_COPY_MOVE_DEFAULT(Dns) - - Dns(IDnsListener *listener); - ~Dns(); - - inline bool isEmpty() const { return m_ipv4.empty() && m_ipv6.empty(); } - inline const String &host() const { return m_host; } - inline int status() const { return m_status; } + inline static const DnsConfig &config() { return m_config; } + inline static void set(const DnsConfig &config) { m_config = config; } - bool resolve(const String &host); - const char *error() const; - const DnsRecord &get(DnsRecord::Type prefered = DnsRecord::A) const; - size_t count(DnsRecord::Type type = DnsRecord::Unknown) const; + static std::shared_ptr resolve(const String &host, IDnsListener *listener, uint64_t ttl = 0); private: - void clear(); - void onResolved(int status, addrinfo *res); - - static void onResolved(uv_getaddrinfo_t *req, int status, addrinfo *res); - - addrinfo m_hints{}; - IDnsListener *m_listener; - int m_status = 0; - std::vector m_ipv4; - std::vector m_ipv6; - String m_host; - uintptr_t m_key; - uv_getaddrinfo_t *m_resolver = nullptr; - - static Storage m_storage; + static DnsConfig m_config; + static std::map > m_backends; }; diff --git a/src/base/net/dns/DnsConfig.cpp b/src/base/net/dns/DnsConfig.cpp new file mode 100644 index 000000000..c2446c2a6 --- /dev/null +++ b/src/base/net/dns/DnsConfig.cpp @@ -0,0 +1,57 @@ +/* XMRig + * Copyright (c) 2018-2021 SChernykh + * Copyright (c) 2016-2021 XMRig , + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + + +#include "base/net/dns/DnsConfig.h" +#include "3rdparty/rapidjson/document.h" +#include "base/io/json/Json.h" + + +#include + + +namespace xmrig { + + +const char *DnsConfig::kField = "dns"; +const char *DnsConfig::kIPv6 = "ipv6"; +const char *DnsConfig::kTTL = "ttl"; + + +} // namespace xmrig + + +xmrig::DnsConfig::DnsConfig(const rapidjson::Value &value) +{ + m_ipv6 = Json::getBool(value, kIPv6, m_ipv6); + m_ttl = std::max(Json::getUint(value, kTTL, m_ttl), 1U); +} + + +rapidjson::Value xmrig::DnsConfig::toJSON(rapidjson::Document &doc) const +{ + using namespace rapidjson; + + auto &allocator = doc.GetAllocator(); + Value obj(kObjectType); + + obj.AddMember(StringRef(kIPv6), m_ipv6, allocator); + obj.AddMember(StringRef(kTTL), m_ttl, allocator); + + return obj; +} diff --git a/src/base/net/dns/DnsConfig.h b/src/base/net/dns/DnsConfig.h new file mode 100644 index 000000000..d42c8ad8b --- /dev/null +++ b/src/base/net/dns/DnsConfig.h @@ -0,0 +1,54 @@ +/* XMRig + * Copyright (c) 2018-2021 SChernykh + * Copyright (c) 2016-2021 XMRig , + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef XMRIG_DNSCONFIG_H +#define XMRIG_DNSCONFIG_H + + +#include "3rdparty/rapidjson/fwd.h" + + +namespace xmrig { + + +class DnsConfig +{ +public: + static const char *kField; + static const char *kIPv6; + static const char *kTTL; + + DnsConfig() = default; + DnsConfig(const rapidjson::Value &object); + + inline bool isIPv6() const { return m_ipv6; } + inline uint32_t ttl() const { return m_ttl * 1000U; } + + rapidjson::Value toJSON(rapidjson::Document &doc) const; + + +private: + bool m_ipv6 = false; + uint32_t m_ttl = 30U; +}; + + +} /* namespace xmrig */ + + +#endif /* XMRIG_DNSCONFIG_H */ diff --git a/src/base/net/dns/DnsRecord.cpp b/src/base/net/dns/DnsRecord.cpp index 1667c715c..bfa84613a 100644 --- a/src/base/net/dns/DnsRecord.cpp +++ b/src/base/net/dns/DnsRecord.cpp @@ -1,6 +1,6 @@ /* XMRig - * Copyright (c) 2018-2020 SChernykh - * Copyright (c) 2016-2020 XMRig , + * Copyright (c) 2018-2021 SChernykh + * Copyright (c) 2016-2021 XMRig , * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -24,38 +24,34 @@ xmrig::DnsRecord::DnsRecord(const addrinfo *addr) : - m_type(addr->ai_family == AF_INET6 ? AAAA : A) + m_type(addr->ai_family == AF_INET6 ? AAAA : (addr->ai_family == AF_INET ? A : Unknown)) { - char *buf = nullptr; - - if (m_type == AAAA) { - buf = new char[45](); - uv_ip6_name(reinterpret_cast(addr->ai_addr), buf, 45); - } - else { - buf = new char[16](); - uv_ip4_name(reinterpret_cast(addr->ai_addr), buf, 16); - } + static_assert(sizeof(m_data) >= sizeof(sockaddr_in6), "Not enough storage for IPv6 address."); - m_ip = buf; + memcpy(m_data, addr->ai_addr, m_type == AAAA ? sizeof(sockaddr_in6) : sizeof(sockaddr_in)); } -sockaddr *xmrig::DnsRecord::addr(uint16_t port) const +const sockaddr *xmrig::DnsRecord::addr(uint16_t port) const { - if (m_type == A) { - auto addr = new sockaddr_in(); - uv_ip4_addr(m_ip.data(), port, addr); + reinterpret_cast(m_data)->sin_port = htons(port); - return reinterpret_cast(addr); - } + return reinterpret_cast(m_data); +} - if (m_type == AAAA) { - auto addr = new sockaddr_in6(); - uv_ip6_addr(m_ip.data(), port, addr); - return reinterpret_cast(addr); +xmrig::String xmrig::DnsRecord::ip() const +{ + char *buf = nullptr; + + if (m_type == AAAA) { + buf = new char[45](); + uv_ip6_name(reinterpret_cast(m_data), buf, 45); + } + else { + buf = new char[16](); + uv_ip4_name(reinterpret_cast(m_data), buf, 16); } - return nullptr; + return buf; } diff --git a/src/base/net/dns/DnsRecord.h b/src/base/net/dns/DnsRecord.h index cf6c25986..7a68ea2f7 100644 --- a/src/base/net/dns/DnsRecord.h +++ b/src/base/net/dns/DnsRecord.h @@ -1,6 +1,6 @@ /* XMRig - * Copyright (c) 2018-2020 SChernykh - * Copyright (c) 2016-2020 XMRig , + * Copyright (c) 2018-2021 SChernykh + * Copyright (c) 2016-2021 XMRig , * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -33,7 +33,7 @@ namespace xmrig { class DnsRecord { public: - enum Type { + enum Type : uint32_t { Unknown, A, AAAA @@ -42,15 +42,15 @@ class DnsRecord DnsRecord() {} DnsRecord(const addrinfo *addr); - sockaddr *addr(uint16_t port = 0) const; + const sockaddr *addr(uint16_t port = 0) const; + String ip() const; inline bool isValid() const { return m_type != Unknown; } - inline const String &ip() const { return m_ip; } inline Type type() const { return m_type; } private: - Type m_type = Unknown; - String m_ip; + mutable uint8_t m_data[28]{}; + const Type m_type = Unknown; }; diff --git a/src/base/net/dns/DnsRecords.cpp b/src/base/net/dns/DnsRecords.cpp new file mode 100644 index 000000000..fb232f276 --- /dev/null +++ b/src/base/net/dns/DnsRecords.cpp @@ -0,0 +1,108 @@ +/* XMRig + * Copyright (c) 2018-2021 SChernykh + * Copyright (c) 2016-2021 XMRig , + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + + +#include + + +#include "base/net/dns/DnsRecords.h" +#include "base/net/dns/Dns.h" + + +const xmrig::DnsRecord &xmrig::DnsRecords::get(DnsRecord::Type prefered) const +{ + static const DnsRecord defaultRecord; + + if (isEmpty()) { + return defaultRecord; + } + + const size_t ipv4 = m_ipv4.size(); + const size_t ipv6 = m_ipv6.size(); + + if (ipv6 && (prefered == DnsRecord::AAAA || Dns::config().isIPv6() || !ipv4)) { + return m_ipv6[ipv6 == 1 ? 0 : static_cast(rand()) % ipv6]; + } + + if (ipv4) { + return m_ipv4[ipv4 == 1 ? 0 : static_cast(rand()) % ipv4]; + } + + return defaultRecord; +} + + +size_t xmrig::DnsRecords::count(DnsRecord::Type type) const +{ + if (type == DnsRecord::A) { + return m_ipv4.size(); + } + + if (type == DnsRecord::AAAA) { + return m_ipv6.size(); + } + + return m_ipv4.size() + m_ipv6.size(); +} + + +void xmrig::DnsRecords::clear() +{ + m_ipv4.clear(); + m_ipv6.clear(); +} + + +void xmrig::DnsRecords::parse(addrinfo *res) +{ + clear(); + + addrinfo *ptr = res; + size_t ipv4 = 0; + size_t ipv6 = 0; + + while (ptr != nullptr) { + if (ptr->ai_family == AF_INET) { + ++ipv4; + } + else if (ptr->ai_family == AF_INET6) { + ++ipv6; + } + + ptr = ptr->ai_next; + } + + if (ipv4 == 0 && ipv6 == 0) { + return; + } + + m_ipv4.reserve(ipv4); + m_ipv6.reserve(ipv6); + + ptr = res; + while (ptr != nullptr) { + if (ptr->ai_family == AF_INET) { + m_ipv4.emplace_back(ptr); + } + else if (ptr->ai_family == AF_INET6) { + m_ipv6.emplace_back(ptr); + } + + ptr = ptr->ai_next; + } +} diff --git a/src/base/net/dns/DnsRecords.h b/src/base/net/dns/DnsRecords.h new file mode 100644 index 000000000..cfa192179 --- /dev/null +++ b/src/base/net/dns/DnsRecords.h @@ -0,0 +1,48 @@ +/* XMRig + * Copyright (c) 2018-2021 SChernykh + * Copyright (c) 2016-2021 XMRig , + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef XMRIG_DNSRECORDS_H +#define XMRIG_DNSRECORDS_H + + +#include "base/net/dns/DnsRecord.h" + + +namespace xmrig { + + +class DnsRecords +{ +public: + inline bool isEmpty() const { return m_ipv4.empty() && m_ipv6.empty(); } + + const DnsRecord &get(DnsRecord::Type prefered = DnsRecord::Unknown) const; + size_t count(DnsRecord::Type type = DnsRecord::Unknown) const; + void clear(); + void parse(addrinfo *res); + +private: + std::vector m_ipv4; + std::vector m_ipv6; +}; + + +} /* namespace xmrig */ + + +#endif /* XMRIG_DNSRECORDS_H */ diff --git a/src/base/net/dns/DnsRequest.h b/src/base/net/dns/DnsRequest.h new file mode 100644 index 000000000..036eaa34f --- /dev/null +++ b/src/base/net/dns/DnsRequest.h @@ -0,0 +1,50 @@ +/* XMRig + * Copyright (c) 2018-2021 SChernykh + * Copyright (c) 2016-2021 XMRig , + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef XMRIG_DNSREQUEST_H +#define XMRIG_DNSREQUEST_H + + +#include "base/tools/Object.h" + + +#include + + +namespace xmrig { + + +class IDnsListener; + + +class DnsRequest +{ +public: + XMRIG_DISABLE_COPY_MOVE_DEFAULT(DnsRequest) + + DnsRequest(IDnsListener *listener) : listener(listener) {} + ~DnsRequest() = default; + + IDnsListener *listener; +}; + + +} /* namespace xmrig */ + + +#endif /* XMRIG_DNSREQUEST_H */ diff --git a/src/base/net/dns/DnsUvBackend.cpp b/src/base/net/dns/DnsUvBackend.cpp new file mode 100644 index 000000000..cb1c0c3eb --- /dev/null +++ b/src/base/net/dns/DnsUvBackend.cpp @@ -0,0 +1,134 @@ +/* XMRig + * Copyright (c) 2018-2021 SChernykh + * Copyright (c) 2016-2021 XMRig , + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + + +#include + + +#include "base/net/dns/DnsUvBackend.h" +#include "base/kernel/interfaces/IDnsListener.h" +#include "base/net/dns/DnsRequest.h" +#include "base/tools/Chrono.h" + + +namespace xmrig { + + +Storage& DnsUvBackend::getStorage() +{ + static Storage* storage = new Storage(); + return *storage; +} + +static addrinfo hints{}; + + +} // namespace xmrig + + +xmrig::DnsUvBackend::DnsUvBackend() +{ + if (!hints.ai_protocol) { + hints.ai_family = AF_UNSPEC; + hints.ai_socktype = SOCK_STREAM; + hints.ai_protocol = IPPROTO_TCP; + } + + m_key = getStorage().add(this); +} + + +xmrig::DnsUvBackend::~DnsUvBackend() +{ + getStorage().release(m_key); +} + + +std::shared_ptr xmrig::DnsUvBackend::resolve(const String &host, IDnsListener *listener, uint64_t ttl) +{ + auto req = std::make_shared(listener); + + if (Chrono::currentMSecsSinceEpoch() - m_ts <= ttl && !m_records.isEmpty()) { + req->listener->onResolved(m_records, 0, nullptr); + } else { + m_queue.emplace(req); + } + + if (m_queue.size() == 1 && !resolve(host)) { + done(); + } + + return req; +} + + +bool xmrig::DnsUvBackend::resolve(const String &host) +{ + m_req = std::make_shared(); + m_req->data = getStorage().ptr(m_key); + + m_status = uv_getaddrinfo(uv_default_loop(), m_req.get(), DnsUvBackend::onResolved, host.data(), nullptr, &hints); + + return m_status == 0; +} + + +void xmrig::DnsUvBackend::done() +{ + const char *error = m_status < 0 ? uv_strerror(m_status) : nullptr; + + while (!m_queue.empty()) { + auto req = std::move(m_queue.front()).lock(); + if (req) { + req->listener->onResolved(m_records, m_status, error); + } + + m_queue.pop(); + } + + m_req.reset(); +} + + +void xmrig::DnsUvBackend::onResolved(int status, addrinfo *res) +{ + m_ts = Chrono::currentMSecsSinceEpoch(); + + if ((m_status = status) < 0) { + return done(); + } + + m_records.parse(res); + + if (m_records.isEmpty()) { + m_status = UV_EAI_NONAME; + } + + done(); +} + + +void xmrig::DnsUvBackend::onResolved(uv_getaddrinfo_t *req, int status, addrinfo *res) +{ + auto backend = getStorage().get(req->data); + if (backend) { + backend->onResolved(status, res); + } + + uv_freeaddrinfo(res); +} diff --git a/src/base/net/dns/DnsUvBackend.h b/src/base/net/dns/DnsUvBackend.h new file mode 100644 index 000000000..f3733f5a4 --- /dev/null +++ b/src/base/net/dns/DnsUvBackend.h @@ -0,0 +1,71 @@ +/* XMRig + * Copyright (c) 2018-2021 SChernykh + * Copyright (c) 2016-2021 XMRig , + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef XMRIG_DNSUVBACKEND_H +#define XMRIG_DNSUVBACKEND_H + + +#include "base/kernel/interfaces/IDnsBackend.h" +#include "base/net/dns/DnsRecords.h" +#include "base/net/tools/Storage.h" + + +#include + + +using uv_getaddrinfo_t = struct uv_getaddrinfo_s; + + +namespace xmrig { + + +class DnsUvBackend : public IDnsBackend +{ +public: + XMRIG_DISABLE_COPY_MOVE(DnsUvBackend) + + DnsUvBackend(); + ~DnsUvBackend() override; + +protected: + inline const DnsRecords &records() const override { return m_records; } + + std::shared_ptr resolve(const String &host, IDnsListener *listener, uint64_t ttl) override; + +private: + bool resolve(const String &host); + void done(); + void onResolved(int status, addrinfo *res); + + static void onResolved(uv_getaddrinfo_t *req, int status, addrinfo *res); + + DnsRecords m_records; + int m_status = 0; + std::queue > m_queue; + std::shared_ptr m_req; + uint64_t m_ts = 0; + uintptr_t m_key; + + static Storage& getStorage(); +}; + + +} /* namespace xmrig */ + + +#endif /* XMRIG_DNSUVBACKEND_H */ diff --git a/src/base/net/http/HttpClient.cpp b/src/base/net/http/HttpClient.cpp index ea0d68c82..3b1e5ad3b 100644 --- a/src/base/net/http/HttpClient.cpp +++ b/src/base/net/http/HttpClient.cpp @@ -23,11 +23,13 @@ #include "base/io/log/Log.h" #include "base/kernel/Platform.h" #include "base/net/dns/Dns.h" +#include "base/net/dns/DnsRecords.h" #include "base/net/tools/NetBuffer.h" #include "base/tools/Timer.h" #include +#include namespace xmrig { @@ -48,7 +50,6 @@ xmrig::HttpClient::HttpClient(const char *tag, FetchRequest &&req, const std::we url = std::move(m_req.path); body = std::move(m_req.body); headers = std::move(m_req.headers); - m_dns = std::make_shared(this); if (m_req.timeout) { m_timer = std::make_shared(this, m_req.timeout, 0); @@ -58,30 +59,29 @@ xmrig::HttpClient::HttpClient(const char *tag, FetchRequest &&req, const std::we bool xmrig::HttpClient::connect() { - return m_dns->resolve(m_req.host); + m_dns = Dns::resolve(m_req.host, this); + + return true; } -void xmrig::HttpClient::onResolved(const Dns &dns, int status) +void xmrig::HttpClient::onResolved(const DnsRecords &records, int status, const char *error) { this->status = status; + m_dns.reset(); - if (status < 0 && dns.isEmpty()) { + if (status < 0 && records.isEmpty()) { if (!isQuiet()) { - LOG_ERR("%s " RED("DNS error: ") RED_BOLD("\"%s\""), tag(), uv_strerror(status)); + LOG_ERR("%s " RED("DNS error: ") RED_BOLD("\"%s\""), tag(), error); } return; } - sockaddr *addr = dns.get().addr(port()); - auto req = new uv_connect_t; req->data = this; - uv_tcp_connect(req, m_tcp, addr, onConnect); - - delete addr; + uv_tcp_connect(req, m_tcp, records.get().addr(port()), onConnect); } @@ -119,7 +119,7 @@ void xmrig::HttpClient::handshake() void xmrig::HttpClient::read(const char *data, size_t size) { - if (parse(data, size) < size) { + if (!parse(data, size)) { close(UV_EPROTO); } } diff --git a/src/base/net/http/HttpClient.h b/src/base/net/http/HttpClient.h index d012d26fb..ccda2e567 100644 --- a/src/base/net/http/HttpClient.h +++ b/src/base/net/http/HttpClient.h @@ -32,7 +32,7 @@ namespace xmrig { -class String; +class DnsRequest; class HttpClient : public HttpContext, public IDnsListener, public ITimerListener @@ -51,7 +51,7 @@ class HttpClient : public HttpContext, public IDnsListener, public ITimerListene bool connect(); protected: - void onResolved(const Dns &dns, int status) override; + void onResolved(const DnsRecords &records, int status, const char *error) override; void onTimer(const Timer *timer) override; virtual void handshake(); @@ -65,7 +65,7 @@ class HttpClient : public HttpContext, public IDnsListener, public ITimerListene const char *m_tag; FetchRequest m_req; - std::shared_ptr m_dns; + std::shared_ptr m_dns; std::shared_ptr m_timer; }; diff --git a/src/base/net/http/HttpContext.cpp b/src/base/net/http/HttpContext.cpp index 92c54c68c..948873c9a 100644 --- a/src/base/net/http/HttpContext.cpp +++ b/src/base/net/http/HttpContext.cpp @@ -118,13 +118,13 @@ bool xmrig::HttpContext::isRequest() const } -size_t xmrig::HttpContext::parse(const char *data, size_t size) +bool xmrig::HttpContext::parse(const char *data, size_t size) { if (size == 0) { - return size; + return true; } - return llhttp_execute(m_parser, data, size); + return llhttp_execute(m_parser, data, size) == HPE_OK; } diff --git a/src/base/net/http/HttpContext.h b/src/base/net/http/HttpContext.h index 81248f28a..9178cf7c3 100644 --- a/src/base/net/http/HttpContext.h +++ b/src/base/net/http/HttpContext.h @@ -62,7 +62,7 @@ class HttpContext : public HttpData void write(std::string &&data, bool close) override; bool isRequest() const override; - size_t parse(const char *data, size_t size); + bool parse(const char *data, size_t size); std::string ip() const override; uint64_t elapsed() const; void close(int status = 0); diff --git a/src/base/net/http/HttpServer.cpp b/src/base/net/http/HttpServer.cpp index 3b7e6ef1f..aab750039 100644 --- a/src/base/net/http/HttpServer.cpp +++ b/src/base/net/http/HttpServer.cpp @@ -50,14 +50,7 @@ void xmrig::HttpServer::onConnection(uv_stream_t *stream, uint16_t) { auto ctx = static_cast(tcp->data); - if (nread >= 0) { - const auto size = static_cast(nread); - const auto parsed = ctx->parse(buf->base, size); - - if (parsed < size) { - ctx->close(); - } - } else { + if (nread < 0 || !ctx->parse(buf->base, static_cast(nread))) { ctx->close(); } diff --git a/src/base/net/https/HttpsContext.cpp b/src/base/net/https/HttpsContext.cpp index ba38e18de..3b0ff79af 100644 --- a/src/base/net/https/HttpsContext.cpp +++ b/src/base/net/https/HttpsContext.cpp @@ -74,7 +74,7 @@ bool xmrig::HttpsContext::write(BIO *bio) void xmrig::HttpsContext::parse(char *data, size_t size) { - if (HttpContext::parse(data, size) < size) { + if (!HttpContext::parse(data, size)) { close(); } } diff --git a/src/base/net/stratum/Client.cpp b/src/base/net/stratum/Client.cpp index 5e37091fc..6e625b917 100644 --- a/src/base/net/stratum/Client.cpp +++ b/src/base/net/stratum/Client.cpp @@ -48,10 +48,11 @@ #include "base/io/log/Log.h" #include "base/kernel/interfaces/IClientListener.h" #include "base/net/dns/Dns.h" +#include "base/net/dns/DnsRecords.h" #include "base/net/stratum/Socks5.h" #include "base/net/tools/NetBuffer.h" -#include "base/tools/Cvt.h" #include "base/tools/Chrono.h" +#include "base/tools/Cvt.h" #include "net/JobResult.h" @@ -86,13 +87,11 @@ xmrig::Client::Client(int id, const char *agent, IClientListener *listener) : { m_reader.setListener(this); m_key = m_storage.add(this); - m_dns = new Dns(this); } xmrig::Client::~Client() { - delete m_dns; delete m_socket; } @@ -295,22 +294,24 @@ void xmrig::Client::tick(uint64_t now) } -void xmrig::Client::onResolved(const Dns &dns, int status) +void xmrig::Client::onResolved(const DnsRecords &records, int status, const char *error) { + m_dns.reset(); + assert(m_listener != nullptr); if (!m_listener) { return reconnect(); } - if (status < 0 && dns.isEmpty()) { + if (status < 0 && records.isEmpty()) { if (!isQuiet()) { - LOG_ERR("%s " RED("DNS error: ") RED_BOLD("\"%s\""), tag(), uv_strerror(status)); + LOG_ERR("%s " RED("DNS error: ") RED_BOLD("\"%s\""), tag(), error); } return reconnect(); } - const auto &record = dns.get(); + const auto &record = records.get(); m_ip = record.ip(); connect(record.addr(m_socks5 ? m_pool.proxy().port() : m_pool.port())); @@ -377,6 +378,19 @@ bool xmrig::Client::parseJob(const rapidjson::Value ¶ms, int *code) return false; } + const char *algo = Json::getString(params, "algo"); + const char *blobData = Json::getString(params, "blob"); + if (algo) { + job.setAlgorithm(algo); + } + else if (m_pool.coin().isValid()) { + uint8_t blobVersion = 0; + if (blobData) { + Cvt::fromHex(&blobVersion, 1, blobData, 2); + } + job.setAlgorithm(m_pool.coin().algorithm(blobVersion)); + } + # ifdef XMRIG_FEATURE_HTTP if (m_pool.mode() == Pool::MODE_SELF_SELECT) { job.setExtraNonce(Json::getString(params, "extra_nonce")); @@ -390,7 +404,7 @@ bool xmrig::Client::parseJob(const rapidjson::Value ¶ms, int *code) else # endif { - if (!job.setBlob(params["blob"].GetString())) { + if (!job.setBlob(blobData)) { *code = 4; return false; } @@ -401,14 +415,6 @@ bool xmrig::Client::parseJob(const rapidjson::Value ¶ms, int *code) return false; } - const char *algo = Json::getString(params, "algo"); - if (algo) { - job.setAlgorithm(algo); - } - else if (m_pool.coin().isValid()) { - job.setAlgorithm(m_pool.coin().algorithm(job.blob()[0])); - } - job.setHeight(Json::getUint64(params, "height")); if (!verifyAlgorithm(job.algorithm(), algo)) { @@ -524,13 +530,7 @@ int xmrig::Client::resolve(const String &host) m_failures = 0; } - if (!m_dns->resolve(host)) { - if (!isQuiet()) { - LOG_ERR("%s " RED("getaddrinfo error: ") RED_BOLD("\"%s\""), tag(), uv_strerror(m_dns->status())); - } - - return 1; - } + m_dns = Dns::resolve(host, this); return 0; } @@ -566,7 +566,7 @@ int64_t xmrig::Client::send(size_t size) } -void xmrig::Client::connect(sockaddr *addr) +void xmrig::Client::connect(const sockaddr *addr) { setState(ConnectingState); @@ -584,8 +584,6 @@ void xmrig::Client::connect(sockaddr *addr) # endif uv_tcp_connect(req, m_socket, addr, onConnect); - - delete addr; } diff --git a/src/base/net/stratum/Client.h b/src/base/net/stratum/Client.h index 859f93a27..223dc8361 100644 --- a/src/base/net/stratum/Client.h +++ b/src/base/net/stratum/Client.h @@ -51,6 +51,7 @@ using BIO = struct bio_st; namespace xmrig { +class DnsRequest; class IClientListener; class JobResult; @@ -85,7 +86,7 @@ class Client : public BaseClient, public IDnsListener, public ILineListener, pub void del_miner(const Miner* miner) override { AlgoSwitch::del_miner(miner); getjob(); } void setPool(const Pool &pool) override { BaseClient::setPool(pool); setDefaultAlgoSwitchAlgo(pool.algorithm()); } - void onResolved(const Dns &dns, int status) override; + void onResolved(const DnsRecords &records, int status, const char *error) override; inline bool hasExtension(Extension extension) const noexcept override { return m_extensions.test(extension); } inline const char *mode() const override { return "pool"; } @@ -116,7 +117,7 @@ class Client : public BaseClient, public IDnsListener, public ILineListener, pub bool write(const uv_buf_t &buf); int resolve(const String &host); int64_t send(size_t size); - void connect(sockaddr *addr); + void connect(const sockaddr *addr); void handshake(); void parse(char *line, size_t len); void parseExtensions(const rapidjson::Value &result); @@ -139,10 +140,10 @@ class Client : public BaseClient, public IDnsListener, public ILineListener, pub static inline Client *getClient(void *data) { return m_storage.get(data); } const char *m_agent; - Dns *m_dns; LineReader m_reader; Socks5 *m_socks5 = nullptr; std::bitset m_extensions; + std::shared_ptr m_dns; std::vector m_sendBuf; String m_rpcId; Tls *m_tls = nullptr; diff --git a/src/base/net/stratum/DaemonClient.cpp b/src/base/net/stratum/DaemonClient.cpp index 087fd0f76..5bfe095ce 100644 --- a/src/base/net/stratum/DaemonClient.cpp +++ b/src/base/net/stratum/DaemonClient.cpp @@ -247,6 +247,12 @@ bool xmrig::DaemonClient::parseJob(const rapidjson::Value ¶ms, int *code) Cvt::toHex(m_blockhashingblob.data() + offset * 2, kBlobReserveSize * 2, Cvt::randomBytes(kBlobReserveSize).data(), kBlobReserveSize); } + if (m_pool.coin().isValid()) { + uint8_t blobVersion = 0; + Cvt::fromHex(&blobVersion, 1, m_blockhashingblob.data(), 2); + job.setAlgorithm(m_pool.coin().algorithm(blobVersion)); + } + if (blocktemplate.isNull() || !job.setBlob(m_blockhashingblob)) { *code = 4; return false; @@ -257,10 +263,6 @@ bool xmrig::DaemonClient::parseJob(const rapidjson::Value ¶ms, int *code) job.setDiff(Json::getUint64(params, "difficulty")); job.setId(blocktemplate.data() + blocktemplate.size() - 32); - if (m_pool.coin().isValid()) { - job.setAlgorithm(m_pool.coin().algorithm(job.blob()[0])); - } - m_job = std::move(job); m_blocktemplate = std::move(blocktemplate); m_prevHash = Json::getString(params, "prev_hash"); diff --git a/src/base/net/stratum/SelfSelectClient.cpp b/src/base/net/stratum/SelfSelectClient.cpp index 7f7ee5447..a902e252f 100644 --- a/src/base/net/stratum/SelfSelectClient.cpp +++ b/src/base/net/stratum/SelfSelectClient.cpp @@ -130,12 +130,17 @@ bool xmrig::SelfSelectClient::parseResponse(int64_t id, rapidjson::Value &result } } - if (!m_job.setBlob(result[kBlockhashingBlob].GetString())) { - return false; + const char *blobData = Json::getString(result, kBlockhashingBlob); + if (pool().coin().isValid()) { + uint8_t blobVersion = 0; + if (blobData) { + Cvt::fromHex(&blobVersion, 1, blobData, 2); + } + m_job.setAlgorithm(pool().coin().algorithm(blobVersion)); } - if (pool().coin().isValid()) { - m_job.setAlgorithm(pool().coin().algorithm(m_job.blob()[0])); + if (!m_job.setBlob(blobData)) { + return false; } m_job.setHeight(Json::getUint64(result, kHeight)); diff --git a/src/base/tools/Handle.h b/src/base/tools/Handle.h index a25381d8c..fcd341478 100644 --- a/src/base/tools/Handle.h +++ b/src/base/tools/Handle.h @@ -45,7 +45,7 @@ class Handle return; } - uv_close(reinterpret_cast(handle), [](uv_handle_t *handle) { delete handle; }); + uv_close(reinterpret_cast(handle), [](uv_handle_t *handle) { delete reinterpret_cast(handle); }); } }; diff --git a/src/core/config/Config.cpp b/src/core/config/Config.cpp index d914353b8..f665838bd 100644 --- a/src/core/config/Config.cpp +++ b/src/core/config/Config.cpp @@ -1,12 +1,6 @@ /* XMRig - * Copyright 2010 Jeff Garzik - * Copyright 2012-2014 pooler - * Copyright 2014 Lucas Jones - * Copyright 2014-2016 Wolf9466 - * Copyright 2016 Jay D Dee - * Copyright 2017-2018 XMR-Stak , - * Copyright 2018-2020 SChernykh - * Copyright 2016-2020 XMRig , + * Copyright (c) 2018-2021 SChernykh + * Copyright (c) 2016-2021 XMRig , * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -26,6 +20,7 @@ #include "3rdparty/rapidjson/document.h" #include "base/io/log/Log.h" #include "base/kernel/interfaces/IJsonReader.h" +#include "base/net/dns/Dns.h" #include "donate.h" @@ -149,6 +144,7 @@ void xmrig::Config::getJSON(rapidjson::Document &doc) const doc.AddMember(StringRef(kTls), m_tls.toJSON(doc), allocator); # endif + doc.AddMember(StringRef(DnsConfig::kField), Dns::config().toJSON(doc), allocator); doc.AddMember(StringRef(kUserAgent), m_userAgent.toJSON(), allocator); doc.AddMember(StringRef(kSyslog), isSyslog(), allocator); doc.AddMember(StringRef(kVerbose), isVerbose(), allocator); diff --git a/src/core/config/Config.h b/src/core/config/Config.h index b1f28d379..4a81cb79c 100644 --- a/src/core/config/Config.h +++ b/src/core/config/Config.h @@ -1,12 +1,6 @@ /* XMRig - * Copyright 2010 Jeff Garzik - * Copyright 2012-2014 pooler - * Copyright 2014 Lucas Jones - * Copyright 2014-2016 Wolf9466 - * Copyright 2016 Jay D Dee - * Copyright 2017-2018 XMR-Stak , - * Copyright 2018-2020 SChernykh - * Copyright 2016-2020 XMRig , + * Copyright (c) 2018-2021 SChernykh + * Copyright (c) 2016-2021 XMRig , * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/src/core/config/Config_platform.h b/src/core/config/Config_platform.h index 140b59267..bd0d400ac 100644 --- a/src/core/config/Config_platform.h +++ b/src/core/config/Config_platform.h @@ -94,6 +94,8 @@ static struct option const options[] = { { "access-password", 1, nullptr, IConfig::ProxyPasswordKey }, { "login-file", 1, nullptr, IConfig::LoginFileKey }, { "data-dir", 1, nullptr, IConfig::DataDirKey }, + { "dns-ipv6", 0, nullptr, IConfig::DnsIPv6Key }, + { "dns-ttl", 1, nullptr, IConfig::DnsTtlKey }, { nullptr, 0, nullptr, 0 } }; diff --git a/src/core/config/usage.h b/src/core/config/usage.h index 33f66e65f..76e9eea5f 100644 --- a/src/core/config/usage.h +++ b/src/core/config/usage.h @@ -1,12 +1,11 @@ /* XMRig - * Copyright 2010 Jeff Garzik - * Copyright 2012-2014 pooler - * Copyright 2014 Lucas Jones - * Copyright 2014-2016 Wolf9466 - * Copyright 2016 Jay D Dee - * Copyright 2017-2018 XMR-Stak , - * Copyright 2018-2019 SChernykh - * Copyright 2016-2019 XMRig , + * Copyright (c) 2010 Jeff Garzik + * Copyright (c) 2012-2014 pooler + * Copyright (c) 2014 Lucas Jones + * Copyright (c) 2014-2016 Wolf9466 + * Copyright (c) 2016 Jay D Dee + * Copyright (c) 2018-2021 SChernykh + * Copyright (c) 2016-2021 XMRig , * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -35,76 +34,96 @@ namespace xmrig { -static char const usage_raw[] = "\ -Usage: " APP_ID " [OPTIONS]\n\ -Options:\n\ - -b, --bind=ADDR bind to specified address, example \"0.0.0.0:3333\"\n\ - -a, --algo=ALGO mining algorithm https://xmrig.com/docs/algorithms\n\ - --coin=COIN specify coin instead of algorithm\n\ - -m, --mode=MODE proxy mode, nicehash (default) or simple\n\ - -o, --url=URL URL of mining server\n\ - -O, --userpass=U:P username:password pair for mining server\n\ - -u, --user=USERNAME username for mining server\n\ - -p, --pass=PASSWORD password for mining server\n\ - --rig-id=ID rig identifier for pool-side statistics (needs pool support)\n\ - --tls-fingerprint=F pool TLS certificate fingerprint, if set enable strict certificate pinning\n\ - -k, --keepalive prevent timeout (needs pool support)\n\ - -r, --retries=N number of times to retry before switch to backup server (default: 1)\n\ - -R, --retry-pause=N time to pause between retries (default: 1 second)\n\ - --custom-diff=N override pool diff\n\ - --custom-diff-stats calculate stats using custom diff shares instead of pool shares\n\ - --reuse-timeout=N timeout in seconds for reuse pool connections in simple mode\n\ - --algo-perf-same-threshold=N algo perf threshold in percent that proxy uses to group miners into one upstream\n\ - --verbose verbose output\n\ - --user-agent=AGENT set custom user-agent string for pool\n\ - --no-color disable colored output\n\ - --no-workers disable per worker statistics\n\ - --variant algorithm PoW variant\n\ - --donate-level=N donate level, default 2%%\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 -"\ - -A --access-log-file=N log all workers access to a file\n\ - --access-password=P set password to restrict connections to the proxy\n\ - --no-algo-ext disable \"algo\" protocol extension\n\ - --api-worker-id=ID custom worker-id (instance name) 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" -#ifdef XMRIG_FEATURE_TLS -"\ - --tls enable SSL/TLS support for pool connection (needs pool support)\n\ - --tls-gen=HOSTNAME generate TLS certificate for specific hostname\n\ - --tls-bind=ADDR bind to specified address with enabled TLS\n\ - --tls-cert=FILE load TLS certificate chain from a file in the PEM format\n\ - --tls-cert-key=FILE load TLS certificate private key from a file in the PEM format\n\ - --tls-dhparam=FILE load DH parameters for DHE ciphers from a file in the PEM format\n\ - --tls-protocols=N enable specified TLS protocols, example: \"TLSv1 TLSv1.1 TLSv1.2 TLSv1.3\"\n\ - --tls-ciphers=S set list of available ciphers (TLSv1.2 and below)\n\ - --tls-ciphersuites=S set list of available TLSv1.3 ciphersuites\n" -#endif -"\ - -h, --help display this help and exit\n\ - -V, --version output version information and exit\n\ -"; - - static inline const std::string &usage() { static std::string u; - if (u.empty()) { - u = usage_raw; + if (!u.empty()) { + return u; } + u += "Usage: " APP_ID " [OPTIONS]\n\nNetwork:\n"; + + u += " -o, --url=URL URL of mining server\n"; + u += " -a, --algo=ALGO mining algorithm https://xmrig.com/docs/algorithms\n"; + u += " --coin=COIN specify coin instead of algorithm\n"; + u += " -u, --user=USERNAME username for mining server\n"; + u += " -p, --pass=PASSWORD password for mining server\n"; + u += " -O, --userpass=U:P username:password pair for mining server\n"; + u += " -x, --proxy=HOST:PORT connect through a SOCKS5 proxy\n"; + u += " -k, --keepalive send keepalived packet for prevent timeout (needs pool support)\n"; + u += " --rig-id=ID rig identifier for pool-side statistics (needs pool support)\n"; + +# ifdef XMRIG_FEATURE_TLS + u += " --tls enable SSL/TLS support (needs pool support)\n"; + u += " --tls-fingerprint=HEX pool TLS certificate fingerprint for strict certificate pinning\n"; +# endif + + u += " --dns-ipv6 prefer IPv6 records from DNS responses\n"; + u += " --dns-ttl=N N seconds (default: 30) TTL for internal DNS cache\n"; + +# ifdef XMRIG_FEATURE_HTTP + u += " --daemon use daemon RPC instead of pool for solo mining\n"; + u += " --daemon-poll-interval=N daemon poll interval in milliseconds (default: 1000)\n"; + u += " --self-select=URL self-select block templates from URL\n"; + u += " --submit-to-origin also submit solution back to self-select URL\n"; +# endif + + u += " -r, --retries=N number of times to retry before switch to backup server (default: 5)\n"; + u += " -R, --retry-pause=N time to pause between retries (default: 5)\n"; + u += " --user-agent set custom user-agent string for pool\n"; + u += " --donate-level=N donate level, default 0%%\n"; + + u += "\nOptions:\n"; + u += " -b, --bind=ADDR bind to specified address, example \"0.0.0.0:3333\"\n"; + u += " -m, --mode=MODE proxy mode, nicehash (default) or simple\n"; + u += " --custom-diff=N override pool diff\n"; + u += " --custom-diff-stats calculate stats using custom diff shares instead of pool shares\n"; + u += " --reuse-timeout=N timeout in seconds for reuse pool connections in simple mode\n"; + u += " --no-workers disable per worker statistics\n"; + u += " --access-password=P set password to restrict connections to the proxy\n"; + u += " --no-algo-ext disable \"algo\" protocol extension\n"; + +# ifdef XMRIG_FEATURE_HTTP + u += "\nAPI:\n"; + u += " --api-worker-id=ID custom worker-id for API\n"; + u += " --api-id=ID custom instance ID for API\n"; + u += " --http-host=HOST bind host for HTTP API (default: 127.0.0.1)\n"; + u += " --http-port=N bind port for HTTP API\n"; + u += " --http-access-token=T access token for HTTP API\n"; + u += " --http-no-restricted enable full remote access to HTTP API (only if access token set)\n"; +# endif + +# ifdef XMRIG_FEATURE_TLS + u += "\nTLS:\n"; + u += " --tls-bind=ADDR bind to specified address with enabled TLS\n"; + u += " --tls-gen=HOSTNAME generate TLS certificate for specific hostname\n"; + u += " --tls-cert=FILE load TLS certificate chain from a file in the PEM format\n"; + u += " --tls-cert-key=FILE load TLS certificate private key from a file in the PEM format\n"; + u += " --tls-dhparam=FILE load DH parameters for DHE ciphers from a file in the PEM format\n"; + u += " --tls-protocols=N enable specified TLS protocols, example: \"TLSv1 TLSv1.1 TLSv1.2 TLSv1.3\"\n"; + u += " --tls-ciphers=S set list of available ciphers (TLSv1.2 and below)\n"; + u += " --tls-ciphersuites=S set list of available TLSv1.3 ciphersuites\n"; +# endif + + u += "\nLogging:\n"; +# ifdef HAVE_SYSLOG_H + u += " -S, --syslog use system log for output messages\n"; +# endif + + u += " -l, --log-file=FILE log all output to a file\n"; + u += " -A --access-log-file=FILE log all workers access to a file\n"; + u += " --no-color disable colored output\n"; + u += " --verbose verbose output\n"; + + u += "\nMisc:\n"; + u += " -c, --config=FILE load a JSON-format configuration file\n"; + u += " -B, --background run the proxy in the background\n"; + u += " -V, --version output version information and exit\n"; + u += " --algo-perf-same-threshold=N algo perf threshold in percent that proxy uses to group miners into one upstream\n"; + u += " -h, --help display this help and exit\n"; + u += " --dry-run test configuration and exit\n"; + return u; } diff --git a/src/version.h b/src/version.h index bc204ff4f..ba1abafd8 100644 --- a/src/version.h +++ b/src/version.h @@ -22,15 +22,15 @@ #define APP_ID "xmrig-proxy" #define APP_NAME "xmrig-proxy" #define APP_DESC "XMRig Stratum proxy" -#define APP_VERSION "6.10.1-mo2" +#define APP_VERSION "6.12.0-mo1" #define APP_DOMAIN "xmrig.com" #define APP_SITE "www.xmrig.com" #define APP_COPYRIGHT "Copyright (C) 2016-2020 xmrig.com" #define APP_KIND "proxy" #define APP_VER_MAJOR 6 -#define APP_VER_MINOR 10 -#define APP_VER_PATCH 1 +#define APP_VER_MINOR 12 +#define APP_VER_PATCH 0 #ifdef _MSC_VER # if (_MSC_VER >= 1920)