Skip to main content

o_sfu/runtime/http_server/
contract.rs

1//! HTTP control-plane contracts
2//!
3//! Odoo uses these paths and payloads to create rooms, disconnect users and read
4//! runtime stats
5
6use serde::{Deserialize, Serialize};
7
8pub mod route {
9    pub const WEBSOCKET: &str = "/";
10    /// Prometheus scrape endpoint, not a `PromQL` API.
11    /// See [`crate::http::telemetry::metrics`] for queries and examples.
12    pub const METRICS: &str = "/metrics";
13
14    pub mod v1 {
15        pub const NOOP: &str = "/v1/noop";
16        /// Compatibility channel statistics.
17        pub const STATS: &str = "/v1/stats";
18        pub const CHANNEL: &str = "/v1/channel";
19        pub const DISCONNECT: &str = "/v1/disconnect";
20    }
21
22    /// Diagnostics `GET` routes.
23    pub mod diagnostics {
24        /// returns [`crate::http::telemetry::diagnostics::DiagnosticsSummaryResponse`].
25        pub const SUMMARY: &str = "/internal/diagnostics/summary";
26        /// returns a JSON array of
27        /// [`crate::http::telemetry::diagnostics::DiagnosticsRoomSummary`].
28        pub const ROOMS: &str = "/internal/diagnostics/rooms";
29        /// returns a JSON array of
30        /// [`crate::http::telemetry::diagnostics::DiagnosticsWorkerSummary`].
31        pub const WORKERS: &str = "/internal/diagnostics/workers";
32        /// returns [`crate::http::telemetry::diagnostics::DiagnosticsRoomDetail`]
33        /// or `404 Not Found`.
34        pub const ROOM: &str = "/internal/diagnostics/rooms/{uuid}";
35        /// returns a JSON array of
36        /// [`crate::http::telemetry::diagnostics::DiagnosticsUserSummary`] or
37        /// `404 Not Found`.
38        pub const ROOM_USERS: &str = "/internal/diagnostics/rooms/{uuid}/users";
39        /// returns [`crate::http::telemetry::diagnostics::DiagnosticsUserDetail`]
40        /// or `404 Not Found`.
41        pub const ROOM_USER: &str = "/internal/diagnostics/rooms/{uuid}/users/{id}";
42    }
43}
44
45/// noop response payload
46#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
47pub struct NoopResponse {
48    pub result: String,
49}
50
51impl NoopResponse {
52    #[must_use]
53    pub fn ok() -> Self {
54        Self {
55            result: "ok".to_owned(),
56        }
57    }
58}
59
60/// channel creation query parameters
61#[derive(Debug, Clone, Default, PartialEq, Eq, Serialize, Deserialize)]
62pub struct CreateRoomQuery {
63    #[serde(rename = "webRTC", skip_serializing_if = "Option::is_none")]
64    pub web_rtc: Option<bool>,
65    /// compatibility field preserved until persistent recording output lands
66    #[serde(rename = "recordingAddress", skip_serializing_if = "Option::is_none")]
67    pub recording_address: Option<String>,
68}
69
70impl CreateRoomQuery {
71    #[must_use]
72    pub fn web_rtc_enabled(&self) -> bool {
73        self.web_rtc.unwrap_or(true)
74    }
75}
76
77/// created-room response payload
78#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
79pub struct RoomResponse {
80    pub uuid: String,
81    pub url: String,
82}
83
84/// incoming bitrate stats by compatibility stream type
85#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
86#[serde(rename_all = "camelCase")]
87pub struct IncomingBitRateStatsResponse {
88    pub total: u64,
89    pub screen: u64,
90    pub audio: u64,
91    pub camera: u64,
92}
93
94/// active-user stats for one room
95#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
96#[serde(rename_all = "camelCase")]
97pub struct UsersStatsResponse {
98    pub incoming_bit_rate: IncomingBitRateStatsResponse,
99    pub count: u64,
100    pub camera_count: u64,
101    pub screen_count: u64,
102}
103
104/// stats entry for one active room
105#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
106#[serde(rename_all = "camelCase")]
107pub struct RoomStatsResponse {
108    pub create_date: String,
109    pub uuid: String,
110    pub remote_address: String,
111    #[serde(rename = "sessionsStats")]
112    pub users_stats: UsersStatsResponse,
113    pub web_rtc_enabled: bool,
114}
115
116/// stats response payload
117pub type StatsResponse = Vec<RoomStatsResponse>;
118
119#[cfg(test)]
120#[path = "TESTS/contract.rs"]
121mod tests;