#include "central-manager.h" /* * * @history * [0] Initialisation des variables * [1] On démarre le SERVEUR d'écoute globale * [2] Attente d'une demande de connection, puis création d'un THREAD * [3] On attends la fin de tous les THREADS * [4] On ferme la SOCKET d'écoute globale * */ int main(int argc, char* argv[]){ /* [0] Initialisation des variables ==========================================================*/ int THREADABLE_SOCKET = -1; // contiendra le BUS DE COMMANDE utilisateur à envoyer à un THREAD struct sockaddr_storage clientInfo; // contiendra les infos client char repeat; // sert à sortir de la boucle socklen_t len = sizeof(struct sockaddr_storage); // retour de @DROP_SERVER char* serverPort; // contiendra le port int LISTENSOCK; // contiendra la socket d'écoute /* [1] On démarre le SERVEUR d'écoute globale ==========================================================*/ serverPort = malloc(maxPortLen); // attribution du port si dans les arguments if( argc > 1 ) strcpy(serverPort, argv[1]); DROP_SERVER(remoteHost, &serverPort, &LISTENSOCK); printf("Port: %s\n", serverPort); /* [2] Attente d'une demande de connection, puis création d'un THREAD ============================================================================*/ int index = -1; while( 1 ){ /* 1. On initialise la SOCKET en attendant la connexion et le rang du "manager" inactif */ THREADABLE_SOCKET = -1; index = -1; /* 2. On attends une connection */ THREADABLE_SOCKET = accept(LISTENSOCK, (struct sockaddr *) &clientInfo, &len); /* 3. On cherche un "manager" libre */ int i; // si on trouve un "manager" inactif, on l'enregistre dans index for( i = 0 ; i < maxListLen ; i++ ) if( activeManagers[i] == 0 ){ index = i; break; } // si on a trouvé un "manager" libre if( index != -1 ){ /* 4. On lance un thread pour le traitement de ce client */ pthread_create(&managers[index], NULL, manageConnection, (void*)(intptr_t) THREADABLE_SOCKET); if( DEBUGMOD&THR ) printf("THREAD[%d] démarré\n", index); /* 5. On signale que ce "manager" est maintenant actif */ activeManagers[index] = 1; }else if( DEBUGMOD&THR ) printf("Demande de thread refusée!\n"); } /* [3] On attends la fin de tous les THREADS ==========================================================*/ int i; for( i = 0 ; i < maxListLen ; i++ ) pthread_join(managers[i], NULL); /* [4] On ferme la SOCKET d'écoute globale ==========================================================*/ printf("FERMETURE DE TOUTES LES CONNECTIONS!\n"); close(LISTENSOCK); } /* Gestion d'une connexion client * * @THREADABLE_SOCKET SOCKET de la connexion client * * @history * [1] Initialisation des variables * [2] Envoi de la séquence de bienvenue * [3] Attente des données reçues et reception (CLIENT_FTP->PROXY) * [4] Traitement de la requête client * [5] Redirection de la requête vers le serveur FTP (PROXY->SERVER_FTP) * [6] Traitement de la reponse du serveur FTP * [7] Redirection de la réponse vers le client (PROXY->CLIENT_FTP) * [8] On vide les buffers * [9] Fermeture des connections (SOCKETS) * [10] Arrêt du THREAD * 1. On récupère le rang dans les "managers" * 2. On met à jour "activeManagers" * 3. On arrête le THREAD * */ void* manageConnection(void* THREADABLE_SOCKET){ int USER_SOCKET = (intptr_t) THREADABLE_SOCKET; // BUS DE COMMANDE utilisateur /* [1] Variables ============================================================================*/ // int USER_SOCKET = -1; int FTP_SOCKET = -1; // contiendra le BUS DE COMMANDE FTP int DUSER_SOCKET = -1; // contiendra le BUS DE DONNES utilisateur int DFTP_SOCKET = -1; // contiendra le BUS DE DONNEES FTP char* BUFFER; // contiendra le BUFFER char* ftp_response; // contiendra le BUFFER de réponse du serveur FTP (commandes) int nbReceived, nbSend; // contiendra les nb reçu && envoyé BUFFER = malloc( maxBuffLen ); int error; /* [2] Envoi de la séquence de bienvenue ============================================================================*/ swrite(&USER_SOCKET, WLCM_MSG); /* BOUCLE DE COMMANDES */ while( USER_SOCKET != -1 ){ /* [3] On récupère les données reçues (+attente) ============================================================================*/ if( WAIT_SOCKET_UPDATE(&USER_SOCKET, BUFFER) == -1 ) break; if( DEBUGMOD&CMD ) xPrint("C->P: %s\n", BUFFER); /* [4] Traitement de la requête ============================================================================*/ error = MANAGE_REQUEST(BUFFER, &USER_SOCKET, &FTP_SOCKET, &DUSER_SOCKET, &DFTP_SOCKET); // si on a pas la connection FTP (commande) initialisée, on quitte if( error == -1 ) break; /* [5] Redirection vers le serveur FTP ============================================================================*/ if( DEBUGMOD&CMD ) xPrint("P->F: %s\n\n", BUFFER); CLIENT_SEND(&FTP_SOCKET, BUFFER, &BUFFER); if( DEBUGMOD&CMD ) xPrint("F->P: %s\n", BUFFER); /* [6] Traitement de la réponse (FTP) ============================================================================*/ MANAGE_RESPONSE(BUFFER, &USER_SOCKET, &FTP_SOCKET, &DUSER_SOCKET, &DFTP_SOCKET); /* [7] Redirection vers le CLIENT ============================================================================*/ if( swrite(&USER_SOCKET, BUFFER) == -1 ) break; if( DEBUGMOD&CMD ) xPrint("P->C: %s\n", BUFFER); /* [8] On vide les buffers ============================================================================*/ memset(BUFFER, '\0', maxBuffLen); // on vide le buffer memset(BUFFER, '\0', maxBuffLen); } /* [9] Fermeture des connections (SOCKETS) ============================================================================*/ printf("CLOSING CONNECTIONS\n"); close(USER_SOCKET); close(FTP_SOCKET); /* [10] Arrêt du THREAD ============================================================================*/ /* 1. On récupère le rang dans les "managers" */ int i, index = -1; for( i = 0 ; i < maxListLen ; i++ ) if( managers[i] == pthread_self() ){ index = i; break; } /* 2. On met à jour "activeManagers" */ if( index != -1 ) activeManagers[index] = 0; /* 3. On arrête le THREAD */ if( DEBUGMOD&THR ) printf("THREAD[%d] libéré\n", index); pthread_exit(NULL); }