Network code cleanup

This commit is contained in:
XMRig 2020-05-30 03:06:19 +07:00
parent 6370d71ebe
commit 95ef32c913
No known key found for this signature in database
GPG key ID: 446A53638BE94409
2 changed files with 109 additions and 85 deletions

View file

@ -51,8 +51,9 @@ int64_t xmrig::EthStratumClient::submit(const JobResult& result)
# endif # endif
if (result.diff == 0) { if (result.diff == 0) {
LOG_ERR("result.diff is 0"); LOG_ERR("%s " RED("result.diff is 0"), tag());
disconnect(); close();
return -1; return -1;
} }
@ -116,13 +117,13 @@ void xmrig::EthStratumClient::onClose()
} }
bool xmrig::EthStratumClient::handleResponse(int64_t id, const rapidjson::Value& result, const rapidjson::Value& error) bool xmrig::EthStratumClient::handleResponse(int64_t id, const rapidjson::Value &result, const rapidjson::Value &error)
{ {
auto it = m_callbacks.find(id); auto it = m_callbacks.find(id);
if (it != m_callbacks.end()) { if (it != m_callbacks.end()) {
const uint64_t elapsed = Chrono::steadyMSecs() - it->second.ts; const uint64_t elapsed = Chrono::steadyMSecs() - it->second.ts;
if (error.IsObject()) { if (error.IsArray() || error.IsObject() || error.IsString()) {
it->second.callback(error, false, elapsed); it->second.callback(error, false, elapsed);
} }
else { else {
@ -134,15 +135,7 @@ bool xmrig::EthStratumClient::handleResponse(int64_t id, const rapidjson::Value&
return true; return true;
} }
const char* err = nullptr; handleSubmitResponse(id, errorMessage(error));
if (error.IsArray() && error.GetArray().Size() > 1) {
auto& value = error.GetArray()[1];
if (value.IsString()) {
err = value.GetString();
}
}
handleSubmitResponse(id, err);
return false; return false;
} }
@ -155,14 +148,14 @@ void xmrig::EthStratumClient::parseNotification(const char *method, const rapidj
if (strcmp(method, "mining.notify") == 0) { if (strcmp(method, "mining.notify") == 0) {
if (!params.IsArray()) { if (!params.IsArray()) {
LOG_ERR("Invalid mining.notify notification: params is not an array"); LOG_ERR("%s " RED("invalid mining.notify notification: params is not an array"), tag());
return; return;
} }
auto arr = params.GetArray(); auto arr = params.GetArray();
if (arr.Size() < 6) { if (arr.Size() < 6) {
LOG_ERR("Invalid mining.notify notification: params array has wrong size"); LOG_ERR("%s " RED("invalid mining.notify notification: params array has wrong size"), tag());
return; return;
} }
@ -205,29 +198,87 @@ void xmrig::EthStratumClient::parseNotification(const char *method, const rapidj
if (!isQuiet()) { if (!isQuiet()) {
LOG_ERR("[%s] incompatible/disabled algorithm \"%s\" detected, reconnect", url(), algo.shortName()); LOG_ERR("[%s] incompatible/disabled algorithm \"%s\" detected, reconnect", url(), algo.shortName());
} }
disconnect(); close();
return; return;
} }
if (m_job != job) { if (m_job != job) {
m_job = std::move(job); m_job = std::move(job);
// Workaround for nanopool.org, mining.notify received before mining.authorize response.
if (!m_authorized) {
m_authorized = true;
m_listener->onLoginSuccess(this);
}
m_listener->onJobReceived(this, m_job, params); m_listener->onJobReceived(this, m_job, params);
} }
else { else {
if (!isQuiet()) { if (!isQuiet()) {
LOG_WARN("%s " YELLOW("duplicate job received, reconnect"), tag()); LOG_WARN("%s " YELLOW("duplicate job received, reconnect"), tag());
} }
disconnect(); close();
} }
} }
} }
bool xmrig::EthStratumClient::disconnect() const char *xmrig::EthStratumClient::errorMessage(const rapidjson::Value &error) const
{ {
m_authorized = false; if (error.IsArray() && error.GetArray().Size() > 1) {
auto &value = error.GetArray()[1];
if (value.IsString()) {
return value.GetString();
}
}
if (error.IsString()) {
return error.GetString();
}
return nullptr;
}
uint64_t xmrig::EthStratumClient::extraNonce(const rapidjson::Value &result) const
{
if (!result.IsArray()) {
throw std::runtime_error("invalid mining.subscribe response: result is not an array");
}
if (result.GetArray().Size() <= 1) {
throw std::runtime_error("invalid mining.subscribe response: result array is too short");
}
auto &extra_nonce = result.GetArray()[1];
if (!extra_nonce.IsString()) {
throw std::runtime_error("invalid mining.subscribe response: extra nonce is not a string");
}
const char* s = extra_nonce.GetString();
size_t len = extra_nonce.GetStringLength();
// Skip "0x"
if ((len >= 2) && (s[0] == '0') && (s[1] == 'x')) {
s += 2;
len -= 2;
}
if (len & 1) {
throw std::runtime_error("invalid mining.subscribe response: extra nonce has an odd number of hex chars");
}
if (len > 8) {
throw std::runtime_error("Invalid mining.subscribe response: extra nonce is too long");
}
std::string extra_nonce_str(s);
extra_nonce_str.resize(16, '0');
LOG_DEBUG("[%s] extra nonce set to %s", url(), s);
return std::stoull(extra_nonce_str, nullptr, 16);
return Client::disconnect();
} }
@ -270,79 +321,52 @@ void xmrig::EthStratumClient::authorize()
} }
void xmrig::EthStratumClient::onAuthorizeResponse(const rapidjson::Value& result, bool success, uint64_t elapsed) void xmrig::EthStratumClient::onAuthorizeResponse(const rapidjson::Value &result, bool success, uint64_t elapsed)
{ {
if (!success) { try {
LOG_ERR("mining.authorize call failed"); if (!success) {
disconnect(); const auto message = errorMessage(result);
if (message) {
throw std::runtime_error(message);
}
throw std::runtime_error("mining.authorize call failed");
}
if (!result.IsBool()) {
throw std::runtime_error("invalid mining.authorize response: result is not a boolean");
}
if (!result.GetBool()) {
throw std::runtime_error("login failed");
}
} catch (const std::exception &ex) {
LOG_ERR("%s " RED_BOLD("%s"), tag(), ex.what());
close();
return; return;
} }
if (!result.IsBool()) { LOG_DEBUG("[%s] login succeeded", url());
LOG_ERR("Invalid mining.authorize response: result is not a boolean");
disconnect(); if (!m_authorized) {
return; m_authorized = true;
m_listener->onLoginSuccess(this);
} }
if (!result.GetBool()) {
LOG_ERR("Login failed");
disconnect();
return;
}
LOG_DEBUG("Login succeeded");
m_authorized = true;
m_listener->onLoginSuccess(this);
} }
void xmrig::EthStratumClient::onSubscribeResponse(const rapidjson::Value& result, bool success, uint64_t elapsed) void xmrig::EthStratumClient::onSubscribeResponse(const rapidjson::Value &result, bool success, uint64_t elapsed)
{ {
if (!success) { if (!success) {
return; return;
} }
if (!result.IsArray()) { try {
LOG_ERR("Invalid mining.subscribe response: result is not an array"); m_extraNonce = extraNonce(result);
return; } catch (const std::exception &ex) {
LOG_ERR("%s " RED("%s"), tag(), ex.what());
} }
if (result.GetArray().Size() <= 1) {
LOG_ERR("Invalid mining.subscribe response: result array is too short");
return;
}
auto& extra_nonce = result.GetArray()[1];
if (!extra_nonce.IsString()) {
LOG_ERR("Invalid mining.subscribe response: extra nonce is not a string");
return;
}
const char* s = extra_nonce.GetString();
size_t len = extra_nonce.GetStringLength();
// Skip "0x"
if ((len >= 2) && (s[0] == '0') && (s[1] == 'x')) {
s += 2;
len -= 2;
}
if (len & 1) {
LOG_ERR("Invalid mining.subscribe response: extra nonce has an odd number of hex chars");
return;
}
if (len > 8) {
LOG_ERR("Invalid mining.subscribe response: extra nonce is too long");
return;
}
std::string extra_nonce_str(s);
extra_nonce_str.resize(16, '0');
m_extraNonce = std::stoull(extra_nonce_str, nullptr, 16);
LOG_DEBUG("Extra nonce set to %s", s);
} }

