void CDownloadQueue::CheckAndAddSource(CPartFile* sender, CUpDownClient* source) { // if we block loopbacks at this point it should prevent us from connecting to ourself if ( source->HasValidHash() ) { if ( source->GetUserHash() == thePrefs::GetUserHash() ) { AddDebugLogLineN( logDownloadQueue, wxT("Tried to add source with matching hash to your own.") ); source->Safe_Delete(); return; } } if (sender->IsStopped()) { source->Safe_Delete(); return; } //Dynamic Leecher Protect - Bill Lee if ( source->IsBanned() ){ source->Safe_Delete(); return; } //Bill Lee end // Filter sources which are known to be dead/useless if ( theApp->clientlist->IsDeadSource( source ) || sender->IsDeadSource(source) ) { source->Safe_Delete(); return; } // Filter sources which are incompatible with our encryption setting (one requires it, and the other one doesn't supports it) if ( (source->RequiresCryptLayer() && (!thePrefs::IsClientCryptLayerSupported() || !source->HasValidHash())) || (thePrefs::IsClientCryptLayerRequired() && (!source->SupportsCryptLayer() || !source->HasValidHash()))) { source->Safe_Delete(); return; } // Find all clients with the same hash if ( source->HasValidHash() ) { CClientList::SourceList found = theApp->clientlist->GetClientsByHash( source->GetUserHash() ); CClientList::SourceList::iterator it = found.begin(); for ( ; it != found.end(); it++ ) { CKnownFile* file = it->GetRequestFile(); // Only check files on the download-queue if ( file ) { // Is the found source queued for something else? if ( file != sender ) { // Try to add a request for the other file if ( it->GetClient()->AddRequestForAnotherFile(sender)) { // Add it to downloadlistctrl Notify_SourceCtrlAddSource(sender, *it, A4AF_SOURCE); } } source->Safe_Delete(); return; } } } // Our new source is real new but maybe it is already uploading to us? // If yes the known client will be attached to the var "source" and the old // source-client will be deleted. However, if the request file of the known // source is NULL, then we have to treat it almost like a new source and if // it isn't NULL and not "sender", then we shouldn't move it, but rather add // a request for the new file. ESourceFrom nSourceFrom = source->GetSourceFrom(); if ( theApp->clientlist->AttachToAlreadyKnown(&source, 0) ) { // Already queued for another file? if ( source->GetRequestFile() ) { // If we're already queued for the right file, then there's nothing to do if ( sender != source->GetRequestFile() ) { // Add the new file to the request list source->AddRequestForAnotherFile( sender ); } } else { // Source was known, but reqfile NULL. source->SetRequestFile( sender ); source->SetSourceFrom(nSourceFrom); sender->AddSource( source ); if ( source->GetFileRating() || !source->GetFileComment().IsEmpty() ) { sender->UpdateFileRatingCommentAvail(); } Notify_SourceCtrlAddSource(sender, CCLIENTREF(source, wxT("CDownloadQueue::CheckAndAddSource Notify_SourceCtrlAddSource 1")), UNAVAILABLE_SOURCE); } } else { // Unknown client, add it to the clients list source->SetRequestFile( sender ); theApp->clientlist->AddClient(source); sender->AddSource( source ); if ( source->GetFileRating() || !source->GetFileComment().IsEmpty() ) { sender->UpdateFileRatingCommentAvail(); } Notify_SourceCtrlAddSource(sender, CCLIENTREF(source, wxT("CDownloadQueue::CheckAndAddSource Notify_SourceCtrlAddSource 2")), UNAVAILABLE_SOURCE); } }
void CUploadQueue::AddClientToQueue(CUpDownClient* client) { if (theApp->serverconnect->IsConnected() && theApp->serverconnect->IsLowID() && !theApp->serverconnect->IsLocalServer(client->GetServerIP(),client->GetServerPort()) && client->GetDownloadState() == DS_NONE && !client->IsFriend() && theStats::GetWaitingUserCount() > 50) { // Well, all that issues finish in the same: don't allow to add to the queue return; } if ( client->IsBanned() ) { return; } client->AddAskedCount(); client->SetLastUpRequest(); // Find all clients with the same user-hash CClientList::SourceList found = theApp->clientlist->GetClientsByHash( client->GetUserHash() ); CClientList::SourceList::iterator it = found.begin(); while (it != found.end()) { CUpDownClient* cur_client = *it++; if ( IsOnUploadQueue( cur_client ) ) { if ( cur_client == client ) { // This is where LowID clients get their upload slot assigned. // They can't be contacted if they reach top of the queue, so they are just marked for uploading. // When they reconnect next time AddClientToQueue() is called, and they get their slot // through the connection they initiated. // Since at that time no slot is free they get assigned an extra slot, // so then the number of slots exceeds the configured number by one. // To prevent a further increase no more LowID clients get a slot, until // - a HighID client has got one (which happens only after two clients // have been kicked so a slot is free again) // - or there is a free slot, which means there is no HighID client on queue if (client->m_bAddNextConnect) { uint16 maxSlots = GetMaxSlots(); if (lastupslotHighID) { maxSlots++; } if (m_uploadinglist.size() < maxSlots) { client->m_bAddNextConnect = false; RemoveFromWaitingQueue(client); AddUpNextClient(client); lastupslotHighID = false; // LowID alternate return; } } client->SendRankingInfo(); Notify_QlistRefreshClient(client); return; } else { // Hash-clash, remove unidentified clients (possibly both) if ( !cur_client->IsIdentified() ) { // Cur_client isn't identifed, remove it theApp->clientlist->AddTrackClient( cur_client ); RemoveFromWaitingQueue( cur_client ); if ( !cur_client->GetSocket() ) { if (cur_client->Disconnected( wxT("AddClientToQueue - same userhash") ) ) { cur_client->Safe_Delete(); } } } if ( !client->IsIdentified() ) { // New client isn't identified, remove it theApp->clientlist->AddTrackClient( client ); if ( !client->GetSocket() ) { if ( client->Disconnected( wxT("AddClientToQueue - same userhash") ) ) { client->Safe_Delete(); } } return; } } } } // Count the number of clients with the same IP-address found = theApp->clientlist->GetClientsByIP( client->GetIP() ); int ipCount = 0; for ( it = found.begin(); it != found.end(); it++ ) { if ( ( *it == client ) || IsOnUploadQueue( *it ) ) { ipCount++; } } // We do not accept more than 3 clients from the same IP if ( ipCount > 3 ) { return; } else if ( theApp->clientlist->GetClientsFromIP(client->GetIP()) >= 3 ) { return; } // statistic values CKnownFile* reqfile = (CKnownFile*) client->GetUploadFile(); if (reqfile) { reqfile->statistic.AddRequest(); } // TODO find better ways to cap the list if (m_waitinglist.size() >= (thePrefs::GetQueueSize())) { return; } if (client->IsDownloading()) { // he's already downloading and wants probably only another file CPacket* packet = new CPacket(OP_ACCEPTUPLOADREQ, 0, OP_EDONKEYPROT); theStats::AddUpOverheadFileRequest(packet->GetPacketSize()); AddDebugLogLineM( false, logLocalClient, wxT("Local Client: OP_ACCEPTUPLOADREQ to ") + client->GetFullIP() ); client->SendPacket(packet,true); return; } uint32 tick = GetTickCount(); client->ClearWaitStartTime(); // if possible start upload right away if (m_waitinglist.empty() && tick - m_nLastStartUpload >= 1000 && m_uploadinglist.size() < GetMaxSlots()) { AddUpNextClient(client); m_nLastStartUpload = tick; } else { m_waitinglist.push_back(client); theStats::AddWaitingClient(); client->ClearAskedCount(); client->SetUploadState(US_ONUPLOADQUEUE); client->SendRankingInfo(); Notify_QlistAddClient(client); Notify_ShowQueueCount(m_waitinglist.size()); } }