Rapport de troisième soutenance
BOUHELIER Stéphane alias Folkensama (Spé
C1)
POUILLER Jérôme alias Hargos (Spé C1)
TESSARI Marco alias Zapata (Spé C1)
TETZLAFF Franck alias Danao (Spé C1)
EPITA - Avril 2002
Dans le cadre pédagogique d'Epita, nous travaillons sur un projet
nommé YooGoo qui à pour but de créer un outil de communication sur
internet. L'étymologie du mot "YooGoo" se perd dans les méandres
des cerveaux dégénérés de quatre épitéens... Le projet est
articulé autour du protocole, il à pour but d'établir les règles
de communication, il nécessite une architecture client / serveur.
A partir du protocole, il est possible de concevoir un logiciel
capable d'interagir avec les autres logiciels YooGoo.
YooGoo se veut sécurisé, il existe donc une couche de
cryptage qui permet la confidentialité des communications. Cette
particularité rend le sniffing (écoute des trames réseau)
impraticable sur YooGoo.
YooGoo se veut simple
d'utilisation, lors de sa conception nous avons tiré partie de
notre expérience des chats pour faire un protocole clair, avec des
commandes simples et aux noms explicites. Le protocole est
suffisamment intuitif pour que l'on puisse se connecter sur un
serveur YooGoo à l'aide d'un simple client texte. Toutes les
commandes retournent un message d'information suffisamment
explicite pour que l'utilisateur sache où est l'erreur. Néanmoins,
l'utilisation d'un client texte étant peu attrayante, nous avons
aussi créé un client graphique. Celui-ci est suffisamment intuitif
pour être utilisé sans avoir besoin de lire l'aide. Mais, il est
suffisamment puissant par tirer pleinement parti des fonctions du
serveur YooGoo. Nous voulons aussi un client entièrement
personnalisable, car
YooGoo se veut capable de s'adapter.
YooGoo est en priorité basé sur des salons de discussion (appelés
aussi canaux). Il permet l'administration des canaux grâce à un
système de hiérarchie totalement invisible pour l'utilisateur
normal. YooGoo gère aussi une liste de contacts qui permet de
savoir qui est connecté en même temps que soi sur YooGoo. Nous
avons aussi ajouté la possibilité à l'utilisateur de s'inscrire
sur YooGoo et d'y avoir un profile. Tout ceci est géré par une
puissante base de données. Nous avons aussi pensé à
l'administration du serveur en incluant de puissantes commandes
d'administration. L'administrateur a ainsi la possibilité de
loguer tous les événements du serveur. Il est ainsi possible d'en
tirer des statistiques sur l'utilisation du serveur.
YooGoo se veut sécurisé, simple d'utilisation et capable
de s'adapter.
Lors de la dernière soutenance, nous avions terminé la base de
données et la gestion des connections sur le serveur. La
conception du protocole était faite depuis la première soutenance
et nous avions commencé à l'implémenter. Pour cette soutenance,
nous avons fini d'implémenter le protocole. Cette implémentation
nous a obligés à faire quelques modifications sur le protocole. Le
protocole d'aujourd'hui a subit beaucoup d'améliorations et
d'ajout depuis la première soutenance. Parmis ces ajouts, on
trouve les commandes d'administration du serveur et la gestion de
la contact list. Pour aider l'administrateur, nous avons aussi
ajouté des logs et la gestion d'un fichier de configuration. Le
serveur a aussi subit une grosse séance de debugging. A l'heure
actuelle, le serveur est en Final Bêta Test. Nous avons implémenté
toutes les fonctions décrites dans le cahier des charges. Nous en
avons même rajoutées quelques-unes. Nous ne devrions plus avoir à
toucher au code du serveur jusqu'à la soutenance finale, à moins
que l'on ne découvre un bug.
Lors des autres soutenances nous avions montré un client en mode
texte qui suffisait pour executer des commandes sur le serveur.
Mais il est prévu un client graphique avec une interface
graphique, et de multiples fonctionnalité qui permettront de
simplifier l'utilisation de YooGoo.Nous nous sommes pour l'instant
occupé du travail graphique. Ce dernier doit être terminé ou bien
avancé pour cette soutenance. Comme les travaux graphiques
demandent un temps énorme en recherche et en poffinage, cette
organisation nous permettra dans la dernière soutenance de nous
consacrer intégralement au code. De plus les projets de l'année
dernière nous ont servis de leçon en matière de graphisme. En
effet avec le graphisme et le multimédia en général, il est
difficile de savoir s'arrêter car il est toujours possible de
mieux faire. Pour la dernière soutenance il ne sera uniquement
question de la création de la skin de base comme pour WinAmp.
Celle-ci ne devrait pas nous prendre énormément de temps.
Puisque nous sommes en avance par rapport au planning du cahier
des charges, les tâches de chacun ont été modifiées. Hargos et
Zapata se sont consacrés uniquement à la finalisation du serveur,
tandis que Danao et Folken ont travaillé sur le client. Voici ce
que chacun à fait :
- Danao
- s'est occupé de l'interface graphique du client,
il a du apprendre à manier les composant et les objets windows.
- Folkensama
- a travaillé sur la mise en forme des messages,
le traiement des couleurs et des images sur le client
- Hargos
- a implementé le protocole, travaillé sur les fonctions
d'administrations, les logs et le fichier de configuration.
- Zapata
- a travaillé sur le protocole et implémenté la gestion
d'une la liste de contacts.
Un serveur de chat à pour but de permettre à plusieurs
utilisateurs de dialoguer entre eux. Chaque utilisateur à la
possibilité d'échanger des messages avec les autres. De plus pour
permettre aux utilisateurs de se regrouper, certaines informations
peuvent être publiées aux autres, et éventuellement, enregistrées
sur le serveur.
Chaque utilisateur est représenté en mémoire sur le serveur par un
objet. On parlera alors d'un objet utilisateur (ou user). Celui ci
regroupe toutes les informations relatives à un utilisateur.
Celles ci peuvent être d'ordre technique comme le socket, le
tampon d'envoi (voir la partie réseaux du rapport de deuxième
soutenance), tout comme des informations sur les utilisateurs
comme la ville où il habite, sa date de naissance. L'objet
utilisateur contient aussi deux files, une pour les messages qu'il
a reçus qui attendent d'être traités, l'autre la liste des canaux
auquel il est connecté.
Pour mettre de l'ordre dans tous ces objets utilisateurs, ils sont
classés dans une base de données. Souvent il sera nécessaire de
retrouver l'objet utilisateur correspondant à un nom. Il existe
donc cinq arbres de classement, en fonction du nom, de la ville,
de la date de naissance et enfin une liste des connectés triés par
nom. La structure interne est un arbre (de type AVL, pour plus
d'informations sur le fonctionnement voir le rapport de deuxième
soutenance).
Un utilisateur qui se connecte ponctuellement sur YooGoo, peut ne
pas vouloir fournir d'informations le concernant. Il est alors un
peu comme un invité. Aucunes des informations qu'il fournit ne
sont conservées sur le serveur. A peine il sera déconnecté que son
profil n'existera plus, il est obligé d'envoyer les informations à
chaque fois. Un utilisateur à tout de même accès à toutes les
fonctions de YooGoo.
Un utilisateur régulier de YooGoo aura fortement intérêt à
s'enregistrer. Toutes les informations qu'il fournit sont alors
enregistrées sur le serveur. Ainsi à chaque connexion il retrouve
toutes les informations qu'il a pu rentrer dans ses précédentes
sessions.
La commande
REG PASSWORD permet d'enregistré le
pseudo sous lequel on est connecté. Par la suite cet utilisateur
devra taper son mot de passe à la connexion pour pouvoir accéder
au serveur. Ainsi on est sur que ce soit toujours la même personne
qui utilise ce nom. Pour se désenregistré on utilise la commande
UNREG (sans paramètre). Chaque enregistrement crée une
entrée dans une base de données d'utilisateur. Lorsqu'on se
désinscrit l'entrée est supprimée, et il ne reste plus de trace de
l'utilisateur.
Le profil d'un utilisateur est conservé dans un fichier (par
défaut "user.yoo"). Quand l'utilisateur s'enregistre, on lui
attribue une ligne dans le fichier (la dernière). Ainsi à chaque
fois qu'on aura besoin d'accéder à ses informations on ira
directement à cette ligne du fichier. Ceci est d'autant plus
facile que chaque ligne du fichier à la même taille.
Cette ligne contient toutes les informations du profil d'un
utilisateur. Chaque champ est séparé par un caractère spécial. Les
champs ne doivent donc pas contenir ce caractère. Les différents
champs du profil sont (dans l'ordre): pseudo, genre, date de
naissance, ville, mot de passe, nom, prénom, adresse, code postal,
langue, pays, téléphone n°1, téléphone n°2, e-mail n°1, e-mail
n°2, photo, description. Dans le fichier la taille de chaque champ
est prédéfinit. Si la valeur fournit ne fait pas la bonne taille,
les trous sont comblés par des espaces.
Lors d'un désenregistrement on supprime la ligne de l'utilisateur
du fichier. Pour cela, on copie la dernière ligne du fichier, on
la met à la place de celle à supprimer, puis on réduit la taille
du fichier de la taille d'une ligne. Il ne faut pas oublier de
mettre à jour la ligne de l'utilisateur qui a été déplacé.
Au démarrage du serveur, le fichier base de données est parcouru,
et on crée en mémoire un objet pour chaque utilisateur enregistré.
Ceci permet de pouvoir effectuer des opérations sur les
utilisateurs enregistrés même si ceux ci ne sont pas connectés.
Les utilisateurs ont donc la possibilité d'envoyer des
informations leur concernant afin de les rendre disponibles aux
autres utilisateurs. Chaque utilisateur, enregistré ou pas, à un
mini profil contenant son pseudo, sa ville, sa date de naissance
et son genre. Un utilisateur enregistré a, quant à lui, un profil
complet avec nom, prénom, adresse etc.
Pour modifier les valeurs des champs de son profil, on utilise les
fonctions
CHN
ICK,
CHG
ENDER,... et ainsi de suite
pour tous les champs du profil. Ces fonctions testent les
arguments passés en paramètre pour voir s'il est acceptable. Si
aucune valeur est passé en paramètre à la fonction, on efface le
contenu du champ.
Le profil complet n'existe pas en mémoire. Il faut donc pour les
fonctions qui modifient ces valeurs écrire directement dans le
fichier. On accède au fichier à la ligne de l'utilisateur, on va
jusqu'au champ que l'on veut modifier en comptant le nombre de
caractères délimiteurs rencontrés et on modifie le champ (toujours
en complétant la taille du champ avec des espaces). Ainsi la base
de données est toujours
à jour.
Les valeurs du mini profil sont aussi stockées en mémoire car on y
accède beaucoup plus souvent. Nous avons vu que les objets
utilisateurs sont triés dans des arbres selon leur pseudo, leur
ville, leur age et leur genre. Lors d'une modification d'une de
ces valeurs il ne faut pas oublier de mettre à jour les arbres,
pour cela on supprime l'ancien utilisateur et on ajoute le
nouveau.
Toutes ces informations sont accessibles aux autres utilisateurs
grâce à deux fonctions. La première est
ASV USER
qui renvoie R
PL_
ASV NICK STATUS GENRE VILLE. On obtient
aussi tout le mini profil. Cette fonction est utilisable aussi
bien sur les utilisateurs enregistrés que sur ceux non
enregistrés. La seule restriction est qu'ils doivent être
connectés. La deuxième fonction est
WHO USER. Elle
renvoie plusieurs réponses R
PL_W
HO. La fonction ne
renvoie que les champs qui ont une valeur non nulle. Les
différentes réponses sont :
- RPL_WHO n°1 = Pseudo + genre + age + ville
- RPL_WHO n°2 = Nom + Prénom + Adresse + Code Postal + Langue + Pays
- RPL_WHO n°3 = Téléphone 1 + Téléphone 2 + Mail 1 + Mail 2
- RPL_WHO n°4 = Photo + Description
La fin de la transmission est marquée par le message
R
PL_E
NDW
HO. La valeur du champ est précédée par un
identifiant par exemple :
Rpl_who NOM= Angeline SEXE= FEMALE AGE= 19821006 VILLE= Paris
La commande
WHO ne marche que sur les utilisateurs
enregistrés, connectés ou non.
Mais le plus grand intérêt du profil est de pouvoir effectué des
recherches dessus. Il existe une fonction de recherche qui
renvoie la liste des utilisateurs correspondant aux critères que
l'on a définit. Il est donc possible de faire une recherche
multicritère. La fonction de recherche se prototype ainsi :
Search [Nick=Pseudo] [Age=Age][Birth=Date_Naissance] [Town=Ville]
[Sex={Male|Female}][Status={OnLine|OffLine}]
Pour chaque argument passé en paramètre à la fonction, on regarde
où est le '

', on regarde quel est l'identifiant qui le précède
et on affecte la valeur de ce champ à un objet utilisateur
temporaire. On recherche ensuite s'il y a un utilisateur qui
correspond exactement, sinon on recherche la liste des
utilisateurs qui ressemble à l'utilisateur recherché. Ceci est
possible grâce aux différents arbres de la base de données. On
renvoie alors une réponse R
PL_S
EARCH PSEUDO pour chaque
utilisateur trouvé.
La liste de contact est une liste de personne que l'on connaît et
qui ont des droits spéciaux. Il y a deux types de personnes que
l'on rajoute dans sa liste, des personnes que l'on aime bien avec
qui on va partager certaines informations. D'autres qu'on essaye
d'éviter, on pourra alors leur interdire certaines choses.
La liste de contact contient en fait deux listes. La liste de
contacts à proprement parler, qui associe à des noms des droits.
Mais aussi une liste de personne dont on est ami. Cette liste
permet de savoir à qui il faut envoyer des informations lorsqu'il
y à des changements.
Les listes des utilisateurs enregistrées sont sauvegardées, tout
comme le profil. Mais vu qu'on ne connaît pas par avance le nombre
de contacts que l'utilisateur va avoir, on ne peut avoir une ligne
de taille fixe par utilisateur. Il y a donc un fichier par
personne. Ce fichier contient une première ligne avec la première
liste, une suite de noms et d'entiers séparés par un caractère
spécial. A chaque connexion d'un utilisateur enregistré on charge
sa liste en mémoire. Il faut alors faire attention car il peut
avoir eu des changements alors qu'il était déconnecté, par exemple
quelqu'un l'a supprimé de sa liste, il faut donc mettre à jour la
liste des personnes dont on est ami pour cesser de le prévenir
lors de changements. Lors de la déconnexion on sauvegarde les
listes dans le fichier.
La fonction permettant de gérer toute la liste de contacts est :
contactlist add|get|del|change|accept|denie|status
Voici le détail de chaque sous fonction :
- ADD USER [DROIT]
- :
ajoute un utilisateur à la liste de contacts. Si droit n'est pas
indiqué c'est la valeur par défaut qui sera donné comme droit. Si
c'est un droit "mauvais" on envoie à l'utilisateur ajouté soit
CL_BLACKLISTEDBY (l'utilisateur à été mit en liste noire)
soit CL_IGNOREDBY (l'utilisateur est ignoré) soit
CL_MUTEBY (l'utilisateur ne peut plus parler avec la
personne). Si le droit est "ami" , on envoie alors une requête
d'ajout à l'utilisateur concerné, sauf si celui ci a aussi donné
un droit "ami" à l'appelant.
- DEL USER
- :
supprime un utilisateur de la liste de contacts. Si l'utilisateur
était un ami il est prévenu par CL_REMOVEDBY. Si
l'utilisateur supprimé était un ami, on supprime le nom de
l'appelant dans la liste des utilisateurs dont il est ami.
- CHANGE USER [DROIT]
- :
change les droit d'un utilisateur de la liste de contacts. Il faut
faire attention aux cas où un "ennemi" devient un "ami" ou
vice-versa. Si pas de droit la valeur par défaut est mise.
- GET [USER]
- :
permet de recevoir la liste de contacts d'un utilisateur. Sans
paramètre la fonction renvoie la liste de contact de l'appelant.
Sinon il faut que l'utilisateur ait les bons droits chez
l'utilisateur dont il désire avoir la liste de contacts.
Renvoie RPL_CL PSEUDO DROIT (avec dix couples
(pseudo, droit)maximum par réponse).
- ACCEPT USER
- :
permet d'accepter la demande d'ajout d'un ami.
- DENIE USER
- :
refuse la demande d'ajout d'un ami.
- STATUS
- :
renvoie le statut de tous les utilisateurs amis présents sur
la liste de contacts.
Comme nous l'avons vu, il est possible de donné des droits "ami"
comme des droits "mauvais" aux utilisateurs présents dans la liste
de contacts ?
Les différents droits sont :
- CL_BLACKLIST
- :
L'utilisateur cible est mis sur liste noire. Il n'a plus accès
aux informations de l'utilisateur appelant (la fonction
WHO et ASV lui sont inaccessibles). Il lui est
impossible de parler avec l'utilisateur appelant. Si l'utilisateur
cible essaye d'ajouter l'appelant à sa liste de contact, il
obtiendra un refus automatiquement. De plus l'appelant ne reçoit
plus les messages de la cible même lorsqu'il est connecté sur le
même canal.
- CL_NOREP
- :
L'utilisateur appelant ne donne plus accès à ces informations
(WHO et ASV inaccessibles). Un ajout sur la
liste de contacts sera automatiquement refusé.
- CL_MUTE
- :
L'utilisateur appelant ne reçoit plus aucun message de la part
de la cible, ni directement ni des canaux.
- CL_NOINOF
- :
L'utilisateur cache ces informations (WHO et
ASV inaccessibles).
- CL_ASVONLY
- :
Le WHO est inaccessible à la cible.
- CL_AMI1
- :
L'utilisateur cible est un ami. La cible prévient de ses
changements de statut, de ses connections et déconnections.
- CL_AMI2
- :
L'utilisateur cible est un ami. La cible prévient de ses
changements de statut, de ses connections et déconnections. La
cible peut avoir accès à la liste de contacts de l'appelant.
Le statut permet d'indiquer dans quel état on est. Souvent
certains utilisateurs restent connecté toute la journée, mais ils
ne sont pas forcement devant leur ordinateur. Pour prévenir les
autres dans un tel cas, il suffit de mettre sont statut sur AWAY,
pour indiquer que l'on est partit. Comme état il existe :
- ONLINE, on est connecté et devant son ordinateur.
- CHAT, on est disponible pour discuter.
- AWAY, on n'est pas devant son écran.
- DND, Do Not Disturb, on ne veut pas être dérangé.
- OCCUPIED, on est occupé.
- BRB, Be right Back, on revient tout de suite.
- OFFLINE, non connecté.
A chaque changement de statut il faut prévenir toutes les
personnes qui sont nos amis. Il faut aussi prévenir tous les
utilisateurs qui sont connectés au même canal, ceci peut permettre
à un client YooGoo de suivre l'évolution du statut des
utilisateurs connectés sur un canal. Il faut aussi prévenir ses
amis lorsqu'on se connecte et quand on se déconnecte. A la
connexion il faut aussi recevoir les statuts de tous les
utilisateurs amis présents dans la liste de contacts. Ceci ce fait
grâce à la fonction contactlist status. Cela est optionnel, donc
ce n'est pas le serveur qui s'en occupe, c'est le client qui doit
envoyer cette commande pour gérer une liste d'amis.
Que serait un serveur de chat sans commande pour dialoguer entre
utilisateurs ? Dans YooGoo il existe deux façons de parler entre
utilisateur, soit en passant par des canaux, soit en communiquant
directement avec un utilisateur.
Pour une discussion directe il y a deux possibilités, soit en
passant par le serveur, soit en connexion directe entre les deux
personnes. Pour une connexion directe c'est la commande
QUERY USER PORT qui sera utilisée. La
commande query envoie à l'utilisateur cible l'adresse IP et le
port où il doit se connecter pour parler avec l'autre utilisateur.
C'est alors aux client de s'occuper d'établir la connexion et de
communiquer. Le serveur ne s'occupe que de fournir l'adresse où se
connecter. L'inconvénient de cette méthode est d'une part que
chaque utilisateur connaît l'IP de l'autre, ce qui dans certains
cas peut être dangereux (selon la personne avec qui on parle),
d'autre part, on ne passe plus par le serveur, donc la
communication n'est pas forcement cryptée. L'avantage est que le
trafic sur le réseau est beaucoup plus moins important et plus
rapide.
Si on communique en passant par le serveur, c'est la commande
MSGUSER USER MSG qui sera utilisé. C'est le
serveur qui s'occupe d'envoyer le message d'un utilisateur à
l'autre. Le message est comme tous les autres crypté. De plus on à
pas besoin de connaître l'IP de l'autre. Un autre grand avantage
de cette méthode est que si l'utilisateur avec qui on parle est
enregistré, on peut aussi lui envoyer des messages même s'il n'est
pas connecté. Lors de sa prochaine connexion il recevra tous les
messages qu'on lui a envoyés. Ceci est extrêmement pratique car
souvent on ne peut pas être connecté en même temps, et il est
difficile de croiser tout le monde.
L'autre possibilité de discussion est en passant par des canaux.
Plusieurs personnes sont regroupées dans une même salle virtuelle,
chaque message envoyé est reçut par tous les autres utilisateurs
du canal. Les canaux sont vus plus en détails dans la partie
suivante.
Le principal but de YooGoo est d'accueillir ses utilisateurs sur
des canaux. Un canal peut aussi être appelé Chatroom ou salon. Un
salon est un "lieu" (ici, virtuel) où les utilisateurs discutent
entre eux. Chaque phrase de chaque utilisateur est retransmise à
tous les autres utilisateurs connectés sur le même salon.
Chaque canal est symbolisé par un objet que nous verrons en détail
un peu plus loin. Nous utilisons la base de données codée pour la
seconde soutenance pour gère les canaux. Les canaux sont triés
dans la base de données selon leurs noms. Effectivement, les
canaux sont repérés par un nom unique. La base de données nous
permet de faire la conversion entre le nom et l'adresse de l'objet
de façon très rapide (cf. rapport de soutenance numéro 2 : le
fonctionnement interne de la base de données).
Par exemple lorsqu'un utilisateur envoie la commande:
MsgChan Epita "Bonjour Tous le monde"
(commande permettant d'envoyer le message "Bonjour tous le monde"
sur le canal "Epita").
La première opération à faire sera de retrouver l'adresse du canal
Epita. Ensuite, nous pourrons traiter le reste de la commande.
L'objet canal correspond grosso modo à une liste chaînée
d'utilisateurs. Effectivement, toutes les fonctions basiques d'un
canal peuvent se faire sur une liste chaînée. Lorsqu'un
utilisateur envoie un message à un canal (
MSGC
HAN
CANAL MESSAGE), on vérifie que l'utilisateur qui
envoie le message est bien connecté au canal. Il suffit de faire
une recherche dans la liste. Ensuite, on parcourt la liste des
connectés sur le canal et on envoie un message à chaque
utilisateur de la liste. Le message renvoyé à la structure
suivante:
msgChan Canal Pseudo_de_l_expéditeur Message
Lorsqu'un utilisateur joint le canal (J
OIN CANAL
[P
ASSWORD] (Nous verrons l'argument P
ASSWORD plus
tard)), il suffit de l'ajouter dans la liste. De même lorsqu'il il
part d'un canal (P
ART CANAL), il suffit de faire
une suppression. Lorsqu'un utilisateur arrive ou part du canal, un
message informe les autres utilisateurs de l'évènement. Lorsqu'un
utilisateur essaye de joindre un canal qui n'est pas trouve dans
la base de données (donc, il n'existe pas) celui-ci est
automatiquement créé. Pour cela on crée un objet canal vide et on
l'ajoute dans la base de données. De même, lorsque le dernier
utilisateur d'un canal s'en va, ce dernier est automatiquement
détruit. Ceci pourra être modifié en changeant l'option
KEEP que nous verrons plus loin.
L'utilisateur aura aussi besoin de savoir qui est connecté avec
lui sur le canal. La fonction G
ETC
ONNECTED renvoie la
liste des utilisateurs d'un canal. Pour cette fonction, nous n'en
pouvions pas renvoyer tous les utilisateurs d'un seul coup. Nous
sommes effectivement limite par la taille du buffer d'envoi. Nous
envoyons donc le résultat par petits morceaux. Un message
R
PL_G
ETC
ONNECTED est envoyé pour chaque utilisateur. La
fin de la liste est signalée par le message
R
PL_E
NDG
ETC
ONNECTEDS. G
ETC
ONNECTEDS renvoie
aussi le statut et le grade des utilisateurs. Nous verrons tout a
l'heure la hiérarchie sur les canaux. Ces information seront utile
au client pour faire la liste
des connectés.
Par exemple :
<- getconnecteds Epita
-> Rpl_GetConnecteds Epita Danao ONLINE ChanRoot
-> Rpl_GetConnecteds Epita Zapata AWAY User
-> Rpl_GetConnecteds Epita Folken DND User
-> Rpl_GetConnecteds Epita Hargos ONLINE Op
-> Rpl_EndGetConnecteds
-> 0 Inf_Ok
Les fonctions précédente permettent d'avoir un objet canal de
base. YooGoo permet une gestion avancée des canaux en ajoutant des
droits à certains utilisateurs. Pour un utilisateur novice, cette
partie administrative est totalement transparente. Son client lui
affiche la liste des canaux, il fait un double click sur l'un
d'entre eux pour le joindre puis, il peut discuter. Il existe
quatre grades sur YooGoo. Tout d'abord l'utilisateur normal sans
droit particulier. Il peut créé un canal (c'est à dire joindre un
canal qui n'existe pas). A ce moment, il est considère fondateur
du canal et obtient tous les droits sur le canal. Il peut nommer
une autre personne comme fondateur du canal pour par exemple
l'administrer à deux ou bien avoir un utilisateurs avec pouvoir de
secours en cas de problèmes. Ces utilisateurs sont appelés
ChanRoots. Il est possible sur des gros canaux d'avoir besoin de
sous fifre pour gérer le canal. Mais, il peut être dangereux de
leurs donner tous les droits. Ces utilisateur avec des droits
moins importants que le ChanRoot sont des Opérateurs (on dira "Op"
(prononcer Opé) dans la pratique). Chanroot peut décider des
droits des Op. Enfin, tout en haut de l'échelle se trouve Root,
c'est à dire l'administrateur du serveur. Il a le droits de tout
faire, il n'a aucune barrière. Nous parlerons plus longuement de
ses fonctions dans la partie "Fonctions d'administrations" .
Signalons enfin, qu'un utilisateur peut être bannis d'un canal.
Lorsqu'un utilisateur se joint à un canal, on vérifie tout d'abord
qu'il n'est pas banni, si c'est le cas, sa demande est refusée et
il ne peut se joindre au canal.
Pour gérer les grades sur les canaux, nous utilisons trois listes
chaînées de Pseudonymes (ou NickName, en anglais). Nous ne
pouvions dans ce cas utiliser des listes de pointeurs sur user
(comme pour les connectés) car ces listes doivent encore être
opérationnelle lorsque l'utilisateur n'est plus connecté. Vu que
les Pseudo(Nîmes) sont protégé par mot de passe, on est sur de
l'identité d'un utilisateur. Il n'est donc pas possible de devenir
ChanRoot sur un canal en usurpant l'identité de celui-ci. Les
fonctions suivantes permettent l'ajout et la suppression dans les
listes des ChanRoot/Op/bannis :
- CHANROOT CANAL PSEUDO (nomme un ChanRoot)
- DECHANROOT CANAL PSEUDO (supprime un utilisateur de la liste des ChanRoot)
- OP CANAL PSEUDO (nomme un Op)
- DEOP CANAL PSEUDO (supprime un utilisateur de la liste des Op)
- BAN CANAL PSEUDO (bannit un utilisateur)
- DEBAN CANAL PSEUDO (supprime un utilisateur de la liste des
Bannis)
Pour gérer les droit des op, nous utilisons donc un entier où
chaque bit correspond à une fonction que les op peuvent utiliser.
Si le bit est à 0, ils n'y ont pas accès, sinon, ils peuvent
utiliser la commande. ChanRoot a accès à la commande
CHM
OD
C
ANAL C
OMMANDE {ONOFF} qui permet aux ops
d'utiliser ou non

Commande

. La fonction
CHM
OD
utilise un masque de bit pour mettre à jour la variable Droit. Si
ChanRoot décide de mettre toutes les commandes sur OFF, l'OP n'a
alors pas plus de droits d'un utilisateur normal. Si ChanRoot
décide de mettre toutes les commandes sur ON, les OP ont alors
presque autant de pouvoir que lui. Lors de la création du canal,
les Ops ont par défaut tout les droits. Tous les champs sont donc
à 1. Les seules commandes qui ne peuvent jamais devenir accessible
aux OP sont C
HANR
OOT (Nommer un ChanRoot),
D
EC
HANR
OOT (supprime un utilisateur de la liste des
ChanRoot),
CHM
OD (Modifier les droits des Ops) et
CHK
EEP et
CHP
RIV (que nous verrons plus bas).
Ainsi, pour chaque commande d'administration du serveur, on
vérifie que le demandeur
est ChanRoot OU (Op ET A_le_Droit).
Voici par exemple de ce qui peut se passer sur un canal Epita où
Hargos est ChanRoot, Danao est Op et Lamer est un utilisateur
normal:
Hargos -> ChMod Epita Ban OFF
Hargos <- Inf_Ok
**** Si l'op n'ont pas le droit de bannir ***
Danao -> ban Epita Lamer
Danao <- Err_Privileges
*** On modifie la variable Droit ***
Hargos -> ChMod Epita Ban On
Hargos <- Inf_Ok
*** Ca marche ***
Danao -> ban Epita Lamer
*** Tout le canal est averti de l'évènement ***
Danao <- ban Danao Epita Lamer
Hargos <- ban Danao Epita Lamer
Lamer <- ban Danao Epita Lamer
Danao <- Inf_Ok
Aux fonctions permettant de gérer la hiérarchie sur le canal
s'ajoute les fonctions permettant de gérer les petits détails du
canal. Tout d'abord, la fonction
KICK C
ANAL
N
ICK. Quand un utilisateur ne respecte pas les règles sur
un canal, un op peut décider de "kicker" celui ci, c'est à dire,
le forcer à partir du canal. Ceci n'empêchera pas l'utilisateur de
revenir tout de suite après, mais, elle sert d'avertissement au
bannissement (généralement accompagne d'un kick). En interne,
cette commande fonctionne exactement comme la fonction part.
L'objet canal possède aussi des variables pour le nom du canal,
son sujet, son mot de passe et sa catégorie. ces variables peuvent
être respectivement modifiée par C
HC
HANN
AME,
C
HC
HANT
OPIC, C
HC
HANP
ASS et
CHC
HANC
AT.
Lorsque l'on change le nom d'un canal, on modifie la variable et
surtout, on met a jour la base de données des canaux. Le sujet
permet de donne un aperçu du sujet de discussion du canal. Le mot
de passe empêche de joindre le canal si on ne possède pas le mot
de passe. Si la variable est vide, cela signifie qu'il n'y a pas
de mot passe. Lorsqu'un utilisateur joint un canal protégé par mot
de passe, il doit passer celui ci en paramètre de la commande
Join. On compare ce mot de passe avec celui du canal. Si ils sont
différents, l'accès est refusé. Enfin, a la catégorie correspond
un nombre qui permet de savoir sur quel sujet est le canal (A la
manière catégories Yahoo : Informatique, Voyage, Informations,
etc...)
Toutes ces informations peuvent être récupérées grâce à la
commande
WHAT CANAL. Cette commande renvoie
diverses info sur le canal sous la forme suivante:
R
PL_W
HAT N
OM S
UJET D
ROITS_
DES_O
P C
ATEGORIE
N
OMBRE_
DE_
CONNECTES N
OMBRE_
D'O
P
N
OMBRE_
DE_
CHANROOT N
OMBRE_
DE_
BANNIS.
Un utilisateur peut aussi recevoir la liste des ChanRoot/Op/bannis
du canal grâce aux commande G
ETC
HANR
OOTS,
G
ETO
PS, G
ETB
ANS. Ces commandes renvoient une
liste de nom de la même façon que G
ETC
ONNECTEDS. C'est à
dire R
PL_G
ETO
PS... R
PL_E
NDG
ETO
PS... etc
Enfin, pour que les utilisateurs puissent parfaitement utiliser
les canaux, il faut une commande permettant de donner la liste de
ceux-ci. G
ETC
HANS effectue cette tache. Le message
renvoyé est base sur le même modèle que G
ETC
ONNECTED,
G
ETB
ANS, etc... En interne, il faut cette fois parcourir
l'arbre des canaux pour récupère les nom de tous les canaux.
Au début de cette partie, nous avons dit que lorsque le dernier
connecte sur un canal s'en allait, le canal était détruit. La
variable Droits possède un bit supplémentaire permettant
d'empêcher ça lorsque ce bit est a 1.
CHK
EEP permet de
modifier la valeur de ce bit.
CHK
EEP n'est utilisable que
pas ChanRoot. Ainsi, lorsque le dernier utilisateur s'en va, le
canal et toute sa configuration sont conservés.
Lors de la fermeture du serveur la liste des canaux permanents est
sauvegardée dans un fichier. Pour chaque canal on sauvegarde aussi
toutes les informations qui lui sont relatives : nom, catégorie,
mot de passe s'il y en a, les droits et la description. Les
différentes listes sont aussi sauvegardés : les ops, les
chanroots, et les bannis. Lors du lancement du serveur, le fichier
est chargé et on recrée tous les canaux dans la base de donnée tel
qu'ils étaient avant la fermeture du serveur.
Nous savons qu'il existe deux sortes d'utilisateurs dans YooGoo,
les enregistrés et les non-enregistrés. De plus les diverses
listes utilisées pour l'administration d'un canal sauvegarde les
noms des utilisateurs. Ces raisons font qu'un administrateur de
canal peut désirer qu'il n'y est que des utilisateurs enregistrés
sur sont canal. Pour cela il existe un fanion P
RIVÉ.
Celui ci fonctionne comme le fanion K
EEP. Il n'est
utilisable que par le ChanRoot. Une fois activé, seuls les
utilisateurs
enregistrés pourront joindre le canal.
Nous avons vu qu'il est possible de protéger l'accès à un canal
par un mot de passe. Ainsi pour permettre à quelqu'un de rejoindre
le canal il faut lui donné le mot de passe. Mais cette méthode
peut être dangereuse, le mot de passe peut rapidement tomber entre
de mauvaises mains. Les ops et chanroot ont alors une autre
méthode pour permettre à un utilisateur lambda d'accédé au canal :
il peuvent l'inviter. La commande
INVITE USER et
DEINVITE USER permette la gestion des invités. Ces
fonctions fonctionnent comme les
OP/
DEOP, grâce
à une liste. Lorsqu'un utilisateur essaye de joindre un canal qui
est protégé par un mot de passe on regarde s'il est invité. Si
oui, on le supprime de la liste d'invité et il peut rejoindre le
canal. Ainsi une invitation n'est valable qu'une fois. De plus la
liste d'invité n'est pas sauvegardée. Ces deux points peuvent
sembler fastidieux mais permettent aux ops d'avoir un maximum de
contrôle des allées et venus dans leur canal. Il faut noter que
l'accès au mot de passe (G
ETC
HANP
ASS) est réservé aux ops
et ChanRoot.
Comme nous l'avons dit plus haut, YooGoo possède une hiérarchie.
Tout en haut de cette hiérarchie se trouve l'administrateur ou
encore appelle Root. A l'image d'UNIX, on considère Root
comme un homme de confiance absolue.
YooGoo permet de gérer plusieurs Root sur un serveur. Nous
utilisons, pour gérer les root, la même liste chaînée que pour la
gestion des ChanRoot, Op (operateurs?) et Bannis. Les seules
différences sont que cette liste est globale au serveur et quelle
est sauvegarde dans un fichier. Pour la structure du fichier, nous
utilisons une ligne par root. Comme pour les ChanRoot,
l'administrateur possède les commandes "root" et "deroot" pour
ajouter et supprimer des roots. Pour l'ajout d'un root dans le
fichier, on écrit une ligne a la fin. Pour la suppression, nous
avons décidé de réécrire tout le fichier plutôt que de faire un
algorithme compliqué. Le fichier étant court et la commande
rarement appelée, ça ne pose pas de problème de charge d'accès au
disque. Le fichier est ensuite lu à chaque démarrage.
Le premier privilège du Root est de ne jamais recevoir de message
"Err_Privileges". Dans toutes les fonctions qui demandent d'être
ChanRoot ou Op ou toute autre barrière, on teste si l'utilisateur
est root. Si c'est le cas, On le laisse faire.
Root possède aussi la commande K
ILL USER. Elle
permet à Root de déconnecter un utilisateur du canal. En interne,
cette
fonction appelle la fonction disconnect du serveur.
La commande
KICKA
LL CANAL permet de vider un canal.
Tous les utilisateurs sont " kickés " (vulgairement, jetés a coups
de pied dehors) et le canal est détruit si le fanion
KEEP
n'est pas actif. (Cf. partie "Les canaux") Si le root met un mot
de passe sur le canal avant de faire cette manip, il empêche
quiconque (puisque personne ne connaît le mot de passe) de se
joindre au canal. Ca peut être utile pour des canaux illégaux. En
interne, on appelle la fonction kick pour chaque personne du canal.
Il peut être intéressant pour le root d'envoyer un message a tous
les connectés pour par exemple signaler une maintenance. La
commande ToAll

Message

le permet. Par exemple :
root -> ToAll "Attention : Fermeture du serveur dans 5 minutes"
user1 <- ToAll "Attention : Fermeture du serveur dans 5 minutes"
user2 <- ToAll "Attention : Fermeture du serveur dans 5 minutes"
user3 <- ToAll "Attention : Fermeture du serveur dans 5 minutes"
.....
root <- Inf_Ok
Pour cette fonction, on parcourt l'arbre des connectes et on
envoie le message a chaque utilisateur.
Enfin, la plus puissante des commandes est peut-être la commande
IAM USER COMMAND. Elle permet d'exécuter une
commande comme si on était cet utilisateur. Pour effectuer ceci,
on appelle le parseur avec la commande et l'utilisateur en
question en paramètre. Nous avons des problèmes pour renvoyer les
retours de messages au root. Effectivement, une fois l'appel du
parseur fait, il n'y a plus moyen de savoir si c'est une commande
détournée ou non. Les messages de retours sont donc envoyés à
l'utilisateur. Nous avions au début pensé à changer le pointeur du
tampon d'envoi de l'utilisateur de façon à ce qu'il pointe sur le
tampon d'envoi du root. Ca aurait sûrement fonctionné avec un
serveur "Normal", mais Yoogoo est un serveur sécurisé. Il faut
donc aussi prendre en compte les clés DES, et ce, avant d'envoyer
le message à root. Bref cette solution aurait sûrement fonctionné,
mais, elle était trop compliquée à mettre en oeuvre. Nous avons
donc ajouté une variable de retour de type user * dans l'objet
user. Dans la fonction d'envoie, si cette variable et non NULL, on
rappelle la fonction d'envoie avec pour destinataire l'utilisateur
pointer par cette variable et le tour est joué.