UniServe : Guide du D�veloppeur

Auteur: SOFTINNOV / Nenad Rakocevic
Date: 02/10/2004
Version: 0.9.9
Commentaires: [email protected]
Traduction: lp.legoff-at-free.fr

Table des Mati�res

1. G�n�ralit�s
2. Premiers Pas
      2.1. Installation
      2.2. Tester votre serveur UniServe
      2.3. Arborescence des r�pertoires
3. D�marrer UniServe
4. API des Services
      4.1. D�finition de service
      4.2. Traitement des donn�es entrantes
      4.3. Propri�t�s
      4.4. Evenements
      4.5. M�thodes
      4.6. Local values isolation
      4.7. Espace partag�
      4.8. Installer un service
      4.9. Fonctionnement des services
      4.10. Exemple: micro-httpd
5. API des Protocoles
      5.1. D�fintion de Protocole
      5.2. Traitement des donn�es entrantes
      5.3. Propri�t�s
      5.4. Evenements
      5.5. Evenements utilisateurs
      5.6. M�thodes
      5.7. Fonctions Globales
      5.8. Local values isolation
      5.9. Exemple: wget
6. Journalisation/D�bogage



1. G�n�ralit�s

UniServe est un serveur d'application multi/protocole pour la programmation r�seau. Il est construit sur un moteur d'I/O asynchrone multiplexe et est inspir� par le framework MEDUSA.

Son objectif est d'offrir une solution simple, mais puissante, pour la programmation d'applications clients/serveurs qui peuvent �tre combin�es avec des interfaces Rebol/View facilement.

UniServe consiste en :

Les services sont charg�s au d�marrage d'UniServe et peuvent �tre aussi chang�s, ot�s et (re)charg�s en cours de fonctionnement. Ils peuvent �tre instanci�s plusieurs fois pour �couter sur plusieurs ports simultan�ment.

Les protocoles sont charg�s �galement au d�marrage d'Uniserve et sont utilisables avec une API similaire � port! l'API native de REBOL. Ils peuvent �tre utilis�s pour cr�er tr�s facilement des clients qui fonctionneront simultan�ment avec les services et les �v�nements View au sein d'une boucle d'�venements REBOL.

Les APIs des services et des protocoles sont orient�s "�venements" . Ceci signifie que la mise en place d'un nouveau service ou protocole se fait juste en d�finissant l'une ou l'autre des fonctions r�entrantes avec le code appropri�. (Un principe proche de ce que VisualBasic faisait pour la programmation facile d'interfaces utilisateur)



2. Premiers Pas


2.1. Installation

D�zipper votre archive Uniserve dans le r�pertoire o� vous souhaitez l'installer. L'installation est finie !

Installer un nouveau logiciel ne devrait pas �tre plus diffcile que cela, non ? ;-)

R�pertoires ayant des espaces dans leur chemin d'acc�s
Parfois, avoir des espaces dans le chemin d'acc�s peut �tre la cause de probl�mes dans les applications REBOL, donc �vitez les noms de dossier ou chemins d'acc�s contenant des espaces.


2.2. Tester votre serveur UniServe

Ex�cutez le script %starter.r. La console REBOL devrait s'afficher avec la liste de tous les services et les protocoles charg�s, et Uniserve devrait rentrer dans sa boucle d'�v�nements (attente de connexion de clients). Si vous constatez une ligne d'erreur dans la console indiquant que le service HTTPd ( par exemple) n'a pa pu �tre lanc�, c'est probablement qu'il existe d�j� un serveur utilisant le m�me port. Arr�tez votre serveur local ou essayez de lancer une autre instance du service HTTPd d'Uniserve sur un autre port (mettre 8181 au lieu de 80 par exemple) en utilisant l'outil Monitor.r (plac� dans le r�pertoire %client ).

Ouvrez votre navigateur Web pr�f�r� et tester l'adresse suivante : http://localhost. Si tout est OK, vous devriez voir une page "Welcome" avec le logo de Softinnov. Vous avez r�ussi le test du service HTTPd d'Uniserve !

Remarque : il peut �tre n�cessaire de tester la page avec l'adresse IP de votre machine au lieu de "localhost".

Si vous avez une version de REBOl avec le composant /Shell actif, vous pouvez essayer de cliquer sur le lien "Example CGI Link". Vous devriez voir � pr�sent un extrait de votre environnement CGI.

