gloox  1.1-svn
asyncdns.cpp
1 /*
2  Copyright (c) 2009 by Jakob Schroeter <js@camaya.net>
3  This file is part of the gloox library. http://camaya.net/gloox
4 
5  This software is distributed under a license. The full license
6  agreement can be found in the file LICENSE in this distribution.
7  This software may not be copied, modified, sold or distributed
8  other than expressed in the named license agreement.
9 
10  This software is distributed without any warranty.
11 */
12 
13 #include "asyncdns.h"
14 #include "asyncdnshandler.h"
15 #include "dns.h"
16 #include "mutexguard.h"
17 #include "thread.h"
18 #include "util.h"
19 
20 namespace gloox
21 {
22 
23 #if ( defined( _WIN32 ) && !defined( __SYMBIAN32__ ) ) || defined( HAVE_PTHREAD )
24 
25  class AsyncDNSWorker : public util::Thread
26  {
27  public:
36  AsyncDNSWorker( AsyncDNSHandler* adh, const std::string& service, const std::string& proto,
37  const std::string& domain, const LogSink& logInstance );
38 
46  AsyncDNSWorker( AsyncDNSHandler* adh, const std::string& host,
47  const LogSink& logInstance );
48 
57  AsyncDNSWorker( AsyncDNSHandler* adh, const std::string& host, int port,
58  const LogSink& logInstance );
59 
63  virtual ~AsyncDNSWorker();
64 
65  protected:
66  // reimplemented from Thread
67  virtual void run();
68 
69  private:
70  enum JobType
71  {
72  Resolve,
73  ConnectResolve,
74  Connect
75  };
76 
77  void* m_context;
78  AsyncDNSHandler* m_adh;
79  std::string m_service;
80  std::string m_proto;
81  std::string m_domain;
82  std::string m_host;
83  int m_port;
84  const LogSink& m_logInstance;
85 
86  JobType m_type;
87 
88  };
89 
90  AsyncDNSWorker::AsyncDNSWorker( AsyncDNSHandler* adh, const std::string& service,
91  const std::string& proto, const std::string& domain,
92  const LogSink& logInstance )
93  : m_adh( adh ), m_service( service ), m_proto( proto ), m_domain( domain ), m_port( -1 ),
94  m_logInstance( logInstance ), m_type( Resolve )
95  {
96  }
97 
98  AsyncDNSWorker::AsyncDNSWorker( AsyncDNSHandler* adh, const std::string& host,
99  const LogSink& logInstance )
100  : m_adh( adh ), m_host( host ), m_port( -1 ), m_logInstance( logInstance ),
101  m_type( ConnectResolve )
102  {
103  }
104 
105  AsyncDNSWorker::AsyncDNSWorker( AsyncDNSHandler* adh, const std::string& host, int port,
106  const LogSink& logInstance )
107  : m_adh( adh ), m_host( host ), m_port( port ), m_logInstance( logInstance ),
108  m_type( Connect )
109  {
110  }
111 
112  AsyncDNSWorker::~AsyncDNSWorker()
113  {
114  }
115 
116  void AsyncDNSWorker::run()
117  {
118  switch( m_type )
119  {
120  case Resolve:
121  {
122  const DNS::HostMap& hm = DNS::resolve( m_service, m_proto, m_domain, m_logInstance );
123  m_adh->handleAsyncResolveResult( hm, this );
124  break;
125  }
126  case ConnectResolve:
127  {
128  int fd = DNS::connect( m_host, m_logInstance );
129  m_adh->handleAsyncConnectResult( fd, this );
130  break;
131  }
132  case Connect:
133  {
134  int fd = DNS::connect( m_host, m_port, m_logInstance );
135  m_adh->handleAsyncConnectResult( fd, this );
136  break;
137  }
138  }
139  }
140  // ---- ~AsyncDNSWorker ----
141 
142  // ---- AsyncDNS ----
144  {
145  }
146 
148  {
149  WorkerMap::iterator it = m_workers.begin();
150  for( ; it != m_workers.end(); ++it )
151  {
152  delete (*it).first;
153  }
154 
155  util::clearList( m_obsoleteWorkers );
156  }
157 
158  void AsyncDNS::resolve( AsyncDNSHandler* adh, const std::string& service, const std::string& proto,
159  const std::string& domain, const LogSink& logInstance, void* context )
160  {
161  m_obsoleteWorkerMutex.lock();
162  util::clearList( m_obsoleteWorkers );
163  m_obsoleteWorkerMutex.unlock();
164 
165  AsyncDNSWorker* adw = new AsyncDNSWorker( this, service, proto, domain, logInstance );
166  AsyncContext ac( adh, context );
167  m_workerMutex.lock();
168  m_workers.insert( std::make_pair( adw, ac ) );
169  m_workerMutex.unlock();
170  adw->start();
171  }
172 
173  void AsyncDNS::connect( AsyncDNSHandler* adh, const std::string& host,
174  const LogSink& logInstance, void* context )
175  {
176  m_obsoleteWorkerMutex.lock();
177  util::clearList( m_obsoleteWorkers );
178  m_obsoleteWorkerMutex.unlock();
179 
180  AsyncDNSWorker* adw = new AsyncDNSWorker( this, host, logInstance );
181  AsyncContext ac( adh, context );
182  m_workerMutex.lock();
183  m_workers.insert( std::make_pair( adw, ac ) );
184  m_workerMutex.unlock();
185  adw->start();
186  }
187 
188  void AsyncDNS::connect( AsyncDNSHandler* adh, const std::string& host, int port,
189  const LogSink& logInstance, void* context )
190  {
191  m_obsoleteWorkerMutex.lock();
192  util::clearList( m_obsoleteWorkers );
193  m_obsoleteWorkerMutex.unlock();
194 
195  AsyncDNSWorker* adw = new AsyncDNSWorker( this, host, port, logInstance );
196  AsyncContext ac( adh, context );
197  m_workerMutex.lock();
198  m_workers.insert( std::make_pair( adw, ac ) );
199  m_workerMutex.unlock();
200  adw->start();
201  }
202 
203  void AsyncDNS::handleAsyncResolveResult( const DNS::HostMap& hosts, void* context )
204  {
205  AsyncDNSWorker* adw = static_cast<AsyncDNSWorker*>( context );
206 
207  util::MutexGuard mg( m_workerMutex );
208  WorkerMap::iterator it = m_workers.begin();
209  for( ; it != m_workers.end(); ++it )
210  {
211  if( (*it).first == adw )
212  {
213  AsyncDNSHandler* adh = (*it).second.handler;
214  void* ctx = (*it).second.context;
215  m_obsoleteWorkerMutex.lock();
216  m_obsoleteWorkers.push_back( (*it).first );
217  m_obsoleteWorkerMutex.unlock();
218  m_workers.erase( it );
219  adh->handleAsyncResolveResult( hosts, ctx );
220  return;
221  }
222  }
223  }
224 
225  void AsyncDNS::handleAsyncConnectResult( int fd, void* context )
226  {
227  AsyncDNSWorker* adw = static_cast<AsyncDNSWorker*>( context );
228 
229  util::MutexGuard mg( m_workerMutex );
230  WorkerMap::iterator it = m_workers.begin();
231  for( ; it != m_workers.end(); ++it )
232  {
233  if( (*it).first == adw )
234  {
235  AsyncDNSHandler* adh = (*it).second.handler;
236  void* ctx = (*it).second.context;
237  m_obsoleteWorkerMutex.lock();
238  m_obsoleteWorkers.push_back( (*it).first );
239  m_obsoleteWorkerMutex.unlock();
240  m_workers.erase( it );
241  adh->handleAsyncConnectResult( fd, ctx );
242  return;
243  }
244  }
245  }
246 
247 #else
248 
249 #endif // WANT_ASYNC_DNS
250 
251 }