📄 downloadclient.cpp
字号:
theStats.AddUpDataOverheadFileRequest(packet->size);
socket->SendPacket(packet, true);
// 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 (thePrefs.GetDebugClientTCPLevel() > 0)
DebugSend("OP__SetReqFileID", this, (char*)reqfile->GetFileHash());
CSafeMemFile dataSetReqFileID(16);
dataSetReqFileID.WriteHash16(reqfile->GetFileHash());
packet = new Packet(&dataSetReqFileID);
packet->opcode = OP_SETREQFILEID;
theStats.AddUpDataOverheadFileRequest(packet->size);
socket->SendPacket(packet, true);
}
if( IsEmuleClient() )
{
SetRemoteQueueFull( true );
SetRemoteQueueRank(0);
}
if(IsSourceRequestAllowed())
{
if (thePrefs.GetDebugClientTCPLevel() > 0){
DebugSend("OP__RequestSources", this, (char*)reqfile->GetFileHash());
if (GetLastAskedForSources() == 0)
Debug(_T(" first source request\n"));
else
Debug(_T(" last source request was before %s\n"), CastSecondsToHM((GetTickCount() - GetLastAskedForSources())/1000));
}
reqfile->SetLastAnsweredTimeTimeout();
Packet* packet = new Packet(OP_REQUESTSOURCES,16,OP_EMULEPROT);
md4cpy(packet->pBuffer,reqfile->GetFileHash());
theStats.AddUpDataOverheadSourceExchange(packet->size);
socket->SendPacket(packet,true,true);
SetLastAskedForSources();
if (thePrefs.GetDebugSourceExchange())
AddDebugLogLine(false, _T("SXSend: Client source request; %s, File=\"%s\""), DbgGetClientInfo(), reqfile->GetFileName());
}
if (IsSupportingAICH()){
Packet* packet = new Packet(OP_AICHFILEHASHREQ,16,OP_EMULEPROT);
md4cpy(packet->pBuffer,reqfile->GetFileHash());
socket->SendPacket(packet,true,true);
}
}
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(GetUnicodeSupport());
// 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))
{
TCHAR* psz = new TCHAR[m_nPartCount + 1];
for (int i = 0; i < m_nPartCount; i++)
psz[i] = m_abyPartStatus[i] ? _T('#') : _T('.');
psz[i] = _T('\0');
Debug(_T(" Parts=%u %s 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){
switch( nNewState )
{
case DS_CONNECTING:
m_dwLastTriedToConnect = ::GetTickCount();
break;
case DS_TOOMANYCONNSKAD:
//This client had already been set to DS_CONNECTING.
//So we reset this time so it isn't stuck at TOOMANYCONNS for 20mins.
m_dwLastTriedToConnect = ::GetTickCount()-20*60*1000;
break;
case DS_WAITCALLBACKKAD:
case DS_WAITCALLBACK:
break;
default:
switch( m_nDownloadState )
{
case DS_WAITCALLBACK:
case DS_WAITCALLBACKKAD:
break;
default:
m_dwLastTriedToConnect = ::GetTickCount()-20*60*1000;
break;
}
break;
}
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-
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -