00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013 #include "asyncdns.h"
00014 #include "asyncdnshandler.h"
00015 #include "dns.h"
00016 #include "mutexguard.h"
00017 #include "thread.h"
00018 #include "util.h"
00019
00020 namespace gloox
00021 {
00022
00023 #if ( defined( _WIN32 ) && !defined( __SYMBIAN32__ ) ) || defined( HAVE_PTHREAD )
00024
00025 class AsyncDNSWorker : public util::Thread
00026 {
00027 public:
00036 AsyncDNSWorker( AsyncDNSHandler* adh, const std::string& service, const std::string& proto,
00037 const std::string& domain, const LogSink& logInstance );
00038
00046 AsyncDNSWorker( AsyncDNSHandler* adh, const std::string& host,
00047 const LogSink& logInstance );
00048
00057 AsyncDNSWorker( AsyncDNSHandler* adh, const std::string& host, int port,
00058 const LogSink& logInstance );
00059
00063 virtual ~AsyncDNSWorker();
00064
00065 protected:
00066
00067 virtual void run();
00068
00069 private:
00070 enum JobType
00071 {
00072 Resolve,
00073 ConnectResolve,
00074 Connect
00075 };
00076
00077 void* m_context;
00078 AsyncDNSHandler* m_adh;
00079 std::string m_service;
00080 std::string m_proto;
00081 std::string m_domain;
00082 std::string m_host;
00083 int m_port;
00084 const LogSink& m_logInstance;
00085
00086 JobType m_type;
00087
00088 };
00089
00090 AsyncDNSWorker::AsyncDNSWorker( AsyncDNSHandler* adh, const std::string& service,
00091 const std::string& proto, const std::string& domain,
00092 const LogSink& logInstance )
00093 : m_adh( adh ), m_service( service ), m_proto( proto ), m_domain( domain ), m_port( -1 ),
00094 m_logInstance( logInstance ), m_type( Resolve )
00095 {
00096 }
00097
00098 AsyncDNSWorker::AsyncDNSWorker( AsyncDNSHandler* adh, const std::string& host,
00099 const LogSink& logInstance )
00100 : m_adh( adh ), m_host( host ), m_port( -1 ), m_logInstance( logInstance ),
00101 m_type( ConnectResolve )
00102 {
00103 }
00104
00105 AsyncDNSWorker::AsyncDNSWorker( AsyncDNSHandler* adh, const std::string& host, int port,
00106 const LogSink& logInstance )
00107 : m_adh( adh ), m_host( host ), m_port( port ), m_logInstance( logInstance ),
00108 m_type( Connect )
00109 {
00110 }
00111
00112 AsyncDNSWorker::~AsyncDNSWorker()
00113 {
00114 }
00115
00116 void AsyncDNSWorker::run()
00117 {
00118 switch( m_type )
00119 {
00120 case Resolve:
00121 {
00122 const DNS::HostMap& hm = DNS::resolve( m_service, m_proto, m_domain, m_logInstance );
00123 m_adh->handleAsyncResolveResult( hm, this );
00124 break;
00125 }
00126 case ConnectResolve:
00127 {
00128 int fd = DNS::connect( m_host, m_logInstance );
00129 m_adh->handleAsyncConnectResult( fd, this );
00130 break;
00131 }
00132 case Connect:
00133 {
00134 int fd = DNS::connect( m_host, m_port, m_logInstance );
00135 m_adh->handleAsyncConnectResult( fd, this );
00136 break;
00137 }
00138 }
00139 }
00140
00141
00142
00143 AsyncDNS::AsyncDNS()
00144 {
00145 }
00146
00147 AsyncDNS::~AsyncDNS()
00148 {
00149 WorkerMap::iterator it = m_workers.begin();
00150 for( ; it != m_workers.end(); ++it )
00151 {
00152 delete (*it).first;
00153 }
00154
00155 util::clearList( m_obsoleteWorkers );
00156 }
00157
00158 void AsyncDNS::resolve( AsyncDNSHandler* adh, const std::string& service, const std::string& proto,
00159 const std::string& domain, const LogSink& logInstance, void* context )
00160 {
00161 m_obsoleteWorkerMutex.lock();
00162 util::clearList( m_obsoleteWorkers );
00163 m_obsoleteWorkerMutex.unlock();
00164
00165 AsyncDNSWorker* adw = new AsyncDNSWorker( this, service, proto, domain, logInstance );
00166 AsyncContext ac( adh, context );
00167 m_workerMutex.lock();
00168 m_workers.insert( std::make_pair( adw, ac ) );
00169 m_workerMutex.unlock();
00170 adw->start();
00171 }
00172
00173 void AsyncDNS::connect( AsyncDNSHandler* adh, const std::string& host,
00174 const LogSink& logInstance, void* context )
00175 {
00176 m_obsoleteWorkerMutex.lock();
00177 util::clearList( m_obsoleteWorkers );
00178 m_obsoleteWorkerMutex.unlock();
00179
00180 AsyncDNSWorker* adw = new AsyncDNSWorker( this, host, logInstance );
00181 AsyncContext ac( adh, context );
00182 m_workerMutex.lock();
00183 m_workers.insert( std::make_pair( adw, ac ) );
00184 m_workerMutex.unlock();
00185 adw->start();
00186 }
00187
00188 void AsyncDNS::connect( AsyncDNSHandler* adh, const std::string& host, int port,
00189 const LogSink& logInstance, void* context )
00190 {
00191 m_obsoleteWorkerMutex.lock();
00192 util::clearList( m_obsoleteWorkers );
00193 m_obsoleteWorkerMutex.unlock();
00194
00195 AsyncDNSWorker* adw = new AsyncDNSWorker( this, host, port, logInstance );
00196 AsyncContext ac( adh, context );
00197 m_workerMutex.lock();
00198 m_workers.insert( std::make_pair( adw, ac ) );
00199 m_workerMutex.unlock();
00200 adw->start();
00201 }
00202
00203 void AsyncDNS::handleAsyncResolveResult( const DNS::HostMap& hosts, void* context )
00204 {
00205 AsyncDNSWorker* adw = static_cast<AsyncDNSWorker*>( context );
00206
00207 util::MutexGuard mg( m_workerMutex );
00208 WorkerMap::iterator it = m_workers.begin();
00209 for( ; it != m_workers.end(); ++it )
00210 {
00211 if( (*it).first == adw )
00212 {
00213 AsyncDNSHandler* adh = (*it).second.handler;
00214 void* ctx = (*it).second.context;
00215 m_obsoleteWorkerMutex.lock();
00216 m_obsoleteWorkers.push_back( (*it).first );
00217 m_obsoleteWorkerMutex.unlock();
00218 m_workers.erase( it );
00219 adh->handleAsyncResolveResult( hosts, ctx );
00220 return;
00221 }
00222 }
00223 }
00224
00225 void AsyncDNS::handleAsyncConnectResult( int fd, void* context )
00226 {
00227 AsyncDNSWorker* adw = static_cast<AsyncDNSWorker*>( context );
00228
00229 util::MutexGuard mg( m_workerMutex );
00230 WorkerMap::iterator it = m_workers.begin();
00231 for( ; it != m_workers.end(); ++it )
00232 {
00233 if( (*it).first == adw )
00234 {
00235 AsyncDNSHandler* adh = (*it).second.handler;
00236 void* ctx = (*it).second.context;
00237 m_obsoleteWorkerMutex.lock();
00238 m_obsoleteWorkers.push_back( (*it).first );
00239 m_obsoleteWorkerMutex.unlock();
00240 m_workers.erase( it );
00241 adh->handleAsyncConnectResult( fd, ctx );
00242 return;
00243 }
00244 }
00245 }
00246
00247 #else
00248
00249 #endif // WANT_ASYNC_DNS
00250
00251 }