📄 partfile.cpp
字号:
int CPartFile::GetValidSourcesCount() const
{
int counter = 0;
for (POSITION pos = srclist.GetHeadPosition(); pos != NULL;){
EDownloadState nDLState = srclist.GetNext(pos)->GetDownloadState();
if (nDLState==DS_ONQUEUE || nDLState==DS_DOWNLOADING || nDLState==DS_CONNECTED || nDLState==DS_REMOTEQUEUEFULL)
++counter;
}
return counter;
}
uint16 CPartFile::GetNotCurrentSourcesCount() const
{
UINT counter = 0;
for (POSITION pos = srclist.GetHeadPosition(); pos != NULL;){
EDownloadState nDLState = srclist.GetNext(pos)->GetDownloadState();
if (nDLState!=DS_ONQUEUE && nDLState!=DS_DOWNLOADING)
counter++;
}
return counter;
}
// SLUGFILLER: checkDiskspace
uint32 CPartFile::GetNeededSpace() const
{
if (m_hpartfile.GetLength() > GetFileSize())
return 0; // Shouldn't happen, but just in case
return GetFileSize()-m_hpartfile.GetLength();
}
// SLUGFILLER: checkDiskspace
EPartFileStatus CPartFile::GetStatus(bool ignorepause) const
{
// SLUGFILLER: checkDiskspace
if ((!paused && !insufficient) || status == PS_ERROR || status == PS_COMPLETING || status == PS_COMPLETE || ignorepause)
return status;
else if (paused)
return PS_PAUSED;
else
return PS_INSUFFICIENT;
// SLUGFILLER: checkDiskspace
}
void CPartFile::AddDownloadingSource(CUpDownClient* client){
POSITION pos = m_downloadingSourceList.Find(client); // to be sure
if(pos == NULL){
m_downloadingSourceList.AddTail(client);
}
}
void CPartFile::RemoveDownloadingSource(CUpDownClient* client){
POSITION pos = m_downloadingSourceList.Find(client); // to be sure
if(pos != NULL){
m_downloadingSourceList.RemoveAt(pos);
}
}
uint32 CPartFile::Process(uint32 reducedownload, uint8 m_icounter/*in percent*/)
{
if (thePrefs.m_iDbgHeap >= 2)
ASSERT_VALID(this);
uint16 nOldTransSourceCount = GetSrcStatisticsValue(DS_DOWNLOADING);
DWORD dwCurTick = ::GetTickCount();
// If buffer size exceeds limit, or if not written within time limit, flush data
if ((m_nTotalBufferData > thePrefs.GetFileBufferSize()) || (dwCurTick > (m_nLastBufferFlushTime + BUFFER_TIME_LIMIT)))
{
// Avoid flushing while copying preview file
if (!m_bPreviewing)
FlushBuffer();
}
datarate = 0;
// calculate datarate, set limit etc.
if(m_icounter < 10)
{
uint32 cur_datarate;
for(POSITION pos = m_downloadingSourceList.GetHeadPosition();pos!=0;)
{
CUpDownClient* cur_src = m_downloadingSourceList.GetNext(pos);
if (thePrefs.m_iDbgHeap >= 2)
ASSERT_VALID( cur_src );
if(cur_src && cur_src->GetDownloadState() == DS_DOWNLOADING)
{
ASSERT( cur_src->socket );
if (cur_src->socket)
{
cur_src->CheckDownloadTimeout();
cur_datarate = cur_src->CalculateDownloadRate();
datarate+=cur_datarate;
if(reducedownload)
{
uint32 limit = reducedownload*cur_datarate/1000;
if(limit<1000 && reducedownload == 200)
limit +=1000;
else if(limit<1)
limit = 1;
cur_src->socket->SetDownloadLimit(limit);
if (cur_src->IsDownloadingFromPeerCache() && cur_src->m_pPCDownSocket && cur_src->m_pPCDownSocket->IsConnected())
cur_src->m_pPCDownSocket->SetDownloadLimit(limit);
}
}
}
}
}
else
{
// -khaos--+++> Moved this here, otherwise we were setting our permanent variables to 0 every tenth of a second...
memset(m_anStates,0,sizeof(m_anStates));
memset(src_stats,0,sizeof(src_stats));
uint16 nCountForState;
for (POSITION pos = srclist.GetHeadPosition(); pos != NULL;)
{
CUpDownClient* cur_src = srclist.GetNext(pos);
if (thePrefs.m_iDbgHeap >= 2)
ASSERT_VALID( cur_src );
// BEGIN -rewritten- refreshing statistics (no need for temp vars since it is not multithreaded)
nCountForState = cur_src->GetDownloadState();
//special case which is not yet set as downloadstate
if (nCountForState == DS_ONQUEUE)
{
if( cur_src->IsRemoteQueueFull() )
nCountForState = DS_REMOTEQUEUEFULL;
}
if (cur_src->IsBanned())
nCountForState = DS_BANNED;
if (cur_src->GetSourceFrom() >= SF_SERVER && cur_src->GetSourceFrom() <= SF_PASSIVE)
++src_stats[cur_src->GetSourceFrom()];
ASSERT( nCountForState < sizeof(m_anStates)/sizeof(m_anStates[0]) );
m_anStates[nCountForState]++;
DWORD dwLastCheck = dwCurTick - cur_src->GetLastAskedTime();
switch (cur_src->GetDownloadState())
{
case DS_DOWNLOADING:{
ASSERT( cur_src->socket );
if (cur_src->socket)
{
cur_src->CheckDownloadTimeout();
uint32 cur_datarate = cur_src->CalculateDownloadRate();
datarate += cur_datarate;
if (reducedownload && cur_src->GetDownloadState() == DS_DOWNLOADING)
{
uint32 limit = reducedownload*cur_datarate/1000; //(uint32)(((float)reducedownload/100)*cur_datarate)/10;
if (limit < 1000 && reducedownload == 200)
limit += 1000;
else if (limit < 1)
limit = 1;
cur_src->socket->SetDownloadLimit(limit);
if (cur_src->IsDownloadingFromPeerCache() && cur_src->m_pPCDownSocket && cur_src->m_pPCDownSocket->IsConnected())
cur_src->m_pPCDownSocket->SetDownloadLimit(limit);
}
else{
cur_src->socket->DisableDownloadLimit();
if (cur_src->IsDownloadingFromPeerCache() && cur_src->m_pPCDownSocket && cur_src->m_pPCDownSocket->IsConnected())
cur_src->m_pPCDownSocket->DisableDownloadLimit();
}
}
break;
}
// Do nothing with this client..
case DS_BANNED:
case DS_ERROR:
break;
// Check if something has changed with our or their ID state..
case DS_LOWTOLOWIP:
{
//Make sure this source is still a LowID Client..
if( cur_src->HasLowID() )
{
//Make sure we still cannot callback to this Client..
if( !theApp.DoCallback( cur_src ) )
{
//If we are almost maxed on sources, slowly remove these client to see if we can find a better source.
if( ((dwCurTick - lastpurgetime) > SEC2MS(30)) && (this->GetSourceCount() >= (thePrefs.GetMaxSourcePerFile()*.8 )) )
{
theApp.downloadqueue->RemoveSource( cur_src );
lastpurgetime = dwCurTick;
}
break;
}
}
// This should no longer be a LOWTOLOWIP..
cur_src->SetDownloadState(DS_ONQUEUE);
break;
}
case DS_NONEEDEDPARTS:
{
// we try to purge noneeded source, even without reaching the limit
if( (dwCurTick - lastpurgetime) > SEC2MS(40) ){
lastpurgetime = dwCurTick; // ZZ:DownloadManager
// we only delete them if reaching the limit
if (GetSourceCount() >= (thePrefs.GetMaxSourcePerFile()*.8 )){
theApp.downloadqueue->RemoveSource( cur_src );
break; //Johnny-B - nothing more to do here (good eye!)
}
}
// doubled reasktime for no needed parts - save connections and traffic
if (!((!cur_src->GetLastAskedTime()) || (dwLastCheck > FILEREASKTIME*2)))
break;
cur_src->SwapToAnotherFile(_T("A4AF for NNP file. CPartFile::Process()"), true, false, false, NULL, true, true); // ZZ:DownloadManager
// Recheck this client to see if still NNP.. Set to DS_NONE so that we force a TCP reask next time..
cur_src->SetDownloadState(DS_NONE);
break;
}
case DS_ONQUEUE:
{
if( cur_src->IsRemoteQueueFull() )
{
if( ((dwCurTick - lastpurgetime) > MIN2MS(1)) && (GetSourceCount() >= (thePrefs.GetMaxSourcePerFile()*.8 )) )
{
theApp.downloadqueue->RemoveSource( cur_src );
lastpurgetime = dwCurTick;
break; //Johnny-B - nothing more to do here (good eye!)
}
}
//Give up to 1 min for UDP to respond.. If we are within on min on TCP, do not try..
if (theApp.IsConnected() && ((cur_src->GetLastAskedTime()) && (dwLastCheck > FILEREASKTIME-MIN2MS(2) && dwLastCheck < FILEREASKTIME-SEC2MS(1))))
cur_src->UDPReaskForDownload();
}
case DS_CONNECTING:
case DS_TOOMANYCONNS:
case DS_NONE:
case DS_WAITCALLBACK:
{
if (theApp.IsConnected() && ((!cur_src->GetLastAskedTime()) || (dwCurTick - cur_src->GetLastAskedTime()) > FILEREASKTIME))
{
if(!cur_src->AskForDownload()) // NOTE: This may *delete* the client!!
break; //I left this break here just as a reminder just in case re rearange things..
}
break;
}
}
}
// ZZ:DownloadManager removed lines here
if( thePrefs.GetMaxSourcePerFileUDP() > GetSourceCount()){
if (theApp.downloadqueue->DoKademliaFileRequest() && (Kademlia::CKademlia::getTotalFile() < KADEMLIATOTALFILE) && (!lastsearchtimeKad || (dwCurTick - lastsearchtimeKad) > KADEMLIAREASKTIME) && Kademlia::CKademlia::isConnected() && theApp.IsConnected() && !stopped){ //Once we can handle lowID users in Kad, we remove the second IsConnected
//Kademlia
theApp.downloadqueue->SetLastKademliaFileRequest();
if (Kademlia::CKademlia::isRunning() && !GetKadFileSearchID())
{
Kademlia::CUInt128 kadFileID;
kadFileID.setValue(GetFileHash());
Kademlia::CSearch* pSearch = Kademlia::CSearchManager::prepareFindFile(Kademlia::CSearch::FILE, true, kadFileID);
if (pSearch)
{
lastsearchtimeKad = dwCurTick;
SetKadFileSearchID(pSearch->getSearchID());
}
else
SetKadFileSearchID(0);
}
}
}
else{
if(GetKadFileSearchID())
{
Kademlia::CSearchManager::stopSearch(GetKadFileSearchID(), true);
}
}
// check if we want new sources from server
if ( !m_bLocalSrcReqQueued && ((!lastsearchtime) || (dwCurTick - lastsearchtime) > SERVERREASKTIME) && theApp.serverconnect->IsConnected()
&& thePrefs.GetMaxSourcePerFileSoft() > GetSourceCount() && !stopped )
{
m_bLocalSrcReqQueued = true;
theApp.downloadqueue->SendLocalSrcRequest(this);
}
count++;
if (count == 3){
count = 0;
UpdateAutoDownPriority();
UpdateDisplayedInfo();
UpdateCompletedInfos();
}
}
if ( GetSrcStatisticsValue(DS_DOWNLOADING) != nOldTransSourceCount ){
if (theApp.emuledlg->transferwnd->downloadlistctrl.curTab == 0)
theApp.emuledlg->transferwnd->downloadlistctrl.ChangeCategory(0);
else
UpdateDisplayedInfo(true);
if (thePrefs.ShowCatTabInfos() )
theApp.emuledlg->transferwnd->UpdateCatTabTitles();
}
return datarate;
}
bool CPartFile::CanAddSource(uint32 userid, uint16 port, uint32 serverip, uint16 serverport, UINT* pdebug_lowiddropped, bool Ed2kID)
{
//The incoming ID could have the userid in the Hyrbid format..
uint32 hybridID = 0;
if( Ed2kID )
hybridID = ntohl(userid);
else
{
hybridID = userid;
userid = ntohl(userid);
}
// MOD Note: Do not change this part - Merkur
if (theApp.serverconnect->IsConnected())
{
if(theApp.serverconnect->IsLowID())
{
if(theApp.serverconnect->GetClientID() == userid && theApp.serverconnect->GetCurrentServer()->GetIP() == serverip && theApp.serverconnect->GetCurrentServer()->GetPort() == serverport )
return false;
if(theApp.serverconnect->GetLocalIP() == userid)
return false;
}
else
{
if(theApp.serverconnect->GetClientID() == userid && thePrefs.GetPort() == port)
return false;
}
}
if (Kademlia::CKademlia::isConnected())
{
if(Kademlia::CKademlia::isFirewalled())
{
//This will change with LowID support is added..
if(Kademlia::CKademlia::getPrefs()->getIPAddress() == hybridID && thePrefs.GetPort() == port)
return false;
}
else
{
if(Kademlia::CKademlia::getIPAddress() == hybridID && thePrefs.GetPort() == port)
return false;
}
}
//This allows *.*.*.0 clients to not be removed..
if ( ((Ed2kID && IsLowID(userid)) || (!Ed2kID && IsLowID(hybridID))) && theApp.IsFirewalled())
{
if (pdebug_lowiddropped)
(*pdebug_lowiddropped)++;
return false;
}
// MOD Note - end
return true;
}
void CPartFile::AddSources(CSafeMemFile* sources, uint32 serverip, uint16 serverport)
{
UINT count = sources->ReadUInt8();
if (stopped)
{
// since we may received multiple search source UDP results we have to "consume" all data of that packet
sources->Seek(count*(4+2), SEEK_SET);
return;
}
UINT debug_lowiddropped = 0;
UINT debug_possiblesources = 0;
for (UINT i = 0; i < count; i++)
{
uint32 userid = sources->ReadUInt32();
uint16 port = sources->ReadUInt16();
// check the HighID(IP) - "Filter LAN IPs" and "IPfilter" the received sources IP addresses
if (!IsLowID(userid))
{
if (!IsGoodIP(userid))
{
// check for 0-IP, localhost and optionally for LAN addresses
if (thePrefs.GetLogFilteredIPs())
AddDebugLogLine(false, _T("Ignored source (IP=%s) received from server - bad IP"), ipstr(userid));
continue;
}
if (theApp.ipfilter->IsFiltered(userid))
{
if (thePrefs.GetLogFilteredIPs())
AddDebugLogLine(false, _T("Ignored source (IP=%s) received from server - IP filter (%s)"), ipstr(userid), theApp.ipfilter->GetLastHit());
continue;
}
if (theApp.clientlist->IsBannedClient(userid)){
#ifdef _DEBUG
if (thePrefs.GetLogBannedClients()){
CUpDownClient* pClient = theApp.clientlist->FindClientByIP(userid);
AddDebugLogLine(false, _T("Ignored source (IP=%s) received from server - banned client %s"), ipstr(userid), pClient->DbgGetClientInfo());
}
#endif
continue;
}
}
// additionally check for LowID and own IP
if (!CanAddSource(userid, port, serverip, serverport, &debug_lowiddropped))
{
if (thePrefs.GetLogFilteredIPs())
AddDebugLogLine(false, _T("Ignored source (IP=%s) received from server"), ipstr(userid));
continue;
}
if( thePrefs.GetMaxSourcePerFile() > this->GetSourceCount() )
{
debug_possiblesources++;
CUpDownClient* newsource = new CUpDownClient(this,port,userid,serverip,serverport,true);
theApp.downloadqueue->CheckAndAddSource(this,newsource);
}
else
{
// since we may received multiple search source UDP results we have to "consume" all data of that packet
sources->Seek((count-i)*(4+2), SEEK_SET);
if(GetKadFileSearchID())
Kademlia::CSearchManager::stopSearch(GetKadFileSearchID(), false);
break;
}
}
if (thePrefs.GetDebugSourceExchange())
AddDebugLogLine(false, _T("RCV: %i sources from server, %i low id dropped, %i possible sources File(%s)"),coun
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -