⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 g1neighbour.cpp

📁 著名的下载软件核心Shareaza
💻 CPP
📖 第 1 页 / 共 2 页
字号:
//
// G1Neighbour.cpp
//
// Copyright (c) Shareaza Development Team, 2002-2004.
// This file is part of SHAREAZA (www.shareaza.com)
//
// Shareaza is free software; you can redistribute it
// and/or modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2 of
// the License, or (at your option) any later version.
//
// Shareaza is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Shareaza; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
//

#include "StdAfx.h"
#include "Shareaza.h"
#include "Settings.h"
#include "Network.h"
#include "Buffer.h"
#include "Statistics.h"
#include "Neighbours.h"
#include "Handshakes.h"
#include "G1Neighbour.h"
#include "G1Packet.h"
#include "G2Packet.h"
#include "HostCache.h"
#include "RouteCache.h"
#include "PacketBuffer.h"
#include "Security.h"
#include "GProfile.h"
#include "PongCache.h"
#include "VendorCache.h"
#include "QuerySearch.h"
#include "QueryHit.h"
#include "QueryHashTable.h"
#include "LocalSearch.h"
#include "SearchManager.h"
#include "DiscoveryServices.h"
#include "Downloads.h"
#include "Uploads.h"
#include "Library.h"
#include "SHA.h"

#include "WndMain.h"
#include "WndChild.h"
#include "WndSearchMonitor.h"


#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif


//////////////////////////////////////////////////////////////////////
// CG1Neighbour construction

CG1Neighbour::CG1Neighbour(CNeighbour* pBase) : CNeighbour( PROTOCOL_G1, pBase )
{
	ZeroMemory( m_nPongNeeded, PONG_NEEDED_BUFFER );

	m_tLastOutPing	= m_tLastPacket;
	m_nHopsFlow		= 0xFF;
	m_pOutbound		= new CG1PacketBuffer( m_pZOutput ? m_pZOutput : m_pOutput );

	theApp.Message( MSG_DEFAULT, IDS_HANDSHAKE_ONLINE, (LPCTSTR)m_sAddress,
		0, m_bShake06 ? 6 : 4,
		m_sUserAgent.IsEmpty() ? _T("Unknown") : (LPCTSTR)m_sUserAgent );

	Send( CG1Packet::New( G1_PACKET_PING ) );
	
	if ( Settings.Gnutella1.VendorMsg && m_bVendorMsg )
	{
		CG1Packet* pVendor = CG1Packet::New( G1_PACKET_VENDOR, 1 );
		pVendor->WriteLongLE( 0 );
		pVendor->WriteShortLE( 0 );
		pVendor->WriteShortLE( 0 );
		pVendor->WriteShortLE( 6 );
		pVendor->WriteLongLE( 'RAEB' );
		pVendor->WriteShortLE( 0x0004 );
		pVendor->WriteShortLE( 1 );
		pVendor->WriteLongLE( 'RAEB' );
		pVendor->WriteShortLE( 0x000B );
		pVendor->WriteShortLE( 1 );
		pVendor->WriteLongLE( 'RAEB' );
		pVendor->WriteShortLE( 0x000C );
		pVendor->WriteShortLE( 1 );
		pVendor->WriteLongLE( 'AZAR' );
		pVendor->WriteShortLE( 0x0001 );
		pVendor->WriteShortLE( 1 );
		pVendor->WriteLongLE( 'AZAR' );
		pVendor->WriteShortLE( 0x0002 );
		pVendor->WriteShortLE( 1 );
		pVendor->WriteLongLE( 'AZAR' );
		pVendor->WriteShortLE( 0x0003 );
		pVendor->WriteShortLE( 1 );
		Send( pVendor );
	}
}

CG1Neighbour::~CG1Neighbour()
{
	if ( m_pOutbound ) delete m_pOutbound;
}

//////////////////////////////////////////////////////////////////////
// CG1Neighbour read and write events

BOOL CG1Neighbour::OnRead()
{
	CNeighbour::OnRead();
	return ProcessPackets();
}

BOOL CG1Neighbour::OnWrite()
{
	CBuffer* pOutput	= m_pZOutput ? m_pZOutput : m_pOutput;
	DWORD nExpire		= GetTickCount();

	CNeighbour::OnWrite();

	while ( pOutput->m_nLength == 0 && m_pOutbound->m_nTotal > 0 )
	{
		CG1Packet* pPacket = m_pOutbound->GetPacketToSend( nExpire );
		if ( ! pPacket ) break;

		pPacket->ToBuffer( pOutput );
		pPacket->Release();

		m_pOutbound->m_nTotal --;

		CNeighbour::OnWrite();
	}

	m_nOutbound		= m_pOutbound->m_nTotal;
	m_nLostCount	= m_pOutbound->m_nDropped;

	return TRUE;
}

