#[cfg(feature = "alloc")]
use alloc::prelude::v1::*;
use byteorder::{ByteOrder, NetworkEndian};
use crate::base::{Encode, Parse};
use crate::types::{
Address, AddressV4, AddressV6, DateTime, Id, ImmutableData, Ip, PublicKey, Signature, ID_LEN,
PUBLIC_KEY_LEN, SIGNATURE_LEN,
};
mod helpers;
#[derive(PartialEq, Debug, Clone)]
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
pub enum Options {
None,
PubKey(PubKey),
PeerId(PeerId),
PrevSig(PrevSig),
Kind(Kind),
Name(Name),
IPv4(AddressV4),
IPv6(AddressV6),
Issued(Issued),
Expiry(Expiry),
Limit(Limit),
Metadata(Metadata),
}
#[derive(PartialEq, Debug, Clone)]
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
pub enum OptionsList<C: AsRef<[Options]>, E: ImmutableData> {
Cleartext(C),
Encrypted(E),
None,
}
#[derive(PartialEq, Debug, Clone)]
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
pub enum OptionsError {
IO,
InvalidMetadata,
InvalidOptionLength,
InvalidOptionKind,
Unimplemented,
}
#[cfg(feature = "std")]
impl From<std::io::Error> for OptionsError {
fn from(e: std::io::Error) -> OptionsError {
error!("io error: {}", e);
OptionsError::IO
}
}
pub struct OptionsIter<T> {
index: usize,
buff: T,
}
impl<T> OptionsIter<T>
where
T: AsRef<[u8]>,
{
pub(crate) fn new(buff: T) -> Self {
Self { index: 0, buff }
}
}
impl<T> Iterator for OptionsIter<T>
where
T: AsRef<[u8]>,
{
type Item = Options;
fn next(&mut self) -> Option<Options> {
let rem = &self.buff.as_ref()[self.index..];
if rem.len() < OPTION_HEADER_LEN {
return None;
}
let (o, n) = match Options::parse(&rem) {
Ok(v) => v,
Err(e) => {
error!("Option parsing error: {:?}", e);
return None;
}
};
self.index += n;
Some(o)
}
}
pub mod option_kinds {
pub const PUBKEY: u16 = 0x0000;
pub const PEER_ID: u16 = 0x0001;
pub const PREV_SIG: u16 = 0x0002;
pub const KIND: u16 = 0x0003;
pub const NAME: u16 = 0x0004;
pub const ADDR_IPV4: u16 = 0x0005;
pub const ADDR_IPV6: u16 = 0x0006;
pub const ISSUED: u16 = 0x0007;
pub const EXPIRY: u16 = 0x0008;
pub const LIMIT: u16 = 0x0009;
pub const META: u16 = 0x000a;
pub const APP: u16 = 0x8000;
}
const OPTION_HEADER_LEN: usize = 4;
impl Options {
pub fn parse_vec(data: &[u8]) -> Result<(Vec<Options>, usize), OptionsError> {
let mut options = Vec::new();
let mut rem = &data[..];
let mut i = 0;
while rem.len() >= OPTION_HEADER_LEN {
let (o, n) = Options::parse(&rem)?;
i += n;
options.push(o);
rem = &data[i..];
}
Ok((options, i))
}
pub fn encode_vec(options: &[Options], data: &mut [u8]) -> Result<usize, OptionsError> {
let mut i = 0;
for o in options.iter() {
i += o.encode(&mut data[i..])?;
}
Ok(i)
}
}
impl Options {
pub fn name(value: &str) -> Options {
Options::Name(Name::new(value))
}
pub fn kind(value: &str) -> Options {
Options::Kind(Kind::new(value))
}
pub fn prev_sig(value: &Signature) -> Options {
Options::PrevSig(PrevSig::new(value.clone()))
}
pub fn meta(key: &str, value: &str) -> Options {
Options::Metadata(Metadata::new(key, value))
}
pub fn issued<T: Into<DateTime>>(now: T) -> Options {
Options::Issued(Issued::new(now))
}
pub fn expiry<T: Into<DateTime>>(when: T) -> Options {
Options::Expiry(Expiry::new(when))
}
pub fn peer_id(id: Id) -> Options {
Options::PeerId(PeerId::new(id))
}
pub fn public_key(public_key: PublicKey) -> Options {
Options::PubKey(PubKey::new(public_key))
}
pub fn address<T: Into<Address>>(address: T) -> Options {
let addr: Address = address.into();
match addr.ip {
Ip::V4(ip) => Options::IPv4(AddressV4::new(ip, addr.port)),
Ip::V6(ip) => Options::IPv6(AddressV6::new(ip, addr.port)),
}
}
pub fn address_v4<T: Into<AddressV4>>(address: T) -> Options {
Options::IPv4(address.into())
}
pub fn address_v6<T: Into<AddressV6>>(address: T) -> Options {
Options::IPv6(address.into())
}
pub fn pub_key(public_key: PublicKey) -> Options {
Options::PubKey(PubKey::new(public_key))
}
}
impl Parse for Options {
type Output = Options;
type Error = OptionsError;
fn parse<'a>(data: &'a [u8]) -> Result<(Self::Output, usize), Self::Error> {
if data.len() < OPTION_HEADER_LEN {
return Err(OptionsError::InvalidOptionLength);
}
let option_kind = NetworkEndian::read_u16(&data[0..2]);
let option_len = NetworkEndian::read_u16(&data[2..4]) as usize;
let d = &data[OPTION_HEADER_LEN..OPTION_HEADER_LEN + option_len];
match option_kind {
option_kinds::PUBKEY => {
let (opt, n) = PubKey::parse(d)?;
Ok((Options::PubKey(opt), n + OPTION_HEADER_LEN))
}
option_kinds::PEER_ID => {
let (opt, n) = PeerId::parse(d)?;
Ok((Options::PeerId(opt), n + OPTION_HEADER_LEN))
}
option_kinds::PREV_SIG => {
let (opt, n) = PrevSig::parse(d)?;
Ok((Options::PrevSig(opt), n + OPTION_HEADER_LEN))
}
option_kinds::KIND => {
let (opt, n) = Kind::parse(d)?;
Ok((Options::Kind(opt), n + OPTION_HEADER_LEN))
}
option_kinds::NAME => {
let (opt, n) = Name::parse(d)?;
Ok((Options::Name(opt), n + OPTION_HEADER_LEN))
}
option_kinds::ADDR_IPV4 => {
let (opt, n) = AddressV4::parse(d)?;
Ok((Options::IPv4(opt), n + OPTION_HEADER_LEN))
}
option_kinds::ADDR_IPV6 => {
let (opt, n) = AddressV6::parse(d)?;
Ok((Options::IPv6(opt), n + OPTION_HEADER_LEN))
}
option_kinds::META => {
let (opt, n) = Metadata::parse(d)?;
Ok((Options::Metadata(opt), n + OPTION_HEADER_LEN))
}
option_kinds::ISSUED => {
let (opt, n) = Issued::parse(d)?;
Ok((Options::Issued(opt), n + OPTION_HEADER_LEN))
}
option_kinds::EXPIRY => {
let (opt, n) = Expiry::parse(d)?;
Ok((Options::Expiry(opt), n + OPTION_HEADER_LEN))
}
option_kinds::LIMIT => {
let (opt, n) = Limit::parse(d)?;
Ok((Options::Limit(opt), n + OPTION_HEADER_LEN))
}
_ => {
Ok((Options::None, OPTION_HEADER_LEN + option_len))
}
}
}
}
impl Encode for Options {
type Error = OptionsError;
fn encode(&self, data: &mut [u8]) -> Result<usize, Self::Error> {
match *self {
Options::PubKey(ref o) => Ok(o.encode(data)?),
Options::PeerId(ref o) => Ok(o.encode(data)?),
Options::PrevSig(ref o) => Ok(o.encode(data)?),
Options::Kind(ref o) => Ok(o.encode(data)?),
Options::Name(ref o) => Ok(o.encode(data)?),
Options::IPv4(ref o) => Ok(o.encode(data)?),
Options::IPv6(ref o) => Ok(o.encode(data)?),
Options::Metadata(ref o) => Ok(o.encode(data)?),
Options::Issued(ref o) => Ok(o.encode(data)?),
Options::Expiry(ref o) => Ok(o.encode(data)?),
Options::Limit(ref o) => Ok(o.encode(data)?),
_ => {
warn!("Option encoding not implemented for object {:?}", *self);
unimplemented!();
}
}
}
}
#[derive(PartialEq, Debug, Clone)]
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
pub struct PubKey {
pub public_key: PublicKey,
}
impl PubKey {
pub fn new(public_key: PublicKey) -> PubKey {
PubKey { public_key }
}
}
impl Parse for PubKey {
type Output = PubKey;
type Error = OptionsError;
fn parse(data: &[u8]) -> Result<(Self::Output, usize), Self::Error> {
let mut public_key = [0u8; PUBLIC_KEY_LEN];
public_key.copy_from_slice(&data[..PUBLIC_KEY_LEN]);
Ok((
PubKey {
public_key: public_key.into(),
},
PUBLIC_KEY_LEN,
))
}
}
impl Encode for PubKey {
type Error = OptionsError;
fn encode(&self, data: &mut [u8]) -> Result<usize, Self::Error> {
NetworkEndian::write_u16(&mut data[0..2], option_kinds::PUBKEY);
NetworkEndian::write_u16(&mut data[2..4], PUBLIC_KEY_LEN as u16);
&mut data[OPTION_HEADER_LEN..OPTION_HEADER_LEN + PUBLIC_KEY_LEN]
.copy_from_slice(&self.public_key);
Ok(OPTION_HEADER_LEN + PUBLIC_KEY_LEN)
}
}
#[derive(PartialEq, Debug, Clone)]
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
pub struct PeerId {
pub peer_id: Id,
}
impl PeerId {
pub fn new(peer_id: Id) -> PeerId {
PeerId { peer_id }
}
}
impl Parse for PeerId {
type Output = PeerId;
type Error = OptionsError;
fn parse(data: &[u8]) -> Result<(Self::Output, usize), Self::Error> {
let mut peer_id = [0u8; ID_LEN];
peer_id.copy_from_slice(&data[..ID_LEN]);
Ok((
PeerId {
peer_id: peer_id.into(),
},
ID_LEN,
))
}
}
impl Encode for PeerId {
type Error = OptionsError;
fn encode(&self, data: &mut [u8]) -> Result<usize, Self::Error> {
NetworkEndian::write_u16(&mut data[0..2], option_kinds::PEER_ID);
NetworkEndian::write_u16(&mut data[2..4], ID_LEN as u16);
&mut data[OPTION_HEADER_LEN..OPTION_HEADER_LEN + ID_LEN].copy_from_slice(&self.peer_id);
Ok(OPTION_HEADER_LEN + ID_LEN)
}
}
#[derive(PartialEq, Debug, Clone)]
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
pub struct PrevSig {
pub sig: Signature,
}
impl PrevSig {
pub fn new(sig: Signature) -> Self {
Self { sig }
}
}
impl Parse for PrevSig {
type Output = Self;
type Error = OptionsError;
fn parse(data: &[u8]) -> Result<(Self::Output, usize), Self::Error> {
let mut sig = [0u8; SIGNATURE_LEN];
sig.copy_from_slice(&data[..SIGNATURE_LEN]);
Ok((Self { sig: sig.into() }, SIGNATURE_LEN))
}
}
impl Encode for PrevSig {
type Error = OptionsError;
fn encode(&self, data: &mut [u8]) -> Result<usize, Self::Error> {
NetworkEndian::write_u16(&mut data[0..2], option_kinds::PREV_SIG);
NetworkEndian::write_u16(&mut data[2..4], SIGNATURE_LEN as u16);
&mut data[OPTION_HEADER_LEN..OPTION_HEADER_LEN + SIGNATURE_LEN].copy_from_slice(&self.sig);
Ok(OPTION_HEADER_LEN + SIGNATURE_LEN)
}
}
#[derive(PartialEq, Debug, Clone)]
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
pub struct Kind {
value: String,
}
impl Kind {
pub fn new(value: &str) -> Kind {
Kind {
value: value.to_owned(),
}
}
}
impl Parse for Kind {
type Output = Kind;
type Error = OptionsError;
fn parse(data: &[u8]) -> Result<(Self::Output, usize), Self::Error> {
let value = core::str::from_utf8(&data).unwrap().to_owned();
Ok((Kind { value }, data.len()))
}
}
impl Encode for Kind {
type Error = OptionsError;
fn encode(&self, data: &mut [u8]) -> Result<usize, Self::Error> {
let value = self.value.as_bytes();
NetworkEndian::write_u16(&mut data[0..2], option_kinds::KIND);
NetworkEndian::write_u16(&mut data[2..4], value.len() as u16);
&mut data[OPTION_HEADER_LEN..OPTION_HEADER_LEN + value.len()].copy_from_slice(&value);
Ok(OPTION_HEADER_LEN + value.len())
}
}
#[derive(PartialEq, Debug, Clone)]
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
pub struct Name {
value: String,
}
impl Name {
pub fn new(value: &str) -> Name {
Name {
value: value.to_owned(),
}
}
}
impl Parse for Name {
type Output = Name;
type Error = OptionsError;
fn parse(data: &[u8]) -> Result<(Self::Output, usize), Self::Error> {
let value = core::str::from_utf8(&data).unwrap().to_owned();
Ok((Name { value }, data.len()))
}
}
impl Encode for Name {
type Error = OptionsError;
fn encode(&self, data: &mut [u8]) -> Result<usize, Self::Error> {
NetworkEndian::write_u16(&mut data[0..2], option_kinds::NAME);
NetworkEndian::write_u16(&mut data[2..4], self.value.len() as u16);
&mut data[OPTION_HEADER_LEN..OPTION_HEADER_LEN + self.value.len()]
.copy_from_slice(&self.value.as_bytes());
Ok(OPTION_HEADER_LEN + self.value.len())
}
}
impl Parse for AddressV4 {
type Output = AddressV4;
type Error = OptionsError;
fn parse(data: &[u8]) -> Result<(Self::Output, usize), Self::Error> {
let mut ip = [0u8; 4];
ip.copy_from_slice(&data[0..4]);
let port = NetworkEndian::read_u16(&data[4..6]);
Ok((AddressV4::new(ip, port), 6))
}
}
impl Encode for AddressV4 {
type Error = OptionsError;
fn encode(&self, data: &mut [u8]) -> Result<usize, Self::Error> {
NetworkEndian::write_u16(&mut data[0..2], option_kinds::ADDR_IPV4);
NetworkEndian::write_u16(&mut data[2..4], 6);
&mut data[OPTION_HEADER_LEN..OPTION_HEADER_LEN + 4].copy_from_slice(&self.ip);
NetworkEndian::write_u16(&mut data[OPTION_HEADER_LEN + 4..], self.port);
Ok(OPTION_HEADER_LEN + 6)
}
}
impl Parse for AddressV6 {
type Output = AddressV6;
type Error = OptionsError;
fn parse(data: &[u8]) -> Result<(Self::Output, usize), Self::Error> {
let mut ip = [0u8; 16];
ip.copy_from_slice(&data[0..16]);
let port = NetworkEndian::read_u16(&data[16..18]);
Ok((AddressV6::new(ip, port), 18))
}
}
impl Encode for AddressV6 {
type Error = OptionsError;
fn encode(&self, data: &mut [u8]) -> Result<usize, Self::Error> {
NetworkEndian::write_u16(&mut data[0..2], option_kinds::ADDR_IPV6);
NetworkEndian::write_u16(&mut data[2..4], 18);
&mut data[OPTION_HEADER_LEN..OPTION_HEADER_LEN + 16].copy_from_slice(&self.ip);
NetworkEndian::write_u16(&mut data[OPTION_HEADER_LEN + 16..], self.port);
Ok(OPTION_HEADER_LEN + 18)
}
}
#[derive(PartialEq, Debug, Clone)]
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
pub struct Metadata {
key: String,
value: String,
}
impl Metadata {
pub fn new(key: &str, value: &str) -> Metadata {
Metadata {
key: key.to_owned(),
value: value.to_owned(),
}
}
}
impl Parse for Metadata {
type Output = Metadata;
type Error = OptionsError;
fn parse(data: &[u8]) -> Result<(Self::Output, usize), Self::Error> {
let kv = core::str::from_utf8(&data).unwrap().to_owned();
let split: Vec<_> = kv.split("|").collect();
if split.len() != 2 {
return Err(OptionsError::InvalidMetadata);
}
Ok((
Metadata {
key: split[0].to_owned(),
value: split[1].to_owned(),
},
data.len(),
))
}
}
impl Encode for Metadata {
type Error = OptionsError;
fn encode(&self, data: &mut [u8]) -> Result<usize, Self::Error> {
let meta = format!("{}|{}", self.key, self.value);
NetworkEndian::write_u16(&mut data[0..2], option_kinds::META);
NetworkEndian::write_u16(&mut data[2..4], meta.len() as u16);
&mut data[OPTION_HEADER_LEN..OPTION_HEADER_LEN + meta.len()]
.copy_from_slice(meta.as_bytes());
Ok(OPTION_HEADER_LEN + meta.len())
}
}
impl From<Metadata> for Options {
fn from(m: Metadata) -> Options {
Options::Metadata(m)
}
}
#[derive(PartialEq, Debug, Clone)]
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
pub struct Issued {
pub when: DateTime,
}
impl Issued {
pub fn new<T>(when: T) -> Issued
where
T: Into<DateTime>,
{
Issued { when: when.into() }
}
}
impl Parse for Issued {
type Output = Issued;
type Error = OptionsError;
fn parse<'a>(data: &'a [u8]) -> Result<(Self::Output, usize), Self::Error> {
let raw = NetworkEndian::read_u64(&data[0..8]);
let when = DateTime::from_secs(raw);
Ok((Issued { when }, 8))
}
}
impl Encode for Issued {
type Error = OptionsError;
fn encode(&self, data: &mut [u8]) -> Result<usize, Self::Error> {
NetworkEndian::write_u16(&mut data[0..2], option_kinds::ISSUED);
NetworkEndian::write_u16(&mut data[2..4], 8);
NetworkEndian::write_u64(&mut data[4..12], self.when.as_secs());
Ok(OPTION_HEADER_LEN + 8)
}
}
#[derive(PartialEq, Debug, Clone)]
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
pub struct Expiry {
pub when: DateTime,
}
impl Expiry {
pub fn new<T>(when: T) -> Expiry
where
T: Into<DateTime>,
{
Expiry { when: when.into() }
}
}
impl Parse for Expiry {
type Output = Expiry;
type Error = OptionsError;
fn parse<'a>(data: &'a [u8]) -> Result<(Self::Output, usize), Self::Error> {
let raw = NetworkEndian::read_u64(&data[0..8]);
let when = DateTime::from_secs(raw);
Ok((Expiry { when }, 8))
}
}
impl Encode for Expiry {
type Error = OptionsError;
fn encode(&self, data: &mut [u8]) -> Result<usize, Self::Error> {
NetworkEndian::write_u16(&mut data[0..2], option_kinds::EXPIRY);
NetworkEndian::write_u16(&mut data[2..4], 8);
NetworkEndian::write_u64(&mut data[4..12], self.when.as_secs());
Ok(OPTION_HEADER_LEN + 8)
}
}
#[derive(PartialEq, Debug, Clone)]
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
pub struct Limit {
pub n: u32,
}
impl Limit {
pub fn new(n: u32) -> Self {
Self { n }
}
}
impl Parse for Limit {
type Output = Self;
type Error = OptionsError;
fn parse(data: &[u8]) -> Result<(Self::Output, usize), Self::Error> {
Ok((
Self {
n: NetworkEndian::read_u32(data),
},
4,
))
}
}
impl Encode for Limit {
type Error = OptionsError;
fn encode(&self, data: &mut [u8]) -> Result<usize, Self::Error> {
NetworkEndian::write_u16(&mut data[0..2], option_kinds::LIMIT);
NetworkEndian::write_u16(&mut data[2..4], 4);
NetworkEndian::write_u32(&mut data[4..8], self.n);
Ok(8)
}
}
#[cfg(test)]
mod tests {
use super::*;
use std::net::{Ipv4Addr, Ipv6Addr, SocketAddrV4, SocketAddrV6};
use std::time::SystemTime;
#[test]
fn encode_decode_option_types() {
let tests = [
Options::PubKey(PubKey::new([1u8; PUBLIC_KEY_LEN].into())),
Options::PeerId(PeerId::new([2u8; ID_LEN].into())),
Options::Kind(Kind::new("test-kind")),
Options::Name(Name::new("test-name")),
Options::address_v4(SocketAddrV4::new(Ipv4Addr::new(127, 0, 0, 1), 8080)),
Options::address_v6(SocketAddrV6::new(
Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0, 1),
8080,
0,
0,
)),
Options::Metadata(Metadata::new("test-key", "test-value")),
Options::issued(SystemTime::now()),
Options::expiry(SystemTime::now()),
Options::Limit(Limit::new(13)),
];
for o in tests.iter() {
println!("Encode/Decode: {:?}", o);
let mut data = vec![0u8; 1024];
let n1 = o
.encode(&mut data)
.expect(&format!("Error encoding {:?}", o));
let (decoded, n2) = Options::parse(&data).expect(&format!("Error decoding {:?}", o));
assert_eq!(
n1, n2,
"Mismatch between encoded and decoded lengths for object: {:?}",
o
);
assert_eq!(o, &decoded, "Mismatch between original and decode objects");
}
}
#[test]
fn encode_decode_option_list() {
let tests = vec![
Options::PubKey(PubKey::new([1u8; PUBLIC_KEY_LEN].into())),
Options::PeerId(PeerId::new([2u8; ID_LEN].into())),
Options::PrevSig(PrevSig::new([3u8; SIGNATURE_LEN].into())),
Options::Kind(Kind::new("test-kind")),
Options::Name(Name::new("test-name")),
Options::address_v4(SocketAddrV4::new(Ipv4Addr::new(127, 0, 0, 1), 8080)),
Options::address_v6(SocketAddrV6::new(
Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0, 1),
8080,
0,
0,
)),
Options::Metadata(Metadata::new("test-key", "test-value")),
Options::issued(SystemTime::now()),
Options::expiry(SystemTime::now()),
];
let mut data = vec![0u8; 1024];
let n1 = Options::encode_vec(&tests, &mut data).expect("Error encoding options vector");
let encoded = &data[0..n1];
let (decoded, n2) = Options::parse_vec(encoded).expect("Error decoding options vector");
assert_eq!(n1, n2, "Mismatch between encoded and decoded length");
assert_eq!(
&tests, &decoded,
"Mismatch between original and decode vectors"
);
}
}