/* Sample code for a simple UDP server */
#include <stdio.h>

#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>

#define CONNECTION_QUEUE_SIZE 5
#define SERVER_PORT ((unsigned)2222)
#define LOCALHOST (0x7f000001)

#define DEBUG

void print_sockname (int sd);
void dump_inet (char *label, void *s, int length);
void color (char *s);

char recv_buff[1024];

int main (int argc, char *argv[])
{
  int listen_sd, udp_proto, msg_len;
  struct protoent *udp_protoent;
  /*  struct sockaddr clientaddr[1024]; */
  struct sockaddr_in client_addr, server_addr;
  unsigned client_addr_len = sizeof (client_addr);
  unsigned server_addr_len = sizeof (server_addr);
  
  udp_protoent = getprotobyname ("udp");
  udp_proto = udp_protoent -> p_proto;
#ifdef DEBUG
  printf ("Looking up udp protocol number: %d\n", udp_proto);
#endif /* DEBUG */

   /* Create socket */
  if ((listen_sd = socket (AF_INET, SOCK_DGRAM, udp_proto)) < 0 ) {
    printf ("Socket creation failed\n");
    perror ("server:main");
    exit (1);
  }
#ifdef DEBUG   
  printf ("Socket created successfully with descriptor %d\n",
	  listen_sd);

  printf ("Initial address is \n");
  print_sockname (listen_sd);
#endif   
  
  server_addr.sin_family = AF_INET;
  server_addr.sin_port = htons(SERVER_PORT);
  server_addr.sin_addr.s_addr = INADDR_ANY;
   
   /* Bind socket to port */
  
  if (bind (listen_sd,
	    (struct sockaddr *) &server_addr,
	    sizeof(server_addr)) < 0) 
    {
      printf ("Unable to bind to port %d\n", SERVER_PORT);
      perror ("server:main");
      exit(1);
    }

#ifdef DEBUG
  printf ("Bound!\n");
  print_sockname (listen_sd);
   printf ("Waiting for something to happen!\n");
#endif
   /* Loop forever */
   while (1)
     {
	int i;
	fd_set readfds, writefds;
	FD_ZERO (&readfds);
	FD_ZERO (&writefds);
	FD_SET (listen_sd,&readfds);
	if (select (listen_sd+1, &readfds, NULL, NULL, NULL) < 0) {
	   printf ("Select returned error\n");
	   perror (argv[0]);
	   exit(1);
	}
#ifdef DEBUG
	printf ("Somebody sent something!\n");
#endif
	if ((msg_len = recvfrom (listen_sd, recv_buff, sizeof(recv_buff), 0,
				 &client_addr, &client_addr_len)) < 0) {
	  fprintf (stderr, "recfrom failed:\n");
	  perror("recvfrom:");
	  exit(1);
	}
	printf ("Datagram received:\n");
	for (i=0; i<msg_len; i++) {
	  printf ("%c", recv_buff[i]);
	}
	printf ("\n");
#ifdef DEBUG
	printf ("Port: %d\n", ntohs(client_addr.sin_port));
	dump_inet ("IP:", &client_addr.sin_addr.s_addr, 4);
#endif
#define MSG "Hello client..."
	if (sendto (listen_sd, MSG, strlen(MSG), 0, &client_addr, sizeof(client_addr)) < 0) {
	  printf ("Sendto failed.\n");
	  perror(argv[0]);
	}
     }
   return 0;
}

void dump_inet (char *label, void *s, int length)
{
  int i;
  printf ("%s", label);
  printf ("%d", ((unsigned char *) s)[0]);

  for (i=1; i<length; i++) {
    printf (".%d", ((unsigned char *) s) [i]);
  }
  printf ("\n");
}

void print_sockname (int sd) 
{
  struct sockaddr_in sockaddr;
  unsigned sockaddr_len = sizeof (sockaddr);
  sockaddr.sin_port = htons(0);
  sockaddr.sin_addr.s_addr = INADDR_ANY;
  
  if (getsockname (sd, (struct sockaddr *) &sockaddr,
		   &sockaddr_len) < 0) {
    printf ("Call to getsockname failed\n");
    perror ("print_sockname");
  }
  printf ("Port: %d\n", ntohs(sockaddr.sin_port));
  dump_inet ("IP:", &sockaddr.sin_addr.s_addr, 4);
}

