/*server.c -- The program implements as a concurrent server. 
 It announces its availability as well as services it offers and on which 
 ip address/port to the dispatcher.Once it has finished doing so, it will 
 listen to the advertised ip address/port to service client calls. 
 After a client connects to it, the server will do the according operation
 requested by client, and return the result directly back to client.*/
 
#include "service.h"

int port;
char dispatcher[100];

char myaddr[150];
int sockfd;         
int acsd;         /*accept socket.*/ 
struct sockaddr_in my_addr;     
int myport=9003;

int main(int argc ,char **argv)
{
      char function[15];
      int func=2;     /*the server provides both sum and product function
                        0 is for "sum", 1 is for "product", 2 is for both
                        "sum" and "product".*/
      
      /*to handle the SIGINT and SIGCHLD */
      signal(SIGINT,myhandler);
      signal(SIGCHLD,myhandler);
      
      if(argc<3) 
	{
	  printf("Usage: client dest port \n");
	  exit(-1);
	}

      strcpy(dispatcher,argv[1]); /*get the ip address of dispatcher.*/
      port=atoi(argv[2]);         /*get the port number of dispatcher.*/
     
      if(func==0) strcpy(function,"sum");
      else if(func==1) strcpy(function ,"product");
      else strcpy(function ,"both");
      provide_service(function);  /*to provide the service*/
      return 0;
}
  

/*A handler to handle the SIGINT and SIGCHLD to the server. */ 
void myhandler(int signum)
{
   char info[100];
   int status;
   

   /*Before termination, sever warns the dispatcher it is no longer
  available, ask the dispatcher to delete its information from the table.*/
   if(signum==SIGINT)
     {
       close(sockfd);
       connect_remote(dispatcher,port,&sockfd,&my_addr);
       printf("Sending exit signal to the dispatcher ......");
       sprintf(info,"%s %s %s %d","server","exit",myaddr,myport);
 
      /*send message to dispatcher, including "exit",server's ip address, 
        server's port number (contained in info). */
       send(sockfd,info,strlen(info)+1,0);
       printf("Done!\n");
       close(sockfd);
       printf("Parent exited,child still working.\n");
       exit(0);
     }
    if(signum==SIGCHLD)
     {
       pid_t child_pid;//the ending child's pid
       child_pid=wait(&status);
       signal(SIGCHLD, SIG_IGN);//ignore other SIGCHLD

       if(WIFEXITED(status))
	 {
	   fprintf(stdout,"\nfork()ed child %d exited normally\n",child_pid);
	   fflush(stdout);
	 }
       else
	 {
	   fprintf(stderr,"Hmm...child did not exit normally\n");
	   fflush(stderr);
	 }
       fprintf(stdout,"Client serviced, process terminated\n\n");
       fflush(stdout); 
       signal(SIGCHLD,myhandler);
       return;
     }
}