Skip to content

Commit 7797155

Browse files
authored
refactor(#219): runtime defaults into settings
2 parents 3effc66 + 4ea2305 commit 7797155

17 files changed

Lines changed: 689 additions & 251 deletions

File tree

crates/libtortillas/src/engine/actor.rs

Lines changed: 16 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ use crate::{
1919
hashes::InfoHash,
2020
peer::PeerId,
2121
protocol::stream::PeerStream,
22+
settings::Settings,
2223
torrent::{PieceStorageStrategy, TorrentActor},
2324
tracker::udp::UdpServer,
2425
};
@@ -51,13 +52,8 @@ pub struct EngineActor {
5152

5253
pub(crate) default_piece_storage_strategy: PieceStorageStrategy,
5354

54-
/// Mailbox size for each torrent instance
55-
pub(crate) mailbox_size: usize,
56-
57-
/// If we autostart torrents
58-
pub(crate) autostart: Option<bool>,
59-
/// How many peers we need to have before we start downloading
60-
pub(crate) sufficient_peers: Option<usize>,
55+
/// Runtime behavior settings shared with torrent, peer, and tracker actors.
56+
pub(crate) settings: Settings,
6157

6258
pub(crate) default_base_path: Option<PathBuf>,
6359
}
@@ -96,21 +92,8 @@ pub struct EngineActorArgs {
9692
/// managed by this engine.
9793
pub piece_storage_strategy: PieceStorageStrategy,
9894

99-
/// Mailbox size for each torrent instance.
100-
///
101-
/// Defaults to 64 if not provided. If set to 0, the mailbox will be
102-
/// unbounded.
103-
pub mailbox_size: Option<usize>,
104-
105-
/// Whether to automatically start torrents when they become ready.
106-
///
107-
/// If not provided, defaults to `None` (use engine-level default).
108-
pub autostart: Option<bool>,
109-
110-
/// Minimum number of peers required before starting download.
111-
///
112-
/// If not provided, defaults to `None` (use engine-level default).
113-
pub sufficient_peers: Option<usize>,
95+
/// Runtime behavior settings.
96+
pub settings: Settings,
11497

11598
/// Default base path for torrent downloads.
11699
///
@@ -144,23 +127,25 @@ impl Actor for EngineActor {
144127
udp_addr,
145128
peer_id,
146129
piece_storage_strategy,
147-
mailbox_size,
148-
autostart,
149-
sufficient_peers,
130+
settings,
150131
default_base_path,
151132
} = args;
152133

153-
let tcp_addr = tcp_addr.unwrap_or_else(|| SocketAddr::from(([0, 0, 0, 0], 0)));
154-
// Should this be port 6881?
155-
let utp_addr = utp_addr.unwrap_or_else(|| SocketAddr::from(([0, 0, 0, 0], 0)));
156-
let udp_addr = udp_addr.unwrap_or_else(|| SocketAddr::from(([0, 0, 0, 0], 0)));
134+
let tcp_addr = tcp_addr.unwrap_or(settings.engine.tcp_addr);
135+
let utp_addr = utp_addr.unwrap_or(settings.engine.utp_addr);
136+
let udp_addr = udp_addr.unwrap_or(settings.engine.udp_addr);
157137
let tcp_socket = TcpListener::bind(tcp_addr)
158138
.await
159139
.map_err(|e| EngineError::NetworkSetupFailed(format!("tcp bind {tcp_addr}: {e}")))?;
160140
let utp_socket = UtpSocketUdp::new_udp(utp_addr)
161141
.await
162142
.map_err(|e| EngineError::NetworkSetupFailed(format!("utp bind {utp_addr}: {e}")))?;
163-
let udp_server = UdpServer::new(Some(udp_addr)).await;
143+
let udp_server = UdpServer::new_with_receive_buffer_size(
144+
Some(udp_addr),
145+
settings.tracker.udp_receive_buffer_size,
146+
)
147+
.await
148+
.map_err(|e| EngineError::NetworkSetupFailed(format!("udp bind {udp_addr}: {e}")))?;
164149

165150
let peer_id = peer_id.unwrap_or_default();
166151

@@ -172,9 +157,7 @@ impl Actor for EngineActor {
172157
peer_id,
173158
actor_ref,
174159
default_piece_storage_strategy: piece_storage_strategy,
175-
mailbox_size: mailbox_size.unwrap_or(64),
176-
autostart,
177-
sufficient_peers,
160+
settings,
178161
default_base_path,
179162
})
180163
}

