void CDownloadQueue::Process() { // send src requests to local server ProcessLocalRequests(); { wxMutexLocker lock(m_mutex); uint32 downspeed = 0; if (thePrefs::GetMaxDownload() != UNLIMITED && m_datarate > 1500) { downspeed = (((uint32)thePrefs::GetMaxDownload())*1024*100)/(m_datarate+1); if (downspeed < 50) { downspeed = 50; } else if (downspeed > 200) { downspeed = 200; } } m_datarate = 0; m_udcounter++; uint32 cur_datarate = 0; uint32 cur_udcounter = m_udcounter; std::list<int> m_sourcecountlist; bool mustPreventSleep = false; for ( uint16 i = 0; i < m_filelist.size(); i++ ) { CPartFile* file = m_filelist[i]; CMutexUnlocker unlocker(m_mutex); uint8 status = file->GetStatus(); mustPreventSleep |= !(status == PS_ERROR || status == PS_INSUFFICIENT || status == PS_PAUSED || status == PS_COMPLETE); if (status == PS_READY || status == PS_EMPTY ){ cur_datarate += file->Process( downspeed, cur_udcounter ); } else { //This will make sure we don't keep old sources to paused and stoped files.. file->StopPausedFile(); } if (!file->IsPaused() && !file->IsStopped()) { m_sourcecountlist.push_back(file->GetSourceCount()); } } if (thePrefs::GetPreventSleepWhileDownloading()) { if ((mustPreventSleep == false) && (theStats::GetSessionSentBytes() < theStats::GetSessionReceivedBytes())) { // I can see right through your clever plan. mustPreventSleep = true; } if (mustPreventSleep) { PlatformSpecific::PreventSleepMode(); } else { PlatformSpecific::AllowSleepMode(); } } else { // Just in case the value changes while we're preventing. Calls to this function are totally inexpensive anwyay PlatformSpecific::AllowSleepMode(); } // Set the source rarity thresholds int nSourceGroups = m_sourcecountlist.size(); if (nSourceGroups) { m_sourcecountlist.sort(); if (nSourceGroups == 1) { // High anyway. m_rareFileThreshold = m_sourcecountlist.front() + 1; m_commonFileThreshold = m_rareFileThreshold + 1; } else if (nSourceGroups == 2) { // One high, one low (unless they're both 0, then both high) m_rareFileThreshold = (m_sourcecountlist.back() > 0) ? (m_sourcecountlist.back() - 1) : 1; m_commonFileThreshold = m_rareFileThreshold + 1; } else { // More than two, time to do some math. // Lower 25% with the current #define values. int rarecutpoint = (nSourceGroups / RARITY_FACTOR); for (int i = 0; i < rarecutpoint; ++ i) { m_sourcecountlist.pop_front(); } m_rareFileThreshold = (m_sourcecountlist.front() > 0) ? (m_sourcecountlist.front() - 1) : 1; // 50% of the non-rare ones, with the curent #define values. int commoncutpoint = (nSourceGroups - rarecutpoint) / NORMALITY_FACTOR; for (int i = 0; i < commoncutpoint; ++ i) { m_sourcecountlist.pop_front(); } m_commonFileThreshold = (m_sourcecountlist.front() > 0) ? (m_sourcecountlist.front() - 1) : 1; } } else { m_rareFileThreshold = RARE_FILE; m_commonFileThreshold = 100; } m_datarate += cur_datarate; if (m_udcounter == 5) { if (theApp->serverconnect->IsUDPSocketAvailable()) { if( (::GetTickCount() - m_lastudpstattime) > UDPSERVERSTATTIME) { m_lastudpstattime = ::GetTickCount(); CMutexUnlocker unlocker(m_mutex); theApp->serverlist->ServerStats(); } } } if (m_udcounter == 10) { m_udcounter = 0; if (theApp->serverconnect->IsUDPSocketAvailable()) { if ( (::GetTickCount() - m_lastudpsearchtime) > UDPSERVERREASKTIME) { SendNextUDPPacket(); } } } if ( (::GetTickCount() - m_lastsorttime) > 10000 ) { DoSortByPriority(); } // Check if any paused files can be resumed CheckDiskspace(thePrefs::GetTempDir()); } // Check for new links once per second. if ((::GetTickCount() - m_nLastED2KLinkCheck) >= 1000) { theApp->AddLinksFromFile(); m_nLastED2KLinkCheck = ::GetTickCount(); } }
void CDownloadQueue::KademliaSearchFile(uint32_t searchID, const Kademlia::CUInt128* pcontactID, const Kademlia::CUInt128* pbuddyID, uint8_t type, uint32_t ip, uint16_t tcp, uint16_t udp, uint32_t buddyip, uint16_t buddyport, uint8_t byCryptOptions) { AddDebugLogLineN(logKadSearch, CFormat(wxT("Search result sources (type %i)")) % type); //Safety measure to make sure we are looking for these sources CPartFile* temp = GetFileByKadFileSearchID(searchID); if( !temp ) { AddDebugLogLineN(logKadSearch, wxT("This is not the file we're looking for...")); return; } //Do we need more sources? if(!(!temp->IsStopped() && thePrefs::GetMaxSourcePerFile() > temp->GetSourceCount())) { AddDebugLogLineN(logKadSearch, wxT("No more sources needed for this file")); return; } uint32_t ED2KID = wxUINT32_SWAP_ALWAYS(ip); if (theApp->ipfilter->IsFiltered(ED2KID)) { AddDebugLogLineN(logKadSearch, wxT("Source ip got filtered")); AddDebugLogLineN(logIPFilter, CFormat(wxT("IPfiltered source IP=%s received from Kademlia")) % Uint32toStringIP(ED2KID)); return; } if( (ip == Kademlia::CKademlia::GetIPAddress() || ED2KID == theApp->GetED2KID()) && tcp == thePrefs::GetPort()) { AddDebugLogLineN(logKadSearch, wxT("Trying to add myself as source, ignore")); return; } CUpDownClient* ctemp = NULL; switch (type) { case 4: case 1: { // NonFirewalled users if(!tcp) { AddDebugLogLineN(logKadSearch, CFormat(wxT("Ignored source (IP=%s) received from Kademlia, no tcp port received")) % Uint32toStringIP(ip)); return; } if (!IsGoodIP(ED2KID,thePrefs::FilterLanIPs())) { AddDebugLogLineN(logKadSearch, CFormat(wxT("%s got filtered")) % Uint32toStringIP(ED2KID)); AddDebugLogLineN(logIPFilter, CFormat(wxT("Ignored source (IP=%s) received from Kademlia, filtered")) % Uint32toStringIP(ED2KID)); return; } ctemp = new CUpDownClient(tcp, ip, 0, 0, temp, false, true); ctemp->SetSourceFrom(SF_KADEMLIA); // not actually sent or needed for HighID sources //ctemp->SetServerIP(serverip); //ctemp->SetServerPort(serverport); ctemp->SetKadPort(udp); byte cID[16]; pcontactID->ToByteArray(cID); ctemp->SetUserHash(CMD4Hash(cID)); break; } case 2: { // Don't use this type... Some clients will process it wrong.. break; } case 5: case 3: { // This will be a firewalled client connected to Kad only. // We set the clientID to 1 as a Kad user only has 1 buddy. ctemp = new CUpDownClient(tcp, 1, 0, 0, temp, false, true); // The only reason we set the real IP is for when we get a callback // from this firewalled source, the compare method will match them. ctemp->SetSourceFrom(SF_KADEMLIA); ctemp->SetKadPort(udp); byte cID[16]; pcontactID->ToByteArray(cID); ctemp->SetUserHash(CMD4Hash(cID)); pbuddyID->ToByteArray(cID); ctemp->SetBuddyID(cID); ctemp->SetBuddyIP(buddyip); ctemp->SetBuddyPort(buddyport); break; } case 6: { // firewalled source which supports direct UDP callback // if we are firewalled ourself, the source is useless to us if (theApp->IsFirewalled()) { break; } if ((byCryptOptions & 0x08) == 0){ AddDebugLogLineN(logKadSearch, CFormat(wxT("Received Kad source type 6 (direct callback) which has the direct callback flag not set (%s)")) % Uint32toStringIP(ED2KID)); break; } ctemp = new CUpDownClient(tcp, 1, 0, 0, temp, false, true); ctemp->SetSourceFrom(SF_KADEMLIA); ctemp->SetKadPort(udp); ctemp->SetIP(ED2KID); // need to set the IP address, which cannot be used for TCP but for UDP byte cID[16]; pcontactID->ToByteArray(cID); ctemp->SetUserHash(CMD4Hash(cID)); } } if (ctemp) { // add encryption settings ctemp->SetConnectOptions(byCryptOptions); AddDebugLogLineN(logKadSearch, CFormat(wxT("Happily adding a source (%s) type %d")) % Uint32_16toStringIP_Port(ED2KID, ctemp->GetUserPort()) % type); CheckAndAddSource(temp, ctemp); } }