@@ -3,7 +3,7 @@ use std::net::{IpAddr, SocketAddr};
33use std:: str:: FromStr ;
44use std:: sync:: Arc ;
55use warp:: { Filter , reject, Rejection } ;
6- use crate :: { InfoHash , MAX_SCRAPE_TORRENTS , TorrentTracker } ;
6+ use crate :: { InfoHash , MAX_SCRAPE_TORRENTS , PeerId , TorrentTracker } ;
77use crate :: key_manager:: AuthKey ;
88use crate :: torrust_http_tracker:: { AnnounceRequest , AnnounceRequestQuery , ScrapeRequest , ServerError , WebResult } ;
99
@@ -44,6 +44,49 @@ async fn info_hashes(raw_query: String) -> WebResult<Vec<InfoHash>> {
4444 }
4545}
4646
47+ /// Check for PeerId
48+ pub fn with_peer_id ( ) -> impl Filter < Extract = ( PeerId , ) , Error = Rejection > + Clone {
49+ warp:: filters:: query:: raw ( )
50+ . and_then ( peer_id)
51+ }
52+
53+ /// Parse PeerId from raw query string
54+ async fn peer_id ( raw_query : String ) -> WebResult < PeerId > {
55+ // put all query params in a vec
56+ let split_raw_query: Vec < & str > = raw_query. split ( "&" ) . collect ( ) ;
57+
58+ let mut peer_id: Option < PeerId > = None ;
59+
60+ for v in split_raw_query {
61+ // look for the peer_id param
62+ if v. contains ( "peer_id" ) {
63+ // get raw percent_encoded peer_id
64+ let raw_peer_id = v. split ( "=" ) . collect :: < Vec < & str > > ( ) [ 1 ] ;
65+
66+ // decode peer_id
67+ let peer_id_bytes = percent_encoding:: percent_decode_str ( raw_peer_id) . collect :: < Vec < u8 > > ( ) ;
68+
69+ // peer_id must be 20 bytes
70+ if peer_id_bytes. len ( ) > 20 {
71+ return Err ( reject:: custom ( ServerError :: InvalidPeerId ) ) ;
72+ }
73+
74+ // clone peer_id_bytes into fixed length array
75+ let mut byte_arr: [ u8 ; 20 ] = Default :: default ( ) ;
76+ byte_arr. clone_from_slice ( peer_id_bytes. as_slice ( ) ) ;
77+
78+ peer_id = Some ( PeerId ( byte_arr) ) ;
79+ break ;
80+ }
81+ }
82+
83+ if peer_id. is_none ( ) {
84+ Err ( reject:: custom ( ServerError :: InvalidPeerId ) )
85+ } else {
86+ Ok ( peer_id. unwrap ( ) )
87+ }
88+ }
89+
4790/// Pass Arc<TorrentTracker> along
4891pub fn with_auth_key ( ) -> impl Filter < Extract = ( Option < AuthKey > , ) , Error = Infallible > + Clone {
4992 warp:: path:: param :: < String > ( )
@@ -59,13 +102,14 @@ pub fn with_auth_key() -> impl Filter<Extract = (Option<AuthKey>,), Error = Infa
59102pub fn with_announce_request ( ) -> impl Filter < Extract = ( AnnounceRequest , ) , Error = Rejection > + Clone {
60103 warp:: filters:: query:: query :: < AnnounceRequestQuery > ( )
61104 . and ( with_info_hash ( ) )
105+ . and ( with_peer_id ( ) )
62106 . and ( warp:: addr:: remote ( ) )
63107 . and ( warp:: header:: optional :: < String > ( "X-Forwarded-For" ) )
64108 . and_then ( announce_request)
65109}
66110
67111/// Parse AnnounceRequest from raw AnnounceRequestQuery, InfoHash and Option<SocketAddr>
68- async fn announce_request ( announce_request_query : AnnounceRequestQuery , info_hashes : Vec < InfoHash > , remote_addr : Option < SocketAddr > , forwarded_for : Option < String > ) -> WebResult < AnnounceRequest > {
112+ async fn announce_request ( announce_request_query : AnnounceRequestQuery , info_hashes : Vec < InfoHash > , peer_id : PeerId , remote_addr : Option < SocketAddr > , forwarded_for : Option < String > ) -> WebResult < AnnounceRequest > {
69113 if remote_addr. is_none ( ) { return Err ( reject:: custom ( ServerError :: AddressNotFound ) ) }
70114
71115 // get first forwarded ip
@@ -76,14 +120,14 @@ async fn announce_request(announce_request_query: AnnounceRequestQuery, info_has
76120 . and_then ( |ip_str| IpAddr :: from_str ( ip_str) . ok ( ) )
77121 }
78122 } ;
79-
123+
80124 Ok ( AnnounceRequest {
81125 info_hash : info_hashes[ 0 ] ,
82126 peer_addr : remote_addr. unwrap ( ) ,
83127 forwarded_ip,
84128 downloaded : announce_request_query. downloaded ,
85129 uploaded : announce_request_query. uploaded ,
86- peer_id : announce_request_query . peer_id ,
130+ peer_id,
87131 port : announce_request_query. port ,
88132 left : announce_request_query. left ,
89133 event : announce_request_query. event ,
0 commit comments