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

📄 handshakes.cpp

📁 p2p软件
💻 CPP
字号:
//
// Handshakes.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 "Handshakes.h"
#include "Connection.h"
#include "Handshake.h"
#include "Network.h"
#include "Security.h"
#include "Datagrams.h"
#include "DiscoveryServices.h"
#include "Transfers.h"
#include "Uploads.h"

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

CHandshakes Handshakes;


//////////////////////////////////////////////////////////////////////
// CHandshakes construction

CHandshakes::CHandshakes()
{
	m_nStableCount	= 0;
	m_tStableTime	= 0;
	m_hSocket		= INVALID_SOCKET;
	m_hThread		= NULL;
}

CHandshakes::~CHandshakes()
{
	Disconnect();
	
	ASSERT( m_hSocket == INVALID_SOCKET );
	ASSERT( m_hThread == NULL );
}

//////////////////////////////////////////////////////////////////////
// CHandshakes listen

BOOL CHandshakes::Listen()
{
	CSingleLock pLock( &m_pSection, TRUE );
	
	if ( m_hSocket != INVALID_SOCKET ) return FALSE;
	
	m_hSocket = socket( PF_INET, SOCK_STREAM, IPPROTO_TCP );
	if ( m_hSocket == INVALID_SOCKET ) return FALSE;
	
	SOCKADDR_IN saListen = Network.m_pHost;
	if ( ! Settings.Connection.InBind ) saListen.sin_addr.S_un.S_addr = 0;
	
	BOOL bBound = FALSE;
	
	for ( int nAttempt = 0 ; nAttempt < 5 ; nAttempt++ )
	{
		bBound = bind( m_hSocket, (SOCKADDR*)&saListen, sizeof(saListen) ) == 0;
		if ( bBound ) break;
		
		theApp.Message( MSG_ERROR, IDS_NETWORK_CANT_LISTEN,
			(LPCTSTR)CString( inet_ntoa( saListen.sin_addr ) ),
			htons( saListen.sin_port ) );
		
		if ( nAttempt )
		{
			int nPort = Network.RandomPort();
			Network.m_pHost.sin_port = saListen.sin_port = htons( nPort );
			if ( Settings.Connection.InPort != 6346 ) Settings.Connection.InPort = nPort;
		}
		else
		{
			saListen.sin_addr.S_un.S_addr = 0;
		}
	}
	
	if ( Network.m_pHost.sin_addr.S_un.S_addr == 0 )
	{
		int nSockLen = sizeof(SOCKADDR_IN);
		getsockname( m_hSocket, (SOCKADDR*)&Network.m_pHost, &nSockLen );
	}
	
	if ( bBound )
	{
		theApp.Message( MSG_DEFAULT, IDS_NETWORK_LISTENING_TCP,
			(LPCTSTR)CString( inet_ntoa( Network.m_pHost.sin_addr ) ),
			htons( Network.m_pHost.sin_port ) );
	}
	
	WSAEventSelect( m_hSocket, m_pWakeup, FD_ACCEPT );
	listen( m_hSocket, 256 );
	
	m_hThread = AfxBeginThread( ThreadStart, this )->m_hThread;
	
	return TRUE;
}

//////////////////////////////////////////////////////////////////////
// CHandshakes disconnect

void CHandshakes::Disconnect()
{
	if ( m_hSocket != INVALID_SOCKET )
	{
		closesocket( m_hSocket );
		m_hSocket = INVALID_SOCKET;
	}
	
	if ( m_hThread != NULL )
	{
		m_pWakeup.SetEvent();
		
		for ( int nAttempt = 10 ; nAttempt > 0 ; nAttempt-- )
		{
			DWORD nCode;
			if ( ! GetExitCodeThread( m_hThread, &nCode ) ) break;
			if ( nCode != STILL_ACTIVE ) break;
			Sleep( 100 );
		}
		
		if ( nAttempt == 0 )
		{
			TerminateThread( m_hThread, 0 );
			theApp.Message( MSG_DEBUG, _T("WARNING: Terminating CHandshakes thread.") );
			Sleep( 100 );
		}
		
		m_hThread = NULL;
	}
	
	CSingleLock pLock( &m_pSection, TRUE );
	
	m_nStableCount	= 0;
	m_tStableTime	= 0;
	
	for ( POSITION pos = GetIterator() ; pos ; ) delete GetNext( pos );
	m_pList.RemoveAll();
}

//////////////////////////////////////////////////////////////////////
// CHandshakes push connection

BOOL CHandshakes::PushTo(IN_ADDR* pAddress, WORD nPort, DWORD nIndex)
{
	CSingleLock pLock1( &Transfers.m_pSection );
	
	if ( pLock1.Lock( 250 ) )
	{
		if ( ! Uploads.AllowMoreTo( pAddress ) )
		{
			CString strAddress = inet_ntoa( *pAddress );
			theApp.Message( MSG_ERROR, IDS_UPLOAD_PUSH_BUSY, (LPCTSTR)strAddress );
			return FALSE;
		}
		
		pLock1.Unlock();
	}
	
	CSingleLock pLock2( &m_pSection, TRUE );
	
	CHandshake* pHandshake = new CHandshake();
	
	if ( pHandshake->Push( pAddress, nPort, nIndex ) )
	{
		m_pList.AddTail( pHandshake );
		return TRUE;
	}
	else
	{
		delete pHandshake;
		return FALSE;
	}
}

