From 6c2fd7952e813a154fc7cb0d1f91ebe400239435 Mon Sep 17 00:00:00 2001 From: Bas van den Aakster Date: Sat, 6 Dec 2025 15:24:09 +0100 Subject: [PATCH] Critical fix: Add ICE candidate handlers to service pool MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The service pool was creating peer connections but never setting up onicecandidate handlers. This meant ICE candidates generated by the TURN relay were never sent to the signaling server, causing all ICE connectivity checks to fail with no remote candidates. Changes: - Add onicecandidate handlers in createOffers() after getting offer IDs - Add onicecandidate handler in publishInitialService() after publishing - Handlers send candidates to server via addIceCandidates() This fixes the "all checks completed success=0 fail=1" error where remote candidates were empty. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Sonnet 4.5 --- src/service-pool.ts | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/src/service-pool.ts b/src/service-pool.ts index e2319a0..4a84469 100644 --- a/src/service-pool.ts +++ b/src/service-pool.ts @@ -417,6 +417,25 @@ export class ServicePool { const createdOffers = await this.offersApi.create(offerRequests); offers.push(...createdOffers); + // Set up ICE candidate handlers AFTER we have offer IDs + for (let i = 0; i < peerConnections.length; i++) { + const pc = peerConnections[i]; + const offerId = createdOffers[i].id; + + pc.onicecandidate = async (event) => { + if (event.candidate) { + const candidateData = event.candidate.toJSON(); + if (candidateData.candidate && candidateData.candidate !== '') { + try { + await this.offersApi.addIceCandidates(offerId, [candidateData]); + } catch (err) { + console.error('Error sending ICE candidate:', err); + } + } + } + }; + } + } catch (error) { // Close any created peer connections on error peerConnections.forEach(pc => pc.close()); @@ -493,6 +512,20 @@ export class ServicePool { const data = await response.json(); + // Set up ICE candidate handler now that we have the offer ID + pc.onicecandidate = async (event) => { + if (event.candidate) { + const candidateData = event.candidate.toJSON(); + if (candidateData.candidate && candidateData.candidate !== '') { + try { + await this.offersApi.addIceCandidates(data.offerId, [candidateData]); + } catch (err) { + console.error('Error sending ICE candidate:', err); + } + } + } + }; + return { serviceId: data.serviceId, uuid: data.uuid,