@@ -37,12 +37,13 @@ use libp2p_core::{
3737 Transport ,
3838} ;
3939use libp2p_identity:: PeerId ;
40+ use socket2:: { Domain , Socket , Type } ;
4041use std:: collections:: hash_map:: { DefaultHasher , Entry } ;
4142use std:: collections:: HashMap ;
42- use std:: fmt;
4343use std:: hash:: { Hash , Hasher } ;
4444use std:: net:: { IpAddr , Ipv4Addr , Ipv6Addr , UdpSocket } ;
4545use std:: time:: Duration ;
46+ use std:: { fmt, io} ;
4647use std:: {
4748 net:: SocketAddr ,
4849 pin:: Pin ,
@@ -172,6 +173,21 @@ impl<P: Provider> GenTransport<P> {
172173 }
173174 }
174175 }
176+
177+ fn create_socket ( & self , socket_addr : SocketAddr ) -> io:: Result < UdpSocket > {
178+ let socket = Socket :: new (
179+ Domain :: for_address ( socket_addr) ,
180+ Type :: DGRAM ,
181+ Some ( socket2:: Protocol :: UDP ) ,
182+ ) ?;
183+ if socket_addr. is_ipv6 ( ) {
184+ socket. set_only_v6 ( true ) ?;
185+ }
186+
187+ socket. bind ( & socket_addr. into ( ) ) ?;
188+
189+ Ok ( socket. into ( ) )
190+ }
175191}
176192
177193impl < P : Provider > Transport for GenTransport < P > {
@@ -188,7 +204,8 @@ impl<P: Provider> Transport for GenTransport<P> {
188204 let ( socket_addr, version, _peer_id) = self . remote_multiaddr_to_socketaddr ( addr, false ) ?;
189205 let endpoint_config = self . quinn_config . endpoint_config . clone ( ) ;
190206 let server_config = self . quinn_config . server_config . clone ( ) ;
191- let socket = UdpSocket :: bind ( socket_addr) . map_err ( Self :: Error :: from) ?;
207+ let socket = self . create_socket ( socket_addr) . map_err ( Self :: Error :: from) ?;
208+
192209 let socket_c = socket. try_clone ( ) . map_err ( Self :: Error :: from) ?;
193210 let endpoint = Self :: new_endpoint ( endpoint_config, Some ( server_config) , socket) ?;
194211 let listener = Listener :: new (
@@ -888,4 +905,25 @@ mod test {
888905 . unwrap ( ) ;
889906 assert ! ( !transport. dialer. contains_key( & SocketFamily :: Ipv4 ) ) ;
890907 }
908+
909+ #[ cfg( feature = "tokio" ) ]
910+ #[ tokio:: test]
911+ async fn test_listens_ipv4_ipv6_separately ( ) {
912+ let keypair = libp2p_identity:: Keypair :: generate_ed25519 ( ) ;
913+ let config = Config :: new ( & keypair) ;
914+ let mut transport = crate :: tokio:: Transport :: new ( config) ;
915+
916+ transport
917+ . listen_on (
918+ ListenerId :: next ( ) ,
919+ "/ip4/0.0.0.0/udp/4001/quic-v1" . parse ( ) . unwrap ( ) ,
920+ )
921+ . unwrap ( ) ;
922+ transport
923+ . listen_on (
924+ ListenerId :: next ( ) ,
925+ "/ip6/::/udp/4001/quic-v1" . parse ( ) . unwrap ( ) ,
926+ )
927+ . unwrap ( ) ;
928+ }
891929}
0 commit comments