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

📄 connection.cpp

📁 著名的下载软件核心Shareaza
💻 CPP
📖 第 1 页 / 共 2 页
字号:
//
// Connection.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 "Connection.h"
#include "Network.h"
#include "Security.h"
#include "Buffer.h"
#include "Statistics.h"

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

#define TEMP_BUFFER			10240
#define METER_SECOND		1000
#define METER_MINIMUM		100
//#define METER_LENGTH		24
//#define METER_PERIOD		2000
#define METER_LENGTH		64
#define METER_PERIOD		6000


//////////////////////////////////////////////////////////////////////
// CConnection construction

CConnection::CConnection()
{
	m_hSocket		= INVALID_SOCKET;
	m_pInput		= NULL;
	m_pOutput		= NULL;
	m_bInitiated	= FALSE;
	m_bConnected	= FALSE;
	m_tConnected	= 0;
	m_nQueuedRun	= 0;
	
	ZeroMemory( &m_mInput, sizeof(m_mInput) );
	ZeroMemory( &m_mOutput, sizeof(m_mOutput) );
}

CConnection::~CConnection()
{
	CConnection::Close();
}

//////////////////////////////////////////////////////////////////////
// CConnection connect to

BOOL CConnection::ConnectTo(SOCKADDR_IN* pHost)
{
	return ConnectTo( &pHost->sin_addr, htons( pHost->sin_port ) );
}

BOOL CConnection::ConnectTo(IN_ADDR* pAddress, WORD nPort)
{
	if ( m_hSocket != INVALID_SOCKET ) return FALSE;
	
	if ( pAddress == NULL || nPort == 0 ) return FALSE;
	if ( pAddress->S_un.S_addr == 0 ) return FALSE;
	
	if ( Security.IsDenied( pAddress ) )
	{
		theApp.Message( MSG_ERROR, IDS_NETWORK_SECURITY_OUTGOING,
			(LPCTSTR)CString( inet_ntoa( *pAddress ) ) );
		return FALSE;
	}
	
	if ( pAddress != &m_pHost.sin_addr )
	{
		ZeroMemory( &m_pHost, sizeof(m_pHost) );
		m_pHost.sin_addr	= *pAddress;
	}
	
	m_pHost.sin_family	= PF_INET;
	m_pHost.sin_port	= htons( nPort );
	
	m_sAddress		= inet_ntoa( m_pHost.sin_addr );
	m_hSocket		= socket( PF_INET, SOCK_STREAM, IPPROTO_TCP );
	// m_hSocket		= WSASocket( PF_INET, SOCK_STREAM, IPPROTO_TCP, NULL, 0, WSA_FLAG_OVERLAPPED );
	
	DWORD dwValue = 1;
	ioctlsocket( m_hSocket, FIONBIO, &dwValue );
	
	if ( Settings.Connection.OutHost.GetLength() )
	{
		SOCKADDR_IN pOutgoing;
		Network.Resolve( Settings.Connection.OutHost, 0, &pOutgoing );
		if ( pOutgoing.sin_addr.S_un.S_addr )
			bind( m_hSocket, (SOCKADDR*)&pOutgoing, sizeof(SOCKADDR_IN) );
	}
	
	// if ( connect( m_hSocket, (SOCKADDR*)&m_pHost, sizeof(SOCKADDR_IN) ) ) 
	if ( WSAConnect( m_hSocket, (SOCKADDR*)&m_pHost, sizeof(SOCKADDR_IN), NULL, NULL, NULL, NULL ) )
	{
		UINT nError = WSAGetLastError();
		
		if ( nError != WSAEWOULDBLOCK )
		{
			theApp.Message( MSG_DEBUG, _T("connect() error 0x%x"), nError );
			closesocket( m_hSocket );
			m_hSocket = INVALID_SOCKET;
			return FALSE;
		}
	}
	
	if ( m_pInput ) delete m_pInput;	// Safe
	if ( m_pOutput ) delete m_pOutput;
	
	m_pInput		= new CBuffer( &Settings.Bandwidth.PeerIn );
	m_pOutput		= new CBuffer( &Settings.Bandwidth.PeerOut );
	m_bInitiated	= TRUE;
	m_tConnected	= GetTickCount();
	
	Statistics.Current.Connections.Outgoing++;
	
	return TRUE;
}

