use {
crate::{IoSet, Session},
bevy_app::prelude::*,
bevy_derive::Deref,
bevy_ecs::prelude::*,
bevy_reflect::prelude::*,
bytes::Bytes,
core::{num::Saturating, time::Duration},
derive_more::{Add, AddAssign, Display, Error, Sub, SubAssign},
tracing::warn,
web_time::Instant,
};
#[derive(Debug)]
pub(crate) struct PacketPlugin;
impl Plugin for PacketPlugin {
fn build(&self, app: &mut App) {
app.register_type::<PacketRtt>()
.register_type::<PacketStats>()
.add_systems(PreUpdate, clear_recv_buffers.before(IoSet::Poll))
.add_systems(PostUpdate, clear_send_buffers.after(IoSet::Flush));
}
}
#[derive(Debug, Clone)]
pub struct RecvPacket {
pub recv_at: Instant,
pub payload: Bytes,
}
pub const IP_MTU: usize = 1024;
#[derive(Debug, Clone, Copy, PartialEq, Eq, Display, Error)]
#[display("packet MTU too small - {mtu} / {min}")]
pub struct MtuTooSmall {
pub mtu: usize,
pub min: usize,
}
#[derive(Debug, Clone, Copy, Default, Reflect)] #[derive(Add, AddAssign, Sub, SubAssign)]
pub struct PacketStats {
pub packets_recv: Saturating<usize>,
pub packets_sent: Saturating<usize>,
pub bytes_recv: Saturating<usize>,
pub bytes_sent: Saturating<usize>,
}
#[derive(Debug, Clone, Copy, Deref, Component, Reflect)]
#[reflect(Component)]
#[doc(alias = "ping", alias = "latency")]
pub struct PacketRtt(pub Duration);
pub fn clear_recv_buffers(mut sessions: Query<(Entity, &mut Session)>) {
for (entity, mut session) in &mut sessions {
let len = session.recv.len();
if len > 0 {
warn!(
"{entity} has {len} received packets which have not been consumed - this \
indicates a bug in code above the IO layer"
);
session.recv.clear();
}
}
}
pub fn clear_send_buffers(mut sessions: Query<(Entity, &mut Session)>) {
for (entity, mut session) in &mut sessions {
let len = session.send.len();
if len > 0 {
warn!(
"{entity} has {len} sent packets which have not been consumed - this indicates a \
bug in the IO layer"
);
session.send.clear();
}
}
}