/**
 * Group : Edison Chindrawaly
 *         Sehoon Jung
 *         Sangtae Park
 *
 * Project: #2 Game Server
 */
#include "game_server.h"

struct test
{
 int pid;
 char name[MAXSIZE];
} TEST;

void main()
{
 
 int listenfd;
 listenfd = openConnection(7778);
 beginProcess(listenfd);
 closeConnection(listenfd);

}


/**
 * openConnection's method is to establish connection
 * between the client and host.
 * @param  int PORT contains predefine port number
 * @return sockfd if flag == 1 else connfd is return
 */
int openConnection(int PORT)
{
 int servsize;
 int yes = 1;
 int sockfd,connfd,clientsize;
 struct sockaddr_in my_add;
 struct sockaddr_in other_add;

 sockfd = socket(AF_INET, SOCK_STREAM,IPPROTO_TCP);
 verify(0,sockfd,socket_flag);

 bzero(&(my_add.sin_zero),sizeof(my_add));
 my_add.sin_family = AF_INET;
 my_add.sin_port = htons(PORT);
 my_add.sin_addr.s_addr = INADDR_ANY;
 
 verify(sockfd,       
 bind(sockfd,(struct sockaddr *)&my_add, sizeof(struct sockaddr)),
 bind_flag);

 verify(sockfd,listen(sockfd,BACKLOG),listen_flag);
 
 return sockfd;
}


/**
 * beginProcess's method is where the process is being
 * execute - send/receive messages. It receives a listen socket
 * descriptors. It accepts more than 2 connections from 2 or
 * more clients. Right now I specify the max number of client
 * to be 5 clients.
 * @param  int sockfd1 contains TCP socket descriptor
 * @return none
 */
void beginProcess(int sockfd)
{

 int fd[2];
 int flag = 0;
 int win = 0;   // contains the flag for winner
 int random[3]; // contains generated random number

 int pid_temp, pid_child;
 char temp[MAXSIZE];

 printf("Generate number: ");
 for(int i=0; i<3; i++)
 {
   random[i] = generateNumber((rand()+i)%10);
   printf("%i ", random[i]);
 }
 printf("\n");

 //for networking purposes
 int new_sock = 0;
 int byteRecv = 0;
 int byteSend = 0;

 struct sockaddr_in other_add;
 int clisize = sizeof(other_add);

 //prepare the set for select()
 fd_set master;
 fd_set read_fds;

 //clean the select() set
 FD_ZERO(&master);
 FD_ZERO(&read_fds);
 
 //add sockfd to master set for listening
 FD_SET(sockfd, &master);
 FD_SET(STDIN, &master);
 FD_SET(fd[READ],&master);

 //initialize struct
 MESSAGE msg;
 STORAGE *store;

 //messages
 char* greet_msg = "You are connected to game server";
 char* win_msg = "One of the players have guess the number. Game is over";
 char* ply_msg = "You have win the game! Congratulation";
 
 printf("Press any key to terminate\n");
 while(true)
 {
  read_fds = master;
  verify(sockfd,
         select(FD_SETSIZE,&read_fds,NULL,NULL,NULL),
         select_flag);

  if(FD_ISSET(STDIN,&read_fds))
  {
   printf("game_server terminates\n");
   break;
  } // end for detecting keyboard
 
  if(FD_ISSET(sockfd,&read_fds))
  {
   new_sock = accept(sockfd,
                    (struct sockaddr *)&other_add,
                    (socklen_t *)&clisize);
   printf("Receive connection from %s\n",
          inet_ntoa(other_add.sin_addr));
   verify(new_sock, pipe(fd), pipe_flag);

   //child process
   if(fork() == 0)
   {
    close(sockfd);
    pid_child = getpid();
    flag = 1;
    msg.flag = 1;
    strcpy(msg.message,greet_msg);
    verify(new_sock,sendStruct(new_sock,msg),send_flag);
    verify(new_sock,receivedStruct(new_sock,msg),receive_flag);
    printf("user name: %s\n",msg.name);
    verify(new_sock,
           write(fd[WRITE],&flag,sizeof(flag)),
           write_flag);
    verify(new_sock,
           write(fd[WRITE],&pid_child,sizeof(int)),
           write_flag);
    verify(new_sock,
           write(fd[WRITE],&(msg.message),sizeof(msg.message)),
           write_flag);
    //FD_SET(new_sock,&read_fds);
    printf("successfully set new_sock\n");
    while(true)
    {
     printf("before select\n");
     //verify(new_sock,
     //select(FD_SETSIZE,&read_fds,NULL,NULL,NULL),
     //select_flag);
     if(FD_ISSET(new_sock,&read_fds)) //receive from client
     {
      printf("receive something from client\n");
      byteRecv = receivedStruct(new_sock,msg);  
      verify(new_sock,byteRecv,receive_flag);
      switch(msg.flag)
      {
       case 0: win = checkGuess(random,msg);
               if(win == 1)
               {
                (*store).win = 1;
                verify(0,write(fd[WRITE],(char *)&store,sizeof(store)),
                       write_flag);
                strcpy(msg.message,win_msg);
                msg.flag = 1;
                byteSend = sendStruct(new_sock,msg);
               }
               else
               {
                msg.flag = 0;
                byteSend = sendStruct (new_sock,msg);
               }
               verify(new_sock,byteSend,send_flag);
               break;
       case 1: if(strcasecmp(msg.message,"END") ==0)
               {
                (*store).end = 1;
                verify(0,write(fd[WRITE],(char *)&store,sizeof(store)),
                       write_flag);
                break;
               }
               printf("client send: %s\n",msg.message);
               break;
       case 2: verify(0,write(fd[WRITE],(char *)&msg,sizeof(msg)),
                      write_flag); 
      }
     }
     if(FD_ISSET(fd[READ],&read_fds)) //receive from parent
     {
      printf("receive something from parent\n");
      verify(0,read(fd[READ],(char *)&msg,sizeof(msg)),read_flag);
      printf("receive : %s\n",msg.message);
     }
     printf("do not get it\n");
    }
    close(new_sock);
    exit(0);
   } // end of child

   close(new_sock);

   //parent
   if(FD_ISSET(fd[READ],&read_fds))
   {
    verify(sockfd,read(fd[READ],&flag,sizeof(flag)),read_flag);
    if(flag == 1)
    {
     verify(sockfd,read(fd[READ],&pid_temp,sizeof(int)),read_flag);
     verify(sockfd,read(fd[READ],&temp,sizeof(temp)),read_flag);
     (*store).pid = pid_temp;
     strcpy((*store).player_name,temp);
     printf("receive from child %i\n",pid_temp);
     *store++;
    }
   } // end for parent
  } // end for detecting a new request for socket

 } // end of while loop
} // end of beginProcess


