From 1b875fdabb879ebe0df5aa94c079967a4de68cd0 Mon Sep 17 00:00:00 2001 From: XMRig Date: Fri, 20 Mar 2020 20:53:27 +0700 Subject: [PATCH] Reduced memory consumption on network level. --- src/base/base.cmake | 6 +- src/base/kernel/Base.cpp | 5 +- src/base/kernel/interfaces/ILineListener.h | 9 +- src/base/net/http/HttpClient.cpp | 10 +- src/base/net/http/HttpServer.cpp | 12 +-- src/base/net/https/HttpsServer.cpp | 16 +--- src/base/net/stratum/Client.cpp | 48 +++------- src/base/net/stratum/Client.h | 8 +- src/base/net/stratum/Socks5.cpp | 2 +- src/base/net/stratum/Tls.cpp | 36 ++++--- src/base/net/stratum/Tls.h | 23 +++-- src/base/net/tools/LineReader.cpp | 103 +++++++++++++++++++++ src/base/net/tools/LineReader.h | 62 +++++++++++++ src/base/net/tools/MemPool.h | 96 +++++++++++++++++++ src/base/net/tools/NetBuffer.cpp | 83 +++++++++++++++++ src/base/net/tools/NetBuffer.h | 49 ++++++++++ src/base/net/tools/RecvBuf.h | 99 -------------------- 17 files changed, 462 insertions(+), 205 deletions(-) create mode 100644 src/base/net/tools/LineReader.cpp create mode 100644 src/base/net/tools/LineReader.h create mode 100644 src/base/net/tools/MemPool.h create mode 100644 src/base/net/tools/NetBuffer.cpp create mode 100644 src/base/net/tools/NetBuffer.h delete mode 100644 src/base/net/tools/RecvBuf.h diff --git a/src/base/base.cmake b/src/base/base.cmake index fe30bd9fb..5116da065 100644 --- a/src/base/base.cmake +++ b/src/base/base.cmake @@ -53,7 +53,9 @@ set(HEADERS_BASE src/base/net/stratum/strategies/StrategyProxy.h src/base/net/stratum/SubmitResult.h src/base/net/stratum/Url.h - src/base/net/tools/RecvBuf.h + src/base/net/tools/LineReader.h + src/base/net/tools/MemPool.h + src/base/net/tools/NetBuffer.h src/base/net/tools/Storage.h src/base/tools/Arguments.h src/base/tools/Baton.h @@ -99,6 +101,8 @@ set(SOURCES_BASE src/base/net/stratum/strategies/FailoverStrategy.cpp src/base/net/stratum/strategies/SinglePoolStrategy.cpp src/base/net/stratum/Url.cpp + src/base/net/tools/LineReader.cpp + src/base/net/tools/NetBuffer.cpp src/base/tools/Arguments.cpp src/base/tools/Buffer.cpp src/base/tools/String.cpp diff --git a/src/base/kernel/Base.cpp b/src/base/kernel/Base.cpp index b7d3b4814..34f6dbfd6 100644 --- a/src/base/kernel/Base.cpp +++ b/src/base/kernel/Base.cpp @@ -27,16 +27,17 @@ #include +#include "base/kernel/Base.h" #include "base/io/json/Json.h" #include "base/io/json/JsonChain.h" #include "base/io/log/backends/ConsoleLog.h" #include "base/io/log/backends/FileLog.h" #include "base/io/log/Log.h" #include "base/io/Watcher.h" -#include "base/kernel/Base.h" #include "base/kernel/interfaces/IBaseListener.h" #include "base/kernel/Platform.h" #include "base/kernel/Process.h" +#include "base/net/tools/NetBuffer.h" #include "core/config/Config.h" #include "core/config/ConfigTransform.h" @@ -84,6 +85,8 @@ public: delete config; delete watcher; + + NetBuffer::destroy(); } diff --git a/src/base/kernel/interfaces/ILineListener.h b/src/base/kernel/interfaces/ILineListener.h index 1a6d49142..2759dcecb 100644 --- a/src/base/kernel/interfaces/ILineListener.h +++ b/src/base/kernel/interfaces/ILineListener.h @@ -5,8 +5,8 @@ * Copyright 2014-2016 Wolf9466 * Copyright 2016 Jay D Dee * Copyright 2017-2018 XMR-Stak , - * Copyright 2018-2019 SChernykh - * Copyright 2016-2019 XMRig , + * Copyright 2018-2020 SChernykh + * Copyright 2016-2020 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,15 +26,12 @@ #define XMRIG_ILINELISTENER_H -#include +#include namespace xmrig { -class String; - - class ILineListener { public: diff --git a/src/base/net/http/HttpClient.cpp b/src/base/net/http/HttpClient.cpp index 59081bc03..82f62c84a 100644 --- a/src/base/net/http/HttpClient.cpp +++ b/src/base/net/http/HttpClient.cpp @@ -29,6 +29,7 @@ #include "base/io/log/Log.h" #include "base/kernel/Platform.h" #include "base/net/dns/Dns.h" +#include "base/net/tools/NetBuffer.h" #include @@ -142,12 +143,7 @@ void xmrig::HttpClient::onConnect(uv_connect_t *req, int status) return; } - uv_read_start(client->stream(), - [](uv_handle_t *, size_t suggested_size, uv_buf_t *buf) - { - buf->base = new char[suggested_size]; - buf->len = suggested_size; - }, + uv_read_start(client->stream(), NetBuffer::onAlloc, [](uv_stream_t *tcp, ssize_t nread, const uv_buf_t *buf) { auto client = static_cast(tcp->data); @@ -162,7 +158,7 @@ void xmrig::HttpClient::onConnect(uv_connect_t *req, int status) client->close(static_cast(nread)); } - delete [] buf->base; + NetBuffer::release(buf); }); client->handshake(); diff --git a/src/base/net/http/HttpServer.cpp b/src/base/net/http/HttpServer.cpp index db8c70f7d..80377f772 100644 --- a/src/base/net/http/HttpServer.cpp +++ b/src/base/net/http/HttpServer.cpp @@ -30,9 +30,8 @@ #include "base/net/http/HttpServer.h" #include "3rdparty/http-parser/http_parser.h" -#include "base/kernel/interfaces/IHttpListener.h" #include "base/net/http/HttpContext.h" -#include "base/net/http/HttpResponse.h" +#include "base/net/tools/NetBuffer.h" xmrig::HttpServer::HttpServer(const std::shared_ptr &listener) : @@ -52,12 +51,7 @@ void xmrig::HttpServer::onConnection(uv_stream_t *stream, uint16_t) auto ctx = new HttpContext(HTTP_REQUEST, m_listener); uv_accept(stream, ctx->stream()); - uv_read_start(ctx->stream(), - [](uv_handle_t *, size_t suggested_size, uv_buf_t *buf) - { - buf->base = new char[suggested_size]; - buf->len = suggested_size; - }, + uv_read_start(ctx->stream(), NetBuffer::onAlloc, [](uv_stream_t *tcp, ssize_t nread, const uv_buf_t *buf) { auto ctx = static_cast(tcp->data); @@ -73,6 +67,6 @@ void xmrig::HttpServer::onConnection(uv_stream_t *stream, uint16_t) ctx->close(); } - delete [] buf->base; + NetBuffer::release(buf); }); } diff --git a/src/base/net/https/HttpsServer.cpp b/src/base/net/https/HttpsServer.cpp index 6e99c3a52..3a6fb0801 100644 --- a/src/base/net/https/HttpsServer.cpp +++ b/src/base/net/https/HttpsServer.cpp @@ -17,17 +17,13 @@ */ -#include #include #include "base/net/https/HttpsServer.h" -#include "3rdparty/http-parser/http_parser.h" -#include "base/kernel/interfaces/IHttpListener.h" -#include "base/net/http/HttpResponse.h" #include "base/net/https/HttpsContext.h" -#include "base/net/tls/TlsConfig.h" #include "base/net/tls/TlsContext.h" +#include "base/net/tools/NetBuffer.h" xmrig::HttpsServer::HttpsServer(const std::shared_ptr &listener) : @@ -57,13 +53,7 @@ void xmrig::HttpsServer::onConnection(uv_stream_t *stream, uint16_t) auto ctx = new HttpsContext(m_tls, m_listener); uv_accept(stream, ctx->stream()); - uv_read_start(ctx->stream(), - [](uv_handle_t *, size_t suggested_size, uv_buf_t *buf) - { - buf->base = new char[suggested_size]; - buf->len = suggested_size; - }, - onRead); + uv_read_start(ctx->stream(), NetBuffer::onAlloc, onRead); } @@ -77,5 +67,5 @@ void xmrig::HttpsServer::onRead(uv_stream_t *stream, ssize_t nread, const uv_buf ctx->close(); } - delete [] buf->base; + NetBuffer::release(buf); } diff --git a/src/base/net/stratum/Client.cpp b/src/base/net/stratum/Client.cpp index bd7b22192..16a5f79c9 100644 --- a/src/base/net/stratum/Client.cpp +++ b/src/base/net/stratum/Client.cpp @@ -38,13 +38,14 @@ #endif +#include "base/net/stratum/Client.h" #include "base/io/json/Json.h" #include "base/io/json/JsonRequest.h" #include "base/io/log/Log.h" #include "base/kernel/interfaces/IClientListener.h" #include "base/net/dns/Dns.h" -#include "base/net/stratum/Client.h" #include "base/net/stratum/Socks5.h" +#include "base/net/tools/NetBuffer.h" #include "base/tools/Buffer.h" #include "base/tools/Chrono.h" #include "net/JobResult.h" @@ -83,6 +84,7 @@ xmrig::Client::Client(int id, const char *agent, IClientListener *listener) : m_agent(agent), m_sendBuf(1024) { + m_reader.setListener(this); m_key = m_storage.add(this); m_dns = new Dns(this); } @@ -542,7 +544,7 @@ int xmrig::Client::resolve(const String &host) { setState(HostLookupState); - m_recvBuf.reset(); + m_reader.reset(); if (m_failures == -1) { m_failures = 0; @@ -837,14 +839,10 @@ void xmrig::Client::ping() } -void xmrig::Client::read(ssize_t nread) +void xmrig::Client::read(ssize_t nread, const uv_buf_t *buf) { const auto size = static_cast(nread); - if (nread > 0 && size > m_recvBuf.available()) { - nread = UV_ENOBUFS; - } - if (nread < 0) { if (!isQuiet()) { LOG_ERR("[%s] read error: \"%s\"", url(), uv_strerror(static_cast(nread))); @@ -859,12 +857,8 @@ void xmrig::Client::read(ssize_t nread) return reconnect(); } - m_recvBuf.nread(size); - if (m_socks5) { - if (m_socks5->read(m_recvBuf.base(), m_recvBuf.pos())) { - m_recvBuf.reset(); - } + m_socks5->read(buf->base, size); if (m_socks5->isReady()) { delete m_socks5; @@ -886,13 +880,12 @@ void xmrig::Client::read(ssize_t nread) if (isTLS()) { LOG_DEBUG("[%s] TLS received (%d bytes)", url(), static_cast(nread)); - m_tls->read(m_recvBuf.base(), m_recvBuf.pos()); - m_recvBuf.reset(); + m_tls->read(buf->base, size); } else # endif { - m_recvBuf.getline(this); + m_reader.parse(buf->base, size); } } @@ -959,23 +952,6 @@ void xmrig::Client::startTimeout() } -void xmrig::Client::onAllocBuffer(uv_handle_t *handle, size_t, uv_buf_t *buf) -{ - auto client = getClient(handle->data); - if (!client) { - return; - } - - buf->base = client->m_recvBuf.current(); - -# ifdef _WIN32 - buf->len = static_cast(client->m_recvBuf.available()); -# else - buf->len = client->m_recvBuf.available(); -# endif -} - - void xmrig::Client::onClose(uv_handle_t *handle) { auto client = getClient(handle->data); @@ -1027,17 +1003,19 @@ void xmrig::Client::onConnect(uv_connect_t *req, int status) client->m_stream->data = req->data; client->setState(ConnectedState); - uv_read_start(client->m_stream, onAllocBuffer, onRead); + uv_read_start(client->m_stream, NetBuffer::onAlloc, onRead); delete req; client->handshake(); } -void xmrig::Client::onRead(uv_stream_t *stream, ssize_t nread, const uv_buf_t *) +void xmrig::Client::onRead(uv_stream_t *stream, ssize_t nread, const uv_buf_t *buf) { auto client = getClient(stream->data); if (client) { - client->read(nread); + client->read(nread, buf); } + + NetBuffer::release(buf); } diff --git a/src/base/net/stratum/Client.h b/src/base/net/stratum/Client.h index ead8039c0..d6ebf396d 100644 --- a/src/base/net/stratum/Client.h +++ b/src/base/net/stratum/Client.h @@ -39,7 +39,7 @@ #include "base/net/stratum/Job.h" #include "base/net/stratum/Pool.h" #include "base/net/stratum/SubmitResult.h" -#include "base/net/tools/RecvBuf.h" +#include "base/net/tools/LineReader.h" #include "base/net/tools/Storage.h" #include "base/tools/Object.h" @@ -61,7 +61,6 @@ public: constexpr static uint64_t kConnectTimeout = 20 * 1000; constexpr static uint64_t kResponseTimeout = 20 * 1000; - constexpr static size_t kInputBufferSize = 1024 * 16; constexpr static size_t kMaxSendBufferSize = 1024 * 16; Client(int id, const char *agent, IClientListener *listener); @@ -108,7 +107,7 @@ private: void parseNotification(const char *method, const rapidjson::Value ¶ms, const rapidjson::Value &error); void parseResponse(int64_t id, const rapidjson::Value &result, const rapidjson::Value &error); void ping(); - void read(ssize_t nread); + void read(ssize_t nread, const uv_buf_t *buf); void reconnect(); void setState(SocketState state); void startTimeout(); @@ -118,7 +117,6 @@ private: inline void setExtension(Extension ext, bool enable) noexcept { m_extensions.set(ext, enable); } template inline bool has() const noexcept { return m_extensions.test(ext); } - static void onAllocBuffer(uv_handle_t *handle, size_t suggested_size, uv_buf_t *buf); static void onClose(uv_handle_t *handle); static void onConnect(uv_connect_t *req, int status); static void onRead(uv_stream_t *stream, ssize_t nread, const uv_buf_t *buf); @@ -127,7 +125,7 @@ private: const char *m_agent; Dns *m_dns; - RecvBuf m_recvBuf; + LineReader m_reader; Socks5 *m_socks5 = nullptr; std::bitset m_extensions; std::vector m_sendBuf; diff --git a/src/base/net/stratum/Socks5.cpp b/src/base/net/stratum/Socks5.cpp index f27ee0d04..9577906fe 100644 --- a/src/base/net/stratum/Socks5.cpp +++ b/src/base/net/stratum/Socks5.cpp @@ -78,7 +78,7 @@ void xmrig::Client::Socks5::connect() const auto &host = m_client->pool().host(); std::vector buf; - sockaddr_storage addr; + sockaddr_storage addr{}; if (isIPv4(host, &addr)) { buf.resize(10); diff --git a/src/base/net/stratum/Tls.cpp b/src/base/net/stratum/Tls.cpp index 8916579b4..5915fad9d 100644 --- a/src/base/net/stratum/Tls.cpp +++ b/src/base/net/stratum/Tls.cpp @@ -6,8 +6,8 @@ * Copyright 2016 Jay D Dee * Copyright 2017-2018 XMR-Stak , * Copyright 2018 Lee Clagett - * Copyright 2018-2019 SChernykh - * Copyright 2016-2019 XMRig , + * Copyright 2018-2020 SChernykh + * Copyright 2016-2020 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,12 +24,9 @@ */ -#include - - +#include "base/net/stratum/Tls.h" #include "base/io/log/Log.h" #include "base/net/stratum/Client.h" -#include "base/net/stratum/Tls.h" #include "base/tools/Buffer.h" @@ -38,12 +35,12 @@ #endif +#include +#include + + xmrig::Client::Tls::Tls(Client *client) : - m_ready(false), - m_buf(), - m_fingerprint(), - m_client(client), - m_ssl(nullptr) + m_client(client) { m_ctx = SSL_CTX_new(SSLv23_method()); assert(m_ctx != nullptr); @@ -52,8 +49,8 @@ xmrig::Client::Tls::Tls(Client *client) : return; } - m_writeBio = BIO_new(BIO_s_mem()); - m_readBio = BIO_new(BIO_s_mem()); + m_write = BIO_new(BIO_s_mem()); + m_read = BIO_new(BIO_s_mem()); SSL_CTX_set_options(m_ctx, SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3); } @@ -80,7 +77,7 @@ bool xmrig::Client::Tls::handshake() } SSL_set_connect_state(m_ssl); - SSL_set_bio(m_ssl, m_readBio, m_writeBio); + SSL_set_bio(m_ssl, m_read, m_write); SSL_do_handshake(m_ssl); return send(); @@ -109,7 +106,7 @@ const char *xmrig::Client::Tls::version() const void xmrig::Client::Tls::read(const char *data, size_t size) { - BIO_write(m_readBio, data, size); + BIO_write(m_read, data, size); if (!SSL_is_init_finished(m_ssl)) { const int rc = SSL_connect(m_ssl); @@ -133,17 +130,18 @@ void xmrig::Client::Tls::read(const char *data, size_t size) return; } + static char buf[16384]{}; int bytes_read = 0; - while ((bytes_read = SSL_read(m_ssl, m_buf, sizeof(m_buf))) > 0) { - m_buf[bytes_read - 1] = '\0'; - m_client->parse(m_buf, static_cast(bytes_read)); + + while ((bytes_read = SSL_read(m_ssl, buf, sizeof(buf))) > 0) { + m_client->m_reader.parse(buf, static_cast(bytes_read)); } } bool xmrig::Client::Tls::send() { - return m_client->send(m_writeBio); + return m_client->send(m_write); } diff --git a/src/base/net/stratum/Tls.h b/src/base/net/stratum/Tls.h index e070be526..38cf2f9e6 100644 --- a/src/base/net/stratum/Tls.h +++ b/src/base/net/stratum/Tls.h @@ -5,8 +5,8 @@ * Copyright 2014-2016 Wolf9466 * Copyright 2016 Jay D Dee * Copyright 2017-2018 XMR-Stak , - * Copyright 2018-2019 SChernykh - * Copyright 2016-2019 XMRig , + * Copyright 2018-2020 SChernykh + * Copyright 2016-2020 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,10 +26,14 @@ #define XMRIG_CLIENT_TLS_H -#include +using BIO = struct bio_st; +using SSL = struct ssl_st; +using SSL_CTX = struct ssl_ctx_st; +using X509 = struct x509_st; #include "base/net/stratum/Client.h" +#include "base/tools/Object.h" namespace xmrig { @@ -38,6 +42,8 @@ namespace xmrig { class Client::Tls { public: + XMRIG_DISABLE_COPY_MOVE_DEFAULT(Tls) + Tls(Client *client); ~Tls(); @@ -52,13 +58,12 @@ private: bool verify(X509 *cert); bool verifyFingerprint(X509 *cert); - BIO *m_readBio; - BIO *m_writeBio; - bool m_ready; - char m_buf[1024 * 2]; - char m_fingerprint[32 * 2 + 8]; + BIO *m_read = nullptr; + BIO *m_write = nullptr; + bool m_ready = false; + char m_fingerprint[32 * 2 + 8]{}; Client *m_client; - SSL *m_ssl; + SSL *m_ssl = nullptr; SSL_CTX *m_ctx; }; diff --git a/src/base/net/tools/LineReader.cpp b/src/base/net/tools/LineReader.cpp new file mode 100644 index 000000000..646852bf6 --- /dev/null +++ b/src/base/net/tools/LineReader.cpp @@ -0,0 +1,103 @@ +/* XMRig + * Copyright 2018-2020 SChernykh + * Copyright 2016-2020 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/tools/LineReader.h" +#include "base/net/tools/NetBuffer.h" +#include "base/kernel/interfaces/ILineListener.h" + +#include +#include + + +xmrig::LineReader::~LineReader() +{ + NetBuffer::release(m_buf); +} + + +void xmrig::LineReader::parse(char *data, size_t size) +{ + assert(m_listener != nullptr && size > 0); + if (!m_listener || size == 0) { + return; + } + + if (!m_buf) { + return getline(data, size); + } + + add(data, size); + getline(m_buf, m_pos); +} + + +void xmrig::LineReader::reset() +{ + if (m_buf) { + NetBuffer::release(m_buf); + m_buf = nullptr; + m_pos = 0; + } +} + + +void xmrig::LineReader::add(const char *data, size_t size) +{ + if (size > NetBuffer::kChunkSize - m_pos) { + return; + } + + if (!m_buf) { + m_buf = NetBuffer::allocate(); + m_pos = 0; + } + + memcpy(m_buf + m_pos, data, size); + m_pos += size; +} + + +void xmrig::LineReader::getline(char *data, size_t size) +{ + char *end = nullptr; + char *start = data; + size_t remaining = size; + + while ((end = static_cast(memchr(start, '\n', remaining))) != nullptr) { + *end = '\0'; + + end++; + + const auto len = static_cast(end - start); + if (len > 1) { + m_listener->onLine(start, len - 1); + } + + remaining -= len; + start = end; + } + + if (remaining == 0) { + return reset(); + } + + if (!m_buf || m_buf != data) { + add(start, remaining); + } +} diff --git a/src/base/net/tools/LineReader.h b/src/base/net/tools/LineReader.h new file mode 100644 index 000000000..601f5cdbc --- /dev/null +++ b/src/base/net/tools/LineReader.h @@ -0,0 +1,62 @@ +/* XMRig + * Copyright 2018-2020 SChernykh + * Copyright 2016-2020 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_LINEREADER_H +#define XMRIG_LINEREADER_H + + +#include "base/tools/Object.h" + + +#include + + +namespace xmrig { + + +class ILineListener; + + +class LineReader +{ +public: + XMRIG_DISABLE_COPY_MOVE(LineReader) + + LineReader() = default; + LineReader(ILineListener *listener) : m_listener(listener) {} + ~LineReader(); + + inline void setListener(ILineListener *listener) { m_listener = listener; } + + void parse(char *data, size_t size); + void reset(); + +private: + void add(const char *data, size_t size); + void getline(char *data, size_t size); + + char *m_buf = nullptr; + ILineListener *m_listener = nullptr; + size_t m_pos = 0; +}; + + +} /* namespace xmrig */ + + +#endif /* XMRIG_NETBUFFER_H */ diff --git a/src/base/net/tools/MemPool.h b/src/base/net/tools/MemPool.h new file mode 100644 index 000000000..3b8a8ef41 --- /dev/null +++ b/src/base/net/tools/MemPool.h @@ -0,0 +1,96 @@ +/* XMRig + * Copyright 2018-2020 SChernykh + * Copyright 2016-2020 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_MEMPOOL_H +#define XMRIG_MEMPOOL_H + + +#include +#include +#include +#include + + +namespace xmrig { + + +template +class MemPool +{ +public: + MemPool() = default; + + + constexpr size_t chunkSize() const { return CHUNK_SIZE; } + inline size_t freeSize() const { return m_free.size() * CHUNK_SIZE; } + inline size_t size() const { return m_data.size() * CHUNK_SIZE * INIT_SIZE; } + + + inline char *allocate() + { + if (m_free.empty()) { + resize(); + } + + const size_t i = *m_free.begin(); + const size_t r = i / INIT_SIZE; + + char *ptr = m_data[r].data() + (i - r * INIT_SIZE) * CHUNK_SIZE; + + m_used.insert({ ptr, i }); + m_free.erase(i); + + return ptr; + } + + + inline void deallocate(const char *ptr) + { + if (ptr == nullptr) { + return; + } + + assert(m_used.count(ptr)); + + m_free.emplace(m_used[ptr]); + m_used.erase(ptr); + } + + +private: + inline void resize() + { + const size_t index = m_data.size(); + m_data[index]; + + for (size_t i = 0; i < INIT_SIZE; ++i) { + m_free.emplace((index * INIT_SIZE) + i); + } + } + + + std::map m_used; + std::map > m_data; + std::set m_free; +}; + + +} /* namespace xmrig */ + + +#endif /* XMRIG_MEMPOOL_H */ diff --git a/src/base/net/tools/NetBuffer.cpp b/src/base/net/tools/NetBuffer.cpp new file mode 100644 index 000000000..3303d9715 --- /dev/null +++ b/src/base/net/tools/NetBuffer.cpp @@ -0,0 +1,83 @@ +/* XMRig + * Copyright 2018-2020 SChernykh + * Copyright 2016-2020 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/tools/MemPool.h" +#include "base/net/tools/NetBuffer.h" + + +#include +#include + + +namespace xmrig { + + +static constexpr size_t kInitSize = 4; +static MemPool *pool = nullptr; + + +inline MemPool *getPool() +{ + if (!pool) { + pool = new MemPool(); + } + + return pool; +} + + +} // namespace xmrig + + +char *xmrig::NetBuffer::allocate() +{ + return getPool()->allocate(); +} + + +void xmrig::NetBuffer::destroy() +{ + if (!pool) { + return; + } + + assert(pool->freeSize() == pool->size()); + + delete pool; + pool = nullptr; +} + + +void xmrig::NetBuffer::onAlloc(uv_handle_t *, size_t, uv_buf_t *buf) +{ + buf->base = getPool()->allocate(); + buf->len = kChunkSize; +} + + +void xmrig::NetBuffer::release(const char *buf) +{ + getPool()->deallocate(buf); +} + + +void xmrig::NetBuffer::release(const uv_buf_t *buf) +{ + getPool()->deallocate(buf->base); +} diff --git a/src/base/net/tools/NetBuffer.h b/src/base/net/tools/NetBuffer.h new file mode 100644 index 000000000..14255bb0b --- /dev/null +++ b/src/base/net/tools/NetBuffer.h @@ -0,0 +1,49 @@ +/* XMRig + * Copyright 2018-2020 SChernykh + * Copyright 2016-2020 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_NETBUFFER_H +#define XMRIG_NETBUFFER_H + + +struct uv_buf_t; +using uv_handle_t = struct uv_handle_s; + + +#include + + +namespace xmrig { + + +class NetBuffer +{ +public: + static constexpr size_t kChunkSize = 16 * 1024; + + static char *allocate(); + static void destroy(); + static void onAlloc(uv_handle_t *handle, size_t suggested_size, uv_buf_t *buf); + static void release(const char *buf); + static void release(const uv_buf_t *buf); +}; + + +} /* namespace xmrig */ + + +#endif /* XMRIG_NETBUFFER_H */ diff --git a/src/base/net/tools/RecvBuf.h b/src/base/net/tools/RecvBuf.h deleted file mode 100644 index 5122c9804..000000000 --- a/src/base/net/tools/RecvBuf.h +++ /dev/null @@ -1,99 +0,0 @@ -/* 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 , - * - * 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_RECVBUF_H -#define XMRIG_RECVBUF_H - - -#include - - -#include "base/kernel/interfaces/ILineListener.h" - - -namespace xmrig { - - -template -class RecvBuf -{ -public: - inline RecvBuf() : - m_buf(), - m_pos(0) - { - } - - inline char *base() { return m_buf; } - inline char *current() { return m_buf + m_pos; } - inline const char *base() const { return m_buf; } - inline const char *current() const { return m_buf + m_pos; } - inline size_t available() const { return N - m_pos; } - inline size_t pos() const { return m_pos; } - inline void nread(size_t size) { m_pos += size; } - inline void reset() { m_pos = 0; } - - constexpr inline size_t size() const { return N; } - - inline void getline(ILineListener *listener) - { - char *end; - char *start = m_buf; - size_t remaining = m_pos; - - while ((end = static_cast(memchr(start, '\n', remaining))) != nullptr) { - *end = '\0'; - - end++; - const size_t len = static_cast(end - start); - - listener->onLine(start, len - 1); - - remaining -= len; - start = end; - } - - if (remaining == 0) { - m_pos = 0; - return; - } - - if (start == m_buf) { - return; - } - - memcpy(m_buf, start, remaining); - m_pos = remaining; - } - -private: - char m_buf[N]; - size_t m_pos; -}; - - -} /* namespace xmrig */ - - -#endif /* XMRIG_RECVBUF_H */