rustpbx/handler/
handler.rs

1use crate::app::AppState;
2use axum::{
3    extract::{Path, Query, State, WebSocketUpgrade},
4    response::{IntoResponse, Response},
5    routing::{get, post},
6    Json, Router,
7};
8use std::time::Instant;
9use tracing::{error, info};
10use uuid::Uuid;
11
12use super::{
13    call::{handle_call, ActiveCallType, CallParams},
14    middleware::clientip::ClientIp,
15};
16
17pub fn router() -> Router<AppState> {
18    Router::new()
19        .route("/call", get(ws_handler))
20        .route("/call/webrtc", get(webrtc_handler))
21        .route("/call/sip", get(sip_handler))
22        .route("/call/lists", get(list_calls))
23        .route("/call/kill/{id}", post(kill_call))
24        .nest("/llm/v1", super::llmproxy::router())
25        .route("/iceservers", get(super::webrtc::get_iceservers))
26}
27
28async fn list_calls(State(state): State<AppState>) -> Response {
29    let calls = serde_json::json!({
30        "calls": state.active_calls.lock().await.iter().map(|(id, call)| {
31            serde_json::json!({
32                "id": id,
33                "call_type": call.call_type,
34                "created_at": call.created_at.to_rfc3339(),
35                "option": call.option,
36            })
37        }).collect::<Vec<_>>(),
38    });
39    Json(calls).into_response()
40}
41
42async fn kill_call(State(state): State<AppState>, Path(id): Path<String>) -> Response {
43    if let Some(call) = state.active_calls.lock().await.remove(&id) {
44        call.cancel_token.cancel();
45        info!("Call {} killed", id);
46    }
47    Json(true).into_response()
48}
49
50pub async fn ws_handler(
51    client_ip: ClientIp,
52    ws: WebSocketUpgrade,
53    State(state): State<AppState>,
54    Query(params): Query<CallParams>,
55) -> Response {
56    call_handler(client_ip, ActiveCallType::WebSocket, ws, state, params).await
57}
58
59pub async fn sip_handler(
60    client_ip: ClientIp,
61    ws: WebSocketUpgrade,
62    State(state): State<AppState>,
63    Query(params): Query<CallParams>,
64) -> Response {
65    call_handler(client_ip, ActiveCallType::Sip, ws, state, params).await
66}
67
68pub async fn webrtc_handler(
69    client_ip: ClientIp,
70    ws: WebSocketUpgrade,
71    State(state): State<AppState>,
72    Query(params): Query<CallParams>,
73) -> Response {
74    call_handler(client_ip, ActiveCallType::Webrtc, ws, state, params).await
75}
76
77async fn call_handler(
78    client_ip: ClientIp,
79    call_type: ActiveCallType,
80    ws: WebSocketUpgrade,
81    state: AppState,
82    params: CallParams,
83) -> Response {
84    let session_id = params.id.unwrap_or_else(|| Uuid::new_v4().to_string());
85    let state_clone = state.clone();
86    ws.on_upgrade(|socket| async move {
87        let start_time = Instant::now();
88        match handle_call(call_type.clone(), session_id.clone(), socket, state).await {
89            Ok(_) => (),
90            Err(e) => {
91                error!("Error handling connection {client_ip}: {}", e);
92            }
93        }
94        let mut active_calls = state_clone.active_calls.lock().await;
95        match active_calls.remove(&session_id) {
96            Some(call) => {
97                info!(
98                    "{client_ip} call end, duration {}s",
99                    start_time.elapsed().as_secs_f32()
100                );
101                call.cancel_token.cancel();
102            }
103            None => {}
104        }
105    })
106}