Skip to content

Commit

Permalink
Auto-switch port when getting AddrInUse error (#4314)
Browse files Browse the repository at this point in the history
Closes #4241 
Allows for multiple rr.serve() sessions open by trying different ports
if the defaults are already in use. This is achieved by attempting to
bind to port 0, which signals the OS to choose a free port.

Some notes:
Since the hyper::Error type does not provide a method to directly check
if the error is due to a port being already in use, I checked the error
string to implement this.
I'm also ignoring the error thrown by format!("{bind_ip}:0").parse() as
it's not possible to convert it into a hyper::Error.
  • Loading branch information
dangush authored Nov 24, 2023
1 parent dd0e37e commit e003829
Show file tree
Hide file tree
Showing 2 changed files with 22 additions and 3 deletions.
11 changes: 11 additions & 0 deletions crates/re_web_viewer_server/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -207,9 +207,20 @@ impl WebViewerServer {
/// ```
pub fn new(bind_ip: &str, port: WebViewerServerPort) -> Result<Self, WebViewerServerError> {
let bind_addr = format!("{bind_ip}:{port}").parse()?;

let server = hyper::Server::try_bind(&bind_addr)
.or_else(|hyper_err| {
if hyper_err.to_string().contains("Address already in use") {
let fallback_addr = format!("{bind_ip}:0").parse().map_err(|_err| hyper_err)?;

hyper::Server::try_bind(&fallback_addr)
} else {
Err(hyper_err)
}
})
.map_err(|err| WebViewerServerError::BindFailed(port, err))?
.serve(MakeSvc);

Ok(Self { server })
}

Expand Down
14 changes: 11 additions & 3 deletions crates/re_ws_comms/src/server.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,9 +33,17 @@ impl RerunServer {
pub async fn new(bind_ip: String, port: RerunServerPort) -> Result<Self, RerunServerError> {
let bind_addr = format!("{bind_ip}:{port}");

let listener = TcpListener::bind(&bind_addr)
.await
.map_err(|err| RerunServerError::BindFailed(port, err))?;
let listener = match TcpListener::bind(&bind_addr).await {
Ok(listener) => listener,
Err(err) if err.kind() == std::io::ErrorKind::AddrInUse => {
let bind_addr = format!("{bind_ip}:0");

TcpListener::bind(&bind_addr)
.await
.map_err(|err| RerunServerError::BindFailed(RerunServerPort(0), err))?
}
Err(err) => return Err(RerunServerError::BindFailed(port, err)),
};

let slf = Self {
local_addr: listener.local_addr()?,
Expand Down

0 comments on commit e003829

Please sign in to comment.