diff options
Diffstat (limited to 'xmrstak/net')
-rw-r--r-- | xmrstak/net/jpsock.cpp | 120 | ||||
-rw-r--r-- | xmrstak/net/jpsock.hpp | 15 | ||||
-rw-r--r-- | xmrstak/net/msgstruct.hpp | 8 | ||||
-rw-r--r-- | xmrstak/net/socket.cpp | 2 |
4 files changed, 95 insertions, 50 deletions
diff --git a/xmrstak/net/jpsock.cpp b/xmrstak/net/jpsock.cpp index 74d1c26..6c41f2b 100644 --- a/xmrstak/net/jpsock.cpp +++ b/xmrstak/net/jpsock.cpp @@ -43,8 +43,9 @@ struct jpsock::call_rsp uint64_t iCallId; Value* pCallData; std::string sCallErr; + uint64_t iMessageId; - call_rsp(Value* val) : pCallData(val) + call_rsp(Value* val) : pCallData(val), iMessageId(0) { bHaveResponse = false; iCallId = 0; @@ -215,6 +216,7 @@ void jpsock::jpsock_thread() prv->oCallRsp.bHaveResponse = true; prv->oCallRsp.iCallId = 0; prv->oCallRsp.pCallData = nullptr; + prv->oCallRsp.iMessageId = 0; bCallWaiting = true; } mlock.unlock(); @@ -286,6 +288,7 @@ bool jpsock::process_line(char* line, size_t len) prv->jsonDoc.SetNull(); prv->parseAllocator.Clear(); prv->callAllocator.Clear(); + ++iMessageCnt; /*NULL terminate the line instead of '\n', parsing will add some more NULLs*/ line[len-1] = '\0'; @@ -320,7 +323,7 @@ bool jpsock::process_line(char* line, size_t len) return set_socket_error("PARSE error: Protocol error 2"); opq_json_val v(mt); - return process_pool_job(&v); + return process_pool_job(&v, iMessageCnt); } else { @@ -334,7 +337,7 @@ bool jpsock::process_line(char* line, size_t len) mt = GetObjectMember(prv->jsonDoc, "error"); const char* sError = nullptr; - size_t iErrorLn = 0; + size_t iErrorLen = 0; if (mt == nullptr || mt->IsNull()) { /* If there was no error we need a result */ @@ -351,7 +354,7 @@ bool jpsock::process_line(char* line, size_t len) if(msg == nullptr || !msg->IsString()) return set_socket_error("PARSE error: Protocol error 6"); - iErrorLn = msg->GetStringLength(); + iErrorLen = msg->GetStringLength(); sError = msg->GetString(); } @@ -365,11 +368,12 @@ bool jpsock::process_line(char* line, size_t len) prv->oCallRsp.bHaveResponse = true; prv->oCallRsp.iCallId = iCallId; + prv->oCallRsp.iMessageId = iMessageCnt; if(sError != nullptr) { prv->oCallRsp.pCallData = nullptr; - prv->oCallRsp.sCallErr.assign(sError, iErrorLn); + prv->oCallRsp.sCallErr.assign(sError, iErrorLen); call_error = true; } else @@ -382,8 +386,20 @@ bool jpsock::process_line(char* line, size_t len) } } -bool jpsock::process_pool_job(const opq_json_val* params) +bool jpsock::process_pool_job(const opq_json_val* params, const uint64_t messageId) { + std::unique_lock<std::mutex> mlock(job_mutex); + if(messageId < iLastMessageId) + { + /* In the case where the processed job message id is lesser than the last + * processed job message id we skip the processing to avoid mining old jobs + */ + return true; + } + iLastMessageId = messageId; + + mlock.unlock(); + if (!params->val->IsObject()) return set_socket_error("PARSE error: Job error 1"); @@ -399,18 +415,45 @@ bool jpsock::process_pool_job(const opq_json_val* params) return set_socket_error("PARSE error: Job error 2"); } + if(motd != nullptr && motd->IsString() && (motd->GetStringLength() & 0x01) == 0) + { + std::unique_lock<std::mutex> lck(motd_mutex); + if(motd->GetStringLength() > 0) + { + pool_motd.resize(motd->GetStringLength()/2 + 1); + if(!hex2bin(motd->GetString(), motd->GetStringLength(), (unsigned char*)&pool_motd.front())) + pool_motd.clear(); + } + else + pool_motd.clear(); + } + if (jobid->GetStringLength() >= sizeof(pool_job::sJobID)) // Note >= return set_socket_error("PARSE error: Job error 3"); - uint32_t iWorkLn = blob->GetStringLength() / 2; - if (iWorkLn > sizeof(pool_job::bWorkBlob)) - return set_socket_error("PARSE error: Invalid job legth. Are you sure you are mining the correct coin?"); - pool_job oPoolJob; - if (!hex2bin(blob->GetString(), iWorkLn * 2, oPoolJob.bWorkBlob)) + + const uint32_t iWorkLen = blob->GetStringLength() / 2; + oPoolJob.iWorkLen = iWorkLen; + + if (iWorkLen > sizeof(pool_job::bWorkBlob)) + return set_socket_error("PARSE error: Invalid job length. Are you sure you are mining the correct coin?"); + + if (!hex2bin(blob->GetString(), iWorkLen * 2, oPoolJob.bWorkBlob)) return set_socket_error("PARSE error: Job error 4"); - oPoolJob.iWorkLen = iWorkLn; + // lock reading of oCurrentJob + std::unique_lock<std::mutex> jobIdLock(job_mutex); + // compare possible non equal length job id's + if(iWorkLen == oCurrentJob.iWorkLen && + memcmp(oPoolJob.bWorkBlob, oCurrentJob.bWorkBlob, iWorkLen) == 0 && + strcmp(jobid->GetString(), oCurrentJob.sJobID) == 0 + ) + { + return set_socket_error("Duplicate equal job detected! Please contact your pool admin."); + } + jobIdLock.unlock(); + memset(oPoolJob.sJobID, 0, sizeof(pool_job::sJobID)); memcpy(oPoolJob.sJobID, jobid->GetString(), jobid->GetStringLength()); //Bounds checking at proto error 3 @@ -423,7 +466,7 @@ bool jpsock::process_pool_job(const opq_json_val* params) if(!hex2bin(sTempStr, 8, (unsigned char*)&iTempInt) || iTempInt == 0) return set_socket_error("PARSE error: Invalid target"); - + oPoolJob.iTarget = t32_to_t64(iTempInt); } else if(target_slen <= 16) @@ -437,25 +480,14 @@ bool jpsock::process_pool_job(const opq_json_val* params) else return set_socket_error("PARSE error: Job error 5"); - if(motd != nullptr && motd->IsString() && (motd->GetStringLength() & 0x01) == 0) - { - std::unique_lock<std::mutex> lck(motd_mutex); - if(motd->GetStringLength() > 0) - { - pool_motd.resize(motd->GetStringLength()/2 + 1); - if(!hex2bin(motd->GetString(), motd->GetStringLength(), (unsigned char*)&pool_motd.front())) - pool_motd.clear(); - } - else - pool_motd.clear(); - } - iJobDiff = t64_to_diff(oPoolJob.iTarget); - executor::inst()->push_event(ex_event(oPoolJob, pool_id)); - std::unique_lock<std::mutex> lck(job_mutex); oCurrentJob = oPoolJob; + lck.unlock(); + // send event after current job data are updated + executor::inst()->push_event(ex_event(oPoolJob, pool_id)); + return true; } @@ -498,7 +530,7 @@ void jpsock::disconnect(bool quiet) quiet_close = false; } -bool jpsock::cmd_ret_wait(const char* sPacket, opq_json_val& poResult) +bool jpsock::cmd_ret_wait(const char* sPacket, opq_json_val& poResult, uint64_t& messageId) { //printf("SEND: %s\n", sPacket); @@ -538,8 +570,10 @@ bool jpsock::cmd_ret_wait(const char* sPacket, opq_json_val& poResult) } if(bSuccess) + { poResult.val = &prv->oCallValue; - + messageId = prv->oCallRsp.iMessageId; + } return bSuccess; } @@ -551,9 +585,10 @@ bool jpsock::cmd_login() usr_login.c_str(), usr_pass.c_str(), usr_rigid.c_str(), get_version_str().c_str()); opq_json_val oResult(nullptr); + uint64_t messageId = 0; /*Normal error conditions (failed login etc..) will end here*/ - if (!cmd_ret_wait(cmd_buffer, oResult)) + if (!cmd_ret_wait(cmd_buffer, oResult, messageId)) return false; if (!oResult.val->IsObject()) @@ -589,7 +624,7 @@ bool jpsock::cmd_login() for(size_t i=0; i < ext->Size(); i++) { const Value& jextname = ext->GetArray()[i]; - + if(!jextname.IsString()) continue; @@ -608,7 +643,7 @@ bool jpsock::cmd_login() } opq_json_val v(job); - if(!process_pool_job(&v)) + if(!process_pool_job(&v, messageId)) { disconnect(); return false; @@ -645,16 +680,22 @@ bool jpsock::cmd_submit(const char* sJobId, uint32_t iNonce, const uint8_t* bRes algo_name = "cryptonight"; break; case cryptonight_lite: - algo_name = "cryptonight-lite"; + algo_name = "cryptonight_lite"; break; case cryptonight_monero: - algo_name = "cryptonight-monerov7"; + algo_name = "cryptonight_v7"; break; case cryptonight_aeon: - algo_name = "cryptonight-aeonv7"; + algo_name = "cryptonight_lite_v7"; + break; + case cryptonight_stellite: + algo_name = "cryptonight_v7_stellite"; + break; + case cryptonight_ipbc: + algo_name = "cryptonight_lite_v7_xor"; break; case cryptonight_heavy: - algo_name = "cryptonight-heavy"; + algo_name = "cryptonight_heavy"; break; default: algo_name = "unknown"; @@ -673,8 +714,9 @@ bool jpsock::cmd_submit(const char* sJobId, uint32_t iNonce, const uint8_t* bRes snprintf(cmd_buffer, sizeof(cmd_buffer), "{\"method\":\"submit\",\"params\":{\"id\":\"%s\",\"job_id\":\"%s\",\"nonce\":\"%s\",\"result\":\"%s\"%s%s%s},\"id\":1}\n", sMinerId, sJobId, sNonce, sResult, sBackend, sHashcount, sAlgo); + uint64_t messageId = 0; opq_json_val oResult(nullptr); - return cmd_ret_wait(cmd_buffer, oResult); + return cmd_ret_wait(cmd_buffer, oResult, messageId); } void jpsock::save_nonce(uint32_t nonce) @@ -696,7 +738,7 @@ bool jpsock::get_current_job(pool_job& job) bool jpsock::get_pool_motd(std::string& strin) { - if(!ext_motd) + if(!ext_motd) return false; std::unique_lock<std::mutex> lck(motd_mutex); diff --git a/xmrstak/net/jpsock.hpp b/xmrstak/net/jpsock.hpp index 2ddeeee..ad34f6c 100644 --- a/xmrstak/net/jpsock.hpp +++ b/xmrstak/net/jpsock.hpp @@ -15,7 +15,7 @@ - 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 + (can be from read-only mem), we pass them in an executor message once the recv thread expires. - Call error This error happens when the "server says no". Usually because the job was @@ -40,9 +40,9 @@ public: 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; + inline double get_pool_weight(bool gross_weight) + { + double ret = pool_weight; if(gross_weight && bRunning) ret += 10.0; if(gross_weight && bLoggedIn) @@ -124,8 +124,8 @@ private: 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); + bool process_pool_job(const opq_json_val* params, const uint64_t messageId); + bool cmd_ret_wait(const char* sPacket, opq_json_val& poResult, uint64_t& messageId); char sMinerId[64]; std::atomic<uint64_t> iJobDiff; @@ -142,5 +142,8 @@ private: opaque_private* prv; base_socket* sck; + + uint64_t iMessageCnt = 0; + uint64_t iLastMessageId = 0; }; diff --git a/xmrstak/net/msgstruct.hpp b/xmrstak/net/msgstruct.hpp index e401f59..20092fe 100644 --- a/xmrstak/net/msgstruct.hpp +++ b/xmrstak/net/msgstruct.hpp @@ -5,7 +5,7 @@ #include <assert.h> // Structures that we use to pass info between threads constructors are here just to make -// the stack allocation take up less space, heap is a shared resouce that needs locks too of course +// the stack allocation take up less space, heap is a shared resource that needs locks too of course struct pool_job { @@ -72,15 +72,15 @@ struct gpu_res_err }; enum ex_event_name { EV_INVALID_VAL, EV_SOCK_READY, EV_SOCK_ERROR, EV_GPU_RES_ERROR, - 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_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 =). Ghosts of endless heap allocations have finally been exorcised. Thanks to the nifty magic of move semantics, string will only be allocated - once on the heap. Considering that it makes a jorney across stack, + once on the heap. Considering that it makes a journey across stack, heap alloced queue, to another stack before being finally processed I think it is kind of nifty, don't you? Also note that for non-arg events we only copy two qwords diff --git a/xmrstak/net/socket.cpp b/xmrstak/net/socket.cpp index 9bc608f..6fcb454 100644 --- a/xmrstak/net/socket.cpp +++ b/xmrstak/net/socket.cpp @@ -339,7 +339,7 @@ bool tls_socket::connect() { if(!pCallback->is_dev_pool()) { - printer::inst()->print_msg(L0, "FINGERPRINT FAILED CHECK [%s] %.*s was given, %s was configured", + 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); } |