Skip to content

Commit caed1fe

Browse files
refactor(swarm)!: remove handler from NetworkBehaviourAction::Dial (#3328)
We create the `ConnectionId` for the new connection as part of `DialOpts`. This allows `NetworkBehaviour`s to accurately track state regarding their own dial attempts. This patch is the main enabler of #3254. Removing the `handler` field will allow us to deprecate the `NetworkBehaviour::new_handler` function in favor of four new ones that give more control over the connection lifecycle.
1 parent 9247cfa commit caed1fe

File tree

31 files changed

+583
-966
lines changed

31 files changed

+583
-966
lines changed

core/src/muxing/boxed.rs

+6
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,12 @@ pub struct StreamMuxerBox {
1313
inner: Pin<Box<dyn StreamMuxer<Substream = SubstreamBox, Error = io::Error> + Send>>,
1414
}
1515

16+
impl fmt::Debug for StreamMuxerBox {
17+
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
18+
f.debug_struct("StreamMuxerBox").finish_non_exhaustive()
19+
}
20+
}
21+
1622
/// Abstract type for asynchronous reading and writing.
1723
///
1824
/// A [`SubstreamBox`] erases the concrete type it is given and only retains its `AsyncRead`

protocols/autonat/src/behaviour.rs

+7-12
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ use libp2p_swarm::{
3838
ExpiredListenAddr, FromSwarm,
3939
},
4040
ConnectionId, ExternalAddresses, ListenAddresses, NetworkBehaviour, NetworkBehaviourAction,
41-
PollParameters, THandlerOutEvent,
41+
PollParameters, THandlerInEvent, THandlerOutEvent,
4242
};
4343
use std::{
4444
collections::{HashMap, VecDeque},
@@ -208,10 +208,7 @@ pub struct Behaviour {
208208
last_probe: Option<Instant>,
209209

210210
pending_actions: VecDeque<
211-
NetworkBehaviourAction<
212-
<Self as NetworkBehaviour>::OutEvent,
213-
<Self as NetworkBehaviour>::ConnectionHandler,
214-
>,
211+
NetworkBehaviourAction<<Self as NetworkBehaviour>::OutEvent, THandlerInEvent<Self>>,
215212
>,
216213

217214
probe_id: ProbeId,
@@ -389,14 +386,14 @@ impl Behaviour {
389386
&mut self,
390387
DialFailure {
391388
peer_id,
392-
handler,
389+
connection_id,
393390
error,
394-
}: DialFailure<<Self as NetworkBehaviour>::ConnectionHandler>,
391+
}: DialFailure,
395392
) {
396393
self.inner
397394
.on_swarm_event(FromSwarm::DialFailure(DialFailure {
398395
peer_id,
399-
handler,
396+
connection_id,
400397
error,
401398
}));
402399
if let Some(event) = self.as_server().on_outbound_dial_error(peer_id, error) {
@@ -560,10 +557,8 @@ impl NetworkBehaviour for Behaviour {
560557
}
561558
}
562559

563-
type Action = NetworkBehaviourAction<
564-
<Behaviour as NetworkBehaviour>::OutEvent,
565-
<Behaviour as NetworkBehaviour>::ConnectionHandler,
566-
>;
560+
type Action =
561+
NetworkBehaviourAction<<Behaviour as NetworkBehaviour>::OutEvent, THandlerInEvent<Behaviour>>;
567562

568563
// Trait implemented for `AsClient` and `AsServer` to handle events from the inner [`request_response::Behaviour`] Protocol.
569564
trait HandleInnerEvent {

protocols/autonat/src/behaviour/as_server.rs

+1-2
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ use libp2p_request_response::{
2929
};
3030
use libp2p_swarm::{
3131
dial_opts::{DialOpts, PeerCondition},
32-
ConnectionId, DialError, NetworkBehaviour, NetworkBehaviourAction, PollParameters,
32+
ConnectionId, DialError, NetworkBehaviourAction, PollParameters,
3333
};
3434
use std::{
3535
collections::{HashMap, HashSet, VecDeque},
@@ -138,7 +138,6 @@ impl<'a> HandleInnerEvent for AsServer<'a> {
138138
)
139139
.addresses(addrs)
140140
.build(),
141-
handler: self.inner.new_handler(),
142141
},
143142
])
144143
}

protocols/dcutr/src/behaviour_impl.rs

