@@ -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,47 @@ 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
+ pub ( crate ) fn should_log ( & self ) -> bool {
75
+ let now = Self :: now ( ) ;
76
+ self . 0
77
+ . fetch_update ( Ordering :: SeqCst , Ordering :: SeqCst , |cur| {
78
+ ( ( now - cur) > IO_ERROR_LOG_INTERVAL ) . then_some ( now)
79
+ } )
80
+ . is_ok ( )
81
+ }
82
+ }
83
+
49
84
impl UdpSocket {
50
85
/// Creates a new UDP socket from a previously created `std::net::UdpSocket`
51
86
pub fn from_std ( socket : std:: net:: UdpSocket ) -> io:: Result < UdpSocket > {
52
87
socket. set_nonblocking ( true ) ?;
53
88
54
89
init ( SockRef :: from ( & socket) ) ?;
55
- let now = Instant :: now ( ) ;
56
90
Ok ( UdpSocket {
57
91
io : tokio:: net:: UdpSocket :: from_std ( socket) ?,
58
- last_send_error : now . checked_sub ( 2 * IO_ERROR_LOG_INTERVAL ) . unwrap_or ( now ) ,
92
+ last_send_error : LastSendError :: default ( ) ,
59
93
} )
60
94
}
61
95
@@ -67,10 +101,9 @@ impl UdpSocket {
67
101
pub async fn bind < A : ToSocketAddrs > ( addr : A ) -> io:: Result < UdpSocket > {
68
102
let io = tokio:: net:: UdpSocket :: bind ( addr) . await ?;
69
103
init ( SockRef :: from ( & io) ) ?;
70
- let now = Instant :: now ( ) ;
71
104
Ok ( UdpSocket {
72
105
io,
73
- last_send_error : now . checked_sub ( 2 * IO_ERROR_LOG_INTERVAL ) . unwrap_or ( now ) ,
106
+ last_send_error : LastSendError :: default ( ) ,
74
107
} )
75
108
}
76
109
@@ -195,13 +228,13 @@ impl UdpSocket {
195
228
///
196
229
/// [`sendmmsg`]: https://linux.die.net/man/2/sendmmsg
197
230
pub async fn send_mmsg < B : AsPtr < u8 > > (
198
- & mut self ,
231
+ & self ,
199
232
state : & UdpState ,
200
233
transmits : & [ Transmit < B > ] ,
201
234
) -> Result < usize , io:: Error > {
202
235
let n = loop {
203
236
self . io . writable ( ) . await ?;
204
- let last_send_error = & mut self . last_send_error ;
237
+ let last_send_error = self . last_send_error . clone ( ) ;
205
238
let io = & self . io ;
206
239
match io. try_io ( Interest :: WRITABLE , || {
207
240
send ( state, SockRef :: from ( io) , last_send_error, transmits)
@@ -278,11 +311,15 @@ impl UdpSocket {
278
311
transmits : & [ Transmit < B > ] ,
279
312
) -> Poll < io:: Result < usize > > {
280
313
loop {
281
- let last_send_error = & mut self . last_send_error ;
282
314
ready ! ( self . io. poll_send_ready( cx) ) ?;
283
315
let io = & self . io ;
284
316
if let Ok ( res) = io. try_io ( Interest :: WRITABLE , || {
285
- send ( state, SockRef :: from ( io) , last_send_error, transmits)
317
+ send (
318
+ state,
319
+ SockRef :: from ( io) ,
320
+ self . last_send_error . clone ( ) ,
321
+ transmits,
322
+ )
286
323
} ) {
287
324
return Poll :: Ready ( Ok ( res) ) ;
288
325
}
@@ -353,7 +390,7 @@ pub mod sync {
353
390
#[ derive( Debug ) ]
354
391
pub struct UdpSocket {
355
392
io : std:: net:: UdpSocket ,
356
- last_send_error : Instant ,
393
+ last_send_error : LastSendError ,
357
394
}
358
395
359
396
impl AsRawFd for UdpSocket {
@@ -372,21 +409,19 @@ pub mod sync {
372
409
pub fn from_std ( socket : std:: net:: UdpSocket ) -> io:: Result < Self > {
373
410
init ( SockRef :: from ( & socket) ) ?;
374
411
socket. set_nonblocking ( false ) ?;
375
- let now = Instant :: now ( ) ;
376
412
Ok ( Self {
377
413
io : socket,
378
- last_send_error : now . checked_sub ( 2 * IO_ERROR_LOG_INTERVAL ) . unwrap_or ( now ) ,
414
+ last_send_error : LastSendError :: default ( ) ,
379
415
} )
380
416
}
381
417
/// create a new UDP socket and attempt to bind to `addr`
382
418
pub fn bind < A : std:: net:: ToSocketAddrs > ( addr : A ) -> io:: Result < Self > {
383
419
let io = std:: net:: UdpSocket :: bind ( addr) ?;
384
420
init ( SockRef :: from ( & io) ) ?;
385
421
io. set_nonblocking ( false ) ?;
386
- let now = Instant :: now ( ) ;
387
422
Ok ( Self {
388
423
io,
389
- last_send_error : now . checked_sub ( 2 * IO_ERROR_LOG_INTERVAL ) . unwrap_or ( now ) ,
424
+ last_send_error : LastSendError :: default ( ) ,
390
425
} )
391
426
}
392
427
/// sets nonblocking mode
@@ -474,7 +509,7 @@ pub mod sync {
474
509
send (
475
510
state,
476
511
SockRef :: from ( & self . io ) ,
477
- & mut self . last_send_error ,
512
+ self . last_send_error . clone ( ) ,
478
513
transmits,
479
514
)
480
515
}
@@ -681,7 +716,7 @@ fn send_msg<B: AsPtr<u8>>(
681
716
fn send < B : AsPtr < u8 > > (
682
717
state : & UdpState ,
683
718
io : SockRef < ' _ > ,
684
- last_send_error : & mut Instant ,
719
+ last_send_error : LastSendError ,
685
720
transmits : & [ Transmit < B > ] ,
686
721
) -> io:: Result < usize > {
687
722
use std:: ptr;
@@ -802,7 +837,7 @@ fn send_msg<B: AsPtr<u8>>(
802
837
fn send < B : AsPtr < u8 > > (
803
838
_state : & UdpState ,
804
839
io : SockRef < ' _ > ,
805
- last_send_error : & mut Instant ,
840
+ last_send_error : LastSendError ,
806
841
transmits : & [ Transmit < B > ] ,
807
842
) -> io:: Result < usize > {
808
843
let mut hdr: libc:: msghdr = unsafe { mem:: zeroed ( ) } ;
@@ -828,7 +863,7 @@ fn send<B: AsPtr<u8>>(
828
863
// Those are not fatal errors, since the
829
864
// configuration can be dynamically changed.
830
865
// - Destination unreachable errors have been observed for other
831
- log_sendmsg_error ( last_send_error, e, & transmits[ sent] ) ;
866
+ log_sendmsg_error ( last_send_error. clone ( ) , e, & transmits[ sent] ) ;
832
867
sent += 1 ;
833
868
}
834
869
}
0 commit comments