//////////////////////////////////////////////////////////////////////
// CG1Neighbour run event

BOOL CG1Neighbour::OnRun()
{
	if ( ! CNeighbour::OnRun() ) return FALSE;
	
	DWORD tNow = GetTickCount();
	
	SendPing( tNow, NULL );
	
	// if ( m_bShareaza && tNow - m_tClusterSent > 60000 ) SendClusterAdvisor();
	
	return TRUE;
}

//////////////////////////////////////////////////////////////////////
// CG1Neighbour send packet

BOOL CG1Neighbour::Send(CPacket* pPacket, BOOL bRelease, BOOL bBuffered)
{
	CG1Packet* pPacketG1 = (CG1Packet*)pPacket;
	BOOL bSuccess = FALSE;
	
	if ( m_nState >= nrsConnected && pPacket->m_nProtocol == PROTOCOL_G1 && pPacketG1->m_nTTL )
	{
		m_nOutputCount++;
		Statistics.Current.Gnutella1.Outgoing++;
		
		m_pOutbound->Add( pPacketG1, bBuffered );
		QueueRun();
		
		pPacketG1->SmartDump( this, NULL, TRUE );
		
		bSuccess = TRUE;
	}
	
	if ( bRelease ) pPacket->Release();
	
	return bSuccess;
}

//////////////////////////////////////////////////////////////////////
// CG1Neighbour packet dispatch

BOOL CG1Neighbour::ProcessPackets()
{
	CBuffer* pInput = m_pZInput ? m_pZInput : m_pInput;
	
	for ( BOOL bSuccess = TRUE ; bSuccess ; )
	{
		GNUTELLAPACKET* pPacket = (GNUTELLAPACKET*)pInput->m_pBuffer;
		if ( pInput->m_nLength < sizeof(*pPacket) ) break;
		
		DWORD nLength = sizeof(*pPacket) + pPacket->m_nLength;
		
		if ( pPacket->m_nLength < 0 || nLength >= Settings.Gnutella1.MaximumPacket )
		{
			Close( IDS_PROTOCOL_TOO_LARGE );
			return FALSE;
		}
		
		if ( pInput->m_nLength < nLength ) break;
		
		CG1Packet* pPacketObject = CG1Packet::New( pPacket );
		bSuccess = OnPacket( pPacketObject );
		pPacketObject->Release();
		
		pInput->Remove( nLength );
	}
	
	if ( bSuccess ) return TRUE;
	
	Close( 0 );
	return FALSE;
}

//////////////////////////////////////////////////////////////////////
// CG1Neighbour packet handler

BOOL CG1Neighbour::OnPacket(CG1Packet* pPacket)
{
	m_nInputCount++;
	m_tLastPacket = GetTickCount();
	Statistics.Current.Gnutella1.Incoming++;
	
	if ( pPacket->m_nTTL == 0 )
	{
		theApp.Message( MSG_DEBUG, IDS_PROTOCOL_NO_TTL, (LPCTSTR)m_sAddress );
	}
	else if (	(DWORD)pPacket->m_nTTL + pPacket->m_nHops > Settings.Gnutella1.MaximumTTL &&
				pPacket->m_nType != G1_PACKET_PUSH && pPacket->m_nType != G1_PACKET_HIT )
	{
		theApp.Message( MSG_ERROR, IDS_PROTOCOL_HIGH_TTL, (LPCTSTR)m_sAddress,
			pPacket->m_nTTL, pPacket->m_nHops );
		pPacket->m_nTTL = 1;
	}
	
	pPacket->SmartDump( this, NULL, FALSE );

	switch ( pPacket->m_nType )
	{
	case G1_PACKET_PING:
		return OnPing( pPacket );

	case G1_PACKET_PONG:
		return OnPong( pPacket );

	case G1_PACKET_BYE:
		return OnBye( pPacket );

	case G1_PACKET_QUERY_ROUTE:
		return OnCommonQueryHash( pPacket );

	case G1_PACKET_VENDOR:
	case G1_PACKET_VENDOR_APP:
		return OnVendor( pPacket );

	case G1_PACKET_PUSH:
		return OnPush( pPacket );

	case G1_PACKET_QUERY:
		return OnQuery( pPacket );

	case G1_PACKET_HIT:
		return OnHit( pPacket );
	}
	
	theApp.Message( MSG_ERROR, IDS_PROTOCOL_UNKNOWN, (LPCTSTR)m_sAddress, pPacket->m_nType );
	
	return ! Settings.Gnutella1.StrictPackets;
}

