Skip to content

Commit 7fa1578

Browse files
committed
fix(web): route viewer signaling through API for desktop hosts
1 parent 9a249fb commit 7fa1578

2 files changed

Lines changed: 48 additions & 28 deletions

File tree

apps/web/src/app/session/[id]/page.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -172,6 +172,7 @@ function P2PSessionViewer({ sessionId, session }: SessionViewerWrapperProps) {
172172
const hookResult = useWebRTC({
173173
sessionId,
174174
participantId,
175+
useApiSignalPost: true,
175176
onCursorUpdate: handleCursorUpdate,
176177
});
177178

apps/web/src/hooks/useWebRTC.ts

Lines changed: 47 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ if (
3737
interface UseWebRTCOptions {
3838
sessionId: string;
3939
participantId: string;
40+
useApiSignalPost?: boolean;
4041
onStreamReady?: (stream: MediaStream) => void;
4142
onStreamEnded?: () => void;
4243
onControlStateChange?: (state: ControlStateUI) => void;
@@ -68,6 +69,7 @@ interface UseWebRTCReturn {
6869
export function useWebRTC({
6970
sessionId,
7071
participantId,
72+
useApiSignalPost = false,
7173
onStreamReady,
7274
onStreamEnded,
7375
onControlStateChange,
@@ -94,6 +96,35 @@ export function useWebRTC({
9496
const inputSequenceRef = useRef(0);
9597
const maxReconnectAttempts = 3;
9698

99+
const sendSignal = useCallback(
100+
async (payload: SignalMessage) => {
101+
if (useApiSignalPost) {
102+
try {
103+
const response = await fetch(`/api/sessions/${sessionId}/signal`, {
104+
method: 'POST',
105+
headers: { 'Content-Type': 'application/json' },
106+
credentials: 'same-origin',
107+
body: JSON.stringify(payload),
108+
});
109+
110+
if (!response.ok) {
111+
console.error('[WebRTC] Failed to send signal:', await response.text());
112+
}
113+
} catch (err) {
114+
console.error('[WebRTC] Error sending signal:', err);
115+
}
116+
return;
117+
}
118+
119+
void channelRef.current?.send({
120+
type: 'broadcast',
121+
event: 'signal',
122+
payload,
123+
});
124+
},
125+
[sessionId, useApiSignalPost]
126+
);
127+
97128
// Buffer ICE candidates that arrive before remote description is set
98129
const pendingCandidatesRef = useRef<RTCIceCandidateInit[]>([]);
99130
// Serialize signaling message processing to prevent race conditions
@@ -341,15 +372,11 @@ export function useWebRTC({
341372

342373
// Send answer back via signaling channel
343374
if (answer.sdp) {
344-
void channelRef.current?.send({
345-
type: 'broadcast',
346-
event: 'signal',
347-
payload: {
348-
type: 'answer',
349-
sdp: answer.sdp,
350-
senderId: participantId,
351-
timestamp: Date.now(),
352-
} satisfies SignalMessage,
375+
void sendSignal({
376+
type: 'answer',
377+
sdp: answer.sdp,
378+
senderId: participantId,
379+
timestamp: Date.now(),
353380
});
354381
}
355382

@@ -410,15 +437,11 @@ export function useWebRTC({
410437
await pc.setLocalDescription(offer);
411438

412439
if (offer.sdp) {
413-
void channelRef.current?.send({
414-
type: 'broadcast',
415-
event: 'signal',
416-
payload: {
417-
type: 'offer',
418-
sdp: offer.sdp,
419-
senderId: participantId,
420-
timestamp: Date.now(),
421-
} satisfies SignalMessage,
440+
void sendSignal({
441+
type: 'offer',
442+
sdp: offer.sdp,
443+
senderId: participantId,
444+
timestamp: Date.now(),
422445
});
423446
}
424447
} catch {
@@ -462,15 +485,11 @@ export function useWebRTC({
462485
// Handle ICE candidates
463486
pc.onicecandidate = (event) => {
464487
if (event.candidate) {
465-
void channelRef.current?.send({
466-
type: 'broadcast',
467-
event: 'signal',
468-
payload: {
469-
type: 'ice-candidate',
470-
candidate: event.candidate.toJSON(),
471-
senderId: participantId,
472-
timestamp: Date.now(),
473-
} satisfies SignalMessage,
488+
void sendSignal({
489+
type: 'ice-candidate',
490+
candidate: event.candidate.toJSON(),
491+
senderId: participantId,
492+
timestamp: Date.now(),
474493
});
475494
}
476495
};
@@ -522,7 +541,7 @@ export function useWebRTC({
522541
};
523542

524543
return pc;
525-
}, [participantId, onStreamReady, onStreamEnded, setupDataChannel]);
544+
}, [participantId, onStreamReady, onStreamEnded, setupDataChannel, sendSignal]);
526545

527546
// Disconnect
528547
const disconnect = useCallback(() => {

0 commit comments

Comments
 (0)