Skip to main content

aria2_core/engine/
bt_download_seeding.rs

1use tracing::info;
2
3use crate::engine::bt_download_command::BtDownloadCommand;
4use crate::engine::bt_peer_connection::BtPeerConn;
5use crate::engine::bt_piece_downloader::FileBackedPieceProvider;
6use crate::engine::bt_seed_manager::{BtSeedManager, SeedExitCondition};
7use crate::engine::bt_upload_session::BtSeedingConfig;
8use crate::error::Result;
9
10impl BtDownloadCommand {
11    pub async fn run_seeding_phase(
12        &mut self,
13        connections: Vec<BtPeerConn>,
14        piece_length: u32,
15        num_pieces: u32,
16    ) -> Result<()> {
17        if connections.is_empty() {
18            info!("No active peers for seeding");
19            return Ok(());
20        }
21
22        let file_provider = std::sync::Arc::new(FileBackedPieceProvider::new(
23            self.output_path.clone(),
24            piece_length,
25            num_pieces,
26            self.multi_file_layout.clone(),
27        ));
28
29        let upload_limit = { self.group.read().await.options().max_upload_limit };
30        let config = BtSeedingConfig {
31            max_upload_bytes_per_sec: upload_limit,
32            max_peers_to_unchoke: 4,
33            optimistic_unchoke_interval_secs: 30,
34        };
35
36        let exit_cond = match (self.seed_time, self.seed_ratio) {
37            (Some(t), Some(r)) => SeedExitCondition {
38                seed_time: Some(t),
39                seed_ratio: Some(r),
40            },
41            (Some(t), None) => SeedExitCondition {
42                seed_time: Some(t),
43                seed_ratio: None,
44            },
45            (None, Some(r)) => SeedExitCondition {
46                seed_time: None,
47                seed_ratio: Some(r),
48            },
49            (None, None) => SeedExitCondition::infinite(),
50        };
51
52        let plain_connections: Vec<aria2_protocol::bittorrent::peer::connection::PeerConnection> =
53            connections
54                .into_iter()
55                .filter_map(|c| match c.inner {
56                    crate::engine::bt_peer_connection::InnerConnection::Plain(p) => Some(p),
57                    _ => None,
58                })
59                .collect();
60
61        let mut manager = BtSeedManager::new_with_choking_algo(
62            plain_connections,
63            file_provider,
64            config,
65            exit_cond,
66            self.completed_bytes,
67            self.choking_algo.take(),
68        );
69        manager.run_seeding_loop().await?;
70
71        self.total_uploaded = manager.total_uploaded();
72        info!(
73            "Seeding complete: uploaded {} bytes in {:?}",
74            self.total_uploaded,
75            manager.seeding_duration()
76        );
77        Ok(())
78    }
79}