kdecore Library API Documentation

kresolverstandardworkers.cpp

00001 /* -*- C++ -*- 00002 * Copyright (C) 2003 Thiago Macieira <thiago.macieira@kdemail.net> 00003 * 00004 * 00005 * Permission is hereby granted, free of charge, to any person obtaining 00006 * a copy of this software and associated documentation files (the 00007 * "Software"), to deal in the Software without restriction, including 00008 * without limitation the rights to use, copy, modify, merge, publish, 00009 * distribute, sublicense, and/or sell copies of the Software, and to 00010 * permit persons to whom the Software is furnished to do so, subject to 00011 * the following conditions: 00012 * 00013 * The above copyright notice and this permission notice shall be included 00014 * in all copies or substantial portions of the Software. 00015 * 00016 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 00017 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 00018 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 00019 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 00020 * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 00021 * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 00022 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 00023 */ 00024 00025 #include <config.h> 00026 00027 #include <sys/types.h> 00028 #include <sys/socket.h> 00029 #include <sys/un.h> 00030 #include <netinet/in.h> 00031 #include <netdb.h> 00032 #include <errno.h> 00033 #include <string.h> 00034 #include <stdlib.h> 00035 00036 #ifdef HAVE_NET_IF_H 00037 #include <net/if.h> 00038 #endif 00039 00040 #include <qthread.h> 00041 #include <qmutex.h> 00042 #include <qstrlist.h> 00043 00044 #include "kresolver.h" 00045 #include "ksocketaddress.h" 00046 #include "kresolver_p.h" 00047 #include "kresolverstandardworkers_p.h" 00048 00049 struct hostent; 00050 struct addrinfo; 00051 00052 using namespace KNetwork; 00053 using namespace KNetwork::Internal; 00054 00055 namespace 00056 { 00057 #ifndef HAVE_GETADDRINFO 00058 class GetHostByNameThread: public KResolverWorkerBase 00059 { 00060 public: 00061 QCString m_hostname; // might be different! 00062 Q_UINT16 m_port; 00063 int m_scopeid; 00064 int m_af; 00065 KResolverResults& results; 00066 00067 GetHostByNameThread(const char * hostname, Q_UINT16 port, 00068 int scopeid, int af, KResolverResults* res) : 00069 m_hostname(hostname), m_port(port), m_scopeid(scopeid), m_af(af), 00070 results(*res) 00071 { } 00072 00073 ~GetHostByNameThread() 00074 { } 00075 00076 virtual bool preprocess() 00077 { return true; } 00078 00079 virtual bool run(); 00080 00081 void processResults(hostent* he, int my_h_errno); 00082 }; 00083 00084 bool GetHostByNameThread::run() 00085 { 00086 /* 00087 * Note on the use of the system resolver functions: 00088 * 00089 * In all cases, we prefer to use the new getaddrinfo(3) call. That means 00090 * it will always be used if it is found. 00091 * 00092 * If it's not found, we have the option to use gethostbyname2_r, 00093 * gethostbyname_r, gethostbyname2 and gethostbyname. If gethostbyname2_r 00094 * is defined, we will use it. 00095 * 00096 * If it's not defined, we have to choose between the non-reentrant 00097 * gethostbyname2 and the reentrant but IPv4-only gethostbyname_r: 00098 * we will choose gethostbyname2 if AF_INET6 is defined. 00099 * 00100 * Lastly, gethostbyname will be used if nothing else is present. 00101 */ 00102 00103 /* 00104 * Note on the use of mutexes: 00105 * if gethostbyname_r and gethostbyname2_r aren't available, we must assume 00106 * that all function calls are non-reentrant. Therefore, we will lock 00107 * a global mutex for protection. 00108 */ 00109 00110 hostent *resultptr; 00111 hostent my_results; 00112 unsigned buflen = 1024; 00113 int res; 00114 int my_h_errno; 00115 char *buf = 0L; 00116 00117 // qDebug("ResolveThread::run(): started threaded gethostbyname for %s (af = %d)", 00118 // m_hostname.data(), m_af); 00119 do 00120 { 00121 res = 0; 00122 my_h_errno = HOST_NOT_FOUND; 00123 00124 # ifdef HAVE_GETHOSTBYNAME2_R 00125 buf = new char[buflen]; 00126 res = gethostbyname2_r(m_hostname, m_af, &my_results, buf, buflen, 00127 &resultptr, &my_h_errno); 00128 00129 # elif defined(HAVE_GETHOSTBYNAME_R) && (!defined(AF_INET6) || !defined(HAVE_GETHOSTBYNAME2)) 00130 if (m_af == AF_INET) 00131 { 00132 buf = new char[buflen]; 00133 res = gethostbyname_r(m_hostname, &my_results, buf, buflen, 00134 &resultptr, &my_h_errno); 00135 } 00136 else 00137 resultptr = 0; // signal error 00138 00139 # elif defined(HAVE_GETHOSTBYNAME2) 00140 // must lock mutex 00141 QMutexLocker locker(&getXXbyYYmutex); 00142 resultptr = gethostbyname2(m_hostname, m_af); 00143 my_h_errno = h_errno; 00144 00145 # else 00146 if (m_af == AF_INET) 00147 { 00148 // must lock mutex 00149 QMutexLocker locker(&getXXbyYYmutex); 00150 resultptr = gethostbyname(m_hostname); 00151 my_h_errno = h_errno; 00152 } 00153 else 00154 resultptr = 0; 00155 # endif 00156 00157 if (resultptr != 0L) 00158 my_h_errno = 0; 00159 // qDebug("GetHostByNameThread::run(): gethostbyname for %s (af = %d) returned: %d", 00160 // m_hostname.data(), m_af, my_h_errno); 00161 00162 if (res == ERANGE) 00163 { 00164 // Enlarge the buffer 00165 buflen += 1024; 00166 delete [] buf; 00167 buf = new char[buflen]; 00168 } 00169 } 00170 while (res == ERANGE); 00171 processResults(resultptr, my_h_errno); 00172 00173 delete [] buf; 00174 00175 finished(); 00176 return results.error() == KResolver::NoError; 00177 } 00178 00179 void GetHostByNameThread::processResults(hostent *he, int herrno) 00180 { 00181 if (herrno) 00182 { 00183 qDebug("KStandardWorker::processResults: got error %d", herrno); 00184 switch (herrno) 00185 { 00186 case HOST_NOT_FOUND: 00187 results.setError(KResolver::NoName); 00188 return; 00189 00190 case TRY_AGAIN: 00191 results.setError(KResolver::TryAgain); 00192 return; 00193 00194 case NO_RECOVERY: 00195 results.setError(KResolver::NonRecoverable); 00196 return; 00197 00198 case NO_ADDRESS: 00199 results.setError(KResolver::NoName); 00200 return; 00201 00202 default: 00203 results.setError(KResolver::UnknownError); 00204 return; 00205 } 00206 } 00207 else if (he == 0L) 00208 { 00209 results.setError(KResolver::NoName); 00210 return; // this was an error 00211 } 00212 00213 // clear any errors 00214 setError(KResolver::NoError); 00215 results.setError(KResolver::NoError); 00216 00217 // we process results in the reverse order 00218 // that is, we prepend each result to the list of results 00219 int proto = protocol(); 00220 int socktype = socketType(); 00221 if (socktype == 0) 00222 socktype = SOCK_STREAM; // default 00223 00224 QString canon = KResolver::domainToUnicode(QString::fromLatin1(he->h_name)); 00225 KInetSocketAddress sa; 00226 sa.setPort(m_port); 00227 if (he->h_addrtype != AF_INET) 00228 sa.setScopeId(m_scopeid); // this will also change the socket into IPv6 00229 00230 for (int i = 0; he->h_addr_list[i]; i++) 00231 { 00232 sa.setHost(KIpAddress(he->h_addr_list[i], he->h_addrtype == AF_INET ? 4 : 6)); 00233 results.prepend(KResolverEntry(sa, socktype, proto, canon, m_hostname)); 00234 // qDebug("KStandardWorker::processResults: adding %s", sa.toString().latin1()); 00235 } 00236 // qDebug("KStandardWorker::processResults: added %d entries", i); 00237 } 00238 00239 #else // HAVE_GETADDRINFO 00240 00241 class GetAddrInfoThread: public KResolverWorkerBase 00242 { 00243 public: 00244 QCString m_node; 00245 QCString m_serv; 00246 int m_af; 00247 KResolverResults& results; 00248 00249 GetAddrInfoThread(const char* node, const char* serv, int af, 00250 KResolverResults* res) : 00251 m_node(node), m_serv(serv), m_af(af), results(*res) 00252 { } 00253 00254 ~GetAddrInfoThread() 00255 { } 00256 00257 virtual bool preprocess() 00258 { return true; } 00259 00260 virtual bool run(); 00261 00262 void processResults(addrinfo* ai, int ret_code, KResolverResults& rr); 00263 }; 00264 00265 bool GetAddrInfoThread::run() 00266 { 00267 # ifdef NEED_MUTEX 00268 // in some platforms, getaddrinfo(3) is not thread-safe nor reentrant 00269 // therefore, we will lock a global mutex (defined in qresolver.cpp) 00270 // relating to all the lookup functions 00271 00272 QMutexLocker locker(&getXXbyYYmutex); 00273 # endif 00274 00275 // process hints 00276 addrinfo hint; 00277 memset(&hint, 0, sizeof(hint)); 00278 hint.ai_family = m_af; 00279 hint.ai_socktype = socketType(); 00280 hint.ai_protocol = protocol(); 00281 00282 if (hint.ai_socktype == 0) 00283 hint.ai_socktype = SOCK_STREAM; // default 00284 00285 if (flags() & KResolver::Passive) 00286 hint.ai_flags |= AI_PASSIVE; 00287 if (flags() & KResolver::CanonName) 00288 hint.ai_flags |= AI_CANONNAME; 00289 # ifdef AI_NUMERICHOST 00290 if (flags() & KResolver::NoResolve) 00291 hint.ai_flags |= AI_NUMERICHOST; 00292 # endif 00293 00294 // now we do the blocking processing 00295 if (m_node.isEmpty()) 00296 m_node = "*"; 00297 00298 addrinfo *result; 00299 int res = getaddrinfo(m_node, m_serv, &hint, &result); 00300 // qDebug("QGetAddrInfoThread::run: getaddrinfo for [%s]:%s (af = %d); result = %d", 00301 // m_node.data(), m_serv.data(), m_af, res); 00302 00303 if (res != 0) 00304 { 00305 switch (res) 00306 { 00307 case EAI_BADFLAGS: 00308 results.setError(KResolver::BadFlags); 00309 break; 00310 00311 #ifdef EAI_NODATA 00312 // In some systems, EAI_NODATA was #define'd to EAI_NONAME which would break this case. 00313 #if EAI_NODATA != EAI_NONAME 00314 case EAI_NODATA: // it was removed in RFC 3493 00315 #endif 00316 #endif 00317 case EAI_NONAME: 00318 results.setError(KResolver::NoName); 00319 break; 00320 00321 case EAI_AGAIN: 00322 results.setError(KResolver::TryAgain); 00323 break; 00324 00325 case EAI_FAIL: 00326 results.setError(KResolver::NonRecoverable); 00327 break; 00328 00329 case EAI_FAMILY: 00330 results.setError(KResolver::UnsupportedFamily); 00331 break; 00332 00333 case EAI_SOCKTYPE: 00334 results.setError(KResolver::UnsupportedSocketType); 00335 break; 00336 00337 case EAI_SERVICE: 00338 results.setError(KResolver::UnsupportedService); 00339 break; 00340 00341 case EAI_MEMORY: 00342 results.setError(KResolver::Memory); 00343 break; 00344 00345 case EAI_SYSTEM: 00346 results.setError(KResolver::SystemError, errno); 00347 break; 00348 00349 default: 00350 results.setError(KResolver::UnknownError, errno); 00351 break; 00352 } 00353 00354 finished(); 00355 return false; // failed 00356 } 00357 00358 // if we are here, lookup succeeded 00359 QString canon; 00360 const char *previous_canon = 0L; 00361 00362 for (addrinfo* p = result; p; p = p->ai_next) 00363 { 00364 // cache the last canon name to avoid doing the ToUnicode processing unnecessarily 00365 if ((previous_canon && !p->ai_canonname) || 00366 (!previous_canon && p->ai_canonname) || 00367 (p->ai_canonname != previous_canon && 00368 strcmp(p->ai_canonname, previous_canon) != 0)) 00369 { 00370 canon = KResolver::domainToUnicode(QString::fromAscii(p->ai_canonname)); 00371 previous_canon = p->ai_canonname; 00372 } 00373 00374 results.append(KResolverEntry(p->ai_addr, p->ai_addrlen, p->ai_socktype, 00375 p->ai_protocol, canon, m_node)); 00376 } 00377 00378 freeaddrinfo(result); 00379 results.setError(KResolver::NoError); 00380 finished(); 00381 return results.error() == KResolver::NoError; 00382 } 00383 00384 #endif // HAVE_GETADDRINFO 00385 } // namespace 00386 00387 bool KStandardWorker::sanityCheck() 00388 { 00389 // check that the requested values are sensible 00390 00391 if (!nodeName().isEmpty()) 00392 { 00393 QString node = nodeName(); 00394 if (node.find('%') != -1) 00395 node.truncate(node.find('%')); 00396 00397 if (node.isEmpty() || node == QString::fromLatin1("*") || 00398 node == QString::fromLatin1("localhost")) 00399 m_encodedName.truncate(0); 00400 else 00401 { 00402 m_encodedName = KResolver::domainToAscii(node); 00403 00404 if (m_encodedName.isNull()) 00405 { 00406 qDebug("could not encode hostname '%s' (UTF-8)", node.utf8().data()); 00407 setError(KResolver::NoName); 00408 return false; // invalid hostname! 00409 } 00410 00411 // qDebug("Using encoded hostname '%s' for '%s' (UTF-8)", m_encodedName.data(), 00412 // node.utf8().data()); 00413 } 00414 } 00415 else 00416 m_encodedName.truncate(0); // just to be sure, but it should be clear already 00417 00418 if (protocol() == -1) 00419 { 00420 setError(KResolver::NonRecoverable); 00421 return false; // user passed invalid protocol name 00422 } 00423 00424 return true; // it's sane 00425 } 00426 00427 bool KStandardWorker::resolveScopeId() 00428 { 00429 // we must test the original name, not the encoded one 00430 scopeid = 0; 00431 int pos = nodeName().findRev('%'); 00432 if (pos == -1) 00433 return true; 00434 00435 QString scopename = nodeName().mid(pos + 1); 00436 00437 bool ok; 00438 scopeid = scopename.toInt(&ok); 00439 if (!ok) 00440 { 00441 // it's not a number 00442 // therefore, it's an interface name 00443 #ifdef HAVE_IF_NAMETOINDEX 00444 scopeid = if_nametoindex(scopename.latin1()); 00445 #else 00446 scopeid = 0; 00447 #endif 00448 } 00449 00450 return true; 00451 } 00452 00453 bool KStandardWorker::resolveService() 00454 { 00455 // find the service first 00456 bool ok; 00457 port = serviceName().toUInt(&ok); 00458 if (!ok) 00459 { 00460 // service name does not contain a port number 00461 // must be a name 00462 00463 if (serviceName().isEmpty() || serviceName().compare(QString::fromLatin1("*")) == 0) 00464 port = 0; 00465 else 00466 { 00467 // it's a name. We need the protocol name in order to lookup. 00468 QCString protoname = protocolName(); 00469 00470 if (protoname.isEmpty() && protocol()) 00471 { 00472 protoname = KResolver::protocolName(protocol()).first(); 00473 00474 // if it's still empty... 00475 if (protoname.isEmpty()) 00476 { 00477 // lookup failed! 00478 setError(KResolver::NoName); 00479 return false; 00480 } 00481 } 00482 else 00483 protoname = "tcp"; 00484 00485 // it's not, so we can do a port lookup 00486 int result = KResolver::servicePort(serviceName().latin1(), protoname); 00487 if (result == -1) 00488 { 00489 // lookup failed! 00490 setError(KResolver::NoName); 00491 return false; 00492 } 00493 00494 // it worked, we have a port number 00495 port = (Q_UINT16)result; 00496 } 00497 } 00498 00499 // we found a port 00500 return true; 00501 } 00502 00503 KResolver::ErrorCodes KStandardWorker::addUnix() 00504 { 00505 // before trying to add, see if the user wants Unix sockets 00506 if ((familyMask() & KResolver::UnixFamily) == 0) 00507 // no, Unix sockets are not wanted 00508 return KResolver::UnsupportedFamily; 00509 00510 // now check if the requested data are good for a Unix socket 00511 if (!m_encodedName.isEmpty()) 00512 return KResolver::AddrFamily; // non local hostname 00513 00514 if (protocol() || protocolName()) 00515 return KResolver::BadFlags; // cannot have Unix sockets with protocols 00516 00517 QString pathname = serviceName(); 00518 if (pathname.isEmpty()) 00519 return KResolver::NoName;; // no path? 00520 00521 if (pathname[0] != '/') 00522 // non absolute pathname 00523 // put it in /tmp 00524 pathname.prepend("/tmp/"); 00525 00526 // qDebug("QNoResolveWorker::addUnix(): adding Unix socket for %s", pathname.local8Bit().data()); 00527 KUnixSocketAddress sa(pathname); 00528 int socktype = socketType(); 00529 if (socktype == 0) 00530 socktype = SOCK_STREAM; // default 00531 00532 results.append(KResolverEntry(sa, socktype, 0)); 00533 setError(KResolver::NoError); 00534 00535 return KResolver::NoError; 00536 } 00537 00538 bool KStandardWorker::resolveNumerically() 00539 { 00540 // if the NoResolve flag is active, our result from this point forward 00541 // will always be true, even if the resolution failed. 00542 // that indicates that our result is authoritative. 00543 00544 bool wantV4 = familyMask() & KResolver::IPv4Family, 00545 wantV6 = familyMask() & KResolver::IPv6Family; 00546 00547 if (!wantV6 && !wantV4) 00548 // no Internet address is wanted! 00549 return (flags() & KResolver::NoResolve); 00550 00551 // now try to find results 00552 if (!resolveScopeId() || !resolveService()) 00553 return (flags() & KResolver::NoResolve); 00554 00555 // we have scope IDs and port numbers 00556 // now try to resolve the hostname numerically 00557 KInetSocketAddress sa; 00558 setError(KResolver::NoError); 00559 sa.setHost(KIpAddress(QString::fromLatin1(m_encodedName))); 00560 00561 // if it failed, the length was reset to 0 00562 bool ok = sa.length() != 0; 00563 00564 sa.setPort(port); 00565 if (sa.ipVersion() == 6) 00566 sa.setScopeId(scopeid); 00567 int proto = protocol(); 00568 int socktype = socketType(); 00569 if (socktype == 0) 00570 socktype = SOCK_STREAM; 00571 00572 if (ok) 00573 { 00574 // the given hostname was successfully converted to an IP address 00575 // check if the user wanted this kind of address 00576 00577 if ((sa.ipVersion() == 4 && wantV4) || 00578 (sa.ipVersion() == 6 && wantV6)) 00579 results.append(KResolverEntry(sa, socktype, proto)); 00580 else 00581 { 00582 // Note: the address *IS* a numeric IP 00583 // but it's not of the kind the user asked for 00584 // 00585 // that means that it cannot be a Unix socket (because it's an IP) 00586 // and that means that no resolution will tell us otherwise 00587 // 00588 // This is a failed resolution 00589 00590 setError(KResolver::AddrFamily); 00591 return true; 00592 } 00593 } 00594 else if (m_encodedName.isEmpty()) 00595 { 00596 // user wanted localhost 00597 if (flags() & KResolver::Passive) 00598 { 00599 if (wantV6) 00600 { 00601 sa.setHost(KIpAddress::anyhostV6); 00602 results.append(KResolverEntry(sa, socktype, proto)); 00603 } 00604 00605 if (wantV4) 00606 { 00607 sa.setHost(KIpAddress::anyhostV4); 00608 results.append(KResolverEntry(sa, socktype, proto)); 00609 } 00610 } 00611 else 00612 { 00613 if (wantV6) 00614 { 00615 sa.setHost(KIpAddress::localhostV6); 00616 results.append(KResolverEntry(sa, socktype, proto)); 00617 } 00618 00619 if (wantV4) 00620 { 00621 sa.setHost(KIpAddress::localhostV4); 00622 results.append(KResolverEntry(sa, socktype, proto)); 00623 } 00624 } 00625 00626 ok = true; 00627 } 00628 else 00629 { 00630 // probably bad flags, since the address is not convertible without 00631 // resolution 00632 00633 setError(KResolver::BadFlags); 00634 ok = false; 00635 } 00636 00637 return ok || (flags() & KResolver::NoResolve); 00638 } 00639 00640 bool KStandardWorker::preprocess() 00641 { 00642 // check sanity 00643 if (!sanityCheck()) 00644 return false; 00645 00646 // this worker class can only handle known families 00647 if (familyMask() & KResolver::UnknownFamily) 00648 { 00649 setError(KResolver::UnsupportedFamily); 00650 return false; // we don't know about this 00651 } 00652 00653 // check the socket types 00654 if (socketType() != SOCK_STREAM && socketType() != SOCK_DGRAM && socketType() != 0) 00655 { 00656 setError(KResolver::UnsupportedSocketType); 00657 return false; 00658 } 00659 00660 // check if we can resolve all numerically 00661 // resolveNumerically always returns true if the NoResolve flag is set 00662 if (resolveNumerically() || m_encodedName.isEmpty()) 00663 { 00664 // indeed, we have resolved numerically 00665 setError(addUnix()); 00666 if (results.count()) 00667 setError(KResolver::NoError); 00668 finished(); 00669 return true; 00670 } 00671 00672 // check if the user wants something we know about 00673 #ifdef AF_INET6 00674 # define mask (KResolver::IPv6Family | KResolver::IPv4Family | KResolver::UnixFamily) 00675 #else 00676 # define mask (KResolver::IPv4Family | KResolver::UnixFamily) 00677 #endif 00678 00679 if ((familyMask() & mask) == 0) 00680 // errr... nothing we know about 00681 return false; 00682 00683 #undef mask 00684 00685 return true; // it's ok 00686 } 00687 00688 bool KStandardWorker::run() 00689 { 00690 #ifndef HAVE_GETADDRINFO 00691 // check the scope id first 00692 // since most of the resolutions won't have a scope id, this should be fast 00693 // and we won't have wasted time on services if this fails 00694 if (!resolveScopeId()) 00695 return false; 00696 00697 // resolve the service now, before entering the blocking operation 00698 if (!resolveService()) 00699 return false; 00700 #endif 00701 00702 // good 00703 // now we need the hostname 00704 setError(KResolver::NoName); 00705 00706 // these are the family types that we know of 00707 struct 00708 { 00709 KResolver::SocketFamilies mask; 00710 int af; 00711 } families[] = { { KResolver::IPv4Family, AF_INET } 00712 #ifdef AF_INET6 00713 , { KResolver::IPv6Family, AF_INET6 } 00714 #endif 00715 }; 00716 int familyCount = sizeof(families)/sizeof(families[0]); 00717 bool skipIPv6 = false; 00718 if (getenv("KDE_NO_IPV6")) 00719 skipIPv6 = true; 00720 resultList.setAutoDelete(true); 00721 00722 for (int i = 0; i < familyCount; i++) 00723 if (familyMask() & families[i].mask) 00724 { 00725 #ifdef AF_INET6 00726 if (skipIPv6 && families[i].af == AF_INET6) 00727 continue; 00728 #endif 00729 00730 KResolverWorkerBase *worker; 00731 KResolverResults *res = new KResolverResults; 00732 resultList.append(res); 00733 #ifdef HAVE_GETADDRINFO 00734 worker = new GetAddrInfoThread(m_encodedName, 00735 serviceName().latin1(), 00736 families[i].af, res); 00737 #else 00738 worker = new GetHostByNameThread(m_encodedName, port, scopeid, 00739 families[i].af, res); 00740 #endif 00741 00742 enqueue(worker); 00743 } 00744 00745 // not finished 00746 return true; 00747 } 00748 00749 bool KStandardWorker::postprocess() 00750 { 00751 if (results.count()) 00752 return true; // no need 00753 // now copy over what we need from the underlying results 00754 00755 // start backwards because IPv6 was launched later (if at all) 00756 if (resultList.isEmpty()) 00757 { 00758 results.setError(KResolver::NoName); 00759 return true; 00760 } 00761 00762 KResolverResults *rr = resultList.last(); 00763 while (rr) 00764 { 00765 if (!rr->isEmpty()) 00766 { 00767 results.setError(KResolver::NoError); 00768 KResolverResults::Iterator it = rr->begin(); 00769 for ( ; it != rr->end(); ++it) 00770 results.append(*it); 00771 } 00772 else if (results.isEmpty()) 00773 // this generated an error 00774 // copy the error code over 00775 setError(rr->error(), rr->systemError()); 00776 00777 rr = resultList.prev(); 00778 } 00779 00780 resultList.clear(); 00781 return true; 00782 } 00783 00784 #ifdef HAVE_GETADDRINFO 00785 KGetAddrinfoWorker::~KGetAddrinfoWorker() 00786 { 00787 } 00788 00789 bool KGetAddrinfoWorker::preprocess() 00790 { 00791 // getaddrinfo(3) can always handle any kind of request that makes sense 00792 if (!sanityCheck()) 00793 return false; 00794 00795 if (flags() & KResolver::NoResolve) 00796 // oops, numeric resolution? 00797 return run(); 00798 00799 return true; 00800 } 00801 00802 bool KGetAddrinfoWorker::run() 00803 { 00804 // make an AF_UNSPEC getaddrinfo(3) call 00805 GetAddrInfoThread worker(m_encodedName, serviceName().latin1(), 00806 AF_UNSPEC, &results); 00807 00808 if (!worker.run()) 00809 { 00810 if (wantThis(AF_UNIX)) 00811 { 00812 if (addUnix() == KResolver::NoError) 00813 setError(KResolver::NoError); 00814 } 00815 else 00816 setError(worker.results.error(), worker.results.systemError()); 00817 00818 return false; 00819 } 00820 00821 // The worker has finished working 00822 // now copy over only what we may want 00823 // keep track of any Unix-domain sockets 00824 00825 bool seen_unix = false; 00826 KResolverResults::Iterator it = results.begin(); 00827 for ( ; it != results.end(); ) 00828 { 00829 if ((*it).family() == AF_UNIX) 00830 seen_unix = true; 00831 if (!wantThis((*it).family())) 00832 it = results.remove(it); 00833 else 00834 ++it; 00835 } 00836 00837 if (!seen_unix) 00838 addUnix(); 00839 00840 finished(); 00841 return true; 00842 } 00843 00844 bool KGetAddrinfoWorker::wantThis(int family) 00845 { 00846 // tells us if the user wants a socket of this family 00847 00848 #ifdef AF_INET6 00849 if (family == AF_INET6 && familyMask() & KResolver::IPv6Family) 00850 return true; 00851 #endif 00852 if (family == AF_INET && familyMask() & KResolver::IPv4Family) 00853 return true; 00854 if (family == AF_UNIX && familyMask() & KResolver::UnixFamily) 00855 return true; 00856 00857 // it's not a family we know about... 00858 if (familyMask() & KResolver::UnknownFamily) 00859 return true; 00860 00861 return false; 00862 } 00863 00864 #endif 00865 00866 void KNetwork::Internal::initStandardWorkers() 00867 { 00868 // register the workers in the order we want them to be tried 00869 // note the no-resolving worker isn't registered. It's handled as a 00870 // special case in KResolverManager::findWorker 00871 00872 KResolverWorkerFactoryBase::registerNewWorker(new KResolverWorkerFactory<KStandardWorker>); 00873 00874 #ifdef HAVE_GETADDRINFO 00875 KResolverWorkerFactoryBase::registerNewWorker(new KResolverWorkerFactory<KGetAddrinfoWorker>); 00876 #endif 00877 }
KDE Logo
This file is part of the documentation for kdecore Library Version 3.3.0.
Documentation copyright © 1996-2004 the KDE developers.
Generated on Wed Sep 29 09:43:11 2004 by doxygen 1.3.8 written by Dimitri van Heesch, © 1997-2003