Der SOCKS-Handshake ist gelungen. Nun liest das Relay vom Client, schreibt zum Ziel, wartet auf eine vollständige Antwort und liest erst danach wieder vom Client. Diese Reihenfolge kann eine völlig gültige Anwendung verklemmen.

Sobald der TCP-Tunnel steht, definiert SOCKS die Nachrichten darin nicht. Das Ziel könnte zuerst senden. Beide Seiten könnten unabhängig senden. Eine Seite könnte einen kurzen Datensatz senden und dann auf die Antwort der anderen warten.

Bytes weiterreichen, keine geratenen Transaktionen

Ein Empfangsaufruf liefert die verfügbaren Bytes gemäß seinen Flags und dem Socket-Zustand. Er teilt einem allgemeinen Relay nicht mit, dass eine Anwendungsantwort vollständig ist. Das Warten auf das Füllen eines beliebig großen Puffers kann verhindern, dass die kleine Nachricht weitergeleitet wird, die der Partner zum Fortfahren braucht.

Nutzen Sie das vorhandene Nebenläufigkeitsmodell der Anwendung, um beide Richtungen zu bedienen: eine Ereignisschleife, asynchrone E/A oder ein anderer bewusst gewählter Entwurf. Wichtig ist, dass Fortschritt in einer Richtung keine erfundene Nachrichtengrenze in der anderen erfordert.

Zwei begrenzte ausstehende Puffer halten

Vom Client gelesene Daten warten möglicherweise noch darauf, das Ziel zu erreichen, während Daten vom Ziel darauf warten, den Client zu erreichen. Verfolgen Sie diese ausstehenden Bytes getrennt.

Ein Sendeaufruf kann weniger Bytes schreiben als angefordert. Behalten Sie den ungeschriebenen Teil; verwerfen Sie ihn nicht und spielen Sie nicht den gesamten Puffer erneut ab. Ein vorübergehend nicht beschreibbarer Socket ist ein Grund, auf das richtige Bereitschaftsereignis zu warten, nicht ständig zu drehen.

Begrenzen Sie die Puffer. Ist das Ziel langsam, verschiebt das Weiterlesen unbegrenzter Client-Daten die Warteschlange nur in den Speicher des Relays. Rückstau bedeutet, Lesen zu pausieren, wenn der zugehörige Puffer voll ist, und fortzusetzen, wenn Schreibvorgänge Platz schaffen.

Ein Ende in einer Richtung braucht eine Richtlinie

TCP kann eine Senderichtung schließen, während die andere Richtung noch nützliche Daten hat. Entscheiden Sie, wie dieser Zustand nach dem Leeren der gepufferten Bytes weitergegeben wird, und unterscheiden Sie geordnetes Schließen von einem Fehler oder einer Frist.

Nichts davon verlangt, dass das Relay die Nutzlast der Anwendung entschlüsselt oder auswertet. Es braucht korrekte Strombehandlung. Allein eine größere Puffergröße kann ein Relay nicht reparieren, das auf die falsche Seite wartet oder annimmt, jedes Lesen entspreche einer ganzen Anfrage.

Ähnliche Artikel