#include <stdio.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <netinet/in.h>

#define MAXCONNECTIONS 5 /* Nombre maximal de connections */
#define BUFFER_SIZE 32  

/* pour mourrir */
void Meurt(char *msg) { 
    perror(msg); 
    exit(1);
}

/* La discution avec un client. 
La socket doit être connectée
*/
void HandleClient(int sock) {
    char buffer[BUFFER_SIZE];
    int received = -1;
    int i;
    /* réception du message */
    if ((received =recv(sock, buffer, BUFFER_SIZE, 0)) < 0) {
        Meurt("Impossible de recevoir les premiers octets du client !");
    }
    /* envoie les données reçues et vérifie qu'il n'y a plus
    rien à recevoir dans une boucle */
    while (received > 0) {
        /* Envoie des données reçues */
        printf("Reception de : ");
        for (i=0 ; (i<received) && (buffer[i] != '\0') ; i++) {
            printf("%c", buffer[i]);
        }
        printf("\n");
        if (send(sock, buffer, received, 0) != received) {
            Meurt("Impossible d'envoyer les données au client !");
        }
        /* Vérifie qu'il y a d'autres données à recevoir */
        if ((received = recv(sock, buffer, BUFFER_SIZE, 0)) < 0) {
            Meurt("Impossible de recevoir les données additionnelles du client");
        }
    }
    /* Fermeture de la socket */
    printf("Fermeture de la connection client\n");
    close(sock);
}

int main(int argc, char *argv[]) {
    int serversock, clientsock;
    struct sockaddr_in echoserver, echoclient;

    if (argc != 2) {
        fprintf(stderr, "usage: %s <port>\n", argv[0]);
        exit(1);
    }
    /* Création de la socket TCP */
    if ((serversock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0) {
        Meurt("Impossible de créer ma chaussette !");
    }
    /* Construction de la structure sockaddr_in */
    memset(&echoserver, 0, sizeof(echoserver));     /* effacement de la structure */
    echoserver.sin_family = AF_INET;                /* Internet/IP */
    echoserver.sin_addr.s_addr = htonl(INADDR_ANY); /* Adresse entrante */
    echoserver.sin_port = htons(atoi(argv[1]));     /* port du serveur */
    
    /* Liaison de la socket du serveur */
    if (bind(serversock, (struct sockaddr *) &echoserver,
                sizeof(echoserver)) < 0) {
        Meurt("Impossible de lier la socket du serveur");
    }
    /* on écoute à traver la socket du serveur */
    if (listen(serversock, MAXCONNECTIONS) < 0) {
        Meurt("Impossible d'écouter sur la socket du serveur");
    }
    /* Tourne jusqu'à être tué */
    while (1) {
        unsigned int clientlen = sizeof(echoclient);
        /* On attend qu'un client se connecte */ 
        if ((clientsock= accept(serversock, (struct sockaddr *) &echoclient, &clientlen)) < 0) {
            Meurt("Impossible d'accepter la connection du client !");
        }
        fprintf(stdout, "Client connecté: %s\n", inet_ntoa(echoclient.sin_addr));
        HandleClient(clientsock);
    }
}

