Skip to content

Commit a4a4fbd

Browse files
authored
Merge pull request #115 from p2p-industries/master
Implement http-path protocol
2 parents fe847fa + 4281ba3 commit a4a4fbd

File tree

2 files changed

+49
-1
lines changed

2 files changed

+49
-1
lines changed

src/protocol.rs

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@ const GARLIC32: u32 = 447;
5858
const SNI: u32 = 449;
5959
const P2P_STARDUST: u32 = 277; // Deprecated
6060
const WEBRTC: u32 = 281;
61+
const HTTP_PATH: u32 = 481;
6162

6263
/// Type-alias for how multi-addresses use `Multihash`.
6364
///
@@ -128,6 +129,7 @@ pub enum Protocol<'a> {
128129
Sni(Cow<'a, str>),
129130
P2pStardust,
130131
WebRTC,
132+
HttpPath(Cow<'a, str>),
131133
}
132134

133135
impl<'a> Protocol<'a> {
@@ -276,6 +278,11 @@ impl<'a> Protocol<'a> {
276278
}
277279
"p2p-stardust" => Ok(Protocol::P2pStardust),
278280
"webrtc" => Ok(Protocol::WebRTC),
281+
"http-path" => {
282+
let s = iter.next().ok_or(Error::InvalidProtocolString)?;
283+
let decoded = percent_encoding::percent_decode(s.as_bytes()).decode_utf8()?;
284+
Ok(Protocol::HttpPath(decoded))
285+
}
279286
unknown => Err(Error::UnknownProtocolString(unknown.to_string())),
280287
}
281288
}
@@ -457,6 +464,14 @@ impl<'a> Protocol<'a> {
457464
}
458465
P2P_STARDUST => Ok((Protocol::P2pStardust, input)),
459466
WEBRTC => Ok((Protocol::WebRTC, input)),
467+
HTTP_PATH => {
468+
let (n, input) = decode::usize(input)?;
469+
let (data, rest) = split_at(n, input)?;
470+
Ok((
471+
Protocol::HttpPath(Cow::Borrowed(str::from_utf8(data)?)),
472+
rest,
473+
))
474+
}
460475
_ => Err(Error::UnknownProtocolId(id)),
461476
}
462477
}
@@ -604,6 +619,12 @@ impl<'a> Protocol<'a> {
604619
}
605620
Protocol::P2pStardust => w.write_all(encode::u32(P2P_STARDUST, &mut buf))?,
606621
Protocol::WebRTC => w.write_all(encode::u32(WEBRTC, &mut buf))?,
622+
Protocol::HttpPath(s) => {
623+
w.write_all(encode::u32(HTTP_PATH, &mut buf))?;
624+
let bytes = s.as_bytes();
625+
w.write_all(encode::usize(bytes.len(), &mut encode::usize_buffer()))?;
626+
w.write_all(bytes)?
627+
}
607628
}
608629
Ok(())
609630
}
@@ -651,6 +672,7 @@ impl<'a> Protocol<'a> {
651672
Sni(cow) => Sni(Cow::Owned(cow.into_owned())),
652673
P2pStardust => P2pStardust,
653674
WebRTC => WebRTC,
675+
HttpPath(cow) => HttpPath(Cow::Owned(cow.into_owned())),
654676
}
655677
}
656678

@@ -698,6 +720,7 @@ impl<'a> Protocol<'a> {
698720
Sni(_) => "sni",
699721
P2pStardust => "p2p-stardust",
700722
WebRTC => "webrtc",
723+
HttpPath(_) => "http-path",
701724
}
702725
}
703726
}
@@ -755,6 +778,11 @@ impl<'a> fmt::Display for Protocol<'a> {
755778
),
756779
Garlic32(addr) => write!(f, "/{}", multibase::Base::Base32Lower.encode(addr)),
757780
Sni(s) => write!(f, "/{s}"),
781+
HttpPath(s) => {
782+
let encoded =
783+
percent_encoding::percent_encode(s.as_bytes(), PATH_SEGMENT_ENCODE_SET);
784+
write!(f, "/{encoded}")
785+
}
758786
_ => Ok(()),
759787
}
760788
}

tests/lib.rs

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,7 @@ impl Arbitrary for Ma {
8484
struct Proto(Protocol<'static>);
8585

8686
impl Proto {
87-
const IMPL_VARIANT_COUNT: u8 = 39;
87+
const IMPL_VARIANT_COUNT: u8 = 40;
8888
}
8989

9090
impl Arbitrary for Proto {
@@ -160,6 +160,7 @@ impl Arbitrary for Proto {
160160
36 => Proto(Sni(Cow::Owned(SubString::arbitrary(g).0))),
161161
37 => Proto(P2pStardust),
162162
38 => Proto(WebRTC),
163+
39 => Proto(HttpPath(Cow::Owned(SubString::arbitrary(g).0))),
163164
_ => panic!("outside range"),
164165
}
165166
}
@@ -290,6 +291,21 @@ fn construct_success() {
290291
"0604D2C003E003",
291292
vec![Tcp(1234), Tls, Http],
292293
);
294+
ma_valid(
295+
"/tcp/1234/http/http-path/user",
296+
"0604D2E003E1030475736572",
297+
vec![Tcp(1234), Http, HttpPath(Cow::Borrowed("user"))],
298+
);
299+
ma_valid(
300+
"/tcp/1234/http/http-path/api%2Fv0%2Flogin",
301+
"0604D2E003E1030C6170692F76302F6C6F67696E",
302+
vec![Tcp(1234), Http, HttpPath(Cow::Borrowed("api/v0/login"))],
303+
);
304+
ma_valid(
305+
"/tcp/1234/http/http-path/a%2520space",
306+
"0604D2E003E10309612532307370616365",
307+
vec![Tcp(1234), Http, HttpPath(Cow::Borrowed("a%20space"))],
308+
);
293309
ma_valid("/tcp/1234/https", "0604D2BB03", vec![Tcp(1234), Https]);
294310
ma_valid(
295311
"/p2p/QmcgpsyWgH8Y8ajJz1Cu72KnS5uo2Aa2LpzU7kinSupNKC/tcp/1234",
@@ -518,6 +534,7 @@ fn construct_fail() {
518534
"/p2p-circuit/50",
519535
"/ip4/127.0.0.1/udp/1234/webrtc-direct/certhash",
520536
"/ip4/127.0.0.1/udp/1234/webrtc-direct/certhash/b2uaraocy6yrdblb4sfptaddgimjmmp", // 1 character missing from certhash
537+
"/tcp/1234/http/http-path/a/b",
521538
];
522539

523540
for address in &addresses {
@@ -672,6 +689,9 @@ fn protocol_stack() {
672689
"/udp/1234/utp",
673690
"/tcp/1234/http",
674691
"/tcp/1234/tls/http",
692+
"/tcp/1234/http/http-path/user",
693+
"/tcp/1234/http/http-path/api%2Fv1%2Flogin",
694+
"/tcp/1234/http/http-path/a%20space",
675695
"/tcp/1234/https",
676696
"/p2p/QmcgpsyWgH8Y8ajJz1Cu72KnS5uo2Aa2LpzU7kinSupNKC/tcp/1234",
677697
"/ip4/127.0.0.1/udp/1234",

0 commit comments

Comments
 (0)