2018-07-17 14:06:23 -07:00
|
|
|
//! A peer network node.
|
|
|
|
|
2018-07-22 01:29:10 -07:00
|
|
|
#![allow(unused_imports, dead_code, unused_variables, unused_mut)]
|
2018-07-17 14:06:23 -07:00
|
|
|
|
2018-09-28 06:13:31 -07:00
|
|
|
use futures::sync::mpsc;
|
|
|
|
use hbbft::crypto::PublicKey;
|
2018-10-03 20:14:04 -07:00
|
|
|
use hbbft::dynamic_honey_badger::Input as HbInput;
|
2018-09-28 06:13:31 -07:00
|
|
|
use hydrabadger::{Error, Hydrabadger};
|
|
|
|
use serde::{Deserialize, Serialize};
|
2018-07-17 14:06:23 -07:00
|
|
|
use std::{
|
2018-09-28 06:13:31 -07:00
|
|
|
borrow::Borrow,
|
2018-07-17 14:06:23 -07:00
|
|
|
collections::{
|
2018-07-17 15:58:48 -07:00
|
|
|
hash_map::{Iter as HashMapIter, Values as HashMapValues},
|
2018-07-19 14:15:00 -07:00
|
|
|
HashMap,
|
2018-07-17 14:06:23 -07:00
|
|
|
},
|
|
|
|
};
|
2018-07-19 14:15:00 -07:00
|
|
|
use tokio::prelude::*;
|
2018-09-28 06:13:31 -07:00
|
|
|
use {
|
|
|
|
Contribution, InAddr, InternalMessage, OutAddr, Uid, WireMessage, WireMessageKind,
|
|
|
|
WireMessages, WireRx, WireTx,
|
2018-09-27 14:42:47 -07:00
|
|
|
};
|
2018-07-17 14:06:23 -07:00
|
|
|
|
|
|
|
/// The state for each connected client.
|
2018-09-27 14:42:47 -07:00
|
|
|
pub struct PeerHandler<T: Contribution> {
|
2018-07-17 14:06:23 -07:00
|
|
|
// Peer uid.
|
2018-07-17 15:58:48 -07:00
|
|
|
uid: Option<Uid>,
|
2018-07-17 14:06:23 -07:00
|
|
|
|
|
|
|
// The incoming stream of messages:
|
2018-09-27 14:42:47 -07:00
|
|
|
wire_msgs: WireMessages<T>,
|
2018-07-17 14:06:23 -07:00
|
|
|
|
|
|
|
/// Handle to the shared message state.
|
2018-09-27 14:42:47 -07:00
|
|
|
hdb: Hydrabadger<T>,
|
2018-07-17 14:06:23 -07:00
|
|
|
|
|
|
|
// TODO: Consider adding back a separate clone of `peer_internal_tx`. Is
|
|
|
|
// there any difference if capacity isn't an issue? -- doubtful
|
|
|
|
/// Receive half of the message channel.
|
2018-09-27 14:42:47 -07:00
|
|
|
rx: WireRx<T>,
|
2018-07-17 14:06:23 -07:00
|
|
|
|
|
|
|
/// Peer socket address.
|
|
|
|
out_addr: OutAddr,
|
|
|
|
}
|
|
|
|
|
2018-09-27 14:42:47 -07:00
|
|
|
impl<T: Contribution> PeerHandler<T> {
|
2018-07-17 14:06:23 -07:00
|
|
|
/// Create a new instance of `Peer`.
|
2018-09-28 06:13:31 -07:00
|
|
|
pub fn new(
|
|
|
|
pub_info: Option<(Uid, InAddr, PublicKey)>,
|
|
|
|
hdb: Hydrabadger<T>,
|
|
|
|
wire_msgs: WireMessages<T>,
|
|
|
|
) -> PeerHandler<T> {
|
2018-07-17 14:06:23 -07:00
|
|
|
// Get the client socket address
|
|
|
|
let out_addr = OutAddr(wire_msgs.socket().peer_addr().unwrap());
|
|
|
|
|
|
|
|
// Create a channel for this peer
|
|
|
|
let (tx, rx) = mpsc::unbounded();
|
|
|
|
|
2018-07-17 15:58:48 -07:00
|
|
|
let uid = pub_info.as_ref().map(|(uid, _, _)| uid.clone());
|
2018-07-17 14:06:23 -07:00
|
|
|
|
|
|
|
// Add an entry for this `Peer` in the shared state map.
|
2018-07-19 14:15:00 -07:00
|
|
|
hdb.peers_mut().add(out_addr, tx, pub_info);
|
2018-07-17 14:06:23 -07:00
|
|
|
|
|
|
|
PeerHandler {
|
|
|
|
uid,
|
|
|
|
wire_msgs,
|
|
|
|
hdb,
|
|
|
|
rx,
|
|
|
|
out_addr,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-09-27 14:42:47 -07:00
|
|
|
pub(crate) fn hdb(&self) -> &Hydrabadger<T> {
|
2018-07-18 19:04:41 -07:00
|
|
|
&self.hdb
|
2018-07-17 14:06:23 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
pub(crate) fn out_addr(&self) -> &OutAddr {
|
2018-07-18 19:04:41 -07:00
|
|
|
&self.out_addr
|
2018-07-17 14:06:23 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/// A future representing the client connection.
|
2018-09-27 14:42:47 -07:00
|
|
|
impl<T: Contribution> Future for PeerHandler<T> {
|
2018-07-17 14:06:23 -07:00
|
|
|
type Item = ();
|
|
|
|
type Error = Error;
|
|
|
|
|
|
|
|
fn poll(&mut self) -> Poll<(), Error> {
|
|
|
|
const MESSAGES_PER_TICK: usize = 10;
|
|
|
|
|
|
|
|
// Receive all messages from peers.
|
|
|
|
for i in 0..MESSAGES_PER_TICK {
|
|
|
|
// Polling an `UnboundedReceiver` cannot fail, so `unwrap` here is
|
|
|
|
// safe.
|
|
|
|
match self.rx.poll().unwrap() {
|
|
|
|
Async::Ready(Some(v)) => {
|
|
|
|
// Buffer the message. Once all messages are buffered, they will
|
|
|
|
// be flushed to the socket (right below).
|
|
|
|
self.wire_msgs.start_send(v)?;
|
|
|
|
|
|
|
|
// Exceeded max messages per tick, schedule notification:
|
|
|
|
if i + 1 == MESSAGES_PER_TICK {
|
|
|
|
task::current().notify();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
_ => break,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Flush the write buffer to the socket
|
|
|
|
let _ = self.wire_msgs.poll_complete()?;
|
|
|
|
|
|
|
|
// Read new messages from the socket
|
|
|
|
while let Async::Ready(message) = self.wire_msgs.poll()? {
|
|
|
|
trace!("Received message: {:?}", message);
|
|
|
|
|
|
|
|
if let Some(msg) = message {
|
|
|
|
match msg.into_kind() {
|
2018-07-19 14:15:00 -07:00
|
|
|
WireMessageKind::HelloRequestChangeAdd(src_uid, _in_addr, _pub_key) => {
|
2018-09-28 06:13:31 -07:00
|
|
|
error!(
|
|
|
|
"Duplicate `WireMessage::HelloRequestChangeAdd` \
|
|
|
|
received from '{}'",
|
|
|
|
src_uid
|
|
|
|
);
|
|
|
|
}
|
2018-07-17 19:10:50 -07:00
|
|
|
WireMessageKind::WelcomeReceivedChangeAdd(src_uid, pk, net_state) => {
|
2018-07-17 14:06:23 -07:00
|
|
|
self.uid = Some(src_uid);
|
2018-09-28 06:13:31 -07:00
|
|
|
self.hdb.send_internal(InternalMessage::wire(
|
|
|
|
Some(src_uid),
|
|
|
|
self.out_addr,
|
|
|
|
WireMessage::welcome_received_change_add(src_uid, pk, net_state),
|
|
|
|
));
|
|
|
|
}
|
2018-07-23 12:01:13 -07:00
|
|
|
WireMessageKind::Message(src_uid, msg) => {
|
|
|
|
if let Some(peer_uid) = self.uid.as_ref() {
|
|
|
|
debug_assert_eq!(src_uid, *peer_uid);
|
|
|
|
}
|
|
|
|
|
2018-09-28 06:13:31 -07:00
|
|
|
self.hdb.send_internal(InternalMessage::hb_message(
|
|
|
|
src_uid,
|
|
|
|
self.out_addr,
|
|
|
|
msg,
|
|
|
|
))
|
|
|
|
}
|
2018-10-03 20:14:04 -07:00
|
|
|
WireMessageKind::Transaction(src_uid, txn) => {
|
2018-07-23 12:34:08 -07:00
|
|
|
if let Some(peer_uid) = self.uid.as_ref() {
|
|
|
|
debug_assert_eq!(src_uid, *peer_uid);
|
|
|
|
}
|
|
|
|
|
2018-09-28 06:13:31 -07:00
|
|
|
self.hdb.send_internal(InternalMessage::hb_input(
|
|
|
|
src_uid,
|
|
|
|
self.out_addr,
|
2018-10-03 20:14:04 -07:00
|
|
|
HbInput::User(txn),
|
2018-09-28 06:13:31 -07:00
|
|
|
))
|
2018-07-18 19:04:41 -07:00
|
|
|
}
|
2018-09-28 06:13:31 -07:00
|
|
|
kind => self.hdb.send_internal(InternalMessage::wire(
|
|
|
|
self.uid.clone(),
|
|
|
|
self.out_addr,
|
|
|
|
kind.into(),
|
|
|
|
)),
|
2018-07-17 14:06:23 -07:00
|
|
|
}
|
|
|
|
} else {
|
2018-09-04 14:58:55 -07:00
|
|
|
info!("Peer ({}: '{:?}') disconnected.", self.out_addr, self.uid);
|
2018-07-17 14:06:23 -07:00
|
|
|
return Ok(Async::Ready(()));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
Ok(Async::NotReady)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-09-27 14:42:47 -07:00
|
|
|
impl<T: Contribution> Drop for PeerHandler<T> {
|
2018-07-17 14:06:23 -07:00
|
|
|
fn drop(&mut self) {
|
2018-09-28 06:13:31 -07:00
|
|
|
debug!(
|
|
|
|
"Removing peer ({}: '{}') from the list of peers.",
|
|
|
|
self.out_addr,
|
|
|
|
self.uid.clone().unwrap()
|
|
|
|
);
|
2018-07-17 14:06:23 -07:00
|
|
|
// Remove peer transmitter from the lists:
|
|
|
|
self.hdb.peers_mut().remove(&self.out_addr);
|
|
|
|
|
|
|
|
if let Some(uid) = self.uid.clone() {
|
2018-09-28 06:13:31 -07:00
|
|
|
debug!(
|
|
|
|
"Sending peer ({}: '{}') disconnect internal message.",
|
|
|
|
self.out_addr,
|
|
|
|
self.uid.clone().unwrap()
|
|
|
|
);
|
|
|
|
|
|
|
|
self.hdb
|
|
|
|
.send_internal(InternalMessage::peer_disconnect(uid, self.out_addr));
|
2018-07-17 14:06:23 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(Clone, Debug)]
|
2018-07-19 14:15:00 -07:00
|
|
|
#[allow(dead_code)]
|
2018-07-17 14:06:23 -07:00
|
|
|
enum State {
|
2018-07-18 19:04:41 -07:00
|
|
|
Handshaking,
|
2018-07-22 01:29:10 -07:00
|
|
|
PendingJoinInfo {
|
|
|
|
uid: Uid,
|
|
|
|
in_addr: InAddr,
|
|
|
|
pk: PublicKey,
|
|
|
|
},
|
|
|
|
EstablishedObserver {
|
|
|
|
uid: Uid,
|
|
|
|
in_addr: InAddr,
|
|
|
|
pk: PublicKey,
|
|
|
|
},
|
|
|
|
EstablishedValidator {
|
2018-07-18 19:04:41 -07:00
|
|
|
uid: Uid,
|
|
|
|
in_addr: InAddr,
|
|
|
|
pk: PublicKey,
|
|
|
|
},
|
2018-07-17 14:06:23 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
/// Nodes of the network.
|
|
|
|
#[derive(Clone, Debug)]
|
2018-09-27 14:42:47 -07:00
|
|
|
pub struct Peer<T: Contribution> {
|
2018-07-17 14:06:23 -07:00
|
|
|
out_addr: OutAddr,
|
2018-09-27 14:42:47 -07:00
|
|
|
tx: WireTx<T>,
|
2018-07-17 14:06:23 -07:00
|
|
|
state: State,
|
|
|
|
}
|
|
|
|
|
2018-09-27 14:42:47 -07:00
|
|
|
impl<T: Contribution> Peer<T> {
|
2018-07-17 14:06:23 -07:00
|
|
|
/// Returns a new `Peer`
|
2018-09-28 06:13:31 -07:00
|
|
|
fn new(
|
|
|
|
out_addr: OutAddr,
|
|
|
|
tx: WireTx<T>,
|
|
|
|
pub_info: Option<(Uid, InAddr, PublicKey)>,
|
|
|
|
) -> Peer<T> {
|
2018-07-18 19:04:41 -07:00
|
|
|
let state = match pub_info {
|
|
|
|
None => State::Handshaking,
|
2018-07-22 01:29:10 -07:00
|
|
|
Some((uid, in_addr, pk)) => State::EstablishedValidator { uid, in_addr, pk },
|
2018-07-18 19:04:41 -07:00
|
|
|
};
|
2018-07-17 14:06:23 -07:00
|
|
|
|
|
|
|
Peer {
|
2018-07-18 19:04:41 -07:00
|
|
|
out_addr,
|
|
|
|
tx,
|
|
|
|
state,
|
2018-07-17 14:06:23 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-07-22 01:29:10 -07:00
|
|
|
/// Sets a peer state to `State::PendingJoinInfo` and stores public info.
|
|
|
|
fn set_pending(&mut self, pub_info: (Uid, InAddr, PublicKey)) {
|
|
|
|
self.state = match self.state {
|
2018-09-28 06:13:31 -07:00
|
|
|
State::Handshaking => State::PendingJoinInfo {
|
|
|
|
uid: pub_info.0,
|
|
|
|
in_addr: pub_info.1,
|
|
|
|
pk: pub_info.2,
|
2018-07-22 01:29:10 -07:00
|
|
|
},
|
2018-09-28 06:13:31 -07:00
|
|
|
_ => panic!(
|
|
|
|
"Peer::set_pending: Can only set pending when \
|
|
|
|
peer state is `Handshaking`."
|
|
|
|
),
|
2018-07-22 01:29:10 -07:00
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Sets a peer state to `State::EstablishedObserver` and stores public info.
|
|
|
|
fn establish_observer(&mut self) {
|
|
|
|
self.state = match self.state {
|
|
|
|
State::PendingJoinInfo { uid, in_addr, pk } => {
|
2018-09-28 06:13:31 -07:00
|
|
|
State::EstablishedObserver { uid, in_addr, pk }
|
|
|
|
}
|
|
|
|
_ => panic!(
|
|
|
|
"Peer::establish_observer: Can only establish observer when \
|
|
|
|
peer state is`PendingJoinInfo`."
|
|
|
|
),
|
2018-07-22 01:29:10 -07:00
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Sets a peer state to `State::EstablishedValidator` and stores public info.
|
|
|
|
fn establish_validator(&mut self, pub_info: Option<(Uid, InAddr, PublicKey)>) {
|
|
|
|
self.state = match self.state {
|
|
|
|
State::Handshaking => match pub_info {
|
2018-09-28 06:13:31 -07:00
|
|
|
Some(pi) => State::EstablishedValidator {
|
|
|
|
uid: pi.0,
|
|
|
|
in_addr: pi.1,
|
|
|
|
pk: pi.2,
|
2018-07-22 01:29:10 -07:00
|
|
|
},
|
|
|
|
None => {
|
2018-09-28 06:13:31 -07:00
|
|
|
panic!(
|
|
|
|
"Peer::establish_validator: `pub_info` must be supplied \
|
|
|
|
when establishing a validator from `Handshaking`."
|
|
|
|
);
|
|
|
|
}
|
2018-07-22 01:29:10 -07:00
|
|
|
},
|
|
|
|
State::EstablishedObserver { uid, in_addr, pk } => {
|
|
|
|
if let Some(_) = pub_info {
|
2018-09-28 06:13:31 -07:00
|
|
|
panic!(
|
|
|
|
"Peer::establish_validator: `pub_info` must be `None` \
|
|
|
|
when upgrading an observer node."
|
|
|
|
);
|
2018-07-22 01:29:10 -07:00
|
|
|
}
|
2018-09-28 06:13:31 -07:00
|
|
|
State::EstablishedValidator { uid, in_addr, pk }
|
|
|
|
}
|
|
|
|
_ => panic!(
|
|
|
|
"Peer::establish_validator: Can only establish validator when \
|
|
|
|
peer state is`Handshaking` or `EstablishedObserver`."
|
|
|
|
),
|
2018-07-18 19:04:41 -07:00
|
|
|
};
|
2018-07-17 19:10:50 -07:00
|
|
|
}
|
|
|
|
|
2018-07-17 14:06:23 -07:00
|
|
|
/// Returns the peer's unique identifier.
|
2018-07-17 15:58:48 -07:00
|
|
|
pub fn uid(&self) -> Option<&Uid> {
|
2018-07-18 19:04:41 -07:00
|
|
|
match self.state {
|
|
|
|
State::Handshaking => None,
|
2018-07-22 01:29:10 -07:00
|
|
|
State::PendingJoinInfo { ref uid, .. } => Some(uid),
|
2018-09-28 06:13:31 -07:00
|
|
|
State::EstablishedObserver { ref uid, .. } => Some(uid),
|
2018-07-22 01:29:10 -07:00
|
|
|
State::EstablishedValidator { ref uid, .. } => Some(uid),
|
2018-07-18 19:04:41 -07:00
|
|
|
}
|
2018-07-17 14:06:23 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
/// Returns the peer's unique identifier.
|
|
|
|
pub fn out_addr(&self) -> &OutAddr {
|
2018-07-18 19:04:41 -07:00
|
|
|
&self.out_addr
|
2018-07-17 14:06:23 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
/// Returns the peer's public key.
|
|
|
|
pub fn public_key(&self) -> Option<&PublicKey> {
|
2018-07-18 19:04:41 -07:00
|
|
|
match self.state {
|
|
|
|
State::Handshaking => None,
|
2018-07-22 01:29:10 -07:00
|
|
|
State::PendingJoinInfo { ref pk, .. } => Some(pk),
|
|
|
|
State::EstablishedObserver { ref pk, .. } => Some(pk),
|
|
|
|
State::EstablishedValidator { ref pk, .. } => Some(pk),
|
2018-07-18 19:04:41 -07:00
|
|
|
}
|
2018-07-17 14:06:23 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
/// Returns the peer's incoming (listening) socket address.
|
|
|
|
pub fn in_addr(&self) -> Option<&InAddr> {
|
2018-07-18 19:04:41 -07:00
|
|
|
match self.state {
|
|
|
|
State::Handshaking => None,
|
2018-07-22 01:29:10 -07:00
|
|
|
State::PendingJoinInfo { ref in_addr, .. } => Some(in_addr),
|
|
|
|
State::EstablishedObserver { ref in_addr, .. } => Some(in_addr),
|
|
|
|
State::EstablishedValidator { ref in_addr, .. } => Some(in_addr),
|
2018-07-18 19:04:41 -07:00
|
|
|
}
|
2018-07-17 14:06:23 -07:00
|
|
|
}
|
|
|
|
|
2018-07-17 15:58:48 -07:00
|
|
|
/// Returns the peer's public info if established.
|
|
|
|
pub fn pub_info(&self) -> Option<(&Uid, &InAddr, &PublicKey)> {
|
2018-07-18 19:04:41 -07:00
|
|
|
match self.state {
|
|
|
|
State::Handshaking => None,
|
2018-09-28 06:13:31 -07:00
|
|
|
State::EstablishedObserver {
|
|
|
|
ref uid,
|
|
|
|
ref in_addr,
|
|
|
|
ref pk,
|
|
|
|
} => Some((uid, in_addr, pk)),
|
|
|
|
State::PendingJoinInfo {
|
|
|
|
ref uid,
|
|
|
|
ref in_addr,
|
|
|
|
ref pk,
|
|
|
|
} => Some((uid, in_addr, pk)),
|
|
|
|
State::EstablishedValidator {
|
|
|
|
ref uid,
|
|
|
|
ref in_addr,
|
|
|
|
ref pk,
|
|
|
|
} => Some((uid, in_addr, pk)),
|
2018-07-22 01:29:10 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Returns true if this peer is pending.
|
|
|
|
pub fn is_pending(&self) -> bool {
|
|
|
|
match self.state {
|
|
|
|
State::PendingJoinInfo { .. } => true,
|
|
|
|
_ => false,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Returns true if this peer is an established observer.
|
|
|
|
pub fn is_observer(&self) -> bool {
|
|
|
|
match self.state {
|
|
|
|
State::EstablishedObserver { .. } => true,
|
|
|
|
_ => false,
|
2018-07-18 19:04:41 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Returns true if this peer is an established validator.
|
|
|
|
pub fn is_validator(&self) -> bool {
|
|
|
|
match self.state {
|
2018-07-22 01:29:10 -07:00
|
|
|
State::EstablishedValidator { .. } => true,
|
2018-07-18 19:04:41 -07:00
|
|
|
_ => false,
|
|
|
|
}
|
2018-07-17 15:58:48 -07:00
|
|
|
}
|
|
|
|
|
2018-07-17 14:06:23 -07:00
|
|
|
/// Returns the peer's wire transmitter.
|
2018-09-27 14:42:47 -07:00
|
|
|
pub fn tx(&self) -> &WireTx<T> {
|
2018-07-18 19:04:41 -07:00
|
|
|
&self.tx
|
2018-07-17 14:06:23 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Peer nodes of the network.
|
2018-07-18 19:04:41 -07:00
|
|
|
//
|
|
|
|
// TODO: Keep a separate `HashSet` of validator `OutAddrs` to avoid having to
|
|
|
|
// iterate through entire list.
|
2018-07-17 14:06:23 -07:00
|
|
|
#[derive(Debug)]
|
2018-10-19 13:50:28 -07:00
|
|
|
pub struct Peers<T: Contribution> {
|
2018-09-27 14:42:47 -07:00
|
|
|
peers: HashMap<OutAddr, Peer<T>>,
|
2018-07-17 15:58:48 -07:00
|
|
|
out_addrs: HashMap<Uid, OutAddr>,
|
2018-07-17 14:06:23 -07:00
|
|
|
}
|
|
|
|
|
2018-09-27 14:42:47 -07:00
|
|
|
impl<T: Contribution> Peers<T> {
|
2018-07-17 14:06:23 -07:00
|
|
|
/// Returns a new empty list of peers.
|
2018-09-27 14:42:47 -07:00
|
|
|
pub(crate) fn new() -> Peers<T> {
|
2018-07-17 14:06:23 -07:00
|
|
|
Peers {
|
|
|
|
peers: HashMap::with_capacity(64),
|
|
|
|
out_addrs: HashMap::with_capacity(64),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Adds a peer to the list.
|
2018-09-28 06:13:31 -07:00
|
|
|
pub(crate) fn add(
|
|
|
|
&mut self,
|
|
|
|
out_addr: OutAddr,
|
|
|
|
tx: WireTx<T>,
|
|
|
|
pub_info: Option<(Uid, InAddr, PublicKey)>,
|
|
|
|
) {
|
2018-07-17 15:58:48 -07:00
|
|
|
let peer = Peer::new(out_addr, tx, pub_info);
|
2018-07-22 01:29:10 -07:00
|
|
|
if let State::EstablishedValidator { uid, .. } = peer.state {
|
2018-07-17 14:06:23 -07:00
|
|
|
self.out_addrs.insert(uid, peer.out_addr);
|
|
|
|
}
|
|
|
|
self.peers.insert(peer.out_addr, peer);
|
|
|
|
}
|
|
|
|
|
2018-07-22 01:29:10 -07:00
|
|
|
/// Attempts to set peer as pending-join-info, storing `pub_info`.
|
|
|
|
///
|
|
|
|
/// Returns `true` if the peer was already pending.
|
|
|
|
///
|
|
|
|
/// ### Panics
|
|
|
|
///
|
|
|
|
/// Peer state must be `Handshaking`.
|
|
|
|
///
|
|
|
|
/// TODO: Error handling...
|
2018-09-28 06:13:31 -07:00
|
|
|
pub(crate) fn set_pending<O: Borrow<OutAddr>>(
|
|
|
|
&mut self,
|
|
|
|
out_addr: O,
|
|
|
|
pub_info: (Uid, InAddr, PublicKey),
|
|
|
|
) -> bool {
|
|
|
|
let peer = self.peers.get_mut(out_addr.borrow()).expect(&format!(
|
|
|
|
"Peers::set_pending: \
|
|
|
|
No peer found with outgoing address: {}",
|
|
|
|
out_addr.borrow()
|
|
|
|
));
|
2018-07-22 01:29:10 -07:00
|
|
|
match self.out_addrs.insert(pub_info.0, *out_addr.borrow()) {
|
|
|
|
Some(_out_addr_pub) => {
|
2018-09-28 06:13:31 -07:00
|
|
|
let pi_pub = peer
|
|
|
|
.pub_info()
|
2018-07-22 01:29:10 -07:00
|
|
|
.expect("Peers::set_pending: internal consistency error");
|
2018-09-28 06:13:31 -07:00
|
|
|
assert!(
|
|
|
|
pub_info.0 == *pi_pub.0 && pub_info.1 == *pi_pub.1 && pub_info.2 == *pi_pub.2
|
|
|
|
);
|
2018-07-22 01:29:10 -07:00
|
|
|
assert!(peer.is_validator());
|
|
|
|
return true;
|
2018-09-28 06:13:31 -07:00
|
|
|
}
|
2018-07-22 01:29:10 -07:00
|
|
|
None => peer.set_pending(pub_info),
|
|
|
|
}
|
2018-07-23 12:34:08 -07:00
|
|
|
|
|
|
|
// false
|
|
|
|
panic!("Peer::set_pending: Do not use yet.");
|
2018-07-22 01:29:10 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
/// Attempts to establish a peer as an observer.
|
|
|
|
///
|
|
|
|
/// ### Panics
|
|
|
|
///
|
|
|
|
/// Peer state must be `Handshaking`.
|
|
|
|
///
|
|
|
|
/// TODO: Error handling...
|
|
|
|
pub(crate) fn establish_observer<O: Borrow<OutAddr>>(&mut self, out_addr: O) {
|
2018-09-28 06:13:31 -07:00
|
|
|
let peer = self.peers.get_mut(out_addr.borrow()).expect(&format!(
|
|
|
|
"Peers::establish_observer: \
|
|
|
|
No peer found with outgoing address: {}",
|
|
|
|
out_addr.borrow()
|
|
|
|
));
|
2018-07-23 12:34:08 -07:00
|
|
|
|
|
|
|
// peer.establish_observer()
|
|
|
|
panic!("Peer::set_pending: Do not use yet.");
|
2018-07-22 01:29:10 -07:00
|
|
|
}
|
|
|
|
|
2018-07-19 14:15:00 -07:00
|
|
|
/// Attempts to establish a peer as a validator, storing `pub_info`.
|
|
|
|
///
|
2018-07-22 01:29:10 -07:00
|
|
|
/// Returns `true` if the peer was already an established validator.
|
|
|
|
///
|
|
|
|
/// ### Panics
|
|
|
|
///
|
|
|
|
/// Peer state must be `Handshaking` or `EstablishedObserver`.
|
2018-07-19 14:15:00 -07:00
|
|
|
///
|
|
|
|
/// TODO: Error handling...
|
2018-09-28 06:13:31 -07:00
|
|
|
pub(crate) fn establish_validator<O: Borrow<OutAddr>>(
|
|
|
|
&mut self,
|
|
|
|
out_addr: O,
|
|
|
|
pub_info: (Uid, InAddr, PublicKey),
|
|
|
|
) -> bool {
|
|
|
|
let peer = self.peers.get_mut(out_addr.borrow()).expect(&format!(
|
|
|
|
"Peers::establish_validator: \
|
|
|
|
No peer found with outgoing address: {}",
|
|
|
|
out_addr.borrow()
|
|
|
|
));
|
2018-07-19 14:15:00 -07:00
|
|
|
match self.out_addrs.insert(pub_info.0, *out_addr.borrow()) {
|
2018-07-22 01:29:10 -07:00
|
|
|
Some(_out_addr_pub) => {
|
2018-09-28 06:13:31 -07:00
|
|
|
let pi_pub = peer
|
|
|
|
.pub_info()
|
2018-07-19 14:15:00 -07:00
|
|
|
.expect("Peers::establish_validator: internal consistency error");
|
2018-09-28 06:13:31 -07:00
|
|
|
assert!(
|
|
|
|
pub_info.0 == *pi_pub.0 && pub_info.1 == *pi_pub.1 && pub_info.2 == *pi_pub.2
|
|
|
|
);
|
2018-07-19 14:15:00 -07:00
|
|
|
assert!(peer.is_validator());
|
|
|
|
return true;
|
2018-09-28 06:13:31 -07:00
|
|
|
}
|
2018-07-22 01:29:10 -07:00
|
|
|
None => peer.establish_validator(Some(pub_info)),
|
2018-07-19 14:15:00 -07:00
|
|
|
}
|
|
|
|
false
|
2018-07-18 19:04:41 -07:00
|
|
|
}
|
2018-07-17 19:10:50 -07:00
|
|
|
|
2018-07-17 14:06:23 -07:00
|
|
|
/// Removes a peer the list if it exists.
|
|
|
|
pub(crate) fn remove<O: Borrow<OutAddr>>(&mut self, out_addr: O) {
|
|
|
|
let peer = self.peers.remove(out_addr.borrow());
|
|
|
|
if let Some(p) = peer {
|
|
|
|
if let Some(uid) = p.uid() {
|
|
|
|
self.out_addrs.remove(&uid);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-09-27 14:42:47 -07:00
|
|
|
pub(crate) fn get<O: Borrow<OutAddr>>(&self, out_addr: O) -> Option<&Peer<T>> {
|
2018-07-17 14:06:23 -07:00
|
|
|
self.peers.get(out_addr.borrow())
|
|
|
|
}
|
|
|
|
|
2018-09-27 14:42:47 -07:00
|
|
|
pub(crate) fn get_by_uid<U: Borrow<Uid>>(&self, uid: U) -> Option<&Peer<T>> {
|
2018-09-28 06:13:31 -07:00
|
|
|
self.out_addrs
|
|
|
|
.get(uid.borrow())
|
|
|
|
.and_then(|addr| self.get(addr))
|
2018-07-17 14:06:23 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
/// Returns an Iterator over the list of peers.
|
2018-09-27 14:42:47 -07:00
|
|
|
pub(crate) fn iter(&self) -> HashMapIter<OutAddr, Peer<T>> {
|
2018-07-17 14:06:23 -07:00
|
|
|
self.peers.iter()
|
|
|
|
}
|
|
|
|
|
2018-07-17 15:58:48 -07:00
|
|
|
/// Returns an Iterator over the list of peers.
|
2018-10-19 13:50:28 -07:00
|
|
|
pub fn peers(&self) -> HashMapValues<OutAddr, Peer<T>> {
|
2018-07-17 15:58:48 -07:00
|
|
|
self.peers.values()
|
|
|
|
}
|
|
|
|
|
2018-07-18 19:04:41 -07:00
|
|
|
/// Returns an iterator over the list of validators.
|
2018-10-19 13:50:28 -07:00
|
|
|
pub fn validators(&self) -> impl Iterator<Item = &Peer<T>> {
|
2018-07-18 19:04:41 -07:00
|
|
|
self.peers.values().filter(|p| p.is_validator())
|
|
|
|
}
|
|
|
|
|
2018-07-17 14:06:23 -07:00
|
|
|
/// Returns the current number of connected peers.
|
2018-10-19 13:50:28 -07:00
|
|
|
pub fn count_total(&self) -> usize {
|
2018-07-17 14:06:23 -07:00
|
|
|
self.peers.len()
|
|
|
|
}
|
2018-07-17 19:10:50 -07:00
|
|
|
|
2018-07-18 19:04:41 -07:00
|
|
|
/// Returns the current number of connected and established validators.
|
|
|
|
///
|
|
|
|
/// This is semi-expensive (O(n)).
|
2018-10-19 13:50:28 -07:00
|
|
|
pub fn count_validators(&self) -> usize {
|
2018-07-18 19:04:41 -07:00
|
|
|
self.validators().count()
|
|
|
|
}
|
|
|
|
|
2018-07-17 19:10:50 -07:00
|
|
|
pub(crate) fn contains_in_addr<I: Borrow<InAddr>>(&self, in_addr: I) -> bool {
|
2018-07-18 19:04:41 -07:00
|
|
|
for peer in self.peers.values() {
|
|
|
|
if let Some(peer_in_addr) = peer.in_addr() {
|
|
|
|
if peer_in_addr == in_addr.borrow() {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
false
|
2018-07-17 19:10:50 -07:00
|
|
|
}
|
2018-07-17 14:06:23 -07:00
|
|
|
}
|