Start · Sprachen · JavaScript · Referenz · RTCTransportStats.iceRole

RTCTransportStats.iceRole

Eigenschaft

Ein String, der angibt, ob der ICE-Agent dieses Transports die Rolle <code>"controlling"</code> (kontrollierend) oder <code>"controlled"</code> (kontrolliert) hat.

seit JavaScript Chromium-basierte Browser (ca. ab Version 112); in Kategorie: webapi

Signatur

RTCTransportStats.iceRole

Beschreibung

Die Eigenschaft iceRole gehört zum Wörterbuch RTCTransportStats. Solche Objekte liefert RTCPeerConnection.getStats() für Einträge mit type === "transport". Der Wert gibt an, welche Rolle der lokale ICE-Agent (Interactive Connectivity Establishment) für diesen Transport übernimmt.

Es gibt drei mögliche Werte:

  • "controlling": Der lokale Agent ist der kontrollierende Agent. Er entscheidet am Ende, welches Kandidatenpaar für die Verbindung benutzt wird („Nomination“). In der Regel ist das die Seite, die das Angebot (Offer) erstellt hat.
  • "controlled": Der lokale Agent ist der kontrollierte Agent und übernimmt die Nominierung der Gegenseite. Das ist normalerweise die antwortende Seite (Answer).
  • "unknown": Die Rolle steht noch nicht fest, zum Beispiel bevor die ICE-Aushandlung begonnen hat.

Die Eigenschaft ist vor allem bei der Fehlersuche und in Monitoring-Werkzeugen nützlich. Damit lässt sich prüfen, welche Seite die Kandidatenwahl steuert, ob Rollenkonflikte aufgetreten sind (ICE-Role-Conflict, RFC 8445) und ob die Signalisierung wie geplant abläuft. Sie ist schreibgeschützt und beschreibt nur einen Zustand. Um die Rolle festzulegen, steuert man, welche Seite das Offer erstellt.

Rückgabewert

Typ
"controlling" | "controlled" | "unknown" | undefined
Beschreibung
Die aktuelle ICE-Rolle des lokalen Agenten für diesen Transport. Unterstützt der Browser die Eigenschaft nicht, ist der Wert undefined.

Beispiele

ICE-Rolle aus den Transport-Statistiken auslesen

const logIceRole = async (pc) => {
  const report = await pc.getStats();
  report.forEach((stats) => {
    if (stats.type === 'transport') {
      console.log(`Transport ${stats.id}: iceRole = ${stats.iceRole ?? 'nicht unterstützt'}`);
    }
  });
};

// Aufruf, nachdem die Verbindung aufgebaut ist
// await logIceRole(peerConnection);
Transport T01: iceRole = controlling

Rollen von Offerer und Answerer lokal vergleichen

const getIceRole = async (pc) => {
  const report = await pc.getStats();
  for (const stats of report.values()) {
    if (stats.type === 'transport') return stats.iceRole;
  }
  return undefined;
};

const pc1 = new RTCPeerConnection();
const pc2 = new RTCPeerConnection();
pc1.onicecandidate = (e) => e.candidate && pc2.addIceCandidate(e.candidate);
pc2.onicecandidate = (e) => e.candidate && pc1.addIceCandidate(e.candidate);

pc1.createDataChannel('test');
await pc1.setLocalDescription(await pc1.createOffer());
await pc2.setRemoteDescription(pc1.localDescription);
await pc2.setLocalDescription(await pc2.createAnswer());
await pc1.setRemoteDescription(pc2.localDescription);

// Kurz warten, bis ICE läuft
await new Promise((r) => setTimeout(r, 1000));
console.log('Offerer:', await getIceRole(pc1));
console.log('Answerer:', await getIceRole(pc2));
Offerer: controlling Answerer: controlled

Rollenwechsel im Monitoring erkennen

const watchIceRole = (pc, intervalMs = 2000) => {
  let lastRole;
  const timer = setInterval(async () => {
    const report = await pc.getStats();
    for (const stats of report.values()) {
      if (stats.type !== 'transport') continue;
      if (stats.iceRole !== lastRole) {
        console.info(`ICE-Rolle geändert: ${lastRole} → ${stats.iceRole}`);
        lastRole = stats.iceRole;
      }
    }
  }, intervalMs);
  // Funktion zum Beenden der Überwachung zurückgeben
  return () => clearInterval(timer);
};

// const stop = watchIceRole(peerConnection);
// später: stop();
ICE-Rolle geändert: undefined → controlling

// Wichtig · Fallstricke

  • Browser-Kompatibilität: iceRole wird derzeit vor allem von Chromium-basierten Browsern gemeldet. Firefox liefert keine oder nur eingeschränkte "transport"-Statistiken. Deshalb immer mit undefined rechnen und zum Beispiel stats.iceRole ?? 'unbekannt' verwenden.
  • Rolle ≠ Offer/Answer: Normalerweise ist die Seite, die das Offer erstellt, "controlling". Bei einem ICE-Rollenkonflikt, etwa wenn beide Seiten ICE-lite nutzen oder gleichzeitig ein Offer erstellen („Glare“), kann sich die Rolle während der Aushandlung ändern. Sie sollte also nicht dauerhaft zwischengespeichert werden.
  • Vor Beginn der ICE-Aushandlung kann der Wert "unknown" sein, oder der Transport-Eintrag fehlt ganz.
  • Bei bundlePolicy: "max-bundle" gibt es meist nur einen einzigen Transport-Eintrag. Ohne Bundling kann es mehrere Transporte mit eigener Rolle geben.
  • getStats() ist asynchron und relativ aufwendig. Beim Monitoring sollte man die Statistiken daher in sinnvollen Abständen abfragen, zum Beispiel alle 1–5 Sekunden, statt in einer engen Schleife.