engine: add engine_peer_list for per-peer status
Enumerates a torrent's connected peers (ip/port/state/rate/bytes/have) for the UI's peer list — the per-peer detail lost in the engine swap. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
parent
d8208685a2
commit
f85278fcf2
2 changed files with 47 additions and 0 deletions
|
|
@ -139,6 +139,24 @@ uint32_t engine_loop_count(engine *e);
|
||||||
|
|
||||||
void engine_torrent_status(engine *e, uint32_t torrent_id, torrent_status *out);
|
void engine_torrent_status(engine *e, uint32_t torrent_id, torrent_status *out);
|
||||||
|
|
||||||
|
/* One connected peer's live state, for the UI's per-peer list. */
|
||||||
|
typedef struct {
|
||||||
|
char ip[64];
|
||||||
|
uint16_t port;
|
||||||
|
int32_t state; /* peer_state */
|
||||||
|
int32_t unchoked; /* peer has unchoked us */
|
||||||
|
uint64_t bytes_received; /* total payload bytes from this peer */
|
||||||
|
double rate_bps; /* current download rate from this peer */
|
||||||
|
uint32_t have_pieces; /* pieces this peer advertises */
|
||||||
|
uint32_t num_pieces; /* torrent piece count (for progress ratio) */
|
||||||
|
} engine_peer_info;
|
||||||
|
|
||||||
|
/* Fill `out` with up to `max` connected peers (handshake completed) of a
|
||||||
|
* torrent; returns the number written. Best-effort snapshot read on the caller
|
||||||
|
* thread (like engine_torrent_status), so fine for status, not control. */
|
||||||
|
uint32_t engine_peer_list(engine *e, uint32_t torrent_id, engine_peer_info *out,
|
||||||
|
uint32_t max);
|
||||||
|
|
||||||
/* Diagnostic: write a human-readable dump of one torrent's piece-selection and
|
/* Diagnostic: write a human-readable dump of one torrent's piece-selection and
|
||||||
* per-connection state to `out`. Reports, for every still-wanted piece
|
* per-connection state to `out`. Reports, for every still-wanted piece
|
||||||
* (priority > 0), whether a peer has claimed it (requested), how many connected
|
* (priority > 0), whether a peer has claimed it (requested), how many connected
|
||||||
|
|
|
||||||
29
src/engine.c
29
src/engine.c
|
|
@ -461,6 +461,35 @@ void engine_torrent_status(engine *e, uint32_t torrent_id, torrent_status *out)
|
||||||
out->rtt_min_ms = rttmin;
|
out->rtt_min_ms = rttmin;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint32_t engine_peer_list(engine *e, uint32_t torrent_id, engine_peer_info *out,
|
||||||
|
uint32_t max) {
|
||||||
|
if (!e || !out || max == 0) return 0;
|
||||||
|
torrent *t = find_locked(e, torrent_id);
|
||||||
|
if (!t) return 0;
|
||||||
|
loop *lp = t->lp;
|
||||||
|
uint32_t n = 0;
|
||||||
|
for (conn *c = lp->conns; c && n < max; c = c->next) {
|
||||||
|
if (c->tor != t) continue;
|
||||||
|
int st = atomic_load_explicit(&c->astate, memory_order_relaxed);
|
||||||
|
if (st != PEER_STATE_RUNNING && st != PEER_STATE_CHOKED) continue;
|
||||||
|
engine_peer_info *p = &out[n++];
|
||||||
|
snprintf(p->ip, sizeof p->ip, "%s", c->ip);
|
||||||
|
p->port = c->port;
|
||||||
|
p->state = st;
|
||||||
|
p->unchoked = c->unchoked;
|
||||||
|
p->bytes_received =
|
||||||
|
atomic_load_explicit(&c->bytes_received, memory_order_relaxed);
|
||||||
|
p->rate_bps = c->rate_bps;
|
||||||
|
p->num_pieces = t->num_pieces;
|
||||||
|
uint32_t have = 0;
|
||||||
|
if (c->have_bits)
|
||||||
|
for (uint32_t i = 0; i < t->num_pieces; i++)
|
||||||
|
if (have_bit(c->have_bits, i)) have++;
|
||||||
|
p->have_pieces = have;
|
||||||
|
}
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
|
||||||
static const char *peer_state_name(int state) {
|
static const char *peer_state_name(int state) {
|
||||||
switch (state) {
|
switch (state) {
|
||||||
case PEER_STATE_IDLE: return "idle";
|
case PEER_STATE_IDLE: return "idle";
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue