Skip to content

Commit eef67f6

Browse files
authored
feat: support SNI multiaddrs in WebSocket transport
Adds support for WebSocket dialing with multiaddrs of the form: ``` /ip4/…/tcp/…/tls/sni/<hostname>/ws ``` This enables `rust-libp2p` nodes to connect to WSS peers using SNI-based addressing, as introduced in the libp2p specs for autotls support. Pull-Request: #6041.
1 parent 5f68f73 commit eef67f6

File tree

5 files changed

+65
-4
lines changed

5 files changed

+65
-4
lines changed

Cargo.lock

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -112,7 +112,7 @@ libp2p-upnp = { version = "0.5.0", path = "protocols/upnp" }
112112
libp2p-webrtc = { version = "0.9.0-alpha.1", path = "transports/webrtc" }
113113
libp2p-webrtc-utils = { version = "0.4.0", path = "misc/webrtc-utils" }
114114
libp2p-webrtc-websys = { version = "0.4.0", path = "transports/webrtc-websys" }
115-
libp2p-websocket = { version = "0.45.1", path = "transports/websocket" }
115+
libp2p-websocket = { version = "0.45.2", path = "transports/websocket" }
116116
libp2p-websocket-websys = { version = "0.5.0", path = "transports/websocket-websys" }
117117
libp2p-webtransport-websys = { version = "0.5.1", path = "transports/webtransport-websys" }
118118
libp2p-yamux = { version = "0.47.0", path = "muxers/yamux" }

transports/websocket/CHANGELOG.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,8 @@
1+
## 0.45.2
2+
3+
- feat(websocket): support `/tls/sni/<hostname>/ws` multiaddrs in the WebSocket transport
4+
See [PR 6041](https://github.com/your-username/rust-libp2p/pull/6041)
5+
16
## 0.45.1
27
- Rename types to match naming convention in [discussion 2174](https://github.com/libp2p/rust-libp2p/discussions/2174).
38
See [PR 5873](https://github.com/libp2p/rust-libp2p/pull/5873).

transports/websocket/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ name = "libp2p-websocket"
33
edition.workspace = true
44
rust-version = { workspace = true }
55
description = "WebSocket transport for libp2p"
6-
version = "0.45.1"
6+
version = "0.45.2"
77
authors = ["Parity Technologies <[email protected]>"]
88
license = "MIT"
99
repository = "https://github.com/libp2p/rust-libp2p"

transports/websocket/src/framed.rs

Lines changed: 57 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -508,7 +508,7 @@ fn parse_ws_dial_addr<T>(addr: Multiaddr) -> Result<WsAddress, Error<T>> {
508508
let mut protocols = addr.iter();
509509
let mut ip = protocols.next();
510510
let mut tcp = protocols.next();
511-
let (host_port, server_name) = loop {
511+
let (host_port, mut server_name) = loop {
512512
match (ip, tcp) {
513513
(Some(Protocol::Ip4(ip)), Some(Protocol::Tcp(port))) => {
514514
let server_name = ServerName::IpAddress(IpAddr::V4(ip).into());
@@ -531,6 +531,8 @@ fn parse_ws_dial_addr<T>(addr: Multiaddr) -> Result<WsAddress, Error<T>> {
531531
}
532532
};
533533

534+
// Will hold a value if the multiaddr carries `/tls/sni/<host>`.
535+
let mut sni_override: Option<ServerName<'static>> = None;
534536
// Now consume the `Ws` / `Wss` protocol from the end of the address,
535537
// preserving the trailing `P2p` protocol that identifies the remote,
536538
// if any.
@@ -540,6 +542,13 @@ fn parse_ws_dial_addr<T>(addr: Multiaddr) -> Result<WsAddress, Error<T>> {
540542
match protocols.pop() {
541543
p @ Some(Protocol::P2p(_)) => p2p = p,
542544
Some(Protocol::Ws(path)) => match protocols.pop() {
545+
Some(Protocol::Sni(domain)) => match protocols.pop() {
546+
Some(Protocol::Tls) => {
547+
sni_override = Some(tls::dns_name_ref(&domain)?);
548+
break (true, path.into_owned());
549+
}
550+
_ => return Err(Error::InvalidMultiaddr(addr)),
551+
},
543552
Some(Protocol::Tls) => break (true, path.into_owned()),
544553
Some(p) => {
545554
protocols.push(p);
@@ -559,6 +568,9 @@ fn parse_ws_dial_addr<T>(addr: Multiaddr) -> Result<WsAddress, Error<T>> {
559568
None => protocols,
560569
};
561570

571+
if let Some(name) = sni_override {
572+
server_name = name;
573+
}
562574
Ok(WsAddress {
563575
host_port,
564576
server_name,
@@ -1013,5 +1025,49 @@ mod tests {
10131025
// Check non-ws address
10141026
let addr = "/ip4/127.0.0.1/tcp/2222".parse::<Multiaddr>().unwrap();
10151027
parse_ws_dial_addr::<io::Error>(addr).unwrap_err();
1028+
1029+
// Check `/tls/sni/.../ws` with `/dns4`
1030+
let addr = "/dns4/example.com/tcp/2222/tls/sni/example.com/ws"
1031+
.parse::<Multiaddr>()
1032+
.unwrap();
1033+
let info = parse_ws_dial_addr::<io::Error>(addr).unwrap();
1034+
assert_eq!(info.host_port, "example.com:2222");
1035+
assert_eq!(info.path, "/");
1036+
assert!(info.use_tls);
1037+
assert_eq!(info.server_name, "example.com".try_into().unwrap());
1038+
assert_eq!(info.tcp_addr, "/dns4/example.com/tcp/2222".parse().unwrap());
1039+
1040+
// Check `/tls/sni/.../ws` with `/ip4`
1041+
let addr = "/ip4/127.0.0.1/tcp/2222/tls/sni/example.test/ws"
1042+
.parse::<Multiaddr>()
1043+
.unwrap();
1044+
let info = parse_ws_dial_addr::<io::Error>(addr).unwrap();
1045+
assert_eq!(info.host_port, "127.0.0.1:2222");
1046+
assert_eq!(info.path, "/");
1047+
assert!(info.use_tls);
1048+
assert_eq!(info.server_name, "example.test".try_into().unwrap());
1049+
assert_eq!(info.tcp_addr, "/ip4/127.0.0.1/tcp/2222".parse().unwrap());
1050+
1051+
// Check `/tls/sni/.../ws` with trailing `/p2p`
1052+
let addr = format!("/dns4/example.com/tcp/2222/tls/sni/example.com/ws/p2p/{peer_id}")
1053+
.parse()
1054+
.unwrap();
1055+
let info = parse_ws_dial_addr::<io::Error>(addr).unwrap();
1056+
assert_eq!(info.host_port, "example.com:2222");
1057+
assert_eq!(info.path, "/");
1058+
assert!(info.use_tls);
1059+
assert_eq!(info.server_name, "example.com".try_into().unwrap());
1060+
assert_eq!(
1061+
info.tcp_addr,
1062+
format!("/dns4/example.com/tcp/2222/p2p/{peer_id}")
1063+
.parse()
1064+
.unwrap()
1065+
);
1066+
1067+
// Negative: `/tls/sni/...` *without* `/ws` → error
1068+
let bad = "/dns4/example.com/tcp/2222/tls/sni/example.com"
1069+
.parse::<Multiaddr>()
1070+
.unwrap();
1071+
parse_ws_dial_addr::<io::Error>(bad).unwrap_err();
10161072
}
10171073
}

0 commit comments

Comments
 (0)