#include <stdio>
#include <string>
#include <stdlib>
#include <arpa>
#include <time>

#if SYSTEM == UNIX
    #include <sys>
    #include <sys>
    #include <netinet>
#else
    #include <winsock>
    #define close closesocket
#endif

#define MAXCONN 5
#define PORT    3666

void
addr_init (struct sockaddr_in *addr, int port, long ip)
{
    addr->sin_family = AF_INET;
    addr->sin_port = htons ((u_short)port);
    addr->sin_addr.s_addr = ip;
}

int
main (int argc, char **argv)
{
    char *msg;
    struct sockaddr_in  server_addr, client_addr;
    int client_len = sizeof(client_addr);
    int sd, new_sd, i, j, N, size;
    time_t ltime = (unsigned) time(NULL);

    #ifdef WIN
        WSADATA wsaData;
        int iResult = WSAStartup (MAKEWORD(2,2), &wsaData);
        
        if (iResult != NO_ERROR) {
            printf ("ERROR occurred in WSAStartup()\n");
            exit (1);
        }
    #endif

    addr_init(&server_addr, PORT, INADDR_ANY);
    
    if ((sd = socket (AF_INET, SOCK_STREAM, 0))==-1) {
        printf ("ERROR during socket creation!\n");
    
        #ifdef WIN
            WSACleanup();
            system ("pause");
            exit (1);
        #endif
        
        exit(1);
    }
    
    if (bind (sd, (struct sockaddr*)&server_addr, sizeof(server_addr)) == -1) {
        printf ("ERROR while binding!\n");
        exit (2);
    }
    
    if (listen(sd, MAXCONN) == -1)  {
        printf ("ERROR: connectons could not be accempted.\n");
        exit (3);
    }
    
    while (1) {
        printf ("\nServer is waiting...\n");
        
        if ((new_sd = accept(sd, (struct sockaddr*)&client_addr, &client_len)) == -1) {
            printf ("ERROR: could not accept connections from %s\n", inet_ntoa (client_addr.sin_addr));
            exit (4);
        }
    
    if (recv (new_sd, (int*)&N, sizeof(int), 0) < 0) {
        exit (5);
    }

    ltime = (unsigned)time(NULL);
    printf ("%s - Message from %s: ", ctime (&ltime), inet_ntoa (client_addr.sin_addr));
    
    for (i=0; i<N; i++) {
        if (recv (new_sd, (int*)&size, sizeof(int), 0) < 0) {
            exit (5);
        }
    
        msg = (char*)malloc(size*sizeof(char));
    
        if (recv (new_sd, (char*)msg, size, 0) < 0) {
            exit (5);
        }
    
        for (j=0; j<size; j++) {
            printf ("%c", msg[j]);
            printf (" ");
        }
    }
    
    close (new_sd);
    close (sd);
}
