@@ -10,14 +10,15 @@ use std::{
10
10
11
11
use log:: { error, warn} ;
12
12
use pin_project:: pin_project;
13
+ use socket2:: { Domain , Protocol , Socket , Type } ;
13
14
use tokio:: {
14
15
io:: { AsyncRead , AsyncWrite , ReadBuf } ,
15
16
net:: { TcpSocket , TcpStream as TokioTcpStream , UdpSocket } ,
16
17
} ;
17
18
use tokio_tfo:: TfoStream ;
18
19
19
20
use crate :: net:: {
20
- sys:: { set_common_sockopt_after_connect, set_common_sockopt_for_connect} ,
21
+ sys:: { set_common_sockopt_after_connect, set_common_sockopt_for_connect, socket_bind_dual_stack } ,
21
22
AddrFamily ,
22
23
ConnectOpts ,
23
24
} ;
@@ -250,7 +251,17 @@ pub async fn create_outbound_udp_socket(af: AddrFamily, config: &ConnectOpts) ->
250
251
( AddrFamily :: Ipv6 , ..) => SocketAddr :: new ( Ipv6Addr :: UNSPECIFIED . into ( ) , 0 ) ,
251
252
} ;
252
253
253
- let socket = UdpSocket :: bind ( bind_addr) . await ?;
254
+ let socket = if af != AddrFamily :: Ipv6 {
255
+ UdpSocket :: bind ( bind_addr) . await ?
256
+ } else {
257
+ let socket = Socket :: new ( Domain :: for_address ( bind_addr) , Type :: DGRAM , Some ( Protocol :: UDP ) ) ?;
258
+ socket_bind_dual_stack ( & socket, & bind_addr, false ) ?;
259
+
260
+ // UdpSocket::from_std requires socket to be non-blocked
261
+ socket. set_nonblocking ( true ) ?;
262
+ UdpSocket :: from_std ( socket. into ( ) ) ?
263
+ } ;
264
+
254
265
if let Err ( err) = set_disable_ip_fragmentation ( af, & socket) {
255
266
warn ! ( "failed to disable IP fragmentation, error: {}" , err) ;
256
267
}
0 commit comments