Votre installation d'Uniserve est OK, � vous maintenant de construire la prochaine "killer-app" ! ;-)


2.3. Arborescence des r�pertoires

UniServe n�cessite une arborescence sp�cifique pour certains de ses r�pertoires, afin de fonctionner correctement. Ne changez pas les noms de ces r�pertoires : directories :

*root*/                 Dossier d'installation
    uni-engine.r        moteur d'UniServe
    starter.r           script lanceur de tous les services
    ...
    libs/               Dossier Librairie
        log.r
        headers.r
    services/           Dossier des services actifs
        ...
        store/          Repository des services
            ...
    protocoles/         Dossier des protocoles actifs
        ...
        store/          Repository des protocoles
            ...
    modules/            Repository des modules
        ...
Utilisez le dossier store/ pour "activer" ou "d�sactiver" des services avant le d�marrage d'UniServe.
Les scripts REBOL valides trouv�s dans le r�pertoire %services seront charg�s comme services lors du d�marrage d'Uniserve. Un simple d�placement d'un script d�crivant un service dans le r�pertoire %store a pour cons�quence de d�sactiver le service.

Un service peut avoir besoin d'autres fichiers pour fonctionner. Ces fichiers suppl�mentaires devront �tre dans un sous-r�pertoire avec un nom identique � celui du service. (Remarque : attention aussi suivant votre OS aux majuscules/minuscules).

Exemple (ici pour le HTTPd):

services/
    ...
    HTTPd.r
    HTTPd/
        wwwroot/
            ...
        mime.types
        httpd.conf
        ...
NB: la gestion des services peut se faire via le service 'Admin ou via la fonction partag�e 'control.
(voir le chap�tre "Services en cours d'utilisation")



3. D�marrer UniServe

Pour charger le moteur Uniserve :

>> do %uni-engine.r
Le moteur est charg� dans un contexte REBOL sp�cifique nomm� : UniServe.

Pour d�marrer le serveur :

>> UniServe/boot
Par d�faut, Uniserve sera lanc� avec tous les services d�clar�s dans le sous-r�pertoire %services/ and
et tous les protocoles trouv�s dans le sous-r�pertoire %protocoles/.

La fonction boot poss�de deux rafinements :

Exemple:

UniServe/boot/no-loop/with [
    services  [HTTPd FTPd...]
    protocoles [HTTP FTP...]
]
NB: Vous pouvez omettre l'un des mots-cl�s ('services ou 'protocoles) au lieu de fournir un bloc vide.

Indication du r�pertoire d'installation
Si vous d�marrez UniServe depuis un r�pertoire diff�rent du r�pertoire courant, vous devez sp�cifier le chemin d'acc�s � l'arborescence d'UniServe en positionnant la variable UniServe-path. Le chemin doit se terminer par un "slash". Vous devez d�finir le chamin d'acc�s avant d'appeler la fonction 'boot.

Example:

>> UniServe-path: %/library/UniServe/
>> UniServe/boot

Une fois d�marr�, si le raffinement /no-loop a �t� sp�cifi�, UniServe n�cessite une boucle d'�venements pour fonctionner.
Cette boucle �venementielle peut �tre r�alis�e par un appel � la fonction 'view ou directement avec un 'do-events :

Pour initier une attente d'�venements, vous pouvez choisir entre ces deux alternatives :

>> view ...
ou

>> do-events



4. API des Services


4.1. D�finition d'un service

Un nouveau service devrait �tre cod� dans un fichier dans le nom est : le nom du service associ� � l'extension ".r" . (voir le r�pertoire %services dans l'archive UniServe )

Chaque service est d�fini en utilisant la fonction install-service. Un en-t�te REBOL (REBOL[...]) est n�cessaire. (Vous pouvez le laisser vide.)

install-service [
    ... definition service...
]
NB: Vous n'avez pas besoin d'effectuer un 'do ou un 'load de vos scripts pour utiliser la fonction.

Mettez tout le code concernant les services dans le bloc de d�finition de service.
Vous pouvez inclure des librairies externes si n�cessaire. Tout ce qui n'est pas � l'int�rieur du bloc de d�finition des services devrait �tre globalement BIND�.


4.2. Traitement des donn�es entrantes

UniServe fournit au d�veloppeur un syst�me unique pour impl�menter des protocoles r�seaux.
La gestion des donn�es entrantes est r�alis�e � bas niveau par UniServe.

