⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 peerlist.cpp

📁 cTorrent advanced 3.3.2。是对 CTorrent 的一个改进版本。这是目前的最新版。
💻 CPP
📖 第 1 页 / 共 4 页
字号:
    }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 + -