mirror of
https://github.com/fluencelabs/rust-libp2p
synced 2025-04-25 11:02:12 +00:00
Allow StreamMuxer to notify changes in the address (#1621)
* Allow StreamMuxer to notify changes in the address * Fix doc link * Revert accidental rename * Other accidental rename Co-authored-by: Roman Borschel <romanb@users.noreply.github.com>
This commit is contained in:
parent
d5b26359bb
commit
826f5130cd
@ -1,3 +1,12 @@
|
|||||||
|
# 0.20.0 [????-??-??]
|
||||||
|
|
||||||
|
- Rename `StreamMuxer::poll_inbound` to `poll_event` and change the
|
||||||
|
return value to `StreamMuxerEvent`. This new `StreamMuxerEvent` makes
|
||||||
|
it possible for the multiplexing layer to notify the upper layers of
|
||||||
|
a change in the address of the underlying connection.
|
||||||
|
|
||||||
|
- Add `ConnectionHandler::inject_address_change`.
|
||||||
|
|
||||||
# 0.19.2 [2020-06-22]
|
# 0.19.2 [2020-06-22]
|
||||||
|
|
||||||
- Add PartialOrd and Ord for PeerId
|
- Add PartialOrd and Ord for PeerId
|
||||||
|
@ -132,6 +132,16 @@ impl ConnectedPoint {
|
|||||||
ConnectedPoint::Listener { .. } => true
|
ConnectedPoint::Listener { .. } => true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Modifies the address of the remote stored in this struct.
|
||||||
|
///
|
||||||
|
/// For `Dialer`, this modifies `address`. For `Listener`, this modifies `send_back_addr`.
|
||||||
|
pub fn set_remote_address(&mut self, new_address: Multiaddr) {
|
||||||
|
match self {
|
||||||
|
ConnectedPoint::Dialer { address } => *address = new_address,
|
||||||
|
ConnectedPoint::Listener { send_back_addr, .. } => *send_back_addr = new_address,
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Information about a successfully established connection.
|
/// Information about a successfully established connection.
|
||||||
@ -169,6 +179,15 @@ impl ConnectionInfo for PeerId {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Event generated by a [`Connection`].
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub enum Event<T> {
|
||||||
|
/// Event generated by the [`ConnectionHandler`].
|
||||||
|
Handler(T),
|
||||||
|
/// Address of the remote has changed.
|
||||||
|
AddressChange(Multiaddr),
|
||||||
|
}
|
||||||
|
|
||||||
/// A multiplexed connection to a peer with an associated `ConnectionHandler`.
|
/// A multiplexed connection to a peer with an associated `ConnectionHandler`.
|
||||||
pub struct Connection<TMuxer, THandler>
|
pub struct Connection<TMuxer, THandler>
|
||||||
where
|
where
|
||||||
@ -239,7 +258,7 @@ where
|
|||||||
/// Polls the connection for events produced by the associated handler
|
/// Polls the connection for events produced by the associated handler
|
||||||
/// as a result of I/O activity on the substream multiplexer.
|
/// as a result of I/O activity on the substream multiplexer.
|
||||||
pub fn poll(mut self: Pin<&mut Self>, cx: &mut Context)
|
pub fn poll(mut self: Pin<&mut Self>, cx: &mut Context)
|
||||||
-> Poll<Result<THandler::OutEvent, ConnectionError<THandler::Error>>>
|
-> Poll<Result<Event<THandler::OutEvent>, ConnectionError<THandler::Error>>>
|
||||||
{
|
{
|
||||||
loop {
|
loop {
|
||||||
let mut io_pending = false;
|
let mut io_pending = false;
|
||||||
@ -255,6 +274,10 @@ where
|
|||||||
let endpoint = SubstreamEndpoint::Dialer(user_data);
|
let endpoint = SubstreamEndpoint::Dialer(user_data);
|
||||||
self.handler.inject_substream(substream, endpoint)
|
self.handler.inject_substream(substream, endpoint)
|
||||||
}
|
}
|
||||||
|
Poll::Ready(Ok(SubstreamEvent::AddressChange(address))) => {
|
||||||
|
self.handler.inject_address_change(&address);
|
||||||
|
return Poll::Ready(Ok(Event::AddressChange(address)));
|
||||||
|
}
|
||||||
Poll::Ready(Err(err)) => return Poll::Ready(Err(ConnectionError::IO(err))),
|
Poll::Ready(Err(err)) => return Poll::Ready(Err(ConnectionError::IO(err))),
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -269,7 +292,7 @@ where
|
|||||||
self.muxing.open_substream(user_data);
|
self.muxing.open_substream(user_data);
|
||||||
}
|
}
|
||||||
Poll::Ready(Ok(ConnectionHandlerEvent::Custom(event))) => {
|
Poll::Ready(Ok(ConnectionHandlerEvent::Custom(event))) => {
|
||||||
return Poll::Ready(Ok(event));
|
return Poll::Ready(Ok(Event::Handler(event)));
|
||||||
}
|
}
|
||||||
Poll::Ready(Err(err)) => return Poll::Ready(Err(ConnectionError::Handler(err))),
|
Poll::Ready(Err(err)) => return Poll::Ready(Err(ConnectionError::Handler(err))),
|
||||||
}
|
}
|
||||||
|
@ -18,7 +18,7 @@
|
|||||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||||
// DEALINGS IN THE SOFTWARE.
|
// DEALINGS IN THE SOFTWARE.
|
||||||
|
|
||||||
use crate::PeerId;
|
use crate::{Multiaddr, PeerId};
|
||||||
use std::{task::Context, task::Poll};
|
use std::{task::Context, task::Poll};
|
||||||
use super::{Connected, SubstreamEndpoint};
|
use super::{Connected, SubstreamEndpoint};
|
||||||
|
|
||||||
@ -58,6 +58,9 @@ pub trait ConnectionHandler {
|
|||||||
/// Notifies the handler of an event.
|
/// Notifies the handler of an event.
|
||||||
fn inject_event(&mut self, event: Self::InEvent);
|
fn inject_event(&mut self, event: Self::InEvent);
|
||||||
|
|
||||||
|
/// Notifies the handler of a change in the address of the remote.
|
||||||
|
fn inject_address_change(&mut self, new_address: &Multiaddr);
|
||||||
|
|
||||||
/// Polls the handler for events.
|
/// Polls the handler for events.
|
||||||
///
|
///
|
||||||
/// Returning an error will close the connection to the remote.
|
/// Returning an error will close the connection to the remote.
|
||||||
|
@ -32,11 +32,13 @@ use std::{
|
|||||||
collections::hash_map,
|
collections::hash_map,
|
||||||
error,
|
error,
|
||||||
fmt,
|
fmt,
|
||||||
|
mem,
|
||||||
pin::Pin,
|
pin::Pin,
|
||||||
task::{Context, Poll},
|
task::{Context, Poll},
|
||||||
};
|
};
|
||||||
use super::{
|
use super::{
|
||||||
Connected,
|
Connected,
|
||||||
|
ConnectedPoint,
|
||||||
Connection,
|
Connection,
|
||||||
ConnectionError,
|
ConnectionError,
|
||||||
ConnectionHandler,
|
ConnectionHandler,
|
||||||
@ -220,7 +222,17 @@ pub enum Event<'a, I, O, H, TE, HE, C> {
|
|||||||
entry: EstablishedEntry<'a, I, C>,
|
entry: EstablishedEntry<'a, I, C>,
|
||||||
/// The produced event.
|
/// The produced event.
|
||||||
event: O
|
event: O
|
||||||
}
|
},
|
||||||
|
|
||||||
|
/// A connection to a node has changed its address.
|
||||||
|
AddressChange {
|
||||||
|
/// The entry associated with the connection that changed address.
|
||||||
|
entry: EstablishedEntry<'a, I, C>,
|
||||||
|
/// The former [`ConnectedPoint`].
|
||||||
|
old_endpoint: ConnectedPoint,
|
||||||
|
/// The new [`ConnectedPoint`].
|
||||||
|
new_endpoint: ConnectedPoint,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<I, O, H, TE, HE, C> Manager<I, O, H, TE, HE, C> {
|
impl<I, O, H, TE, HE, C> Manager<I, O, H, TE, HE, C> {
|
||||||
@ -369,6 +381,23 @@ impl<I, O, H, TE, HE, C> Manager<I, O, H, TE, HE, C> {
|
|||||||
let _ = task.remove();
|
let _ = task.remove();
|
||||||
Event::PendingConnectionError { id, error, handler }
|
Event::PendingConnectionError { id, error, handler }
|
||||||
}
|
}
|
||||||
|
task::Event::AddressChange { id: _, new_address } => {
|
||||||
|
let (new, old) = if let TaskState::Established(c) = &mut task.get_mut().state {
|
||||||
|
let mut new_endpoint = c.endpoint.clone();
|
||||||
|
new_endpoint.set_remote_address(new_address);
|
||||||
|
let old_endpoint = mem::replace(&mut c.endpoint, new_endpoint.clone());
|
||||||
|
(new_endpoint, old_endpoint)
|
||||||
|
} else {
|
||||||
|
unreachable!(
|
||||||
|
"`Event::AddressChange` implies (2) occurred on that task and thus (3)."
|
||||||
|
)
|
||||||
|
};
|
||||||
|
Event::AddressChange {
|
||||||
|
entry: EstablishedEntry { task },
|
||||||
|
old_endpoint: old,
|
||||||
|
new_endpoint: new,
|
||||||
|
}
|
||||||
|
},
|
||||||
task::Event::Error { id, error } => {
|
task::Event::Error { id, error } => {
|
||||||
let id = ConnectionId(id);
|
let id = ConnectionId(id);
|
||||||
let task = task.remove();
|
let task = task.remove();
|
||||||
|
@ -19,8 +19,10 @@
|
|||||||
// DEALINGS IN THE SOFTWARE.
|
// DEALINGS IN THE SOFTWARE.
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
|
Multiaddr,
|
||||||
muxing::StreamMuxer,
|
muxing::StreamMuxer,
|
||||||
connection::{
|
connection::{
|
||||||
|
self,
|
||||||
Close,
|
Close,
|
||||||
Connected,
|
Connected,
|
||||||
Connection,
|
Connection,
|
||||||
@ -55,8 +57,10 @@ pub enum Event<T, H, TE, HE, C> {
|
|||||||
Error { id: TaskId, error: ConnectionError<HE> },
|
Error { id: TaskId, error: ConnectionError<HE> },
|
||||||
/// A pending connection failed.
|
/// A pending connection failed.
|
||||||
Failed { id: TaskId, error: PendingConnectionError<TE>, handler: H },
|
Failed { id: TaskId, error: PendingConnectionError<TE>, handler: H },
|
||||||
|
/// A node we are connected to has changed its address.
|
||||||
|
AddressChange { id: TaskId, new_address: Multiaddr },
|
||||||
/// Notify the manager of an event from the connection.
|
/// Notify the manager of an event from the connection.
|
||||||
Notify { id: TaskId, event: T }
|
Notify { id: TaskId, event: T },
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T, H, TE, HE, C> Event<T, H, TE, HE, C> {
|
impl<T, H, TE, HE, C> Event<T, H, TE, HE, C> {
|
||||||
@ -64,8 +68,9 @@ impl<T, H, TE, HE, C> Event<T, H, TE, HE, C> {
|
|||||||
match self {
|
match self {
|
||||||
Event::Established { id, .. } => id,
|
Event::Established { id, .. } => id,
|
||||||
Event::Error { id, .. } => id,
|
Event::Error { id, .. } => id,
|
||||||
Event::Notify { id, .. } => id,
|
|
||||||
Event::Failed { id, .. } => id,
|
Event::Failed { id, .. } => id,
|
||||||
|
Event::AddressChange { id, .. } => id,
|
||||||
|
Event::Notify { id, .. } => id,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -245,13 +250,20 @@ where
|
|||||||
this.state = State::EstablishedPending(connection);
|
this.state = State::EstablishedPending(connection);
|
||||||
return Poll::Pending
|
return Poll::Pending
|
||||||
}
|
}
|
||||||
Poll::Ready(Ok(event)) => {
|
Poll::Ready(Ok(connection::Event::Handler(event))) => {
|
||||||
this.state = State::EstablishedReady {
|
this.state = State::EstablishedReady {
|
||||||
connection: Some(connection),
|
connection: Some(connection),
|
||||||
event: Event::Notify { id, event }
|
event: Event::Notify { id, event }
|
||||||
};
|
};
|
||||||
continue 'poll
|
continue 'poll
|
||||||
}
|
}
|
||||||
|
Poll::Ready(Ok(connection::Event::AddressChange(new_address))) => {
|
||||||
|
this.state = State::EstablishedReady {
|
||||||
|
connection: Some(connection),
|
||||||
|
event: Event::AddressChange { id, new_address }
|
||||||
|
};
|
||||||
|
continue 'poll
|
||||||
|
}
|
||||||
Poll::Ready(Err(error)) => {
|
Poll::Ready(Err(error)) => {
|
||||||
// Notify the manager of the error via an event,
|
// Notify the manager of the error via an event,
|
||||||
// dropping the connection.
|
// dropping the connection.
|
||||||
|
@ -125,6 +125,16 @@ pub enum PoolEvent<'a, TInEvent, TOutEvent, THandler, TTransErr, THandlerErr, TC
|
|||||||
/// The produced event.
|
/// The produced event.
|
||||||
event: TOutEvent,
|
event: TOutEvent,
|
||||||
},
|
},
|
||||||
|
|
||||||
|
/// The connection to a node has changed its address.
|
||||||
|
AddressChange {
|
||||||
|
/// The connection that has changed address.
|
||||||
|
connection: EstablishedConnection<'a, TInEvent, TConnInfo, TPeerId>,
|
||||||
|
/// The new endpoint.
|
||||||
|
new_endpoint: ConnectedPoint,
|
||||||
|
/// The old endpoint.
|
||||||
|
old_endpoint: ConnectedPoint,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, TInEvent, TOutEvent, THandler, TTransErr, THandlerErr, TConnInfo, TPeerId> fmt::Debug
|
impl<'a, TInEvent, TOutEvent, THandler, TTransErr, THandlerErr, TConnInfo, TPeerId> fmt::Debug
|
||||||
@ -162,6 +172,13 @@ where
|
|||||||
.field("event", event)
|
.field("event", event)
|
||||||
.finish()
|
.finish()
|
||||||
},
|
},
|
||||||
|
PoolEvent::AddressChange { ref connection, ref new_endpoint, ref old_endpoint } => {
|
||||||
|
f.debug_struct("PoolEvent::AddressChange")
|
||||||
|
.field("conn_info", connection.info())
|
||||||
|
.field("new_endpoint", new_endpoint)
|
||||||
|
.field("old_endpoint", old_endpoint)
|
||||||
|
.finish()
|
||||||
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -639,7 +656,27 @@ where
|
|||||||
}),
|
}),
|
||||||
_ => unreachable!("since `entry` is an `EstablishedEntry`.")
|
_ => unreachable!("since `entry` is an `EstablishedEntry`.")
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
manager::Event::AddressChange { entry, new_endpoint, old_endpoint } => {
|
||||||
|
let id = entry.id();
|
||||||
|
|
||||||
|
match self.established.get_mut(entry.connected().peer_id()) {
|
||||||
|
Some(list) => *list.get_mut(&id)
|
||||||
|
.expect("state inconsistency: entry is `EstablishedEntry` but absent \
|
||||||
|
from `established`") = new_endpoint.clone(),
|
||||||
|
None => unreachable!("since `entry` is an `EstablishedEntry`.")
|
||||||
|
};
|
||||||
|
|
||||||
|
match self.get(id) {
|
||||||
|
Some(PoolConnection::Established(connection)) =>
|
||||||
|
return Poll::Ready(PoolEvent::AddressChange {
|
||||||
|
connection,
|
||||||
|
new_endpoint,
|
||||||
|
old_endpoint,
|
||||||
|
}),
|
||||||
|
_ => unreachable!("since `entry` is an `EstablishedEntry`.")
|
||||||
}
|
}
|
||||||
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -18,8 +18,9 @@
|
|||||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||||
// DEALINGS IN THE SOFTWARE.
|
// DEALINGS IN THE SOFTWARE.
|
||||||
|
|
||||||
use crate::muxing::{StreamMuxer, SubstreamRef, substream_from_ref};
|
use crate::muxing::{StreamMuxer, StreamMuxerEvent, SubstreamRef, substream_from_ref};
|
||||||
use futures::prelude::*;
|
use futures::prelude::*;
|
||||||
|
use multiaddr::Multiaddr;
|
||||||
use smallvec::SmallVec;
|
use smallvec::SmallVec;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use std::{fmt, io::Error as IoError, pin::Pin, task::Context, task::Poll};
|
use std::{fmt, io::Error as IoError, pin::Pin, task::Context, task::Poll};
|
||||||
@ -95,6 +96,12 @@ where
|
|||||||
/// destroyed or `close_graceful` is called.
|
/// destroyed or `close_graceful` is called.
|
||||||
substream: Substream<TMuxer>,
|
substream: Substream<TMuxer>,
|
||||||
},
|
},
|
||||||
|
|
||||||
|
/// Address to the remote has changed. The previous one is now obsolete.
|
||||||
|
///
|
||||||
|
/// > **Note**: This can for example happen when using the QUIC protocol, where the two nodes
|
||||||
|
/// > can change their IP address while retaining the same QUIC connection.
|
||||||
|
AddressChange(Multiaddr),
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Identifier for a substream being opened.
|
/// Identifier for a substream being opened.
|
||||||
@ -145,13 +152,15 @@ where
|
|||||||
/// Provides an API similar to `Future`.
|
/// Provides an API similar to `Future`.
|
||||||
pub fn poll(&mut self, cx: &mut Context) -> Poll<Result<SubstreamEvent<TMuxer, TUserData>, IoError>> {
|
pub fn poll(&mut self, cx: &mut Context) -> Poll<Result<SubstreamEvent<TMuxer, TUserData>, IoError>> {
|
||||||
// Polling inbound substream.
|
// Polling inbound substream.
|
||||||
match self.inner.poll_inbound(cx) {
|
match self.inner.poll_event(cx) {
|
||||||
Poll::Ready(Ok(substream)) => {
|
Poll::Ready(Ok(StreamMuxerEvent::InboundSubstream(substream))) => {
|
||||||
let substream = substream_from_ref(self.inner.clone(), substream);
|
let substream = substream_from_ref(self.inner.clone(), substream);
|
||||||
return Poll::Ready(Ok(SubstreamEvent::InboundSubstream {
|
return Poll::Ready(Ok(SubstreamEvent::InboundSubstream {
|
||||||
substream,
|
substream,
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
Poll::Ready(Ok(StreamMuxerEvent::AddressChange(addr))) =>
|
||||||
|
return Poll::Ready(Ok(SubstreamEvent::AddressChange(addr))),
|
||||||
Poll::Ready(Err(err)) => return Poll::Ready(Err(err.into())),
|
Poll::Ready(Err(err)) => return Poll::Ready(Err(err.into())),
|
||||||
Poll::Pending => {}
|
Poll::Pending => {}
|
||||||
}
|
}
|
||||||
@ -253,6 +262,11 @@ where
|
|||||||
.field("substream", substream)
|
.field("substream", substream)
|
||||||
.finish()
|
.finish()
|
||||||
},
|
},
|
||||||
|
SubstreamEvent::AddressChange(address) => {
|
||||||
|
f.debug_struct("SubstreamEvent::AddressChange")
|
||||||
|
.field("address", address)
|
||||||
|
.finish()
|
||||||
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -19,7 +19,7 @@
|
|||||||
// DEALINGS IN THE SOFTWARE.
|
// DEALINGS IN THE SOFTWARE.
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
muxing::StreamMuxer,
|
muxing::{StreamMuxer, StreamMuxerEvent},
|
||||||
ProtocolName,
|
ProtocolName,
|
||||||
transport::{Transport, ListenerEvent, TransportError},
|
transport::{Transport, ListenerEvent, TransportError},
|
||||||
Multiaddr
|
Multiaddr
|
||||||
@ -189,10 +189,26 @@ where
|
|||||||
type OutboundSubstream = EitherOutbound<A, B>;
|
type OutboundSubstream = EitherOutbound<A, B>;
|
||||||
type Error = IoError;
|
type Error = IoError;
|
||||||
|
|
||||||
fn poll_inbound(&self, cx: &mut Context) -> Poll<Result<Self::Substream, Self::Error>> {
|
fn poll_event(&self, cx: &mut Context) -> Poll<Result<StreamMuxerEvent<Self::Substream>, Self::Error>> {
|
||||||
match self {
|
match self {
|
||||||
EitherOutput::First(inner) => inner.poll_inbound(cx).map(|p| p.map(EitherOutput::First)).map_err(|e| e.into()),
|
EitherOutput::First(inner) => inner.poll_event(cx).map(|result| {
|
||||||
EitherOutput::Second(inner) => inner.poll_inbound(cx).map(|p| p.map(EitherOutput::Second)).map_err(|e| e.into()),
|
result.map_err(|e| e.into()).map(|event| {
|
||||||
|
match event {
|
||||||
|
StreamMuxerEvent::AddressChange(addr) => StreamMuxerEvent::AddressChange(addr),
|
||||||
|
StreamMuxerEvent::InboundSubstream(substream) =>
|
||||||
|
StreamMuxerEvent::InboundSubstream(EitherOutput::First(substream))
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}),
|
||||||
|
EitherOutput::Second(inner) => inner.poll_event(cx).map(|result| {
|
||||||
|
result.map_err(|e| e.into()).map(|event| {
|
||||||
|
match event {
|
||||||
|
StreamMuxerEvent::AddressChange(addr) => StreamMuxerEvent::AddressChange(addr),
|
||||||
|
StreamMuxerEvent::InboundSubstream(substream) =>
|
||||||
|
StreamMuxerEvent::InboundSubstream(EitherOutput::Second(substream))
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -53,6 +53,7 @@
|
|||||||
|
|
||||||
use fnv::FnvHashMap;
|
use fnv::FnvHashMap;
|
||||||
use futures::{future, prelude::*, task::Context, task::Poll};
|
use futures::{future, prelude::*, task::Context, task::Poll};
|
||||||
|
use multiaddr::Multiaddr;
|
||||||
use parking_lot::Mutex;
|
use parking_lot::Mutex;
|
||||||
use std::{io, ops::Deref, fmt, pin::Pin, sync::atomic::{AtomicUsize, Ordering}};
|
use std::{io, ops::Deref, fmt, pin::Pin, sync::atomic::{AtomicUsize, Ordering}};
|
||||||
|
|
||||||
@ -64,10 +65,11 @@ mod singleton;
|
|||||||
///
|
///
|
||||||
/// The state of a muxer, as exposed by this API, is the following:
|
/// The state of a muxer, as exposed by this API, is the following:
|
||||||
///
|
///
|
||||||
/// - A connection to the remote. The `flush_all` and `close` methods operate on this.
|
/// - A connection to the remote. The `poll_event`, `flush_all` and `close` methods operate
|
||||||
/// - A list of substreams that are open. The `poll_inbound`, `poll_outbound`, `read_substream`,
|
/// on this.
|
||||||
/// `write_substream`, `flush_substream`, `shutdown_substream` and `destroy_substream` methods
|
/// - A list of substreams that are open. The `poll_outbound`, `read_substream`, `write_substream`,
|
||||||
/// allow controlling these entries.
|
/// `flush_substream`, `shutdown_substream` and `destroy_substream` methods allow controlling
|
||||||
|
/// these entries.
|
||||||
/// - A list of outbound substreams being opened. The `open_outbound`, `poll_outbound` and
|
/// - A list of outbound substreams being opened. The `open_outbound`, `poll_outbound` and
|
||||||
/// `destroy_outbound` methods allow controlling these entries.
|
/// `destroy_outbound` methods allow controlling these entries.
|
||||||
///
|
///
|
||||||
@ -81,7 +83,7 @@ pub trait StreamMuxer {
|
|||||||
/// Error type of the muxer
|
/// Error type of the muxer
|
||||||
type Error: Into<io::Error>;
|
type Error: Into<io::Error>;
|
||||||
|
|
||||||
/// Polls for an inbound substream.
|
/// Polls for a connection-wide event.
|
||||||
///
|
///
|
||||||
/// This function behaves the same as a `Stream`.
|
/// This function behaves the same as a `Stream`.
|
||||||
///
|
///
|
||||||
@ -90,7 +92,7 @@ pub trait StreamMuxer {
|
|||||||
/// Only the latest task that was used to call this method may be notified.
|
/// Only the latest task that was used to call this method may be notified.
|
||||||
///
|
///
|
||||||
/// An error can be generated if the connection has been closed.
|
/// An error can be generated if the connection has been closed.
|
||||||
fn poll_inbound(&self, cx: &mut Context) -> Poll<Result<Self::Substream, Self::Error>>;
|
fn poll_event(&self, cx: &mut Context) -> Poll<Result<StreamMuxerEvent<Self::Substream>, Self::Error>>;
|
||||||
|
|
||||||
/// Opens a new outgoing substream, and produces the equivalent to a future that will be
|
/// Opens a new outgoing substream, and produces the equivalent to a future that will be
|
||||||
/// resolved when it becomes available.
|
/// resolved when it becomes available.
|
||||||
@ -206,18 +208,49 @@ pub trait StreamMuxer {
|
|||||||
fn flush_all(&self, cx: &mut Context) -> Poll<Result<(), Self::Error>>;
|
fn flush_all(&self, cx: &mut Context) -> Poll<Result<(), Self::Error>>;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Polls for an inbound from the muxer but wraps the output in an object that
|
/// Event about a connection, reported by an implementation of [`StreamMuxer`].
|
||||||
/// implements `Read`/`Write`/`AsyncRead`/`AsyncWrite`.
|
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||||
pub fn inbound_from_ref_and_wrap<P>(
|
pub enum StreamMuxerEvent<T> {
|
||||||
|
/// Remote has opened a new substream. Contains the substream in question.
|
||||||
|
InboundSubstream(T),
|
||||||
|
|
||||||
|
/// Address to the remote has changed. The previous one is now obsolete.
|
||||||
|
///
|
||||||
|
/// > **Note**: This can for example happen when using the QUIC protocol, where the two nodes
|
||||||
|
/// > can change their IP address while retaining the same QUIC connection.
|
||||||
|
AddressChange(Multiaddr),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T> StreamMuxerEvent<T> {
|
||||||
|
/// If `self` is a [`StreamMuxerEvent::InboundSubstream`], returns the content. Otherwise
|
||||||
|
/// returns `None`.
|
||||||
|
pub fn into_inbound_substream(self) -> Option<T> {
|
||||||
|
if let StreamMuxerEvent::InboundSubstream(s) = self {
|
||||||
|
Some(s)
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Polls for an event from the muxer and, if an inbound substream, wraps this substream in an
|
||||||
|
/// object that implements `Read`/`Write`/`AsyncRead`/`AsyncWrite`.
|
||||||
|
pub fn event_from_ref_and_wrap<P>(
|
||||||
muxer: P,
|
muxer: P,
|
||||||
) -> impl Future<Output = Result<SubstreamRef<P>, <P::Target as StreamMuxer>::Error>>
|
) -> impl Future<Output = Result<StreamMuxerEvent<SubstreamRef<P>>, <P::Target as StreamMuxer>::Error>>
|
||||||
where
|
where
|
||||||
P: Deref + Clone,
|
P: Deref + Clone,
|
||||||
P::Target: StreamMuxer,
|
P::Target: StreamMuxer,
|
||||||
{
|
{
|
||||||
let muxer2 = muxer.clone();
|
let muxer2 = muxer.clone();
|
||||||
future::poll_fn(move |cx| muxer.poll_inbound(cx))
|
future::poll_fn(move |cx| muxer.poll_event(cx))
|
||||||
.map_ok(|substream| substream_from_ref(muxer2, substream))
|
.map_ok(|event| {
|
||||||
|
match event {
|
||||||
|
StreamMuxerEvent::InboundSubstream(substream) =>
|
||||||
|
StreamMuxerEvent::InboundSubstream(substream_from_ref(muxer2, substream)),
|
||||||
|
StreamMuxerEvent::AddressChange(addr) => StreamMuxerEvent::AddressChange(addr),
|
||||||
|
}
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Same as `outbound_from_ref`, but wraps the output in an object that
|
/// Same as `outbound_from_ref`, but wraps the output in an object that
|
||||||
@ -478,8 +511,8 @@ impl StreamMuxer for StreamMuxerBox {
|
|||||||
type Error = io::Error;
|
type Error = io::Error;
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn poll_inbound(&self, cx: &mut Context) -> Poll<Result<Self::Substream, Self::Error>> {
|
fn poll_event(&self, cx: &mut Context) -> Poll<Result<StreamMuxerEvent<Self::Substream>, Self::Error>> {
|
||||||
self.inner.poll_inbound(cx)
|
self.inner.poll_event(cx)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
@ -550,16 +583,18 @@ where
|
|||||||
type Error = io::Error;
|
type Error = io::Error;
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn poll_inbound(&self, cx: &mut Context) -> Poll<Result<Self::Substream, Self::Error>> {
|
fn poll_event(&self, cx: &mut Context) -> Poll<Result<StreamMuxerEvent<Self::Substream>, Self::Error>> {
|
||||||
let substream = match self.inner.poll_inbound(cx) {
|
let substream = match self.inner.poll_event(cx) {
|
||||||
Poll::Pending => return Poll::Pending,
|
Poll::Pending => return Poll::Pending,
|
||||||
Poll::Ready(Ok(s)) => s,
|
Poll::Ready(Ok(StreamMuxerEvent::AddressChange(a))) =>
|
||||||
|
return Poll::Ready(Ok(StreamMuxerEvent::AddressChange(a))),
|
||||||
|
Poll::Ready(Ok(StreamMuxerEvent::InboundSubstream(s))) => s,
|
||||||
Poll::Ready(Err(err)) => return Poll::Ready(Err(err.into())),
|
Poll::Ready(Err(err)) => return Poll::Ready(Err(err.into())),
|
||||||
};
|
};
|
||||||
|
|
||||||
let id = self.next_substream.fetch_add(1, Ordering::Relaxed);
|
let id = self.next_substream.fetch_add(1, Ordering::Relaxed);
|
||||||
self.substreams.lock().insert(id, substream);
|
self.substreams.lock().insert(id, substream);
|
||||||
Poll::Ready(Ok(id))
|
Poll::Ready(Ok(StreamMuxerEvent::InboundSubstream(id)))
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
|
@ -18,7 +18,8 @@
|
|||||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||||
// DEALINGS IN THE SOFTWARE.
|
// DEALINGS IN THE SOFTWARE.
|
||||||
|
|
||||||
use crate::{connection::Endpoint, muxing::StreamMuxer};
|
use crate::{connection::Endpoint, muxing::{StreamMuxer, StreamMuxerEvent}};
|
||||||
|
|
||||||
use futures::prelude::*;
|
use futures::prelude::*;
|
||||||
use parking_lot::Mutex;
|
use parking_lot::Mutex;
|
||||||
use std::{io, pin::Pin, sync::atomic::{AtomicBool, Ordering}, task::Context, task::Poll};
|
use std::{io, pin::Pin, sync::atomic::{AtomicBool, Ordering}, task::Context, task::Poll};
|
||||||
@ -64,14 +65,14 @@ where
|
|||||||
type OutboundSubstream = OutboundSubstream;
|
type OutboundSubstream = OutboundSubstream;
|
||||||
type Error = io::Error;
|
type Error = io::Error;
|
||||||
|
|
||||||
fn poll_inbound(&self, _: &mut Context) -> Poll<Result<Self::Substream, io::Error>> {
|
fn poll_event(&self, _: &mut Context) -> Poll<Result<StreamMuxerEvent<Self::Substream>, io::Error>> {
|
||||||
match self.endpoint {
|
match self.endpoint {
|
||||||
Endpoint::Dialer => return Poll::Pending,
|
Endpoint::Dialer => return Poll::Pending,
|
||||||
Endpoint::Listener => {}
|
Endpoint::Listener => {}
|
||||||
}
|
}
|
||||||
|
|
||||||
if !self.substream_extracted.swap(true, Ordering::Relaxed) {
|
if !self.substream_extracted.swap(true, Ordering::Relaxed) {
|
||||||
Poll::Ready(Ok(Substream {}))
|
Poll::Ready(Ok(StreamMuxerEvent::InboundSubstream(Substream {})))
|
||||||
} else {
|
} else {
|
||||||
Poll::Pending
|
Poll::Pending
|
||||||
}
|
}
|
||||||
|
@ -416,7 +416,14 @@ where
|
|||||||
Poll::Ready(PoolEvent::ConnectionEvent { connection, event }) => {
|
Poll::Ready(PoolEvent::ConnectionEvent { connection, event }) => {
|
||||||
NetworkEvent::ConnectionEvent {
|
NetworkEvent::ConnectionEvent {
|
||||||
connection,
|
connection,
|
||||||
event
|
event,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Poll::Ready(PoolEvent::AddressChange { connection, new_endpoint, old_endpoint }) => {
|
||||||
|
NetworkEvent::AddressChange {
|
||||||
|
connection,
|
||||||
|
new_endpoint,
|
||||||
|
old_endpoint,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -155,6 +155,16 @@ where
|
|||||||
/// Event that was produced by the node.
|
/// Event that was produced by the node.
|
||||||
event: TOutEvent,
|
event: TOutEvent,
|
||||||
},
|
},
|
||||||
|
|
||||||
|
/// An established connection has changed its address.
|
||||||
|
AddressChange {
|
||||||
|
/// The connection whose address has changed.
|
||||||
|
connection: EstablishedConnection<'a, TInEvent, TConnInfo, TPeerId>,
|
||||||
|
/// New endpoint of this connection.
|
||||||
|
new_endpoint: ConnectedPoint,
|
||||||
|
/// Old endpoint of this connection.
|
||||||
|
old_endpoint: ConnectedPoint,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<TTrans, TInEvent, TOutEvent, THandler, TConnInfo, TPeerId> fmt::Debug for
|
impl<TTrans, TInEvent, TOutEvent, THandler, TConnInfo, TPeerId> fmt::Debug for
|
||||||
@ -240,6 +250,13 @@ where
|
|||||||
.field("event", event)
|
.field("event", event)
|
||||||
.finish()
|
.finish()
|
||||||
}
|
}
|
||||||
|
NetworkEvent::AddressChange { connection, new_endpoint, old_endpoint } => {
|
||||||
|
f.debug_struct("AddressChange")
|
||||||
|
.field("connection", connection)
|
||||||
|
.field("new_endpoint", new_endpoint)
|
||||||
|
.field("old_endpoint", old_endpoint)
|
||||||
|
.finish()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,15 +2,15 @@
|
|||||||
#![allow(dead_code)]
|
#![allow(dead_code)]
|
||||||
|
|
||||||
use futures::prelude::*;
|
use futures::prelude::*;
|
||||||
use libp2p_core::muxing::StreamMuxer;
|
|
||||||
use libp2p_core::{
|
use libp2p_core::{
|
||||||
|
Multiaddr,
|
||||||
connection::{
|
connection::{
|
||||||
ConnectionHandler,
|
ConnectionHandler,
|
||||||
ConnectionHandlerEvent,
|
ConnectionHandlerEvent,
|
||||||
Substream,
|
Substream,
|
||||||
SubstreamEndpoint,
|
SubstreamEndpoint,
|
||||||
},
|
},
|
||||||
muxing::StreamMuxerBox,
|
muxing::{StreamMuxer, StreamMuxerBox},
|
||||||
};
|
};
|
||||||
use std::{io, pin::Pin, task::Context, task::Poll};
|
use std::{io, pin::Pin, task::Context, task::Poll};
|
||||||
|
|
||||||
@ -29,6 +29,9 @@ impl ConnectionHandler for TestHandler {
|
|||||||
fn inject_event(&mut self, _: Self::InEvent)
|
fn inject_event(&mut self, _: Self::InEvent)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
|
fn inject_address_change(&mut self, _: &Multiaddr)
|
||||||
|
{}
|
||||||
|
|
||||||
fn poll(&mut self, _: &mut Context)
|
fn poll(&mut self, _: &mut Context)
|
||||||
-> Poll<Result<ConnectionHandlerEvent<Self::OutboundOpenInfo, Self::OutEvent>, Self::Error>>
|
-> Poll<Result<ConnectionHandlerEvent<Self::OutboundOpenInfo, Self::OutEvent>, Self::Error>>
|
||||||
{
|
{
|
||||||
|
@ -168,6 +168,19 @@ fn build_struct(ast: &DeriveInput, data_struct: &DataStruct) -> TokenStream {
|
|||||||
})
|
})
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Build the list of statements to put in the body of `inject_address_change()`.
|
||||||
|
let inject_address_change_stmts = {
|
||||||
|
data_struct.fields.iter().enumerate().filter_map(move |(field_n, field)| {
|
||||||
|
if is_ignored(&field) {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
Some(match field.ident {
|
||||||
|
Some(ref i) => quote!{ self.#i.inject_address_change(peer_id, connection_id, old, new); },
|
||||||
|
None => quote!{ self.#field_n.inject_address_change(peer_id, connection_id, old, new); },
|
||||||
|
})
|
||||||
|
})
|
||||||
|
};
|
||||||
|
|
||||||
// Build the list of statements to put in the body of `inject_connection_closed()`.
|
// Build the list of statements to put in the body of `inject_connection_closed()`.
|
||||||
let inject_connection_closed_stmts = {
|
let inject_connection_closed_stmts = {
|
||||||
data_struct.fields.iter().enumerate().filter_map(move |(field_n, field)| {
|
data_struct.fields.iter().enumerate().filter_map(move |(field_n, field)| {
|
||||||
@ -441,6 +454,10 @@ fn build_struct(ast: &DeriveInput, data_struct: &DataStruct) -> TokenStream {
|
|||||||
#(#inject_connection_established_stmts);*
|
#(#inject_connection_established_stmts);*
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn inject_address_change(&mut self, peer_id: &#peer_id, connection_id: &#connection_id, old: &#connected_point, new: &#connected_point) {
|
||||||
|
#(#inject_address_change_stmts);*
|
||||||
|
}
|
||||||
|
|
||||||
fn inject_connection_closed(&mut self, peer_id: &#peer_id, connection_id: &#connection_id, endpoint: &#connected_point) {
|
fn inject_connection_closed(&mut self, peer_id: &#peer_id, connection_id: &#connection_id, endpoint: &#connected_point) {
|
||||||
#(#inject_connection_closed_stmts);*
|
#(#inject_connection_closed_stmts);*
|
||||||
}
|
}
|
||||||
|
@ -28,6 +28,7 @@ use bytes::Bytes;
|
|||||||
use libp2p_core::{
|
use libp2p_core::{
|
||||||
Endpoint,
|
Endpoint,
|
||||||
StreamMuxer,
|
StreamMuxer,
|
||||||
|
muxing::StreamMuxerEvent,
|
||||||
upgrade::{InboundUpgrade, OutboundUpgrade, UpgradeInfo},
|
upgrade::{InboundUpgrade, OutboundUpgrade, UpgradeInfo},
|
||||||
};
|
};
|
||||||
use log::{debug, trace};
|
use log::{debug, trace};
|
||||||
@ -174,6 +175,9 @@ where
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Multiplexer. Implements the `StreamMuxer` trait.
|
/// Multiplexer. Implements the `StreamMuxer` trait.
|
||||||
|
///
|
||||||
|
/// This implementation isn't capable of detecting when the underlying socket changes its address,
|
||||||
|
/// and no [`StreamMuxerEvent::AddressChange`] event is ever emitted.
|
||||||
pub struct Multiplex<C> {
|
pub struct Multiplex<C> {
|
||||||
inner: Mutex<MultiplexInner<C>>,
|
inner: Mutex<MultiplexInner<C>>,
|
||||||
}
|
}
|
||||||
@ -362,7 +366,7 @@ where C: AsyncRead + AsyncWrite + Unpin
|
|||||||
type OutboundSubstream = OutboundSubstream;
|
type OutboundSubstream = OutboundSubstream;
|
||||||
type Error = IoError;
|
type Error = IoError;
|
||||||
|
|
||||||
fn poll_inbound(&self, cx: &mut Context) -> Poll<Result<Self::Substream, IoError>> {
|
fn poll_event(&self, cx: &mut Context) -> Poll<Result<StreamMuxerEvent<Self::Substream>, IoError>> {
|
||||||
let mut inner = self.inner.lock();
|
let mut inner = self.inner.lock();
|
||||||
|
|
||||||
if inner.opened_substreams.len() >= inner.config.max_substreams {
|
if inner.opened_substreams.len() >= inner.config.max_substreams {
|
||||||
@ -384,13 +388,13 @@ where C: AsyncRead + AsyncWrite + Unpin
|
|||||||
};
|
};
|
||||||
|
|
||||||
debug!("Successfully opened inbound substream {}", num);
|
debug!("Successfully opened inbound substream {}", num);
|
||||||
Poll::Ready(Ok(Substream {
|
Poll::Ready(Ok(StreamMuxerEvent::InboundSubstream(Substream {
|
||||||
current_data: Bytes::new(),
|
current_data: Bytes::new(),
|
||||||
num,
|
num,
|
||||||
endpoint: Endpoint::Listener,
|
endpoint: Endpoint::Listener,
|
||||||
local_open: true,
|
local_open: true,
|
||||||
remote_open: true,
|
remote_open: true,
|
||||||
}))
|
})))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn open_outbound(&self) -> Self::OutboundSubstream {
|
fn open_outbound(&self) -> Self::OutboundSubstream {
|
||||||
|
@ -65,8 +65,13 @@ fn async_write() {
|
|||||||
let transport = TcpConfig::new().and_then(move |c, e|
|
let transport = TcpConfig::new().and_then(move |c, e|
|
||||||
upgrade::apply(c, mplex, e, upgrade::Version::V1));
|
upgrade::apply(c, mplex, e, upgrade::Version::V1));
|
||||||
|
|
||||||
let client = transport.dial(rx.await.unwrap()).unwrap().await.unwrap();
|
let client = Arc::new(transport.dial(rx.await.unwrap()).unwrap().await.unwrap());
|
||||||
let mut inbound = muxing::inbound_from_ref_and_wrap(Arc::new(client)).await.unwrap();
|
let mut inbound = loop {
|
||||||
|
if let Some(s) = muxing::event_from_ref_and_wrap(client.clone()).await.unwrap()
|
||||||
|
.into_inbound_substream() {
|
||||||
|
break s;
|
||||||
|
}
|
||||||
|
};
|
||||||
inbound.write_all(b"hello world").await.unwrap();
|
inbound.write_all(b"hello world").await.unwrap();
|
||||||
|
|
||||||
// The test consists in making sure that this flushes the substream.
|
// The test consists in making sure that this flushes the substream.
|
||||||
|
@ -65,8 +65,13 @@ fn client_to_server_outbound() {
|
|||||||
let transport = TcpConfig::new().and_then(move |c, e|
|
let transport = TcpConfig::new().and_then(move |c, e|
|
||||||
upgrade::apply(c, mplex, e, upgrade::Version::V1));
|
upgrade::apply(c, mplex, e, upgrade::Version::V1));
|
||||||
|
|
||||||
let client = transport.dial(rx.await.unwrap()).unwrap().await.unwrap();
|
let client = Arc::new(transport.dial(rx.await.unwrap()).unwrap().await.unwrap());
|
||||||
let mut inbound = muxing::inbound_from_ref_and_wrap(Arc::new(client)).await.unwrap();
|
let mut inbound = loop {
|
||||||
|
if let Some(s) = muxing::event_from_ref_and_wrap(client.clone()).await.unwrap()
|
||||||
|
.into_inbound_substream() {
|
||||||
|
break s;
|
||||||
|
}
|
||||||
|
};
|
||||||
inbound.write_all(b"hello world").await.unwrap();
|
inbound.write_all(b"hello world").await.unwrap();
|
||||||
inbound.close().await.unwrap();
|
inbound.close().await.unwrap();
|
||||||
|
|
||||||
@ -98,13 +103,18 @@ fn client_to_server_inbound() {
|
|||||||
|
|
||||||
tx.send(addr).unwrap();
|
tx.send(addr).unwrap();
|
||||||
|
|
||||||
let client = listener
|
let client = Arc::new(listener
|
||||||
.next().await
|
.next().await
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.into_upgrade().unwrap().0.await.unwrap();
|
.into_upgrade().unwrap().0.await.unwrap());
|
||||||
|
|
||||||
let mut inbound = muxing::inbound_from_ref_and_wrap(Arc::new(client)).await.unwrap();
|
let mut inbound = loop {
|
||||||
|
if let Some(s) = muxing::event_from_ref_and_wrap(client.clone()).await.unwrap()
|
||||||
|
.into_inbound_substream() {
|
||||||
|
break s;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
let mut buf = Vec::new();
|
let mut buf = Vec::new();
|
||||||
inbound.read_to_end(&mut buf).await.unwrap();
|
inbound.read_to_end(&mut buf).await.unwrap();
|
||||||
|
@ -22,6 +22,7 @@
|
|||||||
//! [specification](https://github.com/hashicorp/yamux/blob/master/spec.md).
|
//! [specification](https://github.com/hashicorp/yamux/blob/master/spec.md).
|
||||||
|
|
||||||
use futures::{future, prelude::*, ready, stream::{BoxStream, LocalBoxStream}};
|
use futures::{future, prelude::*, ready, stream::{BoxStream, LocalBoxStream}};
|
||||||
|
use libp2p_core::muxing::StreamMuxerEvent;
|
||||||
use libp2p_core::upgrade::{InboundUpgrade, OutboundUpgrade, UpgradeInfo};
|
use libp2p_core::upgrade::{InboundUpgrade, OutboundUpgrade, UpgradeInfo};
|
||||||
use parking_lot::Mutex;
|
use parking_lot::Mutex;
|
||||||
use std::{fmt, io, iter, ops::{Deref, DerefMut}, pin::Pin, task::Context};
|
use std::{fmt, io, iter, ops::{Deref, DerefMut}, pin::Pin, task::Context};
|
||||||
@ -30,6 +31,9 @@ use thiserror::Error;
|
|||||||
pub use yamux::WindowUpdateMode;
|
pub use yamux::WindowUpdateMode;
|
||||||
|
|
||||||
/// A Yamux connection.
|
/// A Yamux connection.
|
||||||
|
///
|
||||||
|
/// This implementation isn't capable of detecting when the underlying socket changes its address,
|
||||||
|
/// and no [`StreamMuxerEvent::AddressChange`] event is ever emitted.
|
||||||
pub struct Yamux<S>(Mutex<Inner<S>>);
|
pub struct Yamux<S>(Mutex<Inner<S>>);
|
||||||
|
|
||||||
impl<S> fmt::Debug for Yamux<S> {
|
impl<S> fmt::Debug for Yamux<S> {
|
||||||
@ -99,10 +103,10 @@ where
|
|||||||
type OutboundSubstream = OpenSubstreamToken;
|
type OutboundSubstream = OpenSubstreamToken;
|
||||||
type Error = YamuxError;
|
type Error = YamuxError;
|
||||||
|
|
||||||
fn poll_inbound(&self, c: &mut Context) -> Poll<Self::Substream> {
|
fn poll_event(&self, c: &mut Context) -> Poll<StreamMuxerEvent<Self::Substream>> {
|
||||||
let mut inner = self.0.lock();
|
let mut inner = self.0.lock();
|
||||||
match ready!(inner.incoming.poll_next_unpin(c)) {
|
match ready!(inner.incoming.poll_next_unpin(c)) {
|
||||||
Some(Ok(s)) => Poll::Ready(Ok(s)),
|
Some(Ok(s)) => Poll::Ready(Ok(StreamMuxerEvent::InboundSubstream(s))),
|
||||||
Some(Err(e)) => Poll::Ready(Err(e)),
|
Some(Err(e)) => Poll::Ready(Err(e)),
|
||||||
None => Poll::Ready(Err(yamux::ConnectionError::Closed.into()))
|
None => Poll::Ready(Err(yamux::ConnectionError::Closed.into()))
|
||||||
}
|
}
|
||||||
|
@ -5,6 +5,10 @@ analogue of `ProtocolsHandler::inject_dial_upgrade_error`, with an
|
|||||||
empty default implementation. No implementation is required to
|
empty default implementation. No implementation is required to
|
||||||
retain existing behaviour.
|
retain existing behaviour.
|
||||||
|
|
||||||
|
- Add `ProtocolsHandler::inject_address_change` and
|
||||||
|
`NetworkBehaviour::inject_address_change` to notify of a change in
|
||||||
|
the address of an existing connection.
|
||||||
|
|
||||||
# 0.19.1 [2020-06-18]
|
# 0.19.1 [2020-06-18]
|
||||||
|
|
||||||
- Bugfix: Fix MultiHandler panicking when empty
|
- Bugfix: Fix MultiHandler panicking when empty
|
||||||
|
@ -101,6 +101,15 @@ pub trait NetworkBehaviour: Send + 'static {
|
|||||||
fn inject_connection_closed(&mut self, _: &PeerId, _: &ConnectionId, _: &ConnectedPoint)
|
fn inject_connection_closed(&mut self, _: &PeerId, _: &ConnectionId, _: &ConnectedPoint)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
|
/// Informs the behaviour that the [`ConnectedPoint`] of an existing connection has changed.
|
||||||
|
fn inject_address_change(
|
||||||
|
&mut self,
|
||||||
|
_: &PeerId,
|
||||||
|
_: &ConnectionId,
|
||||||
|
_old: &ConnectedPoint,
|
||||||
|
_new: &ConnectedPoint
|
||||||
|
) {}
|
||||||
|
|
||||||
/// Informs the behaviour about an event generated by the handler dedicated to the peer identified by `peer_id`.
|
/// Informs the behaviour about an event generated by the handler dedicated to the peer identified by `peer_id`.
|
||||||
/// for the behaviour.
|
/// for the behaviour.
|
||||||
///
|
///
|
||||||
|
@ -496,6 +496,11 @@ where TBehaviour: NetworkBehaviour<ProtocolsHandler = THandler>,
|
|||||||
let connection = connection.id();
|
let connection = connection.id();
|
||||||
this.behaviour.inject_event(peer, connection, event);
|
this.behaviour.inject_event(peer, connection, event);
|
||||||
},
|
},
|
||||||
|
Poll::Ready(NetworkEvent::AddressChange { connection, new_endpoint, old_endpoint }) => {
|
||||||
|
let peer = connection.peer_id();
|
||||||
|
let connection = connection.id();
|
||||||
|
this.behaviour.inject_address_change(&peer, &connection, &old_endpoint, &new_endpoint);
|
||||||
|
},
|
||||||
Poll::Ready(NetworkEvent::ConnectionEstablished { connection, num_established }) => {
|
Poll::Ready(NetworkEvent::ConnectionEstablished { connection, num_established }) => {
|
||||||
let peer_id = connection.peer_id().clone();
|
let peer_id = connection.peer_id().clone();
|
||||||
let endpoint = connection.endpoint().clone();
|
let endpoint = connection.endpoint().clone();
|
||||||
|
@ -53,6 +53,7 @@ pub use crate::upgrade::{
|
|||||||
|
|
||||||
use libp2p_core::{
|
use libp2p_core::{
|
||||||
ConnectedPoint,
|
ConnectedPoint,
|
||||||
|
Multiaddr,
|
||||||
PeerId,
|
PeerId,
|
||||||
upgrade::{self, UpgradeError},
|
upgrade::{self, UpgradeError},
|
||||||
};
|
};
|
||||||
@ -140,6 +141,9 @@ pub trait ProtocolsHandler: Send + 'static {
|
|||||||
/// Injects an event coming from the outside in the handler.
|
/// Injects an event coming from the outside in the handler.
|
||||||
fn inject_event(&mut self, event: Self::InEvent);
|
fn inject_event(&mut self, event: Self::InEvent);
|
||||||
|
|
||||||
|
/// Notifies the handler of a change in the address of the remote.
|
||||||
|
fn inject_address_change(&mut self, _new_address: &Multiaddr) {}
|
||||||
|
|
||||||
/// Indicates to the handler that upgrading an outbound substream to the given protocol has failed.
|
/// Indicates to the handler that upgrading an outbound substream to the given protocol has failed.
|
||||||
fn inject_dial_upgrade_error(
|
fn inject_dial_upgrade_error(
|
||||||
&mut self,
|
&mut self,
|
||||||
|
@ -29,6 +29,7 @@ use crate::protocols_handler::{
|
|||||||
|
|
||||||
use futures::prelude::*;
|
use futures::prelude::*;
|
||||||
use libp2p_core::{
|
use libp2p_core::{
|
||||||
|
Multiaddr,
|
||||||
PeerId,
|
PeerId,
|
||||||
ConnectionInfo,
|
ConnectionInfo,
|
||||||
Connected,
|
Connected,
|
||||||
@ -220,6 +221,10 @@ where
|
|||||||
self.handler.inject_event(event);
|
self.handler.inject_event(event);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn inject_address_change(&mut self, new_address: &Multiaddr) {
|
||||||
|
self.handler.inject_address_change(new_address);
|
||||||
|
}
|
||||||
|
|
||||||
fn poll(&mut self, cx: &mut Context) -> Poll<
|
fn poll(&mut self, cx: &mut Context) -> Poll<
|
||||||
Result<ConnectionHandlerEvent<Self::OutboundOpenInfo, Self::OutEvent>, Self::Error>
|
Result<ConnectionHandlerEvent<Self::OutboundOpenInfo, Self::OutEvent>, Self::Error>
|
||||||
> {
|
> {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user