forked from MystenLabs/sui
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
config: better allocation of available ports
Its not ideal to attempt to allocate ports for a large number of nodes up front. Generally the better thing to do would be to always bind to port 0 and allow from the OS to properly allocate an available port and then communicate the exact port that a network interface is bound to to other entities that would like to speak with it inside of a test environment. Given the above still requires a bit of work and plumbing to be done the next best thing is to be a bit more intelligent about how we're allocating ports when constructing test configs. This patch changes how ports are allocated by requesting a fresh, available port from the OS by binding on port 0, immediately establishing a connection, and then dropping the connection and the listener. This forces the OS to put the port into the TIME_WAIT state ensuring that the OS won't hand out the port for some grace period. Then the port can later be used by by binding on the port using SO_REUSEADDR (which most rust networking libraries do by default).
- Loading branch information
Showing
4 changed files
with
47 additions
and
53 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
// Copyright (c) 2022, Mysten Labs, Inc. | ||
// SPDX-License-Identifier: Apache-2.0 | ||
|
||
use std::net::{TcpListener, TcpStream}; | ||
|
||
/// Return an ephemeral, available port. On unix systems, the port returned will be in the | ||
/// TIME_WAIT state ensuring that the OS won't hand out this port for some grace period. | ||
/// Callers should be able to bind to this port given they use SO_REUSEADDR. | ||
pub fn get_available_port() -> u16 { | ||
const MAX_PORT_RETRIES: u32 = 1000; | ||
|
||
for _ in 0..MAX_PORT_RETRIES { | ||
if let Ok(port) = get_ephemeral_port() { | ||
return port; | ||
} | ||
} | ||
|
||
panic!("Error: could not find an available port"); | ||
} | ||
|
||
fn get_ephemeral_port() -> ::std::io::Result<u16> { | ||
// Request a random available port from the OS | ||
let listener = TcpListener::bind(("localhost", 0))?; | ||
let addr = listener.local_addr()?; | ||
|
||
// Create and accept a connection (which we'll promptly drop) in order to force the port | ||
// into the TIME_WAIT state, ensuring that the port will be reserved from some limited | ||
// amount of time (roughly 60s on some Linux systems) | ||
let _sender = TcpStream::connect(addr)?; | ||
let _incoming = listener.accept()?; | ||
|
||
Ok(addr.port()) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters