#include "service.h"

extern int port;
extern char dispatcher[100];
extern char function[15];
extern char myaddr[150];
extern int sockfd;         
extern int acsd;         /*accept socket.*/ 
extern struct sockaddr_in my_addr;     
extern int myport;

int provide_service(char *function)
  {
      int pid;
      char buff[100];
      int status=0;
      char info[100];
      int a,b,c;
      
      char name[150];
      struct hostent *h;
      struct sockaddr_in client_addr; 
      int len=sizeof(client_addr);

      /*BEGINE TO CONNECT TO DISPATCHER */
      printf("Connecting the dispatcher ......");printf("%s %d\n",dispatcher,port);
      connect_remote(dispatcher,port,&sockfd,&my_addr);

      /*server get the ip address of itself,put it in myaddr.*/
      gethostname(name,100);
      sprintf(myaddr,"%s",name);

      /*send message to dispatcher, including its service, ip address and
        port(contained in info). */
      sprintf(info,"%s %s %s %d","server",function,myaddr,myport);
      printf("Sending my info to the dispatcher ......");
      if(send(sockfd,info,strlen(info)+1,0)<0)
      { perror("send");
        exit(-1);
      }
      printf("Done!\n");

      close(sockfd);
    
      /*BEGINE TO WAIT FOR INCOMING CONNECTION FROM CLIENT.*/
      printf("Listenning to clients ......");
      if(bind_remote(myport,&sockfd,&my_addr)!=0) exit(-1);
      printf("OK!\n");

      while(1) /*forever, until receive SIGINT. */
	{
         if ((acsd = accept(sockfd, (struct sockaddr *) &client_addr, &len)) < 0)
	    {
	      if(errno==EINTR)
		continue;
	      else
		{
		  perror("accept");
		  exit (-1);
		}
	    }
          
	 /*spawn a new process to handle client request.*/
	  pid = fork(); 

	  if (pid <0) /*error in creating a child process*/
	    {
	       perror("fork");
	       exit(-1);
	    }

	  if (pid == 0) /*this is the child.*/
	    {
              /*The child does not need to access the listening socket,
                only the parent does.*/
	      close(sockfd);
	      signal(SIGINT,SIG_IGN);
	      printf("I am %s, working now\n",myaddr);

	      printf("Receiving operands from %s at port %d......",
                     inet_ntoa(client_addr.sin_addr),ntohs(client_addr.sin_port));
	      /*  buff[0]='\0';*/
              /*receive message from client, including the service requested, and
                the operands.*/     
	      if(recv(acsd,buff,100, 0)==-1) exit(-1);
              printf("Done!\n");
	      
              /*abstract the function and operands out.*/
              sscanf(buff,"%s %d %d",function ,&a,&b);
	      /* buff[0]='\0';*/
	      printf("Computing ......");
              fflush(stdout);
	      sleep(DELAY);/*sleep 30s to emulate major computation*/

              if(strcmp(function,"sum")==0) c=a+b; /*sum operation.*/
              else c=a*b;                          /*product operation.*/
              sprintf(buff,"%d",c); /*put the result in d*/
	      printf("Done!\n");

              printf("Sending result to client %s at port %d......",
                     inet_ntoa(client_addr.sin_addr),ntohs(client_addr.sin_port));
              if(send(acsd, (void *) buff, strlen(buff) + 1, 0)==-1)
                 exit(-1);
              printf("Done!\n");

              /*As the service is finished, the socket is no longer usable by 
                this process.*/              
              close(acsd);
            
              printf("Child %d finished procesing, exiting now.\n",getpid());
              /*the child terminates */
	      exit(0);
	    }

	  if (pid > 0) /*this is the parent.*/
	      /*The parent process only listens for new connections and does not
               need the client-connection socket.*/
	       close(acsd);
	}

      close(sockfd);
      return (0);
  }