diff --git a/Cargo.toml b/Cargo.toml index b39f54d1f..e8fd1d4f8 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,5 +1,7 @@ [workspace] members = [ + "examples/get_metadata", + "examples/simple_torrent", "packages/bencode", "packages/dht", "packages/disk", @@ -13,16 +15,12 @@ members = [ "packages/util", "packages/utp", "packages/utracker", - "examples/get_metadata", - "examples/simple_torrent", ] resolver = "2" [workspace.package] -authors = [ - "Nautilus Cyberneering , Andrew ", -] +authors = ["Nautilus Cyberneering , Andrew "] categories = ["network-programming", "web-programming"] description = "A collection of crates for building applications using bittorrent technologies." documentation = "https://github.com/torrust/bittorrent-infrastructure-project" @@ -30,16 +28,16 @@ edition = "2021" homepage = "https://github.com/torrust/bittorrent-infrastructure-project" keywords = ["bittorrent"] license = "Apache-2.0" -publish = false # until we decide where to publish. +publish = false # until we decide where to publish. repository = "https://github.com/torrust/bittorrent-infrastructure-project" rust-version = "1.71" version = "1.0.0-alpha.1" [profile.bench] -opt-level = 3 +codegen-units = 1 debug = false -rpath = false -lto = false debug-assertions = false -codegen-units = 1 -panic = 'unwind' \ No newline at end of file +lto = false +opt-level = 3 +panic = 'unwind' +rpath = false diff --git a/examples/get_metadata/Cargo.toml b/examples/get_metadata/Cargo.toml index bcd51bf63..3603c99f8 100644 --- a/examples/get_metadata/Cargo.toml +++ b/examples/get_metadata/Cargo.toml @@ -1,6 +1,6 @@ [package] -name = "get_metadata" description = "Examples For bip-rs" +name = "get_metadata" readme = "README.md" authors.workspace = true @@ -16,14 +16,14 @@ version.workspace = true [dependencies] dht = { path = "../../packages/dht" } handshake = { path = "../../packages/handshake" } +metainfo = { path = "../../packages/metainfo" } peer = { path = "../../packages/peer" } select = { path = "../../packages/select" } -metainfo = {path ="../../packages/metainfo" } clap = "4" -hex = "0" futures = "0" +hex = "0" tokio = { version = "1", features = ["full"] } -tokio-util = {version = "0", features = ["codec"]} +tokio-util = { version = "0", features = ["codec"] } tracing = "0" tracing-subscriber = "0" diff --git a/examples/get_metadata/src/main.rs b/examples/get_metadata/src/main.rs index 10b963e5c..d1ecd52db 100644 --- a/examples/get_metadata/src/main.rs +++ b/examples/get_metadata/src/main.rs @@ -1,5 +1,3 @@ -use std::fmt::Debug; -use std::fs::File; use std::io::Write as _; use std::net::SocketAddr; use std::sync::{Arc, Once}; @@ -53,7 +51,7 @@ where impl HandshakerTrait for LegacyHandshaker where S: Sink + Send + Unpin, - S::Error: Debug, + S::Error: std::fmt::Debug, { type MetadataEnvelope = (); @@ -340,7 +338,7 @@ async fn main() { }; // Write the metainfo file out to the user provided path - File::create(output) + std::fs::File::create(output) .expect("Failed to create output file") .write_all(&metainfo.to_bytes()) .expect("Failed to write metainfo to file"); diff --git a/examples/simple_torrent/Cargo.toml b/examples/simple_torrent/Cargo.toml index 4839aa390..58b8d08ca 100644 --- a/examples/simple_torrent/Cargo.toml +++ b/examples/simple_torrent/Cargo.toml @@ -1,6 +1,6 @@ [package] -name = "simple_torrent" description = "Examples For bip-rs" +name = "simple_torrent" readme = "README.md" authors.workspace = true @@ -23,6 +23,6 @@ peer = { path = "../../packages/peer" } clap = "4" futures = "0" tokio = { version = "1", features = ["full"] } -tokio-util = {version = "0", features = ["codec"]} +tokio-util = { version = "0", features = ["codec"] } tracing = "0" tracing-subscriber = "0" diff --git a/examples/simple_torrent/src/main.rs b/examples/simple_torrent/src/main.rs index eb5a5b0a1..948f5c20b 100644 --- a/examples/simple_torrent/src/main.rs +++ b/examples/simple_torrent/src/main.rs @@ -1,7 +1,5 @@ -use std::cmp; use std::collections::HashMap; -use std::fs::File; -use std::io::Read; +use std::io::Read as _; use std::sync::{Arc, Once}; use disk::fs::NativeFileSystem; @@ -10,7 +8,7 @@ use disk::{ Block, BlockMetadata, BlockMut, DiskManager, DiskManagerBuilder, DiskManagerSink, DiskManagerStream, IDiskMessage, InfoHash, ODiskMessage, }; -use futures::channel::mpsc::{self, Receiver, Sender}; +use futures::channel::mpsc; use futures::future::Either; use futures::lock::Mutex; use futures::{stream, SinkExt as _, StreamExt as _}; @@ -22,8 +20,8 @@ use metainfo::{Info, Metainfo}; use peer::messages::{BitFieldMessage, HaveMessage, PeerWireProtocolMessage, PieceMessage, RequestMessage}; use peer::protocols::{NullProtocol, PeerWireProtocol}; use peer::{ - PeerInfo, PeerManagerBuilder, PeerManagerInputMessage, PeerManagerOutputError, PeerManagerOutputMessage, PeerManagerSink, - PeerManagerStream, PeerProtocolCodec, + ManagerSink, ManagerStream, PeerInfo, PeerManagerBuilder, PeerManagerInputMessage, PeerManagerOutputError, + PeerManagerOutputMessage, PeerProtocolCodec, }; use tokio::net::TcpStream; use tokio::signal; @@ -182,7 +180,7 @@ fn extract_arguments(matches: &clap::ArgMatches) -> (String, String, String) { fn load_and_parse_torrent_file(torrent_file_path: &str) -> (Metainfo, InfoHash) { let mut torrent_file_bytes = Vec::new(); - File::open(torrent_file_path) + std::fs::File::open(torrent_file_path) .unwrap() .read_to_end(&mut torrent_file_bytes) .unwrap(); @@ -318,10 +316,8 @@ async fn setup_handshaker() -> (TcpHandshaker, JoinSet<()>) { .unwrap() } -type PeerManager = peer::PeerManager< - Framed>>, - PeerWireProtocolMessage, ->; +type PeerManager = + peer::Manager>>, PeerWireProtocolMessage>; #[allow(clippy::type_complexity)] fn setup_peer_manager() -> PeerManager { @@ -333,7 +329,7 @@ fn setup_peer_manager() -> PeerManager { async fn handle_new_connections( handshaker_receiver: HandshakerStream, - peer_manager_sender: PeerManagerSink< + peer_manager_sender: ManagerSink< Framed>>, PeerWireProtocolMessage, >, @@ -357,13 +353,13 @@ async fn handle_new_connections( } async fn handle_peer_manager_messages( - mut peer_manager_receiver: PeerManagerStream< + mut peer_manager_receiver: ManagerStream< Framed>>, PeerWireProtocolMessage, >, info_hash: InfoHash, disk_request_map: Arc>>>, - selection_sender: Sender, + selection_sender: mpsc::Sender, disk_manager_sender: DiskManagerSink>, ) { while let Some(result) = peer_manager_receiver.next().await { @@ -450,8 +446,8 @@ async fn handle_peer_manager_messages( async fn handle_disk_manager_messages( mut disk_manager_receiver: DiskManagerStream, disk_request_map: Arc>>>, - selection_sender: Sender, - peer_manager_sender: PeerManagerSink< + selection_sender: mpsc::Sender, + peer_manager_sender: ManagerSink< Framed>>, PeerWireProtocolMessage, >, @@ -500,10 +496,10 @@ async fn handle_disk_manager_messages( } async fn handle_existing_pieces( - mut selection_receiver: Receiver, + mut selection_receiver: mpsc::Receiver, mut piece_requests: Vec, mut current_pieces: usize, -) -> (Receiver, Vec, usize) { +) -> (mpsc::Receiver, Vec, usize) { loop { match selection_receiver.next().await { Some(PeerSelectionState::GoodPiece(index)) => { @@ -514,7 +510,7 @@ async fn handle_existing_pieces( break (selection_receiver, piece_requests, current_pieces); } Some(message) => { - panic!("Unexpected Message Received In Selection Receiver: {message:?}"); + panic!("Unexpected Message Received In Selection mpsc::Receiver: {message:?}"); } } } @@ -522,8 +518,8 @@ async fn handle_existing_pieces( #[allow(clippy::too_many_arguments)] async fn handle_selection_messages( - mut selection_receiver: Receiver, - mut peer_manager_sender: PeerManagerSink< + mut selection_receiver: mpsc::Receiver, + mut peer_manager_sender: ManagerSink< Framed>>, PeerWireProtocolMessage, >, @@ -584,7 +580,7 @@ async fn handle_selection_messages( break; } else if let Some(peer_info) = optional_peer { let next_piece_requests = if is_unchoked { - let take_blocks = cmp::min(MAX_PENDING_BLOCKS - pending_blocks, piece_requests.len()); + let take_blocks = std::cmp::min(MAX_PENDING_BLOCKS - pending_blocks, piece_requests.len()); pending_blocks += take_blocks; piece_requests @@ -636,7 +632,7 @@ fn generate_piece_requests(info: &Info, block_size: usize) -> Vec BRefAccessExt<'a> for BencodeRef<'a> { #[cfg(test)] mod tests { - use std::default::Default; use crate::access::bencode::BRefAccess; use crate::reference::bencode_ref::BencodeRef; diff --git a/packages/bencode/src/reference/decode.rs b/packages/bencode/src/reference/decode.rs index c2895cad6..97c5cf1ff 100644 --- a/packages/bencode/src/reference/decode.rs +++ b/packages/bencode/src/reference/decode.rs @@ -1,6 +1,6 @@ use std::collections::btree_map::Entry; use std::collections::BTreeMap; -use std::str::{self}; +use std::str; use crate::error::{BencodeParseError, BencodeParseResult}; use crate::reference::bencode_ref::{BencodeRef, Inner}; @@ -157,7 +157,6 @@ fn peek_byte(bytes: &[u8], pos: usize) -> BencodeParseResult { #[cfg(test)] mod tests { - use std::default::Default; use crate::access::bencode::BRefAccess; use crate::reference::bencode_ref::BencodeRef; diff --git a/packages/bencode/src/reference/decode_opt.rs b/packages/bencode/src/reference/decode_opt.rs index e8d9a8337..8409cc72c 100644 --- a/packages/bencode/src/reference/decode_opt.rs +++ b/packages/bencode/src/reference/decode_opt.rs @@ -1,5 +1,3 @@ -use std::default::Default; - const DEFAULT_MAX_RECURSION: usize = 50; const DEFAULT_CHECK_KEY_SORT: bool = false; const DEFAULT_ENFORCE_FULL_DECODE: bool = true; diff --git a/packages/dht/Cargo.toml b/packages/dht/Cargo.toml index 1b6da9241..bf5d8e85e 100644 --- a/packages/dht/Cargo.toml +++ b/packages/dht/Cargo.toml @@ -1,7 +1,7 @@ [package] -name = "dht" description = "Implementation of the bittorrent mainline DHT" -keywords = ["dht", "distributed", "hash", "mainline", "bittorrent"] +keywords = ["bittorrent", "dht", "distributed", "hash", "mainline"] +name = "dht" readme = "README.md" authors.workspace = true @@ -20,11 +20,11 @@ bencode = { path = "../bencode" } handshake = { path = "../handshake" } util = { path = "../util" } +chrono = "0" crc = "3" futures = "0" -tokio = { version = "1", features = ["full"] } rand = "0" -chrono = "0" thiserror = "1" +tokio = { version = "1", features = ["full"] } tracing = "0" tracing-subscriber = "0" diff --git a/packages/dht/examples/debug.rs b/packages/dht/examples/debug.rs index 5651fbdcc..4998bb4ed 100644 --- a/packages/dht/examples/debug.rs +++ b/packages/dht/examples/debug.rs @@ -1,5 +1,5 @@ use std::collections::HashSet; -use std::io::Read; +use std::io::Read as _; use std::net::{Ipv4Addr, SocketAddr, SocketAddrV4}; use std::sync::Once; diff --git a/packages/dht/src/builder.rs b/packages/dht/src/builder.rs index 93c640511..6396b5cea 100644 --- a/packages/dht/src/builder.rs +++ b/packages/dht/src/builder.rs @@ -2,7 +2,7 @@ use std::collections::HashSet; use std::net::SocketAddr; use std::sync::Arc; -use futures::channel::mpsc::{self, Receiver, Sender}; +use futures::channel::mpsc; use futures::SinkExt as _; use tokio::net::UdpSocket; use tokio::task::JoinSet; @@ -15,7 +15,7 @@ use crate::worker::{self, DhtEvent, OneshotTask, ShutdownCause}; /// Maintains a Distributed Hash (Routing) Table. pub struct MainlineDht { - main_task_sender: Sender, + main_task_sender: mpsc::Sender, _tasks: JoinSet<()>, } @@ -84,7 +84,7 @@ impl MainlineDht { /// It is important to at least monitor the DHT for shutdown events as any calls /// after that event occurs will not be processed but no indication will be given. #[must_use] - pub async fn events(&self) -> Receiver { + pub async fn events(&self) -> mpsc::Receiver { let (send, recv) = mpsc::channel(1); if let Err(e) = self.main_task_sender.clone().send(OneshotTask::RegisterSender(send)).await { diff --git a/packages/dht/src/error.rs b/packages/dht/src/error.rs index 6f2ae3a8b..299ed8480 100644 --- a/packages/dht/src/error.rs +++ b/packages/dht/src/error.rs @@ -1,5 +1,3 @@ -use std::io; - use bencode::BencodeConvertError; use thiserror::Error; @@ -11,7 +9,7 @@ pub enum DhtError { #[error("Bencode error: {0}")] Bencode(#[from] BencodeConvertError), #[error("IO error: {0}")] - Io(#[from] io::Error), + Io(#[from] std::io::Error), #[error("Node Sent An Invalid Message With Message Code {code}")] InvalidMessage { code: String }, #[error("Node Sent Us An Invalid Response: {details}")] diff --git a/packages/dht/src/message/compact_info.rs b/packages/dht/src/message/compact_info.rs index 8a55d3217..b06a1fce9 100644 --- a/packages/dht/src/message/compact_info.rs +++ b/packages/dht/src/message/compact_info.rs @@ -1,5 +1,4 @@ use std::borrow::Cow; -use std::fmt::Debug; use std::hash::Hash; use std::net::{Ipv4Addr, SocketAddrV4}; @@ -132,7 +131,7 @@ where impl<'a, B> IntoIterator for CompactValueInfo<'a, B> where B: BRefAccess + Clone, - B::BType: PartialEq + Eq + core::hash::Hash + Debug, + B::BType: PartialEq + Eq + core::hash::Hash + std::fmt::Debug, { type Item = SocketAddrV4; type IntoIter = CompactValueInfoIter<'a, B>; diff --git a/packages/dht/src/message/get_peers.rs b/packages/dht/src/message/get_peers.rs index ac3cdb7f1..52c1cca55 100644 --- a/packages/dht/src/message/get_peers.rs +++ b/packages/dht/src/message/get_peers.rs @@ -1,5 +1,4 @@ use std::collections::BTreeMap; -use std::fmt::Debug; use std::ops::Deref; use bencode::inner::BCowConvert; @@ -85,7 +84,7 @@ impl<'a> GetPeersRequest<'a> { pub enum CompactInfoType<'a, B> where B: BRefAccess + Clone, - B::BType: PartialEq + Eq + core::hash::Hash + Debug, + B::BType: PartialEq + Eq + core::hash::Hash + std::fmt::Debug, { Nodes(CompactNodeInfo<'a>), Values(CompactValueInfo<'a, B::BType>), @@ -97,7 +96,7 @@ where pub struct GetPeersResponse<'a, B> where B: BRefAccess + Clone, - B::BType: PartialEq + Eq + core::hash::Hash + Debug, + B::BType: PartialEq + Eq + core::hash::Hash + std::fmt::Debug, { trans_id: &'a [u8], node_id: NodeId, @@ -110,7 +109,7 @@ where impl<'a, B> GetPeersResponse<'a, B> where B: BRefAccess + Clone, - B::BType: PartialEq + Eq + core::hash::Hash + Debug, + B::BType: PartialEq + Eq + core::hash::Hash + std::fmt::Debug, { #[must_use] pub fn new( diff --git a/packages/dht/src/message/mod.rs b/packages/dht/src/message/mod.rs index 2cc259e6a..68e4c3771 100644 --- a/packages/dht/src/message/mod.rs +++ b/packages/dht/src/message/mod.rs @@ -1,5 +1,3 @@ -use std::fmt::Debug; - use bencode::ext::BConvertExt; use bencode::{BConvert, BRefAccess, BencodeConvertError}; @@ -61,7 +59,7 @@ impl BConvertExt for MessageValidate {} pub enum MessageType<'a, B> where B: BRefAccess + Clone, - B::BType: PartialEq + Eq + core::hash::Hash + Debug, + B::BType: PartialEq + Eq + core::hash::Hash + std::fmt::Debug, { Request(RequestType<'a>), Response(ResponseType<'a, B>), @@ -71,7 +69,7 @@ where impl<'a, B> MessageType<'a, B> where B: BRefAccess + Clone, - B::BType: PartialEq + Eq + core::hash::Hash + Debug, + B::BType: PartialEq + Eq + core::hash::Hash + std::fmt::Debug, { /// Create a new `MessageType` /// diff --git a/packages/dht/src/message/response.rs b/packages/dht/src/message/response.rs index 79a286090..a5d8be600 100644 --- a/packages/dht/src/message/response.rs +++ b/packages/dht/src/message/response.rs @@ -1,5 +1,3 @@ -use std::fmt::Debug; - use bencode::ext::BConvertExt; use bencode::{BConvert, BDictAccess, BListAccess, BRefAccess, BencodeConvertError}; use util::bt::NodeId; @@ -65,7 +63,7 @@ impl<'a> ResponseValidate<'a> { pub fn validate_values<'b, B>(&self, values: &'b dyn BListAccess) -> Result, DhtError> where B: BRefAccess + Clone, - B::BType: PartialEq + Eq + core::hash::Hash + Debug, + B::BType: PartialEq + Eq + core::hash::Hash + std::fmt::Debug, { for bencode in values { match bencode.bytes() { @@ -113,7 +111,7 @@ pub enum ExpectedResponse { pub enum ResponseType<'a, B> where B: BRefAccess + Clone, - B::BType: PartialEq + Eq + core::hash::Hash + Debug, + B::BType: PartialEq + Eq + core::hash::Hash + std::fmt::Debug, { Ping(PingResponse<'a>), FindNode(FindNodeResponse<'a>), @@ -125,7 +123,7 @@ where impl<'a, B> ResponseType<'a, B> where B: BRefAccess + Clone, - B::BType: PartialEq + Eq + core::hash::Hash + Debug, + B::BType: PartialEq + Eq + core::hash::Hash + std::fmt::Debug, { /// Creates a new `ResponseType` from parts. /// diff --git a/packages/dht/src/router.rs b/packages/dht/src/router.rs index 168d46393..64356d534 100644 --- a/packages/dht/src/router.rs +++ b/packages/dht/src/router.rs @@ -1,5 +1,3 @@ -use std::fmt::{self, Display, Formatter}; -use std::io::{Error, ErrorKind}; use std::net::{SocketAddr, SocketAddrV4, SocketAddrV6, ToSocketAddrs}; use std::vec::IntoIter; @@ -47,9 +45,10 @@ impl Router { pub fn ipv4_addr(&self) -> std::io::Result { let mut addrs = self.socket_addrs()?; - addrs - .find_map(map_ipv4) - .ok_or(Error::new(ErrorKind::Other, "No IPv4 Addresses Found For Host")) + addrs.find_map(map_ipv4).ok_or(std::io::Error::new( + std::io::ErrorKind::Other, + "No IPv4 Addresses Found For Host", + )) } /// Returns the [`SocketAddrV6`] of this [`Router`]. @@ -60,9 +59,10 @@ impl Router { pub fn ipv6_addr(&self) -> std::io::Result { let mut addrs = self.socket_addrs()?; - addrs - .find_map(map_ipv6) - .ok_or(Error::new(ErrorKind::Other, "No IPv6 Addresses Found For Host")) + addrs.find_map(map_ipv6).ok_or(std::io::Error::new( + std::io::ErrorKind::Other, + "No IPv6 Addresses Found For Host", + )) } /// Returns the [`SocketAddr`] of this [`Router`]. @@ -73,9 +73,10 @@ impl Router { pub fn socket_addr(&self) -> std::io::Result { let mut addrs = self.socket_addrs()?; - addrs - .next() - .ok_or(Error::new(ErrorKind::Other, "No SocketAddresses Found For Host")) + addrs.next().ok_or(std::io::Error::new( + std::io::ErrorKind::Other, + "No SocketAddresses Found For Host", + )) } fn socket_addrs(&self) -> std::io::Result> { @@ -106,14 +107,14 @@ fn map_ipv6(addr: SocketAddr) -> Option { } } -impl Display for Router { - fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), fmt::Error> { +impl std::fmt::Display for Router { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> Result<(), std::fmt::Error> { match *self { Router::uTorrent => f.write_fmt(format_args!("{}:{}", UTORRENT_DHT.0, UTORRENT_DHT.1)), Router::BitTorrent => f.write_fmt(format_args!("{}:{}", BITTORRENT_DHT.0, BITTORRENT_DHT.1)), Router::BitComet => f.write_fmt(format_args!("{}:{}", BITCOMET_DHT.0, BITCOMET_DHT.1)), Router::Transmission => f.write_fmt(format_args!("{}:{}", TRANSMISSION_DHT.0, TRANSMISSION_DHT.1)), - Router::Custom(n) => Display::fmt(&n, f), + Router::Custom(n) => std::fmt::Display::fmt(&n, f), } } } diff --git a/packages/dht/src/routing/node.rs b/packages/dht/src/routing/node.rs index b5030abf8..7abc3f6ac 100644 --- a/packages/dht/src/routing/node.rs +++ b/packages/dht/src/routing/node.rs @@ -2,7 +2,6 @@ #![allow(unused)] use std::cell::Cell; -use std::fmt::{self, Debug, Formatter}; use std::hash::{Hash, Hasher}; use std::net::SocketAddr; use std::sync::atomic::{AtomicUsize, Ordering}; @@ -190,8 +189,8 @@ impl Clone for Node { } } -impl Debug for Node { - fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), fmt::Error> { +impl std::fmt::Debug for Node { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> Result<(), std::fmt::Error> { f.write_fmt(format_args!( "Node{{ id: {:?}, addr: {:?}, last_request: {:?}, \ last_response: {:?}, refresh_requests: {:?} }}", @@ -256,7 +255,6 @@ fn recently_requested(node: &Node, curr_time: DateTime) -> NodeStatus { #[cfg(test)] mod tests { - use std::iter; use std::net::{Ipv4Addr, SocketAddr, SocketAddrV4}; use chrono::Duration; diff --git a/packages/dht/src/routing/table.rs b/packages/dht/src/routing/table.rs index cdf02a0cf..67263f50a 100644 --- a/packages/dht/src/routing/table.rs +++ b/packages/dht/src/routing/table.rs @@ -1,7 +1,3 @@ -// TODO: Remove when we use find_node, -#![allow(unused)] - -use std::cmp; use std::iter::Filter; use std::slice::Iter; @@ -184,6 +180,7 @@ pub enum BucketContents<'a> { Assorted(&'a Bucket), } +#[allow(dead_code)] impl<'a> BucketContents<'a> { fn is_empty(&self) -> bool { matches!(self, &BucketContents::Empty) @@ -384,7 +381,7 @@ fn next_bucket_index(num_buckets: usize, start_index: usize, curr_index: usize) // to the right. All assuming we can actually do this without going out of bounds. match curr_index.cmp(&start_index) { - cmp::Ordering::Less => { + std::cmp::Ordering::Less => { let offset = (start_index - curr_index) + 1; let right_index = start_index.checked_add(offset); @@ -398,7 +395,7 @@ fn next_bucket_index(num_buckets: usize, start_index: usize, curr_index: usize) None } } - cmp::Ordering::Equal => { + std::cmp::Ordering::Equal => { let right_index = start_index.checked_add(1); let left_index = start_index.checked_sub(1); @@ -410,7 +407,7 @@ fn next_bucket_index(num_buckets: usize, start_index: usize, curr_index: usize) None } } - cmp::Ordering::Greater => { + std::cmp::Ordering::Greater => { let offset = curr_index - start_index; let left_index = start_index.checked_sub(offset); @@ -480,7 +477,7 @@ mod tests { #[test] fn positive_initial_empty_buckets() { let table_id = [1u8; bt::NODE_ID_LEN]; - let mut table = RoutingTable::new(table_id.into()); + let table = RoutingTable::new(table_id.into()); // First buckets should be empty assert_eq!(table.buckets().take(table::MAX_BUCKETS).count(), table::MAX_BUCKETS); diff --git a/packages/dht/src/worker/bootstrap.rs b/packages/dht/src/worker/bootstrap.rs index 7bcb41f77..f278d7941 100644 --- a/packages/dht/src/worker/bootstrap.rs +++ b/packages/dht/src/worker/bootstrap.rs @@ -3,7 +3,7 @@ use std::net::SocketAddr; use std::sync::atomic::{AtomicUsize, Ordering}; use std::sync::{Arc, Mutex, RwLock}; -use futures::channel::mpsc::{SendError, Sender}; +use futures::channel::mpsc::{self, SendError}; use futures::future::BoxFuture; use futures::{FutureExt as _, SinkExt as _}; use tokio::task::JoinSet; @@ -67,8 +67,8 @@ impl TableBootstrap { pub async fn start_bootstrap( &self, - mut out: Sender<(Vec, SocketAddr)>, - mut scheduled_task_sender: Sender, + mut out: mpsc::Sender<(Vec, SocketAddr)>, + mut scheduled_task_sender: mpsc::Sender, ) -> Result { // Reset the bootstrap state self.active_messages.lock().unwrap().clear(); @@ -123,8 +123,8 @@ impl TableBootstrap { &self, trans_id: TransactionID, table: Arc>, - out: Sender<(Vec, SocketAddr)>, - scheduled_task_sender: Sender, + out: mpsc::Sender<(Vec, SocketAddr)>, + scheduled_task_sender: mpsc::Sender, ) -> BootstrapStatus where H: HandshakerTrait + 'static, @@ -160,8 +160,8 @@ impl TableBootstrap { &self, trans_id: TransactionID, table: Arc>, - out: Sender<(Vec, SocketAddr)>, - scheduled_task_sender: Sender, + out: mpsc::Sender<(Vec, SocketAddr)>, + scheduled_task_sender: mpsc::Sender, ) -> BootstrapStatus where H: HandshakerTrait + 'static, @@ -186,8 +186,8 @@ impl TableBootstrap { fn bootstrap_next_bucket( &self, table: Arc>, - out: Sender<(Vec, SocketAddr)>, - scheduled_task_sender: Sender, + out: mpsc::Sender<(Vec, SocketAddr)>, + scheduled_task_sender: mpsc::Sender, ) -> BoxFuture<'_, BootstrapStatus> where H: HandshakerTrait + 'static, @@ -277,8 +277,8 @@ impl TableBootstrap { nodes: I, target_id: NodeId, table: Arc>, - mut out: Sender<(Vec, SocketAddr)>, - scheduled_task_sender: Sender, + mut out: mpsc::Sender<(Vec, SocketAddr)>, + scheduled_task_sender: mpsc::Sender, ) -> BootstrapStatus where I: Iterator, diff --git a/packages/dht/src/worker/handler.rs b/packages/dht/src/worker/handler.rs index 8d5bd8322..55bb46771 100644 --- a/packages/dht/src/worker/handler.rs +++ b/packages/dht/src/worker/handler.rs @@ -5,7 +5,7 @@ use std::sync::atomic::{AtomicBool, AtomicUsize, Ordering}; use std::sync::{Arc, Mutex, RwLock}; use bencode::{ben_bytes, BDecodeOpt, BencodeMut, BencodeRef}; -use futures::channel::mpsc::{self, Sender}; +use futures::channel::mpsc; use futures::future::BoxFuture; use futures::{FutureExt, SinkExt, StreamExt as _}; use tokio::net::UdpSocket; @@ -47,12 +47,12 @@ enum Task { #[allow(clippy::module_name_repetitions)] pub fn create_dht_handler( table: RoutingTable, - out: Sender<(Vec, SocketAddr)>, + out: mpsc::Sender<(Vec, SocketAddr)>, read_only: bool, handshaker: H, kill_sock: Arc, kill_addr: SocketAddr, -) -> (Sender, JoinSet<()>) +) -> (mpsc::Sender, JoinSet<()>) where H: HandshakerTrait + 'static, { @@ -125,9 +125,9 @@ pub struct DhtHandler { routing_table: Arc>, table_actions: Mutex>, - out_channel: Sender<(Vec, SocketAddr)>, - main_task_sender: Sender, - scheduled_task_sender: Sender, + out_channel: mpsc::Sender<(Vec, SocketAddr)>, + main_task_sender: mpsc::Sender, + scheduled_task_sender: mpsc::Sender, read_only: bool, bootstrapping: AtomicBool, @@ -139,7 +139,7 @@ pub struct DhtHandler { // If future actions is not empty, that means we are still bootstrapping // since we will always spin up a table refresh action after bootstrapping. future_actions: Mutex>, - event_notifiers: Mutex>>, + event_notifiers: Mutex>>, } impl DhtHandler @@ -148,9 +148,9 @@ where { fn new( table: RoutingTable, - out: Sender<(Vec, SocketAddr)>, - main_task_sender: Sender, - scheduled_task_sender: Sender, + out: mpsc::Sender<(Vec, SocketAddr)>, + main_task_sender: mpsc::Sender, + scheduled_task_sender: mpsc::Sender, read_only: bool, handshaker: H, ) -> DhtHandler { @@ -629,7 +629,7 @@ where } } - fn handle_register_sender(&self, sender: Sender) { + fn handle_register_sender(&self, sender: mpsc::Sender) { self.event_notifiers.lock().unwrap().push(sender); } @@ -1005,9 +1005,9 @@ fn attempt_rebootstrap( bootstrap: Arc, attempts: Arc, routing_table: Arc>, - out: Sender<(Vec, SocketAddr)>, - main_task_sender: Sender, - scheduled_task_sender: Sender, + out: mpsc::Sender<(Vec, SocketAddr)>, + main_task_sender: mpsc::Sender, + scheduled_task_sender: mpsc::Sender, ) -> BoxFuture<'static, Option> { async move { // Increment the bootstrap counter @@ -1042,7 +1042,7 @@ fn attempt_rebootstrap( } /// Shut down the event loop by sending it a shutdown message with the given cause. -async fn shutdown_event_loop(mut main_task_sender: Sender, cause: ShutdownCause) { +async fn shutdown_event_loop(mut main_task_sender: mpsc::Sender, cause: ShutdownCause) { if main_task_sender.send(OneshotTask::Shutdown(cause)).await.is_err() { tracing::error!("bip_dht: Failed to send a shutdown message to the EventLoop..."); } diff --git a/packages/dht/src/worker/lookup.rs b/packages/dht/src/worker/lookup.rs index 60f46498a..e1643bf08 100644 --- a/packages/dht/src/worker/lookup.rs +++ b/packages/dht/src/worker/lookup.rs @@ -1,11 +1,11 @@ use std::collections::{HashMap, HashSet}; -use std::fmt::Debug; use std::net::{SocketAddr, SocketAddrV4}; use std::sync::atomic::{AtomicBool, Ordering}; use std::sync::{Arc, Mutex, RwLock}; use bencode::BRefAccess; -use futures::channel::mpsc::{SendError, Sender}; +use futures::channel::mpsc; +use futures::channel::mpsc::SendError; use futures::future::BoxFuture; use futures::{FutureExt, SinkExt as _}; use tokio::task::JoinSet; @@ -63,8 +63,8 @@ impl TableLookup { id_generator: MIDGenerator, will_announce: bool, table: Arc>, - out: Sender<(Vec, SocketAddr)>, - scheduled_task_sender: Sender, + out: mpsc::Sender<(Vec, SocketAddr)>, + scheduled_task_sender: mpsc::Sender, ) -> BoxFuture<'a, Option> { async move { let all_sorted_nodes = Mutex::new(Vec::with_capacity(bucket::MAX_BUCKET_SIZE)); @@ -128,12 +128,12 @@ impl TableLookup { trans_id: TransactionID, msg: GetPeersResponse<'_, B>, table: Arc>, - out: Sender<(Vec, SocketAddr)>, - scheduled_task_sender: Sender, + out: mpsc::Sender<(Vec, SocketAddr)>, + scheduled_task_sender: mpsc::Sender, ) -> LookupStatus where B: BRefAccess + Clone, - B::BType: PartialEq + Eq + core::hash::Hash + Debug, + B::BType: PartialEq + Eq + core::hash::Hash + std::fmt::Debug, { let Some((dist_to_beat, _)) = self.active_lookups.lock().unwrap().remove(&trans_id) else { tracing::warn!( @@ -236,8 +236,8 @@ impl TableLookup { &self, trans_id: TransactionID, table: Arc>, - out: Sender<(Vec, SocketAddr)>, - scheduled_task_sender: Sender, + out: mpsc::Sender<(Vec, SocketAddr)>, + scheduled_task_sender: mpsc::Sender, ) -> LookupStatus { if self.active_lookups.lock().unwrap().remove(&trans_id).is_none() { tracing::warn!( @@ -261,7 +261,7 @@ impl TableLookup { &self, handshake_port: u16, table: Arc>, - mut out: Sender<(Vec, SocketAddr)>, + mut out: mpsc::Sender<(Vec, SocketAddr)>, ) -> LookupStatus { let mut fatal_error = false; @@ -336,8 +336,8 @@ impl TableLookup { &self, nodes: I, table: Arc>, - mut out: Sender<(Vec, SocketAddr)>, - scheduled_task_sender: &Sender, + mut out: mpsc::Sender<(Vec, SocketAddr)>, + scheduled_task_sender: &mpsc::Sender, ) -> LookupStatus where I: Iterator, @@ -398,8 +398,8 @@ impl TableLookup { async fn start_endgame_round( &self, table: Arc>, - mut out: Sender<(Vec, SocketAddr)>, - _scheduled_task_sender: Sender, + mut out: mpsc::Sender<(Vec, SocketAddr)>, + _scheduled_task_sender: mpsc::Sender, ) -> LookupStatus { self.in_endgame.store(true, Ordering::SeqCst); diff --git a/packages/dht/src/worker/messenger.rs b/packages/dht/src/worker/messenger.rs index 5af051eab..38808fefc 100644 --- a/packages/dht/src/worker/messenger.rs +++ b/packages/dht/src/worker/messenger.rs @@ -1,7 +1,7 @@ use std::net::SocketAddr; use std::sync::Arc; -use futures::channel::mpsc::{self, Receiver, Sender}; +use futures::channel::mpsc; use futures::stream::StreamExt; use futures::SinkExt as _; use tokio::net::UdpSocket; @@ -12,9 +12,9 @@ use crate::worker::OneshotTask; const OUTGOING_MESSAGE_CAPACITY: usize = 4096; #[allow(clippy::module_name_repetitions)] -pub fn create_outgoing_messenger(socket: &Arc) -> Sender<(Vec, SocketAddr)> { +pub fn create_outgoing_messenger(socket: &Arc) -> mpsc::Sender<(Vec, SocketAddr)> { #[allow(clippy::type_complexity)] - let (send, mut recv): (Sender<(Vec, SocketAddr)>, Receiver<(Vec, SocketAddr)>) = + let (send, mut recv): (mpsc::Sender<(Vec, SocketAddr)>, mpsc::Receiver<(Vec, SocketAddr)>) = mpsc::channel(OUTGOING_MESSAGE_CAPACITY); let socket = socket.clone(); @@ -50,7 +50,7 @@ async fn send_bytes(socket: &UdpSocket, bytes: &[u8], addr: SocketAddr) { } #[allow(clippy::module_name_repetitions)] -pub fn create_incoming_messenger(socket: Arc, send: Sender) { +pub fn create_incoming_messenger(socket: Arc, send: mpsc::Sender) { task::spawn(async move { let mut buffer = vec![0u8; 1500]; @@ -72,6 +72,6 @@ pub fn create_incoming_messenger(socket: Arc, send: Sender, bytes: Vec, addr: SocketAddr) -> bool { +async fn send_message(send: &mpsc::Sender, bytes: Vec, addr: SocketAddr) -> bool { send.clone().send(OneshotTask::Incoming(bytes, addr)).await.is_ok() } diff --git a/packages/dht/src/worker/mod.rs b/packages/dht/src/worker/mod.rs index 9a78924ad..fd21e1d87 100644 --- a/packages/dht/src/worker/mod.rs +++ b/packages/dht/src/worker/mod.rs @@ -1,7 +1,7 @@ use std::net::SocketAddr; use std::sync::Arc; -use futures::channel::mpsc::Sender; +use futures::channel::mpsc; use tokio::net::UdpSocket; use tokio::task::JoinSet; use util::bt::InfoHash; @@ -23,7 +23,7 @@ pub enum OneshotTask { /// Process an incoming message from a remote node. Incoming(Vec, SocketAddr), /// Register a sender to send `DhtEvents` to. - RegisterSender(Sender), + RegisterSender(mpsc::Sender), /// Load a new bootstrap operation into worker storage. StartBootstrap(Vec, Vec), /// Start a lookup for the given `InfoHash`. @@ -78,7 +78,7 @@ pub fn start_mainline_dht( handshaker: H, kill_sock: Arc, kill_addr: SocketAddr, -) -> (Sender, JoinSet<()>) +) -> (mpsc::Sender, JoinSet<()>) where H: HandshakerTrait + 'static, { diff --git a/packages/dht/src/worker/refresh.rs b/packages/dht/src/worker/refresh.rs index 69bce12fc..aff63a398 100644 --- a/packages/dht/src/worker/refresh.rs +++ b/packages/dht/src/worker/refresh.rs @@ -2,7 +2,7 @@ use std::net::SocketAddr; use std::sync::atomic::{AtomicUsize, Ordering}; use std::sync::{Arc, Mutex, RwLock}; -use futures::channel::mpsc::{SendError, Sender}; +use futures::channel::mpsc::{self, SendError}; use futures::SinkExt as _; use tokio::task::JoinSet; use tokio::time::{sleep, Duration}; @@ -43,8 +43,8 @@ impl TableRefresh { pub async fn continue_refresh( &self, table: Arc>, - mut out: Sender<(Vec, SocketAddr)>, - mut scheduled_task_sender: Sender, + mut out: mpsc::Sender<(Vec, SocketAddr)>, + mut scheduled_task_sender: mpsc::Sender, ) -> RefreshStatus { let refresh_bucket = match self.curr_refresh_bucket.load(Ordering::Relaxed) { table::MAX_BUCKETS => { diff --git a/packages/disk/Cargo.toml b/packages/disk/Cargo.toml index 6b2c43583..608c70af0 100644 --- a/packages/disk/Cargo.toml +++ b/packages/disk/Cargo.toml @@ -1,7 +1,7 @@ [package] -name = "disk" description = "Bittorrent Infrastructure Project Disk Module" -keywords = ["filesystem", "fs", "disk"] +keywords = ["disk", "filesystem", "fs"] +name = "disk" readme = "README.md" authors.workspace = true @@ -19,21 +19,20 @@ version.workspace = true metainfo = { path = "../metainfo" } util = { path = "../util" } -crossbeam = "0" -pin-project = "1" bytes = "1" +crossbeam = "0" futures = "0" -tracing = "0" lru-cache = "0" -tokio = { version = "1", features = ["full"] } +pin-project = "1" thiserror = "1" +tokio = { version = "1", features = ["full"] } +tracing = "0" [dev-dependencies] -tracing-subscriber = "0" -rand = "0" criterion = { version = "0", features = ["async_tokio"] } - +rand = "0" +tracing-subscriber = "0" [[bench]] -name = "disk_benchmark" harness = false +name = "disk_benchmark" diff --git a/packages/disk/benches/disk_benchmark.rs b/packages/disk/benches/disk_benchmark.rs index 5fce17400..2fbc581a7 100644 --- a/packages/disk/benches/disk_benchmark.rs +++ b/packages/disk/benches/disk_benchmark.rs @@ -1,4 +1,3 @@ -use std::fs; use std::sync::Arc; use bytes::BytesMut; @@ -197,7 +196,7 @@ fn bench_native_fs_1_mb_pieces_128_kb_blocks(c: &mut Criterion) { let data_directory = "target/bench_data/bench_native_fs_1_mb_pieces_128_kb_blocks"; if WIPE_DATA_DIR { - drop(fs::remove_dir_all(data_directory)); + drop(std::fs::remove_dir_all(data_directory)); } let filesystem = NativeFileSystem::with_directory(data_directory); @@ -213,7 +212,7 @@ fn bench_native_fs_1_mb_pieces_16_kb_blocks(c: &mut Criterion) { let data_directory = "target/bench_data/bench_native_fs_1_mb_pieces_16_kb_blocks"; if WIPE_DATA_DIR { - drop(fs::remove_dir_all(data_directory)); + drop(std::fs::remove_dir_all(data_directory)); } let filesystem = NativeFileSystem::with_directory(data_directory); @@ -229,7 +228,7 @@ fn bench_native_fs_1_mb_pieces_2_kb_blocks(c: &mut Criterion) { let data_directory = "target/bench_data/bench_native_fs_1_mb_pieces_2_kb_blocks"; if WIPE_DATA_DIR { - drop(fs::remove_dir_all(data_directory)); + drop(std::fs::remove_dir_all(data_directory)); } let filesystem = NativeFileSystem::with_directory(data_directory); @@ -245,7 +244,7 @@ fn bench_file_handle_cache_fs_1_mb_pieces_128_kb_blocks(c: &mut Criterion) { let data_directory = "target/bench_data/bench_native_fs_1_mb_pieces_128_kb_blocks"; if WIPE_DATA_DIR { - drop(fs::remove_dir_all(data_directory)); + drop(std::fs::remove_dir_all(data_directory)); } let filesystem = FileHandleCache::new(NativeFileSystem::with_directory(data_directory), 1); @@ -261,7 +260,7 @@ fn bench_file_handle_cache_fs_1_mb_pieces_16_kb_blocks(c: &mut Criterion) { let data_directory = "target/bench_data/bench_native_fs_1_mb_pieces_16_kb_blocks"; if WIPE_DATA_DIR { - drop(fs::remove_dir_all(data_directory)); + drop(std::fs::remove_dir_all(data_directory)); } let filesystem = FileHandleCache::new(NativeFileSystem::with_directory(data_directory), 1); @@ -277,7 +276,7 @@ fn bench_file_handle_cache_fs_1_mb_pieces_2_kb_blocks(c: &mut Criterion) { let data_directory = "target/bench_data/bench_native_fs_1_mb_pieces_2_kb_blocks"; if WIPE_DATA_DIR { - drop(fs::remove_dir_all(data_directory)); + drop(std::fs::remove_dir_all(data_directory)); } let filesystem = FileHandleCache::new(NativeFileSystem::with_directory(data_directory), 1); diff --git a/packages/disk/examples/add_torrent.rs b/packages/disk/examples/add_torrent.rs index 46d000cb0..f2bab7fe5 100644 --- a/packages/disk/examples/add_torrent.rs +++ b/packages/disk/examples/add_torrent.rs @@ -1,5 +1,4 @@ -use std::fs::File; -use std::io::{BufRead, Read, Write}; +use std::io::{BufRead, Read as _, Write as _}; use std::sync::{Arc, Once}; use disk::fs::NativeFileSystem; @@ -39,7 +38,10 @@ async fn main() { let torrent_path = input_lines.next().unwrap().unwrap(); let mut torrent_bytes = Vec::new(); - File::open(torrent_path).unwrap().read_to_end(&mut torrent_bytes).unwrap(); + std::fs::File::open(torrent_path) + .unwrap() + .read_to_end(&mut torrent_bytes) + .unwrap(); let metainfo_file = Metainfo::from_bytes(torrent_bytes).unwrap(); let filesystem = NativeFileSystem::with_directory(download_path); diff --git a/packages/disk/src/disk/fs/native.rs b/packages/disk/src/disk/fs/native.rs index 9f13924d3..a48a34644 100644 --- a/packages/disk/src/disk/fs/native.rs +++ b/packages/disk/src/disk/fs/native.rs @@ -1,6 +1,5 @@ use std::borrow::Cow; -use std::fs::{self, File, OpenOptions}; -use std::io::{Read, Seek, SeekFrom, Write}; +use std::io::{Read as _, Seek as _, Write as _}; use std::path::{Path, PathBuf}; use crate::disk::fs::FileSystem; @@ -10,12 +9,12 @@ use crate::disk::fs::FileSystem; /// File that exists on disk. #[allow(clippy::module_name_repetitions)] pub struct NativeFile { - file: File, + file: std::fs::File, } impl NativeFile { /// Create a new `NativeFile`. - fn new(file: File) -> NativeFile { + fn new(file: std::fs::File) -> NativeFile { NativeFile { file } } } @@ -63,13 +62,13 @@ impl FileSystem for NativeFileSystem { } fn read_file(&self, file: &mut NativeFile, offset: u64, buffer: &mut [u8]) -> std::io::Result { - file.file.seek(SeekFrom::Start(offset))?; + file.file.seek(std::io::SeekFrom::Start(offset))?; file.file.read(buffer) } fn write_file(&self, file: &mut NativeFile, offset: u64, buffer: &[u8]) -> std::io::Result { - file.file.seek(SeekFrom::Start(offset))?; + file.file.seek(std::io::SeekFrom::Start(offset))?; file.file.write(buffer) } @@ -78,15 +77,15 @@ impl FileSystem for NativeFileSystem { /// Create a new file with read and write options. /// /// Intermediate directories will be created if they do not exist. -fn create_new_file

(path: P) -> std::io::Result +fn create_new_file

(path: P) -> std::io::Result where P: AsRef, { match path.as_ref().parent() { Some(parent_dir) => { - fs::create_dir_all(parent_dir)?; + std::fs::create_dir_all(parent_dir)?; - OpenOptions::new() + std::fs::OpenOptions::new() .read(true) .write(true) .create(true) diff --git a/packages/disk/src/disk/manager.rs b/packages/disk/src/disk/manager.rs deleted file mode 100644 index 6b0355d61..000000000 --- a/packages/disk/src/disk/manager.rs +++ /dev/null @@ -1,292 +0,0 @@ -use std::sync::atomic::{AtomicUsize, Ordering}; -use std::sync::{Arc, Mutex}; - -use crossbeam::queue::SegQueue; -use futures::channel::mpsc::{self, Receiver}; -use futures::task::{Context, Poll, Waker}; -use futures::{Stream, StreamExt}; -use pin_project::pin_project; -use tokio::task::JoinSet; - -use crate::disk::builder::DiskManagerBuilder; -use crate::disk::fs::FileSystem; -use crate::disk::tasks::context::DiskManagerContext; -use crate::disk::{tasks, IDiskMessage, ODiskMessage}; - -/// `DiskManager` object which handles the storage of `Blocks` to the `FileSystem`. -#[allow(clippy::module_name_repetitions)] -#[pin_project] -#[derive(Debug)] -pub struct DiskManager -where - F: FileSystem + Sync + 'static, - Arc: Send + Sync, -{ - #[pin] - sink: DiskManagerSink, - #[pin] - stream: DiskManagerStream, -} - -impl DiskManager -where - F: FileSystem + Sync + 'static, - Arc: Send + Sync, -{ - /// Create a `DiskManager` from the given `DiskManagerBuilder`. - pub fn from_builder(builder: &DiskManagerBuilder, fs: Arc) -> DiskManager { - let cur_sink_capacity = Arc::new(AtomicUsize::new(0)); - let sink_capacity = builder.sink_buffer_capacity(); - let stream_capacity = builder.stream_buffer_capacity(); - - let (out_send, out_recv) = mpsc::channel(stream_capacity); - let context = DiskManagerContext::new(out_send, fs); - let wake_queue = Arc::new(SegQueue::new()); - - let sink = DiskManagerSink::new(context, sink_capacity, cur_sink_capacity.clone(), wake_queue.clone()); - let stream = DiskManagerStream::new(out_recv, cur_sink_capacity, wake_queue.clone()); - - DiskManager { sink, stream } - } - - /// Break the `DiskManager` into a sink and stream. - /// - /// The returned sink implements `Clone`. - #[must_use] - pub fn into_parts(self) -> (DiskManagerSink, DiskManagerStream) { - (self.sink, self.stream) - } -} - -impl futures::Sink for DiskManager -where - F: FileSystem + Send + Sync + 'static, -{ - type Error = std::io::Error; - - fn poll_ready(self: std::pin::Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { - self.project().sink.poll_ready(cx) - } - - fn start_send(self: std::pin::Pin<&mut Self>, item: IDiskMessage) -> Result<(), Self::Error> { - self.project().sink.start_send(item) - } - - fn poll_flush(self: std::pin::Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { - self.project().sink.poll_flush(cx) - } - - fn poll_close(self: std::pin::Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { - self.project().sink.poll_close(cx) - } -} - -impl Stream for DiskManager -where - F: FileSystem + Sync + 'static, - Arc: Send + Sync, -{ - type Item = Result; - - fn poll_next(self: std::pin::Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { - self.project().stream.poll_next(cx) - } -} - -//----------------------------------------------------------------------------// - -/// `DiskManagerSink` which is the sink portion of a `DiskManager`. -#[derive(Debug)] -pub struct DiskManagerSink -where - F: FileSystem + Sync + 'static, - Arc: Send + Sync, -{ - context: DiskManagerContext, - max_capacity: usize, - cur_capacity: Arc, - wake_queue: Arc>, - task_set: Arc>>, -} - -impl Clone for DiskManagerSink -where - F: FileSystem + Sync + 'static, - Arc: Send + Sync, -{ - fn clone(&self) -> DiskManagerSink { - DiskManagerSink { - context: self.context.clone(), - max_capacity: self.max_capacity, - cur_capacity: self.cur_capacity.clone(), - wake_queue: self.wake_queue.clone(), - task_set: self.task_set.clone(), - } - } -} - -impl DiskManagerSink -where - F: FileSystem + Sync + 'static, - Arc: Send + Sync, -{ - fn new( - context: DiskManagerContext, - max_capacity: usize, - cur_capacity: Arc, - wake_queue: Arc>, - ) -> DiskManagerSink { - DiskManagerSink { - context, - max_capacity, - cur_capacity, - wake_queue, - task_set: Arc::default(), - } - } - - fn try_submit_work(&self, waker: &Waker) -> Result { - let cap = self.cur_capacity.fetch_add(1, Ordering::SeqCst) + 1; - let max = self.max_capacity; - - #[allow(clippy::comparison_chain)] - if cap < max { - tracing::trace!("now have {cap} of capacity: {max}"); - - Ok(cap) - } else if cap == max { - tracing::trace!("at max capacity: {max}"); - - Ok(cap) - } else { - self.wake_queue.push(waker.clone()); - tracing::debug!("now have {} pending wakers...", self.wake_queue.len()); - - self.cur_capacity.fetch_sub(1, Ordering::SeqCst); - tracing::debug!("at over capacity: {cap} of {max}"); - - Err(cap) - } - } -} - -impl futures::Sink for DiskManagerSink -where - F: FileSystem + Sync + 'static, - Arc: Send + Sync, -{ - type Error = std::io::Error; - - fn poll_ready(self: std::pin::Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { - match self.try_submit_work(cx.waker()) { - Ok(_remaining) => Poll::Ready(Ok(())), - Err(_full) => Poll::Pending, - } - } - - fn start_send(self: std::pin::Pin<&mut Self>, item: IDiskMessage) -> Result<(), Self::Error> { - tracing::trace!("Starting Send For DiskManagerSink With IDiskMessage"); - self.task_set - .lock() - .unwrap() - .spawn(tasks::execute(item, self.context.clone())); - Ok(()) - } - - fn poll_flush(self: std::pin::Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { - let Ok(mut task_set) = self.task_set.try_lock() else { - tracing::warn!("unable to get task_set lock"); - cx.waker().wake_by_ref(); - return Poll::Pending; - }; - - tracing::debug!("flushing the {} tasks", task_set.len()); - - while let Some(ready) = match task_set.poll_join_next(cx) { - Poll::Ready(ready) => ready, - Poll::Pending => { - tracing::debug!("all {} task(s) are still pending...", task_set.len()); - return Poll::Pending; - } - } { - match ready { - Ok(()) => { - tracing::trace!("task completed... with {} remaining...", task_set.len()); - - continue; - } - Err(e) => { - tracing::error!("task completed... with {} remaining, with error: {e}", task_set.len()); - - return Poll::Ready(Err(std::io::Error::new(std::io::ErrorKind::Other, e))); - } - } - } - - Poll::Ready(Ok(())) - } - - fn poll_close(self: std::pin::Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { - self.poll_flush(cx) - } -} - -//----------------------------------------------------------------------------// - -/// `DiskManagerStream` which is the stream portion of a `DiskManager`. -#[derive(Debug)] -pub struct DiskManagerStream { - recv: Receiver, - pub cur_capacity: Arc, - wake_queue: Arc>, -} - -impl DiskManagerStream { - fn new(recv: Receiver, cur_capacity: Arc, wake_queue: Arc>) -> DiskManagerStream { - DiskManagerStream { - recv, - cur_capacity, - wake_queue, - } - } - - fn complete_work(&self) -> usize { - let cap = self.cur_capacity.fetch_sub(1, Ordering::SeqCst) - 1; - - tracing::debug!( - "Notify next waker: {} that there is space again: {cap}", - self.wake_queue.len() - ); - if let Some(waker) = self.wake_queue.pop() { - waker.wake(); - }; - - cap - } -} - -impl Stream for DiskManagerStream { - type Item = Result; - - fn poll_next(mut self: std::pin::Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { - tracing::trace!("Polling DiskManagerStream For ODiskMessage"); - - match self.recv.poll_next_unpin(cx) { - Poll::Ready(Some(msg)) => { - match msg { - ODiskMessage::TorrentAdded(_) - | ODiskMessage::TorrentRemoved(_) - | ODiskMessage::TorrentSynced(_) - | ODiskMessage::BlockLoaded(_) - | ODiskMessage::BlockProcessed(_) => { - self.complete_work(); - } - _ => {} - } - Poll::Ready(Some(Ok(msg))) - } - Poll::Ready(None) => Poll::Ready(None), - Poll::Pending => Poll::Pending, - } - } -} diff --git a/packages/disk/src/disk/manager/mod.rs b/packages/disk/src/disk/manager/mod.rs new file mode 100644 index 000000000..1b8efef72 --- /dev/null +++ b/packages/disk/src/disk/manager/mod.rs @@ -0,0 +1,98 @@ +//! `DiskManager` object which handles the storage of `Blocks` to the `FileSystem`. + +use std::sync::atomic::AtomicUsize; +use std::sync::Arc; +use std::task::{Context, Poll}; + +use crossbeam::queue::SegQueue; +use futures::channel::mpsc; +use futures::Stream; +use pin_project::pin_project; +pub use sink::DiskManagerSink; +pub use stream::DiskManagerStream; + +use super::tasks::context::DiskManagerContext; +use super::{IDiskMessage, ODiskMessage}; +use crate::{DiskManagerBuilder, FileSystem}; + +pub mod sink; +pub mod stream; + +#[allow(clippy::module_name_repetitions)] +#[pin_project] +#[derive(Debug)] +pub struct DiskManager +where + F: FileSystem + Sync + 'static, + Arc: Send + Sync, +{ + #[pin] + sink: DiskManagerSink, + #[pin] + stream: DiskManagerStream, +} + +impl DiskManager +where + F: FileSystem + Sync + 'static, + Arc: Send + Sync, +{ + /// Create a `DiskManager` from the given `DiskManagerBuilder`. + pub fn from_builder(builder: &DiskManagerBuilder, fs: Arc) -> DiskManager { + let cur_sink_capacity = Arc::new(AtomicUsize::new(0)); + let sink_capacity = builder.sink_buffer_capacity(); + let stream_capacity = builder.stream_buffer_capacity(); + + let (out_send, out_recv) = mpsc::channel(stream_capacity); + let context = DiskManagerContext::new(out_send, fs); + let wake_queue = Arc::new(SegQueue::new()); + + let sink = DiskManagerSink::new(context, sink_capacity, cur_sink_capacity.clone(), wake_queue.clone()); + let stream = DiskManagerStream::new(out_recv, cur_sink_capacity, wake_queue.clone()); + + DiskManager { sink, stream } + } + + /// Break the `DiskManager` into a sink and stream. + /// + /// The returned sink implements `Clone`. + #[must_use] + pub fn into_parts(self) -> (DiskManagerSink, DiskManagerStream) { + (self.sink, self.stream) + } +} + +impl futures::Sink for DiskManager +where + F: FileSystem + Send + Sync + 'static, +{ + type Error = std::io::Error; + + fn poll_ready(self: std::pin::Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { + self.project().sink.poll_ready(cx) + } + + fn start_send(self: std::pin::Pin<&mut Self>, item: IDiskMessage) -> Result<(), Self::Error> { + self.project().sink.start_send(item) + } + + fn poll_flush(self: std::pin::Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { + self.project().sink.poll_flush(cx) + } + + fn poll_close(self: std::pin::Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { + self.project().sink.poll_close(cx) + } +} + +impl Stream for DiskManager +where + F: FileSystem + Sync + 'static, + Arc: Send + Sync, +{ + type Item = Result; + + fn poll_next(self: std::pin::Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { + self.project().stream.poll_next(cx) + } +} diff --git a/packages/disk/src/disk/manager/sink.rs b/packages/disk/src/disk/manager/sink.rs new file mode 100644 index 000000000..8ac81dac3 --- /dev/null +++ b/packages/disk/src/disk/manager/sink.rs @@ -0,0 +1,148 @@ +//! `DiskManagerSink` which is the sink portion of a `DiskManager`. + +use std::sync::atomic::{AtomicUsize, Ordering}; +use std::sync::{Arc, Mutex}; +use std::task::{Context, Poll, Waker}; + +use crossbeam::queue::SegQueue; +use tokio::task::JoinSet; + +use crate::disk::tasks; +use crate::disk::tasks::context::DiskManagerContext; +use crate::{FileSystem, IDiskMessage}; + +#[allow(clippy::module_name_repetitions)] +#[derive(Debug)] +pub struct DiskManagerSink +where + F: FileSystem + Sync + 'static, + Arc: Send + Sync, +{ + context: DiskManagerContext, + max_capacity: usize, + cur_capacity: Arc, + wake_queue: Arc>, + task_set: Arc>>, +} + +impl Clone for DiskManagerSink +where + F: FileSystem + Sync + 'static, + Arc: Send + Sync, +{ + fn clone(&self) -> DiskManagerSink { + DiskManagerSink { + context: self.context.clone(), + max_capacity: self.max_capacity, + cur_capacity: self.cur_capacity.clone(), + wake_queue: self.wake_queue.clone(), + task_set: self.task_set.clone(), + } + } +} + +impl DiskManagerSink +where + F: FileSystem + Sync + 'static, + Arc: Send + Sync, +{ + pub(super) fn new( + context: DiskManagerContext, + max_capacity: usize, + cur_capacity: Arc, + wake_queue: Arc>, + ) -> DiskManagerSink { + DiskManagerSink { + context, + max_capacity, + cur_capacity, + wake_queue, + task_set: Arc::default(), + } + } + + fn try_submit_work(&self, waker: &Waker) -> Result { + let cap = self.cur_capacity.fetch_add(1, Ordering::SeqCst) + 1; + let max = self.max_capacity; + + #[allow(clippy::comparison_chain)] + if cap < max { + tracing::trace!("now have {cap} of capacity: {max}"); + + Ok(cap) + } else if cap == max { + tracing::trace!("at max capacity: {max}"); + + Ok(cap) + } else { + self.wake_queue.push(waker.clone()); + tracing::debug!("now have {} pending wakers...", self.wake_queue.len()); + + self.cur_capacity.fetch_sub(1, Ordering::SeqCst); + tracing::debug!("at over capacity: {cap} of {max}"); + + Err(cap) + } + } +} + +impl futures::Sink for DiskManagerSink +where + F: FileSystem + Sync + 'static, + Arc: Send + Sync, +{ + type Error = std::io::Error; + + fn poll_ready(self: std::pin::Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { + match self.try_submit_work(cx.waker()) { + Ok(_remaining) => Poll::Ready(Ok(())), + Err(_full) => Poll::Pending, + } + } + + fn start_send(self: std::pin::Pin<&mut Self>, item: IDiskMessage) -> Result<(), Self::Error> { + tracing::trace!("Starting Send For DiskManagerSink With IDiskMessage"); + self.task_set + .lock() + .unwrap() + .spawn(tasks::execute(item, self.context.clone())); + Ok(()) + } + + fn poll_flush(self: std::pin::Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { + let Ok(mut task_set) = self.task_set.try_lock() else { + tracing::warn!("unable to get task_set lock"); + cx.waker().wake_by_ref(); + return Poll::Pending; + }; + + tracing::debug!("flushing the {} tasks", task_set.len()); + + while let Some(ready) = match task_set.poll_join_next(cx) { + Poll::Ready(ready) => ready, + Poll::Pending => { + tracing::debug!("all {} task(s) are still pending...", task_set.len()); + return Poll::Pending; + } + } { + match ready { + Ok(()) => { + tracing::trace!("task completed... with {} remaining...", task_set.len()); + + continue; + } + Err(e) => { + tracing::error!("task completed... with {} remaining, with error: {e}", task_set.len()); + + return Poll::Ready(Err(std::io::Error::new(std::io::ErrorKind::Other, e))); + } + } + } + + Poll::Ready(Ok(())) + } + + fn poll_close(self: std::pin::Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { + self.poll_flush(cx) + } +} diff --git a/packages/disk/src/disk/manager/stream.rs b/packages/disk/src/disk/manager/stream.rs new file mode 100644 index 000000000..1bccdb188 --- /dev/null +++ b/packages/disk/src/disk/manager/stream.rs @@ -0,0 +1,73 @@ +//! `DiskManagerStream` which is the stream portion of a `DiskManager`. + +use std::sync::atomic::{AtomicUsize, Ordering}; +use std::sync::Arc; +use std::task::{Context, Poll, Waker}; + +use crossbeam::queue::SegQueue; +use futures::channel::mpsc; +use futures::{Stream, StreamExt as _}; + +use crate::ODiskMessage; + +#[allow(clippy::module_name_repetitions)] +#[derive(Debug)] +pub struct DiskManagerStream { + recv: mpsc::Receiver, + pub cur_capacity: Arc, + wake_queue: Arc>, +} + +impl DiskManagerStream { + pub(super) fn new( + recv: mpsc::Receiver, + cur_capacity: Arc, + wake_queue: Arc>, + ) -> DiskManagerStream { + DiskManagerStream { + recv, + cur_capacity, + wake_queue, + } + } + + fn complete_work(&self) -> usize { + let cap = self.cur_capacity.fetch_sub(1, Ordering::SeqCst) - 1; + + tracing::debug!( + "Notify next waker: {} that there is space again: {cap}", + self.wake_queue.len() + ); + if let Some(waker) = self.wake_queue.pop() { + waker.wake(); + }; + + cap + } +} + +impl Stream for DiskManagerStream { + type Item = Result; + + fn poll_next(mut self: std::pin::Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { + tracing::trace!("Polling DiskManagerStream For ODiskMessage"); + + match self.recv.poll_next_unpin(cx) { + Poll::Ready(Some(msg)) => { + match msg { + ODiskMessage::TorrentAdded(_) + | ODiskMessage::TorrentRemoved(_) + | ODiskMessage::TorrentSynced(_) + | ODiskMessage::BlockLoaded(_) + | ODiskMessage::BlockProcessed(_) => { + self.complete_work(); + } + _ => {} + } + Poll::Ready(Some(Ok(msg))) + } + Poll::Ready(None) => Poll::Ready(None), + Poll::Pending => Poll::Pending, + } + } +} diff --git a/packages/disk/src/disk/tasks/context.rs b/packages/disk/src/disk/tasks/context.rs index 6bc5dd0dd..e5d0fbe99 100644 --- a/packages/disk/src/disk/tasks/context.rs +++ b/packages/disk/src/disk/tasks/context.rs @@ -2,7 +2,7 @@ use std::collections::hash_map::Entry; use std::collections::HashMap; use std::sync::{Arc, RwLock}; -use futures::channel::mpsc::Sender; +use futures::channel::mpsc; use futures::future::BoxFuture; use futures::lock::Mutex; use futures::sink::SinkExt; @@ -21,7 +21,7 @@ where Arc: Send + Sync, { torrents: Arc>>, - pub out: Sender, + pub out: mpsc::Sender, fs: Arc, } @@ -56,7 +56,7 @@ where F: FileSystem + Sync + 'static, Arc: Send + Sync, { - pub fn new(out: Sender, fs: Arc) -> DiskManagerContext { + pub fn new(out: mpsc::Sender, fs: Arc) -> DiskManagerContext { DiskManagerContext { torrents: Arc::new(RwLock::new(HashMap::new())), out, diff --git a/packages/disk/src/disk/tasks/helpers/piece_accessor.rs b/packages/disk/src/disk/tasks/helpers/piece_accessor.rs index 5f3057079..57a461bad 100644 --- a/packages/disk/src/disk/tasks/helpers/piece_accessor.rs +++ b/packages/disk/src/disk/tasks/helpers/piece_accessor.rs @@ -1,4 +1,3 @@ -use std::cmp; use std::sync::Arc; use crate::disk::fs::FileSystem; @@ -52,7 +51,7 @@ where let total_file_size = file.length(); let mut bytes_to_access = total_file_size; - let min_bytes_to_skip = cmp::min(total_bytes_to_skip, bytes_to_access); + let min_bytes_to_skip = std::cmp::min(total_bytes_to_skip, bytes_to_access); total_bytes_to_skip -= min_bytes_to_skip; bytes_to_access -= min_bytes_to_skip; @@ -62,7 +61,7 @@ where let fs_file = self.fs.open_file(file_path)?; let total_max_bytes_to_access = total_block_length - total_bytes_accessed; - let actual_bytes_to_access = cmp::min(total_max_bytes_to_access, bytes_to_access); + let actual_bytes_to_access = std::cmp::min(total_max_bytes_to_access, bytes_to_access); let offset = total_file_size - bytes_to_access; #[allow(clippy::cast_possible_truncation)] diff --git a/packages/disk/src/disk/tasks/helpers/piece_checker.rs b/packages/disk/src/disk/tasks/helpers/piece_checker.rs index 92fbf7d52..44f68ffdc 100644 --- a/packages/disk/src/disk/tasks/helpers/piece_checker.rs +++ b/packages/disk/src/disk/tasks/helpers/piece_checker.rs @@ -1,4 +1,3 @@ -use std::cmp; use std::collections::{HashMap, HashSet}; use std::sync::Arc; @@ -307,7 +306,7 @@ fn merge_piece_messages(message_a: &BlockMetadata, message_b: &BlockMetadata) -> // If start b falls between start and end a, then start a is where we start, and we end at the max of end a // or end b, then calculate the length from end minus start. Vice versa if a falls between start and end b. if start_b >= start_a && start_b <= end_a { - let end_to_take = cmp::max(end_a, end_b); + let end_to_take = std::cmp::max(end_a, end_b); let length = end_to_take - start_a; Some(BlockMetadata::new( @@ -317,7 +316,7 @@ fn merge_piece_messages(message_a: &BlockMetadata, message_b: &BlockMetadata) -> length.try_into().unwrap(), )) } else if start_a >= start_b && start_a <= end_b { - let end_to_take = cmp::max(end_a, end_b); + let end_to_take = std::cmp::max(end_a, end_b); let length = end_to_take - start_b; Some(BlockMetadata::new( diff --git a/packages/disk/src/disk/tasks/mod.rs b/packages/disk/src/disk/tasks/mod.rs index 526d6ea16..004a09e8d 100644 --- a/packages/disk/src/disk/tasks/mod.rs +++ b/packages/disk/src/disk/tasks/mod.rs @@ -1,6 +1,6 @@ use std::sync::Arc; -use futures::channel::mpsc::Sender; +use futures::channel::mpsc; use futures::lock::Mutex; use futures::{FutureExt, SinkExt as _}; use metainfo::Metainfo; @@ -61,7 +61,11 @@ where tracing::debug!("finished sending output message... "); } -async fn execute_add_torrent(file: Metainfo, context: DiskManagerContext, sender: Sender) -> TorrentResult<()> +async fn execute_add_torrent( + file: Metainfo, + context: DiskManagerContext, + sender: mpsc::Sender, +) -> TorrentResult<()> where F: FileSystem + Sync + 'static, Arc: Send + Sync, @@ -147,7 +151,11 @@ where } } -async fn execute_process_block(block: &Block, context: DiskManagerContext, sender: Sender) -> BlockResult<()> +async fn execute_process_block( + block: &Block, + context: DiskManagerContext, + sender: mpsc::Sender, +) -> BlockResult<()> where F: FileSystem + Sync + 'static, Arc: Send + Sync, @@ -191,7 +199,7 @@ where async fn send_piece_diff( checker_state: &Arc>, hash: InfoHash, - sender: Sender, + sender: mpsc::Sender, ignore_bad: bool, ) { checker_state diff --git a/packages/disk/src/error.rs b/packages/disk/src/error.rs index bfd473134..799ae0284 100644 --- a/packages/disk/src/error.rs +++ b/packages/disk/src/error.rs @@ -1,4 +1,3 @@ -use std::io; use std::path::PathBuf; use thiserror::Error; @@ -8,7 +7,7 @@ use util::bt::InfoHash; #[derive(Error, Debug)] pub enum BlockError { #[error("IO error")] - Io(#[from] io::Error), + Io(#[from] std::io::Error), #[error("Failed To Load/Process Block Because The InfoHash {hash:?} Is Not Currently Added")] InfoHashNotFound { hash: InfoHash }, @@ -23,7 +22,7 @@ pub enum TorrentError { Block(#[from] BlockError), #[error("IO error")] - Io(#[from] io::Error), + Io(#[from] std::io::Error), #[error("Failed To Add Torrent Because Size Checker Failed For {file_path:?} Where File Size Was {actual_size} But Should Have Been {expected_size}")] ExistingFileSizeCheck { diff --git a/packages/disk/tests/common/mod.rs b/packages/disk/tests/common/mod.rs index c089b85a8..2db3d0668 100644 --- a/packages/disk/tests/common/mod.rs +++ b/packages/disk/tests/common/mod.rs @@ -1,4 +1,3 @@ -use std::cmp; use std::collections::HashMap; use std::path::{Path, PathBuf}; use std::sync::{Arc, Mutex, Once, Weak}; @@ -237,7 +236,7 @@ impl FileSystem for InMemoryFileSystem { .get(&file.path) .map(|file_buffer| { let cast_offset: usize = offset.try_into().unwrap(); - let bytes_to_copy = cmp::min(file_buffer.len() - cast_offset, buffer.len()); + let bytes_to_copy = std::cmp::min(file_buffer.len() - cast_offset, buffer.len()); let bytes = &file_buffer[cast_offset..(bytes_to_copy + cast_offset)]; buffer.clone_from_slice(bytes); @@ -260,7 +259,7 @@ impl FileSystem for InMemoryFileSystem { file_buffer.resize(last_byte_pos, 0); } - let bytes_to_copy = cmp::min(file_buffer.len() - cast_offset, buffer.len()); + let bytes_to_copy = std::cmp::min(file_buffer.len() - cast_offset, buffer.len()); if bytes_to_copy != 0 { file_buffer[cast_offset..(cast_offset + bytes_to_copy)].clone_from_slice(buffer); diff --git a/packages/handshake/Cargo.toml b/packages/handshake/Cargo.toml index 7e26e71b5..705ea3d80 100644 --- a/packages/handshake/Cargo.toml +++ b/packages/handshake/Cargo.toml @@ -1,7 +1,7 @@ [package] -name = "handshake" description = "Common handshaking interface as well as a default handshake implementation" -keywords = ["handshake", "bittorrent"] +keywords = ["bittorrent", "handshake"] +name = "handshake" readme = "README.md" authors.workspace = true @@ -17,14 +17,14 @@ version.workspace = true [dependencies] util = { path = "../util" } + bytes = "1" futures = "0" -tokio = { version = "1", features = ["full"] } nom = "7" -rand = "0" pin-project = "1" +rand = "0" +tokio = { version = "1", features = ["full"] } tracing = "0" [dev-dependencies] tracing-subscriber = "0" - diff --git a/packages/handshake/examples/handshake_torrent.rs b/packages/handshake/examples/handshake_torrent.rs index 7c8bd5d4d..0d8bc20b8 100644 --- a/packages/handshake/examples/handshake_torrent.rs +++ b/packages/handshake/examples/handshake_torrent.rs @@ -1,4 +1,4 @@ -use std::io::{BufRead, Write}; +use std::io::BufRead as _; use std::net::{SocketAddr, ToSocketAddrs}; use std::time::Duration; @@ -45,12 +45,12 @@ async fn main() -> std::io::Result<()> { Ok(()) } -fn prompt(writer: &mut W, message: &str) -> std::io::Result<()> { +fn prompt(writer: &mut W, message: &str) -> std::io::Result<()> { writer.write_all(message.as_bytes())?; writer.flush() } -fn read_line(lines: &mut std::io::Lines) -> std::io::Result { +fn read_line(lines: &mut std::io::Lines) -> std::io::Result { lines.next().unwrap_or_else(|| Ok(String::new())) } diff --git a/packages/handshake/src/bittorrent/framed.rs b/packages/handshake/src/bittorrent/framed.rs index 3b7e350a1..06274b9db 100644 --- a/packages/handshake/src/bittorrent/framed.rs +++ b/packages/handshake/src/bittorrent/framed.rs @@ -1,7 +1,7 @@ //! This module provides the `FramedHandshake` struct, which implements a framed transport for the `BitTorrent` handshake protocol. //! It supports both reading from and writing to an underlying asynchronous stream, handling the framing of handshake messages. -use std::io::Cursor; + use std::pin::Pin; use std::task::{Context, Poll}; @@ -84,7 +84,7 @@ where #[instrument(skip(self))] fn start_send(mut self: Pin<&mut Self>, item: HandshakeMessage) -> Result<(), Self::Error> { tracing::trace!("start_send called with item: {item:?}"); - let mut cursor = Cursor::new(Vec::with_capacity(item.write_len())); + let mut cursor = std::io::Cursor::new(Vec::with_capacity(item.write_len())); item.write_bytes_sync(&mut cursor)?; self.write_buffer.reserve(item.write_len()); @@ -294,12 +294,12 @@ where #[cfg(test)] mod tests { - use std::io::Cursor; + use std::sync::Once; use futures::stream::StreamExt; use futures::SinkExt as _; - use tokio::io::AsyncWriteExt; + use tokio::io::{AsyncRead, AsyncReadExt as _, AsyncWriteExt as _}; use tracing::level_filters::LevelFilter; use util::bt::{self, InfoHash, PeerId}; @@ -340,22 +340,16 @@ mod tests { }); let mut v = vec![0; 100]; - //let mut buf = Cursor::new(v); + //let mut buf = std::io::Cursor::new(v); let mut read_buf = tokio::io::ReadBuf::new(&mut v); - let data: Box>> = Box::new(Cursor::new((0..100).collect())); + let data: Box>> = Box::new(std::io::Cursor::new((0..100).collect())); - let mut data_reader = &mut (data as Box); + let data_reader = &mut (data as Box); - let mut a = tokio::io::AsyncReadExt::read_buf(&mut data_reader, &mut read_buf) - .await - .unwrap(); - a += tokio::io::AsyncReadExt::read_buf(&mut data_reader, &mut read_buf) - .await - .unwrap(); - a += tokio::io::AsyncReadExt::read_buf(&mut data_reader, &mut read_buf) - .await - .unwrap(); + let mut a = data_reader.read_buf(&mut read_buf).await.unwrap(); + a += data_reader.read_buf(&mut read_buf).await.unwrap(); + a += data_reader.read_buf(&mut read_buf).await.unwrap(); assert_eq!(a, 100); } @@ -368,7 +362,7 @@ mod tests { let message = HandshakeMessage::from_parts(Protocol::BitTorrent, any_extensions(), any_info_hash(), any_peer_id()); - let mut framed_handshake = FramedHandshake::new(Cursor::new(Vec::new())); + let mut framed_handshake = FramedHandshake::new(std::io::Cursor::new(Vec::new())); framed_handshake.send(message.clone()).await.unwrap(); @@ -394,7 +388,7 @@ mod tests { any_peer_id(), ); - let mut framed_handshake = FramedHandshake::new(Cursor::new(Vec::new())); + let mut framed_handshake = FramedHandshake::new(std::io::Cursor::new(Vec::new())); framed_handshake.send(message_one.clone()).await.unwrap(); framed_handshake.send(message_two.clone()).await.unwrap(); @@ -417,7 +411,7 @@ mod tests { let exp_message = HandshakeMessage::from_parts(Protocol::BitTorrent, any_extensions(), any_info_hash(), any_peer_id()); tracing::trace!("Handshake Message: {:?}", exp_message); - let mut buffer = Cursor::new(Vec::new()); + let mut buffer = std::io::Cursor::new(Vec::new()); exp_message.write_bytes(&mut buffer).await.unwrap(); buffer.set_position(0); @@ -444,9 +438,9 @@ mod tests { let exp_message = HandshakeMessage::from_parts(Protocol::BitTorrent, any_extensions(), any_info_hash(), any_peer_id()); - let mut buffer = Cursor::new(Vec::new()); + let mut buffer = std::io::Cursor::new(Vec::new()); let () = exp_message.write_bytes(&mut buffer).await.unwrap(); - let () = AsyncWriteExt::write_all(&mut buffer, &[55]).await.unwrap(); + let () = buffer.write_all(&[55]).await.unwrap(); let () = buffer.set_position(0); tracing::trace!("Buffer before reading: {:?}", buffer); @@ -478,7 +472,7 @@ mod tests { // Write some bytes right after the handshake, make sure // our framed handshake doesn't read/buffer these (we need // to be able to read them afterwards) - drop(tokio::io::AsyncWriteExt::write_all(&mut buffer, &[55, 54, 21]).await); + drop(buffer.write_all(&[55, 54, 21]).await); let read_frame = { let mut frame = FramedHandshake::new(&buffer[..]); diff --git a/packages/handshake/src/bittorrent/message.rs b/packages/handshake/src/bittorrent/message.rs index 410485044..f828248d3 100644 --- a/packages/handshake/src/bittorrent/message.rs +++ b/packages/handshake/src/bittorrent/message.rs @@ -1,10 +1,8 @@ -use std::io::Write; - use nom::bytes::complete::take; use nom::combinator::map_res; use nom::sequence::tuple; use nom::IResult; -use tokio::io::{AsyncWrite, AsyncWriteExt}; +use tokio::io::{AsyncWrite, AsyncWriteExt as _}; use util::bt::{self, InfoHash, PeerId}; use crate::message::extensions::{self, Extensions}; @@ -53,7 +51,7 @@ impl HandshakeMessage { pub fn write_bytes_sync(&self, writer: &mut W) -> std::io::Result<()> where - W: Write, + W: std::io::Write, { self.prot.write_bytes_sync(writer)?; self.ext.write_bytes_sync(writer)?; @@ -106,7 +104,7 @@ fn parse_remote_pid(bytes: &[u8]) -> IResult<&[u8], PeerId> { #[cfg(test)] mod tests { - use std::io::Write; + use std::io::Write as _; use util::bt::{self, InfoHash, PeerId}; diff --git a/packages/handshake/src/filter/mod.rs b/packages/handshake/src/filter/mod.rs index 09f3a2a02..323e75e0f 100644 --- a/packages/handshake/src/filter/mod.rs +++ b/packages/handshake/src/filter/mod.rs @@ -1,5 +1,4 @@ use std::any::Any; -use std::cmp::{Eq, PartialEq}; use std::net::SocketAddr; use util::bt::{InfoHash, PeerId}; diff --git a/packages/handshake/src/handshake/builder.rs b/packages/handshake/src/handshake/builder.rs new file mode 100644 index 000000000..bd53929ee --- /dev/null +++ b/packages/handshake/src/handshake/builder.rs @@ -0,0 +1,109 @@ +use std::net::{Ipv4Addr, SocketAddr, SocketAddrV4}; + +use rand::Rng as _; +use tokio::io::{AsyncRead, AsyncWrite}; +use tokio::task::JoinSet; +use util::bt::PeerId; +use util::convert; + +use super::Handshaker; +use crate::{Extensions, HandshakerConfig, Transport}; + +/// Build configuration for `Handshaker` object creation. +#[allow(clippy::module_name_repetitions)] +#[derive(Copy, Clone)] +pub struct HandshakerBuilder { + pub(super) bind: SocketAddr, + pub(super) port: u16, + pub(super) pid: PeerId, + pub(super) ext: Extensions, + pub(super) config: HandshakerConfig, +} + +impl Default for HandshakerBuilder { + fn default() -> Self { + let default_v4_addr = Ipv4Addr::new(0, 0, 0, 0); + let default_v4_port = 0; + + let bind = SocketAddr::V4(SocketAddrV4::new(default_v4_addr, default_v4_port)); + + let seed = rand::thread_rng().gen(); + let pid = PeerId::from_bytes(&convert::four_bytes_to_array(seed)); + + Self { + bind, + port: Default::default(), + pid, + ext: Extensions::default(), + config: HandshakerConfig::default(), + } + } +} + +impl HandshakerBuilder { + /// Create a new `HandshakerBuilder`. + #[must_use] + pub fn new() -> HandshakerBuilder { + Self::default() + } + + /// Address that the host will listen on. + /// + /// Defaults to `IN_ADDR_ANY` using port 0 (any free port). + pub fn with_bind_addr(&mut self, addr: SocketAddr) -> &mut HandshakerBuilder { + self.bind = addr; + + self + } + + /// Port that external peers should connect on. + /// + /// Defaults to the port that is being listened on (will only work if the + /// host is not natted). + pub fn with_open_port(&mut self, port: u16) -> &mut HandshakerBuilder { + self.port = port; + + self + } + + /// Peer id that will be advertised when handshaking with other peers. + /// + /// Defaults to a random SHA-1 hash; official clients should use an encoding scheme. + /// + /// See [BEP 0020](http://www.bittorrent.org/beps/bep_0020.html). + pub fn with_peer_id(&mut self, peer_id: PeerId) -> &mut HandshakerBuilder { + self.pid = peer_id; + + self + } + + /// Extensions supported by our client, advertised to the peer when handshaking. + pub fn with_extensions(&mut self, ext: Extensions) -> &mut HandshakerBuilder { + self.ext = ext; + + self + } + + /// Configuration that will be used to alter the internal behavior of handshaking. + /// + /// This will typically not need to be set unless you know what you are doing. + pub fn with_config(&mut self, config: HandshakerConfig) -> &mut HandshakerBuilder { + self.config = config; + + self + } + + /// Build a `Handshaker` over the given `Transport` with a `Remote` instance. + /// + /// # Errors + /// + /// Returns a IO error if unable to build. + pub async fn build(&self, transport: T) -> std::io::Result<(Handshaker, JoinSet<()>)> + where + T: Transport + Send + Sync + 'static, + ::Socket: AsyncWrite + AsyncRead + std::fmt::Debug + Send + Sync, + ::Listener: Send, + { + Handshaker::with_builder(self, transport).await + } +} diff --git a/packages/handshake/src/handshake/config.rs b/packages/handshake/src/handshake/config.rs index a09a783ae..b3e011e7c 100644 --- a/packages/handshake/src/handshake/config.rs +++ b/packages/handshake/src/handshake/config.rs @@ -1,4 +1,3 @@ -use std::default::Default; use std::time::Duration; const DEFAULT_HANDSHAKE_BUFFER_SIZE: usize = 1000; diff --git a/packages/handshake/src/handshake/handler/handshake.rs b/packages/handshake/src/handshake/handler/handshake.rs index 45939d394..54c6df9ad 100644 --- a/packages/handshake/src/handshake/handler/handshake.rs +++ b/packages/handshake/src/handshake/handler/handshake.rs @@ -1,4 +1,3 @@ -use std::io; use std::net::SocketAddr; use std::time::Duration; @@ -63,9 +62,9 @@ where let socket = framed.into_inner(); if remote_hash != hash { - Err(io::Error::new(io::ErrorKind::Other, "not matching hash")) + Err(std::io::Error::new(std::io::ErrorKind::Other, "not matching hash")) } else if remote_prot != prot { - Err(io::Error::new(io::ErrorKind::Other, "not matching port")) + Err(std::io::Error::new(std::io::ErrorKind::Other, "not matching port")) } else if handler::should_filter( Some(&addr), Some(&remote_prot), @@ -74,7 +73,7 @@ where Some(&remote_pid), &filters, ) { - Err(io::Error::new(io::ErrorKind::Other, "should not filter")) + Err(std::io::Error::new(std::io::ErrorKind::Other, "should not filter")) } else { Ok(Some(CompleteMessage::new( prot, @@ -113,7 +112,7 @@ where Some(&remote_pid), &filters, ) { - Err(io::Error::new(io::ErrorKind::Other, "should not filter")) + Err(std::io::Error::new(std::io::ErrorKind::Other, "should not filter")) } else { let handshake_msg = HandshakeMessage::from_parts(remote_prot.clone(), ext, remote_hash, pid); @@ -137,7 +136,7 @@ where #[cfg(test)] mod tests { - use std::io::Cursor; + use std::time::Duration; use util::bt::{self, InfoHash, PeerId}; @@ -172,7 +171,7 @@ mod tests { let remote_hash = any_info_hash(); let remote_message = HandshakeMessage::from_parts(remote_protocol, any_extensions(), remote_hash, remote_pid); - let mut writer = Cursor::new(Vec::with_capacity(remote_message.write_len() * 2)); + let mut writer = std::io::Cursor::new(Vec::with_capacity(remote_message.write_len() * 2)); writer.set_position(remote_message.write_len() as u64); remote_message.write_bytes(&mut writer).await.unwrap(); @@ -227,7 +226,7 @@ mod tests { let remote_hash = any_info_hash(); let remote_message = HandshakeMessage::from_parts(Protocol::BitTorrent, any_extensions(), remote_hash, remote_pid); - let mut writer = Cursor::new(vec![0u8; remote_message.write_len() * 2]); + let mut writer = std::io::Cursor::new(vec![0u8; remote_message.write_len() * 2]); remote_message.write_bytes(&mut writer).await.unwrap(); writer.set_position(0); diff --git a/packages/handshake/src/handshake/handler/listener.rs b/packages/handshake/src/handshake/handler/listener.rs index 2af4a71ad..44b9ccfae 100644 --- a/packages/handshake/src/handshake/handler/listener.rs +++ b/packages/handshake/src/handshake/handler/listener.rs @@ -1,5 +1,4 @@ use std::cell::Cell; -use std::io; use std::net::SocketAddr; use std::pin::Pin; use std::task::{Context, Poll}; @@ -12,7 +11,7 @@ use crate::handshake::handler::HandshakeType; #[allow(clippy::module_name_repetitions)] pub struct ListenerHandler { - opt_item: Cell>>>, + opt_item: Cell>>>, } impl ListenerHandler { diff --git a/packages/handshake/src/handshake/handler/mod.rs b/packages/handshake/src/handshake/handler/mod.rs index eec1ad604..870f15342 100644 --- a/packages/handshake/src/handshake/handler/mod.rs +++ b/packages/handshake/src/handshake/handler/mod.rs @@ -1,4 +1,3 @@ -use std::io; use std::net::SocketAddr; use std::pin::Pin; @@ -29,7 +28,7 @@ pub async fn loop_handler(mut stream: M, mut handler: H, mut s where M: futures::Stream + Unpin, H: for<'a> FnMut(M::Item, &'a C) -> F, - K: futures::Sink> + Unpin, + K: futures::Sink> + Unpin, F: futures::Future>>, C: 'static, { diff --git a/packages/handshake/src/handshake/handshaker.rs b/packages/handshake/src/handshake/handshaker.rs deleted file mode 100644 index 0caae0228..000000000 --- a/packages/handshake/src/handshake/handshaker.rs +++ /dev/null @@ -1,356 +0,0 @@ -use std::cmp; -use std::net::{Ipv4Addr, SocketAddr, SocketAddrV4}; - -use futures::channel::mpsc::{self, Receiver, Sender}; -use futures::sink::{Sink, SinkExt}; -use futures::stream::{Stream, StreamExt}; -use futures::task::{Context, Poll}; -use rand::{self, Rng}; -use tokio::io::{AsyncRead, AsyncWrite}; -use tokio::task::JoinSet; -use util::bt::PeerId; -use util::convert; - -use super::handler::handshake; -use crate::discovery::DiscoveryInfo; -use crate::filter::filters::Filters; -use crate::filter::{HandshakeFilter, HandshakeFilters}; -use crate::handshake::config::HandshakerConfig; -use crate::handshake::handler; -use crate::handshake::handler::initiator; -use crate::handshake::handler::listener::ListenerHandler; -use crate::message::complete::CompleteMessage; -use crate::message::extensions::Extensions; -use crate::message::initiate::InitiateMessage; -use crate::transport::Transport; -use crate::LocalAddr as _; - -/// Build configuration for `Handshaker` object creation. -#[allow(clippy::module_name_repetitions)] -#[derive(Copy, Clone)] -pub struct HandshakerBuilder { - bind: SocketAddr, - port: u16, - pid: PeerId, - ext: Extensions, - config: HandshakerConfig, -} - -impl Default for HandshakerBuilder { - fn default() -> Self { - let default_v4_addr = Ipv4Addr::new(0, 0, 0, 0); - let default_v4_port = 0; - - let bind = SocketAddr::V4(SocketAddrV4::new(default_v4_addr, default_v4_port)); - - let seed = rand::thread_rng().gen(); - let pid = PeerId::from_bytes(&convert::four_bytes_to_array(seed)); - - Self { - bind, - port: Default::default(), - pid, - ext: Extensions::default(), - config: HandshakerConfig::default(), - } - } -} - -impl HandshakerBuilder { - /// Create a new `HandshakerBuilder`. - #[must_use] - pub fn new() -> HandshakerBuilder { - Self::default() - } - - /// Address that the host will listen on. - /// - /// Defaults to `IN_ADDR_ANY` using port 0 (any free port). - pub fn with_bind_addr(&mut self, addr: SocketAddr) -> &mut HandshakerBuilder { - self.bind = addr; - - self - } - - /// Port that external peers should connect on. - /// - /// Defaults to the port that is being listened on (will only work if the - /// host is not natted). - pub fn with_open_port(&mut self, port: u16) -> &mut HandshakerBuilder { - self.port = port; - - self - } - - /// Peer id that will be advertised when handshaking with other peers. - /// - /// Defaults to a random SHA-1 hash; official clients should use an encoding scheme. - /// - /// See [BEP 0020](http://www.bittorrent.org/beps/bep_0020.html). - pub fn with_peer_id(&mut self, peer_id: PeerId) -> &mut HandshakerBuilder { - self.pid = peer_id; - - self - } - - /// Extensions supported by our client, advertised to the peer when handshaking. - pub fn with_extensions(&mut self, ext: Extensions) -> &mut HandshakerBuilder { - self.ext = ext; - - self - } - - /// Configuration that will be used to alter the internal behavior of handshaking. - /// - /// This will typically not need to be set unless you know what you are doing. - pub fn with_config(&mut self, config: HandshakerConfig) -> &mut HandshakerBuilder { - self.config = config; - - self - } - - /// Build a `Handshaker` over the given `Transport` with a `Remote` instance. - /// - /// # Errors - /// - /// Returns a IO error if unable to build. - pub async fn build(&self, transport: T) -> std::io::Result<(Handshaker, JoinSet<()>)> - where - T: Transport + Send + Sync + 'static, - ::Socket: AsyncWrite + AsyncRead + std::fmt::Debug + Send + Sync, - ::Listener: Send, - { - Handshaker::with_builder(self, transport).await - } -} - -//----------------------------------------------------------------------------------// - -/// Handshaker which is both `Stream` and `Sink`. -pub struct Handshaker { - sink: HandshakerSink, - stream: HandshakerStream, -} - -impl Handshaker { - /// Splits the `Handshaker` into its parts. - /// - /// This is an enhanced version of `Stream::split` in that the returned `Sink` implements - /// `DiscoveryInfo` so it can be cloned and passed in to different peer discovery services. - #[must_use] - pub fn into_parts(self) -> (HandshakerSink, HandshakerStream) { - (self.sink, self.stream) - } -} - -impl DiscoveryInfo for Handshaker { - fn port(&self) -> u16 { - self.sink.port() - } - - fn peer_id(&self) -> PeerId { - self.sink.peer_id() - } -} - -impl Handshaker -where - S: AsyncRead + AsyncWrite + std::fmt::Debug + Send + Sync + Unpin + 'static, -{ - async fn with_builder(builder: &HandshakerBuilder, transport: T) -> std::io::Result<(Handshaker, JoinSet<()>)> - where - T: Transport + Send + Sync + 'static, - ::Listener: Send, - { - let config = builder.config; - let timeout = cmp::max(config.handshake_timeout(), config.connect_timeout()); - - let listener = transport.listen(builder.bind, timeout).await?; - - // Resolve our "real" public port - let open_port = if builder.port == 0 { - listener.local_addr()?.port() - } else { - builder.port - }; - - let (addr_send, addr_recv) = mpsc::channel(config.sink_buffer_size()); - let (hand_send, hand_recv) = mpsc::channel(config.wait_buffer_size()); - let (sock_send, sock_recv) = mpsc::channel(config.done_buffer_size()); - - let filters = Filters::new(); - - // Hook up our pipeline of handlers which will take some connection info, process it, and forward it - - let mut tasks = JoinSet::new(); - - tasks.spawn(handler::loop_handler( - addr_recv, - initiator::initiator_handler, - hand_send.clone(), - Box::pin((transport, filters.clone(), timeout)), - )); - - tasks.spawn(handler::loop_handler( - listener, - ListenerHandler::new, - hand_send, - Box::pin(filters.clone()), - )); - - tasks.spawn(handler::loop_handler( - hand_recv, - handshake::execute_handshake, - sock_send, - Box::pin((builder.ext, builder.pid, filters.clone(), timeout)), - )); - - let sink = HandshakerSink::new(addr_send, open_port, builder.pid, filters); - let stream = HandshakerStream::new(sock_recv); - - Ok((Handshaker { sink, stream }, tasks)) - } -} - -impl Sink for Handshaker { - type Error = mpsc::SendError; - - fn poll_ready(mut self: std::pin::Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { - self.sink.poll_ready_unpin(cx) - } - - fn start_send(mut self: std::pin::Pin<&mut Self>, item: InitiateMessage) -> Result<(), Self::Error> { - self.sink.start_send_unpin(item) - } - - fn poll_flush(mut self: std::pin::Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { - self.sink.poll_flush_unpin(cx) - } - - fn poll_close(mut self: std::pin::Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { - self.sink.poll_close_unpin(cx) - } -} - -impl Stream for Handshaker { - type Item = std::io::Result>; - - fn poll_next(mut self: std::pin::Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { - self.stream.poll_next_unpin(cx) - } -} - -impl HandshakeFilters for Handshaker { - fn add_filter(&self, filter: F) - where - F: HandshakeFilter + PartialEq + Eq + Send + Sync + 'static, - { - self.sink.add_filter(filter); - } - - fn remove_filter(&self, filter: F) - where - F: HandshakeFilter + PartialEq + Eq + Send + Sync + 'static, - { - self.sink.remove_filter(filter); - } - - fn clear_filters(&self) { - self.sink.clear_filters(); - } -} - -//----------------------------------------------------------------------------------// - -/// `Sink` portion of the `Handshaker` for initiating handshakes. -#[allow(clippy::module_name_repetitions)] -#[derive(Clone)] -pub struct HandshakerSink { - send: Sender, - port: u16, - pid: PeerId, - filters: Filters, -} - -impl HandshakerSink { - fn new(send: Sender, port: u16, pid: PeerId, filters: Filters) -> HandshakerSink { - HandshakerSink { - send, - port, - pid, - filters, - } - } -} - -impl DiscoveryInfo for HandshakerSink { - fn port(&self) -> u16 { - self.port - } - - fn peer_id(&self) -> PeerId { - self.pid - } -} - -impl Sink for HandshakerSink { - type Error = mpsc::SendError; - - fn poll_ready(mut self: std::pin::Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { - self.send.poll_ready_unpin(cx) - } - - fn start_send(mut self: std::pin::Pin<&mut Self>, item: InitiateMessage) -> Result<(), Self::Error> { - self.send.start_send_unpin(item) - } - - fn poll_flush(mut self: std::pin::Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { - self.send.poll_flush_unpin(cx) - } - - fn poll_close(mut self: std::pin::Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { - self.send.poll_close_unpin(cx) - } -} - -impl HandshakeFilters for HandshakerSink { - fn add_filter(&self, filter: F) - where - F: HandshakeFilter + PartialEq + Eq + Send + Sync + 'static, - { - self.filters.add_filter(filter); - } - - fn remove_filter(&self, filter: F) - where - F: HandshakeFilter + PartialEq + Eq + Send + Sync + 'static, - { - self.filters.remove_filter(&filter); - } - - fn clear_filters(&self) { - self.filters.clear_filters(); - } -} - -//----------------------------------------------------------------------------------// - -/// `Stream` portion of the `Handshaker` for completed handshakes. -#[allow(clippy::module_name_repetitions)] -pub struct HandshakerStream { - recv: Receiver>>, -} - -impl HandshakerStream { - fn new(recv: Receiver>>) -> HandshakerStream { - HandshakerStream { recv } - } -} - -impl Stream for HandshakerStream { - type Item = std::io::Result>; - - fn poll_next(mut self: std::pin::Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { - self.recv.poll_next_unpin(cx) - } -} diff --git a/packages/handshake/src/handshake/mod.rs b/packages/handshake/src/handshake/mod.rs index f9b09e325..d654d4785 100644 --- a/packages/handshake/src/handshake/mod.rs +++ b/packages/handshake/src/handshake/mod.rs @@ -1,3 +1,156 @@ +use std::task::{Context, Poll}; + +use builder::HandshakerBuilder; +use futures::channel::mpsc; +use futures::{Sink, SinkExt as _, Stream, StreamExt as _}; +use handler::listener::ListenerHandler; +use handler::{handshake, initiator}; +use sink::HandshakerSink; +use stream::HandshakerStream; +use tokio::io::{AsyncRead, AsyncWrite}; +use tokio::task::JoinSet; +use util::bt::PeerId; + +use crate::filter::filters::Filters; +use crate::local_addr::LocalAddr as _; +use crate::{CompleteMessage, DiscoveryInfo, HandshakeFilter, HandshakeFilters, InitiateMessage, Transport}; + +pub mod builder; pub mod config; pub mod handler; -pub mod handshaker; +pub mod sink; +pub mod stream; + +/// Handshaker which is both `Stream` and `Sink`. +pub struct Handshaker { + sink: HandshakerSink, + stream: HandshakerStream, +} + +impl Handshaker { + /// Splits the `Handshaker` into its parts. + /// + /// This is an enhanced version of `Stream::split` in that the returned `Sink` implements + /// `DiscoveryInfo` so it can be cloned and passed in to different peer discovery services. + #[must_use] + pub fn into_parts(self) -> (HandshakerSink, HandshakerStream) { + (self.sink, self.stream) + } +} + +impl DiscoveryInfo for Handshaker { + fn port(&self) -> u16 { + self.sink.port() + } + + fn peer_id(&self) -> PeerId { + self.sink.peer_id() + } +} + +impl HandshakeFilters for Handshaker { + fn add_filter(&self, filter: F) + where + F: HandshakeFilter + PartialEq + Eq + Send + Sync + 'static, + { + self.sink.add_filter(filter); + } + + fn remove_filter(&self, filter: F) + where + F: HandshakeFilter + PartialEq + Eq + Send + Sync + 'static, + { + self.sink.remove_filter(filter); + } + + fn clear_filters(&self) { + self.sink.clear_filters(); + } +} + +impl Handshaker +where + S: AsyncRead + AsyncWrite + std::fmt::Debug + Send + Sync + Unpin + 'static, +{ + async fn with_builder(builder: &HandshakerBuilder, transport: T) -> std::io::Result<(Handshaker, JoinSet<()>)> + where + T: Transport + Send + Sync + 'static, + ::Listener: Send, + { + let config = builder.config; + let timeout = std::cmp::max(config.handshake_timeout(), config.connect_timeout()); + + let listener = transport.listen(builder.bind, timeout).await?; + + // Resolve our "real" public port + let open_port = if builder.port == 0 { + listener.local_addr()?.port() + } else { + builder.port + }; + + let (addr_send, addr_recv) = mpsc::channel(config.sink_buffer_size()); + let (hand_send, hand_recv) = mpsc::channel(config.wait_buffer_size()); + let (sock_send, sock_recv) = mpsc::channel(config.done_buffer_size()); + + let filters = Filters::new(); + + // Hook up our pipeline of handlers which will take some connection info, process it, and forward it + + let mut tasks = JoinSet::new(); + + tasks.spawn(handler::loop_handler( + addr_recv, + initiator::initiator_handler, + hand_send.clone(), + Box::pin((transport, filters.clone(), timeout)), + )); + + tasks.spawn(handler::loop_handler( + listener, + ListenerHandler::new, + hand_send, + Box::pin(filters.clone()), + )); + + tasks.spawn(handler::loop_handler( + hand_recv, + handshake::execute_handshake, + sock_send, + Box::pin((builder.ext, builder.pid, filters.clone(), timeout)), + )); + + let sink = HandshakerSink::new(addr_send, open_port, builder.pid, filters); + let stream = HandshakerStream::new(sock_recv); + + Ok((Handshaker { sink, stream }, tasks)) + } +} + +impl Sink for Handshaker { + type Error = mpsc::SendError; + + fn poll_ready(mut self: std::pin::Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { + self.sink.poll_ready_unpin(cx) + } + + fn start_send(mut self: std::pin::Pin<&mut Self>, item: InitiateMessage) -> Result<(), Self::Error> { + self.sink.start_send_unpin(item) + } + + fn poll_flush(mut self: std::pin::Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { + self.sink.poll_flush_unpin(cx) + } + + fn poll_close(mut self: std::pin::Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { + self.sink.poll_close_unpin(cx) + } +} + +impl Stream for Handshaker { + type Item = std::io::Result>; + + fn poll_next(mut self: std::pin::Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { + self.stream.poll_next_unpin(cx) + } +} diff --git a/packages/handshake/src/handshake/sink.rs b/packages/handshake/src/handshake/sink.rs new file mode 100644 index 000000000..ad3b843ee --- /dev/null +++ b/packages/handshake/src/handshake/sink.rs @@ -0,0 +1,84 @@ +//! `Sink` portion of the `Handshaker` for initiating handshakes. + +use futures::channel::mpsc; +use futures::sink::Sink; +use futures::task::{Context, Poll}; +use futures::SinkExt as _; +use util::bt::PeerId; + +use crate::discovery::DiscoveryInfo; +use crate::filter::filters::Filters; +use crate::filter::{HandshakeFilter, HandshakeFilters}; +use crate::message::initiate::InitiateMessage; + +#[allow(clippy::module_name_repetitions)] +#[derive(Clone)] +pub struct HandshakerSink { + send: mpsc::Sender, + port: u16, + pid: PeerId, + filters: Filters, +} + +impl HandshakerSink { + pub(super) fn new(send: mpsc::Sender, port: u16, pid: PeerId, filters: Filters) -> HandshakerSink { + HandshakerSink { + send, + port, + pid, + filters, + } + } +} + +impl DiscoveryInfo for HandshakerSink { + fn port(&self) -> u16 { + self.port + } + + fn peer_id(&self) -> PeerId { + self.pid + } +} + +impl Sink for HandshakerSink { + type Error = mpsc::SendError; + + fn poll_ready(mut self: std::pin::Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { + self.send.poll_ready_unpin(cx) + } + + fn start_send(mut self: std::pin::Pin<&mut Self>, item: InitiateMessage) -> Result<(), Self::Error> { + self.send.start_send_unpin(item) + } + + fn poll_flush(mut self: std::pin::Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { + self.send.poll_flush_unpin(cx) + } + + fn poll_close(mut self: std::pin::Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { + self.send.poll_close_unpin(cx) + } +} + +impl HandshakeFilters for HandshakerSink { + fn add_filter(&self, filter: F) + where + F: HandshakeFilter + PartialEq + Eq + Send + Sync + 'static, + { + self.filters.add_filter(filter); + } + + fn remove_filter(&self, filter: F) + where + F: HandshakeFilter + PartialEq + Eq + Send + Sync + 'static, + { + self.filters.remove_filter(&filter); + } + + fn clear_filters(&self) { + self.filters.clear_filters(); + } +} + +//----------------------------------------------------------------------------------// diff --git a/packages/handshake/src/handshake/stream.rs b/packages/handshake/src/handshake/stream.rs new file mode 100644 index 000000000..b217cb04c --- /dev/null +++ b/packages/handshake/src/handshake/stream.rs @@ -0,0 +1,26 @@ +use std::task::{Context, Poll}; + +use futures::channel::mpsc; +use futures::{Stream, StreamExt as _}; + +use crate::CompleteMessage; + +/// `Stream` portion of the `Handshaker` for completed handshakes. +#[allow(clippy::module_name_repetitions)] +pub struct HandshakerStream { + recv: mpsc::Receiver>>, +} + +impl HandshakerStream { + pub(super) fn new(recv: mpsc::Receiver>>) -> HandshakerStream { + HandshakerStream { recv } + } +} + +impl Stream for HandshakerStream { + type Item = std::io::Result>; + + fn poll_next(mut self: std::pin::Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { + self.recv.poll_next_unpin(cx) + } +} diff --git a/packages/handshake/src/lib.rs b/packages/handshake/src/lib.rs index 749e38276..ab4ab9744 100644 --- a/packages/handshake/src/lib.rs +++ b/packages/handshake/src/lib.rs @@ -8,8 +8,11 @@ mod transport; pub use crate::discovery::DiscoveryInfo; pub use crate::filter::{FilterDecision, HandshakeFilter, HandshakeFilters}; +pub use crate::handshake::builder::HandshakerBuilder; pub use crate::handshake::config::HandshakerConfig; -pub use crate::handshake::handshaker::{Handshaker, HandshakerBuilder, HandshakerSink, HandshakerStream}; +pub use crate::handshake::sink::HandshakerSink; +pub use crate::handshake::stream::HandshakerStream; +pub use crate::handshake::Handshaker; pub use crate::local_addr::LocalAddr; pub use crate::message::complete::CompleteMessage; pub use crate::message::extensions::{Extension, Extensions}; diff --git a/packages/handshake/src/message/extensions.rs b/packages/handshake/src/message/extensions.rs index d0d6b4197..7ca75fdd8 100644 --- a/packages/handshake/src/message/extensions.rs +++ b/packages/handshake/src/message/extensions.rs @@ -1,5 +1,3 @@ -use std::io::Write; - use nom::bytes::complete::take; use nom::IResult; use tokio::io::{AsyncWrite, AsyncWriteExt as _}; @@ -90,7 +88,7 @@ impl Extensions { /// This function will return an error if unable to write bytes. pub fn write_bytes_sync(&self, writer: &mut W) -> std::io::Result<()> where - W: Write, + W: std::io::Write, { writer.write_all(&self.bytes[..]) } diff --git a/packages/handshake/src/message/protocol.rs b/packages/handshake/src/message/protocol.rs index 80d93972a..8e62197f1 100644 --- a/packages/handshake/src/message/protocol.rs +++ b/packages/handshake/src/message/protocol.rs @@ -1,5 +1,3 @@ -use std::io::Write; - use nom::bytes::complete::take; use nom::number::complete::u8; use nom::sequence::tuple; @@ -54,7 +52,7 @@ impl Protocol { /// This function will return an error if unable to write bytes. pub fn write_bytes_sync(&self, writer: &mut W) -> std::io::Result<()> where - W: Write, + W: std::io::Write, { let (len, bytes) = match self { Protocol::BitTorrent => (BT_PROTOCOL_LEN as usize, BT_PROTOCOL), diff --git a/packages/handshake/src/transport.rs b/packages/handshake/src/transport.rs index 5039969ad..c49af9ff0 100644 --- a/packages/handshake/src/transport.rs +++ b/packages/handshake/src/transport.rs @@ -1,4 +1,3 @@ -use std::io; use std::net::SocketAddr; use std::pin::Pin; use std::task::{Context, Poll}; @@ -55,7 +54,7 @@ impl Transport for TcpTransport { fn connect(&self, addr: SocketAddr, timeout: Duration) -> Self::FutureSocket { let socket = TcpStream::connect(addr); let socket = tokio::time::timeout(timeout, socket) - .map_err(|e| std::io::Error::new(io::ErrorKind::TimedOut, e)) + .map_err(|e| std::io::Error::new(std::io::ErrorKind::TimedOut, e)) .boxed(); socket.map(|s| s.and_then(|s| s)).boxed() @@ -65,7 +64,7 @@ impl Transport for TcpTransport { let listener = TcpListener::bind(addr); let listener = tokio::time::timeout(timeout, listener) - .map_err(|e| std::io::Error::new(io::ErrorKind::TimedOut, e)) + .map_err(|e| std::io::Error::new(std::io::ErrorKind::TimedOut, e)) .boxed(); let listener = listener.map(|l| l.and_then(|l| l)).boxed(); @@ -111,7 +110,7 @@ impl Stream for TcpListenerStream { #[cfg(test)] pub mod test_transports { - use std::io::Cursor; + use std::net::SocketAddr; use std::pin::Pin; use std::task::{Context, Poll}; @@ -129,13 +128,13 @@ pub mod test_transports { pub struct MockTransport; impl Transport for MockTransport { - type Socket = Cursor>; + type Socket = std::io::Cursor>; type FutureSocket = BoxFuture<'static, std::io::Result>; type Listener = MockListener; type FutureListener = BoxFuture<'static, std::io::Result>; fn connect(&self, _addr: SocketAddr, _timeout: Duration) -> Self::FutureSocket { - future::ok(Cursor::new(Vec::new())).boxed() + future::ok(std::io::Cursor::new(Vec::new())).boxed() } fn listen(&self, addr: SocketAddr, _timeout: Duration) -> Self::FutureListener { @@ -148,7 +147,7 @@ pub mod test_transports { /// A mock listener for testing purposes. pub struct MockListener { addr: SocketAddr, - empty: Empty>, SocketAddr)>>, + empty: Empty>, SocketAddr)>>, } impl MockListener { @@ -168,7 +167,7 @@ pub mod test_transports { } impl Stream for MockListener { - type Item = std::io::Result<(Cursor>, SocketAddr)>; + type Item = std::io::Result<(std::io::Cursor>, SocketAddr)>; fn poll_next(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { self.get_mut().empty.poll_next_unpin(cx) diff --git a/packages/handshake/tests/test_byte_after_handshake.rs b/packages/handshake/tests/test_byte_after_handshake.rs index 4d82773b5..d750f6f74 100644 --- a/packages/handshake/tests/test_byte_after_handshake.rs +++ b/packages/handshake/tests/test_byte_after_handshake.rs @@ -1,11 +1,11 @@ -use std::io::{Read, Write}; +use std::io::{Read as _, Write as _}; use std::net::TcpStream; use common::{tracing_stderr_init, INIT}; use futures::stream::StreamExt; use handshake::transports::TcpTransport; use handshake::{DiscoveryInfo, HandshakerBuilder}; -use tokio::io::AsyncReadExt; +use tokio::io::AsyncReadExt as _; use tracing::level_filters::LevelFilter; use util::bt::{self}; diff --git a/packages/handshake/tests/test_bytes_after_handshake.rs b/packages/handshake/tests/test_bytes_after_handshake.rs index 3ab58a1f2..82ec37833 100644 --- a/packages/handshake/tests/test_bytes_after_handshake.rs +++ b/packages/handshake/tests/test_bytes_after_handshake.rs @@ -1,11 +1,11 @@ -use std::io::{Read, Write}; +use std::io::{Read as _, Write as _}; use std::net::{IpAddr, Ipv4Addr, SocketAddr, TcpStream}; use common::{tracing_stderr_init, INIT}; use futures::stream::StreamExt; use handshake::transports::TcpTransport; use handshake::{DiscoveryInfo, HandshakerBuilder}; -use tokio::io::AsyncReadExt; +use tokio::io::AsyncReadExt as _; use tracing::level_filters::LevelFilter; use util::bt::{self}; diff --git a/packages/htracker/Cargo.toml b/packages/htracker/Cargo.toml index 186471aa6..b04e63ae5 100644 --- a/packages/htracker/Cargo.toml +++ b/packages/htracker/Cargo.toml @@ -1,7 +1,7 @@ [package] -name = "htracker" description = "Communication with bittorrent HTTP trackers" -keywords = ["tracker", "bittorrent", "http"] +keywords = ["bittorrent", "http", "tracker"] +name = "htracker" readme = "README.md" authors.workspace = true diff --git a/packages/lpd/Cargo.toml b/packages/lpd/Cargo.toml index 9a23278eb..c8a17f951 100644 --- a/packages/lpd/Cargo.toml +++ b/packages/lpd/Cargo.toml @@ -1,7 +1,7 @@ [package] -name = "lpd" description = "Implementation of the bittorrent Local Peer/Service Discovery mechanism" -keywords = ["peer", "discovery", "local", "service"] +keywords = ["discovery", "local", "peer", "service"] +name = "lpd" readme = "README.md" authors.workspace = true diff --git a/packages/magnet/Cargo.toml b/packages/magnet/Cargo.toml index c32b7c767..854531d11 100644 --- a/packages/magnet/Cargo.toml +++ b/packages/magnet/Cargo.toml @@ -1,7 +1,7 @@ [package] -name = "magnet" description = "Magnet link parsing and construction" -keywords = ["magnet", "bittorrent"] +keywords = ["bittorrent", "magnet"] +name = "magnet" readme = "README.md" authors.workspace = true @@ -17,5 +17,7 @@ version.workspace = true [dependencies] util = { path = "../util" } -url = "2" + base32 = "0" +url = "2" + diff --git a/packages/magnet/src/lib.rs b/packages/magnet/src/lib.rs index 7892ff692..d1b19d64d 100644 --- a/packages/magnet/src/lib.rs +++ b/packages/magnet/src/lib.rs @@ -1,5 +1,3 @@ -use std::default::Default; - use url::Url; use util::bt::InfoHash; use util::sha::ShaHash; diff --git a/packages/metainfo/Cargo.toml b/packages/metainfo/Cargo.toml index 402ead8a2..2a5278ce6 100644 --- a/packages/metainfo/Cargo.toml +++ b/packages/metainfo/Cargo.toml @@ -1,7 +1,7 @@ [package] -name = "metainfo" description = "Parsing and building of bittorrent metainfo files" -keywords = ["metainfo", "torrent", "file", "bittorrent"] +keywords = ["bittorrent", "file", "metainfo", "torrent"] +name = "metainfo" readme = "README.md" authors.workspace = true @@ -18,16 +18,17 @@ version.workspace = true [dependencies] bencode = { path = "../bencode" } util = { path = "../util" } + crossbeam = "0" -walkdir = "2" thiserror = "1" +walkdir = "2" [dev-dependencies] chrono = "0" -rand = "0" -pbr = "1" criterion = "0" +pbr = "1" +rand = "0" [[bench]] -name = "metainfo_benchmark" harness = false +name = "metainfo_benchmark" diff --git a/packages/metainfo/examples/create_torrent.rs b/packages/metainfo/examples/create_torrent.rs index 52f2f9d3c..99a1e550a 100644 --- a/packages/metainfo/examples/create_torrent.rs +++ b/packages/metainfo/examples/create_torrent.rs @@ -1,5 +1,4 @@ -use std::fs::File; -use std::io::{BufRead, Write}; +use std::io::{BufRead as _, Write as _}; use std::path::Path; use chrono::offset::{TimeZone, Utc}; @@ -24,7 +23,7 @@ fn main() { match create_torrent(src_path) { Ok(bytes) => { - let mut output_file = File::create(dst_path).unwrap(); + let mut output_file = std::fs::File::create(dst_path).unwrap(); output_file.write_all(&bytes).unwrap(); print_metainfo_overview(&bytes); diff --git a/packages/metainfo/src/accessor.rs b/packages/metainfo/src/accessor.rs index 3a6df0166..c01aacdcd 100644 --- a/packages/metainfo/src/accessor.rs +++ b/packages/metainfo/src/accessor.rs @@ -1,5 +1,3 @@ -use std::fs::File; -use std::io::{Cursor, Read}; use std::path::{Path, PathBuf}; use util::sha::ShaHash; @@ -77,7 +75,7 @@ where /// (though not required). pub enum PieceAccess<'a> { /// Hash should be computed from the bytes read. - Compute(&'a mut dyn Read), + Compute(&'a mut dyn std::io::Read), /// Hash given should be used directly as the next checksum. PreComputed(ShaHash), } @@ -178,7 +176,7 @@ impl Accessor for FileAccessor { { for res_entry in WalkDir::new(&self.absolute_path).into_iter().filter(entry_file_filter) { let entry = res_entry?; - let mut file = File::open(entry.path())?; + let mut file = std::fs::File::open(entry.path())?; callback(PieceAccess::Compute(&mut file))?; } @@ -241,7 +239,7 @@ impl<'a> Accessor for DirectAccessor<'a> { where C: for<'b> FnMut(PieceAccess<'b>) -> std::io::Result<()>, { - let mut cursor = Cursor::new(self.file_contents); + let mut cursor = std::io::Cursor::new(self.file_contents); callback(PieceAccess::Compute(&mut cursor)) } diff --git a/packages/metainfo/src/builder/buffer.rs b/packages/metainfo/src/builder/buffer.rs index 954d87f55..32af8d7a7 100644 --- a/packages/metainfo/src/builder/buffer.rs +++ b/packages/metainfo/src/builder/buffer.rs @@ -1,5 +1,4 @@ -use core::time; -use std::thread; +use std::time::Duration; use crossbeam::queue::SegQueue; @@ -35,7 +34,7 @@ impl PieceBuffers { /// Checkout a piece buffer (possibly blocking) to be used. pub fn checkout(&self) -> PieceBuffer { let mut pb = None; - let ten_millis = time::Duration::from_millis(10); + let ten_millis = Duration::from_millis(10); while pb.is_none() { pb = self.piece_queue.pop(); @@ -44,7 +43,7 @@ impl PieceBuffers { break; } - thread::sleep(ten_millis); + std::thread::sleep(ten_millis); continue; } diff --git a/packages/metainfo/src/builder/worker.rs b/packages/metainfo/src/builder/worker.rs index c9c9f7d42..5396ad0ac 100644 --- a/packages/metainfo/src/builder/worker.rs +++ b/packages/metainfo/src/builder/worker.rs @@ -1,6 +1,4 @@ -use std::sync::mpsc::{self, Receiver, Sender}; -use std::sync::Arc; -use std::thread; +use std::sync::{mpsc, Arc}; use crossbeam::queue::SegQueue; use util::sha::ShaHash; @@ -53,13 +51,13 @@ where let share_work_queue = work_queue.clone(); let share_piece_buffers = piece_buffers.clone(); - thread::spawn(move || { + std::thread::spawn(move || { start_hash_worker(&share_master_send, &share_work_queue, &share_piece_buffers); }); } // Create a worker thread to execute the user callback for the progress update - thread::spawn(move || { + std::thread::spawn(move || { start_progress_updater(prog_recv, num_pieces, progress); }); @@ -74,10 +72,10 @@ where fn start_hash_master( accessor: A, num_workers: usize, - recv: &Receiver, + recv: &mpsc::Receiver, work: &Arc>, buffers: &Arc, - progress_sender: &Sender, + progress_sender: &mpsc::Sender, ) -> Result, ParseError> where A: Accessor, @@ -162,7 +160,7 @@ where // ----------------------------------------------------------------------------// -fn start_progress_updater(recv: Receiver, num_pieces: u64, mut progress: C) +fn start_progress_updater(recv: mpsc::Receiver, num_pieces: u64, mut progress: C) where C: FnMut(f64), { @@ -177,7 +175,7 @@ where // ----------------------------------------------------------------------------// /// Starts a hasher worker which will hash all of the buffers it receives. -fn start_hash_worker(send: &Sender, work: &Arc>, buffers: &Arc) { +fn start_hash_worker(send: &mpsc::Sender, work: &Arc>, buffers: &Arc) { let mut work_to_do = true; // Loop until we are instructed to stop working @@ -206,7 +204,7 @@ fn start_hash_worker(send: &Sender, work: &Arc FnMut(PieceAccess<'a>) -> std::io::Result<()>, { for range in &self.buffer_ranges { - let mut next_region = Cursor::new(self.contiguous_buffer.index(range.clone())); + let mut next_region = std::io::Cursor::new(self.contiguous_buffer.index(range.clone())); callback(PieceAccess::Compute(&mut next_region))?; } diff --git a/packages/metainfo/src/error.rs b/packages/metainfo/src/error.rs index 421af2af7..091ecb55a 100644 --- a/packages/metainfo/src/error.rs +++ b/packages/metainfo/src/error.rs @@ -1,7 +1,5 @@ //! Errors for torrent file building and parsing. -use std::io; - use bencode::{BencodeConvertError, BencodeParseError}; use thiserror::Error; use walkdir; @@ -10,7 +8,7 @@ use walkdir; #[derive(Error, Debug)] pub enum ParseError { #[error("IO error: {0}")] - Io(#[from] io::Error), + Io(#[from] std::io::Error), #[error("Directory error: {0}")] Dir(#[from] walkdir::Error), diff --git a/packages/metainfo/src/metainfo.rs b/packages/metainfo/src/metainfo.rs index f4da7fc7d..1feaa082a 100644 --- a/packages/metainfo/src/metainfo.rs +++ b/packages/metainfo/src/metainfo.rs @@ -1,6 +1,5 @@ //! Accessing the fields of a Metainfo file. -use std::fmt::Debug; use std::path::{Path, PathBuf}; use bencode::{BDecodeOpt, BDictAccess, BRefAccess, BencodeRef}; diff --git a/packages/peer/Cargo.toml b/packages/peer/Cargo.toml index eb5e16013..d5242f4c6 100644 --- a/packages/peer/Cargo.toml +++ b/packages/peer/Cargo.toml @@ -1,7 +1,7 @@ [package] -name = "peer" description = "Communication with bittorrent peers via peer wire protocol" -keywords = ["peer", "wire", "protocol", "pwp", "bittorrent"] +keywords = ["bittorrent", "peer", "protocol", "pwp", "wire"] +name = "peer" readme = "README.md" authors.workspace = true @@ -15,22 +15,21 @@ publish.workspace = true repository.workspace = true version.workspace = true - [dependencies] bencode = { path = "../bencode" } handshake = { path = "../handshake" } util = { path = "../util" } -pin-project = "1" -crossbeam = "0" +byteorder = "1" bytes = "1" +crossbeam = "0" futures = "0" -tracing = "0" -tokio = { version = "1", features = ["full"] } -tokio-util = {version = "0", features = ["codec"]} nom = "7" +pin-project = "1" thiserror = "1" -byteorder = "1" +tokio = { version = "1", features = ["full"] } +tokio-util = { version = "0", features = ["codec"] } +tracing = "0" [dev-dependencies] tracing-subscriber = "0" diff --git a/packages/peer/src/codec.rs b/packages/peer/src/codec.rs index e1a4780af..fbab54cac 100644 --- a/packages/peer/src/codec.rs +++ b/packages/peer/src/codec.rs @@ -95,8 +95,6 @@ where #[cfg(test)] mod tests { - use std::io::Write; - use bytes::BytesMut; use tokio_util::codec::Decoder as _; @@ -123,7 +121,7 @@ mod tests { _: W, ) -> std::io::Result where - W: Write, + W: std::io::Write, { Ok(0) } diff --git a/packages/peer/src/lib.rs b/packages/peer/src/lib.rs index eac6b188d..41df0bb4f 100644 --- a/packages/peer/src/lib.rs +++ b/packages/peer/src/lib.rs @@ -6,11 +6,11 @@ mod protocol; pub use codec::PeerProtocolCodec; pub use crate::manager::builder::PeerManagerBuilder; +pub use crate::manager::messages::{ManagedMessage, PeerManagerInputMessage, PeerManagerOutputError, PeerManagerOutputMessage}; pub use crate::manager::peer_info::PeerInfo; -pub use crate::manager::peer_manager::PeerManager; -pub use crate::manager::peer_manager_sink::PeerManagerSink; -pub use crate::manager::peer_manager_stream::PeerManagerStream; -pub use crate::manager::{ManagedMessage, PeerManagerInputMessage, PeerManagerOutputError, PeerManagerOutputMessage}; +pub use crate::manager::sink::ManagerSink; +pub use crate::manager::stream::ManagerStream; +pub use crate::manager::Manager; pub use crate::protocol::{NestedPeerProtocol, PeerProtocol}; /// Serializable and deserializable protocol messages. diff --git a/packages/peer/src/manager/builder.rs b/packages/peer/src/manager/builder.rs index f61593e3f..b831b40f8 100644 --- a/packages/peer/src/manager/builder.rs +++ b/packages/peer/src/manager/builder.rs @@ -3,8 +3,7 @@ use std::time::Duration; use futures::sink::Sink; use futures::{Stream, TryStream}; -use super::peer_manager::PeerManager; -use super::ManagedMessage; +use super::{ManagedMessage, Manager}; const DEFAULT_PEER_CAPACITY: usize = 1000; const DEFAULT_SINK_BUFFER_CAPACITY: usize = 100; @@ -103,7 +102,7 @@ impl PeerManagerBuilder { /// Builds a `PeerManager` from the current `PeerManagerBuilder` configuration. #[must_use] - pub fn build(self) -> PeerManager + pub fn build(self) -> Manager where Peer: Sink> + Stream> @@ -114,6 +113,6 @@ impl PeerManagerBuilder { + 'static, Message: ManagedMessage + Send + 'static, { - PeerManager::from_builder(self) + Manager::from_builder(self) } } diff --git a/packages/peer/src/manager/messages.rs b/packages/peer/src/manager/messages.rs new file mode 100644 index 000000000..73387832e --- /dev/null +++ b/packages/peer/src/manager/messages.rs @@ -0,0 +1,74 @@ +use futures::{Sink, Stream, TryStream}; +use thiserror::Error; + +use crate::manager::peer_info::PeerInfo; + +/// Trait for providing `PeerManager` with necessary message information. +/// +/// Any `PeerProtocol` (or plain `Codec`) that wants to be managed by `PeerManager` +/// must ensure that its message type implements this trait to provide the necessary hooks. +pub trait ManagedMessage: std::fmt::Debug { + /// Retrieves a keep-alive message variant. + fn keep_alive() -> Self; + + /// Checks whether this message is a keep-alive message. + fn is_keep_alive(&self) -> bool; +} + +//----------------------------------------------------------------------------// + +/// Identifier for matching sent messages with received messages. +pub type MessageId = u64; + +/// Messages that can be sent to the `PeerManager`. +#[derive(Debug)] +pub enum PeerManagerInputMessage +where + Peer: Sink> + + Stream> + + TryStream + + std::fmt::Debug + + Send + + Unpin + + 'static, + Message: ManagedMessage + Send + 'static, +{ + /// Adds a peer to the peer manager. + AddPeer(PeerInfo, Peer), + /// Removes a peer from the peer manager. + RemovePeer(PeerInfo), + /// Sends a message to a peer. + SendMessage(PeerInfo, MessageId, Message), // TODO: Support querying for statistics +} + +#[derive(Error, Debug)] +pub enum PeerManagerOutputError { + #[error("Peer Disconnected, but Missing")] + PeerDisconnectedAndMissing(PeerInfo), + + #[error("Peer Removed, but Missing")] + PeerRemovedAndMissing(PeerInfo), + + #[error("Peer Errored, but Missing")] + PeerErrorAndMissing(PeerInfo, Option>), + + #[error("Error with Peer")] + PeerError(PeerInfo, std::io::Error), +} + +/// Messages that can be received from the `PeerManager`. +#[derive(Debug)] +pub enum PeerManagerOutputMessage { + /// Indicates a peer has been added to the peer manager. + PeerAdded(PeerInfo), + /// Indicates a peer has been removed from the peer manager. + PeerRemoved(PeerInfo), + /// Indicates a message has been sent to the given peer. + SentMessage(PeerInfo, MessageId), + /// Indicates a message has been received from a peer. + ReceivedMessage(PeerInfo, Message), + /// Indicates a peer has disconnected. + /// + /// Same semantics as `PeerRemoved`, but the peer is not returned. + PeerDisconnect(PeerInfo), +} diff --git a/packages/peer/src/manager/mod.rs b/packages/peer/src/manager/mod.rs index 203b3606f..6fc09d706 100644 --- a/packages/peer/src/manager/mod.rs +++ b/packages/peer/src/manager/mod.rs @@ -1,41 +1,82 @@ -use futures::{Sink, Stream, TryStream}; -use thiserror::Error; +use std::collections::HashMap; +use std::marker::PhantomData; +use std::sync::{Arc, Mutex}; -use crate::manager::peer_info::PeerInfo; +use crossbeam::queue::SegQueue; +use error::PeerManagerError; +use futures::channel::mpsc::{self, SendError}; +use futures::sink::Sink; +use futures::stream::Stream; +use futures::{SinkExt as _, StreamExt, TryStream}; +use sink::ManagerSink; + +use super::ManagedMessage; +use crate::{ManagerStream, PeerManagerBuilder, PeerManagerInputMessage, PeerManagerOutputError, PeerManagerOutputMessage}; pub mod builder; pub mod error; +pub mod messages; pub mod peer_info; -#[allow(clippy::module_name_repetitions)] -pub mod peer_manager; -pub mod peer_manager_sink; -pub mod peer_manager_stream; +pub mod sink; +pub mod stream; mod future; mod task; -//----------------------------------------------------------------------------// +/// Manages a set of peers with beating hearts. +pub struct Manager +where + Peer: Sink> + + Stream> + + TryStream + + std::fmt::Debug + + Send + + Unpin + + 'static, + Message: ManagedMessage + Send + 'static, +{ + sink: ManagerSink, + stream: ManagerStream, + _peer_marker: PhantomData, +} -/// Trait for providing `PeerManager` with necessary message information. -/// -/// Any `PeerProtocol` (or plain `Codec`) that wants to be managed by `PeerManager` -/// must ensure that its message type implements this trait to provide the necessary hooks. -pub trait ManagedMessage: std::fmt::Debug { - /// Retrieves a keep-alive message variant. - fn keep_alive() -> Self; +impl Manager +where + Peer: Sink> + + Stream> + + TryStream + + std::fmt::Debug + + Send + + Unpin + + 'static, + Message: ManagedMessage + Send + 'static, +{ + /// Create a new `PeerManager` from the given `PeerManagerBuilder`. + #[must_use] + pub fn from_builder(builder: PeerManagerBuilder) -> Manager { + let (res_send, res_recv) = mpsc::channel(builder.stream_buffer_capacity()); + let peers = Arc::new(Mutex::new(HashMap::new())); + let task_queue = Arc::new(SegQueue::new()); - /// Checks whether this message is a keep-alive message. - fn is_keep_alive(&self) -> bool; -} + let sink = ManagerSink::new(builder, res_send, peers.clone(), task_queue.clone()); + let stream = ManagerStream::new(res_recv, peers); -//----------------------------------------------------------------------------// + Manager { + sink, + stream, + _peer_marker: PhantomData, + } + } -/// Identifier for matching sent messages with received messages. -pub type MessageId = u64; + /// Break the `PeerManager` into a sink and stream. + /// + /// The returned sink implements `Clone`. + pub fn into_parts(self) -> (ManagerSink, ManagerStream) { + (self.sink, self.stream) + } +} -/// Messages that can be sent to the `PeerManager`. -#[derive(Debug)] -pub enum PeerManagerInputMessage +impl Sink>> for Manager where Peer: Sink> + Stream> @@ -46,42 +87,51 @@ where + 'static, Message: ManagedMessage + Send + 'static, { - /// Adds a peer to the peer manager. - AddPeer(PeerInfo, Peer), - /// Removes a peer from the peer manager. - RemovePeer(PeerInfo), - /// Sends a message to a peer. - SendMessage(PeerInfo, MessageId, Message), // TODO: Support querying for statistics -} + type Error = PeerManagerError; -#[derive(Error, Debug)] -pub enum PeerManagerOutputError { - #[error("Peer Disconnected, but Missing")] - PeerDisconnectedAndMissing(PeerInfo), + fn poll_ready( + mut self: std::pin::Pin<&mut Self>, + cx: &mut std::task::Context<'_>, + ) -> std::task::Poll> { + self.sink.poll_ready_unpin(cx) + } - #[error("Peer Removed, but Missing")] - PeerRemovedAndMissing(PeerInfo), + fn start_send( + mut self: std::pin::Pin<&mut Self>, + item: std::io::Result>, + ) -> Result<(), Self::Error> { + self.sink.start_send_unpin(item) + } - #[error("Peer Errored, but Missing")] - PeerErrorAndMissing(PeerInfo, Option>), + fn poll_flush( + mut self: std::pin::Pin<&mut Self>, + cx: &mut std::task::Context<'_>, + ) -> std::task::Poll> { + self.sink.poll_flush_unpin(cx) + } - #[error("Error with Peer")] - PeerError(PeerInfo, std::io::Error), + fn poll_close( + mut self: std::pin::Pin<&mut Self>, + cx: &mut std::task::Context<'_>, + ) -> std::task::Poll> { + self.sink.poll_close_unpin(cx) + } } -/// Messages that can be received from the `PeerManager`. -#[derive(Debug)] -pub enum PeerManagerOutputMessage { - /// Indicates a peer has been added to the peer manager. - PeerAdded(PeerInfo), - /// Indicates a peer has been removed from the peer manager. - PeerRemoved(PeerInfo), - /// Indicates a message has been sent to the given peer. - SentMessage(PeerInfo, MessageId), - /// Indicates a message has been received from a peer. - ReceivedMessage(PeerInfo, Message), - /// Indicates a peer has disconnected. - /// - /// Same semantics as `PeerRemoved`, but the peer is not returned. - PeerDisconnect(PeerInfo), +impl Stream for Manager +where + Peer: Sink> + + Stream> + + TryStream + + std::fmt::Debug + + Send + + Unpin + + 'static, + Message: ManagedMessage + Send + 'static, +{ + type Item = Result, PeerManagerOutputError>; + + fn poll_next(mut self: std::pin::Pin<&mut Self>, cx: &mut std::task::Context<'_>) -> std::task::Poll> { + self.stream.poll_next_unpin(cx) + } } diff --git a/packages/peer/src/manager/peer_manager.rs b/packages/peer/src/manager/peer_manager.rs deleted file mode 100644 index 214c15636..000000000 --- a/packages/peer/src/manager/peer_manager.rs +++ /dev/null @@ -1,67 +0,0 @@ -use std::collections::HashMap; -use std::marker::PhantomData; -use std::sync::{Arc, Mutex}; - -use crossbeam::queue::SegQueue; -use futures::channel::mpsc::{self}; -use futures::sink::Sink; -use futures::stream::Stream; -use futures::TryStream; - -use super::peer_manager_sink::PeerManagerSink; -use super::peer_manager_stream::PeerManagerStream; -use super::ManagedMessage; -use crate::PeerManagerBuilder; - -/// Manages a set of peers with beating hearts. -pub struct PeerManager -where - Peer: Sink> - + Stream> - + TryStream - + std::fmt::Debug - + Send - + Unpin - + 'static, - Message: ManagedMessage + Send + 'static, -{ - sink: PeerManagerSink, - stream: PeerManagerStream, - _peer_marker: PhantomData, -} - -impl PeerManager -where - Peer: Sink> - + Stream> - + TryStream - + std::fmt::Debug - + Send - + Unpin - + 'static, - Message: ManagedMessage + Send + 'static, -{ - /// Create a new `PeerManager` from the given `PeerManagerBuilder`. - #[must_use] - pub fn from_builder(builder: PeerManagerBuilder) -> PeerManager { - let (res_send, res_recv) = mpsc::channel(builder.stream_buffer_capacity()); - let peers = Arc::new(Mutex::new(HashMap::new())); - let task_queue = Arc::new(SegQueue::new()); - - let sink = PeerManagerSink::new(builder, res_send, peers.clone(), task_queue.clone()); - let stream = PeerManagerStream::new(res_recv, peers); - - PeerManager { - sink, - stream, - _peer_marker: PhantomData, - } - } - - /// Break the `PeerManager` into a sink and stream. - /// - /// The returned sink implements `Clone`. - pub fn into_parts(self) -> (PeerManagerSink, PeerManagerStream) { - (self.sink, self.stream) - } -} diff --git a/packages/peer/src/manager/peer_manager_sink.rs b/packages/peer/src/manager/sink.rs similarity index 90% rename from packages/peer/src/manager/peer_manager_sink.rs rename to packages/peer/src/manager/sink.rs index a68603158..68dcfd8d0 100644 --- a/packages/peer/src/manager/peer_manager_sink.rs +++ b/packages/peer/src/manager/sink.rs @@ -4,20 +4,21 @@ use std::pin::Pin; use std::sync::{Arc, Mutex}; use crossbeam::queue::SegQueue; -use futures::channel::mpsc::{SendError, Sender}; +use futures::channel::mpsc::{self, SendError}; use futures::sink::Sink; use futures::task::{Context, Poll}; use futures::{SinkExt as _, Stream, TryStream}; +use super::messages::{PeerManagerInputMessage, PeerManagerOutputError, PeerManagerOutputMessage}; use super::task::run_peer; -use super::{PeerManagerInputMessage, PeerManagerOutputError, PeerManagerOutputMessage}; use crate::manager::builder::PeerManagerBuilder; use crate::manager::error::PeerManagerError; use crate::manager::peer_info::PeerInfo; use crate::manager::ManagedMessage; /// Sink half of a `PeerManager`. -pub struct PeerManagerSink +#[allow(clippy::module_name_repetitions)] +pub struct ManagerSink where Peer: Sink> + Stream> @@ -29,13 +30,13 @@ where Message: ManagedMessage + Send + 'static, { builder: PeerManagerBuilder, - sender: Sender, PeerManagerOutputError>>, + sender: mpsc::Sender, PeerManagerOutputError>>, #[allow(clippy::type_complexity)] - peers: Arc>>>>, + peers: Arc>>>>, task_queue: Arc>>, } -impl Clone for PeerManagerSink +impl Clone for ManagerSink where Peer: Sink> + Stream> @@ -46,8 +47,8 @@ where + 'static, Message: ManagedMessage + Send + 'static, { - fn clone(&self) -> PeerManagerSink { - PeerManagerSink { + fn clone(&self) -> ManagerSink { + ManagerSink { builder: self.builder, sender: self.sender.clone(), peers: self.peers.clone(), @@ -56,7 +57,7 @@ where } } -impl PeerManagerSink +impl ManagerSink where Peer: Sink> + Stream> @@ -70,11 +71,11 @@ where #[allow(clippy::type_complexity)] pub fn new( builder: PeerManagerBuilder, - sender: Sender, PeerManagerOutputError>>, - peers: Arc>>>>, + sender: mpsc::Sender, PeerManagerOutputError>>, + peers: Arc>>>>, task_queue: Arc>>, - ) -> PeerManagerSink { - PeerManagerSink { + ) -> ManagerSink { + ManagerSink { builder, sender, peers, @@ -83,7 +84,7 @@ where } } -impl PeerManagerSink +impl ManagerSink where Peer: Sink> + Stream> @@ -179,7 +180,7 @@ where } } -impl Sink>> for PeerManagerSink +impl Sink>> for ManagerSink where Peer: Sink> + Stream> diff --git a/packages/peer/src/manager/peer_manager_stream.rs b/packages/peer/src/manager/stream.rs similarity index 85% rename from packages/peer/src/manager/peer_manager_stream.rs rename to packages/peer/src/manager/stream.rs index 91e8e4136..908f08125 100644 --- a/packages/peer/src/manager/peer_manager_stream.rs +++ b/packages/peer/src/manager/stream.rs @@ -2,17 +2,18 @@ use std::collections::HashMap; use std::sync::{Arc, Mutex}; use std::task::{Context, Poll}; -use futures::channel::mpsc::{Receiver, Sender}; +use futures::channel::mpsc; use futures::stream::Stream; use futures::{Sink, StreamExt, TryStream}; use pin_project::pin_project; -use super::{ManagedMessage, PeerManagerInputMessage, PeerManagerOutputError, PeerManagerOutputMessage}; +use super::messages::{ManagedMessage, PeerManagerInputMessage, PeerManagerOutputError, PeerManagerOutputMessage}; use crate::manager::peer_info::PeerInfo; /// Stream half of a `PeerManager`. +#[allow(clippy::module_name_repetitions)] #[pin_project] -pub struct PeerManagerStream +pub struct ManagerStream where Peer: Sink> + Stream> @@ -23,13 +24,13 @@ where + 'static, Message: ManagedMessage + Send + 'static, { - recv: Receiver, PeerManagerOutputError>>, + recv: mpsc::Receiver, PeerManagerOutputError>>, #[allow(clippy::type_complexity)] - peers: Arc>>>>, + peers: Arc>>>>, opt_pending: Option, PeerManagerOutputError>>, } -impl PeerManagerStream +impl ManagerStream where Peer: Sink> + Stream> @@ -42,8 +43,8 @@ where { #[allow(clippy::type_complexity)] pub fn new( - recv: Receiver, PeerManagerOutputError>>, - peers: Arc>>>>, + recv: mpsc::Receiver, PeerManagerOutputError>>, + peers: Arc>>>>, ) -> Self { Self { recv, @@ -53,7 +54,7 @@ where } } -impl Stream for PeerManagerStream +impl Stream for ManagerStream where Peer: Sink> + Stream> diff --git a/packages/peer/src/manager/task.rs b/packages/peer/src/manager/task.rs index 249108c62..ae8c71a6d 100644 --- a/packages/peer/src/manager/task.rs +++ b/packages/peer/src/manager/task.rs @@ -1,14 +1,15 @@ -use futures::channel::mpsc::{self, SendError, Sender}; +use futures::channel::mpsc::{self, SendError}; use futures::stream::SplitSink; use futures::{Sink, SinkExt, Stream, StreamExt, TryStream, TryStreamExt}; use thiserror::Error; use tokio::task::{self, JoinHandle}; use super::future::{PersistentError, PersistentStream, RecurringTimeoutError, RecurringTimeoutStream}; -use super::{PeerManagerInputMessage, PeerManagerOutputError, PeerManagerOutputMessage}; +use super::messages::{PeerManagerInputMessage, PeerManagerOutputMessage}; use crate::manager::builder::PeerManagerBuilder; use crate::manager::peer_info::PeerInfo; use crate::manager::ManagedMessage; +use crate::PeerManagerOutputError; #[derive(Error, Debug)] enum PeerError { @@ -64,9 +65,9 @@ where pub fn run_peer( peer: Peer, info: PeerInfo, - mut send: Sender, PeerManagerOutputError>>, + mut send: mpsc::Sender, PeerManagerOutputError>>, builder: &PeerManagerBuilder, -) -> (Sender>, JoinHandle<()>) +) -> (mpsc::Sender>, JoinHandle<()>) where Peer: Sink> + Stream> @@ -118,7 +119,7 @@ where async fn handle_stream_result( result: Result, MergedError>, peer_send: &mut SplitSink>, - manager_send: &mut Sender, PeerManagerOutputError>>, + manager_send: &mut mpsc::Sender, PeerManagerOutputError>>, info: &PeerInfo, ) -> Result<(), PeerError<>>::Error, SendError>> where diff --git a/packages/peer/src/message/bencode_util.rs b/packages/peer/src/message/bencode_util.rs index 142a61e73..5cff6320c 100644 --- a/packages/peer/src/message/bencode_util.rs +++ b/packages/peer/src/message/bencode_util.rs @@ -1,6 +1,6 @@ use std::collections::HashMap; use std::net::{IpAddr, Ipv4Addr, Ipv6Addr}; -use std::{io, str}; +use std::str; use bencode::{BConvert, BDictAccess, BRefAccess, BencodeConvertError}; use util::convert; @@ -15,7 +15,7 @@ impl BConvert for IoErrorBencodeConvert { type Error = std::io::Error; fn handle_error(&self, error: BencodeConvertError) -> Self::Error { - std::io::Error::new(io::ErrorKind::Other, error.to_string()) + std::io::Error::new(std::io::ErrorKind::Other, error.to_string()) } } diff --git a/packages/peer/src/message/bits_ext/handshake.rs b/packages/peer/src/message/bits_ext/handshake.rs index 5816da20b..d8e606006 100644 --- a/packages/peer/src/message/bits_ext/handshake.rs +++ b/packages/peer/src/message/bits_ext/handshake.rs @@ -1,6 +1,5 @@ use std::collections::HashMap; -use std::io::Write; -use std::mem; +use std::io::Write as _; use std::net::{IpAddr, Ipv4Addr, Ipv6Addr}; use bencode::{ben_bytes, ben_int, BConvert, BDecodeOpt, BMutAccess, BencodeMut, BencodeRef}; @@ -346,7 +345,7 @@ impl ExtendedMessage { #[must_use] pub fn from_builder(mut builder: ExtendedMessageBuilder) -> ExtendedMessage { let mut custom_entries = HashMap::new(); - mem::swap(&mut custom_entries, &mut builder.custom_entries); + std::mem::swap(&mut custom_entries, &mut builder.custom_entries); let encoded_bytes = bencode_from_builder(&builder, custom_entries); let mut raw_bencode = BytesMut::with_capacity(encoded_bytes.len()); @@ -434,7 +433,7 @@ impl ExtendedMessage { /// This function will panic if the bencode size is too large. pub fn write_bytes(&self, mut writer: W) -> std::io::Result where - W: Write, + W: std::io::Write, { let real_length: u32 = (self.bencode_size() + 2) .try_into() diff --git a/packages/peer/src/message/bits_ext/mod.rs b/packages/peer/src/message/bits_ext/mod.rs index 148eb3ca1..84a1dd676 100644 --- a/packages/peer/src/message/bits_ext/mod.rs +++ b/packages/peer/src/message/bits_ext/mod.rs @@ -1,5 +1,5 @@ use std::collections::HashMap; -use std::io::Write; +use std::io::Write as _; use std::net::{IpAddr, Ipv4Addr, Ipv6Addr}; use bencode::{BConvert, BDecodeOpt, BMutAccess, BencodeMut, BencodeRef}; @@ -101,7 +101,7 @@ impl BitsExtensionMessage { /// This function will return an error if unable to write the bytes. pub fn write_bytes(&self, mut writer: W) -> std::io::Result where - W: Write, + W: std::io::Write, { match self { BitsExtensionMessage::Port(msg) => msg.write_bytes(writer), diff --git a/packages/peer/src/message/bits_ext/port.rs b/packages/peer/src/message/bits_ext/port.rs index c6641c548..ea7656bbe 100644 --- a/packages/peer/src/message/bits_ext/port.rs +++ b/packages/peer/src/message/bits_ext/port.rs @@ -1,5 +1,4 @@ -use std::io; -use std::io::Write; +use std::io::Write as _; use bytes::{BufMut, Bytes, BytesMut}; use nom::combinator::map; @@ -59,7 +58,7 @@ impl PortMessage { /// This function will return an error if unable to write the bytes. pub fn write_bytes(&self, mut writer: W) -> std::io::Result where - W: Write, + W: std::io::Write, { let length_len = message::write_length_id_pair(&mut writer, bits_ext::PORT_MESSAGE_LEN, Some(bits_ext::PORT_MESSAGE_ID))?; diff --git a/packages/peer/src/message/mod.rs b/packages/peer/src/message/mod.rs index 763e700a3..080865789 100644 --- a/packages/peer/src/message/mod.rs +++ b/packages/peer/src/message/mod.rs @@ -4,7 +4,7 @@ // Nom has lots of unused warnings atm, keep this here for now. -use std::io::Write; +use std::io::Write as _; use byteorder::{BigEndian, WriteBytesExt}; use bytes::Bytes; @@ -16,7 +16,6 @@ use nom::sequence::{preceded, tuple}; use nom::IResult; use thiserror::Error; -use crate::manager::ManagedMessage; use crate::protocol::PeerProtocol; // TODO: Propagate failures to cast values to/from usize @@ -63,6 +62,7 @@ pub use crate::message::prot_ext::{ }; #[allow(clippy::module_name_repetitions)] pub use crate::message::standard::{BitFieldIter, BitFieldMessage, CancelMessage, HaveMessage, PieceMessage, RequestMessage}; +use crate::ManagedMessage; #[derive(Error, Debug, Clone)] pub enum PeerWireProtocolMessageError {} @@ -170,7 +170,7 @@ where /// This function will return an error if unable to write bytes. pub fn write_bytes(&self, writer: W, ext_protocol: &mut P) -> std::io::Result where - W: Write, + W: std::io::Write, { match self { &PeerWireProtocolMessage::KeepAlive => write_length_id_pair(writer, KEEP_ALIVE_MESSAGE_LEN, None), @@ -220,7 +220,7 @@ where /// Write a length and optional id out to the given writer. fn write_length_id_pair(mut writer: W, length: u32, opt_id: Option) -> std::io::Result where - W: Write, + W: std::io::Write, { writer.write_u32::(length)?; diff --git a/packages/peer/src/message/prot_ext/mod.rs b/packages/peer/src/message/prot_ext/mod.rs index f53249182..c3743c09d 100644 --- a/packages/peer/src/message/prot_ext/mod.rs +++ b/packages/peer/src/message/prot_ext/mod.rs @@ -1,4 +1,4 @@ -use std::io::Write; +use std::io::Write as _; use std::ops::Deref; use std::rc::Rc; use std::sync::Arc; @@ -124,7 +124,7 @@ where /// This function will panic if the message is too long. pub fn write_bytes(&self, mut writer: W, extended: &ExtendedMessage, custom_prot: &mut P) -> std::io::Result where - W: Write, + W: std::io::Write, { match self { PeerExtensionProtocolMessage::UtMetadata(msg) => { diff --git a/packages/peer/src/message/prot_ext/ut_metadata.rs b/packages/peer/src/message/prot_ext/ut_metadata.rs index 394119010..1c8c58dfb 100644 --- a/packages/peer/src/message/prot_ext/ut_metadata.rs +++ b/packages/peer/src/message/prot_ext/ut_metadata.rs @@ -1,5 +1,4 @@ -use std::io; -use std::io::Write; +use std::io::Write as _; use bencode::{ben_int, ben_map, BConvert, BDecodeOpt, BencodeRef}; use bytes::Bytes; @@ -74,7 +73,7 @@ impl UtMetadataMessage { Ok(message) } - Err(err) => Err(io::Error::new( + Err(err) => Err(std::io::Error::new( std::io::ErrorKind::Other, format!("Failed To Parse UtMetadataMessage As Bencode: {err}"), )), @@ -88,7 +87,7 @@ impl UtMetadataMessage { /// This function will return an error if unable to write the bytes. pub fn write_bytes(&self, writer: W) -> std::io::Result<()> where - W: Write, + W: std::io::Write, { match self { UtMetadataMessage::Request(request) => request.write_bytes(writer), @@ -146,7 +145,7 @@ impl UtMetadataRequestMessage { /// This function will return an error if unable to write the bytes. pub fn write_bytes(&self, mut writer: W) -> std::io::Result<()> where - W: Write, + W: std::io::Write, { let encoded_bytes = (ben_map! { bencode_util::MESSAGE_TYPE_KEY => ben_int!(i64::from(REQUEST_MESSAGE_TYPE_ID)), @@ -212,7 +211,7 @@ impl UtMetadataDataMessage { /// This function will return an error if unable to write bytes. pub fn write_bytes(&self, mut writer: W) -> std::io::Result<()> where - W: Write, + W: std::io::Write, { let encoded_bytes = (ben_map! { bencode_util::MESSAGE_TYPE_KEY => ben_int!(i64::from(DATA_MESSAGE_TYPE_ID)), @@ -281,7 +280,7 @@ impl UtMetadataRejectMessage { /// This function will return an error if unable to write the bytes. pub fn write_bytes(&self, mut writer: W) -> std::io::Result<()> where - W: Write, + W: std::io::Write, { let encoded_bytes = (ben_map! { bencode_util::MESSAGE_TYPE_KEY => ben_int!(i64::from(REJECT_MESSAGE_TYPE_ID)), diff --git a/packages/peer/src/message/standard.rs b/packages/peer/src/message/standard.rs index fd391f035..73aef3c85 100644 --- a/packages/peer/src/message/standard.rs +++ b/packages/peer/src/message/standard.rs @@ -1,4 +1,4 @@ -use std::io::Write; +use std::io::Write as _; use byteorder::{BigEndian, WriteBytesExt}; use bytes::Bytes; @@ -62,7 +62,7 @@ impl HaveMessage { /// This function will return an error if unable to write bytes. pub fn write_bytes(&self, mut writer: W) -> std::io::Result where - W: Write, + W: std::io::Write, { let id_length = message::write_length_id_pair(&mut writer, message::HAVE_MESSAGE_LEN, Some(message::HAVE_MESSAGE_ID))?; let () = writer.write_u32::(self.piece_index)?; @@ -161,7 +161,7 @@ impl BitFieldMessage { /// This function will panic if the length is too long. pub fn write_bytes(&self, mut writer: W) -> std::io::Result where - W: Write, + W: std::io::Write, { let message_length: u32 = self .bytes @@ -326,7 +326,7 @@ impl RequestMessage { /// This function will panic if the `block_length` is too large. pub fn write_bytes(&self, mut writer: W) -> std::io::Result where - W: Write, + W: std::io::Write, { let id_length = message::write_length_id_pair(&mut writer, message::REQUEST_MESSAGE_LEN, Some(message::REQUEST_MESSAGE_ID))?; @@ -464,7 +464,7 @@ impl PieceMessage { /// This function will panic if the block length is too large. pub fn write_bytes(&self, mut writer: W) -> std::io::Result where - W: Write, + W: std::io::Write, { let block_length: u32 = self .block_length() @@ -618,7 +618,7 @@ impl CancelMessage { /// This function will panic if the block length is too large. pub fn write_bytes(&self, mut writer: W) -> std::io::Result where - W: Write, + W: std::io::Write, { let id_length = message::write_length_id_pair(&mut writer, message::CANCEL_MESSAGE_LEN, Some(message::CANCEL_MESSAGE_ID))?; diff --git a/packages/peer/src/protocol/extension.rs b/packages/peer/src/protocol/extension.rs index 4b010b121..76c0c400a 100644 --- a/packages/peer/src/protocol/extension.rs +++ b/packages/peer/src/protocol/extension.rs @@ -1,5 +1,3 @@ -use std::io::Write; - use crate::message::{ExtendedMessage, PeerExtensionProtocolMessage, PeerExtensionProtocolMessageError}; use crate::protocol::{NestedPeerProtocol, PeerProtocol}; @@ -60,7 +58,7 @@ where writer: W, ) -> std::io::Result where - W: Write, + W: std::io::Write, { let message = match item { Ok(message) => message, diff --git a/packages/peer/src/protocol/mod.rs b/packages/peer/src/protocol/mod.rs index a2f5367ca..17b1a5743 100644 --- a/packages/peer/src/protocol/mod.rs +++ b/packages/peer/src/protocol/mod.rs @@ -1,7 +1,5 @@ //! Generic `PeerProtocol` implementations. -use std::io::Write; - pub mod extension; pub mod null; pub mod unit; @@ -45,7 +43,7 @@ pub trait PeerProtocol { writer: W, ) -> std::io::Result where - W: Write; + W: std::io::Write; /// Retrieve how many bytes the message will occupy on the wire. /// diff --git a/packages/peer/src/protocol/null.rs b/packages/peer/src/protocol/null.rs index 373f24e63..0532e2510 100644 --- a/packages/peer/src/protocol/null.rs +++ b/packages/peer/src/protocol/null.rs @@ -1,5 +1,3 @@ -use std::io::Write; - use crate::message::NullProtocolMessage; use crate::protocol::{NestedPeerProtocol, PeerProtocol}; @@ -40,7 +38,7 @@ impl PeerProtocol for NullProtocol { fn write_bytes(&mut self, _: &Result, _: W) -> std::io::Result where - W: Write, + W: std::io::Write, { panic!( "bip_peer: NullProtocol::write_bytes Was Called...Wait, How Did You Construct An Instance Of NullProtocolMessage? :)" diff --git a/packages/peer/src/protocol/unit.rs b/packages/peer/src/protocol/unit.rs index c0487a68d..07370ca1a 100644 --- a/packages/peer/src/protocol/unit.rs +++ b/packages/peer/src/protocol/unit.rs @@ -1,5 +1,3 @@ -use std::io::Write; - use crate::protocol::{NestedPeerProtocol, PeerProtocol}; /// Unit protocol which will always return a unit if called. @@ -30,7 +28,7 @@ impl PeerProtocol for UnitProtocol { fn write_bytes(&mut self, _: &Result, _: W) -> std::io::Result where - W: Write, + W: std::io::Write, { Ok(0) } diff --git a/packages/peer/src/protocol/wire.rs b/packages/peer/src/protocol/wire.rs index a353dffae..833958097 100644 --- a/packages/peer/src/protocol/wire.rs +++ b/packages/peer/src/protocol/wire.rs @@ -1,5 +1,3 @@ -use std::io::Write; - use crate::message::{BitsExtensionMessage, ExtendedMessage, PeerWireProtocolMessage, PeerWireProtocolMessageError}; use crate::protocol::{NestedPeerProtocol, PeerProtocol}; @@ -59,7 +57,7 @@ where writer: W, ) -> std::io::Result where - W: Write, + W: std::io::Write, { let message = match item { Ok(message) => message, diff --git a/packages/peer/tests/common/connected_channel.rs b/packages/peer/tests/common/connected_channel.rs index b10cd0298..f68a13f6b 100644 --- a/packages/peer/tests/common/connected_channel.rs +++ b/packages/peer/tests/common/connected_channel.rs @@ -2,13 +2,13 @@ use std::pin::Pin; use std::sync::{Arc, Mutex}; use std::task::{Context, Poll}; -use futures::channel::mpsc::{Receiver, Sender}; +use futures::channel::mpsc; use futures::{Sink, SinkExt as _, Stream, StreamExt as _}; #[derive(Debug)] pub struct ConnectedChannel { - send: Sender, - recv: Arc>>, + send: mpsc::Sender, + recv: Arc>>, } impl Clone for ConnectedChannel { diff --git a/packages/peer/tests/common/mod.rs b/packages/peer/tests/common/mod.rs index be41c54f1..437412b6a 100644 --- a/packages/peer/tests/common/mod.rs +++ b/packages/peer/tests/common/mod.rs @@ -24,7 +24,7 @@ where #[error("Receive Timed Out")] ReceiveTimedOut(Elapsed), - #[error("Receiver Closed")] + #[error("mpsc::Receiver Closed")] ReceiverClosed(), #[error("Peer Manager Input Error {0}")] diff --git a/packages/select/Cargo.toml b/packages/select/Cargo.toml index cfab79534..443f35945 100644 --- a/packages/select/Cargo.toml +++ b/packages/select/Cargo.toml @@ -1,7 +1,7 @@ [package] -name = "select" description = "Bittorrent Infrastructure Project Piece Selection Module" keywords = ["piece", "selection"] +name = "select" readme = "README.md" authors.workspace = true @@ -17,9 +17,9 @@ version.workspace = true [dependencies] handshake = { path = "../handshake" } -util = { path = "../util" } -peer = { path = "../peer" } metainfo = { path = "../metainfo" } +peer = { path = "../peer" } +util = { path = "../util" } utracker = { path = "../utracker" } bit-set = "0" diff --git a/packages/select/src/discovery/ut_metadata.rs b/packages/select/src/discovery/ut_metadata.rs index 7150e5b46..ad15d70db 100644 --- a/packages/select/src/discovery/ut_metadata.rs +++ b/packages/select/src/discovery/ut_metadata.rs @@ -1,6 +1,6 @@ use std::collections::hash_map::Entry; use std::collections::{HashMap, HashSet, VecDeque}; -use std::io::Write; +use std::io::Write as _; use std::pin::Pin; use std::task::{Context, Poll, Waker}; use std::time::Duration; diff --git a/packages/select/src/uber.rs b/packages/select/src/uber.rs deleted file mode 100644 index 2aa25b537..000000000 --- a/packages/select/src/uber.rs +++ /dev/null @@ -1,250 +0,0 @@ -use std::pin::Pin; -use std::sync::{Arc, Mutex}; -use std::task::{Context, Poll}; - -use futures::{Sink, SinkExt, Stream, StreamExt as _}; -use peer::messages::builders::ExtendedMessageBuilder; - -use crate::discovery::error::DiscoveryError; -use crate::discovery::{IDiscoveryMessage, ODiscoveryMessage}; -use crate::error::Error; -use crate::extended::{ExtendedListener, ExtendedModule, IExtendedMessage, OExtendedMessage}; -use crate::ControlMessage; - -pub trait DiscoveryTrait: - ExtendedListener - + Sink - + Stream> - + Send - + Unpin - + 'static -{ -} -impl DiscoveryTrait for T where - T: ExtendedListener - + Sink - + Stream> - + Send - + Unpin - + 'static -{ -} - -/// Enumeration of uber messages that can be sent to the uber module. -#[derive(Clone, Debug, PartialEq, Eq)] -pub enum IUberMessage { - /// Broadcast a control message out to all modules. - Control(Box), - /// Send an extended message to the extended module. - Extended(Box), - /// Send a discovery message to all discovery modules. - Discovery(Box), -} - -/// Enumeration of uber messages that can be received from the uber module. -#[derive(Clone, Debug, PartialEq, Eq)] -pub enum OUberMessage { - /// Receive an extended message from the extended module. - Extended(OExtendedMessage), - /// Receive a discovery message from some discovery module. - Discovery(ODiscoveryMessage), -} - -type UberDiscovery = Arc< - Mutex> + Send + Sync>>>, ->; - -/// Builder for constructing an `UberModule`. -#[allow(clippy::module_name_repetitions)] -#[derive(Default)] -pub struct UberModuleBuilder { - pub discovery: UberDiscovery, - ext_builder: Option, -} - -impl UberModuleBuilder { - /// Create a new `UberModuleBuilder`. - #[must_use] - pub fn new() -> UberModuleBuilder { - UberModuleBuilder { - discovery: Arc::default(), - ext_builder: None, - } - } - - /// Specifies the given builder that all modules will add to when sending an extended message to a peer. - /// - /// This message will only be sent when the extension bit from the handshake it set. Note that if a builder - /// is not given and a peer with the extension bit set connects, we will NOT send any extended message. - #[must_use] - pub fn with_extended_builder(mut self, builder: Option) -> UberModuleBuilder { - self.ext_builder = builder; - self - } - - /// Add the given discovery module to the list of discovery modules. - /// - /// # Panics - /// - /// It would panic if unable to get a lock for the discovery. - #[must_use] - pub fn with_discovery_module(self, module: T) -> UberModuleBuilder - where - T: ExtendedListener - + Sink - + Stream> - + Send - + Sync - + Unpin - + 'static, - { - self.discovery.lock().unwrap().push(Arc::new(module)); - self - } - - /// Build an `UberModule` based on the current builder. - #[must_use] - pub fn build(self) -> UberModule { - UberModule::from_builder(self) - } -} - -//----------------------------------------------------------------------// -/// Module for multiplexing messages across zero or more other modules. -#[allow(clippy::module_name_repetitions)] -pub struct UberModule { - sink: UberSink, - stream: UberStream, -} - -impl UberModule { - /// Create an `UberModule` from the given `UberModuleBuilder`. - pub fn from_builder(builder: UberModuleBuilder) -> UberModule { - let discovery = builder.discovery; - let extended = builder.ext_builder.map(ExtendedModule::new); - - UberModule { - sink: UberSink { - discovery: discovery.clone(), - extended: extended.clone(), - }, - stream: UberStream { discovery, extended }, - } - } - - /// Splits the `UberModule` into its parts. - #[must_use] - pub fn into_parts(self) -> (UberSink, UberStream) { - (self.sink, self.stream) - } -} - -//----------------------------------------------------------------------// -/// `Sink` portion of the `UberModule` for sending messages. -#[allow(clippy::module_name_repetitions)] -#[derive(Clone)] -pub struct UberSink { - discovery: UberDiscovery, - extended: Option, -} - -impl UberSink { - fn handle_message(&mut self, message: IUberMessage) -> Result<(), Error> { - match message { - IUberMessage::Control(control) => { - if let Some(extended) = &mut self.extended { - let mut discovery = self.discovery.lock().unwrap(); - let d_modules = discovery.as_mut_slice(); - extended.process_message(IExtendedMessage::Control(*control.clone()), d_modules); - } - for discovery in self.discovery.lock().unwrap().iter_mut() { - Arc::get_mut(discovery) - .unwrap() - .start_send_unpin(IDiscoveryMessage::Control(*control.clone()))?; - } - } - IUberMessage::Extended(extended) => { - if let Some(ext_module) = &mut self.extended { - let mut discovery = self.discovery.lock().unwrap(); - let d_modules = discovery.as_mut_slice(); - ext_module.process_message(*extended.clone(), d_modules); - } - } - IUberMessage::Discovery(discovery) => { - for discovery_module in self.discovery.lock().unwrap().iter_mut() { - Arc::get_mut(discovery_module).unwrap().start_send_unpin(*discovery.clone())?; - } - } - } - Ok(()) - } - - fn poll_discovery_flush(&mut self, cx: &mut Context<'_>) -> Poll> { - for discovery in self.discovery.lock().unwrap().iter_mut() { - match Arc::get_mut(discovery).unwrap().poll_flush_unpin(cx) { - Poll::Ready(Ok(())) => continue, - Poll::Ready(Err(e)) => return Poll::Ready(Err(Error::Discovery(e))), - Poll::Pending => { - cx.waker().wake_by_ref(); - return Poll::Pending; - } - } - } - Poll::Ready(Ok(())) - } -} - -impl Sink for UberSink { - type Error = Error; - - fn poll_ready(self: Pin<&mut Self>, _: &mut Context<'_>) -> Poll> { - Poll::Ready(Ok(())) - } - - fn start_send(mut self: Pin<&mut Self>, item: IUberMessage) -> Result<(), Self::Error> { - self.handle_message(item) - } - - fn poll_flush(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { - self.poll_discovery_flush(cx) - } - - fn poll_close(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { - self.poll_discovery_flush(cx) - } -} - -//----------------------------------------------------------------------// -/// `Stream` portion of the `UberModule` for receiving messages. -#[allow(clippy::module_name_repetitions)] -pub struct UberStream { - discovery: UberDiscovery, - extended: Option, -} - -impl Stream for UberStream { - type Item = Result; - - fn poll_next(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { - if let Some(extended) = &mut self.extended { - match extended.poll_next_unpin(cx) { - Poll::Ready(Some(Ok(message))) => return Poll::Ready(Some(Ok(OUberMessage::Extended(message)))), - Poll::Ready(Some(Err(e))) => return Poll::Ready(Some(Err(e))), - Poll::Ready(None) => return Poll::Ready(None), - Poll::Pending => (), - } - }; - - for discovery in self.discovery.lock().unwrap().iter_mut() { - match Arc::get_mut(discovery).unwrap().poll_next_unpin(cx) { - Poll::Ready(Some(Ok(message))) => return Poll::Ready(Some(Ok(OUberMessage::Discovery(message)))), - Poll::Ready(Some(Err(e))) => return Poll::Ready(Some(Err(Error::Discovery(e)))), - Poll::Ready(None) => return Poll::Ready(None), - Poll::Pending => (), - } - } - - cx.waker().wake_by_ref(); - Poll::Pending - } -} diff --git a/packages/select/src/uber/mod.rs b/packages/select/src/uber/mod.rs new file mode 100644 index 000000000..617069028 --- /dev/null +++ b/packages/select/src/uber/mod.rs @@ -0,0 +1,142 @@ +use std::sync::{Arc, Mutex}; + +use futures::{Sink, Stream}; +use peer::messages::builders::ExtendedMessageBuilder; +use sink::UberSink; +use stream::UberStream; + +use crate::discovery::error::DiscoveryError; +use crate::discovery::{IDiscoveryMessage, ODiscoveryMessage}; +use crate::extended::{ExtendedListener, ExtendedModule, IExtendedMessage, OExtendedMessage}; +use crate::ControlMessage; + +pub mod sink; +pub mod stream; + +pub trait DiscoveryTrait: + ExtendedListener + + Sink + + Stream> + + Send + + Unpin + + 'static +{ +} +impl DiscoveryTrait for T where + T: ExtendedListener + + Sink + + Stream> + + Send + + Unpin + + 'static +{ +} + +/// Enumeration of uber messages that can be sent to the uber module. +#[derive(Clone, Debug, PartialEq, Eq)] +pub enum IUberMessage { + /// Broadcast a control message out to all modules. + Control(Box), + /// Send an extended message to the extended module. + Extended(Box), + /// Send a discovery message to all discovery modules. + Discovery(Box), +} + +/// Enumeration of uber messages that can be received from the uber module. +#[derive(Clone, Debug, PartialEq, Eq)] +pub enum OUberMessage { + /// Receive an extended message from the extended module. + Extended(OExtendedMessage), + /// Receive a discovery message from some discovery module. + Discovery(ODiscoveryMessage), +} + +type UberDiscovery = Arc< + Mutex> + Send + Sync>>>, +>; + +/// Builder for constructing an `UberModule`. +#[allow(clippy::module_name_repetitions)] +#[derive(Default)] +pub struct UberModuleBuilder { + pub discovery: UberDiscovery, + ext_builder: Option, +} + +impl UberModuleBuilder { + /// Create a new `UberModuleBuilder`. + #[must_use] + pub fn new() -> UberModuleBuilder { + UberModuleBuilder { + discovery: Arc::default(), + ext_builder: None, + } + } + + /// Specifies the given builder that all modules will add to when sending an extended message to a peer. + /// + /// This message will only be sent when the extension bit from the handshake it set. Note that if a builder + /// is not given and a peer with the extension bit set connects, we will NOT send any extended message. + #[must_use] + pub fn with_extended_builder(mut self, builder: Option) -> UberModuleBuilder { + self.ext_builder = builder; + self + } + + /// Add the given discovery module to the list of discovery modules. + /// + /// # Panics + /// + /// It would panic if unable to get a lock for the discovery. + #[must_use] + pub fn with_discovery_module(self, module: T) -> UberModuleBuilder + where + T: ExtendedListener + + Sink + + Stream> + + Send + + Sync + + Unpin + + 'static, + { + self.discovery.lock().unwrap().push(Arc::new(module)); + self + } + + /// Build an `UberModule` based on the current builder. + #[must_use] + pub fn build(self) -> UberModule { + UberModule::from_builder(self) + } +} + +//----------------------------------------------------------------------// +/// Module for multiplexing messages across zero or more other modules. +#[allow(clippy::module_name_repetitions)] +pub struct UberModule { + sink: UberSink, + stream: UberStream, +} + +impl UberModule { + /// Create an `UberModule` from the given `UberModuleBuilder`. + pub fn from_builder(builder: UberModuleBuilder) -> UberModule { + let discovery = builder.discovery; + let extended = builder.ext_builder.map(ExtendedModule::new); + + UberModule { + sink: UberSink { + discovery: discovery.clone(), + extended: extended.clone(), + }, + stream: UberStream { discovery, extended }, + } + } + + /// Splits the `UberModule` into its parts. + #[must_use] + pub fn into_parts(self) -> (UberSink, UberStream) { + (self.sink, self.stream) + } +} diff --git a/packages/select/src/uber/sink.rs b/packages/select/src/uber/sink.rs new file mode 100644 index 000000000..222df041c --- /dev/null +++ b/packages/select/src/uber/sink.rs @@ -0,0 +1,86 @@ +use std::pin::Pin; +use std::sync::Arc; +use std::task::{Context, Poll}; + +use futures::{Sink, SinkExt as _}; + +use super::{IUberMessage, UberDiscovery}; +use crate::discovery::IDiscoveryMessage; +use crate::error::Error; +use crate::extended::ExtendedModule; +use crate::IExtendedMessage; + +//----------------------------------------------------------------------// +/// `Sink` portion of the `UberModule` for sending messages. +#[allow(clippy::module_name_repetitions)] +#[derive(Clone)] +pub struct UberSink { + pub(super) discovery: UberDiscovery, + pub(super) extended: Option, +} + +impl UberSink { + fn handle_message(&mut self, message: IUberMessage) -> Result<(), Error> { + match message { + IUberMessage::Control(control) => { + if let Some(extended) = &mut self.extended { + let mut discovery = self.discovery.lock().unwrap(); + let d_modules = discovery.as_mut_slice(); + extended.process_message(IExtendedMessage::Control(*control.clone()), d_modules); + } + for discovery in self.discovery.lock().unwrap().iter_mut() { + Arc::get_mut(discovery) + .unwrap() + .start_send_unpin(IDiscoveryMessage::Control(*control.clone()))?; + } + } + IUberMessage::Extended(extended) => { + if let Some(ext_module) = &mut self.extended { + let mut discovery = self.discovery.lock().unwrap(); + let d_modules = discovery.as_mut_slice(); + ext_module.process_message(*extended.clone(), d_modules); + } + } + IUberMessage::Discovery(discovery) => { + for discovery_module in self.discovery.lock().unwrap().iter_mut() { + Arc::get_mut(discovery_module).unwrap().start_send_unpin(*discovery.clone())?; + } + } + } + Ok(()) + } + + fn poll_discovery_flush(&mut self, cx: &mut Context<'_>) -> Poll> { + for discovery in self.discovery.lock().unwrap().iter_mut() { + match Arc::get_mut(discovery).unwrap().poll_flush_unpin(cx) { + Poll::Ready(Ok(())) => continue, + Poll::Ready(Err(e)) => return Poll::Ready(Err(Error::Discovery(e))), + Poll::Pending => { + cx.waker().wake_by_ref(); + return Poll::Pending; + } + } + } + Poll::Ready(Ok(())) + } +} + +impl Sink for UberSink { + type Error = Error; + + fn poll_ready(self: Pin<&mut Self>, _: &mut Context<'_>) -> Poll> { + Poll::Ready(Ok(())) + } + + fn start_send(mut self: Pin<&mut Self>, item: IUberMessage) -> Result<(), Self::Error> { + self.handle_message(item) + } + + fn poll_flush(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { + self.poll_discovery_flush(cx) + } + + fn poll_close(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { + self.poll_discovery_flush(cx) + } +} diff --git a/packages/select/src/uber/stream.rs b/packages/select/src/uber/stream.rs new file mode 100644 index 000000000..3b755397a --- /dev/null +++ b/packages/select/src/uber/stream.rs @@ -0,0 +1,44 @@ +use std::pin::Pin; +use std::sync::Arc; +use std::task::{Context, Poll}; + +use futures::{Stream, StreamExt as _}; + +use super::{OUberMessage, UberDiscovery}; +use crate::error::Error; +use crate::extended::ExtendedModule; + +//----------------------------------------------------------------------// +/// `Stream` portion of the `UberModule` for receiving messages. +#[allow(clippy::module_name_repetitions)] +pub struct UberStream { + pub(super) discovery: UberDiscovery, + pub(super) extended: Option, +} + +impl Stream for UberStream { + type Item = Result; + + fn poll_next(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { + if let Some(extended) = &mut self.extended { + match extended.poll_next_unpin(cx) { + Poll::Ready(Some(Ok(message))) => return Poll::Ready(Some(Ok(OUberMessage::Extended(message)))), + Poll::Ready(Some(Err(e))) => return Poll::Ready(Some(Err(e))), + Poll::Ready(None) => return Poll::Ready(None), + Poll::Pending => (), + } + }; + + for discovery in self.discovery.lock().unwrap().iter_mut() { + match Arc::get_mut(discovery).unwrap().poll_next_unpin(cx) { + Poll::Ready(Some(Ok(message))) => return Poll::Ready(Some(Ok(OUberMessage::Discovery(message)))), + Poll::Ready(Some(Err(e))) => return Poll::Ready(Some(Err(Error::Discovery(e)))), + Poll::Ready(None) => return Poll::Ready(None), + Poll::Pending => (), + } + } + + cx.waker().wake_by_ref(); + Poll::Pending + } +} diff --git a/packages/util/Cargo.toml b/packages/util/Cargo.toml index 1befdd165..8d885abac 100644 --- a/packages/util/Cargo.toml +++ b/packages/util/Cargo.toml @@ -1,7 +1,7 @@ [package] -name = "util" description = "Utilities for the Bittorrent Infrastructure Project" keywords = ["utility"] +name = "util" readme = "README.md" authors.workspace = true @@ -15,7 +15,6 @@ publish.workspace = true repository.workspace = true version.workspace = true - [dependencies] chrono = "0" num = "0" diff --git a/packages/util/src/contiguous.rs b/packages/util/src/contiguous.rs index b517c0f69..bee54024f 100644 --- a/packages/util/src/contiguous.rs +++ b/packages/util/src/contiguous.rs @@ -1,5 +1,3 @@ -use std::cmp; - /// Trait for metadata, reading, and writing to a contiguous buffer that doesn't re allocate. #[allow(clippy::module_name_repetitions)] pub trait ContiguousBuffer { @@ -125,7 +123,7 @@ where break; } let available_capacity = buffer.capacity() - buffer.length(); - let amount_to_write = cmp::min(available_capacity, data.len() - bytes_written); + let amount_to_write = std::cmp::min(available_capacity, data.len() - bytes_written); let (start, end) = (bytes_written, bytes_written + amount_to_write); diff --git a/packages/utp/Cargo.toml b/packages/utp/Cargo.toml index 20ea2fce5..9235233d3 100644 --- a/packages/utp/Cargo.toml +++ b/packages/utp/Cargo.toml @@ -1,7 +1,7 @@ [package] -name = "utp" description = "uTorrent Transport Protocol" -keywords = ["utp", "bittorrent", "transport"] +keywords = ["bittorrent", "transport", "utp"] +name = "utp" readme = "README.md" authors.workspace = true @@ -13,4 +13,4 @@ license.workspace = true publish.workspace = true repository.workspace = true -version.workspace = true \ No newline at end of file +version.workspace = true diff --git a/packages/utracker/Cargo.toml b/packages/utracker/Cargo.toml index 13961b77f..29dce63e8 100644 --- a/packages/utracker/Cargo.toml +++ b/packages/utracker/Cargo.toml @@ -1,7 +1,7 @@ [package] -name = "utracker" description = "Communication with bittorrent UDP trackers" -keywords = ["tracker", "bittorrent", "udp"] +keywords = ["bittorrent", "tracker", "udp"] +name = "utracker" readme = "README.md" authors.workspace = true @@ -24,9 +24,9 @@ chrono = "0" futures = "0" nom = "7" rand = "0" -umio = "0" -tracing = "0" thiserror = "1" +tracing = "0" +umio = "0" [dev-dependencies] tokio = { version = "1", features = ["full"] } diff --git a/packages/utracker/src/announce.rs b/packages/utracker/src/announce.rs index 82a0c6454..7906b6ec6 100644 --- a/packages/utracker/src/announce.rs +++ b/packages/utracker/src/announce.rs @@ -1,7 +1,7 @@ #![allow(deprecated)] //! Messaging primitives for announcing. -use std::io::Write; +use std::io::Write as _; use std::net::{Ipv4Addr, Ipv6Addr}; use byteorder::{BigEndian, WriteBytesExt}; @@ -98,7 +98,7 @@ impl<'a> AnnounceRequest<'a> { /// It would return an IO error if unable to write the bytes. pub fn write_bytes(&self, mut writer: W) -> std::io::Result<()> where - W: Write, + W: std::io::Write, { writer.write_all(self.info_hash.as_ref())?; writer.write_all(self.peer_id.as_ref())?; @@ -254,7 +254,7 @@ impl<'a> AnnounceResponse<'a> { /// It would return an IO Error if unable to write the bytes. pub fn write_bytes(&self, mut writer: W) -> std::io::Result<()> where - W: Write, + W: std::io::Write, { writer.write_i32::(self.interval)?; writer.write_i32::(self.leechers)?; @@ -354,7 +354,7 @@ impl ClientState { /// It would return an IO Error if unable to write the bytes. pub fn write_bytes(&self, mut writer: W) -> std::io::Result<()> where - W: Write, + W: std::io::Write, { writer.write_i64::(self.downloaded)?; writer.write_i64::(self.left)?; @@ -429,7 +429,7 @@ impl AnnounceEvent { /// It would return an IO Error if unable to write the bytes. pub fn write_bytes(&self, mut writer: W) -> std::io::Result<()> where - W: Write, + W: std::io::Write, { writer.write_i32::(self.as_id())?; @@ -501,7 +501,7 @@ impl SourceIP { /// It would return an IO Error if unable to write the bytes. pub fn write_bytes(&self, writer: W) -> std::io::Result<()> where - W: Write, + W: std::io::Write, { match *self { SourceIP::ImpliedV4 => SourceIP::write_bytes_slice(writer, &IMPLIED_IPV4_ID[..]), @@ -529,7 +529,7 @@ impl SourceIP { /// Write the given byte slice to the given writer. fn write_bytes_slice(mut writer: W, bytes: &[u8]) -> std::io::Result<()> where - W: Write, + W: std::io::Write, { writer.write_all(bytes) } @@ -593,7 +593,7 @@ impl DesiredPeers { /// It would return an IO Error if unable to write the bytes. pub fn write_bytes(&self, mut writer: W) -> std::io::Result<()> where - W: Write, + W: std::io::Write, { let write_value = match self { DesiredPeers::Default => DEFAULT_NUM_WANT, @@ -617,7 +617,7 @@ fn parse_desired(bytes: &[u8]) -> IResult<&[u8], DesiredPeers> { #[cfg(test)] mod tests { - use std::io::Write; + use std::io::Write as _; use std::net::{Ipv4Addr, Ipv6Addr}; use byteorder::{BigEndian, WriteBytesExt}; diff --git a/packages/utracker/src/client/dispatcher.rs b/packages/utracker/src/client/dispatcher.rs index b425dc454..2d0dd8b9b 100644 --- a/packages/utracker/src/client/dispatcher.rs +++ b/packages/utracker/src/client/dispatcher.rs @@ -1,8 +1,6 @@ use std::collections::hash_map::Entry; use std::collections::HashMap; -use std::io::Cursor; use std::net::SocketAddr; -use std::thread; use chrono::offset::Utc; use chrono::{DateTime, Duration}; @@ -75,7 +73,7 @@ where let dispatch = ClientDispatcher::new(handshaker, bind, limiter); - thread::spawn(move || { + std::thread::spawn(move || { eloop.run(dispatch).expect("bip_utracker: ELoop Shutdown Unexpectedly..."); }); @@ -315,7 +313,7 @@ where // Try to write the request out to the server let mut write_success = false; provider.outgoing(|bytes| { - let mut writer = Cursor::new(bytes); + let mut writer = std::io::Cursor::new(bytes); match tracker_request.write_bytes(&mut writer) { Ok(()) => { write_success = true; diff --git a/packages/utracker/src/client/mod.rs b/packages/utracker/src/client/mod.rs index 27e557c64..fb0449d85 100644 --- a/packages/utracker/src/client/mod.rs +++ b/packages/utracker/src/client/mod.rs @@ -1,4 +1,3 @@ -use std::io; use std::net::SocketAddr; use std::sync::atomic::{AtomicUsize, Ordering}; use std::sync::Arc; diff --git a/packages/utracker/src/contact.rs b/packages/utracker/src/contact.rs index 4fdf4b07f..9ee87b290 100644 --- a/packages/utracker/src/contact.rs +++ b/packages/utracker/src/contact.rs @@ -1,7 +1,7 @@ //! Messaging primitives for contact information. use std::borrow::Cow; -use std::io::Write; +use std::io::Write as _; use std::net::{SocketAddr, SocketAddrV4, SocketAddrV6}; use nom::{IResult, Needed}; @@ -51,7 +51,7 @@ impl<'a> CompactPeers<'a> { /// It would return an IO Error if unable to write the bytes. pub fn write_bytes(&self, writer: W) -> std::io::Result<()> where - W: Write, + W: std::io::Write, { match self { CompactPeers::V4(peers) => peers.write_bytes(writer), @@ -146,7 +146,7 @@ impl<'a> CompactPeersV4<'a> { /// It would return an IO Error if unable to write the bytes. pub fn write_bytes(&self, mut writer: W) -> std::io::Result<()> where - W: Write, + W: std::io::Write, { writer.write_all(&self.peers)?; @@ -268,7 +268,7 @@ impl<'a> CompactPeersV6<'a> { /// It would return an IO Error if unable to write the bytes. pub fn write_bytes(&self, mut writer: W) -> std::io::Result<()> where - W: Write, + W: std::io::Write, { writer.write_all(&self.peers)?; diff --git a/packages/utracker/src/error.rs b/packages/utracker/src/error.rs index 318ab0e55..87fb5c182 100644 --- a/packages/utracker/src/error.rs +++ b/packages/utracker/src/error.rs @@ -1,7 +1,7 @@ //! Messaging primitives for server errors. use std::borrow::Cow; -use std::io::Write; +use std::io::Write as _; use nom::bytes::complete::take; use nom::character::complete::not_line_ending; @@ -49,7 +49,7 @@ impl<'a> ErrorResponse<'a> { /// It would return an IO Error if unable to write the bytes. pub fn write_bytes(&self, mut writer: W) -> std::io::Result<()> where - W: Write, + W: std::io::Write, { writer.write_all(self.message.as_bytes())?; diff --git a/packages/utracker/src/option.rs b/packages/utracker/src/option.rs index 1d388fe3b..bd0a4d01c 100644 --- a/packages/utracker/src/option.rs +++ b/packages/utracker/src/option.rs @@ -3,7 +3,7 @@ use std::borrow::Cow; use std::collections::hash_map::Entry; use std::collections::HashMap; -use std::io::Write; +use std::io::Write as _; use byteorder::WriteBytesExt; use nom::branch::alt; @@ -76,7 +76,7 @@ impl<'a> AnnounceOptions<'a> { #[instrument(skip(self, writer))] pub fn write_bytes(&self, mut writer: W) -> std::io::Result<()> where - W: Write, + W: std::io::Write, { tracing::trace!("writing {} options", self.raw_options.len()); for (byte, content) in &self.raw_options { @@ -233,7 +233,7 @@ impl<'a> AnnounceOption<'a> for URLDataOption<'a> { #[cfg(test)] mod tests { - use std::io::Write; + use std::io::Write as _; use std::sync::Once; use nom::IResult; diff --git a/packages/utracker/src/request.rs b/packages/utracker/src/request.rs index b5be624f5..67180dd73 100644 --- a/packages/utracker/src/request.rs +++ b/packages/utracker/src/request.rs @@ -1,6 +1,6 @@ //! Messaging primitives for requests. -use std::io::Write; +use std::io::Write as _; use byteorder::{BigEndian, WriteBytesExt}; use nom::bytes::complete::take; @@ -78,7 +78,7 @@ impl<'a> TrackerRequest<'a> { /// It would return an IO Error if unable to write the bytes. pub fn write_bytes(&self, mut writer: W) -> std::io::Result<()> where - W: Write, + W: std::io::Write, { writer.write_u64::(self.connection_id())?; diff --git a/packages/utracker/src/response.rs b/packages/utracker/src/response.rs index 11fb95a55..51742a290 100644 --- a/packages/utracker/src/response.rs +++ b/packages/utracker/src/response.rs @@ -1,6 +1,6 @@ //! Messaging primitives for responses. -use std::io::Write; +use std::io::Write as _; use byteorder::{BigEndian, WriteBytesExt}; use nom::combinator::map; @@ -73,7 +73,7 @@ impl<'a> TrackerResponse<'a> { /// It would return an IO Error if unable to write the bytes. pub fn write_bytes(&self, mut writer: W) -> std::io::Result<()> where - W: Write, + W: std::io::Write, { match self.response_type() { &ResponseType::Connect(id) => { diff --git a/packages/utracker/src/scrape.rs b/packages/utracker/src/scrape.rs index 355c9b647..8e0bc64e6 100644 --- a/packages/utracker/src/scrape.rs +++ b/packages/utracker/src/scrape.rs @@ -1,7 +1,7 @@ //! Messaging primitives for scraping. use std::borrow::Cow; -use std::io::Write; +use std::io::Write as _; use std::num::NonZero; use nom::bytes::complete::take; @@ -99,7 +99,7 @@ impl<'a> ScrapeRequest<'a> { /// It would return an IO Error if unable to write the bytes. pub fn write_bytes(&self, mut writer: W) -> std::io::Result<()> where - W: Write, + W: std::io::Write, { writer.write_all(&self.hashes) } @@ -182,7 +182,7 @@ impl<'a> ScrapeResponse<'a> { /// It would return an IO Error if unable to write the bytes. pub fn write_bytes(&self, mut writer: W) -> std::io::Result<()> where - W: Write, + W: std::io::Write, { writer.write_all(&self.stats) } diff --git a/packages/utracker/src/server/dispatcher.rs b/packages/utracker/src/server/dispatcher.rs index c90165046..1d413658e 100644 --- a/packages/utracker/src/server/dispatcher.rs +++ b/packages/utracker/src/server/dispatcher.rs @@ -1,6 +1,4 @@ -use std::io::Cursor; use std::net::SocketAddr; -use std::thread; use nom::IResult; use tracing::instrument; @@ -42,7 +40,7 @@ where let dispatch = ServerDispatcher::new(handler); - thread::spawn(move || { + std::thread::spawn(move || { eloop.run(dispatch).expect("bip_utracker: ELoop Shutdown Unexpectedly..."); }); @@ -191,7 +189,7 @@ where tracing::debug!("write response"); provider.outgoing(|buffer| { - let mut cursor = Cursor::new(buffer); + let mut cursor = std::io::Cursor::new(buffer); match response.write_bytes(&mut cursor) { Ok(()) => Some((cursor.position().try_into().unwrap(), addr)), diff --git a/packages/utracker/src/server/mod.rs b/packages/utracker/src/server/mod.rs index ae837f7ec..5e2126208 100644 --- a/packages/utracker/src/server/mod.rs +++ b/packages/utracker/src/server/mod.rs @@ -1,4 +1,3 @@ -use std::io; use std::net::SocketAddr; use tracing::instrument; diff --git a/packages/utracker/tests/common/mod.rs b/packages/utracker/tests/common/mod.rs index 784f639d9..f410126fa 100644 --- a/packages/utracker/tests/common/mod.rs +++ b/packages/utracker/tests/common/mod.rs @@ -3,7 +3,7 @@ use std::net::{SocketAddr, SocketAddrV4, SocketAddrV6}; use std::sync::{Arc, Mutex, Once}; use std::time::Duration; -use futures::channel::mpsc::{self, UnboundedReceiver, UnboundedSender}; +use futures::channel::mpsc; use futures::sink::SinkExt; use futures::stream::StreamExt; use futures::{Sink, Stream}; @@ -195,7 +195,7 @@ pub fn handshaker() -> (MockHandshakerSink, MockHandshakerStream) { #[derive(Debug, Clone)] pub struct MockHandshakerSink { - send: UnboundedSender, + send: mpsc::UnboundedSender, } impl DiscoveryInfo for MockHandshakerSink { @@ -255,7 +255,7 @@ impl Sink> for MockHandshakerSink { } pub struct MockHandshakerStream { - recv: UnboundedReceiver, + recv: mpsc::UnboundedReceiver, } impl Stream for MockHandshakerStream { diff --git a/packages/utracker/tests/test_announce_start.rs b/packages/utracker/tests/test_announce_start.rs index 72a8a7d93..37ef75f64 100644 --- a/packages/utracker/tests/test_announce_start.rs +++ b/packages/utracker/tests/test_announce_start.rs @@ -1,5 +1,4 @@ use std::net::SocketAddr; -use std::thread::{self}; use std::time::Duration; use common::{handshaker, tracing_stderr_init, MockTrackerHandler, DEFAULT_TIMEOUT, INIT}; @@ -24,7 +23,7 @@ async fn positive_announce_started() { let mock_handler = MockTrackerHandler::new(); let _server = TrackerServer::run(server_addr, mock_handler).unwrap(); - thread::sleep(Duration::from_millis(100)); + std::thread::sleep(Duration::from_millis(100)); let mut client = TrackerClient::new("127.0.0.1:4501".parse().unwrap(), handshaker_sender, None).unwrap(); diff --git a/packages/utracker/tests/test_announce_stop.rs b/packages/utracker/tests/test_announce_stop.rs index 80e4d337e..4fc2fc505 100644 --- a/packages/utracker/tests/test_announce_stop.rs +++ b/packages/utracker/tests/test_announce_stop.rs @@ -1,4 +1,3 @@ -use std::thread::{self}; use std::time::Duration; use common::{handshaker, tracing_stderr_init, MockTrackerHandler, DEFAULT_TIMEOUT, INIT}; @@ -22,7 +21,7 @@ async fn positive_announce_stopped() { let mock_handler = MockTrackerHandler::new(); let _server = TrackerServer::run(server_addr, mock_handler).unwrap(); - thread::sleep(Duration::from_millis(100)); + std::thread::sleep(Duration::from_millis(100)); let mut client = TrackerClient::new("127.0.0.1:4502".parse().unwrap(), sink, None).unwrap(); diff --git a/packages/utracker/tests/test_client_full.rs b/packages/utracker/tests/test_client_full.rs index 94b9dbd59..f2e78d150 100644 --- a/packages/utracker/tests/test_client_full.rs +++ b/packages/utracker/tests/test_client_full.rs @@ -1,5 +1,3 @@ -use std::mem; - use common::{handshaker, tracing_stderr_init, DEFAULT_TIMEOUT, INIT}; use futures::StreamExt as _; use tracing::level_filters::LevelFilter; @@ -49,7 +47,7 @@ async fn positive_client_request_dropped() { ) .is_none()); - mem::drop(client); + std::mem::drop(client); let buffer: Vec<_> = tokio::time::timeout(DEFAULT_TIMEOUT, stream.collect()).await.unwrap(); assert_eq!(request_capacity, buffer.len()); diff --git a/packages/utracker/tests/test_connect.rs b/packages/utracker/tests/test_connect.rs index ac90106a5..2111d5681 100644 --- a/packages/utracker/tests/test_connect.rs +++ b/packages/utracker/tests/test_connect.rs @@ -1,4 +1,3 @@ -use std::thread::{self}; use std::time::Duration; use common::{handshaker, tracing_stderr_init, MockTrackerHandler, DEFAULT_TIMEOUT, INIT}; @@ -22,7 +21,7 @@ async fn positive_receive_connect_id() { let mock_handler = MockTrackerHandler::new(); let _server = TrackerServer::run(server_addr, mock_handler).unwrap(); - thread::sleep(Duration::from_millis(100)); + std::thread::sleep(Duration::from_millis(100)); let mut client = TrackerClient::new("127.0.0.1:4505".parse().unwrap(), sink, None).unwrap(); diff --git a/packages/utracker/tests/test_connect_cache.rs b/packages/utracker/tests/test_connect_cache.rs index 095f82358..25b89f277 100644 --- a/packages/utracker/tests/test_connect_cache.rs +++ b/packages/utracker/tests/test_connect_cache.rs @@ -1,4 +1,3 @@ -use std::thread::{self}; use std::time::Duration; use common::{tracing_stderr_init, MockTrackerHandler, DEFAULT_TIMEOUT, INIT}; @@ -21,7 +20,7 @@ async fn positive_connection_id_cache() { let mock_handler = MockTrackerHandler::new(); let _server = TrackerServer::run(server_addr, mock_handler.clone()).unwrap(); - thread::sleep(Duration::from_millis(100)); + std::thread::sleep(Duration::from_millis(100)); let mut client = TrackerClient::new("127.0.0.1:4506".parse().unwrap(), sink, None).unwrap(); diff --git a/packages/utracker/tests/test_scrape.rs b/packages/utracker/tests/test_scrape.rs index e103cc990..607f02e66 100644 --- a/packages/utracker/tests/test_scrape.rs +++ b/packages/utracker/tests/test_scrape.rs @@ -1,4 +1,3 @@ -use std::thread::{self}; use std::time::Duration; use common::{handshaker, tracing_stderr_init, MockTrackerHandler, DEFAULT_TIMEOUT, INIT}; @@ -21,7 +20,7 @@ async fn positive_scrape() { let mock_handler = MockTrackerHandler::new(); let _server = TrackerServer::run(server_addr, mock_handler).unwrap(); - thread::sleep(Duration::from_millis(100)); + std::thread::sleep(Duration::from_millis(100)); let mut client = TrackerClient::new("127.0.0.1:4507".parse().unwrap(), sink, None).unwrap();