Signatur
Beschreibung
Die Eigenschaft usernameFragment eines RTCIceCandidate enthält das sogenannte Username Fragment (kurz ufrag). ICE (Interactive Connectivity Establishment) verwendet diesen Wert zusammen mit einem Passwort (ice-pwd), um STUN-Verbindungsprüfungen zwischen zwei Peers zu authentifizieren. Der Wert entspricht dem Attribut a=ice-ufrag in der SDP-Beschreibung bzw. der Erweiterung ufrag in der candidate-Zeile.
Wichtig ist das Fragment vor allem bei einem ICE-Restart: Nach RTCPeerConnection.restartIce() bzw. einem Angebot mit iceRestart: true erzeugt der Browser ein neues ufrag. Anhand von usernameFragment lässt sich dann erkennen, ob ein eintreffender Kandidat noch zur alten oder schon zur neuen ICE-Generation gehört. Veraltete Kandidaten kann man so gezielt verwerfen.
Der Wert wird beim Erzeugen des Kandidaten festgelegt, entweder vom Browser (im icecandidate-Ereignis) oder über das Initialisierungsobjekt { candidate, sdpMid, sdpMLineIndex, usernameFragment } im Konstruktor. Beim Serialisieren mit toJSON() ist er enthalten und wird so über den Signalisierungskanal an die Gegenseite übertragen.
Rückgabewert
"EsAw". null, wenn der Kandidat ohne Fragment erzeugt wurde und es auch nicht aus der candidate-Zeile gelesen werden konnte.Beispiele
ufrag lokaler Kandidaten ausgeben
const pc = new RTCPeerConnection({
iceServers: [{ urls: 'stun:stun.l.google.com:19302' }]
});
pc.addEventListener('icecandidate', (event) => {
if (!event.candidate) return; // Sammeln abgeschlossen
console.log('ufrag:', event.candidate.usernameFragment);
});
pc.createDataChannel('chat');
const offer = await pc.createOffer();
await pc.setLocalDescription(offer);
Kandidat mit usernameFragment konstruieren
const candidate = new RTCIceCandidate({
candidate: 'candidate:842163049 1 udp 1677729535 203.0.113.7 54400 typ srflx raddr 0.0.0.0 rport 0 generation 0 ufrag EsAw',
sdpMid: '0',
sdpMLineIndex: 0,
usernameFragment: 'EsAw'
});
console.log(candidate.usernameFragment);
console.log(candidate.toJSON().usernameFragment);
Veraltete Kandidaten nach ICE-Restart verwerfen
// Liest das aktuelle ufrag aus der Remote-SDP
const getRemoteUfrag = (pc) => {
const sdp = pc.remoteDescription?.sdp ?? '';
return sdp.match(/a=ice-ufrag:(\S+)/)?.[1] ?? null;
};
// Wird vom Signalisierungskanal aufgerufen
const handleRemoteCandidate = async (pc, init) => {
const candidate = new RTCIceCandidate(init);
const current = getRemoteUfrag(pc);
if (candidate.usernameFragment && current && candidate.usernameFragment !== current) {
console.warn('Kandidat aus alter ICE-Generation ignoriert:', candidate.usernameFragment);
return;
}
await pc.addIceCandidate(candidate);
};
// Wichtig · Fallstricke
- Schreibgeschützt: Zuweisungen an
usernameFragmenthaben keine Wirkung. Der Wert lässt sich nur beim Konstruieren über das Initialisierungsobjekt setzen. - Immer mit übertragen: Schicke Kandidaten am besten per
candidate.toJSON()über die Signalisierung. Überträgst du nur dencandidate-String, kann das Fragment fehlen. Nach einem ICE-Restart kannaddIceCandidate()den Kandidaten dann eventuell nicht richtig zuordnen. - Kein Geheimnis, aber Sitzungsbezug: Das
ufragsteht im Klartext in der SDP. Die eigentliche Absicherung übernimmt dasice-pwd, das nie im Kandidaten enthalten ist. Trotzdem sollte die Signalisierung verschlüsselt laufen, z. B. über WSS. - Kompatibilität: Ältere Browser (etwa Chrome vor 74 oder Safari vor 14.1) kennen die Eigenschaft nicht und liefern
undefined. In diesem Fall kannst du auf denufrag-Teil dercandidate-Zeile zurückgreifen. - Ein leerer Kandidat, der das Ende des Sammelns signalisiert (
candidate: \"\"), trägt unter Umständen trotzdem einusernameFragment. So wird das Ende der jeweiligen ICE-Generation angezeigt.