00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033 #ifndef TORRENT_BT_PEER_CONNECTION_HPP_INCLUDED
00034 #define TORRENT_BT_PEER_CONNECTION_HPP_INCLUDED
00035
00036 #include <ctime>
00037 #include <algorithm>
00038 #include <vector>
00039 #include <deque>
00040 #include <string>
00041
00042 #include "libtorrent/debug.hpp"
00043
00044 #ifdef _MSC_VER
00045 #pragma warning(push, 1)
00046 #endif
00047
00048 #include <boost/smart_ptr.hpp>
00049 #include <boost/noncopyable.hpp>
00050 #include <boost/array.hpp>
00051 #include <boost/date_time/posix_time/posix_time.hpp>
00052 #include <boost/optional.hpp>
00053 #include <boost/cstdint.hpp>
00054
00055 #ifdef _MSC_VER
00056 #pragma warning(pop)
00057 #endif
00058
00059 #include "libtorrent/buffer.hpp"
00060 #include "libtorrent/peer_connection.hpp"
00061 #include "libtorrent/socket.hpp"
00062 #include "libtorrent/peer_id.hpp"
00063 #include "libtorrent/storage.hpp"
00064 #include "libtorrent/stat.hpp"
00065 #include "libtorrent/alert.hpp"
00066 #include "libtorrent/torrent_handle.hpp"
00067 #include "libtorrent/torrent.hpp"
00068 #include "libtorrent/allocate_resources.hpp"
00069 #include "libtorrent/peer_request.hpp"
00070 #include "libtorrent/piece_block_progress.hpp"
00071 #include "libtorrent/config.hpp"
00072
00073 namespace libtorrent
00074 {
00075 class torrent;
00076
00077 namespace detail
00078 {
00079 struct session_impl;
00080 }
00081
00082 class TORRENT_EXPORT bt_peer_connection
00083 : public peer_connection
00084 {
00085 friend class invariant_access;
00086 public:
00087
00088
00089
00090
00091 bt_peer_connection(
00092 aux::session_impl& ses
00093 , boost::weak_ptr<torrent> t
00094 , boost::shared_ptr<stream_socket> s
00095 , tcp::endpoint const& remote);
00096
00097
00098
00099 bt_peer_connection(
00100 aux::session_impl& ses
00101 , boost::shared_ptr<stream_socket> s);
00102
00103 ~bt_peer_connection();
00104
00105 enum message_type
00106 {
00107
00108 msg_choke = 0,
00109 msg_unchoke,
00110 msg_interested,
00111 msg_not_interested,
00112 msg_have,
00113 msg_bitfield,
00114 msg_request,
00115 msg_piece,
00116 msg_cancel,
00117 msg_dht_port,
00118
00119 msg_extended = 20,
00120
00121 num_supported_messages
00122 };
00123
00124
00125
00126
00127 void on_sent(asio::error_code const& error
00128 , std::size_t bytes_transferred);
00129 void on_receive(asio::error_code const& error
00130 , std::size_t bytes_transferred);
00131
00132 virtual void get_peer_info(peer_info& p) const;
00133 virtual bool in_handshake() const;
00134
00135 #ifndef TORRENT_DISABLE_EXTENSIONS
00136 bool support_extensions() const { return m_supports_extensions; }
00137
00138 template <class T>
00139 T* supports_extension() const
00140 {
00141 for (extension_list_t::const_iterator i = m_extensions.begin()
00142 , end(m_extensions.end()); i != end; ++i)
00143 {
00144 T* ret = dynamic_cast<T*>(i->get());
00145 if (ret) return ret;
00146 }
00147 return 0;
00148 }
00149 #endif
00150
00151
00152
00153
00154
00155
00156
00157
00158
00159 void on_keepalive();
00160 void on_choke(int received);
00161 void on_unchoke(int received);
00162 void on_interested(int received);
00163 void on_not_interested(int received);
00164 void on_have(int received);
00165 void on_bitfield(int received);
00166 void on_request(int received);
00167 void on_piece(int received);
00168 void on_cancel(int received);
00169 void on_dht_port(int received);
00170
00171 void on_extended(int received);
00172
00173 void on_extended_handshake();
00174
00175 typedef void (bt_peer_connection::*message_handler)(int received);
00176
00177
00178
00179 void write_choke();
00180 void write_unchoke();
00181 void write_interested();
00182 void write_not_interested();
00183 void write_request(peer_request const& r);
00184 void write_cancel(peer_request const& r);
00185 void write_bitfield(std::vector<bool> const& bitfield);
00186 void write_have(int index);
00187 void write_piece(peer_request const& r);
00188 void write_handshake();
00189 #ifndef TORRENT_DISABLE_EXTENSIONS
00190 void write_extensions();
00191 #endif
00192 void write_chat_message(const std::string& msg);
00193 void write_metadata(std::pair<int, int> req);
00194 void write_metadata_request(std::pair<int, int> req);
00195 void write_keepalive();
00196 void write_dht_port(int listen_port);
00197 void on_connected() {}
00198 void on_metadata();
00199
00200 #ifndef NDEBUG
00201 void check_invariant() const;
00202 boost::posix_time::ptime m_last_choke;
00203 #endif
00204
00205 private:
00206
00207 bool dispatch_message(int received);
00208
00209
00210
00211
00212
00213 boost::optional<piece_block_progress> downloading_piece_progress() const;
00214
00215 enum state
00216 {
00217 read_protocol_length = 0,
00218 read_protocol_string,
00219 read_info_hash,
00220 read_peer_id,
00221
00222 read_packet_size,
00223 read_packet
00224 };
00225
00226 std::string m_client_version;
00227
00228 state m_state;
00229
00230
00231 int m_timeout;
00232
00233 static const message_handler m_message_handler[num_supported_messages];
00234
00235
00236
00237
00238
00239
00240 struct range
00241 {
00242 range(int s, int l)
00243 : start(s)
00244 , length(l)
00245 {
00246 assert(s >= 0);
00247 assert(l > 0);
00248 }
00249 int start;
00250 int length;
00251 };
00252 static bool range_below_zero(const range& r)
00253 { return r.start < 0; }
00254 std::deque<range> m_payloads;
00255
00256 #ifndef TORRENT_DISABLE_EXTENSIONS
00257
00258
00259
00260 bool m_supports_extensions;
00261 #endif
00262 bool m_supports_dht_port;
00263
00264 #ifndef NDEBUG
00265
00266
00267 bool m_sent_bitfield;
00268
00269 bool m_in_constructor;
00270 #endif
00271 };
00272 }
00273
00274 #endif // TORRENT_BT_PEER_CONNECTION_HPP_INCLUDED
00275