/**
 * checkGuess' method is to check the guess of the player with
 * the assign random number generated by the system. It also
 * written to the result of the user guess into the MESSAGE struct
 * which is going to be return to user.
 * @param  int[] array contains the generated number by the system
 *         MESSAGE& msg contains the user guess
 * @return int 1 if guess is all correct else return 0
 */
int checkGuess(int array[], MESSAGE& msg)
{
 for(int i=0; i<3; i++)
   for(int j=0; j<3; j++)
     if(array[i] == msg.guess[j])
       if(i == j)  // check the position
         msg.result[i] = strike;
       else
         msg.result[i] = ball;

 if(msg.result[1] == strike)
   if(msg.result[2] == strike)
     if(msg.result[3] == strike)
        return 1; // all the guesses is correct

 return 0;    
}

/**
 * verify's method is to verify the success of the operation.
 * if the operation fails, it will terminate the whole program.
 * @param  int sockfd contains socket descriptor if available
 *         int byte contains the byte receives from the operation
 *         int flag contains the description of the flag
 * @return none
 */
void verify(int sockfd, int byte, int flag)
{
 switch(flag)
 {
  case 0:if(byte<0)
         {
           perror("ERROR: socket has failed\n");
           exit(0);
         }
         break;
  case 1:if(byte<0)
         {
           perror("ERROR: bind has failed\n");
           closeConnection(sockfd);
           exit(0);
         }
         break;
  case 2:if(byte<0)
         {
           perror("ERROR: listen has failed\n");
           closeConnection(sockfd);
           exit(0);
         }
         break;
  case 3:if(byte<0)
         {
           perror("ERROR: accept has failed\n");
           closeConnection(sockfd);
           exit(0);
         }
         break;
  case 4:if(byte<0)
         {
           perror("ERROR: send has failed\n");
           closeConnection(sockfd);
           exit(0);
         }
         break;
  case 5:if(byte<0)
         {
           perror("ERROR: receive has failed\n");
           closeConnection(sockfd);
           exit(0);
         }
         break;
  case 6:if(byte<0)
         {
           perror("ERROR: pipe has failed\n");
           exit(0);
         }
         break;
  case 7:if(byte<0)
         {
           perror("ERROR: write has failed\n");
           exit(0);
         }
         break;
  case 8:if(byte<0)
         {
           perror("ERROR: read has failed\n");
           exit(0);
         }
         break;
  case 9:if(byte<0)
         {
           perror("ERROR: select has failed\n");
           exit(0);
         }
  default: break;
 }
}

/**
 * generateNumber's method is to generate random number
 * @param  int number contains the number given by program
 * @return int random number 1 digit long
 */
int generateNumber(int num)
{
  time_t timer;
  srand((unsigned)time(&timer));
  return ((rand() * (num+1)) % 10);
}

/**
 * receivedStruct's method is to receive struct from
 * the given socket. It will return -1 if it fails
 * to receive otherwise it will return int bigger than
 * zero.
 * @param  int sockfd contains sock descriptor
 *         struct MSG contains the struct itself
 * @return int
 */
int receivedStruct(int sockfd, MESSAGE& receivedMsg)
{
  int byteRecv = 0;
  byteRecv = recv(sockfd,(char *)&receivedMsg,sizeof(MESSAGE),0);
  return byteRecv;
}

/**
 * sendStruct's method is to send MESSAGE struct to the client/
 * server that is address by the socket descriptor
 * @param  int sockfd contains socket descriptor
 *         MESSAGE msg contains the message struct
 * @return -1 if fail otherwiser return number of bytes send
 */
int sendStruct(int sockfd, MESSAGE msg)
{
 int numSend = 0;
 numSend = send(sockfd,(char *)&msg, sizeof(MESSAGE),0);
 return numSend;
}


/**
 * closeConnection's method is to close the socket
 * descriptor that contains the connection of
 * the client/server's model
 * @param  int sockfd contains socket descriptor
 * @return none
 */
void closeConnection(int sockfd)
{
 close(sockfd);
}

 

1