123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314 |
- /*
- ** JNetLib
- ** Copyright (C) 2000-2007 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"
- #include <time.h>
- #ifdef _WIN32
- #include <strsafe.h>
- #endif
- enum
- {
- MODE_RESOLVE=0,
- MODE_REVERSE=1,
- };
- struct cache_entry
- {
- time_t last_used; // timestamp.
- bool resolved;
- int mode; // 1=reverse
- unsigned short port;
- char hostname[256];
- addrinfo *addr;
- int sockettype;
- };
- 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()
- {
- 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
- // free all the addrinfo stuff
- for (int x = 0; x < m_cache_size; x ++)
- {
- if (m_cache[x].addr)
- freeaddrinfo(m_cache[x].addr);
- }
- free(m_cache);
- }
- int JNL_AsyncDNS::resolvenow(const char *hostname, unsigned short port, addrinfo **addr, int sockettype)
- {
- addrinfo hints;
- memset(&hints,0,sizeof(hints));
- hints.ai_family = PF_UNSPEC;
- if (hostname)
- hints.ai_flags = AI_NUMERICHOST;
- else
- hints.ai_flags = AI_NUMERICHOST | AI_PASSIVE;
- hints.ai_socktype = sockettype;
- char portString[32] = {0};
- sprintf(portString, "%u", (unsigned int)port);
- if (getaddrinfo(hostname, portString, &hints, addr) == 0)
- {
- return 0;
- }
- else
- {
- hints.ai_flags = 0;
- if (getaddrinfo(hostname, portString, &hints, addr) == 0)
- {
- return 0;
- }
- else
- {
- return -1;
- }
- }
- }
- #ifdef _WIN32
- unsigned long WINAPI JNL_AsyncDNS::_threadfunc(LPVOID _d)
- #else
- unsigned int JNL_AsyncDNS::_threadfunc(void *_d)
- #endif
- {
- 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)
- {
- addrinfo *res=0;
- if (resolvenow(_this->m_cache[x].hostname, _this->m_cache[x].port, &res, _this->m_cache[x].sockettype) == 0)
- {
- _this->m_cache[x].addr=res;
- }
- else
- {
- _this->m_cache[x].addr=0;//INADDR_NONE;
- }
- }
- else if (_this->m_cache[x].mode==1)
- {
- /*
- hostent *ent;
- // TODO: replace with getnameinfo for IPv6
- ent=gethostbyaddr((const char *)&_this->m_cache[x].addr,4,AF_INET);
- if (ent)
- lstrcpyn(_this->m_cache[x].hostname, ent->h_name, 256);
- else
- _this->m_cache[x].hostname[0]=0;
- */
- }
- _this->m_cache[x].resolved=true;
- }
- else
- {
- if (_this->m_cache[x].mode==0)
- {
- _this->m_cache[x].addr=0;//INADDR_NONE;
- _this->m_cache[x].resolved=true;
- }
- else if (_this->m_cache[x].mode==1)
- {
- _this->m_cache[x].hostname[0]=0;
- _this->m_cache[x].resolved=true;
- }
- }
- }
- }
- if (!nowinsock) JNL::close_socketlib();
- _this->m_thread_kill=1;
- return 0;
- }
- int JNL_AsyncDNS::resolve(const char *hostname, unsigned short port, addrinfo **addr, int sockettype)
- {
- // return 0 on success, 1 on wait, -1 on unresolvable
- int x;
- for (x = 0; x < m_cache_size; x ++)
- {
- if (!strcasecmp(m_cache[x].hostname,hostname) && port == m_cache[x].port && m_cache[x].mode==0 && m_cache[x].sockettype==sockettype)
- {
- m_cache[x].last_used=time(0);
- if (m_cache[x].resolved)
- {
- if (m_cache[x].addr == 0)//INADDR_NONE)
- {
- return DNS_RESOLVE_UNRESOLVABLE;
- }
- *addr =m_cache[x].addr;
- return DNS_RESOLVE_SUCCESS;
- }
- makesurethreadisrunning();
- return DNS_RESOLVE_WAIT;
- }
- }
- // 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 DNS_RESOLVE_UNRESOLVABLE;
- }
- #ifdef _WIN32
- StringCchCopyA(m_cache[oi].hostname, 256, hostname);
- #elif defined(__APPLE__)
- strlcpy(m_cache[oi].hostname, hostname, 255);
- #else
- strncpy(m_cache[oi].hostname, hostname, 255);
- m_cache[oi].hostname[255]=0;
- #endif
- m_cache[oi].port=port;
- m_cache[oi].mode=0;
- m_cache[oi].addr=0;//INADDR_NONE;
- m_cache[oi].resolved=false;
- m_cache[oi].last_used=time(0);
- m_cache[oi].sockettype=sockettype;
- makesurethreadisrunning();
- return DNS_RESOLVE_WAIT;
- }
- /*
- int JNL_AsyncDNS::reverse(unsigned long addr, char *hostname, size_t hostnameSize)
- {
- // return 0 on success, 1 on wait, -1 on unresolvable
- int x;
- if (addr == INADDR_NONE)
- {
- return DNS_REVERSE_UNRESOLVABLE;
- }
- #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(0);
- if (m_cache[x].resolved)
- {
- if (!m_cache[x].hostname[0])
- {
- return DNS_REVERSE_UNRESOLVABLE;
- }
- lstrcpyn(hostname,m_cache[x].hostname, hostnameSize);
- return DNS_REVERSE_SUCCESS;
- }
- makesurethreadisrunning();
- return DNS_REVERSE_WAIT;
- }
- }
- // 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 DNS_REVERSE_UNRESOLVABLE;
- }
- m_cache[oi].addr=addr;
- m_cache[oi].hostname[0]=0;
- m_cache[oi].resolved=false;
- m_cache[oi].mode=1;
- m_cache[oi].last_used=time(0);
- makesurethreadisrunning();
- return DNS_REVERSE_WAIT;
- #else
- return DNS_REVERSE_UNRESOLVABLE;
- #endif
- }
- */
- void JNL_AsyncDNS::makesurethreadisrunning(void)
- {
- 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;
- }
- }
- }
|