IFT585 -- Travail pratique #4

Date de remise: 4 août 2014, 23:59:59

Robustesse de connexion

Nous poursuivons le développement de l’application d’exécution de programmes à distance amorcée durant le TP2. Le but de ce dernier TP est de développer, au niveau de l’application, des procédés d’échange de données entre le client et le serveur qui soient robuste aux pertes de connexion.

Ce problème est inhérent au fait que l’internet est un milieu d’échange fluide, où le service et la connectivité ne sont pas garantis. Lorsqu’on se connecte à un serveur par le protocole TCP, les transmissions entre les pairs connectés sont garanties, à l’exception d’une panne de service. Ainsi, la perte de la connexion est une condition limite qui doit être gérée tant par le serveur que par le client. Cependant, pour certaines applications, on aimerait pouvoir bâtir sur une connexion TCP l’abstraction d’une connexion robuste. Une telle connexion, articulée par un protocole de transport construit sur TCP, fait en sorte qu’en cas de perte de connexion, le client et le serveur font le nécessaire pour reprendre contact et poursuivre leurs échanges, sans que l’application ne s’en rende compte. De son côté, l’application ne subirait qu’un temps de transfert plus long que d’ordinaire dans ses échanges.

Une telle perte de connexion peut s’accompagner d’une perte partielle de données en cours de transmission. On peut considérer ce problème comme celui d’une connexion non fiable. La solution est alors l’algorithme de la fenêtre coulissante, que nous avons implanté au cours du TP2. Il reste donc à ajouter au module connection.py développé durant le TP2 la fonctionnalité nécessaire pour restaurer une connexion TCP perdue à un moment inopportun. Dans le cadre de cette tâche, il faut considérer deux éléments importants:

  1. Lorsque la connexion TCP se ferme, on tente de la restaurer. Cependant, il vient un moment dans l’exécution du programme où on désire délibérément fermer la connexion. Il faut donc implanter, dans le protocole encadrant l’échange de messages robuste, une séquence d’échange de messages menant à la fermeture de la connexion. Pour se faire, on peut s’inspirer du protocole TCP, dont la séquence de fermeture vise effectivement à distinguer une honnête interruption de la connexion d’une simple perte de paquets.
  2. Un serveur admet des connexions simultanées de multiples clients. Ainsi, il faut augmenter le protocole encadrant la connexion robuste une façon pour un client de s’authentifier lorsqu’il se connecte au serveur. De cette façon, le serveur peut déterminer si ce client reprend l’une de plusieurs connexions en cours (qui aurait été interrompue) ou s’il s’agit d’un tout nouveau client, pour lequel il faut démarrer un nouveau programme.

Contexte du travail

Vous devriez entreprendre votre travail à partir de cette solution complète et correcte du TP2. Réalisez votre travail en modifiant exclusivement le module connection.py. Consultez l’énoncé du TP2 pour une récapitulation de l’architecture du module connection.py.

Procédé d’attaque

Comme pour le TP2, les pertes de données et de connexions sont réalisées à l’aide d’une attaque par interposition mise en oeuvre via la classe ManInTheMiddle (disponible dans le module mitm.py passé dans l’archive liée ci-haut).

Invariants

La solution du TP2 liée ci-haut contient le code des tests ayant été exécutés pour la correction du TP2. Votre solution doit à son tour réussir ces tests: il s’agit d’un invariant à satisfaire. D’une part, considérons ce qu’il faut faire pour exécuter les tests du TP1. Si on décompresse l’archive, on a dans le répertoire courant les sous-répertoires suivants:

mitm
resh
solution
test

Pour exécuter les tests unitaires du TP1, on se place dans le sous-répertoire test et on exécute la ligne de commande qui suit:

PYTHONPATH=`pwd`/../solution python -u tp1.py ../resh

D’autre part, pour exécuter tous les tests du TP2, on se place similairement dans le sous-répertoire test, puis on exécute:

./alltests.sh ../solution s '>>>>'

Les tests du TP2 nécessitent l’outil tmux, de manière à scripter l’affichage simultané d’un client, d’un serveur et d’une attaque d’interposition. S’il n’est pas installé sur votre machine Ubuntu, vous pouvez installer tmux avec la commande

sudo apt-get install tmux

Lorsque vous voyez la ligne *** Client dead ***, appuyez sur [Enter] pour passer au test suivant. Par ailleurs, chacun des tests unitaires peut être exécuté par lui-même. Par exemple, pour exécuter le test 1, la ligne de commande est

./1_test_frame_reordering.sh ../solution

Les deux derniers tests, qui portent sur des problèmes spécifiques de cadrage, nécessitent qu’on passe aussi la chaîne de caractères correspondant à la sentinelle de fin de cadre, soit >>>>, pour compléter leur exécution adéquatement. Ces tests sont donc invoqués comme suit:

./Ca_test_insert_sentinel_in_body.sh ../solution '>>>>'
./Da_test_force_sentinel_in_body.sh ../solution '>>>>'

Le cadre de mise en oeuvre des tests unitaires du TP2 est relativement simple à comprendre, aussi gagnerez-vous à implanter vos propres tests de manière similaire, afin de pouvoir facilement reproduire vos tests à mesure que vous progressez dans le développement.

Instructions pour la remise

  • Le travail est exécuté par équipes de deux.
  • Le travail doit être remis par courriel à l’une de ces deux adresses: benoit@benoithamelin.com, benoit.hamelin@usherbrooke.ca.
    • Le sujet du courriel: IFT585 TP4
    • Le corps du courriel doit contenir le nom des deux coéquipiers.
    • Un fichier nommé connection.py doit être inclus en pièce jointe.

Évaluation

  • Le travail est évalué sur 20 points:
    • Conformité aux instructions de remise: 2 points
    • Propreté de la sortie des programmes: 1 point
    • Satisfaction des invariants et consignes de développement: 3 points
    • Robustesse de la connexion face aux attaques de rupture: 14 points
  • La conformité du code aux exigences sera testée à l’aide de programmes externes basés sur l’attaque d’interposition dont le code de base est donné. Mettre en oeuvre des tests adéquats en regard de la spécification fait partie de votre travail.
  • Le code ne sera pas examiné. Ses qualités intrinsèques ne sont pas évaluées. On s’attend à ce que la difficulté du problème cause des problèmes de maintenance intractables (ou, à tout le moins, douloureux) pour des programmes conçus avec négligence ou sans égard à la lisibilité.