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

📄 edclient.cpp

📁 著名的下载软件核心Shareaza
💻 CPP
📖 第 1 页 / 共 2 页
字号:
	if ( pPacket->GetRemaining() < sizeof(GUID) + 6 + 4 + 6 )
	{
		theApp.Message( MSG_ERROR, IDS_ED2K_CLIENT_HANDSHAKE_FAIL, (LPCTSTR)m_sAddress );
		Close();
		return FALSE;
	}
	
	GGUID pGUID;
	pPacket->Read( &pGUID, sizeof(GUID) );
	
	/*
	if ( m_bGUID )
	{
		if ( pGUID != m_pGUID )
		{
			theApp.Message( MSG_ERROR, IDS_ED2K_CLIENT_WRONG_GUID, (LPCTSTR)m_sAddress );
			Close();
			return FALSE;
		}
	}
	*/
	
	m_bGUID				= TRUE;
	m_pGUID				= pGUID;
	m_nClientID			= pPacket->ReadLongLE();
	m_pHost.sin_port	= htons( pPacket->ReadShortLE() );
	
	DWORD nCount = pPacket->ReadLongLE();
	
	while ( nCount-- > 0 && pPacket->GetRemaining() > 0 )
	{
		CEDTag pTag;
		if ( ! pTag.Read( pPacket ) )
		{
			theApp.Message( MSG_ERROR, IDS_ED2K_CLIENT_HANDSHAKE_FAIL, (LPCTSTR)m_sAddress );
			Close();
			return FALSE;
		}
		
		if ( pTag.m_nKey == ED2K_CT_NAME && pTag.m_nType == ED2K_TAG_STRING )
		{
			m_sNick = pTag.m_sValue;
		}
		else if ( pTag.m_nKey == ED2K_CT_VERSION && pTag.m_nType == ED2K_TAG_INT )
		{
			m_nVersion = pTag.m_nValue;
		}
		else if ( pTag.m_nKey == ED2K_CT_PORT && pTag.m_nType == ED2K_TAG_INT )
		{
			m_pHost.sin_port = htons( (WORD)pTag.m_nValue );
		}
	}
	
	if ( pPacket->GetRemaining() < 6 )
	{
		theApp.Message( MSG_ERROR, IDS_ED2K_CLIENT_HANDSHAKE_FAIL, (LPCTSTR)m_sAddress );
		Close();
		return FALSE;
	}
	
	m_pServer.sin_addr.S_un.S_addr = pPacket->ReadLongLE();
	m_pServer.sin_port = htons( pPacket->ReadShortLE() );
	
	if ( Settings.eDonkey.LearnNewServers && ! Network.IsFirewalledAddress( &m_pServer.sin_addr ) )
	{
		HostCache.eDonkey.Add( &m_pServer.sin_addr, htons( m_pServer.sin_port ) );
	}
	
	DeriveVersion();
	
	if ( pPacket->m_nType == ED2K_C2C_HELLO )
	{
		if ( m_bEmule ) SendEmuleInfo( ED2K_C2C_EMULEINFO );
		SendHello( ED2K_C2C_HELLOANSWER );
	}
	
	if ( m_bLogin )
		return TRUE;
	else
		return OnLoggedIn();
}

//////////////////////////////////////////////////////////////////////
// CEDClient EMULE INFO packet exchange

