📄 g2neighbour.cpp
字号:
{
pPacket->WritePacket( "NH", 14 + 6, TRUE ); // 4
pPacket->WritePacket( "HS", 2 ); // 4
pPacket->WriteShortBE( (WORD)pNeighbour->m_nLeafCount ); // 2
pPacket->WritePacket( "V", 4 ); // 3
pPacket->WriteString( pNeighbour->m_pVendor->m_sCode ); // 5
}
else
{
pPacket->WritePacket( "NH", 7 + 6, TRUE ); // 4
pPacket->WritePacket( "HS", 2 ); // 4
pPacket->WriteShortBE( (WORD)pNeighbour->m_nLeafCount ); // 2
pPacket->WriteByte( 0 ); // 1
}
pPacket->WriteLongLE( pNeighbour->m_pHost.sin_addr.S_un.S_addr ); // 4
pPacket->WriteShortBE( htons( pNeighbour->m_pHost.sin_port ) ); // 2
}
}
int nCount = Settings.Gnutella2.KHLHubCount;
DWORD tNow = time( NULL );
pPacket->WritePacket( "TS", 4 );
pPacket->WriteLongBE( time( NULL ) );
for ( CHostCacheHost* pHost = HostCache.Gnutella2.GetNewest() ; pHost && nCount > 0 ; pHost = pHost->m_pPrevTime )
{
if ( pHost->CanQuote( tNow ) &&
Neighbours.Get( &pHost->m_pAddress ) == NULL &&
pHost->m_pAddress.S_un.S_addr != Network.m_pHost.sin_addr.S_un.S_addr )
{
int nLength = 10;
if ( pHost->m_pVendor && pHost->m_pVendor->m_sCode.GetLength() == 4 )
nLength += 7;
if ( m_nNodeType == ntLeaf && pHost->m_nKeyValue != 0 && pHost->m_nKeyHost == Network.m_pHost.sin_addr.S_un.S_addr )
nLength += 8;
if ( nLength > 10 )
nLength ++;
pPacket->WritePacket( "CH", nLength, nLength > 10 );
if ( pHost->m_pVendor && pHost->m_pVendor->m_sCode.GetLength() == 4 )
{
pPacket->WritePacket( "V", 4 ); // 3
pPacket->WriteString( pHost->m_pVendor->m_sCode, FALSE ); // 4
}
if ( m_nNodeType == ntLeaf && pHost->m_nKeyValue != 0 && pHost->m_nKeyHost == Network.m_pHost.sin_addr.S_un.S_addr )
{
pPacket->WritePacket( "QK", 4 ); // 4
pPacket->WriteLongBE( pHost->m_nKeyValue ); // 4
}
if ( nLength > 10 ) pPacket->WriteByte( 0 ); // 1
pPacket->WriteLongLE( pHost->m_pAddress.S_un.S_addr ); // 4
pPacket->WriteShortBE( pHost->m_nPort ); // 2
pPacket->WriteLongBE( pHost->m_tSeen ); // 4
nCount--;
}
}
Send( pPacket, TRUE, TRUE );
m_tLastKHL = GetTickCount();
}
//////////////////////////////////////////////////////////////////////
// CG2Neighbour KNOWN HUB LIST : receive
BOOL CG2Neighbour::OnKHL(CG2Packet* pPacket)
{
if ( ! pPacket->m_bCompound ) return TRUE;
CHAR szType[9], szInner[9];
DWORD nLength, nInner;
BOOL bCompound;
DWORD tNow = time( NULL );
m_pHubGroup->Clear();
while ( pPacket->ReadPacket( szType, nLength, &bCompound ) )
{
DWORD nNext = pPacket->m_nPosition + nLength;
if ( strcmp( szType, "NH" ) == 0 ||
strcmp( szType, "CH" ) == 0 )
{
DWORD nAddress = 0, nKey = 0, tSeen = tNow;
WORD nPort = 0, nLeafs = 0;
CString strVendor;
if ( bCompound || 0 == strcmp( szType, "NH" ) )
{
while ( pPacket->m_nPosition < nNext && pPacket->ReadPacket( szInner, nInner ) )
{
DWORD nNextX = pPacket->m_nPosition + nInner;
if ( strcmp( szInner, "NA" ) == 0 && nInner >= 6 )
{
nAddress = pPacket->ReadLongLE();
nPort = pPacket->ReadShortBE();
}
else if ( strcmp( szInner, "V" ) == 0 && nInner >= 4 )
{
strVendor = pPacket->ReadString( 4 );
}
else if ( strcmp( szInner, "QK" ) == 0 && nInner >= 4 )
{
nKey = pPacket->ReadLongBE();
m_bCachedKeys = TRUE;
}
else if ( strcmp( szInner, "TS" ) == 0 && nInner >= 4 )
{
tSeen = pPacket->ReadLongBE() + m_tAdjust;
}
pPacket->m_nPosition = nNextX;
}
nLength = nNext - pPacket->m_nPosition;
}
if ( nLength >= 6 )
{
nAddress = pPacket->ReadLongLE();
nPort = pPacket->ReadShortBE();
if ( nLength >= 10 ) tSeen = pPacket->ReadLongBE() + m_tAdjust;
}
if ( FALSE == Network.IsFirewalledAddress( &nAddress, TRUE ) )
{
CHostCacheHost* pCached = HostCache.Gnutella2.Add(
(IN_ADDR*)&nAddress, nPort, tSeen, strVendor );
if ( pCached != NULL && m_nNodeType == ntHub )
{
if ( pCached->m_nKeyValue == 0 ||
pCached->m_nKeyHost != Network.m_pHost.sin_addr.S_un.S_addr )
{
pCached->SetKey( nKey, &m_pHost.sin_addr );
}
}
if ( strcmp( szType, "NH" ) == 0 )
{
m_pHubGroup->Add( (IN_ADDR*)&nAddress, nPort );
}
}
}
else if ( strcmp( szType, "TS" ) == 0 && nLength >= 4 )
{
m_tAdjust = (LONG)tNow - (LONG)pPacket->ReadLongBE();
}
pPacket->m_nPosition = nNext;
}
return TRUE;
}
//////////////////////////////////////////////////////////////////////
// CG2Neighbour HUB ADVERTISEMENT WALKER : send
void CG2Neighbour::SendHAW()
{
m_tLastHAW = GetTickCount();
if ( m_nNodeType == ntLeaf || Neighbours.IsLeaf() ) return;
CG2Packet* pPacket = CG2Packet::New( G2_PACKET_HAW, TRUE );
WORD nLeafs = 0;
GGUID pGUID;
Network.CreateID( &pGUID );
for ( POSITION pos = Neighbours.GetIterator() ; pos ; )
{
CNeighbour* pNeighbour = Neighbours.GetNext( pos );
if ( pNeighbour != this &&
pNeighbour->m_nState == nrsConnected &&
pNeighbour->m_nNodeType == ntLeaf )
{
nLeafs++;
}
}
pPacket->WritePacket( "NA", 6 );
pPacket->WriteLongLE( Network.m_pHost.sin_addr.S_un.S_addr );
pPacket->WriteShortBE( htons( Network.m_pHost.sin_port ) );
pPacket->WritePacket( "HS", 2 );
pPacket->WriteShortBE( nLeafs );
pPacket->WritePacket( "V", 4 );
pPacket->WriteString( SHAREAZA_VENDOR_A ); // 5 bytes
pPacket->WriteByte( 100 );
pPacket->WriteByte( 0 );
pPacket->Write( &pGUID, sizeof(GGUID) );
Send( pPacket, TRUE, TRUE );
m_pGUIDCache->Add( &pGUID, this );
}
//////////////////////////////////////////////////////////////////////
// CG2Neighbour HUB ADVERTISEMENT WALKER : receive
BOOL CG2Neighbour::OnHAW(CG2Packet* pPacket)
{
if ( ! pPacket->m_bCompound ) return TRUE;
CString strVendor;
CHAR szType[9];
DWORD nLength;
DWORD nAddress = 0;
WORD nPort = 0;
while ( pPacket->ReadPacket( szType, nLength ) )
{
DWORD nNext = pPacket->m_nPosition + nLength;
if ( strcmp( szType, "V" ) == 0 && nLength >= 4 )
{
strVendor = pPacket->ReadString( 4 );
}
else if ( strcmp( szType, "NA" ) == 0 && nLength >= 6 )
{
nAddress = pPacket->ReadLongLE();
nPort = pPacket->ReadShortBE();
}
pPacket->m_nPosition = nNext;
}
if ( pPacket->GetRemaining() < 2 + 16 ) return TRUE;
if ( nAddress == 0 || nPort == 0 ) return TRUE;
if ( Network.IsFirewalledAddress( &nAddress, TRUE ) ) return TRUE;
BYTE* pPtr = pPacket->m_pBuffer + pPacket->m_nPosition;
BYTE nTTL = pPacket->ReadByte();
BYTE nHops = pPacket->ReadByte();
GGUID pGUID;
pPacket->Read( &pGUID, sizeof(GGUID) );
HostCache.Gnutella2.Add( (IN_ADDR*)&nAddress, nPort, 0, strVendor );
if ( nTTL > 0 && nHops < 255 )
{
m_pGUIDCache->Add( &pGUID, this );
pPtr[0] = nTTL - 1;
pPtr[1] = nHops + 1;
if ( CG2Neighbour* pNeighbour = Neighbours.GetRandomHub( this, &pGUID ) )
{
pNeighbour->Send( pPacket, FALSE, TRUE );
}
}
return TRUE;
}
//////////////////////////////////////////////////////////////////////
// CG2Neighbour QUERY packet handler
BOOL CG2Neighbour::SendQuery(CQuerySearch* pSearch, CPacket* pPacket, BOOL bLocal)
{
if ( m_nState != nrsConnected )
{
return FALSE;
}
else if ( pPacket == NULL || pPacket->m_nProtocol != PROTOCOL_G2 )
{
return FALSE;
}
else if ( m_nNodeType == ntHub && ! bLocal )
{
return FALSE;
}
else if ( m_pQueryTableRemote != NULL && m_pQueryTableRemote->m_bLive && ( m_nNodeType == ntLeaf || pSearch->m_bUDP ) )
{
if ( ! m_pQueryTableRemote->Check( pSearch ) ) return FALSE;
}
else if ( m_nNodeType == ntLeaf && ! bLocal )
{
return FALSE;
}
Send( pPacket, FALSE, ! bLocal );
return TRUE;
}
BOOL CG2Neighbour::OnQuery(CG2Packet* pPacket)
{
CQuerySearch* pSearch = CQuerySearch::FromPacket( pPacket );
if ( pSearch == NULL )
{
theApp.Message( MSG_ERROR, IDS_PROTOCOL_BAD_QUERY, (LPCTSTR)m_sAddress );
Statistics.Current.Gnutella2.Dropped++;
m_nDropCount++;
return TRUE;
}
if ( m_nNodeType == ntLeaf && pSearch->m_bUDP &&
pSearch->m_pEndpoint.sin_addr.S_un.S_addr != m_pHost.sin_addr.S_un.S_addr )
{
delete pSearch;
Statistics.Current.Gnutella2.Dropped++;
m_nDropCount++;
return TRUE;
}
if ( ! Network.QueryRoute->Add( &pSearch->m_pGUID, this ) )
{
delete pSearch;
Statistics.Current.Gnutella2.Dropped++;
m_nDropCount++;
return TRUE;
}
if ( m_nNodeType != ntHub )
{
if ( pPacket->IsType( G2_PACKET_QUERY_WRAP ) )
{
if ( ! pPacket->SeekToWrapped() ) return TRUE;
GNUTELLAPACKET* pG1 = (GNUTELLAPACKET*)( pPacket->m_pBuffer + pPacket->m_nPosition );
if ( pG1->m_nTTL > 1 )
{
pG1->m_nTTL--;
pG1->m_nHops++;
Neighbours.RouteQuery( pSearch, pPacket, this, TRUE );
}
}
else
{
Neighbours.RouteQuery( pSearch, pPacket, this, m_nNodeType == ntLeaf );
}
}
Network.OnQuerySearch( pSearch );
if ( pSearch->m_bUDP && /* Network.IsStable() && Datagrams.IsStable() && */
pSearch->m_pEndpoint.sin_addr.S_un.S_addr != m_pHost.sin_addr.S_un.S_addr )
{
CLocalSearch pLocal( pSearch, &pSearch->m_pEndpoint );
pLocal.Execute();
}
else
{
BOOL bIsG1 = pPacket->IsType( G2_PACKET_QUERY_WRAP );
if ( ! bIsG1 || Settings.Gnutella1.EnableToday )
{
CLocalSearch pLocal( pSearch, this, bIsG1 );
pLocal.Execute();
}
}
if ( m_nNodeType == ntLeaf ) Send( Neighbours.CreateQueryWeb( &pSearch->m_pGUID, this ), TRUE, FALSE );
delete pSearch;
Statistics.Current.Gnutella2.Queries++;
return TRUE;
}
BOOL CG2Neighbour::OnQueryAck(CG2Packet* pPacket)
{
HostCache.Gnutella2.Add( &m_pHost.sin_addr, htons( m_pHost.sin_port ) );
SearchManager.OnQueryAck( pPacket, &m_pHost, NULL );
return TRUE;
}
//////////////////////////////////////////////////////////////////////
// CG2Neighbour QUERY KEY REQUEST packet handler
BOOL CG2Neighbour::OnQueryKeyReq(CG2Packet* pPacket)
{
if ( ! pPacket->m_bCompound ) return TRUE;
if ( m_nNodeType != ntLeaf ) return TRUE;
DWORD nLength, nAddress = 0;
BOOL bCacheOkay = TRUE;
CHAR szType[9];
WORD nPort = 0;
while ( pPacket->ReadPacket( szType, nLength ) )
{
DWORD nOffset = pPacket->m_nPosition + nLength;
if ( strcmp( szType, "QNA" ) == 0 && nLength >= 6 )
{
nAddress = pPacket->ReadLongLE();
nPort = pPacket->ReadShortBE();
}
else if ( strcmp( szType, "REF" ) == 0 )
{
bCacheOkay = FALSE;
}
pPacket->m_nPosition = nOffset;
}
if ( Network.IsFirewalledAddress( &nAddress, TRUE ) || 0 == nPort ) return TRUE;
CHostCacheHost* pCached = bCacheOkay ? HostCache.Gnutella2.Find( (IN_ADDR*)&nAddress ) : NULL;
if ( pCached != NULL && pCached->m_nKeyValue != 0 &&
pCached->m_nKeyHost == Network.m_pHost.sin_addr.S_un.S_addr )
{
CG2Packet* pAnswer = CG2Packet::New( G2_PACKET_QUERY_KEY_ANS, TRUE );
pAnswer->WritePacket( "QNA", 6 );
pAnswer->WriteLongLE( nAddress );
pAnswer->WriteShortBE( nPort );
pAnswer->WritePacket( "QK", 4 );
pAnswer->WriteLongBE( pCached->m_nKeyValue );
pAnswer->WritePacket( "CACHED", 0 );
Send( pAnswer );
}
else
{
CG2Packet* pRequest = CG2Packet::New( G2_PACKET_QUERY_KEY_REQ, TRUE );
pRequest->WritePacket( "SNA", 4 );
pRequest->WriteLongLE( m_pHost.sin_addr.S_un.S_addr );
Datagrams.Send( (IN_ADDR*)&nAddress, nPort, pRequest, TRUE, NULL, FALSE );
}
return TRUE;
}
//////////////////////////////////////////////////////////////////////
// CG2Neighbour QUERY KEY ANSWER packet handler
BOOL CG2Neighbour::OnQueryKeyAns(CG2Packet* pPacket)
{
if ( ! pPacket->m_bCompound ) return TRUE;
if ( m_nNodeType != ntHub ) return TRUE;
DWORD nKey = 0, nAddress = 0;
WORD nPort = 0;
CHAR szType[9];
DWORD nLength;
while ( pPacket->ReadPacket( szType, nLength ) )
{
DWORD nOffset = pPacket->m_nPosition + nLength;
if ( strcmp( szType, "QK" ) == 0 && nLength >= 4 )
{
nKey = pPacket->ReadLongBE();
}
else if ( strcmp( szType, "QNA" ) == 0 && nLength >= 6 )
{
nAddress = pPacket->ReadLongLE();
nPort = pPacket->ReadShortBE();
}
else if ( strcmp( szType, "CACHED" ) == 0 )
{
m_bCachedKeys = TRUE;
}
pPacket->m_nPosition = nOffset;
}
theApp.Message( MSG_DEBUG, _T("Got a query key for %s:%i via neighbour %s: 0x%x"),
(LPCTSTR)CString( inet_ntoa( *(IN_ADDR*)&nAddress ) ), nPort, (LPCTSTR)m_sAddress, nKey );
if ( Network.IsFirewalledAddress( &nAddress ) || 0 == nPort ) return TRUE;
CHostCacheHost* pCache = HostCache.Gnutella2.Add( (IN_ADDR*)&nAddress, nPort );
if ( pCache != NULL ) pCache->SetKey( nKey, &m_pHost.sin_addr );
return TRUE;
}
//////////////////////////////////////////////////////////////////////
// CG2Neighbour PUSH packet handler
BOOL CG2Neighbour::OnPush(CG2Packet* pPacket)
{
if ( ! pPacket->m_bCompound ) return TRUE;
DWORD nLength = pPacket->GetRemaining();
if ( ! pPacket->SkipCompound( nLength, 6 ) )
{
pPacket->Debug( _T("BadPush") );
Statistics.Current.Gnutella2.Dropped++;
return TRUE;
}
DWORD nAddress = pPacket->ReadLongLE();
WORD nPort = pPacket->ReadShortBE();
if ( Security.IsDenied( (IN_ADDR*)&nAddress ) )
{
Statistics.Current.Gnutella2.Dropped++;
m_nDropCount++;
return TRUE;
}
else if ( ! nPort || Network.IsFirewalledAddress( &nAddress ) )
{
theApp.Message( MSG_ERROR, IDS_PROTOCOL_ZERO_PUSH, (LPCTSTR)m_sAddress );
Statistics.Current.Gnutella2.Dropped++;
m_nDropCount++;
return TRUE;
}
Handshakes.PushTo( (IN_ADDR*)&nAddress, nPort );
return TRUE;
}
//////////////////////////////////////////////////////////////////////
// CG2Neighbour USER PROFILE CHALLENGE packet handler
BOOL CG2Neighbour::OnProfileChallenge(CG2Packet* pPacket)
{
if ( ! MyProfile.IsValid() ) return TRUE;
CG2Packet* pProfile = CG2Packet::New( G2_PACKET_PROFILE_DELIVERY, TRUE );
CString strXML = MyProfile.GetXML( NULL, TRUE )->ToString( TRUE );
pProfile->WritePacket( "XML", pProfile->GetStringLen( strXML ) );
pProfile->WriteString( strXML, FALSE );
Send( pProfile, TRUE, TRUE );
return TRUE;
}
//////////////////////////////////////////////////////////////////////
// CG2Neighbour USER PROFILE DELIVERY packet handler
BOOL CG2Neighbour::OnProfileDelivery(CG2Packet* pPacket)
{
if ( ! pPacket->m_bCompound ) return TRUE;
CHAR szType[9];
DWORD nLength;
while ( pPacket->ReadPacket( szType, nLength ) )
{
DWORD nOffset = pPacket->m_nPosition + nLength;
if ( strcmp( szType, "XML" ) == 0 )
{
CXMLElement* pXML = CXMLElement::FromString( pPacket->ReadString( nLength ), TRUE );
if ( pXML )
{
if ( m_pProfile == NULL ) m_pProfile = new CGProfile();
if ( ! m_pProfile->FromXML( pXML ) ) delete pXML;
}
}
pPacket->m_nPosition = nOffset;
}
return TRUE;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -