152 lines
5.4 KiB
Rust
152 lines
5.4 KiB
Rust
use std::collections::HashMap;
|
|
|
|
use bytes::Bytes;
|
|
use criterion::{black_box, criterion_group, criterion_main, BenchmarkId, Criterion, Throughput};
|
|
use wgcloak::{
|
|
protocol::{
|
|
direct::{parse_packet_bounded, DataPacket},
|
|
replay::ReplayWindow,
|
|
},
|
|
transport::{http3, tls_tcp::FrameCodec},
|
|
};
|
|
|
|
const SECRET: &[u8] = b"benchmark-secret-with-at-least-32-bytes";
|
|
const SESSION_KEY: [u8; 32] = [0x42; 32];
|
|
const SESSION_ID: u64 = 0x0102_0304_0506_0708;
|
|
|
|
fn bench_direct_protocol(c: &mut Criterion) {
|
|
let mut group = c.benchmark_group("direct_protocol");
|
|
for size in [64usize, 512, 1200] {
|
|
let payload = Bytes::from(vec![0x5a; size]);
|
|
let packet = DataPacket::authenticated(&SESSION_KEY, SESSION_ID, 7, payload);
|
|
group.throughput(Throughput::Bytes(size as u64));
|
|
group.bench_with_input(
|
|
BenchmarkId::new("encode_parse_mac", size),
|
|
&packet,
|
|
|b, packet| {
|
|
b.iter(|| {
|
|
let wire = packet.encode().expect("benchmark packet encodes");
|
|
let parsed = parse_packet_bounded(black_box(&wire), size)
|
|
.expect("benchmark packet parses");
|
|
let parsed = match parsed {
|
|
wgcloak::protocol::Packet::Data(data) => data,
|
|
_ => panic!("benchmark packet changed type"),
|
|
};
|
|
black_box(parsed.verify_authenticator(&SESSION_KEY));
|
|
});
|
|
},
|
|
);
|
|
}
|
|
group.finish();
|
|
}
|
|
|
|
fn bench_tls_frames(c: &mut Criterion) {
|
|
let codec = FrameCodec::new(1200).expect("valid frame maximum");
|
|
let first = vec![0x11; 512];
|
|
let second = vec![0x22; 512];
|
|
let single = codec.encode(&first).expect("frame encodes");
|
|
let mut coalesced = single.clone();
|
|
coalesced.extend_from_slice(&codec.encode(&second).expect("frame encodes"));
|
|
let mut group = c.benchmark_group("tls_frames");
|
|
group.throughput(Throughput::Bytes(single.len() as u64));
|
|
group.bench_function("encode", |b| {
|
|
b.iter(|| black_box(codec.encode(black_box(&first)).expect("frame encodes")))
|
|
});
|
|
group.bench_function("decode_split", |b| {
|
|
b.iter(|| {
|
|
let mut decoder = FrameCodec::new(1200).expect("valid frame maximum");
|
|
let midpoint = single.len() / 2;
|
|
black_box(
|
|
decoder
|
|
.feed(&single[..midpoint])
|
|
.expect("first half accepted"),
|
|
);
|
|
black_box(
|
|
decoder
|
|
.feed(&single[midpoint..])
|
|
.expect("second half accepted"),
|
|
);
|
|
});
|
|
});
|
|
group.bench_function("decode_coalesced", |b| {
|
|
b.iter(|| {
|
|
let mut decoder = FrameCodec::new(1200).expect("valid frame maximum");
|
|
black_box(decoder.feed(&coalesced).expect("coalesced frames accepted"));
|
|
});
|
|
});
|
|
group.finish();
|
|
}
|
|
|
|
fn bench_http3(c: &mut Criterion) {
|
|
let challenge = http3::AuthChallenge { bytes: [0x33; 32] };
|
|
let nonce = [0x44; 16];
|
|
let client_id = "benchmark-client";
|
|
let response = http3::encode_auth_response(&challenge, client_id, &nonce, SECRET)
|
|
.expect("auth response encodes");
|
|
let mut clients = HashMap::new();
|
|
clients.insert(client_id.to_owned(), SECRET.to_vec());
|
|
let datagram_payload = vec![0x55; 1200];
|
|
let mut group = c.benchmark_group("http3_primitives");
|
|
group.throughput(Throughput::Bytes(datagram_payload.len() as u64));
|
|
group.bench_function("datagram_encode_decode", |b| {
|
|
b.iter(|| {
|
|
let encoded = http3::encode_http_datagram(
|
|
http3::CONNECT_UDP_CONTEXT_ID,
|
|
black_box(&datagram_payload),
|
|
1200,
|
|
)
|
|
.expect("HTTP Datagram encodes");
|
|
black_box(
|
|
http3::decode_http_datagram(&encoded, http3::CONNECT_UDP_CONTEXT_ID, 1200)
|
|
.expect("HTTP Datagram decodes"),
|
|
);
|
|
});
|
|
});
|
|
group.bench_function("capsule_encode_decode", |b| {
|
|
b.iter(|| {
|
|
let encoded =
|
|
http3::encode_capsule(0x2a, black_box(&challenge.bytes)).expect("capsule encodes");
|
|
black_box(http3::decode_capsule(&encoded).expect("capsule decodes"));
|
|
});
|
|
});
|
|
group.bench_function("auth_response_verify", |b| {
|
|
b.iter(|| {
|
|
black_box(
|
|
http3::verify_auth_response(&challenge, &response, &clients)
|
|
.expect("auth response verifies"),
|
|
);
|
|
});
|
|
});
|
|
group.finish();
|
|
}
|
|
|
|
fn bench_replay(c: &mut Criterion) {
|
|
let sequence: Vec<u32> = (1..=1024).collect();
|
|
c.bench_function("replay_window_sequential_1024", |b| {
|
|
b.iter(|| {
|
|
let mut window = ReplayWindow::new();
|
|
for sequence in &sequence {
|
|
black_box(window.check_and_record(*sequence));
|
|
}
|
|
});
|
|
});
|
|
c.bench_function("replay_window_duplicate_check", |b| {
|
|
b.iter(|| {
|
|
let mut window = ReplayWindow::new();
|
|
for sequence in 1..=1024 {
|
|
window.check_and_record(sequence);
|
|
}
|
|
black_box(window.check_and_record(512));
|
|
});
|
|
});
|
|
}
|
|
|
|
criterion_group!(
|
|
protocol_transports,
|
|
bench_direct_protocol,
|
|
bench_tls_frames,
|
|
bench_http3,
|
|
bench_replay
|
|
);
|
|
criterion_main!(protocol_transports);
|