#include <stdio.h>	/* standard C i/o facilities */
#include <unistd.h>	/* Unix System Calls */
#include <sys/types.h>	/* system data type definitions */
#include <sys/socket.h> /* socket specific definitions */
#include <netinet/in.h> /* INET constants and stuff */
#include <arpa/inet.h>	/* IP address conversion stuff */

#include <sys/time.h>	/* need for timeval struct */

/* Simple TCP chat server - accepts 2 connections and
   forward stuff from one socket to the other
  
   Example of using select()
*/

int MAXLEN=100;

#define MAX(x,y) (x>y?x:y)

int talk(int sd1, int sd2 ) {
  fd_set rdset;
  int rval,n;
  struct timeval timeout = {1,0};
  char buf[MAXLEN];

  while (1) {
    FD_ZERO(&rdset);		/* Clear out everything */
    FD_SET(sd1,&rdset);		/* Add sd1 to the set */
    FD_SET(sd2,&rdset);		/* Add sd2 to the set */

    /* look for input from either client, but don't wait
       more than 1 second */
    timeout.tv_sec=1;
    timeout.tv_usec=0;

    /* call select, waiting no more than 1 second before returning */
    if ((rval = select( MAX(sd1,sd2)+1, &rdset, NULL, NULL, &timeout))<0) {
      printf("Error calling select\n");
      exit(1);
    }

    if (rval==0) {
      /* if select returns 0 it means the maximum time forced it
	 to return (there is nothing available for reading) */
      printf("THE CLOCK IS TICKING!\n");
    } else {
      /* Check for input from client 1 */
      if (FD_ISSET(sd1,&rdset) ) {
	/* There is data from client 1 (sd1) - read it */
	if ((n=read(sd1,buf,MAXLEN))<0) {
	  printf("ERROR READING\n");
	  exit(1);
	}

	/* If client 1 closed the connection, shut everything down */
	if (n==0) {
	  printf("DONE\n");
	  close(sd1);
	  close(sd2);
	  return(1);
	}

	/* forward the stuff to client 2 */
	if (write(sd2,buf,n)<0) {
	  printf("ERROR WRITING\n");
	  exit(1);
	}
      }

      /* Check to see if client 2 sent anything */
      if (FD_ISSET(sd2,&rdset) ) {
	/* There is data from client 1 (sd1) - read it */
	if ((n=read(sd2,buf,MAXLEN))<0) {
	  printf("ERROR READING\n");
	  exit(1);
	}
	/* If client 1 closed the connection, shut everything down */
	if (n==0) {
	  printf("DONE\n");
	  close(sd1);
	  close(sd2);
	  return(1);
	}
	/* forward the stuff to client 2 */
	if (write(sd1,buf,n)<0) {
	  printf("ERROR WRITING\n");
	  exit(1);
	}
      }
    }
  }
}

int main() {
  int ld,sd1,sd2;			
  struct sockaddr_in skaddr;	
  struct sockaddr_in from;	
  int addrlen,length;
/* create a socket 
       IP protocol family (PF_INET) 
       TCP protocol (SOCK_STREAM)
*/
  
  if ((ld = socket( PF_INET, SOCK_STREAM, 0 )) < 0) {
    perror("Problem creating socket\n");
    exit(1);
  }
  
/* establish our address 
   address family is AF_INET
   our IP address is INADDR_ANY (any of our IP addresses)
   the port number is assigned by the kernel 
*/

  skaddr.sin_family = AF_INET;
  skaddr.sin_addr.s_addr = htonl(INADDR_ANY);
  skaddr.sin_port = htons(0);

  if (bind(ld, (struct sockaddr *) &skaddr, sizeof(skaddr))<0) {
    perror("Problem binding\n");
    exit(0);
  }
  
/* find out what port we were assigned and print it out */

  length = sizeof( skaddr );
  if (getsockname(ld, (struct sockaddr *) &skaddr, &length)<0) {
    perror("Error getsockname\n");
    exit(1);
  }
  printf("The Server passive socket port number is %d\n",ntohs(skaddr.sin_port));

/* put the socket into passive mode (waiting for connections) */

  if (listen(ld,5) < 0 ) {
    perror("Error calling listen\n");
    exit(1);
  }
  
/* now process incoming connections forever ... */

  while (1) {
    printf("Ready for a connection...\n");
    addrlen=sizeof(skaddr);
    if ( (sd1 = accept( ld, (struct sockaddr*) &from, &addrlen)) < 0) {
      perror("Problem with accept call\n");
      exit(1);
    }

    printf("Got connection #1 - waiting...\n");
    if ( (sd2 = accept( ld, (struct sockaddr*) &from, &addrlen)) < 0) {
      perror("Problem with accept call\n");
      exit(1);
    }

    printf("Got 2 connections ...\n");
    talk(sd1,sd2);
  }
}