void CEDClient::SendEmuleInfo(BYTE nType)
{
	CEDPacket* pPacket = CEDPacket::New( nType, ED2K_PROTOCOL_EMULE );
	
	// BYTE nVersion = ( theApp.m_nVersion[0] << 4 ) + ( theApp.m_nVersion[1] & 7 );
	
	pPacket->WriteByte( 0x30 );		// eMule version
	pPacket->WriteByte( 0x01 );		// eMule protocol
	
	pPacket->WriteLongLE( Settings.eDonkey.ExtendedRequest ? 6 : 5 );	// Tags
	CEDTag( ED2K_ET_COMPATIBLECLIENT, 4 ).Write( pPacket );
	CEDTag( ED2K_ET_COMPRESSION, 1 ).Write( pPacket );
	CEDTag( ED2K_ET_SOURCEEXCHANGE, 2 ).Write( pPacket );
	if ( Settings.eDonkey.ExtendedRequest ) CEDTag( ED2K_ET_EXTENDEDREQUEST, 1 ).Write( pPacket );
	CEDTag( ED2K_ET_UDPVER, 2 ).Write( pPacket );
	CEDTag( ED2K_ET_UDPPORT, htons( Network.m_pHost.sin_port ) ).Write( pPacket );
//	CEDTag( ED2K_ET_COMMENTS, 1 ).Write( pPacket );	
	Send( pPacket );
}

BOOL CEDClient::OnEmuleInfo(CEDPacket* pPacket)
{
	if ( pPacket->GetRemaining() < 5 )
	{
		theApp.Message( MSG_ERROR, IDS_ED2K_CLIENT_HANDSHAKE_FAIL, (LPCTSTR)m_sAddress );
		Close();
		return FALSE;
	}
	
	m_nEmVersion	= pPacket->ReadByte();
	BYTE nProtocol	= pPacket->ReadByte();
	
	if ( nProtocol != 1 ) return TRUE;
	
	if ( m_nEmVersion > 0x22 && m_nEmVersion < 0x25 ) m_bEmSources = 1;
	if ( m_nEmVersion == 0x24 ) m_bEmComments = 1;
	
	DWORD nCount = pPacket->ReadLongLE();
	
	while ( nCount-- > 0 && pPacket->GetRemaining() > 0 )
	{
		CEDTag pTag;
		
		if ( ! pTag.Read( pPacket ) )
		{
			theApp.Message( MSG_ERROR, IDS_ED2K_CLIENT_HANDSHAKE_FAIL, (LPCTSTR)m_sAddress );
			Close();
			return FALSE;
		}
		
		if ( pTag.m_nType != ED2K_TAG_INT ) continue;
		
		switch ( pTag.m_nKey )
		{
		case ED2K_ET_SOURCEEXCHANGE:
			m_bEmSources = pTag.m_nValue;
			break;
		case ED2K_ET_COMMENTS:
			m_bEmComments = pTag.m_nValue;
			break;
		case ED2K_ET_EXTENDEDREQUEST:
			m_bEmRequest = pTag.m_nValue;
			break;
		case ED2K_ET_COMPRESSION:
			m_bEmDeflate = pTag.m_nValue;
			break;
		case ED2K_ET_UDPPORT:
			m_nUDP = (WORD)pTag.m_nValue;
			break;
		case ED2K_ET_COMPATIBLECLIENT:
			m_nEmCompatible = pTag.m_nValue;
			break;
		}
	}
	
	m_bEmule = TRUE;
	if ( pPacket->m_nType == ED2K_C2C_EMULEINFO ) SendEmuleInfo( ED2K_C2C_EMULEINFOANSWER );
	
	DeriveVersion();
	
	return TRUE;
}

//////////////////////////////////////////////////////////////////////
// CEDClient client version

