use bevy::prelude::*;
use bytes::Bytes;
use aerox_network::ConnectionId;
use std::net::SocketAddr;
#[derive(Event, Debug, Clone)]
pub struct ConnectionEstablishedEvent {
pub connection_id: ConnectionId,
pub address: SocketAddr,
pub timestamp: std::time::Instant,
}
#[derive(Event, Debug, Clone)]
pub struct ConnectionClosedEvent {
pub connection_id: ConnectionId,
pub address: SocketAddr,
pub reason: String,
pub duration: std::time::Duration,
}
#[derive(Event, Debug, Clone)]
pub struct MessageReceivedEvent {
pub connection_id: ConnectionId,
pub message_id: u32,
pub sequence_id: u64,
pub payload: Bytes,
pub timestamp: std::time::Instant,
}
#[derive(Event, Debug, Clone)]
pub struct MessageSentEvent {
pub connection_id: ConnectionId,
pub message_id: u32,
pub sequence_id: u64,
pub payload_size: usize,
pub timestamp: std::time::Instant,
}
#[derive(Event, Debug, Clone)]
pub struct MessageSendFailedEvent {
pub connection_id: ConnectionId,
pub message_id: u32,
pub error: String,
pub timestamp: std::time::Instant,
}
#[derive(Event, Debug, Clone)]
pub struct HeartbeatTimeoutEvent {
pub connection_id: ConnectionId,
pub timeout_duration: std::time::Duration,
pub last_activity: std::time::Instant,
}
#[derive(Event, Debug, Clone)]
pub struct ConnectionErrorEvent {
pub connection_id: ConnectionId,
pub error_kind: ConnectionErrorKind,
pub error_message: String,
pub timestamp: std::time::Instant,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum ConnectionErrorKind {
IoError,
ProtocolError,
CodecError,
TimeoutError,
Other,
}
pub type CustomEvent = ();
#[derive(Debug, Clone)]
pub enum NetworkEvent {
Connected(ConnectionEstablishedEvent),
Closed(ConnectionClosedEvent),
MessageReceived(MessageReceivedEvent),
MessageSent(MessageSentEvent),
MessageSendFailed(MessageSendFailedEvent),
HeartbeatTimeout(HeartbeatTimeoutEvent),
Error(ConnectionErrorEvent),
}
impl NetworkEvent {
pub fn connection_id(&self) -> ConnectionId {
match self {
NetworkEvent::Connected(e) => e.connection_id,
NetworkEvent::Closed(e) => e.connection_id,
NetworkEvent::MessageReceived(e) => e.connection_id,
NetworkEvent::MessageSent(e) => e.connection_id,
NetworkEvent::MessageSendFailed(e) => e.connection_id,
NetworkEvent::HeartbeatTimeout(e) => e.connection_id,
NetworkEvent::Error(e) => e.connection_id,
}
}
pub fn as_message_received(&self) -> Option<&MessageReceivedEvent> {
match self {
NetworkEvent::MessageReceived(e) => Some(e),
_ => None,
}
}
pub fn as_connection_established(&self) -> Option<&ConnectionEstablishedEvent> {
match self {
NetworkEvent::Connected(e) => Some(e),
_ => None,
}
}
pub fn as_connection_closed(&self) -> Option<&ConnectionClosedEvent> {
match self {
NetworkEvent::Closed(e) => Some(e),
_ => None,
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_connection_established_event() {
let event = ConnectionEstablishedEvent {
connection_id: ConnectionId::new(1),
address: "127.0.0.1:8080".parse().unwrap(),
timestamp: std::time::Instant::now(),
};
assert_eq!(event.address, "127.0.0.1:8080".parse::<SocketAddr>().unwrap());
}
#[test]
fn test_message_received_event() {
let event = MessageReceivedEvent {
connection_id: ConnectionId::new(1),
message_id: 1,
sequence_id: 100,
payload: Bytes::from("hello"),
timestamp: std::time::Instant::now(),
};
assert_eq!(event.message_id, 1);
assert_eq!(event.sequence_id, 100);
assert_eq!(event.payload, Bytes::from("hello"));
}
#[test]
fn test_network_event_wrapper() {
let msg_event = MessageReceivedEvent {
connection_id: ConnectionId::new(1),
message_id: 1,
sequence_id: 100,
payload: Bytes::from("test"),
timestamp: std::time::Instant::now(),
};
let network_event = NetworkEvent::MessageReceived(msg_event);
assert!(network_event.as_message_received().is_some());
assert!(network_event.as_connection_established().is_none());
}
}