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

Commit

Permalink
fix: redirect to our elders on mismatching GetSectionRequest as adult
Browse files Browse the repository at this point in the history
  • Loading branch information
madadam authored and S-Coyle committed Feb 4, 2021
1 parent cb5c24f commit 22c4745
Show file tree
Hide file tree
Showing 3 changed files with 68 additions and 15 deletions.
18 changes: 11 additions & 7 deletions src/routing/approved.rs
Original file line number Diff line number Diff line change
Expand Up @@ -201,7 +201,7 @@ impl Approved {
&mut self,
sender: SocketAddr,
message: Query,
) -> Result<Vec<Command>> {
) -> Vec<Command> {
match message {
Query::GetSectionRequest(name) => {
debug!("Received GetSectionRequest({}) from {}", name, sender);
Expand All @@ -217,20 +217,24 @@ impl Approved {
.map(|peer| (*peer.name(), *peer.addr()))
.collect(),
}
} else if let Some(section) = self.network.closest(&name) {
} else {
// If we are elder, we should know a section that is closer to `name` that us.
// Otherwise redirect to our elders.
let section = self
.network
.closest(&name)
.unwrap_or_else(|| self.section.elders_info());
let addrs = section.peers().map(Peer::addr).copied().collect();
GetSectionResponse::Redirect(addrs)
} else {
return Err(Error::InvalidDstLocation);
};
let response = Query::GetSectionResponse(response);
debug!("Sending {:?} to {}", response, sender);

Ok(vec![Command::SendMessage {
vec![Command::SendMessage {
recipients: vec![sender],
delivery_group_size: 1,
message: MessageType::InfrastructureQuery(response),
}])
}]
}
Query::GetSectionResponse(_) => {
if let Some(RelocateState::InProgress(tx)) = &mut self.relocate_state {
Expand All @@ -240,7 +244,7 @@ impl Approved {
.await;
}

Ok(vec![])
vec![]
}
}
}
Expand Down
13 changes: 6 additions & 7 deletions src/routing/stage.rs
Original file line number Diff line number Diff line change
Expand Up @@ -101,13 +101,12 @@ impl Stage {
.handle_message(sender, message)
.await
}
Command::HandleInfrastructureQuery { sender, message } => {
self.state
.lock()
.await
.handle_infrastructure_query(sender, message)
.await
}
Command::HandleInfrastructureQuery { sender, message } => Ok(self
.state
.lock()
.await
.handle_infrastructure_query(sender, message)
.await),
Command::HandleTimeout(token) => self.state.lock().await.handle_timeout(token),
Command::HandleVote { vote, proof_share } => {
self.state.lock().await.handle_vote(vote, proof_share)
Expand Down
52 changes: 51 additions & 1 deletion src/routing/tests/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ use tokio::sync::mpsc;
use xor_name::{Prefix, XorName};

#[tokio::test]
async fn receive_get_section_request() -> Result<()> {
async fn receive_matching_get_section_request_as_elder() -> Result<()> {
let node = create_node();
let state = Approved::first_node(node, mpsc::unbounded_channel().0)?;
let stage = Stage::new(state, create_comm()?);
Expand Down Expand Up @@ -82,6 +82,56 @@ async fn receive_get_section_request() -> Result<()> {
Ok(())
}

#[tokio::test]
async fn receive_mismatching_get_section_request_as_adult() -> Result<()> {
let good_prefix = Prefix::default().pushed(false);
let bad_prefix = Prefix::default().pushed(true);

let sk_set = SecretKeySet::random();
let (elders_info, _) = gen_elders_info(good_prefix, ELDER_SIZE);
let elders_addrs: Vec<_> = elders_info.peers().map(Peer::addr).copied().collect();
let (section, _) = create_section(&sk_set, &elders_info)?;

let node = create_node();
let state = Approved::new(node, section, None, mpsc::unbounded_channel().0);
let stage = Stage::new(state, create_comm()?);

let new_node_name = bad_prefix.substituted_in(rand::random());
let new_node_addr = gen_addr();

let message = Query::GetSectionRequest(new_node_name);

let mut commands = stage
.handle_command(Command::HandleInfrastructureQuery {
sender: new_node_addr,
message,
})
.await?
.into_iter();

let (recipients, message) = assert_matches!(
commands.next(),
Some(Command::SendMessage {
recipients,
message: MessageType::InfrastructureQuery(message), ..
}) => (recipients, message)
);

assert_eq!(recipients, [new_node_addr]);
assert_matches!(
message,
Query::GetSectionResponse(GetSectionResponse::Redirect(addrs)) => {
assert_eq!(addrs, elders_addrs)
}
);

Ok(())
}

// TODO: add test `receive_mismatching_get_section_request_as_elder` - should respond with
// `Redirect` response containing addresses of nodes in a section that is closer to the joining
// name.

#[tokio::test]
async fn receive_join_request_without_resource_proof_response() -> Result<()> {
let node = create_node();
Expand Down

0 comments on commit 22c4745

Please sign in to comment.