| Serveur et interface d'administration PingOO 2: RFC du protocole PingOOp |
Corba semblait le meilleur choix pour les applications à développer en utilisant les RPC et aussi l'interopérabilité entre le client et le serveur. Malheureusement, après maintes recherches lors des premières semaines du stage nous nous sommes confrontés à plusieurs problèmes lorsqu'est venu le temps de commencer le développement.
Après de nombreuses recherches pour utiliser CORBA dans l'application serveur, nous avons trouvé Mico
MICO est l'acronyme de MICO Is CORBA. Mico est une implémentation de Corba disponible librement et totalement conforme au standard CORBA 2.2. Cette implémentation a été écrite en C++. De plus, un module Perl, disponible sur les CPAN, fournit une interface aux appels C++.
Toutefois, il a été impossible de compiler le module Perl
CORBA-MICO car il utilisait des fonctions inexistantes ou
renommées. Il faut signaler que la version de ce module est toujours
inférieure à un, ce qui signifie qu'il s'agit d'une version de
développement.
D'autres problèmes, moins génants cette fois-ci, se sont aussi
posés du coté java. Le premier est l'absence du compilateur
idl2java pour le JDK 1.2 de LINUX. Cette absence aurait
put être contournée par l'utilisation de idl2java qui est
récupérable chez Sun pour les plates-formes Windows et Solaris.
D'autres sociétés proposaient des implémentations de CORBA (ou encore ORB
ORB : Object Request Broker, des fournisseurs d'objets distribuésmais celles-ci fonctionnaient uniquement avec la version 1.0 de Java ou n'étaient pas libres de droits.
Enfin, parmis les quelques ORB fonctionnels et gratuits , il y avait celui de Xerox : l'ORB ILU
ILU : Inter-Language Unification System ou système d'unification entre langages. Mais les langages supportés (C++, ANSI C, Python, Java et Common Lisp) ne comprenaient pas Perl. On peut cependant noter qu'il aurait été possible faire fonctionner ILU avec un ORB d'une autre société en utilisant la norme IIOP si une implémentation de CORBA pour Perl avait existé.
Ce sont des spécifications et un ensemble d'implémentations qui permettent aux logiciels de tourner sur un ensemble disparate de systèmes pour appeler des fonctions au travers d'internet.
C'est un système d'appel de fonctions à distance (ou Remote Procedure Call (RPC)) qui utilise le protocole HTTP comme moyen de transport et XML comme format d'encodage.
Il est conçu pour être aussi simple que possible tout en permettant d'utiliser des structures de données complexes lors de la transmission, réception et utilisation.
Voici l'URL traitant de XML-RPC : http://www.xmlrpc.com/.
Pour le moment, les langages supportés sont nombreux (Perl, Java, Python, PHP...) mais il ne s'agit là encore que des versions de développement.
Il pourrait etre intéressant d'utiliser XML-RPC par la suite pour formatter les requêtes et les réponses.
Un message se compose dans l'ordre suivant :
Un message peut être soit signé, soit crypté. Il s'agit du mode de transmission. packet lu correspond au message crypté et/ou signé.
Un message à envoyer peut être :
Le mode est déterminé par le contenu de la première ligne.
Dans le cas de la réception, les opérations sur le packet seront à
effectuer à l'envers. Par exemple pour un message crypté, il sera
décrypté puis sa signature sera vérifiée.
Dans ce mode la première ligne du message est toujours : BEGIN-CRYPTED
Dans ce mode la première ligne du message est toujours : BEGIN
Il s'agit là des informations contenue dans le packet qui est signé et/ou crypté.
Le message d'envoi se compose :
end_param (requis).La première ligne se compose :
Exemple :
pingoop://host:port/Session_Id/Request_Id/Module/Function
Les paramètres à envoyer peuvent être une valeur simple (ou chaîne), un tableau de valeur simples, un fichier ou bien une table de hachage ne pouvant contenir que des valeur simples ou d'autres tables de hachages du même type.
Le message de réponse se compose de plusieurs champso requis suivis d'une liste de paramètres de retours. Si un des champs requies est absent le message est invalide.
request_id (requis) : correspond au
numéro de la requête d'appel;accepted (requis) : yes si la fonction
s'est bien déroulée, no sinon. Toute autre valeur sera refusée ;comment (requis) : message
d'information indiquant par exemple l'erreur qui s'est produite
lors de l'exécution ;end_paramCe sont les mêmes types et spécifications qu'il s'agisse de l'envoi ou de la réception. Les paramètres peuvent être une valeur simple (chaîne de caractères), un tableau de valeurs simples, un fichier ou bien une table de hachage contenant des valeurs simples ou des tables de hachages du même type.
Une ligne commançant par le champ :
simple est une valeur simple ;array est un tableau ;hashkey est une liste de chemins depuis la racine
jusqu'à la dernière clé composant la table de hachage. Cette
ligne doit obligatoirement être suivie par une ligne
hasvalue ;hashvalue est une valeur associées aux chemins
précédents ;file est un fichier.A droite de ces mots clés, entre accolades, se trouve le nom du
paramètre. Celui-ci est respecte l'expression régulière
[a-zA-Z0-9_]+. Le nom d'un paramètre est unique. Pour les
tables de hachage, à un hashkey{nom} correspondra un
hashvalue{nom} et vice-versa.
pingoop://host:port/Session_Id/Request_Id/Module/Function
simple{key1}:encoded_value
array{key2}:encoded_value1,encoded_value2 .... ,encoded_valueN
hashkey{key3}:key11.key12.key13.key1n,key21.key22...
hashvalue{key3}:encoded_value1,encoded_value2
end_param
request_id:request_id
accepted:[yes|no]
comment:explain why request is refused
simple{message_key1}:encoded_value
array{message_key2}:encoded_value1,encoded_value2 .... ,encoded_valueN
hashkey{message_key3}:key11.key12.key13.key1n,key21.key22...
hashvalue{message_key3}:encoded_value1,encoded_value2...,encoded_valueM
file{message_key5}:encoded_name,encoded_contain
end_param

