/* 
   This file is part of Practical Distributed Processing
   Copyright (C) 2006-2007 Phillip J. Brooke and Richard F. Paige
*/

#include "constants.h"
#include "netstr.h"
#include <arpa/inet.h>
#include <errno.h>
#include <netinet/in.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <unistd.h>

/* 
   Accept datagrams, printing whatever is sent to us.
*/

int main ()
{
  char *             buffer          = malloc(BUFFER_SIZE);
  int                on              = 1;
  int                recv_value;
  int                s;
  socklen_t          sockaddr_in_len;
  struct sockaddr_in a;

  printf("Server starting...\n");

  /* Create a socket to listen on. */
  if ((s = socket(PF_INET, SOCK_DGRAM, 0)) >= 0)
    printf("The socket has been created\n");
  else
    {
      perror("Could not create socket");
      exit(EXIT_FAILURE);
    }

  /* Reuse local addresses when binding the socket.  See socket(7). */
  if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) < 0)
    {
      perror("Problem setting socket option");
      exit(EXIT_FAILURE);
    }

  /* Describe the addresses we'll accept connections from. */
  a.sin_family = AF_INET;
  a.sin_addr.s_addr = INADDR_ANY;
  a.sin_port = htons(EXAMPLE_PORT);

  /* Bind the socket to the address. */
  if (bind(s, (struct sockaddr *) &a, sizeof(a)) == 0)
    printf("Bound socket\n");
  else
    {
      perror("Could not bind socket");
      exit(EXIT_FAILURE);
    }

  printf("Waiting for inbound datagrams...\n");
  /* Now loop forever. */
  while (1) {

    sockaddr_in_len = sizeof(struct sockaddr_in);
    recv_value = NSrecvfrom(s, buffer, BUFFER_SIZE, 0, 
			  (struct sockaddr *) &a, &sockaddr_in_len);
    if (recv_value < 0) {
      perror("Problem with recv");
      exit(EXIT_FAILURE);
    } else {
      printf("Received from %s: %s\n", 
	     inet_ntoa(a.sin_addr),
	     buffer);
    }
  } 

  /* We never exit the while loop.  If we did, we should close
     s and exit. */
}
