Previous Contents Next

3   Bibliothèques fournies

Trois bibliothèques sont utilisées pour construire la pile. Une bibliothèque concernant les interfaces Ethernet virtuelles et une bibliothèque de gestion d'évenements ont déjà été présentées dans le tutorat précédent de réalisation d'une couche liaison. Une troisième bibliothèque permet de gérer des tableaux associatifs.

3.1   Bibliothèque de tableaux associatifs

Le but de ces tableaux est de remplacer les structures statiques de C. De nombreuses structures seraient nécessaires pour communiquer entre les différentes couches de la pile TCP/IP. Les tableaux associatifs remplacent ces structures.

Un tableau associatif s'initialise à NULL :
AssocArray *a=NULL;
Il est possible d'ajouter un élément au tableau (ici on ajoute l'entier value avec l'indice index) :
arraysSetValue(&a,"index",(void *)&value,sizeof(value),drapeau);
La valeur doit toujours être passée par référence. Le dernier paramètre drapeau peut modifier le comportement de la fonction : Bien sûr la valeur pour un indice peut être retrouvée :
int size;
int *value=(int *)arrayGetValue(a,"index",&size,drapeau);
Le paramètre drapeau doit être AARRAY_FORCE_NUMERIC si la valeur a été ajoutée de façon identique. La taille de la valeur désignée par le pointeur retourné est stockée dans le paramètre size (sauf si ce paramètre est NULL). Enfin un tableau peut être affiché par la fonction arraysDisplayArray et détruit par la fonction arraysFreeArray.

3.2   Bibliothèque de gestion d'événements

Cette bibliothèque permet de gérer des événements déclenchés avec effet immédiat, avec effet différé ou par une activité sur un descripteur de fichier. La création et la suppression d'événements se font avec les fonctions
int eventsCreate(int priority,void *data);
void eventsRemove(int identity);
A ce niveau on associe une priorité à l'événement; si plusieurs événements sont actifs en même temps, les actions liées au plus prioritaire seront exécutées en premier. On associe aussi une donnée à l'événement sous la forme d'un pointeur générique; les actions de l'événement peuvent l'exploiter lorsqu'elles sont appellées. Pour associer une ou plusieurs actions à un événement utilisez la fonction
int eventsAddAction(int identity,
                    unsigned char (*handler)(EventsEvent *,EventsSelector *),
                    int level);
Comme les événements, les actions peuvent être exécutées dans un ordre précis en jouant sur le paramètre level. Les deux paramètres passés à la fonction d'action permettent d'accéder aux champs de l'événement et aux champs du sélecteur ayant déclenché l'événement. Dans les champs utiles de l'événement on peut citer le champ data_init contenant la donnée liée à l'événement. Dans les champs utiles du sélecteur on peut citer les champs data_this contenant la donnée liée au selecteur et le champ selector contenant, par exemple, le numéro du descripteur, dans le cas d'une activation sur descripteur de fichier. Enfin, pour décrire comment un événement est déclenché, trois fonctions permettent d'associer des sélecteurs à des événements :
int eventsTrigger(int identity,void *data);
int eventsSchedule(int identity,long timeout,void *data);
int eventsAssociateDescriptor(int identity,int descriptor,void *data);
La première fonction déclenche l'événement immédiatement; ses actions sont appelées dès que la fonction principale de surveillance des événements s'active. La seconde fonction programme un déclenchement différé au bout de timeout micro-secondes. Enfin la dernière fonction associe un événement à un descripteur; les actions de l'événement sont exécutées dès que des données en lecture sont disponible sur le descripteur. Enfin le gestionnaire d'événement est démarré par la fonction
void eventsScan(void);
L'appel de cette fonction est bloquant. La fonction ne peut se terminer que si aucun événement ne possède plus de sélecteur. Il faut noter que c'est une situation qui peut se produire; les sélecteurs insérés par les fonctions eventsTrigger et eventsSchedule sont supprimés après l'exécutions des actions correspondantes. De même si une des actions liées à un événement déclenché sur un sélecteur de type descripteur retourne une valeur négative le sélecteur est supprimé.

3.3   Bibliothèque de gestion d'interfaces Ethernet virtuelles

Comme dans le projet précédent cette bibliothèque contient une unique fonction permettant de créer une interface Ethernet virtuelle. Ne pas oublier les drapeaux IFF_TAP et IFF_NO_PI lors de l'appel. Il est rappelé que la lecture et l'écriture sur une interface TAP est triviale; les paquets sont envoyés directement sans mention de leur taille. La création d'une interface TAP nécessite des droits spécifiques. Pour donner ces droits à votre programme vous utiliserez le script setcap déclaré dans le fichier super.tab des machines de TP. De la même façon, un utilisateur normal ne peut pas configurer une interface réseau; utilisez à nouveau la commande super mais en appelant cette fois le script ifconfig.

3.4   Prise en main de la bibliothèque de gestion d'événements

Vous allez utiliser la bibliothèque des événements pour écrire un petit programme de test.

Commencez par créer un événement dont l'action est l'affichage des données du sélecteur, c'est à dire du déclencheur de l'action. Pour vérifier que cette première partie fonctionne, ajoutez deux sélecteurs à l'événement pour déclenchements différés de 30s et 60s. Comme données de ces sélecteurs utilisez des chaînes de caractères assez longues et allouées sur le tas. Ces données doivent être libérées après affichage.

Dans un second temps faites en sorte que les deux sélecteurs se déclenchent sous l'une ou l'autre des deux conditions suivantes : l'expiration d'un minuteur (même durées) ou la détection d'une activité sur l'entrée standard. Il est demandé de ne pas dupliquer les chaînes de caractères. L'action doit maintenant afficher la donnée du sélecteur et le texte tapé sur l'entrée standard ou un message expliquant que l'utilisateur n'a pas tapé le texte assez vite.

Il est recommandé de procéder en créant un événement supplémentaire et de faire en sorte que les sélecteurs se déclenchent sur l'activité d'un descripteur. Le descripteur étant le descripteur en lecture d'un pipe. Utilisez valgrind pour vérifier que votre programme ne présente pas de fuite mémoire.


Previous Contents Next