// from: http://beej.us/guide/bgnet/html/#a-simple-stream-client

/*
** client.c -- a stream socket client demo
*/

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

#include <arpa/inet.h>

#define PORT "3490" // the port client will be connecting to 

#define MAXDATASIZE 100 // max number of bytes we can get at once 

// get sockaddr, IPv4 or IPv6:
void *get_in_addr(struct sockaddr *sa)
{
    if (sa->sa_family == AF_INET) {
        return &(((struct sockaddr_in*)sa)->sin_addr);
    }

    return &(((struct sockaddr_in6*)sa)->sin6_addr);
}

int main(int argc, char *argv[])
{
    int sockfd, numbytes;  
    char buf[MAXDATASIZE];
    struct addrinfo hints, *servinfo;
    int rv;

    if (argc != 2) {
        fprintf(stderr,"usage: client hostname\n");
        exit(1);
    }

    memset(&hints, 0, sizeof hints);
    hints.ai_family = AF_INET; // AF_UNSPEC;
    hints.ai_socktype = SOCK_STREAM;

    if ((rv = getaddrinfo(argv[1], PORT, &hints, &servinfo)) != 0) {
        fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(rv));
        return 1;
    }

    if ((sockfd = socket(servinfo->ai_family, servinfo->ai_socktype,
			 servinfo->ai_protocol)) == -1) {
      perror("client: socket");
      exit(1);
    }

    printf("sockfd: %d\n", sockfd);

    if (connect(sockfd, servinfo->ai_addr, servinfo->ai_addrlen) == -1) {
      close(sockfd);
      perror("client: connect");
      exit(1);
    }

    freeaddrinfo(servinfo); // all done with this structure

    char *line = NULL;
    size_t len = 0;
    ssize_t nread;

    // set sockfd to non-blocking
    if (fcntl(sockfd, F_SETFL, O_NONBLOCK) != 0)
      fprintf(stderr, "Error on F_SETFL sockfd \n");
    if (fcntl(0, F_SETFL, O_NONBLOCK) != 0) 
      fprintf(stderr, "Error on F_SETFL 0 (stdin) \n");

    printf("Note - reading from getline non-blocking not working, so ...\n");
    
    // only getline if there is something there.
    while (1) {
      usleep(1000);
      nread = getline(&line, &len, stdin);
      //printf("%ld, %x.  %x, %x\n", nread, errno, EAGAIN, EWOULDBLOCK);
      //break;
      if (nread > 0) {
	if ((numbytes = send(sockfd, line, nread, 0)) != nread) {
	  printf("numbytes sent was : %d\n", numbytes);
	}
      }
      if (nread == -1) {
	if (errno != EAGAIN && errno != EWOULDBLOCK) {
	  perror("getline");
	  break;
	}
      }

      // only recv if there is something there.
      // option 1: make sockfd non-blocking, uncomment appropriate line above
      if ((numbytes = recv(sockfd, buf, MAXDATASIZE-1, 0)) == -1) {
	if (errno == EAGAIN || errno == EWOULDBLOCK) { 	// nothing to receive now
	  continue;
	}
        perror("recv");
        exit(1);
      }

      printf(">> %s\n", buf);

      if (strcmp(line, "quit\n") == 0) break;
    }
    
    close(sockfd);

    return 0;
}