+103-68
Original file line numberDiff line numberDiff line change
@@ -29,12 +29,13 @@ use libp2p_swarm::behaviour::{ConnectionClosed, ConnectionEstablished, DialFailu
2929
use libp2p_swarm::dial_opts::{self, DialOpts};
3030
use libp2p_swarm::{
3131
ConnectionHandlerUpgrErr, ExternalAddresses, NetworkBehaviour, NetworkBehaviourAction,
32-
NotifyHandler, PollParameters,
32+
NotifyHandler, PollParameters, THandlerInEvent,
3333
};
3434
use libp2p_swarm::{ConnectionId, THandlerOutEvent};
3535
use std::collections::{HashMap, HashSet, VecDeque};
3636
use std::task::{Context, Poll};
3737
use thiserror::Error;
38+
use void::Void;
3839

3940
const MAX_NUMBER_OF_UPGRADE_ATTEMPTS: u8 = 3;
4041

@@ -68,14 +69,20 @@ pub enum Error {
6869

6970
pub struct Behaviour {
7071
/// Queue of actions to return when polled.
71-
queued_events: VecDeque<NetworkBehaviourAction<Event, handler::Prototype>>,
72+
queued_events: VecDeque<NetworkBehaviourAction<Event, Either<handler::relayed::Command, Void>>>,
7273

7374
/// All direct (non-relayed) connections.
7475
direct_connections: HashMap<PeerId, HashSet<ConnectionId>>,
7576

7677
external_addresses: ExternalAddresses,
7778

7879
local_peer_id: PeerId,
80+
81+
direct_to_relayed_connections: HashMap<ConnectionId, ConnectionId>,
82+
83+
/// Indexed by the [`ConnectionId`] of the relayed connection and
84+
/// the [`PeerId`] we are trying to establish a direct connection to.
85+
outgoing_direct_connection_attempts: HashMap<(ConnectionId, PeerId), u8>,
7986
}
8087

8188
impl Behaviour {
@@ -85,6 +92,8 @@ impl Behaviour {
8592
direct_connections: Default::default(),
8693
external_addresses: Default::default(),
8794
local_peer_id,
95+
direct_to_relayed_connections: Default::default(),
96+
outgoing_direct_connection_attempts: Default::default(),
8897
}
8998
}
9099

@@ -148,40 +157,57 @@ impl Behaviour {
148157
fn on_dial_failure(
149158
&mut self,
150159
DialFailure {
151-
peer_id, handler, ..
152-
}: DialFailure<<Self as NetworkBehaviour>::ConnectionHandler>,
160+
peer_id,
161+
connection_id: failed_direct_connection,
162+
..
163+
}: DialFailure,
153164
) {
154-
if let handler::Prototype::DirectConnection {
155-
relayed_connection_id,
156-
role: handler::Role::Initiator { attempt },
157-
} = handler
165+
let peer_id = if let Some(peer_id) = peer_id {
166+
peer_id
167+
} else {
168+
return;
169+
};
170+
171+
let relayed_connection_id = if let Some(relayed_connection_id) = self
172+
.direct_to_relayed_connections
173+
.get(&failed_direct_connection)
158174
{
159-
let peer_id = peer_id.expect("Peer of `Prototype::DirectConnection` is always known.");
160-
if attempt < MAX_NUMBER_OF_UPGRADE_ATTEMPTS {
161-
self.queued_events
162-
.push_back(NetworkBehaviourAction::NotifyHandler {
163-
handler: NotifyHandler::One(relayed_connection_id),
164-
peer_id,
165-
event: Either::Left(handler::relayed::Command::Connect {
166-
attempt: attempt + 1,
167-
obs_addrs: self.observed_addreses(),
168-
}),
169-
})
170-
} else {
171-
self.queued_events.extend([
172-
NetworkBehaviourAction::NotifyHandler {
173-
peer_id,
174-
handler: NotifyHandler::One(relayed_connection_id),
175-
event: Either::Left(
176-
handler::relayed::Command::UpgradeFinishedDontKeepAlive,
177-
),
178-
},
179-
NetworkBehaviourAction::GenerateEvent(Event::DirectConnectionUpgradeFailed {
180-
remote_peer_id: peer_id,
181-
error: Error::Dial,
175+
*relayed_connection_id
176+
} else {
177+
return;
178+
};
179+
180+
let attempt = if let Some(attempt) = self
181+
.outgoing_direct_connection_attempts
182+
.get(&(relayed_connection_id, peer_id))
183+
{
184+
*attempt
185+
} else {
186+
return;
187+
};
188+
189+
if attempt < MAX_NUMBER_OF_UPGRADE_ATTEMPTS {
190+
self.queued_events
191+
.push_back(NetworkBehaviourAction::NotifyHandler {
192+
handler: NotifyHandler::One(relayed_connection_id),
193+
peer_id,
194+
event: Either::Left(handler::relayed::Command::Connect {
195+
attempt: attempt + 1,
196+
obs_addrs: self.observed_addreses(),
182197
}),
183-
]);
184-
}
198+
})
199+
} else {
200+
self.queued_events.extend([
201+
NetworkBehaviourAction::NotifyHandler {
202+
peer_id,
203+
handler: NotifyHandler::One(relayed_connection_id),
204+
event: Either::Left(handler::relayed::Command::UpgradeFinishedDontKeepAlive),
205+
},
206+
NetworkBehaviourAction::GenerateEvent(Event::DirectConnectionUpgradeFailed {
207+
remote_peer_id: peer_id,
208+
error: Error::Dial,
209+
}),
210+
]);
185211
}
186212
}
187213

@@ -215,23 +241,34 @@ impl NetworkBehaviour for Behaviour {
215241
type OutEvent = Event;
216242

217243
fn new_handler(&mut self) -> Self::ConnectionHandler {
218-
handler::Prototype::UnknownConnection
244+
handler::Prototype
219245
}
220246

221247
fn on_connection_handler_event(
222248
&mut self,
223249
event_source: PeerId,
224-
connection: ConnectionId,
250+
connection_id: ConnectionId,
225251
handler_event: THandlerOutEvent<Self>,
226252
) {
253+
let relayed_connection_id = match handler_event.as_ref() {
254+
Either::Left(_) => connection_id,
255+
Either::Right(_) => match self.direct_to_relayed_connections.get(&connection_id) {
256+
None => {
257+
// If the connection ID is unknown to us, it means we didn't create it so ignore any event coming from it.
258+
return;
259+
}
260+
Some(relayed_connection_id) => *relayed_connection_id,
261+
},
262+
};
263+
227264
match handler_event {
228265
Either::Left(handler::relayed::Event::InboundConnectRequest {
229266
inbound_connect,
230267
remote_addr,
231268
}) => {
232269
self.queued_events.extend([
233270
NetworkBehaviourAction::NotifyHandler {
234-
handler: NotifyHandler::One(connection),
271+
handler: NotifyHandler::One(relayed_connection_id),
235272
peer_id: event_source,
236273
event: Either::Left(handler::relayed::Command::AcceptInboundConnect {
237274
inbound_connect,
@@ -256,16 +293,17 @@ impl NetworkBehaviour for Behaviour {
256293
));
257294
}
258295
Either::Left(handler::relayed::Event::InboundConnectNegotiated(remote_addrs)) => {
259-
self.queued_events.push_back(NetworkBehaviourAction::Dial {
260-
opts: DialOpts::peer_id(event_source)
261-
.addresses(remote_addrs)
262-
.condition(dial_opts::PeerCondition::Always)
263-
.build(),
264-
handler: handler::Prototype::DirectConnection {
265-
relayed_connection_id: connection,
266-
role: handler::Role::Listener,
267-
},
268-
});
296+
let opts = DialOpts::peer_id(event_source)
297+
.addresses(remote_addrs)
298+
.condition(dial_opts::PeerCondition::Always)
299+
.build();
300+
301+
let maybe_direct_connection_id = opts.connection_id();
302+
303+
self.direct_to_relayed_connections
304+
.insert(maybe_direct_connection_id, relayed_connection_id);
305+
self.queued_events
306+
.push_back(NetworkBehaviourAction::Dial { opts });
269307
}
270308
Either::Left(handler::relayed::Event::OutboundNegotiationFailed { error }) => {
271309
self.queued_events
@@ -276,27 +314,25 @@ impl NetworkBehaviour for Behaviour {
276314
},
277315
));
278316
}
279-
Either::Left(handler::relayed::Event::OutboundConnectNegotiated {
280-
remote_addrs,
281-
attempt,
282-
}) => {
283-
self.queued_events.push_back(NetworkBehaviourAction::Dial {
284-
opts: DialOpts::peer_id(event_source)
285-
.condition(dial_opts::PeerCondition::Always)
286-
.addresses(remote_addrs)
287-
.override_role()
288-
.build(),
289-
handler: handler::Prototype::DirectConnection {
290-
relayed_connection_id: connection,
291-
role: handler::Role::Initiator { attempt },
292-
},
293-
});
317+
Either::Left(handler::relayed::Event::OutboundConnectNegotiated { remote_addrs }) => {
318+
let opts = DialOpts::peer_id(event_source)
319+
.condition(dial_opts::PeerCondition::Always)
320+
.addresses(remote_addrs)
321+
.override_role()
322+
.build();
323+
324+
let maybe_direct_connection_id = opts.connection_id();
325+
326+
self.direct_to_relayed_connections
327+
.insert(maybe_direct_connection_id, relayed_connection_id);
328+
*self
329+
.outgoing_direct_connection_attempts
330+
.entry((relayed_connection_id, event_source))
331+
.or_default() += 1;
332+
self.queued_events
333+
.push_back(NetworkBehaviourAction::Dial { opts });
294334
}
295-
Either::Right(Either::Left(
296-
handler::direct::Event::DirectConnectionUpgradeSucceeded {
297-
relayed_connection_id,
298-
},
299-
)) => {
335+
Either::Right(handler::direct::Event::DirectConnectionEstablished) => {
300336
self.queued_events.extend([
301337
NetworkBehaviourAction::NotifyHandler {
302338
peer_id: event_source,
@@ -312,15 +348,14 @@ impl NetworkBehaviour for Behaviour {
312348
),
313349
]);
314350
}
315-
Either::Right(Either::Right(event)) => void::unreachable(event),
316351
};
317352
}
318353

319354
fn poll(
320355
&mut self,
321356
_cx: &mut Context<'_>,
322357
_: &mut impl PollParameters,
323-
) -> Poll<NetworkBehaviourAction<Self::OutEvent, Self::ConnectionHandler>> {
358+
) -> Poll<NetworkBehaviourAction<Self::OutEvent, THandlerInEvent<Self>>> {
324359
if let Some(event) = self.queued_events.pop_front() {
325360
return Poll::Ready(event);
326361
}

0 commit comments

Comments
 (0)