// this is a sketch of the wifi receiver... next stage is to move this
// code into the CNC multiplexer... (this code is just an echo server,
// with uppercase output forced, to give an indication that it has
// actually done something...)

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

#ifndef MAX_STRING
#define MAX_STRING 1024
#endif

#define MAX 80
#define PORT 8080
#define SA struct sockaddr

int main (int argc, char **argv)
{
  int sockfd, WIFI_Fd, len;
  struct sockaddr_in servaddr, cli;
  fd_set inFds;

  // socket create and verification
  sockfd = socket (AF_INET, SOCK_STREAM, 0);
  if (sockfd == -1) {
    printf ("socket creation failed...\n");
    exit (0);
  }				// else printf("Socket successfully
  // created..\n");

  bzero (&servaddr, sizeof (servaddr));

  // assign IP, PORT
  servaddr.sin_family = AF_INET;
  servaddr.sin_addr.s_addr = htonl (INADDR_ANY);
  servaddr.sin_port = htons (PORT);

  // Binding newly created socket to given IP and verification
  while ((bind (sockfd, (SA *) & servaddr, sizeof (servaddr))) != 0) {
    printf ("socket bind failed... retrying...\n");
    sleep (1);
  }				// else printf("Socket successfully
  // binded..\n");

  // Now server is ready to listen and verification
  if ((listen (sockfd, 5)) != 0) {
    printf ("Listen failed...\n");
    exit (0);
  } else
    printf ("Waiting for client...\n");
  len = sizeof (cli);

  // Accept the data packet from client and verification

  WIFI_Fd = accept (sockfd, (SA *) & cli, &len);

  if (WIFI_Fd < 0) {
    printf ("server accept failed...\n");
    exit (0);
  } else {			// Determine IP of caller...
  static char connecting_host[1024];
  struct sockaddr_storage name;
  int namelen = sizeof (name);
  struct in_addr addr;

    strcpy (connecting_host, "0.0.0.0");	/* Default is an invalid
						   address */
    // test a friendly address by telneting to localhost
    // test a hostile address by running this code from the command-line

    memset (&name, 0, sizeof (name));

    if (getpeername (WIFI_Fd, (struct sockaddr *) &name, &namelen) >= 0) {
      addr = ((struct sockaddr_in *) &name)->sin_addr;
      // Had some portability issues with the IPV6 code.  Removed it.
      // if (name.ss_family == AF_INET) {
      (void) inet_ntop (AF_INET, &addr, connecting_host, MAX_STRING);
      // }
    }
    connecting_host[MAX_STRING - 1] = '\0';	/* just in case */
    fprintf (stderr, "Connected from %s\n", connecting_host);
  }

  // Function for chatting between client and server
  // func(WIFI_Fd);
  {
  char buff[MAX];
  int n, rc;

    // infinite loop for chat
    for (;;) {
      bzero (buff, MAX);

      FD_ZERO (&inFds);
      FD_SET (WIFI_Fd, &inFds);

      rc = select (WIFI_Fd + 1, &inFds, NULL, NULL, NULL);

      if (FD_ISSET (WIFI_Fd, &inFds)) {	/* WIFI -> USB0 */
	n = read (WIFI_Fd, buff, sizeof (buff));

	if (n > 0) {
  int i;

	  for (i = 0; i < n; i++) {
	    if (isalpha (buff[i]) && islower (buff[i]))
	      buff[i] = toupper (buff[i]);
	  }

	  // and send that buffer to client
	  write (WIFI_Fd, buff, n);
	  // and the screen for debugging...
	  write (2, buff, n);

	  // if msg contains "Exit" then server exit and chat ended.
	  if (strncmp ("exit", buff, 4) == 0) {
	    fprintf (stderr, "Server Exit...\n");
	    break;
	  }
	} else {
	  fprintf (stderr,
		   "Did the client exit? - let's try to reconnect...\n");
	  // Now server is ready to listen and verification
	  if ((listen (sockfd, 5)) != 0) {
	    printf ("Listen failed...\n");
	    exit (0);
	  } else
	    printf ("Waiting for client...\n");
	  len = sizeof (cli);

	  // Accept the data packet from client and verification

	  WIFI_Fd = accept (sockfd, (SA *) & cli, &len);

	  if (WIFI_Fd < 0) {
	    printf ("server accept failed...\n");
	    exit (0);
	  } else {		// Determine IP of caller...
  static char connecting_host[1024];
  struct sockaddr_storage name;
  int namelen = sizeof (name);
  struct in_addr addr;

	    strcpy (connecting_host, "0.0.0.0");	/* Default is an
							   invalid address */
	    // test a friendly address by telneting to localhost
	    // test a hostile address by running this code from the
	    // command-line

	    memset (&name, 0, sizeof (name));

	    if (getpeername (WIFI_Fd, (struct sockaddr *) &name, &namelen) >=
		0) {
	      addr = ((struct sockaddr_in *) &name)->sin_addr;
	      // Had some portability issues with the IPV6 code.  Removed it.
	      // if (name.ss_family == AF_INET) {
	      (void) inet_ntop (AF_INET, &addr, connecting_host, MAX_STRING);
	      // }
	    }
	    connecting_host[MAX_STRING - 1] = '\0';	/* just in case */
	    fprintf (stderr, "Connected from %s\n", connecting_host);
	}}
      }
    }
  }

  // After chatting close the socket
  close (sockfd);
}