• Aucun résultat trouvé

7.2 SPL, un langage dédié de programmation

7.2.3 Propriétés garanties

variable resp. La réponse est ensuite vériée. Si l'appel n'est pas accepté (ligne 20), la requête originale est redirigée sur la secrétaire et la nouvelle réponse est retournée à l'appelant (ligne 22).

Flot de contrôle inter-méthode. La notion de session SPL représente également un processus de contrôle. Le protocole SIP décrit un ot de contrôle de session suivant une forte granularité, spéciant par exemple que durant un dialogue le contrôle doit passer du gestionnaire INVITE au gestionnaire ACK et terminer par le gestionnaire BYE.

Pour augmenter son expressivité, SPL fournit au programmeur le moyen de raner la spécication du ot de contrôle via le mécanisme de branche (expression branch du langage). Ce mécanisme passe une information de contrôle d'un gestionnaire à son successeur. Cette abstraction permet, par exemple, de classer une session comme étant personnelle ou professionnelle, ce qui introduit un sous-processus logique à travers les invocations de méthodes restantes de la session.

Une branche est choisie pour une session lorsque la session est créée. La branche est sauvegardée dans l'état de la session et est utilisée pour choisir le code correct pour chaque invocation successive de gestionnaires. Pour une session de type service ou en-registrement, la branche initiale est default. Un gestionnaire peut alors spécier une nouvelle branche, qui écrase la précédente. Lors de l'invocation d'un nouveau gestion-naire, le code correspondant à la branche est exécuté. Le traitement est identique en ce qui concerne les sessions dialogue et souscription, où la branche courante est héri-tée de la session enregistrement. Cependant, si un gestionnaire introduit une nouvelle branche, celle-ci vient s'ajouter à la séquence de branches et ne vient pas écraser la branche courante comme précédemment.

Ce mécanisme est illustré à la gure 7.5, qui représente un extrait d'un service de hotline. Le mécanisme de branche permet de diérencier dans ce service deux contextes distincts, personnel et professionnel (respectivement les branches private et hotline).

Dans le cas professionnel, le but du service est de transférer l'appel à un opérateur libre et de comptabiliser le temps passé au téléphone. Cependant, les appels privés ne doivent pas être pris en compte. Ainsi, à l'arrivée d'une requête INVITE destinée à l'adresse de la hotline (ligne 15), la branche correspondante (hotline) du service est sélectionnée (ligne 22). Si l'appelé est au contraire une personne (ligne 27), l'appel correspond donc à un appel privé et la branche private est alors choisie (ligne 31).

À la réception des requêtes ACK (ligne 37) et BYE (ligne 47), le traitement dépend de la nature de l'appel (private ou hotline). La branche correcte correspondante est automatiquement choisie. L'introduction de branches permet ici de spécier plusieurs contextes d'appel et donc des comportements diérents pour un même service selon la branche.

servicehotline { processing {

type hotliner_t {uri name; time t_call; int ticks;};

[...]

registration { [...]

responseincoming REGISTER()REGISTER() {[...]}

voidunregister()unregister() {[...]}

dialog {

hotliner_t callee;

time t;

response incoming INVITE()INVITE() {

if (TO == 'sip:hotline@domain.com') { foreach (h in hotline_registered) {

if (get_status (h) == AVAILABLE) { response r = forward h.name;

if (r == /SUCCESS) { callee = h;

hotline_registered.remove (h);

return r branch hotline;

} } }

return forward 'sip:voicemail@domain.com';

} else {

responser = forward;

if (r == /SUCCESS) {

hotline_registered.remove (TO);

return r branch private;

} return r;

} }

response incoming ACK()ACK() { branch hotline {

t = get_time();

set_status (h, PHONE);

return forward;

}

branch private {[...]}

branch default { return forward; } }

response BYE()BYE() { branch hotline {

callee.t_call += get_time()-t;

return forward;

}

branch default { return forward; } }

[...]

}}}}

1.

2.

3.

4.

5.

6.

7.

8.

9.

10.

11.

12.

13.

14.

15.

