📄 peerlist.cpp
字号:
}else{ if( peer->RateDL() > peer_array[cancel_idx]->RateDL() // If equal, reciprocate to the peer we've sent less to, proportionally ||(peer_array[cancel_idx]->RateDL() == peer->RateDL() && peer_array[cancel_idx]->TotalUL() / (peer_array[cancel_idx]->TotalDL()+.001) > peer->TotalUL() / (peer->TotalDL()+.001)) ){ loster = peer_array[cancel_idx]; peer_array[cancel_idx] = peer; }else loster = peer; } // opt unchoke if( no_opt ){ if( loster->SetLocal(M_CHOKE) < 0 ){ loster->CloseConnection(); if( peer==loster ) retval = -1; } } else // The last slot is for the optimistic unchoke. if( (btPeer*) 0 == peer_array[m_max_unchoke] || PEER_IS_FAILED(peer_array[m_max_unchoke]) ) peer_array[m_max_unchoke] = loster; else { if( !r-- ){ rndbits = random(); r = 15; } // if loser is empty and current is not, loser gets 75% chance. if( loster->IsEmpty() && !peer_array[m_max_unchoke]->IsEmpty() && (rndbits>>=2)&3 ){ btPeer* tmp = peer_array[m_max_unchoke]; peer_array[m_max_unchoke] = loster; loster = tmp; } else // This mess chooses the loser: // if loser is choked and current is not // OR if both are choked and loser has waited longer // OR if both are unchoked and loser has had less time unchoked. if( (!loster->Is_Local_UnChoked() && ( peer_array[m_max_unchoke]->Is_Local_UnChoked() || loster->GetLastUnchokeTime() < peer_array[m_max_unchoke]->GetLastUnchokeTime() )) || (loster->Is_Local_UnChoked() && peer_array[m_max_unchoke]->Is_Local_UnChoked() && peer_array[m_max_unchoke]->GetLastUnchokeTime() < loster->GetLastUnchokeTime()) ){ // if current is empty and loser is not, loser gets 25% chance; // else loser wins. // transformed to: if loser is empty or current isn't, or 25% chance, // then loser wins. if( !peer_array[m_max_unchoke]->IsEmpty() || loster->IsEmpty() || !((rndbits>>=2)&3) ){ btPeer* tmp = peer_array[m_max_unchoke]; peer_array[m_max_unchoke] = loster; loster = tmp; } } if(loster->SetLocal(M_CHOKE) < 0){ loster->CloseConnection(); if( peer==loster ) retval = -1; } } }else //else if((btPeer*) 0 != peer_array[cancel_idx]..... peer_array[cancel_idx] = peer; return retval;}// When we change what we're going after, we need to evaluate & set our// interest with each peer appropriately.void PeerList::CheckInterest(){ PEERNODE *p = m_head; for( ; p; p = p->next ){ // Don't shortcut by checking Is_Local_Interested(), as we need to let // SetLocal() reset the m_standby flag. if( p->peer->Need_Remote_Data() ){ if( p->peer->SetLocal(M_INTERESTED) < 0 ) p->peer->CloseConnection(); }else{ if( p->peer->SetLocal(M_NOT_INTERESTED) < 0 ) p->peer->CloseConnection(); } }}btPeer* PeerList::GetNextPeer(btPeer *peer) const{ static PEERNODE *p = m_head; if( !peer ) p = m_head; else if( p && p->peer == peer ){ p = p->next; }else{ for( p=m_head; p && (p->peer != peer); p = p->next ); if(p) p = p->next; else p = m_head; } for( ; p; p = p->next ) if( p->peer && PEER_IS_SUCCESS(p->peer) ) break; if(p) return p->peer; else return (btPeer*) 0;}int PeerList::Endgame(){ BitField tmpBitfield; int endgame = 0; tmpBitfield = *BTCONTENT.pBF; tmpBitfield.Invert(); // what I don't have... tmpBitfield.Except(BTCONTENT.GetFilter()); // ...that I want if( tmpBitfield.Count() > 0 && tmpBitfield.Count() < m_peers_count - m_conn_count ) endgame = 1; else{ Pieces_I_Can_Get(&tmpBitfield); // what's available... tmpBitfield.Except(BTCONTENT.GetFilter()); // ...that I want... tmpBitfield.Except(*BTCONTENT.pBF); // ...that I don't have if( tmpBitfield.Count() > 0 && tmpBitfield.Count() < m_peers_count - m_conn_count) endgame = 1; } if( endgame && !m_endgame ){ if(arg_verbose) CONSOLE.Debug("Endgame (dup request) mode"); UnStandby(); }else if( !endgame && m_endgame ){ if(arg_verbose) CONSOLE.Debug("Normal (non dup request) mode"); RecalcDupReqs(); // failsafe } m_endgame = endgame; return endgame;}void PeerList::UnStandby(){ PEERNODE *p = m_head; for( ; p; p = p->next ){ if( PEER_IS_SUCCESS(p->peer) ) p->peer->UnStandby(); }}void PeerList::Pause(){ PEERNODE *p = m_head; m_f_pause = 1; StopDownload(); for( ; p; p = p->next ){ if( p->peer->Is_Local_UnChoked() && p->peer->SetLocal(M_CHOKE) < 0 ) p->peer->CloseConnection(); }}void PeerList::Resume(){ m_f_pause = 0; CheckInterest();}void PeerList::StopDownload(){ PEERNODE *p = m_head; for( ; p; p = p->next ){ if( p->peer->SetLocal(M_NOT_INTERESTED) < 0 ){ p->peer->CloseConnection(); }else p->peer->PutPending(); }}size_t PeerList::GetUnchoked() const{ PEERNODE *p; size_t count = 0; for( p = m_head; p; p = p->next ){ if( PEER_IS_SUCCESS(p->peer) && p->peer->Is_Local_UnChoked() ){ count++; if( count > m_max_unchoke ) break; } } return count;}// This function returns 0 if it could not find an upload faster than the// minimum and all peer upload rates are known (not zero).size_t PeerList::GetSlowestUp(size_t minimum) const{ PEERNODE *p; size_t slowest = 0, zero = 0, unchoked = 0, rate; for( p = m_head; p; p = p->next ){ if( PEER_IS_SUCCESS(p->peer) && p->peer->Is_Local_UnChoked() ){ unchoked++; rate = p->peer->RateUL(); if( 0==rate ) zero = 1; else if( rate >= minimum && (rate < slowest || 0==slowest) ) slowest = rate; } } if( slowest > (rate = Self.RateUL()) ) slowest = rate; // We're looking for slow, so guess low when we must guess a rate. if( slowest ){ if( zero ) return minimum ? minimum : ((slowest+1)/2); else return slowest; }else{ if( 0==unchoked ) unchoked = 1; // safeguard if( zero ) return minimum ? minimum : ((rate = Self.RateUL()) ? rate / unchoked : 1); else return 0; }}int PeerList::BandWidthLimitUp(double when){ return BandWidthLimitUp(when, cfg_max_bandwidth_up);}int PeerList::BandWidthLimitUp(double when, int limit){ int limited = 0; double nexttime; if( limit <= 0 ) return 0; nexttime = Self.LastSendTime() + (double)(Self.LastSizeSent()) / limit; if( nexttime >= now + 1 + when ) limited = 1; else if( nexttime < now + when ) limited = 0; else{ struct timespec nowspec; double rightnow; clock_gettime(CLOCK_REALTIME, &nowspec); rightnow = nowspec.tv_sec + (double)(nowspec.tv_nsec)/1000000000; if( nexttime <= rightnow + when ) limited = 0; else limited = 1; } if( limited ) m_f_ulate = 1; return limited;}int PeerList::BandWidthLimitDown(double when){ return BandWidthLimitDown(when, cfg_max_bandwidth_down);}int PeerList::BandWidthLimitDown(double when, int limit){ int limited = 0; double nexttime; // Don't check SeedOnly() here--need to let the input stream drain. if( limit <= 0 ) return 0; nexttime = Self.LastRecvTime() + (double)(Self.LastSizeRecv()) / limit; if( nexttime >= now + 1 + when ) limited = 1; else if( nexttime < now + when ) limited = 0; else{ struct timespec nowspec; double rightnow; clock_gettime(CLOCK_REALTIME, &nowspec); rightnow = nowspec.tv_sec + (double)(nowspec.tv_nsec)/1000000000; if( nexttime <= rightnow + when ) limited = 0; else limited = 1; } if( limited ) m_f_dlate = 1; return limited;}int PeerList::IsIdle(){ int idle = 0, dlate = 0, ulate = 0, slow = 0; if( ( (cfg_max_bandwidth_down > 0 && (dlate = (now > (time_t)(Self.LastRecvTime() + Self.LateDL() + Self.LastSizeRecv() / (double)cfg_max_bandwidth_down)))) || 0==Self.RateDL() || ((0==cfg_max_bandwidth_down || (slow = (Self.RateDL() < cfg_max_bandwidth_down / 2))) && BandWidthLimitDown(Self.LateDL(), (int)Self.RateDL() * 2)) || (!slow && BandWidthLimitDown(Self.LateDL())) ) && !(dlate && m_f_dlate) && ( (cfg_max_bandwidth_up > 0 && (ulate = (now > (time_t)(Self.LastSendTime() + Self.LateUL() + Self.LastSizeSent() / (double)cfg_max_bandwidth_up)))) || 0==Self.RateUL() || (slow = 0) || // re-initialization ((0==cfg_max_bandwidth_up || (slow = (Self.RateUL() < cfg_max_bandwidth_up / 2))) && BandWidthLimitUp(Self.LateUL(), (int)Self.RateUL() * 2)) || (!slow && BandWidthLimitUp(Self.LateUL())) ) ){ idle = 1; } if( !dlate ) m_f_dlate = 1; else if( m_f_dlate ) idle = 0; if( !ulate ) m_f_ulate = 1; else if( m_f_ulate ) idle = 0; return idle;}// How long must we wait for bandwidth to become available in either direction?double PeerList::WaitBW() const{ struct timespec nowspec; double rightnow, late; double maxwait = 0, nextwake = 0; double nextup = 0, nextdn = 0; int use_up = 0, use_dn = 0; if( cfg_max_bandwidth_up ){ nextup = Self.LastSendTime() + (double)(Self.LastSizeSent()) / cfg_max_bandwidth_up; } if( cfg_max_bandwidth_down ){ nextdn = Self.LastRecvTime() + (double)(Self.LastSizeRecv()) / cfg_max_bandwidth_down; } // could optimize away the clock call when maxwait will be > MAX_SLEEP if( now <= (time_t)nextup || now <= (time_t)nextdn ){ clock_gettime(CLOCK_REALTIME, &nowspec); rightnow = nowspec.tv_sec + (double)(nowspec.tv_nsec)/1000000000; }else rightnow = (double)now; if( nextup >= rightnow ){ if( nextdn < rightnow ) use_up = 1; else if( nextdn < nextup ) use_dn = 1; else use_up = 1; }else if( nextdn >= rightnow ) use_dn = 1; if( use_up ){ nextwake = nextup; late = Self.LateUL(); }else if( use_dn ){ nextwake = nextdn; late = Self.LateDL(); }else{ nextwake = late = 0; } if( (m_f_limitd && nextdn <= rightnow + Self.LateDL()) || (m_f_limitu && nextup <= rightnow + Self.LateUL()) ){ // socket setup is outdated; send a problem indicator value back Self.OntimeUL(0); Self.OntimeDL(0); maxwait = -100; }else if( nextwake > rightnow ){ maxwait = nextwake - rightnow - late; if( maxwait < 0 ){ use_up = use_dn = 0; } Self.OntimeUL(use_up); Self.OntimeDL(use_dn);// CONSOLE.Debug("waitbw %f at %f", maxwait, rightnow); }else{ Self.OntimeUL(0); Self.OntimeDL(0);// CONSOLE.Debug("nextwake %f at %f", nextwake, rightnow); } return maxwait;}void PeerList::UnchokeIfFree(btPeer *peer){ PEERNODE *p; size_t count = 0; if( m_f_pause ) return; for( p = m_head; p; p = p->next ){ if( PEER_IS_SUCCESS(p->peer) && p->peer->Is_Local_UnChoked() && p->peer->Is_Remote_Interested() ){ count++; if( m_max_unchoke < count ) return; } } if( peer->SetLocal(M_UNCHOKE) < 0 ) peer->CloseConnection();}void PeerList::AdjustPeersCount(){ Tracker.AdjustPeersCount();}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -