mirror of
https://github.com/fluencelabs/rust-libp2p
synced 2025-06-23 14:51:34 +00:00
More precise errors in the nodes module (#765)
* More precise errors in the nodes module * Typo * Prove the panics
This commit is contained in:
@ -23,21 +23,21 @@ use crate::{
|
||||
muxing::StreamMuxer,
|
||||
nodes::{
|
||||
node::Substream,
|
||||
handled_node_tasks::{HandledNodesEvent, HandledNodesTasks},
|
||||
handled_node_tasks::{HandledNodesEvent, HandledNodesTasks, TaskClosedEvent},
|
||||
handled_node_tasks::{Task as HandledNodesTask, TaskId},
|
||||
handled_node::NodeHandler
|
||||
handled_node::{HandledNodeError, NodeHandler}
|
||||
}
|
||||
};
|
||||
use fnv::FnvHashMap;
|
||||
use futures::prelude::*;
|
||||
use std::{collections::hash_map::Entry, error, fmt, io, mem};
|
||||
use std::{collections::hash_map::Entry, error, fmt, mem};
|
||||
|
||||
// TODO: make generic over PeerId
|
||||
|
||||
/// Implementation of `Stream` that handles a collection of nodes.
|
||||
pub struct CollectionStream<TInEvent, TOutEvent, THandler> {
|
||||
pub struct CollectionStream<TInEvent, TOutEvent, THandler, TReachErr, THandlerErr> {
|
||||
/// Object that handles the tasks.
|
||||
inner: HandledNodesTasks<TInEvent, TOutEvent, THandler>,
|
||||
inner: HandledNodesTasks<TInEvent, TOutEvent, THandler, TReachErr, THandlerErr>,
|
||||
/// List of nodes, with the task id that handles this node. The corresponding entry in `tasks`
|
||||
/// must always be in the `Connected` state.
|
||||
nodes: FnvHashMap<PeerId, TaskId>,
|
||||
@ -46,7 +46,7 @@ pub struct CollectionStream<TInEvent, TOutEvent, THandler> {
|
||||
tasks: FnvHashMap<TaskId, TaskState>,
|
||||
}
|
||||
|
||||
impl<TInEvent, TOutEvent, THandler> fmt::Debug for CollectionStream<TInEvent, TOutEvent, THandler> {
|
||||
impl<TInEvent, TOutEvent, THandler, TReachErr, THandlerErr> fmt::Debug for CollectionStream<TInEvent, TOutEvent, THandler, TReachErr, THandlerErr> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
|
||||
let mut list = f.debug_list();
|
||||
for (id, task) in &self.tasks {
|
||||
@ -73,10 +73,10 @@ enum TaskState {
|
||||
}
|
||||
|
||||
/// Event that can happen on the `CollectionStream`.
|
||||
pub enum CollectionEvent<'a, TInEvent:'a , TOutEvent: 'a, THandler: 'a> {
|
||||
pub enum CollectionEvent<'a, TInEvent:'a , TOutEvent: 'a, THandler: 'a, TReachErr, THandlerErr> {
|
||||
/// A connection to a node has succeeded. You must use the provided event in order to accept
|
||||
/// the connection.
|
||||
NodeReached(CollectionReachEvent<'a, TInEvent, TOutEvent, THandler>),
|
||||
NodeReached(CollectionReachEvent<'a, TInEvent, TOutEvent, THandler, TReachErr, THandlerErr>),
|
||||
|
||||
/// A connection to a node has been closed.
|
||||
///
|
||||
@ -94,7 +94,7 @@ pub enum CollectionEvent<'a, TInEvent:'a , TOutEvent: 'a, THandler: 'a> {
|
||||
/// Identifier of the node.
|
||||
peer_id: PeerId,
|
||||
/// The error that happened.
|
||||
error: io::Error,
|
||||
error: HandledNodeError<THandlerErr>,
|
||||
},
|
||||
|
||||
/// An error happened on the future that was trying to reach a node.
|
||||
@ -102,7 +102,7 @@ pub enum CollectionEvent<'a, TInEvent:'a , TOutEvent: 'a, THandler: 'a> {
|
||||
/// Identifier of the reach attempt that failed.
|
||||
id: ReachAttemptId,
|
||||
/// Error that happened on the future.
|
||||
error: io::Error,
|
||||
error: TReachErr,
|
||||
/// The handler that was passed to `add_reach_attempt`.
|
||||
handler: THandler,
|
||||
},
|
||||
@ -116,8 +116,10 @@ pub enum CollectionEvent<'a, TInEvent:'a , TOutEvent: 'a, THandler: 'a> {
|
||||
},
|
||||
}
|
||||
|
||||
impl<'a, TInEvent, TOutEvent, THandler> fmt::Debug for CollectionEvent<'a, TInEvent, TOutEvent, THandler>
|
||||
where TOutEvent: fmt::Debug
|
||||
impl<'a, TInEvent, TOutEvent, THandler, TReachErr, THandlerErr> fmt::Debug for CollectionEvent<'a, TInEvent, TOutEvent, THandler, TReachErr, THandlerErr>
|
||||
where TOutEvent: fmt::Debug,
|
||||
TReachErr: fmt::Debug,
|
||||
THandlerErr: fmt::Debug,
|
||||
{
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
|
||||
match *self {
|
||||
@ -155,16 +157,16 @@ where TOutEvent: fmt::Debug
|
||||
|
||||
/// Event that happens when we reach a node.
|
||||
#[must_use = "The node reached event is used to accept the newly-opened connection"]
|
||||
pub struct CollectionReachEvent<'a, TInEvent: 'a, TOutEvent: 'a, THandler: 'a> {
|
||||
pub struct CollectionReachEvent<'a, TInEvent: 'a, TOutEvent: 'a, THandler: 'a, TReachErr, THandlerErr: 'a> {
|
||||
/// Peer id we connected to.
|
||||
peer_id: PeerId,
|
||||
/// The task id that reached the node.
|
||||
id: TaskId,
|
||||
/// The `CollectionStream` we are referencing.
|
||||
parent: &'a mut CollectionStream<TInEvent, TOutEvent, THandler>,
|
||||
parent: &'a mut CollectionStream<TInEvent, TOutEvent, THandler, TReachErr, THandlerErr>,
|
||||
}
|
||||
|
||||
impl<'a, TInEvent, TOutEvent, THandler> CollectionReachEvent<'a, TInEvent, TOutEvent, THandler> {
|
||||
impl<'a, TInEvent, TOutEvent, THandler, TReachErr, THandlerErr> CollectionReachEvent<'a, TInEvent, TOutEvent, THandler, TReachErr, THandlerErr> {
|
||||
/// Returns the peer id of the node that has been reached.
|
||||
#[inline]
|
||||
pub fn peer_id(&self) -> &PeerId {
|
||||
@ -227,7 +229,7 @@ impl<'a, TInEvent, TOutEvent, THandler> CollectionReachEvent<'a, TInEvent, TOutE
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, TInEvent, TOutEvent, THandler> fmt::Debug for CollectionReachEvent<'a, TInEvent, TOutEvent, THandler> {
|
||||
impl<'a, TInEvent, TOutEvent, THandler, TReachErr, THandlerErr> fmt::Debug for CollectionReachEvent<'a, TInEvent, TOutEvent, THandler, TReachErr, THandlerErr> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
|
||||
f.debug_struct("CollectionReachEvent")
|
||||
.field("peer_id", &self.peer_id)
|
||||
@ -236,7 +238,7 @@ impl<'a, TInEvent, TOutEvent, THandler> fmt::Debug for CollectionReachEvent<'a,
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, TInEvent, TOutEvent, THandler> Drop for CollectionReachEvent<'a, TInEvent, TOutEvent, THandler> {
|
||||
impl<'a, TInEvent, TOutEvent, THandler, TReachErr, THandlerErr> Drop for CollectionReachEvent<'a, TInEvent, TOutEvent, THandler, TReachErr, THandlerErr> {
|
||||
fn drop(&mut self) {
|
||||
let task_state = self.parent.tasks.remove(&self.id);
|
||||
debug_assert!(if let Some(TaskState::Pending) = task_state { true } else { false });
|
||||
@ -262,7 +264,7 @@ pub enum CollectionNodeAccept {
|
||||
#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq, PartialOrd, Ord)]
|
||||
pub struct ReachAttemptId(TaskId);
|
||||
|
||||
impl<TInEvent, TOutEvent, THandler> CollectionStream<TInEvent, TOutEvent, THandler> {
|
||||
impl<TInEvent, TOutEvent, THandler, TReachErr, THandlerErr> CollectionStream<TInEvent, TOutEvent, THandler, TReachErr, THandlerErr> {
|
||||
/// Creates a new empty collection.
|
||||
#[inline]
|
||||
pub fn new() -> Self {
|
||||
@ -280,9 +282,10 @@ impl<TInEvent, TOutEvent, THandler> CollectionStream<TInEvent, TOutEvent, THandl
|
||||
pub fn add_reach_attempt<TFut, TMuxer>(&mut self, future: TFut, handler: THandler)
|
||||
-> ReachAttemptId
|
||||
where
|
||||
TFut: Future<Item = (PeerId, TMuxer)> + Send + 'static,
|
||||
TFut::Error: std::error::Error + Send + Sync + 'static,
|
||||
THandler: NodeHandler<Substream = Substream<TMuxer>, InEvent = TInEvent, OutEvent = TOutEvent> + Send + 'static,
|
||||
TFut: Future<Item = (PeerId, TMuxer), Error = TReachErr> + Send + 'static,
|
||||
THandler: NodeHandler<Substream = Substream<TMuxer>, InEvent = TInEvent, OutEvent = TOutEvent, Error = THandlerErr> + Send + 'static,
|
||||
TReachErr: error::Error + Send + 'static,
|
||||
THandlerErr: error::Error + Send + 'static,
|
||||
TInEvent: Send + 'static,
|
||||
TOutEvent: Send + 'static,
|
||||
THandler::OutboundOpenInfo: Send + 'static, // TODO: shouldn't be required?
|
||||
@ -369,7 +372,7 @@ impl<TInEvent, TOutEvent, THandler> CollectionStream<TInEvent, TOutEvent, THandl
|
||||
/// > **Note**: we use a regular `poll` method instead of implementing `Stream` in order to
|
||||
/// > remove the `Err` variant, but also because we want the `CollectionStream` to stay
|
||||
/// > borrowed if necessary.
|
||||
pub fn poll(&mut self) -> Async<CollectionEvent<TInEvent, TOutEvent, THandler>> {
|
||||
pub fn poll(&mut self) -> Async<CollectionEvent<TInEvent, TOutEvent, THandler, TReachErr, THandlerErr>> {
|
||||
let item = match self.inner.poll() {
|
||||
Async::Ready(item) => item,
|
||||
Async::NotReady => return Async::NotReady,
|
||||
@ -378,16 +381,27 @@ impl<TInEvent, TOutEvent, THandler> CollectionStream<TInEvent, TOutEvent, THandl
|
||||
match item {
|
||||
HandledNodesEvent::TaskClosed { id, result, handler } => {
|
||||
match (self.tasks.remove(&id), result, handler) {
|
||||
(Some(TaskState::Pending), Err(err), Some(handler)) => {
|
||||
(Some(TaskState::Pending), Err(TaskClosedEvent::Reach(err)), Some(handler)) => {
|
||||
Async::Ready(CollectionEvent::ReachError {
|
||||
id: ReachAttemptId(id),
|
||||
error: err,
|
||||
handler,
|
||||
})
|
||||
},
|
||||
(Some(TaskState::Pending), _, _) => {
|
||||
// TODO: this variant shouldn't happen; prove this
|
||||
panic!()
|
||||
(Some(TaskState::Pending), Ok(()), _) => {
|
||||
panic!("The API of HandledNodesTasks guarantees that a task cannot \
|
||||
gracefully closed before being connected to a node, in which case \
|
||||
its state should be Connected and not Pending; QED");
|
||||
},
|
||||
(Some(TaskState::Pending), Err(TaskClosedEvent::Node(_)), _) => {
|
||||
panic!("We switch the task state to Connected once we're connected, and \
|
||||
a TaskClosedEvent::Node can only happen after we're \
|
||||
connected; QED");
|
||||
},
|
||||
(Some(TaskState::Pending), Err(TaskClosedEvent::Reach(_)), None) => {
|
||||
// TODO: this could be improved in the API of HandledNodesTasks
|
||||
panic!("The HandledNodesTasks is guaranteed to always return the handler \
|
||||
when producing a TaskClosedEvent::Reach error");
|
||||
},
|
||||
(Some(TaskState::Connected(peer_id)), Ok(()), _handler) => {
|
||||
debug_assert!(_handler.is_none());
|
||||
@ -397,7 +411,7 @@ impl<TInEvent, TOutEvent, THandler> CollectionStream<TInEvent, TOutEvent, THandl
|
||||
peer_id,
|
||||
})
|
||||
},
|
||||
(Some(TaskState::Connected(peer_id)), Err(err), _handler) => {
|
||||
(Some(TaskState::Connected(peer_id)), Err(TaskClosedEvent::Node(err)), _handler) => {
|
||||
debug_assert!(_handler.is_none());
|
||||
let _node_task_id = self.nodes.remove(&peer_id);
|
||||
debug_assert_eq!(_node_task_id, Some(id));
|
||||
@ -406,6 +420,10 @@ impl<TInEvent, TOutEvent, THandler> CollectionStream<TInEvent, TOutEvent, THandl
|
||||
error: err,
|
||||
})
|
||||
},
|
||||
(Some(TaskState::Connected(_)), Err(TaskClosedEvent::Reach(_)), _) => {
|
||||
panic!("A TaskClosedEvent::Reach can only happen before we are connected \
|
||||
to a node; therefore the TaskState won't be Connected; QED");
|
||||
},
|
||||
(None, _, _) => {
|
||||
panic!("self.tasks is always kept in sync with the tasks in self.inner; \
|
||||
when we add a task in self.inner we add a corresponding entry in \
|
||||
@ -506,11 +524,10 @@ mod tests {
|
||||
use tokio::runtime::current_thread::Runtime;
|
||||
use tokio::runtime::Builder;
|
||||
use nodes::NodeHandlerEvent;
|
||||
use std::sync::Arc;
|
||||
use std::{io, sync::Arc};
|
||||
use parking_lot::Mutex;
|
||||
use void::Void;
|
||||
|
||||
type TestCollectionStream = CollectionStream<InEvent, OutEvent, Handler>;
|
||||
type TestCollectionStream = CollectionStream<InEvent, OutEvent, Handler, io::Error, io::Error>;
|
||||
|
||||
#[test]
|
||||
fn has_connection_is_false_before_a_connection_has_been_made() {
|
||||
@ -532,7 +549,7 @@ mod tests {
|
||||
assert!(cs.peer_mut(&peer_id).is_none());
|
||||
|
||||
let handler = Handler::default();
|
||||
let fut = future::ok::<_, Void>((peer_id.clone(), DummyMuxer::new()));
|
||||
let fut = future::ok((peer_id.clone(), DummyMuxer::new()));
|
||||
cs.add_reach_attempt(fut, handler);
|
||||
assert!(cs.peer_mut(&peer_id).is_none()); // task is pending
|
||||
}
|
||||
@ -546,7 +563,7 @@ mod tests {
|
||||
muxer.set_inbound_connection_state(DummyConnectionState::Pending);
|
||||
muxer.set_outbound_connection_state(DummyConnectionState::Opened);
|
||||
|
||||
let fut = future::ok::<_, Void>((peer_id, muxer));
|
||||
let fut = future::ok((peer_id, muxer));
|
||||
cs.add_reach_attempt(fut, Handler::default());
|
||||
let mut rt = Runtime::new().unwrap();
|
||||
let mut poll_count = 0;
|
||||
@ -570,7 +587,7 @@ mod tests {
|
||||
fn accepting_a_node_yields_new_entry() {
|
||||
let mut cs = TestCollectionStream::new();
|
||||
let peer_id = PeerId::random();
|
||||
let fut = future::ok::<_, Void>((peer_id.clone(), DummyMuxer::new()));
|
||||
let fut = future::ok((peer_id.clone(), DummyMuxer::new()));
|
||||
cs.add_reach_attempt(fut, Handler::default());
|
||||
|
||||
let mut rt = Runtime::new().unwrap();
|
||||
@ -622,7 +639,7 @@ mod tests {
|
||||
muxer.set_inbound_connection_state(DummyConnectionState::Pending);
|
||||
muxer.set_outbound_connection_state(DummyConnectionState::Opened);
|
||||
|
||||
let fut = future::ok::<_, Void>((task_peer_id.clone(), muxer));
|
||||
let fut = future::ok((task_peer_id.clone(), muxer));
|
||||
cs.lock().add_reach_attempt(fut, handler);
|
||||
|
||||
let mut rt = Builder::new().core_threads(1).build().unwrap();
|
||||
@ -710,7 +727,7 @@ mod tests {
|
||||
let cs = Arc::new(Mutex::new(TestCollectionStream::new()));
|
||||
let peer_id = PeerId::random();
|
||||
let muxer = DummyMuxer::new();
|
||||
let task_inner_fut = future::ok::<_, Void>((peer_id.clone(), muxer));
|
||||
let task_inner_fut = future::ok((peer_id.clone(), muxer));
|
||||
let mut handler = Handler::default();
|
||||
handler.next_states = vec![HandlerState::Err]; // triggered when sending a NextState event
|
||||
|
||||
@ -756,7 +773,7 @@ mod tests {
|
||||
let cs = Arc::new(Mutex::new(TestCollectionStream::new()));
|
||||
let peer_id = PeerId::random();
|
||||
let muxer = DummyMuxer::new();
|
||||
let task_inner_fut = future::ok::<_, Void>((peer_id.clone(), muxer));
|
||||
let task_inner_fut = future::ok((peer_id.clone(), muxer));
|
||||
let mut handler = Handler::default();
|
||||
handler.next_states = vec![HandlerState::Ready(None)]; // triggered when sending a NextState event
|
||||
|
||||
@ -802,7 +819,7 @@ mod tests {
|
||||
#[test]
|
||||
fn interrupting_a_pending_connection_attempt_is_ok() {
|
||||
let mut cs = TestCollectionStream::new();
|
||||
let fut = future::empty::<_, Void>();
|
||||
let fut = future::empty();
|
||||
let reach_id = cs.add_reach_attempt(fut, Handler::default());
|
||||
let interrupt = cs.interrupt(reach_id);
|
||||
assert!(interrupt.is_ok());
|
||||
@ -811,7 +828,7 @@ mod tests {
|
||||
#[test]
|
||||
fn interrupting_a_connection_attempt_twice_is_err() {
|
||||
let mut cs = TestCollectionStream::new();
|
||||
let fut = future::empty::<_, Void>();
|
||||
let fut = future::empty();
|
||||
let reach_id = cs.add_reach_attempt(fut, Handler::default());
|
||||
assert!(cs.interrupt(reach_id).is_ok());
|
||||
assert_matches!(cs.interrupt(reach_id), Err(InterruptError::ReachAttemptNotFound))
|
||||
@ -822,7 +839,7 @@ mod tests {
|
||||
let cs = Arc::new(Mutex::new(TestCollectionStream::new()));
|
||||
let peer_id = PeerId::random();
|
||||
let muxer = DummyMuxer::new();
|
||||
let task_inner_fut = future::ok::<_, Void>((peer_id.clone(), muxer));
|
||||
let task_inner_fut = future::ok((peer_id.clone(), muxer));
|
||||
let handler = Handler::default();
|
||||
|
||||
let reach_id = cs.lock().add_reach_attempt(task_inner_fut, handler);
|
||||
|
@ -21,7 +21,7 @@
|
||||
use muxing::StreamMuxer;
|
||||
use nodes::node::{NodeEvent, NodeStream, Substream};
|
||||
use futures::{prelude::*, stream::Fuse};
|
||||
use std::{io::Error as IoError, fmt};
|
||||
use std::{error, fmt, io};
|
||||
|
||||
/// Handler for the substreams of a node.
|
||||
// TODO: right now it is possible for a node handler to be built, then shut down right after if we
|
||||
@ -32,6 +32,8 @@ pub trait NodeHandler {
|
||||
type InEvent;
|
||||
/// Custom event that can be produced by the handler and that will be returned by the swarm.
|
||||
type OutEvent;
|
||||
/// Error that can happen during the processing of the node.
|
||||
type Error;
|
||||
/// The type of the substream containing the data.
|
||||
type Substream;
|
||||
/// Information about a substream. Can be sent to the handler through a `NodeHandlerEndpoint`,
|
||||
@ -74,7 +76,7 @@ pub trait NodeHandler {
|
||||
|
||||
/// Should behave like `Stream::poll()`. Should close if no more event can be produced and the
|
||||
/// node should be closed.
|
||||
fn poll(&mut self) -> Poll<Option<NodeHandlerEvent<Self::OutboundOpenInfo, Self::OutEvent>>, IoError>;
|
||||
fn poll(&mut self) -> Poll<Option<NodeHandlerEvent<Self::OutboundOpenInfo, Self::OutEvent>>, Self::Error>;
|
||||
}
|
||||
|
||||
/// Endpoint for a received substream.
|
||||
@ -248,7 +250,7 @@ where
|
||||
THandler: NodeHandler<Substream = Substream<TMuxer>>,
|
||||
{
|
||||
type Item = THandler::OutEvent;
|
||||
type Error = IoError;
|
||||
type Error = HandledNodeError<THandler::Error>;
|
||||
|
||||
fn poll(&mut self) -> Poll<Option<Self::Item>, Self::Error> {
|
||||
loop {
|
||||
@ -258,7 +260,7 @@ where
|
||||
|
||||
let mut node_not_ready = false;
|
||||
|
||||
match self.node.poll()? {
|
||||
match self.node.poll().map_err(HandledNodeError::Node)? {
|
||||
Async::NotReady => node_not_ready = true,
|
||||
Async::Ready(Some(NodeEvent::InboundSubstream { substream })) => {
|
||||
self.handler.inject_substream(substream, NodeHandlerEndpoint::Listener)
|
||||
@ -281,7 +283,7 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
match if self.handler_is_done { Async::Ready(None) } else { self.handler.poll()? } {
|
||||
match if self.handler_is_done { Async::Ready(None) } else { self.handler.poll().map_err(HandledNodeError::Handler)? } {
|
||||
Async::NotReady => {
|
||||
if node_not_ready {
|
||||
break
|
||||
@ -316,13 +318,45 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
/// Error that can happen when polling a `HandledNode`.
|
||||
#[derive(Debug)]
|
||||
pub enum HandledNodeError<THandlerErr> {
|
||||
/// An error happend in the stream muxer.
|
||||
// TODO: eventually this should also be a custom error
|
||||
Node(io::Error),
|
||||
/// An error happened in the handler of the connection to the node.
|
||||
Handler(THandlerErr),
|
||||
}
|
||||
|
||||
impl<THandlerErr> fmt::Display for HandledNodeError<THandlerErr>
|
||||
where THandlerErr: fmt::Display
|
||||
{
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
match self {
|
||||
HandledNodeError::Node(err) => write!(f, "{}", err),
|
||||
HandledNodeError::Handler(err) => write!(f, "{}", err),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<THandlerErr> error::Error for HandledNodeError<THandlerErr>
|
||||
where THandlerErr: error::Error + 'static
|
||||
{
|
||||
fn source(&self) -> Option<&(dyn error::Error + 'static)> {
|
||||
match self {
|
||||
HandledNodeError::Node(err) => Some(err),
|
||||
HandledNodeError::Handler(err) => Some(err),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use tokio::runtime::current_thread;
|
||||
use tests::dummy_muxer::{DummyMuxer, DummyConnectionState};
|
||||
use tests::dummy_handler::{Handler, HandlerState, InEvent, OutEvent, TestHandledNode};
|
||||
use std::marker::PhantomData;
|
||||
use std::{io, marker::PhantomData};
|
||||
|
||||
struct TestBuilder {
|
||||
muxer: DummyMuxer,
|
||||
@ -389,6 +423,7 @@ mod tests {
|
||||
type InEvent = ();
|
||||
type OutEvent = ();
|
||||
type Substream = T;
|
||||
type Error = io::Error;
|
||||
type OutboundOpenInfo = ();
|
||||
fn inject_substream(&mut self, _: Self::Substream, _: NodeHandlerEndpoint<Self::OutboundOpenInfo>) { panic!() }
|
||||
fn inject_inbound_closed(&mut self) {
|
||||
@ -405,7 +440,7 @@ mod tests {
|
||||
assert!(self.substream_attempt_cancelled);
|
||||
self.shutdown_called = true;
|
||||
}
|
||||
fn poll(&mut self) -> Poll<Option<NodeHandlerEvent<(), ()>>, IoError> {
|
||||
fn poll(&mut self) -> Poll<Option<NodeHandlerEvent<(), ()>>, io::Error> {
|
||||
if self.shutdown_called {
|
||||
Ok(Async::Ready(None))
|
||||
} else if !self.did_substream_attempt {
|
||||
|
@ -22,7 +22,7 @@ use crate::{
|
||||
PeerId,
|
||||
muxing::StreamMuxer,
|
||||
nodes::{
|
||||
handled_node::{HandledNode, NodeHandler},
|
||||
handled_node::{HandledNode, HandledNodeError, NodeHandler},
|
||||
node::Substream
|
||||
}
|
||||
};
|
||||
@ -31,8 +31,8 @@ use futures::{prelude::*, stream, sync::mpsc};
|
||||
use smallvec::SmallVec;
|
||||
use std::{
|
||||
collections::hash_map::{Entry, OccupiedEntry},
|
||||
error,
|
||||
fmt,
|
||||
io::{self, Error as IoError},
|
||||
mem
|
||||
};
|
||||
use tokio_executor;
|
||||
@ -57,7 +57,7 @@ use void::Void;
|
||||
// conditions in the user's code. See similar comments in the documentation of `NodeStream`.
|
||||
|
||||
/// Implementation of `Stream` that handles a collection of nodes.
|
||||
pub struct HandledNodesTasks<TInEvent, TOutEvent, THandler> {
|
||||
pub struct HandledNodesTasks<TInEvent, TOutEvent, THandler, TReachErr, THandlerErr> {
|
||||
/// A map between active tasks to an unbounded sender, used to control the task. Closing the sender interrupts
|
||||
/// the task. It is possible that we receive messages from tasks that used to be in this list
|
||||
/// but no longer are, in which case we should ignore them.
|
||||
@ -71,12 +71,12 @@ pub struct HandledNodesTasks<TInEvent, TOutEvent, THandler> {
|
||||
to_spawn: SmallVec<[Box<Future<Item = (), Error = ()> + Send>; 8]>,
|
||||
|
||||
/// Sender to emit events to the outside. Meant to be cloned and sent to tasks.
|
||||
events_tx: mpsc::UnboundedSender<(InToExtMessage<TOutEvent, THandler>, TaskId)>,
|
||||
events_tx: mpsc::UnboundedSender<(InToExtMessage<TOutEvent, THandler, TReachErr, THandlerErr>, TaskId)>,
|
||||
/// Receiver side for the events.
|
||||
events_rx: mpsc::UnboundedReceiver<(InToExtMessage<TOutEvent, THandler>, TaskId)>,
|
||||
events_rx: mpsc::UnboundedReceiver<(InToExtMessage<TOutEvent, THandler, TReachErr, THandlerErr>, TaskId)>,
|
||||
}
|
||||
|
||||
impl<TInEvent, TOutEvent, THandler> fmt::Debug for HandledNodesTasks<TInEvent, TOutEvent, THandler> {
|
||||
impl<TInEvent, TOutEvent, THandler, TReachErr, THandlerErr> fmt::Debug for HandledNodesTasks<TInEvent, TOutEvent, THandler, TReachErr, THandlerErr> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
|
||||
f.debug_list()
|
||||
.entries(self.tasks.keys().cloned())
|
||||
@ -84,9 +84,44 @@ impl<TInEvent, TOutEvent, THandler> fmt::Debug for HandledNodesTasks<TInEvent, T
|
||||
}
|
||||
}
|
||||
|
||||
/// Error that can happen in a task.
|
||||
#[derive(Debug)]
|
||||
pub enum TaskClosedEvent<TReachErr, THandlerErr> {
|
||||
/// An error happend while we were trying to reach the node.
|
||||
Reach(TReachErr),
|
||||
/// An error happened after the node has been reached.
|
||||
Node(HandledNodeError<THandlerErr>),
|
||||
}
|
||||
|
||||
impl<TReachErr, THandlerErr> fmt::Display for TaskClosedEvent<TReachErr, THandlerErr>
|
||||
where
|
||||
TReachErr: fmt::Display,
|
||||
THandlerErr: fmt::Display,
|
||||
{
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
match self {
|
||||
TaskClosedEvent::Reach(err) => write!(f, "{}", err),
|
||||
TaskClosedEvent::Node(err) => write!(f, "{}", err),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<TReachErr, THandlerErr> error::Error for TaskClosedEvent<TReachErr, THandlerErr>
|
||||
where
|
||||
TReachErr: error::Error + 'static,
|
||||
THandlerErr: error::Error + 'static
|
||||
{
|
||||
fn source(&self) -> Option<&(dyn error::Error + 'static)> {
|
||||
match self {
|
||||
TaskClosedEvent::Reach(err) => Some(err),
|
||||
TaskClosedEvent::Node(err) => Some(err),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Event that can happen on the `HandledNodesTasks`.
|
||||
#[derive(Debug)]
|
||||
pub enum HandledNodesEvent<TOutEvent, THandler> {
|
||||
pub enum HandledNodesEvent<TOutEvent, THandler, TReachErr, THandlerErr> {
|
||||
/// A task has been closed.
|
||||
///
|
||||
/// This happens once the node handler closes or an error happens.
|
||||
@ -95,7 +130,7 @@ pub enum HandledNodesEvent<TOutEvent, THandler> {
|
||||
/// Identifier of the task that closed.
|
||||
id: TaskId,
|
||||
/// What happened.
|
||||
result: Result<(), IoError>,
|
||||
result: Result<(), TaskClosedEvent<TReachErr, THandlerErr>>,
|
||||
/// If the task closed before reaching the node, this contains the handler that was passed
|
||||
/// to `add_reach_attempt`.
|
||||
handler: Option<THandler>,
|
||||
@ -122,7 +157,7 @@ pub enum HandledNodesEvent<TOutEvent, THandler> {
|
||||
#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq, PartialOrd, Ord)]
|
||||
pub struct TaskId(usize);
|
||||
|
||||
impl<TInEvent, TOutEvent, THandler> HandledNodesTasks<TInEvent, TOutEvent, THandler> {
|
||||
impl<TInEvent, TOutEvent, THandler, TReachErr, THandlerErr> HandledNodesTasks<TInEvent, TOutEvent, THandler, TReachErr, THandlerErr> {
|
||||
/// Creates a new empty collection.
|
||||
#[inline]
|
||||
pub fn new() -> Self {
|
||||
@ -143,9 +178,10 @@ impl<TInEvent, TOutEvent, THandler> HandledNodesTasks<TInEvent, TOutEvent, THand
|
||||
/// events.
|
||||
pub fn add_reach_attempt<TFut, TMuxer>(&mut self, future: TFut, handler: THandler) -> TaskId
|
||||
where
|
||||
TFut: Future<Item = (PeerId, TMuxer)> + Send + 'static,
|
||||
TFut::Error: std::error::Error + Send + Sync + 'static,
|
||||
THandler: NodeHandler<Substream = Substream<TMuxer>, InEvent = TInEvent, OutEvent = TOutEvent> + Send + 'static,
|
||||
TFut: Future<Item = (PeerId, TMuxer), Error = TReachErr> + Send + 'static,
|
||||
THandler: NodeHandler<Substream = Substream<TMuxer>, InEvent = TInEvent, OutEvent = TOutEvent, Error = THandlerErr> + Send + 'static,
|
||||
TReachErr: error::Error + Send + 'static,
|
||||
THandlerErr: error::Error + Send + 'static,
|
||||
TInEvent: Send + 'static,
|
||||
TOutEvent: Send + 'static,
|
||||
THandler::OutboundOpenInfo: Send + 'static, // TODO: shouldn't be required?
|
||||
@ -203,7 +239,7 @@ impl<TInEvent, TOutEvent, THandler> HandledNodesTasks<TInEvent, TOutEvent, THand
|
||||
}
|
||||
|
||||
/// Provides an API similar to `Stream`, except that it cannot produce an error.
|
||||
pub fn poll(&mut self) -> Async<HandledNodesEvent<TOutEvent, THandler>> {
|
||||
pub fn poll(&mut self) -> Async<HandledNodesEvent<TOutEvent, THandler, TReachErr, THandlerErr>> {
|
||||
for to_spawn in self.to_spawn.drain() {
|
||||
tokio_executor::spawn(to_spawn);
|
||||
}
|
||||
@ -289,8 +325,8 @@ impl<'a, TInEvent> fmt::Debug for Task<'a, TInEvent> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<TInEvent, TOutEvent, THandler> Stream for HandledNodesTasks<TInEvent, TOutEvent, THandler> {
|
||||
type Item = HandledNodesEvent<TOutEvent, THandler>;
|
||||
impl<TInEvent, TOutEvent, THandler, TReachErr, THandlerErr> Stream for HandledNodesTasks<TInEvent, TOutEvent, THandler, TReachErr, THandlerErr> {
|
||||
type Item = HandledNodesEvent<TOutEvent, THandler, TReachErr, THandlerErr>;
|
||||
type Error = Void; // TODO: use ! once stable
|
||||
|
||||
#[inline]
|
||||
@ -301,24 +337,24 @@ impl<TInEvent, TOutEvent, THandler> Stream for HandledNodesTasks<TInEvent, TOutE
|
||||
|
||||
/// Message to transmit from a task to the public API.
|
||||
#[derive(Debug)]
|
||||
enum InToExtMessage<TOutEvent, THandler> {
|
||||
enum InToExtMessage<TOutEvent, THandler, TReachErr, THandlerErr> {
|
||||
/// A connection to a node has succeeded.
|
||||
NodeReached(PeerId),
|
||||
/// The task closed.
|
||||
TaskClosed(Result<(), IoError>, Option<THandler>),
|
||||
TaskClosed(Result<(), TaskClosedEvent<TReachErr, THandlerErr>>, Option<THandler>),
|
||||
/// An event from the node.
|
||||
NodeEvent(TOutEvent),
|
||||
}
|
||||
|
||||
/// Implementation of `Future` that handles a single node, and all the communications between
|
||||
/// the various components of the `HandledNodesTasks`.
|
||||
struct NodeTask<TFut, TMuxer, THandler, TInEvent, TOutEvent>
|
||||
struct NodeTask<TFut, TMuxer, THandler, TInEvent, TOutEvent, TReachErr>
|
||||
where
|
||||
TMuxer: StreamMuxer,
|
||||
THandler: NodeHandler<Substream = Substream<TMuxer>>,
|
||||
{
|
||||
/// Sender to transmit events to the outside.
|
||||
events_tx: mpsc::UnboundedSender<(InToExtMessage<TOutEvent, THandler>, TaskId)>,
|
||||
events_tx: mpsc::UnboundedSender<(InToExtMessage<TOutEvent, THandler, TReachErr, THandler::Error>, TaskId)>,
|
||||
/// Receiving end for events sent from the main `HandledNodesTasks`.
|
||||
in_events_rx: stream::Fuse<mpsc::UnboundedReceiver<TInEvent>>,
|
||||
/// Inner state of the `NodeTask`.
|
||||
@ -351,12 +387,11 @@ where
|
||||
Poisoned,
|
||||
}
|
||||
|
||||
impl<TFut, TMuxer, THandler, TInEvent, TOutEvent> Future for
|
||||
NodeTask<TFut, TMuxer, THandler, TInEvent, TOutEvent>
|
||||
impl<TFut, TMuxer, THandler, TInEvent, TOutEvent, TReachErr> Future for
|
||||
NodeTask<TFut, TMuxer, THandler, TInEvent, TOutEvent, TReachErr>
|
||||
where
|
||||
TMuxer: StreamMuxer,
|
||||
TFut: Future<Item = (PeerId, TMuxer)>,
|
||||
TFut::Error: std::error::Error + Send + Sync + 'static,
|
||||
TFut: Future<Item = (PeerId, TMuxer), Error = TReachErr>,
|
||||
THandler: NodeHandler<Substream = Substream<TMuxer>, InEvent = TInEvent, OutEvent = TOutEvent>,
|
||||
{
|
||||
type Item = ();
|
||||
@ -395,8 +430,7 @@ where
|
||||
},
|
||||
Err(err) => {
|
||||
// End the task
|
||||
let ioerr = IoError::new(io::ErrorKind::Other, err);
|
||||
let event = InToExtMessage::TaskClosed(Err(ioerr), Some(handler));
|
||||
let event = InToExtMessage::TaskClosed(Err(TaskClosedEvent::Reach(err)), Some(handler));
|
||||
let _ = self.events_tx.unbounded_send((event, self.id));
|
||||
return Ok(Async::Ready(()));
|
||||
}
|
||||
@ -442,7 +476,7 @@ where
|
||||
return Ok(Async::Ready(())); // End the task.
|
||||
}
|
||||
Err(err) => {
|
||||
let event = InToExtMessage::TaskClosed(Err(err), None);
|
||||
let event = InToExtMessage::TaskClosed(Err(TaskClosedEvent::Node(err)), None);
|
||||
let _ = self.events_tx.unbounded_send((event, self.id));
|
||||
return Ok(Async::Ready(())); // End the task.
|
||||
}
|
||||
@ -475,17 +509,18 @@ mod tests {
|
||||
use PeerId;
|
||||
|
||||
type TestNodeTask = NodeTask<
|
||||
FutureResult<(PeerId, DummyMuxer), IoError>,
|
||||
FutureResult<(PeerId, DummyMuxer), io::Error>,
|
||||
DummyMuxer,
|
||||
Handler,
|
||||
InEvent,
|
||||
OutEvent,
|
||||
io::Error,
|
||||
>;
|
||||
|
||||
struct NodeTaskTestBuilder {
|
||||
task_id: TaskId,
|
||||
inner_node: Option<TestHandledNode>,
|
||||
inner_fut: Option<FutureResult<(PeerId, DummyMuxer), IoError>>,
|
||||
inner_fut: Option<FutureResult<(PeerId, DummyMuxer), io::Error>>,
|
||||
}
|
||||
|
||||
impl NodeTaskTestBuilder {
|
||||
@ -500,7 +535,7 @@ mod tests {
|
||||
}
|
||||
}
|
||||
|
||||
fn with_inner_fut(&mut self, fut: FutureResult<(PeerId, DummyMuxer), IoError>) -> &mut Self{
|
||||
fn with_inner_fut(&mut self, fut: FutureResult<(PeerId, DummyMuxer), io::Error>) -> &mut Self{
|
||||
self.inner_fut = Some(fut);
|
||||
self
|
||||
}
|
||||
@ -513,9 +548,9 @@ mod tests {
|
||||
fn node_task(&mut self) -> (
|
||||
TestNodeTask,
|
||||
UnboundedSender<InEvent>,
|
||||
UnboundedReceiver<(InToExtMessage<OutEvent, Handler>, TaskId)>,
|
||||
UnboundedReceiver<(InToExtMessage<OutEvent, Handler, io::Error, io::Error>, TaskId)>,
|
||||
) {
|
||||
let (events_from_node_task_tx, events_from_node_task_rx) = mpsc::unbounded::<(InToExtMessage<OutEvent, Handler>, TaskId)>();
|
||||
let (events_from_node_task_tx, events_from_node_task_rx) = mpsc::unbounded::<(InToExtMessage<OutEvent, Handler, _, _>, TaskId)>();
|
||||
let (events_to_node_task_tx, events_to_node_task_rx) = mpsc::unbounded::<InEvent>();
|
||||
let inner = if self.inner_node.is_some() {
|
||||
NodeTaskInner::Node(self.inner_node.take().unwrap())
|
||||
@ -536,7 +571,7 @@ mod tests {
|
||||
}
|
||||
}
|
||||
|
||||
type TestHandledNodesTasks = HandledNodesTasks<InEvent, OutEvent, Handler>;
|
||||
type TestHandledNodesTasks = HandledNodesTasks<InEvent, OutEvent, Handler, io::Error, io::Error>;
|
||||
|
||||
struct HandledNodeTaskTestBuilder {
|
||||
muxer: DummyMuxer,
|
||||
@ -578,7 +613,7 @@ mod tests {
|
||||
let peer_id = PeerId::random();
|
||||
let mut task_ids = Vec::new();
|
||||
for _i in 0..self.task_count {
|
||||
let fut = future::ok::<_, Void>((peer_id.clone(), self.muxer.clone()));
|
||||
let fut = future::ok((peer_id.clone(), self.muxer.clone()));
|
||||
task_ids.push(
|
||||
handled_nodes.add_reach_attempt(fut, self.handler.clone())
|
||||
);
|
||||
@ -743,7 +778,7 @@ mod tests {
|
||||
.handled_nodes_tasks();
|
||||
|
||||
let mut rt = Runtime::new().unwrap();
|
||||
let mut events: (Option<HandledNodesEvent<_,_>>, TestHandledNodesTasks);
|
||||
let mut events: (Option<HandledNodesEvent<_, _, _, _>>, TestHandledNodesTasks);
|
||||
// we're running on a single thread so events are sequential: first
|
||||
// we get a NodeReached, then a TaskClosed
|
||||
for i in 0..5 {
|
||||
|
@ -30,7 +30,10 @@ use crate::{
|
||||
PeerMut as CollecPeerMut,
|
||||
ReachAttemptId
|
||||
},
|
||||
handled_node::NodeHandler,
|
||||
handled_node::{
|
||||
HandledNodeError,
|
||||
NodeHandler
|
||||
},
|
||||
node::Substream
|
||||
},
|
||||
nodes::listeners::{ListenersEvent, ListenersStream},
|
||||
@ -39,14 +42,15 @@ use crate::{
|
||||
use fnv::FnvHashMap;
|
||||
use futures::{prelude::*, future};
|
||||
use std::{
|
||||
fmt,
|
||||
collections::hash_map::{Entry, OccupiedEntry},
|
||||
error,
|
||||
fmt,
|
||||
io::{Error as IoError, ErrorKind as IoErrorKind}
|
||||
};
|
||||
|
||||
/// Implementation of `Stream` that handles the nodes.
|
||||
#[derive(Debug)]
|
||||
pub struct RawSwarm<TTrans, TInEvent, TOutEvent, THandler>
|
||||
pub struct RawSwarm<TTrans, TInEvent, TOutEvent, THandler, THandlerErr>
|
||||
where
|
||||
TTrans: Transport,
|
||||
{
|
||||
@ -54,7 +58,7 @@ where
|
||||
listeners: ListenersStream<TTrans>,
|
||||
|
||||
/// The nodes currently active.
|
||||
active_nodes: CollectionStream<TInEvent, TOutEvent, THandler>,
|
||||
active_nodes: CollectionStream<TInEvent, TOutEvent, THandler, RawSwarmReachError, THandlerErr>,
|
||||
|
||||
/// The reach attempts of the swarm.
|
||||
/// This needs to be a separate struct in order to handle multiple mutable borrows issues.
|
||||
@ -89,7 +93,7 @@ struct OutReachAttempt {
|
||||
}
|
||||
|
||||
/// Event that can happen on the `RawSwarm`.
|
||||
pub enum RawSwarmEvent<'a, TTrans: 'a, TInEvent: 'a, TOutEvent: 'a, THandler: 'a>
|
||||
pub enum RawSwarmEvent<'a, TTrans: 'a, TInEvent: 'a, TOutEvent: 'a, THandler: 'a, THandlerErr: 'a>
|
||||
where
|
||||
TTrans: Transport,
|
||||
{
|
||||
@ -104,7 +108,7 @@ where
|
||||
},
|
||||
|
||||
/// A new connection arrived on a listener.
|
||||
IncomingConnection(IncomingConnectionEvent<'a, TTrans, TInEvent, TOutEvent, THandler>),
|
||||
IncomingConnection(IncomingConnectionEvent<'a, TTrans, TInEvent, TOutEvent, THandler, THandlerErr>),
|
||||
|
||||
/// A new connection was arriving on a listener, but an error happened when negotiating it.
|
||||
///
|
||||
@ -150,14 +154,14 @@ where
|
||||
endpoint: ConnectedPoint,
|
||||
},
|
||||
|
||||
/// The muxer of a node has produced an error.
|
||||
/// The handler of a node has produced an error.
|
||||
NodeError {
|
||||
/// Identifier of the node.
|
||||
peer_id: PeerId,
|
||||
/// Endpoint we were connected to.
|
||||
endpoint: ConnectedPoint,
|
||||
/// The error that happened.
|
||||
error: IoError,
|
||||
error: HandledNodeError<THandlerErr>,
|
||||
},
|
||||
|
||||
/// Failed to reach a peer that we were trying to dial.
|
||||
@ -174,7 +178,7 @@ where
|
||||
multiaddr: Multiaddr,
|
||||
|
||||
/// The error that happened.
|
||||
error: IoError,
|
||||
error: RawSwarmReachError,
|
||||
},
|
||||
|
||||
/// Failed to reach a peer that we were trying to dial.
|
||||
@ -198,10 +202,11 @@ where
|
||||
},
|
||||
}
|
||||
|
||||
impl<'a, TTrans, TInEvent, TOutEvent, THandler> fmt::Debug for RawSwarmEvent<'a, TTrans, TInEvent, TOutEvent, THandler>
|
||||
impl<'a, TTrans, TInEvent, TOutEvent, THandler, THandlerErr> fmt::Debug for RawSwarmEvent<'a, TTrans, TInEvent, TOutEvent, THandler, THandlerErr>
|
||||
where
|
||||
TOutEvent: fmt::Debug,
|
||||
TTrans: Transport,
|
||||
THandlerErr: fmt::Debug,
|
||||
{
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
|
||||
match *self {
|
||||
@ -274,9 +279,42 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
/// Error that can happen when trying to reach a node.
|
||||
#[derive(Debug)]
|
||||
pub enum RawSwarmReachError {
|
||||
/// Error in the transport layer.
|
||||
// TODO: better error type
|
||||
Transport(IoError),
|
||||
/// We successfully reached the peer, but there was a mismatch between the expected id and the
|
||||
/// actual id of the peer.
|
||||
PeerIdMismatch {
|
||||
/// The peer id that the node reports.
|
||||
obtained: PeerId,
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for RawSwarmReachError {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
match self {
|
||||
RawSwarmReachError::Transport(err) => write!(f, "{}", err),
|
||||
RawSwarmReachError::PeerIdMismatch { obtained } => {
|
||||
write!(f, "Peer ID mismatch, obtained: {}", obtained.to_base58())
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl error::Error for RawSwarmReachError {
|
||||
fn source(&self) -> Option<&(dyn error::Error + 'static)> {
|
||||
match self {
|
||||
RawSwarmReachError::Transport(err) => Some(err),
|
||||
RawSwarmReachError::PeerIdMismatch { .. } => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// A new connection arrived on a listener.
|
||||
pub struct IncomingConnectionEvent<'a, TTrans: 'a, TInEvent: 'a, TOutEvent: 'a, THandler: 'a>
|
||||
pub struct IncomingConnectionEvent<'a, TTrans: 'a, TInEvent: 'a, TOutEvent: 'a, THandler: 'a, THandlerErr: 'a>
|
||||
where TTrans: Transport
|
||||
{
|
||||
/// The produced upgrade.
|
||||
@ -286,17 +324,19 @@ where TTrans: Transport
|
||||
/// Address used to send back data to the remote.
|
||||
send_back_addr: Multiaddr,
|
||||
/// Reference to the `active_nodes` field of the swarm.
|
||||
active_nodes: &'a mut CollectionStream<TInEvent, TOutEvent, THandler>,
|
||||
active_nodes: &'a mut CollectionStream<TInEvent, TOutEvent, THandler, RawSwarmReachError, THandlerErr>,
|
||||
/// Reference to the `other_reach_attempts` field of the swarm.
|
||||
other_reach_attempts: &'a mut Vec<(ReachAttemptId, ConnectedPoint)>,
|
||||
}
|
||||
|
||||
impl<'a, TTrans, TInEvent, TOutEvent, TMuxer, THandler> IncomingConnectionEvent<'a, TTrans, TInEvent, TOutEvent, THandler>
|
||||
impl<'a, TTrans, TInEvent, TOutEvent, TMuxer, THandler, THandlerErr>
|
||||
IncomingConnectionEvent<'a, TTrans, TInEvent, TOutEvent, THandler, THandlerErr>
|
||||
where
|
||||
TTrans: Transport<Output = (PeerId, TMuxer)>,
|
||||
TTrans::ListenerUpgrade: Send + 'static,
|
||||
THandler: NodeHandler<Substream = Substream<TMuxer>, InEvent = TInEvent, OutEvent = TOutEvent> + Send + 'static,
|
||||
THandler: NodeHandler<Substream = Substream<TMuxer>, InEvent = TInEvent, OutEvent = TOutEvent, Error = THandlerErr> + Send + 'static,
|
||||
THandler::OutboundOpenInfo: Send + 'static, // TODO: shouldn't be necessary
|
||||
THandlerErr: error::Error + Send + 'static,
|
||||
TMuxer: StreamMuxer + Send + Sync + 'static,
|
||||
TMuxer::OutboundSubstream: Send,
|
||||
TMuxer::Substream: Send,
|
||||
@ -315,7 +355,7 @@ where
|
||||
{
|
||||
let connected_point = self.to_connected_point();
|
||||
let handler = builder(&connected_point);
|
||||
let id = self.active_nodes.add_reach_attempt(self.upgrade, handler);
|
||||
let id = self.active_nodes.add_reach_attempt(self.upgrade.map_err(RawSwarmReachError::Transport), handler);
|
||||
self.other_reach_attempts.push((
|
||||
id,
|
||||
connected_point,
|
||||
@ -323,7 +363,7 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, TTrans, TInEvent, TOutEvent, THandler> IncomingConnectionEvent<'a, TTrans, TInEvent, TOutEvent, THandler>
|
||||
impl<'a, TTrans, TInEvent, TOutEvent, THandler, THandlerErr> IncomingConnectionEvent<'a, TTrans, TInEvent, TOutEvent, THandler, THandlerErr>
|
||||
where TTrans: Transport
|
||||
{
|
||||
/// Address of the listener that received the connection.
|
||||
@ -409,13 +449,14 @@ impl ConnectedPoint {
|
||||
}
|
||||
}
|
||||
|
||||
impl<TTrans, TInEvent, TOutEvent, TMuxer, THandler>
|
||||
RawSwarm<TTrans, TInEvent, TOutEvent, THandler>
|
||||
impl<TTrans, TInEvent, TOutEvent, TMuxer, THandler, THandlerErr>
|
||||
RawSwarm<TTrans, TInEvent, TOutEvent, THandler, THandlerErr>
|
||||
where
|
||||
TTrans: Transport + Clone,
|
||||
TMuxer: StreamMuxer,
|
||||
THandler: NodeHandler<Substream = Substream<TMuxer>, InEvent = TInEvent, OutEvent = TOutEvent> + Send + 'static,
|
||||
THandler: NodeHandler<Substream = Substream<TMuxer>, InEvent = TInEvent, OutEvent = TOutEvent, Error = THandlerErr> + Send + 'static,
|
||||
THandler::OutboundOpenInfo: Send + 'static, // TODO: shouldn't be necessary
|
||||
THandlerErr: error::Error + Send + 'static,
|
||||
{
|
||||
/// Creates a new node events stream.
|
||||
#[inline]
|
||||
@ -497,7 +538,7 @@ where
|
||||
};
|
||||
|
||||
let connected_point = ConnectedPoint::Dialer { address: addr };
|
||||
let reach_id = self.active_nodes.add_reach_attempt(future, handler);
|
||||
let reach_id = self.active_nodes.add_reach_attempt(future.map_err(RawSwarmReachError::Transport), handler);
|
||||
self.reach_attempts.other_reach_attempts.push((reach_id, connected_point));
|
||||
Ok(())
|
||||
}
|
||||
@ -527,7 +568,7 @@ where
|
||||
|
||||
/// Grants access to a struct that represents a peer.
|
||||
#[inline]
|
||||
pub fn peer(&mut self, peer_id: PeerId) -> Peer<TTrans, TInEvent, TOutEvent, THandler> {
|
||||
pub fn peer(&mut self, peer_id: PeerId) -> Peer<TTrans, TInEvent, TOutEvent, THandler, THandlerErr> {
|
||||
// TODO: we do `peer_mut(...).is_some()` followed with `peer_mut(...).unwrap()`, otherwise
|
||||
// the borrow checker yells at us.
|
||||
|
||||
@ -579,20 +620,21 @@ where
|
||||
let reach_id = match self.transport().clone().dial(first.clone()) {
|
||||
Ok(fut) => {
|
||||
let expected_peer_id = peer_id.clone();
|
||||
let fut = fut.and_then(move |(actual_peer_id, muxer)| {
|
||||
let fut = fut
|
||||
.map_err(RawSwarmReachError::Transport)
|
||||
.and_then(move |(actual_peer_id, muxer)| {
|
||||
if actual_peer_id == expected_peer_id {
|
||||
Ok((actual_peer_id, muxer))
|
||||
} else {
|
||||
let msg = format!("public key mismatch; expected = {:?}; obtained = {:?}",
|
||||
expected_peer_id, actual_peer_id);
|
||||
Err(IoError::new(IoErrorKind::Other, msg))
|
||||
Err(RawSwarmReachError::PeerIdMismatch { obtained: actual_peer_id })
|
||||
}
|
||||
});
|
||||
self.active_nodes.add_reach_attempt(fut, handler)
|
||||
},
|
||||
Err((_, addr)) => {
|
||||
// TODO: better error reporting
|
||||
let msg = format!("unsupported multiaddr {}", addr);
|
||||
let fut = future::err(IoError::new(IoErrorKind::Other, msg));
|
||||
let fut = future::err(RawSwarmReachError::Transport(IoError::new(IoErrorKind::Other, msg)));
|
||||
self.active_nodes.add_reach_attempt(fut, handler)
|
||||
},
|
||||
};
|
||||
@ -610,7 +652,7 @@ where
|
||||
}
|
||||
|
||||
/// Provides an API similar to `Stream`, except that it cannot error.
|
||||
pub fn poll(&mut self) -> Async<RawSwarmEvent<TTrans, TInEvent, TOutEvent, THandler>>
|
||||
pub fn poll(&mut self) -> Async<RawSwarmEvent<TTrans, TInEvent, TOutEvent, THandler, THandlerErr>>
|
||||
where
|
||||
TTrans: Transport<Output = (PeerId, TMuxer)>,
|
||||
TTrans::Dial: Send + 'static,
|
||||
@ -620,8 +662,9 @@ where
|
||||
TMuxer::Substream: Send,
|
||||
TInEvent: Send + 'static,
|
||||
TOutEvent: Send + 'static,
|
||||
THandler: NodeHandler<Substream = Substream<TMuxer>, InEvent = TInEvent, OutEvent = TOutEvent> + Send + 'static,
|
||||
THandler: NodeHandler<Substream = Substream<TMuxer>, InEvent = TInEvent, OutEvent = TOutEvent, Error = THandlerErr> + Send + 'static,
|
||||
THandler::OutboundOpenInfo: Send + 'static, // TODO: shouldn't be necessary
|
||||
THandlerErr: error::Error + Send + 'static,
|
||||
{
|
||||
// Start by polling the listeners for events.
|
||||
match self.listeners.poll() {
|
||||
@ -737,10 +780,10 @@ impl<THandler> Default for ActionItem<THandler> {
|
||||
///
|
||||
/// > **Note**: The event **must** have been produced by the collection of nodes, otherwise
|
||||
/// > panics will likely happen.
|
||||
fn handle_node_reached<'a, TTrans, TMuxer, TInEvent, TOutEvent, THandler>(
|
||||
fn handle_node_reached<'a, TTrans, TMuxer, TInEvent, TOutEvent, THandler, THandlerErr>(
|
||||
reach_attempts: &mut ReachAttempts,
|
||||
event: CollectionReachEvent<TInEvent, TOutEvent, THandler>
|
||||
) -> (ActionItem<THandler>, RawSwarmEvent<'a, TTrans, TInEvent, TOutEvent, THandler>)
|
||||
event: CollectionReachEvent<TInEvent, TOutEvent, THandler, RawSwarmReachError, THandlerErr>
|
||||
) -> (ActionItem<THandler>, RawSwarmEvent<'a, TTrans, TInEvent, TOutEvent, THandler, THandlerErr>)
|
||||
where
|
||||
TTrans: Transport<Output = (PeerId, TMuxer)> + Clone,
|
||||
TMuxer: StreamMuxer + Send + Sync + 'static,
|
||||
@ -866,12 +909,12 @@ fn has_dial_prio(local: &PeerId, other: &PeerId) -> bool {
|
||||
///
|
||||
/// > **Note**: The event **must** have been produced by the collection of nodes, otherwise
|
||||
/// > panics will likely happen.
|
||||
fn handle_reach_error<'a, TTrans, TInEvent, TOutEvent, THandler>(
|
||||
fn handle_reach_error<'a, TTrans, TInEvent, TOutEvent, THandler, THandlerErr>(
|
||||
reach_attempts: &mut ReachAttempts,
|
||||
reach_id: ReachAttemptId,
|
||||
error: IoError,
|
||||
error: RawSwarmReachError,
|
||||
handler: THandler,
|
||||
) -> (ActionItem<THandler>, RawSwarmEvent<'a, TTrans, TInEvent, TOutEvent, THandler>)
|
||||
) -> (ActionItem<THandler>, RawSwarmEvent<'a, TTrans, TInEvent, TOutEvent, THandler, THandlerErr>)
|
||||
where TTrans: Transport
|
||||
{
|
||||
// Search for the attempt in `out_reach_attempts`.
|
||||
@ -914,6 +957,10 @@ where TTrans: Transport
|
||||
.position(|i| i.0 == reach_id)
|
||||
{
|
||||
let (_, endpoint) = reach_attempts.other_reach_attempts.swap_remove(in_pos);
|
||||
let error = match error {
|
||||
RawSwarmReachError::Transport(err) => err,
|
||||
RawSwarmReachError::PeerIdMismatch { .. } => unreachable!(), // TODO: prove
|
||||
};
|
||||
match endpoint {
|
||||
ConnectedPoint::Dialer { address } => {
|
||||
return (Default::default(), RawSwarmEvent::UnknownPeerDialError {
|
||||
@ -939,7 +986,7 @@ where TTrans: Transport
|
||||
}
|
||||
|
||||
/// State of a peer in the system.
|
||||
pub enum Peer<'a, TTrans: 'a, TInEvent: 'a, TOutEvent: 'a, THandler: 'a>
|
||||
pub enum Peer<'a, TTrans: 'a, TInEvent: 'a, TOutEvent: 'a, THandler: 'a, THandlerErr: 'a>
|
||||
where
|
||||
TTrans: Transport,
|
||||
{
|
||||
@ -947,16 +994,16 @@ where
|
||||
Connected(PeerConnected<'a, TInEvent>),
|
||||
|
||||
/// We are currently attempting to connect to this peer.
|
||||
PendingConnect(PeerPendingConnect<'a, TInEvent, TOutEvent, THandler>),
|
||||
PendingConnect(PeerPendingConnect<'a, TInEvent, TOutEvent, THandler, THandlerErr>),
|
||||
|
||||
/// We are not connected to this peer at all.
|
||||
///
|
||||
/// > **Note**: It is however possible that a pending incoming connection is being negotiated
|
||||
/// > and will connect to this peer, but we don't know it yet.
|
||||
NotConnected(PeerNotConnected<'a, TTrans, TInEvent, TOutEvent, THandler>),
|
||||
NotConnected(PeerNotConnected<'a, TTrans, TInEvent, TOutEvent, THandler, THandlerErr>),
|
||||
}
|
||||
|
||||
impl<'a, TTrans, TInEvent, TOutEvent, THandler> fmt::Debug for Peer<'a, TTrans, TInEvent, TOutEvent, THandler>
|
||||
impl<'a, TTrans, TInEvent, TOutEvent, THandler, THandlerErr> fmt::Debug for Peer<'a, TTrans, TInEvent, TOutEvent, THandler, THandlerErr>
|
||||
where
|
||||
TTrans: Transport,
|
||||
{
|
||||
@ -983,8 +1030,8 @@ where
|
||||
}
|
||||
|
||||
// TODO: add other similar methods that wrap to the ones of `PeerNotConnected`
|
||||
impl<'a, TTrans, TMuxer, TInEvent, TOutEvent, THandler>
|
||||
Peer<'a, TTrans, TInEvent, TOutEvent, THandler>
|
||||
impl<'a, TTrans, TMuxer, TInEvent, TOutEvent, THandler, THandlerErr>
|
||||
Peer<'a, TTrans, TInEvent, TOutEvent, THandler, THandlerErr>
|
||||
where
|
||||
TTrans: Transport<Output = (PeerId, TMuxer)> + Clone,
|
||||
TTrans::Dial: Send + 'static,
|
||||
@ -993,8 +1040,9 @@ where
|
||||
TMuxer::Substream: Send,
|
||||
TInEvent: Send + 'static,
|
||||
TOutEvent: Send + 'static,
|
||||
THandler: NodeHandler<Substream = Substream<TMuxer>, InEvent = TInEvent, OutEvent = TOutEvent> + Send + 'static,
|
||||
THandler: NodeHandler<Substream = Substream<TMuxer>, InEvent = TInEvent, OutEvent = TOutEvent, Error = THandlerErr> + Send + 'static,
|
||||
THandler::OutboundOpenInfo: Send + 'static,
|
||||
THandlerErr: error::Error + Send + 'static,
|
||||
{
|
||||
/// If we are connected, returns the `PeerConnected`.
|
||||
#[inline]
|
||||
@ -1007,7 +1055,7 @@ where
|
||||
|
||||
/// If a connection is pending, returns the `PeerPendingConnect`.
|
||||
#[inline]
|
||||
pub fn as_pending_connect(self) -> Option<PeerPendingConnect<'a, TInEvent, TOutEvent, THandler>> {
|
||||
pub fn as_pending_connect(self) -> Option<PeerPendingConnect<'a, TInEvent, TOutEvent, THandler, THandlerErr>> {
|
||||
match self {
|
||||
Peer::PendingConnect(peer) => Some(peer),
|
||||
_ => None,
|
||||
@ -1016,7 +1064,7 @@ where
|
||||
|
||||
/// If we are not connected, returns the `PeerNotConnected`.
|
||||
#[inline]
|
||||
pub fn as_not_connected(self) -> Option<PeerNotConnected<'a, TTrans, TInEvent, TOutEvent, THandler>> {
|
||||
pub fn as_not_connected(self) -> Option<PeerNotConnected<'a, TTrans, TInEvent, TOutEvent, THandler, THandlerErr>> {
|
||||
match self {
|
||||
Peer::NotConnected(peer) => Some(peer),
|
||||
_ => None,
|
||||
@ -1033,7 +1081,7 @@ where
|
||||
/// > node.
|
||||
#[inline]
|
||||
pub fn or_connect(self, addr: Multiaddr, handler: THandler)
|
||||
-> Result<PeerPotentialConnect<'a, TInEvent, TOutEvent, THandler>, Self>
|
||||
-> Result<PeerPotentialConnect<'a, TInEvent, TOutEvent, THandler, THandlerErr>, Self>
|
||||
{
|
||||
self.or_connect_with(move |_| addr, handler)
|
||||
}
|
||||
@ -1049,7 +1097,7 @@ where
|
||||
/// > node.
|
||||
#[inline]
|
||||
pub fn or_connect_with<TFn>(self, addr: TFn, handler: THandler)
|
||||
-> Result<PeerPotentialConnect<'a, TInEvent, TOutEvent, THandler>, Self>
|
||||
-> Result<PeerPotentialConnect<'a, TInEvent, TOutEvent, THandler, THandlerErr>, Self>
|
||||
where
|
||||
TFn: FnOnce(&PeerId) -> Multiaddr,
|
||||
{
|
||||
@ -1068,15 +1116,15 @@ where
|
||||
}
|
||||
|
||||
/// Peer we are potentially going to connect to.
|
||||
pub enum PeerPotentialConnect<'a, TInEvent: 'a, TOutEvent: 'a, THandler: 'a> {
|
||||
pub enum PeerPotentialConnect<'a, TInEvent: 'a, TOutEvent: 'a, THandler: 'a, THandlerErr: 'a> {
|
||||
/// We are connected to this peer.
|
||||
Connected(PeerConnected<'a, TInEvent>),
|
||||
|
||||
/// We are currently attempting to connect to this peer.
|
||||
PendingConnect(PeerPendingConnect<'a, TInEvent, TOutEvent, THandler>),
|
||||
PendingConnect(PeerPendingConnect<'a, TInEvent, TOutEvent, THandler, THandlerErr>),
|
||||
}
|
||||
|
||||
impl<'a, TInEvent, TOutEvent, THandler> PeerPotentialConnect<'a, TInEvent, TOutEvent, THandler> {
|
||||
impl<'a, TInEvent, TOutEvent, THandler, THandlerErr> PeerPotentialConnect<'a, TInEvent, TOutEvent, THandler, THandlerErr> {
|
||||
/// Closes the connection or the connection attempt.
|
||||
///
|
||||
/// If the connection was active, returns the list of outbound substream openings that were
|
||||
@ -1101,7 +1149,7 @@ impl<'a, TInEvent, TOutEvent, THandler> PeerPotentialConnect<'a, TInEvent, TOutE
|
||||
|
||||
/// If a connection is pending, returns the `PeerPendingConnect`.
|
||||
#[inline]
|
||||
pub fn as_pending_connect(self) -> Option<PeerPendingConnect<'a, TInEvent, TOutEvent, THandler>> {
|
||||
pub fn as_pending_connect(self) -> Option<PeerPendingConnect<'a, TInEvent, TOutEvent, THandler, THandlerErr>> {
|
||||
match self {
|
||||
PeerPotentialConnect::PendingConnect(peer) => Some(peer),
|
||||
_ => None,
|
||||
@ -1147,12 +1195,12 @@ impl<'a, TInEvent> PeerConnected<'a, TInEvent> {
|
||||
|
||||
/// Access to a peer we are attempting to connect to.
|
||||
#[derive(Debug)]
|
||||
pub struct PeerPendingConnect<'a, TInEvent: 'a, TOutEvent: 'a, THandler: 'a> {
|
||||
pub struct PeerPendingConnect<'a, TInEvent: 'a, TOutEvent: 'a, THandler: 'a, THandlerErr: 'a> {
|
||||
attempt: OccupiedEntry<'a, PeerId, OutReachAttempt>,
|
||||
active_nodes: &'a mut CollectionStream<TInEvent, TOutEvent, THandler>,
|
||||
active_nodes: &'a mut CollectionStream<TInEvent, TOutEvent, THandler, RawSwarmReachError, THandlerErr>,
|
||||
}
|
||||
|
||||
impl<'a, TInEvent, TOutEvent, THandler> PeerPendingConnect<'a, TInEvent, TOutEvent, THandler> {
|
||||
impl<'a, TInEvent, TOutEvent, THandler, THandlerErr> PeerPendingConnect<'a, TInEvent, TOutEvent, THandler, THandlerErr> {
|
||||
/// Interrupt this connection attempt.
|
||||
// TODO: consider returning a PeerNotConnected; however that is really pain in terms of
|
||||
// borrows
|
||||
@ -1195,24 +1243,25 @@ impl<'a, TInEvent, TOutEvent, THandler> PeerPendingConnect<'a, TInEvent, TOutEve
|
||||
|
||||
/// Access to a peer we're not connected to.
|
||||
#[derive(Debug)]
|
||||
pub struct PeerNotConnected<'a, TTrans: 'a, TInEvent: 'a, TOutEvent: 'a, THandler: 'a>
|
||||
pub struct PeerNotConnected<'a, TTrans: 'a, TInEvent: 'a, TOutEvent: 'a, THandler: 'a, THandlerErr: 'a>
|
||||
where
|
||||
TTrans: Transport,
|
||||
{
|
||||
peer_id: PeerId,
|
||||
nodes: &'a mut RawSwarm<TTrans, TInEvent, TOutEvent, THandler>,
|
||||
nodes: &'a mut RawSwarm<TTrans, TInEvent, TOutEvent, THandler, THandlerErr>,
|
||||
}
|
||||
|
||||
impl<'a, TTrans, TInEvent, TOutEvent, TMuxer, THandler>
|
||||
PeerNotConnected<'a, TTrans, TInEvent, TOutEvent, THandler>
|
||||
impl<'a, TTrans, TInEvent, TOutEvent, TMuxer, THandler, THandlerErr>
|
||||
PeerNotConnected<'a, TTrans, TInEvent, TOutEvent, THandler, THandlerErr>
|
||||
where
|
||||
TTrans: Transport<Output = (PeerId, TMuxer)> + Clone,
|
||||
TTrans::Dial: Send + 'static,
|
||||
TMuxer: StreamMuxer + Send + Sync + 'static,
|
||||
TMuxer::OutboundSubstream: Send,
|
||||
TMuxer::Substream: Send,
|
||||
THandler: NodeHandler<Substream = Substream<TMuxer>, InEvent = TInEvent, OutEvent = TOutEvent> + Send + 'static,
|
||||
THandler: NodeHandler<Substream = Substream<TMuxer>, InEvent = TInEvent, OutEvent = TOutEvent, Error = THandlerErr> + Send + 'static,
|
||||
THandler::OutboundOpenInfo: Send + 'static, // TODO: shouldn't be necessary
|
||||
THandlerErr: error::Error + Send + 'static,
|
||||
TInEvent: Send + 'static,
|
||||
TOutEvent: Send + 'static,
|
||||
{
|
||||
@ -1221,7 +1270,7 @@ where
|
||||
/// If we reach a peer but the `PeerId` doesn't correspond to the one we're expecting, then
|
||||
/// the whole connection is immediately closed.
|
||||
#[inline]
|
||||
pub fn connect(self, addr: Multiaddr, handler: THandler) -> Result<PeerPendingConnect<'a, TInEvent, TOutEvent, THandler>, Self> {
|
||||
pub fn connect(self, addr: Multiaddr, handler: THandler) -> Result<PeerPendingConnect<'a, TInEvent, TOutEvent, THandler, THandlerErr>, Self> {
|
||||
self.connect_inner(handler, addr, Vec::new())
|
||||
}
|
||||
|
||||
@ -1235,7 +1284,7 @@ where
|
||||
/// the whole connection is immediately closed.
|
||||
#[inline]
|
||||
pub fn connect_iter<TIter>(self, addrs: TIter, handler: THandler)
|
||||
-> Result<PeerPendingConnect<'a, TInEvent, TOutEvent, THandler>, Self>
|
||||
-> Result<PeerPendingConnect<'a, TInEvent, TOutEvent, THandler, THandlerErr>, Self>
|
||||
where
|
||||
TIter: IntoIterator<Item = Multiaddr>,
|
||||
{
|
||||
@ -1250,7 +1299,7 @@ where
|
||||
|
||||
/// Inner implementation of `connect`.
|
||||
fn connect_inner(self, handler: THandler, first: Multiaddr, rest: Vec<Multiaddr>)
|
||||
-> Result<PeerPendingConnect<'a, TInEvent, TOutEvent, THandler>, Self>
|
||||
-> Result<PeerPendingConnect<'a, TInEvent, TOutEvent, THandler, THandlerErr>, Self>
|
||||
{
|
||||
self.nodes.start_dial_out(self.peer_id.clone(), handler, first, rest);
|
||||
Ok(PeerPendingConnect {
|
||||
@ -1281,13 +1330,13 @@ mod tests {
|
||||
fn query_transport() {
|
||||
let transport = DummyTransport::new();
|
||||
let transport2 = transport.clone();
|
||||
let raw_swarm = RawSwarm::<_, _, _, Handler>::new(transport, PeerId::random());
|
||||
let raw_swarm = RawSwarm::<_, _, _, Handler, _>::new(transport, PeerId::random());
|
||||
assert_eq!(raw_swarm.transport(), &transport2);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn starts_listening() {
|
||||
let mut raw_swarm = RawSwarm::<_, _, _, Handler>::new(DummyTransport::new(), PeerId::random());
|
||||
let mut raw_swarm = RawSwarm::<_, _, _, Handler, _>::new(DummyTransport::new(), PeerId::random());
|
||||
let addr = "/ip4/127.0.0.1/tcp/1234".parse::<Multiaddr>().expect("bad multiaddr");
|
||||
let addr2 = addr.clone();
|
||||
assert!(raw_swarm.listen_on(addr).is_ok());
|
||||
@ -1300,7 +1349,7 @@ mod tests {
|
||||
fn nat_traversal_transforms_the_observed_address_according_to_the_transport_used() {
|
||||
// the DummyTransport nat_traversal increments the port number by one for Ip4 addresses
|
||||
let transport = DummyTransport::new();
|
||||
let mut raw_swarm = RawSwarm::<_, _, _, Handler>::new(transport, PeerId::random());
|
||||
let mut raw_swarm = RawSwarm::<_, _, _, Handler, _>::new(transport, PeerId::random());
|
||||
let addr1 = "/ip4/127.0.0.1/tcp/1234".parse::<Multiaddr>().expect("bad multiaddr");
|
||||
// An unrelated outside address is returned as-is, no transform
|
||||
let outside_addr1 = "/memory".parse::<Multiaddr>().expect("bad multiaddr");
|
||||
@ -1328,7 +1377,7 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn successful_dial_reaches_a_node() {
|
||||
let mut swarm = RawSwarm::<_, _, _, Handler>::new(DummyTransport::new(), PeerId::random());
|
||||
let mut swarm = RawSwarm::<_, _, _, Handler, _>::new(DummyTransport::new(), PeerId::random());
|
||||
let addr = "/ip4/127.0.0.1/tcp/1234".parse::<Multiaddr>().expect("bad multiaddr");
|
||||
let dial_res = swarm.dial(addr, Handler::default());
|
||||
assert!(dial_res.is_ok());
|
||||
@ -1366,7 +1415,7 @@ mod tests {
|
||||
// Set up listener to see an incoming connection
|
||||
transport.set_initial_listener_state(ListenerState::Ok(Async::Ready(Some((peer_id, muxer)))));
|
||||
|
||||
let mut swarm = RawSwarm::<_, _, _, Handler>::new(transport, PeerId::random());
|
||||
let mut swarm = RawSwarm::<_, _, _, Handler, _>::new(transport, PeerId::random());
|
||||
swarm.listen_on("/memory".parse().unwrap()).unwrap();
|
||||
|
||||
// no incoming yet
|
||||
@ -1391,7 +1440,7 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn broadcasted_events_reach_active_nodes() {
|
||||
let mut swarm = RawSwarm::<_, _, _, Handler>::new(DummyTransport::new(), PeerId::random());
|
||||
let mut swarm = RawSwarm::<_, _, _, Handler, _>::new(DummyTransport::new(), PeerId::random());
|
||||
let mut muxer = DummyMuxer::new();
|
||||
muxer.set_inbound_connection_state(DummyConnectionState::Pending);
|
||||
muxer.set_outbound_connection_state(DummyConnectionState::Opened);
|
||||
@ -1438,7 +1487,7 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn querying_for_pending_peer() {
|
||||
let mut swarm = RawSwarm::<_, _, _, Handler>::new(DummyTransport::new(), PeerId::random());
|
||||
let mut swarm = RawSwarm::<_, _, _, Handler, _>::new(DummyTransport::new(), PeerId::random());
|
||||
let peer_id = PeerId::random();
|
||||
let peer = swarm.peer(peer_id.clone());
|
||||
assert_matches!(peer, Peer::NotConnected(PeerNotConnected{ .. }));
|
||||
@ -1450,7 +1499,7 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn querying_for_unknown_peer() {
|
||||
let mut swarm = RawSwarm::<_, _, _, Handler>::new(DummyTransport::new(), PeerId::random());
|
||||
let mut swarm = RawSwarm::<_, _, _, Handler, _>::new(DummyTransport::new(), PeerId::random());
|
||||
let peer_id = PeerId::random();
|
||||
let peer = swarm.peer(peer_id.clone());
|
||||
assert_matches!(peer, Peer::NotConnected( PeerNotConnected { nodes: _, peer_id: node_peer_id }) => {
|
||||
@ -1460,7 +1509,7 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn querying_for_connected_peer() {
|
||||
let mut swarm = RawSwarm::<_, _, _, Handler>::new(DummyTransport::new(), PeerId::random());
|
||||
let mut swarm = RawSwarm::<_, _, _, Handler, _>::new(DummyTransport::new(), PeerId::random());
|
||||
|
||||
// Dial a node
|
||||
let addr = "/ip4/127.0.0.1/tcp/1234".parse().expect("bad multiaddr");
|
||||
@ -1494,7 +1543,7 @@ mod tests {
|
||||
// Set up listener to be closed
|
||||
transport.set_initial_listener_state(ListenerState::Ok(Async::Ready(None)));
|
||||
|
||||
let mut swarm = RawSwarm::<_, _, _, Handler>::new(transport, PeerId::random());
|
||||
let mut swarm = RawSwarm::<_, _, _, Handler, _>::new(transport, PeerId::random());
|
||||
swarm.listen_on("/memory".parse().unwrap()).unwrap();
|
||||
|
||||
let mut rt = Runtime::new().unwrap();
|
||||
@ -1513,7 +1562,7 @@ mod tests {
|
||||
fn unknown_peer_that_is_unreachable_yields_unknown_peer_dial_error() {
|
||||
let mut transport = DummyTransport::new();
|
||||
transport.make_dial_fail();
|
||||
let mut swarm = RawSwarm::<_, _, _, Handler>::new(transport, PeerId::random());
|
||||
let mut swarm = RawSwarm::<_, _, _, Handler, _>::new(transport, PeerId::random());
|
||||
let addr = "/memory".parse::<Multiaddr>().expect("bad multiaddr");
|
||||
let handler = Handler::default();
|
||||
let dial_result = swarm.dial(addr, handler);
|
||||
@ -1544,7 +1593,7 @@ mod tests {
|
||||
let peer_id = PeerId::random();
|
||||
transport.set_next_peer_id(&peer_id);
|
||||
transport.make_dial_fail();
|
||||
let swarm = Arc::new(Mutex::new(RawSwarm::<_, _, _, Handler>::new(transport, PeerId::random())));
|
||||
let swarm = Arc::new(Mutex::new(RawSwarm::<_, _, _, Handler, _>::new(transport, PeerId::random())));
|
||||
|
||||
{
|
||||
let swarm1 = swarm.clone();
|
||||
@ -1584,7 +1633,7 @@ mod tests {
|
||||
let mut transport = DummyTransport::new();
|
||||
let peer_id = PeerId::random();
|
||||
transport.set_next_peer_id(&peer_id);
|
||||
let swarm = Arc::new(Mutex::new(RawSwarm::<_, _, _, Handler>::new(transport, PeerId::random())));
|
||||
let swarm = Arc::new(Mutex::new(RawSwarm::<_, _, _, Handler, _>::new(transport, PeerId::random())));
|
||||
|
||||
{
|
||||
// Set up an outgoing connection with a PeerId we know
|
||||
@ -1638,7 +1687,7 @@ mod tests {
|
||||
let mut transport = DummyTransport::new();
|
||||
let peer_id = PeerId::random();
|
||||
transport.set_next_peer_id(&peer_id);
|
||||
let swarm = Arc::new(Mutex::new(RawSwarm::<_, _, _, Handler>::new(transport, PeerId::random())));
|
||||
let swarm = Arc::new(Mutex::new(RawSwarm::<_, _, _, Handler, _>::new(transport, PeerId::random())));
|
||||
|
||||
{
|
||||
// Set up an outgoing connection with a PeerId we know
|
||||
|
@ -123,6 +123,7 @@ where
|
||||
{
|
||||
type InEvent = TProtoHandler::InEvent;
|
||||
type OutEvent = TProtoHandler::OutEvent;
|
||||
type Error = io::Error; // TODO: better error type
|
||||
type Substream = TProtoHandler::Substream;
|
||||
// The first element of the tuple is the unique upgrade identifier
|
||||
// (see `unique_dial_upgrade_id`).
|
||||
|
@ -45,6 +45,7 @@ where TTransport: Transport,
|
||||
<<TBehaviour as NetworkBehaviour<TTopology>>::ProtocolsHandler as ProtocolsHandler>::InEvent,
|
||||
<<TBehaviour as NetworkBehaviour<TTopology>>::ProtocolsHandler as ProtocolsHandler>::OutEvent,
|
||||
NodeHandlerWrapper<TBehaviour::ProtocolsHandler>,
|
||||
io::Error,
|
||||
>,
|
||||
|
||||
/// Handles which nodes to connect to and how to handle the events sent back by the protocol
|
||||
|
@ -84,6 +84,7 @@ pub(crate) type TestHandledNode = HandledNode<DummyMuxer, Handler>;
|
||||
impl NodeHandler for Handler {
|
||||
type InEvent = InEvent;
|
||||
type OutEvent = OutEvent;
|
||||
type Error = IoError;
|
||||
type OutboundOpenInfo = usize;
|
||||
type Substream = SubstreamRef<Arc<DummyMuxer>>;
|
||||
fn inject_substream(
|
||||
|
Reference in New Issue
Block a user