📄 downloadclient.cpp
字号:
if (thePrefs.GetDebugSourceExchange())
AddDebugLogLine(false, _T("Send:Source Request User(%s) File(%s)"), GetUserName(), reqfile->GetFileName() );
}
}
SetLastAskedTime(); // ZZ:DownloadManager
}
void CUpDownClient::SendStartupLoadReq()
{
if (socket==NULL || reqfile==NULL)
{
ASSERT(0);
return;
}
SetDownloadState(DS_ONQUEUE);
if (thePrefs.GetDebugClientTCPLevel() > 0)
DebugSend("OP__StartupLoadReq", this);
CSafeMemFile dataStartupLoadReq(16);
dataStartupLoadReq.WriteHash16(reqfile->GetFileHash());
Packet* packet = new Packet(&dataStartupLoadReq);
packet->opcode = OP_STARTUPLOADREQ;
theStats.AddUpDataOverheadFileRequest(packet->size);
socket->SendPacket(packet, true, true);
m_fQueueRankPending = 1;
m_fUnaskQueueRankRecv = 0;
}
void CUpDownClient::ProcessFileInfo(CSafeMemFile* data, CPartFile* file)
{
if (file==NULL)
throw GetResString(IDS_ERR_WRONGFILEID) + _T(" (ProcessFileInfo; file==NULL)");
if (reqfile==NULL)
throw GetResString(IDS_ERR_WRONGFILEID) + _T(" (ProcessFileInfo; reqfile==NULL)");
if (file != reqfile)
throw GetResString(IDS_ERR_WRONGFILEID) + _T(" (ProcessFileInfo; reqfile!=file)");
m_strClientFilename = data->ReadString();
// 26-Jul-2003: removed requesting the file status for files <= PARTSIZE for better compatibility with ed2k protocol (eDonkeyHybrid).
// if the remote client answers the OP_REQUESTFILENAME with OP_REQFILENAMEANSWER the file is shared by the remote client. if we
// know that the file is shared, we know also that the file is complete and don't need to request the file status.
if (reqfile->GetPartCount() == 1)
{
if (m_abyPartStatus)
{
delete[] m_abyPartStatus;
m_abyPartStatus = NULL;
}
m_nPartCount = reqfile->GetPartCount();
m_abyPartStatus = new uint8[m_nPartCount];
memset(m_abyPartStatus,1,m_nPartCount);
m_bCompleteSource = true;
if (thePrefs.GetDebugClientTCPLevel() > 0)
{
int iNeeded = 0;
for (int i = 0; i < m_nPartCount; i++)
if (!reqfile->IsComplete(i*PARTSIZE,((i+1)*PARTSIZE)-1))
iNeeded++;
char* psz = new char[m_nPartCount + 1];
for (int i = 0; i < m_nPartCount; i++)
psz[i] = m_abyPartStatus[i] ? '#' : '.';
psz[i] = '\0';
Debug(_T(" Parts=%u %hs Needed=%u\n"), m_nPartCount, psz, iNeeded);
delete[] psz;
}
UpdateDisplayedInfo();
reqfile->UpdateAvailablePartsCount();
// even if the file is <= PARTSIZE, we _may_ need the hashset for that file (if the file size == PARTSIZE)
if (reqfile->hashsetneeded)
{
if (socket)
{
Packet* packet = new Packet(OP_HASHSETREQUEST,16);
md4cpy(packet->pBuffer,reqfile->GetFileHash());
theStats.AddUpDataOverheadFileRequest(packet->size);
socket->SendPacket(packet,true,true);
SetDownloadState(DS_REQHASHSET);
m_fHashsetRequesting = 1;
reqfile->hashsetneeded = false;
}
else
ASSERT(0);
}
else
{
SendStartupLoadReq();
}
reqfile->UpdatePartsInfo();
}
}
void CUpDownClient::ProcessFileStatus(bool bUdpPacket, CSafeMemFile* data, CPartFile* file)
{
if ( !reqfile || file != reqfile )
{
if (reqfile==NULL)
throw GetResString(IDS_ERR_WRONGFILEID) + _T(" (ProcessFileStatus; reqfile==NULL)");
throw GetResString(IDS_ERR_WRONGFILEID) + _T(" (ProcessFileStatus; reqfile!=file)");
}
uint16 nED2KPartCount = data->ReadUInt16();
if (m_abyPartStatus)
{
delete[] m_abyPartStatus;
m_abyPartStatus = NULL;
}
bool bPartsNeeded = false;
int iNeeded = 0;
if (!nED2KPartCount)
{
m_nPartCount = reqfile->GetPartCount();
m_abyPartStatus = new uint8[m_nPartCount];
memset(m_abyPartStatus,1,m_nPartCount);
bPartsNeeded = true;
m_bCompleteSource = true;
if (bUdpPacket ? (thePrefs.GetDebugClientUDPLevel() > 0) : (thePrefs.GetDebugClientTCPLevel() > 0))
{
for (int i = 0; i < m_nPartCount; i++)
{
if (!reqfile->IsComplete(i*PARTSIZE,((i+1)*PARTSIZE)-1))
iNeeded++;
}
}
}
else
{
if (reqfile->GetED2KPartCount() != nED2KPartCount)
{
CString strError;
strError.Format(_T("ProcessFileStatus - wrong part number recv=%u expected=%u %s"), nED2KPartCount, reqfile->GetED2KPartCount(), DbgGetFileInfo(reqfile->GetFileHash()));
m_nPartCount = 0;
throw strError;
}
m_nPartCount = reqfile->GetPartCount();
m_bCompleteSource = false;
m_abyPartStatus = new uint8[m_nPartCount];
uint16 done = 0;
while (done != m_nPartCount)
{
uint8 toread = data->ReadUInt8();
for (sint32 i = 0;i != 8;i++)
{
m_abyPartStatus[done] = ((toread>>i)&1)? 1:0;
if (m_abyPartStatus[done])
{
if (!reqfile->IsComplete(done*PARTSIZE,((done+1)*PARTSIZE)-1)){
bPartsNeeded = true;
iNeeded++;
}
}
done++;
if (done == m_nPartCount)
break;
}
}
}
if (bUdpPacket ? (thePrefs.GetDebugClientUDPLevel() > 0) : (thePrefs.GetDebugClientTCPLevel() > 0))
{
char* psz = new char[m_nPartCount + 1];
for (int i = 0; i < m_nPartCount; i++)
psz[i] = m_abyPartStatus[i] ? '#' : '.';
psz[i] = '\0';
Debug(_T(" Parts=%u %hs Needed=%u\n"), m_nPartCount, psz, iNeeded);
delete[] psz;
}
UpdateDisplayedInfo();
reqfile->UpdateAvailablePartsCount();
// NOTE: This function is invoked from TCP and UDP socket!
if (!bUdpPacket)
{
if (!bPartsNeeded)
SetDownloadState(DS_NONEEDEDPARTS);
//If we are using the eMule filerequest packets, this is taken care of in the Multipacket!
else if (reqfile->hashsetneeded)
{
if (socket)
{
if (thePrefs.GetDebugClientTCPLevel() > 0)
DebugSend("OP__HashSetRequest", this, (char*)reqfile->GetFileHash());
Packet* packet = new Packet(OP_HASHSETREQUEST,16);
md4cpy(packet->pBuffer,reqfile->GetFileHash());
theStats.AddUpDataOverheadFileRequest(packet->size);
socket->SendPacket(packet, true, true);
SetDownloadState(DS_REQHASHSET);
m_fHashsetRequesting = 1;
reqfile->hashsetneeded = false;
}
else
ASSERT(0);
}
else
{
SendStartupLoadReq();
}
}
else
{
if (!bPartsNeeded)
SetDownloadState(DS_NONEEDEDPARTS);
else
SetDownloadState(DS_ONQUEUE);
}
reqfile->UpdatePartsInfo();
}
bool CUpDownClient::AddRequestForAnotherFile(CPartFile* file){
for (POSITION pos = m_OtherNoNeeded_list.GetHeadPosition();pos != 0;){
if (m_OtherNoNeeded_list.GetNext(pos) == file)
return false;
}
for (POSITION pos = m_OtherRequests_list.GetHeadPosition();pos != 0;){
if (m_OtherRequests_list.GetNext(pos) == file)
return false;
}
m_OtherRequests_list.AddTail(file);
file->A4AFsrclist.AddTail(this); // [enkeyDEV(Ottavio84) -A4AF-]
return true;
}
void CUpDownClient::ClearDownloadBlockRequests()
{
for (POSITION pos = m_DownloadBlocks_list.GetHeadPosition();pos != 0;){
Requested_Block_Struct* cur_block = m_DownloadBlocks_list.GetNext(pos);
if (reqfile){
reqfile->RemoveBlockFromList(cur_block->StartOffset,cur_block->EndOffset);
}
delete cur_block;
}
m_DownloadBlocks_list.RemoveAll();
for (POSITION pos = m_PendingBlocks_list.GetHeadPosition();pos != 0;){
Pending_Block_Struct *pending = m_PendingBlocks_list.GetNext(pos);
if (reqfile){
reqfile->RemoveBlockFromList(pending->block->StartOffset, pending->block->EndOffset);
}
delete pending->block;
// Not always allocated
if (pending->zStream){
inflateEnd(pending->zStream);
delete pending->zStream;
}
delete pending;
}
m_PendingBlocks_list.RemoveAll();
}
void CUpDownClient::SetDownloadState(EDownloadState nNewState){
if (m_nDownloadState != nNewState){
if (reqfile){
if(nNewState == DS_DOWNLOADING){
reqfile->AddDownloadingSource(this);
}
else if(m_nDownloadState == DS_DOWNLOADING){
reqfile->RemoveDownloadingSource(this);
}
}
if (m_nDownloadState == DS_DOWNLOADING ){
// -khaos--+++> Extended Statistics (Successful/Failed Download Sessions)
if ( m_bTransferredDownMini && nNewState != DS_ERROR )
thePrefs.Add2DownSuccessfulSessions(); // Increment our counters for successful sessions (Cumulative AND Session)
else
thePrefs.Add2DownFailedSessions(); // Increment our counters failed sessions (Cumulative AND Session)
thePrefs.Add2DownSAvgTime(GetDownTimeDifference()/1000);
// <-----khaos-
m_nDownloadState = nNewState;
ClearDownloadBlockRequests();
m_nDownDatarate = 0;
if (nNewState == DS_NONE){
if (m_abyPartStatus)
delete[] m_abyPartStatus;
m_abyPartStatus = NULL;
m_nPartCount = 0;
}
if (socket && nNewState != DS_ERROR)
socket->DisableDownloadLimit();
}
m_nDownloadState = nNewState;
if( GetDownloadState() == DS_DOWNLOADING ){
if ( IsEmuleClient() )
SetRemoteQueueFull(false);
SetRemoteQueueRank(0);
SetAskedCountDown(0);
}
UpdateDisplayedInfo(true);
}
}
void CUpDownClient::ProcessHashSet(char* packet,uint32 size){
if (!m_fHashsetRequesting)
throw CString(_T("unwanted hashset"));
if ( (!reqfile) || md4cmp(packet,reqfile->GetFileHash())){
CheckFailedFileIdReqs((uchar*)packet);
throw GetResString(IDS_ERR_WRONGFILEID) + _T(" (ProcessHashSet)");
}
CSafeMemFile data((BYTE*)packet,size);
if (reqfile->LoadHashsetFromFile(&data,true)){
m_fHashsetRequesting = 0;
}
else{
reqfile->hashsetneeded = true;
throw GetResString(IDS_ERR_BADHASHSET);
}
SendStartupLoadReq();
}
void CUpDownClient::CreateBlockRequests(int iMaxBlocks)
{
ASSERT( iMaxBlocks >= 1 /*&& iMaxBlocks <= 3*/ );
if (m_DownloadBlocks_list.IsEmpty())
{
uint16 count = iMaxBlocks - m_PendingBlocks_list.GetCount();
Requested_Block_Struct** toadd = new Requested_Block_Struct*[count];
if (reqfile->GetNextRequestedBlock(this,toadd,&count)){
for (int i = 0; i < count; i++)
m_DownloadBlocks_list.AddTail(toadd[i]);
}
delete[] toadd;
}
while (m_PendingBlocks_list.GetCount() < iMaxBlocks && !m_DownloadBlocks_list.IsEmpty())
{
Pending_Block_Struct* pblock = new Pending_Block_Struct;
pblock->block = m_DownloadBlocks_list.RemoveHead();
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -