/* elliottServer.c - code of server program that uses TCP
 *            Used to see how the 4-way handshake behaves. 
 *            We want to see if after the server has closed
 *            it can still read.
 */

#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>

#define PROTOPORT 8765 /* default protocol port number*/
#define QLEN 50
/****************************************************************
 * Program: server
 * Purpose: Allocate a socket and execute the following:
 *          (1) wait for connection from the client
 *          (2) send a short message to the client
 *          (3) close the connection
 *          (4) keep on reading until the client closes the connection
 * 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.
 ****************************************************************/
int main(int argc, char *argv[])
{
	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              */
	unsigned int    alen;  /* length of address                 */
	char   buf[1000];      /* buffer for string the server sends*/
	int option_value;      /* GPI: needed for setsockopt        */

	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 > 1024)           /* 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);
	}


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

	/* 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);
	}

	/* Accept and handle request */
	alen = sizeof(cad);
	if ((sd2 = accept(sd, (struct sockaddr *)&cad, &alen)) < 0){
		fprintf(stderr, "accept failed\n");
		exit(1);
	}
	/* Write a message to client */
	sprintf(buf, "This server has been contacted\n");
	write(sd2, buf, strlen(buf));
	/* Close the socket */
	close(sd2);
	/* See if you can still read */
	while (1) {
		int n = read(sd2, buf, sizeof(buf));
		if (n <= 0) break;
		printf(">>> %s\n", buf);
	}
	return (0);
}