void CEDClient::DeriveVersion()
{
	if ( m_pGUID.n[5] == 13 && m_pGUID.n[14] == 110 )
	{
		m_bEmule = TRUE;
		m_sUserAgent.Format( _T("eMule v%i"), m_nVersion );
	}
	else if ( m_pGUID.n[5] == 14 && m_pGUID.n[14] == 111 )
	{
		m_bEmule = TRUE;
		m_sUserAgent.Format( _T("eMule v%i"), m_nVersion );
	}
	else if ( m_pGUID.n[5] == 'M' && m_pGUID.n[14] == 'L' )
	{
		m_sUserAgent.Format( _T("mlDonkey v%i"), m_nVersion );
	}
	else
	{
		m_sUserAgent.Format( _T("eDonkey v1.%i"), m_nVersion - 1000 );
	}
	
	if ( m_bEmule && m_nEmVersion > 0 )
	{
		switch ( m_nEmCompatible )
		{
		case 0:
			m_sUserAgent.Format( _T("eMule v0.%i%i"), m_nEmVersion >> 4, m_nEmVersion & 15 );
			break;
		case 1:
			m_sUserAgent.Format( _T("cDonkey v%i.%i"), m_nEmVersion >> 4, m_nEmVersion & 15 );
			break;
		case 4:
			m_sUserAgent.Format( _T("Shareaza"), m_nEmVersion >> 4, m_nEmVersion & 15 );
			break;
		default:
			m_sUserAgent.Format( _T("eMule/c v0.%i%i"), m_nEmVersion >> 4, m_nEmVersion & 15 );
			break;
		}
	}
}

//////////////////////////////////////////////////////////////////////
// CEDClient FILE REQUEST handler

BOOL CEDClient::OnFileRequest(CEDPacket* pPacket)
{
	if ( pPacket->GetRemaining() < sizeof(MD4) )
	{
		theApp.Message( MSG_ERROR, IDS_ED2K_CLIENT_BAD_PACKET, (LPCTSTR)m_sAddress, pPacket->m_nType );
		return TRUE;
	}
	
	CEDPacket* pReply = CEDPacket::New( ED2K_C2C_FILEREQANSWER );
	
	pPacket->Read( &m_pUpMD4, sizeof(MD4) );
	pReply->Write( &m_pUpMD4, sizeof(MD4) );
	m_bUpMD4 = TRUE;
	
	if ( CLibraryFile* pFile = LibraryMaps.LookupFileByED2K( &m_pUpMD4, TRUE, TRUE, TRUE ) )
	{
		pReply->WriteEDString( pFile->m_sName );
		Library.Unlock();
		Send( pReply );
		return TRUE;
	}
	else if ( CDownload* pDownload = Downloads.FindByED2K( &m_pUpMD4, TRUE ) )
	{
		pReply->WriteEDString( pDownload->m_sRemoteName );
		Send( pReply );
		return TRUE;
	}
	
	pReply->m_nType = ED2K_C2C_FILENOTFOUND;
	Send( pReply );
	
	theApp.Message( MSG_ERROR, IDS_UPLOAD_FILENOTFOUND, (LPCTSTR)m_sAddress,
		(LPCTSTR)CED2K::HashToString( &m_pUpMD4, TRUE ) );
	
	return TRUE;
}

//////////////////////////////////////////////////////////////////////
// CEDClient file status request

BOOL CEDClient::OnFileStatusRequest(CEDPacket* pPacket)
{
	if ( pPacket->GetRemaining() < sizeof(MD4) )
	{
		theApp.Message( MSG_ERROR, IDS_ED2K_CLIENT_BAD_PACKET, (LPCTSTR)m_sAddress, pPacket->m_nType );
		return TRUE;
	}
	
	CEDPacket* pReply = CEDPacket::New( ED2K_C2C_FILESTATUS );
	
	pPacket->Read( &m_pUpMD4, sizeof(MD4) );
	pReply->Write( &m_pUpMD4, sizeof(MD4) );
	m_bUpMD4 = TRUE;
	
	if ( CLibraryFile* pFile = LibraryMaps.LookupFileByED2K( &m_pUpMD4, TRUE, TRUE, TRUE ) )
	{
		pReply->WriteShortLE( 0 );
		pReply->WriteByte( 0 );
		
		m_nUpSize = pFile->GetSize();
		if ( ! CEDPacket::IsLowID( m_nClientID ) )
			pFile->AddAlternateSource( GetSourceURL() );
		
		Library.Unlock();
		Send( pReply );
		return TRUE;
	}
	else if ( CDownload* pDownload = Downloads.FindByED2K( &m_pUpMD4, TRUE ) )
	{
		WritePartStatus( pReply, pDownload );
		m_nUpSize = pDownload->m_nSize;
		
		pDownload->AddSourceED2K( m_nClientID, htons( m_pHost.sin_port ),
			m_pServer.sin_addr.S_un.S_addr, htons( m_pServer.sin_port ), &m_pGUID );
		
		Send( pReply );
		return TRUE;
	}
	
	m_bUpMD4 = FALSE;
	
	pReply->m_nType = ED2K_C2C_FILENOTFOUND;
	Send( pReply );
	
	theApp.Message( MSG_ERROR, IDS_UPLOAD_FILENOTFOUND, (LPCTSTR)m_sAddress,
		(LPCTSTR)CED2K::HashToString( &m_pUpMD4, TRUE ) );	
	
	return TRUE;
}

