Session

Struct Session 

Source
pub struct Session<P: Protocol, S: ClientState> { /* private fields */ }
Expand description

A typed reflector session.

P is the protocol marker (DPlus, super::DExtra, super::Dcs). S is the connection state marker (Configured, Connecting, etc.). Methods are gated by impl blocks on specific Session<P, S> shapes — calling send_voice on a Session<P, Configured> is a compile error, not a runtime error.

The Session<P, S> is a thin wrapper over SessionCore (the protocol-erased state machine). The phantom types add zero runtime cost — the entire typestate machinery compiles away.

Implementations§

Source§

impl<P: Protocol> Session<P, Configured>

Source

pub const fn builder() -> SessionBuilder<P, Missing, Missing, Missing, Missing>

Entry point for building a typed Session<P, Configured>.

Returns a builder with every required field marked Missing. Chain .callsign(), .local_module(), .reflector_module(), and .peer() in any order, then call .build(). Skipping any of the four setters turns the .build() call into a compile error.

§Example
use dstar_gateway_core::session::client::{Configured, DExtra, Session};
use dstar_gateway_core::types::{Callsign, Module};

let session: Session<DExtra, Configured> =
    Session::<DExtra, Configured>::builder()
        .callsign(Callsign::try_from_str("W1AW")?)
        .local_module(Module::try_from_char('B')?)
        .reflector_module(Module::try_from_char('C')?)
        .peer("127.0.0.1:30001".parse()?)
        .build();
Source§

impl<P: Protocol, S: ClientState> Session<P, S>

Source

pub const fn state_kind(&self) -> ClientStateKind

Runtime discriminator for the current state.

Source

pub const fn peer(&self) -> SocketAddr

The reflector address this session was built to talk to.

Source

pub const fn local_callsign(&self) -> Callsign

The local station callsign.

Source

pub fn diagnostics(&mut self) -> Vec<Diagnostic>

Drain accumulated diagnostics, if any.

Returns a Vec (not an iterator) because the underlying sink lives inside the session; returning a borrowed iterator would force the caller to hold a &mut Session for the lifetime of the iterator. Most consumers call this periodically and process the batch.

Source§

impl<P: Protocol + NoAuthRequired> Session<P, Configured>

Source

pub fn connect( self, now: Instant, ) -> Result<Session<P, Connecting>, Failed<Self, Error>>

Send the LINK/connect packet and transition to Connecting.

§Errors

Returns the original session in the error position if the state machine refuses the transition (e.g., codec encoder failure). This lets the caller retry without rebuilding.

Source§

impl Session<DPlus, Configured>

Source

pub fn authenticate( self, hosts: HostList, ) -> Result<Session<DPlus, Authenticated>, Failed<Self, Error>>

Mark the session as authenticated using a previously-fetched host list.

The actual TCP auth happens in the shell crate — the sans-io core takes the resulting HostList here as input.

§Errors

Returns the original session in the error position if the state machine rejects the host list attachment.

Source§

impl Session<DPlus, Authenticated>

Source

pub fn connect( self, now: Instant, ) -> Result<Session<DPlus, Connecting>, Failed<Self, Error>>

Send LINK1 and transition to Connecting.

§Errors

Returns the original session in the error position if the state machine refuses the transition.

Source

pub fn host_list(&self) -> &HostList

Get the cached host list from the TCP auth step.

The Authenticated state is entered only after SessionCore::attach_host_list succeeds, so the host list is always present here. A None would indicate a bug in SessionCore; we fall back to a module-level empty sentinel rather than panic so lib code stays expect_used-clean.

Source§

impl<P: Protocol> Session<P, Connecting>

Source

pub fn promote(self) -> Result<Session<P, Connected>, Failed<Self, Error>>

Promote a session that has reached Connected state.

The shell calls this after observing Event::Connected from the event stream. promote only succeeds if the core is already in ClientStateKind::Connected; any other state returns a Failed with a StateError::WrongState error. If the session was rejected mid-handshake the caller should inspect the failed session’s Session::state_kind — it may already be in ClientStateKind::Closed.

§Errors

Returns Err(Failed) if the session is not yet in ClientStateKind::Connected. The session field of the Failed carries the unchanged Session<P, Connecting>.

Source§

impl<P: Protocol> Session<P, Connected>

Source

pub fn disconnect( self, now: Instant, ) -> Result<Session<P, Disconnecting>, Failed<Self, Error>>

Initiate a graceful disconnect.

