void makeTrie(void) {
    map<int, hostConf>::iterator j;
    string::iterator stringit;
    char* temp = new char[16];
    string prestring;
    char* size = new char[2];
    struct cidrprefix tempFix;
    for(j = routerEnd.begin(); j != routerEnd.end(); j++) {
        prestring = (j->second).overlayPrefix;
        for(stringit = prestring.begin(); stringit != prestring.end(); stringit++) {
			if(*stringit == '/') {
				strcpy(temp, prestring.substr(0, distance(prestring.begin(),stringit)).c_str());
				cout << "Temp: " << temp << endl;
				inet_pton(AF_INET, temp, (void *)&tempFix.prefix);
				stringit++;
				size[0] = *stringit;
				stringit++;
				size[1] = *stringit;
				break;
			}
        }
        tempFix.size = (char)atoi(size);
        #ifdef DEBUG
			cout << "Prefix: " << tempFix.prefix << "/" << (int)tempFix.size << " for router: " << routerIPs[j->first] << endl;
		#endif
        hosts.insert(tempFix, routerIPs[j->first]);
        #ifdef DEBUG
			cout << "Testing trie." << endl;
			int testaddr;
			inet_pton(AF_INET, "1.2.3.1", (void *)&testaddr);
			cout << testaddr << hosts.search(testaddr) << endl;
		#endif
    }
    
}
int main(int argc, char** argv) {
    #ifdef SANDWICH
        printf("I'm a sandwich!\n");
    #endif
    int o;
    string configPath;
    char isRouter = IP_NOT_FOUND;
    while((o = getopt(argc, argv, "rh")) != -1) {
		switch(o) {
			case 'r':
				//enter router mode
				isRouter = TRUE;
				break;
			case 'h':
				//enter host mode
				isRouter = FALSE;
				break;
			case '?':
			    fprintf(stderr, "Unknown option -%c.\n", optopt);
			    cout << "Specify host with -h or router with -r" << endl;
			    exit(0);
				break;
		}
	}
	configPath = (string)argv[optind];
	if(configPath.empty()) {
		printf("Please, you must provide a filename.\n");
		printf("Usage: overlay [-r -h] config.conf\n");
		exit(1);
	}
	readConfig(configPath);
    makeTrie();
    struct ifaddrs *demAddrs;
    if(getifaddrs(&demAddrs)) {
		fprintf(stderr, "Couldn't get real IP address. Aborting.\n");
		exit(1);
	}
	struct in_addr *myAddr;
	char* addrBuf = new char[INET_ADDRSTRLEN];
	struct sockaddr *mysockaddr = (demAddrs->ifa_addr);
	while((strcmp(demAddrs->ifa_name, "eth0") && strcmp(demAddrs->ifa_name, "eth1") && strcmp(demAddrs->ifa_name, "eth2") && strcmp(demAddrs->ifa_name, "eth3") && strcmp(demAddrs->ifa_name, "wlan0"))||(mysockaddr->sa_family!=AF_INET)) {
		#ifdef DEBUG
			cout << "Interface: " << demAddrs->ifa_name << ". NOPE!" << endl;
		#endif
	    demAddrs = demAddrs->ifa_next;
	    if(demAddrs==NULL) {
		    fprintf(stderr, "Couldn't find the specified interface. Aborting. Sorry! Make sure your computer is set up properly.\n");
		    exit(1);
	    }
	    mysockaddr = (demAddrs->ifa_addr);
	}
	#ifdef DEBUG
		cout << "Interface: " << demAddrs->ifa_name << endl;
	#endif
	myAddr = &(((struct sockaddr_in*)mysockaddr)->sin_addr);
	inet_ntop(AF_INET, (void *)myAddr, addrBuf, INET_ADDRSTRLEN);
	#ifdef DEBUG
		printf("My real IP address is: %s\n", addrBuf);
	#endif
	map<int, string>::iterator routeit;;
	for(routeit = routerIPs.begin(); routeit != routerIPs.end(); routeit++) {
		#ifdef DEBUG
			cout << "Testing: " << (*routeit).second << endl;
		#endif
		if(!(*routeit).second.compare((string)addrBuf)) {
			isRouter = TRUE;
			hostID = (*routeit).first;
			break;
		}
	}
	if(isRouter == IP_NOT_FOUND) {
		map<int, hostIP>::iterator endit;
		for(endit = endIPs.begin(); endit != endIPs.end(); endit++) {
			#ifdef DEBUG
				cout << "Testing: " << (*endit).second.real << endl;
			#endif
			if(!(*endit).second.real.compare((string)addrBuf)) {
				isRouter = FALSE;
				hostID = (*endit).first;
				break;
			}
		}
	}
	if(isRouter == IP_NOT_FOUND) {
		fprintf(stderr, "I couldn't find your IP address in my memory banks. Please check to make sure your configuration file is correct.");
		exit(1);
	}
	if(isRouter) router();
	else {
		uint32_t myIP = 0;
		inet_pton(AF_INET, endIPs[hostID].overlay.c_str(), (void *)&myIP);
		string myRouter = hosts.search(myIP);
		#ifdef DEBUG
			cout << "My router is: " << myRouter << endl;
		#endif
		unsigned long myRouterInt;
		inet_pton(AF_INET, myRouter.c_str(), (void *)&myRouterInt);
		host(myRouterInt);
	}
	return 0;
}
void router(void) {
	#ifdef DEBUG
		cout << "I am router #" << hostID << "!" << endl;
	#endif
    //bind socket 
    int sockfd = create_cs3516_socket();
    //initialize for select() call
    fd_set readfds;
	FD_ZERO(&readfds);
	FD_SET(sockfd, &readfds);
	//We want a truly nonblocking call so...
	struct timeval timeoutval;
	timeoutval.tv_sec = 10;
	timeoutval.tv_usec = 0;
    map<string, deque<struct message *> > outputbuffers;
    map<int, hostIP>::iterator it;
    struct cidrprefix tempFix;
    for(it = endIPs.begin(); it != endIPs.end(); it++) {
		inet_pton(AF_INET, (*it).second.overlay.c_str(), (void *)&tempFix.prefix);
		tempFix.size = 32;
		hosts.insert(tempFix, (*it).second.real);
		outputbuffers[(*it).second.real] = *(new deque<struct message *>);	//Try to access the output buffer for this IP, but since it won't exist, create one.
		#ifdef DEBUG
			cout << "I just inserted " << hosts.search(tempFix.prefix) << endl;
		#endif
	}
		
    while(TRUE){
        //check if we have anything to read
        FD_ZERO(&readfds);
		FD_SET(sockfd, &readfds);
        select(sockfd+1, &readfds, NULL, NULL, &timeoutval);
        //while we have a packet to receive, handle it
        if(FD_ISSET(sockfd, &readfds)){
			#ifdef DEBUG
				cout << "Received a packet!" << endl;
			#endif
            struct message *receivemessage = new struct message();
            receivemessage->buffer = (char*)malloc(MAX_PACKET_SIZE);
            cs3516_recv(sockfd, receivemessage->buffer, MAX_PACKET_SIZE);
            time(&(receivemessage->recvtime));
            iphdr *ip = (iphdr*)(receivemessage->buffer);
	        
	        //get the real ip address of the destination
	        string interface = hosts.search((uint32_t)(ip->daddr)); 
	        cout << "Going to router: " << interface << endl;
	        deque<struct message *> outputqueue;
	        //Get some info from the packet for logging purposes
	        char srcstr[INET_ADDRSTRLEN], dststr[INET_ADDRSTRLEN];
            inet_ntop(AF_INET, &(ip->saddr), srcstr, INET_ADDRSTRLEN);
	        inet_ntop(AF_INET, &(ip->daddr), dststr, INET_ADDRSTRLEN);
	        cout << "This fella is going to " << dststr << endl;
	        short id = ntohs(ip->id);
	        //get the output queue
	        cout << "Interface: " << interface << endl;
	        if(outputbuffers.find(interface)!=outputbuffers.end()){
	            outputqueue = outputbuffers.find(interface)->second;
	        } else {
	            //we don't know who this is! Log it and drop that packet like it's hot
	            writetolog(srcstr, dststr, id, "NO_ROUTE_TO_HOST", "");
	            continue;
	        }
	        //decrement the ttl value
            (ip->ttl)--;
            if((ip->ttl)>0){
                if(outputqueue.size()<=configuration.queueLength){
                    outputbuffers[interface].push_back(receivemessage);
                    writetolog(srcstr, dststr, id, "SENT_OK", interface);
                } else {
                    //drop the packet and log
                    writetolog(srcstr, dststr, id, "MAX_SENDQ_EXCEEDED", "");
                }
            } else {
                //drop the packet and log
                writetolog(srcstr, dststr, id, "TTL_EXPIRED", "");
            }
        }
        //look at queues to see if any send delays have elapsed
        //TODO per-queue send delay as specified by the assignment
	    for(map<string, deque<struct message *> >::iterator i = outputbuffers.begin(); i != outputbuffers.end(); i++) {
	    	string interface = (*i).first;
	    	double delay = 0;
	    	bool isRouter = false;
	    	int hostToSend = lookupHost(interface, &isRouter);
	    	if(isRouter)
				delay = routerRouter[hostToSend].sendDelay;
			else
				delay = routerEnd[hostToSend].sendDelay;
	    	deque<struct message *> buffer = (*i).second;
		    if(buffer.size()>0){
		        struct message* currentmsg = buffer.front();
		        time_t currenttime;
		        time(&currenttime);
		        double waited = difftime(currenttime, currentmsg->recvtime);
		        if(waited>(delay/1000)){
		            unsigned int interfacebytes;
		            //convert address to bytes
		            inet_pton(AF_INET, (char*)interface.c_str(), (void *)&interfacebytes);
		            #ifdef DEBUG
						cout << "Down to the nitty-gritty: sending the packet." << endl;
					#endif
		            int status = cs3516_send(sockfd, currentmsg->buffer, MAX_PACKET_SIZE, interfacebytes);
                    //if(status) sent = TRUE;
                    if(!status) fprintf(stderr, "There was an error sending the file. No bytes were sent.");
                    //free(currentmsg->buffer);
                    delete currentmsg;
                    outputbuffers[interface].pop_front();
                }
		    }
	    }
    }
}