11use serde_bencode:: de;
22use std:: sync:: { atomic:: AtomicBool , Arc , Mutex } ;
3- use tokio:: { select, sync:: Semaphore } ;
3+ use tokio:: { select, sync:: Semaphore , time :: sleep } ;
44use tracing:: { debug, error} ;
55
66use crate :: {
@@ -11,7 +11,7 @@ use crate::{
1111 } ,
1212 peer_state:: PeerStates ,
1313 protocol_udp:: request_udp_peers,
14- session:: { PieceResult , PieceWork } ,
14+ session:: { DownloadState , PieceResult , PieceWork } ,
1515} ;
1616
1717#[ derive( Debug , Clone ) ]
@@ -23,6 +23,7 @@ pub struct TrackerPeers {
2323 pub piece_rx : flume:: Receiver < FullPiece > ,
2424 pub pr_rx : flume:: Receiver < PieceResult > ,
2525 pub have_broadcast : Arc < tokio:: sync:: broadcast:: Sender < u32 > > ,
26+ pub download_state : Arc < Mutex < DownloadState > > ,
2627}
2728
2829impl TrackerPeers {
@@ -33,6 +34,7 @@ impl TrackerPeers {
3334 peer_states : Arc < PeerStates > ,
3435 have_broadcast : Arc < tokio:: sync:: broadcast:: Sender < u32 > > ,
3536 pr_rx : flume:: Receiver < PieceResult > ,
37+ download_state : Arc < Mutex < DownloadState > > ,
3638 ) -> TrackerPeers {
3739 let ( sender, receiver) = flume:: unbounded ( ) ;
3840 TrackerPeers {
@@ -43,9 +45,31 @@ impl TrackerPeers {
4345 pr_rx,
4446 peer_states,
4547 have_broadcast,
48+ download_state,
4649 }
4750 }
4851
52+ pub fn set_download_state ( & self , state : DownloadState ) {
53+ let mut current_state = self . download_state . lock ( ) . unwrap ( ) ;
54+ * current_state = state;
55+ }
56+
57+ pub fn get_download_state ( & self ) -> DownloadState {
58+ * self . download_state . lock ( ) . unwrap ( )
59+ }
60+
61+ pub fn is_paused ( & self ) -> bool {
62+ self . get_download_state ( ) == DownloadState :: Paused
63+ }
64+
65+ pub fn is_downloading ( & self ) -> bool {
66+ self . get_download_state ( ) == DownloadState :: Downloading
67+ }
68+
69+ pub fn is_init ( & self ) -> bool {
70+ self . get_download_state ( ) == DownloadState :: Init
71+ }
72+
4973 pub async fn connect ( & self , pieces_of_work : Vec < PieceWork > ) {
5074 let info_hash = self . torrent_meta . info_hash ;
5175 let peer_id = self . peer_id ;
@@ -70,6 +94,7 @@ impl TrackerPeers {
7094 let peer_states = self . peer_states . clone ( ) ;
7195 let piece_tx = self . piece_tx . clone ( ) ;
7296 let have_broadcast = self . have_broadcast . clone ( ) ;
97+ let download_state = self . download_state . clone ( ) ;
7398 let torrent_downloaded_state = Arc :: new ( TorrentDownloadedState {
7499 semaphore : Semaphore :: new ( 1 ) ,
75100 pieces : pieces_of_work
@@ -84,13 +109,21 @@ impl TrackerPeers {
84109 } ) ;
85110 tokio:: spawn ( async move {
86111 loop {
112+ // Wait while not downloading
113+ while {
114+ let state = * download_state. lock ( ) . unwrap ( ) ;
115+ state != DownloadState :: Downloading
116+ } {
117+ sleep ( std:: time:: Duration :: from_millis ( 100 ) ) . await ;
118+ }
87119 // Handle TCP trackers
88120 for tracker in tcp_trackers. clone ( ) {
89121 let torrent_meta = torrent_meta. clone ( ) ;
90122 let peer_states = peer_states. clone ( ) ;
91123 let piece_tx = piece_tx. clone ( ) ;
92124 let have_broadcast = have_broadcast. clone ( ) ;
93125 let torrent_downloaded_state = torrent_downloaded_state. clone ( ) ;
126+ let download_state = download_state. clone ( ) ;
94127 tokio:: spawn ( async move {
95128 let url = file:: build_tracker_url ( & torrent_meta, & peer_id, 6881 , & tracker)
96129 . map_err ( |e| {
@@ -105,12 +138,16 @@ impl TrackerPeers {
105138 Ok ( new_peers) => {
106139 process_peers (
107140 new_peers,
108- info_hash,
109- peer_id,
110- peer_states. clone ( ) ,
111- piece_tx. clone ( ) ,
112- have_broadcast. clone ( ) ,
113- torrent_downloaded_state. clone ( ) ,
141+ PeerProcessorConfig {
142+ info_hash,
143+ peer_id,
144+ peer_states : peer_states. clone ( ) ,
145+ piece_tx : piece_tx. clone ( ) ,
146+ have_broadcast : have_broadcast. clone ( ) ,
147+ torrent_downloaded_state : torrent_downloaded_state
148+ . clone ( ) ,
149+ download_state : download_state. clone ( ) ,
150+ } ,
114151 )
115152 . await ;
116153
@@ -141,6 +178,7 @@ impl TrackerPeers {
141178 let piece_tx = piece_tx. clone ( ) ;
142179 let have_broadcast = have_broadcast. clone ( ) ;
143180 let torrent_downloaded_state = torrent_downloaded_state. clone ( ) ;
181+ let download_state = download_state. clone ( ) ;
144182 tokio:: spawn ( async move {
145183 match request_udp_peers ( & tracker, & torrent_meta, & peer_id, 6881 ) . await {
146184 Ok ( udp_response) => {
@@ -156,12 +194,15 @@ impl TrackerPeers {
156194
157195 process_peers (
158196 new_peers,
159- info_hash,
160- peer_id,
161- peer_states. clone ( ) ,
162- piece_tx. clone ( ) ,
163- have_broadcast. clone ( ) ,
164- torrent_downloaded_state. clone ( ) ,
197+ PeerProcessorConfig {
198+ info_hash,
199+ peer_id,
200+ peer_states : peer_states. clone ( ) ,
201+ piece_tx : piece_tx. clone ( ) ,
202+ have_broadcast : have_broadcast. clone ( ) ,
203+ torrent_downloaded_state : torrent_downloaded_state. clone ( ) ,
204+ download_state : download_state. clone ( ) ,
205+ } ,
165206 )
166207 . await ;
167208
@@ -185,24 +226,36 @@ impl TrackerPeers {
185226 }
186227}
187228
188- async fn process_peers (
189- new_peers : Vec < std:: net:: SocketAddr > ,
229+ struct PeerProcessorConfig {
190230 info_hash : [ u8 ; 20 ] ,
191231 peer_id : [ u8 ; 20 ] ,
192232 peer_states : Arc < PeerStates > ,
193233 piece_tx : flume:: Sender < FullPiece > ,
194234 have_broadcast : Arc < tokio:: sync:: broadcast:: Sender < u32 > > ,
195235 torrent_downloaded_state : Arc < TorrentDownloadedState > ,
196- ) {
236+ download_state : Arc < Mutex < DownloadState > > ,
237+ }
238+
239+ async fn process_peers ( new_peers : Vec < std:: net:: SocketAddr > , config : PeerProcessorConfig ) {
240+ let info_hash = config. info_hash ;
241+ let peer_id = config. peer_id ;
242+
197243 for peer in new_peers {
198- if peer_states. clone ( ) . states . contains_key ( & peer) {
244+ // Skip processing new peers if not downloading
245+ let current_state = * config. download_state . lock ( ) . unwrap ( ) ;
246+ if current_state != DownloadState :: Downloading {
247+ continue ;
248+ }
249+
250+ if config. peer_states . clone ( ) . states . contains_key ( & peer) {
199251 continue ;
200252 }
201253
202- let piece_tx = piece_tx. clone ( ) ;
203- let have_broadcast = have_broadcast. clone ( ) ;
204- let torrent_downloaded_state = torrent_downloaded_state. clone ( ) ;
205- let peer_states = peer_states. clone ( ) ;
254+ let piece_tx = config. piece_tx . clone ( ) ;
255+ let have_broadcast = config. have_broadcast . clone ( ) ;
256+ let torrent_downloaded_state = config. torrent_downloaded_state . clone ( ) ;
257+ let peer_states = config. peer_states . clone ( ) ;
258+ let download_state = config. download_state . clone ( ) ;
206259
207260 tokio:: spawn ( async move {
208261 let unchoke_notify = tokio:: sync:: Notify :: new ( ) ;
@@ -215,6 +268,7 @@ async fn process_peers(
215268 peer_writer_tx. clone ( ) ,
216269 peer_states. clone ( ) ,
217270 torrent_downloaded_state. clone ( ) ,
271+ download_state. clone ( ) ,
218272 ) ) ;
219273
220274 let peer_connection =
0 commit comments