Skip to content

Commit 47844ca

Browse files
Fix unexpected ConnectionDirection update (#188)
* The handler instructs the service on how to update connection direction. * cargo fmt * cargo fmt * Fix clippy warning * Add tests for inject_session_established() * Rename ConnectionDirectionInstruction shortly * read access * Update src/service/test.rs Co-authored-by: Divma <[email protected]> * Update src/service/test.rs Co-authored-by: Divma <[email protected]> * Add a test case * We never update connection direction if a node already exists in the routing table * Update src/service.rs Fix typo Co-authored-by: Divma <[email protected]> --------- Co-authored-by: Divma <[email protected]>
1 parent 370b147 commit 47844ca

File tree

3 files changed

+73
-7
lines changed

3 files changed

+73
-7
lines changed

src/handler/mod.rs

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -682,12 +682,10 @@ impl Handler {
682682
// outgoing session is that we originally sent a RANDOM packet (signifying we did
683683
// not have a session for a request) and the packet is not a PING (we are not
684684
// trying to update an old session that may have expired.
685-
let connection_direction = {
686-
match (request_call.initiating_session(), &request_call.body()) {
687-
(true, RequestBody::Ping { .. }) => ConnectionDirection::Incoming,
688-
(true, _) => ConnectionDirection::Outgoing,
689-
(false, _) => ConnectionDirection::Incoming,
690-
}
685+
let connection_direction = if request_call.initiating_session() {
686+
ConnectionDirection::Outgoing
687+
} else {
688+
ConnectionDirection::Incoming
691689
};
692690

693691
// We already know the ENR. Send the handshake response packet

src/service.rs

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1369,13 +1369,27 @@ impl Service {
13691369

13701370
/// The equivalent of libp2p `inject_connected()` for a udp session. We have no stream, but a
13711371
/// session key-pair has been negotiated.
1372-
fn inject_session_established(&mut self, enr: Enr, direction: ConnectionDirection) {
1372+
fn inject_session_established(&mut self, enr: Enr, connection_direction: ConnectionDirection) {
13731373
// Ignore sessions with non-contactable ENRs
13741374
if self.ip_mode.get_contactable_addr(&enr).is_none() {
13751375
return;
13761376
}
13771377

13781378
let node_id = enr.node_id();
1379+
1380+
// We never update connection direction if a node already exists in the routing table as we
1381+
// don't want to promote the direction from incoming to outgoing.
1382+
let key = kbucket::Key::from(node_id);
1383+
let direction = match self
1384+
.kbuckets
1385+
.read()
1386+
.get_bucket(&key)
1387+
.map(|bucket| bucket.get(&key))
1388+
{
1389+
Some(Some(node)) => node.status.direction,
1390+
_ => connection_direction,
1391+
};
1392+
13791393
debug!(
13801394
"Session established with Node: {}, direction: {}",
13811395
node_id, direction

src/service/test.rs

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -164,3 +164,57 @@ async fn test_updating_connection_on_ping() {
164164
let node = buckets.iter_ref().next().unwrap();
165165
assert!(node.status.is_connected())
166166
}
167+
168+
#[tokio::test]
169+
async fn test_connection_direction_on_inject_session_established() {
170+
init();
171+
172+
let enr_key1 = CombinedKey::generate_secp256k1();
173+
let ip = std::net::Ipv4Addr::LOCALHOST;
174+
let enr = EnrBuilder::new("v4")
175+
.ip4(ip)
176+
.udp4(10001)
177+
.build(&enr_key1)
178+
.unwrap();
179+
180+
let enr_key2 = CombinedKey::generate_secp256k1();
181+
let ip2 = std::net::Ipv4Addr::LOCALHOST;
182+
let enr2 = EnrBuilder::new("v4")
183+
.ip4(ip2)
184+
.udp4(10002)
185+
.build(&enr_key2)
186+
.unwrap();
187+
188+
let mut service = build_service::<DefaultProtocolId>(
189+
Arc::new(RwLock::new(enr)),
190+
Arc::new(RwLock::new(enr_key1)),
191+
false,
192+
)
193+
.await;
194+
195+
let key = &kbucket::Key::from(enr2.node_id());
196+
197+
// Test that the existing connection direction is not updated.
198+
// Incoming
199+
service.inject_session_established(enr2.clone(), ConnectionDirection::Incoming);
200+
let status = service.kbuckets.read().iter_ref().next().unwrap().status;
201+
assert!(status.is_connected());
202+
assert_eq!(ConnectionDirection::Incoming, status.direction);
203+
204+
service.inject_session_established(enr2.clone(), ConnectionDirection::Outgoing);
205+
let status = service.kbuckets.read().iter_ref().next().unwrap().status;
206+
assert!(status.is_connected());
207+
assert_eq!(ConnectionDirection::Incoming, status.direction);
208+
209+
// (disconnected) Outgoing
210+
let result = service.kbuckets.write().update_node_status(
211+
key,
212+
ConnectionState::Disconnected,
213+
Some(ConnectionDirection::Outgoing),
214+
);
215+
assert!(matches!(result, UpdateResult::Updated));
216+
service.inject_session_established(enr2.clone(), ConnectionDirection::Incoming);
217+
let status = service.kbuckets.read().iter_ref().next().unwrap().status;
218+
assert!(status.is_connected());
219+
assert_eq!(ConnectionDirection::Outgoing, status.direction);
220+
}

0 commit comments

Comments
 (0)