2. Overview of ICE (Überblick über ICE)
In einer typischen ICE-Bereitstellung haben wir zwei Endpunkte (in der RFC 3264-Terminologie als AGENTS (Agenten) bekannt), die kommunizieren möchten. Sie können indirekt über ein Signalisierungsprotokoll (wie SIP) kommunizieren, über das sie einen Offer/Answer-Austausch von SDP [RFC3264]-Nachrichten durchführen können. Beachten Sie, dass ICE nicht für die NAT-Überquerung für SIP gedacht ist, von der angenommen wird, dass sie über einen anderen Mechanismus [RFC5626] bereitgestellt wird. Zu Beginn des ICE-Prozesses sind sich die Agenten ihrer eigenen Topologien nicht bewusst. Insbesondere wissen sie möglicherweise nicht, ob sie sich hinter einem NAT (oder mehreren NAT-Ebenen) befinden oder nicht. ICE ermöglicht es den Agenten, genügend Informationen über ihre Topologien zu entdecken, um möglicherweise einen oder mehrere Pfade zu finden, über die sie kommunizieren können.
Abbildung 1 zeigt eine typische Umgebung für die ICE-Bereitstellung. Die beiden Endpunkte sind mit L und R (für links und rechts, was bei der Visualisierung von Anrufabläufen hilft) gekennzeichnet. Sowohl L als auch R befinden sich hinter ihren jeweiligen NATs, obwohl sie sich dessen möglicherweise nicht bewusst sind. Der Typ des NAT und seine Eigenschaften sind ebenfalls unbekannt. Die Agenten L und R sind in der Lage, einen Offer/Answer-Austausch durchzuführen, über den sie SDP-Nachrichten austauschen können, deren Zweck es ist, eine Mediensitzung zwischen L und R aufzubauen. Typischerweise erfolgt dieser Austausch über einen SIP-Server.
Zusätzlich zu den Agenten, einem SIP-Server und NATs wird ICE typischerweise in Verbindung mit STUN- oder TURN-Servern im Netzwerk verwendet. Jeder Agent kann seinen eigenen STUN- oder TURN-Server haben, oder es können dieselben sein.
+-------+
| SIP |
+-------+ | Srvr | +-------+
| STUN | | | | STUN |
| Srvr | +-------+ | Srvr |
| | / \ | |
+-------+ / \ +-------+
/ \
/ \
/ \
/ \
/ <- Signaling -> \
/ \
/ \
+--------+ +--------+
| NAT | | NAT |
+--------+ +--------+
/ \
/ \
/ \
+-------+ +-------+
| Agent | | Agent |
| L | | R |
| | | |
+-------+ +-------+
Figure 1: ICE Deployment Scenario
Die Grundidee hinter ICE ist folgende: Jeder Agent verfügt über eine Vielzahl von TRANSPORT ADDRESSES (Kandidaten-Transportadressen) (Kombination aus IP-Adresse und Port für ein bestimmtes Transportprotokoll, das in dieser Spezifikation immer UDP ist), die er zur Kommunikation mit dem anderen Agenten verwenden könnte. Dazu könnten gehören:
- Eine Transportadresse auf einer direkt angeschlossenen Netzwerkschnittstelle
- Eine übersetzte Transportadresse auf der öffentlichen Seite eines NAT (eine "server reflexive" (server-reflexive) Adresse)
- Eine von einem TURN-Server zugewiesene Transportadresse (eine "relayed" (weitergeleitete) Adresse).
Potenziell kann jede der Kandidaten-Transportadressen von L verwendet werden, um mit jeder der Kandidaten-Transportadressen von R zu kommunizieren. In der Praxis werden jedoch viele Kombinationen nicht funktionieren. Wenn sich beispielsweise L und R beide hinter NATs befinden, ist es unwahrscheinlich, dass ihre direkt angeschlossenen Schnittstellenadressen direkt kommunizieren können (deshalb wird ICE schließlich benötigt!). Der Zweck von ICE besteht darin, herauszufinden, welche Adresspaare funktionieren. ICE tut dies, indem es systematisch alle möglichen Paare (in einer sorgfältig sortierten Reihenfolge) ausprobiert, bis es eines oder mehrere findet, die funktionieren.
2.1. Gathering Candidate Addresses (Sammeln von Kandidatenadressen)
Um ICE auszuführen, muss ein Agent alle seine Adresskandidaten identifizieren. Ein CANDIDATE (Kandidat) ist eine Transportadresse – eine Kombination aus IP-Adresse und Port für ein bestimmtes Transportprotokoll (wobei hier nur UDP spezifiziert ist). Dieses Dokument definiert drei Arten von Kandidaten, einige stammen von physischen oder logischen Netzwerkschnittstellen, andere sind über STUN und TURN auffindbar. Natürlich ist ein brauchbarer Kandidat eine Transportadresse, die direkt von einer lokalen Schnittstelle bezogen wird. Ein solcher Kandidat wird als HOST CANDIDATE (Host-Kandidat) bezeichnet. Die lokale Schnittstelle könnte Ethernet oder WiFi sein, oder sie könnte eine sein, die über einen Tunnelmechanismus wie ein Virtual Private Network (VPN) oder Mobile IP (MIP) erhalten wird. In allen Fällen erscheint eine solche Netzwerkschnittstelle dem Agenten als lokale Schnittstelle, von der Ports (und damit Kandidaten) zugewiesen werden können.
Wenn ein Agent Multihomed ist, erhält er von jeder IP-Adresse einen Kandidaten. Abhängig vom Standort des PEER (Peers) (des anderen Agenten in der Sitzung) im IP-Netzwerk relativ zum Agenten kann der Agent für den Peer über eine oder mehrere dieser IP-Adressen erreichbar sein. Betrachten Sie beispielsweise einen Agenten, der eine lokale IP-Adresse in einem privaten Net 10-Netzwerk (I1) und eine zweite mit dem öffentlichen Internet (I2) verbundene hat. Ein Kandidat von I1 ist direkt erreichbar, wenn mit einem Peer im selben privaten Net 10-Netzwerk kommuniziert wird, während ein Kandidat von I2 direkt erreichbar ist, wenn mit einem Peer im öffentlichen Internet kommuniziert wird. Anstatt zu versuchen, vor dem Senden eines Angebots zu erraten, welche IP-Adresse funktionieren wird, nimmt der anbietende Agent beide Kandidaten in sein Angebot auf.
Als Nächstes verwendet der Agent STUN oder TURN, um zusätzliche Kandidaten zu erhalten. Diese gibt es in zwei Varianten: übersetzte Adressen auf der öffentlichen Seite eines NAT (SERVER REFLEXIVE CANDIDATES (server-reflexive Kandidaten)) und Adressen auf TURN-Servern (RELAYED CANDIDATES (weitergeleitete Kandidaten)). Wenn TURN-Server verwendet werden, werden beide Arten von Kandidaten vom TURN-Server erhalten. Wenn nur STUN-Server verwendet werden, werden nur server-reflexive Kandidaten von ihnen erhalten. Die Beziehung dieser Kandidaten zum Host-Kandidaten ist in Abbildung 2 dargestellt. In dieser Abbildung werden beide Arten von Kandidaten mithilfe von TURN entdeckt. In der Abbildung bedeutet die Notation X:x die IP-Adresse X und den UDP-Port x.
To Internet
|
|
| /------------ Relayed
Y:y | / Address
+--------+
| |
| TURN |
| Server |
| |
+--------+
|
|
| /------------ Server
X1':x1'|/ Reflexive
+------------+ Address
| NAT |
+------------+
|
| /------------ Local
X:x |/ Address
+--------+
| |
| Agent |
| |
+--------+
Figure 2: Candidate Relationships
Wenn der Agent die TURN Allocate-Anfrage von IP-Adresse und Port X:x sendet, erstellt das NAT (vorausgesetzt, es gibt eines) eine Bindung X1':x1', die diesen server-reflexiven Kandidaten dem Host-Kandidaten X:x zuordnet. Ausgehende Pakete, die vom Host-Kandidaten gesendet werden, werden vom NAT in den server-reflexiven Kandidaten übersetzt. Eingehende Pakete, die an den server-reflexiven Kandidaten gesendet werden, werden vom NAT in den Host-Kandidaten übersetzt und an den Agenten weitergeleitet. Wir nennen den Host-Kandidaten, der einem bestimmten server-reflexiven Kandidaten zugeordnet ist, die BASE (Basis).
Hinweis: "Basis" bezieht sich auf die Adresse, von der ein Agent für einen bestimmten Kandidaten sendet. Somit haben Host-Kandidaten als degenerierter Fall auch eine Basis, aber es ist dieselbe wie der Host-Kandidat.
Wenn sich zwischen dem Agenten und dem TURN-Server mehrere NATs befinden, erstellt die TURN-Anfrage auf jedem NAT eine Bindung, aber nur der äußerste server-reflexive Kandidat (der dem TURN-Server am nächsten liegt) wird vom Agenten entdeckt. Wenn sich der Agent nicht hinter einem NAT befindet, ist der Basiskandidat derselbe wie der server-reflexive Kandidat, und der server-reflexive Kandidat ist redundant und wird eliminiert.
Die Allocate-Anfrage kommt dann am TURN-Server an. Der TURN-Server weist einen Port y von seiner lokalen IP-Adresse Y zu und generiert eine Allocate-Antwort, die den Agenten über diesen weitergeleiteten Kandidaten informiert. Der TURN-Server informiert den Agenten auch über den server-reflexiven Kandidaten X1':x1', indem er die Quelltransportadresse der Allocate-Anfrage in die Allocate-Antwort kopiert. Der TURN-Server fungiert als Paket-Relay und leitet den Verkehr zwischen L und R weiter. Um Verkehr an L zu senden, sendet R Verkehr an den TURN-Server bei Y:y, und der TURN-Server leitet diesen an X1':x1' weiter, der durch das NAT geleitet wird, wo er auf X:x abgebildet und an L zugestellt wird.
Wenn nur STUN-Server verwendet werden, sendet der Agent eine STUN Binding-Anfrage [RFC5389] an seinen STUN-Server. Der STUN-Server informiert den Agenten über den server-reflexiven Kandidaten X1':x1', indem er die Quelltransportadresse der Binding-Anfrage in die Binding-Antwort kopiert.
2.2. Connectivity Checks (Konnektivitätsprüfungen)
Sobald L alle seine Kandidaten gesammelt hat, ordnet es sie in der Reihenfolge von der höchsten zur niedrigsten Priorität und sendet sie über den Signalisierungskanal an R. Die Kandidaten werden in Attributen im SDP-Angebot übertragen. Wenn R das Angebot erhält, führt es denselben Sammelprozess durch und antwortet mit seiner eigenen Liste von Kandidaten. Am Ende dieses Prozesses hat jeder Agent eine vollständige Liste sowohl seiner Kandidaten als auch der Kandidaten seines Peers. Er paart sie und erhält so CANDIDATE PAIRS (Kandidatenpaare). Um zu sehen, welche Paare funktionieren, plant jeder Agent eine Reihe von CHECKS (Prüfungen). Jede Prüfung ist eine STUN-Anfrage/Antwort-Transaktion, die der Client für ein bestimmtes Kandidatenpaar durchführt, indem er eine STUN-Anfrage vom lokalen Kandidaten an den entfernten Kandidaten sendet.
Das Grundprinzip der Konnektivitätsprüfungen ist einfach:
- Sortieren Sie die Kandidatenpaare in Prioritätsreihenfolge.
- Senden Sie Prüfungen für jedes Kandidatenpaar in Prioritätsreihenfolge.
- Bestätigen Sie die vom anderen Agenten empfangenen Prüfungen.
Da beide Agenten eine Prüfung für ein Kandidatenpaar durchführen, ist das Ergebnis ein 4-Wege-Handshake:
L R
- -
STUN request -> \ L's
<- STUN response / check
<- STUN request \ R's
STUN response -> / check
Figure 3: Basic Connectivity Check
Es ist wichtig zu beachten, dass die STUN-Anfragen an genau dieselben IP-Adressen und Ports gesendet und von diesen empfangen werden, die für Medien (z. B. RTP und RTCP) verwendet werden. Folglich demultiplexen Agenten STUN und RTP/RTCP anhand des Inhalts der Pakete und nicht anhand des Ports, an dem sie empfangen werden. Glücklicherweise ist dieses Demultiplexing einfach durchzuführen, insbesondere für RTP und RTCP.
Da für die Konnektivitätsprüfung eine STUN Binding-Anfrage verwendet wird, enthält die STUN Binding-Antwort die übersetzte Transportadresse des Agenten auf der öffentlichen Seite aller NATs zwischen dem Agenten und seinem Peer. Wenn sich diese Transportadresse von anderen Kandidaten unterscheidet, die der Agent bereits gelernt hat, stellt sie einen neuen Kandidaten dar, der als PEER REFLEXIVE CANDIDATE (Peer-reflexiver Kandidat) bezeichnet wird und dann von ICE genau wie jeder andere Kandidat getestet wird.
Als Optimierung plant R, sobald R die Prüfnachricht von L erhält, eine Konnektivitätsprüfnachricht, die an L auf demselben Kandidatenpaar gesendet werden soll. Dies beschleunigt den Prozess der Suche nach einem gültigen Kandidaten und wird als TRIGGERED CHECK (ausgelöste Prüfung) bezeichnet.
Am Ende dieses Handshakes wissen sowohl L als auch R, dass sie Nachrichten in beide Richtungen Ende-zu-Ende senden (und empfangen) können.
2.3. Sorting Candidates (Sortieren von Kandidaten)
Da der obige Algorithmus alle Kandidatenpaare durchsucht, wird er, wenn ein funktionierendes Paar existiert, dieses schließlich finden, egal in welcher Reihenfolge die Kandidaten ausprobiert werden. Um schnellere (und bessere) Ergebnisse zu erzielen, werden die Kandidaten in einer bestimmten Reihenfolge sortiert. Die resultierende Liste sortierter Kandidatenpaare wird als CHECK LIST (Prüfliste) bezeichnet. Der Algorithmus wird in Abschnitt 4.1.2 beschrieben, folgt aber zwei allgemeinen Prinzipien:
- Jeder Agent gibt seinen Kandidaten eine numerische Priorität, die zusammen mit dem Kandidaten an den Peer gesendet wird.
- Die lokalen und entfernten Prioritäten werden kombiniert, so dass jeder Agent die gleiche Reihenfolge für die Kandidatenpaare hat.
Die zweite Eigenschaft ist wichtig, damit ICE funktioniert, wenn sich vor L und R NATs befinden. Häufig erlauben NATs keine Pakete von einem Host, bis der Agent hinter dem NAT ein Paket an diesen Host gesendet hat. Folglich werden ICE-Prüfungen in jeder Richtung erst erfolgreich sein, wenn beide Seiten eine Prüfung durch ihre jeweiligen NATs gesendet haben.
Der Agent arbeitet diese Prüfliste ab, indem er periodisch eine STUN-Anfrage für das nächste Kandidatenpaar auf der Liste sendet. Diese werden als ORDINARY CHECKS (gewöhnliche Prüfungen) bezeichnet.
Im Allgemeinen ist der Prioritätsalgorithmus so konzipiert, dass Kandidaten ähnlichen Typs ähnliche Prioritäten erhalten und direktere Routen (d. h. durch weniger Medienrelais und durch weniger NATs) gegenüber indirekten (solche mit mehr Medienrelais und mehr NATs) bevorzugt werden. Innerhalb dieser Richtlinien haben Agenten jedoch einen gewissen Spielraum, wie sie ihre Algorithmen abstimmen.
2.4. Frozen Candidates (Eingefrorene Kandidaten)
Die vorangegangene Beschreibung behandelt nur den Fall, in dem die Agenten eine Mediensitzung mit einer COMPONENT (Komponente) aufbauen möchten (ein Teil eines Medien-Streams, der eine einzelne Transportadresse erfordert; ein Medien-Stream kann mehrere Komponenten erfordern, von denen jede funktionieren muss, damit der Medien-Stream als Ganzes funktioniert). Typischerweise (z. B. bei RTP und RTCP) müssen die Agenten tatsächlich Konnektivität für mehr als einen Fluss herstellen.
Die Netzwerkeigenschaften dürften für jede Komponente sehr ähnlich sein (insbesondere weil RTP und RTCP von derselben IP-Adresse gesendet und empfangen werden). Es ist normalerweise möglich, Informationen von einer Medienkomponente zu nutzen, um die besten Kandidaten für eine andere zu bestimmen. ICE tut dies mit einem Mechanismus namens "frozen candidates" (eingefrorene Kandidaten).
Jeder Kandidat ist mit einer Eigenschaft namens FOUNDATION (Fundament) verbunden. Zwei Kandidaten haben dasselbe Fundament, wenn sie "ähnlich" sind – vom gleichen Typ und vom gleichen Host-Kandidaten und STUN-Server unter Verwendung des gleichen Protokolls erhalten wurden. Andernfalls ist ihr Fundament unterschiedlich. Auch ein Kandidatenpaar hat ein Fundament, das nur die Verkettung der Fundamente seiner beiden Kandidaten ist. Zunächst werden nur die Kandidatenpaare mit eindeutigen Fundamenten getestet. Die anderen Kandidatenpaare werden als "frozen" (eingefroren) markiert. Wenn die Konnektivitätsprüfungen für ein Kandidatenpaar erfolgreich sind, werden die anderen Kandidatenpaare mit demselben Fundament freigegeben ("unfrozen"). Dies vermeidet die wiederholte Prüfung von Komponenten, die oberflächlich betrachtet attraktiver sind, aber tatsächlich wahrscheinlich scheitern werden.
Während wir "eingefroren" hier zu Erklärungszwecken als separaten Mechanismus beschrieben haben, ist es tatsächlich ein integraler Bestandteil von ICE, und der ICE-Priorisierungsalgorithmus stellt automatisch sicher, dass die richtigen Kandidaten freigegeben und in der richtigen Reihenfolge geprüft werden.
2.5. Security for Checks (Sicherheit für Prüfungen)
Da ICE verwendet wird, um herauszufinden, welche Adressen zum Senden von Medien zwischen zwei Agenten verwendet werden können, ist es wichtig sicherzustellen, dass der Prozess nicht gekapert werden kann, um Medien an den falschen Ort zu senden. Jede STUN-Konnektivitätsprüfung wird durch einen Message Authentication Code (MAC) abgedeckt, der unter Verwendung eines im Signalisierungskanal ausgetauschten Schlüssels berechnet wird. Dieser MAC bietet Nachrichtenintegrität und Datenursprungsauthentifizierung und hindert somit einen Angreifer daran, Konnektivitätsprüfnachrichten zu fälschen oder zu ändern. Wenn der SIP [RFC3261]-Anrufer ICE verwendet und sein Anruf gegabelt wird ("forks"), finden die ICE-Austausche außerdem unabhängig mit jedem gegabelten Empfänger statt. In einem solchen Fall helfen die in der Signalisierung ausgetauschten Schlüssel, jeden ICE-Austausch jedem gegabelten Empfänger zuzuordnen.
2.6. Concluding ICE (Abschluss von ICE)
ICE-Prüfungen werden in einer bestimmten Reihenfolge durchgeführt, so dass Kandidatenpaare mit hoher Priorität zuerst geprüft werden, gefolgt von solchen mit niedrigerer Priorität. Eine Möglichkeit, ICE abzuschließen, besteht darin, den Sieg zu erklären, sobald eine Prüfung für jede Komponente jedes Medien-Streams erfolgreich abgeschlossen ist. In der Tat ist dies ein vernünftiger Algorithmus, und Details dazu werden unten bereitgestellt. Es ist jedoch möglich, dass ein Paketverlust dazu führt, dass eine Prüfung mit höherer Priorität länger dauert. In diesem Fall könnte es bessere Ergebnisse liefern, ICE etwas länger laufen zu lassen. Grundsätzlich liefert die durch diese Spezifikation definierte Priorisierung jedoch möglicherweise keine "optimalen" Ergebnisse. Wenn das Ziel beispielsweise darin besteht, Medienpfade mit geringer Latenz auszuwählen, ist die Verwendung eines Relais ein Hinweis darauf, dass die Latenzen höher sein könnten, aber es ist nichts weiter als ein Hinweis. Es könnte eine tatsächliche Round-Trip-Time (RTT)-Messung durchgeführt werden, und diese könnte zeigen, dass ein Paar mit niedrigerer Priorität tatsächlich besser ist als eines mit höherer Priorität.
Folglich weist ICE einem der Agenten die Rolle des CONTROLLING AGENT (steuernder Agent) und dem anderen die des CONTROLLED AGENT (gesteuerter Agent) zu. Der steuernde Agent darf nominieren, welche Kandidatenpaare für Medien verwendet werden, unter denjenigen, die gültig sind. Er kann dies auf eine von zwei Arten tun – unter Verwendung von REGULAR NOMINATION (reguläre Nominierung) oder AGGRESSIVE NOMINATION (aggressive Nominierung).
Bei der regulären Nominierung lässt der steuernde Agent die Prüfungen fortsetzen, bis mindestens ein gültiges Kandidatenpaar für jeden Medien-Stream gefunden wurde. Dann wählt er unter den gültigen aus und sendet eine zweite STUN-Anfrage auf seinem NOMINATED (nominierten) Kandidatenpaar, diesmal jedoch mit einem gesetzten Flag, um dem Peer mitzuteilen, dass dieses Paar zur Verwendung nominiert wurde. Dies ist in Abbildung 4 dargestellt.
L R
- -
STUN request -> \ L's
<- STUN response / check
<- STUN request \ R's
STUN response -> / check
STUN request + flag -> \ L's
<- STUN response / check
Figure 4: Regular Nomination
Sobald die STUN-Transaktion mit dem Flag abgeschlossen ist, brechen beide Seiten alle zukünftigen Prüfungen für diesen Medien-Stream ab. ICE sendet nun Medien unter Verwendung dieses Paares. Das Paar, das ein ICE-Agent für Medien verwendet, wird als SELECTED PAIR (ausgewähltes Paar) bezeichnet.
Bei der aggressiven Nominierung setzt der steuernde Agent das Flag in jede STUN-Anfrage, die er sendet. Auf diese Weise ist die ICE-Verarbeitung für diesen Medien-Stream abgeschlossen, sobald die erste Prüfung erfolgreich ist, und der steuernde Agent muss keine zweite STUN-Anfrage senden. Das ausgewählte Paar ist das gültige Paar mit der höchsten Priorität, dessen Prüfung erfolgreich war. Aggressive Nominierung ist schneller als reguläre Nominierung, bietet aber weniger Flexibilität. Aggressive Nominierung ist in Abbildung 5 dargestellt.
L R
- -
STUN request + flag -> \ L's
<- STUN response / check
<- STUN request \ R's
STUN response -> / check
Figure 5: Aggressive Nomination
Sobald alle Medien-Streams abgeschlossen sind, sendet der steuernde Endpunkt ein aktualisiertes Angebot, wenn die Kandidaten in den m- und c-Zeilen für den Medien-Stream (genannt DEFAULT CANDIDATES (Standardkandidaten)) nicht mit den SELECTED CANDIDATES (ausgewählten Kandidaten) von ICE übereinstimmen.
Sobald ICE abgeschlossen ist, kann es jederzeit für einen oder alle Medien-Streams von jedem Agenten neu gestartet werden. Dies geschieht durch Senden eines aktualisierten Angebots, das einen Neustart anzeigt.
2.7. Lite Implementations (Lite-Implementierungen)
Damit ICE in einem Anruf verwendet werden kann, müssen beide Agenten es unterstützen. Bestimmte Agenten sind jedoch immer mit dem öffentlichen Internet verbunden und haben eine öffentliche IP-Adresse, unter der sie Pakete von jedem Korrespondenten empfangen können. Um es diesen Geräten zu erleichtern, ICE zu unterstützen, definiert ICE einen speziellen Implementierungstyp namens LITE (im Gegensatz zur normalen FULL (vollständigen) Implementierung). Eine Lite-Implementierung sammelt keine Kandidaten; sie enthält nur Host-Kandidaten für jeden Medien-Stream. Lite-Agenten generieren keine Konnektivitätsprüfungen oder führen die Zustandsautomaten aus, obwohl sie in der Lage sein müssen, auf Konnektivitätsprüfungen zu antworten. Wenn sich eine Lite-Implementierung mit einer vollständigen Implementierung verbindet, übernimmt der vollständige Agent die Rolle des steuernden Agenten und der Lite-Agent die gesteuerte Rolle. Wenn sich zwei Lite-Implementierungen verbinden, werden keine Prüfungen gesendet.
Hinweise dazu, wann eine Lite-Implementierung angemessen ist, finden Sie in der Diskussion in Anhang A.
Es ist wichtig zu beachten, dass die Lite-Implementierung dieser Spezifikation hinzugefügt wurde, um ein Sprungbrett zur vollständigen Implementierung zu bieten. Selbst für Geräte, die immer mit dem öffentlichen Internet verbunden sind, ist eine vollständige Implementierung vorzuziehen, wenn sie erreichbar ist.