@@ -4,9 +4,12 @@ use std::{
4
4
mem:: { self , MaybeUninit } ,
5
5
net:: { IpAddr , Ipv4Addr , Ipv6Addr , SocketAddr , SocketAddrV4 , SocketAddrV6 } ,
6
6
os:: { fd:: AsFd , unix:: io:: AsRawFd } ,
7
- sync:: atomic:: AtomicUsize ,
7
+ sync:: {
8
+ atomic:: { AtomicU64 , AtomicUsize , Ordering } ,
9
+ Arc ,
10
+ } ,
8
11
task:: { Context , Poll } ,
9
- time:: Instant ,
12
+ time:: SystemTime ,
10
13
} ;
11
14
12
15
use crate :: cmsg:: { AsPtr , EcnCodepoint , Source , Transmit } ;
@@ -31,7 +34,7 @@ type IpTosTy = libc::c_int;
31
34
#[ derive( Debug ) ]
32
35
pub struct UdpSocket {
33
36
io : tokio:: net:: UdpSocket ,
34
- last_send_error : Instant ,
37
+ last_send_error : LastSendError ,
35
38
}
36
39
37
40
impl AsRawFd for UdpSocket {
@@ -46,16 +49,51 @@ impl AsFd for UdpSocket {
46
49
}
47
50
}
48
51
52
+ #[ derive( Clone , Debug ) ]
53
+ pub ( crate ) struct LastSendError ( Arc < AtomicU64 > ) ;
54
+
55
+ impl Default for LastSendError {
56
+ fn default ( ) -> Self {
57
+ let now = Self :: now ( ) ;
58
+ Self ( Arc :: new ( AtomicU64 :: new (
59
+ now. checked_sub ( 2 * IO_ERROR_LOG_INTERVAL ) . unwrap_or ( now) ,
60
+ ) ) )
61
+ }
62
+ }
63
+
64
+ impl LastSendError {
65
+ fn now ( ) -> u64 {
66
+ SystemTime :: now ( )
67
+ . duration_since ( SystemTime :: UNIX_EPOCH )
68
+ . unwrap ( )
69
+ . as_secs ( )
70
+ }
71
+
72
+ /// Determine whether the last error was more than `IO_ERROR_LOG_INTERVAL`
73
+ /// seconds ago. If so, update the last error time and return true.
74
+ ///
75
+ /// Note: if the system clock regresses more tha `IO_ERROR_LOG_INTERVAL`,
76
+ /// this function may impose an additional delay on log message emission.
77
+ /// Similarly, if it advances, messages may be emitted prematurely.
78
+ pub ( crate ) fn should_log ( & self ) -> bool {
79
+ let now = Self :: now ( ) ;
80
+ self . 0
81
+ . fetch_update ( Ordering :: SeqCst , Ordering :: SeqCst , |cur| {
82
+ ( now. saturating_sub ( cur) > IO_ERROR_LOG_INTERVAL ) . then_some ( now)
83
+ } )
84
+ . is_ok ( )
85
+ }
86
+ }
87
+
49
88
impl UdpSocket {
50
89
/// Creates a new UDP socket from a previously created `std::net::UdpSocket`
51
90
pub fn from_std ( socket : std:: net:: UdpSocket ) -> io:: Result < UdpSocket > {
52
91
socket. set_nonblocking ( true ) ?;
53
92
54
93
init ( SockRef :: from ( & socket) ) ?;
55
- let now = Instant :: now ( ) ;
56
94
Ok ( UdpSocket {
57
95
io : tokio:: net:: UdpSocket :: from_std ( socket) ?,
58
- last_send_error : now . checked_sub ( 2 * IO_ERROR_LOG_INTERVAL ) . unwrap_or ( now ) ,
96
+ last_send_error : LastSendError :: default ( ) ,
59
97
} )
60
98
}
61
99
@@ -67,10 +105,9 @@ impl UdpSocket {
67
105
pub async fn bind < A : ToSocketAddrs > ( addr : A ) -> io:: Result < UdpSocket > {
68
106
let io = tokio:: net:: UdpSocket :: bind ( addr) . await ?;
69
107
init ( SockRef :: from ( & io) ) ?;
70
- let now = Instant :: now ( ) ;
71
108
Ok ( UdpSocket {
72
109
io,
73
- last_send_error : now . checked_sub ( 2 * IO_ERROR_LOG_INTERVAL ) . unwrap_or ( now ) ,
110
+ last_send_error : LastSendError :: default ( ) ,
74
111
} )
75
112
}
76
113
@@ -195,13 +232,13 @@ impl UdpSocket {
195
232
///
196
233
/// [`sendmmsg`]: https://linux.die.net/man/2/sendmmsg
197
234
pub async fn send_mmsg < B : AsPtr < u8 > > (
198
- & mut self ,
235
+ & self ,
199
236
state : & UdpState ,
200
237
transmits : & [ Transmit < B > ] ,
201
238
) -> Result < usize , io:: Error > {
202
239
let n = loop {
203
240
self . io . writable ( ) . await ?;
204
- let last_send_error = & mut self . last_send_error ;
241
+ let last_send_error = self . last_send_error . clone ( ) ;
205
242
let io = & self . io ;
206
243
match io. try_io ( Interest :: WRITABLE , || {
207
244
send ( state, SockRef :: from ( io) , last_send_error, transmits)
@@ -278,11 +315,15 @@ impl UdpSocket {
278
315
transmits : & [ Transmit < B > ] ,
279
316
) -> Poll < io:: Result < usize > > {
280
317
loop {
281
- let last_send_error = & mut self . last_send_error ;
282
318
ready ! ( self . io. poll_send_ready( cx) ) ?;
283
319
let io = & self . io ;
284
320
if let Ok ( res) = io. try_io ( Interest :: WRITABLE , || {
285
- send ( state, SockRef :: from ( io) , last_send_error, transmits)
321
+ send (
322
+ state,
323
+ SockRef :: from ( io) ,
324
+ self . last_send_error . clone ( ) ,
325
+ transmits,
326
+ )
286
327
} ) {
287
328
return Poll :: Ready ( Ok ( res) ) ;
288
329
}
@@ -353,7 +394,7 @@ pub mod sync {
353
394
#[ derive( Debug ) ]
354
395
pub struct UdpSocket {
355
396
io : std:: net:: UdpSocket ,
356
- last_send_error : Instant ,
397
+ last_send_error : LastSendError ,
357
398
}
358
399
359
400
impl AsRawFd for UdpSocket {
@@ -372,21 +413,19 @@ pub mod sync {
372
413
pub fn from_std ( socket : std:: net:: UdpSocket ) -> io:: Result < Self > {
373
414
init ( SockRef :: from ( & socket) ) ?;
374
415
socket. set_nonblocking ( false ) ?;
375
- let now = Instant :: now ( ) ;
376
416
Ok ( Self {
377
417
io : socket,
378
- last_send_error : now . checked_sub ( 2 * IO_ERROR_LOG_INTERVAL ) . unwrap_or ( now ) ,
418
+ last_send_error : LastSendError :: default ( ) ,
379
419
} )
380
420
}
381
421
/// create a new UDP socket and attempt to bind to `addr`
382
422
pub fn bind < A : std:: net:: ToSocketAddrs > ( addr : A ) -> io:: Result < Self > {
383
423
let io = std:: net:: UdpSocket :: bind ( addr) ?;
384
424
init ( SockRef :: from ( & io) ) ?;
385
425
io. set_nonblocking ( false ) ?;
386
- let now = Instant :: now ( ) ;
387
426
Ok ( Self {
388
427
io,
389
- last_send_error : now . checked_sub ( 2 * IO_ERROR_LOG_INTERVAL ) . unwrap_or ( now ) ,
428
+ last_send_error : LastSendError :: default ( ) ,
390
429
} )
391
430
}
392
431
/// sets nonblocking mode
@@ -474,7 +513,7 @@ pub mod sync {
474
513
send (
475
514
state,
476
515
SockRef :: from ( & self . io ) ,
477
- & mut self . last_send_error ,
516
+ self . last_send_error . clone ( ) ,
478
517
transmits,
479
518
)
480
519
}
@@ -681,7 +720,7 @@ fn send_msg<B: AsPtr<u8>>(
681
720
fn send < B : AsPtr < u8 > > (
682
721
state : & UdpState ,
683
722
io : SockRef < ' _ > ,
684
- last_send_error : & mut Instant ,
723
+ last_send_error : LastSendError ,
685
724
transmits : & [ Transmit < B > ] ,
686
725
) -> io:: Result < usize > {
687
726
use std:: ptr;
@@ -802,7 +841,7 @@ fn send_msg<B: AsPtr<u8>>(
802
841
fn send < B : AsPtr < u8 > > (
803
842
_state : & UdpState ,
804
843
io : SockRef < ' _ > ,
805
- last_send_error : & mut Instant ,
844
+ last_send_error : LastSendError ,
806
845
transmits : & [ Transmit < B > ] ,
807
846
) -> io:: Result < usize > {
808
847
let mut hdr: libc:: msghdr = unsafe { mem:: zeroed ( ) } ;
@@ -828,7 +867,7 @@ fn send<B: AsPtr<u8>>(
828
867
// Those are not fatal errors, since the
829
868
// configuration can be dynamically changed.
830
869
// - Destination unreachable errors have been observed for other
831
- log_sendmsg_error ( last_send_error, e, & transmits[ sent] ) ;
870
+ log_sendmsg_error ( last_send_error. clone ( ) , e, & transmits[ sent] ) ;
832
871
sent += 1 ;
833
872
}
834
873
}
0 commit comments