diff --git a/CHANGELOG.md b/CHANGELOG.md index 65e438e..b45e385 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,7 @@ +# 0.14.0 [unreleased] + +- Add support for TLS protocol (see [PR 48]). + # 0.13.0 [2021-07-08] - Update to multihash v0.14.0 (see [PR 44]). diff --git a/Cargo.toml b/Cargo.toml index 33cce4c..8162f62 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -7,7 +7,7 @@ keywords = ["multiaddr", "ipfs"] license = "MIT" name = "multiaddr" readme = "README.md" -version = "0.13.0" +version = "0.14.0" [features] default = ["url"] diff --git a/src/protocol.rs b/src/protocol.rs index 3749c58..e67d5e6 100644 --- a/src/protocol.rs +++ b/src/protocol.rs @@ -14,6 +14,9 @@ use std::{ use unsigned_varint::{encode, decode}; use crate::onion_addr::Onion3Addr; +// All the values are obtained by converting hexadecimal protocol codes to u32. +// Protocols as well as their corresponding codes are defined in +// https://github.com/multiformats/multiaddr/blob/master/protocols.csv . const DCCP: u32 = 33; const DNS: u32 = 53; const DNS4: u32 = 54; @@ -34,6 +37,7 @@ const P2P_CIRCUIT: u32 = 290; const QUIC: u32 = 460; const SCTP: u32 = 132; const TCP: u32 = 6; +const TLS: u32 = 448; const UDP: u32 = 273; const UDT: u32 = 301; const UNIX: u32 = 400; @@ -85,6 +89,7 @@ pub enum Protocol<'a> { Quic, Sctp(u16), Tcp(u16), + Tls, Udp(u16), Udt, Unix(Cow<'a, str>), @@ -113,6 +118,7 @@ impl<'a> Protocol<'a> { let s = iter.next().ok_or(Error::InvalidProtocolString)?; Ok(Protocol::Tcp(s.parse()?)) } + "tls" => Ok(Protocol::Tls), "udp" => { let s = iter.next().ok_or(Error::InvalidProtocolString)?; Ok(Protocol::Udp(s.parse()?)) @@ -294,6 +300,7 @@ impl<'a> Protocol<'a> { let num = rdr.read_u16::()?; Ok((Protocol::Tcp(num), rest)) } + TLS => Ok((Protocol::Tls, input)), UDP => { let (data, rest) = split_at(2, input)?; let mut rdr = Cursor::new(data); @@ -342,6 +349,7 @@ impl<'a> Protocol<'a> { w.write_all(encode::u32(TCP, &mut buf))?; w.write_u16::(*port)? } + Protocol::Tls => w.write_all(encode::u32(TLS, &mut buf))?, Protocol::Udp(port) => { w.write_all(encode::u32(UDP, &mut buf))?; w.write_u16::(*port)? @@ -455,6 +463,7 @@ impl<'a> Protocol<'a> { Quic => Quic, Sctp(a) => Sctp(a), Tcp(a) => Tcp(a), + Tls => Tls, Udp(a) => Udp(a), Udt => Udt, Unix(cow) => Unix(Cow::Owned(cow.into_owned())), @@ -495,6 +504,7 @@ impl<'a> fmt::Display for Protocol<'a> { Quic => f.write_str("/quic"), Sctp(port) => write!(f, "/sctp/{}", port), Tcp(port) => write!(f, "/tcp/{}", port), + Tls => write!(f, "/tls"), Udp(port) => write!(f, "/udp/{}", port), Udt => f.write_str("/udt"), Unix(s) => write!(f, "/unix/{}", s), diff --git a/tests/lib.rs b/tests/lib.rs index e079446..39ed765 100644 --- a/tests/lib.rs +++ b/tests/lib.rs @@ -86,7 +86,7 @@ struct Proto(Protocol<'static>); impl Arbitrary for Proto { fn arbitrary(g: &mut G) -> Self { use Protocol::*; - match u8::arbitrary(g) % 25 { // TODO: Add Protocol::Quic + match u8::arbitrary(g) % 26 { // TODO: Add Protocol::Quic 0 => Proto(Dccp(Arbitrary::arbitrary(g))), 1 => Proto(Dns(Cow::Owned(SubString::arbitrary(g).0))), 2 => Proto(Dns4(Cow::Owned(SubString::arbitrary(g).0))), @@ -128,6 +128,7 @@ impl Arbitrary for Proto { .unwrap(); Proto(Onion3((a, std::cmp::max(1, u16::arbitrary(g))).into())) }, + 25 => Proto(Tls), _ => panic!("outside range") } } @@ -200,6 +201,7 @@ fn construct_success() { ma_valid("/udp/1234/udt", "910204D2AD02", vec![Udp(1234), Udt]); ma_valid("/udp/1234/utp", "910204D2AE02", vec![Udp(1234), Utp]); ma_valid("/tcp/1234/http", "0604D2E003", vec![Tcp(1234), Http]); + ma_valid("/tcp/1234/tls/http", "0604D2C003E003", vec![Tcp(1234), Tls, Http]); ma_valid("/tcp/1234/https", "0604D2BB03", vec![Tcp(1234), Https]); ma_valid("/p2p/QmcgpsyWgH8Y8ajJz1Cu72KnS5uo2Aa2LpzU7kinSupNKC/tcp/1234", "A503221220D52EBB89D85B02A284948203A62FF28389C57C9F42BEEC4EC20DB76A68911C0B0604D2", @@ -252,6 +254,9 @@ fn construct_success() { "3819736A632D312E626F6F7473747261702E6C69627032702E696F0604D2A50322122006B3608AA000274049EB28AD8E793A26FF6FAB281A7D3BD77CD18EB745DFAABB", vec![Dnsaddr(Cow::Borrowed("sjc-1.bootstrap.libp2p.io")), Tcp(1234), P2p(multihash("QmNnooDu7bfjPFoTZYxMNLWUQJyrVwtbZg5gBMjTezGAJN"))] ); + ma_valid("/ip4/127.0.0.1/tcp/127/ws", "047F00000106007FDD03", vec![Ip4(local.clone()),Tcp(127),Ws("/".into())] ); + ma_valid("/ip4/127.0.0.1/tcp/127/tls", "047F00000106007FC003", vec![Ip4(local.clone()),Tcp(127),Tls] ); + ma_valid("/ip4/127.0.0.1/tcp/127/tls/ws", "047F00000106007FC003DD03", vec![Ip4(local.clone()),Tcp(127),Tls,Ws("/".into())] ); } #[test] @@ -320,9 +325,9 @@ fn from_bytes_fail() { #[test] fn ser_and_deser_json() { - let addr : Multiaddr = "/ip4/0.0.0.0/tcp/0".parse::().unwrap(); + let addr : Multiaddr = "/ip4/0.0.0.0/tcp/0/tls".parse::().unwrap(); let serialized = serde_json::to_string(&addr).unwrap(); - assert_eq!(serialized, "\"/ip4/0.0.0.0/tcp/0\""); + assert_eq!(serialized, "\"/ip4/0.0.0.0/tcp/0/tls\""); let deserialized: Multiaddr = serde_json::from_str(&serialized).unwrap(); assert_eq!(addr, deserialized); } @@ -330,10 +335,10 @@ fn ser_and_deser_json() { #[test] fn ser_and_deser_bincode() { - let addr : Multiaddr = "/ip4/0.0.0.0/tcp/0".parse::().unwrap(); + let addr : Multiaddr = "/ip4/0.0.0.0/tcp/0/tls".parse::().unwrap(); let serialized = bincode::serialize(&addr).unwrap(); // compact addressing - assert_eq!(serialized, vec![8, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 0, 6, 0, 0]); + assert_eq!(serialized, vec![10, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 0, 6, 0, 0, 192, 3]); let deserialized: Multiaddr = bincode::deserialize(&serialized).unwrap(); assert_eq!(addr, deserialized); }