1#[macro_use]
2pub mod macros;
3pub mod parser;
4pub mod stats;
5pub mod torrent;
6pub mod torrent_meta;
7pub mod tracker;
8pub mod util;
9
10mod buffer;
11mod peer;
12mod peer_connection_manager;
13mod state;
14mod storage;
15
16pub use peer::handle_peer;
17pub use state::torrent::{Torrent, TorrentSharedState};
18pub use storage::{FileStorage, PieceHashVerifier, Storage, StorageManager, TorrentFileMetadata};
19
20use std::future::Future;
21use std::time::Duration;
22
23pub(crate) const DEFAULT_BLOCK_SIZE: u32 = 16_384;
24
25pub trait WithTimeout<T, E> {
26 fn with_timeout(
27 self,
28 name: &'static str,
29 timeout: Duration,
30 ) -> impl std::future::Future<Output = anyhow::Result<T>> + Send
31 where
32 Self: Future<Output = std::result::Result<T, E>>;
33}
34
35impl<F, T, E> WithTimeout<T, E> for F
36where
37 F: Future<Output = std::result::Result<T, E>> + Send,
38 anyhow::Error: From<E>,
39{
40 async fn with_timeout(self, name: &'static str, timeout: Duration) -> anyhow::Result<T> {
41 match tokio::time::timeout(timeout, self).await {
42 Ok(result) => Ok(result?),
43 Err(elapsed) => {
44 anyhow::bail!("'{}' task timed out: {}", name, elapsed);
45 }
46 }
47 }
48}
49
50pub trait Elapsed<T> {
51 fn with_elapsed(
52 self,
53 name: &'static str,
54 threshold: Option<Duration>,
55 ) -> impl std::future::Future<Output = T> + Send
56 where
57 Self: Future<Output = T>;
58}
59
60impl<F, T> Elapsed<T> for F
61where
62 F: Future<Output = T> + Send,
63{
64 async fn with_elapsed(self, name: &'static str, expected: Option<Duration>) -> T
65 where
66 Self: Future<Output = T>,
67 {
68 let start = std::time::Instant::now();
69 let result = self.await;
70
71 let elapsed = start.elapsed();
72 if expected.is_some_and(|expected| elapsed > expected) {
73 tracing::trace!( expected = ?expected.unwrap(), ?elapsed, "'{}' task took more time than expected to execute", name);
75 } else {
76 tracing::trace!("'{}' task took {:?} to execute", name, elapsed);
77 }
78
79 result
80 }
81}