-
Notifications
You must be signed in to change notification settings - Fork 1k
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
Support client mode in kademlia #2184
Changes from 22 commits
f8cf486
1a042f8
3e759a0
b8cbe62
fc218a0
e58e544
af1fcbd
c944ecb
4be8fca
e213350
e47148d
cdaa0a1
1a09907
46167a1
8bf3ef4
9ef4c4c
c387f41
5b21774
5ea645e
aa6500f
146405f
2cea417
54331e5
9d23741
b202c5b
8234a17
d5e6509
06c1a30
d420fa6
190c3dd
ab97b10
f3259b1
f308b0c
8f33ba1
520fb8e
d52c6af
81eae5f
f0c2fc3
f0bf7df
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 |
---|---|---|
|
@@ -1287,3 +1287,67 @@ fn network_behaviour_inject_address_change() { | |
kademlia.addresses_of_peer(&remote_peer_id), | ||
); | ||
} | ||
|
||
#[test] | ||
fn client_mode() { | ||
let mut cfg = KademliaConfig::default(); | ||
cfg.set_mode(Mode::Client); | ||
|
||
// Create a server and client peer. | ||
let client_swarm = build_node_with_config(cfg); | ||
let server_swarm = build_node_with_config(KademliaConfig::default()); | ||
|
||
let mut swarms = vec![client_swarm, server_swarm]; | ||
|
||
// Collect addresses and peer IDs. | ||
let addrs: Vec<_> = swarms.iter().map(|(addr, _)| addr.clone()).collect(); | ||
let peers: Vec<_> = swarms | ||
.iter() | ||
.map(|(_, swarm)| swarm.local_peer_id().clone()) | ||
.collect(); | ||
|
||
swarms[0].1.dial_addr(addrs[1].clone()).unwrap(); | ||
swarms[1].1.dial_addr(addrs[0].clone()).unwrap(); | ||
|
||
block_on(poll_fn(move |ctx| { | ||
whereistejas marked this conversation as resolved.
Show resolved
Hide resolved
|
||
// Flag variables to store the result of various checks. | ||
let mut is_server_present = false; | ||
let mut is_client_absent = false; | ||
|
||
for (_, swarm) in swarms.iter_mut() { | ||
loop { | ||
match swarm.poll_next_unpin(ctx) { | ||
Poll::Ready(Some(SwarmEvent::Behaviour(KademliaEvent::RoutingUpdated { | ||
peer, | ||
.. | ||
}))) => { | ||
// Check if the server peer is present in the client peer's routing table. | ||
if swarm.local_peer_id().clone() == peers[0] { | ||
is_server_present = peer == peers[1]; | ||
} | ||
return Poll::Ready(()); | ||
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 is one part of this code, that I don't understand. I noticed that the test fails if we don't add 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. I suggest reading the async book: https://rust-lang.github.io/async-book/ With the early return we might not check whether the server stores the client in its routing table. |
||
} | ||
Poll::Ready(_) => { | ||
whereistejas marked this conversation as resolved.
Show resolved
Hide resolved
|
||
// Check if the client peer is NOT present in the server peer's routing table. | ||
if swarm.local_peer_id().clone() == peers[1] { | ||
is_client_absent = swarm.behaviour_mut().kbucket(peers[0]).is_none(); | ||
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 is kind of hard to reliably check for absence of something, especially in an async setting. How about:
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. Sure. I will implement this. I will try to finish before the same time, tomorrow. Please, keep an eye out for any notifications from this PR. I want to get this PR closed, as early as possible (ofcourse, without sacrificing code quality). Are we finished with the other parts of this PR except the test? |
||
} | ||
return Poll::Ready(()); | ||
} | ||
Poll::Pending => break, | ||
} | ||
} | ||
} | ||
// The assert statements are present outside the match block, to make sure that all the | ||
// necessary events occur. | ||
assert!( | ||
is_server_present, | ||
"The client peer does not have the server peer in its routing table." | ||
); | ||
assert!( | ||
is_client_absent, | ||
"The server peer has the client peer in its routing table." | ||
); | ||
Poll::Pending | ||
})) | ||
} |
Original file line number | Diff line number | Diff line change | ||||||
---|---|---|---|---|---|---|---|---|
|
@@ -46,6 +46,19 @@ pub const DEFAULT_PROTO_NAME: &[u8] = b"/ipfs/kad/1.0.0"; | |||||||
/// The default maximum size for a varint length-delimited packet. | ||||||||
pub const DEFAULT_MAX_PACKET_SIZE: usize = 16 * 1024; | ||||||||
|
||||||||
#[derive(Debug, Clone)] | ||||||||
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.
Suggested change
|
||||||||
/// See [`crate::KademliaConfig::set_mode`]. | ||||||||
pub enum Mode { | ||||||||
Client, | ||||||||
Server, | ||||||||
} | ||||||||
|
||||||||
impl Default for Mode { | ||||||||
fn default() -> Self { | ||||||||
Mode::Server | ||||||||
} | ||||||||
} | ||||||||
|
||||||||
/// Status of our connection to a node reported by the Kademlia protocol. | ||||||||
#[derive(Copy, Clone, PartialEq, Eq, Debug, Hash)] | ||||||||
pub enum KadConnectionType { | ||||||||
|
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.
Why does the server dial the client?
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.
It's there to guarantee that server tried to reach out to the client, before we check if the client is absent from the server's routing table.