@@ -17,6 +17,7 @@ use libp2p::tcp::TokioTcpConfig;
1717use libp2p:: websocket:: WsConfig ;
1818use libp2p:: yamux:: { WindowUpdateMode , YamuxConfig } ;
1919use libp2p:: { core, identity, noise, Multiaddr , PeerId , Transport , TransportError } ;
20+ use log:: info;
2021use std:: sync:: Arc ;
2122use std:: time:: Duration ;
2223use std:: { fmt, io} ;
@@ -36,6 +37,8 @@ pub struct Config {
3637 pub bootstrap_nodes : Vec < Multiaddr > ,
3738 /// List of [`Multiaddr`] on which to listen for incoming connections.
3839 pub listen_on : Vec < Multiaddr > ,
40+ /// Fallback to random port if specified (or default) port is already occupied.
41+ pub listen_on_fallback_to_random_port : bool ,
3942 /// Adds a timeout to the setup and protocol upgrade process for all inbound and outbound
4043 /// connections established through the transport.
4144 pub timeout : Duration ,
@@ -98,6 +101,7 @@ impl Config {
98101 keypair,
99102 bootstrap_nodes : vec ! [ ] ,
100103 listen_on : vec ! [ ] ,
104+ listen_on_fallback_to_random_port : true ,
101105 timeout : Duration :: from_secs ( 10 ) ,
102106 identify,
103107 kademlia,
@@ -129,6 +133,7 @@ pub async fn create(
129133 Config {
130134 keypair,
131135 listen_on,
136+ listen_on_fallback_to_random_port,
132137 timeout,
133138 identify,
134139 kademlia,
@@ -198,8 +203,22 @@ pub async fn create(
198203 } ) )
199204 . build ( ) ;
200205
201- for addr in listen_on {
202- swarm. listen_on ( addr) ?;
206+ for mut addr in listen_on {
207+ if let Err ( error) = swarm. listen_on ( addr. clone ( ) ) {
208+ if !listen_on_fallback_to_random_port {
209+ return Err ( error. into ( ) ) ;
210+ }
211+
212+ let addr_string = addr. to_string ( ) ;
213+ // Listen on random port if specified is already occupied
214+ if let Some ( Protocol :: Tcp ( _port) ) = addr. pop ( ) {
215+ info ! (
216+ "Failed to listen on {addr_string} ({error}), falling back to random port"
217+ ) ;
218+ addr. push ( Protocol :: Tcp ( 0 ) ) ;
219+ swarm. listen_on ( addr) ?;
220+ }
221+ }
203222 }
204223
205224 Ok :: < _ , CreationError > ( swarm)
0 commit comments