⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 q3dns.cpp

📁 奇趣公司比较新的qt/emd版本
💻 CPP
📖 第 1 页 / 共 5 页
字号:
    QByteArray a( 16383 ); // large enough for anything, one suspects    int r;#if defined (QT_NO_IPV6)    r = ipv4Socket->readBlock(a.data(), a.size());#else    if (((QSocketNotifier *)sender())->socket() == ipv4Socket->socket())        r = ipv4Socket->readBlock(a.data(), a.size());    else        r = ipv6Socket->readBlock(a.data(), a.size());#endif#if defined(Q3DNS_DEBUG)#if !defined (QT_NO_IPV6)    qDebug("DNS Manager: answer arrived: %d bytes from %s:%d", r,	   useIpv4Socket ? ipv4Socket->peerAddress().toString().ascii()	   : ipv6Socket->peerAddress().toString().ascii(),	   useIpv4Socket ? ipv4Socket->peerPort() : ipv6Socket->peerPort() );#else    qDebug("DNS Manager: answer arrived: %d bytes from %s:%d", r,           ipv4Socket->peerAddress().toString().ascii(), ipv4Socket->peerPort());;#endif#endif    if ( r < 12 )	return;    // maybe we should check that the answer comes from port 53 on one    // of our name servers...    a.resize( r );    Q_UINT16 aid = (((Q_UINT8)a[0]) << 8) + ((Q_UINT8)a[1]);    uint i = 0;    while( i < queries.size() &&	   !( queries[i] && queries[i]->id == aid ) )	i++;    if ( i == queries.size() ) {#if defined(Q3DNS_DEBUG)	qDebug( "DNS Manager: bad id (0x%04x) %d", aid, i );#endif	return;    }    // at this point queries[i] is whatever we asked for.    if ( ( (Q_UINT8)(a[2]) & 0x80 ) == 0 ) {#if defined(Q3DNS_DEBUG)	qDebug( "DNS Manager: received a query" );#endif	return;    }    Q3DnsQuery * q = queries[i];    Q3DnsAnswer answer( a, q );    answer.parse();    if ( answer.ok ) {	queries.take( i );	answer.notify();	delete q;    }}void Q3DnsManager::transmitQuery( Q3DnsQuery * query_ ){    if ( !query_ )	return;    uint i = 0;    while( i < queries.size() && queries[i] != 0 )	i++;    if ( i == queries.size() )	queries.resize( i+1 );    queries.insert( i, query_ );    transmitQuery( i );}void Q3DnsManager::transmitQuery( int i ){    if ( i < 0 || i >= (int)queries.size() )	return;    Q3DnsQuery * q = queries[i];    if ( q && q->step > 8 ) {	// okay, we've run out of retransmissions. we fake an NXDomain	// with a very short life time...	Q3DnsAnswer answer( q );	answer.notify();	// and then get rid of the query	queries.take( i );#if defined(Q3DNS_DEBUG)	qDebug( "DNS Manager: giving up on query 0x%04x", q->id );#endif	delete q;	QTimer::singleShot( 0, Q3DnsManager::manager(), SLOT(cleanCache()) );	// and don't process anything more	return;    }    if ( q && !q->dns || q->dns->isEmpty() )	// no one currently wants the answer, so there's no point in	// retransmitting the query. we keep it, though. an answer may	// arrive for an earlier query transmission, and if it does we	// may benefit from caching the result.	return;    QByteArray p( 12 + q->l.length() + 2 + 4 );    if ( p.size() > 500 )	return; // way over the limit, so don't even try    // header    // id    p[0] = (q->id & 0xff00) >> 8;    p[1] =  q->id & 0x00ff;    p[2] = 1; // recursion desired, rest is 0    p[3] = 0; // all is 0    // one query    p[4] = 0;    p[5] = 1;    // no answers, name servers or additional data    p[6] = p[7] = p[8] = p[9] = p[10] = p[11] = 0;    // the name is composed of several components.  each needs to be    // written by itself... so we write...    // oh, and we assume that there's no funky characters in there.    int pp = 12;    uint lp = 0;    while( lp < (uint) q->l.length() ) {	int le = q->l.find( QLatin1Char('.'), lp );	if ( le < 0 )	    le = q->l.length();	QString component = q->l.mid( lp, le-lp );	p[pp++] = component.length();	int cp;	for( cp=0; cp < (int)component.length(); cp++ )	    p[pp++] = component[cp].latin1();	lp = le + 1;    }    // final null    p[pp++] = 0;    // query type    p[pp++] = 0;    switch( q->t ) {    case Q3Dns::A:	p[pp++] = 1;	break;    case Q3Dns::Aaaa:	p[pp++] = 28;	break;    case Q3Dns::Mx:	p[pp++] = 15;	break;    case Q3Dns::Srv:	p[pp++] = 33;	break;    case Q3Dns::Cname:	p[pp++] = 5;	break;    case Q3Dns::Ptr:	p[pp++] = 12;	break;    case Q3Dns::Txt:	p[pp++] = 16;	break;    default:	p[pp++] = (char)255; // any	break;    }    // query class (always internet)    p[pp++] = 0;    p[pp++] = 1;    // if we have no name servers, we should regenerate ns in case    // name servers have recently been defined (like on windows,    // plugging/unplugging the network cable will change the name    // server entries)    if ( !ns || ns->isEmpty() )        Q3Dns::doResInit();    if ( !ns || ns->isEmpty() ) {	// we don't find any name servers. We fake an NXDomain	// with a very short life time...	Q3DnsAnswer answer( q );	answer.notify();	// and then get rid of the query	queries.take( i );#if defined(Q3DNS_DEBUG)	qDebug( "DNS Manager: no DNS server found on query 0x%04x", q->id );#endif	delete q;	QTimer::singleShot( 1000*10, Q3DnsManager::manager(), SLOT(cleanCache()) );	// and don't process anything more	return;    }    QHostAddress receiver = *ns->at( q->step % ns->count() );    if (receiver.isIPv4Address())	ipv4Socket->writeBlock( p.data(), pp, receiver, 53 );#if !defined (QT_NO_IPV6)    else	ipv6Socket->writeBlock( p.data(), pp, receiver, 53 );#endif#if defined(Q3DNS_DEBUG)    qDebug( "issuing query 0x%04x (%d) about %s type %d to %s",	    q->id, q->step, q->l.ascii(), q->t,	    ns->at( q->step % ns->count() )->toString().ascii() );#endif    if ( ns->count() > 1 && q->step == 0 && queries.count() == 1 ) {	// if it's the first time, and we don't have any other	// outstanding queries, send nonrecursive queries to the other	// name servers too.	p[2] = 0;	QHostAddress * server;	while( (server=ns->next()) != 0 ) {	    if (server->isIPv4Address())		ipv4Socket->writeBlock( p.data(), pp, *server, 53 );#if !defined (QT_NO_IPV6)	    else		ipv6Socket->writeBlock( p.data(), pp, *server, 53 );#endif#if defined(Q3DNS_DEBUG)	    qDebug( "copying query to %s", server->toString().ascii() );#endif	}    }    q->step++;    // some testing indicates that normal dns queries take up to 0.6    // seconds.  the graph becomes steep around that point, and the    // number of errors rises... so it seems good to retry at that    // point.    q->start( q->step < ns->count() ? 800 : 1500, true );}Q3DnsDomain * Q3DnsManager::domain( const QString & label ){    Q3DnsDomain * d = cache.find( label );    if ( !d ) {	d = new Q3DnsDomain( label );	cache.insert( label, d );    }    return d;}////// the Q3DnsDomain class looks after and coordinates queries for Q3DnsRRs for// each domain, and the cached Q3DnsRRs.  (A domain, in DNS terminology, is// a node in the DNS.  "no", "trolltech.com" and "lupinella.troll.no" are// all domains.)////Q3DnsDomain::Q3DnsDomain( const QString & label ){    l = label;    rrs = 0;}Q3DnsDomain::~Q3DnsDomain(){    delete rrs;    rrs = 0;}void Q3DnsDomain::add( const QString & label, Q3DnsRR * rr ){    Q3DnsDomain * d = Q3DnsManager::manager()->domain( label );    if ( !d->rrs ) {	d->rrs = new Q3PtrList<Q3DnsRR>;	d->rrs->setAutoDelete( true );    }    d->rrs->append( rr );    rr->domain = d;}Q3PtrList<Q3DnsRR> * Q3DnsDomain::cached( const Q3Dns * r ){    Q3PtrList<Q3DnsRR> * l = new Q3PtrList<Q3DnsRR>;    // test at first if you have to start a query at all    if ( r->recordType() == Q3Dns::A ) {	if ( r->label().lower() == QLatin1String("localhost") ) {	    // undocumented hack. ipv4-specific. also, may be a memory	    // leak? not sure. would be better to do this in doResInit(),	    // anyway.	    Q3DnsRR *rrTmp = new Q3DnsRR( r->label() );	    rrTmp->t = Q3Dns::A;	    rrTmp->address = QHostAddress( 0x7f000001 );	    rrTmp->current = true;	    l->append( rrTmp );	    return l;	}	QHostAddress tmp;	if ( tmp.setAddress( r->label() ) ) {	    Q3DnsRR *rrTmp = new Q3DnsRR( r->label() );	    if ( tmp.isIPv4Address() ) {		rrTmp->t = Q3Dns::A;                rrTmp->address = tmp;                rrTmp->current = true;                l->append( rrTmp );            } else {                rrTmp->nxdomain = true;            }	    return l;	}    }    if ( r->recordType() == Q3Dns::Aaaa ) {	QHostAddress tmp;	if ( tmp.setAddress(r->label()) ) {	    Q3DnsRR *rrTmp = new Q3DnsRR( r->label() );	    if ( tmp.isIPv6Address() ) {		rrTmp->t = Q3Dns::Aaaa;                rrTmp->address = tmp;                rrTmp->current = true;                l->append( rrTmp );            } else {                rrTmp->nxdomain = true;            }	    return l;	}    }    // if you reach this point, you have to do the query    Q3DnsManager * m = Q3DnsManager::manager();    QStringList n = r->qualifiedNames();    bool nxdomain;    int cnamecount = 0;    int it = 0;    while( it < n.count() ) {	QString s = n.at(it++);	nxdomain = false;#if defined(Q3DNS_DEBUG)	qDebug( "looking at cache for %s (%s %d)",		s.ascii(), r->label().ascii(), r->recordType() );#endif	Q3DnsDomain * d = m->domain( s );#if defined(Q3DNS_DEBUG)	qDebug( " - found %d RRs", d && d->rrs ? d->rrs->count() : 0 );#endif	if ( d->rrs )	    d->rrs->first();	Q3DnsRR * rr;	bool answer = false;	while( d->rrs && (rr=d->rrs->current()) != 0 ) {	    if ( rr->t == Q3Dns::Cname && r->recordType() != Q3Dns::Cname &&		 !rr->nxdomain && cnamecount < 16 ) {		// cname.  if the code is ugly, that may just		// possibly be because the concept is.#if defined(Q3DNS_DEBUG)		qDebug( "found cname from %s to %s",			r->label().ascii(), rr->target.ascii() );#endif		s = rr->target;		d = m->domain( s );		if ( d->rrs )		    d->rrs->first();		it = n.count();		// we've elegantly moved over to whatever the cname		// pointed to.  well, not elegantly.  let's remember		// that we've done something, anyway, so we can't be		// fooled into an infinte loop as well.		cnamecount++;	    } else {		if ( rr->t == r->recordType() ) {		    if ( rr->nxdomain )			nxdomain = true;		    else			answer = true;		    l->append( rr );		    if ( rr->deleteTime <= lastSweep ) {			// we're returning something that'll be			// deleted soon.  we assume that if the client			// wanted it twice, it'll want it again, so we			// ask the name server again right now.			Q3DnsQuery * query = new Q3DnsQuery;			query->started = now();			query->id = ++::id;			query->t = rr->t;			query->l = rr->domain->name();			// note that here, we don't bother about			// notification. but we do bother about			// timeouts: we make sure to use high timeouts			// and few tramsissions.			query->step = ns->count();			QObject::connect( query, SIGNAL(timeout()),					  Q3DnsManager::manager(),					  SLOT(retransmit()) );			Q3DnsManager::manager()->transmitQuery( query );		    }		}		d->rrs->next();	    }	}	// if we found a positive result, return quickly	if ( answer && l->count() ) {#if defined(Q3DNS_DEBUG)	    qDebug( "found %d records for %s",		    l->count(), r->label().ascii() );	    l->first();	    while( l->current() ) {		qDebug( "  type %d target %s address %s",		       l->current()->t,		       l->current()->target.latin1(),		       l->current()->address.toString().latin1() );		l->next();	    }#endif	    l->first();	    return l;	}#if defined(Q3DNS_DEBUG)	if ( nxdomain )	    qDebug( "found NXDomain %s", s.ascii() );#endif	if ( !nxdomain ) {	    // if we didn't, and not a negative result either, perhaps	    // we need to transmit a query.	    uint q = 0;	    while ( q < m->queries.size() &&		    ( m->queries[q] == 0 ||		      m->queries[q]->t != r->recordType() ||		      m->queries[q]->l != s ) )		q++;	    // we haven't done it before, so maybe we should.  but	    // wait - if it's an unqualified name, only ask when all	    // the other alternatives are exhausted.	    if ( q == m->queries.size() && ( s.find( QLatin1Char('.') ) >= 0 ||					     int(l->count()) >= n.count()-1 ) ) {		Q3DnsQuery * query = new Q3DnsQuery;		query->started = now();		query->id = ++::id;		query->t = r->recordType();		query->l = s;		query->dns->replace( (void*)r, (void*)r );		QObject::connect( query, SIGNAL(timeout()),				  Q3DnsManager::manager(), SLOT(retransmit()) );		Q3DnsManager::manager()->transmitQuery( query );	    } else if ( q < m->queries.size() ) {		// if we've found an earlier query for the same		// domain/type, subscribe to its answer		m->queries[q]->dns->replace( (void*)r, (void*)r );	    }	}    }    l->first();    return l;}void Q3DnsDomain::sweep( Q_UINT32 thisSweep ){    if ( !rrs )	return;    Q3DnsRR * rr;    rrs->first();    while( (rr=rrs->current()) != 0 ) {	if ( !rr->deleteTime )	    rr->deleteTime = thisSweep; // will hit next time around#if defined(Q3DNS_DEBUG)	qDebug( "Q3Dns::sweep: %s type %d expires %u %u - %s / %s",	       rr->domain->name().latin1(), rr->t,	       rr->expireTime, rr->deleteTime,	       rr->target.latin1(), rr->address.toString().latin1());#endif	if ( rr->current == false ||	     rr->t == Q3Dns::None ||	     rr->deleteTime <= thisSweep ||	     rr->expireTime <= thisSweep )	    rrs->remove();	else	    rrs->next();    }    if ( rrs->isEmpty() ) {	delete rrs;	rrs = 0;    }}// the itsy-bitsy little socket class I don't really need except for// so I can subclass and reimplement the slots.Q3DnsSocket::Q3DnsSocket( QObject * parent, const char * name )    : QObject( parent, name ){    // nothing}Q3DnsSocket::~Q3DnsSocket(){    // nothing}void Q3DnsSocket::cleanCache(){    // nothing}void Q3DnsSocket::retransmit(){    // nothing}void Q3DnsSocket::answer(){    // nothing}

⌨️ 快捷键说明

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