Enqueues the UNLINK packet and transitions to Disconnecting. The caller must continue to drive the Driver loop (polling poll_transmit / poll_event) until either the UNLINK ACK arrives (emitting Event::Disconnected with super::DisconnectReason::UnlinkAcked) or the disconnect deadline expires (emitting Event::Disconnected with super::DisconnectReason::DisconnectTimeout).

§Errors

Returns the original session in the error position if the state machine refuses the transition (e.g., codec encoder failure).

Source

pub fn disconnect_in_place(&mut self, now: Instant) -> Result<(), Error>

Enqueue an UNLINK packet without consuming the session.

Used by the tokio shell’s SessionLoop to trigger a disconnect from within the event loop, where consuming self isn’t possible. After this returns, the internal state machine has transitioned to Disconnecting, but the typestate parameter on this handle is still Connected. The caller should exit the event loop and construct a Session<P, Disconnecting> or wait for the internal state to reach Closed.

§Errors

Returns Error if the core’s SessionCore::enqueue_disconnect call fails (e.g., the codec encoder rejects the UNLINK packet).

Source

pub fn send_header( &mut self, now: Instant, header: &DStarHeader, stream_id: StreamId, ) -> Result<(), Error>

Send a voice header and start a new outbound voice stream.

The header is cached internally; subsequent Self::send_voice / Self::send_eot calls will reference it (DCS embeds the full header in every voice frame, so the cache is mandatory there).

This method takes &mut self, NOT self — voice TX does not change the typestate. The session stays in Connected until disconnect or a timeout closes it.

§Errors

Returns Error::Protocol if the codec encoder fails.

Source

pub fn send_voice( &mut self, now: Instant, stream_id: StreamId, seq: u8, frame: &VoiceFrame, ) -> Result<(), Error>

Send a voice data frame.

This method takes &mut self, NOT self.

§Errors

Returns Error::Protocol if the codec encoder fails. On DCS, returns Error::Protocol with crate::error::DcsError::NoTxHeader if Self::send_header has not been called first.

Source

pub fn send_eot( &mut self, now: Instant, stream_id: StreamId, seq: u8, ) -> Result<(), Error>

Send a voice EOT packet, ending the outbound stream.

This method takes &mut self, NOT self. The session stays in Connected after EOT — the caller may begin a new stream by calling Self::send_header again.

§Errors

Returns Error::Protocol if the codec encoder fails. On DCS, returns Error::Protocol with crate::error::DcsError::NoTxHeader if Self::send_header has not been called first.

Source§

impl<P: Protocol> Session<P, Disconnecting>

Source

pub fn promote(self) -> Result<Session<P, Closed>, Failed<Self, Error>>

Promote to Closed once the UNLINK ACK arrives or the deadline fires.

Same pattern as Session::<P, Connecting>::promote. The shell watches for Event::Disconnected and then calls this.

§Errors

Returns Err(Failed) if the session is not yet in ClientStateKind::Closed (the disconnect ACK hasn’t arrived yet).

Trait Implementations§

Source§

impl<P: Debug + Protocol, S: Debug + ClientState> Debug for Session<P, S>

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl<P: Protocol, S: ClientState> Driver for Session<P, S>

Source§

type Event = Event<P>

Consumer-visible event type.
Source§

type Error = Error

Per-protocol structured error type.
Source§

fn handle_input( &mut self, now: Instant, peer: SocketAddr, bytes: &[u8], ) -> Result<(), Self::Error>

Feed an inbound datagram. Parses, advances state, may push events / outbound packets / timer updates. Read more
Source§

fn handle_timeout(&mut self, now: Instant)

Tell the core that wall time has advanced.
Source§

fn poll_transmit(&mut self, now: Instant) -> Option<Transmit<'_>>

Pop the next outbound datagram, if any.
Source§

fn poll_event(&mut self) -> Option<Self::Event>

Pop the next consumer-visible event.
Source§

fn poll_timeout(&self) -> Option<Instant>

Earliest instant at which the core needs to be re-entered. Read more

Auto Trait Implementations§

§

impl<P, S> Freeze for Session<P, S>

§

impl<P, S> RefUnwindSafe for Session<P, S>

§

impl<P, S> Send for Session<P, S>
where S: Send,

§

impl<P, S> Sync for Session<P, S>
where S: Sync,

§

impl<P, S> Unpin for Session<P, S>
where P: Unpin, S: Unpin,

§

impl<P, S> UnwindSafe for Session<P, S>
where P: UnwindSafe, S: UnwindSafe,

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

§

impl<T> Instrument for T

§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided [Span], returning an Instrumented wrapper. Read more
§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
§

impl<T> WithSubscriber for T

§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a [WithDispatch] wrapper. Read more
§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a [WithDispatch] wrapper. Read more