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

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

#define HOST NULL /* bind to any address */
#define PORT "12345"


int main(int argc, char *argv[])
{
	int listenfd, connfd;
	char buf[1024];

	listenfd = createlistensocket(HOST, PORT);

	if (listenfd < 0) {
		fprintf(stderr, "Failed to create listening socket.\n");
		exit(2);
	}

	while (1) {
		int len;
		struct sockaddr_storage from;
		socklen_t fromlen;

		fromlen = sizeof(from);
		connfd = accept(listenfd, (struct sockaddr*)&from, &fromlen);
		/* fork and let the child handle the connection? */
		
		len = read(connfd, buf, sizeof(buf)-1);
		if (len < 0) {
			fprintf(stderr, "ERROR: read() failed. Aborting!\n");
			exit(1);
		}

		buf[len] = '\0'; /* make sure we have a string end */
		printf("client sent: %s\n", buf);
		snprintf(buf, sizeof(buf), "Your socket identifier number in the server process is: %d\n", connfd);
		len = write(connfd, buf, strlen(buf));
		/* if (len < strlen(buf)) send the rest if you're picky, I don't care. */
		close(connfd);
	}

	printf("WTF just happened! How did we get here?\n");
	exit(123);
}

int createlistensocket(char *host, char *port)
{
	int listenfd, err;
	struct addrinfo hints, *res, *curr;

	memset(&hints, 0, sizeof(hints));
	hints.ai_family = AF_UNSPEC;
	hints.ai_socktype = SOCK_STREAM;
	hints.ai_protocol = IPPROTO_TCP;
	hints.ai_flags = AI_PASSIVE;

	err = getaddrinfo(host, port, &hints, &res);
	if (err) {
		fprintf(stderr, "ERROR: getaddrinfo() failed: %s\n", gai_strerror(err));
		return -1;
	}

	for (curr = res; curr != NULL; curr = curr->ai_next) {
		listenfd = socket(curr->ai_family, curr->ai_socktype, curr->ai_protocol);
		if (listenfd < 0) {
			continue;
		}

		err = bind(listenfd, curr->ai_addr, curr->ai_addrlen);
		if (err) {
			close(listenfd);
			continue;
		}

		err = listen(listenfd, 5);
		if (err) {
			close(listenfd);
			continue;
		}

		/* listening socket successfully created! */
		break;
	}

	if (curr == NULL) {
		listenfd = -2;
	}

	freeaddrinfo(res);

	return listenfd;
}

