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

📄 peer_connection_base.cc

📁 LibTorrent is a BitTorrent library written in C++ for *nix, with a focus on high performance and goo
💻 CC
📖 第 1 页 / 共 2 页
字号:
// 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 <sstream>#include <rak/error_number.h>#include "torrent/exceptions.h"#include "torrent/block.h"#include "data/chunk_iterator.h"#include "data/chunk_list.h"#include "download/choke_manager.h"#include "download/chunk_selector.h"#include "download/chunk_statistics.h"#include "download/download_info.h"#include "download/download_main.h"#include "net/socket_base.h"#include "torrent/connection_manager.h"#include "torrent/peer_info.h"#include "peer_connection_base.h"#include "manager.h"namespace torrent {PeerConnectionBase::PeerConnectionBase() :  m_download(NULL),    m_down(new ProtocolRead()),  m_up(new ProtocolWrite()),  m_peerInfo(NULL),  m_downStall(0),  m_sendChoked(false),  m_sendInterested(false) {}PeerConnectionBase::~PeerConnectionBase() {  delete m_up;  delete m_down;}voidPeerConnectionBase::initialize(DownloadMain* download, PeerInfo* peerInfo, SocketFd fd, Bitfield* bitfield) {  if (get_fd().is_valid())    throw internal_error("Tried to re-set PeerConnection.");  if (!peerInfo->is_valid() || !fd.is_valid())    throw internal_error("PeerConnectionBase::set(...) received bad input.");  set_fd(fd);  m_peerInfo = peerInfo;  m_download = download;  m_peerChunks.set_peer_info(m_peerInfo);  m_peerChunks.bitfield()->swap(*bitfield);  m_peerChunks.upload_throttle()->set_list_iterator(m_download->upload_throttle()->end());  m_peerChunks.upload_throttle()->slot_activate(rak::make_mem_fun(this, &PeerConnectionBase::receive_throttle_up_activate));  m_peerChunks.download_throttle()->set_list_iterator(m_download->download_throttle()->end());  m_peerChunks.download_throttle()->slot_activate(rak::make_mem_fun(this, &PeerConnectionBase::receive_throttle_down_activate));  download_queue()->set_delegator(m_download->delegator());  download_queue()->set_peer_chunks(&m_peerChunks);  manager->poll()->open(this);  manager->poll()->insert_read(this);  manager->poll()->insert_write(this);  manager->poll()->insert_error(this);  m_timeLastRead = cachedTime;  m_download->chunk_statistics()->received_connect(&m_peerChunks);  // Hmm... cleanup?  update_interested();  initialize_custom();}voidPeerConnectionBase::cleanup() {  if (!get_fd().is_valid())    return;  if (m_download == NULL)    throw internal_error("PeerConnection::~PeerConnection() m_fd is valid but m_state and/or m_net is NULL");  m_downloadQueue.clear();  up_chunk_release();  down_chunk_release();  m_download->choke_manager()->disconnected(this);  m_download->chunk_statistics()->received_disconnect(&m_peerChunks);  manager->poll()->remove_read(this);  manager->poll()->remove_write(this);  manager->poll()->remove_error(this);  manager->poll()->close(this);    manager->connection_manager()->dec_socket_count();  get_fd().close();  get_fd().clear();  m_download->upload_throttle()->erase(m_peerChunks.upload_throttle());  m_download->download_throttle()->erase(m_peerChunks.download_throttle());  m_up->set_state(ProtocolWrite::INTERNAL_ERROR);  m_down->set_state(ProtocolRead::INTERNAL_ERROR);  m_download = NULL;}voidPeerConnectionBase::load_up_chunk() {  if (m_upChunk.is_valid() && m_upChunk.index() == m_upPiece.index()) {    // Better checking needed.    //     m_upChunk.chunk()->preload(m_upPiece.offset(), m_upChunk.chunk()->size());    return;  }  up_chunk_release();    m_upChunk = m_download->chunk_list()->get(m_upPiece.index(), false);    if (!m_upChunk.is_valid())    throw storage_error("File chunk read error: " + std::string(m_upChunk.error_number().c_str()));  // Make sure we preload the next step once we get past the length  // here. This is just some testing, don't include this with the  // release. (Yet)//   if (m_peerChunks.upload_throttle()->rate()->rate() >= 10 << 10)//     m_upChunk.chunk()->preload(m_upPiece.offset(), m_upChunk.chunk()->size());//   m_upChunk.chunk()->preload(m_upPiece.offset(), std::min(128u << 10, m_peerChunks.upload_throttle()->rate()->rate() * 10));}voidPeerConnectionBase::set_snubbed(bool v) {  if (v == m_peerChunks.is_snubbed())    return;  bool wasUploadWanted = is_upload_wanted();  m_peerChunks.set_snubbed(v);  if (v) {    if (wasUploadWanted)      m_download->choke_manager()->set_not_interested(this);  } else {    if (is_upload_wanted())      m_download->choke_manager()->set_interested(this);  }}voidPeerConnectionBase::receive_choke(bool v) {  if (v == m_up->choked())    throw internal_error("PeerConnectionBase::receive_choke(...) already set to the same state.");  write_insert_poll_safe();  m_sendChoked = true;  m_up->set_choked(v);  m_timeLastChoked = cachedTime;}voidPeerConnectionBase::receive_throttle_down_activate() {  manager->poll()->insert_read(this);}voidPeerConnectionBase::receive_throttle_up_activate() {  manager->poll()->insert_write(this);}voidPeerConnectionBase::event_error() {  m_download->connection_list()->erase(this, 0);}boolPeerConnectionBase::down_chunk_start(const Piece& piece) {  if (!download_queue()->downloading(piece)) {    if (piece.length() == 0)      m_download->info()->signal_network_log().emit("Received piece with length zero.");    return false;  }  if (!m_download->content()->is_valid_piece(piece))    throw internal_error("Incoming pieces list contains a bad piece.");    if (!m_downChunk.is_valid() || piece.index() != m_downChunk.index()) {    down_chunk_release();    m_downChunk = m_download->chunk_list()->get(piece.index(), true);      if (!m_downChunk.is_valid())      throw storage_error("File chunk write error: " + std::string(m_downChunk.error_number().c_str()) + ".");  }  return m_downloadQueue.transfer()->is_leader();}voidPeerConnectionBase::down_chunk_finished() {  if (!download_queue()->transfer()->is_finished())    throw internal_error("PeerConnectionBase::down_chunk_finished() Transfer not finished.");  if (download_queue()->transfer()->is_leader()) {    if (!m_downChunk.is_valid())      throw internal_error("PeerConnectionBase::down_chunk_finished() Transfer is the leader, but no chunk allocated.");    download_queue()->finished();    m_downChunk.object()->set_time_modified(cachedTime);  } else {    download_queue()->skipped();  }          if (m_downStall > 0)    m_downStall--;          // TODO: clear m_down.data?  // TODO: remove throttle if choked? Rarely happens though.  write_insert_poll_safe();}boolPeerConnectionBase::down_chunk() {  if (!m_download->download_throttle()->is_throttled(m_peerChunks.download_throttle()))    throw internal_error("PeerConnectionBase::down_chunk() tried to read a piece but is not in throttle list");  if (!m_downChunk.chunk()->is_writable())    throw internal_error("PeerConnectionBase::down_part() chunk not writable, permission denided");  uint32_t quota = m_download->download_throttle()->node_quota(m_peerChunks.download_throttle());  if (quota == 0) {    manager->poll()->remove_read(this);    m_download->download_throttle()->node_deactivate(m_peerChunks.download_throttle());    return false;  }  uint32_t bytesTransfered = 0;  BlockTransfer* transfer = m_downloadQueue.transfer();  Chunk::data_type data;  ChunkIterator itr(m_downChunk.chunk(),                    transfer->piece().offset() + transfer->position(),                    transfer->piece().offset() + std::min(transfer->position() + quota, transfer->piece().length()));  do {    data = itr.data();    data.second = read_stream_throws(data.first, data.second);    bytesTransfered += data.second;  } while (itr.used(data.second));  transfer->adjust_position(bytesTransfered);

⌨️ 快捷键说明

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