diff --git a/header/puit.h b/header/puit.h index 9cdefad..49276ab 100644 --- a/header/puit.h +++ b/header/puit.h @@ -66,6 +66,20 @@ void receptionEmetteur(int sock, int tailleMessagePrevu, int * tailleMessageRecu * @param recepteur int, id du recepteur. * @param boiteAuxLettres struct listeBAL, la boite aux lettres à renvoyer. */ -void receptionRecepteur(int sock, int recepteur, struct listeBAL boiteAuxLettres); +int receptionRecepteur(int sock, int socketType, struct sockaddr_in socketStruct, int port, int recepteur, struct listeBAL boiteAuxLettres); + +/** + * @brief Permet, à partir de isTCP de choisir la méthode d'envoi. + * + * @param sock int,socket premettant d'utiliser la primitive read()/recvfrom(). + * @param socketStruct struct sockaddr_in, la structure du socket avec l'ip et le port. + * @param longueurRecu int, sizeof(socketStruct) + * @param messageRecu char*, la chaîne de caractère qui recevra le message, doit être allouée + * @param tailleMessage int, la longueur donnée par l'utilisateur + * @param isTCP int, 1 -> TCP, 0 -> UDP + * @param i int, fonctionne comme un count pour le printf() + * @return int, renvoi la longueur n reçue par TCP/UDP. + */ +int readRecvFrom(int sock, struct sockaddr_in socketStruct, int longueurRecu, char * messageRecu, int tailleMessage, int isTCP, int i); #endif \ No newline at end of file diff --git a/header/tsock.h b/header/tsock.h index b0579dd..bad70e8 100644 --- a/header/tsock.h +++ b/header/tsock.h @@ -174,7 +174,7 @@ int protocol2int(char * data, int offset); * @param socketStruct struct sockaddr_in, structure du socket * @param tailleSocket int, sizeof(socketStruct) */ -void connectTCP(int sock, struct sockaddr_in socketStruct, int tailleSocket); +int connectTCP(int sock, struct sockaddr_in socketStruct, int tailleSocket); /** * @brief Récupère la longueur émise par la fonction write() (TCP) ou sendto() (UDP) @@ -202,4 +202,23 @@ void printAndVerif(char * sendingMessage,int tailleMessage,int longueurEmis, int */ int initSocket(int socketType, struct sockaddr_in * socketStruct, int port, char * ipAddress); +/** + * @brief Ouvre un socket à l'aide d'un socketType + * + * @param socketType SOCK_STREAM pour TCP ou SOCK_DGRAM pour UDP + * @return int le socket créé + */ +int openSocket(int socketType); + +/** + * @brief utilise la fonction listen et accept de TCP pour créer un nouveau socket. + * + * @param sock int, le socket pour lancer la connexion. + * @param socketStruct struct sockaddr_in*, la structure du socket sous forme de pointeur. + * @param sizeSocketStruct int, sizeof(*socketStruct) + * @param closeSocket bool, 1-> ferme le socket sock. + * @return int, le socket crée par accept(). + */ +int listenAndAccept(int sock, struct sockaddr_in * socketStruct, int * sizeSocketStruct, bool closeSocket); + #endif \ No newline at end of file diff --git a/src/puit.c b/src/puit.c index 65a593b..b076de0 100644 --- a/src/puit.c +++ b/src/puit.c @@ -4,13 +4,17 @@ int launchPuit(int nombreMessage,int tailleMessage,int isTCP,int port,char * ipA { int sock,socketType; struct sockaddr_in socketPuit; + /*socketType change de valeur en fonction de isTCP -> si isTCp alors SOCK_STREAM, sinon SOCK_DGRAM*/ socketType = (isTCP) ? SOCK_STREAM : SOCK_DGRAM; + /*Si le mode boîte aux lettres est activé alors on entre dans le mode BAL -> on return 0 car nous ne voulons pas + rentrer dans le mode TCP/UDP normal.*/ if(isBAL) { printf("Mode Boîte aux Lettres\n"); - modeBoiteAuxLettres(socketPuit,socketType,port,ipAddress); + modeBoiteAuxLettres(socketPuit,SOCK_STREAM,port,ipAddress); return 0; } + /*Sinon on initialise le socket de base et on rentre dans receiveMultipleData() -> on ferme le socket avant*/ sock = initSocket(socketType,&socketPuit,port,ipAddress); receiveMultipleData(nombreMessage,tailleMessage,sock,socketPuit,isTCP); close(sock); @@ -19,17 +23,20 @@ int launchPuit(int nombreMessage,int tailleMessage,int isTCP,int port,char * ipA void modeBoiteAuxLettres(struct sockaddr_in socketStruct, int socketType, int port, char * ipAddress) { + /*Init : Création de la boite aux lettres, de paramRecu pour la couche protocolaire. + Intiialisation de la taille de socketStruct pour les différentes fonctions. + Création des 4 variables à récupérer dans la couche protocolaire.*/ struct listeBAL boiteAuxLettres = initListeBAL(); char paramRecu[13]; - int n, longueurRecu = sizeof(socketStruct),sock,oldSock, trueTemp = 1,option=1; + int n, longueurRecu = sizeof(socketStruct),sock,oldSock; int param,emetteurRecepteur,tailleMessage,nbMessage; while(1) { + /*Etat d'attente -> création d'un socket pour écouter le premier client et récupérer son IP. n=1 pour rentrer dans le while*/ n=1; oldSock = initSocket(socketType,&socketStruct,port,ipAddress); - listen(oldSock,5); - sock = accept(oldSock,(struct sockaddr *)&socketStruct,(socklen_t * restrict)&longueurRecu); - close(oldSock); + sock = listenAndAccept(oldSock,&socketStruct,&longueurRecu,true); + /*Tant qu'on reçoit des données, on vérifie si le client nous demande une reception ou une emission*/ while(n>0) { n = read(sock,paramRecu,13); @@ -37,18 +44,8 @@ void modeBoiteAuxLettres(struct sockaddr_in socketStruct, int socketType, int po switch(param) { case MODE_RECEPTEUR: - close(sock); - if((sock=socket(AF_INET,socketType,0)) == -1) - { - perror("[tsock] : fonction socket() : echec creation du socket\n"); - exit(EXIT_FAILURE); - } - initStructSocket(&socketStruct,1,port,ipAddress); - /*On attend 1 seconde pour que la source lance un listen TCP*/ - sleep(1); - /*On lance une connexion TCP et on envoit à l'aide de receptionRecepteur() les données*/ - connectTCP(sock,socketStruct,sizeof(socketStruct)); - receptionRecepteur(sock,emetteurRecepteur,boiteAuxLettres); + /*On récupère le socket créé par receptionRecepteur pour le fermer par la suite*/ + sock=receptionRecepteur(sock,socketType,socketStruct,port,emetteurRecepteur,boiteAuxLettres); /*Pour fermer le while on met n=-1*/ n=-1; break; @@ -60,25 +57,46 @@ void modeBoiteAuxLettres(struct sockaddr_in socketStruct, int socketType, int po break; } } + /*Si on est en mode emis, le serveur affiche les données rentrées dans la boite aux lettres*/ if(param == MODE_EMIS) { afficheListeBAL(boiteAuxLettres); } + /*On ferme le socket qu'il provienne du MODE_RECEPTEUR ou MODE_EMIS*/ close(sock); } } -void receptionRecepteur(int sock, int recepteur, struct listeBAL boiteAuxLettres) +int receptionRecepteur(int sock, int socketType, struct sockaddr_in socketStruct, int port, int recepteur, struct listeBAL boiteAuxLettres) { + /*StripAddressStruct va convertir l'adresse de socketStruct en char* car initStructSocket demande ce type de variable. + On crée des pointeurs vers les éléments du recepteur concerné. + inet_ntop permet de convertir une adresse in_addr en char**/ int longueurEmis,i=1; - char *paramMessage; + char *paramMessage,StripAddressStruct[INET_ADDRSTRLEN]; + struct in_addr ipAddressStruct = ((struct sockaddr_in*)&socketStruct)->sin_addr; + struct elementMessage *elementFinal = getMessages(boiteAuxLettres,recepteur)->fin,*elementCourant = getMessages(boiteAuxLettres,recepteur)->courant; + inet_ntop( AF_INET, &ipAddressStruct, StripAddressStruct, INET_ADDRSTRLEN ); + + /*On ferme la connexion qui était en mode listen() + On crée un nouveau socket en initialisant la structure sockaddr_in avec l'adresse IP du client*/ + close(sock); + sock=openSocket(socketType); + initStructSocket(&socketStruct,1,port,StripAddressStruct); + /*On attend 1 seconde pour que la source lance un listen TCP + On lance une connexion TCP -> Si -1 alors on retourne le socket crée et on ferme la connexion (on retourne dans l'état d'attente)*/ + sleep(1); + if (connectTCP(sock,socketStruct,sizeof(socketStruct)) == -1) + { + return sock; + } printf("\n--- Messages à renvoyer pour %d : ---\n",recepteur); - struct elementMessage * elementFinal = getMessages(boiteAuxLettres,recepteur)->fin; - struct elementMessage * elementCourant = getMessages(boiteAuxLettres,recepteur)->courant; + /*Tant qu'il reste des éléments dans la liste on envoi les différents paquets : + La couche protocolaire avec MODE_RECEPTEUR, l'id de celui qui a envoyé le message, la taille et le nombre de messages + Le message avec la taille correcte. On incrémente i pour l'affichage et on passe à l'élément suivant.*/ while(elementCourant->suiv != elementFinal->suiv) { paramMessage = formatTextParam(MODE_RECEPTEUR,recepteur,elementCourant->messageBALActuel->tailleData,getMessages(boiteAuxLettres,recepteur)->nbMessages); - printf("paramMessage [%d] = %s\n",i,paramMessage); longueurEmis = write(sock,paramMessage,13); printAndVerif(paramMessage,13,longueurEmis,i); @@ -87,12 +105,16 @@ void receptionRecepteur(int sock, int recepteur, struct listeBAL boiteAuxLettres i++; elementCourant=elementCourant->suiv; } + return sock; } void receptionEmetteur(int sock, int tailleMessagePrevu, int * tailleMessageRecu, int emetteur, int recepteur, struct listeBAL *boiteAuxLettres) { + /*On créer un pointeur char car nouveauMessage utilise ce dernier pour l'associer à la boite aux lettres*/ char * messageRecu = malloc(sizeof(char)*tailleMessagePrevu); + /*On lit les messages reçus après chaque envoi protocolaire -> la taille est donc connue*/ *tailleMessageRecu = read(sock,messageRecu,tailleMessagePrevu); + /*Le nouveau message n'est mis dans la BAL que si la donnée est correcte : donc au dessus d'une taille de 0 octet*/ if(*tailleMessageRecu>0) { nouveauMessage(boiteAuxLettres,emetteur,recepteur,messageRecu); @@ -101,45 +123,48 @@ void receptionEmetteur(int sock, int tailleMessagePrevu, int * tailleMessageRecu int receiveMultipleData(int nombreMessages, int tailleMessage, int sock, struct sockaddr_in socketStruct, int isTCP) { + /*messageRecu sera affiché avec un printf. La variable count est créé au préalable pour le while, n est mis à 1 pour la même raison*/ char messageRecu[tailleMessage+1]; - int n=1, longueurRecu = sizeof(socketStruct); + int n=1, count=0, longueurRecu = sizeof(socketStruct); + /*Dans le cas d'une connexion TCP on lance la primitive listenAndAccept() pour établir la connexion avec la source/le client*/ if(isTCP) { - listen(sock,5); - sock = accept(sock,(struct sockaddr *)&socketStruct,(socklen_t * restrict)&longueurRecu); + sock = listenAndAccept(sock,&socketStruct,&longueurRecu,true); } + /*On reçoit des messages tant qu'ils sont vide (pour TCP uniquement)*/ if(nombreMessages < 0) { - int i=1; + /*Tant qu'on reçoit des messages on continue.*/ while(n>0) { - if(isTCP) - { - n = read(sock,messageRecu,tailleMessage); - } - else - { - n = recvfrom(sock, (char *)messageRecu, tailleMessage, 0, (struct sockaddr*) &socketStruct,(socklen_t *__restrict__)&longueurRecu); - } - messageRecu[n] = '\0'; - printf("Puit\tReception n°%d (%d) :\t[%s]\n",i,n,messageRecu); - i++; + n=readRecvFrom(sock,socketStruct,longueurRecu,messageRecu,tailleMessage,isTCP,count+1); + count++; } } else{ - for(int i=0;i