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

long usecs;

char *printtimedelta(void) {
	char buf[32];
	struct timeval tnow;
	long usecsnow;
	gettimeofday(&tnow, NULL);
	usecsnow = tnow.tv_sec*1000000 + tnow.tv_usec;
	if(!usecs)
		printf("[         0us] ");
	else
		printf("[+% 9ldus] ", usecsnow-usecs);
	usecs = usecsnow;
}
#define myprintf(...) printtimedelta(); printf(__VA_ARGS__);

void gai_and_connect(char *hostname, int ac) {
	struct addrinfo hints, *res, *cur;
	struct sockaddr_in const *sin;
	struct sockaddr_in6 const *sin6;
	int errcode, sock;
	char buf[INET6_ADDRSTRLEN];

	usecs = 0;
	myprintf("begin gai_and_connect(%s)\n", hostname);

	memset(&hints, 0, sizeof(struct addrinfo));
	hints.ai_family = AF_UNSPEC;
	hints.ai_flags = ac;
	hints.ai_socktype = SOCK_STREAM;
	hints.ai_protocol = 0;

	errcode = getaddrinfo(hostname, "http", &hints, &res);
	if(errcode != 0) {
		myprintf("getaddrinfo(%s) failed: %s\n",
		       hostname, gai_strerror(errcode));
	} else {
		myprintf("getaddinfo(%s) done\n", hostname);
	}

	for(cur = res; cur != NULL; cur = cur->ai_next) {
		sock = socket(cur->ai_family, cur->ai_socktype,
			      cur->ai_protocol);
		if(sock == -1) {
			myprintf("socket() failed\n");
			exit(EXIT_FAILURE);
		}
		if(cur->ai_addr->sa_family == AF_INET) {
			sin = (void *)cur->ai_addr;
			myprintf("dest = %s (AF_INET)\n",
				 inet_ntop(cur->ai_family, &sin->sin_addr,
				 buf, sizeof(buf)));
		} else if(cur->ai_addr->sa_family == AF_INET6) {
			sin6 = (void *)cur->ai_addr;
			myprintf("dest = %s (AF_INET6)\n",
				 inet_ntop(cur->ai_family, &sin6->sin6_addr,
				 buf, sizeof(buf)));

		} else {
			myprintf("unknown AF %d, bailing",
				 cur->ai_addr->sa_family);
		}
		myprintf("about to connect()\n");
		if(connect(sock, cur->ai_addr, cur->ai_addrlen) != -1) {
			myprintf("connect() suceeds\n");
		} else {
			myprintf("connect() fails: %s\n",
			       strerror(errno));
		}
		close(sock);
	}
	freeaddrinfo(res);
	printf("\n");
}

int main(int argc, char **argv) {
	int i, ac = 0;
	for(i = 1; i < argc; i++) {
		if(!strcmp(argv[i], "-ac")) {
			usecs = 0;
			myprintf("-ac seen, using AI_ADDRCONFIG from now on\n\n");
			ac = AI_ADDRCONFIG;
		} else
			gai_and_connect(argv[i], ac);
		}
	exit(EXIT_SUCCESS);
}
