📄 peer_connection_base.cc
字号:
m_download->download_throttle()->node_used(m_peerChunks.download_throttle(), bytesTransfered); m_download->info()->down_rate()->insert(bytesTransfered); return transfer->is_finished();}boolPeerConnectionBase::down_chunk_from_buffer() { m_down->buffer()->move_position(down_chunk_process(m_down->buffer()->position(), m_down->buffer()->remaining())); if (!m_downloadQueue.transfer()->is_finished() && m_down->buffer()->remaining() != 0) throw internal_error("PeerConnectionBase::down_chunk_from_buffer() !transfer->is_finished() && m_down->buffer()->remaining() != 0."); return m_downloadQueue.transfer()->is_finished();} // When this transfer again becomes the leader, we just return false// and wait for the next polling. It is an exceptional case so we// don't really care that much about performance.boolPeerConnectionBase::down_chunk_skip() { uint32_t length = read_stream_throws(m_nullBuffer, m_downloadQueue.transfer()->piece().length() - m_downloadQueue.transfer()->position()); if (down_chunk_skip_process(m_nullBuffer, length) != length) throw internal_error("PeerConnectionBase::down_chunk_skip() down_chunk_skip_process(m_nullBuffer, length) != length."); return m_downloadQueue.transfer()->is_finished();}boolPeerConnectionBase::down_chunk_skip_from_buffer() { m_down->buffer()->move_position(down_chunk_skip_process(m_down->buffer()->position(), m_down->buffer()->remaining())); return m_downloadQueue.transfer()->is_finished();}// Process data from a leading transfer.uint32_tPeerConnectionBase::down_chunk_process(const void* buffer, uint32_t length) { if (!m_downChunk.is_valid() || m_downChunk.index() != m_downloadQueue.transfer()->index()) throw internal_error("PeerConnectionBase::down_chunk_process(...) !m_downChunk.is_valid() || m_downChunk.index() != m_downloadQueue.transfer()->index()."); if (length == 0) return length; BlockTransfer* transfer = m_downloadQueue.transfer(); length = std::min(transfer->piece().length() - transfer->position(), length); m_downChunk.chunk()->from_buffer(buffer, transfer->piece().offset() + transfer->position(), length); transfer->adjust_position(length); m_download->download_throttle()->node_used(m_peerChunks.download_throttle(), length); m_download->info()->down_rate()->insert(length); return length;}// Process data from non-leading transfer. If this transfer encounters// mismatching data with the leader then bork this transfer. If we get// ahead of the leader, we switch the leader.uint32_tPeerConnectionBase::down_chunk_skip_process(const void* buffer, uint32_t length) { BlockTransfer* transfer = m_downloadQueue.transfer(); // Adjust 'length' to be less than or equal to what is remaining of // the block to simplify the rest of the function. length = std::min(length, transfer->piece().length() - transfer->position()); m_download->download_throttle()->node_used(m_peerChunks.download_throttle(), length); m_download->info()->down_rate()->insert(length); if (!transfer->is_valid()) { transfer->adjust_position(length); return length; } if (!transfer->block()->is_transfering()) throw internal_error("PeerConnectionBase::down_chunk_skip_process(...) block is not transfering, yet we have non-leaders."); // Temporary test. if (transfer->position() > transfer->block()->leader()->position()) throw internal_error("PeerConnectionBase::down_chunk_skip_process(...) transfer is past the Block's position."); // If the transfer is valid, compare the downloaded data to the // leader. uint32_t compareLength = std::min(length, transfer->block()->leader()->position() - transfer->position()); // The data doesn't match with what has previously been downloaded, // bork this transfer. if (!m_downChunk.chunk()->compare_buffer(buffer, transfer->piece().offset() + transfer->position(), compareLength)) { m_download->info()->signal_network_log().emit("Data does not match what was previously downloaded."); m_downloadQueue.transfer_dissimilar(); m_downloadQueue.transfer()->adjust_position(length); return length; } transfer->adjust_position(compareLength); if (compareLength == length) return length; // Add another check here to see if we really want to be the new // leader. transfer->block()->change_leader(transfer); if (down_chunk_process(static_cast<const char*>(buffer) + compareLength, length - compareLength) != length - compareLength) throw internal_error("PeerConnectionBase::down_chunk_skip_process(...) down_chunk_process(...) returned wrong value."); return length;}boolPeerConnectionBase::up_chunk() { if (!m_download->upload_throttle()->is_throttled(m_peerChunks.upload_throttle())) throw internal_error("PeerConnectionBase::up_chunk() tried to write a piece but is not in throttle list"); if (!m_upChunk.chunk()->is_readable()) throw internal_error("ProtocolChunk::write_part() chunk not readable, permission denided"); uint32_t quota = m_download->upload_throttle()->node_quota(m_peerChunks.upload_throttle()); if (quota == 0) { manager->poll()->remove_write(this); m_download->upload_throttle()->node_deactivate(m_peerChunks.upload_throttle()); return false; } uint32_t bytesTransfered = 0; Chunk::data_type data; ChunkIterator itr(m_upChunk.chunk(), m_upPiece.offset(), m_upPiece.offset() + std::min(quota, m_upPiece.length())); do { data = itr.data(); data.second = write_stream_throws(data.first, data.second); bytesTransfered += data.second; } while (itr.used(data.second)); m_download->upload_throttle()->node_used(m_peerChunks.upload_throttle(), bytesTransfered); m_download->info()->up_rate()->insert(bytesTransfered); // Just modifying the piece to cover the remaining data ends up // being much cleaner and we avoid an unnessesary position variable. m_upPiece.set_offset(m_upPiece.offset() + bytesTransfered); m_upPiece.set_length(m_upPiece.length() - bytesTransfered); return m_upPiece.length() == 0;}voidPeerConnectionBase::down_chunk_release() { if (m_downChunk.is_valid()) m_download->chunk_list()->release(&m_downChunk);}voidPeerConnectionBase::up_chunk_release() { if (m_upChunk.is_valid()) m_download->chunk_list()->release(&m_upChunk);}voidPeerConnectionBase::read_request_piece(const Piece& p) { PeerChunks::piece_list_type::iterator itr = std::find(m_peerChunks.upload_queue()->begin(), m_peerChunks.upload_queue()->end(), p); if (m_up->choked() || itr != m_peerChunks.upload_queue()->end() || p.length() > (1 << 17)) return; m_peerChunks.upload_queue()->push_back(p); write_insert_poll_safe();}voidPeerConnectionBase::read_cancel_piece(const Piece& p) { PeerChunks::piece_list_type::iterator itr = std::find(m_peerChunks.upload_queue()->begin(), m_peerChunks.upload_queue()->end(), p); if (itr != m_peerChunks.upload_queue()->end()) m_peerChunks.upload_queue()->erase(itr);} voidPeerConnectionBase::read_buffer_move_unused() { uint32_t remaining = m_down->buffer()->remaining(); std::memmove(m_down->buffer()->begin(), m_down->buffer()->position(), remaining); m_down->buffer()->reset_position(); m_down->buffer()->set_end(remaining);}voidPeerConnectionBase::write_prepare_piece() { m_upPiece = m_peerChunks.upload_queue()->front(); m_peerChunks.upload_queue()->pop_front(); // Move these checks somewhere else? if (!m_download->content()->is_valid_piece(m_upPiece) || !m_download->content()->has_chunk(m_upPiece.index())) { std::stringstream s; s << "Peer requested a piece with invalid index or length/offset: " << m_upPiece.index() << ' ' << m_upPiece.length() << ' ' << m_upPiece.offset(); throw communication_error(s.str());// throw communication_error("Peer requested a piece with invalid index or length/offset."); } m_up->write_piece(m_upPiece);}// High stall count peers should request if we're *not* in endgame, or// if we're in endgame and the download is too slow. Prefere not to request// from high stall counts when we are doing decent speeds.boolPeerConnectionBase::should_request() { if (m_down->choked() || !m_up->interested()) // || m_down->get_state() == ProtocolRead::READ_SKIP_PIECE) return false; else if (!m_download->delegator()->get_aggressive()) return true; else // We check if the peer is stalled, if it is not then we should // request. If the peer is stalled then we only request if the // download rate is below a certain value. return m_downStall <= 1 || m_download->info()->down_rate()->rate() < (10 << 10);}boolPeerConnectionBase::try_request_pieces() { if (download_queue()->empty()) m_downStall = 0; uint32_t pipeSize = download_queue()->calculate_pipe_size(m_peerChunks.download_throttle()->rate()->rate()); // Don't start requesting if we can't do it in large enough chunks. if (download_queue()->size() >= (pipeSize + 10) / 2) return false; bool success = false; while (download_queue()->size() < pipeSize && m_up->can_write_request()) { // Delegator should return a vector of pieces, and it should be // passed the number of pieces it should delegate. Try to ensure // it receives large enough request to fill a whole chunk if the // peer is fast enough. const Piece* p = download_queue()->delegate(); if (p == NULL) break; if (!m_download->content()->is_valid_piece(*p) || !m_peerChunks.bitfield()->get(p->index())) throw internal_error("PeerConnectionBase::try_request_pieces() tried to use an invalid piece."); m_up->write_request(*p); success = true; } return success;}voidPeerConnectionBase::set_remote_interested() { if (m_down->interested() || m_peerChunks.bitfield()->is_all_set()) return; m_down->set_interested(true); if (is_upload_wanted()) m_download->choke_manager()->set_interested(this);}voidPeerConnectionBase::set_remote_not_interested() { if (!m_down->interested()) return; bool wasUploadWanted = is_upload_wanted(); m_down->set_interested(false); if (wasUploadWanted) m_download->choke_manager()->set_not_interested(this);}}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -