diff --git a/src/api/ApiState.cpp b/src/api/ApiState.cpp index 66af86bfb..e05afb534 100644 --- a/src/api/ApiState.cpp +++ b/src/api/ApiState.cpp @@ -141,8 +141,14 @@ void ApiState::genId() for (int i = 0; i < count; i++) { if (!interfaces[i].is_internal && interfaces[i].address.address4.sin_family == AF_INET) { uint8_t hash[200]; + const size_t addrSize = sizeof(interfaces[i].phys_addr); + const size_t inSize = strlen(APP_KIND) + addrSize; - keccak(reinterpret_cast(interfaces[i].phys_addr), static_cast(sizeof(interfaces[i].phys_addr)), hash, sizeof(hash)); + uint8_t *input = new uint8_t[inSize](); + memcpy(input, interfaces[i].phys_addr, addrSize); + memcpy(input + addrSize, APP_KIND, strlen(APP_KIND)); + + keccak(input, static_cast(inSize), hash, sizeof(hash)); Job::toHex(hash, 8, m_id); break; } @@ -156,7 +162,12 @@ void ApiState::getConnection(json_t *reply) const { json_t *connection = json_object(); - json_object_set(reply, "connection", connection); + json_object_set(reply, "connection", connection); + json_object_set(connection, "pool", json_string(m_network.pool)); + json_object_set(connection, "uptime", json_integer(m_network.connectionTime())); + json_object_set(connection, "ping", json_integer(m_network.latency())); + json_object_set(connection, "failures", json_integer(m_network.failures)); + json_object_set(connection, "error_log", json_array()); } @@ -220,6 +231,7 @@ void ApiState::getResults(json_t *reply) const json_object_set(results, "diff_current", json_integer(m_network.diff)); json_object_set(results, "shares_good", json_integer(m_network.accepted)); json_object_set(results, "shares_total", json_integer(m_network.accepted + m_network.rejected)); + json_object_set(results, "avg_time", json_integer(m_network.avgTime())); json_object_set(results, "hashes_total", json_integer(m_network.total)); json_object_set(results, "best", best); json_object_set(results, "error_log", json_array()); diff --git a/src/api/NetworkState.cpp b/src/api/NetworkState.cpp index 08c64c219..2222b475a 100644 --- a/src/api/NetworkState.cpp +++ b/src/api/NetworkState.cpp @@ -23,12 +23,56 @@ #include +#include + #include "api/NetworkState.h" #include "net/SubmitResult.h" +NetworkState::NetworkState() : + diff(0), + accepted(0), + failures(0), + rejected(0), + total(0), + m_active(false) +{ + memset(pool, 0, sizeof(pool)); +} + + +int NetworkState::connectionTime() const +{ + return m_active ? ((uv_now(uv_default_loop()) - m_connectionTime) / 1000) : 0; +} + + +uint32_t NetworkState::avgTime() const +{ + if (m_latency.empty()) { + return 0; + } + + return (uint32_t) connectionTime() / m_latency.size(); +} + + +uint32_t NetworkState::latency() const +{ + const size_t calls = m_latency.size(); + if (calls == 0) { + return 0; + } + + auto v = m_latency; + std::nth_element(v.begin(), v.begin() + calls / 2, v.end()); + + return v[calls / 2]; +} + + void NetworkState::add(const SubmitResult &result, const char *error) { if (error) { @@ -44,4 +88,25 @@ void NetworkState::add(const SubmitResult &result, const char *error) topDiff[ln] = result.actualDiff; std::sort(topDiff.rbegin(), topDiff.rend()); } + + m_latency.push_back(result.elapsed > 0xFFFF ? 0xFFFF : (uint16_t) result.elapsed); +} + + +void NetworkState::setPool(const char *host, int port, const char *ip) +{ + snprintf(pool, sizeof(pool) - 1, "%s:%d", host, port); + + m_active = true; + m_connectionTime = uv_now(uv_default_loop()); +} + + +void NetworkState::stop() +{ + m_active = false; + diff = 0; + + failures++; + m_latency.clear(); } diff --git a/src/api/NetworkState.h b/src/api/NetworkState.h index 6832f5343..d09980741 100644 --- a/src/api/NetworkState.h +++ b/src/api/NetworkState.h @@ -25,8 +25,8 @@ #define __NETWORKSTATE_H__ -#include #include +#include class SubmitResult; @@ -35,20 +35,27 @@ class SubmitResult; class NetworkState { public: - inline NetworkState() : - diff(0), - accepted(0), - rejected(0), - total(0) - {} + NetworkState(); + int connectionTime() const; + uint32_t avgTime() const; + uint32_t latency() const; void add(const SubmitResult &result, const char *error); + void setPool(const char *host, int port, const char *ip); + void stop(); + char pool[256]; std::array topDiff { { } }; uint32_t diff; uint64_t accepted; + uint64_t failures; uint64_t rejected; uint64_t total; + +private: + bool m_active; + std::vector m_latency; + uint64_t m_connectionTime; }; #endif /* __NETWORKSTATE_H__ */ diff --git a/src/net/Network.cpp b/src/net/Network.cpp index 840a77f80..23b24a046 100644 --- a/src/net/Network.cpp +++ b/src/net/Network.cpp @@ -100,6 +100,8 @@ void Network::onActive(Client *client) return; } + m_state.setPool(client->host(), client->port(), client->ip()); + LOG_INFO(m_options->colors() ? "\x1B[01;37muse pool \x1B[01;36m%s:%d \x1B[01;30m%s" : "use pool %s:%d %s", client->host(), client->port(), client->ip()); } @@ -134,6 +136,7 @@ void Network::onPause(IStrategy *strategy) if (!m_strategy->isActive()) { LOG_ERR("no active pools, stop mining"); + m_state.stop(); return Workers::pause(); } }