kresolverstandardworkers.cpp

来自「konqueror3 embedded版本, KDE环境下的当家浏览器的嵌入式版」· C++ 代码 · 共 1,029 行 · 第 1/2 页

CPP
1,029
字号
	for (addrinfo* p = result; p; p = p->ai_next)	  {	    // cache the last canon name to avoid doing the ToUnicode processing unnecessarily	    if ((previous_canon && !p->ai_canonname) ||		(!previous_canon && p->ai_canonname) ||		(p->ai_canonname != previous_canon && 		 strcmp(p->ai_canonname, previous_canon) != 0))	      {		canon = KResolver::domainToUnicode(QString::fromAscii(p->ai_canonname));		previous_canon = p->ai_canonname;	      }	    results.append(KResolverEntry(p->ai_addr, p->ai_addrlen, p->ai_socktype, 					  p->ai_protocol, canon, m_node));	  }	freeaddrinfo(result);	results.setError(KResolver::NoError);	finished();	return results.error() == KResolver::NoError;      }    while (true);  }#endif // HAVE_GETADDRINFO} // namespacebool KStandardWorker::sanityCheck(){  // check that the requested values are sensible  if (!nodeName().isEmpty())    {      QString node = nodeName();      if (node.find('%') != -1)	node.truncate(node.find('%'));      if (node.isEmpty() || node == QString::fromLatin1("*") ||	  node == QString::fromLatin1("localhost"))	m_encodedName.truncate(0);      else	{	  m_encodedName = KResolver::domainToAscii(node);	  if (m_encodedName.isNull())	    {	      qDebug("could not encode hostname '%s' (UTF-8)", node.utf8().data());	      setError(KResolver::NoName);	      return false;		// invalid hostname!	    }	  // qDebug("Using encoded hostname '%s' for '%s' (UTF-8)", m_encodedName.data(),	  //	 node.utf8().data());	}    }  else    m_encodedName.truncate(0);	// just to be sure, but it should be clear already  if (protocol() == -1)    {      setError(KResolver::NonRecoverable);      return false;		// user passed invalid protocol name    }  return true;			// it's sane}bool KStandardWorker::resolveScopeId(){  // we must test the original name, not the encoded one  scopeid = 0;  int pos = nodeName().findRev('%');  if (pos == -1)    return true;  QString scopename = nodeName().mid(pos + 1);  bool ok;  scopeid = scopename.toInt(&ok);  if (!ok)    {      // it's not a number      // therefore, it's an interface name#ifdef HAVE_IF_NAMETOINDEX      scopeid = if_nametoindex(scopename.latin1());#else      scopeid = 0;#endif    }  return true;}bool KStandardWorker::resolveService(){  // find the service first  bool ok;  port = serviceName().toUInt(&ok);  if (!ok)    {      // service name does not contain a port number      // must be a name      if (serviceName().isEmpty() || serviceName().compare(QString::fromLatin1("*")) == 0)	port = 0;      else	{	  // it's a name. We need the protocol name in order to lookup.	  QCString protoname = protocolName();	  if (protoname.isEmpty() && protocol())	    {	      protoname = KResolver::protocolName(protocol()).first();	      // if it's still empty...	      if (protoname.isEmpty())		{		  // lookup failed!		  setError(KResolver::NoName);		  return false;		}	    }	  else	    protoname = "tcp";	  // it's not, so we can do a port lookup	  int result = KResolver::servicePort(serviceName().latin1(), protoname);	  if (result == -1)	    {	      // lookup failed!	      setError(KResolver::NoName);	      return false;	    }	  // it worked, we have a port number	  port = (Q_UINT16)result;	}    }  // we found a port  return true;}KResolver::ErrorCodes KStandardWorker::addUnix(){  // before trying to add, see if the user wants Unix sockets  if ((familyMask() & KResolver::UnixFamily) == 0)    // no, Unix sockets are not wanted    return KResolver::UnsupportedFamily;  // now check if the requested data are good for a Unix socket  if (!m_encodedName.isEmpty())    return KResolver::AddrFamily; // non local hostname  if (protocol() || protocolName())    return KResolver::BadFlags;	// cannot have Unix sockets with protocols  QString pathname = serviceName();  if (pathname.isEmpty())    return KResolver::NoName;;	// no path?  if (pathname[0] != '/')    // non absolute pathname    // put it in /tmp    pathname.prepend("/tmp/");  //  qDebug("QNoResolveWorker::addUnix(): adding Unix socket for %s", pathname.local8Bit().data());  KUnixSocketAddress sa(pathname);  int socktype = socketType();  if (socktype == 0)    socktype = SOCK_STREAM;	// default  results.append(KResolverEntry(sa, socktype, 0));  setError(KResolver::NoError);   return KResolver::NoError;}bool KStandardWorker::resolveNumerically(){  // if the NoResolve flag is active, our result from this point forward  // will always be true, even if the resolution failed.  // that indicates that our result is authoritative.  bool wantV4 = familyMask() & KResolver::IPv4Family,    wantV6 = familyMask() & KResolver::IPv6Family;  if (!wantV6 && !wantV4)    // no Internet address is wanted!    return (flags() & KResolver::NoResolve);  // now try to find results  if (!resolveScopeId() || !resolveService())    return (flags() & KResolver::NoResolve);  // we have scope IDs and port numbers  // now try to resolve the hostname numerically  KInetSocketAddress sa;  setError(KResolver::NoError);  sa.setHost(KIpAddress(QString::fromLatin1(m_encodedName)));    // if it failed, the length was reset to 0  bool ok = sa.length() != 0;  sa.setPort(port);  if (sa.ipVersion() == 6)    sa.setScopeId(scopeid);  int proto = protocol();  int socktype = socketType();  if (socktype == 0)    socktype = SOCK_STREAM;  if (ok)    {      // the given hostname was successfully converted to an IP address      // check if the user wanted this kind of address      if ((sa.ipVersion() == 4 && wantV4) ||	  (sa.ipVersion() == 6 && wantV6))	results.append(KResolverEntry(sa, socktype, proto));      else	{	  // Note: the address *IS* a numeric IP	  // but it's not of the kind the user asked for	  //	  // that means that it cannot be a Unix socket (because it's an IP)	  // and that means that no resolution will tell us otherwise	  //	  // This is a failed resolution	  setError(KResolver::AddrFamily);	  return true;	}    }  else if (m_encodedName.isEmpty())    {      // user wanted localhost      if (flags() & KResolver::Passive)	{	  if (wantV6)	    {	      sa.setHost(KIpAddress::anyhostV6);	      results.append(KResolverEntry(sa, socktype, proto));	    }	  if (wantV4)	    {	      sa.setHost(KIpAddress::anyhostV4);	      results.append(KResolverEntry(sa, socktype, proto));	    }	}      else	{	  if (wantV6)	    {	      sa.setHost(KIpAddress::localhostV6);	      results.append(KResolverEntry(sa, socktype, proto));	    }	  if (wantV4)	    {	      sa.setHost(KIpAddress::localhostV4);	      results.append(KResolverEntry(sa, socktype, proto));	    }	}      ok = true;    }  else    {      // probably bad flags, since the address is not convertible without       // resolution      setError(KResolver::BadFlags);      ok = false;    }  return ok || (flags() & KResolver::NoResolve);}bool KStandardWorker::preprocess(){  // check sanity  if (!sanityCheck())    return false;  // this worker class can only handle known families  if (familyMask() & KResolver::UnknownFamily)    {      setError(KResolver::UnsupportedFamily);      return false;		// we don't know about this    }  // check the socket types  if (socketType() != SOCK_STREAM && socketType() != SOCK_DGRAM && socketType() != 0)    {      setError(KResolver::UnsupportedSocketType);      return false;    }  // check if we can resolve all numerically  // resolveNumerically always returns true if the NoResolve flag is set  if (resolveNumerically() || m_encodedName.isEmpty())    {      // indeed, we have resolved numerically      setError(addUnix());      if (results.count())	setError(KResolver::NoError);      finished();      return true;    }  // check if the user wants something we know about#ifdef AF_INET6# define mask	(KResolver::IPv6Family | KResolver::IPv4Family | KResolver::UnixFamily)#else# define mask	(KResolver::IPv4Family | KResolver::UnixFamily)#endif  if ((familyMask() & mask) == 0)    // errr... nothing we know about    return false;#undef mask  return true;			// it's ok}bool KStandardWorker::run(){#ifndef HAVE_GETADDRINFO  // check the scope id first  // since most of the resolutions won't have a scope id, this should be fast  // and we won't have wasted time on services if this fails  if (!resolveScopeId())    return false;  // resolve the service now, before entering the blocking operation  if (!resolveService())    return false;#endif  // good  // now we need the hostname  setError(KResolver::NoName);  // these are the family types that we know of  struct  {    KResolver::SocketFamilies mask;    int af;  } families[] = { { KResolver::IPv4Family, AF_INET }#ifdef AF_INET6					  		  , { KResolver::IPv6Family, AF_INET6 }#endif  };  int familyCount = sizeof(families)/sizeof(families[0]);  bool skipIPv6 = !hasIPv6();  resultList.setAutoDelete(true);  for (int i = 0; i < familyCount; i++)    if (familyMask() & families[i].mask)      {#ifdef AF_INET6	if (skipIPv6 && families[i].af == AF_INET6)	  continue;#endif	KResolverWorkerBase *worker;	KResolverResults *res = new KResolverResults;	resultList.append(res);#ifdef HAVE_GETADDRINFO	worker = new GetAddrInfoThread(m_encodedName, 				       serviceName().latin1(),				       families[i].af, flags(), res);#else	worker = new GetHostByNameThread(m_encodedName, port, scopeid,					 families[i].af, res);#endif	enqueue(worker);      }  // not finished  return true;}bool KStandardWorker::postprocess(){  if (results.count())    return true;		// no need  // now copy over what we need from the underlying results  // start backwards because IPv6 was launched later (if at all)  if (resultList.isEmpty())    {      results.setError(KResolver::NoName);      return true;    }  KResolverResults *rr = resultList.last();  while (rr)    {      if (!rr->isEmpty())	{	  results.setError(KResolver::NoError);	  KResolverResults::Iterator it = rr->begin();	  for ( ; it != rr->end(); ++it)	    results.append(*it);	}      else if (results.isEmpty())	// this generated an error	// copy the error code over	setError(rr->error(), rr->systemError());      rr = resultList.prev();    }  resultList.clear();  return true;}#ifdef HAVE_GETADDRINFOKGetAddrinfoWorker::~KGetAddrinfoWorker(){}bool KGetAddrinfoWorker::preprocess(){  // getaddrinfo(3) can always handle any kind of request that makes sense  if (!sanityCheck())    return false;  if (flags() & KResolver::NoResolve)    // oops, numeric resolution?    return run();  return true;}bool KGetAddrinfoWorker::run(){  // make an AF_UNSPEC getaddrinfo(3) call  GetAddrInfoThread worker(m_encodedName, serviceName().latin1(), 			   AF_UNSPEC, flags(), &results);  if (!worker.run())    {      if (wantThis(AF_UNIX))	{	  if (addUnix() == KResolver::NoError)	    setError(KResolver::NoError);	}      else	setError(worker.results.error(), worker.results.systemError());      return false;    }  // The worker has finished working  // now copy over only what we may want  // keep track of any Unix-domain sockets  bool seen_unix = false;  KResolverResults::Iterator it = results.begin();  for ( ; it != results.end(); )    {      if ((*it).family() == AF_UNIX)	seen_unix = true;      if (!wantThis((*it).family()))	it = results.remove(it);      else	++it;    }  if (!seen_unix)    addUnix();  finished();  return true;}bool KGetAddrinfoWorker::wantThis(int family){  // tells us if the user wants a socket of this family#ifdef AF_INET6  if (family == AF_INET6 && familyMask() & KResolver::IPv6Family)    return true;#endif  if (family == AF_INET && familyMask() & KResolver::IPv4Family)    return true;  if (family == AF_UNIX && familyMask() & KResolver::UnixFamily)    return true;  // it's not a family we know about...  if (familyMask() & KResolver::UnknownFamily)    return true;  return false;}#endifvoid KNetwork::Internal::initStandardWorkers(){  //KResolverWorkerFactoryBase::registerNewWorker(new KResolverWorkerFactory<KBlacklistWorker>);  KResolverWorkerFactoryBase::registerNewWorker(new KResolverWorkerFactory<KStandardWorker>);#ifdef HAVE_GETADDRINFO  KResolverWorkerFactoryBase::registerNewWorker(new KResolverWorkerFactory<KGetAddrinfoWorker>);#endif}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?