summaryrefslogtreecommitdiffstats
path: root/xmrstak/net
diff options
context:
space:
mode:
authorfireice-uk <fireice-uk@users.noreply.github.com>2017-11-09 22:43:08 +0000
committerpsychocrypt <psychocrypt@users.noreply.github.com>2017-11-09 23:43:08 +0100
commitd35893d926c74893d7c85d1b87b24ffa55744649 (patch)
treeb2c1186e3ad96696592e1572e553514af04048b4 /xmrstak/net
parentb3237bab587f937e90a2ff0d06aba5e3630a8047 (diff)
downloadxmr-stak-d35893d926c74893d7c85d1b87b24ffa55744649.zip
xmr-stak-d35893d926c74893d7c85d1b87b24ffa55744649.tar.gz
Multi-pool final version (#90)
* Multi-pool first draft * Fix wspace from new IDE * Better TLS error message * Fix TLS bug * Don't put dev pool on stats + pool change-back * bug fixes * Error message work * fix win build * add per-pool nicehash setting * Fix bugs * rm debug msg * Multipool guided setup * Support TLS and Nicehash in config * prelim jconf changes * final multipool changes * increase default retry_time to 30, fix mac erro * rm debug dev pool settings * Fix another source of connect runaway
Diffstat (limited to 'xmrstak/net')
-rw-r--r--xmrstak/net/jpsock.cpp31
-rw-r--r--xmrstak/net/jpsock.hpp42
-rw-r--r--xmrstak/net/msgstruct.hpp50
-rw-r--r--xmrstak/net/socket.cpp67
4 files changed, 136 insertions, 54 deletions
diff --git a/xmrstak/net/jpsock.cpp b/xmrstak/net/jpsock.cpp
index 68b495d..f6f5c1f 100644
--- a/xmrstak/net/jpsock.cpp
+++ b/xmrstak/net/jpsock.cpp
@@ -94,7 +94,9 @@ struct jpsock::opq_json_val
opq_json_val(const Value* val) : val(val) {}
};
-jpsock::jpsock(size_t id, bool tls) : pool_id(id)
+jpsock::jpsock(size_t id, const char* sAddr, const char* sLogin, const char* sPassword, double pool_weight, bool dev_pool, bool tls, const char* tls_fp, bool nicehash) :
+ net_addr(sAddr), usr_login(sLogin), usr_pass(sPassword), tls_fp(tls_fp), pool_id(id), pool_weight(pool_weight), pool(dev_pool), nicehash(nicehash),
+ connect_time(0), connect_attempts(0), disconnect_time(0), quiet_close(false)
{
sock_init();
@@ -189,7 +191,7 @@ bool jpsock::set_socket_error_strerr(const char* a, int res)
void jpsock::jpsock_thread()
{
jpsock_thd_main();
- executor::inst()->push_event(ex_event(std::move(sSocketError), pool_id));
+ executor::inst()->push_event(ex_event(std::move(sSocketError), quiet_close, pool_id));
// If a call is wating, send an error to end it
bool bCallWaiting = false;
@@ -206,11 +208,16 @@ void jpsock::jpsock_thread()
if(bCallWaiting)
call_cond.notify_one();
- bRunning = false;
bLoggedIn = false;
+ if(bHaveSocketError && !quiet_close)
+ disconnect_time = get_timestamp();
+ else
+ disconnect_time = 0;
+
std::unique_lock<std::mutex>(job_mutex);
memset(&oCurrentJob, 0, sizeof(oCurrentJob));
+ bRunning = false;
}
bool jpsock::jpsock_thd_main()
@@ -417,15 +424,18 @@ bool jpsock::process_pool_job(const opq_json_val* params)
return true;
}
-bool jpsock::connect(const char* sAddr, std::string& sConnectError)
+bool jpsock::connect(std::string& sConnectError)
{
bHaveSocketError = false;
sSocketError.clear();
iJobDiff = 0;
-
- if(sck->set_hostname(sAddr))
+ connect_attempts++;
+
+ if(sck->set_hostname(net_addr.c_str()))
{
bRunning = true;
+ disconnect_time = 0;
+ connect_time = get_timestamp();
oRecvThd = new std::thread(&jpsock::jpsock_thread, this);
return true;
}
@@ -434,8 +444,9 @@ bool jpsock::connect(const char* sAddr, std::string& sConnectError)
return false;
}
-void jpsock::disconnect()
+void jpsock::disconnect(bool quiet)
{
+ quiet_close = quiet;
sck->close(false);
if(oRecvThd != nullptr)
@@ -446,6 +457,7 @@ void jpsock::disconnect()
}
sck->close(true);
+ quiet_close = false;
}
bool jpsock::cmd_ret_wait(const char* sPacket, opq_json_val& poResult)
@@ -493,12 +505,12 @@ bool jpsock::cmd_ret_wait(const char* sPacket, opq_json_val& poResult)
return bSuccess;
}
-bool jpsock::cmd_login(const char* sLogin, const char* sPassword)
+bool jpsock::cmd_login()
{
char cmd_buffer[1024];
snprintf(cmd_buffer, sizeof(cmd_buffer), "{\"method\":\"login\",\"params\":{\"login\":\"%s\",\"pass\":\"%s\",\"agent\":\"" AGENTID_STR "\"},\"id\":1}\n",
- sLogin, sPassword);
+ usr_login.c_str(), usr_pass.c_str());
opq_json_val oResult(nullptr);
@@ -541,6 +553,7 @@ bool jpsock::cmd_login(const char* sLogin, const char* sPassword)
}
bLoggedIn = true;
+ connect_attempts = 0;
return true;
}
diff --git a/xmrstak/net/jpsock.hpp b/xmrstak/net/jpsock.hpp
index e94eaad..db8cd0e 100644
--- a/xmrstak/net/jpsock.hpp
+++ b/xmrstak/net/jpsock.hpp
@@ -26,20 +26,37 @@ class base_socket;
class jpsock
{
public:
- jpsock(size_t id, bool tls);
+ jpsock(size_t id, const char* sAddr, const char* sLogin, const char* sPassword, double pool_weight, bool dev_pool, bool tls, const char* tls_fp, bool nicehash);
~jpsock();
- bool connect(const char* sAddr, std::string& sConnectError);
- void disconnect();
+ bool connect(std::string& sConnectError);
+ void disconnect(bool quiet = false);
- bool cmd_login(const char* sLogin, const char* sPassword);
+ bool cmd_login();
bool cmd_submit(const char* sJobId, uint32_t iNonce, const uint8_t* bResult);
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; }
std::string&& get_call_error();
bool have_sock_error() { return bHaveSocketError; }
@@ -53,8 +70,6 @@ public:
void save_nonce(uint32_t nonce);
bool get_current_job(pool_job& job);
- size_t pool_id;
-
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);
@@ -62,8 +77,23 @@ public:
bool set_socket_error_strerr(const char* a, int res);
private:
+ std::string net_addr;
+ std::string usr_login;
+ std::string usr_pass;
+ std::string tls_fp;
+
+ size_t pool_id;
+ double pool_weight;
+ bool pool;
+ bool nicehash;
+
+ 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;
uint8_t* bJsonRecvMem;
uint8_t* bJsonParseMem;
diff --git a/xmrstak/net/msgstruct.hpp b/xmrstak/net/msgstruct.hpp
index 82b59c1..01aa76c 100644
--- a/xmrstak/net/msgstruct.hpp
+++ b/xmrstak/net/msgstruct.hpp
@@ -39,11 +39,33 @@ struct job_result
}
};
+struct sock_err
+{
+ std::string sSocketError;
+ bool silent;
+
+ sock_err() {}
+ sock_err(std::string&& err, bool silent) : sSocketError(std::move(err)), silent(silent) { }
+ sock_err(sock_err&& from) : sSocketError(std::move(from.sSocketError)), silent(from.silent) {}
+
+ sock_err& operator=(sock_err&& from)
+ {
+ assert(this != &from);
+ sSocketError = std::move(from.sSocketError);
+ silent = from.silent;
+ return *this;
+ }
+
+ ~sock_err() { }
+
+ sock_err(sock_err const&) = delete;
+ sock_err& operator=(sock_err const&) = delete;
+};
enum ex_event_name { EV_INVALID_VAL, EV_SOCK_READY, EV_SOCK_ERROR,
- EV_POOL_HAVE_JOB, EV_MINER_HAVE_RESULT, EV_PERF_TICK, EV_RECONNECT,
- EV_SWITCH_POOL, EV_DEV_POOL_EXIT, EV_USR_HASHRATE, EV_USR_RESULTS, EV_USR_CONNSTAT,
- EV_HASHRATE_LOOP, EV_HTML_HASHRATE, EV_HTML_RESULTS, EV_HTML_CONNSTAT, EV_HTML_JSON };
+ EV_POOL_HAVE_JOB, EV_MINER_HAVE_RESULT, EV_PERF_TICK, EV_EVAL_POOL_CHOICE,
+ EV_USR_HASHRATE, EV_USR_RESULTS, EV_USR_CONNSTAT, EV_HASHRATE_LOOP,
+ EV_HTML_HASHRATE, EV_HTML_RESULTS, EV_HTML_CONNSTAT, EV_HTML_JSON };
/*
This is how I learned to stop worrying and love c++11 =).
@@ -64,11 +86,11 @@ struct ex_event
{
pool_job oPoolJob;
job_result oJobResult;
- std::string sSocketError;
+ sock_err oSocketError;
};
ex_event() { iName = EV_INVALID_VAL; iPoolId = 0;}
- ex_event(std::string&& err, size_t id) : iName(EV_SOCK_ERROR), iPoolId(id), sSocketError(std::move(err)) { }
+ ex_event(std::string&& err, bool silent, size_t id) : iName(EV_SOCK_ERROR), iPoolId(id), oSocketError(std::move(err), silent) { }
ex_event(job_result dat, size_t id) : iName(EV_MINER_HAVE_RESULT), iPoolId(id), oJobResult(dat) {}
ex_event(pool_job dat, size_t id) : iName(EV_POOL_HAVE_JOB), iPoolId(id), oPoolJob(dat) {}
ex_event(ex_event_name ev, size_t id = 0) : iName(ev), iPoolId(id) {}
@@ -85,7 +107,7 @@ struct ex_event
switch(iName)
{
case EV_SOCK_ERROR:
- new (&sSocketError) std::string(std::move(from.sSocketError));
+ new (&oSocketError) sock_err(std::move(from.oSocketError));
break;
case EV_MINER_HAVE_RESULT:
oJobResult = from.oJobResult;
@@ -103,7 +125,7 @@ struct ex_event
assert(this != &from);
if(iName == EV_SOCK_ERROR)
- sSocketError.~basic_string();
+ oSocketError.~sock_err();
iName = from.iName;
iPoolId = from.iPoolId;
@@ -111,8 +133,8 @@ struct ex_event
switch(iName)
{
case EV_SOCK_ERROR:
- new (&sSocketError) std::string();
- sSocketError = std::move(from.sSocketError);
+ new (&oSocketError) sock_err();
+ oSocketError = std::move(from.oSocketError);
break;
case EV_MINER_HAVE_RESULT:
oJobResult = from.oJobResult;
@@ -130,6 +152,14 @@ struct ex_event
~ex_event()
{
if(iName == EV_SOCK_ERROR)
- sSocketError.~basic_string();
+ oSocketError.~sock_err();
}
};
+
+#include <chrono>
+//Get steady_clock timestamp - misc helper function
+inline size_t get_timestamp()
+{
+ using namespace std::chrono;
+ return time_point_cast<seconds>(steady_clock::now()).time_since_epoch().count();
+};
diff --git a/xmrstak/net/socket.cpp b/xmrstak/net/socket.cpp
index b93376e..7079205 100644
--- a/xmrstak/net/socket.cpp
+++ b/xmrstak/net/socket.cpp
@@ -185,7 +185,15 @@ void tls_socket::print_error()
char *buf = nullptr;
size_t len = BIO_get_mem_data(err_bio, &buf);
- pCallback->set_socket_error(buf, len);
+ if(buf == nullptr)
+ {
+ if(jconf::inst()->TlsSecureAlgos())
+ pCallback->set_socket_error("Unknown TLS error. Secure TLS maybe unspported, try setting tls_secure_algo to false.");
+ else
+ pCallback->set_socket_error("Unknown TLS error.");
+ }
+ else
+ pCallback->set_socket_error(buf, len);
BIO_free(err_bio);
}
@@ -290,41 +298,42 @@ bool tls_socket::connect()
return false;
}
- if(pCallback->pool_id != executor::dev_pool_id)
+ //Base64 encode digest
+ BIO *bmem, *b64;
+ b64 = BIO_new(BIO_f_base64());
+ bmem = BIO_new(BIO_s_mem());
+
+ BIO_puts(bmem, "SHA256:");
+ b64 = BIO_push(b64, bmem);
+ BIO_set_flags(b64, BIO_FLAGS_BASE64_NO_NL);
+ BIO_write(b64, md, dlen);
+ BIO_flush(b64);
+
+ const char* conf_md = pCallback->get_tls_fp();
+ char *b64_md = nullptr;
+ size_t b64_len = BIO_get_mem_data(bmem, &b64_md);
+
+ if(strlen(conf_md) == 0)
{
- //Base64 encode digest
- BIO *bmem, *b64;
- b64 = BIO_new(BIO_f_base64());
- bmem = BIO_new(BIO_s_mem());
-
- BIO_puts(bmem, "SHA256:");
- b64 = BIO_push(b64, bmem);
- BIO_set_flags(b64, BIO_FLAGS_BASE64_NO_NL);
- BIO_write(b64, md, dlen);
- BIO_flush(b64);
-
- const char* conf_md = jconf::inst()->GetTlsFingerprint();
- char *b64_md = nullptr;
- size_t b64_len = BIO_get_mem_data(bmem, &b64_md);
-
- if(strlen(conf_md) == 0)
- {
- printer::inst()->print_msg(L1, "Server fingerprint: %.*s", (int)b64_len, b64_md);
- }
- else if(strncmp(b64_md, conf_md, b64_len) != 0)
+ if(!pCallback->is_dev_pool())
+ printer::inst()->print_msg(L1, "TLS fingerprint [%s] %.*s", pCallback->get_pool_addr(), (int)b64_len, b64_md);
+ }
+ else if(strncmp(b64_md, conf_md, b64_len) != 0)
+ {
+ if(!pCallback->is_dev_pool())
{
- printer::inst()->print_msg(L0, "FINGERPRINT FAILED CHECK: %.*s was given, %s was configured",
- (int)b64_len, b64_md, conf_md);
-
- pCallback->set_socket_error("FINGERPRINT FAILED CHECK");
- BIO_free_all(b64);
- X509_free(cert);
- return false;
+ printer::inst()->print_msg(L0, "FINGERPRINT FAILED CHECK [%s] %.*s was given, %s was configured",
+ pCallback->get_pool_addr(), (int)b64_len, b64_md, conf_md);
}
+ pCallback->set_socket_error("FINGERPRINT FAILED CHECK");
BIO_free_all(b64);
+ X509_free(cert);
+ return false;
}
+ BIO_free_all(b64);
+
X509_free(cert);
return true;
}
OpenPOWER on IntegriCloud