rustpbx/handler/
handler.rs1use 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}