Identification

Nous souhaitons identifier les logiciels tournant sur certains ports. Plutôt que de nous contenter d'ouvrir une connexion, nous allons maintenant retourner une valeur indiquant la ligne d'entête renvoyée par le service sur lequel nous nous sommes connecté si elle arrive dans un temps raisonnable :

$ cargo run -- ping -o www.free.fr,smtp.free.fr,imap.free.fr,ftp.free.fr 21,25,80,143,587
ftp.free.fr:21 is open: 220 Welcome to ProXad FTP server
imap.free.fr:143 is open: * OK IMAP4 ready
smtp.free.fr:25 is open: 220 smtp3-g21.free.fr ESMTP Postfix
smtp.free.fr:587 is open: 220 smtp3-g21.free.fr ESMTP Postfix
www.free.fr:80 is open

Le résultat est cohérent : le serveur FTP (port 21), le serveur IMAP (port 143) et les serveurs SMTP (port 25 et port 587) s'annoncent spontanément. Par contre le serveur HTTP (port 80) n'enverra une réponse que si on envoie une requête.

  1. Ajoutez un type scanner::IdentificationResult contenant trois alternatives : WelcomeLine(String), NoWelcomeLine et ConnectionRefused.
  2. Écrivez une fonction asynchrone scanner::net::welcome_line() qui prend un tokio::net::TcpStream en paramètre et qui renvoie un IdentificationResult contenant soit WelcomeLine(…) si le serveur a envoyé une ligne de bienvenue dans la première seconde, ou NoWelcomeLine dans tous les autres cas.

Bien entendu, si on n'a jamais obtenu de TcpStream car la connexion a échoué, on renverra ConnectionRefused.

Vous pouvez enrichir votre stream de capacités de lecture plus puissantes en l'encapsulant dans un tokio::io::BufReader qui implémente le trait tokio::io::AsyncBufRead. Ce trait est étendu par le trait d'extension tokio::io::AsyncBufReadExt. On notera également qu'il est facile d'éliminer d'éventuels caractères de fin de ligne parasites avec des fonctions existantes de str.

  1. Modifiez la fonction tcp_ping() pour qu'elle appelle welcome_line() si la connexion au serveur distant réussi. Le résultat devra être modifié pour renvoyer un IdentificationResult à la place du bool précédemment utilisé.

  2. Modifiez vos fonctions tcp_ping(), tcp_ping_many() et tcp_mping() pour propager de la même manière ce résultat.

  3. Modifiez le programme principal pour qu'il affiche la ligne d'identification quand elle est disponible comme dans l'exemple ci-dessus.