Skip to content

Commit e4d3670

Browse files
author
Threepwood-7
committed
rest: surface our queue position at each download source (queueRank)
The download session decoded OP_QUEUERANK / OP_QUEUERANKING but only logged it, so the REST source list always showed queueRank=0 -- the UI could not tell you where you sit in each peer's upload queue. Record the rank on the live download source (Ed2kSourceActivity.queue_rank via note_download_source_queue_rank at both decode sites), carry it on Ed2kLiveSource, and overlay it in enrich_sources_with_live. clientSoftware on download sources remains a follow-up (needs the peer HELLO software captured into the source registry).
1 parent 702561d commit e4d3670

3 files changed

Lines changed: 47 additions & 0 deletions

File tree

crates/emulebb-core/src/views.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -315,6 +315,9 @@ pub(crate) fn enrich_sources_with_live(
315315
source.download_speed_ki_bps = live_source.download_speed_bytes_per_sec as f64 / 1024.0;
316316
source.available_parts = live_source.available_parts;
317317
source.part_count = part_count;
318+
if let Some(rank) = live_source.queue_rank {
319+
source.queue_rank = rank;
320+
}
318321
let state = if live_source.transferring {
319322
"downloading"
320323
} else {

crates/emulebb-ed2k/src/ed2k_tcp/download/session.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -851,6 +851,7 @@ pub(in crate::ed2k_tcp) async fn drive_download_session(
851851
(OP_EDONKEYPROT, OP_QUEUERANK) => {
852852
let rank = decode_edonkey_queue_rank_payload(&packet.payload)?;
853853
session_state.queued_until = Some(tokio::time::Instant::now() + QUEUE_RANK_GRACE);
854+
transfer_runtime.note_download_source_queue_rank(file_hash_hex, peer_addr, rank);
854855
dump_ed2k_tcp_download_meta(
855856
peer_addr,
856857
Some(transport.mode),
@@ -861,6 +862,11 @@ pub(in crate::ed2k_tcp) async fn drive_download_session(
861862
(OP_EMULEPROT, OP_QUEUERANKING) => {
862863
let rank = decode_emule_queue_ranking_payload(&packet.payload)?;
863864
session_state.queued_until = Some(tokio::time::Instant::now() + QUEUE_RANK_GRACE);
865+
transfer_runtime.note_download_source_queue_rank(
866+
file_hash_hex,
867+
peer_addr,
868+
u32::from(rank),
869+
);
864870
dump_ed2k_tcp_download_meta(
865871
peer_addr,
866872
Some(transport.mode),

crates/emulebb-ed2k/src/ed2k_transfer/download_activity.rs

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,9 @@ pub(super) struct Ed2kSourceActivity {
8080
/// Per-part availability advertised by the peer (OP_FILESTATUS). `None`
8181
/// until a status frame is seen.
8282
part_bitmap: Option<Vec<bool>>,
83+
/// Our queue position at this peer (OP_QUEUERANK / OP_QUEUERANKING). `None`
84+
/// until the peer sends a ranking.
85+
queue_rank: Option<u32>,
8386
}
8487

8588
/// Snapshot of one live source for the REST transfer-source/detail views.
@@ -91,6 +94,7 @@ pub struct Ed2kLiveSource {
9194
pub download_speed_bytes_per_sec: u64,
9295
pub transferring: bool,
9396
pub available_parts: u32,
97+
pub queue_rank: Option<u32>,
9498
}
9599

96100
impl Ed2kTransferRuntime {
@@ -185,6 +189,7 @@ impl Ed2kTransferRuntime {
185189
last_payload_at: None,
186190
window: DatarateWindow::default(),
187191
part_bitmap: None,
192+
queue_rank: None,
188193
});
189194
entry.endpoint = peer;
190195
if user_hash.is_some() {
@@ -225,6 +230,7 @@ impl Ed2kTransferRuntime {
225230
last_payload_at: None,
226231
window: DatarateWindow::default(),
227232
part_bitmap: None,
233+
queue_rank: None,
228234
});
229235
entry.endpoint = peer;
230236
if user_hash.is_some() {
@@ -237,6 +243,37 @@ impl Ed2kTransferRuntime {
237243
entry.part_bitmap = Some(bitmap);
238244
}
239245

246+
/// Record our queue position at a peer (OP_QUEUERANK / OP_QUEUERANKING) so the
247+
/// REST source list can show it. The session entry usually already exists from
248+
/// a payload/status frame; create a minimal one if the ranking arrives first.
249+
pub(crate) fn note_download_source_queue_rank(
250+
&self,
251+
file_hash: &str,
252+
peer: SocketAddr,
253+
rank: u32,
254+
) {
255+
let now = Instant::now();
256+
let Ok(mut sources) = self.download_sources.lock() else {
257+
return;
258+
};
259+
let peers = sources.entry(file_hash.to_string()).or_default();
260+
evict_stale_sources(peers, now);
261+
let entry = peers
262+
.entry(peer.to_string())
263+
.or_insert_with(|| Ed2kSourceActivity {
264+
endpoint: peer,
265+
user_hash: None,
266+
connect_options: None,
267+
last_seen_at: now,
268+
last_payload_at: None,
269+
window: DatarateWindow::default(),
270+
part_bitmap: None,
271+
queue_rank: None,
272+
});
273+
entry.last_seen_at = now;
274+
entry.queue_rank = Some(rank);
275+
}
276+
240277
/// Drop the live-source registry for a file (e.g. on transfer removal).
241278
pub(crate) fn clear_download_sources(&self, file_hash: &str) {
242279
if let Ok(mut sources) = self.download_sources.lock() {
@@ -274,6 +311,7 @@ impl Ed2kTransferRuntime {
274311
.as_ref()
275312
.map(|bitmap| bitmap.iter().filter(|present| **present).count() as u32)
276313
.unwrap_or(0),
314+
queue_rank: peer.queue_rank,
277315
})
278316
.collect()
279317
}

0 commit comments

Comments
 (0)