View file

@ -39,20 +39,20 @@ public:
protected: protected:
protected: protected:
int64_t submit(const JobResult& result) override; int64_t submit(const JobResult &result) override;
void login() override; void login() override;
void onClose() override; void onClose() override;
bool handleResponse(int64_t id, const rapidjson::Value& result, const rapidjson::Value& error) override; bool handleResponse(int64_t id, const rapidjson::Value &result, const rapidjson::Value &error) override;
void parseNotification(const char *method, const rapidjson::Value &params, const rapidjson::Value &error) override; void parseNotification(const char *method, const rapidjson::Value &params, const rapidjson::Value &error) override;
bool disconnect() override;
private: private:
const char *errorMessage(const rapidjson::Value &error) const;
uint64_t extraNonce(const rapidjson::Value &result) const;
uint64_t target(const rapidjson::Value &params) const; uint64_t target(const rapidjson::Value &params) const;
void authorize(); void authorize();
void onAuthorizeResponse(const rapidjson::Value& result, bool success, uint64_t elapsed); void onAuthorizeResponse(const rapidjson::Value &result, bool success, uint64_t elapsed);
void onSubscribeResponse(const rapidjson::Value& result, bool success, uint64_t elapsed); void onSubscribeResponse(const rapidjson::Value &result, bool success, uint64_t elapsed);
void setTarget(const rapidjson::Value &params); void setTarget(const rapidjson::Value &params);
void subscribe(); void subscribe();