diff --git a/mgmtd/src/bee_msg.rs b/mgmtd/src/bee_msg.rs index b8379ef..0d2a542 100644 --- a/mgmtd/src/bee_msg.rs +++ b/mgmtd/src/bee_msg.rs @@ -196,8 +196,8 @@ pub async fn notify_nodes( ) { log::trace!("NOTIFICATION to {node_types:?}: {msg:?}"); - if let Err(err) = async { - for t in node_types { + for t in node_types { + if let Err(err) = async { let nodes = ctx .db .read_tx(move |tx| db::node::get_with_type(tx, *t)) @@ -206,12 +206,12 @@ pub async fn notify_nodes( ctx.conn .broadcast_datagram(nodes.into_iter().map(|e| e.uid), msg) .await?; - } - Ok(()) as Result<_> - } - .await - { - log::error!("Notification could not be sent to all nodes: {err:#}"); + Ok(()) as Result<_> + } + .await + { + log::error!("Notification could not be sent to all {t} nodes: {err:#}"); + } } } diff --git a/mgmtd/src/grpc.rs b/mgmtd/src/grpc.rs index 55ab919..8c69236 100644 --- a/mgmtd/src/grpc.rs +++ b/mgmtd/src/grpc.rs @@ -16,7 +16,7 @@ use sqlite::{TransactionExt, check_affected_rows}; use sqlite_check::sql; use std::fmt::Debug; use std::future::Future; -use std::net::SocketAddr; +use std::net::{SocketAddr, TcpListener}; use std::pin::Pin; use tonic::transport::{Identity, Server, ServerTlsConfig}; use tonic::{Code, Request, Response, Status}; @@ -181,13 +181,12 @@ pub(crate) fn serve(ctx: Context, mut shutdown: RunStateHandle) -> Result<()> { builder }; - let serve_addr = SocketAddr::new("::".parse()?, ctx.info.user_config.grpc_port); - + let ctx2 = ctx.clone(); let service = pm::management_server::ManagementServer::with_interceptor( ManagementService { ctx: ctx.clone() }, move |req: Request<()>| { // If authentication is enabled, require the secret passed with every request - if let Some(required_secret) = ctx.info.auth_secret { + if let Some(required_secret) = ctx2.info.auth_secret { let check = || -> Result<()> { let Some(request_secret) = req.metadata().get("auth-secret") else { bail!("Request requires authentication but no secret was provided") @@ -211,6 +210,20 @@ pub(crate) fn serve(ctx: Context, mut shutdown: RunStateHandle) -> Result<()> { }, ); + let mut serve_addr = SocketAddr::new("::".parse()?, ctx.info.user_config.grpc_port); + + // Test for IPv6 available, fall back to IPv4 sockets if not + match TcpListener::bind(serve_addr) { + Ok(_) => {} + Err(err) if err.raw_os_error() == Some(libc::EAFNOSUPPORT) => { + log::debug!("gRPC: IPv6 not available, falling back to IPv4 sockets"); + serve_addr = SocketAddr::new("0.0.0.0".parse()?, ctx.info.user_config.grpc_port); + } + Err(err) => { + anyhow::bail!(err); + } + } + log::info!("Serving gRPC requests on {serve_addr}"); tokio::spawn(async move { diff --git a/mgmtd/src/lib.rs b/mgmtd/src/lib.rs index 84743a5..d69c3b6 100644 --- a/mgmtd/src/lib.rs +++ b/mgmtd/src/lib.rs @@ -27,7 +27,7 @@ use sqlite::TransactionExt; use sqlite_check::sql; use std::collections::HashSet; use std::future::Future; -use std::net::SocketAddr; +use std::net::{SocketAddr, TcpListener}; use std::sync::Arc; use tokio::net::UdpSocket; use tokio::sync::mpsc; @@ -60,14 +60,22 @@ pub async fn start(info: StaticInfo, license: LicenseVerifier) -> Result {} + Err(err) if err.raw_os_error() == Some(libc::EAFNOSUPPORT) => { + log::debug!("BeeMsg: IPv6 not available, falling back to IPv4 sockets"); + beemsg_serve_addr = SocketAddr::new("0.0.0.0".parse()?, info.user_config.beemsg_port); + } + Err(err) => { + anyhow::bail!(err); + } + } + // UDP socket for in- and outgoing messages - let udp_socket = Arc::new( - UdpSocket::bind(SocketAddr::new( - "::0".parse()?, - info.user_config.beemsg_port, - )) - .await?, - ); + let udp_socket = Arc::new(UdpSocket::bind(beemsg_serve_addr).await?); // Node address store and connection pool let conn_pool = Pool::new( @@ -121,8 +129,9 @@ pub async fn start(info: StaticInfo, license: LicenseVerifier) -> Result( &self, peers: impl IntoIterator, @@ -194,12 +199,29 @@ impl Pool { buf.serialize_msg(msg)?; for node_uid in peers { - let Some(addrs) = self.store.get_node_addrs(node_uid) else { - bail!("No network address found for node with uid {node_uid:?}"); - }; + let addrs = self.store.get_node_addrs(node_uid).unwrap_or_default(); + + if addrs.is_empty() { + log::error!( + "Failed to send datagram to node with uid {node_uid}: No known addresses" + ); + continue; + } + let mut errs = vec![]; for addr in addrs.iter() { - buf.send_to_socket(&self.udp_socket, addr).await?; + if let Err(err) = buf.send_to_socket(&self.udp_socket, addr).await { + log::debug!( + "Sending datagram to node with uid {node_uid} using {addr} failed: {err}" + ); + errs.push((addr, err)); + } + } + + if errs.len() == addrs.len() { + log::error!( + "Failed to send datagram to node with uid {node_uid} on all known addresses: {errs:?}" + ); } }