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

📄 peer_connection_leech.cc

📁 LibTorrent is a BitTorrent library written in C++ for *nix, with a focus on high performance and goo
💻 CC
📖 第 1 页 / 共 2 页
字号:
  // beginning of the buffer. Or do we use position? Propably best,  // therefor ProtocolBuffer::position() points to the beginning of  // the unused data.  try {        // Normal read.    //    // We rarely will read zero bytes as the read of 64 bytes will    // almost always either not fill up or it will require additional    // reads.    //    // Only loop when end hits 64.    do {      switch (m_down->get_state()) {      case ProtocolRead::IDLE:        if (m_down->buffer()->size_end() == read_size)          throw internal_error("PeerConnectionLeech::event_read() m_down->buffer()->size_end() == read_size.");        m_down->buffer()->move_end(read_stream_throws(m_down->buffer()->end(), read_size - m_down->buffer()->size_end()));                while (read_message());                if (m_down->buffer()->size_end() == read_size) {          read_buffer_move_unused();          break;        } else {          read_buffer_move_unused();          return;        }      case ProtocolRead::READ_PIECE:        if (!download_queue()->is_downloading())          throw internal_error("ProtocolRead::READ_PIECE state but RequestList is not downloading");        if (!m_downloadQueue.transfer()->is_valid() || !m_downloadQueue.transfer()->is_leader()) {          m_down->set_state(ProtocolRead::READ_SKIP_PIECE);          break;        }        if (!down_chunk())          return;        m_tryRequest = true;        m_down->set_state(ProtocolRead::IDLE);        down_chunk_finished();        break;      case ProtocolRead::READ_SKIP_PIECE:        if (download_queue()->transfer()->is_leader()) {          m_down->set_state(ProtocolRead::READ_PIECE);          m_download->download_throttle()->insert(m_peerChunks.download_throttle());          break;        }        if (!down_chunk_skip())          return;        m_tryRequest = true;        m_down->set_state(ProtocolRead::IDLE);        down_chunk_finished();        break;      default:        throw internal_error("PeerConnectionLeech::event_read() wrong state.");      }      // Figure out how to get rid of the shouldLoop boolean.    } while (true);  // Exception handlers:  } catch (close_connection& e) {    m_download->connection_list()->erase(this, 0);  } catch (blocked_connection& e) {    m_download->info()->signal_network_log().emit("Momentarily blocked read connection.");    m_download->connection_list()->erase(this, 0);  } catch (network_error& e) {    m_download->info()->signal_network_log().emit(e.what());    m_download->connection_list()->erase(this, 0);  } catch (storage_error& e) {    m_download->info()->signal_storage_error().emit(e.what());    m_download->connection_list()->erase(this, 0);  } catch (base_error& e) {    std::stringstream s;    s << "Connection read fd(" << get_fd().get_fd() << ',' << m_down->get_state() << ',' << m_down->last_command() << ") \"" << e.what() << '"';    e.set(s.str());    throw;  }}inline voidPeerConnectionLeech::fill_write_buffer() {  // No need to use delayed choke as we are a leecher.  if (m_sendChoked && m_up->can_write_choke()) {    m_sendChoked = false;    m_up->write_choke(m_up->choked());    if (m_up->choked()) {      m_download->upload_throttle()->erase(m_peerChunks.upload_throttle());      up_chunk_release();      m_peerChunks.upload_queue()->clear();    } else {      m_download->upload_throttle()->insert(m_peerChunks.upload_throttle());    }  }  // Send the interested state before any requests as some clients,  // e.g. BitTornado 0.7.14 and uTorrent 0.3.0, disconnect if a  // request has been received while uninterested. The problem arises  // as they send unchoke before receiving interested.  if (m_sendInterested && m_up->can_write_interested()) {    m_up->write_interested(m_up->interested());    m_sendInterested = false;  }  if (m_tryRequest &&      !(m_tryRequest = !should_request()) &&      !(m_tryRequest = try_request_pieces()) &&      !download_queue()->is_interested_in_active()) {    m_sendInterested = true;    m_up->set_interested(false);  }  while (!m_peerChunks.have_queue()->empty() && m_up->can_write_have()) {    m_up->write_have(m_peerChunks.have_queue()->front());    m_peerChunks.have_queue()->pop_front();  }  if (!m_up->choked() &&      !m_peerChunks.upload_queue()->empty() &&      m_up->can_write_piece())    write_prepare_piece();}voidPeerConnectionLeech::event_write() {  try {      do {      switch (m_up->get_state()) {      case ProtocolWrite::IDLE:        // We might have buffered keepalive message or similar, but        // 'end' should remain at the start of the buffer.        if (m_up->buffer()->size_end() != 0)          throw internal_error("PeerConnectionLeech::event_write() ProtocolWrite::IDLE in a wrong state.");        // Fill up buffer.        fill_write_buffer();        if (m_up->buffer()->size_position() == 0) {          manager->poll()->remove_write(this);          return;        }        m_up->set_state(ProtocolWrite::MSG);        m_up->buffer()->prepare_end();      case ProtocolWrite::MSG:        m_up->buffer()->move_position(write_stream_throws(m_up->buffer()->position(), m_up->buffer()->remaining()));        if (m_up->buffer()->remaining())          return;        m_up->buffer()->reset();        if (m_up->last_command() != ProtocolBase::PIECE) {          // Break or loop? Might do an ifelse based on size of the          // write buffer. Also the write buffer is relatively large.          m_up->set_state(ProtocolWrite::IDLE);          break;        }        // We're uploading a piece.        load_up_chunk();        m_up->set_state(ProtocolWrite::WRITE_PIECE);      case ProtocolWrite::WRITE_PIECE:        if (!up_chunk())          return;        m_up->set_state(ProtocolWrite::IDLE);        break;      default:        throw internal_error("PeerConnectionLeech::event_write() wrong state.");      }    } while (true);  } catch (close_connection& e) {    m_download->connection_list()->erase(this, 0);  } catch (blocked_connection& e) {    m_download->info()->signal_network_log().emit("Momentarily blocked write connection.");    m_download->connection_list()->erase(this, 0);  } catch (network_error& e) {    m_download->info()->signal_network_log().emit(e.what());    m_download->connection_list()->erase(this, 0);  } catch (storage_error& e) {    m_download->info()->signal_storage_error().emit(e.what());    m_download->connection_list()->erase(this, 0);  } catch (base_error& e) {    std::stringstream s;    s << "Connection write fd(" << get_fd().get_fd() << ',' << m_up->get_state() << ',' << m_up->last_command() << ") \"" << e.what() << '"';    e.set(s.str());    throw;  }}voidPeerConnectionLeech::read_have_chunk(uint32_t index) {  if (index >= m_peerChunks.bitfield()->size_bits())    throw network_error("Peer sent HAVE message with out-of-range index.");  if (m_peerChunks.bitfield()->get(index))    return;  m_download->chunk_statistics()->received_have_chunk(&m_peerChunks, index, m_download->content()->chunk_size());  if (m_peerChunks.bitfield()->is_all_set())    if (m_download->content()->is_done())      throw close_connection();    else      set_remote_not_interested();  if (m_download->content()->is_done())    return;  if (is_up_interested()) {    if (!m_tryRequest && m_download->chunk_selector()->received_have_chunk(&m_peerChunks, index)) {      m_tryRequest = true;      write_insert_poll_safe();    }  } else {    if (m_download->chunk_selector()->received_have_chunk(&m_peerChunks, index)) {      m_sendInterested = true;      m_up->set_interested(true);            // Is it enough to insert into write here? Make the interested      // check branch to include insert_write, even when not sending      // interested.      m_tryRequest = true;      write_insert_poll_safe();    }  }}}

⌨️ 快捷键说明

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