 Donc, bienvenue dans cette interprétation du talk d'Hannes Menach sur le protocole TCP Transmission Control Protocol. Hannes Menach travaille dans une organisation non gouvernementale, le centre pour la cultivation de la technologie. Et il travaille aussi sur MIRAGE OS qui est un système d'exploitation, open source. Ces recherches touchent différentes parties de l'ingénierie, la programmation, les protocoles réseaux, les protocoles de sécurité et bien d'autres choses. Donc, tous vos applaudissements pour sa présentation. Merci. Aujourd'hui, j'aimerais un peu parler du protocole TCP et des protocoles Internet. Donc, de quoi s'agit-il ? C'est un talk fondamental. Donc, si vous connaissez déjà Parker, TCPIP, peut-être que vous ne serez seulement intéressé par les cinq dernières minutes, mais sinon, si ce n'est pas le cas, si vous voulez brancher votre laptop ou si vous voulez aller sur un site web quelque part, vous avez besoin de contacter ce site web, donc le client, le browser sur le laptop envoie une requête HTTP au serveur web, qui est spécifiée par le protocole HTTP, par exemple Gatslash pour obtenir la racine, une méthode commune pour obtenir la page principale dans un site web. Mais comment est-ce que la transmission de l'information au serveur se passe en réalité ? C'est la motivation centrale de ce talk, c'est quelque chose dans lequel j'aimerais entrer dans les détails. Donc, regardons un peu la topologie d'un réseau. À gauche, on a le laptop qui envoie un serveur, une requête GET, on peut voir ça avec la ligne pointillée. Le laptop, en tant que tel, est probablement branché en wifi, internet, mais c'est quoi internet ? Bon, en réalité, internet, c'est une collection d'ordinateurs, ton laptop ou n'importe quoi, est probablement connecté à un router, mais un router, c'est juste un ordinateur normal qui connaît la topologie du réseau dans une certaine mesure, et ce router est probablement connecté par fibre ou par satellite ou n'importe quel autre type de lien, pas forcément un câble, à un autre router ou à des routeurs, des serveurs. Sur cette image, il n'y a que de routeur à et routeur B, mais en réalité, il peut y avoir un nombre potentiellement important de routeurs entre vous et le serveur. Donc, là, le router B est connecté en internet, qui est juste un câble électrique, physique, et internet est le protocole qui permet de communiquer sur un câble. Donc, je ne vais pas rentrer dans les détails physiques de la connectivité, fibre, satellite, câble, etc. Il n'y a pas de cuivre dans ce talk, mais je vais commencer avec le layer qui est au-dessus de la couche du médium physique, donc la première, c'est la couche de lien de données, de tallynclayer, donc à quoi ça sert, quelle est sa tâche. Donc, il n'a lieu uniquement sur le lien sur lequel les machines sont connectées. Typiquement, le layer 2, c'est uniquement entre laptop et router A ou router B et le serveur. Donc, c'est vraiment au niveau local, le layer B. À quoi ça sert, c'est plutôt simple, ça sert à bouger des paquets d'internet entre deux autres sur le même lien physique. Donc, son seul but, c'est de fournir une abstraction de la chose physique sous-jacente, de combien de bytes on peut transporter en une fois, etc. Donc, le layer du dessus, c'est le layer internet déjà. Donc, sa tâche est de transporter des paquets entre différents réseaux, entre des résoms multiples. Donc, sur le diagramme, on avait le router A et le router B qui étaient tous les deux connectés à plusieurs tallynclayers et ils utilisent la couche internet pour communiquer la couche internet, résout déjà le problème des adresses de l'adressage en donnant à chaque hôte une adresse IP. L'adresse IP signifie Internet Portable Address et la couche internet a aussi une autre tâche qui est le routage des paquets. Donc, ré-expédier des paquets aux routeurs suivants en principe, on espère, le plus proche de la désignation finale. La couche internet supporte aussi la fragmentation des paquets. Donc, par exemple, si votre couche supérieur, on voit quelque chose qui est beaucoup plus gros pour la couche data link, alors la couche internet peut fragmenter ça en plusieurs paquets. Donc, au-dessus du layer internet, on a la couche de transport. La couche de transport, c'est la connectivité d'hôte à hôte. Ça permet de faire du multiplexage en utilisant des ports, sources et destinations. Il y a deux protocoles les plus utilisés au niveau transport, d'ailleurs. C'est l'UDP, User Data Gram Protocol et le TCP, Le Transmission Control Protocol. Ils ont des caractéristiques différentes. Donc, l'UDP n'est pas fiable. Les paquets ne sont pas dans l'ordre. C'est juste une abstraction sur un datagram. Et l'avantage, c'est qu'on n'a pas beaucoup d'accès. Tandis que TCP, c'est fiable. Et on a un flow de données dans l'ordre sur lequel on peut bosser. Donc, l'inconvénient, c'est que l'établissement et la suppression de la connexion sont un peu plus complexes. En UDP, il n'y a pas besoin d'établir ou de fermer une connexion. Tandis qu'en TCP, il faut synchroniser l'état des deux autres. Et au-dessus de la couche de transport, enfin, on a la couche applicative. La couche applicative échange juste des données applicatives par-dessus la couche de transport. Donc, par exemple, on a des l'air applicatif tel que HTTP, TLS ou DNS. Dans le premier exemple qu'on a vu, il y avait du HTTP. Et c'était une requête GET en HTTP. Donc, dans ce talk, pas de concentration sur la couche applicative. Pour les couches inférieures, c'est juste une payload, un contenu. Donc, on a donc cette image. On a dessiné les différentes couches réseaux qui sont utilisées par les différents appareils. Ce qui nous donne un diagramme similaire à ceci. Donc, on peut voir encore notre laptop avec les quatre couches. Et ensuite, on a les routers au milieu qui n'utilisent que les couches de données et la couche Internet. Et tout à droite, on a le serveur qui a lui aussi les quatre couches. Donc, la couche de transport, c'est haute à haute. Donc, le TCP, le fait d'établir une connexion TCP entre le laptop et le serveur. Et par-dessus le TCP, on a la communication process à process. Donc, on a l'application qui parle au server web. Donc, la get request, elle n'apparaît qu'en haut. Les routers n'ont pas nécessairement besoin d'inspecter ou d'utiliser des informations de la couche de transport ou de la couche applicative. Que ce soit du laptop ou d'ailleurs. Donc, la couche Internet suffit au routeur pour réexpédier les données, les paquets au routeur suivant ou à la destination. Donc, le laptop envoie un segment ou un paquet TCP entier au routeur. Le routeur décide. Je vais l'envoyer au routeur B. Parce que c'est le routeur B qui est le plus près de la décisation finale. Et le routeur B dit, ah oui mais je sais, je connais ce serveur, je suis connecté en Internet, alors je vais l'envoyer en Internet au serveur. C'est à ça que ressemblera le flow de données dans une connexion de ce style. Donc, le paquet ressemble à quoi ? On a vu la couche applicative en bleu. Et c'est donc la requête get. Après, la couche de prankfort de transport rajoute un préfix avec l'entête TCP qui en code certaines données dont on va parler bientôt. Ensuite, on a la couche Internet qui rajoute aussi un entête, un préfix, l'entête IP qui est mis à l'avant de l'entête TCP. Et enfin, le lien de données, la couche la plus basse à laquelle on va s'intéresser, va probablement préfixer et suffixer d'un lentette et d'un suffix. Histoire d'être sûr qu'au niveau physique sur le câble, l'état soit bien synchronisé. Donc, de ces deux images, vous pouvez voir d'un côté les deux couches du bas. Et à chaque couche, quand on descend, on rajoute des informations dans les entêtes. La couche Internet par exemple, si on prend un entête TCP, on a alors la payload TCP qui est l'application. La donnée applicative. Et on peut remplacer ça par de l'UDP. Donc je ne vais pas rentrer dans les détails du data link layer. Donc on peut voir un entête IPv4 d'un paquet ou d'un frame IPv4. Donc c'est au minimum 20 octets avec certains champs, la version sur 4 bits. En général, actuellement, c'est la version 4. Ensuite, on a 4 bits qui décrivent la longueur de l'entête, multiplié par 32 bits. Donc là, on a un octet qu'on va ignorer. Puis la longueur totale sur 16 bits qui décrit la longueur totale du paquet IP. Ensuite, on a un champ d'identification qui fait aussi 16 bits, qui a un nombre unique. Et 16 bits pour des flags sur la fragmentation et d'autres fonctionnalités. Comment est-ce que la couche IP décide que faire de ce paquet applicatif ? Est-ce que je dois le fragmenter ? Si c'est le cas, ça va réutiliser le même numéro d'identification. Et on va voir des flags dans ce champ de fabrication et offset. Ensuite, on a un champ de 8 bits. Donc un byte, un octet. Le TTL, le temps à vivre, c'est un compteur. Pendant combien de routeurs ce paquet doit être propagé ? Chaque routeur décrémente le contenu de ce champ. Ensuite, on a un champ protocol d'un octet qui indique le type de la payload. Dans un paquet IPv4. Et ensuite, on a la somme de contrôle de l'entête, qui est un CRC. Pour détecter si certains bits ont été inversés pendant le transport. Ensuite, on a l'adresse IP sourd, c'est l'adresse IP destination. Donc, l'IP sourd, c'est celle du laptop. L'IP destination, c'est celle du serveur. Et enfin, après ces 20 octets, on a soit des options dans le protocole, si le champ de longueur est supérieur à 20, ou si non, on a directement la payload. Donc, pour le champ protocole, il y a différents types prédéfinis. Par exemple, ICMP, le protocole de messages de contrôle internet. Qui a le numéro 1 dans son protocole field, dans son champ de protocole. Et 6 pour TCP, 17 pour IDP. Il y a d'autres protocoles qui faut être transportées sur un paquet IP, mais je n'entrairai pas dans les détails. Comme vous pouvez voir, il y a en tout cas 255 numéros de protocole, vu qu'il fait 8 octets de long. On peut rentrer 256 noms différents dans ce champ. Donc, ICMP, c'est un protocole dont je n'ai pas du tout parlé. C'est le protocole de messages de contrôle de l'internet. Donc, c'est un protocole au-dessus du protocole IP. Et son but, c'est d'envoyer des messages d'erreur, du type l'autre de destination n'est pas accessible, ou le type to live a été dépassé. Et ça permet aussi d'effectuer de l'opérationnel. Par exemple, de direct nostiques ou d'écos. Donc, il y a ping. Typiquement, ping, c'est quoi ? C'est qu'on envoie une requête d'éco-routeurs, et le routeur va renvoyer le même paquet avec un bit qui change, et c'est une réponse d'éco. Et ça permet de déterminer que si ça fonctionne correctement, on peut vérifier qu'on a la connectivité IP avec cette autre haute sur cette ligne. Donc, dans la couche de transport, on va regarder pour commencer un entête UDP. Donc, il fait que 8 hectares avec un port source, un port destination, la longueur du datagram UDP et une somme de contrôle. La somme de contrôle fait aussi 16 octaires qui est calculée sur la charge utile complète de l'entête et d'un pseudo-entête IP dans lequel on a les informations de l'adresse IP source et destination. Donc, comme je vais déjà dire, l'UDP, c'est pas fiable et c'est pas dans l'ordre, mais du coup, on a moins d'overhead, on a moins de données dans l'entête, seulement 8 octaires. Alors que le protocole IP a déjà rajouté 20 octaires. Donc, voici un programme UNIX simple qui se compile pas parce que j'en ai enlevé certains bouts, mais ça permet de voir comment est-ce qu'on utilise cette pile IP. Donc, la pile TCPIP est en général dans le noyau et a une API de programmation. Donc, on a la paix de Socket UNIX et donc, en général, elle contène toutes les mêmes six sous cette fonction. Donc, la première, c'est Socket, Socket Open. Donc, ça ouvre un descripteur de fichier, ça spécifie la famille d'adresse et le type de Socket. Donc, là, ça veut dire que c'est une famille d'adresse Internet et que c'est une Socket orientée d'atagram. Donc, une fois que c'est créé, on récupère le file descriptor et pour un client UDP, il y a juste à dire je vais utiliser la fonction send to qui prend en paramètre le file descriptor de la Socket et la donner à envoyer afin de l'envoyer à l'autre bout. Donc, c'est pas fiable, c'est juste envoyer et oublier. Et enfin, on ferme un Socket avec un close si on a envie d'être sympathique. Et de l'autre côté, si on veut implémenter non pas un client mais un server UDP, ce qu'on fait, on ouvre encore une Socket. Ensuite, on a une fonction qui s'appelle Bind. Qui lit un file descriptor à une adresse IP spécifique sur le serveur ou sur la pile réseau. Et ensuite, on a une fonction qui s'appelle Receiform qui prend le file descriptor de la Socket, un buffer, une taille maximum, un offset. Et le Receiform retournera des données qu'une fois qu'il aura reçu des datagrams UDP sur ses adresses IP et support. Ensuite, on peut afficher qu'on a contenu un paquet et fermer le file descriptor. Donc, ça, c'est pour l'UDP. L'UDP s'est utilisé par pas mal de protocoles. C'est crucial de l'avoir. TCP de son côté est un peu plus grand. Donc, au lieu d'avoir un header de 8 octets, on a à minima 20 octets de verre. Donc, de manière similaire, on a les ports sourcés de destination sur 16 bits. Puis, on a un numéro de séquence. Donc, qu'est-ce que c'est ? C'est un nombre de 32 bits. Ensuite, on a un nombre d'acknowledgements, ce qui est le dernier numéro de séquence qu'on a reçu de l'autre partie à la communication. Ensuite, on a un data offset. Donc, les segments TCP peuvent être fragmentés. Et donc, dans le cas où on a plusieurs fragments, on a cet offset qui permet de savoir à quel endroit dans la payload, on doit mettre ce qu'on a reçu dans ce fragment-là. Donc, on a aussi bien entendu des flags sur un bit. Donc, il y en a certains qui sont là en bas. Hacknowledgements, hack, synchronize, ou SIN, et finished or fin. Il y a aussi reset des flag-urgents, mais je n'irai pas dans les détails. Ensuite, on a un champ de 16 bits, qui est la taille de fenêtre. C'est la taille du tampon de réception. Puis, on a encore un checksum sur 16 bits. Et on a 16 bits de libre pour les fonctionnalités d'urgence dont on ne rentra pas dans les détails. Donc, voilà, un client TCP programmé sur la payee Unix. Vraiment similaire à ce qu'on a sur UDP. On appelle d'abord la fonction socket pour créer un file descriptor. Donc, on utilise toujours la famille d'adresse internet. Et là, on utilise Sox Stream, qui signifie qu'on veut un flow de connexion. Donc, une socket TCP, on mettra toujours Sox Stream. Ensuite, en tant que client, on se connecte en utilisant la socket, à notre au-distan. Et une fois qu'on a connecté, connecté va répondre uniquement une fois qu'on a rétabli la session TCP. Ensuite, on appelle la fonction receive, RECV. Donc, on spécifie le file descriptor de la socket, un buffer, la longueur, et on reçoit ça dedans, on peut l'afficher. Donc, le serveur TCP, c'est similaire. Donc, d'abord, on crée une socket, puis on la lit à un IP et un port avec la fonction bind. Ensuite, on utilise une fonction qui s'appelle listen sur le file descriptor de la socket. Ensuite, on rentre dans une bouche. On va à présent attendre des connexions de clients. En certains moments, un client va se connecter. Et à chaque fois qu'un client se connecte, on va appeler la fonction accept, qui va retourner un file descriptor si on a établi avec succès la connexion TCP. Donc, ça nous renvoie un nouveau file descriptor. Donc, c'est pas le même que la socket. On va continuer d'appeler accept sur le file descriptor de la socket. Et en général, quand on a du boulot à faire un file descriptor du client, on va faire ça dans une tâche distincte ou dans un process distinct pour que le serveur puisse continuer à accepter d'autres connexions pendant qu'on gère la connexion qu'on a reçue. Donc, là, on affiche avec printf et on envoie Hello World au client sur ce nouveau file descriptor qui correspond à la connexion du client. Puis on ferme la connexion et on continue à accepter de nouvelles connexions du client. Donc, c'est un serveur TCP tel qu'on peut le voir dans plein de programmes réseaux. Donc, TCP, comme je l'ai déjà dit, doit faire un peu de travail afin d'établir une session. Donc, essentiellement, ce qu'il doit faire c'est synchroniser le numéro de séquence au départ parce qu'on a vu dans l'entête on a ce numéro de séquence et on a besoin d'envoyer cette information à l'autre partie. Donc, voilà la machine à état TCP qui fait partie de la RFC qui est la spécification de TCP et qui est également dupliqué dans des documents comme l'implementation de TCP IP et d'autres bouquins. Donc, on peut voir ici qu'il y a un état spécifique qui est listen, écouté. Donc, comme on a vu dans l'implementation du serveur, quand on appelle la fonction listen, il attend des connexions. On commence toujours à listen et on finit toujours à close. On ferme la connexion en bas. Je vais rentrer dans plus de détails sur l'établissement des connexions. Donc, l'établissement de la connexion on assigne du côté du client. On commence avec une socket qui est fermée. On appelle l'appel système connect pour connecter la socket. Donc ça, on voit un segment TCP initial au serveur qui a le flag SIN qui est activé, qui est mis à 1 ou à vrai et un numéro de séquence quelconque qu'on va appeler A sur 32 bits. Un entier aléatoire. Donc, l'état du file descripteur passe de fermer à SINcent pour dire qu'on a envoyé le paquet avec le flag SIN pour la synchronisation. Donc, c'est un segment TCP sans donner qu'il y a juste un header, un en-tête. Du côté du serveur, on était en closed mais on a préparé le serveur en appelant la fonction listen et donc on était dans l'état listen. On écoute les connexions. Puis on a appelé accept et bloquant jusqu'à ce qu'on ait reçu un paquet avec un SIN d'un client. Et une fois que c'est le cas, on a un nouveau file descripteur qui est créé et du coup le serveur passe dans l'état SIN or SIFT. Donc, il envoie un paquet TCP avec juste un en-tête avec le flag SIN et le flag AC qui sont mis là. Le numéro de séquence qui est mis à B et le numéro d'acnolagement est incrementé de 1. Donc une fois que le client a reçu ce paquet avec les flags SIN et AC il se met dans l'état established la connexion dit comme établi et il va envoyer un paquet avec le flag acknowledgement donc reconnaissance comme ça le serveur voit que du côté du client la connexion a été établi. Donc le numéro de séquence c'est A plus 5 que l'on a déjà utilisé et le numéro d'acnolagement c'est B plus 1 donc le B qu'on a reçu au message d'avant. Donc c'est le numéro de segment du serveur. Donc une fois que le serveur a reçu ça il passe aussi dans l'état established donc la connexion établi. Le numéro de séquence donc c'est une bonne idée de choisir des numéros de séquence aléatoires au début pour m'aider à éviter des attaques diverses le numéro d'acnolagement c'est le numéro de séquence incrémenté de l'autre en face et le numéro de séquence c'est incrémenté pour chaque octet de données FIN et SIN chaque paquet est retransmis s'il n'a pas été acknowledge donc chaque paquet doit être acknowledge sinon ça continue jusqu'à ce qu'il y a un time out qui soit atteint donc ça réessaye plusieurs fois puis ça détermine que la connexion ne passe pas Donc TCP nous permet de faire du contrôle de flow qu'est-ce que ça veut dire dans une pile réseau on a un tempore de réception pour chaque connexion TCP et ce tampon est limité en taille pour éviter de manger toute la mémoire du noyau ce qui veut dire que quand une application un serveur web ou un browser est lié des données ça prend de l'espace dans cet tampon et quand il y a des segments TCP qui arrivent on en récupère c'est une fenêtre tournante c'est un tampon circulaire si on veut donc on a vu ça avec le champ Windowsite, la taille de la fenêtre dans le tête TCP qui détermine qui permet d'indiquer à l'autre partie quelle est la taille du tampon de réception de son côté à soi et afin d'éviter l'interblocage il y a également un timer un compteur quand la taille de fenêtre est 0 ça provoque un time out donc ça permet de déterminer une nouvelle taille de fenêtre d'envoyer des paquets plus petits potentiellement donc on a aussi le contrôle de congestion en gros l'idée c'est contrôler à quelle vitesse les données entrent dans votre réseau parce que si à un moment donné vous saturer une partie de vos équipements réseau ça va pas éviter ça dans TCP en appliquant du contrôle de congestion qui par exemple va mesurer la durée temporale entre le moment où on a envoyé un segment et le moment où on a reçu l'acknowledgement donc en général on commence lentement pour éviter la congestion et puis on augmente la taille de la fenêtre jusqu'à ce que ça commence à congestionner donc les acknowledge de base chaque segment est acknowledged individuellement il y a aussi un mode acknowledgement à retard qui évite d'en envoyer plein donc on en voit un de temps en temps et il y a aussi une manière de faire des acknowledgements sélectifs qui permettent d'acknowledger la réception de segments qui sont pas continu qui arrivent dans le désordre donc on a aussi une taille maximum de segments ou de datagramme définie dans TCP pour éviter la fragmentation donc vu qu'on peut avoir plusieurs connexions ouvertes en même temps qu'est-ce qui peut se passer on peut ajuster cette variable en fonction des conditions d'utilisation il y a des extensions en TCP qui existent à la mise à l'échelle de la fenêtre et l'ouverture rapide de connexion pour que ça aille un peu plus vite il y a des attaques comme le déni de service donc un serveur qui accepte quelque chose une connexion va louer plein de mémoire pour le client et le client a juste envoyé un signe juste un petit paquet donc c'est un déni de service on a le détournement de connexion si on arrive à prédire le numéro de séquence alors on peut détourner la connexion déjà établie et on a aussi des attaques en aveugle dans la fenêtre ou on n'a pas besoin de savoir le numéro de séquence et on peut quand même intérer quelque chose dans une attaque dans une connexion TCP préexistante par exemple envoyer un risette, envoyer un fil pour terminer la connexion donc les spécifications de TCP sont rédigées en prose anglaise dans la RFC et il y a plusieurs interplantations en usage courant donc on a un modèle formel formel qui s'appelle Netsem qui a été développé dans le prouveveur de théorème interactive HL3 c'est une spécification précise avec aucune liberté dans l'applémentation donc on a le modèle de l'API des soquettes on a l'interface TCP des bugs qui permet d'avoir des infos vraiment sur l'état de la pile TCP et on a une interface du câble qu'on a utilisé pour valider d'abord elle-même en dessinant des jolis diagrammes on peut voir les règles à chaque étape sur la à gauche quand il se passe quelque chose par exemple quand on a un connect qui est appelé donc on a une règle logique qui s'appelle connect underscore 1 et voilà un système de transition entre différents atta et on peut voir à droite un segment TCP donc les contributions de Netsem network semantics ça nous a permis de valider le modèle en enregistrant et en rejouant des traces d'exécution réseau et il y a un papier qui est sorti engineering with logic specification and validation TCP IP and socket SPI qui est sorti au GSM en décembre 2018 donc la specification est définie en 384 pages la specification tant que telle c'est 9000 lignes de code et 17000 lignes de commentaires à comparer avec la pile TCP IP UNIX qui en général plus de 15000 lignes de code donc la pile TCP IP que l'on a vu dans le paragraphe précédent on a essayé de la redessiner et de dessiner une machine à état TCP plus correct ce qui est un peu plus compliqué on a cet état non existant là en haut et on a beaucoup plus de transition à cause des problèmes de temps donc vu que ce qu'on a dans la littérature n'est pas complet n'est pas absolument précis on a fait ça en conclusion TCP IP est déployé de manière assez large j'espère que je vous aurais montré des aspects de comment ça fonctionne en réalité c'est une architecture en plusieurs couches qui permet d'être agnostique par rapport à la technologie des couches inférieures et on a donc Netsam qui est une spécification exécutable de TCP c'est tout ce que j'ai à dire et vous êtes bienvenue à poser des questions que ce soit maintenant ou orline merci si vous avez des questions allez au micro nous avons de micro à droite parce que nous avons des questions d'internet non des questions aucune question ah une question merci merci merci c'est une présentation intéressante est-ce que la spécification vous permet de synthétiser une implementation ou seulement de valider donc dans l'implémentation elle est pas définie de manière strict si vous faites un emplément de TCP tu dois choisir si tu implémentes de telle ou de telle manière quand tu arrives sur une condition d'achat est-ce que tu essaies de retransmettre et tu passes en success ou est-ce que t'abandonnes donc on continue à travailler sur Netsam pour pouvoir s'en servir comme implementation est-ce que vous pensez que s'il y a une implementation qui peut en être faite elle peut être efficace merci ta question s'il te plaît à quel point est-ce que TCP est un des pendant de IP est-ce qu'il est possible d'utiliser TCP avec d'autres choses que IP vu que TCP a besoin d'un peu d'ICMP pour les messages d'erreur j'ai jamais vu d'implémentation TCP au-dessus d'un autre medium que le protocole IP donc je ne sais pas je peux y réfléchir ça pourrait fonctionner ta question s'il te plaît donc tu as utilisé whole four pour la spécification est-ce que tu as besoin d'une question de haut niveau pour la spécification il faudrait je relise je crois que qu'on a utilisé des fonctions diohorder offertes par HL4 pour la logique des transitions le papier a été publié sur le journal de l'ACM et il a été téléchargé sur cahyub.is gratuitement par chance d'autres questions non merci Rhanos un peu dissement s'il vous plaît