11use std:: sync:: Arc ;
22
3+ use aquatic_udp_protocol:: PeerClient ;
34use bittorrent_udp_tracker_core:: services:: banning:: BanService ;
45use tokio:: sync:: RwLock ;
56use torrust_tracker_metrics:: label:: LabelSet ;
@@ -8,45 +9,118 @@ use torrust_tracker_primitives::DurationSinceUnixEpoch;
89
910use crate :: event:: { ConnectionContext , ErrorKind , UdpRequestKind } ;
1011use crate :: statistics:: repository:: Repository ;
11- use crate :: statistics:: UDP_TRACKER_SERVER_ERRORS_TOTAL ;
12+ use crate :: statistics:: { UDP_TRACKER_SERVER_CONNECTION_ID_ERRORS_TOTAL , UDP_TRACKER_SERVER_ERRORS_TOTAL } ;
1213
1314pub async fn handle_event (
14- context : ConnectionContext ,
15- kind : Option < UdpRequestKind > ,
16- error : ErrorKind ,
17- stats_repository : & Repository ,
15+ connection_context : ConnectionContext ,
16+ opt_udp_request_kind : Option < UdpRequestKind > ,
17+ error_kind : ErrorKind ,
18+ repository : & Repository ,
1819 ban_service : & Arc < RwLock < BanService > > ,
1920 now : DurationSinceUnixEpoch ,
2021) {
21- // Increase the number of errors
22- // code-review: should we ban IP due to other errors too?
23- if let ErrorKind :: ConnectionCookie ( _msg) = error {
22+ if let ErrorKind :: ConnectionCookie ( _msg) = error_kind. clone ( ) {
2423 let mut ban_service = ban_service. write ( ) . await ;
25- ban_service. increase_counter ( & context . client_socket_addr ( ) . ip ( ) ) ;
24+ ban_service. increase_counter ( & connection_context . client_socket_addr ( ) . ip ( ) ) ;
2625 }
2726
28- // Global fixed metrics
29- match context. client_socket_addr ( ) . ip ( ) {
27+ update_global_fixed_metrics ( & connection_context, repository) . await ;
28+
29+ update_extendable_metrics ( & connection_context, opt_udp_request_kind, error_kind, repository, now) . await ;
30+ }
31+
32+ async fn update_global_fixed_metrics ( connection_context : & ConnectionContext , repository : & Repository ) {
33+ match connection_context. client_socket_addr ( ) . ip ( ) {
3034 std:: net:: IpAddr :: V4 ( _) => {
31- stats_repository . increase_udp4_errors ( ) . await ;
35+ repository . increase_udp4_errors ( ) . await ;
3236 }
3337 std:: net:: IpAddr :: V6 ( _) => {
34- stats_repository . increase_udp6_errors ( ) . await ;
38+ repository . increase_udp6_errors ( ) . await ;
3539 }
3640 }
41+ }
3742
38- // Extendable metrics
39- let mut label_set = LabelSet :: from ( context) ;
40- if let Some ( kind) = kind {
43+ async fn update_extendable_metrics (
44+ connection_context : & ConnectionContext ,
45+ opt_udp_request_kind : Option < UdpRequestKind > ,
46+ error_kind : ErrorKind ,
47+ repository : & Repository ,
48+ now : DurationSinceUnixEpoch ,
49+ ) {
50+ update_all_errors_counter ( connection_context, opt_udp_request_kind. clone ( ) , repository, now) . await ;
51+ update_connection_id_errors_counter ( opt_udp_request_kind, error_kind, repository, now) . await ;
52+ }
53+
54+ async fn update_all_errors_counter (
55+ connection_context : & ConnectionContext ,
56+ opt_udp_request_kind : Option < UdpRequestKind > ,
57+ repository : & Repository ,
58+ now : DurationSinceUnixEpoch ,
59+ ) {
60+ let mut label_set = LabelSet :: from ( connection_context. clone ( ) ) ;
61+
62+ if let Some ( kind) = opt_udp_request_kind. clone ( ) {
4163 label_set. upsert ( label_name ! ( "request_kind" ) , kind. to_string ( ) . into ( ) ) ;
4264 }
43- match stats_repository
65+
66+ match repository
4467 . increase_counter ( & metric_name ! ( UDP_TRACKER_SERVER_ERRORS_TOTAL ) , & label_set, now)
4568 . await
4669 {
4770 Ok ( ( ) ) => { }
4871 Err ( err) => tracing:: error!( "Failed to increase the counter: {}" , err) ,
49- } ;
72+ }
73+ }
74+
75+ async fn update_connection_id_errors_counter (
76+ opt_udp_request_kind : Option < UdpRequestKind > ,
77+ error_kind : ErrorKind ,
78+ repository : & Repository ,
79+ now : DurationSinceUnixEpoch ,
80+ ) {
81+ if let ErrorKind :: ConnectionCookie ( _) = error_kind {
82+ if let Some ( UdpRequestKind :: Announce { announce_request } ) = opt_udp_request_kind {
83+ let ( client_software_name, client_software_version) = extract_name_and_version ( & announce_request. peer_id . client ( ) ) ;
84+
85+ let label_set = LabelSet :: from ( [
86+ ( label_name ! ( "client_software_name" ) , client_software_name. into ( ) ) ,
87+ ( label_name ! ( "client_software_version" ) , client_software_version. into ( ) ) ,
88+ ] ) ;
89+
90+ match repository
91+ . increase_counter ( & metric_name ! ( UDP_TRACKER_SERVER_CONNECTION_ID_ERRORS_TOTAL ) , & label_set, now)
92+ . await
93+ {
94+ Ok ( ( ) ) => { }
95+ Err ( err) => tracing:: error!( "Failed to increase the counter: {}" , err) ,
96+ } ;
97+ }
98+ }
99+ }
100+
101+ fn extract_name_and_version ( peer_client : & PeerClient ) -> ( String , String ) {
102+ match peer_client {
103+ PeerClient :: BitTorrent ( compact_string) => ( "BitTorrent" . to_string ( ) , compact_string. as_str ( ) . to_owned ( ) ) ,
104+ PeerClient :: Deluge ( compact_string) => ( "Deluge" . to_string ( ) , compact_string. as_str ( ) . to_owned ( ) ) ,
105+ PeerClient :: LibTorrentRakshasa ( compact_string) => ( "lt (rakshasa)" . to_string ( ) , compact_string. as_str ( ) . to_owned ( ) ) ,
106+ PeerClient :: LibTorrentRasterbar ( compact_string) => ( "lt (rasterbar)" . to_string ( ) , compact_string. as_str ( ) . to_owned ( ) ) ,
107+ PeerClient :: QBitTorrent ( compact_string) => ( "QBitTorrent" . to_string ( ) , compact_string. as_str ( ) . to_owned ( ) ) ,
108+ PeerClient :: Transmission ( compact_string) => ( "Transmission" . to_string ( ) , compact_string. as_str ( ) . to_owned ( ) ) ,
109+ PeerClient :: UTorrent ( compact_string) => ( "µTorrent" . to_string ( ) , compact_string. as_str ( ) . to_owned ( ) ) ,
110+ PeerClient :: UTorrentEmbedded ( compact_string) => ( "µTorrent Emb." . to_string ( ) , compact_string. as_str ( ) . to_owned ( ) ) ,
111+ PeerClient :: UTorrentMac ( compact_string) => ( "µTorrent Mac" . to_string ( ) , compact_string. as_str ( ) . to_owned ( ) ) ,
112+ PeerClient :: UTorrentWeb ( compact_string) => ( "µTorrent Web" . to_string ( ) , compact_string. as_str ( ) . to_owned ( ) ) ,
113+ PeerClient :: Vuze ( compact_string) => ( "Vuze" . to_string ( ) , compact_string. as_str ( ) . to_owned ( ) ) ,
114+ PeerClient :: WebTorrent ( compact_string) => ( "WebTorrent" . to_string ( ) , compact_string. as_str ( ) . to_owned ( ) ) ,
115+ PeerClient :: WebTorrentDesktop ( compact_string) => ( "WebTorrent Desktop" . to_string ( ) , compact_string. as_str ( ) . to_owned ( ) ) ,
116+ PeerClient :: Mainline ( compact_string) => ( "Mainline" . to_string ( ) , compact_string. as_str ( ) . to_owned ( ) ) ,
117+ PeerClient :: OtherWithPrefixAndVersion { prefix, version } => {
118+ ( format ! ( "Other ({})" , prefix. as_str( ) ) , version. as_str ( ) . to_owned ( ) )
119+ }
120+ PeerClient :: OtherWithPrefix ( compact_string) => ( format ! ( "Other ({compact_string})" ) , String :: new ( ) ) ,
121+ PeerClient :: Other => ( "Other" . to_string ( ) , String :: new ( ) ) ,
122+ _ => ( "Unknown" . to_string ( ) , String :: new ( ) ) ,
123+ }
50124}
51125
52126#[ cfg( test) ]
0 commit comments