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.
 
 
 

162 lines
4.3 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>
#define MAX_PACKET 2048
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) : _server(server), _socket(io_service), _id(id), _subscribed(false), _jobid(0), _shareLimiter(this)
{
_diff = sConfig.Get<uint32>("StratumMinDifficulty");
_minDiff = _diff;
}
tcp::socket& GetSocket()
{
return _socket;
}
void Start()
{
// Get IP
tcp::endpoint remote_ep = _socket.remote_endpoint();
address remote_ad = remote_ep.address();
_ip = remote_ad.to_v4().to_ulong();
// Start reading socket
StartRead();
}
void StartRead()
{
// Read until newline
boost::asio::async_read_until(
_socket,
_recvBuffer,
'\n',
boost::bind(&Client::_OnReceive, this, asio::placeholders::error, asio::placeholders::bytes_transferred));
}
void SendJob(bool clean);
void SendMessage(JSON msg)
{
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()),
boost::bind(&Client::_OnSend, 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.Error(LOG_SERVER, "Method '%s' not found.", method.c_str());
}
// Gets new job from the server
Job GetJob();
// Worker difficulty
uint64 GetDifficulty()
{
return _diff;
}
void SetDifficulty(uint64 diff, bool resendJob = false)
{
_diff = diff;
// Send difficulty update
JSON params;
params.Add(int64(_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;
}
void Disconnect()
{
_socket.close();
}
public:
void _OnReceive(const boost::system::error_code& error, size_t bytes_transferred);
void _OnSend(const boost::system::error_code& error);
private:
// Networking
asio::streambuf _recvBuffer;
tcp::socket _socket;
uint32 _ip;
uint64 _id;
// Pointer to server
Stratum::Server* _server;
// Authorization
std::vector<std::string> _workers;
// Jobs
bool _subscribed;
uint32 _extranonce;
std::map<uint64, Job> _jobs;
uint32 _jobid;
// Share limiting
uint64 _diff;
uint64 _minDiff;
ShareLimiter _shareLimiter;
};
typedef boost::shared_ptr<Client> ClientPtr;
}
#endif