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

#define MAXBUFFER (256*1024)

#define fmtSOCK signed short int

// #define PROGRESS

/* ***************************************************************** */

int conn2server (char *hostname, int port, int *sockfd)
{
    struct hostent *he;
    struct sockaddr_in their_addr;

    if ((he=gethostbyname(hostname)) == NULL) /* get the host info */
       { perror("gethostbyname"); return 1; };

    if ((*sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1) /* open socket */
       { perror("socket"); return 1; };

    bzero(&their_addr,sizeof(their_addr));
    their_addr.sin_family = AF_INET;       /* IPv4 */
    their_addr.sin_port = htons(port);     /* port (netw byte order, short) */
    their_addr.sin_addr = *((struct in_addr *)he->h_addr);

    if (connect(*sockfd, (struct sockaddr *)&their_addr, 
                sizeof(struct sockaddr)) == -1) /* connect to target */
       { perror("connect"); return 1; };
    
    return 0;
};

/* ***************************************************************** */

int main(int argc, char *argv[])
{
  int sockfd, numbytes, putbytes;  
  static fmtSOCK buf[MAXBUFFER];
  char message[100];
    
  if (argc != 4)
     { fprintf(stderr,"Usage: %s hostname port GET<n>|CLOSE\n"
                      "GET writes received Data to standard output!\n",
               argv[0]); return 1; };
  
  /* try to connect to server */
  if (conn2server (argv[1],atoi (argv[2]), &sockfd)) 
     { fprintf(stderr,"Could not connect server\n"); return 1; };
    
  numbytes=recv(sockfd, message, 10, 0); 
  message[(numbytes>0) ? numbytes : 0] = '\0';
  if (strcmp (message,"Hello!")) 
     { fprintf (stderr,"Protocol not recognized\n"); return 1; };
     
  fprintf (stderr,"C - Received %s, now sending %s\n",message,argv[3]);
    
  /* send command to server */
  if (send (sockfd,argv[3],strlen (argv[3])+1, 0)<0)
     { perror("send"); return 1; };
     
  /* if command is GET<n>, then loop, else return */
  if (strncmp (argv[3],"GET",3)) 
     { /* if (!strncmp(argv[3],"CLOSE",5)) return 0; */
       numbytes=recv(sockfd, message, 99, 0);
       if (numbytes<0) { perror("recv"); return 1; };
       message[(numbytes>0) ? numbytes : 0] = '\0';
       fprintf (stderr,"Response was: %s\n",message);     
       return 0;
     };
     
  while (1) 
  {
    /* receive buffer */
    numbytes=recv(sockfd, buf, sizeof(buf), 0);
        
    if (numbytes > 0) 
       { if (send (sockfd,"OK",strlen ("OK")+1, 0)<0)
            { perror("send"); return 1; };
       } else if (numbytes < 0) 
       { perror("recv"); return 1; };

    if (numbytes > 0) 
       { 
         if (!strncmp((char *)buf,"FAIL",4)) 
            { (void)strncpy(message,(char *)buf,sizeof(message));
              if (message[sizeof(message)-1])
                   fprintf(stderr,"Protocol failure: [Msg too long]\n");
              else fprintf(stderr,"Protocol failure: %s\n",message); 
            };

         putbytes = write(1,buf,numbytes);
         if (putbytes != numbytes) { perror("write error"); return 1; };
       };

    usleep(1000);
#ifdef PROGRESS
    if (numbytes>0) fprintf (stderr,"C - received %i bytes\n",numbytes);
#endif

  }; // never leave this unless an error occured...
    
 return 1;
};

