Start · Sprachen · JavaScript · Referenz · RTCDtlsTransport: error

RTCDtlsTransport: error

Ereignis

Wird an einem <code>RTCDtlsTransport</code> ausgelöst, wenn auf der DTLS-Transportebene einer <code>RTCPeerConnection</code> ein Fehler auftritt, etwa ein fehlgeschlagener Handshake.

seit JavaScript WebRTC 1.0 – eingeschränkte Browser-Unterstützung Kategorie: webapi

Signatur

dtlsTransport.addEventListener("error", handler)

Beschreibung

Das error-Ereignis eines RTCDtlsTransport meldet Fehler auf der DTLS-Ebene (Datagram Transport Layer Security). Über diese Ebene laufen in WebRTC die verschlüsselten Medienpakete (SRTP) und die Datenkanäle (SCTP). Das Ereignis ist ein RTCErrorEvent. Seine Eigenschaft error enthält ein RTCError-Objekt mit den Einzelheiten zum Fehler.

Typische Auslöser sind:

  • errorDetail === "dtls-failure": Der DTLS-Handshake ist gescheitert oder die Gegenstelle hat einen DTLS-Alert gesendet. Den Alert-Code findest du in receivedAlert bzw. sentAlert.
  • errorDetail === "fingerprint-failure": Das Zertifikat der Gegenstelle passt zu keinem der im SDP angekündigten Fingerabdrücke (a=fingerprint).

Das zugehörige RTCDtlsTransport-Objekt bekommst du über RTCRtpSender.transport, RTCRtpReceiver.transport oder RTCSctpTransport.transport. Den Handler registrierst du mit addEventListener("error", …) oder über die Eigenschaft onerror. Nach einem solchen Fehler wechselt der Transport normalerweise in den Zustand "failed". Die Verbindung musst du dann neu aushandeln, zum Beispiel per ICE-Restart oder mit einer neuen RTCPeerConnection.

Parameter

Name Typ Default Beschreibung
$type Pflicht string Name des Ereignisses, hier immer "error".
$handler Pflicht (event: RTCErrorEvent) => void Callback, der das RTCErrorEvent erhält. Die Fehlerdetails stehen in event.error (RTCError mit errorDetail, receivedAlert, sentAlert und message).
$options boolean|AddEventListenerOptions false Optionale Listener-Optionen wie once oder signal.

Rückgabewert

Typ
void
Beschreibung
addEventListener gibt nichts zurück. Der Handler bekommt ein RTCErrorEvent, dessen Eigenschaft error ein RTCError enthält.

Beispiele

DTLS-Fehler mit addEventListener auswerten

const pc = new RTCPeerConnection();
const stream = await navigator.mediaDevices.getUserMedia({ audio: true });
const sender = pc.addTrack(stream.getAudioTracks()[0], stream);

// transport ist erst nach setLocalDescription/setRemoteDescription gesetzt
const offer = await pc.createOffer();
await pc.setLocalDescription(offer);

const dtls = sender.transport;
dtls?.addEventListener('error', (event) => {
  const { errorDetail, receivedAlert, sentAlert, message } = event.error;
  switch (errorDetail) {
    case 'fingerprint-failure':
      console.error('Zertifikat passt nicht zum SDP-Fingerabdruck!');
      break;
    case 'dtls-failure':
      console.error(`DTLS-Fehler: ${message} (empfangen: ${receivedAlert}, gesendet: ${sentAlert})`);
      break;
    default:
      console.error('Unbekannter Transportfehler:', event.error);
  }
});
DTLS-Fehler: ... (empfangen: 40, gesendet: null)

onerror-Eigenschaft beim Datenkanal-Transport

const pc = new RTCPeerConnection();
pc.createDataChannel('chat');
await pc.setLocalDescription(await pc.createOffer());

const dtls = pc.sctp?.transport;
if (dtls) {
  dtls.onerror = (event) => {
    console.warn('DTLS-Fehler am Datenkanal:', event.error.errorDetail);
  };
}

Fallback über statechange und Listener aufräumen

const watchDtls = (transport, onFail) => {
  const controller = new AbortController();
  const { signal } = controller;

  // Nicht jeder Browser feuert 'error', 'failed' kommt aber zuverlässig
  transport.addEventListener('error', (e) => onFail(e.error.errorDetail), { signal });
  transport.addEventListener('statechange', () => {
    if (transport.state === 'failed') onFail('state-failed');
  }, { signal });

  return () => controller.abort(); // entfernt beide Listener
};

const pc = new RTCPeerConnection();
const [track] = (await navigator.mediaDevices.getUserMedia({ video: true })).getTracks();
const sender = pc.addTrack(track);
await pc.setLocalDescription(await pc.createOffer());

const stop = watchDtls(sender.transport, (reason) => {
  console.log('Transport ausgefallen:', reason);
  pc.restartIce();
});
// später: stop();
Transport ausgefallen: state-failed

// Wichtig · Fallstricke

  • Browser-Unterstützung: Das error-Ereignis und onerror an RTCDtlsTransport sind nicht in allen Browsern umgesetzt. Beobachte zusätzlich statechange bzw. state === "failed" und RTCPeerConnection.connectionState.
  • Transport erst nach der Aushandlung verfügbar: sender.transport und pc.sctp sind null, bis eine lokale bzw. entfernte Beschreibung gesetzt ist. Registriere den Handler also erst danach.
  • Gemeinsamer Transport: Mit Bundling (max-bundle) teilen sich meist alle Sender und Empfänger denselben RTCDtlsTransport. Ein einzelner Listener reicht dann aus. Wenn du mehrfach registrierst, bekommst du doppelte Meldungen.
  • Sicherheit: Ein "fingerprint-failure" kann auf einen Man-in-the-Middle-Angriff oder einen manipulierten Signalisierungskanal hindeuten. Baue die Verbindung dann nicht blind erneut mit denselben SDP-Daten auf. Sichere den Signalisierungsweg (HTTPS/WSS) ab.
  • Die Alert-Codes in receivedAlert/sentAlert sind numerische TLS-Alert-Werte (z. B. 40 = handshake_failure) oder null.