Zusammenfassung

  • SIP Outbound benutzte vom Endgerät aufgebaute Flows für später eintreffende Anfragen. Damit musste ein Server keine unerreichbare Gegenverbindung durch NAT oder Firewall erfinden.
  • Mehrere Registrierungen konnten verschiedene Wege zu derselben Geräteinstanz bezeichnen. Die Zahl der Bindings war daher weder eine Gerätezahl noch die Erlaubnis, dieselbe Anfrage parallel mehrfach zuzustellen.
  • Ein Fehler 430 betraf einen gescheiterten Flow. Eine andere endgültige Antwort derselben Instanz beendete den Versuch dagegen grundsätzlich auch für ihre übrigen Wege.

Der Transportwechsel brauchte einen schon vorhandenen Weg

Die Warnung steht am Rand der eigentlichen Konstruktion. Abschnitt 13 des RFC 5626 betrachtet eine SIP-Nachricht, die für UDP zu groß wird und nach den Grundregeln über TCP gesendet werden müsste. Bei einem öffentlich erreichbaren Server klingt der Wechsel unspektakulär. Bei einem Telefon hinter einer zustandsbehafteten Grenze ist er das nicht: Der Proxy kann nicht voraussetzen, dass er von außen eine neue TCP-Verbindung zu diesem Telefon öffnen darf.

Outbound löste dieses Problem nicht mit einer pauschalen Ausnahme für große Nachrichten. Das Endgerät musste die geeigneten Flows zuvor selbst herstellen. Nur was als brauchbarer Rückweg existierte, konnte später ausgewählt werden. Die Passage ist ein nicht normativer Betriebshinweis, keine Behauptung, jede UDP-Nachricht scheitere oder jedes Telefon müsse dauerhaft jede Transportart offenhalten.

Gerade dadurch wird die zentrale Frage sichtbar. Wenn ein Telefon zwei Flows vorbereitet, besitzt der Dienst zwei Lieferwege. Er besitzt nicht automatisch zwei Telefone, zwei Benutzer oder zwei voneinander unabhängige Ausfallbereiche. Die Architektur brauchte Begriffe, die diese Dinge getrennt halten.

REGISTER war keine Einladung zu einer neuen Verbindung

Das SIP-Grundmodell von 2002 ordnete beim Registrar eine Address of Record, kurz AOR, einem oder mehreren Contacts zu. Der Location Service stellte diese Bindings dem Proxy für spätere Anfragen bereit. Der RFC 3261 ließ Registrar und Proxy als getrennte Funktionen oder als Teile desselben Systems zu. Ein REGISTER eröffnete jedoch keinen Dialog.

Die Antwort auf REGISTER konnte über dieselbe zuverlässige Verbindung zurückkommen, auf der die Anfrage eingetroffen war. Ein späteres INVITE war etwas anderes: keine Antwort auf die Registrierung, sondern eine neue Anfrage. Der gespeicherte Contact versprach nicht von selbst, dass der Server die dort beschriebene Adresse durch NAT oder Firewall erreichen konnte. Ein Client konnte eine ausgehende TCP- oder TLS-Verbindung aufbauen, ohne als entsprechender Server von außen erreichbar zu sein.

Outbound machte deshalb den vom User Agent erzeugten Flow zum Rückweg. Bei TCP war der Flow eine Verbindung. Bei UDP war er eine bidirektionale Zuordnung aus Adressen, Ports und Transportprotokoll. Die Idee darf nicht auf „TCP offenhalten“ verkürzt werden. Entscheidend war die bekannte Zuordnung zwischen Endgerät und einem bereits benutzbaren Transportweg.

Path erinnerte sich an den Rand des Netzes

Zwischen Telefon und Registrar konnte ein Edge-Proxy liegen. Sollte eine spätere Anfrage wieder über ihn laufen, musste der Dienst den Weg der Registrierung behalten. Dafür hatte der RFC 3327 den Path-Mechanismus eingeführt: Zwischenstationen ergänzten während der Registrierung einen Vektor, der mit dem Binding gespeichert und bei späteren Anfragen als Route vorangestellt werden konnte.

Path war kein Record-Route für REGISTER. Die Registrierung erzeugte weiterhin keinen Dialog. Der gespeicherte Vektor war auch keine universelle Route, die jeder fremde Absender beliebig erzwingen durfte; er diente dem Routing durch die Heimatdomäne unter deren Vertrauens- und Betriebsregeln. Darum waren Integrität und die Beziehung zu einer authentisierten Registrierung wesentlich.

