-
Donnez le code permettant d'initialiser une structure
ARRAYofARRAY8 avec une seule adresse IP contenue dans
la variable globale adresseIP de type
struct in_addr.
Exemple de code convenable :
ARRAYofARRAY8 listeAdresses;
ARRAY8 adresse;
adresse.length=sizeof adresseIP;
adresse.data=(CARD8Ptr)&adresseIP;
adresses.length=1;
adresses.data=&adresse;
- Donnez la fonction remplissant une structure XdmcpBuffer
avec un paquet XDMCP de type MANAGE. Le prototype de
cette fonction est imposé :
XdmcpBufferPtr remplirManage(CARD32 sessionID,CARD16 displayNumber);
Exemple de code convenable :
XdmcpBufferPtr remplirManage(CARD32 sessionID,CARD16 displayNumber){
XdmcpBufferPtr buffer;
XdmcpHeader header;
ARRAY8 displayClass;
/* Allocation du tampon XDMCP */
buffer=allocXDMCPBuffer();
/* Ecriture de l'entete XDMCP */
header.version=XDM_PROTOCOL_VERSION;
header.opcode=(CARD16)MANAGE;
header.length=8+strlen(DISPLAY_CLASS);
XdmcpWriteHeader(buffer,&header);
/* Ecriture des champs additionnels */
XdmcpWriteCARD32(buffer,sessionID);
XdmcpWriteCARD16(buffer,displayNumber);
displayClass.length=strlen(DISPLAY_CLASS);
displayClass.data=DISPLAY_CLASS;
XdmcpWriteARRAY8(buffer,&displayClass);
return buffer;
}
- Donnez la fonction decoderAccept de décodage d'un paquet
XDMCP du type ACCEPT contenu dans une structure
XdmcpBuffer (l'entête XDMCP est sensée avoir été déjÃ
lue). Précisez bien le prototype de cette fonction. Vous
pouvez supposer que les fonctions ARRAY8toString et
ARRAY8toHexa sont déjà écrites.
Exemple de code convenable :
CARD32 decoderAccept(XdmcpBufferPtr paquet){
ARRAY8 authenName,authenData;
ARRAY8 authorName,authorData;
CARD32 sessionID;
/* Initialisation des champs d'Accept */
authenName.length=authenData.length=0;
authenName.data=authenData.data=NULL;
authorName.length=authorData.length=0;
authorName.data=authorData.data=NULL;
/* Lecture des champs dans le tampon */
if(XdmcpReadCARD32(paquet,&sessionID) &&
XdmcpReadARRAY8(paquet,&authenName) &&
XdmcpReadARRAY8(paquet,&authenData) &&
XdmcpReadARRAY8(paquet,&authorName) &&
XdmcpReadARRAY8(paquet,&authorData)){
char authorDataStr[MAX_CHAINE];
char authorNameStr[MAX_CHAINE];
char command[MAX_CHAINE];
/* Conversion en chaines des champs utiles */
ARRAY8toString(authorName,authorNameStr);
ARRAY8toHexa(authorData,authorDataStr);
if(strcmp(authorNameStr,AUTHORIZE_NAME)!=0){
fprintf(stderr,"Unknown authorization %s\n",authorNameStr);
exit(-1);
}
if(verbose) printf("Authorization data is %s\n",authorDataStr);
}
/* Libere la memoire */
XdmcpDisposeARRAY8(&authenName); XdmcpDisposeARRAY8(&authenData);
XdmcpDisposeARRAY8(&authorName); XdmcpDisposeARRAY8(&authorData);
XdmcpDisposeARRAY8(&status);
return sessionID;
}
- Dites dans quels cas le programme quémandeur de session doit
se terminer (on se place dans le cas où tous les paquets
XDMCP sont gérés). Soyez précis : terminaison sur réception de
tel paquet, après l'envoi de tel autre (avec ou non attente
de réponse du serveur), etc.
Il faut sortir sur réception des paquets UNWILLING
et DECLINE. Si l'envoi de paquets KEEPALIVE est
implanté il faut en plus sortir lors de la réception de
REFUSE ou de FAILED. Il faut aussi sortir si l'on
ne reçoit plus de paquet ALIVE. Si on n'implante pas
l'envoi de paquets KEEPALIVE, il faut sortir après
l'émission du paquet MANAGE et sans s'attendre à une
réponse.
- En tenant compte de votre réponse à la question précédente,
donnez le code de la fonction d'envoi de paquet XDMCP. Ce code
doit, bien sûr, envoyer le datagramme au serveur de sessions
mais aussi éventuellement gérer la perte de paquets par UDP
(réémissions). Le prototype de la fonction est à préciser
avec soin.
Exemple de code convenable :
void envoyerPaquet(int ds, /* Socket locale */
XdmcpBufferPtr paquet, /* Contient le paquet XDMCP */
struct sockaddr_in adresse, /* Socket du serveur */
unsigned char reponse /* Attente d'une reponse ? */
){
fd_set lecture ; /* Ensemble de descripteurs en lecture */
struct timeval minuteur; /* Structure du minuteur */
int compteur=0;
while(TRUE) {
/* Envoyer le datagramme XDMCP */
sendto(ds,paquet->data,paquet->pointer,0,
(struct sockaddr *)&adresse,sizeof adresse);
/* Sortie immediate si on ne s'attend pas a une reponse */
if(!reponse) return;
/* Attente d'une reponse avec armement d'un minuteur */
FD_ZERO(&lecture); FD_SET(ds,&lecture);
minuteur.tv_sec=MINUTEUR_DUREE; minuteur.tv_usec=0;
select(ds+1,&lecture,NULL,NULL,&minuteur);
/* Sortie si la reponse est prete a lire */
if(FD_ISSET(ds,&lecture)) break;
/* Nombre d'essais depasse ? */
if(++compteur>MAX_COMPTEUR){
fprintf(stderr,"Server is not answering !\n");
exit(-1);
}
}
}