summaryrefslogtreecommitdiffstats
path: root/xmrstak/net/jpsock.hpp
blob: 2ddeeee29cf6da67e97386cbe2bb228d484cc5ec (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
#pragma once

#include "xmrstak/backend/iBackend.hpp"
#include "msgstruct.hpp"
#include "xmrstak/jconf.hpp"

#include <mutex>
#include <atomic>
#include <condition_variable>
#include <thread>
#include <string>


/* Our pool can have two kinds of errors:
	- Parsing or connection error
	Those are fatal errors (we drop the connection if we encounter them).
	After they are constructed from const char* strings from various places.
	(can be from read-only mem), we passs them in an exectutor message
	once the recv thread expires.
	- Call error
	This error happens when the "server says no". Usually because the job was
	outdated, or we somehow got the hash wrong. It isn't fatal.
	We parse it in-situ in the network buffer, after that we copy it to a
	std::string. Executor will move the buffer via an r-value ref.
*/
class base_socket;

class jpsock
{
public:
	jpsock(size_t id, const char* sAddr, const char* sLogin, const char* sRigId, const char* sPassword, double pool_weight, bool dev_pool, bool tls, const char* tls_fp, bool nicehash);
	~jpsock();

	bool connect(std::string& sConnectError);
	void disconnect(bool quiet = false);

	bool cmd_login();
	bool cmd_submit(const char* sJobId, uint32_t iNonce, const uint8_t* bResult, const char* backend_name, uint64_t backend_hashcount, uint64_t total_hashcount, xmrstak_algo algo);

	static bool hex2bin(const char* in, unsigned int len, unsigned char* out);
	static void bin2hex(const unsigned char* in, unsigned int len, char* out);

	inline double get_pool_weight(bool gross_weight) 
	{ 
		double ret = pool_weight; 
		if(gross_weight && bRunning)
			ret += 10.0;
		if(gross_weight && bLoggedIn)
			ret += 10.0;
		return ret;
	}

	inline size_t can_connect() { return get_timestamp() != connect_time; }
	inline bool is_running() { return bRunning; }
	inline bool is_logged_in() { return bLoggedIn; }
	inline bool is_dev_pool() { return pool; }
	inline size_t get_pool_id() { return pool_id; }
	inline bool get_disconnects(size_t& att, size_t& time) { att = connect_attempts; time = disconnect_time != 0 ? get_timestamp() - disconnect_time + 1 : 0; return pool && usr_login[0]; }
	inline const char* get_pool_addr() { return net_addr.c_str(); }
	inline const char* get_tls_fp() { return tls_fp.c_str(); }
	inline bool is_nicehash() { return nicehash; }

	bool get_pool_motd(std::string& strin);

	std::string&& get_call_error();
	bool have_call_error() { return call_error; }
	bool have_sock_error() { return bHaveSocketError; }

	inline static uint64_t t32_to_t64(uint32_t t) { return 0xFFFFFFFFFFFFFFFFULL / (0xFFFFFFFFULL / ((uint64_t)t)); }
	inline static uint64_t t64_to_diff(uint64_t t) { return 0xFFFFFFFFFFFFFFFFULL / t; }
	inline static uint64_t diff_to_t64(uint64_t d) { return 0xFFFFFFFFFFFFFFFFULL / d; }

	inline uint64_t get_current_diff() { return iJobDiff; }

	void save_nonce(uint32_t nonce);
	bool get_current_job(pool_job& job);

	bool set_socket_error(const char* a);
	bool set_socket_error(const char* a, const char* b);
	bool set_socket_error(const char* a, size_t len);
	bool set_socket_error_strerr(const char* a);
	bool set_socket_error_strerr(const char* a, int res);

private:
	std::string net_addr;
	std::string usr_login;
	std::string usr_rigid;
	std::string usr_pass;
	std::string tls_fp;

	size_t pool_id;
	double pool_weight;
	bool pool;
	bool nicehash;

	bool ext_algo = false;
	bool ext_backend = false;
	bool ext_hashcount = false;
	bool ext_motd = false;

	std::string pool_motd;
	std::mutex motd_mutex;

	size_t connect_time = 0;
	std::atomic<size_t> connect_attempts;
	std::atomic<size_t> disconnect_time;

	std::atomic<bool> bRunning;
	std::atomic<bool> bLoggedIn;
	std::atomic<bool> quiet_close;
	std::atomic<bool> call_error;

	uint8_t* bJsonRecvMem;
	uint8_t* bJsonParseMem;
	uint8_t* bJsonCallMem;

	static constexpr size_t iJsonMemSize = 4096;
	static constexpr size_t iSockBufferSize = 4096;

	struct call_rsp;
	struct opaque_private;
	struct opq_json_val;

	void jpsock_thread();
	bool jpsock_thd_main();
	bool process_line(char* line, size_t len);
	bool process_pool_job(const opq_json_val* params);
	bool cmd_ret_wait(const char* sPacket, opq_json_val& poResult);

	char sMinerId[64];
	std::atomic<uint64_t> iJobDiff;

	std::string sSocketError;
	std::atomic<bool> bHaveSocketError;

	std::mutex call_mutex;
	std::condition_variable call_cond;
	std::thread* oRecvThd;

	std::mutex job_mutex;
	pool_job oCurrentJob;

	opaque_private* prv;
	base_socket* sck;
};

OpenPOWER on IntegriCloud