Skip to content

Commit

Permalink
add ut
Browse files Browse the repository at this point in the history
Signed-off-by: iGxnon <igxnon@gmail.com>
  • Loading branch information
iGxnon committed Feb 7, 2024
1 parent fea1cd2 commit 197eda7
Show file tree
Hide file tree
Showing 13 changed files with 247 additions and 114 deletions.
32 changes: 13 additions & 19 deletions benches/codec.rs
Original file line number Diff line number Diff line change
@@ -1,16 +1,15 @@
use bytes::BytesMut;
use criterion::async_executor::FuturesExecutor;
use criterion::{criterion_group, criterion_main, BatchSize, Criterion, Throughput};
use raknet_rs::codec;
use raknet_rs::micro_bench;

pub fn codec_benchmark(c: &mut Criterion) {
let mut group = c.benchmark_group("codec");
let seed = 114514;

// large packets, every frame set only contains one frame
{
let opts = codec::micro_bench::Options::builder()
.config(codec::Config::default())
let opts = micro_bench::codec::Options::builder()
.frame_per_set(1)
.frame_set_cnt(14400)
.duplicated_ratio(0.01)
Expand All @@ -32,7 +31,7 @@ pub fn codec_benchmark(c: &mut Criterion) {
group.throughput(Throughput::Elements(opts.input_data_cnt() as u64));
group.bench_function("decode_large_packets_same_data_cnt", |bencher| {
bencher.to_async(FuturesExecutor).iter_batched(
|| codec::micro_bench::MicroBench::new(opts.clone()),
|| micro_bench::codec::MicroBench::new(opts.clone()),
|bench| bench.bench_decoded(),
BatchSize::SmallInput,
);
Expand All @@ -41,8 +40,7 @@ pub fn codec_benchmark(c: &mut Criterion) {

// medium packets, every frame set contains 6 frame
{
let opts = codec::micro_bench::Options::builder()
.config(codec::Config::default())
let opts = micro_bench::codec::Options::builder()
.frame_per_set(6)
.frame_set_cnt(600)
.duplicated_ratio(0.01)
Expand All @@ -64,7 +62,7 @@ pub fn codec_benchmark(c: &mut Criterion) {
group.throughput(Throughput::Elements(opts.input_data_cnt() as u64));
group.bench_function("decode_medium_packets_same_data_cnt", |bencher| {
bencher.to_async(FuturesExecutor).iter_batched(
|| codec::micro_bench::MicroBench::new(opts.clone()),
|| micro_bench::codec::MicroBench::new(opts.clone()),
|bench| bench.bench_decoded(),
BatchSize::SmallInput,
);
Expand All @@ -73,8 +71,7 @@ pub fn codec_benchmark(c: &mut Criterion) {

// short packets, every frame set contains 36 frame
{
let opts = codec::micro_bench::Options::builder()
.config(codec::Config::default())
let opts = micro_bench::codec::Options::builder()
.frame_per_set(36)
.frame_set_cnt(100)
.duplicated_ratio(0.01)
Expand All @@ -96,7 +93,7 @@ pub fn codec_benchmark(c: &mut Criterion) {
group.throughput(Throughput::Elements(opts.input_data_cnt() as u64));
group.bench_function("decode_short_packets_same_data_cnt", |bencher| {
bencher.to_async(FuturesExecutor).iter_batched(
|| codec::micro_bench::MicroBench::new(opts.clone()),
|| micro_bench::codec::MicroBench::new(opts.clone()),
|bench| bench.bench_decoded(),
BatchSize::SmallInput,
);
Expand All @@ -105,8 +102,7 @@ pub fn codec_benchmark(c: &mut Criterion) {

// large packets, every frame set only contains one frame
{
let opts = codec::micro_bench::Options::builder()
.config(codec::Config::default())
let opts = micro_bench::codec::Options::builder()
.frame_per_set(1)
.frame_set_cnt(1440)
.duplicated_ratio(0.01)
Expand All @@ -128,7 +124,7 @@ pub fn codec_benchmark(c: &mut Criterion) {
group.throughput(Throughput::Bytes(opts.input_data_size() as u64));
group.bench_function("decode_large_packets_same_data_size", |bencher| {
bencher.to_async(FuturesExecutor).iter_batched(
|| codec::micro_bench::MicroBench::new(opts.clone()),
|| micro_bench::codec::MicroBench::new(opts.clone()),
|bench| bench.bench_decoded(),
BatchSize::SmallInput,
);
Expand All @@ -137,8 +133,7 @@ pub fn codec_benchmark(c: &mut Criterion) {

// medium packets, every frame set contains 6 frame
{
let opts = codec::micro_bench::Options::builder()
.config(codec::Config::default())
let opts = micro_bench::codec::Options::builder()
.frame_per_set(6)
.frame_set_cnt(1550)
.duplicated_ratio(0.01)
Expand All @@ -160,7 +155,7 @@ pub fn codec_benchmark(c: &mut Criterion) {
group.throughput(Throughput::Bytes(opts.input_data_size() as u64));
group.bench_function("decode_medium_packets_same_data_size", |bencher| {
bencher.to_async(FuturesExecutor).iter_batched(
|| codec::micro_bench::MicroBench::new(opts.clone()),
|| micro_bench::codec::MicroBench::new(opts.clone()),
|bench| bench.bench_decoded(),
BatchSize::SmallInput,
);
Expand All @@ -169,8 +164,7 @@ pub fn codec_benchmark(c: &mut Criterion) {

// short packets, every frame set contains 36 frame
{
let opts = codec::micro_bench::Options::builder()
.config(codec::Config::default())
let opts = micro_bench::codec::Options::builder()
.frame_per_set(36)
.frame_set_cnt(1378)
.duplicated_ratio(0.01)
Expand All @@ -192,7 +186,7 @@ pub fn codec_benchmark(c: &mut Criterion) {
group.throughput(Throughput::Bytes(opts.input_data_size() as u64));
group.bench_function("decode_short_packets_same_data_size", |bencher| {
bencher.to_async(FuturesExecutor).iter_batched(
|| codec::micro_bench::MicroBench::new(opts.clone()),
|| micro_bench::codec::MicroBench::new(opts.clone()),
|bench| bench.bench_decoded(),
BatchSize::SmallInput,
);
Expand Down
51 changes: 48 additions & 3 deletions src/client/conn/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,58 @@ use crate::{codec, IO};
/// Connection implementation by using tokio's UDP framework
mod tokio;

#[derive(Debug, Clone, derive_builder::Builder)]
#[derive(Debug, Clone, Copy, derive_builder::Builder)]
pub struct Config {
/// The send buffer of each IO polled by the incoming
send_buf_cap: usize,
codec: codec::Config,
offline: offline::Config,

mtu: u16,
client_guid: u64,
protocol_version: u8,

/// Limit the max size of a parted frames set, 0 means no limit
/// It will abort the split frame if the parted_size reaches limit.
/// Enable it to avoid DoS attack.
/// The maximum number of inflight parted frames is max_parted_size * max_parted_count
#[builder(default = "256")]
max_parted_size: u32,
/// Limit the max count of **all** parted frames sets from an address.
/// It might cause client resending frames if the limit is reached.
/// Enable it to avoid DoS attack.
/// The maximum number of inflight parted frames is max_parted_size * max_parted_count
#[builder(default = "256")]
max_parted_count: usize,
/// Maximum ordered channel, the value should be less than 256
#[builder(default = "1")]
max_channels: usize,
// Limit the maximum deduplication gap for a connection, 0 means no limit.
// Enable it to avoid D-DoS attack based on deduplication.
#[builder(default = "1024")]
max_dedup_gap: usize,
}

impl Config {
fn offline_config(&self) -> offline::Config {
offline::ConfigBuilder::default()
.mtu(self.mtu)
.client_guid(self.client_guid)
.protocol_version(self.protocol_version)
.build()
.unwrap()
}

fn codec_config(&self) -> codec::Config {
codec::ConfigBuilder::default()
.max_parted_count(self.max_parted_count)
.max_parted_size(self.max_parted_size)
.max_channels(self.max_channels)
.max_dedup_gap(self.max_dedup_gap)
.build()
.unwrap()
}
}

pub trait ConnectTo: Sized {
#[allow(async_fn_in_trait)] // No need to consider the auto trait for now.
async fn connect_to(self, addr: impl ToSocketAddrs, config: Config) -> Result<impl IO, Error>;
}
10 changes: 5 additions & 5 deletions src/client/conn/tokio.rs
Original file line number Diff line number Diff line change
Expand Up @@ -52,17 +52,17 @@ impl ConnectTo for TokioUdpSocket {
outgoing_ack_rx,
outgoing_nack_rx,
config.send_buf_cap,
config.offline.mtu,
config.mtu,
)
.frame_encoded(config.offline.mtu, config.codec);
.frame_encoded(config.mtu, config.codec_config());

let io = UdpFramed::new(socket, Codec)
.logged_err(err_f)
.handle_offline(addr, config.offline)
.handle_offline(addr, config.offline_config())
.await?
.handle_incoming_ack(incoming_ack_tx, incoming_nack_tx)
.decoded(config.codec, outgoing_ack_tx, outgoing_nack_tx)
.handle_online(write, addr, config.offline.client_guid)
.decoded(config.codec_config(), outgoing_ack_tx, outgoing_nack_tx)
.handle_online(write, addr, config.client_guid)
.await?;

Ok(IOImpl::new(io))
Expand Down
6 changes: 3 additions & 3 deletions src/client/handler/offline.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,9 @@ use crate::packet::connected::{self, Frames};
use crate::packet::{unconnected, Packet};

#[derive(Debug, Clone, Copy, derive_builder::Builder)]
pub struct Config {
pub(crate) mtu: u16,
pub(crate) client_guid: u64,
pub(crate) struct Config {
mtu: u16,
client_guid: u64,
protocol_version: u8,
}

Expand Down
2 changes: 2 additions & 0 deletions src/client/mod.rs
Original file line number Diff line number Diff line change
@@ -1,2 +1,4 @@
mod conn;
mod handler;

pub use conn::*;
7 changes: 2 additions & 5 deletions src/codec/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ use crate::Message;

/// Codec config
#[derive(Clone, Copy, Debug, Builder)]
pub struct Config {
pub(crate) struct Config {
/// Limit the max size of a parted frames set, 0 means no limit
/// It will abort the split frame if the parted_size reaches limit.
/// Enable it to avoid DoS attack.
Expand Down Expand Up @@ -152,7 +152,6 @@ pub mod micro_bench {

#[derive(derive_builder::Builder, Debug, Clone)]
pub struct Options {
config: Config,
frame_set_cnt: usize,
frame_per_set: usize,
duplicated_ratio: f32,
Expand All @@ -166,7 +165,6 @@ pub mod micro_bench {
impl Options {
pub fn builder() -> OptionsBuilder {
OptionsBuilder {
config: None,
frame_set_cnt: None,
frame_per_set: None,
duplicated_ratio: None,
Expand Down Expand Up @@ -272,7 +270,7 @@ pub mod micro_bench {
impl MicroBench {
pub fn new(option: Options) -> Self {
Self {
config: option.config,
config: Config::default(),
#[cfg(test)]
data: option.data.clone(),
frame_sets: option.gen_inputs(),
Expand Down Expand Up @@ -329,7 +327,6 @@ pub mod micro_bench {
#[tokio::test]
async fn test_bench() {
let opts = Options::builder()
.config(Config::default())
.frame_per_set(8)
.frame_set_cnt(100)
.duplicated_ratio(0.1)
Expand Down
13 changes: 12 additions & 1 deletion src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@
#![feature(coroutines, proc_macro_hygiene, stmt_expr_attributes, gen_future)]

/// Protocol codec
pub mod codec;
mod codec;

/// Errors
mod errors;
Expand All @@ -69,6 +69,17 @@ pub mod client;
/// Service
pub mod service;

/// Unit tests
#[cfg(test)]
mod tests;

#[cfg(feature = "micro-bench")]
pub mod micro_bench {
pub mod codec {
pub use crate::codec::micro_bench::*;
}
}

use std::net::SocketAddr;

use bytes::Bytes;
Expand Down
2 changes: 1 addition & 1 deletion src/packet/connected/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ impl Packet<Frames<BytesMut>> {

/// `uint24` little-endian but actually occupies 4 bytes.
#[derive(Debug, Copy, Clone, Ord, PartialOrd, Eq, PartialEq, Hash)]
pub(crate) struct Uint24le(pub u32);
pub(crate) struct Uint24le(pub(crate) u32);

impl Uint24le {
fn read(buf: &mut BytesMut) -> Self {
Expand Down
4 changes: 2 additions & 2 deletions src/server/handler/offline.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,8 @@ where
}

#[derive(Debug, Clone, derive_builder::Builder)]
pub struct Config {
pub(crate) sever_guid: u64,
pub(crate) struct Config {
sever_guid: u64,
advertisement: Bytes,
min_mtu: u16,
max_mtu: u16,
Expand Down
55 changes: 53 additions & 2 deletions src/server/incoming/mod.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
use bytes::Bytes;
use futures::Stream;

use super::handler::offline;
Expand All @@ -11,8 +12,58 @@ mod tokio;
pub struct Config {
/// The send buffer of each IO polled by the incoming
send_buf_cap: usize,
codec: codec::Config,
offline: offline::Config,

sever_guid: u64,
advertisement: Bytes,
min_mtu: u16,
max_mtu: u16,
// Supported raknet versions, sorted
support_version: Vec<u8>,
max_pending: usize,

/// Limit the max size of a parted frames set, 0 means no limit
/// It will abort the split frame if the parted_size reaches limit.
/// Enable it to avoid DoS attack.
/// The maximum number of inflight parted frames is max_parted_size * max_parted_count
#[builder(default = "256")]
max_parted_size: u32,
/// Limit the max count of **all** parted frames sets from an address.
/// It might cause client resending frames if the limit is reached.
/// Enable it to avoid DoS attack.
/// The maximum number of inflight parted frames is max_parted_size * max_parted_count
#[builder(default = "256")]
max_parted_count: usize,
/// Maximum ordered channel, the value should be less than 256
#[builder(default = "1")]
max_channels: usize,
// Limit the maximum deduplication gap for a connection, 0 means no limit.
// Enable it to avoid D-DoS attack based on deduplication.
#[builder(default = "1024")]
max_dedup_gap: usize,
}

impl Config {
fn offline_config(&self) -> offline::Config {
offline::ConfigBuilder::default()
.sever_guid(self.sever_guid)
.advertisement(self.advertisement.clone())
.min_mtu(self.min_mtu)
.max_mtu(self.max_mtu)
.support_version(self.support_version.clone())
.max_pending(self.max_pending)
.build()
.unwrap()
}

fn codec_config(&self) -> codec::Config {
codec::ConfigBuilder::default()
.max_parted_count(self.max_parted_count)
.max_parted_size(self.max_parted_size)
.max_channels(self.max_channels)
.max_dedup_gap(self.max_dedup_gap)
.build()
.unwrap()
}
}

pub trait MakeIncoming: Sized {
Expand Down

0 comments on commit 197eda7

Please sign in to comment.