arcly-stream 0.1.1

A high-performance live-media streaming kernel: lock-free zero-copy frame fan-out, instant-start GOP cache, pluggable HLS/recording, and trait-driven protocol/storage/auth/observer extension points — runtime, config, and metrics free.
Documentation
//! Stream-level authentication and authorization.
//!
//! Like [`Observer`](crate::Observer), authorization is an **injected trait with
//! a permit-all default** — the engine never bakes in an identity scheme. A host
//! supplies a [`StreamAuthenticator`] (validating stream keys, signed tokens,
//! IP allow-lists, an external auth service, …) and the engine enforces it on
//! the publish and play paths.
//!
//! ```no_run
//! use arcly_stream::auth::{Credentials, StreamAuthenticator};
//! use arcly_stream::prelude::*;
//! use std::sync::Arc;
//!
//! struct KeyAuth { secret: String }
//!
//! #[async_trait]
//! impl StreamAuthenticator for KeyAuth {
//!     async fn authorize_publish(&self, _key: &StreamKey, creds: &Credentials) -> Result<()> {
//!         match creds.token.as_deref() {
//!             Some(t) if t == self.secret => Ok(()),
//!             _ => Err(StreamError::Unauthorized("bad publish key".into())),
//!         }
//!     }
//! }
//!
//! let engine = Engine::builder()
//!     .application(AppSpec::new("live"))
//!     .authenticator(KeyAuth { secret: "s3cr3t".into() })
//!     .build();
//! # let _ = engine;
//! ```

use crate::{Result, StreamKey};
use async_trait::async_trait;
use std::net::SocketAddr;

/// Credentials presented by a connecting publisher or player.
///
/// Protocol handlers populate whichever fields their transport carries (an RTMP
/// stream key in `token`, a WHIP bearer in `token`, the peer address in `addr`,
/// query parameters in `params`).
#[derive(Debug, Default, Clone)]
pub struct Credentials {
    /// Opaque secret: a stream key, signed URL token, or bearer credential.
    pub token: Option<String>,
    /// Remote peer address, when the transport exposes one.
    pub addr: Option<SocketAddr>,
    /// Arbitrary protocol-supplied key/value parameters (e.g. query string).
    pub params: Vec<(String, String)>,
}

impl Credentials {
    /// Credentials carrying only a token (the common stream-key case).
    pub fn token(token: impl Into<String>) -> Self {
        Self {
            token: Some(token.into()),
            ..Self::default()
        }
    }

    /// Look up a protocol parameter by key.
    pub fn param(&self, key: &str) -> Option<&str> {
        self.params
            .iter()
            .find(|(k, _)| k == key)
            .map(|(_, v)| v.as_str())
    }
}

/// Authorizes publish and play attempts. Both methods **default to permit**, so
/// an implementor overrides only the side it gates.
#[async_trait]
pub trait StreamAuthenticator: Send + Sync + 'static {
    /// Decide whether `creds` may publish to `key`. Return
    /// [`StreamError::Unauthorized`](crate::StreamError::Unauthorized) to reject.
    async fn authorize_publish(&self, _key: &StreamKey, _creds: &Credentials) -> Result<()> {
        Ok(())
    }

    /// Decide whether `creds` may subscribe to `key`.
    async fn authorize_play(&self, _key: &StreamKey, _creds: &Credentials) -> Result<()> {
        Ok(())
    }
}

/// The default authenticator: permits everything. Selected when the builder is
/// given none, preserving the engine's zero-policy default.
#[derive(Debug, Default, Clone, Copy)]
pub struct AllowAll;

impl StreamAuthenticator for AllowAll {}