mirror of
https://github.com/fluencelabs/rust-libp2p
synced 2025-05-25 17:01:20 +00:00
Allow a path for WS multiaddresses (#1093)
* Allow a path for WS multiaddresses * Fix tests * Finish * Tests * Don't accept any path other than /
This commit is contained in:
parent
39c476edeb
commit
e7ab8eb1c3
@ -15,6 +15,7 @@ byteorder = "1.3.1"
|
|||||||
bytes = "0.4.12"
|
bytes = "0.4.12"
|
||||||
data-encoding = "2.1"
|
data-encoding = "2.1"
|
||||||
multihash = { package = "parity-multihash", version = "0.1.0", path = "../multihash" }
|
multihash = { package = "parity-multihash", version = "0.1.0", path = "../multihash" }
|
||||||
|
percent-encoding = "1.0.1"
|
||||||
serde = "1.0.70"
|
serde = "1.0.70"
|
||||||
unsigned-varint = "0.2"
|
unsigned-varint = "0.2"
|
||||||
url = { version = "1.7.2", default-features = false }
|
url = { version = "1.7.2", default-features = false }
|
||||||
|
@ -57,11 +57,11 @@ fn from_url_inner(url: &str, lossy: bool) -> std::result::Result<Multiaddr, From
|
|||||||
|
|
||||||
/// Called when `url.scheme()` is an Internet-like URL.
|
/// Called when `url.scheme()` is an Internet-like URL.
|
||||||
fn from_url_inner_http_ws(url: url::Url, lossy: bool) -> std::result::Result<Multiaddr, FromUrlErr> {
|
fn from_url_inner_http_ws(url: url::Url, lossy: bool) -> std::result::Result<Multiaddr, FromUrlErr> {
|
||||||
let (protocol, default_port) = match url.scheme() {
|
let (protocol, lost_path, default_port) = match url.scheme() {
|
||||||
"ws" => (Protocol::Ws, 80),
|
"ws" => (Protocol::Ws(url.path().to_owned().into()), false, 80),
|
||||||
"wss" => (Protocol::Wss, 443),
|
"wss" => (Protocol::Wss(url.path().to_owned().into()), false, 443),
|
||||||
"http" => (Protocol::Http, 80),
|
"http" => (Protocol::Http, true, 80),
|
||||||
"https" => (Protocol::Https, 443),
|
"https" => (Protocol::Https, true, 443),
|
||||||
_ => unreachable!("We only call this function for one of the given schemes; qed")
|
_ => unreachable!("We only call this function for one of the given schemes; qed")
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -78,7 +78,7 @@ fn from_url_inner_http_ws(url: url::Url, lossy: bool) -> std::result::Result<Mul
|
|||||||
|
|
||||||
if !lossy {
|
if !lossy {
|
||||||
if !url.username().is_empty() || url.password().is_some() ||
|
if !url.username().is_empty() || url.password().is_some() ||
|
||||||
(url.path() != "/" && !url.path().is_empty()) ||
|
(lost_path && url.path() != "/" && !url.path().is_empty()) ||
|
||||||
url.query().is_some() || url.fragment().is_some()
|
url.query().is_some() || url.fragment().is_some()
|
||||||
{
|
{
|
||||||
return Err(FromUrlErr::InformationLoss);
|
return Err(FromUrlErr::InformationLoss);
|
||||||
@ -260,4 +260,19 @@ mod tests {
|
|||||||
let addr = from_url("unix:/foo/bar").unwrap();
|
let addr = from_url("unix:/foo/bar").unwrap();
|
||||||
assert_eq!(addr, Multiaddr::from(Protocol::Unix("/foo/bar".into())));
|
assert_eq!(addr, Multiaddr::from(Protocol::Unix("/foo/bar".into())));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn ws_path() {
|
||||||
|
let addr = from_url("ws://1.2.3.4:1000/foo/bar").unwrap();
|
||||||
|
assert_eq!(addr, "/ip4/1.2.3.4/tcp/1000/x-parity-ws/%2ffoo%2fbar".parse().unwrap());
|
||||||
|
|
||||||
|
let addr = from_url("ws://1.2.3.4:1000/").unwrap();
|
||||||
|
assert_eq!(addr, "/ip4/1.2.3.4/tcp/1000/ws".parse().unwrap());
|
||||||
|
|
||||||
|
let addr = from_url("wss://1.2.3.4:1000/foo/bar").unwrap();
|
||||||
|
assert_eq!(addr, "/ip4/1.2.3.4/tcp/1000/x-parity-wss/%2ffoo%2fbar".parse().unwrap());
|
||||||
|
|
||||||
|
let addr = from_url("wss://1.2.3.4:1000").unwrap();
|
||||||
|
assert_eq!(addr, "/ip4/1.2.3.4/tcp/1000/wss".parse().unwrap());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -37,9 +37,16 @@ const UDT: u32 = 301;
|
|||||||
const UNIX: u32 = 400;
|
const UNIX: u32 = 400;
|
||||||
const UTP: u32 = 302;
|
const UTP: u32 = 302;
|
||||||
const WS: u32 = 477;
|
const WS: u32 = 477;
|
||||||
|
const WS_WITH_PATH: u32 = 4770; // Note: not standard
|
||||||
const WSS: u32 = 478;
|
const WSS: u32 = 478;
|
||||||
|
const WSS_WITH_PATH: u32 = 4780; // Note: not standard
|
||||||
|
|
||||||
/// `Protocol` describes all possible multiaddress protocols.
|
/// `Protocol` describes all possible multiaddress protocols.
|
||||||
|
///
|
||||||
|
/// For `Unix`, `Ws` and `Wss` we use `&str` instead of `Path` to allow
|
||||||
|
/// cross-platform usage of `Protocol` since encoding `Paths` to bytes is
|
||||||
|
/// platform-specific. This means that the actual validation of paths needs to
|
||||||
|
/// happen separately.
|
||||||
#[derive(PartialEq, Eq, Clone, Debug)]
|
#[derive(PartialEq, Eq, Clone, Debug)]
|
||||||
pub enum Protocol<'a> {
|
pub enum Protocol<'a> {
|
||||||
Dccp(u16),
|
Dccp(u16),
|
||||||
@ -62,13 +69,10 @@ pub enum Protocol<'a> {
|
|||||||
Tcp(u16),
|
Tcp(u16),
|
||||||
Udp(u16),
|
Udp(u16),
|
||||||
Udt,
|
Udt,
|
||||||
/// For `Unix` we use `&str` instead of `Path` to allow cross-platform usage of
|
|
||||||
/// `Protocol` since encoding `Paths` to bytes is platform-specific.
|
|
||||||
/// This means that the actual validation of paths needs to happen separately.
|
|
||||||
Unix(Cow<'a, str>),
|
Unix(Cow<'a, str>),
|
||||||
Utp,
|
Utp,
|
||||||
Ws,
|
Ws(Cow<'a, str>),
|
||||||
Wss
|
Wss(Cow<'a, str>),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> Protocol<'a> {
|
impl<'a> Protocol<'a> {
|
||||||
@ -134,8 +138,18 @@ impl<'a> Protocol<'a> {
|
|||||||
.and_then(|s| read_onion(&s.to_uppercase()))
|
.and_then(|s| read_onion(&s.to_uppercase()))
|
||||||
.map(|(a, p)| Protocol::Onion(Cow::Owned(a), p)),
|
.map(|(a, p)| Protocol::Onion(Cow::Owned(a), p)),
|
||||||
"quic" => Ok(Protocol::Quic),
|
"quic" => Ok(Protocol::Quic),
|
||||||
"ws" => Ok(Protocol::Ws),
|
"ws" => Ok(Protocol::Ws(Cow::Borrowed("/"))),
|
||||||
"wss" => Ok(Protocol::Wss),
|
"wss" => Ok(Protocol::Wss(Cow::Borrowed("/"))),
|
||||||
|
"x-parity-ws" => {
|
||||||
|
let s = iter.next().ok_or(Error::InvalidProtocolString)?;
|
||||||
|
let decoded = percent_encoding::percent_decode(s.as_bytes()).decode_utf8()?;
|
||||||
|
Ok(Protocol::Ws(decoded))
|
||||||
|
}
|
||||||
|
"x-parity-wss" => {
|
||||||
|
let s = iter.next().ok_or(Error::InvalidProtocolString)?;
|
||||||
|
let decoded = percent_encoding::percent_decode(s.as_bytes()).decode_utf8()?;
|
||||||
|
Ok(Protocol::Wss(decoded))
|
||||||
|
}
|
||||||
"p2p-websocket-star" => Ok(Protocol::P2pWebSocketStar),
|
"p2p-websocket-star" => Ok(Protocol::P2pWebSocketStar),
|
||||||
"p2p-webrtc-star" => Ok(Protocol::P2pWebRtcStar),
|
"p2p-webrtc-star" => Ok(Protocol::P2pWebRtcStar),
|
||||||
"p2p-webrtc-direct" => Ok(Protocol::P2pWebRtcDirect),
|
"p2p-webrtc-direct" => Ok(Protocol::P2pWebRtcDirect),
|
||||||
@ -247,8 +261,18 @@ impl<'a> Protocol<'a> {
|
|||||||
Ok((Protocol::Unix(Cow::Borrowed(str::from_utf8(data)?)), rest))
|
Ok((Protocol::Unix(Cow::Borrowed(str::from_utf8(data)?)), rest))
|
||||||
}
|
}
|
||||||
UTP => Ok((Protocol::Utp, input)),
|
UTP => Ok((Protocol::Utp, input)),
|
||||||
WS => Ok((Protocol::Ws, input)),
|
WS => Ok((Protocol::Ws(Cow::Borrowed("/")), input)),
|
||||||
WSS => Ok((Protocol::Wss, input)),
|
WS_WITH_PATH => {
|
||||||
|
let (n, input) = decode::usize(input)?;
|
||||||
|
let (data, rest) = split_at(n, input)?;
|
||||||
|
Ok((Protocol::Ws(Cow::Borrowed(str::from_utf8(data)?)), rest))
|
||||||
|
}
|
||||||
|
WSS => Ok((Protocol::Wss(Cow::Borrowed("/")), input)),
|
||||||
|
WSS_WITH_PATH => {
|
||||||
|
let (n, input) = decode::usize(input)?;
|
||||||
|
let (data, rest) = split_at(n, input)?;
|
||||||
|
Ok((Protocol::Wss(Cow::Borrowed(str::from_utf8(data)?)), rest))
|
||||||
|
}
|
||||||
_ => Err(Error::UnknownProtocolId(id))
|
_ => Err(Error::UnknownProtocolId(id))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -318,8 +342,20 @@ impl<'a> Protocol<'a> {
|
|||||||
Protocol::Udt => w.write_all(encode::u32(UDT, &mut buf))?,
|
Protocol::Udt => w.write_all(encode::u32(UDT, &mut buf))?,
|
||||||
Protocol::Http => w.write_all(encode::u32(HTTP, &mut buf))?,
|
Protocol::Http => w.write_all(encode::u32(HTTP, &mut buf))?,
|
||||||
Protocol::Https => w.write_all(encode::u32(HTTPS, &mut buf))?,
|
Protocol::Https => w.write_all(encode::u32(HTTPS, &mut buf))?,
|
||||||
Protocol::Ws => w.write_all(encode::u32(WS, &mut buf))?,
|
Protocol::Ws(ref s) if s == "/" => w.write_all(encode::u32(WS, &mut buf))?,
|
||||||
Protocol::Wss => w.write_all(encode::u32(WSS, &mut buf))?,
|
Protocol::Ws(s) => {
|
||||||
|
w.write_all(encode::u32(WS_WITH_PATH, &mut buf))?;
|
||||||
|
let bytes = s.as_bytes();
|
||||||
|
w.write_all(encode::usize(bytes.len(), &mut encode::usize_buffer()))?;
|
||||||
|
w.write_all(&bytes)?
|
||||||
|
},
|
||||||
|
Protocol::Wss(ref s) if s == "/" => w.write_all(encode::u32(WSS, &mut buf))?,
|
||||||
|
Protocol::Wss(s) => {
|
||||||
|
w.write_all(encode::u32(WSS_WITH_PATH, &mut buf))?;
|
||||||
|
let bytes = s.as_bytes();
|
||||||
|
w.write_all(encode::usize(bytes.len(), &mut encode::usize_buffer()))?;
|
||||||
|
w.write_all(&bytes)?
|
||||||
|
},
|
||||||
Protocol::P2pWebSocketStar => w.write_all(encode::u32(P2P_WEBSOCKET_STAR, &mut buf))?,
|
Protocol::P2pWebSocketStar => w.write_all(encode::u32(P2P_WEBSOCKET_STAR, &mut buf))?,
|
||||||
Protocol::P2pWebRtcStar => w.write_all(encode::u32(P2P_WEBRTC_STAR, &mut buf))?,
|
Protocol::P2pWebRtcStar => w.write_all(encode::u32(P2P_WEBRTC_STAR, &mut buf))?,
|
||||||
Protocol::P2pWebRtcDirect => w.write_all(encode::u32(P2P_WEBRTC_DIRECT, &mut buf))?,
|
Protocol::P2pWebRtcDirect => w.write_all(encode::u32(P2P_WEBRTC_DIRECT, &mut buf))?,
|
||||||
@ -357,8 +393,8 @@ impl<'a> Protocol<'a> {
|
|||||||
Udt => Udt,
|
Udt => Udt,
|
||||||
Unix(cow) => Unix(Cow::Owned(cow.into_owned())),
|
Unix(cow) => Unix(Cow::Owned(cow.into_owned())),
|
||||||
Utp => Utp,
|
Utp => Utp,
|
||||||
Ws => Ws,
|
Ws(cow) => Ws(Cow::Owned(cow.into_owned())),
|
||||||
Wss => Wss
|
Wss(cow) => Wss(Cow::Owned(cow.into_owned())),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -391,8 +427,16 @@ impl<'a> fmt::Display for Protocol<'a> {
|
|||||||
Udt => f.write_str("/udt"),
|
Udt => f.write_str("/udt"),
|
||||||
Unix(s) => write!(f, "/unix/{}", s),
|
Unix(s) => write!(f, "/unix/{}", s),
|
||||||
Utp => f.write_str("/utp"),
|
Utp => f.write_str("/utp"),
|
||||||
Ws => f.write_str("/ws"),
|
Ws(ref s) if s == "/" => f.write_str("/ws"),
|
||||||
Wss => f.write_str("/wss"),
|
Ws(s) => {
|
||||||
|
let encoded = percent_encoding::percent_encode(s.as_bytes(), percent_encoding::PATH_SEGMENT_ENCODE_SET);
|
||||||
|
write!(f, "/x-parity-ws/{}", encoded)
|
||||||
|
},
|
||||||
|
Wss(ref s) if s == "/" => f.write_str("/wss"),
|
||||||
|
Wss(s) => {
|
||||||
|
let encoded = percent_encoding::percent_encode(s.as_bytes(), percent_encoding::PATH_SEGMENT_ENCODE_SET);
|
||||||
|
write!(f, "/x-parity-wss/{}", encoded)
|
||||||
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -452,4 +496,3 @@ fn read_onion(s: &str) -> Result<([u8; 10], u16)> {
|
|||||||
|
|
||||||
Ok((buf, port))
|
Ok((buf, port))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -98,8 +98,8 @@ impl Arbitrary for Proto {
|
|||||||
17 => Proto(Udt),
|
17 => Proto(Udt),
|
||||||
18 => Proto(Unix(Cow::Owned(SubString::arbitrary(g).0))),
|
18 => Proto(Unix(Cow::Owned(SubString::arbitrary(g).0))),
|
||||||
19 => Proto(Utp),
|
19 => Proto(Utp),
|
||||||
20 => Proto(Ws),
|
20 => Proto(Ws("/".into())),
|
||||||
21 => Proto(Wss),
|
21 => Proto(Wss("/".into())),
|
||||||
22 => {
|
22 => {
|
||||||
let mut a = [0; 10];
|
let mut a = [0; 10];
|
||||||
g.fill(&mut a);
|
g.fill(&mut a);
|
||||||
@ -196,15 +196,15 @@ fn construct_success() {
|
|||||||
// /ip4/127.0.0.1/p2p/QmcgpsyWgH8Y8ajJz1Cu72KnS5uo2Aa2LpzU7kinSupNKC/tcp/1234/unix/stdio
|
// /ip4/127.0.0.1/p2p/QmcgpsyWgH8Y8ajJz1Cu72KnS5uo2Aa2LpzU7kinSupNKC/tcp/1234/unix/stdio
|
||||||
ma_valid("/ip6/2001:8a0:7ac5:4201:3ac9:86ff:fe31:7095/tcp/8000/ws/p2p/QmcgpsyWgH8Y8ajJz1Cu72KnS5uo2Aa2LpzU7kinSupNKC",
|
ma_valid("/ip6/2001:8a0:7ac5:4201:3ac9:86ff:fe31:7095/tcp/8000/ws/p2p/QmcgpsyWgH8Y8ajJz1Cu72KnS5uo2Aa2LpzU7kinSupNKC",
|
||||||
"29200108A07AC542013AC986FFFE317095061F40DD03A503221220D52EBB89D85B02A284948203A62FF28389C57C9F42BEEC4EC20DB76A68911C0B",
|
"29200108A07AC542013AC986FFFE317095061F40DD03A503221220D52EBB89D85B02A284948203A62FF28389C57C9F42BEEC4EC20DB76A68911C0B",
|
||||||
vec![Ip6(addr6.clone()), Tcp(8000), Ws, P2p(multihash("QmcgpsyWgH8Y8ajJz1Cu72KnS5uo2Aa2LpzU7kinSupNKC"))
|
vec![Ip6(addr6.clone()), Tcp(8000), Ws("/".into()), P2p(multihash("QmcgpsyWgH8Y8ajJz1Cu72KnS5uo2Aa2LpzU7kinSupNKC"))
|
||||||
]);
|
]);
|
||||||
ma_valid("/p2p-webrtc-star/ip4/127.0.0.1/tcp/9090/ws/p2p/QmcgpsyWgH8Y8ajJz1Cu72KnS5uo2Aa2LpzU7kinSupNKC",
|
ma_valid("/p2p-webrtc-star/ip4/127.0.0.1/tcp/9090/ws/p2p/QmcgpsyWgH8Y8ajJz1Cu72KnS5uo2Aa2LpzU7kinSupNKC",
|
||||||
"9302047F000001062382DD03A503221220D52EBB89D85B02A284948203A62FF28389C57C9F42BEEC4EC20DB76A68911C0B",
|
"9302047F000001062382DD03A503221220D52EBB89D85B02A284948203A62FF28389C57C9F42BEEC4EC20DB76A68911C0B",
|
||||||
vec![P2pWebRtcStar, Ip4(local.clone()), Tcp(9090), Ws, P2p(multihash("QmcgpsyWgH8Y8ajJz1Cu72KnS5uo2Aa2LpzU7kinSupNKC"))
|
vec![P2pWebRtcStar, Ip4(local.clone()), Tcp(9090), Ws("/".into()), P2p(multihash("QmcgpsyWgH8Y8ajJz1Cu72KnS5uo2Aa2LpzU7kinSupNKC"))
|
||||||
]);
|
]);
|
||||||
ma_valid("/ip6/2001:8a0:7ac5:4201:3ac9:86ff:fe31:7095/tcp/8000/wss/p2p/QmcgpsyWgH8Y8ajJz1Cu72KnS5uo2Aa2LpzU7kinSupNKC",
|
ma_valid("/ip6/2001:8a0:7ac5:4201:3ac9:86ff:fe31:7095/tcp/8000/wss/p2p/QmcgpsyWgH8Y8ajJz1Cu72KnS5uo2Aa2LpzU7kinSupNKC",
|
||||||
"29200108A07AC542013AC986FFFE317095061F40DE03A503221220D52EBB89D85B02A284948203A62FF28389C57C9F42BEEC4EC20DB76A68911C0B",
|
"29200108A07AC542013AC986FFFE317095061F40DE03A503221220D52EBB89D85B02A284948203A62FF28389C57C9F42BEEC4EC20DB76A68911C0B",
|
||||||
vec![Ip6(addr6.clone()), Tcp(8000), Wss, P2p(multihash("QmcgpsyWgH8Y8ajJz1Cu72KnS5uo2Aa2LpzU7kinSupNKC"))]);
|
vec![Ip6(addr6.clone()), Tcp(8000), Wss("/".into()), P2p(multihash("QmcgpsyWgH8Y8ajJz1Cu72KnS5uo2Aa2LpzU7kinSupNKC"))]);
|
||||||
ma_valid("/ip4/127.0.0.1/tcp/9090/p2p-circuit/p2p/QmcgpsyWgH8Y8ajJz1Cu72KnS5uo2Aa2LpzU7kinSupNKC",
|
ma_valid("/ip4/127.0.0.1/tcp/9090/p2p-circuit/p2p/QmcgpsyWgH8Y8ajJz1Cu72KnS5uo2Aa2LpzU7kinSupNKC",
|
||||||
"047F000001062382A202A503221220D52EBB89D85B02A284948203A62FF28389C57C9F42BEEC4EC20DB76A68911C0B",
|
"047F000001062382A202A503221220D52EBB89D85B02A284948203A62FF28389C57C9F42BEEC4EC20DB76A68911C0B",
|
||||||
vec![Ip4(local.clone()), Tcp(9090), P2pCircuit, P2p(multihash("QmcgpsyWgH8Y8ajJz1Cu72KnS5uo2Aa2LpzU7kinSupNKC"))]);
|
vec![Ip4(local.clone()), Tcp(9090), P2pCircuit, P2p(multihash("QmcgpsyWgH8Y8ajJz1Cu72KnS5uo2Aa2LpzU7kinSupNKC"))]);
|
||||||
|
@ -298,41 +298,41 @@ fn multiaddr_to_target(addr: &Multiaddr) -> Result<String, ()> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
match (&protocols[0], &protocols[1], &protocols[2]) {
|
match (&protocols[0], &protocols[1], &protocols[2]) {
|
||||||
(&Protocol::Ip4(ref ip), &Protocol::Tcp(port), &Protocol::Ws) => {
|
(&Protocol::Ip4(ref ip), &Protocol::Tcp(port), &Protocol::Ws(ref ws_path)) => {
|
||||||
if ip.is_unspecified() || port == 0 {
|
if ip.is_unspecified() || port == 0 {
|
||||||
return Err(());
|
return Err(());
|
||||||
}
|
}
|
||||||
Ok(format!("ws://{}:{}/", ip, port))
|
Ok(format!("ws://{}:{}{}", ip, port, ws_path))
|
||||||
}
|
}
|
||||||
(&Protocol::Ip6(ref ip), &Protocol::Tcp(port), &Protocol::Ws) => {
|
(&Protocol::Ip6(ref ip), &Protocol::Tcp(port), &Protocol::Ws(ref ws_path)) => {
|
||||||
if ip.is_unspecified() || port == 0 {
|
if ip.is_unspecified() || port == 0 {
|
||||||
return Err(());
|
return Err(());
|
||||||
}
|
}
|
||||||
Ok(format!("ws://[{}]:{}/", ip, port))
|
Ok(format!("ws://[{}]:{}{}", ip, port, ws_path))
|
||||||
}
|
}
|
||||||
(&Protocol::Ip4(ref ip), &Protocol::Tcp(port), &Protocol::Wss) => {
|
(&Protocol::Ip4(ref ip), &Protocol::Tcp(port), &Protocol::Wss(ref ws_path)) => {
|
||||||
if ip.is_unspecified() || port == 0 {
|
if ip.is_unspecified() || port == 0 {
|
||||||
return Err(());
|
return Err(());
|
||||||
}
|
}
|
||||||
Ok(format!("wss://{}:{}/", ip, port))
|
Ok(format!("wss://{}:{}{}", ip, port, ws_path))
|
||||||
}
|
}
|
||||||
(&Protocol::Ip6(ref ip), &Protocol::Tcp(port), &Protocol::Wss) => {
|
(&Protocol::Ip6(ref ip), &Protocol::Tcp(port), &Protocol::Wss(ref ws_path)) => {
|
||||||
if ip.is_unspecified() || port == 0 {
|
if ip.is_unspecified() || port == 0 {
|
||||||
return Err(());
|
return Err(());
|
||||||
}
|
}
|
||||||
Ok(format!("wss://[{}]:{}/", ip, port))
|
Ok(format!("wss://[{}]:{}{}", ip, port, ws_path))
|
||||||
}
|
}
|
||||||
(&Protocol::Dns4(ref ns), &Protocol::Tcp(port), &Protocol::Ws) => {
|
(&Protocol::Dns4(ref ns), &Protocol::Tcp(port), &Protocol::Ws(ref ws_path)) => {
|
||||||
Ok(format!("ws://{}:{}/", ns, port))
|
Ok(format!("ws://{}:{}{}", ns, port, ws_path))
|
||||||
}
|
}
|
||||||
(&Protocol::Dns6(ref ns), &Protocol::Tcp(port), &Protocol::Ws) => {
|
(&Protocol::Dns6(ref ns), &Protocol::Tcp(port), &Protocol::Ws(ref ws_path)) => {
|
||||||
Ok(format!("ws://{}:{}/", ns, port))
|
Ok(format!("ws://{}:{}{}", ns, port, ws_path))
|
||||||
}
|
}
|
||||||
(&Protocol::Dns4(ref ns), &Protocol::Tcp(port), &Protocol::Wss) => {
|
(&Protocol::Dns4(ref ns), &Protocol::Tcp(port), &Protocol::Wss(ref ws_path)) => {
|
||||||
Ok(format!("wss://{}:{}/", ns, port))
|
Ok(format!("wss://{}:{}{}", ns, port, ws_path))
|
||||||
}
|
}
|
||||||
(&Protocol::Dns6(ref ns), &Protocol::Tcp(port), &Protocol::Wss) => {
|
(&Protocol::Dns6(ref ns), &Protocol::Tcp(port), &Protocol::Wss(ref ws_path)) => {
|
||||||
Ok(format!("wss://{}:{}/", ns, port))
|
Ok(format!("wss://{}:{}{}", ns, port, ws_path))
|
||||||
}
|
}
|
||||||
_ => Err(()),
|
_ => Err(()),
|
||||||
}
|
}
|
||||||
|
@ -80,27 +80,27 @@ where
|
|||||||
fn listen_on(self, original_addr: Multiaddr) -> Result<Self::Listener, TransportError<Self::Error>> {
|
fn listen_on(self, original_addr: Multiaddr) -> Result<Self::Listener, TransportError<Self::Error>> {
|
||||||
let mut inner_addr = original_addr.clone();
|
let mut inner_addr = original_addr.clone();
|
||||||
match inner_addr.pop() {
|
match inner_addr.pop() {
|
||||||
Some(Protocol::Ws) => {}
|
Some(Protocol::Ws(ref path)) if path == "/" || path.is_empty() => {},
|
||||||
_ => return Err(TransportError::MultiaddrNotSupported(original_addr)),
|
_ => return Err(TransportError::MultiaddrNotSupported(original_addr)),
|
||||||
};
|
};
|
||||||
|
|
||||||
let inner_listen = self.transport.listen_on(inner_addr)
|
let inner_listen = self.transport.listen_on(inner_addr)
|
||||||
.map_err(|err| err.map(WsError::Underlying))?;
|
.map_err(|err| err.map(WsError::Underlying))?;
|
||||||
|
|
||||||
let listen = inner_listen.map_err(WsError::Underlying).map(|event| {
|
let listen = inner_listen.map_err(WsError::Underlying).map(move |event| {
|
||||||
match event {
|
match event {
|
||||||
ListenerEvent::NewAddress(mut a) => {
|
ListenerEvent::NewAddress(mut a) => {
|
||||||
a = a.with(Protocol::Ws);
|
a = a.with(Protocol::Ws(From::from("/")));
|
||||||
debug!("Listening on {}", a);
|
debug!("Listening on {}", a);
|
||||||
ListenerEvent::NewAddress(a)
|
ListenerEvent::NewAddress(a)
|
||||||
}
|
}
|
||||||
ListenerEvent::AddressExpired(mut a) => {
|
ListenerEvent::AddressExpired(mut a) => {
|
||||||
a = a.with(Protocol::Ws);
|
a = a.with(Protocol::Ws(From::from("/")));
|
||||||
ListenerEvent::AddressExpired(a)
|
ListenerEvent::AddressExpired(a)
|
||||||
}
|
}
|
||||||
ListenerEvent::Upgrade { upgrade, mut listen_addr, mut remote_addr } => {
|
ListenerEvent::Upgrade { upgrade, mut listen_addr, mut remote_addr } => {
|
||||||
listen_addr = listen_addr.with(Protocol::Ws);
|
listen_addr = listen_addr.with(Protocol::Ws(From::from("/")));
|
||||||
remote_addr = remote_addr.with(Protocol::Ws);
|
remote_addr = remote_addr.with(Protocol::Ws(From::from("/")));
|
||||||
|
|
||||||
// Upgrade the listener to websockets like the websockets library requires us to do.
|
// Upgrade the listener to websockets like the websockets library requires us to do.
|
||||||
let upgraded = upgrade.map_err(WsError::Underlying).and_then(move |stream| {
|
let upgraded = upgrade.map_err(WsError::Underlying).and_then(move |stream| {
|
||||||
@ -157,9 +157,9 @@ where
|
|||||||
|
|
||||||
fn dial(self, original_addr: Multiaddr) -> Result<Self::Dial, TransportError<Self::Error>> {
|
fn dial(self, original_addr: Multiaddr) -> Result<Self::Dial, TransportError<Self::Error>> {
|
||||||
let mut inner_addr = original_addr.clone();
|
let mut inner_addr = original_addr.clone();
|
||||||
let is_wss = match inner_addr.pop() {
|
let (ws_path, is_wss) = match inner_addr.pop() {
|
||||||
Some(Protocol::Ws) => false,
|
Some(Protocol::Ws(path)) => (path.into_owned(), false),
|
||||||
Some(Protocol::Wss) => true,
|
Some(Protocol::Wss(path)) => (path.into_owned(), true),
|
||||||
_ => {
|
_ => {
|
||||||
trace!(
|
trace!(
|
||||||
"Ignoring dial attempt for {} because it is not a websocket multiaddr",
|
"Ignoring dial attempt for {} because it is not a websocket multiaddr",
|
||||||
@ -171,7 +171,7 @@ where
|
|||||||
|
|
||||||
debug!("Dialing {} through inner transport", inner_addr);
|
debug!("Dialing {} through inner transport", inner_addr);
|
||||||
|
|
||||||
let ws_addr = client_addr_to_ws(&inner_addr, is_wss);
|
let ws_addr = client_addr_to_ws(&inner_addr, &ws_path, is_wss);
|
||||||
|
|
||||||
let inner_dial = self.transport.dial(inner_addr)
|
let inner_dial = self.transport.dial(inner_addr)
|
||||||
.map_err(|err| err.map(WsError::Underlying))?;
|
.map_err(|err| err.map(WsError::Underlying))?;
|
||||||
@ -242,7 +242,7 @@ where TErr: error::Error + 'static
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn client_addr_to_ws(client_addr: &Multiaddr, is_wss: bool) -> String {
|
fn client_addr_to_ws(client_addr: &Multiaddr, ws_path: &str, is_wss: bool) -> String {
|
||||||
let inner = {
|
let inner = {
|
||||||
let protocols: Vec<_> = client_addr.iter().collect();
|
let protocols: Vec<_> = client_addr.iter().collect();
|
||||||
|
|
||||||
@ -268,9 +268,9 @@ fn client_addr_to_ws(client_addr: &Multiaddr, is_wss: bool) -> String {
|
|||||||
};
|
};
|
||||||
|
|
||||||
if is_wss {
|
if is_wss {
|
||||||
format!("wss://{}", inner)
|
format!("wss://{}{}", inner, ws_path)
|
||||||
} else {
|
} else {
|
||||||
format!("ws://{}", inner)
|
format!("ws://{}{}", inner, ws_path)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -301,7 +301,7 @@ mod tests {
|
|||||||
.into_new_address()
|
.into_new_address()
|
||||||
.expect("listen address");
|
.expect("listen address");
|
||||||
|
|
||||||
assert_eq!(Some(Protocol::Ws), addr.iter().nth(2));
|
assert_eq!(Some(Protocol::Ws("/".into())), addr.iter().nth(2));
|
||||||
assert_ne!(Some(Protocol::Tcp(0)), addr.iter().nth(1));
|
assert_ne!(Some(Protocol::Tcp(0)), addr.iter().nth(1));
|
||||||
|
|
||||||
let listener = listener
|
let listener = listener
|
||||||
@ -335,7 +335,7 @@ mod tests {
|
|||||||
.into_new_address()
|
.into_new_address()
|
||||||
.expect("listen address");
|
.expect("listen address");
|
||||||
|
|
||||||
assert_eq!(Some(Protocol::Ws), addr.iter().nth(2));
|
assert_eq!(Some(Protocol::Ws("/".into())), addr.iter().nth(2));
|
||||||
assert_ne!(Some(Protocol::Tcp(0)), addr.iter().nth(1));
|
assert_ne!(Some(Protocol::Tcp(0)), addr.iter().nth(1));
|
||||||
|
|
||||||
let listener = listener
|
let listener = listener
|
||||||
|
Loading…
x
Reference in New Issue
Block a user