diff --git a/mm2src/mm2_bin_lib/src/lib.rs b/mm2src/mm2_bin_lib/src/lib.rs index cbf46087a4..713121b373 100644 --- a/mm2src/mm2_bin_lib/src/lib.rs +++ b/mm2src/mm2_bin_lib/src/lib.rs @@ -41,7 +41,14 @@ fn mm2_status() -> MainStatus { Err(_) => return MainStatus::NoRpc, }; - if *ctx.rpc_started.get().unwrap_or(&false) { + #[cfg(not(target_arch = "wasm32"))] + match ctx.rpc_port.get() { + Some(_) => MainStatus::RpcIsUp, + None => MainStatus::NoRpc, + } + + #[cfg(target_arch = "wasm32")] + if ctx.wasm_rpc.get().is_some() { MainStatus::RpcIsUp } else { MainStatus::NoRpc diff --git a/mm2src/mm2_core/src/mm_ctx.rs b/mm2src/mm2_core/src/mm_ctx.rs index 32afffb12f..53cb30963b 100644 --- a/mm2src/mm2_core/src/mm_ctx.rs +++ b/mm2src/mm2_core/src/mm_ctx.rs @@ -76,8 +76,9 @@ pub struct MmCtx { /// If there are things that are loaded in background then they should be separately optional, /// without invalidating the entire state. pub initialized: OnceLock, - /// True if the RPC HTTP server was started. - pub rpc_started: OnceLock, + /// RPC port of the HTTP server if it was started. + #[cfg(not(target_arch = "wasm32"))] + pub rpc_port: OnceLock, /// Data transfer bridge between server and client where server (which is the mm2 runtime) initiates the request. pub(crate) data_asker: DataAsker, /// A manager for the event streaming system. To be used to start/stop/communicate with event streamers. @@ -153,7 +154,8 @@ impl MmCtx { log: log::LogArc::new(log), metrics: MetricsArc::new(), initialized: OnceLock::default(), - rpc_started: OnceLock::default(), + #[cfg(not(target_arch = "wasm32"))] + rpc_port: OnceLock::default(), data_asker: DataAsker::default(), event_stream_manager: Default::default(), stop: OnceLock::default(), @@ -229,8 +231,9 @@ impl MmCtx { }, None => 7783, // Default port if `rpcport` does not exist in the config }; - if port < 1000 { - return ERR!("rpcport < 1000"); + // A 0 value indicates that the rpc interface should bind on any available port. + if port != 0 && port < 1024 { + return ERR!("rpcport < 1024"); } if port > u16::MAX as u64 { return ERR!("rpcport > u16"); diff --git a/mm2src/mm2_main/src/rpc.rs b/mm2src/mm2_main/src/rpc.rs index 90233e34a4..d3df2042db 100644 --- a/mm2src/mm2_main/src/rpc.rs +++ b/mm2src/mm2_main/src/rpc.rs @@ -412,7 +412,7 @@ pub extern "C" fn spawn_rpc(ctx_h: u32) { $port, now_sec() ); - let _ = $ctx.rpc_started.set(true); + let _ = $ctx.rpc_port.set($port); server }); } @@ -450,6 +450,7 @@ pub extern "C" fn spawn_rpc(ctx_h: u32) { // Create a TcpListener let incoming = AddrIncoming::bind(&rpc_ip_port).unwrap_or_else(|err| panic!("Can't bind on {}: {}", rpc_ip_port, err)); + let bound_to_addr = incoming.local_addr(); let acceptor = TlsAcceptor::builder() .with_single_cert(cert_chain, privkey) .unwrap_or_else(|err| panic!("Can't set certificate for TlsAcceptor: {}", err)) @@ -461,15 +462,16 @@ pub extern "C" fn spawn_rpc(ctx_h: u32) { .serve(make_svc!(TlsStream)) .with_graceful_shutdown(get_shutdown_future!(ctx)); - spawn_server!(server, ctx, rpc_ip_port.ip(), rpc_ip_port.port()); + spawn_server!(server, ctx, bound_to_addr.ip(), bound_to_addr.port()); } else { let server = Server::try_bind(&rpc_ip_port) - .unwrap_or_else(|err| panic!("Can't bind on {}: {}", rpc_ip_port, err)) + .unwrap_or_else(|err| panic!("Failed to bind rpc server on {}: {}", rpc_ip_port, err)) .http1_half_close(false) - .serve(make_svc!(AddrStream)) - .with_graceful_shutdown(get_shutdown_future!(ctx)); + .serve(make_svc!(AddrStream)); + let bound_to_addr = server.local_addr(); + let graceful_shutdown_server = server.with_graceful_shutdown(get_shutdown_future!(ctx)); - spawn_server!(server, ctx, rpc_ip_port.ip(), rpc_ip_port.port()); + spawn_server!(graceful_shutdown_server, ctx, bound_to_addr.ip(), bound_to_addr.port()); } } @@ -518,10 +520,6 @@ pub fn spawn_rpc(ctx_h: u32) { error!("'MmCtx::wasm_rpc' is initialized already"); return; }; - if ctx.rpc_started.set(true).is_err() { - error!("'MmCtx::rpc_started' is set already"); - return; - } log_tag!( ctx,