A lite-wallet-only "Network" tab (full-node keeps the Peers tab; exactly one shows per variant) to manage lightwalletd servers, replacing the basic selector that was in Settings. - Card list of servers with per-server latency + status dot, DNS host + resolved IP, and an Official/Custom pill. Official DragonX servers get a glowing outline. - Pick a server (Sticky) by clicking its card, or toggle "use a random server" (Random mode); selection applies immediately (App::rebuildLiteWallet(force=true) tears down + rebuilds the controller against the new server and resyncs — its dtor detaches the uninterruptible sync thread, so this doesn't block). - Add custom servers; hide/unhide servers (persisted set, revealed by a "Show hidden" toggle). - Latency/IP come from a new background probe (util/LiteServerProbe): libcurl CONNECT_ONLY does the TCP+TLS handshake (works for gRPC lightwalletd, no HTTP response needed), recording APPCONNECT_TIME as latency and CURLINFO_PRIMARY_IP. Auto-runs on tab open + a Refresh button. Wiring: WalletUiSurface::LiteNetwork (gated !fullNodePagesAvailable) + NavPage::LiteNetwork in the sidebar + app.cpp dispatch; settings gains a hidden-servers set; isOfficialLiteServer() added to lite_connection_service. The Settings page lite-server selector + its plumbing are removed (single source of truth = the tab). Reuses the existing server model (LiteServerPreference, Sticky/Random, selectLiteServer) and UI primitives (DrawGlassPanel, ThemeEffects glow, peers-tab ping-dot idiom). Unit-tested (liteServerHost, isOfficialLiteServer) + an env-gated live probe (verified vs lite.dragonx.is: online, latency, IP). Both variants + lite-backend build; suite passes; hygiene clean; GUI smoke-launched without crash. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
64 lines
2.2 KiB
C++
64 lines
2.2 KiB
C++
// DragonX Wallet - ImGui Edition
|
|
// Copyright 2024-2026 The Hush Developers
|
|
// Released under the GPLv3
|
|
//
|
|
// LiteServerProbe — background latency/IP probe for lite (lightwalletd) servers.
|
|
//
|
|
// The lite backend only exposes a yes/no checkServerOnline, so the Network tab measures latency
|
|
// itself: for each server URL, a libcurl CONNECT_ONLY request does the TCP+TLS handshake (which
|
|
// works for gRPC/HTTP-2 lightwalletd endpoints without needing an HTTP response) and records the
|
|
// handshake time as latency plus the resolved IP. Runs on a background thread; results are read
|
|
// thread-safely from the UI thread and re-run on demand (Refresh).
|
|
|
|
#pragma once
|
|
|
|
#include <atomic>
|
|
#include <map>
|
|
#include <mutex>
|
|
#include <string>
|
|
#include <thread>
|
|
#include <vector>
|
|
|
|
namespace dragonx {
|
|
namespace util {
|
|
|
|
struct LiteServerProbeResult {
|
|
bool probed = false; // a probe has completed for this URL
|
|
bool online = false; // the TCP+TLS handshake succeeded
|
|
int latencyMs = 0; // handshake latency (ms); valid when online
|
|
std::string ip; // resolved primary IP (CURLINFO_PRIMARY_IP)
|
|
};
|
|
|
|
// Pure helper: the host[:port] authority of a URL (scheme + path stripped), for display.
|
|
// "https://lite.dragonx.is:443/x" -> "lite.dragonx.is:443"; "" on a malformed input.
|
|
std::string liteServerHost(const std::string& url);
|
|
|
|
class LiteServerProbe {
|
|
public:
|
|
LiteServerProbe() = default;
|
|
~LiteServerProbe();
|
|
LiteServerProbe(const LiteServerProbe&) = delete;
|
|
LiteServerProbe& operator=(const LiteServerProbe&) = delete;
|
|
|
|
// Probe each URL on a background thread (replacing any in-flight probe). Results stream in as
|
|
// each server completes; poll results() each frame.
|
|
void start(std::vector<std::string> urls);
|
|
|
|
// Snapshot of results so far, keyed by URL.
|
|
std::map<std::string, LiteServerProbeResult> results() const;
|
|
|
|
bool busy() const { return busy_.load(); }
|
|
|
|
private:
|
|
void run(std::vector<std::string> urls);
|
|
|
|
mutable std::mutex mutex_;
|
|
std::map<std::string, LiteServerProbeResult> results_;
|
|
std::atomic<bool> busy_{false};
|
|
std::atomic<bool> cancel_{false};
|
|
std::thread worker_;
|
|
};
|
|
|
|
} // namespace util
|
|
} // namespace dragonx
|