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); } } }
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 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 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); }
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 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::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 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 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(); } }