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

#define	BUFSIZE	1024

int main();
void bail();

/**
 * A quick and dirty program to pump requests through an HTTP server.
 * To see if my Java HTTP GETter (timingexp.HttpExp) is slow because
 * it's Java.
 */
int main()
{
	int sockfd, rc;
	struct sockaddr_in srcname;
	struct sockaddr_in destname;
	struct protoent *proto;
	struct hostent *hostent;
	char *request_f;
	char request[1024];
	int request_length;
	char reply[BUFSIZE];
	int loops, tries;
	int expNum, fileLength;
	int tinylog[] = { 100, 398, 1584, 6309, 25118, 100000 };
	int numberOfConnections = 200;
	struct timeval ts1;
	struct timeval ts2;

	request_f = "GET /timing/data-%06d.txt HTTP/1.0\n\n";

	proto = getprotobyname("tcp");

	srcname.sin_family = AF_INET;
	srcname.sin_addr.s_addr = INADDR_ANY;
	srcname.sin_port = 0;

	hostent = gethostbyname("shovel.cs.dartmouth.edu");
	destname.sin_family = AF_INET;
	memcpy(&destname.sin_addr.s_addr,
		hostent->h_addr_list[0],
		sizeof(destname.sin_addr.s_addr));
	destname.sin_port = 80;
		
	for (expNum = 0; expNum<6; expNum++) {
		fileLength = tinylog[expNum];
		printf("EXP %d fileLength %06d\n", expNum, fileLength);
		printf("EXP %d client fastget\n", expNum);
		printf("EXP %d server apache\n", expNum);
		printf("EXP %d protocol 1.1\n", expNum);
		printf("EXP %d numberOfConnections %d\n", expNum, numberOfConnections);
		printf("EXP %d experimentID %d\n", expNum, expNum);
		sprintf(request, request_f, fileLength);
		request_length = strlen(request);

		for (tries = 0; tries<10; tries++) {
			// let the cache warm up
			gettimeofday(&ts1, NULL);
			for (loops=0; loops<numberOfConnections; loops++) {
				sockfd = socket(PF_INET, SOCK_STREAM, proto->p_proto);
				if (sockfd<0) { bail(); }
		
				rc = bind(sockfd, (struct sockaddr *) &srcname, sizeof(srcname));
				if (rc<0) { bail(); }
		
				rc = connect(sockfd, (struct sockaddr *) &destname, sizeof(destname));
				if (rc<0) { bail(); }
		
				rc = write(sockfd, request, request_length);
				if (rc<request_length) { bail(); }
		
				while (1) {
					rc = read(sockfd, reply, BUFSIZE);
					if (rc==0) {
						break;
					} else if (rc<0) {
						bail();
					} else {
						/* write(0, reply, rc); */
					}
				}
				close(sockfd);
			}
			gettimeofday(&ts2, NULL);
			ts2.tv_sec -= ts1.tv_sec;
			ts2.tv_usec -= ts1.tv_usec;
			if (ts2.tv_usec < 0) {
				ts2.tv_sec-=1;
				ts2.tv_usec+=1000000;
			}
			printf("%d %d %d.%06d %d\n",
				expNum, loops, ts2.tv_sec, ts2.tv_usec, -1);
			fflush(stdout);
		}
	}
}

void bail()
{
	fprintf(stderr, "something bites, dude. Dude, errno is %d.\n", errno);
	perror("laaaaame");
	exit(1);
}
