dstar_gateway_core/session/driver.rs
1//! Sans-io `Driver` trait.
2
3use std::net::SocketAddr;
4use std::time::Instant;
5
6/// One outbound datagram from the sans-io core.
7#[derive(Debug, Clone)]
8pub struct Transmit<'a> {
9 /// Destination address.
10 pub dst: SocketAddr,
11 /// Wire bytes (borrowed from the session's internal scratch buffer).
12 pub payload: &'a [u8],
13}
14
15impl<'a> Transmit<'a> {
16 /// Construct a transmit from a destination + borrowed payload.
17 #[must_use]
18 pub const fn new(dst: SocketAddr, payload: &'a [u8]) -> Self {
19 Self { dst, payload }
20 }
21}
22
23/// Sans-io driver. Mirrors `quinn-proto::Connection` and
24/// `rustls::Connection`.
25///
26/// The shell calls these methods in a loop. The core never calls
27/// back into the shell. **Time is injected via the `now: Instant`
28/// parameter on every call** — implementors of this trait must NOT
29/// consult `Instant::now()` themselves.
30pub trait Driver {
31 /// Consumer-visible event type.
32 type Event;
33 /// Per-protocol structured error type.
34 type Error;
35
36 /// Feed an inbound datagram. Parses, advances state, may push
37 /// events / outbound packets / timer updates.
38 ///
39 /// # Errors
40 ///
41 /// Returns the protocol-specific error if the bytes cannot be
42 /// parsed.
43 fn handle_input(
44 &mut self,
45 now: Instant,
46 peer: SocketAddr,
47 bytes: &[u8],
48 ) -> Result<(), Self::Error>;
49
50 /// Tell the core that wall time has advanced.
51 fn handle_timeout(&mut self, now: Instant);
52
53 /// Pop the next outbound datagram, if any.
54 fn poll_transmit(&mut self, now: Instant) -> Option<Transmit<'_>>;
55
56 /// Pop the next consumer-visible event.
57 fn poll_event(&mut self) -> Option<Self::Event>;
58
59 /// Earliest instant at which the core needs to be re-entered.
60 ///
61 /// `None` means "no pending timer — only wake me on input".
62 fn poll_timeout(&self) -> Option<Instant>;
63}
64
65#[cfg(test)]
66mod tests {
67 use super::*;
68 use std::net::{IpAddr, Ipv4Addr};
69
70 const ADDR: SocketAddr = SocketAddr::new(IpAddr::V4(Ipv4Addr::LOCALHOST), 30001);
71
72 #[test]
73 fn transmit_new_constructs() {
74 let payload: &[u8] = &[0x05, 0x00, 0x18, 0x00, 0x01];
75 let tx = Transmit::new(ADDR, payload);
76 assert_eq!(tx.dst, ADDR);
77 assert_eq!(tx.payload, payload);
78 }
79}