Added xmrigCC-common src
This commit is contained in:
parent
3129c39347
commit
28c94eac6a
16 changed files with 2014 additions and 0 deletions
228
src/cc/CCClient.cpp
Normal file
228
src/cc/CCClient.cpp
Normal file
|
@ -0,0 +1,228 @@
|
||||||
|
/* 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 2016-2017 XMRig <support@xmrig.com>
|
||||||
|
* Copyright 2017- BenDr0id <ben@graef.in>
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* 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 <fstream>
|
||||||
|
#include <3rdparty/rapidjson/stringbuffer.h>
|
||||||
|
#include <3rdparty/rapidjson/prettywriter.h>
|
||||||
|
#include <Platform.h>
|
||||||
|
|
||||||
|
#include "CCClient.h"
|
||||||
|
#include "App.h"
|
||||||
|
#include "ControlCommand.h"
|
||||||
|
|
||||||
|
#include "api/NetworkState.h"
|
||||||
|
#include "log/Log.h"
|
||||||
|
#include "workers/Workers.h"
|
||||||
|
#include "workers/Hashrate.h"
|
||||||
|
|
||||||
|
#if _WIN32
|
||||||
|
# include "winsock2.h"
|
||||||
|
#else
|
||||||
|
# include "unistd.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
CCClient *CCClient::m_self = nullptr;
|
||||||
|
uv_mutex_t CCClient::m_mutex;
|
||||||
|
|
||||||
|
CCClient::CCClient(const Options *options)
|
||||||
|
: m_options(options)
|
||||||
|
{
|
||||||
|
uv_mutex_init(&m_mutex);
|
||||||
|
|
||||||
|
m_self = this;
|
||||||
|
|
||||||
|
std::string clientId;
|
||||||
|
if (m_options->ccWorkerId()) {
|
||||||
|
clientId = m_options->ccWorkerId();
|
||||||
|
} else{
|
||||||
|
char hostname[128];
|
||||||
|
memset(hostname, 0, sizeof(hostname));
|
||||||
|
gethostname(hostname, sizeof(hostname)-1);
|
||||||
|
clientId = std::string(hostname);
|
||||||
|
}
|
||||||
|
|
||||||
|
m_clientStatus.setClientId(clientId);
|
||||||
|
|
||||||
|
if (m_options->algoName() != nullptr) {
|
||||||
|
m_clientStatus.setCurrentAlgoName(m_options->algoName());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_options->ccToken() != nullptr) {
|
||||||
|
m_authorization = std::string("Bearer ") + m_self->m_options->ccToken();
|
||||||
|
}
|
||||||
|
|
||||||
|
uv_timer_init(uv_default_loop(), &m_timer);
|
||||||
|
uv_timer_start(&m_timer, CCClient::onReport,
|
||||||
|
static_cast<uint64_t>(m_options->ccUpdateInterval() * 1000),
|
||||||
|
static_cast<uint64_t>(m_options->ccUpdateInterval() * 1000));
|
||||||
|
}
|
||||||
|
|
||||||
|
CCClient::~CCClient()
|
||||||
|
{
|
||||||
|
uv_timer_stop(&m_timer);
|
||||||
|
m_self = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CCClient::updateHashrate(const Hashrate *hashrate)
|
||||||
|
{
|
||||||
|
uv_mutex_lock(&m_mutex);
|
||||||
|
|
||||||
|
if (m_self) {
|
||||||
|
m_self->m_clientStatus.setHashrateShort(hashrate->calc(Hashrate::ShortInterval));
|
||||||
|
m_self->m_clientStatus.setHashrateMedium(hashrate->calc(Hashrate::MediumInterval));
|
||||||
|
m_self->m_clientStatus.setHashrateLong(hashrate->calc(Hashrate::LargeInterval));
|
||||||
|
m_self->m_clientStatus.setHashrateHighest(hashrate->highest());
|
||||||
|
}
|
||||||
|
|
||||||
|
uv_mutex_unlock(&m_mutex);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void CCClient::updateNetworkState(const NetworkState &network)
|
||||||
|
{
|
||||||
|
uv_mutex_lock(&m_mutex);
|
||||||
|
|
||||||
|
if (m_self) {
|
||||||
|
m_self->m_clientStatus.setCurrentStatus(Workers::isEnabled() ? ClientStatus::RUNNING : ClientStatus::PAUSED);
|
||||||
|
m_self->m_clientStatus.setCurrentPool(network.pool);
|
||||||
|
m_self->m_clientStatus.setSharesGood(network.accepted);
|
||||||
|
m_self->m_clientStatus.setSharesTotal(network.accepted + network.rejected);
|
||||||
|
m_self->m_clientStatus.setHashesTotal(network.total);
|
||||||
|
m_self->m_clientStatus.setAvgTime(network.avgTime());
|
||||||
|
}
|
||||||
|
uv_mutex_unlock(&m_mutex);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CCClient::publishClientStatusReport()
|
||||||
|
{
|
||||||
|
std::string requestUrl = "/client/setClientStatus?clientId=" + m_self->m_clientStatus.getClientId();
|
||||||
|
std::string requestBuffer = m_self->m_clientStatus.toJsonString();
|
||||||
|
|
||||||
|
auto res = performRequest(requestUrl, requestBuffer, "POST");
|
||||||
|
if (!res) {
|
||||||
|
LOG_ERR("[CC-Client] error: unable to performRequest POST -> http://%s:%d%s",
|
||||||
|
m_self->m_options->ccHost(), m_self->m_options->ccPort(), requestUrl.c_str());
|
||||||
|
} else if (res->status != 200) {
|
||||||
|
LOG_ERR("[CC-Client] error: \"%d\" -> http://%s:%d%s", res->status, m_self->m_options->ccHost(),
|
||||||
|
m_self->m_options->ccPort(), requestUrl.c_str());
|
||||||
|
} else {
|
||||||
|
ControlCommand controlCommand;
|
||||||
|
if (controlCommand.parseFromJsonString(res->body)) {
|
||||||
|
if (controlCommand.getCommand() == ControlCommand::START) {
|
||||||
|
if (!Workers::isEnabled()) {
|
||||||
|
LOG_WARN("[CC-Client] Command: START received -> resume");
|
||||||
|
Workers::setEnabled(true);
|
||||||
|
}
|
||||||
|
} else if (controlCommand.getCommand() == ControlCommand::STOP) {
|
||||||
|
if (Workers::isEnabled()) {
|
||||||
|
LOG_WARN("[CC-Client] Command: STOP received -> pause");
|
||||||
|
Workers::setEnabled(false);
|
||||||
|
}
|
||||||
|
} else if (controlCommand.getCommand() == ControlCommand::UPDATE_CONFIG) {
|
||||||
|
LOG_WARN("[CC-Client] Command: UPDATE_CONFIG received -> update config");
|
||||||
|
updateConfig();
|
||||||
|
} else if (controlCommand.getCommand() == ControlCommand::RESTART) {
|
||||||
|
LOG_WARN("[CC-Client] Command: RESTART received -> restart");
|
||||||
|
App::restart();
|
||||||
|
} else if (controlCommand.getCommand() == ControlCommand::SHUTDOWN) {
|
||||||
|
LOG_WARN("[CC-Client] Command: SHUTDOWN received -> shutdown");
|
||||||
|
App::shutdown();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
LOG_ERR("[CC-Client] Unknown command received from CC Server.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CCClient::updateConfig()
|
||||||
|
{
|
||||||
|
std::string requestUrl = "/client/getConfig?clientId=" + m_self->m_clientStatus.getClientId();
|
||||||
|
std::string requestBuffer;
|
||||||
|
|
||||||
|
auto res = performRequest(requestUrl, requestBuffer, "GET");
|
||||||
|
if (!res) {
|
||||||
|
LOG_ERR("[CC-Client] error: unable to performRequest GET -> http://%s:%d%s",
|
||||||
|
m_self->m_options->ccHost(), m_self->m_options->ccPort(), requestUrl.c_str());
|
||||||
|
} else if (res->status != 200) {
|
||||||
|
LOG_ERR("[CC-Client] error: \"%d\" -> http://%s:%d%s", res->status, m_self->m_options->ccHost(),
|
||||||
|
m_self->m_options->ccPort(), requestUrl.c_str());
|
||||||
|
} else {
|
||||||
|
rapidjson::Document document;
|
||||||
|
if (!document.Parse(res->body.c_str()).HasParseError()) {
|
||||||
|
std::ofstream clientConfigFile(m_self->m_options->configFile());
|
||||||
|
if (clientConfigFile) {
|
||||||
|
rapidjson::StringBuffer buffer(0, 65536);
|
||||||
|
rapidjson::PrettyWriter<rapidjson::StringBuffer> writer(buffer);
|
||||||
|
writer.SetMaxDecimalPlaces(10);
|
||||||
|
document.Accept(writer);
|
||||||
|
|
||||||
|
clientConfigFile << buffer.GetString();
|
||||||
|
clientConfigFile.close();
|
||||||
|
|
||||||
|
LOG_WARN("[CC-Client] Config updated. -> restart");
|
||||||
|
App::restart();
|
||||||
|
} else {
|
||||||
|
LOG_ERR("[CC-Client] Not able to store client config to file %s.", m_self->m_options->configFile());
|
||||||
|
}
|
||||||
|
} else{
|
||||||
|
LOG_ERR("[CC-Client] Not able to store client config. received client config is broken!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::shared_ptr<httplib::Response> CCClient::performRequest(const std::string& requestUrl,
|
||||||
|
const std::string& requestBuffer,
|
||||||
|
const std::string& operation)
|
||||||
|
{
|
||||||
|
httplib::Client cli(m_self->m_options->ccHost(), m_self->m_options->ccPort());
|
||||||
|
|
||||||
|
httplib::Request req;
|
||||||
|
req.method = operation.c_str();
|
||||||
|
req.path = requestUrl.c_str();
|
||||||
|
req.set_header("Host", "");
|
||||||
|
req.set_header("Accept", "*/*");
|
||||||
|
req.set_header("User-Agent", Platform::userAgent());
|
||||||
|
req.set_header("Accept", "application/json");
|
||||||
|
req.set_header("Content-Type", "application/json");
|
||||||
|
|
||||||
|
if (!m_self->m_authorization.empty()) {
|
||||||
|
req.set_header("Authorization", m_self->m_authorization.c_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!requestBuffer.empty()) {
|
||||||
|
req.body = requestBuffer.c_str();
|
||||||
|
}
|
||||||
|
|
||||||
|
auto res = std::make_shared<httplib::Response>();
|
||||||
|
|
||||||
|
return cli.send(req, *res) ? res : nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CCClient::onReport(uv_timer_t *handle)
|
||||||
|
{
|
||||||
|
if (m_self) {
|
||||||
|
m_self->publishClientStatusReport();
|
||||||
|
}
|
||||||
|
}
|
71
src/cc/CCClient.h
Normal file
71
src/cc/CCClient.h
Normal file
|
@ -0,0 +1,71 @@
|
||||||
|
/* 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 2016-2017 XMRig <support@xmrig.com>
|
||||||
|
* Copyright 2017- BenDr0id <ben@graef.in>
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* 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 __CC_CLIENT_H__
|
||||||
|
#define __CC_CLIENT_H__
|
||||||
|
|
||||||
|
#ifndef XMRIG_NO_CC
|
||||||
|
|
||||||
|
#include <uv.h>
|
||||||
|
#include <3rdparty/cpp-httplib/httplib.h>
|
||||||
|
#include "Options.h"
|
||||||
|
#include "ClientStatus.h"
|
||||||
|
|
||||||
|
class Hashrate;
|
||||||
|
class NetworkState;
|
||||||
|
|
||||||
|
class CCClient
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
CCClient(const Options *options);
|
||||||
|
~CCClient();
|
||||||
|
|
||||||
|
static void updateHashrate(const Hashrate *hashrate);
|
||||||
|
static void updateNetworkState(const NetworkState &results);
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
static void publishClientStatusReport();
|
||||||
|
static void updateConfig();
|
||||||
|
static std::shared_ptr<httplib::Response> performRequest(const std::string& requestUrl,
|
||||||
|
const std::string& requestBuffer,
|
||||||
|
const std::string& operation);
|
||||||
|
|
||||||
|
static void onReport(uv_timer_t *handle);
|
||||||
|
|
||||||
|
const Options *m_options;
|
||||||
|
|
||||||
|
static CCClient* m_self;
|
||||||
|
static uv_mutex_t m_mutex;
|
||||||
|
|
||||||
|
ClientStatus m_clientStatus;
|
||||||
|
|
||||||
|
std::string m_authorization;
|
||||||
|
|
||||||
|
uv_timer_t m_timer;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
|
#endif /* __CC_CLIENT_H__ */
|
198
src/cc/CCServer.cpp
Normal file
198
src/cc/CCServer.cpp
Normal file
|
@ -0,0 +1,198 @@
|
||||||
|
/* XMRigCC
|
||||||
|
* 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 2016-2017 XMRig <support@xmrig.com>
|
||||||
|
* Copyright 2017- BenDr0id <ben@graef.in>
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* 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 "CCServer.h"
|
||||||
|
#include "Service.h"
|
||||||
|
#include "Httpd.h"
|
||||||
|
#include "Console.h"
|
||||||
|
#include "log/ConsoleLog.h"
|
||||||
|
#include "log/FileLog.h"
|
||||||
|
#include "log/Log.h"
|
||||||
|
#include "Options.h"
|
||||||
|
#include "Summary.h"
|
||||||
|
|
||||||
|
#if _WIN32
|
||||||
|
#include <winsock2.h>
|
||||||
|
#include <windows.h>
|
||||||
|
#else
|
||||||
|
# include "unistd.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef HAVE_SYSLOG_H
|
||||||
|
# include "log/SysLog.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
CCServer *CCServer::m_self = nullptr;
|
||||||
|
|
||||||
|
|
||||||
|
CCServer::CCServer(int argc, char** argv) :
|
||||||
|
m_console(nullptr),
|
||||||
|
m_httpd(nullptr),
|
||||||
|
m_options(nullptr)
|
||||||
|
{
|
||||||
|
m_self = this;
|
||||||
|
|
||||||
|
Log::init();
|
||||||
|
|
||||||
|
m_options = Options::parse(argc, argv);
|
||||||
|
if (!m_options) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!m_options->background()) {
|
||||||
|
Log::add(new ConsoleLog(m_options->colors()));
|
||||||
|
m_console = new Console(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_options->logFile()) {
|
||||||
|
Log::add(new FileLog(m_options->logFile()));
|
||||||
|
}
|
||||||
|
|
||||||
|
# ifdef HAVE_SYSLOG_H
|
||||||
|
if (m_options->syslog()) {
|
||||||
|
Log::add(new SysLog());
|
||||||
|
}
|
||||||
|
# endif
|
||||||
|
|
||||||
|
uv_signal_init(uv_default_loop(), &m_signal);
|
||||||
|
}
|
||||||
|
|
||||||
|
CCServer::~CCServer()
|
||||||
|
{
|
||||||
|
uv_tty_reset_mode();
|
||||||
|
|
||||||
|
delete m_httpd;
|
||||||
|
}
|
||||||
|
|
||||||
|
int CCServer::start()
|
||||||
|
{
|
||||||
|
if (!m_options) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
uv_signal_start(&m_signal, CCServer::onSignal, SIGHUP);
|
||||||
|
uv_signal_start(&m_signal, CCServer::onSignal, SIGTERM);
|
||||||
|
uv_signal_start(&m_signal, CCServer::onSignal, SIGINT);
|
||||||
|
|
||||||
|
if (m_options->background()) {
|
||||||
|
moveToBackground();
|
||||||
|
}
|
||||||
|
|
||||||
|
Summary::print();
|
||||||
|
|
||||||
|
Service::start();
|
||||||
|
|
||||||
|
m_httpd = new Httpd(m_options);
|
||||||
|
m_httpd->start();
|
||||||
|
|
||||||
|
const int r = uv_run(uv_default_loop(), UV_RUN_DEFAULT);
|
||||||
|
uv_loop_close(uv_default_loop());
|
||||||
|
|
||||||
|
Options::release();
|
||||||
|
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CCServer::onConsoleCommand(char command)
|
||||||
|
{
|
||||||
|
switch (command) {
|
||||||
|
case 'q':
|
||||||
|
case 'Q':
|
||||||
|
stop();
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 3:
|
||||||
|
LOG_WARN("Ctrl+C received, exiting");
|
||||||
|
stop();
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CCServer::stop()
|
||||||
|
{
|
||||||
|
uv_stop(uv_default_loop());
|
||||||
|
}
|
||||||
|
|
||||||
|
void CCServer::onSignal(uv_signal_t* handle, int signum)
|
||||||
|
{
|
||||||
|
switch (signum)
|
||||||
|
{
|
||||||
|
case SIGHUP:
|
||||||
|
LOG_WARN("SIGHUP received, exiting");
|
||||||
|
break;
|
||||||
|
|
||||||
|
case SIGTERM:
|
||||||
|
LOG_WARN("SIGTERM received, exiting");
|
||||||
|
break;
|
||||||
|
|
||||||
|
case SIGINT:
|
||||||
|
LOG_WARN("SIGINT received, exiting");
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
uv_signal_stop(handle);
|
||||||
|
m_self->stop();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CCServer::moveToBackground()
|
||||||
|
{
|
||||||
|
#ifdef WIN32
|
||||||
|
HWND hcon = GetConsoleWindow();
|
||||||
|
if (hcon) {
|
||||||
|
ShowWindow(hcon, SW_HIDE);
|
||||||
|
} else {
|
||||||
|
HANDLE h = GetStdHandle(STD_OUTPUT_HANDLE);
|
||||||
|
CloseHandle(h);
|
||||||
|
FreeConsole();
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
int i = fork();
|
||||||
|
if (i < 0) {
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (i > 0) {
|
||||||
|
exit(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
i = setsid();
|
||||||
|
|
||||||
|
if (i < 0) {
|
||||||
|
LOG_ERR("setsid() failed (errno = %d)", errno);
|
||||||
|
}
|
||||||
|
|
||||||
|
i = chdir("/");
|
||||||
|
if (i < 0) {
|
||||||
|
LOG_ERR("chdir() failed (errno = %d)", errno);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
65
src/cc/CCServer.h
Normal file
65
src/cc/CCServer.h
Normal file
|
@ -0,0 +1,65 @@
|
||||||
|
/* XMRigCC
|
||||||
|
* 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 2016-2017 XMRig <support@xmrig.com>
|
||||||
|
* Copyright 2017- BenDr0id <ben@graef.in>
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* 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 __CC_SERVER_H__
|
||||||
|
#define __CC_SERVER_H__
|
||||||
|
|
||||||
|
|
||||||
|
#include <uv.h>
|
||||||
|
|
||||||
|
|
||||||
|
#include "interfaces/IConsoleListener.h"
|
||||||
|
|
||||||
|
|
||||||
|
class Console;
|
||||||
|
class Httpd;
|
||||||
|
class Options;
|
||||||
|
|
||||||
|
class CCServer : public IConsoleListener
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
CCServer(int argc, char **argv);
|
||||||
|
~CCServer();
|
||||||
|
|
||||||
|
int start();
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void onConsoleCommand(char command) override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
void stop();
|
||||||
|
void moveToBackground();
|
||||||
|
|
||||||
|
static void onSignal(uv_signal_t* handle, int signum);
|
||||||
|
|
||||||
|
static CCServer* m_self;
|
||||||
|
|
||||||
|
Console* m_console;
|
||||||
|
Httpd* m_httpd;
|
||||||
|
Options* m_options;
|
||||||
|
uv_signal_t m_signal;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#endif /* __CC_SERVER_H__ */
|
279
src/cc/ClientStatus.cpp
Normal file
279
src/cc/ClientStatus.cpp
Normal file
|
@ -0,0 +1,279 @@
|
||||||
|
/* 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 2016-2017 XMRig <support@xmrig.com>
|
||||||
|
* Copyright 2017- BenDr0id <ben@graef.in>
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* 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 <chrono>
|
||||||
|
#include <cstring>
|
||||||
|
#include <3rdparty/rapidjson/stringbuffer.h>
|
||||||
|
#include <3rdparty/rapidjson/prettywriter.h>
|
||||||
|
#include <log/Log.h>
|
||||||
|
|
||||||
|
#include "ClientStatus.h"
|
||||||
|
|
||||||
|
ClientStatus::ClientStatus()
|
||||||
|
: m_hashrateShort(0),
|
||||||
|
m_hashrateMedium(0),
|
||||||
|
m_hashrateLong(0),
|
||||||
|
m_sharesGood(0),
|
||||||
|
m_sharesTotal(0),
|
||||||
|
m_hashesTotal(0),
|
||||||
|
m_lastStatusUpdate(0)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string ClientStatus::getClientId() const
|
||||||
|
{
|
||||||
|
return m_clientId;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ClientStatus::setClientId(const std::string& clientId)
|
||||||
|
{
|
||||||
|
m_clientId = clientId;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string ClientStatus::getCurrentPool() const
|
||||||
|
{
|
||||||
|
return m_currentPool;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ClientStatus::setCurrentPool(const std::string& currentPool)
|
||||||
|
{
|
||||||
|
m_currentPool = currentPool;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ClientStatus::setCurrentAlgoName(const std::string& algoName)
|
||||||
|
{
|
||||||
|
m_currentAlgoName = algoName;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string ClientStatus::getCurrentAlgoName() const
|
||||||
|
{
|
||||||
|
return m_currentAlgoName;
|
||||||
|
}
|
||||||
|
|
||||||
|
ClientStatus::Status ClientStatus::getCurrentStatus() const
|
||||||
|
{
|
||||||
|
return m_currentStatus;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ClientStatus::setCurrentStatus(Status currentStatus)
|
||||||
|
{
|
||||||
|
m_currentStatus = currentStatus;
|
||||||
|
}
|
||||||
|
|
||||||
|
double ClientStatus::getHashrateShort() const
|
||||||
|
{
|
||||||
|
return m_hashrateShort;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ClientStatus::setHashrateShort(double hashrateShort)
|
||||||
|
{
|
||||||
|
m_hashrateShort = hashrateShort;
|
||||||
|
}
|
||||||
|
|
||||||
|
double ClientStatus::getHashrateMedium() const
|
||||||
|
{
|
||||||
|
return m_hashrateMedium;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ClientStatus::setHashrateMedium(double hashrateMedium)
|
||||||
|
{
|
||||||
|
m_hashrateMedium = hashrateMedium;
|
||||||
|
}
|
||||||
|
|
||||||
|
double ClientStatus::getHashrateLong() const
|
||||||
|
{
|
||||||
|
return m_hashrateLong;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ClientStatus::setHashrateLong(double hashrateLong)
|
||||||
|
{
|
||||||
|
m_hashrateLong = hashrateLong;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint64_t ClientStatus::getSharesGood() const
|
||||||
|
{
|
||||||
|
return m_sharesGood;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ClientStatus::setSharesGood(uint64_t sharesGood)
|
||||||
|
{
|
||||||
|
m_sharesGood = sharesGood;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint64_t ClientStatus::getSharesTotal() const
|
||||||
|
{
|
||||||
|
return m_sharesTotal;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ClientStatus::setSharesTotal(uint64_t sharesTotal)
|
||||||
|
{
|
||||||
|
m_sharesTotal = sharesTotal;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint64_t ClientStatus::getHashesTotal() const
|
||||||
|
{
|
||||||
|
return m_hashesTotal;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ClientStatus::setHashesTotal(uint64_t hashesTotal)
|
||||||
|
{
|
||||||
|
m_hashesTotal = hashesTotal;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ClientStatus::setHashrateHighest(double hashrateHighest)
|
||||||
|
{
|
||||||
|
m_hashrateHighest = hashrateHighest;
|
||||||
|
}
|
||||||
|
|
||||||
|
double ClientStatus::getHashrateHighest() const
|
||||||
|
{
|
||||||
|
return m_hashrateHighest;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ClientStatus::setAvgTime(uint32_t avgTime)
|
||||||
|
{
|
||||||
|
m_avgTime = avgTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t ClientStatus::getAvgTime() const
|
||||||
|
{
|
||||||
|
return m_avgTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::time_t ClientStatus::getLastStatusUpdate() const
|
||||||
|
{
|
||||||
|
return m_lastStatusUpdate;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ClientStatus::parseFromJson(const rapidjson::Document& document)
|
||||||
|
{
|
||||||
|
bool result = false;
|
||||||
|
|
||||||
|
if (document.HasMember("client_status"))
|
||||||
|
{
|
||||||
|
rapidjson::Value::ConstObject clientStatus = document["client_status"].GetObject();
|
||||||
|
|
||||||
|
if (clientStatus.HasMember("client_id")) {
|
||||||
|
m_clientId = clientStatus["client_id"].GetString();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (clientStatus.HasMember("current_pool")) {
|
||||||
|
m_currentPool = clientStatus["current_pool"].GetString();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (clientStatus.HasMember("current_status")) {
|
||||||
|
m_currentStatus = toStatus(clientStatus["current_status"].GetString());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (clientStatus.HasMember("current_algo_name")) {
|
||||||
|
m_currentAlgoName = clientStatus["current_algo_name"].GetString();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (clientStatus.HasMember("hashrate_short")) {
|
||||||
|
m_hashrateShort = clientStatus["hashrate_short"].GetDouble();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (clientStatus.HasMember("hashrate_medium")) {
|
||||||
|
m_hashrateMedium = clientStatus["hashrate_medium"].GetDouble();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (clientStatus.HasMember("hashrate_long")) {
|
||||||
|
m_hashrateLong = clientStatus["hashrate_long"].GetDouble();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (clientStatus.HasMember("hashrate_highest")) {
|
||||||
|
m_hashrateHighest = clientStatus["hashrate_highest"].GetDouble();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (clientStatus.HasMember("avg_time")) {
|
||||||
|
m_avgTime = clientStatus["avg_time"].GetUint();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (clientStatus.HasMember("shares_good")) {
|
||||||
|
m_sharesGood = clientStatus["shares_good"].GetUint64();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (clientStatus.HasMember("shares_total")) {
|
||||||
|
m_sharesTotal = clientStatus["shares_total"].GetUint64();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (clientStatus.HasMember("hashes_total")) {
|
||||||
|
m_hashesTotal = clientStatus["hashes_total"].GetUint64();
|
||||||
|
}
|
||||||
|
|
||||||
|
auto time_point = std::chrono::system_clock::now();
|
||||||
|
m_lastStatusUpdate = std::chrono::system_clock::to_time_t(time_point);
|
||||||
|
|
||||||
|
result = true;
|
||||||
|
} else {
|
||||||
|
LOG_ERR("Parse Error, JSON does not contain: control_command");
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
rapidjson::Value ClientStatus::toJson(rapidjson::MemoryPoolAllocator<rapidjson::CrtAllocator>& allocator)
|
||||||
|
{
|
||||||
|
rapidjson::Value clientStatus(rapidjson::kObjectType);
|
||||||
|
|
||||||
|
clientStatus.AddMember("client_id", rapidjson::StringRef(m_clientId.c_str()), allocator);
|
||||||
|
clientStatus.AddMember("current_pool", rapidjson::StringRef(m_currentPool.c_str()), allocator);
|
||||||
|
clientStatus.AddMember("current_status", rapidjson::StringRef(toString(m_currentStatus)), allocator);
|
||||||
|
clientStatus.AddMember("current_algo_name", rapidjson::StringRef(m_currentAlgoName.c_str()), allocator);
|
||||||
|
|
||||||
|
clientStatus.AddMember("hashrate_short", m_hashrateShort, allocator);
|
||||||
|
clientStatus.AddMember("hashrate_medium", m_hashrateMedium, allocator);
|
||||||
|
clientStatus.AddMember("hashrate_long", m_hashrateLong, allocator);
|
||||||
|
clientStatus.AddMember("hashrate_highest", m_hashrateHighest, allocator);
|
||||||
|
clientStatus.AddMember("avg_time", m_avgTime, allocator);
|
||||||
|
|
||||||
|
clientStatus.AddMember("shares_good", m_sharesGood, allocator);
|
||||||
|
clientStatus.AddMember("shares_total", m_sharesTotal, allocator);
|
||||||
|
clientStatus.AddMember("hashes_total", m_hashesTotal, allocator);
|
||||||
|
|
||||||
|
clientStatus.AddMember("last_status_update", m_lastStatusUpdate, allocator);
|
||||||
|
|
||||||
|
return clientStatus;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string ClientStatus::toJsonString()
|
||||||
|
{
|
||||||
|
rapidjson::Document respDocument;
|
||||||
|
respDocument.SetObject();
|
||||||
|
|
||||||
|
auto& allocator = respDocument.GetAllocator();
|
||||||
|
|
||||||
|
rapidjson::Value clientStatus = ClientStatus::toJson(allocator);
|
||||||
|
respDocument.AddMember("client_status", clientStatus, allocator);
|
||||||
|
|
||||||
|
rapidjson::StringBuffer buffer(0, 4096);
|
||||||
|
rapidjson::Writer<rapidjson::StringBuffer> writer(buffer);
|
||||||
|
writer.SetMaxDecimalPlaces(10);
|
||||||
|
respDocument.Accept(writer);
|
||||||
|
|
||||||
|
return strdup(buffer.GetString());
|
||||||
|
}
|
||||||
|
|
131
src/cc/ClientStatus.h
Normal file
131
src/cc/ClientStatus.h
Normal file
|
@ -0,0 +1,131 @@
|
||||||
|
/* 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 2016-2017 XMRig <support@xmrig.com>
|
||||||
|
* Copyright 2017- BenDr0id <ben@graef.in>
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* 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 __CLIENT_STATUS_H__
|
||||||
|
#define __CLIENT_STATUS_H__
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include <ctime>
|
||||||
|
#include "rapidjson/document.h"
|
||||||
|
|
||||||
|
class ClientStatus
|
||||||
|
{
|
||||||
|
|
||||||
|
public:
|
||||||
|
enum Status {
|
||||||
|
RUNNING,
|
||||||
|
PAUSED,
|
||||||
|
CONFIG_UPDATED
|
||||||
|
};
|
||||||
|
|
||||||
|
public:
|
||||||
|
ClientStatus();
|
||||||
|
|
||||||
|
inline const char *toString (Status status)
|
||||||
|
{
|
||||||
|
return status_str[static_cast<int>(status)];
|
||||||
|
}
|
||||||
|
|
||||||
|
inline Status toStatus (const char *status)
|
||||||
|
{
|
||||||
|
const int n = sizeof(status_str) / sizeof(status_str[0]);
|
||||||
|
for (int i = 0; i < n; ++i)
|
||||||
|
{
|
||||||
|
if (strcmp(status_str[i], status) == 0)
|
||||||
|
return (Status) i;
|
||||||
|
}
|
||||||
|
return Status::RUNNING;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string getClientId() const;
|
||||||
|
void setClientId(const std::string& clientId);
|
||||||
|
|
||||||
|
std::string getCurrentPool() const;
|
||||||
|
void setCurrentPool(const std::string& currentPool);
|
||||||
|
|
||||||
|
std::string getCurrentAlgoName() const;
|
||||||
|
void setCurrentAlgoName(const std::string &algoName);
|
||||||
|
|
||||||
|
Status getCurrentStatus() const;
|
||||||
|
void setCurrentStatus(Status currentStatus);
|
||||||
|
|
||||||
|
double getHashrateShort() const;
|
||||||
|
void setHashrateShort(double hashrateShort);
|
||||||
|
|
||||||
|
double getHashrateMedium() const;
|
||||||
|
void setHashrateMedium(double hashrateMedium);
|
||||||
|
|
||||||
|
double getHashrateLong() const;
|
||||||
|
void setHashrateLong(double hashrateLong);
|
||||||
|
|
||||||
|
uint64_t getSharesGood() const;
|
||||||
|
void setSharesGood(uint64_t sharesGood);
|
||||||
|
|
||||||
|
uint64_t getSharesTotal() const;
|
||||||
|
void setSharesTotal(uint64_t sharesTotal);
|
||||||
|
|
||||||
|
uint64_t getHashesTotal() const;
|
||||||
|
void setHashesTotal(uint64_t hashesTotal);
|
||||||
|
|
||||||
|
void setHashrateHighest(double hashrateHighest);
|
||||||
|
double getHashrateHighest() const;
|
||||||
|
|
||||||
|
void setAvgTime(uint32_t avgTime);
|
||||||
|
uint32_t getAvgTime() const;
|
||||||
|
|
||||||
|
std::time_t getLastStatusUpdate() const;
|
||||||
|
|
||||||
|
std::string toJsonString();
|
||||||
|
rapidjson::Value toJson(rapidjson::MemoryPoolAllocator<rapidjson::CrtAllocator>& allocator);
|
||||||
|
bool parseFromJson(const rapidjson::Document& document);
|
||||||
|
|
||||||
|
|
||||||
|
private:
|
||||||
|
const char* status_str[3] = {
|
||||||
|
"RUNNING",
|
||||||
|
"PAUSED",
|
||||||
|
"CONFIG_UPDATED"
|
||||||
|
};
|
||||||
|
|
||||||
|
Status m_currentStatus;
|
||||||
|
|
||||||
|
std::string m_clientId;
|
||||||
|
std::string m_currentPool;
|
||||||
|
std::string m_currentAlgoName;
|
||||||
|
|
||||||
|
double m_hashrateShort;
|
||||||
|
double m_hashrateMedium;
|
||||||
|
double m_hashrateLong;
|
||||||
|
double m_hashrateHighest;
|
||||||
|
|
||||||
|
uint64_t m_sharesGood;
|
||||||
|
uint64_t m_sharesTotal;
|
||||||
|
uint64_t m_hashesTotal;
|
||||||
|
|
||||||
|
uint32_t m_avgTime;
|
||||||
|
|
||||||
|
std::time_t m_lastStatusUpdate;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif /* __CLIENT_STATUS_H__ */
|
99
src/cc/ControlCommand.cpp
Normal file
99
src/cc/ControlCommand.cpp
Normal file
|
@ -0,0 +1,99 @@
|
||||||
|
/* 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 2016-2017 XMRig <support@xmrig.com>
|
||||||
|
* Copyright 2017- BenDr0id <ben@graef.in>
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* 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 <3rdparty/rapidjson/stringbuffer.h>
|
||||||
|
#include <3rdparty/rapidjson/prettywriter.h>
|
||||||
|
|
||||||
|
#include "log/Log.h"
|
||||||
|
#include "ControlCommand.h"
|
||||||
|
|
||||||
|
ControlCommand::ControlCommand()
|
||||||
|
: m_command(Command::START)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
ControlCommand::ControlCommand(Command command)
|
||||||
|
: m_command(command)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ControlCommand::parseFromJsonString(const std::string& json)
|
||||||
|
{
|
||||||
|
bool result = false;
|
||||||
|
|
||||||
|
rapidjson::Document document;
|
||||||
|
if (!document.Parse(json.c_str()).HasParseError()) {
|
||||||
|
result = parseFromJson(document);
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ControlCommand::parseFromJson(const rapidjson::Document& document)
|
||||||
|
{
|
||||||
|
bool result = false;
|
||||||
|
|
||||||
|
if (document.HasMember("control_command")) {
|
||||||
|
rapidjson::Value::ConstObject controlCommand = document["control_command"].GetObject();
|
||||||
|
if (controlCommand.HasMember("command")) {
|
||||||
|
m_command = toCommand(controlCommand["command"].GetString());
|
||||||
|
result = true;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
LOG_ERR("Parse Error, JSON does not contain: command");
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
LOG_ERR("Parse Error, JSON does not contain: control_command");
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
rapidjson::Value ControlCommand::toJson(rapidjson::MemoryPoolAllocator<rapidjson::CrtAllocator>& allocator)
|
||||||
|
{
|
||||||
|
rapidjson::Value controlCommand(rapidjson::kObjectType);
|
||||||
|
|
||||||
|
controlCommand.AddMember("command", rapidjson::StringRef(toString(m_command)), allocator);
|
||||||
|
|
||||||
|
return controlCommand;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ControlCommand::setCommand(Command command)
|
||||||
|
{
|
||||||
|
m_command = command;
|
||||||
|
}
|
||||||
|
|
||||||
|
ControlCommand::Command ControlCommand::getCommand() const
|
||||||
|
{
|
||||||
|
return m_command;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ControlCommand::isOneTimeCommand() const {
|
||||||
|
|
||||||
|
return m_command == ControlCommand::UPDATE_CONFIG ||
|
||||||
|
m_command == ControlCommand::RESTART ||
|
||||||
|
m_command == ControlCommand::SHUTDOWN;
|
||||||
|
}
|
83
src/cc/ControlCommand.h
Normal file
83
src/cc/ControlCommand.h
Normal file
|
@ -0,0 +1,83 @@
|
||||||
|
/* 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 2016-2017 XMRig <support@xmrig.com>
|
||||||
|
* Copyright 2017- BenDr0id <ben@graef.in>
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* 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 __CONTROL_COMMAND_H__
|
||||||
|
#define __CONTROL_COMMAND_H__
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include "rapidjson/document.h"
|
||||||
|
|
||||||
|
class ControlCommand
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
enum Command {
|
||||||
|
START,
|
||||||
|
STOP,
|
||||||
|
UPDATE_CONFIG,
|
||||||
|
RESTART,
|
||||||
|
SHUTDOWN
|
||||||
|
};
|
||||||
|
|
||||||
|
public:
|
||||||
|
ControlCommand();
|
||||||
|
explicit ControlCommand(Command command);
|
||||||
|
|
||||||
|
inline const char *toString (Command command)
|
||||||
|
{
|
||||||
|
return command_str[static_cast<int>(command)];
|
||||||
|
}
|
||||||
|
|
||||||
|
inline Command toCommand (const char *command)
|
||||||
|
{
|
||||||
|
const int n = sizeof(command_str) / sizeof(command_str[0]);
|
||||||
|
for (int i = 0; i < n; ++i)
|
||||||
|
{
|
||||||
|
if (strcmp(command_str[i], command) == 0)
|
||||||
|
return (Command) i;
|
||||||
|
}
|
||||||
|
return Command::START;
|
||||||
|
}
|
||||||
|
|
||||||
|
rapidjson::Value toJson(rapidjson::MemoryPoolAllocator<rapidjson::CrtAllocator>& allocator);
|
||||||
|
bool parseFromJsonString(const std::string& json);
|
||||||
|
bool parseFromJson(const rapidjson::Document& document);
|
||||||
|
|
||||||
|
Command getCommand() const;
|
||||||
|
void setCommand(Command command);
|
||||||
|
|
||||||
|
bool isOneTimeCommand() const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
const char* command_str[5] = {
|
||||||
|
"START",
|
||||||
|
"STOP",
|
||||||
|
"UPDATE_CONFIG",
|
||||||
|
"RESTART",
|
||||||
|
"SHUTDOWN"
|
||||||
|
};
|
||||||
|
|
||||||
|
Command m_command;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif /* __CONTROL_COMMAND_H__ */
|
238
src/cc/Httpd.cpp
Normal file
238
src/cc/Httpd.cpp
Normal file
|
@ -0,0 +1,238 @@
|
||||||
|
/* 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 2016-2017 XMRig <support@xmrig.com>
|
||||||
|
* Copyright 2017- BenDr0id <ben@graef.in>
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* 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 <cstring>
|
||||||
|
#include <microhttpd.h>
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
|
#include "version.h"
|
||||||
|
#include "Service.h"
|
||||||
|
#include "Httpd.h"
|
||||||
|
#include "log/Log.h"
|
||||||
|
|
||||||
|
Httpd::Httpd(const Options *options)
|
||||||
|
: m_options(options)
|
||||||
|
, m_daemon(nullptr)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Httpd::start()
|
||||||
|
{
|
||||||
|
if (!m_options->ccPort()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_daemon = MHD_start_daemon(MHD_USE_SELECT_INTERNALLY, static_cast<uint16_t>(m_options->ccPort()), nullptr, nullptr, &Httpd::handler,
|
||||||
|
this, MHD_OPTION_END);
|
||||||
|
|
||||||
|
if (!m_daemon) {
|
||||||
|
LOG_ERR("HTTP Daemon failed to start.");
|
||||||
|
return false;
|
||||||
|
} else {
|
||||||
|
LOG_INFO("%s Server started on Port: %d", APP_NAME, m_options->ccPort());
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned Httpd::tokenAuth(struct MHD_Connection* connection)
|
||||||
|
{
|
||||||
|
if (!m_options->ccToken()) {
|
||||||
|
LOG_WARN("AccessToken not set. Access Granted!");
|
||||||
|
return MHD_HTTP_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char* header = MHD_lookup_connection_value(connection, MHD_HEADER_KIND, MHD_HTTP_HEADER_AUTHORIZATION);
|
||||||
|
if (m_options->ccToken() && !header) {
|
||||||
|
return MHD_HTTP_UNAUTHORIZED;
|
||||||
|
}
|
||||||
|
|
||||||
|
const size_t size = strlen(header);
|
||||||
|
if (size < 8 || strlen(m_options->ccToken()) != size - 7 || memcmp("Bearer ", header, 7) != 0) {
|
||||||
|
LOG_WARN("AccessToken wrong. Access Forbidden!");
|
||||||
|
return MHD_HTTP_FORBIDDEN;
|
||||||
|
}
|
||||||
|
|
||||||
|
return strncmp(m_options->ccToken(), header + 7, strlen(m_options->ccToken())) == 0 ? MHD_HTTP_OK : MHD_HTTP_FORBIDDEN;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned Httpd::basicAuth(struct MHD_Connection* connection, std::string& resp)
|
||||||
|
{
|
||||||
|
if (!m_options->ccAdminUser() || !m_options->ccAdminPass()) {
|
||||||
|
resp = std::string("<html><body\\>"
|
||||||
|
"Please configure admin user and pass to view this Page."
|
||||||
|
"</body><html\\>");
|
||||||
|
|
||||||
|
LOG_WARN("Admin user/password not set. Access Forbidden!");
|
||||||
|
return MHD_HTTP_FORBIDDEN;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char* header = MHD_lookup_connection_value(connection, MHD_HEADER_KIND, MHD_HTTP_HEADER_AUTHORIZATION);
|
||||||
|
if (!header) {
|
||||||
|
return MHD_HTTP_UNAUTHORIZED;
|
||||||
|
}
|
||||||
|
|
||||||
|
char* user;
|
||||||
|
char* pass;
|
||||||
|
|
||||||
|
user = MHD_basic_auth_get_username_password(connection, &pass);
|
||||||
|
|
||||||
|
if (user == nullptr || strcmp(user, m_options->ccAdminUser()) != 0 ||
|
||||||
|
pass == nullptr || strcmp(pass, m_options->ccAdminPass()) != 0) {
|
||||||
|
|
||||||
|
LOG_WARN("Admin user/password wrong. Access Unauthorized!");
|
||||||
|
return MHD_HTTP_UNAUTHORIZED;
|
||||||
|
}
|
||||||
|
|
||||||
|
return MHD_HTTP_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
int Httpd::sendResponse(MHD_Connection* connection, unsigned status, MHD_Response* rsp, const char* contentType)
|
||||||
|
{
|
||||||
|
if (!rsp) {
|
||||||
|
rsp = MHD_create_response_from_buffer(0, nullptr, MHD_RESPMEM_MUST_COPY);
|
||||||
|
}
|
||||||
|
|
||||||
|
MHD_add_response_header(rsp, "Content-Type", contentType);
|
||||||
|
MHD_add_response_header(rsp, "Access-Control-Allow-Origin", "*");
|
||||||
|
MHD_add_response_header(rsp, "Access-Control-Allow-Methods", "POST, GET, OPTIONS");
|
||||||
|
MHD_add_response_header(rsp, "Access-Control-Allow-Headers", "Content-Type, Authorization");
|
||||||
|
MHD_add_response_header(rsp, "WWW-Authenticate", "Basic");
|
||||||
|
MHD_add_response_header(rsp, "WWW-Authenticate", "Bearer");
|
||||||
|
|
||||||
|
int ret = MHD_queue_response(connection, status, rsp);
|
||||||
|
|
||||||
|
MHD_destroy_response(rsp);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int Httpd::handler(void* httpd, MHD_Connection* connection, const char* url, const char* method,
|
||||||
|
const char* version, const char* upload_data, size_t* upload_data_size, void** con_cls)
|
||||||
|
{
|
||||||
|
if (strcmp(method, MHD_HTTP_METHOD_OPTIONS) == 0) {
|
||||||
|
LOG_INFO("OPTIONS Requested");
|
||||||
|
return sendResponse(connection, MHD_HTTP_OK, nullptr, CONTENT_TYPE_HTML);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (strcmp(method, MHD_HTTP_METHOD_GET) != 0 && strcmp(method, MHD_HTTP_METHOD_POST) != 0) {
|
||||||
|
LOG_ERR("HTTP_METHOD_NOT_ALLOWED");
|
||||||
|
return sendResponse(connection, MHD_HTTP_METHOD_NOT_ALLOWED, nullptr, CONTENT_TYPE_HTML);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (strstr(url, "/client/")) {
|
||||||
|
unsigned status = static_cast<Httpd*>(httpd)->tokenAuth(connection);
|
||||||
|
if (status != MHD_HTTP_OK) {
|
||||||
|
return sendResponse(connection, status, nullptr, CONTENT_TYPE_JSON);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
std::string resp;
|
||||||
|
unsigned status = static_cast<Httpd*>(httpd)->basicAuth(connection, resp);
|
||||||
|
if (status != MHD_HTTP_OK) {
|
||||||
|
MHD_Response* rsp = nullptr;
|
||||||
|
if (!resp.empty()) {
|
||||||
|
rsp = MHD_create_response_from_buffer(resp.length(), (void*)resp.c_str(), MHD_RESPMEM_MUST_COPY);
|
||||||
|
}
|
||||||
|
return sendResponse(connection, status, rsp, CONTENT_TYPE_HTML);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (strcmp(method, MHD_HTTP_METHOD_GET) == 0) {
|
||||||
|
return handleGET(static_cast<Httpd*>(httpd), connection, url);
|
||||||
|
} else {
|
||||||
|
return handlePOST(static_cast<Httpd*>(httpd), connection, url, upload_data, upload_data_size, con_cls);
|
||||||
|
}
|
||||||
|
|
||||||
|
return MHD_NO;
|
||||||
|
}
|
||||||
|
|
||||||
|
int Httpd::handleGET(const Httpd* httpd, struct MHD_Connection* connection, const char* urlPtr)
|
||||||
|
{
|
||||||
|
std::string resp;
|
||||||
|
std::string url(urlPtr);
|
||||||
|
std::string clientId;
|
||||||
|
|
||||||
|
const char* clientIdPtr = MHD_lookup_connection_value(connection, MHD_GET_ARGUMENT_KIND, "clientId");
|
||||||
|
if (clientIdPtr)
|
||||||
|
{
|
||||||
|
clientId = std::string(clientIdPtr);
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned status = Service::handleGET(httpd->m_options, url, clientId, resp);
|
||||||
|
|
||||||
|
MHD_Response* rsp = nullptr;
|
||||||
|
if (!resp.empty()) {
|
||||||
|
rsp = MHD_create_response_from_buffer(resp.length(), (void*) resp.c_str(), MHD_RESPMEM_MUST_COPY);
|
||||||
|
}
|
||||||
|
|
||||||
|
char* contentType;
|
||||||
|
if (url == "/") {
|
||||||
|
contentType = const_cast<char*>(CONTENT_TYPE_HTML);
|
||||||
|
} else {
|
||||||
|
contentType = const_cast<char*>(CONTENT_TYPE_JSON);
|
||||||
|
}
|
||||||
|
|
||||||
|
return sendResponse(connection, status, rsp, contentType);
|
||||||
|
}
|
||||||
|
|
||||||
|
int Httpd::handlePOST(const Httpd* httpd, struct MHD_Connection* connection, const char* urlPtr, const char* upload_data,
|
||||||
|
size_t* upload_data_size, void** con_cls)
|
||||||
|
{
|
||||||
|
auto* cc = (ConnectionContext*)* con_cls;
|
||||||
|
if (cc == nullptr) {
|
||||||
|
cc = new ConnectionContext();
|
||||||
|
*con_cls = (void*) cc;
|
||||||
|
} else {
|
||||||
|
if (*upload_data_size != 0) {
|
||||||
|
cc->data << std::string(upload_data, *upload_data_size);
|
||||||
|
|
||||||
|
*upload_data_size = 0;
|
||||||
|
} else {
|
||||||
|
std::string resp;
|
||||||
|
std::string url(urlPtr);
|
||||||
|
std::string clientId;
|
||||||
|
|
||||||
|
const char* clientIdPtr = MHD_lookup_connection_value(connection, MHD_GET_ARGUMENT_KIND, "clientId");
|
||||||
|
if (clientIdPtr)
|
||||||
|
{
|
||||||
|
clientId = std::string(clientIdPtr);
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned status = Service::handlePOST(httpd->m_options, url, clientId, cc->data.str(), resp);
|
||||||
|
|
||||||
|
MHD_Response* rsp = nullptr;
|
||||||
|
if (!resp.empty()) {
|
||||||
|
rsp = MHD_create_response_from_buffer(resp.length(), (void*) resp.c_str(), MHD_RESPMEM_MUST_COPY);
|
||||||
|
}
|
||||||
|
|
||||||
|
delete cc;
|
||||||
|
*con_cls = nullptr;
|
||||||
|
|
||||||
|
return sendResponse(connection, status, rsp, CONTENT_TYPE_JSON);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return MHD_YES;
|
||||||
|
}
|
66
src/cc/Httpd.h
Normal file
66
src/cc/Httpd.h
Normal file
|
@ -0,0 +1,66 @@
|
||||||
|
/* 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 2016-2017 XMRig <support@xmrig.com>
|
||||||
|
* Copyright 2017- BenDr0id <ben@graef.in>
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* 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 __HTTPD_H__
|
||||||
|
#define __HTTPD_H__
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include <sstream>
|
||||||
|
#include <uv.h>
|
||||||
|
|
||||||
|
#include "Options.h"
|
||||||
|
|
||||||
|
|
||||||
|
struct MHD_Connection;
|
||||||
|
struct MHD_Daemon;
|
||||||
|
struct MHD_Response;
|
||||||
|
|
||||||
|
class Httpd
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
Httpd(const Options *options);
|
||||||
|
bool start();
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
typedef struct PostContext
|
||||||
|
{
|
||||||
|
std::stringstream data;
|
||||||
|
} ConnectionContext;
|
||||||
|
|
||||||
|
static int sendResponse(MHD_Connection* connection, unsigned status, MHD_Response* rsp, const char* contentType);
|
||||||
|
|
||||||
|
unsigned basicAuth(MHD_Connection* connection, std::string &resp);
|
||||||
|
unsigned tokenAuth(MHD_Connection* connection);
|
||||||
|
|
||||||
|
static int handler(void* httpd, MHD_Connection* connection, const char* url, const char* method, const char* version, const char* upload_data, size_t* upload_data_size, void**con_cls);
|
||||||
|
static int handleGET(const Httpd* httpd, MHD_Connection* connection, const char* url);
|
||||||
|
static int handlePOST(const Httpd* httpd, MHD_Connection* connection, const char* url, const char* upload_data, size_t* upload_data_size, void** con_cls);
|
||||||
|
|
||||||
|
const Options* m_options;
|
||||||
|
MHD_Daemon* m_daemon;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif /* __HTTPD_H__ */
|
7
src/cc/README.md
Normal file
7
src/cc/README.md
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
# XMRigCC common repository
|
||||||
|
This repository contains all common XMRigCC files.
|
||||||
|
|
||||||
|
# Used in this repos
|
||||||
|
* [xmrigCC](https://github.com/bendr0id/xmrigCC)
|
||||||
|
* [xmrigCC-nvidia](https://github.com/bendr0id/xmrigCC-nvidia)
|
||||||
|
|
322
src/cc/Service.cpp
Normal file
322
src/cc/Service.cpp
Normal file
|
@ -0,0 +1,322 @@
|
||||||
|
/* 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 2016-2017 XMRig <support@xmrig.com>
|
||||||
|
* Copyright 2017- BenDr0id <ben@graef.in>
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* 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 <cstring>
|
||||||
|
#include <sstream>
|
||||||
|
#include <fstream>
|
||||||
|
#include <3rdparty/rapidjson/document.h>
|
||||||
|
#include <3rdparty/rapidjson/stringbuffer.h>
|
||||||
|
#include <3rdparty/rapidjson/writer.h>
|
||||||
|
#include <3rdparty/rapidjson/filewritestream.h>
|
||||||
|
#include <3rdparty/rapidjson/filereadstream.h>
|
||||||
|
#include <3rdparty/rapidjson/error/en.h>
|
||||||
|
#include <3rdparty/rapidjson/prettywriter.h>
|
||||||
|
#include "log/Log.h"
|
||||||
|
#include "Service.h"
|
||||||
|
|
||||||
|
uv_mutex_t Service::m_mutex;
|
||||||
|
std::map<std::string, ControlCommand> Service::m_clientCommand;
|
||||||
|
std::map<std::string, ClientStatus> Service::m_clientStatus;
|
||||||
|
|
||||||
|
bool Service::start()
|
||||||
|
{
|
||||||
|
uv_mutex_init(&m_mutex);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Service::release()
|
||||||
|
{
|
||||||
|
uv_mutex_lock(&m_mutex);
|
||||||
|
|
||||||
|
m_clientCommand.clear();
|
||||||
|
m_clientStatus.clear();
|
||||||
|
|
||||||
|
uv_mutex_unlock(&m_mutex);
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned Service::handleGET(const Options* options, const std::string& url, const std::string& clientId, std::string& resp)
|
||||||
|
{
|
||||||
|
uv_mutex_lock(&m_mutex);
|
||||||
|
|
||||||
|
unsigned resultCode = MHD_HTTP_NOT_FOUND;
|
||||||
|
|
||||||
|
LOG_INFO("GET(url='%s', clientId='%s')", url.c_str(), clientId.c_str());
|
||||||
|
|
||||||
|
if (url == "/") {
|
||||||
|
resultCode = getAdminPage(options, resp);
|
||||||
|
} else if (url.rfind("/admin/getClientStatusList", 0) == 0) {
|
||||||
|
resultCode = getClientStatusList(resp);
|
||||||
|
} else {
|
||||||
|
if (!clientId.empty()) {
|
||||||
|
if (url.rfind("/client/getConfig", 0) == 0 || url.rfind("/admin/getClientConfig", 0) == 0) {
|
||||||
|
resultCode = getClientConfig(options, clientId, resp);
|
||||||
|
} else if (url.rfind("/admin/getClientCommand", 0) == 0) {
|
||||||
|
resultCode = getClientCommand(clientId, resp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
LOG_ERR("Request does not contain clientId: %s", url.c_str());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
uv_mutex_unlock(&m_mutex);
|
||||||
|
|
||||||
|
return resultCode;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned Service::handlePOST(const Options* options, const std::string& url, const std::string& clientId, const std::string& data, std::string& resp)
|
||||||
|
{
|
||||||
|
uv_mutex_lock(&m_mutex);
|
||||||
|
|
||||||
|
unsigned resultCode = MHD_HTTP_NOT_FOUND;
|
||||||
|
|
||||||
|
LOG_INFO("POST(url='%s', clientId='%s', dataLen='%d')", url.c_str(), clientId.c_str(), data.length());
|
||||||
|
|
||||||
|
if (url.rfind("/client/setClientStatus", 0) == 0) {
|
||||||
|
resultCode = setClientStatus(clientId, data, resp);
|
||||||
|
} else if (url.rfind("/admin/setClientConfig", 0) == 0) {
|
||||||
|
resultCode = setClientConfig(options, clientId, data, resp);
|
||||||
|
} else if (url.rfind("/admin/setClientCommand", 0) == 0) {
|
||||||
|
resultCode = setClientCommand(clientId, data, resp);
|
||||||
|
}
|
||||||
|
|
||||||
|
uv_mutex_unlock(&m_mutex);
|
||||||
|
|
||||||
|
return resultCode;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned Service::getClientConfig(const Options* options, const std::string& clientId, std::string& resp)
|
||||||
|
{
|
||||||
|
unsigned resultCode = MHD_HTTP_INTERNAL_SERVER_ERROR;
|
||||||
|
|
||||||
|
std::string clientConfigFileName = getClientConfigFileName(options, clientId);
|
||||||
|
|
||||||
|
std::stringstream data;
|
||||||
|
std::ifstream clientConfig(clientConfigFileName);
|
||||||
|
if (clientConfig) {
|
||||||
|
data << clientConfig.rdbuf();
|
||||||
|
clientConfig.close();
|
||||||
|
} else {
|
||||||
|
std::ifstream defaultConfig("default_config.json");
|
||||||
|
if (defaultConfig) {
|
||||||
|
data << defaultConfig.rdbuf();
|
||||||
|
defaultConfig.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (data.tellp() > 0) {
|
||||||
|
rapidjson::Document document;
|
||||||
|
document.Parse(data.str().c_str());
|
||||||
|
|
||||||
|
if (!document.HasParseError()) {
|
||||||
|
rapidjson::StringBuffer buffer(0, 65536);
|
||||||
|
rapidjson::Writer<rapidjson::StringBuffer> writer(buffer);
|
||||||
|
writer.SetMaxDecimalPlaces(10);
|
||||||
|
document.Accept(writer);
|
||||||
|
|
||||||
|
resp = strdup(buffer.GetString());
|
||||||
|
|
||||||
|
resultCode = MHD_HTTP_OK;
|
||||||
|
} else {
|
||||||
|
LOG_ERR("Not able to send client config. Client config %s is broken!", clientConfigFileName.c_str());
|
||||||
|
}
|
||||||
|
} else{
|
||||||
|
LOG_ERR("Not able to load a client config. Please check your configuration!");
|
||||||
|
}
|
||||||
|
|
||||||
|
return resultCode;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned Service::setClientConfig(const Options* options, const std::string &clientId, const std::string &data, std::string &resp)
|
||||||
|
{
|
||||||
|
unsigned resultCode = MHD_HTTP_BAD_REQUEST;
|
||||||
|
|
||||||
|
rapidjson::Document document;
|
||||||
|
if (!document.Parse(data.c_str()).HasParseError()) {
|
||||||
|
std::string clientConfigFileName = getClientConfigFileName(options, clientId);
|
||||||
|
std::ofstream clientConfigFile(clientConfigFileName);
|
||||||
|
|
||||||
|
if (clientConfigFile){
|
||||||
|
rapidjson::StringBuffer buffer(0, 4096);
|
||||||
|
rapidjson::PrettyWriter<rapidjson::StringBuffer> writer(buffer);
|
||||||
|
writer.SetMaxDecimalPlaces(10);
|
||||||
|
document.Accept(writer);
|
||||||
|
|
||||||
|
clientConfigFile << buffer.GetString();
|
||||||
|
clientConfigFile.close();
|
||||||
|
|
||||||
|
resultCode = MHD_HTTP_OK;
|
||||||
|
} else {
|
||||||
|
LOG_ERR("Not able to store client config to file %s.", clientConfigFileName.c_str());
|
||||||
|
}
|
||||||
|
} else{
|
||||||
|
LOG_ERR("Not able to store client config. The received client config for client %s is broken!", clientId.c_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
return resultCode;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned Service::getClientStatusList(std::string& resp)
|
||||||
|
{
|
||||||
|
rapidjson::Document document;
|
||||||
|
document.SetObject();
|
||||||
|
|
||||||
|
auto& allocator = document.GetAllocator();
|
||||||
|
|
||||||
|
rapidjson::Value clientStatusList(rapidjson::kArrayType);
|
||||||
|
for (auto& clientStatus : m_clientStatus) {
|
||||||
|
rapidjson::Value clientStatusEntry(rapidjson::kObjectType);
|
||||||
|
clientStatusEntry.AddMember("client_status", clientStatus.second.toJson(allocator), allocator);
|
||||||
|
clientStatusList.PushBack(clientStatusEntry, allocator);
|
||||||
|
}
|
||||||
|
|
||||||
|
document.AddMember("client_status_list", clientStatusList, allocator);
|
||||||
|
|
||||||
|
rapidjson::StringBuffer buffer(0, 4096);
|
||||||
|
rapidjson::Writer<rapidjson::StringBuffer> writer(buffer);
|
||||||
|
writer.SetMaxDecimalPlaces(10);
|
||||||
|
document.Accept(writer);
|
||||||
|
|
||||||
|
resp = strdup(buffer.GetString());
|
||||||
|
|
||||||
|
return MHD_HTTP_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned Service::setClientStatus(const std::string& clientId, const std::string& data, std::string& resp)
|
||||||
|
{
|
||||||
|
int resultCode = MHD_HTTP_BAD_REQUEST;
|
||||||
|
|
||||||
|
rapidjson::Document document;
|
||||||
|
if (!document.Parse(data.c_str()).HasParseError()) {
|
||||||
|
LOG_INFO("Status from client: %s", clientId.c_str());
|
||||||
|
|
||||||
|
ClientStatus clientStatus;
|
||||||
|
clientStatus.parseFromJson(document);
|
||||||
|
|
||||||
|
m_clientStatus[clientId] = clientStatus;
|
||||||
|
|
||||||
|
resultCode = getClientCommand(clientId, resp);
|
||||||
|
|
||||||
|
if (m_clientCommand[clientId].isOneTimeCommand()) {
|
||||||
|
m_clientCommand.erase(clientId);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
LOG_ERR("Parse Error Occured: %d", document.GetParseError());
|
||||||
|
}
|
||||||
|
|
||||||
|
return resultCode;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned Service::getClientCommand(const std::string& clientId, std::string& resp)
|
||||||
|
{
|
||||||
|
if (m_clientCommand.find(clientId) == m_clientCommand.end()) {
|
||||||
|
m_clientCommand[clientId] = ControlCommand();
|
||||||
|
}
|
||||||
|
|
||||||
|
rapidjson::Document respDocument;
|
||||||
|
respDocument.SetObject();
|
||||||
|
|
||||||
|
auto& allocator = respDocument.GetAllocator();
|
||||||
|
|
||||||
|
rapidjson::Value controlCommand = m_clientCommand[clientId].toJson(allocator);
|
||||||
|
respDocument.AddMember("control_command", controlCommand, allocator);
|
||||||
|
|
||||||
|
rapidjson::StringBuffer buffer(0, 4096);
|
||||||
|
rapidjson::Writer<rapidjson::StringBuffer> writer(buffer);
|
||||||
|
writer.SetMaxDecimalPlaces(10);
|
||||||
|
respDocument.Accept(writer);
|
||||||
|
|
||||||
|
resp = strdup(buffer.GetString());
|
||||||
|
|
||||||
|
return MHD_HTTP_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned Service::setClientCommand(const std::string& clientId, const std::string& data, std::string& resp)
|
||||||
|
{
|
||||||
|
ControlCommand controlCommand;
|
||||||
|
|
||||||
|
rapidjson::Document document;
|
||||||
|
if (!document.Parse(data.c_str()).HasParseError()) {
|
||||||
|
controlCommand.parseFromJson(document);
|
||||||
|
|
||||||
|
m_clientCommand[clientId] = controlCommand;
|
||||||
|
|
||||||
|
return MHD_HTTP_OK;
|
||||||
|
} else {
|
||||||
|
return MHD_HTTP_BAD_REQUEST;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned Service::getAdminPage(const Options* options, std::string& resp)
|
||||||
|
{
|
||||||
|
std::stringstream data;
|
||||||
|
|
||||||
|
if (options->ccCustomDashboard() != nullptr) {
|
||||||
|
std::ifstream customDashboard(options->ccCustomDashboard());
|
||||||
|
if (customDashboard)
|
||||||
|
{
|
||||||
|
data << customDashboard.rdbuf();
|
||||||
|
customDashboard.close();
|
||||||
|
resp = data.str();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (resp.empty()) {
|
||||||
|
data << "<!DOCTYPE html>";
|
||||||
|
data << "<html lang=\"en\">";
|
||||||
|
data << "<head>";
|
||||||
|
data << "<meta charset=\"utf-8\">";
|
||||||
|
data << "<title>XMRigCC Dashboard</title>";
|
||||||
|
data << "</head>";
|
||||||
|
data << "<body>";
|
||||||
|
data << " <div style=\"text-align: center;\">";
|
||||||
|
data << " <h1>Please configure a Dashboard</h1>";
|
||||||
|
data << " </div>";
|
||||||
|
data << "</body>";
|
||||||
|
data << "</html>";
|
||||||
|
}
|
||||||
|
|
||||||
|
resp = data.str();
|
||||||
|
|
||||||
|
return MHD_HTTP_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string Service::getClientConfigFileName(const Options* options, const std::string& clientId)
|
||||||
|
{
|
||||||
|
std::string clientConfigFileName;
|
||||||
|
|
||||||
|
if (options->ccClientConfigFolder() != nullptr) {
|
||||||
|
clientConfigFileName += options->ccClientConfigFolder();
|
||||||
|
# ifdef WIN32
|
||||||
|
clientConfigFileName += '\\';
|
||||||
|
# else
|
||||||
|
clientConfigFileName += '/';
|
||||||
|
# endif
|
||||||
|
}
|
||||||
|
|
||||||
|
clientConfigFileName += clientId + std::string("_config.json");
|
||||||
|
|
||||||
|
return clientConfigFileName;
|
||||||
|
}
|
68
src/cc/Service.h
Normal file
68
src/cc/Service.h
Normal file
|
@ -0,0 +1,68 @@
|
||||||
|
/* 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 2016-2017 XMRig <support@xmrig.com>
|
||||||
|
* Copyright 2017- BenDr0id <ben@graef.in>
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* 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 __SERVICE_H__
|
||||||
|
#define __SERVICE_H__
|
||||||
|
|
||||||
|
#define CONTENT_TYPE_HTML "text/html"
|
||||||
|
#define CONTENT_TYPE_JSON "application/json"
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include <uv.h>
|
||||||
|
#include <microhttpd.h>
|
||||||
|
#include <map>
|
||||||
|
#include "Options.h"
|
||||||
|
#include "ClientStatus.h"
|
||||||
|
#include "ControlCommand.h"
|
||||||
|
|
||||||
|
class Service
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
static bool start();
|
||||||
|
static void release();
|
||||||
|
|
||||||
|
static unsigned handleGET(const Options* options, const std::string& url, const std::string& clientId, std::string& resp);
|
||||||
|
static unsigned handlePOST(const Options* options, const std::string& url, const std::string& clientId, const std::string& data, std::string& resp);
|
||||||
|
|
||||||
|
private:
|
||||||
|
static unsigned getClientConfig(const Options* options, const std::string& clientId, std::string& resp);
|
||||||
|
static unsigned getClientCommand(const std::string& clientId, std::string& resp);
|
||||||
|
static unsigned getClientStatusList(std::string& resp);
|
||||||
|
static unsigned getAdminPage(const Options* options, std::string& resp);
|
||||||
|
|
||||||
|
static unsigned setClientStatus(const std::string& clientId, const std::string& data, std::string& resp);
|
||||||
|
static unsigned setClientCommand(const std::string& clientId, const std::string& data, std::string& resp);
|
||||||
|
static unsigned setClientConfig(const Options* options, const std::string &clientId, const std::string &data, std::string &resp);
|
||||||
|
|
||||||
|
static std::string getClientConfigFileName(const Options *options, const std::string &clientId);
|
||||||
|
|
||||||
|
private:
|
||||||
|
static std::map<std::string, ClientStatus> m_clientStatus;
|
||||||
|
static std::map<std::string, ControlCommand> m_clientCommand;
|
||||||
|
|
||||||
|
static uv_mutex_t m_mutex;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif /* __SERVICE_H__ */
|
67
src/cc/Summary.cpp
Normal file
67
src/cc/Summary.cpp
Normal file
|
@ -0,0 +1,67 @@
|
||||||
|
|
||||||
|
/* 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 2016-2017 XMRig <support@xmrig.com>
|
||||||
|
* Copyright 2017- BenDr0id <ben@graef.in>
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* 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 "log/Log.h"
|
||||||
|
#include "Options.h"
|
||||||
|
#include "Summary.h"
|
||||||
|
#include "version.h"
|
||||||
|
|
||||||
|
static void print_versions()
|
||||||
|
{
|
||||||
|
char buf[16];
|
||||||
|
|
||||||
|
# if defined(__clang__)
|
||||||
|
snprintf(buf, 16, " clang/%d.%d.%d", __clang_major__, __clang_minor__, __clang_patchlevel__);
|
||||||
|
# elif defined(__GNUC__)
|
||||||
|
snprintf(buf, 16, " gcc/%d.%d.%d", __GNUC__, __GNUC_MINOR__, __GNUC_PATCHLEVEL__);
|
||||||
|
# elif defined(_MSC_VER)
|
||||||
|
snprintf(buf, 16, " MSVC/%d", MSVC_VERSION);
|
||||||
|
# else
|
||||||
|
buf[0] = '\0';
|
||||||
|
# endif
|
||||||
|
|
||||||
|
|
||||||
|
Log::i()->text(Options::i()->colors() ? "\x1B[01;32m * \x1B[01;37mVERSIONS: \x1B[01;36m%s/%s\x1B[01;37m libuv/%s%s" : " * VERSIONS: %s/%s libuv/%s%s",
|
||||||
|
APP_NAME, APP_VERSION, uv_version_string(), buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void print_commands()
|
||||||
|
{
|
||||||
|
if (Options::i()->colors()) {
|
||||||
|
Log::i()->text("\x1B[01;32m * \x1B[01;37mCOMMANDS: \x1B[01;35mq\x1B[01;37muit");
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
Log::i()->text(" * COMMANDS: 'q' Quit");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Summary::print()
|
||||||
|
{
|
||||||
|
print_versions();
|
||||||
|
print_commands();
|
||||||
|
}
|
31
src/cc/XMRigCC.cpp
Normal file
31
src/cc/XMRigCC.cpp
Normal file
|
@ -0,0 +1,31 @@
|
||||||
|
/* XMRigCC
|
||||||
|
* 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 2016-2017 XMRig <support@xmrig.com>
|
||||||
|
* Copyright 2017- BenDr0id <ben@graef.in>
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* 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 "CCServer.h"
|
||||||
|
|
||||||
|
|
||||||
|
int main(int argc, char** argv) {
|
||||||
|
CCServer ccServer(argc, argv);
|
||||||
|
return ccServer.start();
|
||||||
|
}
|
61
src/cc/XMRigd.cpp
Normal file
61
src/cc/XMRigd.cpp
Normal file
|
@ -0,0 +1,61 @@
|
||||||
|
/* 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 2016-2017 XMRig <support@xmrig.com>
|
||||||
|
* Copyright 2017- BenDr0id <ben@graef.in>
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* 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 <stdlib.h>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
#ifdef WIN32
|
||||||
|
#define WIN32_LEAN_AND_MEAN /* avoid including junk */
|
||||||
|
#include <windows.h>
|
||||||
|
#include <signal.h>
|
||||||
|
#endif
|
||||||
|
int main(int argc, char **argv) {
|
||||||
|
|
||||||
|
std::string ownPath(argv[0]);
|
||||||
|
std::string xmrigDaemon("xmrigDaemon");
|
||||||
|
std::string xmrigMiner("xmrigMiner");
|
||||||
|
|
||||||
|
std::string xmrigMinerPath = ownPath.replace(ownPath.rfind(xmrigDaemon),xmrigDaemon.size(), xmrigMiner);
|
||||||
|
|
||||||
|
#ifdef WIN32
|
||||||
|
xmrigMinerPath = "\"" + xmrigMinerPath + "\"";
|
||||||
|
#endif
|
||||||
|
|
||||||
|
for (int i=1; i < argc; i++){
|
||||||
|
xmrigMinerPath += " ";
|
||||||
|
xmrigMinerPath += argv[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
xmrigMinerPath += " --daemonized";
|
||||||
|
|
||||||
|
int status = 0;
|
||||||
|
|
||||||
|
do {
|
||||||
|
status = system(xmrigMinerPath.c_str());
|
||||||
|
#ifdef WIN32
|
||||||
|
} while (status == EINTR);
|
||||||
|
#else
|
||||||
|
} while (WEXITSTATUS(status) == EINTR);
|
||||||
|
#endif
|
||||||
|
}
|
Loading…
Add table
Add a link
Reference in a new issue