Start · Sprachen · JavaScript · Referenz · RTCIceTransport.role

RTCIceTransport.role

Eigenschaft

Schreibgeschützte Eigenschaft, die die ICE-Rolle des Transports angibt: <code>"controlling"</code>, <code>"controlled"</code> oder <code>"unknown"</code>.

seit JavaScript WebRTC 1.0; Chromium-Browser und Safari, in Firefo Kategorie: webapi

Signatur

RTCIceTransport.role

Beschreibung

Die schreibgeschützte Eigenschaft role eines RTCIceTransport zeigt, welche Rolle der lokale ICE-Agent in der aktuellen Sitzung hat. Laut ICE-Protokoll (RFC 8445) übernimmt immer genau eine Seite die Rolle des kontrollierenden Agenten (controlling). Diese Seite entscheidet, welches Kandidatenpaar am Ende verwendet wird („Nominierung“). Die andere Seite ist der kontrollierte Agent (controlled) und übernimmt diese Entscheidung.

Mögliche Werte:

  • "controlling": Der lokale Agent nominiert das Kandidatenpaar. Das ist normalerweise die Seite, die das Angebot (Offer) erstellt hat.
  • "controlled": Der lokale Agent wartet, bis die Gegenseite ein Kandidatenpaar nominiert. Das ist normalerweise die antwortende Seite (Answer).
  • "unknown": Die Rolle steht noch nicht fest, zum Beispiel weil die Aushandlung noch nicht begonnen hat.

Direkt erzeugen kann man ein RTCIceTransport nicht. Man erreicht es über RTCDtlsTransport.iceTransport, also zum Beispiel über sender.transport.iceTransport, receiver.transport.iceTransport oder pc.sctp.transport.iceTransport. Die Eigenschaft ist vor allem beim Debuggen nützlich, beim Auswerten von Statistiken und beim Nachvollziehen von Verbindungsproblemen, etwa wenn man wissen will, welche Seite die Nominierung steuert.

Rückgabewert

Typ
"controlling" | "controlled" | "unknown"
Beschreibung
Ein String aus der Aufzählung RTCIceRole, der die aktuelle ICE-Rolle des lokalen Agenten angibt.

Beispiele

Rolle nach der Aushandlung auslesen (lokale Schleife)

const pc1 = new RTCPeerConnection();
const pc2 = new RTCPeerConnection();

// ICE-Kandidaten direkt austauschen
pc1.onicecandidate = (e) => e.candidate && pc2.addIceCandidate(e.candidate);
pc2.onicecandidate = (e) => e.candidate && pc1.addIceCandidate(e.candidate);

// Datenkanal erzwingt einen SCTP-Transport
pc1.createDataChannel('chat');

const offer = await pc1.createOffer();
await pc1.setLocalDescription(offer);
await pc2.setRemoteDescription(offer);
const answer = await pc2.createAnswer();
await pc2.setLocalDescription(answer);
await pc1.setRemoteDescription(answer);

const ice1 = pc1.sctp?.transport.iceTransport;
const ice2 = pc2.sctp?.transport.iceTransport;
console.log('pc1 (Anbieter):', ice1?.role);
console.log('pc2 (Antwortender):', ice2?.role);
pc1 (Anbieter): controlling pc2 (Antwortender): controlled

Rolle für alle Sender protokollieren

const logIceRoles = (pc) => {
  for (const sender of pc.getSenders()) {
    const ice = sender.transport?.iceTransport;
    if (!ice) continue;
    console.log(`${sender.track?.kind ?? 'leer'}: Rolle=${ice.role}, Zustand=${ice.state}`);
  }
};

const stream = await navigator.mediaDevices.getUserMedia({ audio: true });
const pc = new RTCPeerConnection();
stream.getTracks().forEach((t) => pc.addTrack(t, stream));
await pc.setLocalDescription(await pc.createOffer());
logIceRoles(pc);
audio: Rolle=unknown, Zustand=new

Rolle bei Zustandswechseln überwachen

const watchIce = (iceTransport) => {
  iceTransport.addEventListener('statechange', () => {
    console.log(`ICE-Zustand: ${iceTransport.state}, Rolle: ${iceTransport.role}`);
  });
  iceTransport.addEventListener('selectedcandidatepairchange', () => {
    const pair = iceTransport.getSelectedCandidatePair();
    const wer = iceTransport.role === 'controlling' ? 'lokal' : 'entfernt';
    console.log(`Paar nominiert (${wer}):`, pair?.local.address, '→', pair?.remote.address);
  });
};

// Aufruf, z. B. nach setLocalDescription:
// watchIce(pc.sctp.transport.iceTransport);
ICE-Zustand: checking, Rolle: controlling Paar nominiert (lokal): 192.168.0.10 → 192.168.0.20 ICE-Zustand: connected, Rolle: controlling

// Wichtig · Fallstricke

  • Browser-Unterstützung: RTCIceTransport und damit role gibt es in Chromium-Browsern (Chrome, Edge, Opera) und in Safari. In Firefox fehlt die Schnittstelle je nach Version ganz oder teilweise. Den Zugriff deshalb immer mit optionaler Verkettung absichern (sender.transport?.iceTransport?.role).
  • Vor der Aushandlung, also vor setLocalDescription() bzw. setRemoteDescription(), ist sender.transport oft null und pc.sctp ebenfalls null.
  • Der Wert kann "unknown" sein, solange die Rolle nicht feststeht. Er kann sich auch nachträglich ändern: Wenn beide Seiten dieselbe Rolle beanspruchen, löst ICE den Konflikt über einen Tie-Breaker-Wert auf. Das passiert etwa bei ICE Lite oder bei einer erneuten Aushandlung.
  • Ein ICE-Lite-Endpunkt, wie ihn manche Media-Server verwenden, ist immer "controlled". Der Browser wird in dem Fall "controlling", auch wenn er das Angebot nicht erstellt hat.
  • Die Eigenschaft ist schreibgeschützt. Die Rolle lässt sich nur indirekt steuern, nämlich darüber, wer das Offer erstellt.