mirror of
https://github.com/fluencelabs/rust-libp2p
synced 2025-06-29 09:41:34 +00:00
multiaddr: add support for onion protocol. (#542)
* multiaddr: add support for onion protocol. * Comment `read_onion`. * Split onion into address and port parts.
This commit is contained in:
committed by
Pierre Krieger
parent
d81f4e264f
commit
e05422c05f
@ -9,8 +9,10 @@ readme = "README.md"
|
|||||||
version = "0.3.0"
|
version = "0.3.0"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
|
arrayref = "0.3"
|
||||||
bs58 = "0.2.0"
|
bs58 = "0.2.0"
|
||||||
byteorder = "0.4"
|
byteorder = "0.4"
|
||||||
|
data-encoding = "2.1"
|
||||||
multihash = { path = "../multihash" }
|
multihash = { path = "../multihash" }
|
||||||
serde = "1.0.70"
|
serde = "1.0.70"
|
||||||
unsigned-varint = "0.1"
|
unsigned-varint = "0.1"
|
||||||
|
@ -3,8 +3,11 @@
|
|||||||
///! Implementation of [multiaddr](https://github.com/jbenet/multiaddr)
|
///! Implementation of [multiaddr](https://github.com/jbenet/multiaddr)
|
||||||
///! in Rust.
|
///! in Rust.
|
||||||
|
|
||||||
|
#[macro_use]
|
||||||
|
extern crate arrayref;
|
||||||
extern crate bs58;
|
extern crate bs58;
|
||||||
extern crate byteorder;
|
extern crate byteorder;
|
||||||
|
extern crate data_encoding;
|
||||||
extern crate serde;
|
extern crate serde;
|
||||||
extern crate unsigned_varint;
|
extern crate unsigned_varint;
|
||||||
pub extern crate multihash;
|
pub extern crate multihash;
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
use bs58;
|
use bs58;
|
||||||
use byteorder::{BigEndian, ReadBytesExt, WriteBytesExt};
|
use byteorder::{BigEndian, ByteOrder, ReadBytesExt, WriteBytesExt};
|
||||||
|
use data_encoding::BASE32;
|
||||||
use multihash::Multihash;
|
use multihash::Multihash;
|
||||||
use std::{
|
use std::{
|
||||||
borrow::Cow,
|
borrow::Cow,
|
||||||
@ -50,7 +51,7 @@ pub enum Protocol<'a> {
|
|||||||
P2pWebRtcStar,
|
P2pWebRtcStar,
|
||||||
P2pWebSocketStar,
|
P2pWebSocketStar,
|
||||||
Memory,
|
Memory,
|
||||||
Onion(Cow<'a, [u8]>),
|
Onion(Cow<'a, [u8; 10]>, u16),
|
||||||
P2p(Multihash),
|
P2p(Multihash),
|
||||||
P2pCircuit,
|
P2pCircuit,
|
||||||
Quic,
|
Quic,
|
||||||
@ -121,7 +122,11 @@ impl<'a> Protocol<'a> {
|
|||||||
}
|
}
|
||||||
"http" => Ok(Protocol::Http),
|
"http" => Ok(Protocol::Http),
|
||||||
"https" => Ok(Protocol::Https),
|
"https" => Ok(Protocol::Https),
|
||||||
"onion" => unimplemented!(), // FIXME
|
"onion" =>
|
||||||
|
iter.next()
|
||||||
|
.ok_or(Error::InvalidProtocolString)
|
||||||
|
.and_then(|s| read_onion(&s.to_uppercase()))
|
||||||
|
.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),
|
||||||
"wss" => Ok(Protocol::Wss),
|
"wss" => Ok(Protocol::Wss),
|
||||||
@ -191,7 +196,11 @@ impl<'a> Protocol<'a> {
|
|||||||
P2P_WEBRTC_STAR => Ok((Protocol::P2pWebRtcStar, input)),
|
P2P_WEBRTC_STAR => Ok((Protocol::P2pWebRtcStar, input)),
|
||||||
P2P_WEBSOCKET_STAR => Ok((Protocol::P2pWebSocketStar, input)),
|
P2P_WEBSOCKET_STAR => Ok((Protocol::P2pWebSocketStar, input)),
|
||||||
MEMORY => Ok((Protocol::Memory, input)),
|
MEMORY => Ok((Protocol::Memory, input)),
|
||||||
ONION => unimplemented!(), // FIXME
|
ONION => {
|
||||||
|
let (data, rest) = split_at(12, input)?;
|
||||||
|
let port = BigEndian::read_u16(&data[10 ..]);
|
||||||
|
Ok((Protocol::Onion(Cow::Borrowed(array_ref!(data, 0, 10)), port), rest))
|
||||||
|
}
|
||||||
P2P => {
|
P2P => {
|
||||||
let (n, input) = decode::usize(input)?;
|
let (n, input) = decode::usize(input)?;
|
||||||
let (data, rest) = split_at(n, input)?;
|
let (data, rest) = split_at(n, input)?;
|
||||||
@ -285,7 +294,11 @@ impl<'a> Protocol<'a> {
|
|||||||
w.write_all(encode::usize(bytes.len(), &mut encode::usize_buffer()))?;
|
w.write_all(encode::usize(bytes.len(), &mut encode::usize_buffer()))?;
|
||||||
w.write_all(&bytes)?
|
w.write_all(&bytes)?
|
||||||
}
|
}
|
||||||
Protocol::Onion(_) => unimplemented!(), // FIXME
|
Protocol::Onion(addr, port) => {
|
||||||
|
w.write_all(encode::u32(ONION, &mut buf))?;
|
||||||
|
w.write_all(addr.as_ref())?;
|
||||||
|
w.write_u16::<BigEndian>(*port)?
|
||||||
|
}
|
||||||
Protocol::Quic => w.write_all(encode::u32(QUIC, &mut buf))?,
|
Protocol::Quic => w.write_all(encode::u32(QUIC, &mut buf))?,
|
||||||
Protocol::Utp => w.write_all(encode::u32(UTP, &mut buf))?,
|
Protocol::Utp => w.write_all(encode::u32(UTP, &mut buf))?,
|
||||||
Protocol::Udt => w.write_all(encode::u32(UDT, &mut buf))?,
|
Protocol::Udt => w.write_all(encode::u32(UDT, &mut buf))?,
|
||||||
@ -317,7 +330,7 @@ impl<'a> Protocol<'a> {
|
|||||||
P2pWebRtcStar => P2pWebRtcStar,
|
P2pWebRtcStar => P2pWebRtcStar,
|
||||||
P2pWebSocketStar => P2pWebSocketStar,
|
P2pWebSocketStar => P2pWebSocketStar,
|
||||||
Memory => Memory,
|
Memory => Memory,
|
||||||
Onion(cow) => Onion(Cow::Owned(cow.into_owned())),
|
Onion(addr, port) => Onion(Cow::Owned(addr.into_owned()), port),
|
||||||
P2p(a) => P2p(a),
|
P2p(a) => P2p(a),
|
||||||
P2pCircuit => P2pCircuit,
|
P2pCircuit => P2pCircuit,
|
||||||
Quic => Quic,
|
Quic => Quic,
|
||||||
@ -348,7 +361,10 @@ impl<'a> fmt::Display for Protocol<'a> {
|
|||||||
P2pWebRtcStar => f.write_str("/p2p-webrtc-star"),
|
P2pWebRtcStar => f.write_str("/p2p-webrtc-star"),
|
||||||
P2pWebSocketStar => f.write_str("/p2p-websocket-star"),
|
P2pWebSocketStar => f.write_str("/p2p-websocket-star"),
|
||||||
Memory => f.write_str("/memory"),
|
Memory => f.write_str("/memory"),
|
||||||
Onion(_) => unimplemented!(), // FIXME!
|
Onion(addr, port) => {
|
||||||
|
let s = BASE32.encode(addr.as_ref());
|
||||||
|
write!(f, "/onion/{}:{}", s.to_lowercase(), port)
|
||||||
|
}
|
||||||
P2p(c) => write!(f, "/p2p/{}", bs58::encode(c.as_bytes()).into_string()),
|
P2p(c) => write!(f, "/p2p/{}", bs58::encode(c.as_bytes()).into_string()),
|
||||||
P2pCircuit => f.write_str("/p2p-circuit"),
|
P2pCircuit => f.write_str("/p2p-circuit"),
|
||||||
Quic => f.write_str("/quic"),
|
Quic => f.write_str("/quic"),
|
||||||
@ -378,3 +394,35 @@ impl<'a> From<Ipv6Addr> for Protocol<'a> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Parse a version 2 onion address and return its binary representation.
|
||||||
|
//
|
||||||
|
// Format: <base-32 address> ":" <port number>
|
||||||
|
fn read_onion(s: &str) -> Result<([u8; 10], u16)> {
|
||||||
|
let mut parts = s.split(':');
|
||||||
|
|
||||||
|
// address part (without ".onion")
|
||||||
|
let b32 = parts.next().ok_or(Error::InvalidMultiaddr)?;
|
||||||
|
if b32.len() != 16 {
|
||||||
|
return Err(Error::InvalidMultiaddr)
|
||||||
|
}
|
||||||
|
|
||||||
|
// port number
|
||||||
|
let port = parts.next()
|
||||||
|
.ok_or(Error::InvalidMultiaddr)
|
||||||
|
.and_then(|p| str::parse(p).map_err(From::from))?;
|
||||||
|
|
||||||
|
// nothing else expected
|
||||||
|
if parts.next().is_some() {
|
||||||
|
return Err(Error::InvalidMultiaddr)
|
||||||
|
}
|
||||||
|
|
||||||
|
if 10 != BASE32.decode_len(b32.len()).map_err(|_| Error::InvalidMultiaddr)? {
|
||||||
|
return Err(Error::InvalidMultiaddr)
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut buf = [0u8; 10];
|
||||||
|
BASE32.decode_mut(b32.as_bytes(), &mut buf).map_err(|_| Error::InvalidMultiaddr)?;
|
||||||
|
|
||||||
|
Ok((buf, port))
|
||||||
|
}
|
||||||
|
|
||||||
|
@ -59,7 +59,7 @@ struct Proto(Protocol<'static>);
|
|||||||
impl Arbitrary for Proto {
|
impl Arbitrary for Proto {
|
||||||
fn arbitrary<G: Gen>(g: &mut G) -> Self {
|
fn arbitrary<G: Gen>(g: &mut G) -> Self {
|
||||||
use Protocol::*;
|
use Protocol::*;
|
||||||
match g.gen_range(0, 22) { // TODO: Add Protocol::Quic
|
match g.gen_range(0, 23) { // TODO: Add Protocol::Quic
|
||||||
0 => Proto(Dccp(g.gen())),
|
0 => Proto(Dccp(g.gen())),
|
||||||
1 => Proto(Dns4(Cow::Owned(SubString::arbitrary(g).0))),
|
1 => Proto(Dns4(Cow::Owned(SubString::arbitrary(g).0))),
|
||||||
2 => Proto(Dns6(Cow::Owned(SubString::arbitrary(g).0))),
|
2 => Proto(Dns6(Cow::Owned(SubString::arbitrary(g).0))),
|
||||||
@ -83,6 +83,11 @@ impl Arbitrary for Proto {
|
|||||||
19 => Proto(Utp),
|
19 => Proto(Utp),
|
||||||
20 => Proto(Ws),
|
20 => Proto(Ws),
|
||||||
21 => Proto(Wss),
|
21 => Proto(Wss),
|
||||||
|
22 => {
|
||||||
|
let mut a = [0; 10];
|
||||||
|
g.fill(&mut a);
|
||||||
|
Proto(Onion(Cow::Owned(a), g.gen()))
|
||||||
|
}
|
||||||
_ => panic!("outside range")
|
_ => panic!("outside range")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user