bool CNetwork::RoutePacket(QUuid& pTargetGUID, G2Packet* pPacket) { CG2Node* pNode = 0; CEndPoint pAddr; if(m_oRoutingTable.Find(pTargetGUID, &pNode, &pAddr)) { if(pNode) { pNode->SendPacket(pPacket, true, false); systemLog.postLog(LogSeverity::Debug, QString("CNetwork::RoutePacket %1 Packet: %2 routed to neighbour: %3").arg(pTargetGUID.toString()).arg(pPacket->GetType()).arg(pNode->m_oAddress.toString().toAscii().constData())); //qDebug() << "CNetwork::RoutePacket " << pTargetGUID.toString() << " Packet: " << pPacket->GetType() << " routed to neighbour: " << pNode->m_oAddress.toString().toAscii().constData(); return true; } else if(!pAddr.isNull()) { Datagrams.SendPacket(pAddr, pPacket, true); systemLog.postLog(LogSeverity::Debug, QString("CNetwork::RoutePacket %1 Packet: %2 routed to remote node: %3").arg(pTargetGUID.toString()).arg(pPacket->GetType()).arg(pNode->m_oAddress.toString().toAscii().constData())); //qDebug() << "CNetwork::RoutePacket " << pTargetGUID.toString() << " Packet: " << pPacket->GetType() << " routed to remote node: " << pNode->m_oAddress.toString().toAscii().constData(); return true; } systemLog.postLog(LogSeverity::Debug, QString("CNetwork::RoutePacket - No node and no address!")); //qDebug() << "CNetwork::RoutePacket - weird thing, should not happen..."; } systemLog.postLog(LogSeverity::Debug, QString("CNetwork::RoutePacket %1 Packet: %2 DROPED!").arg(pTargetGUID.toString()).arg(pPacket->GetType())); //qDebug() << "CNetwork::RoutePacket " << pTargetGUID.toString() << " Packet: " << pPacket->GetType() << " DROPPED!"; return false; }
bool CNetwork::RoutePacket(G2Packet* pPacket, CG2Node* pNbr) { QUuid pGUID; if(pPacket->GetTo(pGUID) && pGUID != quazaaSettings.Profile.GUID) // no i adres != moj adres { CG2Node* pNode = 0; CEndPoint pAddr; if(m_oRoutingTable.Find(pGUID, &pNode, &pAddr)) { bool bForwardTCP = false; bool bForwardUDP = false; if(pNbr) { if(pNbr->m_nType == G2_LEAF) // if received from leaf - can forward anywhere { bForwardTCP = bForwardUDP = true; } else // if received from a hub - can be forwarded to leaf { if(pNode && pNode->m_nType == G2_LEAF) { bForwardTCP = true; } } } else // received from udp - do not forward via udp { bForwardTCP = true; } if(pNode && bForwardTCP) { pNode->SendPacket(pPacket, true, false); return true; } else if(!pAddr.isNull() && bForwardUDP) { Datagrams.SendPacket(pAddr, pPacket, true); return true; } // drop } return true; } return false; }
void CDatagrams::listen() { QMutexLocker l(&m_pSection); if(m_bActive) { systemLog.postLog(LogSeverity::Debug, QString("CDatagrams::Listen - already listening")); return; } Q_ASSERT(m_pSocket == 0); m_pSocket = new QUdpSocket(this); CEndPoint addr = Network.getLocalAddress(); if(m_pSocket->bind(addr.port())) { systemLog.postLog(LogSeverity::Debug, QString("Datagrams listening on %1").arg(m_pSocket->localPort())); m_nDiscarded = 0; for(int i = 0; i < quazaaSettings.Gnutella2.UdpBuffers; i++) { m_FreeBuffer.append(new CBuffer(1024)); } for(int i = 0; i < quazaaSettings.Gnutella2.UdpInFrames; i++) { m_FreeDatagramIn.append(new DatagramIn); } for(int i = 0; i < quazaaSettings.Gnutella2.UdpOutFrames; i++) { m_FreeDatagramOut.append(new DatagramOut); } connect(this, SIGNAL(sendQueueUpdated()), this, SLOT(flushSendCache()), Qt::QueuedConnection); connect(m_pSocket, SIGNAL(readyRead()), this, SLOT(onDatagram()), Qt::QueuedConnection); m_bActive = true; } else { systemLog.postLog(LogSeverity::Debug, QString("Can't bind UDP socket! UDP communication disabled!")); disconnectNode(); } m_bFirewalled = true; }
bool CNetwork::routePacket(QUuid& pTargetGUID, G2Packet* pPacket, bool bLockNeighbours, bool bBuffered) { CG2Node* pNode = 0; CEndPoint pAddr; if(m_oRoutingTable.find(pTargetGUID, &pNode, &pAddr)) { if(pNode) { if( bLockNeighbours ) { Neighbours.m_pSection.lock(); } if( Neighbours.neighbourExists(pNode) ) { pNode->sendPacket(pPacket, bBuffered, false); systemLog.postLog(LogSeverity::Debug, QString("CNetwork::RoutePacket %1 Packet: %2 routed to neighbour: %3").arg(pTargetGUID.toString()).arg(pPacket->getType()).arg(pNode->m_oAddress.toString().toLocal8Bit().constData())); } if( bLockNeighbours ) { Neighbours.m_pSection.unlock(); } return true; } else if(pAddr.isValid()) { Datagrams.sendPacket(pAddr, pPacket, true); systemLog.postLog(LogSeverity::Debug, QString("CNetwork::RoutePacket %1 Packet: %2 routed to remote node: %3").arg(pTargetGUID.toString()).arg(pPacket->getType()).arg(pAddr.toString().toLocal8Bit().constData())); return true; } systemLog.postLog(LogSeverity::Debug, QString("CNetwork::RoutePacket - No node and no address!")); } systemLog.postLog(LogSeverity::Debug, QString("CNetwork::RoutePacket %1 Packet: %2 DROPPED!").arg(pTargetGUID.toString()).arg(pPacket->getType())); return false; }
CHostCache::CHostCache() { QFile f("hostcache.dat"); if(f.exists() && f.open(QFile::ReadOnly)) { QDataStream s(&f); quint16 nVersion; s >> nVersion; CEndPoint addr; quint32 ts; quint16 nPort; while(!f.atEnd()) { s >> *(QHostAddress*)&addr >> nPort >> ts; addr.setPort(nPort); Add(addr, ts); } f.close(); }
void CDatagrams::sendPacket(CEndPoint& oAddr, G2Packet* pPacket, bool bAck, DatagramWatcher* pWatcher, void* pParam) { if(!m_bActive) { return; } QMutexLocker l(&m_pSection); Q_UNUSED(pWatcher); Q_UNUSED(pParam); if(m_FreeDatagramOut.isEmpty()) { systemLog.postLog(LogSeverity::Debug, QString("UDP out frames exhausted")); if( !bAck ) // if caller does not want ACK, drop the packet here return; // TODO: needs more testing remove(m_SendCache.last()); } if(m_FreeBuffer.isEmpty()) { removeOldIn(false); if(m_FreeBuffer.isEmpty()) { systemLog.postLog(LogSeverity::Debug, QString("UDP out discarded, out of buffers")); return; } } DatagramOut* pDatagramOut = m_FreeDatagramOut.takeFirst(); pDatagramOut->create(oAddr, pPacket, m_nSequence++, m_FreeBuffer.takeFirst(), (bAck && (m_nInFrags > 0))); // to prevent net spam when unable to receive datagrams m_SendCache.prepend(pDatagramOut); m_SendCacheMap[pDatagramOut->m_nSequence] = pDatagramOut; // TODO: Notify the listener if we have one. #ifdef DEBUG_UDP systemLog.postLog(LogSeverity::Debug, "UDP queued for %s seq %u parts %u", oAddr.toString().toLocal8Bit().constData(), pDatagramOut->m_nSequence, pDatagramOut->m_nCount); #endif //emit SendQueueUpdated(); __FlushSendCache(); }
void CNetworkConnection::ConnectTo(CEndPoint oAddress) { m_oAddress = oAddress; m_bInitiated = true; m_bConnected = false; m_tConnected = time(0); Q_ASSERT(m_pInput == 0); Q_ASSERT(m_pOutput == 0); m_pInput = new CBuffer(8192); m_pOutput = new CBuffer(8192); Q_ASSERT(m_pSocket == 0); m_pSocket = new QTcpSocket(); initializeSocket(); m_pSocket->connectToHost(oAddress, oAddress.port()); }
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::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::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 }
bool CSearchManager::OnQueryAcknowledge(G2Packet* pPacket, CEndPoint& addr, QUuid& oGUID) { if(!pPacket->m_bCompound) { return false; } pPacket->SkipCompound(); // skip children to get search GUID if(pPacket->GetRemaining() < 16) // must be at least 16 bytes for GUID { return false; } oGUID = pPacket->ReadGUID(); // Read search GUID QMutexLocker l(&m_pSection); if(CManagedSearch* pSearch = Find(oGUID)) // is it our Query Ack? { // YES, this is ours, let's parse the packet and process it CEndPoint oFromIp = addr; QList<QHostAddress> lDone; quint32 nRetryAfter = 0; qint64 tAdjust = 0; quint32 tNow = time(0); quint32 nHubs = 0, nLeaves = 0, nSuggestedHubs = 0; pPacket->m_nPosition = 0; // reset position char szType[9]; quint32 nLength = 0, nNext = 0; while(pPacket->ReadPacket(&szType[0], nLength)) { nNext = pPacket->m_nPosition + nLength; if(strcmp("D", szType) == 0 && nLength >= 4) { QHostAddress ha; if( nLength >= 16 ) { // IPv6 Q_IPV6ADDR nIP; pPacket->Read(&nIP, 16); ha.setAddress(nIP); if( nLength >= 18 ) { quint16 nPort = pPacket->ReadIntLE<quint16>(); CEndPoint a(nIP, nPort); HostCache.Add(a, tNow); } if(nLength >= 20) { nLeaves += pPacket->ReadIntLE<quint16>(); } } else { // IPv4 quint32 nIP = pPacket->ReadIntBE<quint32>(); ha.setAddress(nIP); if(nLength >= 6) { quint16 nPort = pPacket->ReadIntLE<quint16>(); CEndPoint a(nIP, nPort); HostCache.Add(a, tNow); } if(nLength >= 8) { nLeaves += pPacket->ReadIntLE<quint16>(); } } lDone.append(ha); nHubs++; } else if(strcmp("S", szType) == 0 && nLength >= 6) { CEndPoint a; pPacket->ReadHostAddress(&a, !(nLength >= 18)); quint32 tSeen = (nLength >= (a.protocol() == 0 ? 10 : 22)) ? pPacket->ReadIntLE<quint32>() + tAdjust : tNow; HostCache.Add(a, tSeen); nSuggestedHubs++; } else if(strcmp("TS", szType) == 0 && nLength >= 4) { tAdjust = tNow - pPacket->ReadIntLE<quint32>(); } else if(strcmp("RA", szType) == 0 && nLength >= 2) { if(nLength >= 4) { nRetryAfter = pPacket->ReadIntLE<quint32>(); } else if(nLength >= 2) { nRetryAfter = pPacket->ReadIntLE<quint16>(); } CHostCacheHost* pHost = HostCache.Find(oFromIp); if(pHost) { pHost->m_tRetryAfter = tNow + nRetryAfter; } } else if(strcmp("FR", szType) == 0 && nLength >= 4) { if( nLength >= 16 ) { Q_IPV6ADDR ip; pPacket->Read(&ip, 16); oFromIp.setAddress(ip); } else { quint32 nFromIp = pPacket->ReadIntBE<quint32>(); oFromIp.setAddress(nFromIp); } } pPacket->m_nPosition = nNext; } // we already know QA GUID systemLog.postLog(LogSeverity::Debug, "Processing query acknowledge from %s (time adjust %+d seconds): %d hubs, %d leaves, %d suggested hubs, retry after %d seconds.", addr.toString().toAscii().constData(), int(tAdjust), nHubs, nLeaves, nSuggestedHubs, nRetryAfter); //qDebug("Processing query acknowledge from %s (time adjust %+d seconds): %d hubs, %d leaves, %d suggested hubs, retry after %d seconds.", // addr.toString().toAscii().constData(), int(tAdjust), nHubs, nLeaves, nSuggestedHubs, nRetryAfter); pSearch->m_nHubs += nHubs; pSearch->m_nLeaves += nLeaves; pSearch->OnHostAcknowledge(oFromIp, tNow); for(int i = 0; i < lDone.size(); i++) { pSearch->OnHostAcknowledge(lDone[i], tNow); } emit pSearch->StatsUpdated(); return false; } // not our ack - tell caller to route it return true; }