mod network;
mod node;
#[cfg(test)]
mod tests;
pub use self::network::Network;
use self::node::Node;
use bytes::Bytes;
use crossbeam_channel::Sender;
use hex_fmt::HexFmt;
use serde::{Deserialize, Serialize};
use std::{
cell::RefCell,
collections::HashSet,
fmt::{self, Display, Formatter},
iter,
net::{IpAddr, SocketAddr},
rc::Rc,
str::FromStr,
};
use structopt::StructOpt;
pub struct Builder {
event_tx: Sender<Event>,
config: Option<Config>,
}
impl Builder {
pub fn new(event_tx: Sender<Event>) -> Self {
Self {
event_tx,
config: Default::default(),
}
}
pub fn with_config(mut self, config: Config) -> Self {
self.config = Some(config);
self
}
pub fn build(self) -> Result<QuicP2p, Error> {
Ok(QuicP2p::new(
self.event_tx,
self.config.unwrap_or_else(Config::default),
))
}
}
pub struct QuicP2p {
inner: Rc<RefCell<Node>>,
}
impl QuicP2p {
pub fn bootstrap(&mut self) {
self.inner.borrow_mut().bootstrap()
}
pub fn connect_to(&mut self, peer_info: NodeInfo) {
self.inner.borrow().connect(peer_info.peer_addr);
}
pub fn disconnect_from(&mut self, peer_addr: SocketAddr) {
self.inner.borrow_mut().disconnect(peer_addr)
}
pub fn send(&mut self, peer: Peer, msg: Bytes, _token: u64) {
self.inner.borrow_mut().send(peer.peer_addr(), msg)
}
pub fn our_connection_info(&mut self) -> Result<NodeInfo, Error> {
self.inner.borrow().our_connection_info()
}
pub fn bootstrap_cache(&mut self) -> Result<Vec<NodeInfo>, Error> {
Ok(self.inner.borrow().bootstrap_cache())
}
pub fn is_hard_coded_contact(&self, _node_info: &NodeInfo) -> bool {
true
}
fn new(event_tx: Sender<Event>, config: Config) -> Self {
Self {
inner: Node::new(event_tx, config),
}
}
}
#[cfg(test)]
impl QuicP2p {
fn addr(&self) -> SocketAddr {
*self.inner.borrow().addr()
}
fn our_type(&self) -> OurType {
self.inner.borrow().our_type()
}
}
#[derive(Clone, Debug, Default, Serialize, Deserialize, Eq, PartialEq, StructOpt)]
#[structopt(rename_all = "kebab-case")]
pub struct Config {
#[structopt(
short,
long,
default_value = "[]",
parse(try_from_str = "serde_json::from_str")
)]
pub hard_coded_contacts: HashSet<NodeInfo>,
#[structopt(short, long)]
pub port: Option<u16>,
#[structopt(long)]
pub ip: Option<IpAddr>,
#[structopt(short = "t", long, default_value = "node")]
pub our_type: OurType,
}
impl Config {
pub fn node() -> Self {
Self {
hard_coded_contacts: HashSet::new(),
our_type: OurType::Node,
..Self::default()
}
}
pub fn client() -> Self {
Self {
hard_coded_contacts: HashSet::new(),
our_type: OurType::Client,
..Self::default()
}
}
pub fn with_hard_coded_contacts<I>(self, contacts: I) -> Self
where
I: IntoIterator,
I::Item: Into<NodeInfo>,
{
Self {
hard_coded_contacts: contacts.into_iter().map(Into::into).collect(),
..self
}
}
pub fn with_hard_coded_contact<T>(self, contact: T) -> Self
where
T: Into<NodeInfo>,
{
self.with_hard_coded_contacts(iter::once(contact))
}
}
#[derive(Clone, Copy, Eq, PartialEq, Debug, Serialize, Deserialize)]
pub enum OurType {
Client,
Node,
}
impl FromStr for OurType {
type Err = String;
fn from_str(s: &str) -> Result<Self, Self::Err> {
match s.to_lowercase().as_str() {
"client" => Ok(OurType::Client),
"node" => Ok(OurType::Node),
x => Err(format!("Unknown client type: {}", x)),
}
}
}
impl Default for OurType {
fn default() -> Self {
OurType::Node
}
}
#[derive(Debug)]
pub enum Event {
BootstrapFailure,
BootstrappedTo {
node: NodeInfo,
},
ConnectionFailure {
peer_addr: SocketAddr,
err: Error,
},
SentUserMessage {
peer_addr: SocketAddr,
msg: Bytes,
},
UnsentUserMessage {
peer_addr: SocketAddr,
msg: Bytes,
},
ConnectedTo {
peer: Peer,
},
NewMessage {
peer_addr: SocketAddr,
msg: Bytes,
},
Finish,
}
impl Display for Event {
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
use self::Event::*;
match self {
BootstrappedTo { node } => write!(f, "BootstrappedTo {{ {} }}", node.peer_addr),
BootstrapFailure => write!(f, "BootstrapFailure"),
ConnectedTo { peer } => {
let peer_type = match peer {
Peer::Node { .. } => "Node",
Peer::Client { .. } => "Client",
};
write!(f, "ConnectedTo {{ {}({}) }}", peer_type, peer.peer_addr())
}
ConnectionFailure { peer_addr, .. } => {
write!(f, "ConnectionFailure {{ {} }}", peer_addr)
}
NewMessage { peer_addr, msg } => write!(
f,
"NewMessage {{ peer_addr: {}, msg: {:<8} }}",
peer_addr,
HexFmt(msg)
),
SentUserMessage { peer_addr, msg } => write!(
f,
"SentUserMessage {{ peer_addr: {}, msg: {:<8} }}",
peer_addr,
HexFmt(msg)
),
UnsentUserMessage { peer_addr, msg } => write!(
f,
"UnsentUserMessage {{ peer_addr: {}, msg: {:<8} }}",
peer_addr,
HexFmt(msg)
),
Finish => write!(f, "Finish"),
}
}
}
#[derive(Debug, Clone, Eq, PartialEq)]
pub enum Peer {
Node {
node_info: NodeInfo,
},
Client {
peer_addr: SocketAddr,
},
}
impl Peer {
pub(super) fn new(peer_type: OurType, addr: SocketAddr) -> Self {
match peer_type {
OurType::Client => Peer::Client { peer_addr: addr },
OurType::Node => Peer::Node {
node_info: NodeInfo::from(addr),
},
}
}
pub(super) fn node(addr: SocketAddr) -> Self {
Peer::Node {
node_info: NodeInfo::from(addr),
}
}
pub fn peer_addr(&self) -> SocketAddr {
match *self {
Peer::Node { ref node_info } => node_info.peer_addr,
Peer::Client { peer_addr } => peer_addr,
}
}
}
#[derive(Debug, Clone, Eq, PartialEq, Hash, Serialize, Deserialize)]
pub struct NodeInfo {
pub peer_addr: SocketAddr,
pub peer_cert_der: Vec<u8>,
}
impl From<SocketAddr> for NodeInfo {
fn from(addr: SocketAddr) -> Self {
Self {
peer_addr: addr,
peer_cert_der: vec![],
}
}
}
#[derive(Debug)]
pub struct Error;
impl Display for Error {
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
write!(f, "Error")
}
}
impl std::error::Error for Error {}