Signatur
Beschreibung
Die Eigenschaft usernameFragment eines RTCIceCandidateStats-Objekts enthält das ICE-Benutzernamenfragment (ice-ufrag). Es gehört zu dem ICE-Kandidaten, den der Statistikeintrag beschreibt. Solche Einträge liefert RTCPeerConnection.getStats(). Ihr type ist entweder "local-candidate" oder "remote-candidate".
Das Fragment wird bei der ICE-Aushandlung zusammen mit dem ICE-Passwort (ice-pwd) festgelegt und steht in der SDP-Zeile a=ice-ufrag:…. Aus den Fragmenten beider Seiten (remoteUfrag:localUfrag) setzt sich der Benutzername zusammen, mit dem STUN-Verbindungsprüfungen gegenseitig authentifiziert werden. Außerdem ordnet das Fragment einen Kandidaten einer bestimmten ICE-Generation zu.
In der Praxis nutzt man die Eigenschaft vor allem für die Fehlersuche und Überwachung:
- Man erkennt einen ICE-Neustart (
restartIce()), denn danach entsteht ein neues Fragment. - Man kann Kandidaten aus den Statistiken den passenden SDP-Abschnitten oder Signalisierungsnachrichten zuordnen.
- Man kann veraltete Kandidaten aus einer früheren ICE-Generation herausfiltern.
Rückgabewert
"EsAw". Ist die Eigenschaft nicht implementiert oder das Fragment (noch) unbekannt, fehlt sie und der Wert ist undefined.Beispiele
Benutzernamenfragmente aller Kandidaten ausgeben
const pc = new RTCPeerConnection();
pc.createDataChannel('probe');
await pc.setLocalDescription(await pc.createOffer());
// Etwas warten, bis Kandidaten gesammelt wurden
await new Promise((r) => setTimeout(r, 1000));
const stats = await pc.getStats();
stats.forEach((report) => {
if (report.type === 'local-candidate' || report.type === 'remote-candidate') {
console.log(report.type, report.candidateType, report.address, report.usernameFragment ?? '(nicht verfügbar)');
}
});
ICE-Neustart anhand des Fragments erkennen
const getLocalUfrag = async (pc) => {
const stats = await pc.getStats();
for (const report of stats.values()) {
if (report.type === 'local-candidate' && report.usernameFragment) {
return report.usernameFragment;
}
}
return undefined;
};
// pc: bestehende, verbundene RTCPeerConnection
const vorher = await getLocalUfrag(pc);
pc.restartIce();
// ... nach neuer Aushandlung über die Signalisierung:
const nachher = await getLocalUfrag(pc);
console.log(vorher !== nachher ? 'ICE-Neustart erfolgt' : 'Gleiche ICE-Generation');
Mit dem ice-ufrag der SDP abgleichen
// pc: RTCPeerConnection mit gesetzter lokaler Beschreibung
const sdpUfrag = pc.localDescription.sdp.match(/a=ice-ufrag:(\S+)/)?.[1];
const stats = await pc.getStats();
const veraltet = [...stats.values()].filter(
(r) => r.type === 'local-candidate' && r.usernameFragment && r.usernameFragment !== sdpUfrag
);
console.log(`SDP-ufrag: ${sdpUfrag}, veraltete Kandidaten: ${veraltet.length}`);
// Wichtig · Fallstricke
- Browser-Kompatibilität: Die Eigenschaft ist erst in neueren Browserversionen implementiert und fehlt in einigen Umgebungen. Prüfe den Wert deshalb immer auf
undefined, z. B. mitreport.usernameFragment ?? …. - Die Eigenschaft gibt es nur bei Einträgen mit
type"local-candidate"oder"remote-candidate", nicht bei"candidate-pair"oder"transport". - Entfernte Kandidaten, die als peer-reflexive erkannt wurden (
candidateType === "prflx"), haben unter Umständen noch kein bekanntes Fragment. - Nach
restartIce()können kurzzeitig Kandidaten mit altem und neuem Fragment gleichzeitig in den Statistiken stehen. - Sicherheit/Datenschutz: Das Fragment allein ist kein Geheimnis, denn es steht im Klartext in der SDP. Das zugehörige
ice-pwddagegen schon. Beim Protokollieren von Statistiken die Kandidaten-IP-Adressen (address) nicht ungeschützt an Dritte weitergeben.