From 20a38943b1a047342018e4a48305fd670ce5efef Mon Sep 17 00:00:00 2001 From: Lukas Herman Date: Fri, 17 Jul 2026 13:15:42 -0400 Subject: [PATCH 1/2] feat: experimental dual stack IPv6 --- Cargo.lock | 1 + Cargo.toml | 14 +- pulsebeam-runtime/src/net/udp.rs | 23 ++- pulsebeam-runtime/src/net/udp_scalar.rs | 20 ++ pulsebeam-runtime/src/system.rs | 181 +++++++++++++++--- .../src/tests/common/client.rs | 13 +- pulsebeam-simulator/src/tests/common/mod.rs | 12 +- pulsebeam/Cargo.toml | 1 + pulsebeam/src/main.rs | 22 ++- pulsebeam/src/node.rs | 181 +++++++++++++----- 10 files changed, 365 insertions(+), 103 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index b655d0d8..205021ad 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2828,6 +2828,7 @@ dependencies = [ "serde_json", "sha3", "slotmap", + "socket2", "str0m", "tachyonix", "thiserror 2.0.18", diff --git a/Cargo.toml b/Cargo.toml index 3fdbf4b0..5ab943ec 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -65,19 +65,13 @@ panic = "abort" inherits = "release" lto = "thin" -[profile.profiling] -inherits = "release" +# We want to crash during simulation +[profile.sim] +inherits = "dev" +opt-level = 2 debug = true split-debuginfo = "unpacked" strip = "none" lto = "off" codegen-units = 256 incremental = true - -# We want to crash during simulation -[profile.sim] -inherits = "dev" -opt-level = 1 - -[profile.profiling.package."*"] -opt-level = 3 diff --git a/pulsebeam-runtime/src/net/udp.rs b/pulsebeam-runtime/src/net/udp.rs index a922245d..72abc0b5 100644 --- a/pulsebeam-runtime/src/net/udp.rs +++ b/pulsebeam-runtime/src/net/udp.rs @@ -5,9 +5,22 @@ use super::{BATCH_SIZE, CHUNK_SIZE, RecvPacketBatch, SendPacketBatch, fmt_bytes} use quinn_udp::RecvMeta; use std::{ io::{self, ErrorKind, IoSliceMut}, - net::SocketAddr, + net::{IpAddr, SocketAddr}, }; +fn normalize_v4_mapped(addr: SocketAddr) -> SocketAddr { + match addr.ip() { + IpAddr::V6(v6) => { + if let Some(v4) = v6.to_ipv4_mapped() { + SocketAddr::new(IpAddr::V4(v4), addr.port()) + } else { + addr + } + } + IpAddr::V4(_) => addr, + } +} + pub const SOCKET_SEND_SIZE: usize = 2 * 1024 * 1024; pub const SOCKET_RECV_SIZE: usize = 4 * 1024 * 1024; @@ -56,6 +69,12 @@ pub async fn bind(addr: SocketAddr, external_addr: Option) -> io::Re socket2::Type::DGRAM, Some(socket2::Protocol::UDP), )?; + + if addr.is_ipv6() { + // Prefer dual-stack listeners so a single IPv6 socket can accept IPv4-mapped peers. + socket2_sock.set_only_v6(false)?; + } + socket2_sock.set_nonblocking(true)?; socket2_sock.set_reuse_address(true)?; @@ -152,7 +171,7 @@ impl UdpTransportReader { let buf = &self.batch_buffer[base..tail]; out.push(RecvPacketBatch { - src: m.addr, + src: normalize_v4_mapped(m.addr), dst: self.local_addr, buf: buf.to_vec(), // Contains the entire GRO block stride: m.stride, // Downstream will use this to skip through buf diff --git a/pulsebeam-runtime/src/net/udp_scalar.rs b/pulsebeam-runtime/src/net/udp_scalar.rs index b8e882f2..acb1accd 100644 --- a/pulsebeam-runtime/src/net/udp_scalar.rs +++ b/pulsebeam-runtime/src/net/udp_scalar.rs @@ -48,7 +48,27 @@ impl UdpTransport { } pub async fn bind(addr: SocketAddr, external_addr: Option) -> io::Result { + #[cfg(not(feature = "sim"))] + let socket = { + let socket2_sock = socket2::Socket::new( + socket2::Domain::for_address(addr), + socket2::Type::DGRAM, + Some(socket2::Protocol::UDP), + )?; + + if addr.is_ipv6() { + // Prefer dual-stack listeners so a single IPv6 socket can accept IPv4-mapped peers. + socket2_sock.set_only_v6(false)?; + } + + socket2_sock.set_nonblocking(true)?; + socket2_sock.bind(&addr.into())?; + UdpSocket::from_std(socket2_sock.into())? + }; + + #[cfg(feature = "sim")] let socket = UdpSocket::bind(addr).await?; + let socket = Arc::new(socket); let local_addr = external_addr.unwrap_or(socket.local_addr()?); diff --git a/pulsebeam-runtime/src/system.rs b/pulsebeam-runtime/src/system.rs index 1d861084..1a1b44d0 100644 --- a/pulsebeam-runtime/src/system.rs +++ b/pulsebeam-runtime/src/system.rs @@ -1,5 +1,4 @@ -use std::net::IpAddr; - +use std::net::{IpAddr, Ipv4Addr, Ipv6Addr}; use systemstat::{IpAddr as SysIpAddr, Platform, System}; /// https://stackoverflow.com/questions/77585473/rust-tokio-how-to-handle-more-signals-than-just-sigint-i-e-sigquit @@ -45,21 +44,66 @@ pub async fn wait_for_signal() { wait_for_signal_impl().await } -pub fn select_host_address() -> IpAddr { +pub fn select_host_addresses() -> Vec { + #[derive(Default, Clone)] + struct InterfaceCandidates { + external_v4: Option, + lan_v4: Option, + external_v6: Option, // Global Unicast (e.g., 2001::) + ula_v6: Option, // Unique Local / LAN (fc00::/7) + link_local_v6: Option, // Link-Local fallback (fe80::/10) + } + + impl InterfaceCandidates { + fn best_v4(&self) -> Option { + self.external_v4.or(self.lan_v4) + } + + fn best_v6(&self) -> Option { + self.external_v6.or(self.ula_v6).or(self.link_local_v6) + } + + // Rank 3 = Public/External, Rank 2 = Private/LAN/ULA, Rank 1 = Link-Local, 0 = Empty + fn v4_rank(&self) -> u8 { + if self.external_v4.is_some() { + 3 + } else if self.lan_v4.is_some() { + 2 + } else { + 0 + } + } + + fn v6_rank(&self) -> u8 { + if self.external_v6.is_some() { + 3 + } else if self.ula_v6.is_some() { + 2 + } else if self.link_local_v6.is_some() { + 1 + } else { + 0 + } + } + } + let system = System::new(); let networks = match system.networks() { Ok(n) => n, Err(e) => { tracing::warn!("could not get network interfaces: {e}"); - return IpAddr::V4(std::net::Ipv4Addr::LOCALHOST); + return vec![ + IpAddr::V4(Ipv4Addr::LOCALHOST), + IpAddr::V6(Ipv6Addr::LOCALHOST), + ]; } }; - let mut external_candidates = vec![]; - let mut lan_candidates = vec![]; + let mut best_iface_name: Option = None; + let mut best_iface: Option = None; for (name, net) in &networks { - // skip virtual / docker / bridge interfaces + // Skip virtual/container management abstractions if name.starts_with("docker") || name.starts_with("veth") || name.starts_with("br-") @@ -69,38 +113,113 @@ pub fn select_host_address() -> IpAddr { continue; } - // optionally restrict to known LAN interface patterns - // if !(name.starts_with("en") || name.starts_with("eth") || name.starts_with("wlp")) { - // tracing::debug!("skipping non-lan interface {}", name); - // continue; - // } + let mut candidates = InterfaceCandidates::default(); for n in &net.addrs { - if let SysIpAddr::V4(ipv4) = n.addr { - if ipv4.is_loopback() { - tracing::debug!("skipping loopback {}: {}", name, ipv4); - continue; + match n.addr { + SysIpAddr::V4(ipv4) => { + if ipv4.is_loopback() + || ipv4.is_unspecified() + || ipv4.is_multicast() + || ipv4.is_link_local() + { + tracing::debug!("skipping loopback/unroutable v4 on {}: {}", name, ipv4); + continue; + } + + if !ipv4.is_private() { + if candidates.external_v4.is_none() { + candidates.external_v4 = Some(ipv4); + } + tracing::info!("found candidate external ipv4 on {}: {}", name, ipv4); + } else { + if candidates.lan_v4.is_none() { + candidates.lan_v4 = Some(ipv4); + } + tracing::info!("found candidate lan ipv4 on {}: {}", name, ipv4); + } } + SysIpAddr::V6(ipv6) => { + if ipv6.is_loopback() || ipv6.is_unspecified() || ipv6.is_multicast() { + tracing::debug!( + "skipping fundamental unroutable ipv6 on {}: {}", + name, + ipv6 + ); + continue; + } - if !ipv4.is_private() { - external_candidates.push(IpAddr::V4(ipv4)); - tracing::info!("found candidate external ip on {}: {}", name, ipv4); - } else { - lan_candidates.push(IpAddr::V4(ipv4)); - tracing::info!("found candidate lan ip on {}: {}", name, ipv4); + if ipv6.is_unicast_link_local() { + if candidates.link_local_v6.is_none() { + candidates.link_local_v6 = Some(ipv6); + } + tracing::info!( + "found candidate link-local fallback ipv6 on {}: {}", + name, + ipv6 + ); + } else if ipv6.is_unique_local() { + if candidates.ula_v6.is_none() { + candidates.ula_v6 = Some(ipv6); + } + tracing::info!("found candidate lan ula ipv6 on {}: {}", name, ipv6); + } else { + if candidates.external_v6.is_none() { + candidates.external_v6 = Some(ipv6); + } + tracing::info!( + "found candidate external global ipv6 on {}: {}", + name, + ipv6 + ); + } + } + SysIpAddr::Empty | SysIpAddr::Unsupported => { + tracing::debug!("skipping unsupported interface address type on {}", name); } } } + + // An interface is valid if it possesses AT LEAST one usable address (v4 or v6) + if candidates.best_v4().is_none() && candidates.best_v6().is_none() { + continue; + } + + // Compare using tuple comparison rules: V4 rank takes priority, V6 rank breaks ties. + let replace_best = match &best_iface { + None => true, + Some(current) => { + (candidates.v4_rank(), candidates.v6_rank()) + > (current.v4_rank(), current.v6_rank()) + } + }; + + if replace_best { + best_iface_name = Some(name.clone()); + best_iface = Some(candidates); + } } - if let Some(ip) = external_candidates.first() { - tracing::info!("selecting external ip: {}", ip); - *ip - } else if let Some(ip) = lan_candidates.first() { - tracing::info!("selecting lan ip: {}", ip); - *ip - } else { - tracing::warn!("falling back to localhost"); - IpAddr::V4(std::net::Ipv4Addr::LOCALHOST) + if let Some(selected) = best_iface { + let mut out = Vec::with_capacity(2); + if let Some(v4) = selected.best_v4() { + out.push(IpAddr::V4(v4)); + } + if let Some(v6) = selected.best_v6() { + out.push(IpAddr::V6(v6)); + } + + tracing::info!( + iface = best_iface_name.unwrap_or_else(|| "".to_string()), + ?out, + "selected interface host addresses dynamically" + ); + return out; } + + tracing::warn!("no active network interfaces detected; returning local fallback anchors"); + vec![ + IpAddr::V4(Ipv4Addr::LOCALHOST), + IpAddr::V6(Ipv6Addr::LOCALHOST), + ] } diff --git a/pulsebeam-simulator/src/tests/common/client.rs b/pulsebeam-simulator/src/tests/common/client.rs index 132b927f..3f029970 100644 --- a/pulsebeam-simulator/src/tests/common/client.rs +++ b/pulsebeam-simulator/src/tests/common/client.rs @@ -20,10 +20,17 @@ pub struct SimClientBuilder { agent_builder: AgentBuilder, } +fn http_base_uri(ip: IpAddr, port: u16) -> String { + match ip { + IpAddr::V4(v4) => format!("http://{}:{}", v4, port), + IpAddr::V6(v6) => format!("http://[{}]:{}", v6, port), + } +} + impl SimClientBuilder { pub async fn bind(ip: IpAddr, server_ip: IpAddr) -> anyhow::Result { let client = create_http_client(); - let server_base_uri = format!("http://{}:7070", server_ip); + let server_base_uri = http_base_uri(server_ip, 7070); let api = HttpApiClient::new(client, &server_base_uri)?; let socket = UdpSocket::bind("0.0.0.0:0").await?; @@ -38,11 +45,11 @@ impl SimClientBuilder { /// port (3478). Use with `start_sfu_node_tcp_only` to test TCP connectivity. pub async fn bind_tcp(ip: IpAddr, server_ip: IpAddr) -> anyhow::Result { let client = create_http_client(); - let server_base_uri = format!("http://{}:7070", server_ip); + let server_base_uri = http_base_uri(server_ip, 7070); let api = HttpApiClient::new(client, &server_base_uri)?; let socket = UdpSocket::bind("0.0.0.0:0").await?; - let server_tcp_addr: std::net::SocketAddr = format!("{}:3478", server_ip).parse()?; + let server_tcp_addr = std::net::SocketAddr::new(server_ip, 3478); Ok(Self { ip, diff --git a/pulsebeam-simulator/src/tests/common/mod.rs b/pulsebeam-simulator/src/tests/common/mod.rs index 5905622d..d3f7f3cf 100644 --- a/pulsebeam-simulator/src/tests/common/mod.rs +++ b/pulsebeam-simulator/src/tests/common/mod.rs @@ -45,14 +45,14 @@ pub fn setup_tracing() { pub async fn start_sfu_node(ip: IpAddr, rng: pulsebeam_runtime::rand::Rng) -> anyhow::Result<()> { let rtc_port = 3478; - let external_addr: SocketAddr = format!("{}:3478", ip).parse()?; + let external_addr = SocketAddr::new(ip, rtc_port); let local_addr: SocketAddr = format!("0.0.0.0:{}", rtc_port).parse()?; let http_api_addr: SocketAddr = "0.0.0.0:7070".parse()?; pulsebeam::node::NodeBuilder::new() .workers(1) .local_addr(local_addr) - .external_addr(external_addr) + .external_addrs(vec![external_addr]) .rng(rng) .with_udp_mode(UdpMode::Scalar) .with_http_api(http_api_addr) @@ -69,14 +69,14 @@ pub async fn start_sfu_node_tcp_only( rng: pulsebeam_runtime::rand::Rng, ) -> anyhow::Result<()> { let rtc_port = 3478; - let external_addr: SocketAddr = format!("{}:3478", ip).parse()?; + let external_addr = SocketAddr::new(ip, rtc_port); let local_addr: SocketAddr = format!("0.0.0.0:{}", rtc_port).parse()?; let http_api_addr: SocketAddr = "0.0.0.0:7070".parse()?; pulsebeam::node::NodeBuilder::new() .workers(1) .local_addr(local_addr) - .external_addr(external_addr) + .external_addrs(vec![external_addr]) .rng(rng) .with_udp_mode(UdpMode::Scalar) .with_http_api(http_api_addr) @@ -98,14 +98,14 @@ pub async fn start_sfu_node_tcp_only_multi_shard( rng: pulsebeam_runtime::rand::Rng, ) -> anyhow::Result<()> { let rtc_port = 3478; - let external_addr: SocketAddr = format!("{}:3478", ip).parse()?; + let external_addr = SocketAddr::new(ip, rtc_port); let local_addr: SocketAddr = format!("0.0.0.0:{}", rtc_port).parse()?; let http_api_addr: SocketAddr = "0.0.0.0:7070".parse()?; pulsebeam::node::NodeBuilder::new() .workers(2) .local_addr(local_addr) - .external_addr(external_addr) + .external_addrs(vec![external_addr]) .rng(rng) .with_udp_mode(UdpMode::Scalar) .with_http_api(http_api_addr) diff --git a/pulsebeam/Cargo.toml b/pulsebeam/Cargo.toml index 908486d5..dceedc7e 100644 --- a/pulsebeam/Cargo.toml +++ b/pulsebeam/Cargo.toml @@ -48,6 +48,7 @@ serde = { workspace = true } serde_json = "1.0.150" sha3 = "0.12.0" slotmap = "1.1.1" +socket2 = "0.6.4" str0m = { workspace = true } tachyonix = "0.3.1" thiserror = { workspace = true } diff --git a/pulsebeam/src/main.rs b/pulsebeam/src/main.rs index 213fbacd..0d66a152 100644 --- a/pulsebeam/src/main.rs +++ b/pulsebeam/src/main.rs @@ -100,18 +100,26 @@ pub async fn run( rtc_port: u16, use_shared_runtime: bool, ) { - let external_ip = pulsebeam_runtime::system::select_host_address(); - let external_addr: SocketAddr = format!("{}:{}", external_ip, rtc_port).parse().unwrap(); - let local_addr: SocketAddr = format!("0.0.0.0:{}", rtc_port).parse().unwrap(); - let http_api_addr: SocketAddr = "0.0.0.0:7070".parse().unwrap(); - let metrics_addr: SocketAddr = "0.0.0.0:6060".parse().unwrap(); + let external_ips = pulsebeam_runtime::system::select_host_addresses(); + let external_addrs: Vec = external_ips + .iter() + .copied() + .map(|ip| SocketAddr::new(ip, rtc_port)) + .collect(); + let local_addr: SocketAddr = format!("[::]:{}", rtc_port).parse().unwrap(); + let http_api_addr: SocketAddr = "[::]:7070".parse().unwrap(); + let metrics_addr: SocketAddr = "[::]:6060".parse().unwrap(); - tracing::info!("Starting node on {external_addr} (RTC), {http_api_addr} (API)"); + tracing::info!( + ?external_addrs, + "Starting node with advertised RTC addresses" + ); + tracing::info!("API listening on {http_api_addr}"); let rng = rand::os_rng(); let mut node_builder = NodeBuilder::new() .workers(workers) .local_addr(local_addr) - .external_addr(external_addr) + .external_addrs(external_addrs) .rng(rng) .with_http_api(http_api_addr) .with_internal_metrics(metrics_addr); diff --git a/pulsebeam/src/node.rs b/pulsebeam/src/node.rs index ff5f3a99..ff2ef73d 100644 --- a/pulsebeam/src/node.rs +++ b/pulsebeam/src/node.rs @@ -3,13 +3,13 @@ use core_affinity::get_core_ids; use pulsebeam_core::net::TcpListener; use pulsebeam_runtime::mailbox; use pulsebeam_runtime::net; -use pulsebeam_runtime::net::Transport; use pulsebeam_runtime::net::UdpMode; use pulsebeam_runtime::net::UnifiedSocket; use pulsebeam_runtime::rand; use pulsebeam_runtime::rand::{RngCore, SeedableRng}; +use std::collections::HashSet; use std::future::Future; -use std::net::{Ipv4Addr, SocketAddr}; +use std::net::{Ipv6Addr, SocketAddr}; use std::sync::Arc; use std::time::Duration; use str0m::Candidate; @@ -40,11 +40,37 @@ enum WorkerExecution { SharedRuntime, } +#[cfg(not(feature = "sim"))] +async fn bind_tcp_listener(addr: SocketAddr) -> std::io::Result { + let socket2_sock = socket2::Socket::new( + socket2::Domain::for_address(addr), + socket2::Type::STREAM, + Some(socket2::Protocol::TCP), + )?; + + if addr.is_ipv6() { + // Prefer dual-stack listeners so a single IPv6 socket can accept IPv4-mapped peers. + socket2_sock.set_only_v6(false)?; + } + + socket2_sock.set_nonblocking(true)?; + socket2_sock.set_reuse_address(true)?; + socket2_sock.bind(&addr.into())?; + socket2_sock.listen(1024)?; + + tokio::net::TcpListener::from_std(socket2_sock.into()) +} + +#[cfg(feature = "sim")] +async fn bind_tcp_listener(addr: SocketAddr) -> std::io::Result { + TcpListener::bind(addr).await +} + pub struct NodeBuilder { // Configuration workers: usize, local_addr: Option, - external_addr: Option, + external_addrs: Vec, // Dependencies (Transport / Logic) rng: Option, @@ -73,7 +99,7 @@ impl NodeBuilder { Self { workers: 1, local_addr: None, - external_addr: None, + external_addrs: Vec::new(), rng: None, udp_mode: UdpMode::Batch, http_api: None, @@ -96,9 +122,9 @@ impl NodeBuilder { self } - /// Set the external address advertised to peers. - pub fn external_addr(mut self, addr: SocketAddr) -> Self { - self.external_addr = Some(addr); + /// Set multiple external addresses (e.g. dual-stack IPv4/IPv6) advertised to peers. + pub fn external_addrs(mut self, addrs: Vec) -> Self { + self.external_addrs = addrs; self } @@ -156,16 +182,61 @@ impl NodeBuilder { /// Consumes the builder and runs the node until `shutdown` is cancelled. pub async fn run(self, shutdown: CancellationToken) -> Result<()> { let workers_count = self.workers; - // Default to binding 0.0.0.0:0 if no address is provided but binding is required + // Default to an IPv6-any listener and disable v6-only mode so one socket can serve + // both IPv6 and IPv4 peers. let local_addr = self .local_addr - .unwrap_or_else(|| SocketAddr::new(Ipv4Addr::UNSPECIFIED.into(), 0)); - let external_addr = self.external_addr; + .unwrap_or_else(|| SocketAddr::new(Ipv6Addr::UNSPECIFIED.into(), 0)); + if self.external_addrs.is_empty() { + return Err(anyhow::anyhow!( + "NodeBuilder requires at least one external IPv4 address; call `.external_addrs(...)`" + )); + } + + let advertised_addrs = self.external_addrs; + + let mut deduped = Vec::with_capacity(advertised_addrs.len()); + let mut seen = HashSet::with_capacity(advertised_addrs.len()); + for addr in advertised_addrs { + if seen.insert(addr) { + deduped.push(addr); + } + } + let mut v4_addrs = Vec::new(); + let mut v6_addrs = Vec::new(); + for addr in deduped { + if addr.is_ipv4() { + v4_addrs.push(addr); + } else { + v6_addrs.push(addr); + } + } + + if v4_addrs.is_empty() { + return Err(anyhow::anyhow!( + "NodeBuilder requires at least one IPv4 external address in `.external_addrs(...)`" + )); + } + if v4_addrs.len() > 1 { + return Err(anyhow::anyhow!( + "NodeBuilder currently supports exactly one external IPv4 address" + )); + } + if v6_addrs.len() > 1 { + return Err(anyhow::anyhow!( + "NodeBuilder currently supports at most one external IPv6 address" + )); + } + + let mut advertised_addrs = Vec::with_capacity(2); + advertised_addrs.extend(v4_addrs); + advertised_addrs.extend(v6_addrs); + let primary_external_addr = advertised_addrs.first().copied(); let mut join_set = JoinSet::new(); if let Some(source) = self.internal_metrics { let listener = match source { - ListenerSource::Bind(addr) => TcpListener::bind(addr) + ListenerSource::Bind(addr) => bind_tcp_listener(addr) .await .context("binding internal metrics")?, ListenerSource::PreBound(l) => l, @@ -188,31 +259,44 @@ impl NodeBuilder { ); } - let udp_sockets = - bind_udp_sockets(local_addr, external_addr, workers_count, self.udp_mode).await?; + let udp_sockets = bind_udp_sockets( + local_addr, + primary_external_addr, + workers_count, + self.udp_mode, + ) + .await?; - let tcp_listener = TcpListener::bind(local_addr) + let tcp_listener = bind_tcp_listener(local_addr) .await .context("binding tcp listener")?; - let tcp_local_addr = external_addr.unwrap_or(tcp_listener.local_addr()?); + let tcp_local_addr = primary_external_addr.unwrap_or(tcp_listener.local_addr()?); let tcp_sockets: Vec = (0..workers_count) .map(|_| net::tcp::TcpTransport::new(tcp_local_addr)) .collect(); - let mut candidates = sockets_to_candidates(&udp_sockets); + let mut candidates = sockets_to_candidates(&udp_sockets, &advertised_addrs); if self.tcp_only { candidates.clear(); } if !tcp_sockets.is_empty() { - candidates.push( - Candidate::builder() - .tcp() - .host(tcp_local_addr) - .tcptype(str0m::net::TcpType::Passive) - .build() - .expect("a TCP passive host candidate"), - ); + let tcp_candidate_addrs = if advertised_addrs.is_empty() { + vec![tcp_local_addr] + } else { + advertised_addrs.clone() + }; + + for addr in tcp_candidate_addrs { + candidates.push( + Candidate::builder() + .tcp() + .host(addr) + .tcptype(str0m::net::TcpType::Passive) + .build() + .expect("a TCP passive host candidate"), + ); + } } let (shard_event_tx, shard_event_rx) = mailbox::new(4096); @@ -318,7 +402,7 @@ impl NodeBuilder { // Resolve listener let listener = match source { ListenerSource::Bind(addr) => { - TcpListener::bind(addr).await.context("binding http api")? + bind_tcp_listener(addr).await.context("binding http api")? } ListenerSource::PreBound(l) => l, }; @@ -331,7 +415,7 @@ impl NodeBuilder { // Best effort to guess host if bound randomly default_host: local_addr .map(|a| a.to_string()) - .unwrap_or_else(|| "0.0.0.0:0".to_string()), + .unwrap_or_else(|| "[::]:0".to_string()), }; let cors = CorsLayer::new() @@ -395,14 +479,14 @@ pub struct NodeContext { async fn bind_udp_sockets( local_addr: SocketAddr, - external_addr: Option, + advertised_addr: Option, workers: usize, mode: UdpMode, ) -> Result> { let mut sockets = Vec::with_capacity(workers); for _ in 0..workers { - let socket = match net::bind(local_addr, net::Transport::Udp(mode), external_addr).await { + let socket = match net::bind(local_addr, net::Transport::Udp(mode), advertised_addr).await { Ok(s) => s, Err(e) if sockets.is_empty() => { return Err(anyhow::Error::new(e).context("failed to bind first udp socket")); @@ -421,22 +505,31 @@ async fn bind_udp_sockets( Ok(sockets) } -fn sockets_to_candidates(sockets: &[UnifiedSocket]) -> Vec { - let mut candidates = Vec::with_capacity(sockets.len()); - for s in sockets { - let candidate = match s.transport() { - Transport::Udp(_) => Candidate::builder() - .udp() - .host(s.local_addr()) - .build() - .expect("a UDP host candidate"), - Transport::Tcp => Candidate::builder() - .tcp() - .host(s.local_addr()) - .tcptype(str0m::net::TcpType::Passive) - .build() - .expect("a TCP passive host candidate"), - }; +fn sockets_to_candidates( + sockets: &[UnifiedSocket], + advertised_addrs: &[SocketAddr], +) -> Vec { + let candidate_addrs = if advertised_addrs.is_empty() { + let mut unique = Vec::with_capacity(sockets.len()); + let mut seen = HashSet::with_capacity(sockets.len()); + for socket in sockets { + let addr = socket.local_addr(); + if seen.insert(addr) { + unique.push(addr); + } + } + unique + } else { + advertised_addrs.to_vec() + }; + + let mut candidates = Vec::with_capacity(candidate_addrs.len()); + for addr in candidate_addrs { + let candidate = Candidate::builder() + .udp() + .host(addr) + .build() + .expect("a UDP host candidate"); candidates.push(candidate); } From a04a18c528d59b39e001c8225c2a03c1abc4af1f Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 17 Jul 2026 17:24:58 +0000 Subject: [PATCH 2/2] Bump the cargo-dependencies group across 1 directory with 19 updates Bumps the cargo-dependencies group with 19 updates in the / directory: | Package | From | To | | --- | --- | --- | | [anyhow](https://github.com/dtolnay/anyhow) | `1.0.102` | `1.0.103` | | [bytes](https://github.com/tokio-rs/bytes) | `1.11.1` | `1.12.1` | | [rand](https://github.com/rust-random/rand) | `0.10.1` | `0.10.2` | | [tokio](https://github.com/tokio-rs/tokio) | `1.52.3` | `1.53.0` | | [triomphe](https://github.com/Manishearth/triomphe) | `0.1.15` | `0.1.16` | | [arrayvec](https://github.com/bluss/arrayvec) | `0.7.6` | `0.7.8` | | [bitvec](https://github.com/bitvecto-rs/bitvec) | `1.0.1` | `1.1.1` | | [clap](https://github.com/clap-rs/clap) | `4.6.1` | `4.6.2` | | [socket2](https://github.com/rust-lang/socket2) | `0.6.4` | `0.6.5` | | [thread-priority](https://github.com/iddm/thread-priority) | `3.0.0` | `3.1.1` | | [tower-http](https://github.com/tower-rs/tower-http) | `0.6.11` | `0.7.0` | | [uuid](https://github.com/uuid-rs/uuid) | `1.23.2` | `1.24.0` | | [http](https://github.com/hyperium/http) | `1.4.1` | `1.4.2` | | [prost](https://github.com/tokio-rs/prost) | `0.14.3` | `0.14.4` | | [prost-types](https://github.com/tokio-rs/prost) | `0.14.3` | `0.14.4` | | [prost-build](https://github.com/tokio-rs/prost) | `0.14.3` | `0.14.4` | | [crossbeam-queue](https://github.com/crossbeam-rs/crossbeam) | `0.3.12` | `0.3.13` | | [crossbeam-utils](https://github.com/crossbeam-rs/crossbeam) | `0.8.21` | `0.8.22` | | [http-body-util](https://github.com/hyperium/http-body) | `0.1.3` | `0.1.4` | Updates `anyhow` from 1.0.102 to 1.0.103 - [Release notes](https://github.com/dtolnay/anyhow/releases) - [Commits](https://github.com/dtolnay/anyhow/compare/1.0.102...1.0.103) Updates `bytes` from 1.11.1 to 1.12.1 - [Release notes](https://github.com/tokio-rs/bytes/releases) - [Changelog](https://github.com/tokio-rs/bytes/blob/master/CHANGELOG.md) - [Commits](https://github.com/tokio-rs/bytes/compare/v1.11.1...v1.12.1) Updates `rand` from 0.10.1 to 0.10.2 - [Release notes](https://github.com/rust-random/rand/releases) - [Changelog](https://github.com/rust-random/rand/blob/master/CHANGELOG.md) - [Commits](https://github.com/rust-random/rand/compare/0.10.1...0.10.2) Updates `tokio` from 1.52.3 to 1.53.0 - [Release notes](https://github.com/tokio-rs/tokio/releases) - [Commits](https://github.com/tokio-rs/tokio/compare/tokio-1.52.3...tokio-1.53.0) Updates `triomphe` from 0.1.15 to 0.1.16 - [Commits](https://github.com/Manishearth/triomphe/compare/v0.1.15...v0.1.16) Updates `arrayvec` from 0.7.6 to 0.7.8 - [Release notes](https://github.com/bluss/arrayvec/releases) - [Changelog](https://github.com/bluss/arrayvec/blob/master/CHANGELOG.md) - [Commits](https://github.com/bluss/arrayvec/compare/0.7.6...0.7.8) Updates `bitvec` from 1.0.1 to 1.1.1 - [Changelog](https://github.com/ferrilab/bitvec/blob/main/CHANGELOG.md) - [Commits](https://github.com/bitvecto-rs/bitvec/commits) Updates `clap` from 4.6.1 to 4.6.2 - [Release notes](https://github.com/clap-rs/clap/releases) - [Changelog](https://github.com/clap-rs/clap/blob/master/CHANGELOG.md) - [Commits](https://github.com/clap-rs/clap/compare/clap_complete-v4.6.1...clap_complete-v4.6.2) Updates `socket2` from 0.6.4 to 0.6.5 - [Release notes](https://github.com/rust-lang/socket2/releases) - [Changelog](https://github.com/rust-lang/socket2/blob/master/CHANGELOG.md) - [Commits](https://github.com/rust-lang/socket2/commits/v0.6.5) Updates `thread-priority` from 3.0.0 to 3.1.1 - [Release notes](https://github.com/iddm/thread-priority/releases) - [Changelog](https://github.com/iddm/thread-priority/blob/master/CHANGELOG.md) - [Commits](https://github.com/iddm/thread-priority/commits) Updates `tower-http` from 0.6.11 to 0.7.0 - [Release notes](https://github.com/tower-rs/tower-http/releases) - [Commits](https://github.com/tower-rs/tower-http/compare/tower-http-0.6.11...tower-http-0.7.0) Updates `uuid` from 1.23.2 to 1.24.0 - [Release notes](https://github.com/uuid-rs/uuid/releases) - [Commits](https://github.com/uuid-rs/uuid/compare/v1.23.2...v1.24.0) Updates `http` from 1.4.1 to 1.4.2 - [Release notes](https://github.com/hyperium/http/releases) - [Changelog](https://github.com/hyperium/http/blob/master/CHANGELOG.md) - [Commits](https://github.com/hyperium/http/compare/v1.4.1...v1.4.2) Updates `prost` from 0.14.3 to 0.14.4 - [Release notes](https://github.com/tokio-rs/prost/releases) - [Changelog](https://github.com/tokio-rs/prost/blob/master/CHANGELOG.md) - [Commits](https://github.com/tokio-rs/prost/compare/v0.14.3...v0.14.4) Updates `prost-types` from 0.14.3 to 0.14.4 - [Release notes](https://github.com/tokio-rs/prost/releases) - [Changelog](https://github.com/tokio-rs/prost/blob/master/CHANGELOG.md) - [Commits](https://github.com/tokio-rs/prost/compare/v0.14.3...v0.14.4) Updates `prost-build` from 0.14.3 to 0.14.4 - [Release notes](https://github.com/tokio-rs/prost/releases) - [Changelog](https://github.com/tokio-rs/prost/blob/master/CHANGELOG.md) - [Commits](https://github.com/tokio-rs/prost/compare/v0.14.3...v0.14.4) Updates `crossbeam-queue` from 0.3.12 to 0.3.13 - [Release notes](https://github.com/crossbeam-rs/crossbeam/releases) - [Changelog](https://github.com/crossbeam-rs/crossbeam/blob/main/CHANGELOG.md) - [Commits](https://github.com/crossbeam-rs/crossbeam/compare/crossbeam-queue-0.3.12...crossbeam-queue-0.3.13) Updates `crossbeam-utils` from 0.8.21 to 0.8.22 - [Release notes](https://github.com/crossbeam-rs/crossbeam/releases) - [Changelog](https://github.com/crossbeam-rs/crossbeam/blob/main/CHANGELOG.md) - [Commits](https://github.com/crossbeam-rs/crossbeam/compare/crossbeam-utils-0.8.21...crossbeam-utils-0.8.22) Updates `http-body-util` from 0.1.3 to 0.1.4 - [Release notes](https://github.com/hyperium/http-body/releases) - [Commits](https://github.com/hyperium/http-body/compare/http-body-util-v0.1.3...http-body-util-v0.1.4) --- updated-dependencies: - dependency-name: anyhow dependency-version: 1.0.103 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: cargo-dependencies - dependency-name: arrayvec dependency-version: 0.7.8 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: cargo-dependencies - dependency-name: bitvec dependency-version: 1.1.1 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: cargo-dependencies - dependency-name: bytes dependency-version: 1.12.1 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: cargo-dependencies - dependency-name: clap dependency-version: 4.6.2 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: cargo-dependencies - dependency-name: crossbeam-queue dependency-version: 0.3.13 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: cargo-dependencies - dependency-name: crossbeam-utils dependency-version: 0.8.22 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: cargo-dependencies - dependency-name: http dependency-version: 1.4.2 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: cargo-dependencies - dependency-name: http-body-util dependency-version: 0.1.4 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: cargo-dependencies - dependency-name: prost dependency-version: 0.14.4 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: cargo-dependencies - dependency-name: prost-build dependency-version: 0.14.4 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: cargo-dependencies - dependency-name: prost-types dependency-version: 0.14.4 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: cargo-dependencies - dependency-name: rand dependency-version: 0.10.2 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: cargo-dependencies - dependency-name: socket2 dependency-version: 0.6.5 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: cargo-dependencies - dependency-name: thread-priority dependency-version: 3.1.1 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: cargo-dependencies - dependency-name: tokio dependency-version: 1.52.4 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: cargo-dependencies - dependency-name: tower-http dependency-version: 0.7.0 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: cargo-dependencies - dependency-name: triomphe dependency-version: 0.1.16 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: cargo-dependencies - dependency-name: uuid dependency-version: 1.24.0 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: cargo-dependencies ... Signed-off-by: dependabot[bot] --- Cargo.lock | 269 ++++++++++++++++--------------------------- pulsebeam/Cargo.toml | 2 +- 2 files changed, 99 insertions(+), 172 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 205021ad..c3cbba8c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -101,9 +101,9 @@ dependencies = [ [[package]] name = "anstyle" -version = "1.0.13" +version = "1.0.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5192cca8006f1fd4f7237516f40fa183bb07f8fbdfedaa0036de5ea9b0b45e78" +checksum = "940b3a0ca603d1eade50a4846a2afffd5ef57a9feac2c0e2ec2e14f9ead76000" [[package]] name = "anstyle-parse" @@ -136,9 +136,9 @@ dependencies = [ [[package]] name = "anyhow" -version = "1.0.102" +version = "1.0.103" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f202df86484c868dbad7eaa557ef785d5c66295e41b460ef922eca0723b842c" +checksum = "2a4385e2e34eb35d6b3efe798b9eb88096925d87726c0798709bf56d9ed84af3" [[package]] name = "arbitrary" @@ -151,9 +151,9 @@ dependencies = [ [[package]] name = "arrayvec" -version = "0.7.6" +version = "0.7.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7c02d123df017efcdfbd739ef81735b36c5ba83ec3c59c80a9d7ecc718f92e50" +checksum = "d3fb67a6e08acf24fdeccbac2cb6ac4305825bd1f117462e0e6f2f193345ad56" dependencies = [ "serde", ] @@ -386,7 +386,7 @@ dependencies = [ "miniz_oxide", "object", "rustc-demangle", - "windows-link 0.2.1", + "windows-link", ] [[package]] @@ -448,9 +448,9 @@ checksum = "c4512299f36f043ab09a583e57bceb5a5aab7a73db1805848e8fef3c9e8c78b3" [[package]] name = "bitvec" -version = "1.0.1" +version = "1.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1bc2832c24239b0141d5674bb9174f9d68a8b5b3f2753311927c172ca46f7e9c" +checksum = "ddcec3d12c579d40898fe0a9a358a803c23e9c52ca3c425707f81c9436211837" dependencies = [ "funty", "radium", @@ -487,9 +487,9 @@ checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" [[package]] name = "bytes" -version = "1.11.1" +version = "1.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e748733b7cbc798e1434b6ac524f0c1ff2ab456fe201501e6497c8417a4fc33" +checksum = "fc652a48c352aef3ea3aed32080501cf3ef6ed5da78602a020c991775b0aff04" [[package]] name = "bytesize" @@ -595,9 +595,9 @@ dependencies = [ [[package]] name = "clap" -version = "4.6.1" +version = "4.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ddb117e43bbf7dacf0a4190fef4d345b9bad68dfc649cb349e7d17d28428e51" +checksum = "dd059f9da4f5c36b3787f65d38ccaab1cc315f07b01f89abc8359ee6a8205011" dependencies = [ "clap_builder", "clap_derive", @@ -605,9 +605,9 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.6.0" +version = "4.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "714a53001bf66416adb0e2ef5ac857140e7dc3a0c48fb28b2f10762fc4b5069f" +checksum = "f09628afdcc538b57f3c6341e9c8e9970f18e4a481690a64974d7023bd33548b" dependencies = [ "anstream", "anstyle", @@ -861,18 +861,18 @@ dependencies = [ [[package]] name = "crossbeam-queue" -version = "0.3.12" +version = "0.3.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0f58bbc28f91df819d0aa2a2c00cd19754769c2fad90579b3592b1c9ba7a3115" +checksum = "803d13fb3b09d88be9f4dbc29062c66b19bf7170867ceb746d2a8689bf6c7a26" dependencies = [ "crossbeam-utils", ] [[package]] name = "crossbeam-utils" -version = "0.8.21" +version = "0.8.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28" +checksum = "61803da095bee82a81bb1a452ecc25d3b2f1416d1897eb86430c6159ef717c17" [[package]] name = "crunchy" @@ -1440,8 +1440,8 @@ dependencies = [ "libc", "log", "rustversion", - "windows-link 0.2.1", - "windows-result 0.4.1", + "windows-link", + "windows-result", ] [[package]] @@ -1625,9 +1625,9 @@ checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" [[package]] name = "http" -version = "1.4.1" +version = "1.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8be7462df143984c4598a256ef469b251d7d7f9e271135073e78fc535414f3d0" +checksum = "6970f50e31d6fc17d3fa27329444bfa74e196cf62e95052a3f6fee181dba6425" dependencies = [ "bytes", "itoa", @@ -1645,9 +1645,9 @@ dependencies = [ [[package]] name = "http-body-util" -version = "0.1.3" +version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b021d93e26becf5dc7e1b75b1bed1fd93124b374ceb73f43d4d4eafec896a64a" +checksum = "e9f41fd6a08e4d4ec69df65976da761afd5ad5e58a9d4acb46bd1c953a9e3ff2" dependencies = [ "bytes", "futures-core", @@ -2462,7 +2462,7 @@ dependencies = [ "libc", "redox_syscall", "smallvec", - "windows-link 0.2.1", + "windows-link", ] [[package]] @@ -2678,12 +2678,12 @@ dependencies = [ [[package]] name = "prost" -version = "0.14.3" +version = "0.14.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d2ea70524a2f82d518bce41317d0fae74151505651af45faf1ffbd6fd33f0568" +checksum = "528ac67416ff8646872a3c02cad9cc4ee5dc9f9540c9b10771855c95cb2e5ae1" dependencies = [ "bytes", - "prost-derive 0.14.3", + "prost-derive 0.14.4", ] [[package]] @@ -2709,9 +2709,9 @@ dependencies = [ [[package]] name = "prost-build" -version = "0.14.3" +version = "0.14.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "343d3bd7056eda839b03204e68deff7d1b13aba7af2b2fd16890697274262ee7" +checksum = "03da047801ff44bb6a4d407d4860c05fd70bb81714e6b2f3812603d5b145b042" dependencies = [ "heck", "itertools 0.14.0", @@ -2719,8 +2719,8 @@ dependencies = [ "multimap", "petgraph 0.8.3", "prettyplease", - "prost 0.14.3", - "prost-types 0.14.3", + "prost 0.14.4", + "prost-types 0.14.4", "regex", "syn", "tempfile", @@ -2741,9 +2741,9 @@ dependencies = [ [[package]] name = "prost-derive" -version = "0.14.3" +version = "0.14.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "27c6023962132f4b30eb4c172c91ce92d933da334c59c23cddee82358ddafb0b" +checksum = "b570b25f7617e43d59005d0990ccb79e950a423952cea19671b7a876da390adf" dependencies = [ "anyhow", "itertools 0.14.0", @@ -2763,11 +2763,11 @@ dependencies = [ [[package]] name = "prost-types" -version = "0.14.3" +version = "0.14.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8991c4cbdb8bc5b11f0b074ffe286c30e523de90fee5ba8132f1399f23cb3dd7" +checksum = "f94967dc7688f3054c7fac87473ffae4cc4c3904800e2d9f5b857246d8963b0a" dependencies = [ - "prost 0.14.3", + "prost 0.14.4", ] [[package]] @@ -2822,7 +2822,7 @@ dependencies = [ "pulsebeam-proto", "pulsebeam-runtime", "pulsebeam-testdata", - "rand 0.10.1", + "rand 0.10.2", "rustix", "serde", "serde_json", @@ -2837,7 +2837,7 @@ dependencies = [ "tokio", "tokio-stream", "tokio-util", - "tower-http", + "tower-http 0.7.0", "tracing", "tracing-appender", "tracing-subscriber", @@ -2880,7 +2880,7 @@ dependencies = [ "pulsebeam-agent", "pulsebeam-core", "pulsebeam-testdata", - "rand 0.10.1", + "rand 0.10.2", "reqwest", "tachyonix", "tikv-jemallocator", @@ -2905,9 +2905,9 @@ dependencies = [ name = "pulsebeam-proto" version = "0.3.2" dependencies = [ - "prost 0.14.3", - "prost-build 0.14.3", - "prost-types 0.14.3", + "prost 0.14.4", + "prost-build 0.14.4", + "prost-types 0.14.4", ] [[package]] @@ -2937,7 +2937,7 @@ dependencies = [ "pulsebeam-core", "quanta", "quinn-udp 0.6.1", - "rand 0.10.1", + "rand 0.10.2", "socket2", "systemstat", "tachyonix", @@ -3118,9 +3118,9 @@ dependencies = [ [[package]] name = "rand" -version = "0.10.1" +version = "0.10.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d2e8e8bcc7961af1fdac401278c6a831614941f6164ee3bf4ce61b7edb162207" +checksum = "c7f5fa3a058cd35567ef9bfa5e75732bee0f9e4c55fa90477bef2dfcdbc4be80" dependencies = [ "chacha20", "getrandom 0.4.2", @@ -3299,7 +3299,7 @@ dependencies = [ "tokio", "tokio-rustls", "tower", - "tower-http", + "tower-http 0.6.11", "tower-service", "url", "wasm-bindgen", @@ -3763,9 +3763,9 @@ checksum = "67b1b7a3b5fe4f1376887184045fcf45c69e92af734b7aaddc05fb777b6fbd03" [[package]] name = "socket2" -version = "0.6.4" +version = "0.6.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "52d1cfed4120b4d927bf7c0f86d2087a4a7d6027c906d9f9d525a80573b9be51" +checksum = "c3d1e2c7f27f8d4cb10542a02c49005dbd6e93095799d6f3be745fae9f8fedd4" dependencies = [ "libc", "windows-sys 0.61.2", @@ -4059,16 +4059,16 @@ dependencies = [ [[package]] name = "thread-priority" -version = "3.0.0" +version = "3.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2210811179577da3d54eb69ab0b50490ee40491a25d95b8c6011ba40771cb721" +checksum = "8d2e834949be5111506bb252643498af1514f600d9e1dceedaa42afae155b67f" dependencies = [ "bitflags 2.11.1", "cfg-if", "libc", "log", "rustversion", - "windows 0.61.3", + "windows 0.62.2", ] [[package]] @@ -4168,9 +4168,9 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] name = "tokio" -version = "1.52.3" +version = "1.53.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8fc7f01b389ac15039e4dc9531aa973a135d7a4135281b12d7c1bc79fd57fffe" +checksum = "d988bcd52dbe076d3d46903332f58c912b87a2c49b1428419a5845154762ffee" dependencies = [ "bytes", "libc", @@ -4252,22 +4252,38 @@ name = "tower-http" version = "0.6.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4cfcf7e2740e6fc6d4d688b4ef00650406bb94adf4731e43c096c3a19fe40840" +dependencies = [ + "bitflags 2.11.1", + "bytes", + "futures-util", + "http", + "http-body", + "pin-project-lite", + "tower", + "tower-layer", + "tower-service", + "url", +] + +[[package]] +name = "tower-http" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b11f75e912b0c2be01b63d8cf8057b8c3f97cf34abb3d431a3a4c8675498e233" dependencies = [ "async-compression", "bitflags 2.11.1", "bytes", "futures-core", - "futures-util", "http", "http-body", "http-body-util", + "percent-encoding", "pin-project-lite", "tokio", "tokio-util", - "tower", "tower-layer", "tower-service", - "url", ] [[package]] @@ -4372,9 +4388,9 @@ dependencies = [ [[package]] name = "triomphe" -version = "0.1.15" +version = "0.1.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd69c5aa8f924c7519d6372789a74eac5b94fb0f8fcf0d4a97eb0bfc3e785f39" +checksum = "b40688ea6389c8171614b25491f71d4a27946e0c7ce2da1c6de27e25abf1a0ae" dependencies = [ "serde", "stable_deref_trait", @@ -4518,9 +4534,9 @@ dependencies = [ [[package]] name = "uuid" -version = "1.23.2" +version = "1.24.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d258b83ceec21034727ecee8c382cfa6c3e133699b0742c64571814fb420c9f7" +checksum = "bf3923a6f5c4c6382e0b653c4117f48d631ea17f38ed86e2a828e6f7412f5239" dependencies = [ "getrandom 0.4.2", "js-sys", @@ -4761,38 +4777,16 @@ dependencies = [ "windows-targets 0.48.5", ] -[[package]] -name = "windows" -version = "0.61.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9babd3a767a4c1aef6900409f85f5d53ce2544ccdfaa86dad48c91782c6d6893" -dependencies = [ - "windows-collections 0.2.0", - "windows-core 0.61.2", - "windows-future 0.2.1", - "windows-link 0.1.3", - "windows-numerics 0.2.0", -] - [[package]] name = "windows" version = "0.62.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "527fadee13e0c05939a6a05d5bd6eec6cd2e3dbd648b9f8e447c6518133d8580" dependencies = [ - "windows-collections 0.3.2", - "windows-core 0.62.2", - "windows-future 0.3.2", - "windows-numerics 0.3.1", -] - -[[package]] -name = "windows-collections" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3beeceb5e5cfd9eb1d76b381630e82c4241ccd0d27f1a39ed41b2760b255c5e8" -dependencies = [ - "windows-core 0.61.2", + "windows-collections", + "windows-core", + "windows-future", + "windows-numerics", ] [[package]] @@ -4801,20 +4795,7 @@ version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "23b2d95af1a8a14a3c7367e1ed4fc9c20e0a26e79551b1454d72583c97cc6610" dependencies = [ - "windows-core 0.62.2", -] - -[[package]] -name = "windows-core" -version = "0.61.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0fdd3ddb90610c7638aa2b3a3ab2904fb9e5cdbecc643ddb3647212781c4ae3" -dependencies = [ - "windows-implement", - "windows-interface", - "windows-link 0.1.3", - "windows-result 0.3.4", - "windows-strings 0.4.2", + "windows-core", ] [[package]] @@ -4825,20 +4806,9 @@ checksum = "b8e83a14d34d0623b51dce9581199302a221863196a1dde71a7663a4c2be9deb" dependencies = [ "windows-implement", "windows-interface", - "windows-link 0.2.1", - "windows-result 0.4.1", - "windows-strings 0.5.1", -] - -[[package]] -name = "windows-future" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fc6a41e98427b19fe4b73c550f060b59fa592d7d686537eebf9385621bfbad8e" -dependencies = [ - "windows-core 0.61.2", - "windows-link 0.1.3", - "windows-threading 0.1.0", + "windows-link", + "windows-result", + "windows-strings", ] [[package]] @@ -4847,9 +4817,9 @@ version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e1d6f90251fe18a279739e78025bd6ddc52a7e22f921070ccdc67dde84c605cb" dependencies = [ - "windows-core 0.62.2", - "windows-link 0.2.1", - "windows-threading 0.2.1", + "windows-core", + "windows-link", + "windows-threading", ] [[package]] @@ -4874,36 +4844,20 @@ dependencies = [ "syn", ] -[[package]] -name = "windows-link" -version = "0.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5e6ad25900d524eaabdbbb96d20b4311e1e7ae1699af4fb28c17ae66c80d798a" - [[package]] name = "windows-link" version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5" -[[package]] -name = "windows-numerics" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9150af68066c4c5c07ddc0ce30421554771e528bde427614c61038bc2c92c2b1" -dependencies = [ - "windows-core 0.61.2", - "windows-link 0.1.3", -] - [[package]] name = "windows-numerics" version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6e2e40844ac143cdb44aead537bbf727de9b044e107a0f1220392177d15b0f26" dependencies = [ - "windows-core 0.62.2", - "windows-link 0.2.1", + "windows-core", + "windows-link", ] [[package]] @@ -4912,18 +4866,9 @@ version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "02752bf7fbdcce7f2a27a742f798510f3e5ad88dbe84871e5168e2120c3d5720" dependencies = [ - "windows-link 0.2.1", - "windows-result 0.4.1", - "windows-strings 0.5.1", -] - -[[package]] -name = "windows-result" -version = "0.3.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "56f42bd332cc6c8eac5af113fc0c1fd6a8fd2aa08a0119358686e5160d0586c6" -dependencies = [ - "windows-link 0.1.3", + "windows-link", + "windows-result", + "windows-strings", ] [[package]] @@ -4932,16 +4877,7 @@ version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7781fa89eaf60850ac3d2da7af8e5242a5ea78d1a11c49bf2910bb5a73853eb5" dependencies = [ - "windows-link 0.2.1", -] - -[[package]] -name = "windows-strings" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "56e6c93f3a0c3b36176cb1327a4958a0353d5d166c2a35cb268ace15e91d3b57" -dependencies = [ - "windows-link 0.1.3", + "windows-link", ] [[package]] @@ -4950,7 +4886,7 @@ version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7837d08f69c77cf6b07689544538e017c1bfcf57e34b4c0ff58e6c2cd3b37091" dependencies = [ - "windows-link 0.2.1", + "windows-link", ] [[package]] @@ -4977,7 +4913,7 @@ version = "0.61.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ae137229bcbd6cdf0f7b80a31df61766145077ddf49416a728b02cb3921ff3fc" dependencies = [ - "windows-link 0.2.1", + "windows-link", ] [[package]] @@ -5026,22 +4962,13 @@ dependencies = [ "windows_x86_64_msvc 0.52.6", ] -[[package]] -name = "windows-threading" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b66463ad2e0ea3bbf808b7f1d371311c80e115c0b71d60efc142cafbcfb057a6" -dependencies = [ - "windows-link 0.1.3", -] - [[package]] name = "windows-threading" version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3949bd5b99cafdf1c7ca86b43ca564028dfe27d66958f2470940f73d86d75b37" dependencies = [ - "windows-link 0.2.1", + "windows-link", ] [[package]] diff --git a/pulsebeam/Cargo.toml b/pulsebeam/Cargo.toml index dceedc7e..94b75f2f 100644 --- a/pulsebeam/Cargo.toml +++ b/pulsebeam/Cargo.toml @@ -56,7 +56,7 @@ thread-priority = "3.0.0" tokio = { workspace = true } tokio-stream = { version = "0.1.18", features = ["sync"] } tokio-util = { workspace = true, features = ["time"] } -tower-http = { version = "0.6.11", features = [ +tower-http = { version = "0.7.0", features = [ "compression-zstd", "cors", "decompression-gzip",