crates/libtortillas/src/engine/messages.rs

Lines changed: 12 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
use futures::future::try_join_all;
22
use kameo::{actor::Spawn, mailbox, messages, prelude::ActorRef, supervision::RestartPolicy};
3-
use tokio::time::{Duration, timeout};
3+
use tokio::time::timeout;
44
use tracing::{error, warn};
55

66
use super::{EngineActor, EngineExport};
@@ -12,8 +12,6 @@ use crate::{
1212
torrent::{self, TorrentActor, TorrentActorArgs, TorrentState},
1313
};
1414

15-
const INCOMING_PEER_HANDSHAKE_TIMEOUT: Duration = Duration::from_secs(10);
16-
1715
pub(crate) mod commands {
1816
use anyhow::anyhow;
1917

@@ -25,19 +23,15 @@ pub(crate) mod commands {
2523
/// handshaked nor verified at this point.
2624
#[message]
2725
pub(crate) async fn incoming_peer(&mut self, mut stream: PeerStream) {
28-
let handshake = match timeout(
29-
INCOMING_PEER_HANDSHAKE_TIMEOUT,
30-
stream.recv_handshake_message(),
31-
)
32-
.await
33-
{
26+
let handshake_timeout = self.settings.engine.incoming_peer_handshake_timeout;
27+
let handshake = match timeout(handshake_timeout, stream.recv_handshake_message()).await {
3428
Ok(Ok(handshake)) => handshake,
3529
Ok(Err(err)) => {
3630
warn!(error = %err, %stream, "Failed to read incoming peer handshake");
3731
return;
3832
}
3933
Err(_) => {
40-
warn!(%stream, timeout = ?INCOMING_PEER_HANDSHAKE_TIMEOUT, "Timed out reading incoming peer handshake");
34+
warn!(%stream, timeout = ?handshake_timeout, "Timed out reading incoming peer handshake");
4135
return;
4236
}
4337
};
@@ -116,14 +110,18 @@ pub(crate) mod commands {
116110
tracker_server: self.udp_server.clone(),
117111
primary_addr: None,
118112
piece_storage: self.default_piece_storage_strategy.clone(),
119-
autostart: self.autostart,
120-
sufficient_peers: self.sufficient_peers,
113+
autostart: None,
114+
sufficient_peers: None,
121115
base_path: self.default_base_path.clone(),
116+
settings: self.settings.clone(),
122117
},
123118
)
124119
.restart_policy(RestartPolicy::Permanent)
125-
.restart_limit(3, Duration::from_secs(60))
126-
.spawn_with_mailbox(match self.mailbox_size {
120+
.restart_limit(
121+
self.settings.engine.torrent_restart.limit,
122+
self.settings.engine.torrent_restart.period,
123+
)
124+
.spawn_with_mailbox(match self.settings.engine.torrent_mailbox_size {
127125
0 => {
128126
warn!(
129127
?info_hash,

crates/libtortillas/src/engine/mod.rs

Lines changed: 39 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ use crate::{
5151
errors::EngineError,
5252
metainfo::{MetaInfo, TorrentFile},
5353
peer::PeerId,
54+
settings::Settings,
5455
torrent::{PieceStorageStrategy, Torrent, TorrentExport},
5556
};
5657

@@ -104,36 +105,69 @@ impl Engine {
104105
/// Strategy for storing pieces of the torrent.
105106
#[builder(default)]
106107
piece_storage_strategy: PieceStorageStrategy,
108+
/// Runtime behavior settings for engine, torrent, peer, and tracker
109+
/// actors.
110+
settings: Option<Settings>,
107111
/// The mailbox size for each torrent instance.
108112
///
109113
/// In simple terms, this is the number of messages that each torrent
110114
/// instance can have in queue.
111115
///
112116
/// If `Some(0)` is provided, the mailbox will be unbounded (no limit).
113-
/// If `None` is provided, a sensible default is used.
117+
/// If `Some(_)` is provided, it overrides
118+
/// [`Settings::engine.
119+
/// torrent_mailbox_size`](crate::settings::EngineSettings::torrent_mailbox_size).
120+
/// If `None` is provided, the supplied [`Settings`] value is
121+
/// preserved.
114122
///
115123
/// Higher values increase memory usage but reduce sender backpressure
116124
/// when the mailbox is busy, which can improve throughput. Lower values
117125
/// do the inverse.
118126
///
119-
/// Default: `64` when `None` is provided.
127+
/// Default: `64` through [`Settings::default`] when no custom settings
128+
/// are supplied.
120129
mailbox_size: Option<usize>,
121130
/// If we autostart torrents as soon as we have [`Self::sufficient_peers`]
122131
/// peers connected.
123-
/// Default: `true`
132+
///
133+
/// If `Some(_)` is provided, it overrides
134+
/// [`Settings::torrent.
135+
/// autostart`](crate::settings::TorrentSettings::autostart).
136+
/// If `None` is provided, the supplied [`Settings`] value is preserved.
137+
///
138+
/// Default: `true` through [`Settings::default`] when no custom settings
139+
/// are supplied.
124140
autostart: Option<bool>,
125141
/// How many peers we need to have before we start downloading.
126142
///
127143
/// Is ignored if [`Self::autostart`] is `false`.
128144
///
129-
/// Default: `6`
145+
/// If `Some(_)` is provided, it overrides
146+
/// [`Settings::torrent.
147+
/// sufficient_peers`](crate::settings::TorrentSettings::sufficient_peers).
148+
/// If `None` is provided, the supplied [`Settings`] value is
149+
/// preserved.
150+
///
151+
/// Default: `6` through [`Settings::default`] when no custom settings
152+
/// are supplied.
130153
sufficient_peers: Option<usize>,
131154
/// Default base path for torrents
132155
///
133156
/// Default: `std::env::current_dir()`
134157
#[builder(into)]
135158
output_path: Option<PathBuf>,
136159
) -> Self {
160+
let mut settings = settings.unwrap_or_default();
161+
if let Some(mailbox_size) = mailbox_size {
162+
settings.engine.torrent_mailbox_size = mailbox_size;
163+
}
164+
if let Some(autostart) = autostart {
165+
settings.torrent.autostart = autostart;
166+
}
167+
if let Some(sufficient_peers) = sufficient_peers {
168+
settings.torrent.sufficient_peers = sufficient_peers;
169+
}
170+
137171
let output_path = match output_path {
138172
Some(path) => {
139173
if path.is_absolute() {
@@ -153,9 +187,7 @@ impl Engine {
153187
udp_addr,
154188
peer_id: Some(custom_id),
155189
piece_storage_strategy,
156-
mailbox_size,
157-
autostart,
158-
sufficient_peers,
190+
settings,
159191
default_base_path: Some(output_path),
160192
};
161193

crates/libtortillas/src/lib.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ pub mod metainfo;
55
pub mod peer;
66
pub mod pieces;
77
pub mod protocol;
8+
pub mod settings;
89
pub mod torrent;
910
pub mod tracker;
1011

@@ -92,7 +93,7 @@ pub(crate) mod testing {
9293
}
9394

9495
pub(crate) async fn udp_server() -> UdpServer {
95-
UdpServer::new(None).await
96+
UdpServer::new(None).await.unwrap()
9697
}
9798

9899
pub(crate) fn init_tracing() {
@@ -119,6 +120,7 @@ pub mod prelude {
119120
hashes::InfoHash,
120121
metainfo::*,
121122
peer::{Peer, PeerId},
123+
settings::*,
122124
torrent::*,
123125
tracker::Tracker,
124126
};

0 commit comments

Comments
 (0)