use std::{sync::Arc, time::Duration};
use async_trait::async_trait;
use crate::{PathKind, Result};
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct NetBenchTelemetry {
pub path: PathKind,
pub lost_packets: u64,
pub lost_bytes: u64,
pub congestion_events: u64,
pub rx_datagrams: u64,
pub tx_datagrams: u64,
pub current_mtu: u16,
pub black_holes_detected: u64,
pub rtt: Duration,
}
impl Default for NetBenchTelemetry {
fn default() -> Self {
Self {
path: PathKind::Unknown,
lost_packets: 0,
lost_bytes: 0,
congestion_events: 0,
rx_datagrams: 0,
tx_datagrams: 0,
current_mtu: 0,
black_holes_detected: 0,
rtt: Duration::ZERO,
}
}
}
#[async_trait]
pub trait NetBenchSendStream: Send {
async fn write(&mut self, bytes: &[u8]) -> Result<usize> {
self.write_all(bytes).await?;
Ok(bytes.len())
}
async fn write_all(&mut self, bytes: &[u8]) -> Result<()>;
fn finish(&mut self) -> Result<()>;
fn cancel(&mut self);
}
#[async_trait]
impl<T: NetBenchSendStream + ?Sized> NetBenchSendStream for Box<T> {
async fn write(&mut self, bytes: &[u8]) -> Result<usize> {
(**self).write(bytes).await
}
async fn write_all(&mut self, bytes: &[u8]) -> Result<()> {
(**self).write_all(bytes).await
}
fn finish(&mut self) -> Result<()> {
(**self).finish()
}
fn cancel(&mut self) {
(**self).cancel();
}
}
#[async_trait]
pub trait NetBenchReceiveStream: Send {
async fn read(&mut self, bytes: &mut [u8]) -> Result<usize>;
async fn read_exact(&mut self, bytes: &mut [u8]) -> Result<()>;
fn cancel(&mut self);
}
#[async_trait]
impl<T: NetBenchReceiveStream + ?Sized> NetBenchReceiveStream for Box<T> {
async fn read(&mut self, bytes: &mut [u8]) -> Result<usize> {
(**self).read(bytes).await
}
async fn read_exact(&mut self, bytes: &mut [u8]) -> Result<()> {
(**self).read_exact(bytes).await
}
fn cancel(&mut self) {
(**self).cancel();
}
}
pub trait NetBenchBidirectionalStream: Send {
fn into_split(self: Box<Self>)
-> (Box<dyn NetBenchSendStream>, Box<dyn NetBenchReceiveStream>);
}
#[async_trait]
pub trait NetBenchSession: Send + Sync {
fn remote_peer_id(&self) -> String;
fn telemetry(&self) -> NetBenchTelemetry;
fn max_datagram_size(&self) -> Option<usize>;
async fn open_bi(&self) -> Result<Box<dyn NetBenchBidirectionalStream>>;
async fn accept_bi(&self) -> Result<Box<dyn NetBenchBidirectionalStream>>;
async fn send_datagram(&self, bytes: Vec<u8>) -> Result<()>;
async fn read_datagram(&self) -> Result<Vec<u8>>;
}
pub struct NetBenchFlow {
session: Arc<dyn NetBenchSession>,
control_send: Box<dyn NetBenchSendStream>,
control_recv: Box<dyn NetBenchReceiveStream>,
}
impl std::fmt::Debug for NetBenchFlow {
fn fmt(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
formatter
.debug_struct("NetBenchFlow")
.field("remote_peer_id", &self.session.remote_peer_id())
.finish_non_exhaustive()
}
}
impl NetBenchFlow {
#[must_use]
pub fn new(
session: Arc<dyn NetBenchSession>,
control_send: Box<dyn NetBenchSendStream>,
control_recv: Box<dyn NetBenchReceiveStream>,
) -> Self {
Self {
session,
control_send,
control_recv,
}
}
pub(crate) fn into_parts(
self,
) -> (
Arc<dyn NetBenchSession>,
Box<dyn NetBenchSendStream>,
Box<dyn NetBenchReceiveStream>,
) {
(self.session, self.control_send, self.control_recv)
}
}