void CDatagrams::onQA(CEndPoint& addr, G2Packet* pPacket)
{
	hostCache.m_pSection.lock();

	CHostCacheHost* pHost = hostCache.add( addr, common::getTNowUTC() );
	if ( pHost )
	{
		pHost->m_tAck = 0;
	}

	hostCache.m_pSection.unlock();

	QUuid oGuid;

	// Hubs are only supposed to route UDP /QA - we'll drop it if we're in leaf mode
	if ( SearchManager.onQueryAcknowledge( pPacket, addr, oGuid ) && Neighbours.isG2Hub() )
	{
		// Add from address
		G2Packet* pFR = G2Packet::newPacket( "FR" );
		pFR->writeHostAddress( &addr );
		pPacket->addOrReplaceChild( "FR", pFR );

		Network.m_pSection.lock();
		Network.routePacket( oGuid, pPacket, true, false );
		Network.m_pSection.unlock();
	}
}
Beispiel #2
0
G2Packet* Query::toG2Packet( EndPoint* pAddr, quint32 nKey )
{
	G2Packet* pPacket = G2Packet::newPacket( "Q2", true );

	//bool bWantURL = true;
	bool bWantDN = ( !m_sDescriptiveName.isEmpty() );
	bool bWantMD = !m_sMetadata.isEmpty();
	//bool bWantPFS = true;

	if ( pAddr )
	{
		G2Packet* pUDP = pPacket->writePacket( "UDP", 10 );
		pUDP->writeHostAddress( *pAddr );
		pUDP->writeIntLE( nKey );
	}

	if ( bWantDN )
	{
		pPacket->writePacket( "DN", m_sDescriptiveName.toUtf8().size() )->writeString( m_sDescriptiveName, false );
	}
	if ( bWantMD )
	{
		pPacket->writePacket( "MD", m_sMetadata.toUtf8().size() )->writeString( m_sMetadata, false );
	}

	for ( quint8 i = 0, nSize = m_vHashes.size(); i < nSize; ++i )
	{
		if ( m_vHashes[i] )
		{
			pPacket->writePacket( "URN", m_vHashes[i]->getFamilyName().size() + Hash::byteCount( m_vHashes[i]->algorithm() ) + 1 );
			pPacket->writeString( m_vHashes[i]->getFamilyName() + "\0" + m_vHashes[i]->rawValue(), false );
		}
	}

	/*if( m_nMinimumSize > 0 && m_nMaximumSize < 0xFFFFFFFFFFFFFFFF )
	{
		G2Packet* pSZR = pPacket->WriteChild("SZR");
		pSZR->writeIntLE(m_nMinimumSize);
		pSZR->writeIntLE(m_nMaximumSize);
	}
	else if( m_nMinimumSize > 0 )
	{
		G2Packet* pSZR = pPacket->WriteChild("SZR");
		pSZR->writeIntLE(m_nMinimumSize);
		pSZR->writeIntLE(0xFFFFFFFFFFFFFFFF);
	}
	else if( m_nMaximumSize < 0xFFFFFFFFFFFFFFFF )
	{
		G2Packet* pSZR = pPacket->WriteChild("SZR");
		pSZR->writeIntLE(0);
		pSZR->writeIntLE(m_nMaximumSize);
	}

	if( bWantURL || bWantDN || bWantMD || bWantPFS )
	{
		G2Packet* pInt = pPacket->WriteChild("I");
		if( bWantURL )
			pInt->writeString("URL", true);
		if( bWantDN )
			pInt->writeString("DN", true);
		if( bWantMD )
			pInt->writeString("MD", true);
		if( bWantPFS )
			pInt->writeString("PFS", true);
	}*/

	pPacket->writeByte( 0 );
	pPacket->writeGUID( m_oGUID );

	return pPacket;
}
void CDatagrams::onQKR(CEndPoint& addr, G2Packet* pPacket)
{
	if(!Neighbours.isG2Hub())
	{
		return;
	}

	CEndPoint oRequestedAddress = addr;
	CEndPoint oSendingAddress = addr;

	if(pPacket->m_bCompound)
	{
		char szType[9];
		quint32 nLength = 0, nNext = 0;

		while(pPacket->readPacket(&szType[0], nLength))
		{
			nNext = pPacket->m_nPosition + nLength;

			if(strcmp("SNA", szType) == 0 && nLength >= 4)
			{
				if(nLength >= 16)
				{
					Q_IPV6ADDR ip;
					pPacket->read(&ip, 16);
					oSendingAddress.setAddress(ip);
				}
				else
				{
					quint32	nIp = pPacket->readIntBE<quint32>();
					oSendingAddress.setAddress(nIp);
				}
			}
			else if(strcmp("RNA", szType) == 0 && nLength >= 6)
			{
				if(nLength >= 18)
				{
					pPacket->readHostAddress(&oRequestedAddress, false);
				}
				else
				{
					pPacket->readHostAddress(&oRequestedAddress);
				}
			}
			pPacket->m_nPosition = nNext;
		}
	}

	if(!oRequestedAddress.port() || oRequestedAddress.isFirewalled())
	{
		return;
	}

	G2Packet* pAns = G2Packet::newPacket("QKA", true);
	quint32 nKey = QueryKeys.create(oRequestedAddress);
	pAns->writePacket("QK", 4);
	pAns->writeIntLE<quint32>(nKey);
	G2Packet* pSNA = G2Packet::newPacket("SNA");
	pSNA->writeHostAddress(&oSendingAddress);
	pAns->writePacket(pSNA);
	pSNA->release();

	sendPacket(oRequestedAddress, pAns, false);
	pAns->release();

#if LOG_QUERY_HANDLING
	systemLog.postLog(LogSeverity::Debug, "Node %s asked for a query key (0x%08x) for node %s", qPrintable(addr.toStringWithPort()), nKey, qPrintable(oRequestedAddress.toStringWithPort()));
#endif // LOG_QUERY_HANDLING
}
void CDatagrams::onQKA(CEndPoint& addr, G2Packet* pPacket)
{
	if ( !pPacket->m_bCompound )
	{
		return;
	}

	quint32 nKey = 0;
	QHostAddress nKeyHost;

	char szType[9];
	quint32 nLength = 0, nNext = 0;

	while(pPacket->readPacket(&szType[0], nLength))
	{
		nNext = pPacket->m_nPosition + nLength;

		if(strcmp("QK", szType) == 0 && nLength >= 4)
		{
			nKey = pPacket->readIntLE<quint32>();
		}
		else if(strcmp("SNA", szType) == 0 && nLength >= 4)
		{
			if(nLength >= 16)
			{
				Q_IPV6ADDR ip;
				pPacket->read(&ip, 16);
				nKeyHost.setAddress(ip);
			}
			else
			{
				quint32 nIp = pPacket->readIntBE<quint32>();
				nKeyHost.setAddress(nIp);
			}
		}
		pPacket->m_nPosition = nNext;
	}

	hostCache.m_pSection.lock();
	CHostCacheHost* pCache = hostCache.add( addr, common::getTNowUTC() );
	if ( pCache )
	{
		if( !nKey ) // null QK means a hub does not want to be queried or just downgraded
		{
			hostCache.remove( pCache );
		}
		else
		{
			pCache->setKey( nKey );
		}
	}
	hostCache.m_pSection.unlock();

#if LOG_QUERY_HANDLING
	systemLog.postLog(LogSeverity::Debug, QString("Got a query key for %1 = 0x%2").arg(addr.toString().toLocal8Bit().constData()).arg(nKey));
	//qDebug("Got a query key for %s = 0x%x", addr.toString().toLocal8Bit().constData(), nKey);
#endif // LOG_QUERY_HANDLING

	if(Neighbours.isG2Hub() && !nKeyHost.isNull() && nKeyHost != ((QHostAddress)Network.m_oAddress))
	{
		G2Packet* pQNA = G2Packet::newPacket("QNA");
		pQNA->writeHostAddress(&addr);
		pPacket->prependPacket(pQNA);

		Neighbours.m_pSection.lock();
		CNeighbour* pNode = Neighbours.find(nKeyHost, dpG2);
		if( pNode )
		{
			((CG2Node*)pNode)->sendPacket(pPacket, true, false);
		}
		Neighbours.m_pSection.unlock();
	}
}
void CDatagrams::onQuery(CEndPoint &addr, G2Packet *pPacket)
{
	CQueryPtr pQuery = CQuery::fromPacket(pPacket, &addr);

	if(pQuery.isNull())
	{
#if LOG_QUERY_HANDLING
		qDebug() << "Received malformed query from" << qPrintable(addr.toStringWithPort());
#endif // LOG_QUERY_HANDLING
		return;
	}

	if( !Neighbours.isG2Hub() )
	{
		// Stop receiving queries from others
		// We are here because we just downgraded to leaf mode
		// Shareaza should not retry with QK == 0
		// TODO: test this
#if LOG_QUERY_HANDLING
		systemLog.postLog(LogSeverity::Debug, "Sending null query key to %s because we're not a hub.", qPrintable(addr.toStringWithPort()));
#endif // LOG_QUERY_HANDLING

		G2Packet* pQKA = G2Packet::newPacket("QKA", true);
		pQKA->writePacket("QK", 4)->writeIntLE<quint32>(0);

		if( addr != pQuery->m_oEndpoint )
		{
			pQKA->writePacket("SNA", (pQuery->m_oEndpoint.protocol() == QAbstractSocket::IPv6Protocol ? 18 : 6))->writeHostAddress(&pQuery->m_oEndpoint);
		}

		sendPacket(pQuery->m_oEndpoint, pQKA);
		pQKA->release();

		return;
	}

	if(!QueryKeys.check(pQuery->m_oEndpoint, pQuery->m_nQueryKey))
	{
#if LOG_QUERY_HANDLING
		systemLog.postLog(LogSeverity::Debug, "Issuing query key correction for %s.", qPrintable(addr.toStringWithPort()));
#endif // LOG_QUERY_HANDLING

		G2Packet* pQKA = G2Packet::newPacket("QKA", true);
		pQKA->writePacket("QK", 4)->writeIntLE<quint32>(QueryKeys.create(pQuery->m_oEndpoint));

		if( addr != pQuery->m_oEndpoint )
		{
			pQKA->writePacket("SNA", (pQuery->m_oEndpoint.protocol() == QAbstractSocket::IPv6Protocol ? 18 : 6))->writeHostAddress(&pQuery->m_oEndpoint);
		}
		sendPacket(addr, pPacket);
		pQKA->release();

		return;
	}

	if( !Network.m_oRoutingTable.add(pQuery->m_oGUID, pQuery->m_oEndpoint) )
	{
#if LOG_QUERY_HANDLING
		qDebug() << "Query already processed, ignoring";
#endif // LOG_QUERY_HANDLING
		G2Packet* pQA = Neighbours.createQueryAck(pQuery->m_oGUID, false, 0, false);
		sendPacket(pQuery->m_oEndpoint, pQA, true);
		pQA->release();
		return;
	}

#if LOG_QUERY_HANDLING
	qDebug() << "Processing query from: " << qPrintable(addr.toStringWithPort());
#endif // LOG_QUERY_HANDLING

	// just in case
	if( pQuery->m_oEndpoint == Network.m_oAddress )
	{
		systemLog.postLog( LogSeverity::Error, Components::Network,
						   "Q2 received via UDP and return address points to us, changing return address to source %s",
						   qPrintable( addr.toStringWithPort() ) );
		G2Packet* pUDP = G2Packet::newPacket("UDP");
		pUDP->writeHostAddress(&addr);
		pUDP->writeIntLE<quint32>(0);
		pPacket->addOrReplaceChild("UDP", pUDP);
	}

	Neighbours.m_pSection.lock();
	G2Packet* pQA = Neighbours.createQueryAck(pQuery->m_oGUID);
	sendPacket(pQuery->m_oEndpoint, pQA, true);
	pQA->release();

	Neighbours.routeQuery(pQuery, pPacket);
	Neighbours.m_pSection.unlock();

	// local search
}