예제 #1
0
// Called when a remote computer wants to connect to us
// When WSAAccept accepted the connection, it created a new socket hSocket for it and wrote the remote IP in pHost
void CConnection::AcceptFrom(SOCKET hSocket, SOCKADDR_IN* pHost)
{
	// Make sure the newly accepted socket is valid
	ASSERT( ! IsValid() );

	// Record the connection information here
	m_hSocket		= hSocket;							// Keep the socket here
	m_pHost			= *pHost;							// Copy the remote IP address into this object
	m_sAddress		= inet_ntoa( m_pHost.sin_addr );	// Store it as a string also
	UpdateCountry();

	// Make new input and output buffer objects
	ASSERT( m_pInput == NULL );
	ASSERT( m_pOutput == NULL );
	CreateBuffers();

	// Facts about the connection
	m_bInitiated	= FALSE;			// We didn't initiate this connection
	m_bConnected	= TRUE;				// We're connected right now
	m_tConnected	= GetTickCount();	// Record the time this happened

	// Choose asynchronous, non-blocking reading and writing on the new socket
	DWORD dwValue = 1;
	ioctlsocket( m_hSocket, FIONBIO, &dwValue );

	// Record one more incoming connection in the statistics
	Statistics.Current.Connections.Incoming++;
}
예제 #2
0
BOOL CDownloadTransferBT::Initiate()
{
	ASSUME_LOCK( Transfers.m_pSection );
	ASSERT( m_pClient == NULL );
	ASSERT( m_nState == dtsNull );

	theApp.Message( MSG_DEBUG, _T("Connecting to BitTorrent host %s..."),
		(LPCTSTR)CString( inet_ntoa( m_pSource->m_pAddress ) ) );

	m_pClient = new CBTClient();
	if ( ! m_pClient->Connect( this ) )
	{
		delete m_pClient;
		m_pClient = NULL;
		Close( TRI_FALSE );
		return FALSE;
	}
	SetState( dtsConnecting );
	m_tConnected	= GetTickCount();
	m_pHost			= m_pClient->m_pHost;
	m_sAddress		= m_pClient->m_sAddress;
	UpdateCountry();
	
	return TRUE;
}
예제 #3
0
BOOL CDownloadTransferBT::OnConnected()
{
	ASSUME_LOCK( Transfers.m_pSection );
	ASSERT( m_pClient != NULL );
	ASSERT( m_pSource != NULL );

	SetState( dtsTorrent );
	m_pHost		= m_pClient->m_pHost;
	m_sAddress	= m_pClient->m_sAddress;
	UpdateCountry();

	// not deleting source for source exchange.
	if ( m_pDownload->IsCompleted() )
	{
		// This source is only here to push start torrent uploads. (We don't want to download)
		m_bInterested = FALSE;
		theApp.Message( MSG_INFO, _T("Initiated push start for upload to %s"), (LPCTSTR)m_sAddress );
	}
	else
	{
		// Regular download
		m_pClient->m_mInput.pLimit = &m_nBandwidth;
		theApp.Message( MSG_INFO, IDS_DOWNLOAD_CONNECTED, (LPCTSTR)m_sAddress );
		if ( ! m_pDownload->PrepareFile() )
		{
			Close( TRI_TRUE );
			return FALSE;
		}
		m_pClient->m_mInput.pLimit = &m_nBandwidth;
	}

	m_pSource->SetLastSeen();
	return TRUE;
}
BOOL CDownloadTransferED2K::OnConnected()
{
	ASSERT( m_pClient != NULL );
	ASSERT( m_pSource != NULL );

	m_pHost				= m_pClient->m_pHost;
	m_sAddress			= m_pClient->m_sAddress;
	UpdateCountry();

	m_pSource->m_oGUID	= m_pClient->m_oGUID;
	m_pSource->m_sNick	= m_pClient->m_sNick;
	m_pSource->m_sServer = m_sUserAgent = m_pClient->m_sUserAgent;
	m_pSource->SetLastSeen();

	theApp.Message( MSG_INFO, IDS_DOWNLOAD_CONNECTED, (LPCTSTR)m_sAddress );

	return SendPrimaryRequest();
}
BOOL CDownloadTransferED2K::Initiate()
{
	ASSERT( m_pClient == NULL );
	ASSERT( m_nState == dtsNull );

	if ( ! m_pDownload->m_oED2K || m_pDownload->m_nSize == SIZE_UNKNOWN )
	{
		Close( TRI_FALSE );
		return FALSE;
	}

	m_pClient = EDClients.Connect(
		m_pSource->m_pAddress.S_un.S_addr,
		m_pSource->m_nPort,
		m_pSource->m_nServerPort ? &m_pSource->m_pServerAddress : NULL,
		m_pSource->m_nServerPort,
		m_pSource->m_oGUID );

	if ( m_pClient == NULL )
	{
		Close( EDClients.IsFull() ? TRI_TRUE : TRI_FALSE );
		return FALSE;
	}

	SetState( dtsConnecting );
	m_tConnected = GetTickCount();

	if ( ! m_pClient->AttachDownload( this ) )
	{
		SetState( dtsNull );
		m_pClient = NULL;
		Close( TRI_TRUE );
		return FALSE;
	}

	m_pHost		= m_pClient->m_pHost;
	m_sAddress	= m_pClient->m_sAddress;
	if ( m_sAddress.IsEmpty() )
		m_sAddress = inet_ntoa( m_pHost.sin_addr );
	UpdateCountry();
	m_pClient->m_mInput.pLimit = &m_nBandwidth;

	return TRUE;
}
예제 #6
0
BOOL CUploadTransferDC::OnUpload(const std::string& strType, const std::string& strFilename, QWORD nOffset, QWORD nLength, const std::string& strOptions)
{
	ASSERT( m_pClient );

	if ( m_nState >= upsUploading )
	{
		// Drop unsent data
		CLockedBuffer pOutput( m_pClient->GetOutput() );
		pOutput->Clear();

		m_nState = upsRequest;
	}

	ClearRequest();

	m_sUserAgent = m_pClient->GetUserAgent();
	m_pHost = m_pClient->m_pHost;
	m_sAddress = m_pClient->m_sAddress;
	UpdateCountry();

	m_pClient->m_mInput.pLimit  = &Settings.Bandwidth.Request;
	m_pClient->m_mOutput.pLimit = &m_nBandwidth;

	m_tRequest = GetTickCount();

	BOOL bZip = ( strOptions.find("ZL1") != std::string::npos );

	if ( strType == "tthl" )
	{
		m_bGet = FALSE;

		if ( strFilename.substr( 0, 4 ) == "TTH/" )
		{
			Hashes::TigerHash oTiger;
			if ( oTiger.fromString( CA2W( strFilename.substr( 4 ).c_str() ) ) )
			{
				CSingleLock oLock( &Library.m_pSection );
				if ( oLock.Lock( 1000 ) )
				{
					if ( CLibraryFile* pFile = LibraryMaps.LookupFileByTiger( oTiger, TRUE, TRUE ) )
					{
						if ( RequestTigerTree( pFile, nOffset, nLength ) )
							return TRUE;
					}
				}
			}
		}
	}
	else if ( strType == "file" || strType =="get" )
	{
		m_bGet = ( strType == "get" );

		if ( strFilename == "files.xml" || strFilename == "files.xml.bz2" )
		{
			if ( RequestFileList( TRUE, bZip, strFilename, nOffset, nLength ) )
				return TRUE;
		}
		else if ( strFilename.substr( 0, 4 ) == "TTH/" )
		{
			Hashes::TigerHash oTiger;
			if ( oTiger.fromString( CA2W( strFilename.substr( 4 ).c_str() ) ) )
			{
				CSingleLock oLock( &Library.m_pSection );
				if ( oLock.Lock( 1000 ) )
				{
					if ( CLibraryFile* pFile = LibraryMaps.LookupFileByTiger( oTiger, TRUE, TRUE ) )
					{
						if ( RequestFile( pFile, nOffset, nLength ) )
							return TRUE;
					}
				}
			}
		}
	}
	else if ( strType == "list" )
	{
		m_bGet = FALSE;

		if ( RequestFileList( FALSE, bZip, strFilename, nOffset, nLength ) )
			return TRUE;
	}
	else if ( strType == "send" )
	{
		if ( m_bGet )
		{
			if ( m_pXML.GetCount() )
			{
				// Send cached file list
				m_bGet = FALSE;

				StartSending( upsBrowse );

				m_pClient->Write( &m_pXML );

				m_pXML.Clear();

				return TRUE;
			}
			else if ( SendFile() )
			{
				// Send already requested file
				return TRUE;
			}
		}
		// else $Send without $Get
	}
	else
	{
		// Invalid request type
		theApp.Message( MSG_ERROR, _T("DC++ Invalid request type from %s"), (LPCTSTR)m_sAddress );
		return FALSE;
	}

	theApp.Message( MSG_ERROR, IDS_UPLOAD_FILENOTFOUND, (LPCTSTR)m_sAddress, (LPCTSTR)CA2CT( strFilename.c_str() ) );

	m_pClient->SendCommand( FILE_NOT_AVAILABLE );

	return TRUE;
}
예제 #7
0
// Connect this CConnection object to a remote computer on the Internet
// Takes pAddress, a Windows Sockets structure that holds an IP address, and takes the port number seprately
// Returns true if connected
BOOL CConnection::ConnectTo(const IN_ADDR* pAddress, WORD nPort)
{
	// Make sure the socket isn't already connected somehow
	if ( IsValid() )
		return FALSE;

	// Make sure we have an address and a nonzero port number
	if ( pAddress == NULL || nPort == 0 )
		return FALSE;

	// S_un.S_addr is the IP as a single unsigned 4-byte long
	if ( pAddress->S_un.S_addr == 0 )
		return FALSE;

	// The IP address is in the security list of government and corporate addresses we want to avoid
	if ( Security.IsDenied( pAddress ) )
	{
		// Report that we aren't connecting to this IP address and return false
		theApp.Message( MSG_ERROR, IDS_NETWORK_SECURITY_OUTGOING, (LPCTSTR)CString( inet_ntoa( *pAddress ) ) );
		return FALSE;
	}

	// The IN_ADDR structure we just got passed isn't the same as the one already stored in this object
	if ( pAddress != &m_pHost.sin_addr )
	{
		// Zero the memory of the entire SOCKADDR_IN structure m_pHost, and then copy in the sin_addr part
		ZeroMemory( &m_pHost, sizeof( m_pHost ) );
		m_pHost.sin_addr = *pAddress;
	}

	// Fill in more parts of the m_pHost structure
	m_pHost.sin_family	= AF_INET;							// PF_INET means just normal IPv4, not IPv6 yet
	m_pHost.sin_port	= htons( nPort );					// Copy the port number into the m_pHost structure
	m_sAddress			= inet_ntoa( m_pHost.sin_addr );	// Save the IP address as a string of text
	UpdateCountry();

	// Create a socket and store it in m_hSocket
	// Normal IPv4 not IPv6, and the two-way sequenced reliable byte streams of TCP, not the datagrams of UDP
	m_hSocket = socket( PF_INET, SOCK_STREAM, IPPROTO_TCP );

	// Choose asynchronous, non-blocking reading and writing on our new socket
	DWORD dwValue = 1;
	ioctlsocket( m_hSocket, FIONBIO, &dwValue );
		// Call Windows Sockets ioctlsocket to control the input/output mode of our new socket
		// Give it our new socket
		// Select the option for blocking i/o, should the program wait on read and write calls, or keep going?
		// Nonzero, it should keep going

	// If the OutHost string in connection settings has an IP address written in it
	if ( Settings.Connection.OutHost.GetLength() )
	{
		// Read the text and copy the IP address and port into a new local MFC SOCKADDR_IN structure called pOutgoing
		SOCKADDR_IN pOutgoing;
		Network.Resolve( Settings.Connection.OutHost, 0, &pOutgoing );

		// S_addr is the IP address as a single long number, if it's not zero
		if ( pOutgoing.sin_addr.S_un.S_addr )
		{
			// Call bind in Windows Sockets to associate the local address with the socket
			bind(
				m_hSocket,					// Our socket
				(SOCKADDR*)&pOutgoing,		// The IP address this computer appears to have on the Internet (do)
				sizeof( SOCKADDR_IN ) );	// Tell bind how many bytes it can read at the pointer
		}
	}

	DestroyBuffers();

	// Try to connect to the remote computer
	if ( WSAConnect(
		m_hSocket,					// Our socket
		(SOCKADDR*)&m_pHost,		// The remote IP address and port number
		sizeof( SOCKADDR_IN ),		// How many bytes the function can read
		NULL, NULL, NULL, NULL ) )	// No advanced features
	{
		// If no error occurs, WSAConnect returns 0, so if we're here an error happened
		int nError = WSAGetLastError();		// Get the last Windows Sockets error number

		// An error of "would block" is normal because connections can't be made instantly and this is a non-blocking socket
		if ( nError != WSAEWOULDBLOCK )
		{
			CNetwork::CloseSocket( m_hSocket, true );

			if ( nError != 0 )
				Statistics.Current.Connections.Errors++;

			return FALSE;
		}
	}

	CreateBuffers();

	// Record that we initiated this connection, and when it happened
	m_bInitiated	= TRUE;
	m_tConnected	= GetTickCount();

	// Record one more outgoing connection in the statistics
	Statistics.Current.Connections.Outgoing++;

	// Connection successfully attempted
	return TRUE;
}