Skip to content

Commit fd75e24

Browse files
committed
fix(site): race condition on connect when sending ice candidates
1 parent 5b2b715 commit fd75e24

File tree

4 files changed

+43
-29
lines changed

4 files changed

+43
-29
lines changed

overlay/receive.go

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -117,9 +117,10 @@ func getWebRTCConfig() webrtc.Configuration {
117117
}
118118
for i, server := range iceConfig.IceServers {
119119
config.ICEServers[i] = webrtc.ICEServer{
120-
URLs: server.URLs,
121-
Username: server.Username,
122-
Credential: server.Credential,
120+
URLs: server.URLs,
121+
Username: server.Username,
122+
Credential: server.Credential,
123+
CredentialType: webrtc.ICECredentialTypePassword,
123124
}
124125
}
125126

overlay/wasm_js.go

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,6 @@ type Wasm struct {
7272
DerpRegionID uint16
7373
DerpLatency time.Duration
7474

75-
// peers is a map of channels that notify peers of node updates.
7675
activePeer atomic.Pointer[chan *overlayMessage]
7776
onNewPeer js.Value
7877

@@ -138,7 +137,6 @@ func (r *Wasm) SendTailscaleNodeUpdate(node *tailcfg.Node) {
138137
}
139138

140139
func (r *Wasm) SendWebrtcCandidate(peer string, cand webrtc.ICECandidateInit) {
141-
142140
fmt.Println("go: sending webrtc candidate")
143141
r.out <- &overlayMessage{
144142
Typ: messageTypeWebRTCCandidate,
@@ -180,14 +178,14 @@ func (r *Wasm) Connect(ctx context.Context, ca ClientAuth, offer webrtc.SessionD
180178
go func() {
181179
defer r.activePeer.CompareAndSwap(&updates, nil)
182180
defer c.Close()
181+
defer fmt.Println("closing send goroutine")
183182

184183
for {
185184
select {
186185
case <-ctx.Done():
187186
return
188187
case msg, ok := <-updates:
189188
if !ok {
190-
c.Close()
191189
return
192190
}
193191

@@ -199,9 +197,10 @@ func (r *Wasm) Connect(ctx context.Context, ca ClientAuth, offer webrtc.SessionD
199197
sealed := ca.OverlayPrivateKey.SealTo(ca.ReceiverPublicKey, raw)
200198
err = c.Send(ca.ReceiverPublicKey, sealed)
201199
if err != nil {
202-
fmt.Printf("send response over derp: %s\n", err)
200+
fmt.Println("send response over derp:", err)
203201
return
204202
}
203+
fmt.Println("sent message to connected peer")
205204
}
206205
}
207206
}()
@@ -318,10 +317,6 @@ func (r *Wasm) ListenOverlayDERP(ctx context.Context) error {
318317
return true
319318
})
320319
if selectedPeer := r.activePeer.Load(); selectedPeer != nil {
321-
// *selectedPeer <- &overlayMessage{
322-
// Typ: messageTypeNodeUpdate,
323-
// Node: *msg.Node.Clone(),
324-
// }
325320
*selectedPeer <- msg
326321
fmt.Println("sending message")
327322
}
@@ -332,6 +327,7 @@ func (r *Wasm) ListenOverlayDERP(ctx context.Context) error {
332327
for {
333328
msg, err := c.Recv()
334329
if err != nil {
330+
fmt.Println("Recv derp:", err)
335331
return err
336332
}
337333

site/context/wush.tsx

Lines changed: 29 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -9,12 +9,13 @@ const iceServers = [
99
{
1010
urls: "stun:stun.l.google.com:19302",
1111
},
12-
...(process.env.PUBLIC_TURN_SERVER_URL
12+
...(process.env.NEXT_PUBLIC_TURN_SERVER_URL
1313
? [
1414
{
15-
urls: process.env.PUBLIC_TURN_SERVER_URL,
16-
username: process.env.PUBLIC_TURN_USERNAME ?? "",
17-
credential: process.env.PUBLIC_TURN_CREDENTIAL ?? "",
15+
urls: process.env.NEXT_PUBLIC_TURN_SERVER_URL,
16+
username: process.env.NEXT_PUBLIC_TURN_USERNAME ?? "",
17+
credential: process.env.NEXT_PUBLIC_TURN_CREDENTIAL ?? "",
18+
credentialType: "password",
1819
},
1920
]
2021
: []),
@@ -149,8 +150,6 @@ export const WasmProvider: React.FC<WasmProviderProps> = ({ children }) => {
149150
id: string,
150151
offer: RTCSessionDescriptionInit
151152
): Promise<RTCSessionDescription | null> => {
152-
console.log("got webrtc offer", id, JSON.stringify(offer));
153-
154153
const rtc = wasm.rtc.current.get(id);
155154
if (!rtc) {
156155
console.log(
@@ -168,7 +167,6 @@ export const WasmProvider: React.FC<WasmProviderProps> = ({ children }) => {
168167
console.error(`failed to create answer: ${ex}`);
169168
}
170169

171-
console.log("desc", JSON.stringify(rtc.localDescription));
172170
return rtc.localDescription;
173171
},
174172
onWebrtcAnswer: async (
@@ -305,16 +303,16 @@ export const WasmProvider: React.FC<WasmProviderProps> = ({ children }) => {
305303
throw new Error("failed to parse peer id");
306304
}
307305

306+
// Initialize an array to buffer candidates
307+
const bufferedCandidates: RTCIceCandidate[] = [];
308+
308309
// Set up 'onicecandidate' handler before starting ICE gathering
309310
newPeerConnection.onicecandidate = (
310311
event: RTCPeerConnectionIceEvent
311312
) => {
312313
if (event.candidate) {
313-
console.log("onicecandidate", event.candidate);
314-
wasm.wush.current?.sendWebrtcCandidate(
315-
peerInfo.id,
316-
event.candidate
317-
);
314+
console.log("Buffering ICE candidate", event.candidate);
315+
bufferedCandidates.push(event.candidate);
318316
}
319317
};
320318

@@ -340,6 +338,25 @@ export const WasmProvider: React.FC<WasmProviderProps> = ({ children }) => {
340338
throw new Error("Failed to connect to peer: peer is null");
341339
}
342340

341+
newPeerConnection.onicecandidate = (
342+
event: RTCPeerConnectionIceEvent
343+
) => {
344+
if (event.candidate) {
345+
console.log("onicecandidate", event.candidate);
346+
wasm.wush.current?.sendWebrtcCandidate(
347+
peerInfo.id,
348+
event.candidate
349+
);
350+
}
351+
};
352+
353+
// Add a method to send buffered candidates
354+
for (const candidate of bufferedCandidates) {
355+
wasm.wush.current?.sendWebrtcCandidate(peerInfo.id, candidate);
356+
}
357+
// Clear the buffer after sending
358+
bufferedCandidates.length = 0;
359+
343360
setWasm((prevState) => {
344361
return {
345362
...prevState,

site/pages/api/iceConfig.ts

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -26,14 +26,14 @@ export default function handler(
2626

2727
// Add TURN server if credentials are configured
2828
if (
29-
process.env.PUBLIC_TURN_SERVER_URL &&
30-
process.env.PUBLIC_TURN_USERNAME &&
31-
process.env.PUBLIC_TURN_CREDENTIAL
29+
process.env.NEXT_PUBLIC_TURN_SERVER_URL &&
30+
process.env.NEXT_PUBLIC_TURN_USERNAME &&
31+
process.env.NEXT_PUBLIC_TURN_CREDENTIAL
3232
) {
3333
iceServers.push({
34-
urls: [process.env.PUBLIC_TURN_SERVER_URL],
35-
username: process.env.PUBLIC_TURN_USERNAME,
36-
credential: process.env.PUBLIC_TURN_CREDENTIAL,
34+
urls: [process.env.NEXT_PUBLIC_TURN_SERVER_URL],
35+
username: process.env.NEXT_PUBLIC_TURN_USERNAME,
36+
credential: process.env.NEXT_PUBLIC_TURN_CREDENTIAL,
3737
});
3838
}
3939

0 commit comments

Comments
 (0)