1
1
use crate :: RecvData ;
2
+ use std:: io:: ErrorKind ;
2
3
use std:: io:: Result ;
4
+ use std:: task:: Context ;
5
+ use std:: task:: Poll ;
3
6
4
- use crate :: async_imports:: * ;
7
+ use tokio:: io:: Interest ;
8
+ use tokio:: net:: UdpSocket ;
5
9
6
10
#[ cfg( target_os = "linux" ) ]
7
11
mod linux {
@@ -13,64 +17,74 @@ mod linux {
13
17
use linux:: * ;
14
18
15
19
#[ cfg( target_os = "linux" ) ]
16
- pub async fn send_to (
17
- socket : & UdpSocket , send_buf : & [ u8 ] , send_msg_settings : SendMsgCmsgSettings ,
18
- ) -> Result < usize > {
20
+ pub fn poll_send_to (
21
+ socket : & UdpSocket , ctx : & mut Context < ' _ > , send_buf : & [ u8 ] ,
22
+ sendmsg_settings : SendMsgSettings ,
23
+ ) -> Poll < Result < usize > > {
19
24
loop {
20
- // Important to use try_io so that Tokio can clear the socket's readiness
21
- // flag
22
- let res = socket. try_io ( Interest :: WRITABLE , || {
23
- let fd = socket. as_fd ( ) ;
24
- send_msg ( fd, send_buf, send_msg_settings) . map_err ( Into :: into)
25
- } ) ;
26
-
27
- match res {
28
- Err ( e) if e. kind ( ) == ErrorKind :: WouldBlock =>
29
- socket. writable ( ) . await ?,
30
- res => return res,
25
+ match socket. poll_send_ready ( ctx) {
26
+ Poll :: Ready ( Ok ( ( ) ) ) => {
27
+ // Important to use try_io so that Tokio can clear the socket's
28
+ // readiness flag
29
+ match socket. try_io ( Interest :: WRITABLE , || {
30
+ let fd = socket. as_fd ( ) ;
31
+ send_msg ( fd, send_buf, sendmsg_settings) . map_err ( Into :: into)
32
+ } ) {
33
+ Err ( e) if e. kind ( ) == ErrorKind :: WouldBlock => { } ,
34
+ io_res => break Poll :: Ready ( io_res) ,
35
+ }
36
+ } ,
37
+ Poll :: Ready ( Err ( e) ) => break Poll :: Ready ( Err ( e) ) ,
38
+ Poll :: Pending => break Poll :: Pending ,
31
39
}
32
40
}
33
41
}
34
42
35
43
#[ cfg( target_os = "linux" ) ]
36
- pub async fn recv_from (
37
- socket : & UdpSocket , read_buf : & mut [ u8 ] , msg_flags : Option < MsgFlags > ,
38
- store_cmsg_settings : & mut RecvMsgCmsgSettings ,
39
- ) -> Result < RecvData > {
40
- loop {
41
- // Important to use try_io so that Tokio can clear the socket's readiness
42
- // flag
43
- let res = socket. try_io ( Interest :: READABLE , || {
44
- let fd = socket. as_fd ( ) ;
45
- recv_msg (
46
- fd,
47
- read_buf,
48
- msg_flags. unwrap_or ( MsgFlags :: empty ( ) ) ,
49
- store_cmsg_settings,
50
- )
51
- . map_err ( Into :: into)
52
- } ) ;
44
+ pub async fn send_to (
45
+ socket : & UdpSocket , send_buf : & [ u8 ] , sendmsg_settings : SendMsgSettings ,
46
+ ) -> Result < usize > {
47
+ std:: future:: poll_fn ( |mut cx| {
48
+ poll_send_to ( socket, & mut cx, send_buf, sendmsg_settings)
49
+ } )
50
+ . await
51
+ }
53
52
54
- match res {
55
- Err ( e) if e. kind ( ) == ErrorKind :: WouldBlock =>
56
- socket. readable ( ) . await ?,
57
- _ => return res,
53
+ #[ cfg( target_os = "linux" ) ]
54
+ pub fn poll_recv_from (
55
+ socket : & UdpSocket , ctx : & mut Context < ' _ > , recv_buf : & mut [ u8 ] ,
56
+ recvmsg_settings : & mut RecvMsgSettings ,
57
+ ) -> Poll < Result < RecvData > > {
58
+ loop {
59
+ match socket. poll_recv_ready ( ctx) {
60
+ Poll :: Ready ( Ok ( ( ) ) ) => {
61
+ // Important to use try_io so that Tokio can clear the socket's
62
+ // readiness flag
63
+ match socket. try_io ( Interest :: READABLE , || {
64
+ let fd = socket. as_fd ( ) ;
65
+ recv_msg ( fd, recv_buf, recvmsg_settings) . map_err ( Into :: into)
66
+ } ) {
67
+ // The `poll_recv_ready` future registers the ctx with Tokio.
68
+ // We can only return Pending when that
69
+ // future is Pending or we won't wake the
70
+ // runtime properly
71
+ Err ( e) if e. kind ( ) == ErrorKind :: WouldBlock => { } ,
72
+ io_res => break Poll :: Ready ( io_res) ,
73
+ }
74
+ } ,
75
+ Poll :: Ready ( Err ( e) ) => break Poll :: Ready ( Err ( e) ) ,
76
+ Poll :: Pending => break Poll :: Pending ,
58
77
}
59
78
}
60
79
}
61
80
62
- #[ cfg( not( target_os = "linux" ) ) ]
63
- pub async fn send_to (
64
- socket : & UdpSocket , client_addr : SocketAddr ,
65
- ) -> Result < usize > {
66
- socket. send_to ( send_buf, client_addr) . await
67
- }
68
-
69
- #[ cfg( not( target_os = "linux" ) ) ]
81
+ #[ cfg( target_os = "linux" ) ]
70
82
pub async fn recv_from (
71
- socket : & UdpSocket , read_buf : & mut [ u8 ] ,
83
+ socket : & UdpSocket , recv_buf : & mut [ u8 ] ,
84
+ recvmsg_settings : & mut RecvMsgSettings < ' _ > ,
72
85
) -> Result < RecvData > {
73
- let recv = socket. recv ( read_buf) . await ?;
74
-
75
- Ok ( RecvData :: from_bytes ( bytes) )
86
+ std:: future:: poll_fn ( |mut ctx| {
87
+ poll_recv_from ( socket, & mut ctx, recv_buf, recvmsg_settings)
88
+ } )
89
+ . await
76
90
}
0 commit comments