16. Proxy-Verhalten (Proxy Behavior)
16.1 Überblick (Overview)
Ein SIP-Proxy ist ein Element, das SIP-Anfragen an einen User Agent Server (UAS) und SIP-Antworten an einen User Agent Client (UAC) weiterleitet. Eine Anfrage kann auf dem Weg zum UAS mehrere Proxys durchlaufen. Jeder Proxy trifft eine Routing-Entscheidung und ändert die Anfrage, bevor er sie an das nächste Element weiterleitet. Antworten werden über dieselbe Reihe von Proxys in umgekehrter Reihenfolge geroutet.
Proxy zu sein ist eine logische Rolle, die ein SIP-Element spielen kann. Wenn eine Anfrage eintrifft, muss ein Element, das die Rolle eines Proxys spielen kann, zunächst entscheiden, ob es selbst auf die Anfrage antworten muss. Beispielsweise kann die Anfrage ungültig formatiert sein oder der Proxy benötigt Anmeldeinformationen vom Client, bevor er als Proxy agiert. Das Element darf mit einem beliebigen geeigneten Fehlercode antworten (KANN). Wenn es direkt auf die Anfrage antwortet, spielt dieses Element die Rolle eines UAS und muss sich gemäß Abschnitt 8.2 verhalten.
Ein Proxy kann für jede neue Anfrage entweder zustandsbehaftet (stateful) oder zustandslos (stateless) arbeiten. Wenn er zustandslos ist, agiert der Proxy als einfaches Weiterleitungselement. Er trifft Targeting- und Routing-Entscheidungen basierend auf der Anfrage und leitet die Anfrage an ein einzelnes Element flussabwärts weiter. Alle empfangenen Antworten werden einfach flussaufwärts weitergeleitet. Ein zustandsloser Proxy verwirft alle Informationen über die Nachricht, nachdem er sie weitergeleitet hat. Ein zustandsbehafteter Proxy speichert Informationen (insbesondere den Transaktionsstatus) über jede empfangene Anfrage und über alle Anfragen, die als Ergebnis der Verarbeitung dieser Anfrage gesendet werden. Er verwendet diese Informationen, um die Verarbeitung künftiger, mit dieser Anfrage verbundener Nachrichten zu beeinflussen. Ein zustandsbehafteter Proxy darf eine Anfrage „forken“ (an mehrere Ziele routen). Anfragen, die an mehrere Orte weitergeleitet werden, MÜSSEN zustandsbehaftet verarbeitet werden.
Je nach den Umständen darf ein Proxy eine Anfrage zustandslos bezüglich der Transaktion über einen zustandsbehafteten Transport (wie TCP) weiterleiten (KANN). Beispielsweise darf ein Proxy eine Anfrage zustandslos bezüglich der Transaktion zwischen zwei TCP-Verbindungen weiterleiten, solange er in der Nachricht genügend Informationen enthält, um die Antwort über dieselbe Verbindung weiterzuleiten, über die die Anfrage eingetroffen ist. Anfragen, die zwischen verschiedenen Transporttypen weitergeleitet werden, bei denen das TU eine aktive Rolle übernehmen muss, um eine zuverlässige Zustellung über einen der Transporte zu gewährleisten, MÜSSEN zustandsbehaftet bezüglich der Transaktion weitergeleitet werden.
Ob zustandsbehaftet oder zustandslos, ein Proxy darf jederzeit während der Verarbeitung der Anfrage zu zustandslosem Verhalten übergehen (KANN), solange er nichts getan hat, was dies von vornherein ausschließt (wie Forking oder das Erzeugen einer 100-Antwort). Bei diesem Übergang verwirft er einfach den gesamten Status. Ein Proxy SOLLTE keine CANCEL-Anfrage initiieren.
Egal ob der Proxy zustandsbehaftet oder zustandslos arbeitet, der Großteil der Anfragenverarbeitung ist identisch. Die folgenden Unterabschnitte sind aus der Sicht eines zustandsbehafteten Proxys beschrieben. Der letzte Abschnitt gibt an, wo ein zustandsloser Proxy sich anders verhält.
16.2 Zustandsbehafteter Proxy (Stateful Proxy)
Wenn er zustandsbehaftet arbeitet, ist der Proxy eine reiner SIP-Transaktionsverarbeitungs-Engine. Sein Verhalten wird hier in Begriffen der in Abschnitt 17 definierten Server- und Client-Transaktionen modelliert. Ein zustandsbehafteter Proxy besitzt, einer oder mehreren Client-Transaktionen zugeordnet, Server-Transaktionen, die von einer Proxy-Verarbeitungskomponente höherer Ebene verwaltet werden (siehe Abbildung 3, genannt Proxy-Kern). Eingehende Anfragen werden von der Server-Transaktion verarbeitet. Die aus der Server-Transaktion stammende Anfrage wird an den Proxy-Kern übergeben. Der Proxy-Kern bestimmt, wohin die Anfrage geroutet wird (ein oder mehrere Orte des nächsten Hops). Das Senden der Anfrage an jeden Ort des nächsten Hops wird von einer jeweils zugeordneten Client-Transaktion verarbeitet. Der Proxy-Kern sammelt die Antworten der Client-Transaktionen und verwendet sie, um Antworten auf der Server-Transaktion zu senden.
Für jede neue Anfrage erstellt ein zustandsbehafteter Proxy eine neue Server-Transaktion. Alle Retransmissionen der Anfrage werden von dieser Server-Transaktion gemäß Abschnitt 17 verarbeitet. Der Proxy-Kern MUSS als UAS handeln, indem er eine unmittelbare vorläufige Antwort (wie 100 Trying) auf dieser Server-Transaktion sendet, wie in Abschnitt 8.2.6 beschrieben. Daher SOLLTE ein zustandsbehafteter Proxy keine 100 (Trying)-Antwort für eine Nicht-INVITE-Anfrage erzeugen.
Dies ist ein Modell des Proxy-Verhaltens, nicht ein Software-Modell. Implementierungen dürfen jeden Ansatz wählen, der das von diesem Modell definierte externe Verhalten reproduziert.
Für jede neue Anfrage (einschließlich unbekannter Methoden) MUSS ein Element, das die Anfrage proxifizieren will:
1. Die Anfrage validieren (Abschnitt 16.3)
2. Routing-Informationen vorverarbeiten (Abschnitt 16.4)
3. Die Ziele der Anfrage bestimmen (Abschnitt 16.5)
+--------------------+
| | +---+
| | | C |
| | | T |
| | +---+
+---+ | Proxy | +---+ CT = Client Transaction
| S | | "Higher" Layer | | C |
| T | | | | T | ST = Server Transaction
+---+ | | +---+
| | +---+
| | | C |
| | | T |
| | +---+
+--------------------+
Abbildung 3: Modell eines zustandsbehafteten Proxys
4. Die Anfrage an jedes Ziel weiterleiten (Abschnitt 16.6)
5. Alle Antworten verarbeiten (Abschnitt 16.7)
16.3 Validierung der Anfrage (Request Validation)
Bevor ein Element eine Anfrage proxifiziert, MUSS es die Gültigkeit der Nachricht validieren. Eine gültige Nachricht MUSS die folgenden Prüfungen bestehen.
1. Vernünftige Syntax (Reasonable Syntax)
2. URI-Schema (URI scheme)
3. Max-Forwards
4. (Optional) Schleifenerkennung (Loop Detection)
5. Proxy-Require
6. Proxy-Authorization
Wenn eine dieser Prüfungen fehlschlägt, MUSS das Element als User Agent Server handeln (siehe Abschnitt 8.2) und mit einem Fehlercode antworten.
Ein Proxy ist nicht verpflichtet, zusammengeführte (merged) Anfragen zu erkennen, und DARF sie nicht als Fehlerzustand behandeln. Das Endpunkt, das die Anfrage empfängt, löst die Zusammenführung gemäß Abschnitt 8.2.2.2 auf.
-
Prüfung auf vernünftige Syntax (Reasonable syntax check)
Die Anfrage MUSS ausreichend formatiert sein, um von der Server-Transaktion verarbeitet zu werden. Alle an den folgenden Schritten zur Anfragevalidierung oder Anfragenweiterleitung beteiligten Komponenten MÜSSEN ausreichend formatiert sein. Andere Komponenten SOLLTEN ignoriert werden, unabhängig davon, ob ihr Format korrekt ist, und beim Weiterleiten der Nachricht unverändert bleiben. Beispielsweise lehnt ein Element eine Anfrage nicht ab, nur weil das Date-Headerfeld falsch formatiert ist. Ebenso entfernt ein Proxy ein falsch formatiertes Date-Headerfeld nicht vor dem Weiterleiten der Anfrage.
Dieses Protokoll ist darauf ausgelegt, erweitert zu werden. Künftige Erweiterungen können jederzeit neue Methoden oder Headerfelder definieren. Ein Element DARF eine Anfrage nicht mit der Begründung ablehnen, sie enthalte unbekannte Methoden oder Headerfelder.
-
Prüfung des URI-Schemas (URI scheme check)
Wenn der Request-URI eine URI ist, deren Schema der Proxy nicht versteht, SOLLTE der Proxy die Anfrage mit einer 416 (Unsupported URI Scheme)-Antwort ablehnen.
-
Max-Forwards-Prüfung
Das Max-Forwards-Headerfeld (Abschnitt 20.22) wird verwendet, um die Anzahl der Elemente zu begrenzen, die eine SIP-Anfrage durchlaufen kann.
Wenn die Anfrage kein Max-Forwards-Headerfeld enthält, besteht diese Prüfung.
Wenn die Anfrage ein Max-Forwards-Headerfeld mit einem Wert größer als Null enthält, besteht diese Prüfung.
Wenn die Anfrage ein Max-Forwards-Headerfeld mit dem Wert Null (0) enthält, DARF das Element die Anfrage nicht weiterleiten. Wenn die Anfrage an OPTIONS gerichtet war, darf das Element als letzter Empfänger handeln und gemäß Abschnitt 11 antworten (KANN). Andernfalls MUSS das Element eine 483 (Too many hops)-Antwort zurückgeben.
-
Optionale Schleifenerkennungs-Prüfung (Optional Loop Detection check)
Ein Element darf vor dem Weiterleiten einer Anfrage auf Weiterleitungs-Schleifen prüfen (KANN). Wenn die Anfrage ein Via-Headerfeld mit einem sent-by-Wert enthält, der gleich dem ist, den der Proxy zuvor gesetzt hat, wurde die Anfrage von diesem Element bereits weitergeleitet. Die Anfrage hat eine Schleife gebildet oder ist legitimerweise als Spirale durch das Element gelaufen. Um zu bestimmen, ob die Anfrage eine Schleife gebildet hat, darf das Element die in Schritt 8 von Abschnitt 16.6 beschriebene Berechnung des branch-Parameters für diese Nachricht ausführen und mit dem im Via-Headerfeld empfangenen Parameter vergleichen (KANN). Stimmen die Parameter überein, hat die Anfrage eine Schleife gebildet. Unterscheiden sie sich, hat die Anfrage eine Spirale gebildet und die Verarbeitung wird fortgesetzt. Wenn eine Schleife erkannt wird, darf das Element eine 482 (Loop Detected)-Antwort zurückgeben (KANN).
-
Proxy-Require-Prüfung
Künftige Erweiterungen dieses Protokolls können Funktionen einführen, die eine spezielle Verarbeitung durch Proxys erfordern. Endpunkte schließen ein Proxy-Require-Headerfeld in Anfragen ein, die diese Funktionen verwenden, und weisen den Proxy an, die Anfrage nicht zu verarbeiten, es sei denn, die Funktion wird verstanden.
Wenn die Anfrage ein Proxy-Require-Headerfeld (Abschnitt 20.29) mit einem oder mehreren option-tags enthält, die dieses Element nicht versteht, MUSS das Element eine 420 (Bad Extension)-Antwort zurückgeben. Die Antwort MUSS ein Unsupported-Headerfeld (Abschnitt 20.40) enthalten, das die option-tags aufzählt, die das Element nicht verstanden hat.
-
Proxy-Authorization-Prüfung
Wenn ein Element vor dem Weiterleiten einer Anfrage Anmeldeinformationen benötigt, MUSS es die Anfrage gemäß Abschnitt 22.3 untersuchen. Dieser Abschnitt definiert auch, was das Element bei einem Fehlschlag der Untersuchung tun muss.
16.4 Vorbereitung der Anfrage für das Routing (Preparing the Request for Routing)
Bevor die Anfrage weitergeleitet wird, MUSS das Element die das Routing beeinflussenden Headerfelder prüfen und ändern. Das Record-Route-Headerfeld (Abschnitt 20.30) verbleibt unverändert in der Anfrage. Zusätzlich MUSS das Element die folgenden Schritte ausführen:
1. Wenn die Anfrage ein Route-Headerfeld (Abschnitt 20.34) enthält und dessen erster Wert (oberster) nicht auf das Element zeigt, fährt das Element mit Abschnitt 16.6 fort, ohne die Anfrage zu ändern. Das Element fügt der Anfrage keinen Record-Route-Headerfeldwert hinzu. Das Element leitet die Anfrage unverändert an das nächste Element weiter.
Hinweis: Dass der oberste Route-Headerfeldwert nicht auf das Element zeigt, bedeutet, dass das Element ein Route-Headerfeld verarbeitet, das von einem früheren Element eingefügt wurde, das kein Loose-Routing implementiert.
2. Wenn die Anfrage ein Route-Headerfeld (Abschnitt 20.34) enthält und dessen erster Wert auf das Element zeigt:
Wenn das Element Loose-Routing unterstützt, MUSS es den ersten Wert des Route-Headerfelds entfernen. Die Loose-Routing-Verfahren kommen zur Anwendung.
Wenn das Element kein Loose-Routing implementiert, MUSS es die Strict-Routing-Verfahren der RFC 2543 ausführen.
3. Schließlich darf das Element der Anfrage einen Record-Route-Headerfeldwert hinzufügen, der auf sich selbst zeigt (KANN).
16.5 Bestimmung der Ziele der Anfrage (Determining Request Targets)
Wenn ein Element eine dialogerstellende Anfrage (z. B. INVITE) verarbeitet, MUSS es den Routensatz (route set) des Dialogs initialisieren. Der Routensatz wird initialisiert, wenn das Element einen Record-Route-Headerfeldwert in die Anfrage einfügt.
Wenn ein Element eine dialogerstellende Anfrage verarbeitet, MUSS es die Anfrage an einen oder mehrere Orte weiterleiten. Dies wird Zielmenge (target set) genannt.
Die Art und Weise, wie das Element die Ziele bestimmt, hängt von der Art der Anfrage (dialogerstellend oder innerhalb eines Dialogs) und davon ab, ob der Request-URI eine vom Element verwaltete Domäne angibt.
1. Wenn die Anfrage kein Route-Headerfeld enthält, MUSS das Element prüfen, ob die vom Request-URI bezeichnete Ressource im Besitz des Elements ist. Wenn die URI eine Ressource innerhalb einer vom Element verwalteten Domäne angibt, MUSS es den Wert des Request-URI durch eine Menge ersetzen, die den Ort dieser Ressource darstellt (z. B. registrierte Contacts oder der Home-Agent der Ressource). Dies geschieht normalerweise durch Ausführung des Lokalisierungsdienstes des Elements. Der Ort kann durch Registrierung (Abschnitt 10), Umleitung oder andere Mittel stammen.
Wenn der Request-URI keine Ressource einer verwalteten Domäne angibt, platziert das Element den Request-URI in die Zielmenge.
2. Wenn die Anfrage ein Route-Headerfeld enthält, MUSS das Element die Zielmenge auf den Ort setzen, auf den der erste Wert (oberster) des Route-Headerfelds zeigt. Wenn das Element Loose-Routing implementiert, wurde der erste Wert des Route-Headerfelds bereits (in Schritt 2 von Abschnitt 16.4) entfernt, daher wird der nächste Route-Headerfeldwert (falls vorhanden) zur Zielmenge. Der URI des Request-URI wird nicht zur Berechnung der Zielmenge verwendet.
Für eine Anfrage innerhalb eines Dialogs (z. B. BYE) MUSS das Element die Zielmenge auf den ersten Wert des Routensatzes des Dialogs setzen. Der entfernte Ziel-URI des Dialogs wird nicht zur Berechnung der Zielmenge verwendet.
Das Element darf lokale Richtlinienprüfungen an der Zielmenge vor dem Weiterleiten durchführen (KANN). Das Element darf die Zielmenge ändern, um bei Erhalt einer 3xx-Antwort zu rekursieren (KANN).
16.6 Weiterleiten der Anfrage (Forwarding the Request)
Bevor ein Element eine Anfrage weiterleitet (oder proxifiziert), MUSS es für jedes Ziel seiner Zielmenge die folgenden Schritte ausführen:
1. Kopie erstellen (Make a copy)
Das Element erstellt eine Kopie der empfangenen Anfrage und ändert diese Kopie in den folgenden Schritten. Das Element DARF die empfangene Anfrage nicht direkt ändern. Dies ermöglicht es dem Element, die ursprüngliche Anfrage weiterzuleiten, falls ein Fehler oder eine Anomalie auftritt.
2. Multicast-Adresse gegen einen multicast-fähigen Host austauschen (Swap multicast address for a multicast-capable host)
Wenn der Host-Teil des Request-URI die Adresse einer IP-Multicast-Gruppe ist, darf das Element den Host-Teil durch eine Unicast-Adresse eines multicast-fähigen Hosts ersetzen (KANN), der die Gruppe abhört und die Anfrage verarbeiten kann. Dies verhindert, dass andere Hosts der Multicast-Gruppe eine Kopie der Anfrage empfangen und verarbeiten.
3. Record-Route-Wert bei Bedarf hinzufügen (Add a Record-Route value if necessary)
Wenn das Element einen Record-Route-Headerfeldwert einfügt, MUSS es am Anfang der Kopie einen neuen Record-Route-Headerfeldwert einfügen, der dem folgenden URI entspricht:
o Wenn das Element die Anfrage über UDP empfangen, aber über TCP sendet, MUSS der URI eine SIP-URI sein und den Hostnamen oder die IP-Adresse (und den optionalen Port) des Elements sowie einen transport-Parameter enthalten, der den abgehörten Transport angibt. Wenn das Element ursprünglich über UDP empfangen und über TCP sendet, MUSS der URI das sip:-Schema verwenden.
o Wenn das Element die Anfrage über TCP empfangen, aber über UDP sendet, MUSS der URI eine SIP-URI sein und den Hostnamen oder die IP-Adresse (und den optionalen Port) des Elements sowie einen transport=udp-Parameter enthalten.
o Wenn das Element über TLS empfangen und über eine Nicht-TLS-Verbindung sendet (oder umgekehrt), MUSS der URI eine SIPS-URI oder SIP-URI sein, je nachdem, ob der Empfangstransport TLS war.
o Andernfalls darf das Element eine SIP- oder SIPS-URI verwenden, die seinen Hostnamen oder seine IP-Adresse (und den optionalen Port) enthält. Das Element darf auf einem anderen Port lauschen als dem, über den die Anfrage eingetroffen ist. Das Element darf einen transport-Parameter zur Angabe seiner Fähigkeiten enthalten (KANN).
Das Element MUSS den lr-Parameter in dem URI enthalten, den es in das Record-Route-Headerfeld einfügt (siehe Abschnitt 19.1.1).
4. Routing-Informationen verarbeiten (Process routing information)
Wenn das Element Loose-Routing implementiert, ändert es den Request-URI nicht. Andernfalls, wenn es ein Strict-Router ist, MUSS das Element den ersten Wert des Route-Headerfelds in den Request-URI kopieren und ihn aus dem Route-Headerfeld entfernen. Das Element DARF die Parameter in diesem URI in keiner Weise ändern, bevor es ihn in den Request-URI platziert.
Das Element darf prüfen, ob einer der Werte des Route-Headerfelds auf sich selbst zeigt. Wenn ja, darf es diesen Wert entfernen (KANN).
5. Request-URI zur Kopie hinzufügen (Add the Request-URI to the copy)
Wenn das Element ein Strict-Router ist und der Request-URI der Kopie aus dem ersten Wert des Route-Headerfelds stammt, MUSS es diesen aus dem Route-Headerfeld entfernen.
6. Max-Forwards verringern (Decrement Max-Forwards)
Wenn die Kopie kein Max-Forwards-Headerfeld enthält, MUSS das Element es auf 70 setzen. Andernfalls MUSS das Element den Feldwert um 1 verringern.
7. Adresse, Port und Transport des nächsten Hops bestimmen (Determine the next-hop address, port, and transport)
Das Element bestimmt für ein Mitglied der Zielmenge die Adresse, den Port und den Transport.
War die Zielmenge ein Route-Headerfeldwert, werden Adresse, Port und Transport durch Auflösen dieses URI gemäß den in Anhang C der RFC 2543 beschriebenen Verfahren bestimmt.
War die Zielmenge der Request-URI, werden die Verfahren der RFC 3263 unter Verwendung der Methode und des Request-URI angewendet.
8. Eigenes Via zur Kopie hinzufügen (Add own Via to the copy)
Das Element MUSS am Anfang des Via-Headerfelds der Kopie einen neuen Via-Headerfeldwert einfügen, der seine sent-by-Adresse enthält. Die Adresse MUSS der Ort sein, an dem das Element auf diesem Transport lauscht, und es MUSS sicherstellen, dass es die Antwort über diese Verbindung empfängt.
Der Via-Headerfeldwert MUSS den branch-Parameter enthalten, den das Element beim Senden der Anfrage an dieses Ziel über diesen Transport gewählt hat.
Der branch-Parameter MUSS für alle vom Element gesendeten Anfragen (außer CANCEL und Nicht-2xx-ACK) eindeutig sein. Diese Anforderung verlangt Eindeutigkeit in Raum und Zeit. Um diesen branch-Parameter zu berechnen, MUSS das Element einen bestimmten Teil der Anfrage (eine Zeichenkette, die mit dem Magic-Cookie „z9hG4bK“ der RFC 3261 beginnt) hashen.
Wenn ein Proxy eine Anfrage weiterleitet, erstellt er eine Kopie, die alle empfangenen Werte (einschließlich Request-URI) enthält, und fügt sein Via hinzu. Alle Parameter, die die Syntax der Anfrage bilden, und alle Headerfeldwerte, die das Routing oder die Annahme der Anfrage beeinflussen, MÜSSEN in die Hash-Berechnung einbezogen werden. Dies ist notwendig, um eine Anfrage, die eine Schleife gebildet hat, von einer Anfrage zu unterscheiden, deren Routing-Parameter geändert wurden, bevor sie zu diesem Server zurückkehrte.
Die Anfragemethode DARF nicht in die Berechnung des branch-Parameters einbezogen werden. Insbesondere MÜSSEN CANCEL- und ACK-Anfragen (für Nicht-2xx-Antworten) denselben branch-Wert wie die entsprechende Anfrage haben, die sie abbrechen oder bestätigen. Der branch-Parameter wird verwendet, um diese Anfragen auf dem Server zu korrelieren (siehe Abschnitte 17.2.3 und 9.2).
9. Content-Length-Headerfeld bei Bedarf hinzufügen (Add a Content-Length header field if necessary)
Wenn die Anfrage über einen streambasierten Transport an den nächsten Hop gesendet wird und die Kopie kein Content-Length-Headerfeld enthält, MUSS der Proxy eines mit dem korrekten Wert für den Nachrichtentext der Anfrage einfügen (Abschnitt 20.14).
10. Anfrage weiterleiten (Forward Request)
Ein zustandsbehafteter Proxy MUSS für diese Anfrage eine neue Client-Transaktion erstellen, wie in Abschnitt 17.1 beschrieben, und die Transaktion anweisen, die Anfrage unter Verwendung der in Schritt 7 bestimmten Adresse, des Ports und des Transports zu senden.
11. Timer C setzen (Set timer C)
Um den Fall abzudecken, dass eine INVITE-Anfrage keine finale Antwort erzeugt, verwendet das TU einen Timer namens Timer C. Wenn eine INVITE-Anfrage proxifiziert wird, MUSS Timer C für jede Client-Transaktion gesetzt werden. Der Timer MUSS länger als 3 Minuten sein. Abschnitt 16.7 Punkt 2 erklärt, wie dieser Timer mit vorläufigen Antworten zurückgesetzt wird, und Abschnitt 16.8 erklärt die Verarbeitung bei seinem Ablauf.
16.7 Verarbeitung von Antworten (Response Processing)
Wenn ein Element eine Antwort empfängt, versucht es zunächst, eine Client-Transaktion (Abschnitt 17.1.3) zu finden, die mit der Antwort übereinstimmt. Wenn keine gefunden wird, MUSS das Element die Antwort (selbst wenn es sich um eine Informationsantwort handelt) als zustandsloser Proxy verarbeiten (siehe unten). Wenn eine Übereinstimmung gefunden wird, wird die Antwort an die Client-Transaktion übergeben.
Das Weiterleiten von Antworten, für die keine Client-Transaktion (oder allgemeiner kein Wissen über eine gesendete zugehörige Anfrage) gefunden wird, erhöht die Robustheit. Insbesondere stellt dies sicher, dass „verspätete“ 2xx-Antworten auf INVITE-Anfragen ordnungsgemäß weitergeleitet werden.
Wenn die Client-Transaktionen die Antworten an die Proxy-Schicht übergeben, MUSS die folgende Verarbeitung stattfinden:
1. Den passenden Antwortkontext finden
2. Timer C für vorläufige Antworten zurücksetzen
3. Das oberste Via entfernen
4. Die Antwort zum Antwortkontext hinzufügen
5. Prüfen, ob diese Antwort sofort weitergeleitet werden soll
6. Bei Bedarf die beste finale Antwort aus dem Antwortkontext auswählen
Wenn nach Beendigung aller mit dem Antwortkontext verbundenen Client-Transaktionen noch keine finale Antwort weitergeleitet wurde, MUSS der Proxy die beste Antwort auswählen und weiterleiten, die er bis dahin gesehen hat.
Die folgende Verarbeitung MUSS für jede weitergeleitete Antwort durchgeführt werden. Es ist wahrscheinlich, dass mehrere Antworten für jede Anfrage weitergeleitet werden: mindestens jede vorläufige und eine finale Antwort.
7. Authorization-Headerfeldwerte bei Bedarf aggregieren
8. Record-Route-Headerfeldwerte optional umschreiben
9. Die Antwort weiterleiten
10. Erforderliche CANCEL-Anfragen erzeugen
Jeder der obigen Schritte wird im Folgenden detailliert:
1. Kontext finden (Find Context)
Der Proxy sucht den „Antwortkontext“, den er vor dem Weiterleiten der ursprünglichen Anfrage mit dem in Abschnitt 16.6 beschriebenen Schlüssel erstellt hat. Die restlichen Verarbeitungsschritte finden in diesem Kontext statt.
2. Timer C für vorläufige Antworten zurücksetzen (Update timer C for provisional responses)
Bei einer INVITE-Transaktion, wenn die Antwort eine vorläufige Antwort mit einem Statuscode von 101 bis 199 einschließlich (also außer 100) ist, MUSS der Proxy den Timer C dieser Client-Transaktion zurücksetzen. Der Timer darf auf einen anderen Wert zurückgesetzt werden, dieser Wert MUSS jedoch länger als 3 Minuten sein.
3. Via
Der Proxy entfernt den obersten Wert des Via-Headerfelds aus der Antwort.
Wenn in der Antwort kein Via-Headerfeldwert verbleibt, war die Antwort an dieses Element gerichtet und DARF NICHT weitergeleitet werden. Die restliche Verarbeitung dieses Abschnitts wird auf diese Nachricht nicht angewendet; stattdessen werden die UAC-Verarbeitungsregeln aus Abschnitt 8.1.3 befolgt (die Transport-Schicht-Verarbeitung ist bereits erfolgt).
Dies geschieht beispielsweise, wenn das Element CANCEL-Anfragen erzeugt, wie in Abschnitt 10 beschrieben.
4. Antwort zum Kontext hinzufügen (Add response to context)
Empfangene finale Antworten werden im Antwortkontext gespeichert, bis eine finale Antwort auf der Server-Transaktion gesendet wird, die mit diesem Kontext verbunden ist. Die Antwort kann Kandidat für die beste finale Antwort sein, die auf dieser Server-Transaktion zurückgegeben wird. Informationen aus dieser Antwort können benötigt werden, um die beste Antwort zu bilden, selbst wenn diese Antwort nicht ausgewählt wird.
Wenn der Proxy wählt, über einen beliebigen Contact einer 3xx-Antwort zu rekursieren, indem er ihn zur Zielmenge hinzufügt, MUSS er ihn aus der Antwort entfernen, bevor er die Antwort zum Antwortkontext hinzufügt. Wenn jedoch der Request-URI der ursprünglichen Anfrage ein SIPS-URI war, SOLLTE der Proxy nicht über einen Nicht-SIPS-URI rekursieren. Wenn der Proxy über alle Contacts einer 3xx-Antwort rekurisiert, SOLLTE er die resultierende Contact-losen Antwort nicht zum Antwortkontext hinzufügen.
Das Entfernen des Contact vor dem Hinzufügen der Antwort zum Antwortkontext verhindert, dass das nächste Element flussaufwärts einen Ort erneut versucht, den dieser Proxy bereits probiert hat.
3xx-Antworten können eine Mischung aus SIP-, SIPS- und Nicht-SIP-URIs enthalten. Ein Proxy darf über SIP- und SIPS-URIs rekursieren und den Rest in den Antwortkontext stellen, um möglicherweise in der finalen Antwort zurückgegeben zu werden.
Wenn ein Proxy eine 416 (Unsupported URI Scheme)-Antwort auf eine Anfrage erhält, deren Request-URI-Schema nicht SIP war, aber das Schema der ursprünglich empfangenen Anfrage SIP oder SIPS war (d. h. der Proxy hat das Schema beim Proxifizieren von SIP oder SIPS auf etwas anderes geändert), SOLLTE der Proxy der Zielmenge eine neue URI hinzufügen. Diese URI SOLLTE eine SIP-URI-Version der gerade versuchten Nicht-SIP-URI sein. Im Fall einer tel-URL wird dies erreicht, indem der telephone-subscriber-Teil der tel-URL in den user-Teil der SIP-URI gesetzt und der hostpart auf die Domäne gesetzt wird, an die die vorherige Anfrage gesendet wurde. Siehe Abschnitt 19.1.6 für Details zur Bildung von SIP-URIs aus tel-URLs.
Wie bei einer 3xx-Antwort SOLLTE, wenn ein Proxy über das 416 rekursiert, indem er stattdessen eine SIP- oder SIPS-URI versucht, die 416-Antwort nicht zum Antwortkontext hinzugefügt werden.
5. Antwort auf Weiterleitung prüfen (Check response for forwarding)
Bis eine finale Antwort auf der Server-Transaktion gesendet wird, MÜSSEN die folgenden Antworten sofort weitergeleitet werden:
- Jede vorläufige Antwort außer 100 (Trying)
- Jede 2xx-Antwort
Wenn eine 6xx-Antwort empfangen wird, wird sie nicht sofort weitergeleitet, aber der zustandsbehaftete Proxy SOLLTE alle ausstehenden Client-Transaktionen abbrechen, wie in Abschnitt 10 beschrieben, und DARF in diesem Kontext keine neuen Zweige erstellen.
Dies ist eine Änderung gegenüber RFC 2543, die vorschrieb, dass ein Proxy die 6xx-Antwort sofort weiterleitet. Bei einer INVITE-Transaktion hatte dieser Ansatz das Problem, dass möglicherweise eine 2xx-Antwort auf einem anderen Zweig eintraf, woraufhin der Proxy das 2xx weiterleiten müsste. Das Ergebnis war, dass der UAC möglicherweise eine 6xx-Antwort gefolgt von einer 2xx-Antwort erhalten hätte, was niemals erlaubt sein sollte. Unter den neuen Regeln gibt ein Proxy bei Erhalt eines 6xx eine CANCEL-Anfrage aus, was normalerweise 487-Antworten von allen ausstehenden Client-Transaktionen zur Folge hat, woraufhin das 6xx flussaufwärts weitergeleitet wird.
Nachdem eine finale Antwort auf der Server-Transaktion gesendet wurde, MÜSSEN die folgenden Antworten sofort weitergeleitet werden:
- Jede 2xx-Antwort auf eine INVITE-Anfrage
Ein zustandsbehafteter Proxy DARF keine andere Antwort sofort weiterleiten. Insbesondere DARF ein zustandsbehafteter Proxy keine 100 (Trying)-Antwort weiterleiten. Antworten, die als Kandidaten für eine spätere Weiterleitung als „beste“ Antwort gesammelt wurden, sind im Schritt „Antwort zum Kontext hinzufügen“ gesammelt.
Jede für eine sofortige Weiterleitung ausgewählte Antwort MUSS wie in den Schritten „Authorization-Headerfeldwerte aggregieren“ bis „Record-Route“ beschrieben verarbeitet werden.
Dieser Schritt, kombiniert mit dem nächsten, stellt sicher, dass ein zustandsbehafteter Proxy genau eine finale Antwort auf eine Nicht-INVITE-Anfrage und entweder genau eine Nicht-2xx-Antwort oder eine oder mehrere 2xx-Antworten auf eine INVITE-Anfrage weiterleitet.
6. Die beste Antwort auswählen (Choosing the best response)
Ein zustandsbehafteter Proxy MUSS eine finale Antwort an den Antwortkontext der Server-Transaktion senden, wenn keine finale Antwort durch die obigen Regeln sofort weitergeleitet wurde und alle Client-Transaktionen dieses Kontexts beendet sind.
Der zustandsbehaftete Proxy MUSS die beste finale Antwort aus den im Antwortkontext empfangenen und gespeicherten Antworten auswählen.
Wenn sich keine finale Antwort im Kontext befindet, MUSS der Proxy eine 408 (Request Timeout)-Antwort an die Server-Transaktion senden.
Andernfalls MUSS der Proxy eine Antwort aus den im Antwortkontext gespeicherten Antworten weiterleiten. Er MUSS aus den 6xx-Klasse-Antworten wählen, falls solche im Kontext vorhanden sind. Wenn keine 6xx-Klasse-Antwort vorhanden ist, SOLLTE der Proxy aus der niedrigsten im Antwortkontext gespeicherten Antwortklasse wählen. Der Proxy darf eine beliebige Antwort innerhalb dieser gewählten Klasse auswählen. Der Proxy SOLLTE Antworten den Vorzug geben, die Informationen liefern, die das erneute Senden dieser Anfrage beeinflussen (401, 407, 415, 420, 484, wenn die 4xx-Klasse gewählt wird).
Ein Proxy, der eine 503 (Service Unavailable)-Antwort empfängt, SOLLTE sie nicht flussaufwärts weiterleiten, es sei denn, er kann bestimmen, dass jede künftige Anfrage, die er proxifizieren könnte, ebenfalls ein 503 erzeugen würde. Mit anderen Worten bedeutet das Weiterleiten eines 503, dass der Proxy weiß, dass er keine Anfrage bedienen kann, nicht nur die vom Request-URI, der das 503 erzeugt hat. Wenn die einzige empfangene Antwort ein 503 ist, SOLLTE der Proxy eine 500-Antwort erzeugen und flussaufwärts weiterleiten.
Die weitergeleitete Antwort MUSS wie in den Schritten „Authorization-Headerfeldwerte aggregieren“ bis „Record-Route“ beschrieben verarbeitet werden.
Zum Beispiel, wenn ein Proxy eine Anfrage an 4 Orte weiterleitet und die Antworten 503, 407, 501, 404 empfängt, darf er wählen, die 407 (Proxy Authentication Required)-Antwort weiterzuleiten.
1xx- und 2xx-Antworten können an der Dialogerstellung beteiligt sein. Wenn eine Anfrage keinen To-Tag enthält, wird der To-Tag der Antwort vom UAC verwendet, um mehrere Antworten auf eine dialogerstellende Anfrage zu unterscheiden. Ein Proxy DARF keinen Tag in das To-Headerfeld einer 1xx- oder 2xx-Antwort einfügen, wenn die Anfrage keinen enthielt. Ein Proxy DARF den Tag im To-Headerfeld einer 1xx- oder 2xx-Antwort nicht ändern.
Da ein Proxy keinen Tag in das To-Headerfeld einer 1xx-Antwort auf eine Anfrage ohne Tag einfügen kann, kann er keine eigenen Nicht-100-vorläufigen Antworten ausgeben. Er kann die Anfrage jedoch an einen UAS verzweigen, der denselben Element wie der Proxy teilt. Dieser UAS kann seine eigenen vorläufigen Antworten zurückgeben und in einen frühen Dialog mit dem Initiator der Anfrage eintreten. Der UAS muss kein separater Prozess vom Proxy sein. Er könnte ein virtueller UAS sein, der im selben Code-Bereich wie der Proxy implementiert ist.
3-6xx-Antworten werden hop-by-hop zugestellt. Beim Ausgeben einer 3-6xx-Antwort agiert das Element effektiv als UAS und gibt normalerweise seine eigene Antwort aus, basierend auf den von nachgelagerten Elementen empfangenen Antworten. Ein Element SOLLTE den To-Tag beibehalten, wenn es einfach eine 3-6xx-Antwort auf eine Anfrage ohne To-Tag weiterleitet.
Ein Proxy DARF den To-Tag in einer weitergeleiteten Antwort auf eine Anfrage mit To-Tag nicht ändern.
Obwohl es für die Elemente flussaufwärts keinen Unterschied macht, wenn der Proxy den To-Tag in einer weitergeleiteten 3-6xx-Antwort ersetzt, kann das Beibehalten des ursprünglichen Tags beim Debuggen helfen.
Wenn ein Proxy Informationen aus mehreren Antworten aggregiert, ist die Auswahl eines To-Tags darunter beliebig, und das Erzeugen eines neuen To-Tags kann das Debuggen erleichtern. Dies geschieht beispielsweise beim Kombinieren der Challenges 401 (Unauthorized) und 407 (Proxy Authentication Required) oder beim Kombinieren von Contact-Werten aus unverschlüsselten und nicht authentifizierten 3xx-Antworten.
7. Authorization-Headerfeldwerte aggregieren (Aggregate Authorization Header Field Values)
Wenn die ausgewählte Antwort eine 401 (Unauthorized) oder 407 (Proxy Authentication Required) ist, MUSS der Proxy alle WWW-Authenticate- und Proxy-Authenticate-Headerfeldwerte aus allen anderen 401- und 407-Antworten sammeln, die bisher in diesem Antwortkontext empfangen wurden, und sie unverändert zu dieser Antwort hinzufügen, bevor er sie weiterleitet. Die resultierende 401- oder 407-Antwort kann mehrere WWW-Authenticate- und Proxy-Authenticate-Headerfeldwerte enthalten.
Dies ist notwendig, da einer oder alle der Ziele, an die die Anfrage weitergeleitet wurde, Anmeldeinformationen angefordert haben könnten. Der Client muss alle diese Challenges erhalten und die jeweiligen Anmeldeinformationen bereitstellen, wenn er die Anfrage erneut versucht. Die Motivation für dieses Verhalten wird in Abschnitt 26 gegeben.
8. Record-Route
Wenn die ausgewählte Antwort einen Record-Route-Headerfeldwert enthält, der ursprünglich von diesem Proxy bereitgestellt wurde, darf der Proxy den Wert vor dem Weiterleiten der Antwort umschreiben (KANN). Dies ermöglicht es dem Proxy, unterschiedliche URIs für sich selbst gegenüber den folgenden Elementen flussaufwärts und flussabwärts anzugeben. Ein Proxy darf diesen Mechanismus aus beliebigem Grund wählen. Dies ist beispielsweise für Multihome-Hosts nützlich.
Wenn der Proxy die Anfrage über TLS empfangen und über eine Nicht-TLS-Verbindung gesendet hat, MUSS der Proxy den URI im Record-Route-Headerfeld in eine SIPS-URI umschreiben. Wenn der Proxy die Anfrage über eine Nicht-TLS-Verbindung empfangen und über TLS gesendet hat, MUSS der Proxy den URI im Record-Route-Headerfeld in eine SIP-URI umschreiben.
Die neue vom Proxy bereitgestellte URI MUSS dieselben Einschränkungen erfüllen wie die URIs, die in die Record-Route-Headerfelder der Anfragen eingefügt werden (siehe Schritt 4 von Abschnitt 16.6), mit folgenden Änderungen:
Die URI SOLLTE keinen transport-Parameter enthalten, es sei denn, der Proxy weiß, dass das nächste Element flussaufwärts (nicht flussabwärts) auf dem Pfad künftiger Anfragen diesen Transport unterstützt.
Wenn ein Proxy beschließt, den Record-Route-Headerfeldwert in der Antwort zu ändern, ist einer der Vorgänge, die er ausführt, das Auffinden des Record-Route-Werts, den er eingefügt hat. Wenn die Anfrage eine Spirale gebildet hat und der Proxy bei jeder Iteration der Spirale einen Record-Route-Wert eingefügt hat, ist das Auffinden des richtigen Werts in der Antwort (der in der entsprechenden Iterration in Gegenrichtung sein muss) schwierig. Die obigen Regeln empfehlen, dass ein Proxy, der Record-Route-Headerfeldwerte umschreiben möchte, ausreichend unterschiedliche URIs in das Record-Route-Headerfeld einfügt, damit der richtige für das Umschreiben ausgewählt werden kann. Ein empfohlener Mechanismus dafür ist, dass der Proxy einen eindeutigen Bezeichner der Proxy-Instanz an den user-Teil der URI anhängt.
Wenn die Antwort eintrifft, ändert der Proxy den ersten Record-Route, dessen Bezeichner mit der Proxy-Instanz übereinstimmt. Die Änderung führt zu einer URI ohne dieses Datenstück, das an den user-Teil der URI angehängt war. Bei der nächsten Iteration wird derselbe Algorithmus (den Record-Route-Headerfeldwert mit Parameter an oberster Stelle suchen) den nächsten, von diesem Proxy eingefügten Record-Route-Headerfeldwert korrekt extrahieren.
Nicht alle Antworten auf eine Anfrage, der ein Proxy einen Record-Route-Headerfeldwert hinzugefügt hat, enthalten ein Record-Route-Headerfeld. Wenn die Antwort ein Record-Route-Headerfeld enthält, enthält sie den vom Proxy hinzugefügten Wert.
9. Antwort weiterleiten (Forward response)
Nach dem Ausführen der Verarbeitung, die in den Schritten „Authorization-Headerfeldwerte aggregieren“ bis „Record-Route“ beschrieben ist, darf der Proxy funktionsspezifische Manipulationen an der ausgewählten Antwort vornehmen (KANN). Der Proxy DARF den Nachrichtentext nicht hinzufügen, ändern oder entfernen. Sofern nicht anders angegeben, DARF der Proxy keine anderen Headerfeldwerte als den in Artikel 3 von Abschnitt 16.7 besprochenen Via-Headerfeldwert entfernen. Insbesondere DARF der Proxy einen „received“-Parameter nicht entfernen, den er möglicherweise dem nächsten Via-Headerfeldwert hinzugefügt hat, als er die mit dieser Antwort verbundene Anfrage verarbeitete. Der Proxy MUSS die Antwort an die mit dem Antwortkontext verbundene Server-Transaktion übergeben. Dies führt dazu, dass die Antwort an den Ort gesendet wird, der nun im obersten Via-Headerfeldwert angegeben ist. Wenn die Server-Transaktion für die Übertragung nicht mehr verfügbar ist, MUSS das Element die Antwort zustandslos weiterleiten, indem es sie an den Server-Transport sendet. Die Server-Transaktion kann einen Sende-Fehler anzeigen oder einen Timeout in ihrer Zustandsmaschine melden. Diese Fehler würden zu Diagnosezwecken protokolliert, aber das Protokoll verlangt keine Korrekturmaßnahme vom Proxy.
Der Proxy MUSS den Antwortkontext aufrechterhalten, bis alle damit verbundenen Transaktionen beendet sind, selbst nachdem er eine finale Antwort weitergeleitet hat.
10. CANCELs erzeugen (Generate CANCELs)
Wenn die weitergeleitete Antwort eine finale Antwort war, MUSS der Proxy eine CANCEL-Anfrage für alle ausstehenden Client-Transaktionen erzeugen, die mit diesem Antwortkontext verbunden sind. Ein Proxy SOLLTE auch eine CANCEL-Anfrage für alle ausstehenden Client-Transaktionen erzeugen, die mit diesem Antwortkontext verbunden sind, wenn er eine 6xx-Antwort empfängt. Eine ausstehende Client-Transaktion ist eine, die eine vorläufige Antwort, aber keine finale Antwort empfangen hat (sie befindet sich im Zustand „proceeding“) und für die kein zugehöriges CANCEL erzeugt wurde. Das Erzeugen von CANCEL-Anfragen ist in Abschnitt 9.1 beschrieben.
Die Anforderung, ausstehende Client-Transaktionen bei der Weiterleitung einer finalen Antwort abzubrechen, stellt nicht sicher, dass ein Endpunkt nicht mehrere 200 (OK)-Antworten auf ein INVITE erhält. Mehrere 200 (OK)-Antworten auf verschiedenen Zweigen könnten erzeugt werden, bevor die CANCEL-Anfragen gesendet und verarbeitet werden können. Darüber hinaus ist vernünftigerweise zu erwarten, dass eine künftige Erweiterung diese Anforderung zur Ausgabe von CANCEL außer Kraft setzt.
16.8 Verarbeitung von Timer C (Processing Timer C)
Wenn Timer C abläuft, MUSS der Proxy entweder den Timer mit einem selbst gewählten Wert zurücksetzen oder die Client-Transaktion beenden. Wenn die Client-Transaktion eine vorläufige Antwort empfangen hatte, MUSS der Proxy eine passende CANCEL-Anfrage für diese Transaktion erzeugen. Wenn die Client-Transaktion keine vorläufige Antwort empfangen hatte, MUSS sich der Proxy verhalten, als hätte die Transaktion eine 408 (Request Timeout)-Antwort empfangen.
Dem Proxy zu erlauben, den Timer zurückzusetzen, ermöglicht es ihm, die Lebensdauer der Transaktion dynamisch basierend auf den aktuellen Bedingungen (wie Auslastung) bei seinem Ablauf zu verlängern.
16.9 Umgang mit Transportfehlern (Handling Transport Errors)
Wenn die Transportschicht einem Proxy einen Fehler beim Versuch mitteilt, eine Anfrage weiterzuleiten (siehe Abschnitt 18.4), MUSS sich der Proxy verhalten, als hätte die weitergeleitete Anfrage eine 503 (Service Unavailable)-Antwort empfangen.
Wenn dem Proxy ein Fehler beim Weiterleiten einer Antwort mitgeteilt wird, verwirft er die Antwort. Der Proxy SOLLTE die ausstehenden Client-Transaktionen, die mit diesem Antwortkontext verbunden sind, wegen dieser Mitteilung nicht abbrechen.
Wenn ein Proxy seine ausstehenden Client-Transaktionen abbright, könnte ein einzelner bösartiger oder fehlerhafter Client alle Transaktionen über seinen Via-Headerfeldwert zum Scheitern bringen.
16.10 Verarbeitung von CANCEL (CANCEL Processing)
Ein zustandsbehafteter Proxy darf jederzeit ein CANCEL für eine andere von ihm erzeugte Anfrage erzeugen (KANN) (vorbehaltlich des Empfangs einer vorläufigen Antwort auf diese Anfrage, wie in Abschnitt 9.1 beschrieben). Ein Proxy MUSS alle ausstehenden Client-Transaktionen abbrechen, die mit einem Antwortkontext verbunden sind, wenn er eine passende CANCEL-Anfrage empfängt.
Ein zustandsbehafteter Proxy darf CANCEL-Anfragen für ausstehende INVITE-Client-Transaktionen erzeugen, basierend auf dem Ablauf des Expires-Headerfelds des INVITE. Dies ist jedoch im Allgemeinen unnötig, da die beteiligten Endpunkte sich darum kümmern werden, das Ende der Transaktion zu signalisieren.
Obwohl eine CANCEL-Anfrage in einem zustandsbehafteten Proxy durch seine eigene Server-Transaktion verarbeitet wird, wird kein neuer Antwortkontext für sie erstellt. Stattdessen sucht die Proxy-Schicht in ihren bestehenden Antwortkontexten nach der Server-Transaktion, die die Anfrage verarbeitet, die mit diesem CANCEL verbunden ist. Wenn ein passender Antwortkontext gefunden wird, MUSS das Element sofort eine 200 (OK)-Antwort auf die CANCEL-Anfrage zurückgeben. In diesem Fall agiert das Element als in Abschnitt 8.2 definierter User Agent Server. Darüber hinaus MUSS das Element CANCEL-Anfragen für alle ausstehenden Client-Transaktionen im Kontext erzeugen, wie in Schritt 10 von Abschnitt 16.7 beschrieben.
Wenn kein Antwortkontext gefunden wird, besitzt das Element kein Wissen über die Anfrage, auf die das CANCEL anzuwenden ist. Es MUSS die CANCEL-Anfrage zustandslos weiterleiten (es hat die zugehörige Anfrage möglicherweise zuvor zustandslos weitergeleitet).
16.11 Zustandsloser Proxy (Stateless Proxy)
Wenn er zustandslos arbeitet, ist ein Proxy ein einfacher Nachrichtenweiterleiter. Ein Großteil der Verarbeitung, die zustandslos durchgeführt wird, ist identisch mit der zustandsbehaftet durchgeführten. Die Unterschiede werden hier dargelegt.
Ein zustandsloser Proxy kennt keine Transaktionen noch das Konzept des Antwortkontexts, das zur Beschreibung des Verhaltens des zustandsbehafteten Proxys verwendet wird. Stattdessen nimmt der zustandslose Proxy Nachrichten, sowohl Anfragen als auch Antworten, direkt von der Transportschicht (siehe Abschnitt 18). Daher retransmitieren zustandslose Proxys keine Nachrichten selbst. Sie leiten jedoch alle empfangenen Retransmissionen weiter (sie können eine Retransmission nicht von der ursprünglichen Nachricht unterscheiden). Darüber hinaus DARF ein Element bei der zustandslosen Verarbeitung einer Anfrage keine eigene 100 (Trying)- oder andere vorläufige Antwort erzeugen.
Ein zustandsloser Proxy MUSS eine Anfrage wie in Abschnitt 16.3 beschrieben validieren.
Ein zustandsloser Proxy MUSS den Anfragenverarbeitungsschritten der Abschnitte 16.4 bis 16.5 folgen, mit folgender Ausnahme:
o Ein zustandsloser Proxy MUSS genau ein Ziel aus der Zielmenge auswählen. Diese Auswahl DARF nur auf Feldern der Nachricht und zeitinvarianten Eigenschaften des Servers basieren. Insbesondere MUSS eine retransmitierte Anfrage bei jeder Verarbeitung an dasselbe Ziel weitergeleitet werden. Darüber hinaus MÜSSEN CANCEL- und Nicht-Routing-ACK-Anfragen dieselbe Auswahl wie ihr zugehöriges INVITE erzeugen.
Ein zustandsloser Proxy MUSS den Anfragenverarbeitungsschritten von Abschnitt 16.6 folgen, mit folgenden Ausnahmen:
o Die Anforderung eindeutiger branch-IDs in Raum und Zeit gilt auch für zustandslose Proxys. Ein zustandsloser Proxy kann jedoch nicht einfach einen Zufallszahlengenerator verwenden, um die erste Komponente der branch-ID zu berechnen, wie in Schritt 8 von Abschnitt 16.6 beschrieben. Dies liegt daran, dass Retransmissionen einer Anfrage denselben Wert haben müssen, und ein zustandsloser Proxy eine Retransmission nicht von der ursprünglichen Anfrage unterscheiden kann. Daher MUSS die Komponente des branch-Parameters, die ihn eindeutig macht, bei jeder Weiterleitung einer retransmitierten Anfrage dieselbe sein. Daher MUSS für einen zustandslosen Proxy der branch-Parameter als kombinierende Funktion von nachrichteninvarianten Parametern berechnet werden.
Der zustandslose Proxy darf jede Technik verwenden, die er möchte, um die Eindeutigkeit seiner branch-IDs zwischen Transaktionen zu gewährleisten. Es wird jedoch das folgende Verfahren empfohlen. Der Proxy untersucht die branch-ID im obersten Via-Headerfeld der empfangenen Anfrage. Wenn sie mit dem Magic-Cookie beginnt, wird die erste Komponente der branch-ID der ausgehenden Anfrage als Hash der empfangenen branch-ID berechnet. Andernfalls wird die erste Komponente als Hash des obersten Via, des Tags im To-Headerfeld, des Tags im From-Headerfeld, des Call-ID-Headerfelds, der CSeq-Nummer (aber nicht der Methode) und des Request-URI der empfangenen Anfrage berechnet. Eines dieser Felder wird sich immer zwischen zwei verschiedenen Transaktionen ändern.
o Alle anderen in Abschnitt 16.6 angegebenen Nachrichtentransformationen MÜSSEN dieselbe Transformation einer retransmitierten Anfrage ergeben. Insbesondere, wenn der Proxy einen Record-Route-Wert einfügt oder URIs in das Route-Headerfeld schiebt, MUSS er dieselben Werte in die Retransmissionen der Anfrage platzieren. Wie beim Via-branch-Parameter bedeutet dies, dass die Transformationen auf zeitinvarianter Konfiguration oder retransmissionsinvarianten Eigenschaften der Anfrage basieren müssen.
o Ein zustandsloser Proxy bestimmt, wohin die Anfrage weitergeleitet wird, wie für zustandsbehaftete Proxys in Artikel 10 von Abschnitt 16.6 beschrieben. Die Anfrage wird direkt an die Transportschicht gesendet, anstatt durch eine Client-Transaktion.
Da ein zustandsloser Proxy retransmitierte Anfragen an dasselbe Ziel weiterleiten und jedem dieselben branch-Parameter hinzufügen muss, kann er für diese Berechnungen nur Informationen aus der Nachricht selbst und zeitinvariante Konfigurationsdaten verwenden. Wenn der Konfigurationszustand nicht zeitinvariant ist (z. B. wenn eine Routing-Tabelle aktualisiert wird), könnten Anfragen, die vom Wechsel betroffen sein könnten, für ein Intervall gleich dem Transaktions-Timeout-Fenster vor oder nach dem Wechsel nicht zustandslos weitergeleitet werden. Die Methode zur Verarbeitung betroffener Anfragen während dieses Intervalls ist eine Implementierungsentscheidung. Eine gängige Lösung ist, sie zustandsbehaftet bezüglich der Transaktion weiterzuleiten.
Zustandslose Proxys DÜRFEN keine spezielle Verarbeitung für CANCEL-Anfragen durchführen. Sie werden durch die obigen Regeln wie jede andere Anfrage behandelt. Insbesondere wendet ein zustandsloser Proxy dieselbe Route-Headerfeld-Verarbeitung auf CANCEL-Anfragen an wie auf jede andere Anfrage.
Die in Abschnitt 16.7 beschriebene Antwortverarbeitung gilt nicht für einen zustandslos arbeitenden Proxy. Wenn eine Antwort bei einem zustandslosen Proxy eintrifft, MUSS der Proxy den sent-by-Wert im ersten (obersten) Via-Headerfeldwert prüfen. Wenn diese Adresse mit dem Proxy übereinstimmt (sie ist gleich einem Wert, den dieser Proxy zuvor in Anfragen eingefügt hat), MUSS der Proxy diesen Wert aus dem Via-Headerfeld der Antwort entfernen und das Ergebnis an den im nächsten Via-Headerfeldwert angegebenen Ort weiterleiten. Der Proxy DARF den Nachrichtentext nicht hinzufügen, ändern oder entfernen. Sofern nicht anders angegeben, DARF der Proxy keine anderen Headerfeldwerte entfernen. Wenn die Adresse nicht mit dem Proxy übereinstimmt, MUSS die Nachricht stillschweigend verworfen werden.
16.12 Zusammenfassung der Proxy-Routing-Verarbeitung (Summary of Proxy Route Processing)
Sofern keine entgegenstehende lokale Richtlinie besteht, lässt sich die Verarbeitung, die ein Proxy für eine Anfrage mit Route-Headerfeld durchführt, in den folgenden Schritten zusammenfassen.
1. Der Proxy prüft den Request-URI. Wenn er eine Ressource angibt, die zu diesem Proxy gehört, ersetzt der Proxy ihn durch die Ergebnisse der Ausführung eines Lokalisierungsdienstes. Andernfalls ändert der Proxy den Request-URI nicht.
2. Der Proxy prüft den URI im ersten Wert des Route-Headerfelds. Wenn er auf diesen Proxy zeigt, entfernt der Proxy ihn aus dem Route-Headerfeld (dieser Routing-Knoten wurde erreicht).
3. Der Proxy leitet die Anfrage an die Ressource weiter, die durch den URI im ersten Wert des Route-Headerfelds oder, falls kein Route-Headerfeld vorhanden ist, durch den Request-URI angegeben wird. Der Proxy bestimmt die Adresse, den Port und den Transport für das Weiterleiten der Anfrage, indem er die Verfahren von [4] auf diesen URI anwendet.
Wenn auf dem Pfad der Anfrage kein Strict-Routing-Element auftritt, zeigt der Request-URI immer das Ziel der Anfrage an.
16.12.1 Beispiele (Examples)
16.12.1.1 Grundlegendes SIP-Trapez (Basic SIP Trapezoid)
Dieses Szenario ist das grundlegende SIP-Trapez, U1 -> P1 -> P2 -> U2, wobei beide Proxys Record-Routing durchführen. Der Ablauf ist wie folgt.
U1 sendet:
INVITE sip:[email protected] SIP/2.0
Contact: sip:[email protected]
an P1. P1 ist ein Outbound-Proxy. P1 verwaltet domain.com nicht, daher sucht er im DNS und sendet dorthin. Er fügt außerdem einen Record-Route-Headerfeldwert hinzu:
INVITE sip:[email protected] SIP/2.0
Contact: sip:[email protected]
Record-Route: `<sip:p1.example.com;lr>`
P2 empfängt dies. P2 verwaltet domain.com, führt also einen Lokalisierungsdienst aus und schreibt den Request-URI um. Er fügt außerdem einen Record-Route-Headerfeldwert hinzu. Da kein Route-Headerfeld vorhanden ist, löst er den neuen Request-URI auf, um zu bestimmen, wohin die Anfrage gesendet wird:
INVITE sip:[email protected] SIP/2.0
Contact: sip:[email protected]
Record-Route: `<sip:p2.domain.com;lr>`
Record-Route: `<sip:p1.example.com;lr>`
Der Gerufene auf u2.domain.com empfängt dies und antwortet mit 200 OK:
SIP/2.0 200 OK
Contact: sip:[email protected]
Record-Route: `<sip:p2.domain.com;lr>`
Record-Route: `<sip:p1.example.com;lr>`
Der Gerufene auf u2 setzt außerdem den entfernten Ziel-URI seines Dialogzustands auf sip:[email protected] und seinen Routensatz auf:
(`<sip:p2.domain.com;lr>`,`<sip:p1.example.com;lr>`)
Dies wird normal von P2 über P1 an U1 weitergeleitet. Nun setzt U1 den entfernten Ziel-URI seines Dialogzustands auf sip:[email protected] und seinen Routensatz auf:
(`<sip:p1.example.com;lr>`,`<sip:p2.domain.com;lr>`)
Da alle Elemente des Routensatzes den lr-Parameter enthalten, konstruiert U1 die folgende BYE-Anfrage:
BYE sip:[email protected] SIP/2.0
Route: `<sip:p1.example.com;lr>`,`<sip:p2.domain.com;lr>`
Wie jedes andere Element (einschließlich Proxys) löst er den URI im ersten Wert des Route-Headerfelds über DNS auf, um zu bestimmen, wohin die Anfrage gesendet wird. Dies geht an P1. P1 stellt fest, dass es nicht für die durch den Request-URI bezeichnete Ressource zuständig ist, also ändert es ihn nicht. Es sieht, dass es der erste Wert im Route-Headerfeld ist, also entfernt es ihn und leitet die Anfrage an P2 weiter:
BYE sip:[email protected] SIP/2.0
Route: `<sip:p2.domain.com;lr>`
P2 stellt ebenfalls fest, dass es nicht für die durch den Request-URI bezeichnete Ressource zuständig ist (es verwaltet domain.com, nicht u2.domain.com), also ändert es ihn nicht. Es sieht sich im ersten Wert des Route-Headerfelds, also entfernt es ihn und leitet das Folgende an u2.domain.com basierend auf einer DNS-Suche des Request-URI weiter:
BYE sip:[email protected] SIP/2.0
16.12.1.2 Durchqueren eines Strict-Routing-Proxys (Traversing a Strict-Routing Proxy)
In diesem Szenario wird ein Dialog über vier Proxys etabliert, von denen jeder Record-Route-Headerfeldwerte hinzufügt. Der dritte Proxy implementiert die in RFC 2543 und vielen Arbeitsentwürfen spezifizierten Strict-Routing-Verfahren.
U1->P1->P2->P3->P4->U2
Die bei U2 eintreffende INVITE enthält:
INVITE sip:[email protected] SIP/2.0
Contact: sip:[email protected]
Record-Route: `<sip:p4.domain.com;lr>`
Record-Route: `<sip:p3.middle.com>`
Record-Route: `<sip:p2.example.com;lr>`
Record-Route: `<sip:p1.example.com;lr>`
U2 antwortet darauf mit einem 200 OK. Später sendet U2 die folgende BYE-Anfrage an P4 basierend auf dem ersten Wert des Route-Headerfelds.
BYE sip:[email protected] SIP/2.0
Route: `<sip:p4.domain.com;lr>`
Route: `<sip:p3.middle.com>`
Route: `<sip:p2.example.com;lr>`
Route: `<sip:p1.example.com;lr>`
P4 ist nicht für die durch den Request-URI bezeichnete Ressource zuständig, also lässt er ihn unverändert. Es stellt fest, dass es das Element im ersten Wert des Route-Headerfelds ist, also entfernt es ihn. Es bereitet dann das Senden der Anfrage basierend auf dem nun ersten Route-Headerfeldwert sip:p3.middle.com vor, stellt jedoch fest, dass diese URI den lr-Parameter nicht enthält, also formatiert es die Anfrage vor dem Senden um:
BYE sip:p3.middle.com SIP/2.0
Route: `<sip:p2.example.com;lr>`
Route: `<sip:p1.example.com;lr>`
Route: `<sip:[email protected]>`
P3 ist ein Strict-Router, leitet also das Folgende an P2 weiter:
BYE sip:p2.example.com;lr SIP/2.0
Route: `<sip:p1.example.com;lr>`
Route: `<sip:[email protected]>`
P2 sieht, dass der request-URI ein Wert ist, den es in ein Record-Route-Headerfeld platziert hat, also schreibt es die Anfrage vor weiterer Verarbeitung um:
BYE sip:[email protected] SIP/2.0
Route: `<sip:p1.example.com;lr>`
P2 verwaltet u1.example.com nicht, also sendet es die Anfrage an P1 basierend auf der Auflösung des Route-Headerfeldwerts.
P1 stellt seine Anwesenheit im obersten Route-Headerfeldwert fest, also entfernt es ihn, was ergibt:
BYE sip:[email protected] SIP/2.0
Da P1 nicht für u1.example.com zuständig ist und kein Route-Headerfeld vorhanden ist, wird P1 die Anfrage an u1.example.com basierend auf dem Request-URI weiterleiten.
16.12.1.3 Umschreiben von Record-Route-Headerfeldwerten (Rewriting Record-Route Header Field Values)
In diesem Szenario befinden sich U1 und U2 in verschiedenen privaten Namensräumen und treten über einen Proxy P1 in einen Dialog ein, der als Gateway zwischen den Namensräumen fungiert.
U1->P1->U2
U1 sendet:
INVITE sip:[email protected] SIP/2.0
Contact: `<sip:[email protected]>`
P1 verwendet seinen Lokalisierungsdienst und sendet das Folgende an U2:
INVITE sip:[email protected] SIP/2.0
Contact: `<sip:[email protected]>`
Record-Route: `<sip:gateway.rightprivatespace.com;lr>`
U2 sendet dieses 200 (OK) an P1 zurück:
SIP/2.0 200 OK
Contact: `<sip:[email protected]>`
Record-Route: `<sip:gateway.rightprivatespace.com;lr>`
P1 schreibt seinen Record-Route-Parameter um, um einen für U1 nützlichen Wert bereitzustellen, und sendet das Folgende an U1:
SIP/2.0 200 OK
Contact: `<sip:[email protected]>`
Record-Route: `<sip:gateway.leftprivatespace.com;lr>`
Später sendet U1 die folgende BYE-Anfrage an P1:
BYE sip:[email protected] SIP/2.0
Route: `<sip:gateway.leftprivatespace.com;lr>`
die P1 an U2 in der Form weiterleitet:
BYE sip:[email protected] SIP/2.0