#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>  /* memcpy() */
#include <sys/types.h> 
#include <sys/socket.h>
#include <sys/select.h>
#include <netinet/in.h>

#include <time.h>    /* time(), ctime() */

#include <sys/stat.h>  /* open() */
#include <fcntl.h>
#include <sys/wait.h>

#define MAXBUF  1024


int main(int argc, char *argv[])
{
/*  int sockfd, newsockfd, portno;*/
  char buf[26];
  char buf2[MAXBUF];
/*  int n;*/
  int sockd1, sockd2, tmp_sockd;
  int opt;
  struct sockaddr_in serv_addr1, serv_addr2, client_addr;
  socklen_t clilen;
  int port1, port2;
  fd_set select_set, read_set;
  int rc;
  struct timeval timeRec;

  time_t ticks;
  int fd, fd2;
  int ret, status, nread;

  if (argc < 3) {
   printf("Use: %s port1 port2\n",argv[0]);
   exit(1);
  }
  port1 = atoi(argv[1]);
  port2 = atoi(argv[2]);

  /** Create socket 1 on port1 for providing service 1 */
  printf("Creating socket 1 on port %d\n",port1);
  sockd1 = socket(AF_INET, SOCK_STREAM, 0);
  if (sockd1 < 0) {
    perror("Errore apertura socket 1\n");
  }
  opt = 1;
  if(setsockopt(sockd1, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)) < 0) {
    perror("setsockopt 1");
    exit(1);
  }
  serv_addr1.sin_family = AF_INET;
  serv_addr1.sin_addr.s_addr = INADDR_ANY;
  serv_addr1.sin_port = htons(port1);
  if (bind(sockd1, (struct sockaddr *) &serv_addr1, sizeof(serv_addr1)) < 0) {
    perror("Errore binding socket 1");
  }
  listen(sockd1,5);

  /** Create socket 2 on port2 for providing service 2 */
  printf("Creating socket 2 on port %d\n",port2);
  sockd2 = socket(AF_INET, SOCK_STREAM, 0);
  if (sockd2 < 0) {
    perror("Errore apertura socket 1\n");
  }
  opt = 1;
  if(setsockopt(sockd2, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)) < 0) {
    perror("setsockopt 1");
    exit(1);
  }
  serv_addr2.sin_family = AF_INET;
  serv_addr2.sin_addr.s_addr = INADDR_ANY;
  serv_addr2.sin_port = htons(port2);
  if (bind(sockd2, (struct sockaddr *) &serv_addr2, sizeof(serv_addr2)) < 0) {
    perror("Errore binding socket 2");
  }
  listen(sockd2,5);

  /* Initializes select mask */
  timeRec.tv_sec=60*5;
  timeRec.tv_usec=0;
  FD_ZERO(&select_set);
  FD_SET(sockd1,&select_set);
  FD_SET(sockd2,&select_set);

  /* Test di lettura sulla socket (i select_set di scrittura e delle eccezioni sono posti a 0!) */
  while (1) {
    /* Bloccato sino a che ci siano una o piu' socket attive. */
    memcpy(&read_set, &select_set, sizeof(select_set));  /* read_set contiene una copia della maschera... */
    rc = select(FD_SETSIZE,&read_set,0,0,&timeRec);
    if (rc > 0 && FD_ISSET(sockd1,&read_set)) {
      /* accept sockd1 !*/   
      printf("service on port %d (sockd1)\n",port1);  
      tmp_sockd = accept(sockd1,(struct sockaddr *)& client_addr,&clilen);

      ticks = time(NULL);                /* calcola data e ora corrente */
      strcpy(buf,ctime(&ticks));      /* la converte in stringa e la memorizza in buf[26] */
      if (write(tmp_sockd,buf,26) < 0) {
        perror("writing on stream socket");	
      }
      close(tmp_sockd);
    }
    
    if (rc > 0 && FD_ISSET(sockd2,&read_set)) {
      /* accept sockd2 !*/   
      printf("service on port %d (sockd2)\n",port2);   
      tmp_sockd = accept(sockd2,(struct sockaddr *)& client_addr,&clilen);

      ret = fork();
      if (ret < 0) {
        perror("failed on fork()");
      }
      else if (ret == 0) {  /* figlio */
        /**************************************************
                         COMPLETARE QUI! 
         **************************************************/
        close(tmp_sockd);
        exit(0);
      }
      else {
        /**************************************************
                         COMPLETARE QUI! 
         **************************************************/
        close(tmp_sockd);
      }
    }
  }

  close(sockd1);
  close(sockd2);
  return 0; 
}
