Cryptocurrency mining pool written in C++ for speed. Supports Stratum.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

200 lines
5.8 KiB

#ifndef STRATUM_CLIENT_H_
#define STRATUM_CLIENT_H_
#include "Common.h"
#include "Config.h"
#include "Log.h"
#include "JSON.h"
#include "Server.h"
#include "Job.h"
#include "ShareLimiter.h"
#include <boost/asio.hpp>
#include <boost/bind.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/enable_shared_from_this.hpp>
#include <set>
using namespace boost;
using namespace boost::asio::ip;
namespace Stratum
{
class Server;
class Client : public boost::enable_shared_from_this<Client>
{
public:
Client(Server* server, asio::io_service& io_service, uint64 id) : _io_service(io_service), _server(server), _socket(io_service), _ioStrand(io_service), _id(id), _subscribed(false), _jobid(0), _shareLimiter(this)
{
_diff = sConfig.Get<double>("RetargetStartingDiff");
_minDiff = sConfig.Get<double>("RetargetMinDiff");
}
~Client()
{
CleanJobs();
sLog.Info(LOG_STRATUM, "%u: I'm going out! Cya!", _ip);
}
tcp::socket& GetSocket()
{
return _socket;
}
// Start client up!
bool Start();
void StartRead()
{
// Read until newline
asio::async_read(
_socket,
_recvBuffer,
asio::transfer_at_least(1),
_ioStrand.wrap(boost::bind(&Client::_OnReceive, shared_from_this(), asio::placeholders::error, asio::placeholders::bytes_transferred)));
}
void SendJob(bool clean);
void SendMessage(JSON msg)
{
boost::unique_lock<boost::mutex> lock(_mtxWrite);
std::string data = msg.ToString();
data += '\n';
sLog.Debug(LOG_SERVER, "Sending: %s", data.c_str());
boost::asio::async_write(
_socket,
boost::asio::buffer(data.c_str(), data.length()),
_ioStrand.wrap(boost::bind(&Client::_OnSend, shared_from_this(), boost::asio::placeholders::error)));
}
void OnMiningSubmit(JSON msg);
void OnMiningSubscribe(JSON msg);
void OnMiningAuthorize(JSON msg);
void OnMessage(JSON msg)
{
std::string method = msg["method"].GetString();
sLog.Debug(LOG_SERVER, "Decoded: %s", msg.ToString().c_str());
if (method.compare("mining.submit") == 0)
OnMiningSubmit(msg);
else if (method.compare("mining.subscribe") == 0)
OnMiningSubscribe(msg);
else if (method.compare("mining.authorize") == 0)
OnMiningAuthorize(msg);
else
sLog.Debug(LOG_STRATUM, "Method '%s' not found.", method.c_str());
}
// Gets new job from the server
Job* GetJob();
void CleanJobs()
{
for (std::map<uint64, Job*>::iterator it = _jobs.begin(); it != _jobs.end(); ++it)
delete it->second;
_jobs.clear();
}
// Worker difficulty
double GetDifficulty()
{
return _diff;
}
void SetDifficulty(double diff, bool resendJob = false)
{
if (diff < _minDiff)
diff = _minDiff;
if (diff == _diff)
return;
_diff = diff;
// Send difficulty update
JSON params;
params.Add(double(_diff));
JSON msg;
msg["id"];
msg["params"] = params;
msg["method"] = "mining.set_difficulty";
SendMessage(msg);
if (resendJob)
SendJob(false);
}
// Client ID
uint64 GetID()
{
return _id;
}
uint32 GetIP()
{
return _ip;
}
void Ban(uint32 time);
void Disconnect();
void RedirectGetwork()
{
sLog.Info(LOG_STRATUM, "Sending redirect to stratum for client %u", _ip);
std::string redirect(Util::FS("HTTP/1.1 200 OK\r\nX-Stratum: stratum+tcp://%s:%u\r\nConnection: Close\r\nContent-Length: 41\r\n\r\n{\"error\": null, \"result\": false, \"id\": 0}\n", sConfig.Get<std::string>("StratumRedirectHost").c_str(), sConfig.Get<uint16>("StratumPort")));
boost::asio::async_write(
_socket,
boost::asio::buffer(redirect.c_str(), redirect.length()),
_ioStrand.wrap(boost::bind(&Client::_OnSend, shared_from_this(), boost::asio::placeholders::error)));
}
void CloseSocket()
{
boost::system::error_code ec;
_socket.shutdown(asio::ip::tcp::socket::shutdown_both, ec);
_socket.close(ec);
}
public:
void _OnReceive(const boost::system::error_code& error, size_t bytes_transferred);
void _OnSend(const boost::system::error_code& error);
private:
// ASIO
asio::io_service& _io_service;
// Networking
asio::streambuf _recvBuffer;
std::string _recvMessage;
tcp::socket _socket;
asio::strand _ioStrand;
boost::mutex _mtxWrite;
uint32 _ip;
uint64 _id;
// Pointer to server
Stratum::Server* _server;
// Authorization
std::set<std::string> _workers;
// Jobs
bool _subscribed;
uint32 _extranonce;
std::map<uint64, Job*> _jobs;
uint32 _jobid;
// Share limiting
double _diff;
double _minDiff;
ShareLimiter _shareLimiter;
};
typedef boost::shared_ptr<Client> ClientPtr;
}
#endif