mirror of
https://github.com/xmrig/xmrig.git
synced 2025-02-02 03:06:30 +00:00
Merge branch 'dev'
This commit is contained in:
commit
253e349ef9
41 changed files with 760 additions and 274 deletions
11
CHANGELOG.md
11
CHANGELOG.md
|
@ -1,3 +1,14 @@
|
|||
# v6.11.0
|
||||
- [#2196](https://github.com/xmrig/xmrig/pull/2196) Improved DNS subsystem and added new DNS specific options.
|
||||
- [#2172](https://github.com/xmrig/xmrig/pull/2172) Fixed build on Alpine 3.13.
|
||||
- [#2177](https://github.com/xmrig/xmrig/pull/2177) Fixed ARM specific compilation error with GCC 10.2.
|
||||
- [#2214](https://github.com/xmrig/xmrig/pull/2214) [#2216](https://github.com/xmrig/xmrig/pull/2216) [#2235](https://github.com/xmrig/xmrig/pull/2235) Optimized `cn-heavy` algorithm.
|
||||
- [#2217](https://github.com/xmrig/xmrig/pull/2217) Fixed mining job creation sequence.
|
||||
- [#2225](https://github.com/xmrig/xmrig/pull/2225) Fixed build without OpenCL support on some systems.
|
||||
- [#2229](https://github.com/xmrig/xmrig/pull/2229) Don't use RandomX JIT if `WITH_ASM=OFF`.
|
||||
- [#2228](https://github.com/xmrig/xmrig/pull/2228) Removed useless code for cryptonight algorithms.
|
||||
- [#2234](https://github.com/xmrig/xmrig/pull/2234) Fixed build error on gcc 4.8.
|
||||
|
||||
# v6.10.0
|
||||
- [#2122](https://github.com/xmrig/xmrig/pull/2122) Fixed pause logic when both pause on battery and user activity are enabled.
|
||||
- [#2123](https://github.com/xmrig/xmrig/issues/2123) Fixed compatibility with gcc 4.8.
|
||||
|
|
|
@ -42,13 +42,13 @@ if (WITH_RANDOMX)
|
|||
src/crypto/rx/RxVm.cpp
|
||||
)
|
||||
|
||||
if (CMAKE_C_COMPILER_ID MATCHES MSVC)
|
||||
if (WITH_ASM AND CMAKE_C_COMPILER_ID MATCHES MSVC)
|
||||
enable_language(ASM_MASM)
|
||||
list(APPEND SOURCES_CRYPTO
|
||||
src/crypto/randomx/jit_compiler_x86_static.asm
|
||||
src/crypto/randomx/jit_compiler_x86.cpp
|
||||
)
|
||||
elseif (NOT XMRIG_ARM AND CMAKE_SIZEOF_VOID_P EQUAL 8)
|
||||
elseif (WITH_ASM AND NOT XMRIG_ARM AND CMAKE_SIZEOF_VOID_P EQUAL 8)
|
||||
list(APPEND SOURCES_CRYPTO
|
||||
src/crypto/randomx/jit_compiler_x86_static.S
|
||||
src/crypto/randomx/jit_compiler_x86.cpp
|
||||
|
|
|
@ -20,6 +20,9 @@
|
|||
#define XMRIG_WORKERS_H
|
||||
|
||||
|
||||
#include <memory>
|
||||
|
||||
|
||||
#include "backend/common/Thread.h"
|
||||
#include "backend/cpu/CpuLaunchData.h"
|
||||
|
||||
|
|
|
@ -24,6 +24,7 @@
|
|||
#include "backend/opencl/wrappers/OclDevice.h"
|
||||
|
||||
|
||||
#include <limits.h>
|
||||
#include <dirent.h>
|
||||
#include <fstream>
|
||||
#include <map>
|
||||
|
|
|
@ -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/BaseClient.cpp
|
||||
src/base/net/stratum/Client.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<char *>(m_endl), sizeof(m_endl) - 1)
|
||||
};
|
||||
|
||||
memcpy(buf[0].base, data, size);
|
||||
|
|
|
@ -42,9 +42,9 @@ public:
|
|||
|
||||
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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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<uint64_t>(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);
|
||||
|
|
|
@ -82,6 +82,8 @@ public:
|
|||
HugePageSizeKey = 1050,
|
||||
PauseOnActiveKey = 1051,
|
||||
SubmitToOriginKey = 1052,
|
||||
DnsIPv6Key = 1053,
|
||||
DnsTtlKey = 1054,
|
||||
|
||||
// xmrig common
|
||||
CPUPriorityKey = 1021,
|
||||
|
|
54
src/base/kernel/interfaces/IDnsBackend.h
Normal file
54
src/base/kernel/interfaces/IDnsBackend.h
Normal file
|
@ -0,0 +1,54 @@
|
|||
/* XMRig
|
||||
* Copyright (c) 2018-2021 SChernykh <https://github.com/SChernykh>
|
||||
* Copyright (c) 2016-2021 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_IDNSBACKEND_H
|
||||
#define XMRIG_IDNSBACKEND_H
|
||||
|
||||
|
||||
#include "base/tools/Object.h"
|
||||
|
||||
|
||||
#include <memory>
|
||||
|
||||
|
||||
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<DnsRequest> resolve(const String &host, IDnsListener *listener, uint64_t ttl) = 0;
|
||||
};
|
||||
|
||||
|
||||
} /* namespace xmrig */
|
||||
|
||||
|
||||
#endif // XMRIG_IDNSBACKEND_H
|
|
@ -1,6 +1,6 @@
|
|||
/* XMRig
|
||||
* Copyright (c) 2018-2020 SChernykh <https://github.com/SChernykh>
|
||||
* Copyright (c) 2016-2020 XMRig <https://github.com/xmrig>, <support@xmrig.com>
|
||||
* Copyright (c) 2018-2021 SChernykh <https://github.com/SChernykh>
|
||||
* Copyright (c) 2016-2021 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
|
||||
|
@ -26,7 +26,7 @@
|
|||
namespace xmrig {
|
||||
|
||||
|
||||
class Dns;
|
||||
class DnsRecords;
|
||||
|
||||
|
||||
class IDnsListener
|
||||
|
@ -37,7 +37,7 @@ public:
|
|||
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;
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/* XMRig
|
||||
* Copyright (c) 2018-2020 SChernykh <https://github.com/SChernykh>
|
||||
* Copyright (c) 2016-2020 XMRig <https://github.com/xmrig>, <support@xmrig.com>
|
||||
* Copyright (c) 2018-2021 SChernykh <https://github.com/SChernykh>
|
||||
* Copyright (c) 2016-2021 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
|
||||
|
@ -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> Dns::m_storage;
|
||||
static const DnsRecord defaultRecord;
|
||||
}
|
||||
|
||||
|
||||
xmrig::Dns::Dns(IDnsListener *listener) :
|
||||
m_listener(listener)
|
||||
DnsConfig Dns::m_config;
|
||||
std::map<String, std::shared_ptr<IDnsBackend> > Dns::m_backends;
|
||||
|
||||
|
||||
} // namespace xmrig
|
||||
|
||||
|
||||
std::shared_ptr<xmrig::DnsRequest> xmrig::Dns::resolve(const String &host, IDnsListener *listener, uint64_t ttl)
|
||||
{
|
||||
m_key = m_storage.add(this);
|
||||
if (m_backends.find(host) == m_backends.end()) {
|
||||
m_backends.insert({ host, std::make_shared<DnsUvBackend>() });
|
||||
}
|
||||
|
||||
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();
|
||||
}
|
||||
|
||||
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<size_t>(rand()) % ipv6];
|
||||
}
|
||||
|
||||
if (ipv4) {
|
||||
return m_ipv4[ipv4 == 1 ? 0 : static_cast<size_t>(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);
|
||||
}
|
||||
|
||||
|
||||
void xmrig::Dns::onResolved(uv_getaddrinfo_t *req, int status, addrinfo *res)
|
||||
{
|
||||
Dns *dns = m_storage.get(req->data);
|
||||
if (dns) {
|
||||
dns->onResolved(status, res);
|
||||
}
|
||||
|
||||
uv_freeaddrinfo(res);
|
||||
return m_backends.at(host)->resolve(host, listener, ttl == 0 ? m_config.ttl() : ttl);
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/* XMRig
|
||||
* Copyright (c) 2018-2020 SChernykh <https://github.com/SChernykh>
|
||||
* Copyright (c) 2016-2020 XMRig <https://github.com/xmrig>, <support@xmrig.com>
|
||||
* Copyright (c) 2018-2021 SChernykh <https://github.com/SChernykh>
|
||||
* Copyright (c) 2016-2021 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
|
||||
|
@ -20,55 +20,34 @@
|
|||
#define XMRIG_DNS_H
|
||||
|
||||
|
||||
#include <vector>
|
||||
#include <uv.h>
|
||||
|
||||
|
||||
#include "base/net/dns/DnsRecord.h"
|
||||
#include "base/net/tools/Storage.h"
|
||||
#include "base/tools/Object.h"
|
||||
#include "base/net/dns/DnsConfig.h"
|
||||
#include "base/tools/String.h"
|
||||
|
||||
|
||||
#include <map>
|
||||
#include <memory>
|
||||
|
||||
|
||||
namespace xmrig {
|
||||
|
||||
|
||||
class DnsConfig;
|
||||
class DnsRequest;
|
||||
class IDnsBackend;
|
||||
class IDnsListener;
|
||||
|
||||
|
||||
class Dns
|
||||
{
|
||||
public:
|
||||
XMRIG_DISABLE_COPY_MOVE_DEFAULT(Dns)
|
||||
inline static const DnsConfig &config() { return m_config; }
|
||||
inline static void set(const DnsConfig &config) { m_config = config; }
|
||||
|
||||
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; }
|
||||
|
||||
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<DnsRequest> 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<DnsRecord> m_ipv4;
|
||||
std::vector<DnsRecord> m_ipv6;
|
||||
String m_host;
|
||||
uintptr_t m_key;
|
||||
uv_getaddrinfo_t *m_resolver = nullptr;
|
||||
|
||||
static Storage<Dns> m_storage;
|
||||
static DnsConfig m_config;
|
||||
static std::map<String, std::shared_ptr<IDnsBackend> > m_backends;
|
||||
};
|
||||
|
||||
|
||||
|
|
57
src/base/net/dns/DnsConfig.cpp
Normal file
57
src/base/net/dns/DnsConfig.cpp
Normal file
|
@ -0,0 +1,57 @@
|
|||
/* XMRig
|
||||
* Copyright (c) 2018-2021 SChernykh <https://github.com/SChernykh>
|
||||
* Copyright (c) 2016-2021 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/net/dns/DnsConfig.h"
|
||||
#include "3rdparty/rapidjson/document.h"
|
||||
#include "base/io/json/Json.h"
|
||||
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
|
||||
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;
|
||||
}
|
54
src/base/net/dns/DnsConfig.h
Normal file
54
src/base/net/dns/DnsConfig.h
Normal file
|
@ -0,0 +1,54 @@
|
|||
/* XMRig
|
||||
* Copyright (c) 2018-2021 SChernykh <https://github.com/SChernykh>
|
||||
* Copyright (c) 2016-2021 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_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 */
|
|
@ -1,6 +1,6 @@
|
|||
/* XMRig
|
||||
* Copyright (c) 2018-2020 SChernykh <https://github.com/SChernykh>
|
||||
* Copyright (c) 2016-2020 XMRig <https://github.com/xmrig>, <support@xmrig.com>
|
||||
* Copyright (c) 2018-2021 SChernykh <https://github.com/SChernykh>
|
||||
* Copyright (c) 2016-2021 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
|
||||
|
@ -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))
|
||||
{
|
||||
static_assert(sizeof(m_data) >= sizeof(sockaddr_in6), "Not enough storage for IPv6 address.");
|
||||
|
||||
memcpy(m_data, addr->ai_addr, m_type == AAAA ? sizeof(sockaddr_in6) : sizeof(sockaddr_in));
|
||||
}
|
||||
|
||||
|
||||
const sockaddr *xmrig::DnsRecord::addr(uint16_t port) const
|
||||
{
|
||||
reinterpret_cast<sockaddr_in*>(m_data)->sin_port = htons(port);
|
||||
|
||||
return reinterpret_cast<const sockaddr *>(m_data);
|
||||
}
|
||||
|
||||
|
||||
xmrig::String xmrig::DnsRecord::ip() const
|
||||
{
|
||||
char *buf = nullptr;
|
||||
|
||||
if (m_type == AAAA) {
|
||||
buf = new char[45]();
|
||||
uv_ip6_name(reinterpret_cast<sockaddr_in6*>(addr->ai_addr), buf, 45);
|
||||
uv_ip6_name(reinterpret_cast<sockaddr_in6*>(m_data), buf, 45);
|
||||
}
|
||||
else {
|
||||
buf = new char[16]();
|
||||
uv_ip4_name(reinterpret_cast<sockaddr_in*>(addr->ai_addr), buf, 16);
|
||||
uv_ip4_name(reinterpret_cast<sockaddr_in*>(m_data), buf, 16);
|
||||
}
|
||||
|
||||
m_ip = buf;
|
||||
}
|
||||
|
||||
|
||||
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);
|
||||
|
||||
return reinterpret_cast<sockaddr *>(addr);
|
||||
}
|
||||
|
||||
if (m_type == AAAA) {
|
||||
auto addr = new sockaddr_in6();
|
||||
uv_ip6_addr(m_ip.data(), port, addr);
|
||||
|
||||
return reinterpret_cast<sockaddr *>(addr);
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
return buf;
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/* XMRig
|
||||
* Copyright (c) 2018-2020 SChernykh <https://github.com/SChernykh>
|
||||
* Copyright (c) 2016-2020 XMRig <https://github.com/xmrig>, <support@xmrig.com>
|
||||
* Copyright (c) 2018-2021 SChernykh <https://github.com/SChernykh>
|
||||
* Copyright (c) 2016-2021 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
|
||||
|
@ -33,7 +33,7 @@ namespace xmrig {
|
|||
class DnsRecord
|
||||
{
|
||||
public:
|
||||
enum Type {
|
||||
enum Type : uint32_t {
|
||||
Unknown,
|
||||
A,
|
||||
AAAA
|
||||
|
@ -42,15 +42,15 @@ public:
|
|||
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;
|
||||
};
|
||||
|
||||
|
||||
|
|
108
src/base/net/dns/DnsRecords.cpp
Normal file
108
src/base/net/dns/DnsRecords.cpp
Normal file
|
@ -0,0 +1,108 @@
|
|||
/* XMRig
|
||||
* Copyright (c) 2018-2021 SChernykh <https://github.com/SChernykh>
|
||||
* Copyright (c) 2016-2021 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 <uv.h>
|
||||
|
||||
|
||||
#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<size_t>(rand()) % ipv6];
|
||||
}
|
||||
|
||||
if (ipv4) {
|
||||
return m_ipv4[ipv4 == 1 ? 0 : static_cast<size_t>(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;
|
||||
}
|
||||
}
|
48
src/base/net/dns/DnsRecords.h
Normal file
48
src/base/net/dns/DnsRecords.h
Normal file
|
@ -0,0 +1,48 @@
|
|||
/* XMRig
|
||||
* Copyright (c) 2018-2021 SChernykh <https://github.com/SChernykh>
|
||||
* Copyright (c) 2016-2021 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_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<DnsRecord> m_ipv4;
|
||||
std::vector<DnsRecord> m_ipv6;
|
||||
};
|
||||
|
||||
|
||||
} /* namespace xmrig */
|
||||
|
||||
|
||||
#endif /* XMRIG_DNSRECORDS_H */
|
50
src/base/net/dns/DnsRequest.h
Normal file
50
src/base/net/dns/DnsRequest.h
Normal file
|
@ -0,0 +1,50 @@
|
|||
/* XMRig
|
||||
* Copyright (c) 2018-2021 SChernykh <https://github.com/SChernykh>
|
||||
* Copyright (c) 2016-2021 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_DNSREQUEST_H
|
||||
#define XMRIG_DNSREQUEST_H
|
||||
|
||||
|
||||
#include "base/tools/Object.h"
|
||||
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
|
||||
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 */
|
134
src/base/net/dns/DnsUvBackend.cpp
Normal file
134
src/base/net/dns/DnsUvBackend.cpp
Normal file
|
@ -0,0 +1,134 @@
|
|||
/* XMRig
|
||||
* Copyright (c) 2018-2021 SChernykh <https://github.com/SChernykh>
|
||||
* Copyright (c) 2016-2021 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 <uv.h>
|
||||
|
||||
|
||||
#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>& DnsUvBackend::getStorage()
|
||||
{
|
||||
static Storage<DnsUvBackend>* storage = new Storage<DnsUvBackend>();
|
||||
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::DnsRequest> xmrig::DnsUvBackend::resolve(const String &host, IDnsListener *listener, uint64_t ttl)
|
||||
{
|
||||
auto req = std::make_shared<DnsRequest>(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<uv_getaddrinfo_t>();
|
||||
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);
|
||||
}
|
71
src/base/net/dns/DnsUvBackend.h
Normal file
71
src/base/net/dns/DnsUvBackend.h
Normal file
|
@ -0,0 +1,71 @@
|
|||
/* XMRig
|
||||
* Copyright (c) 2018-2021 SChernykh <https://github.com/SChernykh>
|
||||
* Copyright (c) 2016-2021 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_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 <queue>
|
||||
|
||||
|
||||
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<DnsRequest> 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<std::weak_ptr<DnsRequest> > m_queue;
|
||||
std::shared_ptr<uv_getaddrinfo_t> m_req;
|
||||
uint64_t m_ts = 0;
|
||||
uintptr_t m_key;
|
||||
|
||||
static Storage<DnsUvBackend>& getStorage();
|
||||
};
|
||||
|
||||
|
||||
} /* namespace xmrig */
|
||||
|
||||
|
||||
#endif /* XMRIG_DNSUVBACKEND_H */
|
|
@ -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 <sstream>
|
||||
#include <uv.h>
|
||||
|
||||
|
||||
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<Dns>(this);
|
||||
|
||||
if (m_req.timeout) {
|
||||
m_timer = std::make_shared<Timer>(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);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -32,7 +32,7 @@
|
|||
namespace xmrig {
|
||||
|
||||
|
||||
class String;
|
||||
class DnsRequest;
|
||||
|
||||
|
||||
class HttpClient : public HttpContext, public IDnsListener, public ITimerListener
|
||||
|
@ -51,7 +51,7 @@ public:
|
|||
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 @@ private:
|
|||
|
||||
const char *m_tag;
|
||||
FetchRequest m_req;
|
||||
std::shared_ptr<Dns> m_dns;
|
||||
std::shared_ptr<DnsRequest> m_dns;
|
||||
std::shared_ptr<Timer> m_timer;
|
||||
};
|
||||
|
||||
|
|
|
@ -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,14 @@ 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]));
|
||||
}
|
||||
|
||||
# ifdef XMRIG_FEATURE_HTTP
|
||||
if (m_pool.mode() == Pool::MODE_SELF_SELECT) {
|
||||
job.setExtraNonce(Json::getString(params, "extra_nonce"));
|
||||
|
@ -401,14 +410,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 +525,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 +561,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 +579,6 @@ void xmrig::Client::connect(sockaddr *addr)
|
|||
# endif
|
||||
|
||||
uv_tcp_connect(req, m_socket, addr, onConnect);
|
||||
|
||||
delete addr;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -50,6 +50,7 @@ using BIO = struct bio_st;
|
|||
namespace xmrig {
|
||||
|
||||
|
||||
class DnsRequest;
|
||||
class IClientListener;
|
||||
class JobResult;
|
||||
|
||||
|
@ -79,7 +80,7 @@ protected:
|
|||
void deleteLater() override;
|
||||
void tick(uint64_t now) override;
|
||||
|
||||
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"; }
|
||||
|
@ -108,7 +109,7 @@ private:
|
|||
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);
|
||||
|
@ -131,10 +132,10 @@ private:
|
|||
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<EXT_MAX> m_extensions;
|
||||
std::shared_ptr<DnsRequest> m_dns;
|
||||
std::vector<char> m_sendBuf;
|
||||
String m_rpcId;
|
||||
Tls *m_tls = nullptr;
|
||||
|
|
|
@ -247,6 +247,10 @@ 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()) {
|
||||
job.setAlgorithm(m_pool.coin().algorithm(job.blob()[0]));
|
||||
}
|
||||
|
||||
if (blocktemplate.isNull() || !job.setBlob(m_blockhashingblob)) {
|
||||
*code = 4;
|
||||
return false;
|
||||
|
@ -257,10 +261,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");
|
||||
|
|
|
@ -27,6 +27,7 @@
|
|||
#include "base/io/log/Tags.h"
|
||||
#include "base/kernel/interfaces/IClientListener.h"
|
||||
#include "base/net/dns/Dns.h"
|
||||
#include "base/net/dns/DnsRecords.h"
|
||||
#include "base/net/http/Fetch.h"
|
||||
#include "base/net/http/HttpData.h"
|
||||
#include "base/net/http/HttpListener.h"
|
||||
|
@ -47,8 +48,8 @@ xmrig::BenchClient::BenchClient(const std::shared_ptr<BenchConfig> &benchmark, I
|
|||
std::vector<char> blob(112 * 2 + 1, '0');
|
||||
blob.back() = '\0';
|
||||
|
||||
m_job.setBlob(blob.data());
|
||||
m_job.setAlgorithm(m_benchmark->algorithm());
|
||||
m_job.setBlob(blob.data());
|
||||
m_job.setDiff(std::numeric_limits<uint64_t>::max());
|
||||
m_job.setHeight(1);
|
||||
m_job.setId("00000000");
|
||||
|
@ -185,16 +186,18 @@ void xmrig::BenchClient::onHttpData(const HttpData &data)
|
|||
}
|
||||
|
||||
|
||||
void xmrig::BenchClient::onResolved(const Dns &dns, int status)
|
||||
void xmrig::BenchClient::onResolved(const DnsRecords &records, int status, const char *error)
|
||||
{
|
||||
# ifdef XMRIG_FEATURE_HTTP
|
||||
assert(!m_httpListener);
|
||||
|
||||
m_dns.reset();
|
||||
|
||||
if (status < 0) {
|
||||
return setError(dns.error(), "DNS error");
|
||||
return setError(error, "DNS error");
|
||||
}
|
||||
|
||||
m_ip = dns.get().ip();
|
||||
m_ip = records.get().ip();
|
||||
m_httpListener = std::make_shared<HttpListener>(this, tag());
|
||||
|
||||
if (m_mode == ONLINE_BENCH) {
|
||||
|
@ -307,11 +310,7 @@ void xmrig::BenchClient::onGetReply(const rapidjson::Value &value)
|
|||
|
||||
void xmrig::BenchClient::resolve()
|
||||
{
|
||||
m_dns = std::make_shared<Dns>(this);
|
||||
|
||||
if (!m_dns->resolve(BenchConfig::kApiHost)) {
|
||||
setError(m_dns->error(), "getaddrinfo error");
|
||||
}
|
||||
m_dns = Dns::resolve(BenchConfig::kApiHost, this);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -70,7 +70,7 @@ protected:
|
|||
void onBenchDone(uint64_t result, uint64_t diff, uint64_t ts) override;
|
||||
void onBenchReady(uint64_t ts, uint32_t threads, const IBackend *backend) override;
|
||||
void onHttpData(const HttpData &data) override;
|
||||
void onResolved(const Dns &dns, int status) override;
|
||||
void onResolved(const DnsRecords &records, int status, const char *error) override;
|
||||
|
||||
private:
|
||||
enum Mode : uint32_t {
|
||||
|
@ -110,7 +110,7 @@ private:
|
|||
Pool m_pool;
|
||||
Request m_request = NO_REQUEST;
|
||||
std::shared_ptr<BenchConfig> m_benchmark;
|
||||
std::shared_ptr<Dns> m_dns;
|
||||
std::shared_ptr<DnsRequest> m_dns;
|
||||
std::shared_ptr<IHttpListener> m_httpListener;
|
||||
String m_ip;
|
||||
String m_token;
|
||||
|
|
|
@ -45,7 +45,7 @@ public:
|
|||
return;
|
||||
}
|
||||
|
||||
uv_close(reinterpret_cast<uv_handle_t *>(handle), [](uv_handle_t *handle) { delete handle; });
|
||||
uv_close(reinterpret_cast<uv_handle_t *>(handle), [](uv_handle_t *handle) { delete reinterpret_cast<T>(handle); });
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -28,6 +28,7 @@
|
|||
#include "backend/cpu/Cpu.h"
|
||||
#include "base/io/log/Log.h"
|
||||
#include "base/kernel/interfaces/IJsonReader.h"
|
||||
#include "base/net/dns/Dns.h"
|
||||
#include "crypto/common/Assembly.h"
|
||||
|
||||
|
||||
|
@ -295,6 +296,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(kVerbose), Log::verbose(), allocator);
|
||||
doc.AddMember(StringRef(kWatch), m_watch, allocator);
|
||||
|
|
|
@ -93,7 +93,9 @@ static const option options[] = {
|
|||
{ "title", 1, nullptr, IConfig::TitleKey },
|
||||
{ "no-title", 0, nullptr, IConfig::NoTitleKey },
|
||||
{ "pause-on-battery", 0, nullptr, IConfig::PauseOnBatteryKey },
|
||||
{ "pause-on-active", 1, nullptr, IConfig::PauseOnActiveKey },
|
||||
{ "pause-on-active", 1, nullptr, IConfig::PauseOnActiveKey },
|
||||
{ "dns-ipv6", 0, nullptr, IConfig::DnsIPv6Key },
|
||||
{ "dns-ttl", 1, nullptr, IConfig::DnsTtlKey },
|
||||
# ifdef XMRIG_FEATURE_BENCHMARK
|
||||
{ "stress", 0, nullptr, IConfig::StressKey },
|
||||
{ "bench", 1, nullptr, IConfig::BenchKey },
|
||||
|
|
|
@ -59,6 +59,9 @@ static inline const std::string &usage()
|
|||
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";
|
||||
|
|
|
@ -190,8 +190,8 @@
|
|||
r##part[1] = static_cast<uint32_t>(h##part[12] >> 32); \
|
||||
r##part[2] = static_cast<uint32_t>(h##part[13]); \
|
||||
r##part[3] = static_cast<uint32_t>(h##part[13] >> 32); \
|
||||
} \
|
||||
v4_random_math_init<ALGO>(code##part, height);
|
||||
v4_random_math_init<ALGO>(code##part, height); \
|
||||
}
|
||||
|
||||
#define VARIANT4_RANDOM_MATH(part, al, ah, cl, bx0, bx1) \
|
||||
if (props.isR()) { \
|
||||
|
|
|
@ -739,8 +739,18 @@ inline void cryptonight_single_hash(const uint8_t *__restrict__ input, size_t si
|
|||
# ifdef XMRIG_ALGO_CN_HEAVY
|
||||
if (props.isHeavy()) {
|
||||
int64_t n = ((int64_t*)&l0[interleaved_index<interleave>(idx0 & MASK)])[0];
|
||||
int32_t d = ((int32_t*)&l0[interleaved_index<interleave>(idx0 & MASK)])[2];
|
||||
int64_t q = n / (d | 0x5);
|
||||
int64_t d = ((int32_t*)&l0[interleaved_index<interleave>(idx0 & MASK)])[2];
|
||||
|
||||
int64_t d5;
|
||||
|
||||
# if defined(_MSC_VER) || (defined(__GNUC__) && (__GNUC__ == 8))
|
||||
d5 = d | 5;
|
||||
# else
|
||||
// Workaround for stupid GCC which converts to 32 bit before doing "| 5" and then converts back to 64 bit
|
||||
asm("mov %1, %0\n\tor $5, %0" : "=r"(d5) : "r"(d));
|
||||
# endif
|
||||
|
||||
int64_t q = n / d5;
|
||||
|
||||
((int64_t*)&l0[interleaved_index<interleave>(idx0 & MASK)])[0] = n ^ q;
|
||||
|
||||
|
|
|
@ -343,7 +343,7 @@ typedef union ALIGN_STRUCT(16) SIMDVec {
|
|||
|
||||
// Older gcc does not define vld1q_u8_x4 type
|
||||
#if defined(__GNUC__) && !defined(__clang__) && \
|
||||
((__GNUC__ == 10 && (__GNUC_MINOR__ <= 1)) || \
|
||||
((__GNUC__ == 10 && (__GNUC_MINOR__ <= 2)) || \
|
||||
(__GNUC__ == 9 && (__GNUC_MINOR__ <= 3)) || \
|
||||
(__GNUC__ == 8 && (__GNUC_MINOR__ <= 4)) || __GNUC__ <= 7)
|
||||
FORCE_INLINE uint8x16x4_t _sse2neon_vld1q_u8_x4(const uint8_t *p)
|
||||
|
|
|
@ -103,7 +103,7 @@ namespace randomx {
|
|||
#endif
|
||||
#endif
|
||||
|
||||
#if defined(_M_X64) || defined(__x86_64__)
|
||||
#if defined(XMRIG_FEATURE_ASM) && (defined(_M_X64) || defined(__x86_64__))
|
||||
#define RANDOMX_HAVE_COMPILER 1
|
||||
class JitCompilerX86;
|
||||
using JitCompiler = JitCompilerX86;
|
||||
|
|
|
@ -28,7 +28,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||
|
||||
#pragma once
|
||||
|
||||
#if defined(_M_X64) || defined(__x86_64__)
|
||||
#if defined(XMRIG_FEATURE_ASM) && (defined(_M_X64) || defined(__x86_64__))
|
||||
#include "crypto/randomx/jit_compiler_x86.hpp"
|
||||
#elif defined(__aarch64__)
|
||||
#include "crypto/randomx/jit_compiler_a64.hpp"
|
||||
|
|
|
@ -148,7 +148,7 @@ RandomX_ConfigurationBase::RandomX_ConfigurationBase()
|
|||
fillAes4Rx4_Key[6] = rx_set_int_vec_i128(0xf63befa7, 0x2ba9660a, 0xf765a38b, 0xf273c9e7);
|
||||
fillAes4Rx4_Key[7] = rx_set_int_vec_i128(0xc0b0762d, 0x0c06d1fd, 0x915839de, 0x7a7cd609);
|
||||
|
||||
# if defined(_M_X64) || defined(__x86_64__)
|
||||
# if defined(XMRIG_FEATURE_ASM) && (defined(_M_X64) || defined(__x86_64__))
|
||||
// Workaround for Visual Studio placing trampoline in debug builds.
|
||||
auto addr = [](void (*func)()) {
|
||||
const uint8_t* p = reinterpret_cast<const uint8_t*>(func);
|
||||
|
@ -214,7 +214,7 @@ void RandomX_ConfigurationBase::Apply()
|
|||
ScratchpadL3Mask_Calculated = (((ScratchpadL3_Size / sizeof(uint64_t)) - 1) * 8);
|
||||
ScratchpadL3Mask64_Calculated = ((ScratchpadL3_Size / sizeof(uint64_t)) / 8 - 1) * 64;
|
||||
|
||||
#if defined(_M_X64) || defined(__x86_64__)
|
||||
#if defined(XMRIG_FEATURE_ASM) && (defined(_M_X64) || defined(__x86_64__))
|
||||
*(uint32_t*)(codeShhPrefetchTweaked + 3) = ArgonMemory * 16 - 1;
|
||||
// Not needed right now because all variants use default dataset base size
|
||||
//const uint32_t DatasetBaseMask = DatasetBaseSize - RANDOMX_DATASET_ITEM_SIZE;
|
||||
|
|
|
@ -28,14 +28,14 @@
|
|||
#define APP_ID "xmrig"
|
||||
#define APP_NAME "XMRig"
|
||||
#define APP_DESC "XMRig miner"
|
||||
#define APP_VERSION "6.10.0"
|
||||
#define APP_VERSION "6.11.0-dev"
|
||||
#define APP_DOMAIN "xmrig.com"
|
||||
#define APP_SITE "www.xmrig.com"
|
||||
#define APP_COPYRIGHT "Copyright (C) 2016-2021 xmrig.com"
|
||||
#define APP_KIND "miner"
|
||||
|
||||
#define APP_VER_MAJOR 6
|
||||
#define APP_VER_MINOR 10
|
||||
#define APP_VER_MINOR 11
|
||||
#define APP_VER_PATCH 0
|
||||
|
||||
#ifdef _MSC_VER
|
||||
|
|
Loading…
Reference in a new issue