Update lox-distributor to handle gone resources more correctly
This commit is contained in:
parent
2e4090e21c
commit
221f490d26
|
@ -66,15 +66,17 @@ impl LoxServerContext {
|
||||||
ba_obj.add_spare_bucket(bucket);
|
ba_obj.add_spare_bucket(bucket);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn replace_with_new(&self, bridgeline: BridgeLine) -> bool {
|
pub fn replace_with_new(&self, bridgeline: BridgeLine) -> lox::ReplaceSuccess {
|
||||||
let mut ba_obj = self.ba.lock().unwrap();
|
let mut ba_obj = self.ba.lock().unwrap();
|
||||||
let eb_obj = self.extra_bridges.lock().unwrap();
|
let eb_obj = self.extra_bridges.lock().unwrap();
|
||||||
let available_bridge = eb_obj.last();
|
let available_bridge = eb_obj.last();
|
||||||
// .last() doesn't actually remove the object so we still have to do that
|
let result = ba_obj.bridge_replace(&bridgeline, available_bridge);
|
||||||
if eb_obj.len() > 0 {
|
// .last() doesn't actually remove the object so we still have to do that if the bridge was
|
||||||
|
// replaced with an available bridge
|
||||||
|
if result == lox::ReplaceSuccess::Replaced && eb_obj.len() > 0 {
|
||||||
self.remove_single_bridge();
|
self.remove_single_bridge();
|
||||||
}
|
}
|
||||||
ba_obj.bridge_replace(&bridgeline, available_bridge)
|
result
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn add_unreachable(&self, bridgeline: BridgeLine) -> bool {
|
pub fn add_unreachable(&self, bridgeline: BridgeLine) -> bool {
|
||||||
|
|
|
@ -135,9 +135,15 @@ async fn context_manager(mut context_rx: mpsc::Receiver<Command>) {
|
||||||
if context.unreplaced_bridges.lock().unwrap().len() > 0 {
|
if context.unreplaced_bridges.lock().unwrap().len() > 0 {
|
||||||
println!("BridgeLine to be replaced: {:?}", bridgeline);
|
println!("BridgeLine to be replaced: {:?}", bridgeline);
|
||||||
let res = context.replace_with_new(bridgeline);
|
let res = context.replace_with_new(bridgeline);
|
||||||
if res {
|
if res == lox::ReplaceSuccess::NotFound {
|
||||||
|
println!(
|
||||||
|
"BridgeLine not found in bridge_table, already updated {:?}",
|
||||||
|
bridgeline
|
||||||
|
);
|
||||||
|
} else if res == lox::ReplaceSuccess::Replaced {
|
||||||
println!("BridgeLine successfully replaced: {:?}", bridgeline);
|
println!("BridgeLine successfully replaced: {:?}", bridgeline);
|
||||||
} else {
|
} else {
|
||||||
|
assert!(res == lox::ReplaceSuccess::NotReplaced, "ReplaceSuccess incorrectly set somehow");
|
||||||
// Add the bridge to the list of unreplaced bridges in the Lox context and try
|
// Add the bridge to the list of unreplaced bridges in the Lox context and try
|
||||||
// again to replace at the next update (nothing changes in the Lox Authority)
|
// again to replace at the next update (nothing changes in the Lox Authority)
|
||||||
println!("'Gone' BridgeLine NOT replaced, saved for next update! : {:?}", bridgeline);
|
println!("'Gone' BridgeLine NOT replaced, saved for next update! : {:?}", bridgeline);
|
||||||
|
@ -210,9 +216,9 @@ async fn context_manager(mut context_rx: mpsc::Receiver<Command>) {
|
||||||
let bridgeline = parse_resource(resource);
|
let bridgeline = parse_resource(resource);
|
||||||
println!("BridgeLine to be replaced: {:?}", bridgeline);
|
println!("BridgeLine to be replaced: {:?}", bridgeline);
|
||||||
let res = context.replace_with_new(bridgeline);
|
let res = context.replace_with_new(bridgeline);
|
||||||
if res {
|
if res == lox::ReplaceSuccess::Replaced {
|
||||||
println!("BridgeLine successfully replaced: {:?}", bridgeline);
|
println!("BridgeLine successfully replaced: {:?}", bridgeline);
|
||||||
} else {
|
} else if res == lox::ReplaceSuccess::NotReplaced {
|
||||||
// Add the bridge to the list of unreplaced bridges in the Lox context and try
|
// Add the bridge to the list of unreplaced bridges in the Lox context and try
|
||||||
// again to replace at the next update (nothing changes in the Lox Authority)
|
// again to replace at the next update (nothing changes in the Lox Authority)
|
||||||
println!(
|
println!(
|
||||||
|
|
|
@ -322,7 +322,7 @@ mod tests {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn test_handle_not_found(){
|
async fn test_handle_not_found() {
|
||||||
let th = TestHarness::new();
|
let th = TestHarness::new();
|
||||||
// Test Random page
|
// Test Random page
|
||||||
let four_oh_four_req = Request::builder()
|
let four_oh_four_req = Request::builder()
|
||||||
|
@ -336,7 +336,7 @@ mod tests {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn test_handle_bad_request(){
|
async fn test_handle_bad_request() {
|
||||||
let th = TestHarness::new();
|
let th = TestHarness::new();
|
||||||
// Test that empty request to a credential issuing endpoint fails
|
// Test that empty request to a credential issuing endpoint fails
|
||||||
let req = Request::builder()
|
let req = Request::builder()
|
||||||
|
@ -349,7 +349,7 @@ mod tests {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn test_handle_invite(){
|
async fn test_handle_invite() {
|
||||||
let th = TestHarness::new();
|
let th = TestHarness::new();
|
||||||
let lc = LoxClientMock {};
|
let lc = LoxClientMock {};
|
||||||
|
|
||||||
|
@ -360,7 +360,7 @@ mod tests {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn test_handle_reachability(){
|
async fn test_handle_reachability() {
|
||||||
let th = TestHarness::new();
|
let th = TestHarness::new();
|
||||||
let lc = LoxClientMock {};
|
let lc = LoxClientMock {};
|
||||||
// Test Reachability
|
// Test Reachability
|
||||||
|
@ -372,7 +372,7 @@ mod tests {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn test_handle_pubkeys(){
|
async fn test_handle_pubkeys() {
|
||||||
let th = TestHarness::new();
|
let th = TestHarness::new();
|
||||||
let lc = LoxClientMock {};
|
let lc = LoxClientMock {};
|
||||||
// Test Pubkeys
|
// Test Pubkeys
|
||||||
|
@ -382,7 +382,7 @@ mod tests {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn test_handle_lox_protocols(){
|
async fn test_handle_lox_protocols() {
|
||||||
let mut th = TestHarness::new();
|
let mut th = TestHarness::new();
|
||||||
let lc = LoxClientMock {};
|
let lc = LoxClientMock {};
|
||||||
// Request Invite and pubkeys required for protocol tests
|
// Request Invite and pubkeys required for protocol tests
|
||||||
|
@ -416,7 +416,8 @@ mod tests {
|
||||||
state,
|
state,
|
||||||
open_response_obj,
|
open_response_obj,
|
||||||
&pubkeys_obj.lox_pub,
|
&pubkeys_obj.lox_pub,
|
||||||
).unwrap();
|
)
|
||||||
|
.unwrap();
|
||||||
let lox_cred: lox_utils::LoxCredential = lox_utils::LoxCredential {
|
let lox_cred: lox_utils::LoxCredential = lox_utils::LoxCredential {
|
||||||
lox_credential: lox_cred.0,
|
lox_credential: lox_cred.0,
|
||||||
bridgeline: Some(lox_cred.1),
|
bridgeline: Some(lox_cred.1),
|
||||||
|
|
|
@ -58,6 +58,13 @@ lazy_static! {
|
||||||
dalek_constants::RISTRETTO_BASEPOINT_TABLE;
|
dalek_constants::RISTRETTO_BASEPOINT_TABLE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(PartialEq, Eq)]
|
||||||
|
pub enum ReplaceSuccess {
|
||||||
|
NotFound = 0,
|
||||||
|
NotReplaced = 1,
|
||||||
|
Replaced = 2,
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, Serialize, Deserialize)]
|
#[derive(Clone, Debug, Serialize, Deserialize)]
|
||||||
pub struct IssuerPrivKey {
|
pub struct IssuerPrivKey {
|
||||||
x0tilde: Scalar,
|
x0tilde: Scalar,
|
||||||
|
@ -406,10 +413,12 @@ impl BridgeAuth {
|
||||||
&mut self,
|
&mut self,
|
||||||
bridge: &BridgeLine,
|
bridge: &BridgeLine,
|
||||||
available_bridge: Option<&BridgeLine>,
|
available_bridge: Option<&BridgeLine>,
|
||||||
) -> bool {
|
) -> ReplaceSuccess {
|
||||||
let mut res: bool = false;
|
let mut res = ReplaceSuccess::NotFound;
|
||||||
let reachable_bridges = &self.bridge_table.reachable.clone();
|
let reachable_bridges = &self.bridge_table.reachable.clone();
|
||||||
if let Some(positions) = reachable_bridges.get(bridge) {
|
match reachable_bridges.get(bridge) {
|
||||||
|
Some(positions) => {
|
||||||
|
println!("Should not get here");
|
||||||
if let Some(replacement) = available_bridge {
|
if let Some(replacement) = available_bridge {
|
||||||
for (bucketnum, offset) in positions.iter() {
|
for (bucketnum, offset) in positions.iter() {
|
||||||
assert!(self.bridge_table.buckets[*bucketnum as usize][*offset] == *bridge);
|
assert!(self.bridge_table.buckets[*bucketnum as usize][*offset] == *bridge);
|
||||||
|
@ -420,7 +429,7 @@ impl BridgeAuth {
|
||||||
.insert(*replacement, positions.clone());
|
.insert(*replacement, positions.clone());
|
||||||
// Remove the bridge from the bucket
|
// Remove the bridge from the bucket
|
||||||
self.bridge_table.reachable.remove(bridge);
|
self.bridge_table.reachable.remove(bridge);
|
||||||
res = true
|
res = ReplaceSuccess::Replaced
|
||||||
}
|
}
|
||||||
} else if !self.bridge_table.unallocated_bridges.is_empty() {
|
} else if !self.bridge_table.unallocated_bridges.is_empty() {
|
||||||
let replacement = &self.bridge_table.unallocated_bridges.pop().unwrap();
|
let replacement = &self.bridge_table.unallocated_bridges.pop().unwrap();
|
||||||
|
@ -432,7 +441,7 @@ impl BridgeAuth {
|
||||||
// Remove the bridge from the bucket
|
// Remove the bridge from the bucket
|
||||||
self.bridge_table.reachable.remove(bridge);
|
self.bridge_table.reachable.remove(bridge);
|
||||||
}
|
}
|
||||||
res = true
|
res = ReplaceSuccess::Replaced
|
||||||
} else if !self.bridge_table.spares.is_empty() {
|
} else if !self.bridge_table.spares.is_empty() {
|
||||||
// Get the first spare and remove it from the spares set.
|
// Get the first spare and remove it from the spares set.
|
||||||
let spare = *self.bridge_table.spares.iter().next().unwrap();
|
let spare = *self.bridge_table.spares.iter().next().unwrap();
|
||||||
|
@ -461,15 +470,19 @@ impl BridgeAuth {
|
||||||
// Remove the bridge from the bucket
|
// Remove the bridge from the bucket
|
||||||
self.bridge_table.reachable.remove(bridge);
|
self.bridge_table.reachable.remove(bridge);
|
||||||
}
|
}
|
||||||
res = true
|
res = ReplaceSuccess::Replaced
|
||||||
}
|
} else {
|
||||||
// If there are no available bridges that can be assigned here, the only thing
|
// If there are no available bridges that can be assigned here, the only thing
|
||||||
// that can be done is return an indication that updating the gone bridge
|
// that can be done is return an indication that updating the gone bridge
|
||||||
// didn't work.
|
// didn't work.
|
||||||
// In this case, we do not mark the bridge as unreachable or remove it from the
|
// In this case, we do not mark the bridge as unreachable or remove it from the
|
||||||
// reachable bridges so that we can still find it when a new bridge does become available
|
// reachable bridges so that we can still find it when a new bridge does become available
|
||||||
|
res = ReplaceSuccess::NotReplaced
|
||||||
}
|
}
|
||||||
res
|
}
|
||||||
|
None => return res,
|
||||||
|
};
|
||||||
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Mark a bridge as unreachable
|
/// Mark a bridge as unreachable
|
||||||
|
|
|
@ -727,7 +727,7 @@ fn test_update_bridge() {
|
||||||
#[test]
|
#[test]
|
||||||
fn test_bridge_replace() {
|
fn test_bridge_replace() {
|
||||||
// Create 3 open invitation buckets and 3 spare buckets
|
// Create 3 open invitation buckets and 3 spare buckets
|
||||||
let cases = vec!["available", "unallocated", "spare", "failed"];
|
let cases = vec!["not found", "available", "unallocated", "spare", "failed"];
|
||||||
for case in cases {
|
for case in cases {
|
||||||
let mut th: TestHarness;
|
let mut th: TestHarness;
|
||||||
if case != "failed" {
|
if case != "failed" {
|
||||||
|
@ -735,6 +735,7 @@ fn test_bridge_replace() {
|
||||||
} else {
|
} else {
|
||||||
th = TestHarness::new_buckets(5, 0);
|
th = TestHarness::new_buckets(5, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Randomly select a bridge to replace
|
// Randomly select a bridge to replace
|
||||||
let table_size = th.ba.bridge_table.buckets.len();
|
let table_size = th.ba.bridge_table.buckets.len();
|
||||||
let num = rand::thread_rng().gen_range(0, table_size - 1);
|
let num = rand::thread_rng().gen_range(0, table_size - 1);
|
||||||
|
@ -747,7 +748,22 @@ fn test_bridge_replace() {
|
||||||
.contains_key(replacement_bridge),
|
.contains_key(replacement_bridge),
|
||||||
"Random bridge to replace not in reachable bridges"
|
"Random bridge to replace not in reachable bridges"
|
||||||
);
|
);
|
||||||
|
|
||||||
match case {
|
match case {
|
||||||
|
"not found" => {
|
||||||
|
// Case zero: bridge to be replaced is not in the bridgetable
|
||||||
|
let random_bridgeline = &BridgeLine::random();
|
||||||
|
assert!(
|
||||||
|
!th.ba.bridge_table.reachable.contains_key(random_bridgeline),
|
||||||
|
"Random bridgeline happens to be in the bridge_table (and should not be)"
|
||||||
|
);
|
||||||
|
assert!(
|
||||||
|
th.ba
|
||||||
|
.bridge_replace(random_bridgeline, Some(random_bridgeline))
|
||||||
|
== ReplaceSuccess::NotFound,
|
||||||
|
"Bridge should be marked as NotFound"
|
||||||
|
);
|
||||||
|
}
|
||||||
"available" => {
|
"available" => {
|
||||||
// Case one: available_bridge != null
|
// Case one: available_bridge != null
|
||||||
let random_bridgeline = &BridgeLine::random();
|
let random_bridgeline = &BridgeLine::random();
|
||||||
|
@ -766,7 +782,8 @@ fn test_bridge_replace() {
|
||||||
);
|
);
|
||||||
assert!(
|
assert!(
|
||||||
th.ba
|
th.ba
|
||||||
.bridge_replace(replacement_bridge, Some(random_bridgeline)),
|
.bridge_replace(replacement_bridge, Some(random_bridgeline))
|
||||||
|
== ReplaceSuccess::Replaced,
|
||||||
"Bridge was not replaced with available bridge"
|
"Bridge was not replaced with available bridge"
|
||||||
);
|
);
|
||||||
assert!(
|
assert!(
|
||||||
|
@ -807,7 +824,7 @@ fn test_bridge_replace() {
|
||||||
"Unallocated bridge already marked as reachable"
|
"Unallocated bridge already marked as reachable"
|
||||||
);
|
);
|
||||||
assert!(
|
assert!(
|
||||||
th.ba.bridge_replace(replacement_bridge, None),
|
th.ba.bridge_replace(replacement_bridge, None) == ReplaceSuccess::Replaced,
|
||||||
"Bridge was not replaced with available bridge"
|
"Bridge was not replaced with available bridge"
|
||||||
);
|
);
|
||||||
assert!(
|
assert!(
|
||||||
|
@ -830,13 +847,13 @@ fn test_bridge_replace() {
|
||||||
println!("Successfully added unallocated bridgeline");
|
println!("Successfully added unallocated bridgeline");
|
||||||
}
|
}
|
||||||
"spare" => {
|
"spare" => {
|
||||||
// Case three: available_bridge == null and unallocated_bridges ==null
|
// Case three: available_bridge == null and unallocated_bridges == null
|
||||||
assert!(
|
assert!(
|
||||||
th.ba.bridge_table.unallocated_bridges.len() == 0,
|
th.ba.bridge_table.unallocated_bridges.len() == 0,
|
||||||
"Unallocated bridges should have a length of 0"
|
"Unallocated bridges should have a length of 0"
|
||||||
);
|
);
|
||||||
assert!(
|
assert!(
|
||||||
th.ba.bridge_replace(replacement_bridge, None),
|
th.ba.bridge_replace(replacement_bridge, None) == ReplaceSuccess::Replaced,
|
||||||
"Bridge was not replaced with available spare bridge"
|
"Bridge was not replaced with available spare bridge"
|
||||||
);
|
);
|
||||||
assert!(
|
assert!(
|
||||||
|
@ -865,7 +882,7 @@ fn test_bridge_replace() {
|
||||||
"Unallocated bridges should have a length of 0"
|
"Unallocated bridges should have a length of 0"
|
||||||
);
|
);
|
||||||
assert!(
|
assert!(
|
||||||
!th.ba.bridge_replace(replacement_bridge, None),
|
th.ba.bridge_replace(replacement_bridge, None) == ReplaceSuccess::NotReplaced,
|
||||||
"Bridge was somehow marked as replaced despite no replaceable bridges"
|
"Bridge was somehow marked as replaced despite no replaceable bridges"
|
||||||
);
|
);
|
||||||
assert!(
|
assert!(
|
||||||
|
|
Loading…
Reference in New Issue