Converting bridgetable vectors to HashMaps
This commit is contained in:
parent
73c3ef8728
commit
607ecd89c7
|
@ -213,8 +213,10 @@ impl BridgeLine {
|
||||||
#[serde_as]
|
#[serde_as]
|
||||||
#[derive(Debug, Default, Serialize, Deserialize)]
|
#[derive(Debug, Default, Serialize, Deserialize)]
|
||||||
pub struct BridgeTable {
|
pub struct BridgeTable {
|
||||||
pub keys: Vec<[u8; 16]>,
|
// All structures in the bridgetable are indexed by counter
|
||||||
pub buckets: Vec<[BridgeLine; MAX_BRIDGES_PER_BUCKET]>,
|
pub counter: u32,
|
||||||
|
pub keys: HashMap<u32, [u8; 16]>,
|
||||||
|
pub buckets: HashMap<u32, [BridgeLine; MAX_BRIDGES_PER_BUCKET]>,
|
||||||
#[serde_as(as = "Vec<[_; ENC_BUCKET_BYTES]>")]
|
#[serde_as(as = "Vec<[_; ENC_BUCKET_BYTES]>")]
|
||||||
pub encbuckets: Vec<[u8; ENC_BUCKET_BYTES]>,
|
pub encbuckets: Vec<[u8; ENC_BUCKET_BYTES]>,
|
||||||
/// Individual bridges that are reachable
|
/// Individual bridges that are reachable
|
||||||
|
@ -249,20 +251,21 @@ impl BridgeTable {
|
||||||
self.buckets.len()
|
self.buckets.len()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO Don't need with hashmaps, but remove unused buckets
|
||||||
pub fn recycle_bucket(&mut self, bucket: &[BridgeLine; MAX_BRIDGES_PER_BUCKET], index: u32) {
|
pub fn recycle_bucket(&mut self, bucket: &[BridgeLine; MAX_BRIDGES_PER_BUCKET], index: u32) {
|
||||||
// Pick a random key to encrypt this bucket
|
// Pick a random key to encrypt this bucket
|
||||||
let mut rng = rand::thread_rng();
|
let mut rng = rand::thread_rng();
|
||||||
let mut key: [u8; 16] = [0; 16];
|
let mut key: [u8; 16] = [0; 16];
|
||||||
rng.fill_bytes(&mut key);
|
rng.fill_bytes(&mut key);
|
||||||
self.keys[index as usize] = key;
|
let key = self.keys.get(&index).unwrap();
|
||||||
self.buckets[index as usize] = *bucket;
|
let bucket = *self.buckets.get(&index).unwrap();
|
||||||
for (i, b) in bucket.iter().enumerate() {
|
for (i, bridgeline) in bucket.iter().enumerate() {
|
||||||
if b.port > 0 {
|
if bridgeline.port > 0 {
|
||||||
if let Some(v) = self.reachable.get_mut(b) {
|
if let Some(v) = self.reachable.get_mut(bridgeline) {
|
||||||
v.push((index, i));
|
v.push((index, i));
|
||||||
} else {
|
} else {
|
||||||
let v = vec![(index, i)];
|
let v = vec![(index, i)];
|
||||||
self.reachable.insert(*b, v);
|
self.reachable.insert(*bridgeline, v);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -274,21 +277,23 @@ impl BridgeTable {
|
||||||
let mut rng = rand::thread_rng();
|
let mut rng = rand::thread_rng();
|
||||||
let mut key: [u8; 16] = [0; 16];
|
let mut key: [u8; 16] = [0; 16];
|
||||||
rng.fill_bytes(&mut key);
|
rng.fill_bytes(&mut key);
|
||||||
self.keys.push(key);
|
// Increase the counter to identify the bucket, wrap value if beyond u32::MAX
|
||||||
self.buckets.push(*bucket);
|
self.counter = self.counter.wrapping_add(1);
|
||||||
let bucketnum: u32 = (self.buckets.len() - 1).try_into().unwrap();
|
self.keys.insert(self.counter, key);
|
||||||
|
self.buckets.insert(self.counter, *bucket);
|
||||||
|
// TODO: maybe we don't need this if the hashtable can keep track of available bridges
|
||||||
// Mark the new bridges as available
|
// Mark the new bridges as available
|
||||||
for (i, b) in bucket.iter().enumerate() {
|
for (i, b) in bucket.iter().enumerate() {
|
||||||
if b.port > 0 {
|
if b.port > 0 {
|
||||||
if let Some(v) = self.reachable.get_mut(b) {
|
if let Some(v) = self.reachable.get_mut(b) {
|
||||||
v.push((bucketnum, i));
|
v.push((self.counter, i));
|
||||||
} else {
|
} else {
|
||||||
let v = vec![(bucketnum, i)];
|
let v = vec![(self.counter, i)];
|
||||||
self.reachable.insert(*b, v);
|
self.reachable.insert(*b, v);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
bucketnum
|
self.counter
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Create the vector of encrypted buckets from the keys and buckets
|
/// Create the vector of encrypted buckets from the keys and buckets
|
||||||
|
@ -303,13 +308,14 @@ impl BridgeTable {
|
||||||
self.encbuckets.clear();
|
self.encbuckets.clear();
|
||||||
// We want id to be a u32, so we use .zip(0u32..) instead of
|
// We want id to be a u32, so we use .zip(0u32..) instead of
|
||||||
// enumerate()
|
// enumerate()
|
||||||
for ((key, bucket), id) in self.keys.iter().zip(self.buckets.iter()).zip(0u32..) {
|
for (uid, key) in self.keys.iter(){
|
||||||
|
let bucket = self.buckets.get(uid).unwrap();
|
||||||
let mut encbucket: [u8; ENC_BUCKET_BYTES] = [0; ENC_BUCKET_BYTES];
|
let mut encbucket: [u8; ENC_BUCKET_BYTES] = [0; ENC_BUCKET_BYTES];
|
||||||
let plainbucket: [u8; BUCKET_BYTES] = BridgeLine::bucket_encode(
|
let plainbucket: [u8; BUCKET_BYTES] = BridgeLine::bucket_encode(
|
||||||
bucket,
|
bucket,
|
||||||
&self.reachable,
|
&self.reachable,
|
||||||
today,
|
today,
|
||||||
&to_scalar(id, key),
|
&to_scalar(*uid, key),
|
||||||
reachability_priv,
|
reachability_priv,
|
||||||
);
|
);
|
||||||
// Set the AES key
|
// Set the AES key
|
||||||
|
@ -390,15 +396,15 @@ mod tests {
|
||||||
// Create the encrypted bridge table
|
// Create the encrypted bridge table
|
||||||
btable.encrypt_table(today, &reachability_priv);
|
btable.encrypt_table(today, &reachability_priv);
|
||||||
// Try to decrypt a 1-bridge bucket
|
// Try to decrypt a 1-bridge bucket
|
||||||
let key7 = btable.keys[7];
|
let key7 = btable.keys[&7u32];
|
||||||
let bucket7 = btable.decrypt_bucket_id(7, &key7)?;
|
let bucket7 = btable.decrypt_bucket_id(7, &key7)?;
|
||||||
println!("bucket 7 = {:?}", bucket7);
|
println!("bucket 7 = {:?}", bucket7);
|
||||||
// Try to decrypt a 3-bridge bucket
|
// Try to decrypt a 3-bridge bucket
|
||||||
let key24 = btable.keys[24];
|
let key24 = btable.keys[&24u32];
|
||||||
let bucket24 = btable.decrypt_bucket_id(24, &key24)?;
|
let bucket24 = btable.decrypt_bucket_id(24, &key24)?;
|
||||||
println!("bucket 24 = {:?}", bucket24);
|
println!("bucket 24 = {:?}", bucket24);
|
||||||
// Try to decrypt a bucket with the wrong key
|
// Try to decrypt a bucket with the wrong key
|
||||||
let key12 = btable.keys[12];
|
let key12 = btable.keys[&12u32];
|
||||||
let res = btable.decrypt_bucket_id(15, &key12).unwrap_err();
|
let res = btable.decrypt_bucket_id(15, &key12).unwrap_err();
|
||||||
println!("bucket key mismatch = {:?}", res);
|
println!("bucket key mismatch = {:?}", res);
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|
|
@ -380,14 +380,22 @@ impl BridgeAuth {
|
||||||
if let Some(v) = positions {
|
if let Some(v) = positions {
|
||||||
for (bucketnum, offset) in v.iter() {
|
for (bucketnum, offset) in v.iter() {
|
||||||
println!("Bucket num: {:?} and offset: {:?}", bucketnum, offset);
|
println!("Bucket num: {:?} and offset: {:?}", bucketnum, offset);
|
||||||
|
let bridgelines = match self.bridge_table.buckets.get(bucketnum) {
|
||||||
|
Some(bridgelines) => *bridgelines,
|
||||||
|
None => return res
|
||||||
|
};
|
||||||
assert!(
|
assert!(
|
||||||
self.bridge_table.buckets[*bucketnum as usize][*offset]
|
bridgelines[*offset]
|
||||||
== reachable_bridge.0
|
== reachable_bridge.0
|
||||||
);
|
);
|
||||||
self.bridge_table.buckets[*bucketnum as usize][*offset] = *bridge;
|
bridgelines[*offset] = *bridge;
|
||||||
assert!(self.bridge_table.buckets[*bucketnum as usize][*offset] == *bridge);
|
self.bridge_table.buckets.insert(*bucketnum, bridgelines);
|
||||||
|
let bridgelines = match self.bridge_table.buckets.get(bucketnum) {
|
||||||
|
Some(bridgelines) => *bridgelines,
|
||||||
|
None => return res
|
||||||
|
};
|
||||||
assert!(
|
assert!(
|
||||||
self.bridge_table.buckets[*bucketnum as usize][*offset]
|
bridgelines[*offset]
|
||||||
!= reachable_bridge.0
|
!= reachable_bridge.0
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -418,23 +426,33 @@ impl BridgeAuth {
|
||||||
let reachable_bridges = &self.bridge_table.reachable.clone();
|
let reachable_bridges = &self.bridge_table.reachable.clone();
|
||||||
match reachable_bridges.get(bridge) {
|
match reachable_bridges.get(bridge) {
|
||||||
Some(positions) => {
|
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);
|
let bridgelines = match self.bridge_table.buckets.get(bucketnum) {
|
||||||
self.bridge_table.buckets[*bucketnum as usize][*offset] = *replacement;
|
Some(bridgelines) => *bridgelines,
|
||||||
|
None => return ReplaceSuccess::NotFound,
|
||||||
|
};
|
||||||
|
assert!(bridgelines[*offset] == *bridge);
|
||||||
|
bridgelines[*offset] = *replacement;
|
||||||
|
self.bridge_table.buckets.insert(*bucketnum, bridgelines);
|
||||||
// Remove the bridge from the reachable bridges and add new bridge
|
// Remove the bridge from the reachable bridges and add new bridge
|
||||||
self.bridge_table
|
self.bridge_table
|
||||||
.reachable
|
.reachable
|
||||||
.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 = ReplaceSuccess::Replaced
|
|
||||||
}
|
}
|
||||||
|
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();
|
||||||
for (bucketnum, offset) in positions.iter() {
|
for (bucketnum, offset) in positions.iter() {
|
||||||
self.bridge_table.buckets[*bucketnum as usize][*offset] = *replacement;
|
let bridgelines = match self.bridge_table.buckets.get(bucketnum) {
|
||||||
|
Some(bridgelines) => *bridgelines,
|
||||||
|
None => return ReplaceSuccess::NotFound,
|
||||||
|
};
|
||||||
|
assert!(bridgelines[*offset] == *bridge);
|
||||||
|
bridgelines[*offset] = *replacement;
|
||||||
|
self.bridge_table.buckets.insert(*bucketnum, bridgelines);
|
||||||
self.bridge_table
|
self.bridge_table
|
||||||
.reachable
|
.reachable
|
||||||
.insert(*replacement, positions.clone());
|
.insert(*replacement, positions.clone());
|
||||||
|
@ -446,10 +464,8 @@ impl BridgeAuth {
|
||||||
// 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();
|
||||||
self.bridge_table.spares.remove(&spare);
|
self.bridge_table.spares.remove(&spare);
|
||||||
// Indicate the removed bucket as a recyclable bucket
|
|
||||||
self.bridge_table.recyclable.insert(spare);
|
|
||||||
// Get the actual bridges from the spare bucket
|
// Get the actual bridges from the spare bucket
|
||||||
let spare_bucket = self.bridge_table.buckets[spare as usize];
|
let spare_bucket = self.bridge_table.buckets[&spare];
|
||||||
let mut replacement: &BridgeLine = &BridgeLine::default();
|
let mut replacement: &BridgeLine = &BridgeLine::default();
|
||||||
// Make the first spare the replacement bridge, add the others to the set of
|
// Make the first spare the replacement bridge, add the others to the set of
|
||||||
// unallocated_bridges
|
// unallocated_bridges
|
||||||
|
|
|
@ -196,9 +196,10 @@ impl BridgeAuth {
|
||||||
|
|
||||||
// Create the bucket attribute (Scalar), which is a combination
|
// Create the bucket attribute (Scalar), which is a combination
|
||||||
// of the bucket id (u32) and the bucket's decryption key ([u8; 16])
|
// of the bucket id (u32) and the bucket's decryption key ([u8; 16])
|
||||||
let bucket_key = self.bridge_table.keys[bucket_id];
|
let bucket_key = self.bridge_table.keys.get(&bucket_id_u32).unwrap();
|
||||||
let bucket: Scalar = bridge_table::to_scalar(bucket_id_u32, &bucket_key);
|
let bucket: Scalar = bridge_table::to_scalar(bucket_id_u32, &bucket_key);
|
||||||
let bridge_line = self.bridge_table.buckets[bucket_id][0];
|
let bridge_lines = self.bridge_table.buckets.get(&bucket_id_u32).unwrap();
|
||||||
|
let bridge_line = bridge_lines[0];
|
||||||
|
|
||||||
// Create the level_since attribute (Scalar), which is today's
|
// Create the level_since attribute (Scalar), which is today's
|
||||||
// Julian date
|
// Julian date
|
||||||
|
|
Loading…
Reference in New Issue