/* server.c - code for example server program that uses TCP 
 *            From "Computer Networks and Internets" by 
 *            D.Comer.
 *            Modified by G.Ingargiola to print out information on
 *            identity of client and to make reusable the listening socket
 *            (Unix only).
 */

#ifndef unix
#define WIN32
#include <windows.h>
#include <winsock.h>
#else
#define closesocket close
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#endif

#include <stdio.h>
#include <string.h>

#define PROTOPORT 5194 /* default protocol port number*/
#define QLEN 6
int visits = 6;        /* counts client connections */
/****************************************************************
 * Program: server
 * Purpose: Allocate a socket and then repeatedly execute the following:
 *          (1) wait for the next connection from the client
 *          (2) send a short message to the client
 *          (3) close the connection
 *          (4) go back to step (1)
 * Syntax: server [port]
 *            port:protocol port number to use
 * Note: The port argument is optional. If no protocol port is
 *       specified, the server uses the default given by PROTOPORT.
 ****************************************************************/
main(argc, argv)
int argc;
char *argv[];
{
	struct hostent *ptrh;  /* pointer to a host table entry     */
	struct protoent *ptrp; /* pointer to a protocol table entry */
	struct sockaddr_in sad;/* structure to hold server's address*/
	struct sockaddr_in cad;/* structure to hold client's address*/
	int    sd, sd2;        /* socket descriptors                */
	int    port;           /* protocol port number              */
	int    alen;           /* length of address                 */
	char   buf[1000];      /* buffer for string the server sends*/
	int option_value;      /* GPI: needed for setsockopt        */
#ifdef WIN32
	WSADATA wsaData;
	WSAStartup(0x0101, &wsaData);
#endif
	memset((char *)&sad, 0, sizeof(sad)); /* clear sockaddr structure */
	sad.sin_family = AF_INET;  /* set family to Internet */
	sad.sin_addr.s_addr = INADDR_ANY; /* set the local IP address */

	/* Check command-line argument for protocol port and extract
	 * port number if one is specified. Otherwise, use the default
	 * port value given by constant PROTOPORT
	 */
	if (argc > 1) {         /* If protocol port is specified */
       port = atoi(argv[1]);/* Convert to binary */
	} else {
	   port = PROTOPORT;    /* use default port number */
	}
	if (port > 0)           /* Test for legal value */
		sad.sin_port = htons((u_short)port);
	else {                  /* Print error message and exit */
		fprintf(stderr,"bad port number %s\n", argv[1]);
		exit(1);
	}


	/* Map TCP transport protocol name to protocol number */
	if (((int)(ptrp = getprotobyname("tcp"))) == 0) {
		fprintf(stderr, "cannot map \"tcp\" to protocol number");
		exit(1);
	}

	/* Create a socket */
	sd = socket(PF_INET, SOCK_STREAM, ptrp->p_proto);
	if (sd < 0) {
		fprintf(stderr, "socket creation failed\n");
		exit(1);
	}

	/* GPI: make port reusable */
	option_value = 1;
	if (setsockopt(sd,SOL_SOCKET, SO_REUSEADDR, (char *)&option_value,
		       sizeof(option_value)) < 0)
	  {
	    perror("setsockopt");
	    exit(0);
	  }

	/* Bind a local address to the socket */
	if (bind(sd, (struct sockaddr *)&sad, sizeof(sad)) < 0) {
		fprintf(stderr, "bind failed\n");
		exit(1);
	}

	/* Specify size of request queue */
	if (listen(sd, QLEN) < 0) {
		fprintf(stderr, "listen failed\n");
		exit(1);
	}

	/* Main server loop - accept and handle requests */
	while (1) {
		alen = sizeof(cad);
		if ((sd2 = accept(sd, (struct sockaddr *)&cad, &alen)) < 0){
			fprintf(stderr, "accept failed\n");
			exit(1);
		}
		/*GPIVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV*/
                printf("Client Socket Family: %x\n", ntohs(cad.sin_family));
                printf("Client Port = %u\n", ntohs(cad.sin_port));
                printf("Client IP = %s\n", inet_ntoa(cad.sin_addr));
                /*GPI^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*/
		visits++;
		sprintf(buf, "This server has been contacted %d time%s\n",
			visits, visits==1?".":"s.");
		send(sd2, buf, strlen(buf),0);
		closesocket(sd2);
	}
}
