ProtocolEndpoint

Struct ProtocolEndpoint 

Source
pub struct ProtocolEndpoint<P: Protocol> { /* private fields */ }
Expand description

Per-protocol reflector endpoint.

Owns the client pool, the per-module stream cache, and the authorizer used to admit LINK attempts for one reflector protocol. Supports all three D-STAR reflector protocols (DExtra, DPlus, DCS); the endpoint’s default reflector module is used as the fallback for DPlus sessions (which don’t carry a module on the wire) and as the seed for DExtra/DCS sessions before the LINK packet overwrites it.

Implementations§

Source§

impl<P: Protocol> ProtocolEndpoint<P>

Source

pub fn new( protocol: ProtocolKind, default_reflector_module: Module, authorizer: Arc<dyn ClientAuthorizer>, ) -> Self

Construct a new endpoint for the given protocol with the supplied authorizer.

default_reflector_module is passed to every [ServerSessionCore] created on this endpoint; DExtra and DCS sessions overwrite their client_module from the LINK packet but DPlus sessions keep the default because the DPlus LINK2 wire packet doesn’t carry a module.

The authorizer is consulted on every inbound LINK attempt; rejected attempts never materialize a ClientHandle and instead produce a protocol-appropriate NAK plus a [ServerEvent::ClientRejected] event.

Source

pub fn new_with_voice_bus( protocol: ProtocolKind, default_reflector_module: Module, authorizer: Arc<dyn ClientAuthorizer>, voice_bus: Option<Sender<CrossProtocolEvent>>, ) -> Self

Construct a new endpoint with an optional cross-protocol voice bus.

Identical to Self::new except the caller supplies a [broadcast::Sender<CrossProtocolEvent>] clone; when Some, the endpoint publishes inbound voice events to the bus so other protocols’ endpoints can transcode and re-broadcast.

Used by crate::reflector::Reflector when its config has cross_protocol_forwarding = true. Pass None to disable cross-protocol participation on this endpoint.

Source

pub const fn protocol_kind(&self) -> ProtocolKind

Runtime protocol discriminator for this endpoint.

Source

pub const fn clients(&self) -> &ClientPool<P>

Access the endpoint’s client pool (primarily for tests).

Source

pub async fn handle_inbound( &self, bytes: &[u8], peer: SocketAddr, now: Instant, ) -> Result<EndpointOutcome<P>, ShellError>

Feed one inbound datagram into the endpoint.

Dispatches to the protocol-specific handler based on Self::protocol_kind. Each handler pre-decodes the inbound packet, consults the authorizer on LINK attempts, gates voice-stream ingress on AccessPolicy, drives the core via the private drive_core helper, then updates the per-module stream cache and drains pending background events into the outcome.

§Errors

Returns ShellError::Core if the core rejects the input (parse failure, wrong-state, etc.). Returns ShellError::Protocol if the endpoint was constructed with a [ProtocolKind] the shell does not recognize.

§Cancellation safety

This method is not cancel-safe. It takes multiple ClientPool locks in sequence (containsinsertset_modulerecord_last_heard) and cancellation between any two awaits can leave the pool in a half-updated state where a session has been created but not yet attached to its module in the reverse index. The reflector’s run loop is the only expected caller and it never cancels this future except via shutdown.

Source

pub async fn run( self: Arc<Self>, socket: Arc<UdpSocket>, shutdown: Receiver<bool>, ) -> Result<(), ShellError>

Bind-less run loop that owns a pre-bound [UdpSocket].

Each iteration reads one datagram, feeds it to Self::handle_inbound, writes outbound responses back to their destination peer, and finally fans voice frames out to every other peer on the same module.

Returns when shutdown transitions to true, or when an unrecoverable I/O error occurs.

§Errors

Returns ShellError::Io if the socket errors during a recv_from. Send-side failures are logged and the offending peer is marked unhealthy; they do not terminate the loop.

§Cancellation safety

Dropping this future is the intended shutdown mechanism for an endpoint task — the enclosing [tokio::task::JoinSet] in crate::reflector::Reflector::run will abort the task when the shutdown watch channel fires, which drops the run future cleanly. Any in-progress handle_inbound call for a single datagram will be abandoned mid-lock-sequence, which is acceptable during shutdown because the entire ClientPool is about to be dropped with it. Do not race run() against another future with tokio::select! while the endpoint is expected to remain operational.

Trait Implementations§

Source§

impl<P: Protocol> Debug for ProtocolEndpoint<P>

Source§

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

Formats the value using the given formatter. Read more

Auto Trait Implementations§

§

impl<P> !Freeze for ProtocolEndpoint<P>

§

impl<P> !RefUnwindSafe for ProtocolEndpoint<P>

§

impl<P> Send for ProtocolEndpoint<P>

§

impl<P> Sync for ProtocolEndpoint<P>

§

impl<P> Unpin for ProtocolEndpoint<P>
where P: Unpin,

§

impl<P> !UnwindSafe for ProtocolEndpoint<P>

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