mirror of https://github.com/GOSTSec/poolserver
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
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
|
|
|