mirror of
https://github.com/fluencelabs/rust-libp2p
synced 2025-06-30 10:11:33 +00:00
Kademlia Records (#1144)
* initial implementation of the records * move to multihash keys * correctly process query results * comments and formatting * correctly return closer_peers in query * checking wrong peer id in test * Apply suggestions from code review Co-Authored-By: Roman Borschel <romanb@users.noreply.github.com> * Fix changes from suggestions * Send responses to PUT_VALUE requests * Shortcut in get_value * Update protocols/kad/src/behaviour.rs Co-Authored-By: Roman Borschel <romanb@users.noreply.github.com> * Revert "Update protocols/kad/src/behaviour.rs" This reverts commit 579ce742a7f4c94587f1e1f0866d2a3a37418efb. * Remove duplicate insertion * Adds a record to a PUT_VALUE response * Fix a racy put_value test * Store value ourselves only if we are in K closest * Abstract over storage * Revert "Abstract over storage": bad take This reverts commit eaebf5b6d915712eaf3b05929577fdf697f204d8. * Abstract over records storage using hashmap as default * Constructor for custom records * New Record type and its traits * Fix outdated storage name * Fixes returning an event * Change FindNodeReq key type to Multihash * WriteState for a second stage of a PUT_VALUE request * GET_VALUE should not have a record * Refactor a match arm * Add successes and failures counters to PutValueRes * If value is found no need to return closer peers * Remove a custo storage from tests * Rename a test to get_value_not_found * Adds a TODO to change FindNode request key to Multihash Co-Authored-By: Roman Borschel <romanb@users.noreply.github.com> * Move MemoryRecordStorage to record.rs * Return a Cow-ed Record from get * Fix incorrect GET_VALUE parsing * Various fixes with review * Fixes get_value_not_found * Fix peerids names in test * another fix * PutValue correctly distributes values * Simplify the test * Check that results are actually the closest * Reverts changes to tests * Fix the test topology and checking the results * Run put_value test ten times * Adds a get_value test * Apply suggestions from code review Co-Authored-By: Roman Borschel <romanb@users.noreply.github.com> * Make Record fields public * Moves WriteState to write.rs * A couple of minor fixes * Another few fixes of review * Simplify the put_value test * Dont synchronously return an error from put_value * Formatting fixes and comments * Collect a bunch of results * Take exactly as much elements as neede * Check if the peer is still connected * Adds a multiple GetValueResults results number test * Unnecessary mut iterators in put_value * Ask for num_results in get_value * Dont allocate twice in get_value * Dont count same errored peer multiple times * Apply suggestions from code review Co-Authored-By: Roman Borschel <romanb@users.noreply.github.com> * Fix another review * Apply suggestions from code review Co-Authored-By: Pierre Krieger <pierre.krieger1708@gmail.com> * Bring back FromIterator and improve a panic message * Update protocols/kad/src/behaviour.rs Co-Authored-By: Pierre Krieger <pierre.krieger1708@gmail.com>
This commit is contained in:
committed by
Pierre Krieger
parent
603fd5744f
commit
22527e7eb6
@ -33,6 +33,7 @@
|
||||
use bytes::BytesMut;
|
||||
use codec::UviBytes;
|
||||
use crate::protobuf_structs::dht as proto;
|
||||
use crate::record::Record;
|
||||
use futures::{future::{self, FutureResult}, sink, stream, Sink, Stream};
|
||||
use libp2p_core::{Multiaddr, PeerId};
|
||||
use libp2p_core::upgrade::{InboundUpgrade, OutboundUpgrade, UpgradeInfo, Negotiated};
|
||||
@ -273,6 +274,20 @@ pub enum KadRequestMsg {
|
||||
/// Known provider for this key.
|
||||
provider_peer: KadPeer,
|
||||
},
|
||||
|
||||
/// Request to get a value from the dht records.
|
||||
GetValue {
|
||||
/// The key we are searching for.
|
||||
key: Multihash,
|
||||
},
|
||||
|
||||
/// Request to put a value into the dht records.
|
||||
PutValue {
|
||||
/// The key of the record.
|
||||
key: Multihash,
|
||||
/// The value of the record.
|
||||
value: Vec<u8>,
|
||||
}
|
||||
}
|
||||
|
||||
/// Response that we can send to a peer or that we received from a peer.
|
||||
@ -294,6 +309,22 @@ pub enum KadResponseMsg {
|
||||
/// Known providers for this key.
|
||||
provider_peers: Vec<KadPeer>,
|
||||
},
|
||||
|
||||
/// Response to a `GetValue`.
|
||||
GetValue {
|
||||
/// Result that might have been found
|
||||
result: Option<Record>,
|
||||
/// Nodes closest to the key
|
||||
closer_peers: Vec<KadPeer>,
|
||||
},
|
||||
|
||||
/// Response to a `PutValue`.
|
||||
PutValue {
|
||||
/// The key of the record.
|
||||
key: Multihash,
|
||||
/// Value of the record.
|
||||
value: Vec<u8>,
|
||||
},
|
||||
}
|
||||
|
||||
/// Converts a `KadRequestMsg` into the corresponding protobuf message for sending.
|
||||
@ -326,6 +357,24 @@ fn req_msg_to_proto(kad_msg: KadRequestMsg) -> proto::Message {
|
||||
msg.mut_providerPeers().push(provider_peer.into());
|
||||
msg
|
||||
}
|
||||
KadRequestMsg::GetValue { key } => {
|
||||
let mut msg = proto::Message::new();
|
||||
msg.set_field_type(proto::Message_MessageType::GET_VALUE);
|
||||
msg.set_clusterLevelRaw(10);
|
||||
msg.set_key(key.into_bytes());
|
||||
|
||||
msg
|
||||
}
|
||||
KadRequestMsg::PutValue { key, value} => {
|
||||
let mut msg = proto::Message::new();
|
||||
msg.set_field_type(proto::Message_MessageType::PUT_VALUE);
|
||||
let mut record = proto::Record::new();
|
||||
record.set_value(value);
|
||||
record.set_key(key.into_bytes());
|
||||
|
||||
msg.set_record(record);
|
||||
msg
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -361,6 +410,41 @@ fn resp_msg_to_proto(kad_msg: KadResponseMsg) -> proto::Message {
|
||||
}
|
||||
msg
|
||||
}
|
||||
KadResponseMsg::GetValue {
|
||||
result,
|
||||
closer_peers,
|
||||
} => {
|
||||
let mut msg = proto::Message::new();
|
||||
msg.set_field_type(proto::Message_MessageType::GET_VALUE);
|
||||
msg.set_clusterLevelRaw(9);
|
||||
for peer in closer_peers {
|
||||
msg.mut_closerPeers().push(peer.into());
|
||||
}
|
||||
|
||||
if let Some(Record{ key, value }) = result {
|
||||
let mut record = proto::Record::new();
|
||||
record.set_key(key.into_bytes());
|
||||
record.set_value(value);
|
||||
msg.set_record(record);
|
||||
}
|
||||
|
||||
msg
|
||||
}
|
||||
KadResponseMsg::PutValue {
|
||||
key,
|
||||
value,
|
||||
} => {
|
||||
let mut msg = proto::Message::new();
|
||||
msg.set_field_type(proto::Message_MessageType::PUT_VALUE);
|
||||
msg.set_key(key.clone().into_bytes());
|
||||
|
||||
let mut record = proto::Record::new();
|
||||
record.set_key(key.into_bytes());
|
||||
record.set_value(value);
|
||||
msg.set_record(record);
|
||||
|
||||
msg
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -371,11 +455,16 @@ fn proto_to_req_msg(mut message: proto::Message) -> Result<KadRequestMsg, io::Er
|
||||
match message.get_field_type() {
|
||||
proto::Message_MessageType::PING => Ok(KadRequestMsg::Ping),
|
||||
|
||||
proto::Message_MessageType::PUT_VALUE =>
|
||||
Err(invalid_data("Unsupported: PUT_VALUE message.")),
|
||||
proto::Message_MessageType::PUT_VALUE => {
|
||||
let record = message.mut_record();
|
||||
let key = Multihash::from_bytes(record.take_key()).map_err(invalid_data)?;
|
||||
Ok(KadRequestMsg::PutValue { key, value: record.take_value() })
|
||||
}
|
||||
|
||||
proto::Message_MessageType::GET_VALUE =>
|
||||
Err(invalid_data("Unsupported: GET_VALUE message.")),
|
||||
proto::Message_MessageType::GET_VALUE => {
|
||||
let key = Multihash::from_bytes(message.take_key()).map_err(invalid_data)?;
|
||||
Ok(KadRequestMsg::GetValue { key })
|
||||
}
|
||||
|
||||
proto::Message_MessageType::FIND_NODE => {
|
||||
let key = PeerId::from_bytes(message.take_key())
|
||||
@ -414,8 +503,24 @@ fn proto_to_resp_msg(mut message: proto::Message) -> Result<KadResponseMsg, io::
|
||||
match message.get_field_type() {
|
||||
proto::Message_MessageType::PING => Ok(KadResponseMsg::Pong),
|
||||
|
||||
proto::Message_MessageType::GET_VALUE =>
|
||||
Err(invalid_data("Unsupported: GET_VALUE message")),
|
||||
proto::Message_MessageType::GET_VALUE => {
|
||||
let result = match message.has_record() {
|
||||
true => {
|
||||
let mut record = message.take_record();
|
||||
let key = Multihash::from_bytes(record.take_key()).map_err(invalid_data)?;
|
||||
Some(Record { key, value: record.take_value() })
|
||||
}
|
||||
false => None,
|
||||
};
|
||||
|
||||
let closer_peers = message
|
||||
.mut_closerPeers()
|
||||
.iter_mut()
|
||||
.filter_map(|peer| KadPeer::try_from(peer).ok())
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
Ok(KadResponseMsg::GetValue { result, closer_peers })
|
||||
},
|
||||
|
||||
proto::Message_MessageType::FIND_NODE => {
|
||||
let closer_peers = message
|
||||
@ -446,8 +551,18 @@ fn proto_to_resp_msg(mut message: proto::Message) -> Result<KadResponseMsg, io::
|
||||
})
|
||||
}
|
||||
|
||||
proto::Message_MessageType::PUT_VALUE =>
|
||||
Err(invalid_data("received an unexpected PUT_VALUE message")),
|
||||
proto::Message_MessageType::PUT_VALUE => {
|
||||
let key = Multihash::from_bytes(message.take_key()).map_err(invalid_data)?;
|
||||
if !message.has_record() {
|
||||
return Err(invalid_data("received PUT_VALUE message with no record"));
|
||||
}
|
||||
|
||||
let mut record = message.take_record();
|
||||
Ok(KadResponseMsg::PutValue {
|
||||
key,
|
||||
value: record.take_value(),
|
||||
})
|
||||
}
|
||||
|
||||
proto::Message_MessageType::ADD_PROVIDER =>
|
||||
Err(invalid_data("received an unexpected ADD_PROVIDER message"))
|
||||
|
Reference in New Issue
Block a user