diff --git a/crates/librqbit/src/chunk_tracker.rs b/crates/librqbit/src/chunk_tracker.rs index 7f56b20..e289293 100644 --- a/crates/librqbit/src/chunk_tracker.rs +++ b/crates/librqbit/src/chunk_tracker.rs @@ -1,3 +1,4 @@ +use anyhow::Context; use librqbit_core::lengths::{ChunkInfo, Lengths, ValidPieceIndex}; use peer_binary_protocol::Piece; use tracing::{debug, trace}; @@ -32,25 +33,27 @@ pub struct ChunkTracker { // Needed pieces are the ones we need to download, not necessarily the ones we have. // E.g. we might have more pieces, but the client asks to download only some files // partially. -fn compute_chunk_status(lengths: &Lengths, needed_pieces: &BF) -> BF { +fn compute_chunk_status(lengths: &Lengths, needed_pieces: &BF) -> anyhow::Result { let required_size = lengths.chunk_bitfield_bytes(); let vec = vec![0u8; required_size]; let mut chunk_bf = BF::from_boxed_slice(vec.into_boxed_slice()); + let range = 0..lengths.total_pieces() as usize; for piece_index in needed_pieces - .get(0..lengths.total_pieces() as usize) - .unwrap() + .get(range.clone()) + .with_context(|| format!("error getting range {range:?} from needed_pieces"))? .iter_zeros() { let offset = piece_index * lengths.default_max_chunks_per_piece() as usize; let chunks_per_piece = lengths - .chunks_per_piece(lengths.validate_piece_index(piece_index as u32).unwrap()) + .chunks_per_piece(lengths.try_validate_piece_index(piece_index as u32)?) as usize; + let range = offset..offset + chunks_per_piece; chunk_bf - .get_mut(offset..offset + chunks_per_piece) - .unwrap() + .get_mut(range.clone()) + .with_context(|| format!("error getting range {range:?} from chunk_bf"))? .fill(true); } - chunk_bf + Ok(chunk_bf) } pub enum ChunkMarkingResult { @@ -65,7 +68,7 @@ impl ChunkTracker { have_pieces: BF, lengths: Lengths, total_selected_bytes: u64, - ) -> Self { + ) -> anyhow::Result { // TODO: ideally this needs to be a list based on needed files, e.g. // last needed piece for each file. But let's keep simple for now. @@ -81,14 +84,15 @@ impl ChunkTracker { // E.g. if it's a video file, than the last piece often contains some index, or just // players look into it, and it's better be there. let priority_piece_ids = last_needed_piece_id.into_iter().collect(); - Self { - chunk_status: compute_chunk_status(&lengths, &needed_pieces), + Ok(Self { + chunk_status: compute_chunk_status(&lengths, &needed_pieces) + .context("error computing chunk status")?, needed_pieces, lengths, have: have_pieces, priority_piece_ids, total_selected_bytes, - } + }) } pub fn get_total_selected_bytes(&self) -> u64 { diff --git a/crates/librqbit/src/torrent_state/initializing.rs b/crates/librqbit/src/torrent_state/initializing.rs index 33e97a2..fa02232 100644 --- a/crates/librqbit/src/torrent_state/initializing.rs +++ b/crates/librqbit/src/torrent_state/initializing.rs @@ -127,7 +127,8 @@ impl TorrentStateInitializing { initial_check_results.have_pieces, self.meta.lengths, initial_check_results.total_selected_bytes, - ); + ) + .context("error creating chunk tracker")?; let paused = TorrentStatePaused { info: self.meta.clone(), diff --git a/crates/librqbit_core/src/lengths.rs b/crates/librqbit_core/src/lengths.rs index 7b7fac0..0cb8909 100644 --- a/crates/librqbit_core/src/lengths.rs +++ b/crates/librqbit_core/src/lengths.rs @@ -1,3 +1,5 @@ +use anyhow::Context; + use crate::{constants::CHUNK_SIZE, torrent_metainfo::TorrentMetaV1Info}; const fn is_power_of_two(x: u64) -> bool { @@ -123,6 +125,10 @@ impl Lengths { } Some(ValidPieceIndex(index)) } + pub fn try_validate_piece_index(&self, index: u32) -> anyhow::Result { + self.validate_piece_index(index) + .with_context(|| format!("invalid piece index {index}")) + } pub const fn default_piece_length(&self) -> u32 { self.piece_length } diff --git a/desktop/src-tauri/Cargo.lock b/desktop/src-tauri/Cargo.lock index b9520f9..f2ebb83 100644 --- a/desktop/src-tauri/Cargo.lock +++ b/desktop/src-tauri/Cargo.lock @@ -1842,7 +1842,7 @@ dependencies = [ [[package]] name = "librqbit" -version = "5.5.3" +version = "5.5.4" dependencies = [ "anyhow", "async-stream", @@ -1890,7 +1890,7 @@ dependencies = [ [[package]] name = "librqbit-bencode" -version = "2.2.1" +version = "2.2.2" dependencies = [ "anyhow", "librqbit-buffers", @@ -1901,7 +1901,7 @@ dependencies = [ [[package]] name = "librqbit-buffers" -version = "2.2.1" +version = "3.0.0" dependencies = [ "librqbit-clone-to-owned", "serde", @@ -1913,7 +1913,7 @@ version = "2.2.1" [[package]] name = "librqbit-core" -version = "3.6.1" +version = "3.6.2" dependencies = [ "anyhow", "directories", @@ -1933,7 +1933,7 @@ dependencies = [ [[package]] name = "librqbit-dht" -version = "5.0.1" +version = "5.0.2" dependencies = [ "anyhow", "backoff", @@ -1958,7 +1958,7 @@ dependencies = [ [[package]] name = "librqbit-peer-protocol" -version = "3.5.0" +version = "3.5.1" dependencies = [ "anyhow", "bincode", @@ -1973,14 +1973,14 @@ dependencies = [ [[package]] name = "librqbit-sha1-wrapper" -version = "2.2.1" +version = "3.0.0" dependencies = [ "crypto-hash", ] [[package]] name = "librqbit-tracker-comms" -version = "1.0.0" +version = "1.0.1" dependencies = [ "anyhow", "async-stream", @@ -3023,7 +3023,7 @@ dependencies = [ [[package]] name = "rqbit-desktop" -version = "5.5.3" +version = "5.5.4" dependencies = [ "anyhow", "base64 0.21.5",