//////////////////////////////////////////////////////////////////////
// CEDClient hash set request

BOOL CEDClient::OnHashsetRequest(CEDPacket* pPacket)
{
	if ( pPacket->GetRemaining() < sizeof(MD4) )
	{
		theApp.Message( MSG_ERROR, IDS_ED2K_CLIENT_BAD_PACKET, (LPCTSTR)m_sAddress, pPacket->m_nType );
		return TRUE;
	}
	
	MD4 pHash;
	pPacket->Read( &pHash, sizeof(MD4) );
	
	CED2K* pHashset	= NULL;
	BOOL bDelete = FALSE;
	CString strName;
	
	if ( CLibraryFile* pFile = LibraryMaps.LookupFileByED2K( &pHash, TRUE, TRUE, TRUE ) )
	{
		strName		= pFile->m_sName;
		pHashset	= pFile->GetED2K();
		bDelete		= TRUE;
		Library.Unlock();
	}
	else if ( CDownload* pDownload = Downloads.FindByED2K( &pHash, TRUE ) )
	{
		if ( pHashset = pDownload->GetHashset() )
		{
			strName		= pDownload->m_sRemoteName;
			bDelete		= FALSE;
		}
	}
	
	if ( pHashset != NULL )
	{
		CEDPacket* pReply = CEDPacket::New( ED2K_C2C_HASHSETANSWER );
		pReply->Write( &pHash, sizeof(MD4) );
		int nBlocks = pHashset->GetBlockCount();
		if ( nBlocks <= 1 ) nBlocks = 0;
		pReply->WriteShortLE( (WORD)nBlocks );
		pReply->Write( pHashset->GetRawPtr(), sizeof(MD4) * nBlocks );
		if ( bDelete ) delete pHashset;
		Send( pReply );
		
		theApp.Message( MSG_DEFAULT, IDS_ED2K_CLIENT_SENT_HASHSET,
			(LPCTSTR)strName, (LPCTSTR)m_sAddress );	
	}
	else
	{
		CEDPacket* pReply = CEDPacket::New( ED2K_C2C_FILENOTFOUND );
		pReply->Write( &pHash, sizeof(MD4) );
		Send( pReply );
		
		theApp.Message( MSG_ERROR, IDS_UPLOAD_FILENOTFOUND, (LPCTSTR)m_sAddress,
			(LPCTSTR)CED2K::HashToString( &pHash, TRUE ) );	
	}
	
	return TRUE;
}

//////////////////////////////////////////////////////////////////////
// CEDClient queue request

BOOL CEDClient::OnQueueRequest(CEDPacket* pPacket)
{
	if ( m_bUpMD4 == FALSE )
	{
		// MESSAGE: File not requested yet
		return TRUE;
	}
	
	if ( m_pUpload != NULL && m_pUpload->m_pED2K != m_pUpMD4 )
		DetachUpload();
	
	if ( m_pUpload == NULL )
		m_pUpload = new CUploadTransferED2K( this );
	
	m_pUpload->Request( &m_pUpMD4 );
	
	return TRUE;
}

//////////////////////////////////////////////////////////////////////
// CEDClient source request