Cette permière procédure de connexion permet au client et au serveur d'échanger leur clé publiques ainsi que de passer d'autres paramètres importants comme le nom de login ou le mot de passe.
Voici la liste des étapes lors de la connexion au serveur :
HELLO au serveur ;
Le serveur renvoie sa clé publique dans le champs
public_key ;
Kernel/Login avec les paramètres
login, public_key et local_host qui
contiennent respectivement la clé publique du client, le nom de
l'utilisateur et le nom de la machine sur laquelle fonctionne le client.
Le serveur renvoie alors le salt permettant de crypter le
mot de passe de l'utilisateur ;
Kernel/Password avec le paramètre
passwd qui contient le mot de passe de l'utilisateur
crypté avec le salt récupéré dans l'appel précédent.
Le serveur renvoie la réponse au client pour l'informer si
l'authentification a fonctionné ou non (dans ce cas déconnexion).
Ce message contient également le numéro d'id_session
associé à cette connexion. A partir de ce moment toutes les
requêtes doivent avoir le numéro d'id session fourni par
le serveur.
Kernel/Update et contient le paramètre version.
Si le serveur accepte ce message et renvoie la chaîne Version
OK contenue dans le paramètre version alors la
session peut réellement commencer. Si au contraire le message est
accepté mais que le champs version ne contient pas le bon
texte alors une mise à jour doit avoir lieu.
Kernel/GetJar pour récupérer un fichier mis-à-jour dans
le paramètre jar.Kernel/SetLanguage et en passant la
langue courante du client dans le paramètre language.Cet appel sert à deconnecter complètement le client du serveur. Cet appel devrait couper toutes les connexions qui existent entre les deux parties.
L'appel se fait sur la fonction
Kernel/Disconnect. Après que cet appel ai eût lieu, il
n'est plus possible d'écrire sur n'importe quelle socket reliant
le client au serveur. Toutes les connexion doivent avoir été fermées.
Le reconnexion a lieu lorsqu'il faut ouvrir un nouveau canal de communication entre le client et le serveur pour une application particulière. Ce procédé évite d'avoir à recommencer intégralement l'identification de l'utilisateur.
HELLO2 au serveur.Kernel/Relog. Cette requête contient dans le paramètre
module le nom de l'application qui va utiliser cette
connexion.
le serveur vérifie la valididé du numéro de session en utilisant la clé publique associée puis renvoie la réponse au client pour l'informer si l'authentification a fonctionné ou non (dans ce cas déconnexion).
Contrairement à l'appel de déconnexion précédent celui-ci ne ferme que le canal spécifique sur lequel l'appel est lancé.
Il s'agit d'un appel à la fonction Kernel/DisconnectChild
qui prend en paramètre module le nom de l'application à
fermer.
Les données transmises sont en partie encodées en base 64. En effet, chaque paramètre étant transcrit sur une seule ligne, les différents éléments la constituant devaient être facilement reconnaissables.
Exemple :
request_id:OQ==
accepted:eWVz
comment:
array{applications}:VUdN,U2h1dGRvd24=,TWFpbFNN,QmFja3Vw,TWFpbnRlbmFuY2U=
end_param
Le protocole défini à ce jour permet de transmettre et recevoir :
simple{key}:b64value
où :
array{key}:b64value1,b64value2,...,b64valueN
où :
file{key}:b64value1,b64value2
ou
file{key}:b64value1
où :
hashkey{key}:b64path1,b64path2,...,b64pathN
hashvalue{key}:b64value1,b64value2,...,b64valueN
où :
Si la valeur associée à un chemin est vide, cette valeur est une chaîne vide et non une table de hachage vide.