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

📄 tracker_manager.cc

📁 LibTorrent is a BitTorrent library written in C++ for *nix, with a focus on high performance and goo
💻 CC
字号:
// libTorrent - BitTorrent library// Copyright (C) 2005-2006, Jari Sundell//// This program is free software; you can redistribute it and/or modify// it under the terms of the GNU General Public License as published by// the Free Software Foundation; either version 2 of the License, or// (at your option) any later version.// // This program is distributed in the hope that it will be useful,// but WITHOUT ANY WARRANTY; without even the implied warranty of// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the// GNU General Public License for more details.// // You should have received a copy of the GNU General Public License// along with this program; if not, write to the Free Software// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA//// In addition, as a special exception, the copyright holders give// permission to link the code of portions of this program with the// OpenSSL library under certain conditions as described in each// individual source file, and distribute linked combinations// including the two.//// You must obey the GNU General Public License in all respects for// all of the code used other than OpenSSL.  If you modify file(s)// with this exception, you may extend this exception to your version// of the file(s), but you are not obligated to do so.  If you do not// wish to do so, delete this exception statement from your version.// If you delete this exception statement from all source files in the// program, then also delete it here.//// Contact:  Jari Sundell <jaris@ifi.uio.no>////           Skomakerveien 33//           3185 Skoppum, NORWAY#include "config.h"#include "torrent/exceptions.h"#include "tracker_control.h"#include "tracker_manager.h"namespace torrent {TrackerManager::TrackerManager() :  m_control(new TrackerControl),  m_active(false),  m_isRequesting(false),  m_numRequests(0),  m_maxRequests(3),  m_failedRequests(0),  m_initialTracker(0) {  m_control->slot_success(rak::make_mem_fun(this, &TrackerManager::receive_success));  m_control->slot_failed(rak::make_mem_fun(this, &TrackerManager::receive_failed));  m_taskTimeout.set_slot(rak::mem_fn(this, &TrackerManager::receive_timeout));}TrackerManager::~TrackerManager() {  if (is_active())    throw internal_error("TrackerManager::~TrackerManager() called but is_active() != false.");  delete m_control;}boolTrackerManager::is_busy() const {  return m_control->is_busy();}voidTrackerManager::close() {  m_isRequesting = false;  m_failedRequests = 0;  m_control->close();  priority_queue_erase(&taskScheduler, &m_taskTimeout);}voidTrackerManager::send_start() {  close();  m_control->set_focus_index(0);  m_control->send_state(DownloadInfo::STARTED);}voidTrackerManager::send_stop() {  close();  m_control->set_focus_index(m_initialTracker);  m_control->send_state(DownloadInfo::STOPPED);}voidTrackerManager::send_completed() {  close();  m_control->send_state(DownloadInfo::COMPLETED);}// When request_{current,next} is called, m_isRequesting is set to// true. This ensures that if none of the remaining trackers can be// reached or if a connection is successfull, it will not reset the// focus to the first tracker.//// The client can therefor call these functions after// TrackerControl::signal_success is emited and know it won't cause// looping if there are unreachable trackers.//// When the number of consequtive requests from the same tracker// through this function has reached a certain limit, it will stop the// request. 'm_maxRequests' thus makes sure that a client with a very// high "min peers" setting will not cause too much traffic.boolTrackerManager::request_current() {  if (m_control->is_busy() || m_numRequests >= m_maxRequests)    return false;  // Keep track of how many times we've requested from the current  // tracker without waiting for some minimum interval.  m_isRequesting = true;  manual_request(true);  return true;}voidTrackerManager::request_next() {  // Check next against last successfull connection?  if (m_control->is_busy() || !m_control->focus_next_group())    return;  m_isRequesting = true;  m_numRequests  = 0;  manual_request(true);}// Manual requests do not change the status of m_isRequesting, so if// it is trying to retrive more peers only the current timeout will be// affected.voidTrackerManager::manual_request(bool force) {  if (!m_taskTimeout.is_queued())    return;  rak::timer t(cachedTime + rak::timer::from_seconds(2));    if (!force)    t = std::max(t, m_control->time_last_connection() + rak::timer::from_seconds(m_control->get_min_interval()));  priority_queue_erase(&taskScheduler, &m_taskTimeout);  priority_queue_insert(&taskScheduler, &m_taskTimeout, t.round_seconds());}voidTrackerManager::cycle_group(int group) {  m_control->cycle_group(group);}voidTrackerManager::randomize() {  m_control->get_list().randomize();}TrackerManager::size_typeTrackerManager::size() const {  return m_control->get_list().size();}TrackerManager::size_typeTrackerManager::group_size() const {  if (m_control->get_list().rbegin() == m_control->get_list().rend())    return 0;  else    return m_control->get_list().rbegin()->first + 1;}TrackerManager::value_typeTrackerManager::get(size_type idx) const {  return m_control->get_list()[idx];}TrackerManager::size_typeTrackerManager::focus_index() const {  return m_control->focus_index();}voidTrackerManager::insert(int group, const std::string& url) {  // Consider borking m_initialTracker.  m_control->insert(group, url);}DownloadInfo*TrackerManager::info() {  return m_control->info();}const DownloadInfo*TrackerManager::info() const {  return m_control->info();}voidTrackerManager::set_info(DownloadInfo* info) {  m_control->set_info(info);}voidTrackerManager::receive_timeout() {  if (m_control->is_busy())    throw internal_error("TrackerManager::receive_timeout() called but m_control->is_busy() == true.");  if (!m_active)    return;  m_control->send_state(m_control->get_state());}voidTrackerManager::receive_success(AddressList* l) {  m_failedRequests = 0;  if (m_control->get_state() == DownloadInfo::STOPPED || !m_active) {    m_slotSuccess(l);    return;  }  if (m_control->get_state() == DownloadInfo::STARTED)    m_initialTracker = m_control->focus_index();  // Don't reset the focus when we're requesting more peers. If we  // want to query the next tracker in the list we need to remember  // the current focus.  if (m_isRequesting) {    m_numRequests++;  } else {    m_numRequests = 1;    m_control->set_focus_index(0);  }  // Reset m_isRequesting so a new call to request_*() is needed to  // try from the rest of the trackers in the list. If not called, the  // next tracker request will reset the focus to the first tracker.  m_isRequesting = false;  m_control->set_state(DownloadInfo::NONE);  priority_queue_insert(&taskScheduler, &m_taskTimeout, (cachedTime + rak::timer::from_seconds(m_control->get_normal_interval())).round_seconds());  m_slotSuccess(l);}voidTrackerManager::receive_failed(const std::string& msg) {  if (m_control->get_state() == DownloadInfo::STOPPED || !m_active) {    m_slotFailed(msg);    return;  }  if (m_isRequesting) {    // Currently trying to request additional peers.    if (m_control->focus_index() == m_control->get_list().size()) {      // Don't start from the beginning of the list if we've gone      // through the whole list. Return to normal timeout.      m_isRequesting = false;      priority_queue_insert(&taskScheduler, &m_taskTimeout, (cachedTime + rak::timer::from_seconds(m_control->get_normal_interval())).round_seconds());    } else {      priority_queue_insert(&taskScheduler, &m_taskTimeout, (cachedTime + rak::timer::from_seconds(20)).round_seconds());    }  } else {    // Normal retry.    if (m_control->focus_index() == m_control->get_list().size()) {      // Tried all the trackers, start from the beginning.      m_failedRequests++;      m_control->set_focus_index(0);    }        priority_queue_insert(&taskScheduler, &m_taskTimeout, (cachedTime + rak::timer::from_seconds(std::min<uint32_t>(600, 20 + 20 * m_failedRequests))).round_seconds());  }  m_slotFailed(msg);}}

⌨️ 快捷键说明

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