#include "main.h"
#include "listhash.h"
#include "misc.h"

#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>

#include <fcntl.h>

typedef u_int32_t ipaddr_t;

int pointpipe;
int resolvpipe;

/* Hash Table */
struct hash_table resolv;

/* Temporary Points */
struct point_t tmppoint;
struct point_t tmptext;

/* Resolv Counter */
//struct counter_t rc;

void dispatch(struct point_t *p) {
	if(DEBUG) {fprintf(stderr,"dispatch: %p\n",p);}
	write(pointpipe,p,sizeof(struct point_t));
}

ipaddr_t get_request(void) {
	ipaddr_t ip;
	read(resolvpipe,&ip,sizeof(ipaddr_t));
	return ip;
}

char *resolv_ip(ipaddr_t ip) {
	struct hostent *h;
	struct in_addr in;
	static char name[LABELSIZE];
	
	h = gethostbyaddr(&ip,sizeof(ipaddr_t),AF_INET);
	if(h != NULL) {
		strncpy(name,h->h_name,LABELSIZE);
	} else {
		in.s_addr = ip;
		strncpy(name,inet_ntoa(in),LABELSIZE);
	}
	return name;
}

struct point_t *resolve(ipaddr_t ip) {
	struct point_t *p;
	p = hash_findu(&resolv,ip);
	return p;
}

struct point_t *resolv_add(ipaddr_t ip) {
	struct point_t *p;
	
	strncpy(tmppoint.label,resolv_ip(ip),LABELSIZE);
	niptov(&(tmppoint.vertex),ip);
	
	tmppoint.life 	= 0;
	tmppoint.ip 	= ip;
	tmppoint.hash 	= hash(&ip,sizeof(ipaddr_t));
	
	p = hash_add_lose(&resolv,ip,&tmppoint,sizeof(struct point_t));
	return p;
}	

void process_request(ipaddr_t ip) {
	struct point_t *p = resolve(ip);
	static unsigned int re = 0;
	static time_t last_re = 0;
	time_t this_re = time(NULL);
	
	if(p == NULL) {
		p = resolv_add(ip);
	}
	++p->life;
	
	/* Only send 10 Hosts Per Second MAX */	
	if(this_re == last_re) {
		++re;
	} else {
		last_re = this_re;
		re = 0;
	}
	if(re < 10) {
		strncpy(&(tmptext.label),p->label,LABELSIZE);
		tmptext.ip = ip;
		tmptext.hash = hash(&ip,sizeof(ipaddr_t));
		dispatch(&tmptext);
	}
	
	/* Life Handling */
	if(p->life > 50) {
		if(DEBUG) {fprintf(stderr,"process_request: %p Reached life 50\n",p);}
		p->life = 500;
		dispatch(p);
		p->life = 0;
	}
}

void sigpipe(int i) {
	fprintf(stderr,"resolv: SIGPIPE\n");
	exit(1);
}

int point_handling_child(int pop, int rp) {
	ipaddr_t ip;

	signal(SIGPIPE,sigpipe);
	
	/* Set Pipes */
	pointpipe = pop;
	//fcntl(pointpipe, F_SETFL, O_NONBLOCK);
	resolvpipe = rp;

	/* Init Hash */
	hash_table_init(&resolv);
	
	/* Init Counter */
	//counter_init(&rc);
	
	/* Set Up Temp Points */
	memset(&tmppoint,0,sizeof(struct point_t));
	memset(&tmptext,0,sizeof(struct point_t));
	tmppoint.type = POINT | LABEL;
	tmppoint.vertex.col.r = 1.0;
	tmppoint.vertex.col.g = 1.0;
	tmppoint.vertex.col.b = 1.0;
	tmptext.type = TEXT;
	
	for(;;) {
		ip = get_request();
		process_request(ip);
	}
	
	exit(0);
}
