mirror of
https://github.com/fluencelabs/rust-libp2p
synced 2025-06-29 17:51:35 +00:00
feat: report changes in supported protocols to ConnectionHandler
With this patch, implementations of `ConnectionHandler` (which are typically composed in a tree) can exchange information about the supported protocols of a remote with each other via `ConnectionHandlerEvent::ReportRemoteProtocols`. The provided `ProtocolSupport` enum can describe either additions or removals of the remote peer's protocols. This information is aggregated in the connection and passed down to the `ConnectionHandler` via `ConnectionEvent::RemoteProtocolsChange`. Similarly, if the listen protocols of a connection change, all `ConnectionHandler`s on the connection will be notified via `ConnectionEvent::LocalProtocolsChange`. This will allow us to eventually remove `PollParameters` from `NetworkBehaviour`. This pattern allows protocols on a connection to communicate with each other. For example, protocols like identify can share the list of (supposedly) supported protocols by the remote with all other handlers. A protocol like kademlia can accurately add and remove a remote from its routing table as a result. Resolves: #2680. Related: #3124. Pull-Request: #3651.
This commit is contained in:
@ -19,15 +19,14 @@
|
||||
// DEALINGS IN THE SOFTWARE.
|
||||
|
||||
use crate::handler::{self, Handler, InEvent};
|
||||
use crate::protocol::{Info, Protocol, UpgradeError};
|
||||
use crate::protocol::{Info, UpgradeError};
|
||||
use libp2p_core::{multiaddr, ConnectedPoint, Endpoint, Multiaddr};
|
||||
use libp2p_identity::PeerId;
|
||||
use libp2p_identity::PublicKey;
|
||||
use libp2p_swarm::behaviour::{ConnectionClosed, ConnectionEstablished, DialFailure, FromSwarm};
|
||||
use libp2p_swarm::{
|
||||
AddressScore, ConnectionDenied, DialError, ExternalAddresses, ListenAddresses,
|
||||
NetworkBehaviour, NotifyHandler, PollParameters, StreamProtocol, StreamUpgradeError,
|
||||
THandlerInEvent, ToSwarm,
|
||||
NetworkBehaviour, NotifyHandler, PollParameters, StreamUpgradeError, THandlerInEvent, ToSwarm,
|
||||
};
|
||||
use libp2p_swarm::{ConnectionId, THandler, THandlerOutEvent};
|
||||
use lru::LruCache;
|
||||
@ -50,10 +49,6 @@ pub struct Behaviour {
|
||||
config: Config,
|
||||
/// For each peer we're connected to, the observed address to send back to it.
|
||||
connected: HashMap<PeerId, HashMap<ConnectionId, Multiaddr>>,
|
||||
/// Pending requests to be fulfilled, either `Handler` requests for `Behaviour` info
|
||||
/// to address identification requests, or push requests to peers
|
||||
/// with current information about the local peer.
|
||||
requests: Vec<Request>,
|
||||
/// Pending events to be emitted when polled.
|
||||
events: VecDeque<ToSwarm<Event, InEvent>>,
|
||||
/// The addresses of all peers that we have discovered.
|
||||
@ -63,15 +58,6 @@ pub struct Behaviour {
|
||||
external_addresses: ExternalAddresses,
|
||||
}
|
||||
|
||||
/// A `Behaviour` request to be fulfilled, either `Handler` requests for `Behaviour` info
|
||||
/// to address identification requests, or push requests to peers
|
||||
/// with current information about the local peer.
|
||||
#[derive(Debug, PartialEq, Eq)]
|
||||
struct Request {
|
||||
peer_id: PeerId,
|
||||
protocol: Protocol,
|
||||
}
|
||||
|
||||
/// Configuration for the [`identify::Behaviour`](Behaviour).
|
||||
#[non_exhaustive]
|
||||
#[derive(Debug, Clone)]
|
||||
@ -184,7 +170,6 @@ impl Behaviour {
|
||||
Self {
|
||||
config,
|
||||
connected: HashMap::new(),
|
||||
requests: Vec::new(),
|
||||
events: VecDeque::new(),
|
||||
discovered_peers,
|
||||
listen_addresses: Default::default(),
|
||||
@ -203,13 +188,11 @@ impl Behaviour {
|
||||
continue;
|
||||
}
|
||||
|
||||
let request = Request {
|
||||
self.events.push_back(ToSwarm::NotifyHandler {
|
||||
peer_id: p,
|
||||
protocol: Protocol::Push,
|
||||
};
|
||||
if !self.requests.contains(&request) {
|
||||
self.requests.push(request);
|
||||
}
|
||||
handler: NotifyHandler::Any,
|
||||
event: InEvent::Push,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@ -239,6 +222,14 @@ impl Behaviour {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn all_addresses(&self) -> HashSet<Multiaddr> {
|
||||
self.listen_addresses
|
||||
.iter()
|
||||
.chain(self.external_addresses.iter())
|
||||
.cloned()
|
||||
.collect()
|
||||
}
|
||||
}
|
||||
|
||||
impl NetworkBehaviour for Behaviour {
|
||||
@ -261,6 +252,7 @@ impl NetworkBehaviour for Behaviour {
|
||||
self.config.protocol_version.clone(),
|
||||
self.config.agent_version.clone(),
|
||||
remote_addr.clone(),
|
||||
self.all_addresses(),
|
||||
))
|
||||
}
|
||||
|
||||
@ -280,13 +272,14 @@ impl NetworkBehaviour for Behaviour {
|
||||
self.config.protocol_version.clone(),
|
||||
self.config.agent_version.clone(),
|
||||
addr.clone(), // TODO: This is weird? That is the public address we dialed, shouldn't need to tell the other party?
|
||||
self.all_addresses(),
|
||||
))
|
||||
}
|
||||
|
||||
fn on_connection_handler_event(
|
||||
&mut self,
|
||||
peer_id: PeerId,
|
||||
connection_id: ConnectionId,
|
||||
_: ConnectionId,
|
||||
event: THandlerOutEvent<Self>,
|
||||
) {
|
||||
match event {
|
||||
@ -315,12 +308,6 @@ impl NetworkBehaviour for Behaviour {
|
||||
self.events
|
||||
.push_back(ToSwarm::GenerateEvent(Event::Pushed { peer_id }));
|
||||
}
|
||||
handler::Event::Identify => {
|
||||
self.requests.push(Request {
|
||||
peer_id,
|
||||
protocol: Protocol::Identify(connection_id),
|
||||
});
|
||||
}
|
||||
handler::Event::IdentificationError(error) => {
|
||||
self.events
|
||||
.push_back(ToSwarm::GenerateEvent(Event::Error { peer_id, error }));
|
||||
@ -331,50 +318,13 @@ impl NetworkBehaviour for Behaviour {
|
||||
fn poll(
|
||||
&mut self,
|
||||
_cx: &mut Context<'_>,
|
||||
params: &mut impl PollParameters,
|
||||
_: &mut impl PollParameters,
|
||||
) -> Poll<ToSwarm<Self::OutEvent, THandlerInEvent<Self>>> {
|
||||
if let Some(event) = self.events.pop_front() {
|
||||
return Poll::Ready(event);
|
||||
}
|
||||
|
||||
// Check for pending requests.
|
||||
match self.requests.pop() {
|
||||
Some(Request {
|
||||
peer_id,
|
||||
protocol: Protocol::Push,
|
||||
}) => Poll::Ready(ToSwarm::NotifyHandler {
|
||||
peer_id,
|
||||
handler: NotifyHandler::Any,
|
||||
event: InEvent {
|
||||
listen_addrs: self
|
||||
.listen_addresses
|
||||
.iter()
|
||||
.chain(self.external_addresses.iter())
|
||||
.cloned()
|
||||
.collect(),
|
||||
supported_protocols: supported_protocols(params),
|
||||
protocol: Protocol::Push,
|
||||
},
|
||||
}),
|
||||
Some(Request {
|
||||
peer_id,
|
||||
protocol: Protocol::Identify(connection_id),
|
||||
}) => Poll::Ready(ToSwarm::NotifyHandler {
|
||||
peer_id,
|
||||
handler: NotifyHandler::One(connection_id),
|
||||
event: InEvent {
|
||||
listen_addrs: self
|
||||
.listen_addresses
|
||||
.iter()
|
||||
.chain(self.external_addresses.iter())
|
||||
.cloned()
|
||||
.collect(),
|
||||
supported_protocols: supported_protocols(params),
|
||||
protocol: Protocol::Identify(connection_id),
|
||||
},
|
||||
}),
|
||||
None => Poll::Pending,
|
||||
}
|
||||
Poll::Pending
|
||||
}
|
||||
|
||||
fn handle_pending_outbound_connection(
|
||||
@ -393,8 +343,35 @@ impl NetworkBehaviour for Behaviour {
|
||||
}
|
||||
|
||||
fn on_swarm_event(&mut self, event: FromSwarm<Self::ConnectionHandler>) {
|
||||
self.listen_addresses.on_swarm_event(&event);
|
||||
self.external_addresses.on_swarm_event(&event);
|
||||
let listen_addr_changed = self.listen_addresses.on_swarm_event(&event);
|
||||
let external_addr_changed = self.external_addresses.on_swarm_event(&event);
|
||||
|
||||
if listen_addr_changed || external_addr_changed {
|
||||
// notify all connected handlers about our changed addresses
|
||||
let change_events = self
|
||||
.connected
|
||||
.iter()
|
||||
.flat_map(|(peer, map)| map.keys().map(|id| (*peer, id)))
|
||||
.map(|(peer_id, connection_id)| ToSwarm::NotifyHandler {
|
||||
peer_id,
|
||||
handler: NotifyHandler::One(*connection_id),
|
||||
event: InEvent::AddressesChanged(self.all_addresses()),
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
self.events.extend(change_events)
|
||||
}
|
||||
|
||||
if listen_addr_changed && self.config.push_listen_addr_updates {
|
||||
// trigger an identify push for all connected peers
|
||||
let push_events = self.connected.keys().map(|peer| ToSwarm::NotifyHandler {
|
||||
peer_id: *peer,
|
||||
handler: NotifyHandler::Any,
|
||||
event: InEvent::Push,
|
||||
});
|
||||
|
||||
self.events.extend(push_events);
|
||||
}
|
||||
|
||||
match event {
|
||||
FromSwarm::ConnectionEstablished(connection_established) => {
|
||||
@ -408,30 +385,11 @@ impl NetworkBehaviour for Behaviour {
|
||||
}) => {
|
||||
if remaining_established == 0 {
|
||||
self.connected.remove(&peer_id);
|
||||
self.requests.retain(|request| {
|
||||
request
|
||||
!= &Request {
|
||||
peer_id,
|
||||
protocol: Protocol::Push,
|
||||
}
|
||||
});
|
||||
} else if let Some(addrs) = self.connected.get_mut(&peer_id) {
|
||||
addrs.remove(&connection_id);
|
||||
}
|
||||
}
|
||||
FromSwarm::DialFailure(DialFailure { peer_id, error, .. }) => {
|
||||
if let Some(peer_id) = peer_id {
|
||||
if !self.connected.contains_key(&peer_id) {
|
||||
self.requests.retain(|request| {
|
||||
request
|
||||
!= &Request {
|
||||
peer_id,
|
||||
protocol: Protocol::Push,
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(entry) = peer_id.and_then(|id| self.discovered_peers.get_mut(&id)) {
|
||||
if let DialError::Transport(errors) = error {
|
||||
for (addr, _error) in errors {
|
||||
@ -440,20 +398,9 @@ impl NetworkBehaviour for Behaviour {
|
||||
}
|
||||
}
|
||||
}
|
||||
FromSwarm::NewListenAddr(_) | FromSwarm::ExpiredListenAddr(_) => {
|
||||
if self.config.push_listen_addr_updates {
|
||||
for p in self.connected.keys() {
|
||||
let request = Request {
|
||||
peer_id: *p,
|
||||
protocol: Protocol::Push,
|
||||
};
|
||||
if !self.requests.contains(&request) {
|
||||
self.requests.push(request);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
FromSwarm::AddressChange(_)
|
||||
FromSwarm::NewListenAddr(_)
|
||||
| FromSwarm::ExpiredListenAddr(_)
|
||||
| FromSwarm::AddressChange(_)
|
||||
| FromSwarm::ListenFailure(_)
|
||||
| FromSwarm::NewListener(_)
|
||||
| FromSwarm::ListenerError(_)
|
||||
@ -496,17 +443,6 @@ pub enum Event {
|
||||
},
|
||||
}
|
||||
|
||||
fn supported_protocols(params: &impl PollParameters) -> Vec<StreamProtocol> {
|
||||
// The protocol names can be bytes, but the identify protocol except UTF-8 strings.
|
||||
// There's not much we can do to solve this conflict except strip non-UTF-8 characters.
|
||||
params
|
||||
.supported_protocols()
|
||||
.filter_map(|p| {
|
||||
StreamProtocol::try_from_owned(String::from_utf8_lossy(&p).to_string()).ok()
|
||||
})
|
||||
.collect()
|
||||
}
|
||||
|
||||
/// If there is a given peer_id in the multiaddr, make sure it is the same as
|
||||
/// the given peer_id. If there is no peer_id for the peer in the mutiaddr, this returns true.
|
||||
fn multiaddr_matches_peer_id(addr: &Multiaddr, peer_id: &PeerId) -> bool {
|
||||
|
@ -18,9 +18,7 @@
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
// DEALINGS IN THE SOFTWARE.
|
||||
|
||||
use crate::protocol::{
|
||||
self, Identify, InboundPush, Info, OutboundPush, Protocol, Push, UpgradeError,
|
||||
};
|
||||
use crate::protocol::{Identify, InboundPush, Info, OutboundPush, Push, UpgradeError};
|
||||
use either::Either;
|
||||
use futures::future::BoxFuture;
|
||||
use futures::prelude::*;
|
||||
@ -32,15 +30,16 @@ use libp2p_identity::PeerId;
|
||||
use libp2p_identity::PublicKey;
|
||||
use libp2p_swarm::handler::{
|
||||
ConnectionEvent, DialUpgradeError, FullyNegotiatedInbound, FullyNegotiatedOutbound,
|
||||
ProtocolSupport,
|
||||
};
|
||||
use libp2p_swarm::{
|
||||
ConnectionHandler, ConnectionHandlerEvent, KeepAlive, NegotiatedSubstream, StreamProtocol,
|
||||
StreamUpgradeError, SubstreamProtocol,
|
||||
ConnectionHandler, ConnectionHandlerEvent, KeepAlive, StreamProtocol, StreamUpgradeError,
|
||||
SubstreamProtocol, SupportedProtocols,
|
||||
};
|
||||
use log::warn;
|
||||
use smallvec::SmallVec;
|
||||
use std::collections::{HashSet, VecDeque};
|
||||
use std::{io, pin::Pin, task::Context, task::Poll, time::Duration};
|
||||
use std::collections::HashSet;
|
||||
use std::{io, task::Context, task::Poll, time::Duration};
|
||||
|
||||
/// Protocol handler for sending and receiving identification requests.
|
||||
///
|
||||
@ -55,9 +54,6 @@ pub struct Handler {
|
||||
[ConnectionHandlerEvent<Either<Identify, Push<OutboundPush>>, (), Event, io::Error>; 4],
|
||||
>,
|
||||
|
||||
/// Streams awaiting `BehaviourInfo` to then send identify requests.
|
||||
reply_streams: VecDeque<NegotiatedSubstream>,
|
||||
|
||||
/// Pending identification replies, awaiting being sent.
|
||||
pending_replies: FuturesUnordered<BoxFuture<'static, Result<PeerId, UpgradeError>>>,
|
||||
|
||||
@ -80,19 +76,17 @@ pub struct Handler {
|
||||
|
||||
/// Address observed by or for the remote.
|
||||
observed_addr: Multiaddr,
|
||||
|
||||
local_supported_protocols: SupportedProtocols,
|
||||
remote_supported_protocols: HashSet<StreamProtocol>,
|
||||
external_addresses: HashSet<Multiaddr>,
|
||||
}
|
||||
|
||||
/// An event from `Behaviour` with the information requested by the `Handler`.
|
||||
#[derive(Debug)]
|
||||
pub struct InEvent {
|
||||
/// The addresses that the peer is listening on.
|
||||
pub listen_addrs: HashSet<Multiaddr>,
|
||||
|
||||
/// The list of protocols supported by the peer, e.g. `/ipfs/ping/1.0.0`.
|
||||
pub supported_protocols: Vec<StreamProtocol>,
|
||||
|
||||
/// The protocol w.r.t. the information requested.
|
||||
pub protocol: Protocol,
|
||||
pub enum InEvent {
|
||||
AddressesChanged(HashSet<Multiaddr>),
|
||||
Push,
|
||||
}
|
||||
|
||||
/// Event produced by the `Handler`.
|
||||
@ -105,14 +99,13 @@ pub enum Event {
|
||||
Identification(PeerId),
|
||||
/// We actively pushed our identification information to the remote.
|
||||
IdentificationPushed,
|
||||
/// We received a request for identification.
|
||||
Identify,
|
||||
/// Failed to identify the remote, or to reply to an identification request.
|
||||
IdentificationError(StreamUpgradeError<UpgradeError>),
|
||||
}
|
||||
|
||||
impl Handler {
|
||||
/// Creates a new `Handler`.
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
pub fn new(
|
||||
initial_delay: Duration,
|
||||
interval: Duration,
|
||||
@ -121,12 +114,12 @@ impl Handler {
|
||||
protocol_version: String,
|
||||
agent_version: String,
|
||||
observed_addr: Multiaddr,
|
||||
external_addresses: HashSet<Multiaddr>,
|
||||
) -> Self {
|
||||
Self {
|
||||
remote_peer_id,
|
||||
inbound_identify_push: Default::default(),
|
||||
events: SmallVec::new(),
|
||||
reply_streams: VecDeque::new(),
|
||||
pending_replies: FuturesUnordered::new(),
|
||||
trigger_next_identify: Delay::new(initial_delay),
|
||||
interval,
|
||||
@ -134,6 +127,9 @@ impl Handler {
|
||||
protocol_version,
|
||||
agent_version,
|
||||
observed_addr,
|
||||
local_supported_protocols: SupportedProtocols::default(),
|
||||
remote_supported_protocols: HashSet::default(),
|
||||
external_addresses,
|
||||
}
|
||||
}
|
||||
|
||||
@ -148,16 +144,14 @@ impl Handler {
|
||||
) {
|
||||
match output {
|
||||
future::Either::Left(substream) => {
|
||||
self.events
|
||||
.push(ConnectionHandlerEvent::Custom(Event::Identify));
|
||||
if !self.reply_streams.is_empty() {
|
||||
warn!(
|
||||
"New inbound identify request from {} while a previous one \
|
||||
is still pending. Queueing the new one.",
|
||||
self.remote_peer_id,
|
||||
);
|
||||
}
|
||||
self.reply_streams.push_back(substream);
|
||||
let peer_id = self.remote_peer_id;
|
||||
let info = self.build_info();
|
||||
|
||||
self.pending_replies.push(Box::pin(async move {
|
||||
crate::protocol::send(substream, info).await?;
|
||||
|
||||
Ok(peer_id)
|
||||
}));
|
||||
}
|
||||
future::Either::Right(fut) => {
|
||||
if self.inbound_identify_push.replace(fut).is_some() {
|
||||
@ -182,6 +176,7 @@ impl Handler {
|
||||
) {
|
||||
match output {
|
||||
future::Either::Left(remote_info) => {
|
||||
self.update_supported_protocols_for_remote(&remote_info);
|
||||
self.events
|
||||
.push(ConnectionHandlerEvent::Custom(Event::Identified(
|
||||
remote_info,
|
||||
@ -207,6 +202,47 @@ impl Handler {
|
||||
)));
|
||||
self.trigger_next_identify.reset(self.interval);
|
||||
}
|
||||
|
||||
fn build_info(&mut self) -> Info {
|
||||
Info {
|
||||
public_key: self.public_key.clone(),
|
||||
protocol_version: self.protocol_version.clone(),
|
||||
agent_version: self.agent_version.clone(),
|
||||
listen_addrs: Vec::from_iter(self.external_addresses.iter().cloned()),
|
||||
protocols: Vec::from_iter(self.local_supported_protocols.iter().cloned()),
|
||||
observed_addr: self.observed_addr.clone(),
|
||||
}
|
||||
}
|
||||
|
||||
fn update_supported_protocols_for_remote(&mut self, remote_info: &Info) {
|
||||
let new_remote_protocols = HashSet::from_iter(remote_info.protocols.clone());
|
||||
|
||||
let remote_added_protocols = new_remote_protocols
|
||||
.difference(&self.remote_supported_protocols)
|
||||
.cloned()
|
||||
.collect::<HashSet<_>>();
|
||||
let remote_removed_protocols = self
|
||||
.remote_supported_protocols
|
||||
.difference(&new_remote_protocols)
|
||||
.cloned()
|
||||
.collect::<HashSet<_>>();
|
||||
|
||||
if !remote_added_protocols.is_empty() {
|
||||
self.events
|
||||
.push(ConnectionHandlerEvent::ReportRemoteProtocols(
|
||||
ProtocolSupport::Added(remote_added_protocols),
|
||||
));
|
||||
}
|
||||
|
||||
if !remote_removed_protocols.is_empty() {
|
||||
self.events
|
||||
.push(ConnectionHandlerEvent::ReportRemoteProtocols(
|
||||
ProtocolSupport::Removed(remote_removed_protocols),
|
||||
));
|
||||
}
|
||||
|
||||
self.remote_supported_protocols = new_remote_protocols;
|
||||
}
|
||||
}
|
||||
|
||||
impl ConnectionHandler for Handler {
|
||||
@ -222,42 +258,18 @@ impl ConnectionHandler for Handler {
|
||||
SubstreamProtocol::new(SelectUpgrade::new(Identify, Push::inbound()), ())
|
||||
}
|
||||
|
||||
fn on_behaviour_event(
|
||||
&mut self,
|
||||
InEvent {
|
||||
listen_addrs,
|
||||
supported_protocols,
|
||||
protocol,
|
||||
}: Self::InEvent,
|
||||
) {
|
||||
let info = Info {
|
||||
public_key: self.public_key.clone(),
|
||||
protocol_version: self.protocol_version.clone(),
|
||||
agent_version: self.agent_version.clone(),
|
||||
listen_addrs: Vec::from_iter(listen_addrs),
|
||||
protocols: supported_protocols,
|
||||
observed_addr: self.observed_addr.clone(),
|
||||
};
|
||||
|
||||
match protocol {
|
||||
Protocol::Push => {
|
||||
fn on_behaviour_event(&mut self, event: Self::InEvent) {
|
||||
match event {
|
||||
InEvent::AddressesChanged(addresses) => {
|
||||
self.external_addresses = addresses;
|
||||
}
|
||||
InEvent::Push => {
|
||||
let info = self.build_info();
|
||||
self.events
|
||||
.push(ConnectionHandlerEvent::OutboundSubstreamRequest {
|
||||
protocol: SubstreamProtocol::new(Either::Right(Push::outbound(info)), ()),
|
||||
});
|
||||
}
|
||||
Protocol::Identify(_) => {
|
||||
let substream = self
|
||||
.reply_streams
|
||||
.pop_front()
|
||||
.expect("A BehaviourInfo reply should have a matching substream.");
|
||||
let peer = self.remote_peer_id;
|
||||
let fut = Box::pin(async move {
|
||||
protocol::send(substream, info).await?;
|
||||
Ok(peer)
|
||||
});
|
||||
self.pending_replies.push(fut);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -270,10 +282,6 @@ impl ConnectionHandler for Handler {
|
||||
return KeepAlive::Yes;
|
||||
}
|
||||
|
||||
if !self.reply_streams.is_empty() {
|
||||
return KeepAlive::Yes;
|
||||
}
|
||||
|
||||
KeepAlive::No
|
||||
}
|
||||
|
||||
@ -283,20 +291,17 @@ impl ConnectionHandler for Handler {
|
||||
) -> Poll<
|
||||
ConnectionHandlerEvent<Self::OutboundProtocol, Self::OutboundOpenInfo, Event, Self::Error>,
|
||||
> {
|
||||
if !self.events.is_empty() {
|
||||
return Poll::Ready(self.events.remove(0));
|
||||
if let Some(event) = self.events.pop() {
|
||||
return Poll::Ready(event);
|
||||
}
|
||||
|
||||
// Poll the future that fires when we need to identify the node again.
|
||||
match Future::poll(Pin::new(&mut self.trigger_next_identify), cx) {
|
||||
Poll::Pending => {}
|
||||
Poll::Ready(()) => {
|
||||
self.trigger_next_identify.reset(self.interval);
|
||||
let ev = ConnectionHandlerEvent::OutboundSubstreamRequest {
|
||||
protocol: SubstreamProtocol::new(Either::Left(Identify), ()),
|
||||
};
|
||||
return Poll::Ready(ev);
|
||||
}
|
||||
if let Poll::Ready(()) = self.trigger_next_identify.poll_unpin(cx) {
|
||||
self.trigger_next_identify.reset(self.interval);
|
||||
let ev = ConnectionHandlerEvent::OutboundSubstreamRequest {
|
||||
protocol: SubstreamProtocol::new(Either::Left(Identify), ()),
|
||||
};
|
||||
return Poll::Ready(ev);
|
||||
}
|
||||
|
||||
if let Some(Poll::Ready(res)) = self
|
||||
@ -307,20 +312,21 @@ impl ConnectionHandler for Handler {
|
||||
self.inbound_identify_push.take();
|
||||
|
||||
if let Ok(info) = res {
|
||||
self.update_supported_protocols_for_remote(&info);
|
||||
return Poll::Ready(ConnectionHandlerEvent::Custom(Event::Identified(info)));
|
||||
}
|
||||
}
|
||||
|
||||
// Check for pending replies to send.
|
||||
match self.pending_replies.poll_next_unpin(cx) {
|
||||
Poll::Ready(Some(Ok(peer_id))) => Poll::Ready(ConnectionHandlerEvent::Custom(
|
||||
Event::Identification(peer_id),
|
||||
)),
|
||||
Poll::Ready(Some(Err(err))) => Poll::Ready(ConnectionHandlerEvent::Custom(
|
||||
Event::IdentificationError(StreamUpgradeError::Apply(err)),
|
||||
)),
|
||||
Poll::Ready(None) | Poll::Pending => Poll::Pending,
|
||||
if let Poll::Ready(Some(result)) = self.pending_replies.poll_next_unpin(cx) {
|
||||
let event = result
|
||||
.map(Event::Identification)
|
||||
.unwrap_or_else(|err| Event::IdentificationError(StreamUpgradeError::Apply(err)));
|
||||
|
||||
return Poll::Ready(ConnectionHandlerEvent::Custom(event));
|
||||
}
|
||||
|
||||
Poll::Pending
|
||||
}
|
||||
|
||||
fn on_connection_event(
|
||||
@ -342,7 +348,12 @@ impl ConnectionHandler for Handler {
|
||||
ConnectionEvent::DialUpgradeError(dial_upgrade_error) => {
|
||||
self.on_dial_upgrade_error(dial_upgrade_error)
|
||||
}
|
||||
ConnectionEvent::AddressChange(_) | ConnectionEvent::ListenUpgradeError(_) => {}
|
||||
ConnectionEvent::AddressChange(_)
|
||||
| ConnectionEvent::ListenUpgradeError(_)
|
||||
| ConnectionEvent::RemoteProtocolsChange(_) => {}
|
||||
ConnectionEvent::LocalProtocolsChange(change) => {
|
||||
self.local_supported_protocols.on_protocols_change(change);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -28,7 +28,7 @@ use libp2p_core::{
|
||||
};
|
||||
use libp2p_identity as identity;
|
||||
use libp2p_identity::PublicKey;
|
||||
use libp2p_swarm::{ConnectionId, StreamProtocol};
|
||||
use libp2p_swarm::StreamProtocol;
|
||||
use log::{debug, trace};
|
||||
use std::convert::TryFrom;
|
||||
use std::{io, iter, pin::Pin};
|
||||
@ -41,13 +41,6 @@ pub const PROTOCOL_NAME: StreamProtocol = StreamProtocol::new("/ipfs/id/1.0.0");
|
||||
|
||||
pub const PUSH_PROTOCOL_NAME: StreamProtocol = StreamProtocol::new("/ipfs/id/push/1.0.0");
|
||||
|
||||
/// The type of the Substream protocol.
|
||||
#[derive(Debug, PartialEq, Eq)]
|
||||
pub enum Protocol {
|
||||
Identify(ConnectionId),
|
||||
Push,
|
||||
}
|
||||
|
||||
/// Substream upgrade protocol for `/ipfs/id/1.0.0`.
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct Identify;
|
||||
|
Reference in New Issue
Block a user