00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #include <netcomm/utils/resolver_thread.h>
00025 #include <netcomm/utils/resolver.h>
00026 #ifdef HAVE_AVAHI
00027 #include <netcomm/dns-sd/avahi_thread.h>
00028 #endif
00029 #include <core/exceptions/system.h>
00030
00031 #include <sys/types.h>
00032 #include <netdb.h>
00033 #include <netinet/in.h>
00034 #include <cstring>
00035 #include <cstdlib>
00036
00037 namespace fawkes {
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060 NetworkNameResolverThread::NetworkNameResolverThread(NetworkNameResolver *resolver,
00061 AvahiThread *avahi_thread)
00062 : Thread("NetworkNameResolverThread", Thread::OPMODE_WAITFORWAKEUP)
00063 {
00064 __resolver = resolver;
00065 __addrq_mutex = new Mutex();
00066 __namesq_mutex = new Mutex();
00067
00068 __namesq_active = 0;
00069 __namesq = &__namesqs[0];
00070 __namesq_proc = &__namesqs[1];
00071
00072 __addrq_active = 0;
00073 __addrq = &__addrqs[0];
00074 __addrq_proc = &__addrqs[1];
00075
00076 #ifdef HAVE_AVAHI
00077 __avahi_thread = avahi_thread;
00078 #endif
00079 }
00080
00081
00082 NetworkNameResolverThread::~NetworkNameResolverThread()
00083 {
00084 __namesq_mutex->lock();
00085 while ( ! __namesq->empty() ) {
00086 NamesQMap::iterator nqit = __namesq->begin();
00087 char *nqn = (*nqit);
00088 __namesq->erase(nqit);
00089 free(nqn);
00090 }
00091 while ( ! __namesq_proc->empty() ) {
00092 NamesQMap::iterator nqit = __namesq_proc->begin();
00093 char *nqn = (*nqit);
00094 __namesq->erase(nqit);
00095 free(nqn);
00096 }
00097 __namesq_mutex->unlock();
00098 __addrq_mutex->lock();
00099 while ( ! __addrq->empty() ) {
00100 AddrQMap::iterator nqit = __addrq->begin();
00101 free(nqit->second.first);
00102 __addrq->erase(nqit);
00103 }
00104
00105
00106
00107 while ( ! __addrq_proc->empty() ) {
00108 AddrQMap::iterator nqit = __addrq_proc->begin();
00109 free(nqit->second.first);
00110 __addrq->erase(nqit);
00111 }
00112 __addrq_mutex->unlock();
00113 delete __addrq_mutex;
00114 delete __namesq_mutex;
00115 }
00116
00117
00118
00119
00120
00121
00122
00123
00124
00125
00126
00127
00128
00129
00130 bool
00131 NetworkNameResolverThread::resolve_name_immediately(const char *name,
00132 struct sockaddr **addr, socklen_t *addr_len)
00133 {
00134 bool found = false;
00135
00136
00137 struct addrinfo *ai;
00138 if ( getaddrinfo(name, NULL, NULL, &ai) == 0 ) {
00139
00140 struct sockaddr *tmp = (struct sockaddr *)malloc(ai->ai_addrlen);
00141 memcpy(tmp, ai->ai_addr, ai->ai_addrlen);
00142 *addr = tmp;
00143 *addr_len = ai->ai_addrlen;
00144 freeaddrinfo(ai);
00145 found = true;
00146 }
00147
00148 #ifdef HAVE_AVAHI
00149
00150 char *n = (char *)name + strlen(name) - 6;
00151 const char *f = strstr(name, ".local");
00152 if ( __avahi_thread && f && (f == n) ) {
00153 __avahi_thread->resolve_name(name, this);
00154
00155
00156
00157
00158
00159
00160
00161
00162
00163
00164
00165
00166 }
00167 #endif
00168
00169 return found;
00170 }
00171
00172
00173
00174
00175
00176
00177
00178
00179
00180
00181
00182
00183
00184
00185
00186 bool
00187 NetworkNameResolverThread::resolve_address_immediately(struct sockaddr *addr, socklen_t addr_len,
00188 char **name, bool *namefound)
00189 {
00190 bool found = false;
00191 char hbuf[NI_MAXHOST];
00192 if ( getnameinfo(addr, addr_len, hbuf, sizeof(hbuf), NULL, 0, NI_NAMEREQD) == 0 ) {
00193 char *tmp = (char *)malloc(strlen(hbuf) + 1);
00194 if ( ! tmp ) {
00195 throw OutOfMemoryException();
00196 }
00197 strcpy(tmp, hbuf);
00198 *name = tmp;
00199 *namefound = true;
00200 found = true;
00201 } else if ( getnameinfo(addr, addr_len, hbuf, sizeof(hbuf), NULL, 0, 0) == 0 ) {
00202 char *tmp = (char *)malloc(strlen(hbuf) + 1);
00203 if ( ! tmp ) {
00204 throw OutOfMemoryException();
00205 }
00206 strcpy(tmp, hbuf);
00207 *name = tmp;
00208 *namefound = false;
00209 found = true;
00210 }
00211
00212 #ifdef HAVE_AVAHI
00213 if ( __avahi_thread ) {
00214 __avahi_thread->resolve_address(addr, addr_len, this);
00215 }
00216 #endif
00217
00218 return found;
00219 }
00220
00221
00222
00223
00224
00225
00226
00227 void
00228 NetworkNameResolverThread::resolve_name(const char *name)
00229 {
00230 __namesq_mutex->lock();
00231 if ( __namesq->find((char *)name) == __namesq->end() ) {
00232 char *tmp = strdup(name);
00233 __namesq->insert(tmp);
00234 __namesq_mutex->unlock();
00235 wakeup();
00236 } else {
00237 __namesq_mutex->unlock();
00238 }
00239 }
00240
00241
00242
00243
00244
00245
00246
00247
00248 void
00249 NetworkNameResolverThread::resolve_address(struct sockaddr *addr, socklen_t addrlen)
00250 {
00251 struct ::sockaddr_in *saddr = (struct ::sockaddr_in *)addr;
00252 __addrq_mutex->lock();
00253 if ( __addrq->find(saddr->sin_addr.s_addr) == __addrq->end() ) {
00254 struct sockaddr *taddr = (struct sockaddr *)malloc(addrlen);
00255 memcpy(taddr, addr, addrlen);
00256 (*__addrq)[saddr->sin_addr.s_addr] = std::make_pair(taddr, addrlen);
00257 __addrq_mutex->unlock();
00258 wakeup();
00259 } else {
00260 __addrq_mutex->unlock();
00261 }
00262 }
00263
00264
00265
00266
00267
00268
00269
00270
00271
00272
00273
00274
00275 void
00276 NetworkNameResolverThread::resolved_name(char *name,
00277 struct sockaddr *addr, socklen_t addrlen)
00278 {
00279 __resolver->name_resolved(name, addr, addrlen);
00280 }
00281
00282
00283
00284
00285
00286
00287
00288
00289
00290
00291
00292
00293 void
00294 NetworkNameResolverThread::resolved_address(struct sockaddr_in *addr, socklen_t addrlen,
00295 char *name)
00296 {
00297 __resolver->addr_resolved((struct sockaddr *)addr, addrlen, name, true);
00298 }
00299
00300
00301
00302
00303
00304
00305
00306
00307
00308 void
00309 NetworkNameResolverThread::name_resolution_failed(char *name)
00310 {
00311 __resolver->name_resolution_failed(name);
00312 }
00313
00314
00315
00316
00317
00318
00319
00320
00321
00322
00323 void
00324 NetworkNameResolverThread::address_resolution_failed(struct sockaddr_in *addr, socklen_t addrlen)
00325 {
00326 __resolver->address_resolution_failed((struct sockaddr *)addr, addrlen);
00327 }
00328
00329
00330
00331
00332
00333 void
00334 NetworkNameResolverThread::loop()
00335 {
00336 __addrq_mutex->lock();
00337 __addrq_proc = __addrq;
00338 __addrq_active = 1 - __addrq_active;
00339 __addrq = &__addrqs[__addrq_active];
00340 __addrq_mutex->unlock();
00341 AddrQMap::iterator aqit;
00342 while ( ! __addrq_proc->empty() ) {
00343 aqit = __addrq_proc->begin();
00344
00345 char *name;
00346 bool namefound;
00347
00348 if ( resolve_address_immediately(aqit->second.first, aqit->second.second, &name, &namefound) ) {
00349 __resolver->addr_resolved(aqit->second.first, aqit->second.second, name, namefound);
00350 } else {
00351 __resolver->address_resolution_failed(aqit->second.first, aqit->second.second);
00352 }
00353 __addrq_proc->erase(aqit);
00354 }
00355
00356 __namesq_mutex->lock();
00357 __namesq_proc = __namesq;
00358 __namesq_active = 1 - __namesq_active;
00359 __namesq = &__namesqs[__namesq_active];
00360 __namesq_mutex->unlock();
00361 NamesQMap::iterator nqit;
00362 while ( ! __namesq_proc->empty() ) {
00363 nqit = __namesq_proc->begin();
00364 char *nqn = (*nqit);
00365
00366 struct sockaddr *addr;
00367 socklen_t addrlen;
00368
00369
00370
00371
00372
00373
00374 if ( resolve_name_immediately(nqn, &addr, &addrlen) ) {
00375 __resolver->name_resolved(strdup(nqn), addr, addrlen);
00376 } else {
00377 __resolver->name_resolution_failed(strdup(nqn));
00378 }
00379 __namesq_proc->erase(nqit);
00380 free(nqn);
00381 }
00382 }
00383
00384 }