📄 peer_connection.hpp
字号:
/*Copyright (c) 2003, Arvid NorbergAll rights reserved.Redistribution and use in source and binary forms, with or withoutmodification, are permitted provided that the following conditionsare met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * Neither the name of the author nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THEIMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSEARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BELIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, ORCONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OFSUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESSINTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER INCONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THEPOSSIBILITY OF SUCH DAMAGE.*/#ifndef TORRENT_PEER_CONNECTION_HPP_INCLUDED#define TORRENT_PEER_CONNECTION_HPP_INCLUDED#include <ctime>#include <algorithm>#include <vector>#include <deque>#include <string>#include "libtorrent/debug.hpp"#ifdef _MSC_VER#pragma warning(push, 1)#endif#include <boost/smart_ptr.hpp>#include <boost/weak_ptr.hpp>#include <boost/noncopyable.hpp>#include <boost/array.hpp>#include <boost/optional.hpp>#include <boost/cstdint.hpp>#include <boost/pool/pool.hpp>#ifdef _MSC_VER#pragma warning(pop)#endif#include "libtorrent/buffer.hpp"#include "libtorrent/socket.hpp"#include "libtorrent/peer_id.hpp"#include "libtorrent/storage.hpp"#include "libtorrent/stat.hpp"#include "libtorrent/alert.hpp"#include "libtorrent/torrent_handle.hpp"#include "libtorrent/torrent.hpp"#include "libtorrent/peer_request.hpp"#include "libtorrent/piece_block_progress.hpp"#include "libtorrent/config.hpp"#include "libtorrent/session.hpp"#include "libtorrent/bandwidth_limit.hpp"#include "libtorrent/policy.hpp"#include "libtorrent/socket_type.hpp"#include "libtorrent/intrusive_ptr_base.hpp"#include "libtorrent/assert.hpp"#include "libtorrent/chained_buffer.hpp"namespace libtorrent{ class torrent; struct peer_plugin; namespace detail { struct session_impl; } struct TORRENT_EXPORT protocol_error: std::runtime_error { protocol_error(const std::string& msg): std::runtime_error(msg) {}; }; class TORRENT_EXPORT peer_connection : public intrusive_ptr_base<peer_connection> , public boost::noncopyable { friend class invariant_access; public: enum channels { upload_channel, download_channel, num_channels }; // this is the constructor where the we are the active part. // The peer_conenction should handshake and verify that the // other end has the correct id peer_connection( aux::session_impl& ses , boost::weak_ptr<torrent> t , boost::shared_ptr<socket_type> s , tcp::endpoint const& remote , policy::peer* peerinfo); // with this constructor we have been contacted and we still don't // know which torrent the connection belongs to peer_connection( aux::session_impl& ses , boost::shared_ptr<socket_type> s , policy::peer* peerinfo); virtual ~peer_connection(); void set_peer_info(policy::peer* pi) { m_peer_info = pi; } policy::peer* peer_info_struct() const { return m_peer_info; } enum peer_speed_t { slow, medium, fast }; peer_speed_t peer_speed(); void send_allowed_set();#ifndef TORRENT_DISABLE_EXTENSIONS void add_extension(boost::shared_ptr<peer_plugin>);#endif // this function is called once the torrent associated // with this peer connection has retrieved the meta- // data. If the torrent was spawned with metadata // this is called from the constructor. void init(); // this is called when the metadata is retrieved // and the files has been checked virtual void on_metadata() {} void set_upload_limit(int limit); void set_download_limit(int limit); int upload_limit() const { return m_upload_limit; } int download_limit() const { return m_download_limit; } int prefer_whole_pieces() const { if (on_parole()) return 1; return m_prefer_whole_pieces; } bool on_parole() const { return peer_info_struct() && peer_info_struct()->on_parole; } void prefer_whole_pieces(int num) { m_prefer_whole_pieces = num; } bool request_large_blocks() const { return m_request_large_blocks; } void request_large_blocks(bool b) { m_request_large_blocks = b; } void set_priority(int p) { m_priority = p; } void fast_reconnect(bool r); bool fast_reconnect() const { return m_fast_reconnect; } // this adds an announcement in the announcement queue // it will let the peer know that we have the given piece void announce_piece(int index); // tells if this connection has data it want to send // and has enough upload bandwidth quota left to send it. bool can_write() const; bool can_read() const; bool is_seed() const; bool has_timed_out() const; // will send a keep-alive message to the peer void keep_alive(); peer_id const& pid() const { return m_peer_id; } void set_pid(const peer_id& pid) { m_peer_id = pid; } bool has_piece(int i) const; std::deque<piece_block> const& download_queue() const; std::deque<piece_block> const& request_queue() const; std::deque<peer_request> const& upload_queue() const; bool is_interesting() const { return m_interesting; } bool is_choked() const { return m_choked; } bool is_peer_interested() const { return m_peer_interested; } bool has_peer_choked() const { return m_peer_choked; } void update_interest(); virtual void get_peer_info(peer_info& p) const; // returns the torrent this connection is a part of // may be zero if the connection is an incoming connection // and it hasn't received enough information to determine // which torrent it should be associated with boost::weak_ptr<torrent> associated_torrent() const { return m_torrent; } const stat& statistics() const { return m_statistics; } void add_stat(size_type downloaded, size_type uploaded); // is called once every second by the main loop void second_tick(float tick_interval); boost::shared_ptr<socket_type> get_socket() const { return m_socket; } tcp::endpoint const& remote() const { return m_remote; } std::vector<bool> const& get_bitfield() const; std::vector<int> const& allowed_fast(); std::vector<int> const& suggested_pieces() const { return m_suggested_pieces; } void timed_out(); // this will cause this peer_connection to be disconnected. void disconnect(); bool is_disconnecting() const { return m_disconnecting; } // this is called when the connection attempt has succeeded // and the peer_connection is supposed to set m_connecting // to false, and stop monitor writability void on_connection_complete(asio::error_code const& e); // returns true if this connection is still waiting to // finish the connection attempt bool is_connecting() const { return m_connecting; } // returns true if the socket of this peer hasn't been // attempted to connect yet (i.e. it's queued for // connection attempt). bool is_queued() const { return m_queued; } // called when it's time for this peer_conncetion to actually // initiate the tcp connection. This may be postponed until // the library isn't using up the limitation of half-open // tcp connections. void connect(int ticket); // This is called for every peer right after the upload // bandwidth has been distributed among them // It will reset the used bandwidth to 0. void reset_upload_quota(); // free upload. size_type total_free_upload() const; void add_free_upload(size_type free_upload); // trust management. void received_valid_data(int index); void received_invalid_data(int index); size_type share_diff() const; // a connection is local if it was initiated by us. // if it was an incoming connection, it is remote bool is_local() const { return m_active; } bool on_local_network() const; bool ignore_bandwidth_limits() const { return m_ignore_bandwidth_limits; } void set_failed() { m_failed = true; } bool failed() const { return m_failed; } int desired_queue_size() const { return m_desired_queue_size; }#ifdef TORRENT_VERBOSE_LOGGING boost::shared_ptr<logger> m_logger;#endif // the message handlers are called // each time a recv() returns some new // data, the last time it will be called // is when the entire packet has been // received, then it will no longer // be called. i.e. most handlers need // to check how much of the packet they // have received before any processing void incoming_keepalive(); void incoming_choke(); void incoming_unchoke(); void incoming_interested(); void incoming_not_interested(); void incoming_have(int piece_index); void incoming_bitfield(std::vector<bool> const& bitfield); void incoming_request(peer_request const& r); void incoming_piece(peer_request const& p, char const* data); void incoming_piece_fragment(); void incoming_cancel(peer_request const& r); void incoming_dht_port(int listen_port); void incoming_reject_request(peer_request const& r); void incoming_have_all(); void incoming_have_none(); void incoming_allowed_fast(int index); void incoming_suggest(int index); // the following functions appends messages // to the send buffer void send_choke(); void send_unchoke(); void send_interested(); void send_not_interested(); // adds a block to the request queue void add_request(piece_block const& b); // removes a block from the request queue or download queue // sends a cancel message if appropriate // refills the request queue, and possibly ignoring pieces requested // by peers in the ignore list (to avoid recursion) void cancel_request(piece_block const& b); void send_block_requests(); int max_assignable_bandwidth(int channel) const { return m_bandwidth_limit[channel].max_assignable(); } int bandwidth_throttle(int channel) const { return m_bandwidth_limit[channel].throttle(); } void assign_bandwidth(int channel, int amount); void expire_bandwidth(int channel, int amount);#ifndef NDEBUG void check_invariant() const; ptime m_last_choke;#endif // is true until we can be sure that the other end // speaks our protocol (be it bittorrent or http). virtual bool in_handshake() const = 0; // returns the block currently being // downloaded. And the progress of that // block. If the peer isn't downloading // a piece for the moment, the boost::optional // will be invalid. virtual boost::optional<piece_block_progress> downloading_piece_progress() const {#ifdef TORRENT_VERBOSE_LOGGING (*m_logger) << "downloading_piece_progress() dispatched to the base class!\n";#endif return boost::optional<piece_block_progress>(); } // these functions are virtual to let bt_peer_connection hook into them // and encrypt the content virtual void send_buffer(char const* begin, int size); virtual buffer::interval allocate_send_buffer(int size); virtual void setup_send(); template <class Destructor> void append_send_buffer(char* buffer, int size, Destructor const& destructor)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -