Skip to content
This repository has been archived by the owner on Jun 25, 2021. It is now read-only.

Commit

Permalink
feat: modify bootstrap to use infrastructure queries
Browse files Browse the repository at this point in the history
  • Loading branch information
madadam authored and joshuef committed Feb 4, 2021
1 parent e0b999f commit 9fb438f
Show file tree
Hide file tree
Showing 8 changed files with 187 additions and 252 deletions.
14 changes: 11 additions & 3 deletions src/messages/envelope.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,9 @@
// KIND, either express or implied. Please review the Licences for the specific language governing
// permissions and limitations relating to use of the SAFE Network Software.

use std::convert::TryFrom;

use super::{InfrastructureQuery, Message};
use bytes::Bytes;
use bytes::{BufMut, Bytes, BytesMut};
use std::convert::TryFrom;
use thiserror::Error;

/// Single byte that identifies the message type.
Expand All @@ -26,6 +25,15 @@ pub enum MessageKind {
Infrastructure = 3,
}

impl MessageKind {
pub(crate) fn prepend_to(self, message: Bytes) -> Bytes {
let mut buffer = BytesMut::with_capacity(1 + message.len());
buffer.put_u8(self as u8);
buffer.put(message);
buffer.freeze()
}
}

impl TryFrom<u8> for MessageKind {
type Error = UnknownMessageKind;

Expand Down
11 changes: 9 additions & 2 deletions src/messages/infrastructure_query.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,16 @@ use xor_name::{Prefix, XorName};
pub enum InfrastructureQuery {
/// Message to request information about the section that matches the given name.
GetSectionRequest(XorName),
/// Response to `GetSectionRequest`.
GetSectionResponse(GetSectionResponse),
}

/// Information about a section.
#[derive(Debug, Serialize, Deserialize)]
pub enum GetSectionResponse {
/// Successful response to `GetSectionRequest`. Contains information about the requested
/// section.
GetSectionSuccess {
Success {
/// Prefix of the section.
prefix: Prefix,
/// Public key of the section.
Expand All @@ -27,5 +34,5 @@ pub enum InfrastructureQuery {
},
/// Response to `GetSectionRequest` containing addresses of nodes that are closer to the
/// requested name than the recipient. The request should be repeated to these addresses.
GetSectionRedirect(Vec<SocketAddr>),
Redirect(Vec<SocketAddr>),
}
4 changes: 3 additions & 1 deletion src/messages/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,9 @@ pub(crate) use self::{
variant::{BootstrapResponse, JoinRequest, ResourceProofResponse, Variant},
};
pub use self::{
envelope::MessageKind, hash::MessageHash, infrastructure_query::InfrastructureQuery,
envelope::MessageKind,
hash::MessageHash,
infrastructure_query::{GetSectionResponse, InfrastructureQuery},
src_authority::SrcAuthority,
};
use crate::{
Expand Down
9 changes: 0 additions & 9 deletions src/messages/variant.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,7 @@ use serde::{Deserialize, Serialize};
use std::{
collections::VecDeque,
fmt::{self, Debug, Formatter},
net::SocketAddr,
};
use xor_name::XorName;

#[derive(Clone, Eq, PartialEq, Serialize, Deserialize)]
#[allow(clippy::large_enum_variant)]
Expand Down Expand Up @@ -60,9 +58,6 @@ pub(crate) enum Variant {
/// - from a section to a current elder to be relocated after they are demoted.
/// - from the node to be relocated back to its section after it was demoted.
RelocatePromise(RelocatePromise),
/// Sent from a newly connected peer to the bootstrap node to request connection infos of
/// members of the section matching the given name.
BootstrapRequest(XorName),
/// Sent from the bootstrap node to a peer in response to `BootstrapRequest`. It can either
/// accept the peer into the section, or redirect it to another set of bootstrap peers
BootstrapResponse(BootstrapResponse),
Expand Down Expand Up @@ -186,7 +181,6 @@ impl Debug for Variant {
.finish(),
Self::Relocate(payload) => write!(f, "Relocate({:?})", payload),
Self::RelocatePromise(payload) => write!(f, "RelocatePromise({:?})", payload),
Self::BootstrapRequest(payload) => write!(f, "BootstrapRequest({})", payload),
Self::BootstrapResponse(payload) => write!(f, "BootstrapResponse({:?})", payload),
Self::JoinRequest(payload) => write!(f, "JoinRequest({:?})", payload),
Self::BouncedUntrustedMessage(message) => f
Expand Down Expand Up @@ -256,9 +250,6 @@ pub enum BootstrapResponse {
elders_info: EldersInfo,
section_key: bls::PublicKey,
},
/// The new peer should retry bootstrapping with another section. The set of connection infos
/// of the members of that section is provided.
Rebootstrap(Vec<SocketAddr>),
}

/// Joining peer's proof of resolvement of given resource proofing challenge.
Expand Down
47 changes: 7 additions & 40 deletions src/routing/approved.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,9 @@ use crate::{
location::{DstLocation, SrcLocation},
message_filter::MessageFilter,
messages::{
BootstrapResponse, Envelope, InfrastructureQuery, JoinRequest, Message, MessageHash,
MessageKind, MessageStatus, PlainMessage, ResourceProofResponse, Variant, VerifyStatus,
BootstrapResponse, Envelope, GetSectionResponse, InfrastructureQuery, JoinRequest, Message,
MessageHash, MessageKind, MessageStatus, PlainMessage, ResourceProofResponse, Variant,
VerifyStatus,
},
network::Network,
node::Node,
Expand Down Expand Up @@ -202,7 +203,7 @@ impl Approved {
debug!("Received GetSectionRequest({}) from {}", name, sender);

let response = if self.section.prefix().matches(&name) {
InfrastructureQuery::GetSectionSuccess {
GetSectionResponse::Success {
prefix: self.section.elders_info().prefix,
key: *self.section.chain().last_key(),
elders: self
Expand All @@ -214,10 +215,11 @@ impl Approved {
}
} else if let Some(section) = self.network.closest(&name) {
let addrs = section.peers().map(Peer::addr).copied().collect();
InfrastructureQuery::GetSectionRedirect(addrs)
GetSectionResponse::Redirect(addrs)
} else {
return Err(Error::InvalidDstLocation);
};
let response = InfrastructureQuery::GetSectionResponse(response);
let response = bincode::serialize(&response)?.into();

debug!("Sending {:?} to {}", response, sender);
Expand All @@ -228,8 +230,7 @@ impl Approved {
message: response,
}])
}
InfrastructureQuery::GetSectionSuccess { .. }
| InfrastructureQuery::GetSectionRedirect(_) => {
InfrastructureQuery::GetSectionResponse(_) => {
if let Some(RelocateState::InProgress(tx)) = &mut self.relocate_state {
trace!("Forwarding {:?} to the bootstrap task", message);
let _ = tx.send((Envelope::Infrastructure(message), sender)).await;
Expand Down Expand Up @@ -525,7 +526,6 @@ impl Approved {
}
Variant::Sync { .. }
| Variant::Relocate(_)
| Variant::BootstrapRequest(_)
| Variant::BouncedUntrustedMessage(_)
| Variant::BouncedUnknownMessage { .. }
| Variant::DKGMessage { .. }
Expand Down Expand Up @@ -563,14 +563,6 @@ impl Approved {
Variant::RelocatePromise(promise) => {
self.handle_relocate_promise(*promise, msg.to_bytes())
}
Variant::BootstrapRequest(name) => {
let sender = sender.ok_or(Error::InvalidSrcLocation)?;
Ok(vec![self.handle_bootstrap_request(
msg.src().to_node_peer(sender)?,
*name,
)?])
}

Variant::JoinRequest(join_request) => {
let sender = sender.ok_or(Error::InvalidSrcLocation)?;
self.handle_join_request(msg.src().to_node_peer(sender)?, *join_request.clone())
Expand Down Expand Up @@ -1000,31 +992,6 @@ impl Approved {
Ok(commands)
}

// Note: As an adult, we should only give info about our section elders and they would
// further guide the joining node. However this lead to a loop if the Adult is the new Elder so
// we use the same code as for Elder and return Join in some cases.
fn handle_bootstrap_request(&self, peer: Peer, destination: XorName) -> Result<Command> {
debug!(
"Received BootstrapRequest to section at {} from {:?}.",
destination, peer
);

let response = if self.section.prefix().matches(&destination) {
BootstrapResponse::Join {
elders_info: self.section.elders_info().clone(),
section_key: *self.section.chain().last_key(),
}
} else if let Some(section) = self.network.closest(&destination) {
let conn_infos = section.peers().map(Peer::addr).copied().collect();
BootstrapResponse::Rebootstrap(conn_infos)
} else {
return Err(Error::InvalidDstLocation);
};

debug!("Sending BootstrapResponse {:?} to {}", response, peer);
self.send_direct_message(peer.addr(), Variant::BootstrapResponse(response))
}

fn handle_join_request(
&mut self,
peer: Peer,
Expand Down

0 comments on commit 9fb438f

Please sign in to comment.