//////////////////////////////////////////////////////////////////////
// CConnection accept an incoming connection

void CConnection::AcceptFrom(SOCKET hSocket, SOCKADDR_IN* pHost)
{
	ASSERT( m_hSocket == INVALID_SOCKET );
	
	m_pHost			= *pHost;
	m_sAddress		= inet_ntoa( m_pHost.sin_addr );
	m_hSocket		= hSocket;
	m_pInput		= new CBuffer( &Settings.Bandwidth.PeerIn );
	m_pOutput		= new CBuffer( &Settings.Bandwidth.PeerOut );
	m_bInitiated	= FALSE;
	m_bConnected	= TRUE;
	m_tConnected	= GetTickCount();
	
	DWORD dwValue = 1;
	ioctlsocket( m_hSocket, FIONBIO, &dwValue );
	
	Statistics.Current.Connections.Incoming++;
}

//////////////////////////////////////////////////////////////////////
// CConnection attach to an existing connection

void CConnection::AttachTo(CConnection* pConnection)
{
	ASSERT( m_hSocket == INVALID_SOCKET );
	ASSERT( pConnection != NULL );
	ASSERT( pConnection->m_hSocket != INVALID_SOCKET );
	
	m_pHost			= pConnection->m_pHost;
	m_sAddress		= pConnection->m_sAddress;
	m_hSocket		= pConnection->m_hSocket;
	m_bInitiated	= pConnection->m_bInitiated;
	m_bConnected	= pConnection->m_bConnected;
	m_tConnected	= pConnection->m_tConnected;
	m_pInput		= pConnection->m_pInput;
	m_pOutput		= pConnection->m_pOutput;
	m_sUserAgent	= pConnection->m_sUserAgent;
	// m_mInput		= pConnection->m_mInput;
	// m_mOutput	= pConnection->m_mOutput;
	
	m_mInput.tLast = m_mOutput.tLast = GetTickCount();
	
	pConnection->m_hSocket	= INVALID_SOCKET;
	pConnection->m_pInput	= NULL;
	pConnection->m_pOutput	= NULL;
	ZeroMemory( &pConnection->m_mInput, sizeof(m_mInput) );
	ZeroMemory( &pConnection->m_mOutput, sizeof(m_mOutput) );
}

//////////////////////////////////////////////////////////////////////
// CConnection close

void CConnection::Close()
{
	ASSERT( this != NULL );
	ASSERT( AfxIsValidAddress( this, sizeof(*this) ) );
	
	if ( m_hSocket != INVALID_SOCKET )
	{
		closesocket( m_hSocket );
		m_hSocket = INVALID_SOCKET;
	}
	
	if ( m_pOutput ) delete m_pOutput;
	m_pOutput = NULL;
	
	if ( m_pInput ) delete m_pInput;
	m_pInput = NULL;
	
	m_bConnected = FALSE;
}

//////////////////////////////////////////////////////////////////////
// CConnection run function

