mirror of
https://github.com/xtr-dev/rondevu-server.git
synced 2025-12-10 02:43:24 +00:00
Fix ICE candidate handling - include sdpMid and sdpMLineIndex
- Update IceCandidate interface to include sdpMid and sdpMLineIndex fields - Update SQLite and D1 storage to store full ICE candidate data - Update server API to accept and return complete candidate objects - This fixes the '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:
@@ -59,6 +59,8 @@ export class D1Storage implements Storage {
|
||||
peer_id TEXT NOT NULL,
|
||||
role TEXT NOT NULL CHECK(role IN ('offerer', 'answerer')),
|
||||
candidate TEXT NOT NULL,
|
||||
sdp_mid TEXT,
|
||||
sdp_m_line_index INTEGER,
|
||||
created_at INTEGER NOT NULL,
|
||||
FOREIGN KEY (offer_id) REFERENCES offers(id) ON DELETE CASCADE
|
||||
);
|
||||
@@ -242,14 +244,26 @@ export class D1Storage implements Storage {
|
||||
offerId: string,
|
||||
peerId: string,
|
||||
role: 'offerer' | 'answerer',
|
||||
candidates: string[]
|
||||
candidates: Array<{
|
||||
candidate: string;
|
||||
sdpMid?: string | null;
|
||||
sdpMLineIndex?: number | null;
|
||||
}>
|
||||
): Promise<number> {
|
||||
// D1 doesn't have transactions, so insert one by one
|
||||
for (const candidate of candidates) {
|
||||
for (const cand of candidates) {
|
||||
await this.db.prepare(`
|
||||
INSERT INTO ice_candidates (offer_id, peer_id, role, candidate, created_at)
|
||||
VALUES (?, ?, ?, ?, ?)
|
||||
`).bind(offerId, peerId, role, candidate, Date.now()).run();
|
||||
INSERT INTO ice_candidates (offer_id, peer_id, role, candidate, sdp_mid, sdp_m_line_index, created_at)
|
||||
VALUES (?, ?, ?, ?, ?, ?, ?)
|
||||
`).bind(
|
||||
offerId,
|
||||
peerId,
|
||||
role,
|
||||
cand.candidate,
|
||||
cand.sdpMid ?? null,
|
||||
cand.sdpMLineIndex ?? null,
|
||||
Date.now()
|
||||
).run();
|
||||
}
|
||||
|
||||
return candidates.length;
|
||||
@@ -286,6 +300,8 @@ export class D1Storage implements Storage {
|
||||
peerId: row.peer_id,
|
||||
role: row.role,
|
||||
candidate: row.candidate,
|
||||
sdpMid: row.sdp_mid,
|
||||
sdpMLineIndex: row.sdp_m_line_index,
|
||||
createdAt: row.created_at,
|
||||
}));
|
||||
}
|
||||
|
||||
@@ -56,6 +56,8 @@ export class SQLiteStorage implements Storage {
|
||||
peer_id TEXT NOT NULL,
|
||||
role TEXT NOT NULL CHECK(role IN ('offerer', 'answerer')),
|
||||
candidate TEXT NOT NULL,
|
||||
sdp_mid TEXT,
|
||||
sdp_m_line_index INTEGER,
|
||||
created_at INTEGER NOT NULL,
|
||||
FOREIGN KEY (offer_id) REFERENCES offers(id) ON DELETE CASCADE
|
||||
);
|
||||
@@ -252,16 +254,28 @@ export class SQLiteStorage implements Storage {
|
||||
offerId: string,
|
||||
peerId: string,
|
||||
role: 'offerer' | 'answerer',
|
||||
candidates: string[]
|
||||
candidates: Array<{
|
||||
candidate: string;
|
||||
sdpMid?: string | null;
|
||||
sdpMLineIndex?: number | null;
|
||||
}>
|
||||
): Promise<number> {
|
||||
const stmt = this.db.prepare(`
|
||||
INSERT INTO ice_candidates (offer_id, peer_id, role, candidate, created_at)
|
||||
VALUES (?, ?, ?, ?, ?)
|
||||
INSERT INTO ice_candidates (offer_id, peer_id, role, candidate, sdp_mid, sdp_m_line_index, created_at)
|
||||
VALUES (?, ?, ?, ?, ?, ?, ?)
|
||||
`);
|
||||
|
||||
const transaction = this.db.transaction((candidates: string[]) => {
|
||||
for (const candidate of candidates) {
|
||||
stmt.run(offerId, peerId, role, candidate, Date.now());
|
||||
const transaction = this.db.transaction((candidates: typeof candidates) => {
|
||||
for (const cand of candidates) {
|
||||
stmt.run(
|
||||
offerId,
|
||||
peerId,
|
||||
role,
|
||||
cand.candidate,
|
||||
cand.sdpMid ?? null,
|
||||
cand.sdpMLineIndex ?? null,
|
||||
Date.now()
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
@@ -297,6 +311,8 @@ export class SQLiteStorage implements Storage {
|
||||
peerId: row.peer_id,
|
||||
role: row.role,
|
||||
candidate: row.candidate,
|
||||
sdpMid: row.sdp_mid,
|
||||
sdpMLineIndex: row.sdp_m_line_index,
|
||||
createdAt: row.created_at,
|
||||
}));
|
||||
}
|
||||
|
||||
@@ -23,6 +23,8 @@ export interface IceCandidate {
|
||||
peerId: string;
|
||||
role: 'offerer' | 'answerer';
|
||||
candidate: string;
|
||||
sdpMid: string | null;
|
||||
sdpMLineIndex: number | null;
|
||||
createdAt: number;
|
||||
}
|
||||
|
||||
@@ -125,14 +127,18 @@ export interface Storage {
|
||||
* @param offerId Offer identifier
|
||||
* @param peerId Peer ID posting the candidates
|
||||
* @param role Role of the peer (offerer or answerer)
|
||||
* @param candidates Array of ICE candidate strings
|
||||
* @param candidates Array of ICE candidate objects
|
||||
* @returns Number of candidates added
|
||||
*/
|
||||
addIceCandidates(
|
||||
offerId: string,
|
||||
peerId: string,
|
||||
role: 'offerer' | 'answerer',
|
||||
candidates: string[]
|
||||
candidates: Array<{
|
||||
candidate: string;
|
||||
sdpMid?: string | null;
|
||||
sdpMLineIndex?: number | null;
|
||||
}>
|
||||
): Promise<number>;
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user