Skip to content

Commit 450fc1e

Browse files
Add test for kademlia client mode
1 parent 7699a1e commit 450fc1e

File tree

6 files changed

+88
-22
lines changed

6 files changed

+88
-22
lines changed

Cargo.lock

Lines changed: 3 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

protocols/kad/Cargo.toml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,9 +34,13 @@ serde = { version = "1.0", optional = true, features = ["derive"] }
3434
thiserror = "1"
3535

3636
[dev-dependencies]
37+
async-std = { version = "1.12.0", features = ["attributes"] }
3738
env_logger = "0.10.0"
3839
futures-timer = "3.0"
40+
libp2p-identify = { path = "../identify" }
3941
libp2p-noise = { path = "../../transports/noise" }
42+
libp2p-swarm = { path = "../../swarm", features = ["macros"] }
43+
libp2p-swarm-test = { path = "../../swarm-test" }
4044
libp2p-yamux = { path = "../../muxers/yamux" }
4145
quickcheck = { package = "quickcheck-ext", path = "../../misc/quickcheck-ext" }
4246

protocols/kad/src/behaviour.rs

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,7 @@ pub struct Kademlia<TStore> {
116116

117117
/// The record storage.
118118
store: TStore,
119+
mode: Mode,
119120
}
120121

121122
/// The configurable strategies for the insertion of peers
@@ -182,6 +183,7 @@ pub struct KademliaConfig {
182183
connection_idle_timeout: Duration,
183184
kbucket_inserts: KademliaBucketInserts,
184185
caching: KademliaCaching,
186+
mode: Mode,
185187
}
186188

187189
impl Default for KademliaConfig {
@@ -199,6 +201,7 @@ impl Default for KademliaConfig {
199201
connection_idle_timeout: Duration::from_secs(10),
200202
kbucket_inserts: KademliaBucketInserts::OnConnected,
201203
caching: KademliaCaching::Enabled { max_peers: 1 },
204+
mode: Mode::Server,
202205
}
203206
}
204207
}
@@ -399,6 +402,14 @@ impl KademliaConfig {
399402
self.caching = c;
400403
self
401404
}
405+
406+
/// Sets the mode.
407+
///
408+
/// TODO: More docs.
409+
pub fn set_mode(&mut self, m: Mode) -> &mut Self {
410+
self.mode = m;
411+
self
412+
}
402413
}
403414

404415
impl<TStore> Kademlia<TStore>
@@ -453,6 +464,7 @@ where
453464
connection_idle_timeout: config.connection_idle_timeout,
454465
external_addresses: Default::default(),
455466
local_peer_id: id,
467+
mode: config.mode,
456468
}
457469
}
458470

