/* Author: Pete Broadwell, Grinnell College

   This program simulates a scenario of the readers-writers program in which
   multiple readers (clients) and a single writer (server) communicate through
   a datagram socket. This server process handles the clients iteratively. */

#include <sys/types.h>
#include <unistd.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <signal.h>   /* socket command libraries needed by some compilers */
#include <sys/socket.h>
#include <sys/un.h>
#include <netinet/in.h>

#define SIM_LENGTH 6 /* number of integers to be written and read */
#define NUM_READERS 3
#define PORT 1229 /* local port on which the server establishes connection */

/* procedure to remove socket file and exit */
void clean_up(int cond, int *sock)
{ printf("Exiting now.\n");
  close(*sock);
  exit(cond);
} /* end of clean_up */

int main(void)
{ /* processing for server */
  int sock; /* socket file descriptor */
  struct sockaddr_in serv_name; /* socket address structure */
  int count, i, data;
  char msg[20]; /* array for greetings to be read from socket */
  size_t len; /* variable for the size of the cli_name structure */

  /* set socket descriptor */
  sock = socket(AF_INET, SOCK_DGRAM, 0);
  if (sock < 0)
    { perror("Opening channel");
      clean_up(1, &sock);
    }

  /* set the physical address (serv_name) of the socket descriptor */
  bzero(&serv_name, sizeof(serv_name));
  serv_name.sin_family = AF_INET;
  serv_name.sin_port = htons(PORT);

  /* bind the socket address to the socket descriptor */
  if (bind(sock, (struct sockaddr *)&serv_name, sizeof(serv_name)) < 0)
    { perror("Naming channel");
      clean_up(1, &sock);
    }

  printf("Server is on line.\n");
    
  /* initialize the msg array */
  for (count = 0; count < 20; count++)
    msg[count] = 0;

  /* iteratively read greetings from readers and write integers to them */
  len = sizeof(serv_name);

  for (i = 1; i <= NUM_READERS; i++)
    { recvfrom(sock, &msg, 20, 0, (struct sockaddr *)&serv_name, &len);
      printf("Server has read  %s  from socket.\n", msg);
      sendto(sock, &i, 4, 0, (struct sockaddr *)&serv_name, len);
      printf("Server has sent ID number to client %d.\n", i);	

      for (count = 1; count <= SIM_LENGTH; count++)
        { data = ( (i - 1) * 10) + count;
          sendto(sock, &data, 4, 0, (struct sockaddr *)&serv_name, len);
          printf("Server has written %d to socket.\n", data);
        }
    }

  clean_up(0, &sock); /* Exit with no errors */

} /* end of main */
