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

📄 shakeneighbour.cpp

📁 著名的下载软件核心Shareaza
💻 CPP
📖 第 1 页 / 共 2 页
字号:
//
// ShakeNeighbour.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 "HostCache.h"
#include "DiscoveryServices.h"
#include "Neighbours.h"
#include "ShakeNeighbour.h"
#include "G1Neighbour.h"
#include "G2Neighbour.h"
#include "Packet.h"

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


//////////////////////////////////////////////////////////////////////
// CShakeNeighbour construction

CShakeNeighbour::CShakeNeighbour() : CNeighbour( PROTOCOL_NULL )
{
	m_bSentAddress		= FALSE;

	m_bG2Send			= FALSE;
	m_bG2Accept			= FALSE;
	
	m_bDeflateSend		= FALSE;
	m_bDeflateAccept	= FALSE;
	m_bCanDeflate		= Neighbours.IsLeaf() ? ( Settings.Gnutella.DeflateHub2Hub || Settings.Gnutella.DeflateLeaf2Hub ) : ( Settings.Gnutella.DeflateHub2Hub || Settings.Gnutella.DeflateHub2Hub );
	
	m_bUltraPeerSet		= TS_UNKNOWN;
	m_bUltraPeerNeeded	= TS_UNKNOWN;
	m_bUltraPeerLoaded	= TS_UNKNOWN;
}

CShakeNeighbour::~CShakeNeighbour()
{
}

//////////////////////////////////////////////////////////////////////
// CShakeNeighbour connect to

BOOL CShakeNeighbour::ConnectTo(IN_ADDR* pAddress, WORD nPort, BOOL bAutomatic, BOOL bNoUltraPeer)
{
	if ( CConnection::ConnectTo( pAddress, nPort ) )
	{
		WSAEventSelect( m_hSocket, Network.m_pWakeup, FD_CONNECT|FD_READ|FD_WRITE|FD_CLOSE );
		
		theApp.Message( MSG_DEFAULT, IDS_CONNECTION_ATTEMPTING,
			(LPCTSTR)m_sAddress, htons( m_pHost.sin_port ) );
	}
	else
	{
		theApp.Message( MSG_ERROR, IDS_CONNECTION_CONNECT_FAIL,
			(LPCTSTR)CString( inet_ntoa( m_pHost.sin_addr ) ) );
		return FALSE;
	}
	
	m_nState		= nrsConnecting;
	m_bAutomatic	= bAutomatic;
	m_bUltraPeerSet	= bNoUltraPeer ? TS_FALSE : TS_UNKNOWN;
	
	Neighbours.Add( this );
	
	return TRUE;
}

//////////////////////////////////////////////////////////////////////
// CShakeNeighbour accept from

void CShakeNeighbour::AttachTo(CConnection* pConnection)
{
	CConnection::AttachTo( pConnection );
	WSAEventSelect( m_hSocket, Network.m_pWakeup, FD_READ|FD_WRITE|FD_CLOSE );
	
	m_nState = nrsHandshake1;
	
	Neighbours.Add( this );
}

//////////////////////////////////////////////////////////////////////
// CShakeNeighbour close

void CShakeNeighbour::Close(UINT nError, BOOL bRetry04)
{
	if ( m_bInitiated )
	{
		if ( bRetry04 && m_bShake06 && m_nState == nrsHandshake1 && ( Settings.Gnutella1.EnableToday && Settings.Gnutella1.Handshake04 ) )
		{
			Neighbours.Remove( this );
			CConnection::Close();
			
			m_bShake06 = FALSE;
			theApp.Message( MSG_ERROR, IDS_HANDSHAKE_RETRY, (LPCTSTR)m_sAddress );
			
			IN_ADDR pAddress = m_pHost.sin_addr;
			WORD nPort = htons( m_pHost.sin_port );
			
			ConnectTo( &pAddress, nPort, m_bAutomatic );
			
			return;
		}
		else if ( m_nState < nrsHandshake2 )
		{
			HostCache.OnFailure( &m_pHost.sin_addr, htons( m_pHost.sin_port ) );
		}
	}
	
	CNeighbour::Close( nError );
}

//////////////////////////////////////////////////////////////////////
// CShakeNeighbour connection event