@@ -1976,7 +1988,7 @@ where
19761988
Ok(KademliaHandler::new(
19771989
KademliaHandlerConfig {
19781990
protocol_config: self.protocol_config.clone(),
1979-
allow_listening: true,
1991+
allow_listening: self.mode == Mode::Server,
19801992
idle_timeout: self.connection_idle_timeout,
19811993
},
19821994
ConnectedPoint::Listener {
@@ -1997,7 +2009,7 @@ where
19972009
Ok(KademliaHandler::new(
19982010
KademliaHandlerConfig {
19992011
protocol_config: self.protocol_config.clone(),
2000-
allow_listening: true,
2012+
allow_listening: self.mode == Mode::Server,
20012013
idle_timeout: self.connection_idle_timeout,
20022014
},
20032015
ConnectedPoint::Dialer {
@@ -3190,3 +3202,9 @@ pub enum RoutingUpdate {
31903202
/// peer ID).
31913203
Failed,
31923204
}
3205+
3206+
#[derive(Debug, Clone, Copy, PartialEq)]
3207+
pub enum Mode {
3208+
Client,
3209+
Server,
3210+
}

protocols/kad/src/handler.rs

Lines changed: 1 addition & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -789,25 +789,7 @@ where
789789
ConnectionEvent::AddressChange(_)
790790
| ConnectionEvent::ListenUpgradeError(_)
791791
| ConnectionEvent::LocalProtocolsChange(_) => {}
792-
ConnectionEvent::RemoteProtocolsChange(ProtocolsChange { protocols }) => {
793-
// TODO: We should cache this / it will get simpler with #2831.
794-
let kademlia_protocols = self
795-
.config
796-
.protocol_config
797-
.protocol_names()
798-
.iter()
799-
.filter_map(|b| String::from_utf8(b.to_vec()).ok())
800-
.collect::<Vec<_>>();
801-
802-
let remote_supports_our_kademlia_protocols =
803-
kademlia_protocols.iter().all(|p| protocols.contains(p));
804-
805-
if remote_supports_our_kademlia_protocols {
806-
self.protocol_status = ProtocolStatus::Confirmed;
807-
} else {
808-
self.protocol_status = ProtocolStatus::NotSupported;
809-
}
810-
}
792+
ConnectionEvent::RemoteProtocolsChange(_) => {}
811793
}
812794
}
813795
}

protocols/kad/src/lib.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ pub use behaviour::{
6161
AddProviderContext, AddProviderError, AddProviderOk, AddProviderPhase, AddProviderResult,
6262
BootstrapError, BootstrapOk, BootstrapResult, GetClosestPeersError, GetClosestPeersOk,
6363
GetClosestPeersResult, GetProvidersError, GetProvidersOk, GetProvidersResult, GetRecordError,
64-
GetRecordOk, GetRecordResult, InboundRequest, NoKnownPeers, PeerRecord, PutRecordContext,
64+
GetRecordOk, GetRecordResult, InboundRequest, Mode, NoKnownPeers, PeerRecord, PutRecordContext,
6565
PutRecordError, PutRecordOk, PutRecordPhase, PutRecordResult, QueryInfo, QueryMut, QueryRef,
6666
QueryResult, QueryStats,
6767
};

protocols/kad/tests/client_mode.rs

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
use libp2p_identify as identify;
2+
use libp2p_identity as identity;
3+
use libp2p_kad::store::MemoryStore;
4+
use libp2p_kad::{Kademlia, KademliaConfig, KademliaEvent, Mode};
5+
use libp2p_swarm::Swarm;
6+
use libp2p_swarm_test::SwarmExt;
7+
8+
#[async_std::test]
9+
async fn connection_to_node_in_client_mode_does_not_update_routing_table() {
10+
let mut client = Swarm::new_ephemeral(MyBehaviour::client);
11+
let mut server = Swarm::new_ephemeral(MyBehaviour::server);
12+
13+
server.listen().await;
14+
client.connect(&mut server).await;
15+
16+
let server_peer_id = *server.local_peer_id();
17+
18+
match libp2p_swarm_test::drive(&mut client, &mut server).await {
19+
(
20+
[MyBehaviourEvent::Identify(_), MyBehaviourEvent::Identify(_), MyBehaviourEvent::Kad(KademliaEvent::RoutingUpdated { peer, .. })],
21+
[MyBehaviourEvent::Identify(_), MyBehaviourEvent::Identify(_)],
22+
) => {
23+
assert_eq!(peer, server_peer_id)
24+
}
25+
other => panic!("Unexpected events: {other:?}"),
26+
}
27+
}
28+
29+
#[derive(libp2p_swarm::NetworkBehaviour)]
30+
#[behaviour(prelude = "libp2p_swarm::derive_prelude")]
31+
struct MyBehaviour {
32+
identify: identify::Behaviour,
33+
kad: Kademlia<MemoryStore>,
34+
}
35+
36+
impl MyBehaviour {
37+
fn client(k: identity::Keypair) -> Self {
38+
let mut config = KademliaConfig::default();
39+
config.set_mode(Mode::Client);
40+
41+
Self::with_config(k, config)
42+
}
43+
44+
fn server(k: identity::Keypair) -> Self {
45+
Self::with_config(k, KademliaConfig::default())
46+
}
47+
48+
fn with_config(k: identity::Keypair, config: KademliaConfig) -> MyBehaviour {
49+
let local_peer_id = k.public().to_peer_id();
50+
51+
Self {
52+
identify: identify::Behaviour::new(identify::Config::new(
53+
"/test/1.0.0".to_owned(),
54+
k.public(),
55+
)),
56+
kad: Kademlia::with_config(local_peer_id, MemoryStore::new(local_peer_id), config),
57+
}
58+
}
59+
}

0 commit comments

Comments
 (0)