Cleanup
This commit is contained in:
@@ -10,7 +10,7 @@ fn bench_sequential_counters(c: &mut Criterion) {
|
||||
group.sample_size(1000);
|
||||
|
||||
for size in [100, 1000, 10000] {
|
||||
group.throughput(Throughput::Elements(size as u64));
|
||||
group.throughput(Throughput::Elements(size));
|
||||
|
||||
group.bench_with_input(
|
||||
BenchmarkId::new("sequential_counters", size),
|
||||
@@ -69,7 +69,7 @@ fn bench_thread_safety(c: &mut Criterion) {
|
||||
group.sample_size(1000);
|
||||
|
||||
for size in [100, 1000, 10000] {
|
||||
group.throughput(Throughput::Elements(size as u64));
|
||||
group.throughput(Throughput::Elements(size));
|
||||
|
||||
group.bench_with_input(
|
||||
BenchmarkId::new("thread_safe_validator", size),
|
||||
@@ -103,7 +103,7 @@ fn bench_window_sliding(c: &mut Criterion) {
|
||||
group.sample_size(100);
|
||||
|
||||
for window_size in [128, 512, 1024] {
|
||||
group.throughput(Throughput::Elements(window_size as u64));
|
||||
group.throughput(Throughput::Elements(window_size));
|
||||
|
||||
group.bench_with_input(
|
||||
BenchmarkId::new("window_sliding", window_size),
|
||||
@@ -138,7 +138,7 @@ fn bench_core_operations(c: &mut Criterion) {
|
||||
group.sample_size(1000);
|
||||
|
||||
// Create validators with different states
|
||||
let mut empty_validator = ReceivingKeyCounterValidator::default();
|
||||
let empty_validator = ReceivingKeyCounterValidator::default();
|
||||
let mut half_full_validator = ReceivingKeyCounterValidator::default();
|
||||
let mut full_validator = ReceivingKeyCounterValidator::default();
|
||||
|
||||
@@ -156,7 +156,8 @@ fn bench_core_operations(c: &mut Criterion) {
|
||||
b.iter(|| {
|
||||
let mut validator = empty_validator.clone();
|
||||
// Force window sliding that will clear bitmap
|
||||
black_box(validator.mark_did_receive_branchless(2000).unwrap());
|
||||
let _: () = validator.mark_did_receive_branchless(2000).unwrap();
|
||||
black_box(());
|
||||
})
|
||||
});
|
||||
|
||||
@@ -164,7 +165,8 @@ fn bench_core_operations(c: &mut Criterion) {
|
||||
b.iter(|| {
|
||||
let mut validator = half_full_validator.clone();
|
||||
// Force window sliding that will clear bitmap
|
||||
black_box(validator.mark_did_receive_branchless(2000).unwrap());
|
||||
let _: () = validator.mark_did_receive_branchless(2000).unwrap();
|
||||
black_box(());
|
||||
})
|
||||
});
|
||||
|
||||
@@ -172,7 +174,8 @@ fn bench_core_operations(c: &mut Criterion) {
|
||||
b.iter(|| {
|
||||
let mut validator = full_validator.clone();
|
||||
// Force window sliding that will clear bitmap
|
||||
black_box(validator.mark_did_receive_branchless(2000).unwrap());
|
||||
let _: () = validator.mark_did_receive_branchless(2000).unwrap();
|
||||
black_box(());
|
||||
})
|
||||
});
|
||||
|
||||
|
||||
@@ -110,22 +110,6 @@ mod tests {
|
||||
use crate::LpError;
|
||||
use bytes::BytesMut;
|
||||
|
||||
// Helper function to create a test packet's BytesMut representation directly
|
||||
fn create_test_packet_bytes(counter: u64, message: LpMessage, trailer_fill: u8) -> BytesMut {
|
||||
let packet = LpPacket {
|
||||
header: LpHeader {
|
||||
protocol_version: 1,
|
||||
session_id: 42,
|
||||
counter,
|
||||
},
|
||||
message,
|
||||
trailer: [trailer_fill; TRAILER_LEN],
|
||||
};
|
||||
let mut buf = BytesMut::new();
|
||||
serialize_lp_packet(&packet, &mut buf).unwrap();
|
||||
buf
|
||||
}
|
||||
|
||||
// === Updated Encode/Decode Tests ===
|
||||
|
||||
#[test]
|
||||
|
||||
+40
-40
@@ -37,13 +37,13 @@ pub fn sessions_for_tests() -> (LpSession, LpSession) {
|
||||
|
||||
let keypair_1 = Keypair::default();
|
||||
let keypair_2 = Keypair::default();
|
||||
let id = make_lp_id(&keypair_1.public_key(), &keypair_2.public_key());
|
||||
let id = make_lp_id(keypair_1.public_key(), keypair_2.public_key());
|
||||
|
||||
// Use consistent salt for deterministic tests
|
||||
let salt = [1u8; 32];
|
||||
|
||||
// Initiator derives PSK from their perspective
|
||||
let initiator_psk = derive_psk(keypair_1.private_key(), &keypair_2.public_key(), &salt);
|
||||
let initiator_psk = derive_psk(keypair_1.private_key(), keypair_2.public_key(), &salt);
|
||||
|
||||
let initiator_session = LpSession::new(
|
||||
id,
|
||||
@@ -55,7 +55,7 @@ pub fn sessions_for_tests() -> (LpSession, LpSession) {
|
||||
.expect("Test session creation failed");
|
||||
|
||||
// Responder derives same PSK from their perspective
|
||||
let responder_psk = derive_psk(keypair_2.private_key(), &keypair_1.public_key(), &salt);
|
||||
let responder_psk = derive_psk(keypair_2.private_key(), keypair_1.public_key(), &salt);
|
||||
|
||||
let responder_session = LpSession::new(
|
||||
id,
|
||||
@@ -69,6 +69,40 @@ pub fn sessions_for_tests() -> (LpSession, LpSession) {
|
||||
(initiator_session, responder_session)
|
||||
}
|
||||
|
||||
/// Generates a deterministic u32 session ID for the Lewes Protocol
|
||||
/// based on two public keys. The order of the keys does not matter.
|
||||
///
|
||||
/// Uses a different internal delimiter than `make_conv_id` to avoid
|
||||
/// potential collisions if the same key pairs were used in both contexts.
|
||||
fn make_id(key1_bytes: &[u8], key2_bytes: &[u8], sep: u8) -> u32 {
|
||||
let mut hasher = DefaultHasher::new();
|
||||
|
||||
// Ensure consistent order for hashing to make the ID order-independent.
|
||||
// This guarantees make_lp_id(a, b) == make_lp_id(b, a).
|
||||
if key1_bytes < key2_bytes {
|
||||
hasher.write(key1_bytes);
|
||||
// Use a delimiter specific to Lewes Protocol ID generation
|
||||
// (0xCC chosen arbitrarily, could be any value different from 0xFF)
|
||||
hasher.write_u8(sep);
|
||||
hasher.write(key2_bytes);
|
||||
} else {
|
||||
hasher.write(key2_bytes);
|
||||
hasher.write_u8(sep);
|
||||
hasher.write(key1_bytes);
|
||||
}
|
||||
|
||||
// Truncate the u64 hash result to u32
|
||||
(hasher.finish() & 0xFFFF_FFFF) as u32
|
||||
}
|
||||
|
||||
pub fn make_lp_id(key1_bytes: &PublicKey, key2_bytes: &PublicKey) -> u32 {
|
||||
make_id(key1_bytes.as_bytes(), key2_bytes.as_bytes(), 0xCC)
|
||||
}
|
||||
|
||||
pub fn make_conv_id(src: &[u8], dst: &[u8]) -> u32 {
|
||||
make_id(src, dst, 0xFF)
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use crate::keypair::Keypair;
|
||||
@@ -184,12 +218,12 @@ mod tests {
|
||||
let remote_manager = SessionManager::new();
|
||||
let local_keypair = Keypair::default();
|
||||
let remote_keypair = Keypair::default();
|
||||
let lp_id = make_lp_id(&local_keypair.public_key(), &remote_keypair.public_key());
|
||||
let lp_id = make_lp_id(local_keypair.public_key(), remote_keypair.public_key());
|
||||
// Create a session via manager
|
||||
let _ = local_manager
|
||||
.create_session_state_machine(
|
||||
&local_keypair,
|
||||
&remote_keypair.public_key(),
|
||||
remote_keypair.public_key(),
|
||||
true,
|
||||
&[2u8; 32],
|
||||
)
|
||||
@@ -198,7 +232,7 @@ mod tests {
|
||||
let _ = remote_manager
|
||||
.create_session_state_machine(
|
||||
&remote_keypair,
|
||||
&local_keypair.public_key(),
|
||||
local_keypair.public_key(),
|
||||
false,
|
||||
&[2u8; 32],
|
||||
)
|
||||
@@ -293,37 +327,3 @@ mod tests {
|
||||
// Do not mark received
|
||||
}
|
||||
}
|
||||
|
||||
/// Generates a deterministic u32 session ID for the Lewes Protocol
|
||||
/// based on two public keys. The order of the keys does not matter.
|
||||
///
|
||||
/// Uses a different internal delimiter than `make_conv_id` to avoid
|
||||
/// potential collisions if the same key pairs were used in both contexts.
|
||||
fn make_id(key1_bytes: &[u8], key2_bytes: &[u8], sep: u8) -> u32 {
|
||||
let mut hasher = DefaultHasher::new();
|
||||
|
||||
// Ensure consistent order for hashing to make the ID order-independent.
|
||||
// This guarantees make_lp_id(a, b) == make_lp_id(b, a).
|
||||
if key1_bytes < key2_bytes {
|
||||
hasher.write(key1_bytes);
|
||||
// Use a delimiter specific to Lewes Protocol ID generation
|
||||
// (0xCC chosen arbitrarily, could be any value different from 0xFF)
|
||||
hasher.write_u8(sep);
|
||||
hasher.write(key2_bytes);
|
||||
} else {
|
||||
hasher.write(key2_bytes);
|
||||
hasher.write_u8(sep);
|
||||
hasher.write(key1_bytes);
|
||||
}
|
||||
|
||||
// Truncate the u64 hash result to u32
|
||||
(hasher.finish() & 0xFFFF_FFFF) as u32
|
||||
}
|
||||
|
||||
pub fn make_lp_id(key1_bytes: &PublicKey, key2_bytes: &PublicKey) -> u32 {
|
||||
make_id(key1_bytes.as_bytes(), key2_bytes.as_bytes(), 0xCC)
|
||||
}
|
||||
|
||||
pub fn make_conv_id(src: &[u8], dst: &[u8]) -> u32 {
|
||||
make_id(src, dst, 0xFF)
|
||||
}
|
||||
|
||||
@@ -71,12 +71,12 @@ mod tests {
|
||||
// Derive PSK twice with same inputs
|
||||
let psk1 = derive_psk(
|
||||
keypair_1.private_key(),
|
||||
&keypair_2.public_key(),
|
||||
keypair_2.public_key(),
|
||||
&salt,
|
||||
);
|
||||
let psk2 = derive_psk(
|
||||
keypair_1.private_key(),
|
||||
&keypair_2.public_key(),
|
||||
keypair_2.public_key(),
|
||||
&salt,
|
||||
);
|
||||
|
||||
@@ -92,14 +92,14 @@ mod tests {
|
||||
// Client derives PSK
|
||||
let client_psk = derive_psk(
|
||||
keypair_1.private_key(),
|
||||
&keypair_2.public_key(),
|
||||
keypair_2.public_key(),
|
||||
&salt,
|
||||
);
|
||||
|
||||
// Gateway derives PSK from their perspective
|
||||
let gateway_psk = derive_psk(
|
||||
keypair_2.private_key(),
|
||||
&keypair_1.public_key(),
|
||||
keypair_1.public_key(),
|
||||
&salt,
|
||||
);
|
||||
|
||||
@@ -117,8 +117,8 @@ mod tests {
|
||||
let salt1 = [1u8; 32];
|
||||
let salt2 = [2u8; 32];
|
||||
|
||||
let psk1 = derive_psk(keypair_1.private_key(), &keypair_2.public_key(), &salt1);
|
||||
let psk2 = derive_psk(keypair_1.private_key(), &keypair_2.public_key(), &salt2);
|
||||
let psk1 = derive_psk(keypair_1.private_key(), keypair_2.public_key(), &salt1);
|
||||
let psk2 = derive_psk(keypair_1.private_key(), keypair_2.public_key(), &salt2);
|
||||
|
||||
assert_ne!(psk1, psk2, "Different salts should produce different PSKs");
|
||||
}
|
||||
@@ -130,8 +130,8 @@ mod tests {
|
||||
let keypair_3 = Keypair::default();
|
||||
let salt = [3u8; 32];
|
||||
|
||||
let psk1 = derive_psk(keypair_1.private_key(), &keypair_2.public_key(), &salt);
|
||||
let psk2 = derive_psk(keypair_1.private_key(), &keypair_3.public_key(), &salt);
|
||||
let psk1 = derive_psk(keypair_1.private_key(), keypair_2.public_key(), &salt);
|
||||
let psk2 = derive_psk(keypair_1.private_key(), keypair_3.public_key(), &salt);
|
||||
|
||||
assert_ne!(
|
||||
psk1, psk2,
|
||||
@@ -145,7 +145,7 @@ mod tests {
|
||||
let keypair_2 = Keypair::default();
|
||||
let salt = [4u8; 32];
|
||||
|
||||
let psk = derive_psk(keypair_1.private_key(), &keypair_2.public_key(), &salt);
|
||||
let psk = derive_psk(keypair_1.private_key(), keypair_2.public_key(), &salt);
|
||||
|
||||
assert_eq!(psk.len(), 32, "PSK should be exactly 32 bytes");
|
||||
}
|
||||
|
||||
@@ -728,7 +728,7 @@ mod tests {
|
||||
|
||||
// Check final state of the validator
|
||||
let final_state = validator.lock().unwrap();
|
||||
let (next, receive_cnt) = final_state.current_packet_cnt();
|
||||
let (_next, receive_cnt) = final_state.current_packet_cnt();
|
||||
|
||||
// Verify that the received count matches our successful operations
|
||||
assert_eq!(receive_cnt, total_successes as u64);
|
||||
@@ -786,7 +786,7 @@ mod tests {
|
||||
}
|
||||
|
||||
// Create a copy for comparison
|
||||
let original_bitmap = validator.bitmap;
|
||||
let _original_bitmap = validator.bitmap;
|
||||
|
||||
// Simulate SIMD clear (4 words at a time)
|
||||
#[cfg(target_feature = "avx2")]
|
||||
|
||||
@@ -450,13 +450,12 @@ mod tests {
|
||||
let responder_session =
|
||||
create_handshake_test_session(false, &responder_keys, &initiator_keys.public, &psk);
|
||||
|
||||
let mut initiator_to_responder_msg = None;
|
||||
let mut responder_to_initiator_msg = None;
|
||||
let mut rounds = 0;
|
||||
const MAX_ROUNDS: usize = 10; // Safety break for the loop
|
||||
|
||||
// Start by priming the initiator message
|
||||
initiator_to_responder_msg = initiator_session.prepare_handshake_message().unwrap().ok();
|
||||
let mut initiator_to_responder_msg = initiator_session.prepare_handshake_message().unwrap().ok();
|
||||
assert!(
|
||||
initiator_to_responder_msg.is_some(),
|
||||
"Initiator did not produce initial message"
|
||||
|
||||
@@ -50,16 +50,16 @@ mod tests {
|
||||
// 2. Generate keys and PSK
|
||||
let peer_a_keys = Keypair::default();
|
||||
let peer_b_keys = Keypair::default();
|
||||
let lp_id = make_lp_id(&peer_a_keys.public_key(), &peer_b_keys.public_key());
|
||||
let lp_id = make_lp_id(peer_a_keys.public_key(), peer_b_keys.public_key());
|
||||
let psk = [1u8; 32]; // Define a pre-shared key for the test
|
||||
|
||||
// 4. Create sessions using the pre-built Noise states
|
||||
let peer_a_sm = session_manager_1
|
||||
.create_session_state_machine(&peer_a_keys, &peer_b_keys.public_key(), true, &psk)
|
||||
.create_session_state_machine(&peer_a_keys, peer_b_keys.public_key(), true, &psk)
|
||||
.expect("Failed to create session A");
|
||||
|
||||
let peer_b_sm = session_manager_2
|
||||
.create_session_state_machine(&peer_b_keys, &peer_a_keys.public_key(), false, &psk)
|
||||
.create_session_state_machine(&peer_b_keys, peer_a_keys.public_key(), false, &psk)
|
||||
.expect("Failed to create session B");
|
||||
|
||||
// Verify session count
|
||||
@@ -452,14 +452,14 @@ mod tests {
|
||||
// 2. Setup sessions and complete handshake (similar to test_full_session_flow)
|
||||
let peer_a_keys = Keypair::default();
|
||||
let peer_b_keys = Keypair::default();
|
||||
let lp_id = make_lp_id(&peer_a_keys.public_key(), &peer_b_keys.public_key());
|
||||
let lp_id = make_lp_id(peer_a_keys.public_key(), peer_b_keys.public_key());
|
||||
let psk = [2u8; 32];
|
||||
|
||||
let peer_a_sm = session_manager_1
|
||||
.create_session_state_machine(&peer_a_keys, &peer_b_keys.public_key(), true, &psk)
|
||||
.create_session_state_machine(&peer_a_keys, peer_b_keys.public_key(), true, &psk)
|
||||
.unwrap();
|
||||
let peer_b_sm = session_manager_2
|
||||
.create_session_state_machine(&peer_b_keys, &peer_a_keys.public_key(), false, &psk)
|
||||
.create_session_state_machine(&peer_b_keys, peer_a_keys.public_key(), false, &psk)
|
||||
.unwrap();
|
||||
|
||||
// Drive handshake to completion (simplified)
|
||||
@@ -618,11 +618,11 @@ mod tests {
|
||||
let keys = Keypair::default();
|
||||
let psk = [3u8; 32];
|
||||
|
||||
let lp_id = make_lp_id(&keys.public_key(), &keys.public_key());
|
||||
let lp_id = make_lp_id(keys.public_key(), keys.public_key());
|
||||
|
||||
// 2. Create a session (using real noise state)
|
||||
let _session = session_manager
|
||||
.create_session_state_machine(&keys, &keys.public_key(), true, &psk)
|
||||
.create_session_state_machine(&keys, keys.public_key(), true, &psk)
|
||||
.expect("Failed to create session");
|
||||
|
||||
// 3. Try to get a non-existent session
|
||||
@@ -638,7 +638,7 @@ mod tests {
|
||||
|
||||
// 5. Create and immediately remove a session
|
||||
let _temp_session = session_manager
|
||||
.create_session_state_machine(&keys, &keys.public_key(), true, &psk)
|
||||
.create_session_state_machine(&keys, keys.public_key(), true, &psk)
|
||||
.expect("Failed to create temp session");
|
||||
|
||||
assert!(
|
||||
@@ -717,15 +717,15 @@ mod tests {
|
||||
// 2. Generate keys and PSK
|
||||
let peer_a_keys = Keypair::default();
|
||||
let peer_b_keys = Keypair::default();
|
||||
let lp_id = make_lp_id(&peer_a_keys.public_key(), &peer_b_keys.public_key());
|
||||
let lp_id = make_lp_id(peer_a_keys.public_key(), peer_b_keys.public_key());
|
||||
let psk = [1u8; 32];
|
||||
|
||||
// 3. Create sessions state machines
|
||||
assert!(session_manager_1
|
||||
.create_session_state_machine(&peer_a_keys, &peer_b_keys.public_key(), true, &psk) // Initiator
|
||||
.create_session_state_machine(&peer_a_keys, peer_b_keys.public_key(), true, &psk) // Initiator
|
||||
.is_ok());
|
||||
assert!(session_manager_2
|
||||
.create_session_state_machine(&peer_b_keys, &peer_a_keys.public_key(), false, &psk) // Responder
|
||||
.create_session_state_machine(&peer_b_keys, peer_a_keys.public_key(), false, &psk) // Responder
|
||||
.is_ok());
|
||||
|
||||
assert_eq!(session_manager_1.session_count(), 1);
|
||||
|
||||
@@ -462,7 +462,7 @@ mod tests {
|
||||
let psk = vec![0u8; 32];
|
||||
let remote_pub_key = resp_key.public_key();
|
||||
|
||||
let initiator_sm = LpStateMachine::new(true, &init_key, &remote_pub_key, &psk);
|
||||
let initiator_sm = LpStateMachine::new(true, &init_key, remote_pub_key, &psk);
|
||||
assert!(initiator_sm.is_ok());
|
||||
let initiator_sm = initiator_sm.unwrap();
|
||||
assert!(matches!(
|
||||
@@ -472,7 +472,7 @@ mod tests {
|
||||
let init_session = initiator_sm.session().unwrap();
|
||||
assert!(init_session.is_initiator());
|
||||
|
||||
let responder_sm = LpStateMachine::new(false, &resp_key, &init_key.public_key(), &psk);
|
||||
let responder_sm = LpStateMachine::new(false, &resp_key, init_key.public_key(), &psk);
|
||||
assert!(responder_sm.is_ok());
|
||||
let responder_sm = responder_sm.unwrap();
|
||||
assert!(matches!(
|
||||
@@ -483,7 +483,7 @@ mod tests {
|
||||
assert!(!resp_session.is_initiator());
|
||||
|
||||
// Check lp_id is the same
|
||||
let expected_lp_id = make_lp_id(&init_key.public_key(), remote_pub_key);
|
||||
let expected_lp_id = make_lp_id(init_key.public_key(), remote_pub_key);
|
||||
assert_eq!(init_session.id(), expected_lp_id);
|
||||
assert_eq!(resp_session.id(), expected_lp_id);
|
||||
}
|
||||
@@ -499,7 +499,7 @@ mod tests {
|
||||
let mut initiator = LpStateMachine::new(
|
||||
true, // is_initiator
|
||||
&init_key,
|
||||
&resp_key.public_key(),
|
||||
resp_key.public_key(),
|
||||
&psk.clone(),
|
||||
)
|
||||
.unwrap();
|
||||
@@ -507,7 +507,7 @@ mod tests {
|
||||
let mut responder = LpStateMachine::new(
|
||||
false, // is_initiator
|
||||
&resp_key,
|
||||
&init_key.public_key(),
|
||||
init_key.public_key(),
|
||||
&psk,
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
@@ -79,9 +79,10 @@ impl LpRegistrationRequest {
|
||||
ticket_type,
|
||||
mode: RegistrationMode::Dvpn,
|
||||
client_ip,
|
||||
#[allow(clippy::expect_used)]
|
||||
timestamp: std::time::SystemTime::now()
|
||||
.duration_since(std::time::UNIX_EPOCH)
|
||||
.unwrap()
|
||||
.expect("System time before UNIX epoch")
|
||||
.as_secs(),
|
||||
}
|
||||
}
|
||||
@@ -139,7 +140,7 @@ mod tests {
|
||||
public_key: nym_crypto::asymmetric::x25519::PublicKey::from(nym_sphinx::PublicKey::from([1u8; 32])),
|
||||
private_ipv4: Ipv4Addr::new(10, 0, 0, 1),
|
||||
private_ipv6: Ipv6Addr::new(0xfc00, 0, 0, 0, 0, 0, 0, 1),
|
||||
endpoint: "192.168.1.1:8080".parse().unwrap(),
|
||||
endpoint: "192.168.1.1:8080".parse().expect("Valid test endpoint"),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -162,7 +163,7 @@ mod tests {
|
||||
assert_eq!(response.allocated_bandwidth, allocated_bandwidth);
|
||||
assert_eq!(response.session_id, session_id);
|
||||
|
||||
let returned_gw_data = response.gateway_data.unwrap();
|
||||
let returned_gw_data = response.gateway_data.expect("Gateway data should be present in success response");
|
||||
assert_eq!(returned_gw_data.public_key, gateway_data.public_key);
|
||||
assert_eq!(returned_gw_data.private_ipv4, gateway_data.private_ipv4);
|
||||
assert_eq!(returned_gw_data.private_ipv6, gateway_data.private_ipv6);
|
||||
|
||||
@@ -259,18 +259,4 @@ async fn register_wg_peer(
|
||||
},
|
||||
client_id,
|
||||
))
|
||||
}
|
||||
|
||||
// Helper function to convert bandwidth to ClientBandwidth if needed
|
||||
// This would integrate with the actual bandwidth controller
|
||||
#[allow(dead_code)]
|
||||
async fn store_client_bandwidth(
|
||||
client_id: String,
|
||||
bandwidth: i64,
|
||||
_storage: &nym_gateway_storage::GatewayStorage,
|
||||
) -> Result<(), GatewayError> {
|
||||
// This would integrate with the actual bandwidth storage
|
||||
// For now, just log it
|
||||
info!("Storing bandwidth {} for client {}", bandwidth, client_id);
|
||||
Ok(())
|
||||
}
|
||||
Reference in New Issue
Block a user