BOOL CShakeNeighbour::OnConnected()
{
	CConnection::OnConnected();

	theApp.Message( MSG_DEFAULT, IDS_CONNECTION_CONNECTED, (LPCTSTR)m_sAddress );

	if ( m_bShake06 )
	{
		m_pOutput->Print( "GNUTELLA CONNECT/0.6\r\n" );
		SendPublicHeaders();
		SendHostHeaders();
		m_pOutput->Print( "\r\n" );
	}
	else
	{
		m_pOutput->Print( "GNUTELLA CONNECT/0.4\n\n" );
	}
	
	m_nState = nrsHandshake1;

	OnWrite();

	return TRUE;
}

//////////////////////////////////////////////////////////////////////
// CShakeNeighbour connection loss event

void CShakeNeighbour::OnDropped(BOOL bError)
{
	if ( m_nState == nrsConnecting )
	{
		Close( IDS_CONNECTION_REFUSED );
	}
	else
	{
		Close( IDS_CONNECTION_DROPPED, TRUE );
	}
}

//////////////////////////////////////////////////////////////////////
// CShakeNeighbour read and write events

BOOL CShakeNeighbour::OnRead()
{
	CConnection::OnRead();

	if ( m_nState == nrsHandshake1 && ! ReadResponse() ) return FALSE;
	if ( m_nState == nrsHandshake2 && ! ReadHeaders() )  return FALSE;
	if ( m_nState == nrsHandshake1 && ! ReadResponse() ) return FALSE;
	if ( m_nState == nrsHandshake3 && ! ReadHeaders() )  return FALSE;
	if ( m_nState == nrsRejected   && ! ReadHeaders() )  return FALSE;

	return TRUE;
}

//////////////////////////////////////////////////////////////////////
// CShakeNeighbour run event

BOOL CShakeNeighbour::OnRun()
{
	DWORD nTimeNow = GetTickCount();
	
	switch ( m_nState )
	{
	case nrsConnecting:

		if ( nTimeNow - m_tConnected > Settings.Connection.TimeoutConnect )
		{
			DiscoveryServices.OnGnutellaFailed( &m_pHost.sin_addr );
			Close( IDS_CONNECTION_TIMEOUT_CONNECT );
			return FALSE;
		}
		break;

	case nrsHandshake1:
	case nrsHandshake2:
	case nrsHandshake3:
	case nrsRejected:

		if ( nTimeNow - m_tConnected > Settings.Connection.TimeoutHandshake )
		{
			Close( IDS_HANDSHAKE_TIMEOUT, TRUE );
			return FALSE;
		}
		break;

	case nrsClosing:

		Close( 0 );
		return FALSE;

	}

	return TRUE;
}

//////////////////////////////////////////////////////////////////////
// CShakeNeighbour handshake header dispatch

void CShakeNeighbour::SendMinimalHeaders()
{
	CString strHeader = Settings.SmartAgent( Settings.General.UserAgent );
	
	if ( strHeader.GetLength() )
	{
		strHeader = _T("User-Agent: ") + strHeader + _T("\r\n");
		m_pOutput->Print( strHeader );
	}
	
	if ( Settings.Gnutella2.EnableToday )
	{
		if ( m_bInitiated )
		{
			m_pOutput->Print( "Accept: application/x-gnutella2,application/x-gnutella-packets\r\n" );
		}
		else if ( m_bG2Accept )
		{
			m_pOutput->Print( "Accept: application/x-gnutella2\r\n" );
			m_pOutput->Print( "Content-Type: application/x-gnutella2\r\n" );
		}
	}
}