//////////////////////////////////////////////////////////////////////
// CHandshakes connection test

BOOL CHandshakes::IsConnectedTo(IN_ADDR* pAddress)
{
	CSingleLock pLock( &m_pSection, TRUE );
	
	for ( POSITION pos = GetIterator() ; pos ; )
	{
		CHandshake* pHandshake = GetNext( pos );
		if ( pHandshake->m_pHost.sin_addr.S_un.S_addr == pAddress->S_un.S_addr ) return TRUE;
	}
	
	return FALSE;
}

//////////////////////////////////////////////////////////////////////
// CHandshakes list modification

void CHandshakes::Substitute(CHandshake* pOld, CHandshake* pNew)
{
	POSITION pos = m_pList.Find( pOld );
	ASSERT( pos != NULL );
	m_pList.SetAt( pos, pNew );
	delete pOld;
}

void CHandshakes::Remove(CHandshake* pHandshake)
{
	POSITION pos = m_pList.Find( pHandshake );
	ASSERT( pos != NULL );
	m_pList.RemoveAt( pos );
	delete pHandshake;
}

//////////////////////////////////////////////////////////////////////
// CHandshakes thread run

UINT CHandshakes::ThreadStart(LPVOID pParam)
{
	((CHandshakes*)pParam)->OnRun();
	return 0;
}

void CHandshakes::OnRun()
{
	while ( m_hSocket != INVALID_SOCKET )
	{
		WaitForSingleObject( m_pWakeup, 1000 );
		while ( AcceptConnection() );
		RunHandshakes();
		while ( AcceptConnection() );
		RunStableUpdate();
	}
}

//////////////////////////////////////////////////////////////////////
// CHandshakes run the handshake
	
void CHandshakes::RunHandshakes()
{
	CSingleLock pLock( &m_pSection, TRUE );
	
	for ( POSITION posNext = GetIterator() ; posNext ; )
	{
		POSITION posThis = posNext;		
		CHandshake* pHandshake = GetNext( posNext );
		
		if ( ! pHandshake->DoRun() && m_pList.GetAt( posThis ) == pHandshake )
		{
			delete pHandshake;
			m_pList.RemoveAt( posThis );
		}
	}
}

//////////////////////////////////////////////////////////////////////
// CHandshakes accept a connection

BOOL CHandshakes::AcceptConnection()
{
	/*
	WSANETWORKEVENTS pEvents;
	WSAEnumNetworkEvents( m_hSocket, NULL, &pEvents );
	if ( ( pEvents.lNetworkEvents & FD_ACCEPT ) == 0 ) return FALSE;
	*/
	
	SOCKADDR_IN pHost;
	int nHost = sizeof(pHost);
	
	SOCKET hSocket = WSAAccept( m_hSocket, (SOCKADDR*)&pHost, &nHost, AcceptCheck, (DWORD)this );
	if ( hSocket == INVALID_SOCKET ) return FALSE;
	
	InterlockedIncrement( (PLONG)&m_nStableCount );
	
	if ( Security.IsDenied( &pHost.sin_addr ) )
	{
		closesocket( hSocket );
		CString strHost = inet_ntoa( pHost.sin_addr );
		theApp.Message( MSG_ERROR, IDS_NETWORK_SECURITY_DENIED, (LPCTSTR)strHost );
	}
	else
	{
		CreateHandshake( hSocket, &pHost );
	}
	
	return TRUE;
}

void CHandshakes::CreateHandshake(SOCKET hSocket, SOCKADDR_IN* pHost)
{
	CSingleLock pLock( &m_pSection, TRUE );
	
	WSAEventSelect( hSocket, m_pWakeup, FD_READ|FD_WRITE|FD_CLOSE );
	m_pList.AddTail( new CHandshake( hSocket, pHost ) );
}

//////////////////////////////////////////////////////////////////////
// CHandshakes inbound connection security check callback

int CALLBACK CHandshakes::AcceptCheck(IN LPWSABUF lpCallerId, IN LPWSABUF lpCallerData, IN OUT LPQOS lpSQOS, IN OUT LPQOS lpGQOS, IN LPWSABUF lpCalleeId, OUT LPWSABUF lpCalleeData, OUT GROUP FAR * g, IN DWORD dwCallbackData)
{
	if ( lpCallerId == NULL ) return CF_REJECT;
	if ( lpCallerId->len < sizeof(SOCKADDR_IN) ) return CF_REJECT;
	
	SOCKADDR_IN* pHost = (SOCKADDR_IN*)lpCallerId->buf;
	
	if ( Security.IsDenied( &pHost->sin_addr ) )
	{
		CString strHost = inet_ntoa( pHost->sin_addr );
		theApp.Message( MSG_ERROR, IDS_NETWORK_SECURITY_DENIED, (LPCTSTR)strHost );
		return CF_REJECT;
	}
	else
	{
		return CF_ACCEPT;
	}
}

//////////////////////////////////////////////////////////////////////
// CHandshakes update stable state

void CHandshakes::RunStableUpdate()
{
	if ( m_nStableCount > 0 )
	{
		if ( m_tStableTime == 0 ) m_tStableTime = (DWORD)time( NULL );
		DiscoveryServices.Update();
	}
}

⌨️ 快捷键说明

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