/* 
 * Example of master using TCP protocol.
 * Reference: W. Richard Stevens. "UNIX Network Programming". 
 *            Prentice Hall Software Series. 1990.
 *            Chapter 6: Berkeley Sockets.
 */

#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <stdio.h>
#include <stdlib.h>
#include <strings.h>
#include <unistd.h>
#include <pthread.h>

#define HOST_ADDR_SIZE 15
#define NUM_HOSTS      2
#define REQ_SIZE       100
#define RES_SIZE       100
#define SERV_HOST1_ADDR "150.164.3.10"   /* host addr for slave 1 */
#define SERV_HOST2_ADDR "150.164.3.12"   /* host addr for slave 2 */
#define SERV_TCP_PORT  1024

struct strSchArgs{
  int sockfd;
};

/***********************************************/
/* Function: schedule */
/**********************************************/
void *schedule(void *voidargs){
  int sockfd;    
  char request[REQ_SIZE];
  char response[RES_SIZE];
  struct strSchArgs *schArgs;

  /*
   * Unpack arguments.
   */
  schArgs = (struct strSchArgs *)voidargs;
  sockfd = schArgs->sockfd;
  /* 
   * Send the request to the slave. 
   */
  strcpy(request,"teste");
  if (send(sockfd, (void *)request, REQ_SIZE, MSG_NOSIGNAL) < 0){
    fprintf(stderr,"master: can't send request\n");    
    close(sockfd);
    exit(1);
  }    
  /* 
   * Receive the response from the slave. 
   */
  if (recv(sockfd, (void *)response, RES_SIZE, MSG_WAITALL|MSG_NOSIGNAL) < 0){
    fprintf(stderr,"master: can't receive response\n");    
    close(sockfd);
    exit(1);
  }
  printf("master: response= %s \n",response);
  return(0);
}
/***********************************************/
/* Function: main */
/**********************************************/
int main(int argc, char *argv[]){    
  char addr[NUM_HOSTS][HOST_ADDR_SIZE];
  pthread_t proc[NUM_HOSTS];
  int procId;
  struct strSchArgs schArgs[NUM_HOSTS];
  struct sockaddr_in serv_addr;
  int sockfd[NUM_HOSTS];    

  /* 
   * Set host addresses.
   */
  strcpy(addr[0],SERV_HOST1_ADDR);
  strcpy(addr[1],SERV_HOST2_ADDR);
  /* 
   * Connect to slaves.
   */
  for (procId=0;procId<NUM_HOSTS;procId++){
    /*
     * Fill in the structure "serv_addr" with the address of the 
     * slave that we want to connect with.
     */  
    bzero((char *) &serv_addr, sizeof(serv_addr));
    serv_addr.sin_family = AF_INET;
    serv_addr.sin_addr.s_addr = inet_addr(addr[procId]);
    serv_addr.sin_port = htons(SERV_TCP_PORT);  
    /*
     * Open a TCP socket (an Internet stream socket).
     */  
    if ( (sockfd[procId] = socket(AF_INET, SOCK_STREAM, 0)) < 0){
      fprintf(stderr,"master: can't open stream socket\n");
    }
    /* 
     * Connect to the slave.
     */
    if (connect(sockfd[procId], (struct sockaddr *) &serv_addr, sizeof(serv_addr)) < 0){
      fprintf(stderr,"master: can't connect to slave\n");
    }
  }
  /* 
   * Create threads. 
   */
  for (procId=0;procId<NUM_HOSTS;procId++){
    /*
     * Set arguments for the function applied by the thread. 
     */
    schArgs[procId].sockfd = sockfd[procId];
      /*
       * Create the thread.
       */
      pthread_create(&proc[procId], NULL,schedule,&schArgs[procId]);
  }
  for (procId=0;procId<NUM_HOSTS;procId++){
    pthread_join(proc[procId],NULL);
  }
  for (procId=0;procId<NUM_HOSTS;procId++){
    close(sockfd[procId]);
  }
  return(0);
}
