Background http changes from proxy.

This commit is contained in:
XMRig 2018-03-27 14:01:38 +07:00
parent f1bc06473f
commit 9fe863b5d7
17 changed files with 929 additions and 125 deletions

View file

@ -28,14 +28,64 @@
#include "api/Api.h"
#include "api/Httpd.h"
#include "api/HttpReply.h"
#include "api/HttpRequest.h"
#include "log/Log.h"
Httpd::Httpd(int port, const char *accessToken) :
m_accessToken(accessToken),
class UploadCtx
{
public:
inline UploadCtx() :
m_pos(0)
{}
inline bool write(const char *data, size_t size)
{
if (size > (sizeof(m_data) - m_pos - 1)) {
return false;
}
memcpy(m_data + m_pos, data, size);
m_pos += size;
m_data[m_pos] = '\0';
return true;
}
inline const char *data() const { return m_data; }
private:
char m_data[32768];
size_t m_pos;
};
Httpd::Httpd(int port, const char *accessToken, bool IPv6, bool restricted) :
m_idle(true),
m_IPv6(IPv6),
m_restricted(restricted),
m_accessToken(accessToken ? strdup(accessToken) : nullptr),
m_port(port),
m_daemon(nullptr)
{
uv_timer_init(uv_default_loop(), &m_timer);
m_timer.data = this;
}
Httpd::~Httpd()
{
uv_timer_stop(&m_timer);
if (m_daemon) {
MHD_stop_daemon(m_daemon);
}
delete m_accessToken;
}
@ -45,15 +95,14 @@ bool Httpd::start()
return false;
}
unsigned int flags = MHD_USE_SELECT_INTERNALLY;
unsigned int flags = 0;
# if MHD_VERSION >= 0x00093500
if (MHD_is_feature_supported(MHD_FEATURE_EPOLL)) {
flags = MHD_USE_EPOLL_LINUX_ONLY | MHD_USE_EPOLL_INTERNALLY_LINUX_ONLY;
if (m_IPv6 && MHD_is_feature_supported(MHD_FEATURE_IPv6)) {
flags |= MHD_USE_DUAL_STACK;
}
if (MHD_is_feature_supported(MHD_FEATURE_IPv6)) {
flags |= MHD_USE_DUAL_STACK;
if (MHD_is_feature_supported(MHD_FEATURE_EPOLL)) {
flags |= MHD_USE_EPOLL_LINUX_ONLY;
}
# endif
@ -63,66 +112,61 @@ bool Httpd::start()
return false;
}
uv_timer_start(&m_timer, Httpd::onTimer, kIdleInterval, kIdleInterval);
return true;
}
int Httpd::auth(const char *header)
int Httpd::process(xmrig::HttpRequest &req)
{
if (!m_accessToken) {
return MHD_HTTP_OK;
xmrig::HttpReply reply;
if (!req.process(m_accessToken, m_restricted, reply)) {
return req.end(reply);
}
if (m_accessToken && !header) {
return MHD_HTTP_UNAUTHORIZED;
if (!req.isFulfilled()) {
return MHD_YES;
}
const size_t size = strlen(header);
if (size < 8 || strlen(m_accessToken) != size - 7 || memcmp("Bearer ", header, 7) != 0) {
return MHD_HTTP_FORBIDDEN;
}
Api::exec(req, reply);
return strncmp(m_accessToken, header + 7, strlen(m_accessToken)) == 0 ? MHD_HTTP_OK : MHD_HTTP_FORBIDDEN;
return req.end(reply);
}
int Httpd::done(MHD_Connection *connection, int status, MHD_Response *rsp)
void Httpd::run()
{
if (!rsp) {
rsp = MHD_create_response_from_buffer(0, nullptr, MHD_RESPMEM_PERSISTENT);
MHD_run(m_daemon);
const MHD_DaemonInfo *info = MHD_get_daemon_info(m_daemon, MHD_DAEMON_INFO_CURRENT_CONNECTIONS);
if (m_idle && info->num_connections) {
uv_timer_set_repeat(&m_timer, kActiveInterval);
m_idle = false;
}
else if (!m_idle && !info->num_connections) {
uv_timer_set_repeat(&m_timer, kIdleInterval);
m_idle = true;
}
MHD_add_response_header(rsp, "Content-Type", "application/json");
MHD_add_response_header(rsp, "Access-Control-Allow-Origin", "*");
MHD_add_response_header(rsp, "Access-Control-Allow-Methods", "GET");
MHD_add_response_header(rsp, "Access-Control-Allow-Headers", "Authorization");
const int ret = MHD_queue_response(connection, status, rsp);
MHD_destroy_response(rsp);
return ret;
}
int Httpd::handler(void *cls, struct MHD_Connection *connection, const char *url, const char *method, const char *version, const char *upload_data, size_t *upload_data_size, void **con_cls)
int Httpd::handler(void *cls, struct MHD_Connection *connection, const char *url, const char *method, const char *version, const char *uploadData, size_t *uploadSize, void **con_cls)
{
if (strcmp(method, "OPTIONS") == 0) {
return done(connection, MHD_HTTP_OK, nullptr);
xmrig::HttpRequest req(connection, url, method, uploadData, uploadSize, con_cls);
if (req.method() == xmrig::HttpRequest::Options) {
return req.end(MHD_HTTP_OK, nullptr);
}
if (strcmp(method, "GET") != 0) {
return MHD_NO;
if (req.method() == xmrig::HttpRequest::Unsupported) {
return req.end(MHD_HTTP_METHOD_NOT_ALLOWED, nullptr);
}
int status = static_cast<Httpd*>(cls)->auth(MHD_lookup_connection_value(connection, MHD_HEADER_KIND, "Authorization"));
if (status != MHD_HTTP_OK) {
return done(connection, status, nullptr);
}
char *buf = Api::get(url, &status);
if (buf == nullptr) {
return MHD_NO;
}
MHD_Response *rsp = MHD_create_response_from_buffer(strlen(buf), (void*) buf, MHD_RESPMEM_MUST_FREE);
return done(connection, status, rsp);
return static_cast<Httpd*>(cls)->process(req);
}
void Httpd::onTimer(uv_timer_t *handle)
{
static_cast<Httpd*>(handle->data)->run();
}