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(); } }
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(); }
void CDatagrams::onPing(CEndPoint& addr, G2Packet* pPacket) { Q_UNUSED(pPacket); G2Packet* pNew = G2Packet::newPacket("PO", false); sendPacket(addr, pNew, false); pNew->release(); }
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(); }
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); }
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); }
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(); }
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); }
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); } } }
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; } }
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; }
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); }
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(); } }
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(); }
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); }
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::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(); } }
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); } }
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(); }
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 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(); } }
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 }