2 Commits

Author SHA1 Message Date
8d7075ccc4 0.7.3 2025-11-16 17:51:24 +01:00
db8f0f4ced Fix answerer authorization for ICE candidates
The answerer was getting 403 Forbidden when sending ICE candidates because
the server didn't know who the answerer was yet. ICE gathering starts when
setLocalDescription is called, but we were calling /answer AFTER that.

Fixed by sending the answer to the server BEFORE setLocalDescription:
1. Create answer SDP
2. Send answer to server (registers answererPeerId)
3. Set up ICE handler
4. Set local description (ICE gathering starts)

This ensures the server has answererPeerId set before ICE candidates arrive,
so they're properly authorized.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-16 17:51:04 +01:00
3 changed files with 13 additions and 9 deletions

4
package-lock.json generated
View File

@@ -1,12 +1,12 @@
{ {
"name": "@xtr-dev/rondevu-client", "name": "@xtr-dev/rondevu-client",
"version": "0.7.2", "version": "0.7.3",
"lockfileVersion": 3, "lockfileVersion": 3,
"requires": true, "requires": true,
"packages": { "packages": {
"": { "": {
"name": "@xtr-dev/rondevu-client", "name": "@xtr-dev/rondevu-client",
"version": "0.7.2", "version": "0.7.3",
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@xtr-dev/rondevu-client": "^0.5.1" "@xtr-dev/rondevu-client": "^0.5.1"

View File

@@ -1,6 +1,6 @@
{ {
"name": "@xtr-dev/rondevu-client", "name": "@xtr-dev/rondevu-client",
"version": "0.7.2", "version": "0.7.3",
"description": "TypeScript client for Rondevu topic-based peer discovery and signaling server", "description": "TypeScript client for Rondevu topic-based peer discovery and signaling server",
"type": "module", "type": "module",
"main": "dist/index.js", "main": "dist/index.js",

View File

@@ -23,15 +23,19 @@ export class AnsweringState extends PeerState {
sdp: offerSdp sdp: offerSdp
}); });
// Create answer
const answer = await this.peer.pc.createAnswer();
// Send answer to server BEFORE setLocalDescription
// This registers us as the answerer so ICE candidates will be accepted
await this.peer.offersApi.answer(offerId, answer.sdp!);
// Enable trickle ICE - set up handler before ICE gathering starts // Enable trickle ICE - set up handler before ICE gathering starts
this.setupIceCandidateHandler(); this.setupIceCandidateHandler();
// Create answer // Set local description - ICE gathering starts here
const answer = await this.peer.pc.createAnswer(); // Server already knows we're the answerer, so candidates will be accepted
await this.peer.pc.setLocalDescription(answer); // ICE gathering starts here await this.peer.pc.setLocalDescription(answer);
// Send answer to server immediately (don't wait for ICE)
await this.peer.offersApi.answer(offerId, answer.sdp!);
// Transition to exchanging ICE // Transition to exchanging ICE
const { ExchangingIceState } = await import('./exchanging-ice-state.js'); const { ExchangingIceState } = await import('./exchanging-ice-state.js');