#include<sys/types.h>
#include<sys/time.h>
#include<math.h>
#include "inet.h"
#define EPORT 3001
int max(int a,int b)
{
  if(a>b) return b;
  return a;
}
void main()
{
  struct timeval tv;
  int tcp_sfd,newsockfd,childpid,clilen;
  struct sockaddr_in servaddr,cliaddr;


  
  if((tcp_sfd=socket(AF_INET,SOCK_STREAM,0))<0)
  
   perror("socket error");
  
  bzero((char*)&servaddr,sizeof(servaddr));
  servaddr.sin_family=AF_INET;
  servaddr.sin_addr.s_addr=htonl(INADDR_ANY);
  servaddr.sin_port=htons(EPORT);


  
  if(bind(tcp_sfd,(struct sockaddr*)&servaddr,sizeof(servaddr))<0)
    perror("can't bind");


  




  int udp_sfd;
  struct sockaddr_in cli_addr,ser_addr;
 

 bzero((char*)&ser_addr,sizeof(ser_addr));
  ser_addr.sin_family = AF_INET;
  ser_addr.sin_addr.s_addr = htonl(INADDR_ANY);
  ser_addr.sin_port = htons(EPORT);

  if( (udp_sfd = socket(AF_INET,SOCK_DGRAM,0))<0)
    perror("socket fails");
  


  if(bind(udp_sfd,(struct sockaddr*)&servaddr,sizeof(servaddr))<0)
    perror("can't bind");


  listen(tcp_sfd,5);
  const int MAXLEN = 2048;
  char rec_buf[MAXLEN+1];
  for(;;)
  {
    fd_set fdvar;
    FD_ZERO(&fdvar);
    FD_SET(tcp_sfd,&fdvar);
    FD_SET(udp_sfd,&fdvar);
    int maxpl = max(tcp_sfd,udp_sfd);
    //cout << "select " << flush;
    cout << "Waiting for a client...\n";
    
    if(select(maxpl+2 ,&fdvar,NULL,NULL,NULL)==-1)
    {
      perror("error in select");
    }
  

  //cout << "hi" <<cout.flush();
    if(FD_ISSET(udp_sfd,&fdvar))
    {
      // UDP
      //cout<<"UDP"<<flush;
      unsigned clilen=MAXLEN;
      int n = recvfrom(udp_sfd,rec_buf,MAXLEN,0,(struct sockaddr*) &cli_addr, &clilen);
      if(n<0) perror("Err rec");
      rec_buf[n]=0;
      
      cout<< "UDP : Received from " <<  inet_ntoa(cliaddr.sin_addr) << " : " << rec_buf<<endl << flush;


      if(sendto(udp_sfd,rec_buf,MAXLEN,0,(struct sockaddr * )&cli_addr,sizeof(cli_addr))==-1)
	perror("send err");
      //close(udp_sfd);
    
  }
  else
  {
      //TCP
    
    //cout<<"TCP"<<flush;
      clilen=sizeof(cliaddr);
      newsockfd=accept(tcp_sfd,(struct sockaddr*)&cliaddr,&clilen);

      if(newsockfd<0)
	perror("accept error");

      if((childpid=fork())<0)
	perror(" fork error");
      else if(childpid==0)
      {
	char buf[2048];
	close(tcp_sfd);
	while(1)
	{
	  int n=recv(newsockfd,buf,MAXLEN,0);
	  if(n==0)
	  {
	    break;
	  }
	  else if(n<0)
	  {
	    perror("recv error");
	    break;
	  }
	  buf[n]=0;
	  cout<< "TCP : Received from " <<  inet_ntoa(cliaddr.sin_addr) << " : " << buf<<endl << flush;
	
	
	  if(send(newsockfd,buf,n,0)==-1)
	  {
	    perror("Send error");
	    break;
	  }
	}
	exit(0); 
      }
      close(newsockfd);
    }
  }
}












