#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/time.h>

int main(int argc,char * argv[])
{
  int sock;
  struct sockaddr_in server;
  struct hostent *hp;
  char buf[1024];
  int rval;
  int k;

  /* printf("Argc:%d\n",argc);*/
  if (argc<4) { printf("ERROR: too few arguements\n");return 1;};
  sock=socket(AF_INET,SOCK_STREAM,0);
  if (sock<0)
  {
	printf("ERROR: opening stream socket\n");
	return 1;
  }


//Get the name for the remote host
  server.sin_family=AF_INET;
  hp=gethostbyname(argv[1]);
  if (hp==0)
  {
	printf("ERROR: %s:unknown host\n",argv[1]);
	return 2;
  }

  memcpy((char *)&server.sin_addr,(char *)hp->h_addr,hp->h_length);
  server.sin_port=htons(atoi(argv[2]));


//Try to connect
  if (connect(sock,(struct sockaddr *)&server,sizeof server)<0)
  {
	printf("ERROR: connecting stream socket\n");
	exit(1);
  }


//Create the message
  k=sprintf((&(buf[k])),"%s", argv[3]);
  //tmp=sprintf((&(buf[k])),"\n"); k+=tmp;

//Send the message	  
  printf("Sending %s...\n",buf);
  if (write(sock,buf,k)<0)
	 printf("ERROR: writing on stream socket\n");

//The following is to implement the timeout with receiving message(optional in the lab)

  struct timeval finishtime;
  gettimeofday(&finishtime,NULL);

  int delay = atoi(argv[4]); 


  printf("Start time: %d:%d\n",finishtime.tv_sec, finishtime.tv_usec);
  finishtime.tv_sec+=delay;
  printf("Delay:%d\n Expect time: %d:%d\n",delay,finishtime.tv_sec, finishtime.tv_usec);

  while (1)
  {    
      struct timeval tv;
      gettimeofday(&tv, NULL);
     
      printf("Now time: %d:%d\n",tv.tv_sec, tv.tv_usec);

     
      if ((finishtime.tv_sec<tv.tv_sec)||((finishtime.tv_sec==tv.tv_sec)&&(finishtime.tv_usec<tv.tv_usec)))
      {	
//time out
	printf("Time out since %d:%d < %d:%d \n", finishtime.tv_sec, finishtime.tv_usec, tv.tv_sec, tv.tv_usec);	
	close(sock);
	return 0;
      }
      else
      {
//otherwise, calculate the time left for listening (saved in "tv")
           if (tv.tv_usec>finishtime.tv_usec)
	   {
		tv.tv_usec=1000000+finishtime.tv_usec-tv.tv_usec;
		tv.tv_sec=finishtime.tv_sec-1-tv.tv_sec;
           }
	   else
	   {
		tv.tv_usec=finishtime.tv_usec-tv.tv_usec;
		tv.tv_sec=finishtime.tv_sec-tv.tv_sec;
	   };
      };

      fd_set setForSelect;
      FD_ZERO(&setForSelect);
      FD_SET(sock,&setForSelect);
      
      printf("Timeout after %d:%d\n", tv.tv_sec, tv.tv_usec);

//wait for message until timeout.
      select(sock+1,&setForSelect,NULL,NULL,&tv);
      if FD_ISSET(sock, &setForSelect)
      {
//something comes in
      	memset(buf,0,sizeof buf);
      	if ((rval=read(sock,buf,1024))<0)
	     printf("Error: reading on stream socket\n");
      	else
	if (rval==0)
	{
	     printf("Server closed the connection\n"); close(sock);return 0;
	}
	else
             printf("Received %d characters: %s\n",rval,buf);
      }
      else
      {
//nothing happens until timeout.
         printf("Time out\n");
         close(sock);
	 return 0;
      }
  }
  close(sock);
  return 0;
}

