Use the ip addr for WS connect in WASM when available

This commit is contained in:
Brandon Vandegrift authored and Christien Rioux committed 2026-03-15 19:02:16 -04:00
1 parent e1b49783e9
commit ca2a3f5cf9
4 files changed
+170 -1

No files matched your search

@@ -137,8 +137,22 @@ impl WebsocketProtocolHandler {
bail_io_error_other!("invalid websocket url scheme");
}
let socket_address = dial_info.socket_address();
let connect_request = if socket_address.ip_addr().is_unspecified() {
request
} else {
let ip_based_url = SplitUrl::new(
scheme,
split_url.userinfo.clone(),
SplitUrlHost::IpAddr(socket_address.ip_addr()),
Some(socket_address.port()),
split_url.path.clone(),
);
ip_based_url.to_string()
};
let fut = SendWrapper::new(timeout(timeout_ms, async move {
WsMeta::connect(request, None)
WsMeta::connect(connect_request, None)
.await
.map_err(ws_err_to_io_error)
}));
@@ -1,6 +1,15 @@
use super::*;
use core::convert::TryInto;
fn reject_unspecified_socket_address(socket_address: &SocketAddress) -> Result<(), RPCError> {
if socket_address.address().is_unspecified() {
return Err(RPCError::protocol(
"dial info with unspecified (0.0.0.0 or ::) address not allowed",
));
}
Ok(())
}
pub fn decode_dial_info(reader: &veilid_capnp::dial_info::Reader) -> Result<DialInfo, RPCError> {
let pt = reader.get_protocol_type();
@@ -13,6 +22,7 @@ pub fn decode_dial_info(reader: &veilid_capnp::dial_info::Reader) -> Result<Dial
rpc_ignore_missing_property!(udp, socket_address);
let socket_address_reader = udp.get_socket_address()?;
let socket_address = decode_socket_address(&socket_address_reader)?;
reject_unspecified_socket_address(&socket_address)?;
Ok(DialInfo::udp(socket_address))
}
FOURCC_PROTOCOL_TYPE_TCP => {
@@ -23,6 +33,7 @@ pub fn decode_dial_info(reader: &veilid_capnp::dial_info::Reader) -> Result<Dial
rpc_ignore_missing_property!(tcp, socket_address);
let socket_address_reader = tcp.get_socket_address()?;
let socket_address = decode_socket_address(&socket_address_reader)?;
reject_unspecified_socket_address(&socket_address)?;
Ok(DialInfo::tcp(socket_address))
}
FOURCC_PROTOCOL_TYPE_WS => {
@@ -33,6 +44,7 @@ pub fn decode_dial_info(reader: &veilid_capnp::dial_info::Reader) -> Result<Dial
rpc_ignore_missing_property!(ws, socket_address);
let socket_address_reader = ws.get_socket_address()?;
let socket_address = decode_socket_address(&socket_address_reader)?;
reject_unspecified_socket_address(&socket_address)?;
rpc_ignore_missing_property!(ws, request);
let request = ws.get_request()?;
DialInfo::try_ws(
@@ -54,6 +66,7 @@ pub fn decode_dial_info(reader: &veilid_capnp::dial_info::Reader) -> Result<Dial
.get_socket_address()
.map_err(RPCError::map_protocol("missing WSS socketAddress"))?;
let socket_address = decode_socket_address(&socket_address_reader)?;
reject_unspecified_socket_address(&socket_address)?;
rpc_ignore_missing_property!(wss, request);
let request = wss.get_request()?;
DialInfo::try_wss(
@@ -1,7 +1,15 @@
use super::*;
mod test_dial_info;
mod test_signed_value_data;
#[expect(clippy::unused_async)]
pub async fn test_all() {
test_signed_value_data::test_encode_and_decode_signed_value_data();
test_dial_info::test_encode_and_decode_dial_info_udp();
test_dial_info::test_encode_and_decode_dial_info_tcp();
test_dial_info::test_encode_and_decode_dial_info_ws();
#[cfg(feature = "enable-protocol-wss")]
test_dial_info::test_encode_and_decode_dial_info_wss();
test_dial_info::test_decode_dial_info_rejects_unspecified_ipv4();
test_dial_info::test_decode_dial_info_rejects_unspecified_ipv6();
}
@@ -0,0 +1,134 @@
use super::*;
use std::net::Ipv4Addr;
fn round_trip_dial_info(dial_info: &DialInfo) {
let mut message_builder = capnp::message::Builder::new_default();
let mut builder = message_builder.init_root::<veilid_capnp::dial_info::Builder>();
encode_dial_info(dial_info, &mut builder).unwrap();
let buffer = canonical_message_builder_to_vec_packed(message_builder).unwrap();
let mut cursor = &mut &buffer[..];
let tmp_reader =
capnp::serialize_packed::read_message(&mut cursor, capnp::message::ReaderOptions::new())
.unwrap();
let reader = tmp_reader
.get_root::<veilid_capnp::dial_info::Reader>()
.unwrap();
let decoded = decode_dial_info(&reader).unwrap();
assert_eq!(dial_info, &decoded);
}
pub fn test_encode_and_decode_dial_info_udp() {
let socket_address = SocketAddress::new(Address::IPV4(Ipv4Addr::new(192, 168, 1, 1)), 8080);
let dial_info = DialInfo::udp(socket_address);
round_trip_dial_info(&dial_info);
}
pub fn test_encode_and_decode_dial_info_tcp() {
let socket_address = SocketAddress::new(Address::IPV4(Ipv4Addr::new(10, 0, 0, 1)), 443);
let dial_info = DialInfo::tcp(socket_address);
round_trip_dial_info(&dial_info);
}
pub fn test_encode_and_decode_dial_info_ws() {
let socket_address = SocketAddress::new(Address::IPV4(Ipv4Addr::new(192, 168, 1, 1)), 8080);
let dial_info =
DialInfo::try_ws(socket_address, "ws://192.168.1.1:8080/ws".to_string()).unwrap();
round_trip_dial_info(&dial_info);
}
#[cfg(feature = "enable-protocol-wss")]
pub fn test_encode_and_decode_dial_info_wss() {
let socket_address = SocketAddress::new(Address::IPV4(Ipv4Addr::new(10, 0, 0, 1)), 443);
let dial_info = DialInfo::try_wss(socket_address, "wss://10.0.0.1:443/ws".to_string()).unwrap();
round_trip_dial_info(&dial_info);
}
fn build_dial_info_message_unspecified_ipv4() -> Vec<u8> {
let mut message_builder = capnp::message::Builder::new_default();
let mut builder = message_builder.init_root::<veilid_capnp::dial_info::Builder>();
builder.set_protocol_type(FOURCC_PROTOCOL_TYPE_UDP);
let mut udp_builder = builder
.reborrow()
.init_detail()
.init_as::<veilid_capnp::dial_info_u_d_p::Builder>();
let mut sa_builder = udp_builder.reborrow().init_socket_address();
let mut addr_builder = sa_builder.reborrow().init_address();
addr_builder.set_address_type(FOURCC_ADDRESS_TYPE_IPV4);
let mut v4_builder = addr_builder
.reborrow()
.init_detail()
.init_as::<veilid_capnp::address_i_p_v4::Builder>();
v4_builder.set_addr(0u32); // 0.0.0.0 in big endian
sa_builder.set_port(8080);
canonical_message_builder_to_vec_packed(message_builder).unwrap()
}
fn build_dial_info_message_unspecified_ipv6() -> Vec<u8> {
let mut message_builder = capnp::message::Builder::new_default();
let mut builder = message_builder.init_root::<veilid_capnp::dial_info::Builder>();
builder.set_protocol_type(FOURCC_PROTOCOL_TYPE_UDP);
let mut udp_builder = builder
.reborrow()
.init_detail()
.init_as::<veilid_capnp::dial_info_u_d_p::Builder>();
let mut sa_builder = udp_builder.reborrow().init_socket_address();
let mut addr_builder = sa_builder.reborrow().init_address();
addr_builder.set_address_type(FOURCC_ADDRESS_TYPE_IPV6);
let mut v6_builder = addr_builder
.reborrow()
.init_detail()
.init_as::<veilid_capnp::address_i_p_v6::Builder>();
v6_builder.set_addr0(0u32);
v6_builder.set_addr1(0u32);
v6_builder.set_addr2(0u32);
v6_builder.set_addr3(0u32);
sa_builder.set_port(8080);
canonical_message_builder_to_vec_packed(message_builder).unwrap()
}
pub fn test_decode_dial_info_rejects_unspecified_ipv4() {
let buffer = build_dial_info_message_unspecified_ipv4();
let mut cursor = &mut &buffer[..];
let tmp_reader =
capnp::serialize_packed::read_message(&mut cursor, capnp::message::ReaderOptions::new())
.unwrap();
let reader = tmp_reader
.get_root::<veilid_capnp::dial_info::Reader>()
.unwrap();
let result = decode_dial_info(&reader);
assert!(result.is_err());
assert!(result.unwrap_err().to_string().contains("unspecified"));
}
pub fn test_decode_dial_info_rejects_unspecified_ipv6() {
let buffer = build_dial_info_message_unspecified_ipv6();
let mut cursor = &mut &buffer[..];
let tmp_reader =
capnp::serialize_packed::read_message(&mut cursor, capnp::message::ReaderOptions::new())
.unwrap();
let reader = tmp_reader
.get_root::<veilid_capnp::dial_info::Reader>()
.unwrap();
let result = decode_dial_info(&reader);
assert!(result.is_err());
assert!(result.unwrap_err().to_string().contains("unspecified"));
}