From 67fe286a03c0c2f0d425ef01a068a006b91df247 Mon Sep 17 00:00:00 2001 From: xdrm-brackets Date: Wed, 16 Dec 2015 11:02:05 +0100 Subject: [PATCH] =?UTF-8?q?Ajout=20de=20DEBUGMOD=20en=20mode=20avanc=C3=A9?= =?UTF-8?q?=20(selectif)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- dep/client.c | 87 +++++++++++++++++++++++----------------------- dep/server.c | 94 +++++++++++++++++++++++++++----------------------- dep/utility.c | 64 ++++++++++++++++++++++++++-------- dep/utility.h | 18 +++++++++- proxy_ftp.c | 14 +++----- proxy_ftp.h | 22 ++++++++---- test | Bin 18811 -> 22955 bytes 7 files changed, 183 insertions(+), 116 deletions(-) diff --git a/dep/client.c b/dep/client.c index f9add28..35e3f22 100644 --- a/dep/client.c +++ b/dep/client.c @@ -7,7 +7,7 @@ void CLIENT_REQUEST(char* serverHost, char* serverPort, char* pRequest, char** pAnswer){ - if( DEBUGMOD ) printf("====== CLIENT_REQUEST(%s, %s, %s, %s) ======\n\n", serverHost, serverPort, pRequest, *pAnswer); + if( DEBUGMOD&HDR ) printf("====== CLIENT_REQUEST(%s, %s, %s, %s) ======\n\n", serverHost, serverPort, pRequest, *pAnswer); struct addrinfo hints; // contiendra le filtre/format struct addrinfo* addrinfo; // contiendra les infos @@ -23,32 +23,32 @@ void CLIENT_REQUEST(char* serverHost, char* serverPort, char* pRequest, char** p hints.ai_flags = 0; // non spécifié hints.ai_protocol = 0; // non spécifié - if( DEBUGMOD ) printf("============HINTS===========\n"); - if( DEBUGMOD ) printf( "AI_FLAGS = %d\n", hints.ai_flags ); // int - if( DEBUGMOD ) printf( "AI_FAMILY = %d\n", hints.ai_family ); // int - if( DEBUGMOD ) printf( "AI_SOCKTYPE = %d\n", hints.ai_socktype ); // int - if( DEBUGMOD ) printf( "AI_PROTOCOL = %d\n", hints.ai_protocol ); // int - if( DEBUGMOD ) printf( "AI_ADDRLEN = %d\n", hints.ai_addrlen ); // int - if( DEBUGMOD ) printf("\n"); + if( DEBUGMOD&SCK ) printf("============HINTS===========\n"); + if( DEBUGMOD&SCK ) printf( "AI_FLAGS = %d\n", hints.ai_flags ); // int + if( DEBUGMOD&SCK ) printf( "AI_FAMILY = %d\n", hints.ai_family ); // int + if( DEBUGMOD&SCK ) printf( "AI_SOCKTYPE = %d\n", hints.ai_socktype ); // int + if( DEBUGMOD&SCK ) printf( "AI_PROTOCOL = %d\n", hints.ai_protocol ); // int + if( DEBUGMOD&SCK ) printf( "AI_ADDRLEN = %d\n", hints.ai_addrlen ); // int + if( DEBUGMOD&SCK ) printf("\n"); /* [2] On récupère les infos =======================================================*/ getaddrinfo(serverHost, serverPort, &hints, &addrinfo); - if( DEBUGMOD ) printf("=============RES============\n"); - if( DEBUGMOD ) printf( "AI_FLAGS = %d\n", addrinfo->ai_flags ); // int - if( DEBUGMOD ) printf( "AI_FAMILY = %d\n", addrinfo->ai_family ); // int - if( DEBUGMOD ) printf( "AI_SOCKTYPE = %d\n", addrinfo->ai_socktype ); // int - if( DEBUGMOD ) printf( "AI_PROTOCOL = %d\n", addrinfo->ai_protocol ); // int - if( DEBUGMOD ) printf( "AI_ADDRLEN = %d\n", addrinfo->ai_addrlen ); // int - if( DEBUGMOD ) printf("\n"); + if( DEBUGMOD&SCK ) printf("=============RES============\n"); + if( DEBUGMOD&SCK ) printf( "AI_FLAGS = %d\n", addrinfo->ai_flags ); // int + if( DEBUGMOD&SCK ) printf( "AI_FAMILY = %d\n", addrinfo->ai_family ); // int + if( DEBUGMOD&SCK ) printf( "AI_SOCKTYPE = %d\n", addrinfo->ai_socktype ); // int + if( DEBUGMOD&SCK ) printf( "AI_PROTOCOL = %d\n", addrinfo->ai_protocol ); // int + if( DEBUGMOD&SCK ) printf( "AI_ADDRLEN = %d\n", addrinfo->ai_addrlen ); // int + if( DEBUGMOD&SCK ) printf("\n"); /* [3] Création de la socket =======================================================*/ SOCKET = socket(addrinfo->ai_family, addrinfo->ai_socktype, 0); - if( DEBUGMOD ) printf("SOCKET = %d\n", SOCKET); + if( DEBUGMOD&SCK ) printf("SOCKET = %d\n", SOCKET); // si erreur if( SOCKET == -1 ) return; @@ -61,7 +61,7 @@ void CLIENT_REQUEST(char* serverHost, char* serverPort, char* pRequest, char** p addrinfo->ai_addrlen ); - if( DEBUGMOD ) printf("CONNECT = %d\n", CONNECT); + if( DEBUGMOD&SCK ) printf("CONNECT = %d\n", CONNECT); // si erreur if( CONNECT == -1 ) return; @@ -74,8 +74,8 @@ void CLIENT_REQUEST(char* serverHost, char* serverPort, char* pRequest, char** p =======================================================*/ int nbSend = swrite(&SOCKET, pRequest); - if( DEBUGMOD ) printf("nbSend: %d\n", nbSend); - if( DEBUGMOD ) printf("Message: %s\n", pRequest); + if( DEBUGMOD&BUF ) printf("nbSend: %d\n", nbSend); + if( DEBUGMOD&BUF ) printf("Message: %s\n", pRequest); // si pas tout envoyé if( strlen(pRequest) != nbSend ) return; @@ -88,8 +88,8 @@ void CLIENT_REQUEST(char* serverHost, char* serverPort, char* pRequest, char** p *pAnswer = malloc( maxBuffLen ); strcpy(*pAnswer, BUFFER); - if( DEBUGMOD ) printf("nbReceived: %d\n", nbRecup); - if( DEBUGMOD ) printf("Message: %s\n", *pAnswer); + if( DEBUGMOD&BUF ) printf("nbReceived: %d\n", nbRecup); + if( DEBUGMOD&BUF ) printf("Message: %s\n", *pAnswer); /* [7] On ferme la connection @@ -103,7 +103,7 @@ void CLIENT_REQUEST(char* serverHost, char* serverPort, char* pRequest, char** p void CONNECT_CLIENT(char* serverHost, char* serverPort, int* pSocket){ - if( DEBUGMOD ) printf("====== INIT_CLIENT(%s, %s, %d) ======\n\n", serverHost, serverPort, *pSocket); + if( DEBUGMOD&HDR ) printf("====== INIT_CLIENT(%s, %s, %d) ======\n\n", serverHost, serverPort, *pSocket); struct addrinfo hints; // contiendra le filtre/format struct addrinfo* addrinfo; // contiendra les infos @@ -119,32 +119,32 @@ void CONNECT_CLIENT(char* serverHost, char* serverPort, int* pSocket){ hints.ai_flags = 0; // non spécifié hints.ai_protocol = 0; // non spécifié - if( DEBUGMOD ) printf("============HINTS===========\n"); - if( DEBUGMOD ) printf( "AI_FLAGS = %d\n", hints.ai_flags ); // int - if( DEBUGMOD ) printf( "AI_FAMILY = %d\n", hints.ai_family ); // int - if( DEBUGMOD ) printf( "AI_SOCKTYPE = %d\n", hints.ai_socktype ); // int - if( DEBUGMOD ) printf( "AI_PROTOCOL = %d\n", hints.ai_protocol ); // int - if( DEBUGMOD ) printf( "AI_ADDRLEN = %d\n", hints.ai_addrlen ); // int - if( DEBUGMOD ) printf("\n"); + if( DEBUGMOD&SCK ) printf("============HINTS===========\n"); + if( DEBUGMOD&SCK ) printf( "AI_FLAGS = %d\n", hints.ai_flags ); // int + if( DEBUGMOD&SCK ) printf( "AI_FAMILY = %d\n", hints.ai_family ); // int + if( DEBUGMOD&SCK ) printf( "AI_SOCKTYPE = %d\n", hints.ai_socktype ); // int + if( DEBUGMOD&SCK ) printf( "AI_PROTOCOL = %d\n", hints.ai_protocol ); // int + if( DEBUGMOD&SCK ) printf( "AI_ADDRLEN = %d\n", hints.ai_addrlen ); // int + if( DEBUGMOD&SCK ) printf("\n"); /* [2] On récupère les infos =======================================================*/ getaddrinfo(serverHost, serverPort, &hints, &addrinfo); - if( DEBUGMOD ) printf("=============RES============\n"); - if( DEBUGMOD ) printf( "AI_FLAGS = %d\n", addrinfo->ai_flags ); // int - if( DEBUGMOD ) printf( "AI_FAMILY = %d\n", addrinfo->ai_family ); // int - if( DEBUGMOD ) printf( "AI_SOCKTYPE = %d\n", addrinfo->ai_socktype ); // int - if( DEBUGMOD ) printf( "AI_PROTOCOL = %d\n", addrinfo->ai_protocol ); // int - if( DEBUGMOD ) printf( "AI_ADDRLEN = %d\n", addrinfo->ai_addrlen ); // int - if( DEBUGMOD ) printf("\n"); + if( DEBUGMOD&SCK ) printf("=============RES============\n"); + if( DEBUGMOD&SCK ) printf( "AI_FLAGS = %d\n", addrinfo->ai_flags ); // int + if( DEBUGMOD&SCK ) printf( "AI_FAMILY = %d\n", addrinfo->ai_family ); // int + if( DEBUGMOD&SCK ) printf( "AI_SOCKTYPE = %d\n", addrinfo->ai_socktype ); // int + if( DEBUGMOD&SCK ) printf( "AI_PROTOCOL = %d\n", addrinfo->ai_protocol ); // int + if( DEBUGMOD&SCK ) printf( "AI_ADDRLEN = %d\n", addrinfo->ai_addrlen ); // int + if( DEBUGMOD&SCK ) printf("\n"); /* [3] Création de la socket =======================================================*/ *pSocket = socket(addrinfo->ai_family, addrinfo->ai_socktype, 0); - if( DEBUGMOD ) printf("SOCKET = %d\n", *pSocket); + if( DEBUGMOD&SCK ) printf("SOCKET = %d\n", *pSocket); // si erreur if( *pSocket == -1 ) return; @@ -157,7 +157,7 @@ void CONNECT_CLIENT(char* serverHost, char* serverPort, int* pSocket){ addrinfo->ai_addrlen ); - if( DEBUGMOD ) printf("CONNECT = %d\n", CONNECT); + if( DEBUGMOD&SCK ) printf("CONNECT = %d\n", CONNECT); // si erreur if( CONNECT == -1 ) return; @@ -169,14 +169,15 @@ void CONNECT_CLIENT(char* serverHost, char* serverPort, int* pSocket){ void CLIENT_SEND(int* pSocket, char* pRequest, char** pAnswer){ - char BUFFER[maxBuffLen] = {'\0'}; + if( DEBUGMOD&HDR ) printf("====== CLIENT_SEND(%d, %s, %s) ======\n\n", *pSocket, pRequest, *pRequest); + char BUFFER[maxBuffLen] = {0}; /* [5] On écrit sur la socket =======================================================*/ int nbSend = swrite(pSocket, pRequest); - if( DEBUGMOD ) printf("nbSend: %d\n", nbSend); - if( DEBUGMOD ) printf("Message: %s\n", pRequest); + if( DEBUGMOD&BUF ) printf("nbSend: %d\n", nbSend); + if( DEBUGMOD&BUF ) printf("Message: %s\n", pRequest); // si pas tout envoyé if( strlen(pRequest) != nbSend ) return; @@ -188,6 +189,6 @@ void CLIENT_SEND(int* pSocket, char* pRequest, char** pAnswer){ *pAnswer = malloc( maxBuffLen ); strcpy(*pAnswer, BUFFER); - if( DEBUGMOD ) printf("nbReceived: %d\n", nbRecup); - if( DEBUGMOD ) printf("Message: %s\n", *pAnswer); + if( DEBUGMOD&BUF ) printf("nbReceived: %d\n", nbRecup); + if( DEBUGMOD&BUF ) printf("Message: %s\n", *pAnswer); } \ No newline at end of file diff --git a/dep/server.c b/dep/server.c index ed12234..13707dc 100644 --- a/dep/server.c +++ b/dep/server.c @@ -7,7 +7,7 @@ void DROP_SERVER(char* serverHost, char** givenPort, int* listenSocket){ - if( DEBUGMOD ) printf("====== DROP_SERVER(%s, %s, %d) ======\n\n", serverHost, *givenPort, *listenSocket); + if( DEBUGMOD&HDR ) printf("====== DROP_SERVER(%s, %s, %d) ======\n\n", serverHost, *givenPort, *listenSocket); // FONCTIONNEMENT struct addrinfo hints; // contiendra le filtre/format @@ -28,13 +28,13 @@ void DROP_SERVER(char* serverHost, char** givenPort, int* listenSocket){ hints.ai_flags = AI_PASSIVE; // mode SERVER hints.ai_protocol = 0; // non spécifié - if( DEBUGMOD ) printf("============HINTS===========\n"); - if( DEBUGMOD ) printf( "AI_FLAGS = %d\n", hints.ai_flags ); // int - if( DEBUGMOD ) printf( "AI_FAMILY = %d\n", hints.ai_family ); // int - if( DEBUGMOD ) printf( "AI_SOCKTYPE = %d\n", hints.ai_socktype ); // int - if( DEBUGMOD ) printf( "AI_PROTOCOL = %d\n", hints.ai_protocol ); // int - if( DEBUGMOD ) printf( "AI_ADDRLEN = %d\n", hints.ai_addrlen ); // int - if( DEBUGMOD ) printf("\n"); + if( DEBUGMOD&SCK ) printf("============HINTS===========\n"); + if( DEBUGMOD&SCK ) printf( "AI_FLAGS = %d\n", hints.ai_flags ); // int + if( DEBUGMOD&SCK ) printf( "AI_FAMILY = %d\n", hints.ai_family ); // int + if( DEBUGMOD&SCK ) printf( "AI_SOCKTYPE = %d\n", hints.ai_socktype ); // int + if( DEBUGMOD&SCK ) printf( "AI_PROTOCOL = %d\n", hints.ai_protocol ); // int + if( DEBUGMOD&SCK ) printf( "AI_ADDRLEN = %d\n", hints.ai_addrlen ); // int + if( DEBUGMOD&SCK ) printf("\n"); /* [2] On récupère les infos @@ -45,20 +45,20 @@ void DROP_SERVER(char* serverHost, char** givenPort, int* listenSocket){ getaddrinfo(serverHost, *givenPort, &hints, &addrinfo); // Remarque: port=0 donc va être défini dynamiquement - if( DEBUGMOD ) printf("=============RES============\n"); - if( DEBUGMOD ) printf( "AI_FLAGS = %d\n", addrinfo->ai_flags ); // int - if( DEBUGMOD ) printf( "AI_FAMILY = %d\n", addrinfo->ai_family ); // int - if( DEBUGMOD ) printf( "AI_SOCKTYPE = %d\n", addrinfo->ai_socktype ); // int - if( DEBUGMOD ) printf( "AI_PROTOCOL = %d\n", addrinfo->ai_protocol ); // int - if( DEBUGMOD ) printf( "AI_ADDRLEN = %d\n", addrinfo->ai_addrlen ); // int - if( DEBUGMOD ) printf("\n"); + if( DEBUGMOD&SCK ) printf("=============RES============\n"); + if( DEBUGMOD&SCK ) printf( "AI_FLAGS = %d\n", addrinfo->ai_flags ); // int + if( DEBUGMOD&SCK ) printf( "AI_FAMILY = %d\n", addrinfo->ai_family ); // int + if( DEBUGMOD&SCK ) printf( "AI_SOCKTYPE = %d\n", addrinfo->ai_socktype ); // int + if( DEBUGMOD&SCK ) printf( "AI_PROTOCOL = %d\n", addrinfo->ai_protocol ); // int + if( DEBUGMOD&SCK ) printf( "AI_ADDRLEN = %d\n", addrinfo->ai_addrlen ); // int + if( DEBUGMOD&SCK ) printf("\n"); /* [3] Création de la socket =======================================================*/ SOCKET = socket(addrinfo->ai_family, addrinfo->ai_socktype, 0); - if( DEBUGMOD ) printf("SOCKET = %d\n", SOCKET); + if( DEBUGMOD&SCK ) printf("SOCKET = %d\n", SOCKET); // si erreur if( SOCKET == -1 ) return; @@ -71,7 +71,7 @@ void DROP_SERVER(char* serverHost, char** givenPort, int* listenSocket){ addrinfo->ai_addrlen ); - if( DEBUGMOD ) printf("BIND = %d\n", BIND); + if( DEBUGMOD&SCK ) printf("BIND = %d\n", BIND); // si erreur if( BIND == -1 ) return; @@ -92,8 +92,8 @@ void DROP_SERVER(char* serverHost, char** givenPort, int* listenSocket){ if( getInfo == -1 ) return; - if( DEBUGMOD ) printf("Server host: %s\n", infoHost); - if( DEBUGMOD ) printf("Server port: %s\n", infoPort); + if( DEBUGMOD&SCKL ) printf("Server host: %s\n", infoHost); + if( DEBUGMOD&SCKL ) printf("Server port: %s\n", infoPort); // on a plus besoin des infos de l'adresse @@ -104,7 +104,7 @@ void DROP_SERVER(char* serverHost, char** givenPort, int* listenSocket){ =======================================================*/ LISTEN = listen(SOCKET, maxListLen); - if( DEBUGMOD ) printf("LISTEN = %d\n", LISTEN); + if( DEBUGMOD&SCK ) printf("LISTEN = %d\n", LISTEN); // si erreur if( LISTEN == -1 ) return; @@ -128,7 +128,7 @@ void DROP_SERVER(char* serverHost, char** givenPort, int* listenSocket){ // DTA: CLIENT (CLT) PROXY (CLT) FTP // void MANAGE_REQUEST(char* pRequest, int* DUSER_SOCKET, int* DFTP_SOCKET){ - if( DEBUGMOD ) printf("====== MANAGE_REQUEST(%s, %d, %d) ======\n\n", pRequest, *DUSER_SOCKET, *DFTP_SOCKET); + if( DEBUGMOD&HDR ) printf("====== MANAGE_REQUEST(%s, %d, %d) ======\n\n", pRequest, *DUSER_SOCKET, *DFTP_SOCKET); char answer[maxBuffLen]; // contiendra la réponse int nbSend; // contiendra le nombre de données envoyées @@ -166,9 +166,9 @@ void MANAGE_REQUEST(char* pRequest, int* DUSER_SOCKET, int* DFTP_SOCKET){ // on se connecte au client - printf("CONNECTING TO CLIENT %s:%s\n", serverHost, serverPort); + if( DEBUGMOD&SCK ) printf("CONNECTING TO CLIENT %s:%s\n", serverHost, serverPort); CONNECT_CLIENT(serverHost, serverPort, DUSER_SOCKET); - printf("CONNECTED TO CLIENT %s:%s\n", serverHost, serverPort); + if( DEBUGMOD&SCK ) printf("CONNECTED TO CLIENT %s:%s\n", serverHost, serverPort); // on envoie PASV car on veut être en mode passif entre le proxy et le serveur FTP strcpy(pRequest, "PASV\n"); @@ -183,7 +183,7 @@ void MANAGE_REQUEST(char* pRequest, int* DUSER_SOCKET, int* DFTP_SOCKET){ void MANAGE_RESPONSE(int* USER_SOCKET, int* FTP_SOCKET, char* pAnswer, int* DUSER_SOCKET, int* DFTP_SOCKET){ - if( DEBUGMOD ) printf("====== MANAGE_RESPONSE(%d, %s, %d, %d) ======\n\n", *USER_SOCKET, pAnswer, *DUSER_SOCKET, *DFTP_SOCKET); + if( DEBUGMOD&HDR ) printf("====== MANAGE_RESPONSE(%d, %s, %d, %d) ======\n\n", *USER_SOCKET, pAnswer, *DUSER_SOCKET, *DFTP_SOCKET); char response[maxBuffLen]; // contiendra la réponse char ftpCodeStr[4]; // contiendra le code FTP (1ère partie) @@ -256,9 +256,9 @@ void MANAGE_RESPONSE(int* USER_SOCKET, int* FTP_SOCKET, char* pAnswer, int* DUSE sprintf(serverPort, "%d", p1*256+p2); // on se connecte au serveur FTP - printf("CONNECTING TO FTP %s:%s\n", serverHost, serverPort); + if( DEBUGMOD&SCK ) printf("CONNECTING TO FTP %s:%s\n", serverHost, serverPort); CONNECT_CLIENT(serverHost, serverPort, DFTP_SOCKET); - printf("CONNECTED TO FTP %s:%s\n", serverHost, serverPort); + if( DEBUGMOD&SCK ) printf("CONNECTED TO FTP %s:%s\n", serverHost, serverPort); strcpy(response, "200 PORT command successful\n"); } @@ -270,33 +270,41 @@ void MANAGE_RESPONSE(int* USER_SOCKET, int* FTP_SOCKET, char* pAnswer, int* DUSE char BUFFER[maxBuffLen]; - // on lit la SOCKET FTP + /* 1. Envoi au client de l'écoute de la réponse (associée) du BUS DE DONNEES */ + sread(FTP_SOCKET, BUFFER); + if( DEBUGMOD&CMD ) xPrint("F->P: %s\n", BUFFER); + swrite(USER_SOCKET, "150 Connection établie!\n"); + if( DEBUGMOD&CMD ) xPrint("P->C: %s\n", "150 Connection établie!\n"); + + /* 2. On lit la SOCKET FTP (BUS DE DONNEES)*/ int nbRead = WAIT_SOCKET_UPDATE(DFTP_SOCKET, BUFFER); - if( DEBUGMOD && nbRead == -1 ) printf("ERROR\n"); - else if( DEBUGMOD ) xPrint("[BUS_IN]: %s\n", BUFFER); + if( DEBUGMOD&DAT && nbRead == -1 ) printf("ERROR\n"); + else if( DEBUGMOD&DAT ) xPrint("[BUS_IN]: %s\n", BUFFER); - // on redirige sur la SOCKET utilisateur - int nbWritten = swrite(DUSER_SOCKET, BUFFER); + /* 3. On redirige sur la SOCKET utilisateur (BUS DE DONNEES) */ + int nbSend = swrite(DUSER_SOCKET, BUFFER); - if( DEBUGMOD && nbWritten == -1 ) printf("ERROR\n"); - else if( DEBUGMOD ) xPrint("[BUS_OUT]: %s\n", BUFFER); + if( DEBUGMOD&DAT && nbSend == -1 ) printf("ERROR\n"); + else if( DEBUGMOD&DAT ) xPrint("[BUS_OUT]: %s\n", BUFFER); - xPrint("BUS_FTP->BUS_CLIENT: %s\n", BUFFER); + if( DEBUGMOD&DAT ) xPrint("BUS_FTP->BUS_CLIENT: %s\n", BUFFER); + /* 4. On ferme les SOCKETS du BUS DE DONNEES */ close(*DFTP_SOCKET); - if( DEBUGMOD ) printf("BUS_FTP fermé\n"); + if( DEBUGMOD&CMD ) printf("BUS_FTP fermé\n"); close(*DUSER_SOCKET); - if( DEBUGMOD ) printf("BUS_USER fermé\n"); + if( DEBUGMOD&CMD ) printf("BUS_USER fermé\n"); - // on vide le SOCKET FTP du BUS DE DONNEES - WAIT_SOCKET_UPDATE(FTP_SOCKET, BUFFER); - WAIT_SOCKET_UPDATE(DFTP_SOCKET, BUFFER); - swrite(USER_SOCKET, "150 Attente de la réception!\n"); - + // on vide les SOCKET FTP des 2 BUS + // WAIT_SOCKET_UPDATE(FTP_SOCKET, BUFFER); // command + // WAIT_SOCKET_UPDATE(DFTP_SOCKET, BUFFER); // données + // printf("") + + // fin de la transaction strcpy(response, "226 Données reçues!\n"); } @@ -348,6 +356,6 @@ int WAIT_SOCKET_UPDATE(int* pSocket, char* pBuffer){ -void prefixFtpResponse(char* pBuffer, char* ftpCode){ +// void prefixFtpResponse(char* pBuffer, char* ftpCode){ -} \ No newline at end of file +// } \ No newline at end of file diff --git a/dep/utility.c b/dep/utility.c index 951924d..4dcf167 100644 --- a/dep/utility.c +++ b/dep/utility.c @@ -16,7 +16,7 @@ void splitFtpRequest(char* pRequest, char* pCommand, char* pContent){ ===========================================*/ int i; - for( i = 0 ; i < strlen(pRequest) || pRequest[i] != '\0' ; i++ ){ + for( i = 0 ; i < strlen(pRequest) && pRequest[i] != '\0' ; i++ ){ if( i < firstSpaceIndex ) // première partie (pCommand) strcpy( pCommand, strcat(pCommand, (char[2]) { (char) pRequest[i], '\0' }) ); @@ -39,7 +39,7 @@ void splitFtpResponse(char* pAnswer, char* ftpCode, char* ftpText){ ===========================================*/ int i; - for( i = 0 ; i < strlen(pAnswer) || pAnswer[i] != '\0' ; i++ ){ + for( i = 0 ; i < strlen(pAnswer) && pAnswer[i] != '\0' ; i++ ){ if( i < codeLength ) // première partie (ftpCode) strcpy( ftpCode, strcat(ftpCode, (char[2]) { (char) pAnswer[i], '\0' }) ); @@ -57,7 +57,7 @@ void splitFtpResponse(char* pAnswer, char* ftpCode, char* ftpText){ int indexOf(char* haystack, char needle){ int i; - for( i = 0 ; i < strlen(haystack) || haystack[i] != '\0' ; i++ ) + for( i = 0 ; i < strlen(haystack) && haystack[i] != '\0' ; i++ ) if( haystack[i] == needle ) // si on trouve le caractère return i; @@ -66,8 +66,8 @@ int indexOf(char* haystack, char needle){ } void formatBuffer(char* pBuffer){ - if( DEBUGMOD ) printf( "BUFLEN (bef): %lu\n", strlen(pBuffer) ); - if( DEBUGMOD ) printf( "BUFFER: (%s)\n", pBuffer ); + if( DEBUGMOD&BUF ) printf( "BUFLEN (bef): %lu\n", strlen(pBuffer) ); + if( DEBUGMOD&BUF ) printf( "BUFFER: (%s)\n", pBuffer ); /* [1] On retire les "\n" et "\r" de la fin de la chaine ============================================================*/ @@ -80,7 +80,7 @@ void formatBuffer(char* pBuffer){ ============================================================*/ strcpy(pBuffer, strcat(pBuffer, "\r\n")); - if( DEBUGMOD ) printf( "BUFLEN (aft): %lu\n", strlen(pBuffer) ); + if( DEBUGMOD&BUF ) printf( "BUFLEN (aft): %lu\n", strlen(pBuffer) ); } @@ -94,18 +94,30 @@ void read_stdin(char* pBuffer, unsigned long pLength){ while( pBuffer[strlen(pBuffer)-1] == '\r' || pBuffer[strlen(pBuffer)-1] == '\n' ) pBuffer[strlen(pBuffer)-1] = '\0'; - strcpy(pBuffer, strcat(pBuffer, "\r\n")); + strcpy(pBuffer, strcat(pBuffer, "\r\n\0")); } int swrite(int* pSocket, char* pBuffer){ if( *pSocket == -1 ) return -1; // si SOCKET fermée, on retourne une erreur + if( strlen(pBuffer) == 0 ) return 0; // si on a rien à écrire, on n'écrit rien :p - // if( strlen(pBuffer) == 0 ) return 0; + if( DEBUGMOD&BUF ) printf("SENDLEN_1: %lu\n", strlen(pBuffer)); + int nbSent = write(*pSocket, pBuffer, strlen(pBuffer)); + if( DEBUGMOD&BUF ) printf("SENDLEN_2: %d\n", nbSent); - - return write(*pSocket, pBuffer, strlen(pBuffer)); + // si on est déconnecté, on ferme la SOCKET + if( nbSent <= 0 ){ + if( DEBUGMOD&BUF ) printf("NOTHING TO SEND\n"); + return -1; // on retourne une erreur + } + + if( DEBUGMOD&RVL ) printf("SEND_1\n"); + if( DEBUGMOD&RVL ) revealString(pBuffer); + if( DEBUGMOD&RVL ) printf("SEND_2\n"); + + return nbSent; } @@ -115,15 +127,20 @@ int sread(int* pSocket, char* pBuffer){ // on vide le buffer avant de lire memset(pBuffer, '\0', maxBuffLen); + if( DEBUGMOD&BUF ) printf("READLEN_1: %lu\n", strlen(pBuffer)); int nbRead = read(*pSocket, pBuffer, maxBuffLen); - + if( DEBUGMOD&BUF ) printf("READLEN_3: %d\n", nbRead); // si on est déconnecté, on ferme la SOCKET - if( nbRead == 0 ){ - // close(*pSocket); + if( nbRead <= 0 ){ + if( DEBUGMOD&BUF ) printf("NOTHING TO READ\n"); return -1; // on retourne une erreur } + if( DEBUGMOD&RVL ) printf("READ_1\n"); + if( DEBUGMOD&RVL ) revealString(pBuffer); + if( DEBUGMOD&RVL ) printf("READ_2\n"); + return nbRead; } @@ -137,11 +154,30 @@ void xPrint(char* pPattern, char* pBuffer){ int i; // on supprimes les retours à la ligne de la fin - for( i = strlen(tmpBuffer)-1 ; i >= 0 || tmpBuffer[i] != '\0' ; i-- ) + for( i = strlen(tmpBuffer)-1 ; i >= 0 && tmpBuffer[i] != '\0' ; i-- ) if( tmpBuffer[i] == '\n' || tmpBuffer[i] == '\r' ) // si c'est un retour chariot tmpBuffer[i] = '\0'; // on efface else break; printf(pPattern, pBuffer); +} + + +void revealString(char* pString){ + /* 1. On créé une copie de @pString */ + char revealedString[maxBuffLen] = {0}; + + /* 2. On rend visible tous les caractères "invisibles" */ + int i; + for( i = 0 ; i < strlen(pString) && pString[i] != '\0' ; i++ ){ + if( pString[i] == '\r' ){ revealedString[strlen(revealedString)] = '\\'; revealedString[strlen(revealedString)] = 'r'; } + else if( pString[i] == '\n' ){ revealedString[strlen(revealedString)] = '\\'; revealedString[strlen(revealedString)] = 'n'; } + else revealedString[strlen(revealedString)] = pString[i]; + + revealedString[strlen(revealedString)] = '\0'; + } + + /* 3. On affiche la chaîne explicite */ + if( DEBUGMOD&RVL ) printf("REVEALED: %s\n", revealedString); } \ No newline at end of file diff --git a/dep/utility.h b/dep/utility.h index fa2f562..f6962b5 100644 --- a/dep/utility.h +++ b/dep/utility.h @@ -51,5 +51,21 @@ int sread(int* pSocket, char* pBuffer); +/* Affiche une string en supprimant les retours à la ligne de fin de chaînes +* +* @pPattern Schéma du print (1er arg) +* @pBuffer Buffer en question +* +*/ +void xPrint(char* pPattern, char* pBuffer); -void xPrint(char* pPattern, char* pBuffer); \ No newline at end of file + +/* Révèle les caractères spéciaux d'une string +* +* @pString La string à révéler +* +* +* @print explicitString On affiche la chaîne explicité +* +*/ +void revealString(char* pString); \ No newline at end of file diff --git a/proxy_ftp.c b/proxy_ftp.c index e42a183..f280052 100644 --- a/proxy_ftp.c +++ b/proxy_ftp.c @@ -83,8 +83,8 @@ static void* testServer(char* localPort){ MANAGE_RESPONSE(&USER_SOCKET, &FTP_SOCKET, ftp_response, &DUSER_SOCKET, &DFTP_SOCKET); swrite(&USER_SOCKET, ftp_response); - xPrint("P->F: %s\n\n", BUFFER); - xPrint("F->P: %s\n", ftp_response); + if( DEBUGMOD&CMD ) xPrint("P->F: %s\n\n", BUFFER); + if( DEBUGMOD&CMD ) xPrint("F->P: %s\n", ftp_response); /* BOUCLE DE COMMANDES */ while( USER_SOCKET != -1 && FTP_SOCKET != -1 ){ @@ -92,10 +92,7 @@ static void* testServer(char* localPort){ /* [3] On récupère les données reçues (+attente) ============================================================================*/ if( WAIT_SOCKET_UPDATE(&USER_SOCKET, BUFFER) == -1 ) break; - xPrint("C->P: %s\n", BUFFER); - - if( DEBUGMOD ) printf("Recu: %d\n", nbReceived); - if( DEBUGMOD ) printf("C->P: %s\n", BUFFER); + if( DEBUGMOD&CMD ) xPrint("C->P: %s\n", BUFFER); /* [4] Traitement de la requête @@ -107,8 +104,7 @@ static void* testServer(char* localPort){ ============================================================================*/ xPrint("P->F: %s\n\n", BUFFER); CLIENT_SEND(&FTP_SOCKET, BUFFER, &ftp_response); - xPrint("F->P: %s\n", ftp_response); - + if( DEBUGMOD&CMD ) xPrint("F->P: %s\n", ftp_response); /* [6] Traitement de la réponse (FTP) ============================================================================*/ @@ -118,7 +114,7 @@ static void* testServer(char* localPort){ /* [7] Redirection vers le CLIENT ============================================================================*/ if( swrite(&USER_SOCKET, ftp_response) == -1 ) break; - printf("P->C: %s\n", ftp_response); + if( DEBUGMOD&CMD ) xPrint("P->C: %s\n", ftp_response); /* [8] On vide les buffers diff --git a/proxy_ftp.h b/proxy_ftp.h index 2cf1ab0..8da8114 100644 --- a/proxy_ftp.h +++ b/proxy_ftp.h @@ -13,14 +13,24 @@ #include // getaddrinfo, getnameinfo #include -/* basis */ -#define TRUE 1 -#define FALSE 0 - /* debug */ -#define DEBUGMOD FALSE // TRUE = débugmode activé -// #define DEBUGMOD TRUE // TRUE = débugmode activé +#define ONLY_SOCKETS 0x01 // debug RESEAU +#define ONLY_COMMAND 0x02 // debug COMMANDES +#define ONLY_DATA 0x04 // debug DONNEES +#define ONLY_REVEALS 0x08 // debug EXPLICITATION des strings +#define ONLY_BUFFERS 0x10 // debug des BUFFERS +#define ONLY_HEADERS 0x20 // debug des HEADERS de fonctions + +#define SCK 0x01 // FILTRE pour ONLY_SOCKET +#define CMD 0x02 // FILTRE pour ONLY_COMMAND +#define DAT 0x04 // FILTRE pour ONLY_DATA +#define RVL 0x08 // FILTRE pour ONLY_REVEALS +#define BUF 0x10 // FILTRE pour ONLY_BUFFERS +#define HDR 0x20 // FILTRE pour ONLY_HEADERS + +#define DEBUGMOD ONLY_SOCKETS + /* vars */ #define remoteHost "localhost" diff --git a/test b/test index 97383f1007962fc337b34bd2d5e7a115378cff13..548c9f7e6fd3d899dc154c6b705a000e8b9882b5 100755 GIT binary patch literal 22955 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 EUrjR~XaE2J delta 7776 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