feat: Update trackers with current torrent state#180
Conversation
`TorrentActor::start`
WalkthroughAdds tracker coordination and bookkeeping to TorrentActor: new tracker message/update types, async helpers to broadcast updates/announces, total-bytes calculation and piece-path resolution, and sequences Started/Announce/Empty/Completed events during start and piece-completion flows. Changes
Sequence Diagram(s)sequenceDiagram
participant TA as TorrentActor
participant Trackers as Tracker Actors
participant Disk as Disk Storage
participant Peers as Peer Actors
rect rgba(200,230,255,0.3)
TA->>Trackers: update_trackers(TrackerUpdate::Event(Event::Started))
TA->>Trackers: broadcast_to_trackers(TrackerMessage::Announce)
TA->>Trackers: update_trackers(TrackerUpdate::Event(Event::Empty))
end
Peers->>TA: IncomingPiece(blocks)
TA->>Disk: write blocks
TA->>Peers: broadcast Have
alt final piece completed
TA->>TA: total_bytes_downloaded()
TA->>Trackers: update_trackers(TrackerUpdate::Left(0))
TA->>Trackers: update_trackers(TrackerUpdate::Event(Event::Completed))
TA->>Trackers: broadcast_to_trackers(TrackerMessage::Announce)
TA->>TA: set state = Seeding
else regular piece completed
TA->>TA: compute remaining bytes
TA->>Trackers: update_trackers(TrackerUpdate::Left(remaining))
end
Estimated code review effort🎯 4 (Complex) | ⏱️ ~45 minutes Areas requiring extra attention:
Possibly related PRs
Suggested reviewers
Pre-merge checks and finishing touches✅ Passed checks (3 passed)
✨ Finishing touches
🧪 Generate unit tests (beta)
📜 Recent review detailsConfiguration used: CodeRabbit UI Review profile: CHILL Plan: Pro 📒 Files selected for processing (2)
🧰 Additional context used🧠 Learnings (3)📚 Learning: 2025-08-18T18:25:24.831ZApplied to files:
📚 Learning: 2025-08-28T06:33:16.003ZApplied to files:
📚 Learning: 2025-10-14T04:03:55.852ZApplied to files:
🧬 Code graph analysis (2)crates/libtortillas/src/tracker/mod.rs (2)
crates/libtortillas/src/torrent/actor.rs (2)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
🔇 Additional comments (3)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 2
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (4)
crates/libtortillas/src/torrent/actor.rs(5 hunks)crates/libtortillas/src/torrent/messages.rs(3 hunks)crates/libtortillas/src/tracker/http.rs(1 hunks)crates/libtortillas/src/tracker/mod.rs(4 hunks)
🧰 Additional context used
🧠 Learnings (4)
📚 Learning: 2025-08-18T18:25:24.831Z
Learnt from: kurealnum
Repo: artrixdotdev/tortillas PR: 99
File: crates/libtortillas/src/engine/mod.rs:153-155
Timestamp: 2025-08-18T18:25:24.831Z
Learning: The peer stream handling logic in the Engine's EngineMessage::IncomingPeer handler in crates/libtortillas/src/engine/mod.rs is temporary and planned to be migrated to separate code in the future, so extensive refactoring may not be worthwhile in this location.
Applied to files:
crates/libtortillas/src/torrent/messages.rscrates/libtortillas/src/tracker/mod.rs
📚 Learning: 2025-10-14T04:03:55.852Z
Learnt from: artrixdotdev
Repo: artrixdotdev/tortillas PR: 160
File: crates/libtortillas/src/peer/actor.rs:76-76
Timestamp: 2025-10-14T04:03:55.852Z
Learning: In BitTorrent P2P networking (libtortillas crate), peer network errors (I/O errors, connection resets, unexpected EOF) occur at very high frequency as normal protocol behavior. These should be logged at trace level to avoid excessive log volume, not at debug/warn/error levels.
Applied to files:
crates/libtortillas/src/torrent/messages.rscrates/libtortillas/src/torrent/actor.rs
📚 Learning: 2025-08-28T06:33:16.003Z
Learnt from: artrixdotdev
Repo: artrixdotdev/tortillas PR: 125
File: crates/libtortillas/src/torrent/actor.rs:151-171
Timestamp: 2025-08-28T06:33:16.003Z
Learning: In the torrent actor's append_peer function in crates/libtortillas/src/torrent/actor.rs, when a PeerStream is provided, the peer has already been pre-handshaked by the engine. The engine handles the initial handshake validation, info hash verification, and peer ID extraction before passing the stream to the torrent actor. Therefore, the peer.id should already be populated when a stream is provided.
Applied to files:
crates/libtortillas/src/torrent/messages.rscrates/libtortillas/src/torrent/actor.rs
📚 Learning: 2025-08-28T06:30:48.942Z
Learnt from: artrixdotdev
Repo: artrixdotdev/tortillas PR: 125
File: crates/libtortillas/src/torrent/actor.rs:136-139
Timestamp: 2025-08-28T06:30:48.942Z
Learning: In the libtortillas crate, BitVec<AtomicU8> is used for thread-safe bitfield operations in TorrentActor, providing atomic access to individual bits without requiring additional synchronization like RwLock.
Applied to files:
crates/libtortillas/src/torrent/actor.rs
🧬 Code graph analysis (3)
crates/libtortillas/src/torrent/messages.rs (2)
crates/libtortillas/src/metainfo/file.rs (2)
total_length(144-149)piece_count(140-142)crates/libtortillas/src/torrent/actor.rs (1)
info_dict(205-214)
crates/libtortillas/src/torrent/actor.rs (1)
crates/libtortillas/src/torrent/piece_manager.rs (2)
info(17-17)info(147-149)
crates/libtortillas/src/tracker/mod.rs (2)
crates/libtortillas/src/tracker/http.rs (4)
interval(175-177)interval(270-272)new(97-123)new(144-169)crates/libtortillas/src/tracker/udp.rs (4)
interval(595-597)interval(929-931)new(359-371)new(544-580)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
- GitHub Check: build_and_test
There was a problem hiding this comment.
Actionable comments posted: 1
♻️ Duplicate comments (1)
crates/libtortillas/src/torrent/actor.rs (1)
322-335: Still overcounting partial pieces (risking underflow).
Line 328 multipliescount_ones()by the uniformpiece_lengthand Line 331 assumes every block is a fullBLOCK_SIZE. The final piece is usually shorter and the last block of any piece may be partial, so we overcount bytes. WhenTorrentMessage::IncomingPiecesubtracts that figure frominfo.total_length()the subtraction can panic in debug or wrap in release, which makes us send bogusleftvalues to trackers. Please compute actual per-piece and per-block sizes—derive the last-piece length frominfo.total_length(), iterate the block bitsets by index, clamp each block withmin(BLOCK_SIZE, remaining_bytes), and cap the aggregate at the torrent length—before returning.- let completed_pieces = self.bitfield.count_ones(); - let piece_size = self.info_dict().map(|info| info.piece_length)? as usize; - - let mut total_bytes = completed_pieces * piece_size; - - for block in self.block_map.iter() { - total_bytes += BLOCK_SIZE * block.count_ones(); - } - - Some(total_bytes) + let info = self.info_dict()?; + let piece_len = usize::try_from(info.piece_length).ok()?; + let total_len = info.total_length() as usize; + let piece_count = info.piece_count(); + if piece_len == 0 || piece_count == 0 { + return Some(0); + } + let last_piece_len = { + let rem = total_len % piece_len; + if rem == 0 { piece_len } else { rem } + }; + + let mut total_bytes = 0usize; + for idx in self.bitfield.as_bitslice().iter_ones() { + let piece_bytes = if idx + 1 == piece_count { + last_piece_len + } else { + piece_len + }; + total_bytes = total_bytes.saturating_add(piece_bytes); + } + for entry in self.block_map.iter() { + let piece_idx = *entry.key(); + let piece_bytes = if piece_idx + 1 == piece_count { + last_piece_len + } else { + piece_len + }; + for block_idx in entry.value().as_bitslice().iter_ones() { + let offset = block_idx * BLOCK_SIZE; + if offset >= piece_bytes { + continue; + } + let remaining = piece_bytes - offset; + total_bytes = + total_bytes.saturating_add(remaining.min(BLOCK_SIZE)); + } + } + Some(total_bytes.min(total_len))
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (1)
crates/libtortillas/src/torrent/actor.rs(4 hunks)
🧰 Additional context used
🧠 Learnings (2)
📚 Learning: 2025-08-28T06:33:16.003Z
Learnt from: artrixdotdev
Repo: artrixdotdev/tortillas PR: 125
File: crates/libtortillas/src/torrent/actor.rs:151-171
Timestamp: 2025-08-28T06:33:16.003Z
Learning: In the torrent actor's append_peer function in crates/libtortillas/src/torrent/actor.rs, when a PeerStream is provided, the peer has already been pre-handshaked by the engine. The engine handles the initial handshake validation, info hash verification, and peer ID extraction before passing the stream to the torrent actor. Therefore, the peer.id should already be populated when a stream is provided.
Applied to files:
crates/libtortillas/src/torrent/actor.rs
📚 Learning: 2025-10-14T04:03:55.852Z
Learnt from: artrixdotdev
Repo: artrixdotdev/tortillas PR: 160
File: crates/libtortillas/src/peer/actor.rs:76-76
Timestamp: 2025-10-14T04:03:55.852Z
Learning: In BitTorrent P2P networking (libtortillas crate), peer network errors (I/O errors, connection resets, unexpected EOF) occur at very high frequency as normal protocol behavior. These should be logged at trace level to avoid excessive log volume, not at debug/warn/error levels.
Applied to files:
crates/libtortillas/src/torrent/actor.rs
🧬 Code graph analysis (1)
crates/libtortillas/src/torrent/actor.rs (2)
crates/libtortillas/src/torrent/piece_manager.rs (2)
info(17-17)info(147-149)crates/libtortillas/src/tracker/mod.rs (1)
uri(121-127)
#174
#175
Summary by CodeRabbit
New Features
Refactor