cog/Frameworks/JNetLib/jnetlib/asyncdns.cpp

263 lines
5.6 KiB
C++
Executable File

/*
** JNetLib
** Copyright (C) 2000-2001 Nullsoft, Inc.
** Author: Justin Frankel
** File: asyncdns.cpp - JNL portable asynchronous DNS implementation
** License: see jnetlib.h
*/
#include "netinc.h"
#include "util.h"
#include "asyncdns.h"
JNL_AsyncDNS::JNL_AsyncDNS(int max_cache_entries)
{
m_thread_kill=1;
m_thread=0;
m_cache_size=max_cache_entries;
m_cache=(cache_entry *)::malloc(sizeof(cache_entry)*m_cache_size);
memset(m_cache,0,sizeof(cache_entry)*m_cache_size);
}
JNL_AsyncDNS::~JNL_AsyncDNS()
{
#ifndef NO_DNS_SUPPORT
m_thread_kill=1;
#ifdef _WIN32
if (m_thread)
{
WaitForSingleObject(m_thread,INFINITE);
CloseHandle(m_thread);
}
#else
if (m_thread)
{
void *p;
pthread_join(m_thread,&p);
}
#endif//!_WIN32
#endif//NO_DNS_SUPPORT
free(m_cache);
}
#ifdef _WIN32
unsigned long WINAPI JNL_AsyncDNS::_threadfunc(LPVOID _d)
#else
unsigned int JNL_AsyncDNS::_threadfunc(void *_d)
#endif
{
#ifndef NO_DNS_SUPPORT
int nowinsock=JNL::open_socketlib();
JNL_AsyncDNS *_this=(JNL_AsyncDNS*)_d;
int x;
for (x = 0; x < _this->m_cache_size && !_this->m_thread_kill; x ++)
{
if (_this->m_cache[x].last_used && !_this->m_cache[x].resolved)
{
if (!nowinsock)
{
if (_this->m_cache[x].mode==0)
{
struct hostent *hostentry;
hostentry=::gethostbyname(_this->m_cache[x].hostname);
if (hostentry)
{
_this->m_cache[x].addr=*((int*)hostentry->h_addr);
}
else
_this->m_cache[x].addr=INADDR_NONE;
}
else if (_this->m_cache[x].mode==1)
{
struct hostent *ent;
ent=::gethostbyaddr((const char *)&_this->m_cache[x].addr,4,AF_INET);
if (ent)
{
strncpy(_this->m_cache[x].hostname,ent->h_name,255);
_this->m_cache[x].hostname[255]=0;
}
else
{
_this->m_cache[x].hostname[0]=0;
}
}
_this->m_cache[x].resolved=1;
}
else
{
if (_this->m_cache[x].mode==0)
{
_this->m_cache[x].addr=INADDR_NONE;
_this->m_cache[x].resolved=1;
}
else if (_this->m_cache[x].mode==1)
{
_this->m_cache[x].hostname[0]=0;
_this->m_cache[x].resolved=1;
}
}
}
}
if (!nowinsock) JNL::close_socketlib();
_this->m_thread_kill=1;
#endif // NO_DNS_SUPPORT
return 0;
}
int JNL_AsyncDNS::resolve(char *hostname, unsigned long *addr)
{
// return 0 on success, 1 on wait, -1 on unresolvable
int x;
unsigned long ip=inet_addr(hostname);
if (ip != INADDR_NONE)
{
*addr=ip;
return 0;
}
#ifndef NO_DNS_SUPPORT
for (x = 0; x < m_cache_size; x ++)
{
if (!strcasecmp(m_cache[x].hostname,hostname) && m_cache[x].mode==0)
{
m_cache[x].last_used=time(NULL);
if (m_cache[x].resolved)
{
if (m_cache[x].addr == INADDR_NONE)
{
return -1;
}
struct in_addr in;
in.s_addr=m_cache[x].addr;
*addr=m_cache[x].addr;
return 0;
}
makesurethreadisrunning();
return 1;
}
}
// add to resolve list
int oi=-1;
for (x = 0; x < m_cache_size; x ++)
{
if (!m_cache[x].last_used)
{
oi=x;
break;
}
if ((oi==-1 || m_cache[x].last_used < m_cache[oi].last_used) && m_cache[x].resolved)
{
oi=x;
}
}
if (oi == -1)
{
return -1;
}
strcpy(m_cache[oi].hostname,hostname);
m_cache[oi].mode=0;
m_cache[oi].addr=INADDR_NONE;
m_cache[oi].resolved=0;
m_cache[oi].last_used=time(NULL);
makesurethreadisrunning();
return 1;
#else
return -1;
#endif
}
int JNL_AsyncDNS::reverse(unsigned long addr, char *hostname)
{
// return 0 on success, 1 on wait, -1 on unresolvable
int x;
if (addr == INADDR_NONE)
{
return -1;
}
#ifndef NO_DNS_SUPPORT
for (x = 0; x < m_cache_size; x ++)
{
if (m_cache[x].addr==addr && m_cache[x].mode==1)
{
m_cache[x].last_used=time(NULL);
if (m_cache[x].resolved)
{
if (!m_cache[x].hostname[0])
{
return -1;
}
strncpy(hostname,m_cache[x].hostname,255);
hostname[255]=0;
return 0;
}
makesurethreadisrunning();
return 1;
}
}
// add to resolve list
int oi=-1;
for (x = 0; x < m_cache_size; x ++)
{
if (!m_cache[x].last_used)
{
oi=x;
break;
}
if ((oi==-1 || m_cache[x].last_used < m_cache[oi].last_used) && m_cache[x].resolved)
{
oi=x;
}
}
if (oi == -1)
{
return -1;
}
m_cache[oi].addr=addr;
m_cache[oi].hostname[0]=0;
m_cache[oi].resolved=0;
m_cache[oi].mode=1;
m_cache[oi].last_used=time(NULL);
makesurethreadisrunning();
return 1;
#else
return -1;
#endif
}
void JNL_AsyncDNS::makesurethreadisrunning(void)
{
#ifndef NO_DNS_SUPPORT
if (m_thread_kill)
{
#ifdef _WIN32
if (m_thread)
{
WaitForSingleObject(m_thread,INFINITE);
CloseHandle(m_thread);
}
DWORD id;
m_thread_kill=0;
m_thread=CreateThread(NULL,0,_threadfunc,(LPVOID)this,0,&id);
if (!m_thread)
{
#else
if (m_thread)
{
void *p;
pthread_join(m_thread,&p);
}
m_thread_kill=0;
if (pthread_create(&m_thread,NULL,(void *(*) (void *))_threadfunc,(void*)this) != 0)
{
#endif
m_thread_kill=1;
}
}
#endif//NO_DNS_SUPPORT
}