#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <fcntl.h>   /* File control definitions */
#include <errno.h>   /* Error number definitions */
#include <termios.h> /* POSIX terminal control definitions */
#define PORT 3814

int open_port(void)
{
  /*
    by default 9600baud
  */

  int fd; /* File descriptor for the port */
  struct termios opzioni;
  fd = open("/dev/ttyS0", O_RDWR | O_NOCTTY | O_NDELAY);
  if (fd == -1)
  {
    perror("open_port: Unable to open /dev/ttyS0 - ");
  }
  else fcntl(fd, F_SETFL, 0);
  tcgetattr(fd,&opzioni);
  opzioni.c_lflag = 0;
  tcsetattr(fd,TCSANOW,&opzioni); 
  return (fd);
}


void addr_initialize(struct sockaddr_in *indirizzo, int port, long IPaddr)
{
  indirizzo->sin_family=AF_INET;
  indirizzo->sin_port=htons((u_short) port);
  indirizzo->sin_addr.s_addr=IPaddr;
}

int main(int argc, char * argv[])
{
  int sd, new_sd, bind_result, listen_reslut, pidTx, pidRx;
  char inbuff;
  struct sockaddr_in server_addr;
  struct sockaddr_in client_addr;
  int client_len=sizeof(client_addr);
  int ricevuti=0;
  int fd = open_port();
  addr_initialize(&server_addr, PORT, INADDR_ANY);
  sd = socket(AF_INET, SOCK_STREAM, 0);

  bind_result = bind(sd, (struct sockaddr *) &server_addr, sizeof(server_addr));
  if(bind_result !=0)
  {
    printf("errore di binding -\n");
  }
  listen_reslut=listen(sd, 5);
  if(listen_reslut !=0)
  {
    printf("errore di listening -\n");
  }

  for(;;)
  {
    new_sd = accept(sd, (struct sockaddr*) &client_addr, &client_len);

    pidRx=fork();
    if(pidRx==0)
    {
      int res=0;
      char buf;
      while(1)
      {
        res = read(fd,&buf,1);
        if(res>0)
        {
          if(send(new_sd, &buf,1, 0)<1)
          {
            printf("connection down, quit\n");
	    exit(0);
          }
        }
      }
    }
    else{
      pidTx=fork();
      if(pidTx==0)
      {
        while(1)
        {
          ricevuti=recv(new_sd, &inbuff, 1, 0);
          if(ricevuti>=1)
          {
            int n = write(fd, &inbuff, 1);
            if (n < 0)
              printf("write() of 1 bytes failed %d!!-\n", n); 
          }
          else{
            printf("Connection closed, quit\n");
            close(new_sd);
            kill(pidRx);
            exit(0);
          }
        }  
      }
    }
  }
}