Outbound ergänzte am ersten Edge einen geschützten Flow-Token und die Kennzeichnung ob. Der Token half genau diesem Edge, den passenden Flow wiederzufinden. Er war weder ein weltweiter Name des Menschen noch eine dauerhafte Bezeichnung des Telefons. Ein lokal wiederverwendeter Dateideskriptor durfte eine neue Verbindung nicht in den Besitzer alter Bindings verwandeln.

Eine Identität blieb, die Wege durften wechseln

Für mehrere gleichzeitige Flows brauchte das System zwei verschiedene Arten von Stabilität. Die instance-id bezeichnete die User-Agent-Instanz und blieb über Neustart oder Netzwechsel hinweg erhalten. Die reg-id unterschied die einzelnen Registrierungen ihrer Flows. Zusammen mit der AOR entstand der Schlüssel, der Empfänger und Weg in Beziehung setzte.

Nach einem Neustart sollte das Telefon seine Folge von reg-id-Werten absichtlich wiederverwenden. Die neue Registrierung kollidierte damit an der richtigen Stelle mit einem alten Binding und ersetzte es. „Eindeutig“ bedeutete hier nicht, für immer neue Zahlen zu produzieren. Es bedeutete, dieselbe logische Rolle so zu benennen, dass veralteter Zustand gezielt verdrängt werden konnte.

Der Contact blieb gespeichert und wurde weiterhin zum Aufbau der Zielmenge benötigt. Er verlor also nicht jede Bedeutung. Doch sein Text allein entschied nicht mehr, ob zwei Zeilen zwei Empfänger waren. Der Proxy durfte nicht gleichzeitig mehr als einen Contact derselben AOR und derselben Instanz in seine Zielmenge aufnehmen. Verschiedene Geräte unter einer AOR blieben möglich; untersagt wurde die künstliche Vervielfachung einer Instanz nur wegen ihrer Ersatzwege.

430 sagte: Dieser Flow ist fort

Der Spezifikation zufolge konnte ein Edge nach Absturz und Neustart eine Anfrage für einen Flow erhalten, den er nicht mehr kannte. Dann sollte er 430 Flow Failed an den zuständigen Proxy zurückgeben. Gab es für dieselbe AOR und Instanz ein weiteres Binding mit anderer reg-id, sollte der Proxy diesen Weg versuchen.

Das Beispiel in Abschnitt 9.3 lässt den Fehler eintreten, bevor das Telefon seinen alten Flow selbst als verloren erkannt hat. Die neue Anfrage erreicht zunächst den neu gestarteten Edge, erhält 430 und wird danach über den zweiten Edge zugestellt. Der zweite Edge trägt sich für den entstehenden Dialog in Record-Route ein. Später repariert das Telefon die beschädigte Registrierung mit derselben reg-id und einem neuen Flow-Token.

Das ist ein Ablaufbeispiel des Standards, kein Bericht über den Ausfall eines Betreibers und keine Messung einer Wiederherstellungszeit. Es verspricht auch nicht, jeden bestehenden Dialog nahtlos auf einen anderen Flow zu verschieben. Für bestimmte Mid-Dialog-Fälle ließ die Spezifikation Verfahren am Edge offen. Bewiesen ist die engere Aussage: Eine neue Anfrage konnte einen bekannten defekten Weg umgehen, bevor der Client seine eigene Fehlererkennung abgeschlossen hatte.

430 bezeichnete den Weg, nicht das Konto und nicht den Willen des Benutzers. Endgeräte sollten den Code nicht erhalten und ihn, falls doch, wie 400 behandeln. Ein manipuliertes Flow-Token führte zu einer anderen empfohlenen Reaktion, nämlich 403. Wer alle diese Fälle unter „nicht erreichbar“ zusammenfasst, entfernt genau die Information, die kontrolliertes Failover benötigt.

Eine Antwort setzte dem Ersatzweg eine Grenze

Der zweite Flow war kein Recht, so lange weiterzufragen, bis eine gewünschte Antwort erschien. Erhielt der Proxy von der Instanz eine endgültige Antwort, durfte er dieselbe Anfrage grundsätzlich nicht an ein weiteres Ziel derselben AOR und Instanz senden. Der RFC nennt für diese Regel die Ausnahmen 408 und 430.

