/* 
   server.ch
   This is a server program that waits for clients to connect
   and records the connected times by clients. You need run client.ch after 
   this program is started. 

   Usage :
      server.ch [PORT_NUMBER]
*/

#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>

#define PROTOPORT 5139 /* default protocol port number */
#define QLEN 6         /* lenght of listenning queue */
 
/* Usage will be display if there is any incorrect option */
char usage[]= "\nThis is a server program that waits for clients to connect.\n\nUsage :\n      server.ch [PORT_NUMBER]\n\n      PORT_NUMBER : TCP port number will be used\n\nFor example :\n      server.ch\n      server.ch 6000\n\nThe default optional value :\n      PORT_NUMBER : 5139\n\n"; 

int main(int argc,char *argv[]) {
    struct protoent *ptrp;  /* pointer to a protocol table entry  */
    struct sockaddr_in sad; /* structure to hold server's address */
    struct sockaddr_in cad; /* structure to hold client's address */
    int    sd,sd2;          /* socket descriptors                 */
    int port;               /* ptotocol prot number               */
    int alen;               /* length of address                  */
    char buf[1000];         /* buffer for string the server sends */
    int childpid, guest_num = 0;

    memset((char *)&sad,0,sizeof(sad)); /* clear sockaddr structure */
    sad.sin_family=AF_INET;             /* set family to Internet   */ 
    sad.sin_addr.s_addr=INADDR_ANY;     /* set the local IP address */
    
    if(argc>1) {              /* if argument specified */     
        port=atoi(argv[1]);   /* convert argument to binary */
    }
    else {
        port=PROTOPORT;       /* use default port number */
    }
    if(port>0)              /* test for illegal value */
        sad.sin_port=htons((u_short)port);
    else {                   /* print erro message and exit */ 
        fprintf(stderr,"\nError : bad port number %s\n",argv[1]);
        printf("%s", usage);
        exit(1);
    }

    /* Map TCP transport protocol name to protocol number */ 
    if(((int)(ptrp=getprotobyname("tcp")))==0) {
        fprintf(stderr,"\nError : cannot map \"tcp\" to protocol number");
        printf("%s", usage);
        exit(1);
    }
    
    /* Creat a socket */
    sd=socket(PF_INET,SOCK_STREAM,ptrp->p_proto);
    if(sd<0) {
        fprintf(stderr,"\nError : socket creation failed \n");
        printf("%s", usage);
        exit(1);
    }
    
    /* Bind a local address to the socket */
    if(bind(sd,(struct sockaddr *)&sad,sizeof(sad))<0) {
        fprintf(stderr,"\nError : bind failed\n");
        printf("%s", usage);
        close(sd);
        exit(1);
    }
    
    /* Specify size of request queue */
    if(listen(sd,QLEN)<0) {
        fprintf(stderr,"listen failed \n");
        close(sd);
        exit(1);
    }
    
    /* Main server loop - accept and handle requests */
    while(1) {
        alen = sizeof(cad);
        if((sd2=accept(sd,(struct sockaddr *)&cad, &alen))<0) {
            fprintf(stderr,"accept failed \n");
            exit(1);
        }

        guest_num++; 
        if( (childpid = fork()) < 0) {
           printf("server: fork error\n");
           exit(1);
        }
        else if( childpid == 0 ) { /* Child process */
           close(sd);
           recv(sd2,buf,sizeof(buf),0);
           printf("\nData received from guest %d : %s\n", guest_num, buf);

           sprintf(buf,"From the Server to guest No. %d", guest_num);
           send(sd2,buf,strlen(buf),0);
	   printf("Connection to guest %d closed\n", guest_num);
           exit(0);
        }

        close(sd2); /* Parent process */
    }
} 
