char/live.umm.gay

git clone https://git.t4t.associates/char/live.umm.gay

videogame hacker[wish-server-rs] Refactor :)e154831

main
3.6 KiB124 linesraw
1use std::sync::{atomic::Ordering, Arc};
2
3use axum::{
4    extract::State,
5    http::{header, HeaderMap, Method, StatusCode},
6    response::{IntoResponse, Response},
7};
8use miette::{miette, Context, IntoDiagnostic, Result};
9
10use crate::{
11    streams::{get_ongoing_stream, OngoingStream},
12    util::log_http_error,
13    AppState,
14};
15
16use tracing::instrument;
17use webrtc::{
18    api::API as WebRTC,
19    peer_connection::{
20        configuration::RTCConfiguration, peer_connection_state::RTCPeerConnectionState,
21        sdp::session_description::RTCSessionDescription, RTCPeerConnection,
22    },
23};
24
25async fn setup_whep_connection(
26    channel: &str,
27    webrtc: Arc<WebRTC>,
28) -> Result<Arc<RTCPeerConnection>> {
29    let rtc_config = RTCConfiguration::default();
30    let peer_connection = Arc::new(
31        webrtc
32            .new_peer_connection(rtc_config)
33            .await
34            .into_diagnostic()?,
35    );
36
37    let OngoingStream {
38        video_track,
39        audio_track,
40        viewer_count,
41    } = get_ongoing_stream(channel).await?;
42
43    peer_connection.on_peer_connection_state_change(Box::new(move |s: RTCPeerConnectionState| {
44        if s == RTCPeerConnectionState::Connected {
45            viewer_count.fetch_add(1, Ordering::Relaxed);
46        }
47
48        if s == RTCPeerConnectionState::Disconnected {
49            viewer_count.fetch_sub(1, Ordering::Relaxed);
50        }
51
52        Box::pin(async {})
53    }));
54
55    peer_connection
56        .add_track(video_track)
57        .await
58        .into_diagnostic()
59        .wrap_err("Failed to add video track")?;
60
61    peer_connection
62        .add_track(audio_track)
63        .await
64        .into_diagnostic()
65        .wrap_err("Failed to add audio track")?;
66
67    Ok(peer_connection)
68}
69
70#[instrument(skip_all)]
71pub async fn handle_whep(
72    method: Method,
73    headers: HeaderMap,
74    State(app): State<AppState>,
75    offer: String,
76) -> Response {
77    if method != Method::POST {
78        return (StatusCode::METHOD_NOT_ALLOWED, "Please use POST!").into_response();
79    }
80
81    let channel = match headers
82        .get(header::AUTHORIZATION)
83        .ok_or(miette!("Authorization header was not set"))
84        .and_then(|h| {
85            h.to_str()
86                .into_diagnostic()
87                .wrap_err("Authorization header was malformed")
88        }) {
89        Ok(a) => a,
90        Err(e) => return log_http_error(StatusCode::BAD_REQUEST, e),
91    };
92    let channel = channel.strip_prefix("Bearer ").unwrap_or(channel);
93
94    let peer_connection = match setup_whep_connection(channel, app.webrtc).await {
95        Ok(p) => p,
96        Err(e) => return log_http_error(StatusCode::INTERNAL_SERVER_ERROR, e),
97    };
98
99    let Ok(description) = RTCSessionDescription::offer(offer) else { return log_http_error(StatusCode::BAD_REQUEST, "Malformed SDP offer") };
100    if let Err(e) = peer_connection.set_remote_description(description).await {
101        return log_http_error(StatusCode::INTERNAL_SERVER_ERROR, e);
102    };
103
104    let mut gather_complete = peer_connection.gathering_complete_promise().await;
105
106    let answer = match peer_connection.create_answer(None).await {
107        Ok(answer) => answer,
108        Err(e) => return log_http_error(StatusCode::INTERNAL_SERVER_ERROR, e),
109    };
110
111    if let Err(e) = peer_connection.set_local_description(answer).await {
112        return log_http_error(StatusCode::INTERNAL_SERVER_ERROR, e);
113    }
114
115    let _ = gather_complete.recv().await;
116
117    match peer_connection.local_description().await {
118        Some(desc) => (StatusCode::CREATED, desc.sdp).into_response(),
119        None => log_http_error(
120            StatusCode::INTERNAL_SERVER_ERROR,
121            miette!("No local description exists!"),
122        ),
123    }
124}