@@ -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