//////////////////////////////////////////////////////////////////////
// CG1Neighbour PING packet handlers

BOOL CG1Neighbour::SendPing(DWORD dwNow, GGUID* pGUID)
{
	if ( m_nNodeType == ntLeaf && pGUID != NULL ) return FALSE;

	BOOL bNeedPeers =	Neighbours.NeedMoreHubs( TS_FALSE ) ||
						Neighbours.NeedMoreLeafs( TS_FALSE );

	if ( ! dwNow ) dwNow = GetTickCount();

	if ( m_bPongCaching )
	{
		if ( dwNow - m_tLastOutPing < Settings.Gnutella1.PingRate * 2 ) return FALSE;
		// if ( ! bNeedPeers && dwNow - m_tLastPacket < Settings.Gnutella1.PingRate ) return FALSE;
	}
	else
	{
		if ( dwNow - m_tLastOutPing < Settings.Gnutella1.PingRate * 2 ) return FALSE;
	}

	m_tLastOutPing = dwNow;

	Send( CG1Packet::New( G1_PACKET_PING, ( pGUID || bNeedPeers ) ? 0 : 1, pGUID ), TRUE, TRUE );

	return TRUE;
}

BOOL CG1Neighbour::OnPing(CG1Packet* pPacket)
{
	if ( ! Neighbours.m_pPingRoute->Add( &pPacket->m_pGUID, this ) )
	{
		Statistics.Current.Gnutella1.Dropped++;
		m_nDropCount++;
		return TRUE;
	}

	if ( pPacket->m_nLength != 0 && Settings.Gnutella1.StrictPackets )
	{
		theApp.Message( MSG_ERROR, IDS_PROTOCOL_SIZE_PING, (LPCTSTR)m_sAddress );
		Statistics.Current.Gnutella1.Dropped++;
		m_nDropCount++;
		return TRUE;
	}
	else if ( pPacket->m_nLength > Settings.Gnutella1.MaximumQuery )
	{
		theApp.Message( MSG_ERROR, IDS_PROTOCOL_TOO_LARGE, (LPCTSTR)m_sAddress );
		Statistics.Current.Gnutella1.Dropped++;
		m_nDropCount++;
		return TRUE;
	}

	BOOL bIsKeepAlive	= ( pPacket->m_nTTL == 1 && pPacket->m_nHops == 0 );
	DWORD dwNow			= GetTickCount();
	
	if ( dwNow - m_tLastInPing < Settings.Gnutella1.PingFlood && ! bIsKeepAlive )
	{
		Statistics.Current.Gnutella1.Dropped++;
		m_nDropCount++;
		return TRUE;
	}
	
	if ( pPacket->m_nLength && m_bGGEP )
	{
		if ( pPacket->ReadByte() != GGEP_MAGIC )
		{
			theApp.Message( MSG_ERROR, IDS_PROTOCOL_GGEP_REQUIRED, (LPCTSTR)m_sAddress );
			Statistics.Current.Gnutella1.Dropped++;
			m_nDropCount++;
			return TRUE;
		}
		else if ( pPacket->Hop() )
		{
			if ( Neighbours.Broadcast( pPacket, this, TRUE ) )
				Statistics.Current.Gnutella1.Routed ++;
			pPacket->m_nHops --; // Dehop
			pPacket->m_nTTL ++;
		}
	}
	
	m_tLastInPing	= dwNow;
	m_nLastPingHops	= pPacket->m_nHops + 1;
	m_pLastPingID	= pPacket->m_pGUID;
	
	if ( pPacket->m_nTTL == 2 && pPacket->m_nHops == 0 )
	{
		for ( POSITION pos = Neighbours.GetIterator() ; pos ; )
		{
			CNeighbour* pConnection = Neighbours.GetNext( pos );
			if ( pConnection->m_nState != nrsConnected ) continue;

			CG1Packet* pPong = CG1Packet::New( G1_PACKET_PONG, m_nLastPingHops, &m_pLastPingID );
			
			pPong->WriteShortLE( htons( pConnection->m_pHost.sin_port ) );
			pPong->WriteLongLE( pConnection->m_pHost.sin_addr.S_un.S_addr );
			pPong->WriteLongLE( 0 );
			pPong->WriteLongLE( 0 );

			Send( pPong );
		}
		
		// theApp.Message( MSG_DEFAULT, IDS_CONNECTION_CRAWLER, (LPCTSTR)m_sAddress );
		
		return TRUE;
	}
	
	if ( bIsKeepAlive || ( Network.IsListening() && ! Neighbours.IsLeaf() ) )
	{
		CG1Packet* pPong = CG1Packet::New( G1_PACKET_PONG, m_nLastPingHops, &m_pLastPingID );
		
		QWORD nMyVolume;
		DWORD nMyFiles;
		LibraryMaps.GetStatistics( &nMyFiles, &nMyVolume );
		
		pPong->WriteShortLE( htons( Network.m_pHost.sin_port ) );
		pPong->WriteLongLE( Network.m_pHost.sin_addr.S_un.S_addr );
		pPong->WriteLongLE( nMyFiles );
		pPong->WriteLongLE( (DWORD)nMyVolume );
		
		Send( pPong );
	}
	
	if ( bIsKeepAlive || m_nNodeType == ntHub || ! pPacket->Hop() ) return TRUE;
	
	Neighbours.OnG1Ping();
	
	CPtrList pIgnore;
	
	ZeroMemory( m_nPongNeeded, PONG_NEEDED_BUFFER ); 
	
	for ( BYTE nHops = 1 ; nHops <= pPacket->m_nTTL ; nHops++ )
	{
		m_nPongNeeded[ nHops ] = Settings.Gnutella1.PongCount / pPacket->m_nTTL;
		
		CPongItem* pCache = NULL;
		
		while (	( m_nPongNeeded[ nHops ] > 0 ) &&
				( pCache = Neighbours.m_pPongCache->Lookup( this, nHops, &pIgnore ) ) )
		{
			Send( pCache->ToPacket( m_nLastPingHops, &m_pLastPingID ) );

			pIgnore.AddTail( pCache );
			m_nPongNeeded[ nHops ]--;
		}
	}
	
	return TRUE;
}

