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

📄 peerlist.cpp

📁 最经典的bittorrent协议的实现的源码
💻 CPP
📖 第 1 页 / 共 3 页
字号:
        }        if( !Self.OntimeDL() && !Self.OntimeUL() ){          FD_CLR(sk,rfdnextp);          peer->CloseConnection();        }      }else if( FD_ISSET(sk,wfdp) ){        (*nready)--;         if( !Self.OntimeDL() && !Self.OntimeUL() ){          FD_CLR(sk,wfdnextp);          if( peer->Send_ShakeInfo() < 0 ){            if(arg_verbose) CONSOLE.Debug("close: Sending handshake");            peer->CloseConnection();          }else peer->SetStatus(P_HANDSHAKE);        }      }    }  }// end for  if( !m_ul_limited && !BandWidthLimitUp() ) m_missed_count++;}void PeerList::CloseAllConnectionToSeed(){  PEERNODE *p = m_head;  for( ; p; p = p->next ){    if( p->peer->bitfield.IsFull() ||        /* Drop peers who remain uninterested, but keep recent connections.           Peers who connected recently will resolve by bitfield exchange. */        (PEER_IS_SUCCESS(p->peer) && !p->peer->Is_Remote_Interested() &&          BTCONTENT.GetSeedTime() - now >= 300 &&          !p->peer->ConnectedWhileSeed()) ){      p->peer->DontWantAgain();      if(arg_verbose) CONSOLE.Debug("close: seed<->seed");      p->peer->CloseConnection();    }    else p->peer->stream.in_buffer.SetSize(BUF_DEF_SIZ);  }}int PeerList::UnChokeCheck(btPeer* peer, btPeer *peer_array[]){  int i = 0;  int cancel_idx = 0;  btPeer *loster = (btPeer*) 0;  int f_seed = BTCONTENT.Seeding();  int no_opt = 0;  unsigned long rndbits;  int r=0;  int retval = 0;  if(m_opt_timestamp) no_opt = 1;  if(f_seed) no_opt = 1 - no_opt;// Find my 3 or 4 fastest peers.// The m_max_unchoke+1 (4th) slot is for the optimistic unchoke when it happens.  // Find a slot for the candidate--the slowest peer, or an available slot.  for( cancel_idx = i = 0; i < m_max_unchoke + no_opt; i++ ){    if((btPeer*) 0 == peer_array[i] ||        PEER_IS_FAILED(peer_array[i]) ){	// 有空位      cancel_idx = i;       break;    }else{      if(cancel_idx == i) continue;      if(f_seed){        // compare time unchoked        if( (!peer_array[i]->Is_Local_UnChoked() &&            (peer_array[cancel_idx]->Is_Local_UnChoked() ||              peer_array[cancel_idx]->GetLastUnchokeTime() <                peer_array[i]->GetLastUnchokeTime())) ||            (peer_array[i]->Is_Local_UnChoked() &&             peer_array[cancel_idx]->Is_Local_UnChoked() &&             peer_array[i]->GetLastUnchokeTime() <               peer_array[cancel_idx]->GetLastUnchokeTime()) )          cancel_idx = i;      }else{        // compare download rate.        if( peer_array[cancel_idx]->RateDL() > peer_array[i]->RateDL()          //if equal, reciprocate to the peer we've sent less to, proportionally          ||(peer_array[cancel_idx]->RateDL() == peer_array[i]->RateDL()            && peer_array[cancel_idx]->TotalUL()                / (peer_array[cancel_idx]->TotalDL()+.001)              < peer_array[i]->TotalUL() / (peer_array[i]->TotalDL()+.001)) )          cancel_idx = i;      }    }  } // end for  if( (btPeer*) 0 != peer_array[cancel_idx] &&      PEER_IS_SUCCESS(peer_array[cancel_idx]) ){    if(f_seed){      if( (!peer_array[cancel_idx]->Is_Local_UnChoked() &&           (peer->Is_Local_UnChoked() ||             peer->GetLastUnchokeTime() <               peer_array[cancel_idx]->GetLastUnchokeTime())) ||           (peer_array[cancel_idx]->Is_Local_UnChoked() &&            peer->Is_Local_UnChoked() &&            peer_array[cancel_idx]->GetLastUnchokeTime() <              peer->GetLastUnchokeTime()) ){        loster = peer_array[cancel_idx];        peer_array[cancel_idx] = peer;      }else        loster = peer;    }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() const{  BitField tmpBitfield;  tmpBitfield = *BTCONTENT.pBF;  tmpBitfield.Invert();                       // what I don't have...  tmpBitfield.Except(BTCONTENT.GetFilter());  // ...that I want  if( tmpBitfield.Count() < m_peers_count ) return 1;  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() < m_peers_count ) return 1;  return 0;}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->Is_Local_Interested() ){      if(p->peer->PutPending() < 0 || p->peer->SetLocal(M_NOT_INTERESTED) < 0)        p->peer->CloseConnection();    }  }}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;  }}size_t PeerList::GetDownloads() const{  PEERNODE *p;  size_t count = 0;  for( p = m_head; p; p = p->next ){    if( PEER_IS_SUCCESS(p->peer) && p->peer->Is_Remote_UnChoked() ) count++;  }  return count;}int PeerList::BandWidthLimitUp(double when) const{  double nexttime;  if( cfg_max_bandwidth_up <= 0 ) return 0;  nexttime = Self.LastSendTime() +             (double)(Self.LastSizeSent()) / cfg_max_bandwidth_up;  if( nexttime >= now + 1 + when ) return 1;  else if( nexttime < now + when ) return 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 ) return 0;    else return 1;  }}int PeerList::BandWidthLimitDown(double when) const{  double nexttime;  // Don't check SeedOnly() here--need to let the input stream drain.  if( cfg_max_bandwidth_down <= 0 ) return 0;  nexttime = Self.LastRecvTime() +             (double)(Self.LastSizeRecv()) / cfg_max_bandwidth_down;  if( nexttime >= now + 1 + when ) return 1;  else if( nexttime < now + when ) return 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 ) return 0;    else return 1;  }}int PeerList::IsIdle() const{  return (    ( 0==cfg_max_bandwidth_down ||      now > (time_t)(Self.LastRecvTime() + Self.LateDL() +                     Self.LastSizeRecv() / (double)cfg_max_bandwidth_down) ||      BandWidthLimitDown(Self.LateDL()) )    &&    ( 0==cfg_max_bandwidth_up ||      now > (time_t)(Self.LastSendTime() + Self.LateUL() +                     Self.LastSizeSent() / (double)cfg_max_bandwidth_up) ||      BandWidthLimitUp(Self.LateUL()) )  );}// 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( nextwake > rightnow ){    maxwait = nextwake - rightnow - late;    if( maxwait < 0 ){      use_up = use_dn = 0;    }    Self.OntimeUL(use_up);    Self.OntimeDL(use_dn);  }else{    Self.OntimeUL(0);    Self.OntimeDL(0);  }  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();}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -