Move everything to workspaces
This commit is contained in:
parent
75547d3000
commit
ad867e8e3c
42 changed files with 338 additions and 168 deletions
69
Cargo.lock
generated
69
Cargo.lock
generated
|
|
@ -40,6 +40,17 @@ version = "0.13.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "904dfeac50f3cdaba28fc6f57fdcddb75f49ed61346676a78c4ffe55877802fd"
|
||||
|
||||
[[package]]
|
||||
name = "bencode"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"buffers",
|
||||
"clone_to_owned",
|
||||
"serde",
|
||||
"sha1w",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "bincode"
|
||||
version = "1.3.3"
|
||||
|
|
@ -86,6 +97,14 @@ dependencies = [
|
|||
"safemem",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "buffers"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"clone_to_owned",
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "bumpalo"
|
||||
version = "3.7.0"
|
||||
|
|
@ -148,6 +167,10 @@ dependencies = [
|
|||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "clone_to_owned"
|
||||
version = "0.1.0"
|
||||
|
||||
[[package]]
|
||||
name = "commoncrypto"
|
||||
version = "0.2.0"
|
||||
|
|
@ -643,20 +666,26 @@ name = "librqbit"
|
|||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"bencode",
|
||||
"bincode",
|
||||
"bitvec",
|
||||
"buffers",
|
||||
"byteorder",
|
||||
"clone_to_owned",
|
||||
"crypto-hash",
|
||||
"futures",
|
||||
"hex 0.4.3",
|
||||
"librqbit_core",
|
||||
"log",
|
||||
"openssl",
|
||||
"parking_lot",
|
||||
"peer_binary_protocol",
|
||||
"pretty_env_logger",
|
||||
"rand 0.8.4",
|
||||
"reqwest",
|
||||
"serde",
|
||||
"sha1",
|
||||
"sha1w",
|
||||
"size_format",
|
||||
"tokio",
|
||||
"url",
|
||||
|
|
@ -665,6 +694,22 @@ dependencies = [
|
|||
"warp",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "librqbit_core"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"bencode",
|
||||
"buffers",
|
||||
"clone_to_owned",
|
||||
"hex 0.4.3",
|
||||
"log",
|
||||
"parking_lot",
|
||||
"serde",
|
||||
"url",
|
||||
"uuid",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "lock_api"
|
||||
version = "0.4.4"
|
||||
|
|
@ -928,6 +973,21 @@ dependencies = [
|
|||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "peer_binary_protocol"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"bencode",
|
||||
"bincode",
|
||||
"bitvec",
|
||||
"buffers",
|
||||
"byteorder",
|
||||
"clone_to_owned",
|
||||
"librqbit_core",
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "percent-encoding"
|
||||
version = "2.1.0"
|
||||
|
|
@ -1338,6 +1398,15 @@ version = "0.6.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2579985fda508104f7587689507983eadd6a6e84dd35d6d115361f530916fa0d"
|
||||
|
||||
[[package]]
|
||||
name = "sha1w"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"crypto-hash",
|
||||
"openssl",
|
||||
"sha1",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "size_format"
|
||||
version = "1.0.2"
|
||||
|
|
|
|||
14
Cargo.toml
14
Cargo.toml
|
|
@ -1,5 +1,17 @@
|
|||
[workspace]
|
||||
members = [
|
||||
"crates/librqbit",
|
||||
"crates/rqbit"
|
||||
"crates/rqbit",
|
||||
"crates/buffers",
|
||||
"crates/clone_to_owned",
|
||||
"crates/bencode",
|
||||
"crates/sha1w",
|
||||
"crates/librqbit_core",
|
||||
"crates/peer_binary_protocol"
|
||||
]
|
||||
|
||||
[profile.dev]
|
||||
panic = "abort"
|
||||
|
||||
[profile.release]
|
||||
panic = "abort"
|
||||
13
crates/bencode/Cargo.toml
Normal file
13
crates/bencode/Cargo.toml
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
[package]
|
||||
name = "bencode"
|
||||
version = "0.1.0"
|
||||
edition = "2018"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
serde = {version = "1", features=["derive"]}
|
||||
buffers = {path = "../buffers"}
|
||||
clone_to_owned = {path = "../clone_to_owned"}
|
||||
anyhow = "1"
|
||||
sha1w = {path="../sha1w"}
|
||||
|
|
@ -1,12 +1,10 @@
|
|||
use std::{collections::HashMap, marker::PhantomData};
|
||||
|
||||
use buffers::{ByteBuf, ByteString};
|
||||
use clone_to_owned::CloneToOwned;
|
||||
use serde::{Deserialize, Deserializer};
|
||||
|
||||
use crate::{
|
||||
buffers::{ByteBuf, ByteString},
|
||||
clone_to_owned::CloneToOwned,
|
||||
serde_bencode_de::from_bytes,
|
||||
};
|
||||
use crate::serde_bencode_de::from_bytes;
|
||||
|
||||
pub fn dyn_from_bytes<'de, ByteBuf>(buf: &'de [u8]) -> anyhow::Result<BencodeValue<ByteBuf>>
|
||||
where
|
||||
7
crates/bencode/src/lib.rs
Normal file
7
crates/bencode/src/lib.rs
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
mod bencode_value;
|
||||
mod serde_bencode_de;
|
||||
mod serde_bencode_ser;
|
||||
|
||||
pub use bencode_value::*;
|
||||
pub use serde_bencode_de::*;
|
||||
pub use serde_bencode_ser::*;
|
||||
|
|
@ -1,14 +1,15 @@
|
|||
use crate::buffers::ByteBuf;
|
||||
use crate::sha1w::ISha1;
|
||||
use crate::type_aliases::Sha1;
|
||||
use buffers::ByteBuf;
|
||||
use serde::de::Error as DeError;
|
||||
use sha1w::{ISha1, Sha1};
|
||||
|
||||
pub struct BencodeDeserializer<'de> {
|
||||
buf: &'de [u8],
|
||||
field_context: Vec<ByteBuf<'de>>,
|
||||
parsing_key: bool,
|
||||
pub(crate) is_torrent_info: bool,
|
||||
pub(crate) torrent_info_digest: Option<[u8; 20]>,
|
||||
|
||||
// This is a f**ing hack
|
||||
pub is_torrent_info: bool,
|
||||
pub torrent_info_digest: Option<[u8; 20]>,
|
||||
}
|
||||
|
||||
impl<'de> BencodeDeserializer<'de> {
|
||||
|
|
@ -2,7 +2,7 @@ use std::collections::BTreeMap;
|
|||
|
||||
use serde::{Serialize, Serializer};
|
||||
|
||||
use crate::buffers::ByteString;
|
||||
use buffers::ByteString;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum SerErrorKind {
|
||||
10
crates/buffers/Cargo.toml
Normal file
10
crates/buffers/Cargo.toml
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
[package]
|
||||
name = "buffers"
|
||||
version = "0.1.0"
|
||||
edition = "2018"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
serde = {version = "1", features=["derive"]}
|
||||
clone_to_owned = {path="../clone_to_owned"}
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
use serde::{Deserialize, Deserializer};
|
||||
|
||||
use crate::clone_to_owned::CloneToOwned;
|
||||
use clone_to_owned::CloneToOwned;
|
||||
|
||||
#[derive(Default, PartialEq, Eq, Hash, Clone, PartialOrd, Ord)]
|
||||
pub struct ByteString(pub Vec<u8>);
|
||||
|
|
@ -69,7 +69,15 @@ impl std::fmt::Display for ByteString {
|
|||
}
|
||||
}
|
||||
|
||||
impl<B: ByteBufT> CloneToOwned for B {
|
||||
impl<'a> CloneToOwned for ByteBuf<'a> {
|
||||
type Target = ByteString;
|
||||
|
||||
fn clone_to_owned(&self) -> Self::Target {
|
||||
ByteString(self.as_slice().to_owned())
|
||||
}
|
||||
}
|
||||
|
||||
impl CloneToOwned for ByteString {
|
||||
type Target = ByteString;
|
||||
|
||||
fn clone_to_owned(&self) -> Self::Target {
|
||||
8
crates/clone_to_owned/Cargo.toml
Normal file
8
crates/clone_to_owned/Cargo.toml
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
[package]
|
||||
name = "clone_to_owned"
|
||||
version = "0.1.0"
|
||||
edition = "2018"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
|
|
@ -13,6 +13,13 @@ sha1-rust = ["sha1"]
|
|||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
bencode = {path = "../bencode"}
|
||||
buffers = {path = "../buffers"}
|
||||
librqbit_core = {path = "../librqbit_core"}
|
||||
clone_to_owned = {path = "../clone_to_owned"}
|
||||
peer_binary_protocol = {path = "../peer_binary_protocol"}
|
||||
sha1w = {path = "../sha1w"}
|
||||
|
||||
tokio = {version = "1", features = ["macros", "rt-multi-thread"]}
|
||||
serde = {version = "1", features=["derive"]}
|
||||
anyhow = "1"
|
||||
|
|
@ -40,10 +47,3 @@ hex = "0.4"
|
|||
[dev-dependencies]
|
||||
futures = {version = "0.3"}
|
||||
pretty_env_logger = "0.4"
|
||||
hex = "0.4"
|
||||
|
||||
[profile.dev]
|
||||
panic = "abort"
|
||||
|
||||
[profile.release]
|
||||
panic = "abort"
|
||||
|
|
@ -1,10 +1,8 @@
|
|||
use librqbit_core::lengths::{ChunkInfo, Lengths, ValidPieceIndex};
|
||||
use log::{debug, info};
|
||||
use peer_binary_protocol::Piece;
|
||||
|
||||
use crate::{
|
||||
lengths::{ChunkInfo, Lengths, ValidPieceIndex},
|
||||
peer_binary_protocol::Piece,
|
||||
type_aliases::BF,
|
||||
};
|
||||
use crate::type_aliases::BF;
|
||||
|
||||
pub struct ChunkTracker {
|
||||
// This forms the basis of a "queue" to pull from.
|
||||
|
|
@ -131,7 +129,11 @@ impl ChunkTracker {
|
|||
where
|
||||
ByteBuf: AsRef<[u8]>,
|
||||
{
|
||||
let chunk_info = self.lengths.chunk_info_from_received_piece(piece)?;
|
||||
let chunk_info = self.lengths.chunk_info_from_received_piece(
|
||||
piece.index,
|
||||
piece.begin,
|
||||
piece.block.as_ref().len() as u32,
|
||||
)?;
|
||||
let chunk_range = self.lengths.chunk_range(chunk_info.piece_index);
|
||||
let chunk_range = self.chunk_status.get_mut(chunk_range).unwrap();
|
||||
if chunk_range.all() {
|
||||
|
|
|
|||
|
|
@ -1,10 +1,12 @@
|
|||
use std::net::SocketAddr;
|
||||
|
||||
use buffers::ByteString;
|
||||
use futures::{stream::FuturesUnordered, StreamExt};
|
||||
use librqbit_core::torrent_metainfo::TorrentMetaV1Info;
|
||||
use log::debug;
|
||||
use tokio::sync::mpsc::UnboundedReceiver;
|
||||
|
||||
use crate::{buffers::ByteString, peer_info_reader, torrent_metainfo::TorrentMetaV1Info};
|
||||
use crate::peer_info_reader;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum ReadMetainfoResult {
|
||||
|
|
@ -61,9 +63,11 @@ pub async fn read_metainfo_from_peer_receiver(
|
|||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use librqbit_core::{info_hash::decode_info_hash, peer_id::generate_peer_id};
|
||||
|
||||
use crate::dht::jsdht::JsDht;
|
||||
|
||||
use super::*;
|
||||
use crate::info_hash::decode_info_hash;
|
||||
use crate::{dht::jsdht::JsDht, peer_id::generate_peer_id};
|
||||
use std::sync::Once;
|
||||
|
||||
static LOG_INIT: Once = Once::new();
|
||||
|
|
|
|||
|
|
@ -6,17 +6,17 @@ use std::{
|
|||
};
|
||||
|
||||
use anyhow::Context;
|
||||
use buffers::ByteString;
|
||||
use librqbit_core::{
|
||||
lengths::{ChunkInfo, Lengths, ValidPieceIndex},
|
||||
torrent_metainfo::{FileIteratorName, TorrentMetaV1Info},
|
||||
};
|
||||
use log::{debug, trace, warn};
|
||||
use parking_lot::Mutex;
|
||||
use peer_binary_protocol::Piece;
|
||||
use sha1w::ISha1;
|
||||
|
||||
use crate::{
|
||||
buffers::ByteString,
|
||||
lengths::{ChunkInfo, Lengths, ValidPieceIndex},
|
||||
peer_binary_protocol::Piece,
|
||||
sha1w::ISha1,
|
||||
torrent_metainfo::{FileIteratorName, TorrentMetaV1Info},
|
||||
type_aliases::{PeerHandle, BF},
|
||||
};
|
||||
use crate::type_aliases::{PeerHandle, BF};
|
||||
|
||||
pub struct InitialCheckResults {
|
||||
pub needed_pieces: BF,
|
||||
|
|
|
|||
|
|
@ -1,11 +1,11 @@
|
|||
use std::sync::Arc;
|
||||
|
||||
use librqbit_core::speed_estimator::SpeedEstimator;
|
||||
use std::io::Write;
|
||||
use std::sync::atomic::Ordering;
|
||||
use std::time::Instant;
|
||||
use warp::Filter;
|
||||
|
||||
use crate::speed_estimator::SpeedEstimator;
|
||||
use crate::torrent_state::TorrentState;
|
||||
|
||||
// This is just a stub for debugging, nothing useful here.
|
||||
|
|
|
|||
|
|
@ -1,27 +1,20 @@
|
|||
pub mod bencode_value;
|
||||
pub mod buffers;
|
||||
pub mod chunk_tracker;
|
||||
pub mod clone_to_owned;
|
||||
pub mod constants;
|
||||
pub mod dht;
|
||||
pub mod file_ops;
|
||||
pub mod http_api;
|
||||
pub mod info_hash;
|
||||
pub mod lengths;
|
||||
pub mod magnet;
|
||||
pub mod peer_binary_protocol;
|
||||
pub mod peer_connection;
|
||||
pub mod peer_handler;
|
||||
pub mod peer_id;
|
||||
pub mod peer_info_reader;
|
||||
pub mod peer_state;
|
||||
pub mod serde_bencode_de;
|
||||
pub mod serde_bencode_ser;
|
||||
pub mod sha1w;
|
||||
pub mod spawn_utils;
|
||||
pub mod speed_estimator;
|
||||
pub mod torrent_manager;
|
||||
pub mod torrent_metainfo;
|
||||
pub mod torrent_state;
|
||||
pub mod tracker_comms;
|
||||
pub mod type_aliases;
|
||||
|
||||
pub use buffers::*;
|
||||
pub use clone_to_owned::CloneToOwned;
|
||||
pub use librqbit_core::info_hash::*;
|
||||
pub use librqbit_core::magnet::*;
|
||||
pub use librqbit_core::peer_id::*;
|
||||
pub use librqbit_core::torrent_metainfo::*;
|
||||
|
|
|
|||
|
|
@ -1,20 +1,16 @@
|
|||
use std::{net::SocketAddr, time::Duration};
|
||||
|
||||
use anyhow::Context;
|
||||
use buffers::{ByteBuf, ByteString};
|
||||
use clone_to_owned::CloneToOwned;
|
||||
use librqbit_core::{lengths::ChunkInfo, peer_id::try_decode_peer_id};
|
||||
use log::{debug, trace};
|
||||
use tokio::time::timeout;
|
||||
|
||||
use crate::{
|
||||
buffers::{ByteBuf, ByteString},
|
||||
clone_to_owned::CloneToOwned,
|
||||
lengths::ChunkInfo,
|
||||
peer_binary_protocol::{
|
||||
use peer_binary_protocol::{
|
||||
extended::{handshake::ExtendedHandshake, ExtendedMessage},
|
||||
serialize_piece_preamble, Handshake, Message, MessageBorrowed, MessageDeserializeError,
|
||||
MessageOwned, PIECE_MESSAGE_DEFAULT_LEN,
|
||||
},
|
||||
peer_id::try_decode_peer_id,
|
||||
};
|
||||
use tokio::time::timeout;
|
||||
|
||||
pub trait PeerConnectionHandler {
|
||||
fn get_have_bytes(&self) -> u64;
|
||||
|
|
|
|||
|
|
@ -1,23 +1,22 @@
|
|||
use std::net::SocketAddr;
|
||||
|
||||
use crate::sha1w::ISha1;
|
||||
use log::debug;
|
||||
use parking_lot::{Mutex, RwLock};
|
||||
use tokio::sync::mpsc::UnboundedSender;
|
||||
|
||||
use crate::{
|
||||
buffers::{ByteBuf, ByteString},
|
||||
use bencode::from_bytes;
|
||||
use buffers::{ByteBuf, ByteString};
|
||||
use librqbit_core::{
|
||||
constants::CHUNK_SIZE,
|
||||
lengths::{ceil_div_u64, last_element_size_u64, ChunkInfo},
|
||||
peer_binary_protocol::{
|
||||
torrent_metainfo::TorrentMetaV1Info,
|
||||
};
|
||||
use log::debug;
|
||||
use parking_lot::{Mutex, RwLock};
|
||||
use peer_binary_protocol::{
|
||||
extended::{handshake::ExtendedHandshake, ut_metadata::UtMetadata, ExtendedMessage},
|
||||
Handshake, Message,
|
||||
},
|
||||
peer_connection::{PeerConnection, PeerConnectionHandler, WriterRequest},
|
||||
serde_bencode_de::from_bytes,
|
||||
torrent_metainfo::TorrentMetaV1Info,
|
||||
type_aliases::Sha1,
|
||||
};
|
||||
use sha1w::{ISha1, Sha1};
|
||||
use tokio::sync::mpsc::UnboundedSender;
|
||||
|
||||
use crate::peer_connection::{PeerConnection, PeerConnectionHandler, WriterRequest};
|
||||
|
||||
pub async fn read_metainfo_from_peer(
|
||||
addr: SocketAddr,
|
||||
|
|
@ -217,7 +216,7 @@ impl PeerConnectionHandler for Handler {
|
|||
mod tests {
|
||||
use std::{net::SocketAddr, str::FromStr, sync::Once};
|
||||
|
||||
use crate::peer_id::generate_peer_id;
|
||||
use librqbit_core::peer_id::generate_peer_id;
|
||||
|
||||
use super::read_metainfo_from_peer;
|
||||
|
||||
|
|
|
|||
|
|
@ -1,11 +1,9 @@
|
|||
use std::{collections::HashSet, net::SocketAddr, sync::Arc};
|
||||
|
||||
use librqbit_core::lengths::{ChunkInfo, ValidPieceIndex};
|
||||
use tokio::sync::{Notify, Semaphore};
|
||||
|
||||
use crate::{
|
||||
lengths::{ChunkInfo, ValidPieceIndex},
|
||||
type_aliases::BF,
|
||||
};
|
||||
use crate::type_aliases::BF;
|
||||
|
||||
#[derive(Debug, Hash, PartialEq, Eq)]
|
||||
pub struct InflightRequest {
|
||||
|
|
|
|||
|
|
@ -12,24 +12,25 @@ use std::{
|
|||
};
|
||||
|
||||
use anyhow::Context;
|
||||
use bencode::from_bytes;
|
||||
use buffers::ByteString;
|
||||
use librqbit_core::{
|
||||
lengths::Lengths, peer_id::generate_peer_id, speed_estimator::SpeedEstimator,
|
||||
torrent_metainfo::TorrentMetaV1Info,
|
||||
};
|
||||
use log::{debug, info};
|
||||
use parking_lot::{Mutex, RwLock};
|
||||
use reqwest::Url;
|
||||
use sha1w::Sha1;
|
||||
use size_format::SizeFormatterBinary as SF;
|
||||
|
||||
use crate::{
|
||||
buffers::ByteString,
|
||||
chunk_tracker::ChunkTracker,
|
||||
file_ops::FileOps,
|
||||
http_api::make_and_run_http_api,
|
||||
lengths::Lengths,
|
||||
peer_id::generate_peer_id,
|
||||
spawn_utils::{spawn, BlockingSpawner},
|
||||
speed_estimator::SpeedEstimator,
|
||||
torrent_metainfo::TorrentMetaV1Info,
|
||||
torrent_state::{AtomicStats, TorrentState, TorrentStateLocked},
|
||||
tracker_comms::{TrackerError, TrackerRequest, TrackerRequestEvent, TrackerResponse},
|
||||
type_aliases::Sha1,
|
||||
};
|
||||
pub struct TorrentManagerBuilder {
|
||||
info: TorrentMetaV1Info<ByteString>,
|
||||
|
|
@ -307,13 +308,13 @@ impl TorrentManager {
|
|||
anyhow::bail!("tracker responded with {:?}", response.status());
|
||||
}
|
||||
let bytes = response.bytes().await?;
|
||||
if let Ok(error) = crate::serde_bencode_de::from_bytes::<TrackerError>(&bytes) {
|
||||
if let Ok(error) = from_bytes::<TrackerError>(&bytes) {
|
||||
anyhow::bail!(
|
||||
"tracker returned failure. Failure reason: {}",
|
||||
error.failure_reason
|
||||
)
|
||||
};
|
||||
let response = crate::serde_bencode_de::from_bytes::<TrackerResponse>(&bytes)?;
|
||||
let response = from_bytes::<TrackerResponse>(&bytes)?;
|
||||
|
||||
for peer in response.peers.iter_sockaddrs() {
|
||||
self.state.add_peer_if_not_seen(peer);
|
||||
|
|
|
|||
|
|
@ -10,25 +10,28 @@ use std::{
|
|||
};
|
||||
|
||||
use anyhow::Context;
|
||||
use buffers::{ByteBuf, ByteString};
|
||||
use clone_to_owned::CloneToOwned;
|
||||
use futures::{stream::FuturesUnordered, StreamExt};
|
||||
use librqbit_core::{
|
||||
lengths::{ChunkInfo, Lengths, ValidPieceIndex},
|
||||
torrent_metainfo::TorrentMetaV1Info,
|
||||
};
|
||||
use log::{debug, info, trace, warn};
|
||||
use parking_lot::{Mutex, RwLock};
|
||||
use peer_binary_protocol::{
|
||||
extended::handshake::ExtendedHandshake, Handshake, Message, MessageOwned, Piece, Request,
|
||||
};
|
||||
use sha1w::Sha1;
|
||||
use tokio::{sync::mpsc::UnboundedSender, time::timeout};
|
||||
|
||||
use crate::{
|
||||
buffers::{ByteBuf, ByteString},
|
||||
chunk_tracker::{ChunkMarkingResult, ChunkTracker},
|
||||
clone_to_owned::CloneToOwned,
|
||||
file_ops::FileOps,
|
||||
lengths::{Lengths, ValidPieceIndex},
|
||||
peer_binary_protocol::{
|
||||
extended::handshake::ExtendedHandshake, Handshake, Message, MessageOwned, Piece, Request,
|
||||
},
|
||||
peer_connection::{PeerConnection, PeerConnectionHandler, WriterRequest},
|
||||
peer_state::{InflightRequest, LivePeerState, PeerState},
|
||||
spawn_utils::{spawn, BlockingSpawner},
|
||||
torrent_metainfo::TorrentMetaV1Info,
|
||||
type_aliases::{PeerHandle, Sha1, BF},
|
||||
type_aliases::{PeerHandle, BF},
|
||||
};
|
||||
|
||||
pub struct InflightPiece {
|
||||
|
|
@ -516,7 +519,7 @@ impl PeerConnectionHandler for PeerHandler {
|
|||
.fetch_add(bytes as u64, Ordering::Relaxed);
|
||||
}
|
||||
|
||||
fn read_chunk(&self, chunk: &crate::lengths::ChunkInfo, buf: &mut [u8]) -> anyhow::Result<()> {
|
||||
fn read_chunk(&self, chunk: &ChunkInfo, buf: &mut [u8]) -> anyhow::Result<()> {
|
||||
self.state.file_ops().read_chunk(self.addr, chunk, buf)
|
||||
}
|
||||
|
||||
|
|
@ -764,7 +767,11 @@ impl PeerHandler {
|
|||
}
|
||||
|
||||
fn on_received_piece(&self, handle: PeerHandle, piece: Piece<ByteBuf>) -> anyhow::Result<()> {
|
||||
let chunk_info = match self.state.lengths.chunk_info_from_received_piece(&piece) {
|
||||
let chunk_info = match self.state.lengths.chunk_info_from_received_piece(
|
||||
piece.index,
|
||||
piece.begin,
|
||||
piece.block.len() as u32,
|
||||
) {
|
||||
Some(i) => i,
|
||||
None => {
|
||||
anyhow::bail!(
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
use buffers::ByteBuf;
|
||||
use byteorder::ByteOrder;
|
||||
use serde::{Deserialize, Deserializer};
|
||||
use std::{
|
||||
|
|
@ -7,8 +8,6 @@ use std::{
|
|||
str::FromStr,
|
||||
};
|
||||
|
||||
use crate::buffers::ByteBuf;
|
||||
|
||||
#[derive(Clone, Copy)]
|
||||
pub enum TrackerRequestEvent {
|
||||
Started,
|
||||
|
|
|
|||
|
|
@ -3,12 +3,3 @@ use std::net::SocketAddr;
|
|||
pub type BF = bitvec::vec::BitVec<bitvec::order::Msb0, u8>;
|
||||
|
||||
pub type PeerHandle = SocketAddr;
|
||||
|
||||
#[cfg(feature = "sha1-openssl")]
|
||||
pub type Sha1 = crate::sha1w::Sha1Openssl;
|
||||
|
||||
#[cfg(feature = "sha1-system")]
|
||||
pub type Sha1 = crate::sha1w::Sha1System;
|
||||
|
||||
#[cfg(feature = "sha1-rust")]
|
||||
pub type Sha1 = crate::sha1w::Sha1Rust;
|
||||
|
|
|
|||
18
crates/librqbit_core/Cargo.toml
Normal file
18
crates/librqbit_core/Cargo.toml
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
[package]
|
||||
name = "librqbit_core"
|
||||
version = "0.1.0"
|
||||
edition = "2018"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
hex = "0.4"
|
||||
anyhow = "1"
|
||||
url = "2"
|
||||
uuid = {version = "0.8", features = ["v4"]}
|
||||
log = "0.4"
|
||||
parking_lot = "0.11"
|
||||
serde = {version = "1", features=["derive"]}
|
||||
buffers = {path="../buffers"}
|
||||
bencode = {path="../bencode"}
|
||||
clone_to_owned = {path="../clone_to_owned"}
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
use crate::{constants::CHUNK_SIZE, peer_binary_protocol::Piece};
|
||||
use crate::constants::CHUNK_SIZE;
|
||||
|
||||
const fn is_power_of_two(x: u64) -> bool {
|
||||
(x != 0) && ((x & (x - 1)) == 0)
|
||||
|
|
@ -189,18 +189,13 @@ impl Lengths {
|
|||
})
|
||||
}
|
||||
|
||||
pub fn chunk_info_from_received_piece<ByteBuf>(
|
||||
pub fn chunk_info_from_received_piece(
|
||||
&self,
|
||||
piece: &Piece<ByteBuf>,
|
||||
) -> Option<ChunkInfo>
|
||||
where
|
||||
ByteBuf: AsRef<[u8]>,
|
||||
{
|
||||
self.chunk_info_from_received_data(
|
||||
self.validate_piece_index(piece.index)?,
|
||||
piece.begin,
|
||||
piece.block.as_ref().len() as u32,
|
||||
)
|
||||
index: u32,
|
||||
begin: u32,
|
||||
block_len: u32,
|
||||
) -> Option<ChunkInfo> {
|
||||
self.chunk_info_from_received_data(self.validate_piece_index(index)?, begin, block_len)
|
||||
}
|
||||
pub const fn chunk_range(&self, index: ValidPieceIndex) -> std::ops::Range<usize> {
|
||||
let start = index.0 * self.chunks_per_piece;
|
||||
7
crates/librqbit_core/src/lib.rs
Normal file
7
crates/librqbit_core/src/lib.rs
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
pub mod constants;
|
||||
pub mod info_hash;
|
||||
pub mod lengths;
|
||||
pub mod magnet;
|
||||
pub mod peer_id;
|
||||
pub mod speed_estimator;
|
||||
pub mod torrent_metainfo;
|
||||
|
|
@ -1,13 +1,10 @@
|
|||
use std::{fmt::Write, ops::Deref, path::PathBuf};
|
||||
|
||||
use bencode::BencodeDeserializer;
|
||||
use buffers::{ByteBuf, ByteString};
|
||||
use clone_to_owned::CloneToOwned;
|
||||
use serde::Deserialize;
|
||||
|
||||
use crate::{
|
||||
buffers::{ByteBuf, ByteString},
|
||||
clone_to_owned::CloneToOwned,
|
||||
serde_bencode_de::BencodeDeserializer,
|
||||
};
|
||||
|
||||
pub type TorrentMetaV1Borrowed<'a> = TorrentMetaV1<ByteBuf<'a>>;
|
||||
pub type TorrentMetaV1Owned = TorrentMetaV1<ByteString>;
|
||||
|
||||
17
crates/peer_binary_protocol/Cargo.toml
Normal file
17
crates/peer_binary_protocol/Cargo.toml
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
[package]
|
||||
name = "peer_binary_protocol"
|
||||
version = "0.1.0"
|
||||
edition = "2018"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
serde = {version = "1", features = ["derive"]}
|
||||
bincode = "1"
|
||||
byteorder = "1"
|
||||
buffers = {path="../buffers"}
|
||||
bencode = {path="../bencode"}
|
||||
clone_to_owned = {path="../clone_to_owned"}
|
||||
librqbit_core = {path="../librqbit_core"}
|
||||
bitvec = "0.22"
|
||||
anyhow = "1"
|
||||
|
|
@ -3,13 +3,13 @@ use std::{
|
|||
net::{IpAddr, Ipv4Addr, Ipv6Addr},
|
||||
};
|
||||
|
||||
use buffers::ByteBuf;
|
||||
use byteorder::ByteOrder;
|
||||
use byteorder::BE;
|
||||
use clone_to_owned::CloneToOwned;
|
||||
use serde::{Deserialize, Deserializer, Serialize};
|
||||
|
||||
use crate::{
|
||||
buffers::ByteBuf, clone_to_owned::CloneToOwned, peer_binary_protocol::MY_EXTENDED_UT_METADATA,
|
||||
};
|
||||
use crate::MY_EXTENDED_UT_METADATA;
|
||||
|
||||
#[derive(Deserialize, Serialize, Debug, Default)]
|
||||
pub struct ExtendedHandshake<ByteBuf: Eq + std::hash::Hash> {
|
||||
|
|
@ -1,7 +1,10 @@
|
|||
use bencode::bencode_serialize_to_writer;
|
||||
use bencode::from_bytes;
|
||||
use bencode::BencodeValue;
|
||||
use buffers::ByteString;
|
||||
use clone_to_owned::CloneToOwned;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use crate::{bencode_value::BencodeValue, buffers::ByteString, clone_to_owned::CloneToOwned};
|
||||
|
||||
use self::{handshake::ExtendedHandshake, ut_metadata::UtMetadata};
|
||||
|
||||
use super::MessageDeserializeError;
|
||||
|
|
@ -46,11 +49,11 @@ impl<'a, ByteBuf: 'a + std::hash::Hash + Eq + Serialize> ExtendedMessage<ByteBuf
|
|||
match self {
|
||||
ExtendedMessage::Dyn(msg_id, v) => {
|
||||
out.push(*msg_id);
|
||||
crate::serde_bencode_ser::bencode_serialize_to_writer(v, out)?;
|
||||
bencode_serialize_to_writer(v, out)?;
|
||||
}
|
||||
ExtendedMessage::Handshake(h) => {
|
||||
out.push(0);
|
||||
crate::serde_bencode_ser::bencode_serialize_to_writer(h, out)?;
|
||||
bencode_serialize_to_writer(h, out)?;
|
||||
}
|
||||
ExtendedMessage::UtMetadata(u) => {
|
||||
let h = extended_handshake.ok_or_else(|| {
|
||||
|
|
@ -70,8 +73,6 @@ impl<'a, ByteBuf: 'a + std::hash::Hash + Eq + Serialize> ExtendedMessage<ByteBuf
|
|||
where
|
||||
ByteBuf: Deserialize<'a> + From<&'a [u8]>,
|
||||
{
|
||||
use crate::serde_bencode_de::from_bytes;
|
||||
|
||||
let emsg_id = buf.get(0).copied().ok_or_else(|| {
|
||||
MessageDeserializeError::Other(anyhow::anyhow!(
|
||||
"cannot deserialize extended message: can't read first byte"
|
||||
|
|
@ -1,12 +1,13 @@
|
|||
use std::io::Write;
|
||||
|
||||
use crate::{
|
||||
clone_to_owned::CloneToOwned, peer_binary_protocol::MessageDeserializeError,
|
||||
serde_bencode_de::BencodeDeserializer, serde_bencode_ser::bencode_serialize_to_writer,
|
||||
};
|
||||
use bencode::bencode_serialize_to_writer;
|
||||
use bencode::BencodeDeserializer;
|
||||
use clone_to_owned::CloneToOwned;
|
||||
use serde::Deserialize;
|
||||
use serde::Serialize;
|
||||
|
||||
use crate::MessageDeserializeError;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum UtMetadata<ByteBuf> {
|
||||
Request(u32),
|
||||
|
|
@ -1,16 +1,12 @@
|
|||
pub mod extended;
|
||||
|
||||
use bincode::Options;
|
||||
use buffers::{ByteBuf, ByteString};
|
||||
use byteorder::{ByteOrder, BE};
|
||||
use clone_to_owned::CloneToOwned;
|
||||
use librqbit_core::{constants::CHUNK_SIZE, lengths::ChunkInfo};
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use crate::{
|
||||
buffers::{ByteBuf, ByteString},
|
||||
clone_to_owned::CloneToOwned,
|
||||
constants::CHUNK_SIZE,
|
||||
lengths::ChunkInfo,
|
||||
};
|
||||
|
||||
use self::extended::{handshake::ExtendedHandshake, ExtendedMessage};
|
||||
|
||||
const INTEGER_LEN: usize = 4;
|
||||
|
|
@ -19,9 +19,3 @@ regex = "1"
|
|||
|
||||
[dev-dependencies]
|
||||
futures = {version = "0.3"}
|
||||
|
||||
[profile.dev]
|
||||
panic = "abort"
|
||||
|
||||
[profile.release]
|
||||
panic = "abort"
|
||||
|
|
@ -3,14 +3,12 @@ use std::{fs::File, io::Read, net::SocketAddr, time::Duration};
|
|||
use anyhow::Context;
|
||||
use clap::Clap;
|
||||
use librqbit::{
|
||||
buffers::ByteString,
|
||||
dht::{inforead::read_metainfo_from_peer_receiver, jsdht::JsDht},
|
||||
info_hash::InfoHash,
|
||||
magnet,
|
||||
peer_id::generate_peer_id,
|
||||
generate_peer_id,
|
||||
spawn_utils::{spawn, BlockingSpawner},
|
||||
torrent_from_bytes,
|
||||
torrent_manager::TorrentManagerBuilder,
|
||||
torrent_metainfo::{torrent_from_bytes, TorrentMetaV1Info, TorrentMetaV1Owned},
|
||||
ByteString, InfoHash, Magnet, TorrentMetaV1Info, TorrentMetaV1Owned,
|
||||
};
|
||||
use log::{info, warn};
|
||||
use reqwest::Url;
|
||||
|
|
@ -171,11 +169,10 @@ fn main() -> anyhow::Result<()> {
|
|||
async fn async_main(opts: Opts, spawner: BlockingSpawner) -> anyhow::Result<()> {
|
||||
let peer_id = generate_peer_id();
|
||||
if opts.torrent_path.starts_with("magnet:") {
|
||||
let magnet::Magnet {
|
||||
let Magnet {
|
||||
info_hash,
|
||||
trackers,
|
||||
} = magnet::Magnet::parse(&opts.torrent_path)
|
||||
.context("provided path is not a valid magnet URL")?;
|
||||
} = Magnet::parse(&opts.torrent_path).context("provided path is not a valid magnet URL")?;
|
||||
let dht_rx = JsDht::new(info_hash).start_peer_discovery()?;
|
||||
let (info, dht_rx, initial_peers) =
|
||||
match read_metainfo_from_peer_receiver(peer_id, info_hash, dht_rx).await {
|
||||
|
|
|
|||
22
crates/sha1w/Cargo.toml
Normal file
22
crates/sha1w/Cargo.toml
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
[package]
|
||||
name = "sha1w"
|
||||
version = "0.1.0"
|
||||
edition = "2018"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[features]
|
||||
default = ["default-sha1-openssl"]
|
||||
sha1-system = ["crypto-hash"]
|
||||
sha1-openssl = ["openssl"]
|
||||
sha1-rust = ["sha1"]
|
||||
default-sha1-openssl = ["sha1-openssl"]
|
||||
default-sha1-rust = ["sha1-rust"]
|
||||
default-sha1-system = ["sha1-system"]
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
openssl = {version="0.10", optional=true}
|
||||
crypto-hash = {version="0.3", optional=true}
|
||||
sha1 = {version = "0.6", optional=true}
|
||||
|
|
@ -4,6 +4,15 @@
|
|||
// leaving the pure-rust impl here too. Maybe someday make them
|
||||
// runtime swappable or enabled with a feature.
|
||||
|
||||
#[cfg(feature = "default-sha1-openssl")]
|
||||
pub type Sha1 = Sha1Openssl;
|
||||
|
||||
#[cfg(feature = "default-sha1-rust")]
|
||||
pub type Sha1 = Sha1Rust;
|
||||
|
||||
#[cfg(feature = "default-sha1-system")]
|
||||
pub type Sha1 = Sha1System;
|
||||
|
||||
pub trait ISha1 {
|
||||
fn new() -> Self;
|
||||
fn update(&mut self, buf: &[u8]);
|
||||
Loading…
Add table
Add a link
Reference in a new issue