1- use crate :: entity:: { ParticipantId , RoomId } ;
2- use crate :: { controller, entity:: ExternalRoomId } ;
1+ use std:: sync:: Arc ;
2+
3+ use crate :: controller;
4+ use crate :: entity:: { ExternalRoomId , ParticipantId , RoomId } ;
35use axum:: {
46 Router ,
5- extract:: { Query , State } ,
6- http:: StatusCode ,
7- response:: { IntoResponse , Response } ,
8- routing:: { delete, post} ,
7+ extract:: { Path , State } ,
8+ http:: { HeaderMap , StatusCode } ,
9+ response:: IntoResponse ,
10+ routing:: { delete, get , post} ,
911} ;
10- use axum_extra:: { TypedHeader , headers :: ContentType } ;
11- use hyper :: HeaderMap ;
12+ use axum_extra:: TypedHeader ;
13+ use axum_extra :: headers :: ContentType ;
1214use hyper:: header:: LOCATION ;
1315
16+ /// Error type for signaling operations
1417#[ derive( thiserror:: Error , Debug ) ]
1518pub enum SignalingError {
1619 #[ error( "join failed: {0}" ) ]
@@ -24,7 +27,7 @@ pub enum SignalingError {
2427}
2528
2629impl IntoResponse for SignalingError {
27- fn into_response ( self ) -> Response {
30+ fn into_response ( self ) -> axum :: response :: Response {
2831 let status = match self {
2932 SignalingError :: JoinError ( controller:: ControllerError :: OfferInvalid ( _) ) => {
3033 StatusCode :: BAD_REQUEST
@@ -48,56 +51,67 @@ impl IntoResponse for SignalingError {
4851 }
4952}
5053
51- #[ derive( serde:: Deserialize , serde:: Serialize , Debug ) ]
52- pub struct ParticipantInfo {
53- room : ExternalRoomId ,
54- }
55-
54+ /// Join a room / create participant
55+ /// POST /api/v1/rooms/{roomId}
5656#[ axum:: debug_handler]
57- async fn spawn_participant (
58- Query ( info ) : Query < ParticipantInfo > ,
57+ async fn join_room (
58+ Path ( room_id ) : Path < ExternalRoomId > ,
5959 State ( con) : State < controller:: ControllerHandle > ,
6060 TypedHeader ( _content_type) : TypedHeader < ContentType > ,
6161 raw_offer : String ,
6262) -> Result < impl IntoResponse , SignalingError > {
63- // TODO: validate content_type = "application/sdp"
64-
65- let room_id = RoomId :: new ( info. room ) ;
63+ let room_id = RoomId :: new ( room_id) ;
64+ let room_id = Arc :: new ( room_id) ;
6665 let participant_id = ParticipantId :: new ( ) ;
67- tracing :: info! ( "allocated {} to {}" , participant_id, room_id ) ;
66+ let participant_id = Arc :: new ( participant_id) ;
6867
69- // TODO: better unique ID to handle session.
70- let location_url = format ! ( "/rooms/{}/participants/{}" , & room_id, & participant_id, ) ;
7168 let ( answer_tx, answer_rx) = tokio:: sync:: oneshot:: channel ( ) ;
7269 con. send_high ( controller:: ControllerMessage :: Allocate (
73- room_id,
74- participant_id,
70+ room_id. clone ( ) ,
71+ participant_id. clone ( ) ,
7572 raw_offer,
7673 answer_tx,
7774 ) )
7875 . await
7976 . map_err ( |_| controller:: ControllerError :: ServiceUnavailable ) ?;
80- let answer = answer_rx
77+ let answer_sdp = answer_rx
8178 . await
8279 . map_err ( |_| controller:: ControllerError :: ServiceUnavailable ) ??;
8380
84- let mut headers = HeaderMap :: new ( ) ;
85- headers. insert ( LOCATION , location_url. parse ( ) . unwrap ( ) ) ;
86- let resp = ( StatusCode :: CREATED , headers, answer) ;
87- Ok ( resp)
81+ let location_url = format ! (
82+ "/api/v1/rooms/{}/participants/{}" ,
83+ & room_id, & participant_id
84+ ) ;
85+ let mut response_headers = HeaderMap :: new ( ) ;
86+ response_headers. insert ( LOCATION , location_url. parse ( ) . unwrap ( ) ) ;
87+ Ok ( ( StatusCode :: CREATED , response_headers, answer_sdp) )
8888}
8989
90+ /// Leave a room / delete participant
91+ /// DELETE /api/v1/rooms/{roomId}/participants/{participantId}
9092#[ axum:: debug_handler]
91- async fn delete_participant (
92- State ( _state) : State < controller:: ControllerHandle > ,
93+ async fn leave_room (
94+ Path ( ( room_id, participant_id) ) : Path < ( ExternalRoomId , ParticipantId ) > ,
95+ State ( _controller) : State < controller:: ControllerHandle > ,
9396) -> Result < impl IntoResponse , SignalingError > {
94- // TODO: delete participant from the room
95- Ok ( StatusCode :: OK )
97+ // TODO: terminate participant session
98+ Ok ( StatusCode :: NO_CONTENT )
99+ }
100+
101+ /// Healthcheck endpoint for Kubernetes
102+ /// GET /healthz
103+ async fn healthcheck ( ) -> impl IntoResponse {
104+ StatusCode :: OK
96105}
97106
107+ /// Router setup
98108pub fn router ( controller : controller:: ControllerHandle ) -> Router {
99109 Router :: new ( )
100- . route ( "/" , post ( spawn_participant) )
101- . route ( "/" , delete ( delete_participant) )
110+ . route ( "/api/v1/rooms/{external_room_id}" , post ( join_room) )
111+ . route (
112+ "/api/v1/rooms/{external_room_id}/participants/{participant_id}" ,
113+ delete ( leave_room) ,
114+ )
115+ . route ( "/healthz" , get ( healthcheck) )
102116 . with_state ( controller)
103117}
0 commit comments