mod addr;
mod contact;
mod link;
mod namespace;
mod peer;
mod recv;
mod send;
pub use addr::*;
use byteorder::{BigEndian, ByteOrder};
pub use contact::*;
pub use link::*;
pub use namespace::*;
pub use peer::*;
pub use recv::*;
pub use send::*;
use serde::{Deserialize, Serialize};
use crate::{
frame::{
generate::generate_cstring,
micro::parse::vec_of,
parse::{self, take_cstring, take_id, take_u32, take_u64},
FrameGenerator, FrameParser,
},
types::{Address, Ident32},
ClientError, EncodingError, Result,
};
use core::fmt;
use nom::{bytes::complete::take, IResult};
use std::{ffi::CString, fmt::Display};
#[derive(Debug, PartialEq, Eq, PartialOrd, Ord)]
pub struct Handshake {
pub client_version: [u8; 2],
}
impl Handshake {
pub fn new() -> Self {
Self {
client_version: super::VERSION,
}
}
}
impl FrameGenerator for Handshake {
fn generate(self, buf: &mut Vec<u8>) -> Result<()> {
buf.push(1);
buf.extend_from_slice(self.client_version.as_slice());
Ok(())
}
}
impl FrameParser for Handshake {
type Output = Self;
fn parse(input: &[u8]) -> IResult<&[u8], Self::Output> {
let (input, version) = parse::take_byte(input).unwrap();
assert_eq!(version, 1);
let (input, proto_version) = parse::take(2 as usize)(input)?;
Ok((
input,
Self {
client_version: proto_version.try_into().expect("wat??"),
},
))
}
}
#[derive(Debug)]
pub enum ServerPing {
Ok,
Update {
available_subscriptions: Vec<Ident32>,
},
Error(ClientError),
IncompatibleVersion {
router: CString,
client: CString,
},
Timeout,
Subscription {
sub_id: Ident32,
sub_bind: CString,
},
AddrList(Vec<Address>),
PeerList(PeerList),
SendSocket {
socket_bind: CString,
},
Status {
num_peers: u64,
num_local: u64,
num_auth: u64,
num_collector_workers: u64,
},
Anycast(Vec<(Address, u64)>),
}
#[derive(Serialize, Deserialize)]
pub struct RouterStatus {
pub num_peers: u64,
pub num_local: u64,
pub num_auth: u64,
pub num_collector_workers: u64,
}
impl Display for RouterStatus {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(
f,
"known peers: {}, local addrs: {}, active auths: {}, collector workers: {}",
self.num_peers, self.num_local, self.num_auth, self.num_collector_workers
)
}
}
impl FrameGenerator for ServerPing {
#[tracing::instrument]
fn generate(self, buf: &mut Vec<u8>) -> Result<()> {
match self {
Self::Ok => buf.push(1),
Self::Update {
available_subscriptions,
} => {
buf.push(2);
available_subscriptions.generate(buf)?;
}
Self::Error(error) => {
buf.push(3);
let mut err_buf = bincode::serialize(&error)?;
let mut len_buf = vec![0; 4];
BigEndian::write_u32(len_buf.as_mut_slice(), err_buf.len() as u32);
trace!("Ping::Error(len_buf) = {:?}", len_buf);
trace!("Ping::Error(err_buf) = {:?}", err_buf);
buf.append(&mut len_buf);
buf.append(&mut err_buf);
}
Self::Timeout => buf.push(4),
Self::IncompatibleVersion { router, client } => {
buf.push(5);
generate_cstring(router, buf)?;
generate_cstring(client, buf)?;
}
Self::Subscription { sub_id, sub_bind } => {
buf.push(6);
Some(sub_id).generate(buf)?;
generate_cstring(sub_bind, buf)?;
}
Self::AddrList(list) => {
buf.push(7);
list.generate(buf)?;
}
Self::PeerList(list) => {
buf.push(8);
list.generate(buf)?;
}
Self::SendSocket { socket_bind } => {
buf.push(9);
generate_cstring(socket_bind, buf)?;
}
Self::Status {
num_peers,
num_local,
num_auth,
num_collector_workers,
} => {
buf.push(10);
num_peers.generate(buf)?;
num_local.generate(buf)?;
num_auth.generate(buf)?;
num_collector_workers.generate(buf)?;
}
Self::Anycast(list) => {
buf.push(11);
list.generate(buf)?;
}
}
Ok(())
}
}
impl FrameParser for ServerPing {
type Output = Result<Self>;
fn parse(input: &[u8]) -> IResult<&[u8], Self::Output> {
let (mut input, tt) = parse::take_byte(input)?;
let output = match tt {
1 => Ok(Self::Ok),
2 => {
let (input_, available_subscriptions) = vec_of(take_id, input)?;
input = input_; Ok(Self::Update {
available_subscriptions,
})
}
3 => {
let (input_, err_len) = take_u32(input)?;
let (input_, err_buf) = take(err_len as usize)(input_)?;
let err = bincode::deserialize(&err_buf).unwrap();
input = input_;
Ok(Self::Error(err))
}
4 => Ok(Self::Timeout),
5 => {
let (input_, router) = take_cstring(input)?;
let (input_, client) = take_cstring(input_)?;
input = input_;
Ok(Self::IncompatibleVersion {
router: router.expect("failed to decode version string"),
client: client.expect("failed to decode version string"),
})
}
6 => {
let (input_, sub_id) = take_id(input)?;
let (input_, sub_bind) = take_cstring(input_)?;
input = input_;
sub_bind.map(|sub_bind| Self::Subscription { sub_id, sub_bind })
}
7 => {
let (input_, list) = Vec::<Address>::parse(input)?;
input = input_;
Ok(Self::AddrList(list))
}
8 => {
let (input_, list) = PeerList::parse(input)?;
input = input_;
list.map(|list| Self::PeerList(list))
}
9 => {
let (input_, send_bind) = take_cstring(input)?;
input = input_;
send_bind.map(|socket_bind| Self::SendSocket { socket_bind })
}
10 => {
let (input_, num_peers) = take_u64(input)?;
let (input_, num_local) = take_u64(input_)?;
let (input_, num_auth) = take_u64(input_)?;
let (input_, num_collector_workers) = take_u64(input_)?;
input = input_;
Ok(Self::Status {
num_peers,
num_local,
num_auth,
num_collector_workers,
})
}
11 => {
let (input_, list) = Vec::<(Address, u64)>::parse(input)?;
input = input_;
Ok(Self::Anycast(list))
}
_ => Err(EncodingError::Parsing(format!("Invalid ServerPing type={}", tt)).into()),
};
Ok((input, output))
}
}