void CShakeNeighbour::SendPublicHeaders()
{
	CString strHeader = Settings.SmartAgent( Settings.General.UserAgent );
	
	if ( strHeader.GetLength() )
	{
		strHeader = _T("User-Agent: ") + strHeader + _T("\r\n");
		m_pOutput->Print( strHeader );
	}
	
	m_bSentAddress |= SendMyAddress();
	
	strHeader.Format( _T("Remote-IP: %s\r\n"),
		(LPCTSTR)CString( inet_ntoa( m_pHost.sin_addr ) ) );
	m_pOutput->Print( strHeader );
	
	if ( Settings.Gnutella2.EnableToday )
	{
		if ( m_bInitiated )
		{
			m_pOutput->Print( "Accept: application/x-gnutella2,application/x-gnutella-packets\r\n" );
		}
		else if ( m_bG2Accept )
		{
			m_pOutput->Print( "Accept: application/x-gnutella2\r\n" );
			m_pOutput->Print( "Content-Type: application/x-gnutella2\r\n" );
		}
	}
	
	if ( m_bCanDeflate )
	{
		m_pOutput->Print( "Accept-Encoding: deflate\r\n" );
		
		if ( ! m_bInitiated && m_bDeflateAccept )
		{
			m_pOutput->Print( "Content-Encoding: deflate\r\n" );
		}
	}
	
	if ( Settings.Gnutella1.EnableToday )
	{
		if ( Settings.Gnutella1.EnableGGEP ) m_pOutput->Print( "GGEP: 0.5\r\n" );
		m_pOutput->Print( "Pong-Caching: 0.1\r\n" );
		if ( Settings.Gnutella1.VendorMsg ) m_pOutput->Print( "Vendor-Message: 0.1\r\n" );
		m_pOutput->Print( "X-Query-Routing: 0.1\r\n" );
		
		if ( Settings.Gnutella1.NumLeafs == 0 )
		{
			/*
			m_pOutput->Print( "X-Degree: 15\r\n" );
			m_pOutput->Print( "X-Ultrapeer-Query-Routing: 0.1\r\n" );
			m_pOutput->Print( "X-Max-TTL: 4\r\n" );
			m_pOutput->Print( "X-Dynamic-Querying: 0.1\r\n" );
			*/
		}
	}
	
	if ( m_bInitiated && m_bUltraPeerSet == TS_FALSE )
	{
		m_bUltraPeerSet = TS_UNKNOWN;
	}
	else
	{
		if ( Neighbours.IsHub() || Neighbours.IsHubCapable() )
		{
			m_pOutput->Print( "X-Ultrapeer: True\r\n" );
			
			/*
			if ( Neighbours.IsHubLoaded( TS_TRUE ) )	// TS_TRUE ?
			{
				m_pOutput->Print( "X-Ultrapeer-Loaded: True\r\n" );
			}
			else
			{
				m_pOutput->Print( "X-Ultrapeer-Loaded: False\r\n" );
			}
			*/
		}
		else if ( Settings.Gnutella.LeafEnable )
		{
			m_pOutput->Print( "X-Ultrapeer: False\r\n" );
		}
	}
}

void CShakeNeighbour::SendPrivateHeaders()
{
	if ( ! m_bSentAddress ) m_bSentAddress = SendMyAddress();
	
	if ( m_bInitiated && m_bG2Send && m_bG2Accept )
	{
		m_pOutput->Print( "Accept: application/x-gnutella2\r\n" );
		m_pOutput->Print( "Content-Type: application/x-gnutella2\r\n" );
	}
	
	if ( m_bInitiated )
	{
		if ( m_bDeflateSend ) 
		{
			m_pOutput->Print( "Accept-Encoding: deflate\r\n" );
		}
		if ( m_bDeflateAccept ) 
		{
			m_pOutput->Print( "Content-Encoding: deflate\r\n" );
		}
	}
}

void CShakeNeighbour::SendHostHeaders(LPCTSTR pszMessage)
{
	DWORD nTime = time( NULL );
	CString strHosts, strHost;
	CHostCacheHost* pHost;
	
	if ( pszMessage )
	{
		m_pOutput->Print( pszMessage );
		m_pOutput->Print( "\r\n" );
		SendMinimalHeaders();
	}
	
	int nCount = Settings.Gnutella1.PongCount;
	
	if ( m_bG2Accept || m_bG2Send || m_bShareaza )
	{
		for ( pHost = HostCache.Gnutella2.GetNewest() ; pHost && nCount > 0 ; pHost = pHost->m_pPrevTime )
		{
			if ( pHost->CanQuote( nTime ) )
			{
				strHost = pHost->ToString();
				if ( strHosts.GetLength() ) strHosts += _T(",");
				strHosts += strHost;
				nCount--;
			}
		}
	}
	else
	{
		for ( pHost = HostCache.Gnutella1.GetNewest() ; pHost && nCount > 0 ; pHost = pHost->m_pPrevTime )
		{
			if ( pHost->CanQuote( nTime ) )
			{
				strHost = pHost->ToString();
				if ( strHosts.GetLength() ) strHosts += _T(",");
				strHosts += strHost;
				nCount--;
			}
		}
	}
	
	if ( strHosts.GetLength() )
	{
		m_pOutput->Print( "X-Try-Ultrapeers: " );
		m_pOutput->Print( strHosts );
		m_pOutput->Print( "\r\n" );
	}

	if ( pszMessage ) m_pOutput->Print( "\r\n" );
}

//////////////////////////////////////////////////////////////////////
// CShakeNeighbour handshake response processor

⌨️ 快捷键说明

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