mirror of
https://github.com/xtr-dev/rondevu-client.git
synced 2025-12-10 02:43:25 +00:00
Fix ICE candidate handling - send full candidate objects
- Update IceCandidate interface to include sdpMid and sdpMLineIndex - Update addIceCandidates to accept full candidate objects - Update connection manager to send and receive complete ICE data - Fixes 'Either sdpMid or sdpMLineIndex must be specified' error 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -60,7 +60,11 @@ export class RondevuConnection {
|
||||
private lastIceTimestamp: number = Date.now();
|
||||
private eventListeners: Map<keyof RondevuConnectionEvents, Set<Function>> = new Map();
|
||||
private dataChannel?: RTCDataChannel;
|
||||
private pendingIceCandidates: string[] = [];
|
||||
private pendingIceCandidates: Array<{
|
||||
candidate: string;
|
||||
sdpMid: string | null;
|
||||
sdpMLineIndex: number | null;
|
||||
}> = [];
|
||||
|
||||
/**
|
||||
* Current connection state
|
||||
@@ -103,18 +107,22 @@ export class RondevuConnection {
|
||||
private setupPeerConnection(): void {
|
||||
this.pc.onicecandidate = async (event) => {
|
||||
if (event.candidate) {
|
||||
const candidateString = event.candidate.candidate;
|
||||
const candidateData = {
|
||||
candidate: event.candidate.candidate,
|
||||
sdpMid: event.candidate.sdpMid,
|
||||
sdpMLineIndex: event.candidate.sdpMLineIndex,
|
||||
};
|
||||
|
||||
if (this.offerId) {
|
||||
// offerId is set, send immediately (trickle ICE)
|
||||
try {
|
||||
await this.offersApi.addIceCandidates(this.offerId, [candidateString]);
|
||||
await this.offersApi.addIceCandidates(this.offerId, [candidateData]);
|
||||
} catch (err) {
|
||||
console.error('Error sending ICE candidate:', err);
|
||||
}
|
||||
} else {
|
||||
// offerId not set yet, buffer the candidate
|
||||
this.pendingIceCandidates.push(candidateString);
|
||||
this.pendingIceCandidates.push(candidateData);
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -275,10 +283,11 @@ export class RondevuConnection {
|
||||
);
|
||||
|
||||
for (const candidate of candidates) {
|
||||
// Create ICE candidate from candidate string only
|
||||
// Don't hardcode sdpMLineIndex/sdpMid - let WebRTC parse from candidate string
|
||||
// Create ICE candidate with all fields
|
||||
await this.pc.addIceCandidate(new RTCIceCandidate({
|
||||
candidate: candidate.candidate
|
||||
candidate: candidate.candidate,
|
||||
sdpMid: candidate.sdpMid ?? undefined,
|
||||
sdpMLineIndex: candidate.sdpMLineIndex ?? undefined,
|
||||
}));
|
||||
this.lastIceTimestamp = candidate.createdAt;
|
||||
}
|
||||
|
||||
@@ -26,6 +26,8 @@ export interface Offer {
|
||||
|
||||
export interface IceCandidate {
|
||||
candidate: string;
|
||||
sdpMid: string | null;
|
||||
sdpMLineIndex: number | null;
|
||||
peerId: string;
|
||||
role: 'offerer' | 'answerer';
|
||||
createdAt: number;
|
||||
@@ -278,7 +280,14 @@ export class RondevuOffers {
|
||||
/**
|
||||
* Post ICE candidates for an offer
|
||||
*/
|
||||
async addIceCandidates(offerId: string, candidates: string[]): Promise<void> {
|
||||
async addIceCandidates(
|
||||
offerId: string,
|
||||
candidates: Array<{
|
||||
candidate: string;
|
||||
sdpMid?: string | null;
|
||||
sdpMLineIndex?: number | null;
|
||||
}>
|
||||
): Promise<void> {
|
||||
const response = await this.fetchFn(`${this.baseUrl}/offers/${encodeURIComponent(offerId)}/ice-candidates`, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
|
||||
Reference in New Issue
Block a user