use crate::core::Result;
use crate::endpoint::{EndpointPoll, EngineConfig, MessageId, PeerSlot, ReceiveReport};
#[derive(Clone, Debug, Default, Eq, PartialEq)]
pub struct PassiveEndpoint {
peer: PeerSlot,
}
impl PassiveEndpoint {
#[must_use]
pub const fn new(config: EngineConfig) -> Self {
Self {
peer: PeerSlot::new(config),
}
}
#[must_use]
pub const fn peer(&self) -> &PeerSlot {
&self.peer
}
pub fn peer_mut(&mut self) -> &mut PeerSlot {
&mut self.peer
}
pub fn disconnect(&mut self) {
self.peer.disconnect();
}
pub fn send(&mut self, message: &[u8]) -> Result<Option<MessageId>> {
self.peer.send(message)
}
pub fn receive(&mut self, now_ms: u64, bytes: &[u8]) -> ReceiveReport {
self.peer.accept_passive_if_needed(now_ms);
self.peer.receive(now_ms, bytes)
}
pub fn poll<'a>(&mut self, now_ms: u64, tx_buf: &'a mut [u8]) -> Result<EndpointPoll<'a>> {
self.peer.poll(now_ms, tx_buf)
}
pub fn disconnect_if_idle(&mut self, now_ms: u64, timeout_ms: u64) -> bool {
self.peer.disconnect_if_idle(now_ms, timeout_ms)
}
}
#[cfg(test)]
mod tests {
use crate::endpoint::{ClientEndpoint, EndpointPoll, PeerState};
use super::PassiveEndpoint;
#[test]
fn passive_endpoint_starts_without_engine_and_accepts_first_peer_bytes() {
let mut host = ClientEndpoint::default();
let mut passive = PassiveEndpoint::default();
let mut host_tx = [0; 128];
let mut passive_tx = [0; 128];
assert!(!passive.peer().has_session());
host.connect(1).unwrap();
let EndpointPoll::Transmit {
bytes: hello_bytes, ..
} = host.poll(1, &mut host_tx).unwrap()
else {
panic!("host should transmit hello");
};
passive.receive(2, hello_bytes);
assert!(passive.peer().has_session());
assert_eq!(passive.peer().state(), PeerState::Connected);
let EndpointPoll::Transmit {
bytes: ack_bytes, ..
} = passive.poll(2, &mut passive_tx).unwrap()
else {
panic!("passive endpoint should transmit ack");
};
host.receive(3, ack_bytes);
assert_eq!(host.peer().state(), PeerState::Connected);
}
#[test]
fn passive_disconnect_drops_engine_until_next_receive() {
let mut passive = PassiveEndpoint::default();
passive.receive(1, &[]);
assert!(passive.peer().has_session());
passive.disconnect();
assert!(!passive.peer().has_session());
assert_eq!(passive.peer().state(), PeerState::Disconnected);
}
}