-
Notifications
You must be signed in to change notification settings - Fork 984
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat: move Identify I/O from NetworkBehaviour to ConnectionHandler #3208
Changes from 3 commits
cff7c4a
d703ba6
3db1ec1
e01c02e
11a9254
57013bb
a84178f
0db0c52
aa0d81a
fa05a2e
7aab6a6
963f11d
8e88bf6
c0afa8f
60470d2
b484572
d457cbd
bbe124d
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -18,9 +18,8 @@ | |
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER | ||
// DEALINGS IN THE SOFTWARE. | ||
|
||
use crate::handler::{self, Proto, Push}; | ||
use crate::handler::{self, InEvent, Proto, Reply}; | ||
use crate::protocol::{Info, ReplySubstream, UpgradeError}; | ||
use futures::prelude::*; | ||
use libp2p_core::{ | ||
connection::ConnectionId, multiaddr::Protocol, ConnectedPoint, Multiaddr, PeerId, PublicKey, | ||
}; | ||
|
@@ -35,7 +34,6 @@ use std::num::NonZeroUsize; | |
use std::{ | ||
collections::{HashMap, HashSet, VecDeque}, | ||
iter::FromIterator, | ||
pin::Pin, | ||
task::Context, | ||
task::Poll, | ||
time::Duration, | ||
|
@@ -51,8 +49,8 @@ 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 replies to send. | ||
pending_replies: VecDeque<Reply>, | ||
/// Pending requests to respond. | ||
requests: VecDeque<Request>, | ||
/// Pending events to be emitted when polled. | ||
events: VecDeque<NetworkBehaviourAction<Event, Proto>>, | ||
/// Peers to which an active push with current information about | ||
|
@@ -63,18 +61,10 @@ pub struct Behaviour { | |
} | ||
|
||
/// A pending reply to an inbound identification request. | ||
enum Reply { | ||
/// The reply is queued for sending. | ||
Queued { | ||
peer: PeerId, | ||
io: ReplySubstream<NegotiatedSubstream>, | ||
observed: Multiaddr, | ||
}, | ||
/// The reply is being sent. | ||
Sending { | ||
peer: PeerId, | ||
io: Pin<Box<dyn Future<Output = Result<(), UpgradeError>> + Send>>, | ||
}, | ||
struct Request { | ||
peer: PeerId, | ||
io: ReplySubstream<NegotiatedSubstream>, | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It would be nice to not pass this back and forth. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yeah agreed thanks, updated! |
||
observed: Multiaddr, | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. but we only get it on There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. You have to implement There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. thanks Thomas, updated! |
||
} | ||
|
||
/// Configuration for the [`identify::Behaviour`](Behaviour). | ||
|
@@ -184,7 +174,7 @@ impl Behaviour { | |
Self { | ||
config, | ||
connected: HashMap::new(), | ||
pending_replies: VecDeque::new(), | ||
requests: VecDeque::new(), | ||
events: VecDeque::new(), | ||
pending_push: HashSet::new(), | ||
discovered_peers, | ||
|
@@ -271,6 +261,12 @@ impl NetworkBehaviour for Behaviour { | |
score: AddressScore::Finite(1), | ||
}); | ||
} | ||
handler::Event::Identification(peer) => { | ||
self.events | ||
.push_back(NetworkBehaviourAction::GenerateEvent(Event::Sent { | ||
peer_id: peer, | ||
})); | ||
} | ||
handler::Event::IdentificationPushed => { | ||
self.events | ||
.push_back(NetworkBehaviourAction::GenerateEvent(Event::Pushed { | ||
|
@@ -287,7 +283,7 @@ impl NetworkBehaviour for Behaviour { | |
with an established connection and calling `NetworkBehaviour::on_event` \ | ||
with `FromSwarm::ConnectionEstablished ensures there is an entry; qed", | ||
); | ||
self.pending_replies.push_back(Reply::Queued { | ||
self.requests.push_back(Request { | ||
peer: peer_id, | ||
io: sender, | ||
observed: observed.clone(), | ||
|
@@ -305,7 +301,7 @@ impl NetworkBehaviour for Behaviour { | |
|
||
fn poll( | ||
&mut self, | ||
cx: &mut Context<'_>, | ||
_cx: &mut Context<'_>, | ||
params: &mut impl PollParameters, | ||
) -> Poll<NetworkBehaviourAction<Self::OutEvent, Self::ConnectionHandler>> { | ||
if let Some(event) = self.events.pop_front() { | ||
|
@@ -333,7 +329,7 @@ impl NetworkBehaviour for Behaviour { | |
observed_addr, | ||
}; | ||
|
||
(*peer, Push(info)) | ||
(*peer, InEvent::Push(info)) | ||
}) | ||
}); | ||
|
||
|
@@ -346,55 +342,21 @@ impl NetworkBehaviour for Behaviour { | |
}); | ||
} | ||
|
||
// Check for pending replies to send. | ||
if let Some(r) = self.pending_replies.pop_front() { | ||
let mut sending = 0; | ||
let to_send = self.pending_replies.len() + 1; | ||
let mut reply = Some(r); | ||
loop { | ||
match reply { | ||
Some(Reply::Queued { peer, io, observed }) => { | ||
let info = Info { | ||
listen_addrs: listen_addrs(params), | ||
protocols: supported_protocols(params), | ||
public_key: self.config.local_public_key.clone(), | ||
protocol_version: self.config.protocol_version.clone(), | ||
agent_version: self.config.agent_version.clone(), | ||
observed_addr: observed, | ||
}; | ||
let io = Box::pin(io.send(info)); | ||
reply = Some(Reply::Sending { peer, io }); | ||
} | ||
Some(Reply::Sending { peer, mut io }) => { | ||
sending += 1; | ||
match Future::poll(Pin::new(&mut io), cx) { | ||
Poll::Ready(Ok(())) => { | ||
let event = Event::Sent { peer_id: peer }; | ||
return Poll::Ready(NetworkBehaviourAction::GenerateEvent(event)); | ||
} | ||
Poll::Pending => { | ||
self.pending_replies.push_back(Reply::Sending { peer, io }); | ||
if sending == to_send { | ||
// All remaining futures are NotReady | ||
break; | ||
} else { | ||
reply = self.pending_replies.pop_front(); | ||
} | ||
} | ||
Poll::Ready(Err(err)) => { | ||
let event = Event::Error { | ||
peer_id: peer, | ||
error: ConnectionHandlerUpgrErr::Upgrade( | ||
libp2p_core::upgrade::UpgradeError::Apply(err), | ||
), | ||
}; | ||
return Poll::Ready(NetworkBehaviourAction::GenerateEvent(event)); | ||
} | ||
} | ||
} | ||
None => unreachable!(), | ||
} | ||
} | ||
// Check for pending requests to send back to the handler for reply. | ||
if let Some(Request { peer, io, observed }) = self.requests.pop_front() { | ||
let info = Info { | ||
listen_addrs: listen_addrs(params), | ||
protocols: supported_protocols(params), | ||
public_key: self.config.local_public_key.clone(), | ||
protocol_version: self.config.protocol_version.clone(), | ||
agent_version: self.config.agent_version.clone(), | ||
observed_addr: observed, | ||
}; | ||
return Poll::Ready(NetworkBehaviourAction::NotifyHandler { | ||
peer_id: peer, | ||
handler: NotifyHandler::Any, | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Here is the curlpit! This will be buggy with > 1 connection per peer. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Thanks Thomas, addressed. |
||
event: InEvent::Identify(Reply { peer, info, io }), | ||
}); | ||
} | ||
|
||
Poll::Pending | ||
|
@@ -557,6 +519,7 @@ impl PeerCache { | |
mod tests { | ||
use super::*; | ||
use futures::pin_mut; | ||
use futures::prelude::*; | ||
use libp2p::mplex::MplexConfig; | ||
use libp2p::noise; | ||
use libp2p::tcp; | ||
|
@@ -618,7 +581,7 @@ mod tests { | |
|
||
// nb. Either swarm may receive the `Identified` event first, upon which | ||
// it will permit the connection to be closed, as defined by | ||
// `IdentifyHandler::connection_keep_alive`. Hence the test succeeds if | ||
// `Handler::connection_keep_alive`. Hence the test succeeds if | ||
// either `Identified` event arrives correctly. | ||
async_std::task::block_on(async move { | ||
loop { | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The handler could learn this via
IntoConnectionHandler
. It will never change across its lifespan.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
updated!