Added new HTTP server (tiny wrapper on top of libuv + http_parser), removed libmicrohttpd support.

This commit is contained in:
XMRig 2019-03-29 12:33:11 +07:00
parent 725796a1ab
commit 01ad6bf2d9
29 changed files with 4312 additions and 237 deletions

View file

@ -25,7 +25,6 @@
#include "3rdparty/rapidjson/document.h"
#include "base/io/Json.h"
#include "base/io/log/Log.h"
#include "base/net/http/Http.h"
@ -92,18 +91,6 @@ void xmrig::Http::load(const rapidjson::Value &http)
}
void xmrig::Http::print() const
{
# ifdef XMRIG_FEATURE_API
if (!isEnabled()) {
return;
}
Log::print(GREEN_BOLD(" * ") WHITE_BOLD("%-13s") BLUE_BOLD("http://%s:%d"), "HTTP API", host().data(), port());
# endif
}
void xmrig::Http::setPort(int port)
{
if (port >= 0 && port <= 65536) {

View file

@ -54,7 +54,6 @@ public:
bool isEqual(const Http &other) const;
rapidjson::Value toJSON(rapidjson::Document &doc) const;
void load(const rapidjson::Value &http);
void print() const;
void setPort(int port);
private:

View file

@ -0,0 +1,142 @@
/* XMRig
* Copyright 2010 Jeff Garzik <jgarzik@pobox.com>
* Copyright 2012-2014 pooler <pooler@litecoinpool.org>
* Copyright 2014 Lucas Jones <https://github.com/lucasjones>
* Copyright 2014-2016 Wolf9466 <https://github.com/OhGodAPet>
* Copyright 2016 Jay D Dee <jayddee246@gmail.com>
* Copyright 2017-2018 XMR-Stak <https://github.com/fireice-uk>, <https://github.com/psychocrypt>
* Copyright 2014-2019 heapwolf <https://github.com/heapwolf>
* Copyright 2018-2019 SChernykh <https://github.com/SChernykh>
* Copyright 2016-2019 XMRig <https://github.com/xmrig>, <support@xmrig.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <algorithm>
#include <uv.h>
#include "3rdparty/http-parser/http_parser.h"
#include "base/net/http/HttpContext.h"
xmrig::HttpContext::HttpContext(int parser_type, IHttpListener *listener) :
listener(listener),
connect(nullptr),
m_wasHeaderValue(false)
{
parser = new http_parser;
tcp = new uv_tcp_t;
uv_tcp_init(uv_default_loop(), tcp);
http_parser_init(parser, static_cast<http_parser_type>(parser_type));
parser->data = tcp->data = this;
}
xmrig::HttpContext::~HttpContext()
{
delete connect;
delete tcp;
delete parser;
}
void xmrig::HttpContext::attach(http_parser_settings *settings)
{
settings->on_message_begin = nullptr;
settings->on_status = nullptr;
settings->on_chunk_header = nullptr;
settings->on_chunk_complete = nullptr;
settings->on_url = [](http_parser *parser, const char *at, size_t length) -> int
{
static_cast<HttpContext*>(parser->data)->url = std::string(at, length);
return 0;
};
settings->on_header_field = onHeaderField;
settings->on_header_value = onHeaderValue;
settings->on_headers_complete = [](http_parser* parser) -> int {
HttpContext *ctx = static_cast<HttpContext*>(parser->data);
ctx->method = std::string(http_method_str(static_cast<http_method>(parser->method)));
if (!ctx->m_lastHeaderField.empty()) {
ctx->setHeader();
}
return 0;
};
settings->on_body = [](http_parser *parser, const char *at, size_t len) -> int
{
static_cast<HttpContext*>(parser->data)->body << std::string(at, len);
return 0;
};
}
void xmrig::HttpContext::close(uv_handle_t* handle)
{
delete reinterpret_cast<HttpContext*>(handle->data);
}
int xmrig::HttpContext::onHeaderField(http_parser *parser, const char *at, size_t length)
{
HttpContext *ctx = static_cast<HttpContext*>(parser->data);
if (ctx->m_wasHeaderValue) {
if (!ctx->m_lastHeaderField.empty()) {
ctx->setHeader();
}
ctx->m_lastHeaderField = std::string(at, length);
ctx->m_wasHeaderValue = false;
} else {
ctx->m_lastHeaderField += std::string(at, length);
}
return 0;
}
int xmrig::HttpContext::onHeaderValue(http_parser *parser, const char *at, size_t length)
{
HttpContext *ctx = static_cast<HttpContext*>(parser->data);
if (!ctx->m_wasHeaderValue) {
ctx->m_lastHeaderValue = std::string(at, length);
ctx->m_wasHeaderValue = true;
} else {
ctx->m_lastHeaderValue += std::string(at, length);
}
return 0;
}
void xmrig::HttpContext::setHeader()
{
std::transform(m_lastHeaderField.begin(), m_lastHeaderField.end(), m_lastHeaderField.begin(), ::tolower);
headers.insert({ m_lastHeaderField, m_lastHeaderValue });
m_lastHeaderField.clear();
m_lastHeaderValue.clear();
}

View file

@ -0,0 +1,81 @@
/* XMRig
* Copyright 2010 Jeff Garzik <jgarzik@pobox.com>
* Copyright 2012-2014 pooler <pooler@litecoinpool.org>
* Copyright 2014 Lucas Jones <https://github.com/lucasjones>
* Copyright 2014-2016 Wolf9466 <https://github.com/OhGodAPet>
* Copyright 2016 Jay D Dee <jayddee246@gmail.com>
* Copyright 2017-2018 XMR-Stak <https://github.com/fireice-uk>, <https://github.com/psychocrypt>
* Copyright 2014-2019 heapwolf <https://github.com/heapwolf>
* Copyright 2018-2019 SChernykh <https://github.com/SChernykh>
* Copyright 2016-2019 XMRig <https://github.com/xmrig>, <support@xmrig.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef XMRIG_HTTPCONTEXT_H
#define XMRIG_HTTPCONTEXT_H
typedef struct http_parser http_parser;
typedef struct http_parser_settings http_parser_settings;
typedef struct uv_connect_s uv_connect_t;
typedef struct uv_handle_s uv_handle_t;
typedef struct uv_stream_s uv_stream_t;
typedef struct uv_tcp_s uv_tcp_t;
#include "base/net/http/HttpRequest.h"
namespace xmrig {
class IHttpListener;
class HttpContext : public HttpRequest
{
public:
HttpContext(int parser_type, IHttpListener *listener);
~HttpContext();
inline uv_stream_t *stream() const { return reinterpret_cast<uv_stream_t *>(tcp); }
inline uv_handle_t *handle() const { return reinterpret_cast<uv_handle_t *>(tcp); }
static void attach(http_parser_settings *settings);
static void close(uv_handle_t* handle);
http_parser *parser;
IHttpListener *listener;
uv_connect_t *connect;
uv_tcp_t *tcp;
private:
static int onHeaderField(http_parser *parser, const char *at, size_t length);
static int onHeaderValue(http_parser *parser, const char *at, size_t length);
void setHeader();
bool m_wasHeaderValue;
std::string m_lastHeaderField;
std::string m_lastHeaderValue;
};
} // namespace xmrig
#endif // XMRIG_HTTPCONTEXT_H

View file

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

View file

@ -0,0 +1,97 @@
/* XMRig
* Copyright 2010 Jeff Garzik <jgarzik@pobox.com>
* Copyright 2012-2014 pooler <pooler@litecoinpool.org>
* Copyright 2014 Lucas Jones <https://github.com/lucasjones>
* Copyright 2014-2016 Wolf9466 <https://github.com/OhGodAPet>
* Copyright 2016 Jay D Dee <jayddee246@gmail.com>
* Copyright 2017-2018 XMR-Stak <https://github.com/fireice-uk>, <https://github.com/psychocrypt>
* Copyright 2014-2019 heapwolf <https://github.com/heapwolf>
* Copyright 2018-2019 SChernykh <https://github.com/SChernykh>
* Copyright 2016-2019 XMRig <https://github.com/xmrig>, <support@xmrig.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <uv.h>
#include "3rdparty/http-parser/http_parser.h"
#include "base/net/http/HttpContext.h"
#include "base/net/http/HttpResponse.h"
namespace xmrig {
static const char *kCRLF = "\r\n";
static const char *kTransferEncoding = "Transfer-Encoding";
} // namespace xmrig
xmrig::HttpResponse::HttpResponse() :
parser(nullptr),
statusCode(HTTP_STATUS_OK),
body(""),
statusAdjective("OK"), // FIXME
m_writtenOrEnded(false)
{
}
void xmrig::HttpResponse::writeOrEnd(const std::string &str, bool end)
{
std::stringstream ss;
if (!m_writtenOrEnded) {
ss << "HTTP/1.1 " << statusCode << " " << statusAdjective << kCRLF;
for (auto &header : headers) {
ss << header.first << ": " << header.second << kCRLF;
}
ss << kCRLF;
m_writtenOrEnded = true;
}
if (headers.count(kTransferEncoding) && headers[kTransferEncoding] == "chunked") {
ss << std::hex << str.size() << std::dec << kCRLF << str << kCRLF;
if (end) {
ss << "0" << kCRLF << kCRLF;
}
}
else {
ss << str;
}
const std::string out = ss.str();
# ifdef _WIN32
uv_buf_t resbuf = uv_buf_init(const_cast<char *>(out.c_str()), static_cast<unsigned int>(out.size()));
# else
uv_buf_t resbuf = uv_buf_init(const_cast<char *>(out.c_str()), out.size());
# endif
HttpContext* context = static_cast<HttpContext*>(parser->data);
uv_try_write(context->stream(), &resbuf, 1);
if (end) {
if (!uv_is_closing(context->handle())) {
uv_close(context->handle(), HttpContext::close);
}
}
}

View file

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

View file

@ -0,0 +1,108 @@
/* XMRig
* Copyright 2010 Jeff Garzik <jgarzik@pobox.com>
* Copyright 2012-2014 pooler <pooler@litecoinpool.org>
* Copyright 2014 Lucas Jones <https://github.com/lucasjones>
* Copyright 2014-2016 Wolf9466 <https://github.com/OhGodAPet>
* Copyright 2016 Jay D Dee <jayddee246@gmail.com>
* Copyright 2017-2018 XMR-Stak <https://github.com/fireice-uk>, <https://github.com/psychocrypt>
* Copyright 2014-2019 heapwolf <https://github.com/heapwolf>
* Copyright 2018-2019 SChernykh <https://github.com/SChernykh>
* Copyright 2016-2019 XMRig <https://github.com/xmrig>, <support@xmrig.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <functional>
#include <uv.h>
#include "3rdparty/http-parser/http_parser.h"
#include "base/kernel/interfaces/IHttpListener.h"
#include "base/net/http/HttpContext.h"
#include "base/net/http/HttpResponse.h"
#include "base/net/http/HttpServer.h"
xmrig::HttpServer::HttpServer(IHttpListener *listener) :
m_listener(listener)
{
m_settings = new http_parser_settings();
HttpContext::attach(m_settings);
m_settings->on_message_complete = HttpServer::onComplete;
}
xmrig::HttpServer::~HttpServer()
{
delete m_settings;
}
void xmrig::HttpServer::onConnection(uv_stream_t *stream, uint16_t)
{
static std::function<void(uv_stream_t *socket, int status)> onConnect;
static std::function<void(uv_stream_t *tcp, ssize_t nread, const uv_buf_t *buf)> onRead;
HttpContext *context = new HttpContext(HTTP_REQUEST, m_listener);
uv_accept(stream, context->stream());
onRead = [&](uv_stream_t *tcp, ssize_t nread, const uv_buf_t *buf) {
HttpContext* context = static_cast<HttpContext*>(tcp->data);
if (nread >= 0) {
const size_t size = static_cast<size_t>(nread);
const size_t parsed = http_parser_execute(context->parser, m_settings, buf->base, size);
if (parsed < size) {
uv_close(context->handle(), HttpContext::close);
}
} else {
uv_close(context->handle(), HttpContext::close);
}
delete [] buf->base;
};
uv_read_start(context->stream(),
[](uv_handle_t *, size_t suggested_size, uv_buf_t *buf)
{
buf->base = new char[suggested_size];
# ifdef _WIN32
buf->len = static_cast<unsigned int>(suggested_size);
# else
buf->len = suggested_size;
# endif
},
[](uv_stream_t *tcp, ssize_t nread, const uv_buf_t *buf)
{
onRead(tcp, nread, buf);
});
}
int xmrig::HttpServer::onComplete(http_parser *parser)
{
HttpContext *context = reinterpret_cast<HttpContext*>(parser->data);
HttpResponse res;
res.parser = parser;
context->listener->onHttp(*context, res);
return 0;
}

View file

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