#include<stdio.h>
#include<sys/types.h>
#include<sys/socket.h>
#include<netinet/in.h>
#include<arpa/inet.h>
#include<signal.h>
#include<sys/param.h>
#include<sys/time.h>


#define TM_GUI_PORT 60000  // in TM for GUI
#define TM_MRS_PORT 60001  // in TM for MRS
#define TM_MP_PORT 60002

#define GUI_TM_PORT 50000 // in GUI for TM
#define MRS_TM_PORT 50001 // in MRS for TM
#define MP_TM_PORT 50002

//#define TM_HOST_ADDR "139.85.243.90"

int guiSockFd, mrsSockFd, mpSockFd;

void terminateTmgr()
{
	printf("Shutting down the test manager!\n\t");
	close(guiSockFd);
	close(mrsSockFd);
	close(mpSockFd);
	exit(0);
} 
void timerHandler()
{
        printf("Send heartbeat signal to SSE\n");
}

int main()
{
int  cli_len, maxfdp1;
struct sockaddr_in guiSockAddr, mrsSockAddr, mpSockAddr, cli_addr;
char mesg[50];
fd_set allset;
fd_set rset;
struct itimerval value;

	printf("\n\tIn Test Manager main function !\n\t");

	signal(SIGINT,terminateTmgr);
	signal(SIGQUIT,terminateTmgr);
	signal(SIGHUP,terminateTmgr);
	signal(SIGALRM,timerHandler);
	printf("Signal Handler installed!\n\t");

	value.it_interval.tv_sec = 5; //reset value, actual timer value
        value.it_interval.tv_usec = 0;
        value.it_value.tv_sec = 1; // only once, first time, countdown
        value.it_value.tv_usec =0;

	/*if(setitimer(ITIMER_REAL,&value,NULL) < 0)
        {
                printf("Error in timer\n");
        }*/


	if ((guiSockFd = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
	{
		printf("Socket System Call failed!\n\t");
		exit(1);
	}

	bzero((char *) &guiSockAddr, sizeof(guiSockAddr));
	guiSockAddr.sin_family = AF_INET;
	guiSockAddr.sin_addr.s_addr = htonl(INADDR_ANY);
	guiSockAddr.sin_port = htons(TM_GUI_PORT);
	
	if (bind(guiSockFd, (struct sockaddr *) &guiSockAddr, sizeof(guiSockAddr)) < 0)	{
		printf("Error in bind!\n\t");
		exit(1);
	}

	if ((mrsSockFd = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
	{
		printf("Socket System Call failed!\n\t");
		exit(1);
	}

	bzero((char *) &mrsSockAddr, sizeof(mrsSockAddr));
	mrsSockAddr.sin_family = AF_INET;
	mrsSockAddr.sin_addr.s_addr = htonl(INADDR_ANY);
	mrsSockAddr.sin_port = htons(TM_MRS_PORT);

	if (bind(mrsSockFd, (struct sockaddr *) &mrsSockAddr, sizeof(mrsSockAddr)) < 0)	{
		printf("Error in bind!\n\t");
		exit(1);
	}
	
	if ((mpSockFd = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
	{
		printf("Socket System Call failed!\n\t");
		exit(1);
	}

	bzero((char *) &mpSockAddr, sizeof(mpSockAddr));
	mpSockAddr.sin_family = AF_INET;
	mpSockAddr.sin_addr.s_addr = htonl(INADDR_ANY);
	mpSockAddr.sin_port = htons(TM_MP_PORT);


	if (bind(mpSockFd, (struct sockaddr *) &mpSockAddr, sizeof(mpSockAddr)) < 0)	{
		printf("Error in bind!\n\t");
		exit(1);
	}
	FD_ZERO(&allset);
	FD_SET(guiSockFd, &allset);
	FD_SET(mrsSockFd, &allset);
	FD_SET(mpSockFd, &allset);
	//printf("%d %d %d\n",guiSockFd,mrsSockFd,mpSockFd);
	
	maxfdp1 = mpSockFd + 1;

			bzero((char *) &cli_addr, sizeof(cli_addr));
  	        	cli_addr.sin_family = AF_INET;
        		cli_addr.sin_addr.s_addr = htonl(INADDR_ANY);
        		cli_addr.sin_port = htons(MRS_TM_PORT);
			if(sendto(mrsSockFd, &mesg, sizeof(mesg), 0, &cli_addr, sizeof(cli_addr)) < 0)
			{
				printf("Error in send to MRS\n");
				perror("Error");
			}
			else
			{
				printf("Message sent to MRS!\n\t");
			}

/* Remove the following comment for probelm no. 2 ! */

/*
			if(sendto(mrsSockFd, &mesg, sizeof(mesg), 0, &cli_addr, sizeof(cli_addr)) < 0)
			{
				printf("Error in send to MRS\n");
				perror("Error");
			}
			else
			{
				printf("Message sent to MRS!\n\t"); 
			} */
	
	while(1)
	{
		printf("Waiting on select system call....\n\t");	
		rset = allset;
		if(select(maxfdp1, &rset, NULL, NULL, 0) < 0)
		{
			//printf("Error in select system call !\n\t");
			/* Whenever the timer expires and SIGALRM signal is received , there is an error in the select system call */

			continue; 
			/* since  u are getting an error in select, it is entering gui portion and waiting on recvfrom , hence the "continue" workaround*/
		} 
		if(FD_ISSET(guiSockFd, &rset))
		{
			printf("Data received from GUI!\n\t");
			cli_len = sizeof(cli_addr);
			if(recvfrom(guiSockFd, &mesg, sizeof(mesg), 0, &cli_addr, &cli_len) < 0)
			{
				printf("Error in receive!\n\t");
			}
			printf("Servicing a GUI request!\n\t");
			printf("Message received = %s\n\t",mesg);

			bzero((char *) &cli_addr, sizeof(cli_addr));
  	        	cli_addr.sin_family = AF_INET;
        		cli_addr.sin_addr.s_addr = htonl(INADDR_ANY);
        		cli_addr.sin_port = htons(MRS_TM_PORT);


			if(sendto(mrsSockFd, &mesg, sizeof(mesg), 0, &cli_addr, sizeof(cli_addr)) < 0)
			{
				printf("Error in send to GUI\n");
			}
			printf("Message sent to MRS!\n\t");

	 
		}
		if(FD_ISSET(mrsSockFd, &rset))
		{
		printf("Data received from MRS!\n\t");
		cli_len = sizeof(cli_addr);
		if(recvfrom(mrsSockFd, &mesg, sizeof(mesg), 0, &cli_addr, &cli_len) < 0)
		{
			printf("Error in receive!\n\t");
		}
		printf("Servicing a MRS request!\n\t");
		printf("Message received = %s\n\t",mesg); 
		}

		if(FD_ISSET(mpSockFd, &rset))
		{
		printf("Data received from MP!\n\t");
		cli_len = sizeof(cli_addr);
		if(recvfrom(mpSockFd, &mesg, sizeof(mesg), 0, &cli_addr, &cli_len) < 0)
		{
			printf("Error in receive!\n\t");
		}
		printf("Servicing a MP request!\n\t");
		printf("Message received = %s\n\t",mesg);
		}	
	}	
	return 0;		 
} 
	 
