📄 uploadqueue.cpp
字号:
bool CUploadQueue::AcceptNewClient(){
uint32 curUploadSlots = (uint32)uploadinglist.GetCount();
return AcceptNewClient(curUploadSlots);
}
bool CUploadQueue::AcceptNewClient(uint32 curUploadSlots){
// check if we can allow a new client to start downloading from us
if (curUploadSlots < MIN_UP_CLIENTS_ALLOWED)
return true;
uint16 MaxSpeed;
if (thePrefs.IsDynUpEnabled())
MaxSpeed = theApp.lastCommonRouteFinder->GetUpload()/1024;
else
MaxSpeed = thePrefs.GetMaxUpload();
if (thePrefs.GetUploadClients())
{
if (curUploadSlots < thePrefs.GetUploadClients())
return true;
else if (curUploadSlots >= thePrefs.GetUploadClients())
return false;
}
else if (curUploadSlots >= MAX_UP_CLIENTS_ALLOWED ||
curUploadSlots >= 4 &&
(
curUploadSlots >= (datarate/UPLOAD_CHECK_CLIENT_DR) ||
curUploadSlots >= ((uint32)MaxSpeed)*1024/UPLOAD_CLIENT_DATARATE ||
(
thePrefs.GetMaxUpload() == UNLIMITED &&
!thePrefs.IsDynUpEnabled() &&
thePrefs.GetMaxGraphUploadRate() > 0 &&
curUploadSlots >= ((uint32)thePrefs.GetMaxGraphUploadRate())*1024/UPLOAD_CLIENT_DATARATE
)
)
) // max number of clients to allow for all circumstances
return false;
return true;
}
bool CUploadQueue::ForceNewClient(bool allowEmptyWaitingQueue) {
if(!allowEmptyWaitingQueue && waitinglist.GetSize() <= 0)
return false;
if (::GetTickCount() - m_nLastStartUpload < 1000 && datarate < 102400 )
return false;
uint32 curUploadSlots = (uint32)uploadinglist.GetCount();
if (curUploadSlots < MIN_UP_CLIENTS_ALLOWED)
return true;
if(!AcceptNewClient(curUploadSlots) || !theApp.lastCommonRouteFinder->AcceptNewClient()) { // UploadSpeedSense can veto a new slot if USS enabled
return false;
}
uint16 MaxSpeed;
if (thePrefs.IsDynUpEnabled())
MaxSpeed = theApp.lastCommonRouteFinder->GetUpload()/1024;
else
MaxSpeed = thePrefs.GetMaxUpload();
uint32 upPerClient = UPLOAD_CLIENT_DATARATE;
// if throttler doesn't require another slot, go with a slightly more restrictive method
if( MaxSpeed > 20 || MaxSpeed == UNLIMITED)
upPerClient += datarate/43;
if( upPerClient > 7680 )
upPerClient = 7680;
//now the final check
if ( MaxSpeed == UNLIMITED )
{
if (curUploadSlots < (datarate/upPerClient))
return true;
}
else{
uint16 nMaxSlots;
if (MaxSpeed > 12)
nMaxSlots = (uint16)(((float)(MaxSpeed*1024)) / upPerClient);
else if (MaxSpeed > 7)
nMaxSlots = MIN_UP_CLIENTS_ALLOWED + 2;
else if (MaxSpeed > 3)
nMaxSlots = MIN_UP_CLIENTS_ALLOWED + 1;
else
nMaxSlots = MIN_UP_CLIENTS_ALLOWED;
// AddLogLine(true,"maxslots=%u, upPerClient=%u, datarateslot=%u|%u|%u",nMaxSlots,upPerClient,datarate/UPLOAD_CHECK_CLIENT_DR, datarate, UPLOAD_CHECK_CLIENT_DR);
if ( curUploadSlots < nMaxSlots )
{
return true;
}
}
if(m_iHighestNumberOfFullyActivatedSlotsSinceLastCall > (uint32)uploadinglist.GetSize()) {
// uploadThrottler requests another slot. If throttler says it needs another slot, we will allow more slots
// than what we require ourself. Never allow more slots than to give each slot high enough average transfer speed, though (checked above).
if(thePrefs.GetLogUlDlEvents() && waitinglist.GetSize() > 0)
AddDebugLogLine(false, _T("UploadQueue: Added new slot since throttler needs it. m_iHighestNumberOfFullyActivatedSlotsSinceLastCall: %i uploadinglist.GetSize(): %i tick: %i"), m_iHighestNumberOfFullyActivatedSlotsSinceLastCall, uploadinglist.GetSize(), ::GetTickCount());
return true;
}
//nope
return false;
}
CUploadQueue::~CUploadQueue(){
if (h_timer)
KillTimer(0,h_timer);
}
CUpDownClient* CUploadQueue::GetWaitingClientByIP_UDP(uint32 dwIP, uint16 nUDPPort){
for (POSITION pos = waitinglist.GetHeadPosition();pos != 0;){
CUpDownClient* cur_client = waitinglist.GetNext(pos);
if (dwIP == cur_client->GetIP() && nUDPPort == cur_client->GetUDPPort())
return cur_client;
}
return 0;
}
CUpDownClient* CUploadQueue::GetWaitingClientByIP(uint32 dwIP){
for (POSITION pos = waitinglist.GetHeadPosition();pos != 0;){
CUpDownClient* cur_client = waitinglist.GetNext(pos);
if (dwIP == cur_client->GetIP())
return cur_client;
}
return 0;
}
/**
* Add a client to the waiting queue for uploads.
*
* @param client address of the client that should be added to the waiting queue
*
* @param bIgnoreTimelimit don't check timelimit to possibly ban the client.
*/
void CUploadQueue::AddClientToQueue(CUpDownClient* client, bool bIgnoreTimelimit)
{
if (theApp.serverconnect->IsConnected() && theApp.serverconnect->IsLowID() //This may need to be changed with the Kad now being used.
&& !theApp.serverconnect->IsLocalServer(client->GetServerIP(),client->GetServerPort())
&& client->GetDownloadState() == DS_NONE && !client->IsFriend()
&& GetWaitingUserCount() > 50)
return;
client->AddAskedCount();
client->SetLastUpRequest();
if (!bIgnoreTimelimit)
{
client->AddRequestCount(client->GetUploadFileID());
}
if (client->IsBanned())
return;
uint16 cSameIP = 0;
// check for double
POSITION pos1, pos2;
for (pos1 = waitinglist.GetHeadPosition();( pos2 = pos1 ) != NULL;)
{
waitinglist.GetNext(pos1);
CUpDownClient* cur_client= waitinglist.GetAt(pos2);
if (cur_client == client)
{
//already on queue
// VQB LowID Slot Patch -- note: should add limit so only if #slots < UL -or- UL+1 for Low UL (?)
if (client->HasLowID() &&
client->m_bAddNextConnect && AcceptNewClient())
{
if (lastupslotHighID)
{
if(thePrefs.GetLogUlDlEvents())
AddDebugLogLine(true, _T("Adding ****lowid when reconneting. Client: %s"), client->DbgGetClientInfo());
client->m_bAddNextConnect = false;
RemoveFromWaitingQueue(client, true);
AddUpNextClient(client);
lastupslotHighID = false; // LowID alternate
return;
}
}
// VQB end
client->SendRankingInfo();
theApp.emuledlg->transferwnd->queuelistctrl.RefreshClient(client);
return;
}
else if ( client->Compare(cur_client) )
{
theApp.clientlist->AddTrackClient(client); // in any case keep track of this client
// another client with same ip:port or hash
// this happens only in rare cases, because same userhash / ip:ports are assigned to the right client on connecting in most cases
if (cur_client->credits != NULL && cur_client->credits->GetCurrentIdentState(cur_client->GetIP()) == IS_IDENTIFIED)
{
//cur_client has a valid secure hash, don't remove him
if (thePrefs.GetVerbose())
AddDebugLogLine(false,CString(GetResString(IDS_SAMEUSERHASH)),client->GetUserName(),cur_client->GetUserName(),client->GetUserName() );
return;
}
if (client->credits != NULL && client->credits->GetCurrentIdentState(client->GetIP()) == IS_IDENTIFIED)
{
//client has a valid secure hash, add him remove other one
if (thePrefs.GetVerbose())
AddDebugLogLine(false,CString(GetResString(IDS_SAMEUSERHASH)),client->GetUserName(),cur_client->GetUserName(),cur_client->GetUserName() );
RemoveFromWaitingQueue(pos2,true);
if (!cur_client->socket)
{
if(cur_client->Disconnected(_T("AddClientToQueue - same userhash 1")))
{
delete cur_client;
}
}
}
else
{
// remove both since we dont know who the bad on is
if (thePrefs.GetVerbose())
AddDebugLogLine(false,CString(GetResString(IDS_SAMEUSERHASH)),client->GetUserName(),cur_client->GetUserName(),"Both" );
RemoveFromWaitingQueue(pos2,true);
if (!cur_client->socket)
{
if(cur_client->Disconnected(_T("AddClientToQueue - same userhash 2")))
{
delete cur_client;
}
}
return;
}
}
else if (client->GetIP() == cur_client->GetIP())
{
// same IP, different port, different userhash
cSameIP++;
}
}
if (cSameIP >= 3)
{
// do not accept more than 3 clients from the same IP
if (thePrefs.GetVerbose())
DEBUG_ONLY( AddDebugLogLine(false,_T("%s's (%s) request to enter the queue was rejected, because of too many clients with the same IP"), client->GetUserName(), ipstr(client->GetConnectIP())) );
return;
}
else if (theApp.clientlist->GetClientsFromIP(client->GetIP()) >= 3)
{
if (thePrefs.GetVerbose())
DEBUG_ONLY( AddDebugLogLine(false,_T("%s's (%s) request to enter the queue was rejected, because of too many clients with the same IP (found in TrackedClientsList)"), client->GetUserName(), ipstr(client->GetConnectIP())) );
return;
}
// done
// Add clients server to list.
if (thePrefs.AddServersFromClient() && client->GetServerIP() && client->GetServerPort())
{
CServer* srv = new CServer(client->GetServerPort(), ipstr(client->GetServerIP()));
srv->SetListName(srv->GetAddress());
if (!theApp.emuledlg->serverwnd->serverlistctrl.AddServer(srv, true))
delete srv;
}
// statistic values
CKnownFile* reqfile = theApp.sharedfiles->GetFileByID((uchar*)client->GetUploadFileID());
if (reqfile)
reqfile->statistic.AddRequest();
// cap the list
// the queue limit in prefs is only a soft limit. Hard limit is 25% higher, to let in powershare clients and other
// high ranking clients after soft limit has been reached
uint32 softQueueLimit = thePrefs.GetQueueSize();
uint32 hardQueueLimit = thePrefs.GetQueueSize() + max(thePrefs.GetQueueSize()/4, 200);
// if soft queue limit has been reached, only let in high ranking clients
if ((uint32)waitinglist.GetCount() >= hardQueueLimit ||
(uint32)waitinglist.GetCount() >= softQueueLimit && // soft queue limit is reached
(client->IsFriend() && client->GetFriendSlot()) == false && // client is not a friend with friend slot
client->GetCombinedFilePrioAndCredit() < GetAverageCombinedFilePrioAndCredit()) { // and client has lower credits/wants lower prio file than average client in queue
// then block client from getting on queue
return;
}
if (client->IsDownloading())
{
// he's already downloading and wants probably only another file
if (thePrefs.GetDebugClientTCPLevel() > 0)
DebugSend("OP__AcceptUploadReq", client);
Packet* packet = new Packet(OP_ACCEPTUPLOADREQ,0);
theStats.AddUpDataOverheadFileRequest(packet->size);
client->socket->SendPacket(packet,true);
return;
}
if (waitinglist.IsEmpty() && AcceptNewClient())
{
AddUpNextClient(client);
}
else
{
waitinglist.AddTail(client);
client->SetUploadState(US_ONUPLOADQUEUE);
theApp.emuledlg->transferwnd->queuelistctrl.AddClient(client,true);
theApp.emuledlg->transferwnd->ShowQueueCount(waitinglist.GetCount());
client->SendRankingInfo();
}
}
float CUploadQueue::GetAverageCombinedFilePrioAndCredit() {
DWORD curTick = ::GetTickCount();
if (curTick - m_dwLastCalculatedAverageCombinedFilePrioAndCredit > 5*1000) {
m_dwLastCalculatedAverageCombinedFilePrioAndCredit = curTick;
POSITION pos1, pos2;
// TODO: is there a risk of overflow? I don't think so...
double sum = 0;
for (pos1 = waitinglist.GetHeadPosition();( pos2 = pos1 ) != NULL;){
waitinglist.GetNext(pos1);
CUpDownClient* cur_client = waitinglist.GetAt(pos2);
sum += cur_client->GetCombinedFilePrioAndCredit();
}
m_fAverageCombinedFilePrioAndCredit = sum/waitinglist.GetSize();
}
return m_fAverageCombinedFilePrioAndCredit;
}
bool CUploadQueue::RemoveFromUploadQueue(CUpDownClient* client, LPCTSTR pszReason, bool updatewindow, bool earlyabort){
bool result = false;
uint32 slotCounter = 1;
for (POSITION pos = uploadinglist.GetHeadPosition();pos != 0;){
POSITION curPos = pos;
CUpDownClient* curClient = uploadinglist.GetNext(pos);
if (client == curClient){
if (updatewindow)
theApp.emuledlg->transferwnd->uploadlistctrl.RemoveClient(client);
if (thePrefs.GetLogUlDlEvents())
AddDebugLogLine(DLP_VERYLOW, true,_T("---- %s: Removing client from upload list. Reason: %s ----"), client->DbgGetClientInfo(), pszReason==NULL ? _T("") : pszReason);
client->m_bAddNextConnect = false;
uploadinglist.RemoveAt(curPos);
bool removed = theApp.uploadBandwidthThrottler->RemoveFromStandardList(client->socket);
bool pcRemoved = theApp.uploadBandwidthThrottler->RemoveFromStandardList((CClientReqSocket*)client->m_pPCUpSocket);
//if(thePrefs.GetLogUlDlEvents() && !(removed || pcRemoved)) {
// AddDebugLogLine(false, _T("UploadQueue: Didn't find socket to delete. Adress: 0x%x"), client->socket);
//}
if(client->GetSessionUp() > 0) {
++successfullupcount;
totaluploadtime += client->GetUpStartTimeDelay()/1000;
} else if(earlyabort == false)
++failedupcount;
CKnownFile* requestedFile = theApp.sharedfiles->GetFileByID(client->GetUploadFileID());
if(requestedFile != NULL) {
requestedFile->UpdatePartsInfo();
}
theApp.clientlist->AddTrackClient(client); // Keep track of this client
client->SetUploadState(US_NONE);
client->ClearUploadBlockRequests();
m_iHighestNumberOfFullyActivatedSlotsSinceLastCall = 0;
result = true;
} else {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -