123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277 |
- /*
- ** 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 "wac_network_dns.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;
- };
- wa::Components::WAC_Network_AsyncDNS::WAC_Network_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 );
- if ( m_cache )
- memset( m_cache, 0, sizeof( cache_entry ) * m_cache_size );
- else
- m_cache_size = 0;
- }
- wa::Components::WAC_Network_AsyncDNS::~WAC_Network_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 wa::Components::WAC_Network_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 wa::Components::WAC_Network_AsyncDNS::_threadfunc( LPVOID _d )
- #else
- unsigned int WAC_Network_AsyncDNS::_threadfunc( void *_d )
- #endif
- {
- int nowinsock = JNL::open_socketlib();
- wa::Components::WAC_Network_AsyncDNS *_this = (WAC_Network_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 wa::Components::WAC_Network_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;
- }
- void wa::Components::WAC_Network_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;
- }
- }
- }
- #define CBCLASS wa::Components::WAC_Network_AsyncDNS
- START_DISPATCH;
- CB( API_DNS_RESOLVE, resolve );
- END_DISPATCH;
- #undef CBCLASS
|