Der Umfang ist wichtig. Es geht um dieselbe Anfrage an dieselbe Instanz, nicht um ein Verbot jedes späteren neuen Anrufs und nicht um sämtliche Wiederholungen in sämtlichen Protokollen. Ein Flow-Fehler kann den Wechsel des Weges begründen. Eine endgültige Antwort bedeutet dagegen, dass der Empfänger bereits gesprochen hat. Ein weiterer Weg darf diese Tatsache nicht in bloße Unsicherheit zurückverwandeln.

Damit erhielt Redundanz eine Stop-Regel. Ohne sie könnte eine Zielmenge aus mehreren Bindings das Telefon doppelt klingeln lassen, einen Vorgang doppelt auslösen oder eine Ablehnung wie ein Transportproblem behandeln. Mehr Erreichbarkeit entstand nur, wenn der Proxy zugleich wusste, wann weiteres Handeln falsch war.

Keepalive, Registrierung und NAT hatten verschiedene Uhren

Ein lebender Flow und eine gültige Registrierung waren nicht dasselbe. Ein vorübergehender Fehler wie 503 beim Auffrischen des Bindings zwang den Client nicht, eine Verbindung zu schließen, die weiterhin auf Keepalives antwortete. Umgekehrt konnte eine empfangene Antwort beweisen, dass der alte Flow nicht mehr derselbe war: Meldete STUN bei UDP eine veränderte XOR-MAPPED-ADDRESS, galt die frühere Zuordnung als gescheitert.

Die Outbound-Keepalives arbeiteten bis zum nächsten SIP-Hop, nicht bis zum angerufenen Menschen und nicht bis zum Audiostrom. Das Flow-Timer-Feld bezeichnete die erwartete Häufigkeit mit zusätzlichem Spielraum, keine Liefergarantie für den ganzen Zeitraum. Kürzere Intervalle konnten Ausfälle schneller entdecken, kosteten aber Batterie und Serverlast. Mehrere Flows begrenzten die Lücke, ohne diese Kosten aufzuheben.

Der RFC 6223 machte später die Keepalive-Aushandlung zwischen benachbarten Hops mit dem Via-Parameter keep ausdrücklich. Er erklärte ebenso ausdrücklich, dass diese Aushandlung keine Wiederverwendung einer Verbindung definiert. Einen Weg am Leben zu halten und zu entscheiden, welche Rückwärtsanfrage ihn benutzen darf, blieben getrennte Aufgaben.

Auch verwandte Mechanismen blieben voneinander getrennt

Der RFC 5923 regelte TLS-Verbindungsaliasse zwischen SIP-Nachbarn, die in beide Richtungen Verbindungen initiieren konnten. Authentisierung und die lokale Entscheidung, einen Kanal wiederzuverwenden, blieben dabei maßgeblich. Ein offener Socket war nicht automatisch eine allgemeine Berechtigung für rückwärtigen Verkehr; bei erzwungener Öffnungsrichtung verwies der Anwendungsbereich gerade auf Outbound.

Der RFC 5627 löste ein anderes Identitätsproblem. Bei einer blinden Vermittlung konnte ein Rückruf an die AOR ein anderes Gerät oder die Mailbox erreichen, obwohl die konkrete beteiligte Instanz gemeint war. Eine GRUU bot dafür eine von außen nutzbare, instanzbezogene URI über die Domäne. Sie war weder der Flow-Token des Edge noch der Beweis, dass dieser Flow noch lebte.

Im WebSocket-Szenario des RFC 7118 wurde die Trennung besonders anschaulich. Ein Browser-Client, der seine lokale Transportadresse nicht kannte, konnte unter den beschriebenen Outbound-Bedingungen einen zufälligen Namen unter .invalid in Via und Contact verwenden. Die eingehende Signalisierung kam über Proxy und bestehenden Flow zurück. Das war eine bedingte Möglichkeit dieses Szenarios, keine allgemeine Freigabe unerreichbarer Contacts; Zertifikatsprüfung blieb erforderlich, und Medien lagen außerhalb des Umfangs.

Das SIP-Parameterregister der IANA hält Namen, Codes und Verweise fest. Es misst weder Verbreitung noch korrekte Implementierung. Die historische Leistung lag in einer schmaleren, überprüfbaren Unterscheidung: Zwei Rückwege konnten verfügbar sein, ohne den Empfänger und seine bereits gegebene Antwort zu verdoppeln.