BOOL CConnection::DoRun()
{
	if ( m_hSocket == INVALID_SOCKET ) return OnRun();
	
	WSANETWORKEVENTS pEvents;
	WSAEnumNetworkEvents( m_hSocket, NULL, &pEvents );
	
	if ( pEvents.lNetworkEvents & FD_CONNECT )
	{
		if ( pEvents.iErrorCode[ FD_CONNECT_BIT ] != 0 )
		{
			OnDropped( TRUE );
			return FALSE;
		}
		
		m_bConnected = TRUE;
		m_tConnected = m_mInput.tLast = m_mOutput.tLast = GetTickCount();

		if ( ! OnConnected() ) return FALSE;
	}
	
	BOOL bClosed = ( pEvents.lNetworkEvents & FD_CLOSE ) ? TRUE : FALSE;
	
	if ( bClosed ) m_mInput.pLimit = NULL;
	
	m_nQueuedRun = 1;
	
	// if ( pEvents.lNetworkEvents & FD_WRITE )
	{
		if ( ! OnWrite() ) return FALSE;
	}

	// if ( pEvents.lNetworkEvents & FD_READ )
	{
		if ( ! OnRead() ) return FALSE;
	}
	
	if ( bClosed )
	{
		OnDropped( pEvents.iErrorCode[ FD_CLOSE_BIT ] != 0 );
		return FALSE;
	}
	
	if ( ! OnRun() ) return FALSE;
	if ( m_nQueuedRun == 2 && ! OnWrite() ) return FALSE;
	m_nQueuedRun = 0;

	return TRUE;
}

void CConnection::QueueRun()
{
	if ( m_nQueuedRun )
	{
		m_nQueuedRun = 2;
	}
	else
	{
		OnWrite();
	}
}

//////////////////////////////////////////////////////////////////////
// CConnection socket event handlers

BOOL CConnection::OnConnected()
{
	return TRUE;
}

void CConnection::OnDropped(BOOL bError)
{
}

BOOL CConnection::OnRun()
{
	return TRUE;
}

//////////////////////////////////////////////////////////////////////
// CConnection read event handler

BOOL CConnection::OnRead()
{
	if ( m_hSocket == INVALID_SOCKET ) return FALSE;

	BYTE pData[TEMP_BUFFER];

	DWORD tNow		= GetTickCount();
	DWORD nLimit	= 0xFFFFFFFF;
	DWORD nTotal	= 0;
	
	if ( m_mInput.pLimit && *m_mInput.pLimit && ( Settings.Live.BandwidthScale <= 100 || m_mInput.bUnscaled ) )
	{
		DWORD tCutoff	= tNow - METER_SECOND;
		DWORD* pHistory	= m_mInput.pHistory;
		DWORD* pTime	= m_mInput.pTimes;
		nLimit			= 0;
		
		for ( int nSeek = METER_LENGTH ; nSeek ; nSeek--, pHistory++, pTime++ )
		{
			if ( *pTime >= tCutoff ) nLimit += *pHistory;
		}
		
		DWORD nActual = *m_mInput.pLimit;

		if ( Settings.Live.BandwidthScale < 100 && ! m_mInput.bUnscaled )
		{
			nActual = nActual * Settings.Live.BandwidthScale / 100;
		}

		tCutoff = nActual * ( tNow - m_mInput.tLastAdd ) / 1000;
		m_mInput.tLastAdd = tNow;
		
		nLimit = ( nLimit >= nActual ) ? 0 : ( nActual - nLimit );
		nLimit = min( nLimit, tCutoff );
	}

	while ( nLimit )
	{
		int nLength = min( ( nLimit & 0xFFFFF ), TEMP_BUFFER );
		
		nLength = recv( m_hSocket, (char*)pData, nLength, 0 );
		if ( nLength <= 0 ) break;
		
		m_mInput.tLast = tNow;
		
		if ( nLength > 0 && nLength <= TEMP_BUFFER )
		{
			m_pInput->Add( pData, nLength );
		}
		
		nTotal += nLength;
		if ( nLimit != 0xFFFFFFFF ) nLimit -= nLength;
	}

	if ( m_mInput.pHistory && nTotal )
	{
		if ( tNow - m_mInput.tLastSlot < METER_MINIMUM )
		{
			m_mInput.pHistory[ m_mInput.nPosition ] += nTotal;
		}

⌨️ 快捷键说明

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