From b830abe3f49e0ed04ef360d388f8f0a5bb744806 Mon Sep 17 00:00:00 2001 From: Nell Date: Wed, 23 Sep 2026 19:05:09 +0200 Subject: [PATCH] add event_bus_typed --- frontend/src/stores/app.ts | 2 +- frontend/vite.config.mts | 6 ++++-- src/rtc/README.md | 36 +++++++++++++++++++++++++++++------- 3 files changed, 34 insertions(+), 10 deletions(-) diff --git a/frontend/src/stores/app.ts b/frontend/src/stores/app.ts index 86cf865..71be497 100644 --- a/frontend/src/stores/app.ts +++ b/frontend/src/stores/app.ts @@ -2,6 +2,6 @@ import {defineStore} from 'pinia' export const useAppStore = defineStore('app', { state: () => ({ - baseurl: 'http://localhost:8080', + baseurl: 'http://goesseau.eu:8080', }), }); diff --git a/frontend/vite.config.mts b/frontend/vite.config.mts index 62e754e..4d35c2b 100644 --- a/frontend/vite.config.mts +++ b/frontend/vite.config.mts @@ -46,13 +46,15 @@ export default defineConfig({ }, server: { port: 3000, + host: '0.0.0.0', + allowedHosts: ["goesseau.eu"], proxy: { '/api': { - target: 'http://localhost:8080', + target: 'http://goesseau.eu:8080', changeOrigin: true, }, '/ws': { - target: 'ws://localhost:8080', + target: 'ws://goesseau.eu:8080', ws: true, }, }, diff --git a/src/rtc/README.md b/src/rtc/README.md index 2a221a5..a1d1be1 100644 --- a/src/rtc/README.md +++ b/src/rtc/README.md @@ -1,11 +1,33 @@ -### Step 1 - handshake WebSocket +## Parcours technique RTC -Le client doit effectuer une connexion HTTP (websocket) sur /rtc/{channel_id} -Le server vérifiera avant d'accepter la connexion si : +Ce module gère la signalisation WebSocket et le relais audio WebRTC d'un canal. Le WebSocket transporte les descriptions SDP, les candidats ICE et les événements du salon ; les échantillons audio passent par la `PeerConnection`, pas par le WebSocket. Une connexion WebSocket correspond à un `RTCClient` et à une `PeerConnection`. -- Le channel existe -- Vérifiera les permissions sur le canal (check_perm ou si c'est un canal privé) +### Entrée et création du client -### Step 2 - SDP (négociation du type de media) +1. `routes/mod.rs` monte `routes/rtc/routes.rs` sous `/ws` : le navigateur ouvre `/ws/rtc/{channel_id}`. +2. `routes/rtc/handlers.rs::ws_handler` reçoit le canal et l'utilisateur via `CurrentUser`, cherche le canal en base, puis accepte l'upgrade WebSocket avec `ws_entrypoint_handler`. L'utilisateur doit être connecté et le canal doit exister. Le type du canal et les permissions ne sont **pas encore vérifiés**. +3. `rtc/ws_entrypoint.rs::ws_entrypoint_handler` crée une connexion via `RTCManager::new_peer_connection`, puis un `RTCClient` avec le canal, l'utilisateur, un identifiant propre à cette connexion et le gestionnaire partagé des salons (`RTCManager::rooms`). `RTCManager::new`, dans `rtc/mod.rs`, prépare aussi la configuration réseau `rustrtc`, notamment le port UDP ICE. +4. L'entrypoint démarre `RTCClient::forward_ice_candidates` avant la négociation, ainsi qu'une tâche de lecture WebSocket (`RTCClient::ws_on_message`) et une tâche d'écriture. `RTCClient::send_response` sérialise les réponses JSON dans le canal lu par cette dernière. -### Step 3 - ICE (Négociation du flux réseaux) +### Négociation initiale : SDP et ICE + +Les actions JSON sont définies dans `rtc/messages.rs`. Le `channel_id` n'est pas répété dans les messages : il est fixé par l'URL du WebSocket. + +1. Le navigateur envoie `sdp-offer`. `RTCClient::ws_on_message` appelle `handle_sdp_offer`, qui lit le type de charge utile Opus proposé et applique l'offre avec `PeerConnection::set_remote_description`. +2. Si l'offre contient une piste audio, `handle_sdp_offer` récupère sa piste entrante, réserve la première section audio pour éviter sa réutilisation par un autre locuteur, inscrit le client dans le salon avec `VoiceRoomManager::join`, puis démarre `forward_audio`. +3. `create_initial_answer` crée et applique la réponse SDP locale. `opus_sdp` reprend le type de charge utile Opus proposé par le navigateur ; `ws_on_message` renvoie ensuite `answer` et lance `run_room` pour écouter les événements du salon. +4. Le navigateur envoie ses messages `ice-candidate` : `handle_ice_candidate` les transmet à `rustrtc`. Un candidat vide marque la fin de collecte et est ignoré. En sens inverse, `forward_ice_candidates` transmet les candidats locaux sous forme de messages `ice-candidate` sur le WebSocket. Un candidat refusé produit un message `error` ; les noms mDNS `.local` peuvent notamment être refusés par `rustrtc`. + +### Audio et changements de participants + +`VoiceRoomManager` (`rtc/mod.rs`) maintient un salon par identifiant de canal. `join` crée une source audio propre au client, prévient les autres participants avec `RoomEvent::Joined` et informe le nouvel arrivant des sources existantes. Aucun événement n'inscrit sa propre source comme piste à recevoir : le client ne s'entend pas lui-même. + +`RTCClient::forward_audio` lit les échantillons de la piste entrante et les confie à `VoiceRoomManager::forward`, qui les publie uniquement sur la source de ce client et dans ce canal. Pour chaque `RoomEvent::Joined`, `RTCClient::run_room` crée une piste sortante distincte et une tâche qui alimente cette piste depuis la source correspondante. Le serveur relaie les échantillons Opus sans mixer les voix ; chaque navigateur lit et mixe ses pistes reçues. + +Une nouvelle piste nécessite une renégociation : `run_room` crée une offre SDP, stabilise les identifiants d'extensions RTP avec `stable_extmaps`, envoie `sdp-offer`, puis attend le `sdp-answer` du navigateur. `ws_on_message` applique cette réponse et débloque l'attente. Les renégociations sont traitées l'une après l'autre, avec un délai maximal de dix secondes. Lors d'un `RoomEvent::Left`, `run_room` arrête le transfert de cette source, rend sa piste inactive sans réutiliser sa section SDP, envoie `source-left` au navigateur et renégocie. + +### Déconnexion et responsabilités + +Un message `leave`, une fermeture WebSocket ou l'arrêt de la lecture/écriture termine le traitement dans `ws_entrypoint_handler`. Celui-ci arrête l'autre tâche WebSocket, arrête la tâche ICE et appelle `RTCClient::close`. `close` retire le participant du salon via `VoiceRoomManager::leave` (qui avertit les autres et supprime le salon devenu vide), arrête la tâche de salon et ferme la `PeerConnection`. + +En résumé : `routes/rtc` contrôle l'entrée HTTP, `ws_entrypoint` supervise les tâches et la fermeture, `RTCClient` possède la signalisation et la connexion WebRTC individuelle, et `VoiceRoomManager` distribue les sources audio entre les connexions du même canal. L'ancien module `voice` est distinct de ce parcours RTC.