diff --git a/crates/lox-library/src/bridge_table.rs b/crates/lox-library/src/bridge_table.rs index ec2e0f6..1750d7b 100644 --- a/crates/lox-library/src/bridge_table.rs +++ b/crates/lox-library/src/bridge_table.rs @@ -249,6 +249,25 @@ impl BridgeTable { self.buckets.len() } + pub fn recycle_bucket(&mut self, bucket: &[BridgeLine; MAX_BRIDGES_PER_BUCKET], index: u32) { + // Pick a random key to encrypt this bucket + let mut rng = rand::thread_rng(); + let mut key: [u8; 16] = [0; 16]; + rng.fill_bytes(&mut key); + self.keys[index as usize] = key; + self.buckets[index as usize] = *bucket; + for (i, b) in bucket.iter().enumerate() { + if b.port > 0 { + if let Some(v) = self.reachable.get_mut(b) { + v.push((index, i)); + } else { + let v = vec![(index, i)]; + self.reachable.insert(*b, v); + } + } + } + } + /// Append a new bucket to the bridge table, returning its index pub fn new_bucket(&mut self, bucket: &[BridgeLine; MAX_BRIDGES_PER_BUCKET]) -> u32 { // Pick a random key to encrypt this bucket diff --git a/crates/lox-library/src/lib.rs b/crates/lox-library/src/lib.rs index 81e9d6b..5fc9eb7 100644 --- a/crates/lox-library/src/lib.rs +++ b/crates/lox-library/src/lib.rs @@ -293,7 +293,14 @@ impl BridgeAuth { bridges: [BridgeLine; MAX_BRIDGES_PER_BUCKET], bdb: &mut BridgeDb, ) { - let bnum = self.bridge_table.new_bucket(&bridges); + let bnum: u32; + if self.bridge_table.recyclable.is_empty() { + bnum = self.bridge_table.new_bucket(&bridges); + } else { + bnum = *self.bridge_table.recyclable.iter().next().unwrap(); + self.bridge_table.recyclable.remove(&bnum); + self.bridge_table.recycle_bucket(&bridges, bnum) + } let mut single = [BridgeLine::default(); MAX_BRIDGES_PER_BUCKET]; for b in bridges.iter() { single[0] = *b; @@ -305,7 +312,14 @@ impl BridgeAuth { /// Insert a hot spare bucket of bridges pub fn add_spare_bucket(&mut self, bucket: [BridgeLine; MAX_BRIDGES_PER_BUCKET]) { - let bnum = self.bridge_table.new_bucket(&bucket); + let bnum: u32; + if self.bridge_table.recyclable.is_empty() { + bnum = self.bridge_table.new_bucket(&bucket); + } else { + bnum = *self.bridge_table.recyclable.iter().next().unwrap(); + self.bridge_table.recyclable.remove(&bnum); + self.bridge_table.recycle_bucket(&bucket, bnum) + } self.bridge_table.spares.insert(bnum); } @@ -320,6 +334,19 @@ impl BridgeAuth { // This will be the bad/annoying part } + pub fn allocate_bridges(&mut self, distributor_bridges: &mut Vec, bdb: &mut BridgeDb) { + while let Some(bridge) = distributor_bridges.iter().next_back() { + self.bridge_table.unallocated_bridges.push(*bridge) + } + while self.bridge_table.unallocated_bridges.len() >= MAX_BRIDGES_PER_BUCKET { + let mut bucket = [BridgeLine::default(); MAX_BRIDGES_PER_BUCKET]; + for i in 0..MAX_BRIDGES_PER_BUCKET { + bucket[i] = self.bridge_table.unallocated_bridges.pop().unwrap(); + } + self.add_openinv_bridges(bucket, bdb); + } + } + // Update the details of a bridge in the bridge table. This assumes that the IP and Port // of a given bridge remains the same and thus can be updated. // First we must retrieve the list of reachable bridges, then we must search for any matching our partial key diff --git a/crates/lox-library/src/tests.rs b/crates/lox-library/src/tests.rs index 885980c..b9c5d9e 100644 --- a/crates/lox-library/src/tests.rs +++ b/crates/lox-library/src/tests.rs @@ -682,6 +682,27 @@ fn test_update_bridge() { println!("After update openinv = {:?}\n", th.bdb.openinv_buckets); } +#[test] +fn test_bridge_replace() { + // TODO + let mut th = TestHarness::new(); + // Add new bridge to table with known values, + // check that I can find and update the values and that everything else stays the same + + // Create 3 bridges to test harness + let bucket = [ + BridgeLine::random(), + BridgeLine::random(), + BridgeLine::random(), + ]; + +} + +#[test] +fn test_allocate_bridges() { + // TODO +} + #[test] fn test_mark_unreachable() { let mut th = TestHarness::new();