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        /// returns a JSON object with `nodes` and `edges` arrays or `404 Not Found`.
43        pub const ROOM_GRAPH: &str = "/internal/diagnostics/node-graph/rooms/{uuid}";
44        /// returns a JSON object with `nodes` and `edges` arrays or `404 Not Found`.
45        pub const USER_GRAPH: &str = "/internal/diagnostics/node-graph/rooms/{uuid}/users/{id}";
46    }
47}
48
49/// noop response payload
50#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
51pub struct NoopResponse {
52    pub result: String,
53}
54
55impl NoopResponse {
56    #[must_use]
57    pub fn ok() -> Self {
58        Self {
59            result: "ok".to_owned(),
60        }
61    }
62}
63
64/// channel creation query parameters
65#[derive(Debug, Clone, Default, PartialEq, Eq, Serialize, Deserialize)]
66pub struct CreateRoomQuery {
67    #[serde(rename = "webRTC", skip_serializing_if = "Option::is_none")]
68    pub web_rtc: Option<bool>,
69    /// compatibility field preserved until persistent recording output lands
70    #[serde(rename = "recordingAddress", skip_serializing_if = "Option::is_none")]
71    pub recording_address: Option<String>,
72}
73
74impl CreateRoomQuery {
75    #[must_use]
76    pub fn web_rtc_enabled(&self) -> bool {
77        self.web_rtc.unwrap_or(true)
78    }
79}
80
81/// created-room response payload
82#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
83pub struct RoomResponse {
84    pub uuid: String,
85    pub url: String,
86}
87
88/// incoming bitrate stats by compatibility stream type
89#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
90#[serde(rename_all = "camelCase")]
91pub struct IncomingBitRateStatsResponse {
92    pub total: u64,
93    pub screen: u64,
94    pub audio: u64,
95    pub camera: u64,
96}
97
98/// active-user stats for one room
99#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
100#[serde(rename_all = "camelCase")]
101pub struct UsersStatsResponse {
102    pub incoming_bit_rate: IncomingBitRateStatsResponse,
103    pub count: u64,
104    pub camera_count: u64,
105    pub screen_count: u64,
106}
107
108/// stats entry for one active room
109#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
110#[serde(rename_all = "camelCase")]
111pub struct RoomStatsResponse {
112    pub create_date: String,
113    pub uuid: String,
114    pub remote_address: String,
115    #[serde(rename = "sessionsStats")]
116    pub users_stats: UsersStatsResponse,
117    pub web_rtc_enabled: bool,
118}
119
120/// stats response payload
121pub type StatsResponse = Vec<RoomStatsResponse>;
122
123#[cfg(test)]
124#[path = "TESTS/contract.rs"]
125mod tests;