Twitter iPhone pliant OnePlus 11 PS5 Disney+ Orange Livebox Windows 11

Telnet et read() sur socket bloquant

1 réponse
Avatar
Vincent Hiribarren
Bonjour,

j'ai un assez gros problème concernant l'implantation d'une sorte d'API
pour envoyer des commandes unix via telnet. En gros, je veux
automatiquement :
- me logger via telnet sur un système unix
- envoyer une commande
- récupérer les sorties standards générées par la commande
- terminer la connexion.

J'ai bien trouvé des implantations open sources (jtelnet, jta25), mais
elles servent toutes surtout à implanter un client telnet interactif là
où je ne veux envoyer qu'une seule commande unix automatique via le
protocole telnet. De ce que j'ai vu, c'est plus qu'embêtant à implanter
dans la mesure où on ne sait pas quand commence et se termine
l'exécution de la commande unix : on ne peut vraiment se baser que sur
la reconnaissance de l'invite du shell courant, ce qui n'est pas
terrible. De même, il faut envoyer le login/password au bon moment,
c'est à dire après avoir reçu l'invite d'entré de l'identifiant.

jta25 se débrouille par exemple en cherchant les mots clefs "login",
"password", et en séparant les résultats des commandes unix en
reconnaissant l'invite du shell... qu'on lui a préalablement déclaré
dans le code. A mon sens, c'est vraiment pas génial et pas suffisamment
automatisé, du moins pour ce que je veux faire. L'invite du shell n'est
pas forcément la même pour tous les systèmes, et parfois on a du texte
déchet ("SunOS System... Last login was...") qu'il faut séparer du reste.

Pour le résultat de la commande unix je me débrouille à peu près. Là où
je bloque c'est pour se logger, et la transition entre se logger et
l'envoi de la commande. Quand on cherche à se connecter, voilà ce qui
arrive :
- envoi de texte déchet par le serveur
- invite de login
- blocage du read() sur le flux de la socket
- invite de password
- blocage du read() sur le flux de la socket
- envoi de texte déchet par le serveur + invite
- blocage du read() sur le flux de la socket

Donc pour décomposer les actions, le seul moyen que je vois, c'est de se
baser sur les blocages de lecture de la socket... Oui, pas terrible.
Surtout que quand le read() bloque, et bien... ça bloque, et ça il faut
le détecter tout en se débloquant. Et je ne vois pas de solution
élégante pour y arriver facilement. Je pense crédible de considérer
qu'on n'a pas de blocage entre les blocages détaillé au dessus, le
nombre de lettres envoyés étant très faible et pouvant tenir sur un seul
paquet. Si juste après un des blocage régulier donné au-dessus on a un
blocage autre, on peut considérer que le paquet n'est pas encore arrivé
et l'attendre.

Un moyen que je vois et de mettre un timer via setSoTimeOut() sur ma
socket, et de récupérer l'exception générée en cas de blocage de
lecture. Mais je n'aime pas cette solution. Surtout qu'il faut régler le
TimeOut pour qu'il ne soit pas trop long, pas trop court, universel...

Bref, des idées ? Comment puis-je faire ? Si vous avez déjà rencontré ce
genre de problème, comment l'avez-vous résolu ? Là je verrai un système
à base de Threads avec une sorte de WatchDog qui regarderait le
processus de lecture de socket, et préviendrait si au bout d'un certain
temps une variable n'a pas été réactualisée, mais ça revient à se baser
sur un timeout... Ce que je n'aime guère.

Merci d'avance pour vos idées !

1 réponse

Avatar
Hervé AGNOUX
Vincent Hiribarren wrote:

[...]
Bref, des idées ? Comment puis-je faire ? Si vous avez déjà rencontré ce
genre de problème, comment l'avez-vous résolu ? Là je verrai un système
à base de Threads avec une sorte de WatchDog qui regarderait le
processus de lecture de socket, et préviendrait si au bout d'un certain
temps une variable n'a pas été réactualisée, mais ça revient à se baser
sur un timeout... Ce que je n'aime guère.



Comme tu dis, inutile de chercher : il n'y a aucune solution éléguante :-)
Tout se fait à partir d'observations du comportement des shells et logins,
de devinettes sur la forme des prompts, etc.

Je ne sais pas quel est ton contexte. Moi j'ai à l'utiliser dans un contexte
relativement organisé, ou le prestataire maîtrise à la fois le coté serveur
et la portion client telnet ; donc ils se fabriquent des utilisateurs unix,
des logins et des prompts à leur main, et même comme cela ce n'est pas
toujours facile.

Si tu veux pouvoir commander un séquence shell interactif sans préssuposés
minimas, je ne suis vraiment pas sûr que ce soit possible. Je ne sais pas
quels sont tes contraintes, mais à mon avis la meilleure solution en ce cas
serait plutôt de s'orienter vers l'usage de logins et shells non
interactifs (déjà y'a plus le problème du prompt), ou tu exécutes sur le
serveur distant un fichier de commande.

Cordialement.


--
Hervé AGNOUX
http://www.diaam-informatique.com