/*
 * Example of client using TCP protocol, adapted from
 *   W.R. Stevens' "Unix Network Programming", 1st ed. 
 */

#include  <stdio.h>
#include  <sys/types.h>
#include  <sys/socket.h>
#include  <netinet/in.h>
#include  <arpa/inet.h>

#include  <stdio.h>
#include  <strings.h> // bzero
#include  <stdlib.h>  // exit
#include  <unistd.h>  // close

#include <stdint.h>   // uint8_t

#define SERV_TCP_PORT   5051
#define SERV_HOST_ADDR  "127.0.0.1"  

#include "pow.h"

void worker_func( int sockfd, uint32_t num, uint8_t pow )
{
     int n, i;
     char buff[MAXLINE];

     struct request req;
     struct response *res;

     req.pow = pow;
     req.num = htonl(num);

     n = write( sockfd, (void*) &req, sizeof(req));
     if( n < sizeof(req) ){
          perror( "Error sending request" );
          exit(1);
     }

     n = read(sockfd, buff, MAXLINE);
     if( n < 7 ){
          perror("Message truncated");
          exit(1);
     }
     
     res = (struct response *)buff;

     if( res->status != 1 ){
          printf( "Something went wrong! This is what I received:\n" );
          for (i = 0; i < n; i++) {           /* print packet */
               printf("%02X%s", (uint8_t)buff[i], (i + 1)%16 ? " " : "\n");
          }
          printf("\n");
          exit(1);
     }
     else{
          int len;
          printf( "Result: %d\n", ntohl(res->result) );
          len = ntohs(res->len);
          if( len > 0 ){
               fwrite( buff + 7, len, 1, stdout );
          }
          printf("\n");          
     }
}

int main(argc, argv)
int	argc;
char	*argv[];
{
     int sockfd;
     struct sockaddr_in	serv_addr;

     unsigned int num;
     unsigned char pow;

     num = atoi(argv[1]);
     pow = atoi(argv[2]);


     /*
      * Fill in the structure "serv_addr" with the address of the
      * server that we want to connect with.
      */
     
     bzero((char *) &serv_addr, sizeof(serv_addr));
     serv_addr.sin_family      = AF_INET;  /* Internet! */

     // These values are formatted for immediated use with a packet's fields,
     //   hence they are represented exactly as they'd appear in a packet.
     serv_addr.sin_addr.s_addr = inet_addr(SERV_HOST_ADDR); /* string to 4-byte IPv4 address */
     serv_addr.sin_port        = htons(SERV_TCP_PORT);      /* must be network-ordered! */
     
     /*
      * Open a TCP socket (an Internet stream socket).
      */
     
     if ( (sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0){  /* AF_INET is 2, SOCK_STREAM is 1 */
          perror("tcp client: can't open stream socket");
          exit(1);
     }

     /*
      * Connect to the server.
      */
     
     if (connect(sockfd, (struct sockaddr *) &serv_addr,
                 sizeof(serv_addr)) < 0){
          perror("tcp client: can't connect to server");
          exit(1);
     }

     worker_func(sockfd, num, pow);
     
     close(sockfd);
     return 0;
}



/*
 *  Read from STDIN, write into the socket, so long as STDIN lasts.
 */
void str_cli(sockfd)
{
     int     n;
     char    sendline[MAXLINE], recvline[MAXLINE + 1];
     
     while (fgets(sendline, MAXLINE, stdin) != NULL) {
          n = strlen(sendline);
          if (write(sockfd, sendline, n) != n)
               perror("str_cli: writen error on socket"); 
          
          /*
           * Now read a line from the socket and write it to
           * our standard output.
           */
          

          if (n < 0){
               perror("str_cli: readline error");
               exit(1);
          }
          recvline[n] = 0;        /* null terminate */
          fputs(recvline, stdout);
     }
}
