예제 #1
0
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();
	}
}
예제 #2
0
파일: g2node.cpp 프로젝트: geekt/quazaa
void CG2Node::FlushSendQueue(bool bFullFlush)
{
    QByteArray* pOutput = GetOutputBuffer();

	while( bytesToWrite() == 0 && m_lSendQueue.size() )
	{
		while( pOutput->size() < 4096 && m_lSendQueue.size() )
		{
			G2Packet* pPacket = m_lSendQueue.dequeue();
			pPacket->ToBuffer(pOutput);
			pPacket->Release();
		}
		emit readyToTransfer();
	}


    if( bFullFlush )
    {
        if( m_bCompressedOutput && pOutput->size() )
            m_bOutputPending = true;
    }

    if( pOutput->size() )
        emit readyToTransfer();
}
예제 #3
0
void CDatagrams::onPing(CEndPoint& addr, G2Packet* pPacket)
{
	Q_UNUSED(pPacket);

	G2Packet* pNew = G2Packet::newPacket("PO", false);
	sendPacket(addr, pNew, false);
	pNew->release();
}
예제 #4
0
파일: g2node.cpp 프로젝트: geekt/quazaa
void CG2Node::OnRead()
{
	if( !Network.m_pSection.tryLock(50) )
	{
		emit readyRead(); // it is a queued connection, lets requeue the missed signal
		return;
	}

    //qDebug() << "CG2Node::OnRead";
    if( m_nState == nsHandshaking )
    {
        if( peek(bytesAvailable()).indexOf("\r\n\r\n") != -1 )
        {
            if( m_bInitiated )
            {
                ParseOutgoingHandshake();
            }
            else
            {
                ParseIncomingHandshake();
            }
        }
    }
    else if ( m_nState == nsConnected )
    {

		G2Packet* pPacket = 0;
        try
        {
			while( (pPacket = G2Packet::ReadBuffer(GetInputBuffer())) )
            {
				m_tLastPacketIn = time(0);
				m_nPacketsIn++;

				OnPacket(pPacket);

				pPacket->Release();
            }
        }
		catch(...)
        {
			if( pPacket )
			{
				qDebug() << pPacket->ToHex() << "\n" << pPacket->ToASCII();
				pPacket->Release();
			}

            qDebug() << "Packet error - " << m_oAddress.toString().toAscii();
            m_nState = nsClosing;
            emit NodeStateChanged();
            deleteLater();
        }
    }

	Network.m_pSection.unlock();
}
예제 #5
0
파일: query.cpp 프로젝트: c3c/quazaa
G2Packet* CQuery::ToG2Packet(CEndPoint* pAddr, quint32 nKey)
{
	G2Packet* pPacket = G2Packet::New("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);
	}

	foreach(CHash pHash, m_lHashes)
	{
		pPacket->WritePacket("URN", pHash.GetFamilyName().size() + CHash::ByteCount(pHash.getAlgorithm()) + 1);
		pPacket->WriteString(pHash.GetFamilyName() + "\0" + pHash.RawValue(), false);
	}
예제 #6
0
void CChatSessionG2::SendStartups()
{
	qDebug() << "sending startups";
	G2Packet* pPacket = G2Packet::New("UPROC", false);

	// A dirty workaround for Shareaza bug...
	if( m_bShareaza )
		pPacket->WriteString("dupa");

	SendPacket(pPacket);
}
예제 #7
0
파일: g2node.cpp 프로젝트: geekt/quazaa
void CG2Node::SendStartups()
{
	if( Network.IsListening() )
    {
        IPv4_ENDPOINT addr = Network.GetLocalAddress();
		G2Packet* pPacket = G2Packet::New("PI", true);
		pPacket->WritePacket("UDP", 6);
		pPacket->WriteHostAddress(&addr);
		pPacket->WritePacket("TFW", 0);
		SendPacket(pPacket, false, true);
    }

	SendLNI();
}
예제 #8
0
void CChatSessionG2::OnUPROC(G2Packet *pPacket)
{
	Q_UNUSED(pPacket);

	// Temporary code, needs to be moved to GProfile class

	QString sXML = "<?xml version=\"1.0\"?><gprofile xmlns=\"http://www.shareaza.com/schemas/GProfile.xsd\"><gnutella guid=\"%1\"/><identity><handle primary=\"%2\"/></identity></gprofile>";
	sXML = sXML.arg(quazaaSettings.Profile.GUID.toString().toUpper().replace("{", "").replace("}", "")).arg(quazaaSettings.Profile.GnutellaScreenName);

	G2Packet* pD = G2Packet::New("UPROD", true);
	pD->WritePacket("XML", sXML.toUtf8().size());
	pD->WriteString(sXML);

	SendPacket(pD);
}
예제 #9
0
파일: g2node.cpp 프로젝트: geekt/quazaa
void CG2Node::OnQuery(G2Packet *pPacket)
{
	// just read guid for now to have it in routing table

	QUuid oGUID;
	if( pPacket->m_bCompound )
		pPacket->SkipCompound();

	if( pPacket->GetRemaining() >= 16 )
	{
		oGUID = pPacket->ReadGUID();
		Network.m_oRoutingTable.Add(oGUID, this, false);

		if( m_nType == G2_LEAF ) // temporary
		{
			G2Packet* pQA = G2Packet::New("QA", true);
			quint32 tNow = time(0);
			pQA->WritePacket("TS", 4)->WriteIntLE(tNow);
			pQA->WritePacket("D", 8)->WriteHostAddress(&Network.m_oAddress);
			pQA->WriteIntLE(Network.m_nLeavesConnected);

			quint32 nCount = 0;

			for( uint i = 0; i < HostCache.size() && nCount < 100u; i++, nCount++ )
			{
				pQA->WritePacket("S", 6)->WriteHostAddress(&HostCache.m_lHosts[i]->m_oAddress);
			}

			pQA->WriteByte(0);
			pQA->WriteGUID(oGUID);
			//qDebug() << "Sending query ACK " << pQA->ToHex() << pQA->ToASCII();
			SendPacket(pQA, true, true);
		}
	}
}
예제 #10
0
void CChatSessionG2::OnRead()
{
	if( m_nState == csHandshaking )
	{
		if(Peek(bytesAvailable()).indexOf("\r\n\r\n") != -1)
		{
			if(m_bInitiated)
			{
				ParseOutgoingHandshake();
			}
			else
			{
				//ParseIncomingHandshake();
			}
		}
	}
	else if( m_nState == csConnected || m_nState == csActive )
	{
		G2Packet* pPacket = 0;
		try
		{
			while((pPacket = G2Packet::ReadBuffer(GetInputBuffer())))
			{
				OnPacket(pPacket);

				pPacket->Release();
			}
		}
		catch(...)
		{
			if(pPacket)
			{
				pPacket->Release();
			}

			emit systemMessage("Received corrupted G2 packet, connection lost.");

			CNetworkConnection::Close();
		}
		m_bReadyReadSent = false;
	}
}
예제 #11
0
파일: g2packet.cpp 프로젝트: geekt/quazaa
G2Packet* G2Packet::New(char* pSource)
{
	G2Packet* pPacket = New();

	char nInput		= *pSource++;

	char nLenLen	= ( nInput & 0xC0 ) >> 6;
	char nTypeLen	= ( nInput & 0x38 ) >> 3;
	char nFlags	= ( nInput & 0x07 );

	pPacket->m_bCompound	= ( nFlags & G2_FLAG_COMPOUND ) ? true : false;
	bool	bBigEndian	= ( nFlags & G2_FLAG_BIG_ENDIAN ) ? true : false;

	quint32 nLength = 0;

	if ( bBigEndian )
	{
		throw packet_error();
	}
	else
	{
		char* pLenOut = (char*)&nLength;
		while ( nLenLen-- ) *pLenOut++ = *pSource++;
	}

	nTypeLen++;
	char* pszType = pPacket->m_sType;
	for ( ; nTypeLen-- ;  )
	{
		*pszType++ = *pSource++;
	}
	*pszType++ = 0;

	pPacket->Write( pSource, nLength );

	return pPacket;
}
예제 #12
0
파일: g2node.cpp 프로젝트: geekt/quazaa
void CG2Node::SendLNI()
{
	G2Packet* pLNI = G2Packet::New("LNI", true);
	pLNI->WritePacket("NA", 6)->WriteHostAddress(&Network.m_oAddress);
	pLNI->WritePacket("GU", 16)->WriteGUID(quazaaSettings.Profile.GUID);
	pLNI->WritePacket("V", 4)->WriteString(quazaaGlobals.VendorCode(), false);

	if( Network.isHub() )
	{
		quint16 nLeafs = quazaaSettings.Gnutella2.NumLeafs;
		pLNI->WritePacket("HS", 4);
		pLNI->WriteIntLE(Network.m_nLeavesConnected);
		pLNI->WriteIntLE(nLeafs);
		pLNI->WritePacket("QK", 0);
	}

	pLNI->WritePacket("g2core", 0);

	SendPacket(pLNI, false, true);
}
예제 #13
0
파일: g2node.cpp 프로젝트: geekt/quazaa
void CG2Node::OnQKR(G2Packet *pPacket)
{
	if( !pPacket->m_bCompound || m_nType != G2_LEAF )
		return;

	char szType[9];
	quint32 nLength = 0, nNext = 0;
	bool bCacheOK = true;
	IPv4_ENDPOINT addr;

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

		if( strcmp("QNA", szType) == 0 && nLength >= 6 )
		{
			pPacket->ReadHostAddress(&addr);
		}
		else if( strcmp("REF", szType) == 0 )
		{
			bCacheOK = false;
		}

		pPacket->m_nPosition = nNext;
	}

	if( addr.ip == 0 || addr.port == 0 ) // TODO: sprawdzene czy adres jest za fw
		return;

	CHostCacheHost* pHost = bCacheOK ? HostCache.Find(addr) : 0;

	if( pHost != 0 && pHost->m_nQueryKey != 0 && pHost->m_nKeyHost == Network.m_oAddress.ip && time(0) - pHost->m_nKeyTime < quazaaSettings.Gnutella2.QueryKeyTime )
	{
		G2Packet* pQKA = G2Packet::New("QKA", true);
		pQKA->WritePacket("QNA", 6)->WriteHostAddress(&addr);
		pQKA->WritePacket("QK", 4)->WriteIntBE(pHost->m_nQueryKey);
		pQKA->WritePacket("CACHED", 0);
		SendPacket(pQKA, true, true);
	}
	else
	{
		G2Packet* pQKR = G2Packet::New("QKR", true);
		pQKR->WritePacket("SNA", 6)->WriteHostAddress(&m_oAddress);
		Datagrams.SendPacket(addr, pQKR, false);
		pQKR->Release();
	}
}
예제 #14
0
void CNetwork::DispatchKHL()
{
	QMutexLocker l(&Neighbours.m_pSection);

	if(Neighbours.m_lNodes.isEmpty())
	{
		return;
	}

	G2Packet* pKHL = G2Packet::New("KHL");
	quint32 ts = time(0);
	pKHL->WritePacket("TS", 4)->WriteIntLE(ts);

	for(QList<CNeighbour*>::iterator itNode = Neighbours.begin(); itNode != Neighbours.end(); ++itNode)
	{
		CNeighbour* pNode = *itNode;

		if( pNode->m_nProtocol != dpGnutella2 )
				continue;

		if(((CG2Node*)pNode)->m_nType == G2_HUB && pNode->m_nState == nsConnected)
		{
			pKHL->WritePacket("NH", 6)->WriteHostAddress(&pNode->m_oAddress);
		}
	}

	quint32 nCount = 0;

	for(; nCount < (quint32)quazaaSettings.Gnutella2.KHLHubCount && HostCache.size() > nCount; nCount++)
	{
		pKHL->WritePacket("CH", 10)->WriteHostAddress(&HostCache.m_lHosts.at(nCount)->m_oAddress);
		pKHL->WriteIntLE(&HostCache.m_lHosts.at(nCount)->m_tTimestamp);
	}


	for(QList<CNeighbour*>::iterator itNode = Neighbours.begin(); itNode != Neighbours.end(); ++itNode)
	{
		CNeighbour* pNode = *itNode;

		if( pNode->m_nProtocol != dpGnutella2 )
			continue;

		if(pNode->m_nState == nsConnected)
		{
			((CG2Node*)pNode)->SendPacket(pKHL, false, false);
		}
	}
	pKHL->Release();
}
예제 #15
0
void CChatSessionG2::SendMessage(QString sMessage, bool bAction)
{
	qDebug() << "Send message:" << sMessage << bAction;

	G2Packet* pPacket = G2Packet::New("CMSG", true);
	if( bAction )
		pPacket->WritePacket("ACT", 0);

	G2Packet* pBody = G2Packet::New("BODY");
	pBody->WriteString(sMessage);
	pPacket->WritePacket(pBody);
	pBody->Release();

	SendPacket(pPacket);
}
예제 #16
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;
}
예제 #17
0
void CDatagrams::onReceiveGND()
{
	GND_HEADER* pHeader = (GND_HEADER*)m_pRecvBuffer->data();
	QHostAddress nIp = *m_pHostAddress;
	quint32 nSeq = ((pHeader->nSequence << 16) & 0xFFFF0000) + (m_nPort & 0x0000FFFF);

#ifdef DEBUG_UDP
	systemLog.postLog(LogSeverity::Debug, "Received GND from %s:%u nSequence = %u nPart = %u nCount = %u", m_pHostAddress->toString().toLocal8Bit().constData(), m_nPort, pHeader->nSequence, pHeader->nPart, pHeader->nCount);
#endif

	DatagramIn* pDatagramIn = 0;

	if(m_RecvCache.contains(nIp) && m_RecvCache[nIp].contains(nSeq))
	{
		pDatagramIn = m_RecvCache[nIp][nSeq];

		// To give a chance for bigger packages ;)
		if(pDatagramIn->m_nLeft)
		{
			pDatagramIn->m_tStarted = time(0);
		}
	}
	else
	{
		QMutexLocker l(&m_pSection);

		if(!m_FreeDatagramIn.isEmpty())
		{
			pDatagramIn = m_FreeDatagramIn.takeFirst();
		}
		else
		{
			if(m_FreeDatagramIn.isEmpty())
			{
				removeOldIn(true);
				if(m_FreeDatagramIn.isEmpty())
				{
#ifdef DEBUG_UDP
					systemLog.postLog(LogSeverity::Debug, QString("UDP in frames exhausted"));
#endif
					m_nDiscarded++;
					return;
				}
			}

			pDatagramIn = m_FreeDatagramIn.takeFirst();
		}

		if(m_FreeBuffer.size() < pHeader->nCount)
		{
			m_nDiscarded++;
			m_FreeDatagramIn.append(pDatagramIn);
			removeOldIn(false);
			return;
		}

		pDatagramIn->create(CEndPoint(*m_pHostAddress, m_nPort), pHeader->nFlags, pHeader->nSequence, pHeader->nCount);

		for(int i = 0; i < pHeader->nCount; i++)
		{
			Q_ASSERT(pDatagramIn->m_pBuffer[i] == 0);
			pDatagramIn->m_pBuffer[i] = m_FreeBuffer.takeFirst();
		}

		m_RecvCache[nIp][nSeq] = pDatagramIn;
		m_RecvCacheTime.prepend(pDatagramIn);
	}

	// It is here, in case if we did not have free datagrams
	// ACK = I've received a datagram, and if you have received and rejected it, do not send ACK-a
	if(pHeader->nFlags & 0x02)
	{
		GND_HEADER* pAck = new GND_HEADER;

		memcpy(pAck, pHeader, sizeof(GND_HEADER));
		pAck->nCount = 0;
		pAck->nFlags = 0;

#ifdef DEBUG_UDP
		systemLog.postLog(LogSeverity::Debug, "Sending UDP ACK to %s:%u", m_pHostAddress->toString().toLocal8Bit().constData(), m_nPort);
#endif

		//m_pSocket->writeDatagram((char*)&oAck, sizeof(GND_HEADER), *m_pHostAddress, m_nPort);
		//m_mOutput.Add(sizeof(GND_HEADER));
		m_AckCache.append(qMakePair(CEndPoint(*m_pHostAddress, m_nPort), reinterpret_cast<char*>(pAck)));
		if( m_AckCache.count() == 1 )
			QMetaObject::invokeMethod(this, "flushSendCache", Qt::QueuedConnection);
	}

	if(pDatagramIn->add(pHeader->nPart, m_pRecvBuffer->data() + sizeof(GND_HEADER), m_pRecvBuffer->size() - sizeof(GND_HEADER)))
	{

		G2Packet* pPacket = 0;
		try
		{
			CEndPoint addr(*m_pHostAddress, m_nPort);
			pPacket = pDatagramIn->toG2Packet();
			if(pPacket)
			{
				onPacket(addr, pPacket);
			}
		}
		catch(...)
		{

		}
		if(pPacket)
		{
			pPacket->release();
		}

		m_pSection.lock();
		remove(pDatagramIn, true);
		m_pSection.unlock();
	}
}
예제 #18
0
void CChatSessionG2::OnUPROD(G2Packet *pPacket)
{
	qDebug() << "OnUPROD";

	if( !pPacket->m_bCompound )
		return;

	QUuid oGUID;
	bool hasXML = false;

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

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

		if(strcmp("XML", szType) == 0)
		{
			// Temporary code, needs to be moved to GProfile class
			QXmlStreamReader oXML;
			bool hasGprofile = false;
			bool hasGUID = false;
			bool hasIdentity = false;
			bool hasNick = false;
			oXML.addData(pPacket->ReadString(nLength));

			while(!oXML.atEnd() && !oXML.hasError())
			{
				QXmlStreamReader::TokenType token = oXML.readNext();

				if( token == QXmlStreamReader::StartDocument)
				{
					continue;
				}
				else if( token == QXmlStreamReader::StartElement )
				{
					if( oXML.name() == "gprofile" )
					{
						/*
						if( oXML.attributes().value("xmlns") != "http://www.shareaza.com/schemas/GProfile.xsd" )
							return;*/
						hasGprofile = true;
						continue;
					}
					else if( hasGprofile && oXML.name() == "gnutella" )
					{
						if( oXML.attributes().hasAttribute("guid") )
						{
							QString sTemp = oXML.attributes().value("guid").toString();
							QUuid oTemp(sTemp);
							oGUID = oTemp;
							hasGUID = true;
							continue;
						}
					}
					else if( hasGprofile && oXML.name() == "identity" )
					{
						hasIdentity = true;
						continue;
					}
					else if( hasGprofile && hasIdentity && oXML.name() == "handle" )
					{
						if( oXML.attributes().hasAttribute("primary") )
						{
							m_sNick = oXML.attributes().value("primary").toString();
							hasNick = true;
							continue;
						}
					}
				}
			}

			if( !hasNick || !hasGUID )
				return;

			hasXML = true;
		}

		pPacket->m_nPosition = nNext;
	}

	if( !hasXML )
		return;

	m_oGUID = oGUID;
	emit guidChanged(oGUID);
	emit nickChanged(m_sNick);

	if( m_bInitiated ) // TODO PUSH handling
	{
		G2Packet* pReq = G2Packet::New("CHATREQ", true);
		pReq->WritePacket("USERGUID", 16);
		pReq->WriteGUID(m_oGUID);

		SendPacket(pReq);
	}
}
예제 #19
0
void CDatagrams::onCRAWLR(CEndPoint& addr, G2Packet* pPacket)
{
	QMutexLocker l2(&Neighbours.m_pSection);

//	bool bRLeaf = false;
//	bool bRNick = false;
//	bool bRGPS = false;
//	bool bRExt = false;

	if(!pPacket->m_bCompound)
	{
		return;
	}

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

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

		if(strcmp("RLEAF", szType) == 0)
		{
//			bRLeaf = true;
		}
		else if(strcmp("RNAME", szType) == 0)
		{
//			bRNick = true;
		}
		else if(strcmp("RGPS", szType) == 0)
		{
//			bRGPS = true;
		}
		else if(strcmp("REXT", szType) == 0)
		{
//			bRExt = true;
		}

		pPacket->m_nPosition = nNext;
	}

	G2Packet* pCA = G2Packet::newPacket("CRAWLA", true);

	G2Packet* pTmp = G2Packet::newPacket("SELF", true);
	if(Neighbours.isG2Hub())
	{
		pTmp->writePacket("HUB", 0);
	}
	else
	{
		pTmp->writePacket("LEAF", 0);
	}
	pTmp->writePacket("NA", ((Network.m_oAddress.protocol() == 0) ? 6 : 18))->writeHostAddress(&Network.m_oAddress);
	pTmp->writePacket("CV", CQuazaaGlobals::USER_AGENT_STRING().toUtf8().size())->writeString(CQuazaaGlobals::USER_AGENT_STRING(), false);
	pTmp->writePacket("V", 4)->writeString(CQuazaaGlobals::VENDOR_CODE(), false);;
	quint16 nLeaves = Neighbours.m_nLeavesConnectedG2;
	pTmp->writePacket("HS", 2)->writeIntLE(nLeaves);
	if(!quazaaSettings.Profile.GnutellaScreenName.isEmpty())
	{
		pTmp->writePacket("NAME", quazaaSettings.Profile.GnutellaScreenName.left(255).toUtf8().size())->writeString(quazaaSettings.Profile.GnutellaScreenName.left(255));
	}

	pCA->writePacket(pTmp);
	pTmp->release();

	for(QList<CNeighbour*>::iterator itNode = Neighbours.begin(); itNode != Neighbours.end(); ++itNode)
	{
		if((*itNode)->m_nProtocol != dpG2)
		{
			continue;
		}

		CG2Node* pNode = (CG2Node*) * itNode;
		if(pNode->m_nState == nsConnected)
		{
			if(pNode->m_nType == G2_HUB)
			{
				G2Packet* pNH = G2Packet::newPacket("NH");
				pNH->writePacket("NA", ((pNode->m_oAddress.protocol() == 0) ? 6 : 18))->writeHostAddress(&pNode->m_oAddress);
				pNH->writePacket("HS", 2)->writeIntLE(pNode->m_nLeafCount);
				pCA->writePacket(pNH);
				pNH->release();
			}
			else if(pNode->m_nType == G2_LEAF)
			{
				G2Packet* pNL = G2Packet::newPacket("NL");
				pNL->writePacket("NA", ((pNode->m_oAddress.protocol() == 0) ? 6 : 18))->writeHostAddress(&pNode->m_oAddress);
				pCA->writePacket(pNL);
				pNL->release();
			}
		}
	}

	sendPacket(addr, pCA, true);

	pCA->release();
}
예제 #20
0
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
}
예제 #21
0
파일: g2node.cpp 프로젝트: geekt/quazaa
void CG2Node::OnPing(G2Packet* pPacket)
{
	bool bUdp = false;
    bool bRelay = false;
    bool bTestFirewall = false;
    IPv4_ENDPOINT 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("UDP", szType) == 0 && nLength >= 6)
			{
				pPacket->ReadHostAddress(&addr);
				if( addr.ip != 0 && addr.port != 0)
					bUdp = true;
			}
			else if( strcmp("RELAY", szType) == 0 )
			{
				bRelay = true;
			}
			else if( strcmp("TFW", szType) == 0 )
			{
				bTestFirewall = true;
			}

			pPacket->m_nPosition = nNext;
		}

    }

    if( !bUdp && !bRelay )
    {
        // direct ping
		G2Packet* pPong = G2Packet::New("PO", false);
		SendPacket(pPong, false, true);
        return;
    }

    if( bUdp && !bRelay )
    {
        // /PI/UDP

        if( Network.isHub() )
        {
			char* pRelay = pPacket->WriteGetPointer(7, 0);
			*pRelay++ = 0x60;
			*pRelay++ = 0;
			*pRelay++ = 'R'; *pRelay++ = 'E'; *pRelay++ = 'L';
			*pRelay++ = 'A'; *pRelay++ = 'Y';


            QList<CG2Node*> lToRelay;

            for( int i = 0; i < Network.m_lNodes.size(); i++ )
            {
                if( Network.m_lNodes.at(i)->m_nState == nsConnected )
                    lToRelay.append(Network.m_lNodes[i]);
            }

			for( int nCount = 0; nCount < quazaaSettings.Gnutella2.PingRelayLimit && lToRelay.size(); nCount++ )
            {
                int nIndex = qrand() % lToRelay.size();
                pPacket->AddRef();
                CG2Node* pNode = lToRelay.at(nIndex);
				pNode->SendPacket(pPacket, true, true);
                lToRelay.removeAt(nIndex);
            }

            return;
        }
    }

    if( bUdp && bRelay )
    {
		G2Packet* pPong = G2Packet::New("PO", true);
		pPong->WritePacket("RELAY", 0);
        Datagrams.SendPacket(addr, pPong, true);
        pPong->Release();
	}
}
예제 #22
0
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();
	}
}
예제 #23
0
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
}