📄 shakeneighbour.cpp
字号:
//
// 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 + -