16.

17.

18.

19.

20.

21.

22.

23.

24.

25.

26.

27.

28.

29.

30.

31.

32.

33.

34.

35.

36.

37.

38.

39.

40.

41.

42.

43.

44.

45.

46.

47.

48.

49.

50.

51.

52.

53.

54.

55.

Fig. 7.5 Le service hotline écrit en SPL

certains types d'erreurs qui peuvent se produire lors de la programmation de services de Téléphonie sur IP avec des solutions existantes. Nous montrons de plus la manière dont SPL permet d'empêcher directement ces erreurs ou de les détecter par le biais de vérications statiques.

La sémantique de SPL a été formellement spéciée [Pho06], ce qui permet une dénition précise de ses interactions avec l'environnement d'exécution SIP-SLEE. Cette dénition formelle sert de fondation pour la dénition d'analyses de programmes.

Traitement d'appel erroné. Le but du service SIP est ultimement de réaliser une opération de signalisation pour ne pas perdre d'appels. En outre, le traitement de chaque message doit être compatible avec le traitement du message original. Par exemple, une erreur consisterait à renvoyer une réponse d'erreur à l'appelant alors que l'ap-pelé a accepté l'appel. Une autre erreur consisterait à traiter un type de requête (e.g., INVITE), et à en transférer une autre (e.g., ACK). Dans SPL, les opérations de signa-lisation prennent la forme de mots clés du langage, comme forward pour transférer une requête ou /SUCCESS pour indiquer une réponse de type succès. Ainsi, cela permet de vérier que tous les chemins d'exécution à travers un gestionnaire accomplissent au moins une opération de signalisation, et que ces actions sont cohérentes entre elles. De plus, SPL empêche de changer le nom de la requête lors du transfert de cette dernière ; le seul argument à forward est la destination, laissant la structure et le nom de la requête implicites.

Un autre type d'erreur concerne la manipulation de messages SIP. Un message SIP contient de nombreux en-têtes, parmi lesquels certains peuvent être optionnels ou en lecture seule. De plus, les messages SIP sont implémentés sous une forme textuelle.

L'implémentation sous-jacente de tous les en-têtes est de type string, même si un en-tête peut avoir un sens plus intuitif comme, par exemple, un entier ou un URI4. Plusieurs actions peuvent alors rentrer en contradiction avec le protocole SIP et produire une erreur : accéder à un en-tête qui n'est pas présent dans le message, essayer de modier la valeur d'un en-tête accessible en lecture seule, ou encore se tromper dans le type d'une valeur d'un en-tête. Le langage SPL empêche l'accès à un en-tête non présent, via une construction when qui combine à la fois une vérication de présence de l'en-tête et l'accès à sa valeur. SPL fournit également une construction with qui permet de mettre à jour la valeur. Dans ce cas, une vérication est faite pour savoir si l'en-tête est accessible en écriture. Ces deux constructions permettent de traiter les en-têtes sous la forme de string ou de types plus élaborés ; dans le dernier cas, une vérication est faite sur la validité de la contrainte de type.

Gestion de ressources erronée. Les API SIP basées sur des langages généralistes ne font rien pour se protéger contre les erreurs de programmation qui peuvent se produire avec ces langages. Par exemple, les API ne se protègent pas contre les boucles innies, et les API basées sur C ne se protègent pas contre les accès hors limites des structures

4Un URI, de l'anglais Uniform Resource Identier, soit littéralement identiant uniforme de res-source, est une chaîne de caractères identiant une ressource sur le Web.

de données ou l'accès à des données libérées. Ainsi, à la diérence de langages géné-ralistes, SPL propose quelques restrictions simples qui permettent d'éviter les erreurs de programmation les plus courantes sans sacrier la puissance d'expression nécessaire au domaine ciblé. SPL autorise seulement des itérations bornées, comme illustré par la construction foreach de la gure 7.5 (ligne 16). De plus, il inclut des vérications sur l'accès aux structures de données, comme dans Java. Enn, SPL ne possède aucun mécanisme d'allocation dynamique de données.