BOOL CEDClient::OnSourceRequest(CEDPacket* pPacket)
{
	if ( pPacket->GetRemaining() < sizeof(MD4) )
	{
		theApp.Message( MSG_ERROR, IDS_ED2K_CLIENT_BAD_PACKET, (LPCTSTR)m_sAddress, pPacket->m_nType );
		return TRUE;
	}
	
	MD4 pHash;
	pPacket->Read( &pHash, sizeof(MD4) );
	
	CEDPacket* pReply = CEDPacket::New( ED2K_C2C_ANSWERSOURCES, ED2K_PROTOCOL_EMULE );
	int nCount = 0;
	
	if ( CDownload* pDownload = Downloads.FindByED2K( &pHash, TRUE ))
	{
		for ( CDownloadSource* pSource = pDownload->GetFirstSource() ; pSource ; pSource = pSource->m_pNext )
		{
			if ( pSource->m_nProtocol == PROTOCOL_ED2K && pSource->m_bReadContent )
			{
				pReply->WriteLongLE( pSource->m_pAddress.S_un.S_addr );
				pReply->WriteShortLE( pSource->m_nPort );
				pReply->WriteLongLE( pSource->m_pServerAddress.S_un.S_addr );
				pReply->WriteShortLE( (WORD)pSource->m_nServerPort );
				if ( m_bEmSources >= 2 ) pReply->Write( &pSource->m_pGUID, sizeof(GGUID) );
				nCount++;
			}
		}
	}
	
	if ( pReply->m_nLength > 0 )
	{
		BYTE* pStart = pReply->WriteGetPointer( sizeof(MD4) + 2, 0 );
		CopyMemory( pStart, &pHash, sizeof(MD4) );
		pStart += sizeof(MD4);
		*(WORD*)pStart = nCount;
		Send( pReply, FALSE );
	}
	
	pReply->Release();
	
	return TRUE;
}

//////////////////////////////////////////////////////////////////////
// CEDClient source answer

BOOL CEDClient::OnSourceAnswer(CEDPacket* pPacket)
{
	if ( Settings.Library.SourceMesh == FALSE ) return TRUE;
	
	if ( pPacket->GetRemaining() < sizeof(MD4) + 2 )
	{
		theApp.Message( MSG_ERROR, IDS_ED2K_CLIENT_BAD_PACKET, (LPCTSTR)m_sAddress, pPacket->m_nType );
		return TRUE;
	}
	
	MD4 pHash;
	pPacket->Read( &pHash, sizeof(MD4) );
	int nCount = pPacket->ReadShortLE();
	
	if ( pPacket->GetRemaining() < nCount * ( m_bEmSources >= 2 ? 12+16 : 12 ) )
	{
		theApp.Message( MSG_ERROR, IDS_ED2K_CLIENT_BAD_PACKET, (LPCTSTR)m_sAddress, pPacket->m_nType );
		return TRUE;
	}
	
	if ( CDownload* pDownload = Downloads.FindByED2K( &pHash ))
	{
		while ( nCount-- > 0 )
		{
			GGUID pGUID;
			
			DWORD nClientID		= pPacket->ReadLongLE();
			WORD nClientPort	= pPacket->ReadShortLE();
			DWORD nServerIP		= pPacket->ReadLongLE();
			WORD nServerPort	= pPacket->ReadShortLE();
			
			if ( m_bEmSources >= 2 )
			{
				pPacket->Read( &pGUID, sizeof(GGUID) );
				pDownload->AddSourceED2K( nClientID, nClientPort, nServerIP, nServerPort, &pGUID );
			}
			else
			{
				pDownload->AddSourceED2K( nClientID, nClientPort, nServerIP, nServerPort );
			}
		}
	}	
	
	return TRUE;
}

//////////////////////////////////////////////////////////////////////
// CEDClient source URL utility