//////////////////////////////////////////////////////////////////////
// CG1Neighbour PONG packet handlers

BOOL CG1Neighbour::OnPong(CG1Packet* pPacket)
{
	if ( pPacket->m_nLength < 14 || ( pPacket->m_nLength > 14 && Settings.Gnutella1.StrictPackets ) )
	{
		theApp.Message( MSG_ERROR, IDS_PROTOCOL_SIZE_PONG, (LPCTSTR)m_sAddress );
		Statistics.Current.Gnutella1.Dropped++;
		m_nDropCount++;
		return TRUE;
	}

	WORD nPort		= pPacket->ReadShortLE();
	DWORD nAddress	= pPacket->ReadLongLE();
	DWORD nFiles	= pPacket->ReadLongLE();
	DWORD nVolume	= pPacket->ReadLongLE();

	if ( Security.IsDenied( (IN_ADDR*)&nAddress ) )
	{
		Statistics.Current.Gnutella1.Dropped++;
		m_nDropCount++;
		return TRUE;
	}

	if ( pPacket->m_nLength > 14 && m_bGGEP )
	{
		if ( pPacket->ReadByte() != GGEP_MAGIC )
		{
			theApp.Message( MSG_ERROR, IDS_PROTOCOL_GGEP_REQUIRED, (LPCTSTR)m_sAddress );
			Statistics.Current.Gnutella1.Dropped++;
			m_nDropCount++;
			return TRUE;
		}
		else if ( pPacket->Hop() )
		{
			CG1Neighbour* pOrigin;
			
			Neighbours.m_pPingRoute->Lookup( &pPacket->m_pGUID, (CNeighbour**)&pOrigin );

			if ( pOrigin && pOrigin->m_bGGEP )
			{
				Statistics.Current.Gnutella1.Routed++;
				pOrigin->Send( pPacket, FALSE, TRUE );
			}

			pPacket->m_nHops--;	// Dehop
		}
	}

	BOOL bLocal = ! nPort || Network.IsFirewalledAddress( &nAddress );

	if ( pPacket->m_nHops != 0 && bLocal )
	{
		if ( pPacket->m_nHops ) theApp.Message( MSG_DEBUG, IDS_PROTOCOL_ZERO_PONG, (LPCTSTR)m_sAddress );
		Statistics.Current.Gnutella1.Dropped++;
		m_nDropCount++;
		return TRUE;
	}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -