La poignée de main SOCKS a réussi. Le relais lit maintenant chez le client, écrit vers la destination, attend une réponse complète et ne relit le client qu'ensuite. Cette séquence peut bloquer une application parfaitement valide.

Une fois le tunnel TCP établi, SOCKS ne définit pas les messages qu'il contient. La destination peut envoyer en premier. Les deux côtés peuvent envoyer indépendamment. Un côté peut envoyer un court enregistrement puis attendre la réponse de l'autre.

Transmettez des octets, pas des transactions devinées

Un appel de réception renvoie les octets disponibles selon ses indicateurs et l'état de la socket. Il ne dit pas à un relais générique qu'une réponse applicative est complète. Attendre le remplissage d'un tampon arbitrairement grand peut empêcher de transmettre le petit message dont le pair a besoin pour continuer.

Utilisez le modèle de concurrence existant de l'application pour servir les deux directions : une boucle d'événements, des E/S asynchrones ou une autre conception délibérément choisie. Le comportement important est que le progrès dans une direction n'exige pas de frontière de message inventée dans l'autre.

Gardez deux tampons en attente bornés

Les données lues chez le client peuvent encore attendre d'atteindre la destination, tandis que les données de la destination attendent d'atteindre le client. Suivez ces octets en attente séparément.

Un envoi peut écrire moins d'octets que demandé. Conservez la partie non écrite ; ne la jetez pas et ne rejouez pas tout le tampon. Une socket temporairement non inscriptible est une raison d'attendre le bon événement de disponibilité, pas de tourner en continu.

Bornez les tampons. Si la destination est lente, continuer à lire des données client illimitées ne fait que déplacer la file dans la mémoire du relais. La contre-pression consiste à suspendre les lectures lorsque le tampon en attente correspondant est plein et à les reprendre lorsque les écritures libèrent de la place.

Une fin dans une direction demande une politique

TCP peut fermer une direction d'envoi alors que l'autre direction contient encore des données utiles. Décidez comment propager cet état une fois les octets tamponnés évacués, et distinguez une fermeture ordonnée d'une erreur ou d'un délai.

Rien de tout cela n'exige que le relais déchiffre ou analyse la charge utile de l'application. Il a besoin d'un traitement de flux correct. Augmenter seule la taille du tampon ne peut pas réparer un relais qui attend le mauvais côté ou suppose que chaque lecture correspond à une requête entière.

Articles similaires