Pour �tre capable de d�coder n'importe quel paquet logique de donn�es entrantes (pas les paquets physiques IP),
vous devez savoir quand le paquet se termine. Il existe deux fa�ons de r�aliser ceci :

UniServe va g�rer automatiquement les donn�es entrantes en utilisant l'une de ces deux m�thodes.
C'est au d�veloppeur de d�finir la bonne m�thode en utilisant la propri�t� stop-at des services.

Lorsque l'un de ces indicateurs de fin est atteint, UniServe appelle la fonction on-received d�finie dans votre d�claration de service avec les donn�es recues en argument.

Exemple :

Une machine distante envoie la cha�ne "Hello. I'm ok." � votre service
[stop-at: #"."]       g�n�rera les appels suivants :
-> on-received "Hello."
-> on-received " I'm ok."
[stop-at: 1]        g�n�rera les appels suivants :
-> on-received "H"
-> on-received "e"
-> on-received "l"
-> on-received "l"
-> on-received "o"
-> on-received "."
-> on-received " "
-> on-received "I"
-> on-received "'"
-> on-received "o"
-> on-received "k"
-> on-received "."
[stop-at: 4]        g�n�rera les appels suivants :
-> on-received "Hell"
-> on-received "o. I"
-> on-received "'m o"
                    <- notez qu'il manque ici les caract�res "k."
                    puisqu'il n'y a pas encore de donn�es dans le buffer d'entr�e
                    pour d�clencher un nouvel �venement de type 'on-receive !!
                    Un nouvel �venement peut �tre g�n�rer si des nouvelles donn�es arrivent
                    ("k." est pr�sent dans le buffer interne d'UniServe)
stop-at peut �tre modifi� � n'importe quel moment dans la d�finition de service, permettant l'impl�mentation de protocoles plus complexes (par exemple en switchant d'un mode � l'autre).
Les nouvelles valeurs deviennent effectives d�s que la fonction en cours sur un �venement se termine.

Vous pouvez �ventuellement d�cider de d�sengager le syst�me de gestion des donn�es entrantes en positionnant stop-at � la valeur none! .
Dans ce mode, UniServe appellera la fonction on-raw-received dans votre definition de service chaque fois que votre application recoit un paquet physique (TCP ou UDP) de la machine distante.

Type de donn�es recues
Rappelez-vous que les donn�es sont toujours transmises sous forme de valeurs binaires (binary!) � vos fonctions 'on-received et 'on-raw-received.
Il sera souvent n�cessaire de les convertir en string! pour les manipuler correctement.


4.3. Propri�t�s

La liste suivante recense les propri�t�s utiles pour coder votre service.
Certaines sont obligatoires pour d�velopper un service valide.

Mot/item Type Rebol Obligatoire? Description
name word! oui Id, nom identifiant de mani�re unique le service
port-id integer! oui Le num�ro du port d'�coute par d�faut.
stop-at integer!
string!
char!
binary!
none!
non D�finit quand l'�venement 'on-received sera g�n�r�.
Valeur par d�faut: none.
scheme word! non Valeur par d�faut : 'tcp, il est possible de changer cela pour 'udp
module word! non Le nom du module pour le traitement en t�che de fond
hidden logic! non (r�serv� pour un usage futur)
client port! non Propri�t� positionn�e sur la valeur courante du port! client
shared object! non Acc�s � l'espace partag� d'UniServe. Vous �tes libre d'ajouter des variables ici, pour que les autres services puissent les utiliser .

propri�t� Client
Client (de type port!) r�f�rence les informations de connexions utilis�es par le client distant.
Vous pouvez utiliser les propri�t�s internes de cet objet pour acc�der aux informations de connexion.

Par exemple, si vous voulez connaitre l'adresse IP du client :

client/remote-ip


4.4. Evenements

Les �venements sont des fonctions sp�ciales appel�es par le moteur d'UniServe pour traiter les �venements r�seau. Par d�faut, ces fonctions sont d�finies � none. C'est au d�veloppeur de choisir et d'impl�menter les �venements appropri�s.

Mot Prototype Description
on-load func [] Appel�e au chargement du service par Uniserve. Placez votre code d'initialisation ici si besoin.
on-new-client func [] Appel�e quand une nouvelle connexion est accept�e par UniServe
on-close-client func [] Appel�e lorsqu'un client ou le service cl�ture la connexion .
on-received func [data [binary!]] Appel�e quand la s�quence attendue ou la longueur d�finie dans stop-at est atteinte.

data : toutes les donn�es recues du client depuis le pr�c�dent �venement 'on-received. data est effac� une fois que la fonction a �t� �valu�e, donc utilisez 'copy si vous voulez conserver le contenu de data.
on-raw-received func [data [binary!]] Appel�e quand un paquet brut TCP ou UDP est re�u..

data : Toutes les donn�es recues du client depuis le dernier �venement 'on-raw-received. data est effac� une fois que la fonction a �t� �valu�e, donc utilisez 'copy si vous voulez conserver le contenu de data.

Au moins un !
Vous devez d�finir au moins l'un de ces �venements si vous voulez que votre service serve � quelque chose !

Evitez d'employer du code bloquant dans les �v�nements !
Les d�veloppeurs doivent faire attention � leur impl�mentation des fonctions pour les �v�nements et doivent �tre s�r qu'il n'y a pas de t�ches bloquantes
(comme une connexion � une machine distante en mode synchrone, effectuer de longs calculs, etc...).
Ceci affecte directement les performances du serveur Uniserve. Si vous avez � r�aliser des t�ches bloquantes ou longues, utilisez le service 'task-master et des processus en t�che de fond.


4.5. M�thodes

Il y a plusieurs fonctions pr�-d�finies dans le contexte des services :

Mot Prototype Description
write-client data [string! binary! file!] Renvoie des donn�es au client. Cette fonction est non bloquante, de sorte que vous pouvez l'utiliser sans souci dans les fonctions d'�venements. (Les donn�es ne sont pas envoy�es imm�diatement, mais sont mises en attente pour le traitement suivant)

data : data � envoyer.
close-client /now Ferme la connexion du client . Cette fonction est non bloquante, de sorte que vous pouvez l'utiliser sans souci dans les fonctions d'�venements.
(Le port client sera ferm� lorsqu'il n'y aura plus de donn�es en attente)

/now : Ferme la connexion client imm�diatement et efface les donn�es en attente.
share values [block!] Ajoute des valeurs dans l'espace partag�. (voir la section "Espace partag�")

values : block of name/value pairs. (name [set-word!], value [any-type])

Serving files
si vous utilisez un argument de type file! pour write-client, le fichier consid�r� ne devrait pas �tre charg� (load) en m�moire. Uniserve l'enverra par morceaux au client, en lisant � chaque fois sur le disque seulement les donn�es n�cessaires. Ceci permet d'utiliser des fichiers sans limite de taille, sans impact sur les performances d'Uniserve ou la m�moire.


4.6. Port�e locale des variables

Le code d�finissant un service doit �tre r�-entrant, c'est � dire qu'il peur �tre appel� avec diff�rents contextes clients sans alt�ration ou m�lange de donn�es entre clients. Pour �viter de tels probl�mes, vous avez � stocker les param�tres de session d'un client dans : client/user-data.

Exemple :

client/user-data: context [
    id: 3432
    state: 'logged
    etc...
]
Tous les mots d�finis dans le contexte du service sont "globaux" pour tous les clients qui l'utilisent. Par contre, les mots stock�s dans client/user-data sont sp�cifiques � ce client.

Par exemple, si vous comptabilisez le nombre courant de clients, vous pouvez faire :

install-service [
    ...
    count: 0
    on-new-client: does [count: count + 1]
    on-close-client: does [count: count - 1]
]
Il y a d'autres mani�res de sauver les param�tres de session. Vous �tes libre de choisir quelle m�thode vous souhaitez pour "isoler" des donn�es sp�cifiques d'un client.


4.7. Espace partag�

L'espace partag� global est juste une variable (object!) qui peut �tre utilis�e � n'importe quel moment par n'importe quel service.

Tous les services peuvent ajouter au chargement leurs propres valeurs dans cet espace partag� avec la fonction share.

share [
    a: "hello"
    pool: 50
    do-task: func [...]...
    ...
]
Tous les services peuvent acc�der � cet espace durant le fonctionnement gr�ce � : shared.

probe shared/a
shared/a: 2
shared/do-task args...
L'objet shared contient par d�faut une seule m�thode d�finie :

shared: context [
    control: func [...]...      ; fonction d'administration UniServe  .
]


4.8. Installer un service

Une fois cr��, votre nouveau service se place dans le r�pertoire %services et sera automatiquement charg� par UniServe au d�marrage suivant.

Chargement manuel des services
Si vous souhaitez charger manuellement des services particuliers, vous devrez le faire avant le d�marrage de la boucle �venementielle.

Exemple :

do %uni-engine.r
UniServe/boot/no-loop
install-service [...]
ou

#include %services/my-service.r     ; pour le pr�processeur PREBOL 
puis

do-events   ; ou view...


4.9. Fonctionnement des services

Quand un nouveau client se connecte via un service actif, UniServe cr�e une variable de type port! pour g�rer la connection.
UniServe utilise la propri�t� locals de l'objet port! pour stocker toutes les informations n�cessaires au traitement des �v�nements sur la connexion.

port/locals
La variable locals de chaque connexion ('port) g�r�e par UniServe est r�serv�e pour un usage interne. Ne changez rien dans 'port/locals � moins de savoir exactement ce que vous faites !

Ici, un point int�ressant � noter est que chaque port/locals/handler pointera sur votre d�finition de service.

L'arr�t d'un service, en cours de fonctionnement, peut �tre r�alis� � distance gr�ce au protocole admin:// ou localement en utilisant la fonction Uniserve (partag�e) control ( chemin : shared/control)

Voici une courte description de la fonction control :

control
    name        [word!]     Nom du service
    id          [integer!]  Num�ro du port d'acoute du service
    /start                  D�marre une nouvelle instance du service sur le port d'�coute :id
        /all                D�marre tous les services avec leur port d'acout� par d�faut
    /stop                   Arr�te un service
    /list                   Retourne la liste des services
    /install                (not implemented)
        file                (not implemented)


4.10. Exemple: micro-httpd

Voici le code source pour un mini serveur web, adapt� d'apr�s le script %webserver.r script (vous pouvez trouver le script originel ici)

Les mots-cl�s UniServe's sont color�s en rouge.

'micro-httpd service source code
install-service [

    name: 'micro-httpd
    port-id: 81

    mime: htfile: file: none

    stop-at: join crlf crlf

    wwwpath: %wwwroot/  ; path must end with a slash !

    html: "text/html" gif: "image/gif"  jpg: "image/jpeg"

    not-found: [
        "404 Not Found"
        [<HTML><STRONG><H1>ERROR</H1></STRONG><H4><p><p>
         "REBOL Webserver error 404"<BR>"File not found"</html>]
    ]

    bad-perms: [
        "400 Forbidden"
        [<HTML><STRONG><H1>ERROR</H1></STRONG><H4><p><p>"REBOL Webserver"
         "error 400"<br>"You do not have permission to view the file"</html>]
    ]

    http-head: func [type mime][
        reform ["HTTP/1.0" type newline "Content-type:" mime newline newline]
    ]

    error: func [err][
        write-client append http-head err/1 html err/2
    ]

    on-received: func [data][
        if "HTTP" = htfile: third parse data "/" [htfile: "index.html"]
        mime: parse htfile "."
        if error? try [mime: get to-word mime/2][mime: html]
        any [all [not exists? file: join wwwpath htfile error not-found]
             all [error? try [read/binary/part file 1] error bad-perms]
             all [
                write-client http-head "200 OK" mime
                write-client file
             ]
        ]
        close-client
    ]
]

Remarques :



5. API des protocoles


5.1. D�finition de Protocole

Les protocoles sont les �quivalents c�t� client des services. Leur but est de fournir une impl�mentation de protocoles r�seaux orient�s clients, en tant que protocoles d�di�s. Vous constaterez un grand nombre de ressemblance entre les APIs des protocoles et des services, de sorte que si vous savez coder un service, vous saurez aussi coder un protocole client ! :-)

Un nouveau protocole doit �tre �crit dans un fichier dont le nom correspond au nom du protocole, plus l'extension ".r" . (voir le r�pertoire %protocoles de l'archive UniServe)

Chaque protocole est d�fini avec la fonction install-protocol .
Un en-t�te REBOL ( Rebol[...]) est requis, m�me si vous le laissez vide.

install-protocol [
    ...d�finition protocole ...
]
(NB: Vous n'avez pas besoin de charger ( 'do ou 'load) vos scripts pour utiliser cette fonction .)

Mettez tout le code d�finissant le protocole dans la d�finition. Vous pouvez inclure des librairies externes si besoin. Tout ce qui se trouve en dehors du bloc de d�finition devra �tre globalement BIND�.


5.2. Traitement des donn�es entrantes

Les donn�es entrantes sont manipul�es exactement de la m�me mani�re que pour les services.


5.3. Propri�t�s

Voici la liste des propri�t�s possibles pouvant �tre utilis�es dans la d�finition de votre protocole. Certaines d'entre elles sont obligatoires pour obtenir un protocole valide.

Mot Type Obligatoire?? Description
name word! oui Nom identifiant de mani�re unique le protocole
port-id integer! oui Le num�ro de port par d�faut
events block! oui Liste des noms d'�venements d�finis par l'utiisateur
stop-at integer!
string!
char!
binary!
none!
non D�finit quand l'�venement 'on-received event sera g�n�r�.
La valeur par d�faut est none.
scheme word! non La valeur par d�faut est 'tcp, il est possible de le changer pour : 'udp
server port! non Valeur d�finie durant le fonctionnement et r�f�rencant la valeur server de l'objet port! (nom du serveur)
connect-retries integer! non D�finit le nombre maximum de tentatives de connexions au serveur. Par d�faut : 5

Propri�t� Server
L'objet Server r�f�rence les infos courantes de connections (type port!) pour la machine distante. Vous pouvez utilisez les d�finitions habituelles internes � port! pour acc�der � toutes les informations de connection .

Par exemple, si vous souhaitez conna�tre l'adresse IP du serveur :

server/remote-ip


5.4. Evenements

Les �venements s'assimilent � des fonctions sp�ciales appel�es par le moteur UniServe pour traiter les �venements du r�seau. Par d�faut, ces items sont d�finis � none. Il revient au d�veloppeur de choisir et d'impl�menter les �venements appropri�s.

Mot/item Prototype Description
on-init-port func [port [port!] url [url!]] Appel�e avant l'ouverture d'une connexion. Utile pour les changements de param�tres de derni�re minute comme le nom utilisateur et le mot de passe.
on-connected func [] Appel�e lorsque la connection est �tablie avec la machine distante. (avant l'envoi ou la r�ception des donn�es )
on-close-server func [] Appel�e quand le client ou le serveur ferme la connection.
on-received func [data [binary!]] Appel�e lorsque la s�quence attendue ou la longueur d�finie par stop-at est atteinte.

data : contient toutes les donn�es recues par le client depuis le pr�c�dent appel � 'on-received. data est effac�e une fois que la fonction a �t� �valu�e, de sorte qu'il est conseill� d'utiliser 'copy si vous souhaitez conserver le contenu de data .
on-raw-received func [data [binary!]] Appel�e quand un paquet physique TCP ou UDP est re�u.

data : contient toutes les donn�es recues par le client depuis le pr�c�dent appel � 'on-raw-received. data est effac�e une fois que la fonction a �t� �valu�e, de sorte qu'il est conseill� d'utiliser 'copy si vous souhaitez conserver le contenu de data .
on-error func [why [word!] port [port!]] Appel�e lorsqu'une erreur se produit durant la connexion.

L'argument why dans l'�venement on-error peut prendre les valeurs suivantes :

 unknown-hostLe nom de machine n'a pu �tre r�solu !
 unreachableil n'y a pas de route valable pour atteindre le serveur !
 connect-failedLe serveur n'a pas r�pondu apr�s plusieurs tentatives de connections !


5.5. Evenements utilisateur

En vue de rendre vos protocoles utilisables, vous avez � d�finir une API, utilisant des �venements personnalis�s, appel�e ici "user events". Elle est orient�e "user", car c'est l'interface que l'impl�mentation de votre protocole fournira au protocole utilisateur.

Les protocoles sont, en fait, juste une couche entre les �v�nements Uniserve et les �venements utilisateurs !

Les �v�nements utilisateurs sont d�finis dans votre protocole en utilisant le mot-cl� events. Vous avez juste � fournir la liste des noms d'�venements, sans ordre particulier. Vous appelez alors ces �venements comme des fonctions aux endroits strat�giques de votre code . C'est tout !

Exemple :

events: [
    on-login-ok
    on-message
    ...
]
Vous pouvez utiliser n'importe quel nom. Dans UniServe, les noms des �venements sont pr�fix�s avec on- pour facilement les reconna�tre dans le code source. Utilisez des noms significatifs qui refl�tent l'�tat courant de la communication avec le serveur ou de l'objet que vous vous attendez � recevoir, etc...

Si vous devez passer des arguments � vos �v�nements d'utilisateur, faites-le !
Il n'y a rien de sp�cial � faire pour permettre � vos �venements de prendre des arguments. Souvenez-vous de documenter vos fonctions quelque part ! Pour l'instant, une ligne de commentaire pour chaque �venement sp�cifiant l'en-t�te attendu . (Nous pensons ajouter un moyen de g�n�ration automatique de la documentation pour les �venements utilisateur dans les prochaines versions)

Un exemple plus complet :

install-protocol [
    name: 'pop
    ...
    on-received: func [data][
        ...
        on-login-ok server
        ...
        ...
        on-message server import-email msg
        ...
    ]

    events: [
        on-login-ok     ; [port [port!]]
        on-message      ; [port [port!] msg [object!]]
        ...
    ]
]
NB: Il est pratique (mais pas obligatoire) de passer la valeur du port en tant que premier argument. Ceci donne au protocole utilisateur un moyen facile d'acc�s � toutes les propri�t�s du port en incluant le contexte local port/user-data .


5.6. M�thodes

Plusieurs fonctions sont pr�-d�finies dans le contexte du protocole :

Word Arguments Description
write-server data [string! binary! file!]

/with port [port!]
Envoie les donn�es au serveur. Cette fonction n'est pas bloquante, aussi vous pouvez l'utiliser sans inqui�tude dans vos fonctions �venements. (Les donn�es ne sont pas envoy�es en une fois, mais mise en cache pour le traitement suivant.)

data : Donn�es � transmettre.

port : valeur du port � utiliser pour envoyer les donn�es.
close-server   Ferme la connection avec le serveur. Cette fonction n'�tant pas bloquante, vous pouvez l'utiliser sans souci dans vos fonctions �venements. (Le port serveur sera ferm� lorsque qu'il n'y aura plus de donn�es en attente)

Envoi de fichiers
Si l'argument de write-server est de type file!, le fichier ne sera pas charg� dans la m�moire. UniServe l'enverra par morceaux au serveur, lisant seulement sur le disque � chaque fois que des donn�es sont requises. Ceci permet l'envoi de fichiers non limit�s en taille sans d�grader les performances d'UniServe.


5.7. Fonctions Globales

Ce jeu de fonctions vous permet d'administrer les protocoles Uniserve durant le fonctionnement, de fa�on tr�s similaire � celle des protocoles pr�-d�finis avec REBOL. Elles sont globalement d�finies (dans le contexte global REBOL), de fa�on � pouvoir les utiliser partout. Rappelez-vous que ces fonctions sont non bloquantes !

Word/mot Arguments Description
open-port url [url!] events [block!]

/with spec [block!]
Cr�e et renvoie un nouvel objet port! travaillant en mode asynchrone.

url : une url valide sp�cifiant les informations usuelles de connexion : scheme, host, target, etc...
events : un bloc de fonctions-�venements.

spec : �tend la port�e de l'objet port! avec des d�finitions suppl�mentaires. Cela consiste en une liste de paires : nom: valeur .
insert-port port [port!] data [any-type!] Envoie les donn�es via le port!.
close-port port [port!] Ferme la connexion et d�clenche l'�venement on-close-server.

L'argument events de 'open-port est un bloc d'�venements utilisant le format suivant :

open-port url [
    event1: func ...
    event2: func ...
    ...
]
Chaque nom d'�v�nement doit �tre d�fini dans l'impl�mentation du protocole qui est appel� via l'URL.
N'ajoutez pas aucune autre genre de valeur au bloc d'�v�nement !

Le rafinement /with de la fonction 'open-port est utile pour stoker des valeurs locales qui peuvent facilement �tre rappel�es par l'�venement.

Personaliser 'insert-port
La fonction insert-port est, basiquement, un wrapper (encapsulateur) sur write-server. Cela signifie que les donn�es devront �tre envoy�es sans aucun formatage ou encodage. Si vous voulez ajouter une couche pour traiter les donn�es avant envoi (dialecte, compression, encodage, etc...).
Ceci peut �tre r�alis� en d�finissant une nouvelle fonction dans la d�finition de votre protocole, qui sera automatiquement appel�ee par insert-port.

Votre nouvelle fonction insert-port devra �tre nomm�e new-insert-port et d�finie ainsi :

new-insert-port: func [port [port!] data [...]]...
si vous d�finissez 'new-insert-port, souvenez-vous d'appelez write-server pour envoyer les donn�es trait�es au serveur.


5.8. Port�e locale des variables

Les m�mes r�gles d�crites dans la d�finition des services s'appliquent � l'�criture du code des protocoles.

Vous pouvez aussi utiliser les rafinements /with de la fonction 'open-port pour ajouter des variables locales � votre 'port.


5.9. Exemple: wget

Voici le code source d'une impl�mentation pour un simple HTTP GET utilisant UniServe.

Les mots-cl�s d'Uniserve sont color�s en rouge.

'wget protocol source code
install-protocol [

    name: 'wget
    port-id: 80

    stop-at: header-end: join crlf crlf

    on-connected: does [
        write-server rejoin [
            "GET " server/target
            " HTTP/1.0" crlf
            "Host: " server/host
            crlf crlf
        ]
        print ["connecting to:" server/host]
    ]

    on-received: func [data /local pos][
        either integer? stop-at  [
            on-response server to-string data
            stop-at: header-end    ; Reset stop-at for next request
        ][
            ; HTTP header received
            either pos: find/tail data "Content-Length:" [
                ; Extract document size
                data: to-string trim/all copy/part pos find pos newline
                stop-at: to-integer data
            ][
                on-failed server
            ]
        ]
    ]

    events: [
        on-response     ; [port [port!] result]
        on-failed       ; [port [port!]]
    ]
]

Exemple d'usage avec la console :

>> UniServe/boot/no-loop/with [protocoles [wget]]
[UniServe] Async Protocol wget loaded
>> open-port wget://www.rebol.net [
    on-response: func [port result][
        print ["Page size =" length? result]
    ]
]
>> do-events
connecting to: www.rebol.net
Page size = 4375
Remarque :



6. Journalisation/D�bogage

Tous les �l�ments d'UniServe : moteur, services, protocoles utilisent l'objet logger (d�fini dans le fichier %libs/log.r) pour g�n�rer des informations en cours de fonctionnement . Vous pouvez aussi l'utiliser facilement dans vos services et protocoles. L'objet logger �tant charg� avec le moteur Uniserve, il est donc accessible par tout votre code source. Il poss�de une fonction globale appel�e log ayant les sp�cifications suivantes :

log msg
    /info       ; affiche une information
    /warn       ; affiche une alerte
    /error      ; affiche une erreur (sans bloquer le programme)
L'argument msg peut �tre de n'importe quel type. Il sera modifi� (REJOIN) par la fonction log.

L'objet logger peut �galement permettre de contr�ler le mode de sortie (output) via la variable logger/level. Celle-ci peut prendre l'une des valeurs : 'screen (default), 'file, 'both, 'csv. ('both = 'screen + 'file)

Pour autoriser ou non la redirection , nous utilisons habituellement un mot particulier dans tous les contextes d�rivant de l'objet logger : verbose. En lui donnant une valeur enti�re (integer!), vous pouvez contr�ler la quantit� d'informations g�n�r�e. (zero signifie : pas de sortie).

Chaque service et protocole dans l'archive Uniserve est b�ti sur l'objet logger, lequel fournit des possibilit�s de journalisation avanc�es. Mettre la variable verbose � 0 supprime toute journalisation. A 4, la journalisation est maximale.

par exemple, pour voir comment fonctionne le moteur en temps r�el :

uniserve/verbose: 2
L'exemple pr�c�dent avec 'wget en console devrait � pr�sent donner :

>> do-events
[uniserve] Connecting to www.rebol.net : 80
[uniserve] Connected to 209.167.34.214 port: 80
[uniserve] Calling >on-connected<
connecting to: www.rebol.net
[uniserve] << low-level writing: 39
[uniserve] >> low-level reading: 1420
[uniserve] Calling >on-received< with "HTTP/1.1 200 OK^M^/Date: Sat, 09 Oct 2004 21:37:30 G"
[uniserve] >> low-level reading: 1420
[uniserve] >> low-level reading: 1420
[uniserve] >> low-level reading: 412
[uniserve] Calling >on-received< with {<HTML>
<!--Page generated by REBOL-->
<HEAD>
<TITL}
Page size = 4375
[uniserve] Connection closed by peer 209.167.34.214
[uniserve] Calling >on-close-server<
[uniserve] Port closed : 209.167.34.214
NdT: Autre exemple, l'usage de : "verbose: 2" dans la d�claration du service HTTPd permet d'obtenir les traces sur le service.


Copyright 2004 SOFTINNOV All Rights Reserved.
Formatted with REBOL Make-Doc 0.9.6.1 on 10-Oct-2004 at 17:53:46