crab-net 0.0.4

<TCP|UDP> + TLS packets generator
Documentation
use coarsetime::{Duration, Instant};
use kanal::AsyncSender;
use log::debug;
use tokio::{
    io::{AsyncWrite, AsyncWriteExt},
    net::UdpSocket,
    time::sleep,
};

use crate::{DtlsSession, statistics::StatPacket};

pub async fn sender_task_udp(
    id: usize,
    socket: UdpSocket,
    payload: Vec<u8>,
    rate: usize,
    stats_tx: AsyncSender<StatPacket>,
) {
    debug!("client {id} spawned");
    let one_sec = Duration::new(1, 0);

    loop {
        let start_time = Instant::now();
        let mut packets_error = 0;

        for _ in 0..rate {
            if socket.send(&payload).await.is_err() {
                packets_error += 1;
            }
        }

        send_stats(rate, payload.len(), packets_error, &stats_tx).await;
        maybe_sleep(start_time, one_sec).await;
    }
}

pub async fn sender_task_dtls(
    id: usize,
    mut session: DtlsSession,
    payload: Vec<u8>,
    rate: usize,
    stats_tx: AsyncSender<StatPacket>,
) {
    debug!("client {id} spawned");
    let one_sec = Duration::new(1, 0);

    loop {
        let start_time = Instant::now();
        let mut packets_error = 0;

        for _ in 0..rate {
            if session.write(&payload).await.is_err() {
                packets_error += 1;
            }
        }

        send_stats(rate, payload.len(), packets_error, &stats_tx).await;
        maybe_sleep(start_time, one_sec).await;
    }
}

pub async fn sender_task_tcp(
    id: usize,
    mut stream: Box<dyn AsyncWrite + Unpin + Send>,
    payload: Vec<u8>,
    rate: usize,
    stats_tx: AsyncSender<StatPacket>,
) {
    debug!("client {id} spawned");
    let one_sec = Duration::new(1, 0);

    loop {
        let start_time = Instant::now();
        let mut packets_error = 0;

        for _ in 0..rate {
            if stream.write_all(&payload).await.is_err() {
                packets_error += 1;
            }
        }

        send_stats(rate, payload.len(), packets_error, &stats_tx).await;
        maybe_sleep(start_time, one_sec).await;
    }
}

async fn send_stats(
    rate: usize,
    payload_len: usize,
    packets_error: usize,
    stats_tx: &AsyncSender<StatPacket>,
) {
    let packets_sent = rate - packets_error;
    let _ = stats_tx
        .send((packets_sent * payload_len, packets_sent))
        .await;
}

async fn maybe_sleep(start_time: Instant, duration: Duration) {
    let time_elapsed = Instant::now() - start_time;

    if time_elapsed < duration {
        let time_to_sleep = duration - time_elapsed;
        sleep(time_to_sleep.into()).await;
    }
}