CString CEDClient::GetSourceURL()
{
	ASSERT( m_bGUID );
	ASSERT( m_bUpMD4 );
	
	CString str;

	if ( CEDPacket::IsLowID( m_nClientID ) )
	{
		str.Format( _T("ed2kftp://%lu@%s:%i/%s/%I64i/"),
			m_nClientID,
			(LPCTSTR)CString( inet_ntoa( m_pHost.sin_addr ) ),
			htons( m_pHost.sin_port ),
			(LPCTSTR)CED2K::HashToString( &m_pUpMD4 ), m_nUpSize );
	}
	else
	{
		str.Format( _T("ed2kftp://%s:%lu/%s/%I64i/"),
			(LPCTSTR)CString( inet_ntoa( m_pHost.sin_addr ) ),
			htons( m_pHost.sin_port ),
			(LPCTSTR)CED2K::HashToString( &m_pUpMD4 ), m_nUpSize );
	}
	
	return str;
}

//////////////////////////////////////////////////////////////////////
// CEDClient part status utility

void CEDClient::WritePartStatus(CEDPacket* pPacket, CDownload* pDownload)
{
	QWORD nParts = ( pDownload->m_nSize + ED2K_PART_SIZE - 1 ) / ED2K_PART_SIZE;
	pPacket->WriteShortLE( (WORD)nParts );
	
	if ( pDownload->m_pHashsetBlock != NULL && pDownload->m_nHashsetBlock == nParts )
	{
		for ( QWORD nPart = 0 ; nPart < nParts ; )
		{
			BYTE nByte = 0;
			
			for ( DWORD nBit = 0 ; nBit < 8 && nPart < nParts ; nBit++, nPart++ )
			{
				if ( pDownload->m_pHashsetBlock[ nPart ] == TS_TRUE )
				{
					nByte |= ( 1 << nBit );
				}
			}
			
			pPacket->WriteByte( nByte );
		}
	}
	else
	{
		for ( QWORD nPart = 0 ; nPart < nParts ; )
		{
			BYTE nByte = 0;
			
			for ( DWORD nBit = 0 ; nBit < 8 && nPart < nParts ; nBit++, nPart++ )
			{
				QWORD nOffset = nPart * ED2K_PART_SIZE;
				QWORD nLength = min( ED2K_PART_SIZE, pDownload->m_nSize - nOffset );
				
				if ( pDownload->IsRangeUseful( nOffset, nLength ) == FALSE )
				{
					nByte |= ( 1 << nBit );
				}
			}
			
			pPacket->WriteByte( nByte );
		}
	}
}

//////////////////////////////////////////////////////////////////////
// CEDClient UDP packet handlers

BOOL CEDClient::OnUdpReask(CEDPacket* pPacket)
{
	if ( pPacket->GetRemaining() < sizeof(MD4) ) return FALSE;
	if ( m_bUpMD4 == FALSE || m_pUpload == NULL ) return FALSE;
	
	MD4 pMD4;
	pPacket->Read( &pMD4, sizeof(MD4) );
	if ( pMD4 != m_pUpMD4 ) return FALSE;
	
	return m_pUpload->OnReask();
}

BOOL CEDClient::OnUdpReaskAck(CEDPacket* pPacket)
{
	if ( pPacket->GetRemaining() < 2 ) return FALSE;
	if ( m_pDownload == NULL ) return FALSE;
	
	int nRank = pPacket->ReadShortLE();
	m_pDownload->SetQueueRank( nRank );
	
	return TRUE;
}

BOOL CEDClient::OnUdpQueueFull(CEDPacket* pPacket)
{
	if ( m_pDownload != NULL )
	{
		m_pDownload->m_pSource->m_tAttempt = GetTickCount() + Settings.eDonkey.ReAskTime * 1000;
		m_pDownload->Close( TS_UNKNOWN );
	}
	
	return TRUE;
}

BOOL CEDClient::OnUdpFileNotFound(CEDPacket* pPacket)
{
	if ( m_pDownload != NULL ) m_pDownload->Close( TS_FALSE );
	return TRUE;
}

⌨️ 快捷键说明

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