pub struct SessionCore { /* private fields */ }Expand description
Protocol-erased session core.
Holds all mutable state for one reflector session. The typestate
Session<P, S> wrapper forwards most calls straight through; the
core does not itself enforce state transitions at compile time —
that discipline is the wrapper’s job.
Implementations§
Source§impl SessionCore
impl SessionCore
Sourcepub fn new(
kind: ProtocolKind,
callsign: Callsign,
local_module: Module,
reflector_module: Module,
peer: SocketAddr,
) -> Self
pub fn new( kind: ProtocolKind, callsign: Callsign, local_module: Module, reflector_module: Module, peer: SocketAddr, ) -> Self
Build a new SessionCore in ClientStateKind::Configured.
The session has no host list, no pending packets, and no
active timers. The typestate builder (super::SessionBuilder)
wraps this constructor and enforces per-protocol state-transition
rules.
Sourcepub fn new_with_reflector_callsign(
kind: ProtocolKind,
callsign: Callsign,
local_module: Module,
reflector_module: Module,
peer: SocketAddr,
reflector_callsign: Option<Callsign>,
) -> Self
pub fn new_with_reflector_callsign( kind: ProtocolKind, callsign: Callsign, local_module: Module, reflector_module: Module, peer: SocketAddr, reflector_callsign: Option<Callsign>, ) -> Self
Build a new SessionCore with an explicit reflector
callsign.
Required for DCS sessions that target a non-DCS001
reflector — the DCS codec embeds the reflector callsign in
every LINK/UNLINK/POLL packet, and the default fallback is
DCS001 . Optional for DPlus and DExtra, which do not
carry the reflector callsign on the wire.
Emits a tracing::warn! at construction time if the
protocol is DCS and reflector_callsign is None, so
operators can see why connections to non-DCS001 reflectors
fail without the real callsign.
Sourcepub fn drain_diagnostics(&mut self) -> Vec<Diagnostic>
pub fn drain_diagnostics(&mut self) -> Vec<Diagnostic>
Drain accumulated parser diagnostics.
Returns everything the internal VecSink has captured since
the previous drain (or since construction). The sink is empty
on return. Called by Session::diagnostics() from the
typestate wrapper.
Sourcepub const fn state_kind(&self) -> ClientStateKind
pub const fn state_kind(&self) -> ClientStateKind
Current runtime state.
Sourcepub const fn peer(&self) -> SocketAddr
pub const fn peer(&self) -> SocketAddr
Peer address of the reflector.
Sourcepub const fn local_module(&self) -> Module
pub const fn local_module(&self) -> Module
Client local module letter.
Sourcepub const fn reflector_module(&self) -> Module
pub const fn reflector_module(&self) -> Module
Reflector module letter.
Sourcepub const fn protocol_kind(&self) -> ProtocolKind
pub const fn protocol_kind(&self) -> ProtocolKind
Runtime protocol discriminator.
Sourcepub const fn host_list(&self) -> Option<&HostList>
pub const fn host_list(&self) -> Option<&HostList>
Cached DPlus host list (None unless authenticated).
Sourcepub fn attach_host_list(&mut self, list: HostList) -> Result<(), Error>
pub fn attach_host_list(&mut self, list: HostList) -> Result<(), Error>
Attach a DPlus host list, transitioning the session from
ClientStateKind::Configured to
ClientStateKind::Authenticated.
Only valid for DPlus sessions. The host list is what the
dstar-gateway shell would obtain from the
auth.dstargateway.org TCP handshake; the core does not
itself perform any I/O.
§Errors
Returns StateError::WrongState if the session is not a
DPlus session or is not in ClientStateKind::Configured.
The typestate wrapper prevents both cases at compile time —
this runtime check is the residual safety net for direct
SessionCore users (tests + the protocol-erased fallback path).
Sourcepub fn enqueue_connect(&mut self, now: Instant) -> Result<(), Error>
pub fn enqueue_connect(&mut self, now: Instant) -> Result<(), Error>
Enqueue the protocol-appropriate LINK packet and transition
the session to ClientStateKind::Connecting.
§Errors
Returns Error::Protocol if a codec encoder reports a
buffer-too-small (should never happen — the scratch
buffers in this core are oversized for every known packet).
Sourcepub fn enqueue_disconnect(&mut self, now: Instant) -> Result<(), Error>
pub fn enqueue_disconnect(&mut self, now: Instant) -> Result<(), Error>
Enqueue the protocol-appropriate UNLINK packet and transition
the session to ClientStateKind::Disconnecting.
§Errors
Returns Error::Protocol if a codec encoder fails.
Sourcepub fn enqueue_send_header(
&mut self,
now: Instant,
header: &DStarHeader,
stream_id: StreamId,
) -> Result<(), Error>
pub fn enqueue_send_header( &mut self, now: Instant, header: &DStarHeader, stream_id: StreamId, ) -> Result<(), Error>
Enqueue a voice header packet for transmission.
Caches the header internally so subsequent
Self::enqueue_send_voice and Self::enqueue_send_eot
calls can use it (required by DCS, which embeds the full
header in every voice frame).
For DCS, the protocol does NOT have a separate header packet
— the first frame (seq=0) carries the embedded header. This
method emits a synthetic silence frame at seq=0 to start the
stream and matches the legacy
crate-internal behavior.
§Errors
Returns Error::State with StateError::WrongState if
the session is not in ClientStateKind::Connected. The
typestate wrapper prevents this at compile time, but the runtime
check is the residual safety net for direct SessionCore users.
Returns Error::Protocol if the codec encoder fails
(buffer too small, etc.).
Sourcepub fn enqueue_send_voice(
&mut self,
now: Instant,
stream_id: StreamId,
seq: u8,
frame: &VoiceFrame,
) -> Result<(), Error>
pub fn enqueue_send_voice( &mut self, now: Instant, stream_id: StreamId, seq: u8, frame: &VoiceFrame, ) -> Result<(), Error>
Enqueue a voice data frame for transmission.
On DCS, the cached header from Self::enqueue_send_header
is required — DCS embeds the full header in every voice frame.
On DPlus and DExtra, the cache is consulted but not
strictly required for voice data.
§Errors
Returns Error::State with StateError::WrongState if
the session is not in ClientStateKind::Connected.
Returns Error::Protocol with
ProtocolError::Dcs
if called on a DCS session before Self::enqueue_send_header
has cached a TX header.
Returns Error::Protocol if the codec encoder fails.
Sourcepub fn enqueue_send_eot(
&mut self,
now: Instant,
stream_id: StreamId,
seq: u8,
) -> Result<(), Error>
pub fn enqueue_send_eot( &mut self, now: Instant, stream_id: StreamId, seq: u8, ) -> Result<(), Error>
Enqueue a voice EOT packet for transmission.
On DCS, the cached header from Self::enqueue_send_header
is required — DCS embeds the full header in every voice frame
(including the EOT). On DPlus and DExtra, the cache is not
consulted.
§Errors
Returns Error::State with StateError::WrongState if
the session is not in ClientStateKind::Connected.
Returns Error::Protocol with
ProtocolError::Dcs
if called on a DCS session before Self::enqueue_send_header
has cached a TX header.
Returns Error::Protocol if the codec encoder fails.
Sourcepub fn handle_input(
&mut self,
now: Instant,
peer: SocketAddr,
bytes: &[u8],
) -> Result<(), Error>
pub fn handle_input( &mut self, now: Instant, peer: SocketAddr, bytes: &[u8], ) -> Result<(), Error>
Feed an inbound UDP datagram.
Parses the bytes, updates state, pushes events and outbound
packets as needed. Protocol-erased dispatch: matches on
Self::protocol_kind and calls the appropriate codec.
The peer argument is the source address of the datagram.
The typestate wrapper filters out datagrams whose source does
not match the expected reflector; the core accepts whatever
the shell passes it.
§Errors
Returns Error::Protocol wrapping the codec error if the
datagram cannot be parsed.
Sourcepub fn handle_timeout(&mut self, now: Instant)
pub fn handle_timeout(&mut self, now: Instant)
Advance the session timers using now as the current
instant.
Checks each named timer:
keepaliveexpired → enqueue poll packet, re-armkeepalive_inactivityexpired → transition to Closed, emitEvent::Disconnectedwith reasonDisconnectReason::KeepaliveInactivitydisconnect_deadlineexpired (in Disconnecting) → transition to Closed, emitEvent::Disconnectedwith reasonDisconnectReason::DisconnectTimeout
Sourcepub fn pop_transmit(&mut self, now: Instant) -> Option<Transmit<'_>>
pub fn pop_transmit(&mut self, now: Instant) -> Option<Transmit<'_>>
Pop the next outbound datagram, if any.
The returned Transmit borrows from self.current_tx,
which holds the most-recently-popped packet until the next
call replaces it. Callers must consume the borrow before
calling this method again.
Sourcepub fn pop_event<P: Protocol>(&mut self) -> Option<Event<P>>
pub fn pop_event<P: Protocol>(&mut self) -> Option<Event<P>>
Pop the next consumer-visible event.
The P type parameter re-attaches the protocol phantom at
drain time — the event queue itself is protocol-erased.
Sourcepub fn next_deadline(&self) -> Option<Instant>
pub fn next_deadline(&self) -> Option<Instant>
Earliest instant at which this core wants to be woken up.
Combines the outbox’s next release instant with the timer wheel’s next deadline.