diff options
| author | zirkonya <zirkonya@iridium.lan> | 2026-08-27 09:45:12 +0200 |
|---|---|---|
| committer | zirkonya <zirkonya@iridium.lan> | 2026-08-27 09:45:12 +0200 |
| commit | bb41e396aca01fee9f81785681fac0a79d0fd9d8 (patch) | |
| tree | 94ebe4800a50c14abc413cbcabe9ffaaab7496ef | |
| parent | 8bae725a803ee00bf5bc86b9fc0be6853b95115e (diff) | |
split event and enhance context
| -rw-r--r-- | src/codec.rs | 4 | ||||
| -rw-r--r-- | src/codec/decode.rs | 41 | ||||
| -rw-r--r-- | src/codec/encode.rs | 33 | ||||
| -rw-r--r-- | src/context.rs | 8 | ||||
| -rw-r--r-- | src/event.rs | 88 | ||||
| -rw-r--r-- | src/event/connection.rs | 13 | ||||
| -rw-r--r-- | src/event/disconnect.rs | 25 | ||||
| -rw-r--r-- | src/event/handler.rs | 67 | ||||
| -rw-r--r-- | src/event/listener.rs | 47 | ||||
| -rw-r--r-- | src/event/received.rs | 7 | ||||
| -rw-r--r-- | src/event/sent.rs | 7 | ||||
| -rw-r--r-- | src/types/prefix/count.rs | 19 | ||||
| -rw-r--r-- | src/types/prefix/length.rs | 19 |
13 files changed, 267 insertions, 111 deletions
diff --git a/src/codec.rs b/src/codec.rs index 778001f..6680699 100644 --- a/src/codec.rs +++ b/src/codec.rs @@ -4,5 +4,5 @@ pub mod decode; pub mod encode; pub mod error; -pub trait Codec<Ctx>: Encode<Ctx> + Decode<Ctx> {} -impl<Ctx, T> Codec<Ctx> for T where T: Encode<Ctx> + Decode<Ctx> {} +pub trait Codec<Data = ()>: Encode<Data> + Decode<Data> {} +impl<Data, T> Codec<Data> for T where T: Encode<Data> + Decode<Data> {} diff --git a/src/codec/decode.rs b/src/codec/decode.rs index fa4ae95..39253a2 100644 --- a/src/codec/decode.rs +++ b/src/codec/decode.rs @@ -1,13 +1,14 @@ //! Decoding: reading protocol values from a byte stream. +use crate::context::Context; use std::{io::Read, sync::Arc}; use crate::{DEFAULT_BUFFER_LEN, codec::error::Result}; macro_rules! impl_decode { ($type: ty) => { - impl<Ctx> Decode<Ctx> for $type { + impl<Data> Decode<Data> for $type { // decode number using big endian - fn decode(reader: &mut dyn Read, _: &mut Ctx) -> Result<Self> + fn decode(reader: &mut dyn Read, _: &Context<Data>) -> Result<Self> where Self: Sized, { @@ -21,14 +22,14 @@ macro_rules! impl_decode { } /// Read a value from a byte stream -pub trait Decode<Ctx> { - fn decode(reader: &mut dyn Read, ctx: &mut Ctx) -> Result<Self> +pub trait Decode<Data> { + fn decode(reader: &mut dyn Read, ctx: &Context<Data>) -> Result<Self> where Self: Sized; } -impl<Ctx> Decode<Ctx> for bool { - fn decode(reader: &mut dyn Read, _: &mut Ctx) -> Result<Self> +impl<Data> Decode<Data> for bool { + fn decode(reader: &mut dyn Read, _: &Context<Data>) -> Result<Self> where Self: Sized, { @@ -38,8 +39,8 @@ impl<Ctx> Decode<Ctx> for bool { } } -impl<Ctx, T: Decode<Ctx>> Decode<Ctx> for Option<T> { - fn decode(reader: &mut dyn Read, ctx: &mut Ctx) -> Result<Self> +impl<Data, T: Decode<Data>> Decode<Data> for Option<T> { + fn decode(reader: &mut dyn Read, ctx: &Context<Data>) -> Result<Self> where Self: Sized, { @@ -52,8 +53,8 @@ impl<Ctx, T: Decode<Ctx>> Decode<Ctx> for Option<T> { } } -impl<Ctx, T: Decode<Ctx>> Decode<Ctx> for Vec<T> { - fn decode(reader: &mut dyn Read, ctx: &mut Ctx) -> Result<Self> +impl<Data, T: Decode<Data>> Decode<Data> for Vec<T> { + fn decode(reader: &mut dyn Read, ctx: &Context<Data>) -> Result<Self> where Self: Sized, { @@ -66,8 +67,8 @@ impl<Ctx, T: Decode<Ctx>> Decode<Ctx> for Vec<T> { } } -impl<Ctx> Decode<Ctx> for String { - fn decode(reader: &mut dyn Read, _: &mut Ctx) -> Result<Self> +impl<Data> Decode<Data> for String { + fn decode(reader: &mut dyn Read, _: &Context<Data>) -> Result<Self> where Self: Sized, { @@ -77,16 +78,16 @@ impl<Ctx> Decode<Ctx> for String { } } -impl<Ctx> Decode<Ctx> for Arc<[u8]> { - fn decode(reader: &mut dyn Read, _: &mut Ctx) -> Result<Self> { +impl<Data> Decode<Data> for Arc<[u8]> { + fn decode(reader: &mut dyn Read, _: &Context<Data>) -> Result<Self> { let mut buf = Vec::with_capacity(DEFAULT_BUFFER_LEN); reader.read_to_end(&mut buf)?; Ok(Arc::<[u8]>::from(buf.into_boxed_slice())) } } -impl<Ctx, const S: usize> Decode<Ctx> for [u8; S] { - fn decode(reader: &mut dyn Read, _: &mut Ctx) -> Result<Self> +impl<Data, const S: usize> Decode<Data> for [u8; S] { + fn decode(reader: &mut dyn Read, _: &Context<Data>) -> Result<Self> where Self: Sized, { @@ -110,8 +111,8 @@ impl_decode!(i64); impl_decode!(i128); impl_decode!(isize); -impl<Ctx> Decode<Ctx> for f64 { - fn decode(reader: &mut dyn Read, ctx: &mut Ctx) -> Result<Self> +impl<Data> Decode<Data> for f64 { + fn decode(reader: &mut dyn Read, ctx: &Context<Data>) -> Result<Self> where Self: Sized, { @@ -121,8 +122,8 @@ impl<Ctx> Decode<Ctx> for f64 { } } -impl<Ctx> Decode<Ctx> for f32 { - fn decode(reader: &mut dyn Read, ctx: &mut Ctx) -> Result<Self> +impl<Data> Decode<Data> for f32 { + fn decode(reader: &mut dyn Read, ctx: &Context<Data>) -> Result<Self> where Self: Sized, { diff --git a/src/codec/encode.rs b/src/codec/encode.rs index c8d1c7b..b9ac961 100644 --- a/src/codec/encode.rs +++ b/src/codec/encode.rs @@ -1,12 +1,13 @@ //! Encoding: writing protocol values into a byte stream. use crate::codec::error::Error; +use crate::context::Context; use std::{io::Write, sync::Arc}; macro_rules! impl_encode { ($t: ty) => { - impl<Ctx> Encode<Ctx> for $t { + impl<Data> Encode<Data> for $t { /// write number using big endian - fn encode(&self, buffer: &mut dyn Write, _: &mut Ctx) -> Result<usize, Error> { + fn encode(&self, buffer: &mut dyn Write, _: &Context<Data>) -> Result<usize, Error> { let size = buffer.write(&self.to_be_bytes())?; Ok(size) } @@ -15,20 +16,20 @@ macro_rules! impl_encode { } /// Write a value into a byte stream -pub trait Encode<Ctx> { - fn encode(&self, buffer: &mut dyn Write, ctx: &mut Ctx) -> Result<usize, Error>; +pub trait Encode<Data> { + fn encode(&self, buffer: &mut dyn Write, ctx: &Context<Data>) -> Result<usize, Error>; } -impl<Ctx> Encode<Ctx> for bool { - fn encode(&self, buffer: &mut dyn Write, _: &mut Ctx) -> Result<usize, Error> { +impl<Data> Encode<Data> for bool { + fn encode(&self, buffer: &mut dyn Write, _: &Context<Data>) -> Result<usize, Error> { let size = buffer.write(&[*self as u8])?; Ok(size) } } -impl<Ctx, T: Encode<Ctx>> Encode<Ctx> for Option<T> { +impl<Data, T: Encode<Data>> Encode<Data> for Option<T> { /// Encode `T` if Some(T) or do nothing if None - fn encode(&self, buffer: &mut dyn Write, ctx: &mut Ctx) -> Result<usize, Error> { + fn encode(&self, buffer: &mut dyn Write, ctx: &Context<Data>) -> Result<usize, Error> { match self { Some(val) => { let size = val.encode(buffer, ctx)?; @@ -39,11 +40,11 @@ impl<Ctx, T: Encode<Ctx>> Encode<Ctx> for Option<T> { } } -impl<Ctx, T: Encode<Ctx>> Encode<Ctx> for Vec<T> { +impl<Data, T: Encode<Data>> Encode<Data> for Vec<T> { /// Encode each element of vector /// use `CountPrefix` to prefix the vector with number of elements /// use `LenPrefix` to prefix the vector with encoded byte size - fn encode(&self, buffer: &mut dyn Write, ctx: &mut Ctx) -> Result<usize, Error> { + fn encode(&self, buffer: &mut dyn Write, ctx: &Context<Data>) -> Result<usize, Error> { let mut size = 0; for item in self { size += item.encode(buffer, ctx)?; @@ -52,30 +53,30 @@ impl<Ctx, T: Encode<Ctx>> Encode<Ctx> for Vec<T> { } } -impl<Ctx> Encode<Ctx> for String { +impl<Data> Encode<Data> for String { /// Encode the string using utf8 /// use `CountPrefix` to prefix the string with char length /// use `LenPrefix` to prefix the string with utf8 bytes length - fn encode(&self, buffer: &mut dyn Write, _: &mut Ctx) -> Result<usize, Error> { + fn encode(&self, buffer: &mut dyn Write, _: &Context<Data>) -> Result<usize, Error> { let utf8 = self.as_bytes(); buffer.write_all(utf8)?; Ok(utf8.len()) } } -impl<Ctx> Encode<Ctx> for Arc<[u8]> { +impl<Data> Encode<Data> for Arc<[u8]> { /// write raw slice into the buffer /// use `LenPrefix` to prefix with byte length - fn encode(&self, buffer: &mut dyn Write, _: &mut Ctx) -> Result<usize, Error> { + fn encode(&self, buffer: &mut dyn Write, _: &Context<Data>) -> Result<usize, Error> { let len = buffer.write(self)?; Ok(len) } } -impl<Ctx, const S: usize> Encode<Ctx> for [u8; S] { +impl<Data, const S: usize> Encode<Data> for [u8; S] { /// write raw slice into the buffer /// use `LenPrefix` to prefix with byte length - fn encode(&self, buffer: &mut dyn Write, _ctx: &mut Ctx) -> Result<usize, Error> { + fn encode(&self, buffer: &mut dyn Write, _: &Context<Data>) -> Result<usize, Error> { let len = buffer.write(self)?; Ok(len) } diff --git a/src/context.rs b/src/context.rs index 8b13789..bcc0b6d 100644 --- a/src/context.rs +++ b/src/context.rs @@ -1 +1,9 @@ +pub struct Context<Data> { + pub data: Data, +} +impl<Data> Context<Data> { + pub fn new(data: Data) -> Self { + Self { data } + } +}
\ No newline at end of file diff --git a/src/event.rs b/src/event.rs index bbba586..95d5a12 100644 --- a/src/event.rs +++ b/src/event.rs @@ -1,94 +1,72 @@ -use std::{io, net::SocketAddr, time::Instant}; +use std::{cell::Cell, time::Instant}; -use getset::{Getters, Setters}; +use getset::Getters; + +use crate::event::{ + connection::ConnectionEvent, disconnect::DisconnectEvent, received::PacketReceivedEvent, + sent::PacketSentEvent, +}; pub mod handler; pub mod listener; -pub enum EventKind<Packet, Uid = u64> +pub mod connection; +pub mod disconnect; +pub mod received; +pub mod sent; + +pub enum EventKind<Packet, Uid> where Uid: PartialEq, { - Connection(ConnectionEvent<Uid>), + Connection(ConnectionEvent), PacketReceived(PacketReceivedEvent<Packet>), PacketSent(PacketSentEvent<Packet>), Disconnect(DisconnectEvent<Uid>), } -// TODO : identification -// TODO : reason type #[derive(Getters)] -pub struct ConnectionEvent<Uid> +pub struct Event<Packet, Uid> where Uid: PartialEq, { #[getset(get = "pub")] - peer_addr: SocketAddr, - #[getset(get = "pub")] - local_addr: SocketAddr, - #[getset(get = "pub")] - connection_id: Uid, -} -#[derive(Getters)] -pub struct PacketReceivedEvent<Packet> { - #[getset(get = "pub")] - packet: Packet, -} -#[derive(Getters)] -pub struct PacketSentEvent<Packet> { - #[getset(get = "pub")] - packet: Packet, -} - -// TODO : better error type for protocol violation -pub type ProtocolViolation = String; - -pub enum DisconnectReason { - Normal, - Error(io::Error), - ProtocolError(ProtocolViolation), - Timeout, - ServerShutdown, -} + instant: Instant, -#[derive(Getters)] -pub struct DisconnectEvent<Uid> -where - Uid: PartialEq, -{ #[getset(get = "pub")] connection_id: Uid, + canceled: Cell<bool>, #[getset(get = "pub")] - reason: DisconnectReason, + kind: EventKind<Packet, Uid>, } -#[derive(Getters, Setters)] -pub struct Event<Packet, Uid = u64> +impl<Packet, Uid> Event<Packet, Uid> where Uid: PartialEq, { - #[getset(get = "pub")] - instant: Instant, - #[getset(get = "pub", set = "pub")] - canceled: bool, - #[getset(get = "pub")] - kind: EventKind<Packet, Uid>, -} - -impl<Packet> Event<Packet> { - pub fn new(kind: EventKind<Packet>) -> Self { + pub fn new(connection_id: Uid, kind: EventKind<Packet, Uid>) -> Self { Self { + connection_id, instant: Instant::now(), - canceled: false, + canceled: Cell::new(true), kind, } } - pub fn differed(when: Instant, kind: EventKind<Packet>) -> Self { + pub fn differed(connection_id: Uid, when: Instant, kind: EventKind<Packet, Uid>) -> Self { Self { + connection_id, instant: when, - canceled: false, + canceled: Cell::new(true), kind, } } + + pub fn canceled(&self) -> bool { + self.canceled.get() + } + + pub fn cancel(&self) { + self.canceled.set(true); + } } diff --git a/src/event/connection.rs b/src/event/connection.rs new file mode 100644 index 0000000..99813fd --- /dev/null +++ b/src/event/connection.rs @@ -0,0 +1,13 @@ +use std::net::SocketAddr; + +use getset::Getters; + +// TODO : identification +// TODO : reason type +#[derive(Getters)] +pub struct ConnectionEvent { + #[getset(get = "pub")] + peer_addr: SocketAddr, + #[getset(get = "pub")] + local_addr: SocketAddr, +} diff --git a/src/event/disconnect.rs b/src/event/disconnect.rs new file mode 100644 index 0000000..6511027 --- /dev/null +++ b/src/event/disconnect.rs @@ -0,0 +1,25 @@ +use std::io; + +use getset::Getters; + +// TODO : better error type for protocol violation +pub type ProtocolViolation = String; + +pub enum DisconnectReason { + Normal, + Error(io::Error), + ProtocolError(ProtocolViolation), + Timeout, + ServerShutdown, +} + +#[derive(Getters)] +pub struct DisconnectEvent<Uid> +where + Uid: PartialEq, +{ + #[getset(get = "pub")] + connection_id: Uid, + #[getset(get = "pub")] + reason: DisconnectReason, +} diff --git a/src/event/handler.rs b/src/event/handler.rs index 7d8b5b5..3f9827e 100644 --- a/src/event/handler.rs +++ b/src/event/handler.rs @@ -1,2 +1,69 @@ // TODO : dispatch event through all listener // TODO : maybe compile listener into one ? + +use crate::{ + context::Context, + event::{ + Event, + listener::{Listener, ListenerResult}, + }, +}; + +pub struct EventHandler<Packet, Data = (), Uid = u64> +where + Uid: PartialEq, +{ + listeners: Vec<Box<dyn Listener<Packet, Data, Uid>>>, +} + +impl<Packet, Data, Uid> EventHandler<Packet, Data, Uid> +where + Uid: PartialEq + Clone, +{ + pub fn register<L: Listener<Packet, Data, Uid> + 'static>(&mut self, listener: L) { + self.listeners.push(Box::new(listener)); + } + + pub fn dispatch(&self, event: &Event<Packet, Uid>, ctx: &Context<Data>) { + match event.kind() { + super::EventKind::Connection(connection_event) => { + for listener in &self.listeners { + if matches!( + listener.on_connection(connection_event, ctx), + ListenerResult::Cancel | ListenerResult::Disconnect + ) { + event.cancel(); + break; + } + } + } + super::EventKind::PacketReceived(packet_received_event) => { + for listener in &self.listeners { + if matches!( + listener.on_packet_received(packet_received_event, ctx), + ListenerResult::Cancel | ListenerResult::Disconnect + ) { + event.cancel(); + break; + } + } + } + super::EventKind::PacketSent(packet_sent_event) => { + for listener in &self.listeners { + if matches!( + listener.on_packet_sent(packet_sent_event, ctx), + ListenerResult::Cancel | ListenerResult::Disconnect + ) { + event.cancel(); + break; + } + } + } + super::EventKind::Disconnect(disconnect_event) => { + for listener in &self.listeners { + listener.on_disconnect(disconnect_event, ctx); + } + } + } + } +} diff --git a/src/event/listener.rs b/src/event/listener.rs index 178dda8..81f4b57 100644 --- a/src/event/listener.rs +++ b/src/event/listener.rs @@ -1 +1,48 @@ +use crate::{ + context::Context, + event::{ConnectionEvent, DisconnectEvent, PacketReceivedEvent, PacketSentEvent}, +}; + // TODO : Listener ; interface to perform action when event occured +// TODO async trait for async runtime + +pub enum ListenerResult { + Continue, + /// Cancel the event + /// `ConectionEvent` => same as `ListenerResult::Disconnect` + /// `PacketReceived` => the received packet is drop + /// `PacketSent` => the packet isn't send + /// `Disconnect` => non sense + Cancel, + /// Force disconnect the connection + Disconnect, +} + +pub trait Listener<Packet, Data = (), Uid = u64> +where + Uid: PartialEq, +{ + fn on_connection(&self, event: &ConnectionEvent, ctx: &Context<Data>) -> ListenerResult { + let _ = (event, ctx); + ListenerResult::Continue + } + fn on_packet_received( + &self, + event: &PacketReceivedEvent<Packet>, + ctx: &Context<Data>, + ) -> ListenerResult { + let _ = (event, ctx); + ListenerResult::Continue + } + fn on_packet_sent( + &self, + event: &PacketSentEvent<Packet>, + ctx: &Context<Data>, + ) -> ListenerResult { + let _ = (event, ctx); + ListenerResult::Continue + } + fn on_disconnect(&self, event: &DisconnectEvent<Uid>, ctx: &Context<Data>) { + let _ = (event, ctx); + } +} diff --git a/src/event/received.rs b/src/event/received.rs new file mode 100644 index 0000000..0ef6d0e --- /dev/null +++ b/src/event/received.rs @@ -0,0 +1,7 @@ +use getset::Getters; + +#[derive(Getters)] +pub struct PacketReceivedEvent<Packet> { + #[getset(get = "pub")] + packet: Packet, +} diff --git a/src/event/sent.rs b/src/event/sent.rs new file mode 100644 index 0000000..5278842 --- /dev/null +++ b/src/event/sent.rs @@ -0,0 +1,7 @@ +use getset::Getters; + +#[derive(Getters)] +pub struct PacketSentEvent<Packet> { + #[getset(get = "pub")] + packet: Packet, +} diff --git a/src/types/prefix/count.rs b/src/types/prefix/count.rs index 0896167..e00c18c 100644 --- a/src/types/prefix/count.rs +++ b/src/types/prefix/count.rs @@ -4,6 +4,7 @@ use getset::Getters; use crate::{ codec::{Codec, decode::Decode, encode::Encode}, + context::Context, types::size::Size, }; @@ -59,16 +60,16 @@ where } } -impl<I, L, D, Ctx> Encode<Ctx> for CountPrefix<I, L, D> +impl<I, L, D, Data> Encode<Data> for CountPrefix<I, L, D> where - I: Codec<Ctx>, - L: Codec<Ctx> + Size + TryFrom<usize>, + I: Codec<Data>, + L: Codec<Data> + Size + TryFrom<usize>, D: IntoIterator<Item = I> + Clone, { fn encode( &self, buffer: &mut dyn std::io::prelude::Write, - ctx: &mut Ctx, + ctx: &Context<Data>, ) -> Result<usize, crate::codec::error::Error> where Self: Sized, @@ -85,13 +86,13 @@ where } } -impl<I, L, D, Ctx> Decode<Ctx> for CountPrefix<I, L, D> +impl<I, L, D, Data> Decode<Data> for CountPrefix<I, L, D> where - I: Codec<Ctx>, - L: Codec<Ctx> + Size, + I: Codec<Data>, + L: Codec<Data> + Size, D: IntoIterator<Item = I> + FromIterator<I>, { - fn decode(reader: &mut dyn Read, ctx: &mut Ctx) -> crate::codec::error::Result<Self> + fn decode(reader: &mut dyn Read, ctx: &Context<Data>) -> crate::codec::error::Result<Self> where Self: Sized, { @@ -106,4 +107,4 @@ where _len: PhantomData, }) } -} +}
\ No newline at end of file diff --git a/src/types/prefix/length.rs b/src/types/prefix/length.rs index 3bb150a..750aa23 100644 --- a/src/types/prefix/length.rs +++ b/src/types/prefix/length.rs @@ -5,6 +5,7 @@ use getset::Getters; use crate::{ DEFAULT_BUFFER_LEN, codec::{self, Codec, decode::Decode, encode::Encode}, + context::Context, types::size::Size, }; @@ -48,12 +49,12 @@ impl<L, D> AsMut<D> for LenPrefixed<L, D> { } } -impl<L, D, Ctx> Encode<Ctx> for LenPrefixed<L, D> +impl<L, D, Data> Encode<Data> for LenPrefixed<L, D> where - L: Codec<Ctx> + Size, - D: Codec<Ctx>, + L: Codec<Data> + Size, + D: Codec<Data>, { - fn encode(&self, writer: &mut dyn Write, ctx: &mut Ctx) -> Result<usize, codec::error::Error> { + fn encode(&self, writer: &mut dyn Write, ctx: &Context<Data>) -> Result<usize, codec::error::Error> { let mut buf = Vec::with_capacity(DEFAULT_BUFFER_LEN); self.data.encode(&mut buf, ctx)?; let len = L::from_size(buf.len()); @@ -63,14 +64,14 @@ where } } -impl<L, D, Ctx> Decode<Ctx> for LenPrefixed<L, D> +impl<L, D, Data> Decode<Data> for LenPrefixed<L, D> where - L: Codec<Ctx> + Size, - D: Codec<Ctx>, + L: Codec<Data> + Size, + D: Codec<Data>, { fn decode( reader: &mut dyn std::io::prelude::Read, - ctx: &mut Ctx, + ctx: &Context<Data>, ) -> crate::codec::error::Result<Self> where Self: Sized, @@ -84,4 +85,4 @@ where _len: PhantomData, }) } -} +}
\ No newline at end of file |
