/*
	ZazouMiniWebServer

	Copyright (C) 2003-2011 Xavier Garreau <xavier@xgarreau.org>

	This file is part of ZazouMiniWebServer.

    ZazouMiniWebServer is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 2 of the License, or
    (at your option) any later version.

    ZazouMiniWebServer is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with ZazouMiniWebServer; if not, write to the Free Software
    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
*/
	
#include "stdafx.h"
#include "ZMWSResolver.h" // class's header file
#include "ZOSAL.h"

CRITICAL_SECTION* ZMWSResolver::resolverCS = NULL;
hosts_map_type ZMWSResolver::hosts_map;

// class constructor
ZMWSResolver::ZMWSResolver()
{
}

// class destructor
ZMWSResolver::~ZMWSResolver()
{
	hosts_map.clear();
	if (resolverCS) {
		DeleteCriticalSection(resolverCS);
		resolverCS = NULL;
	}
}

std::string ZMWSResolver::getHostName(struct in_addr addr)
{
/* test - was:
	unsigned long laddr = addr.S_un.S_addr;
	if (addr.S_un.S_un_b.s_b1==127) {
		return "localhost";
	}

	// TODO : Problems when resolving class A IPs
	if (addr.S_un.S_un_b.s_b1==10) {
		return "";
	}
*/
	// Façon "multiplateforme" d'accéder à l'IP dans une struct in_addr ...
	unsigned long laddr = *((unsigned long*)(&addr));
	if (laddr >> 24 == 127) {
		return "localhost";
	}

	// TODO : Problems when resolving private class A IPs on windows
	// TODO : Check this with private class B IPs
	if (laddr >> 24==10) {
		return "";
	}

	if (!resolverCS) {
		resolverCS = new CRITICAL_SECTION;
		InitializeCriticalSection(resolverCS);
	}

	std::string hostname = "";
	EnterCriticalSection(resolverCS);
	if (hosts_map.find(laddr) == hosts_map.end()) {
	LeaveCriticalSection(resolverCS);
	HOSTENT* he = gethostbyaddr((const char *)&(addr), sizeof(struct in_addr), AF_INET);
	if (he && he->h_name) {
		hostname = he->h_name;
	} else {
		EnterCriticalSection(resolverCS);
		/* TODO: Add a better cache system to the resolver
			Erasing the whole map is not a acceptable solution */
		if (hosts_map.size() >= 204800) {
		hosts_map.clear();
		}    
		hosts_map[laddr] = 0;
		LeaveCriticalSection(resolverCS);
	}    
	} else {	
		LeaveCriticalSection(resolverCS);
	}		
	return hostname;
}

