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_SESSION_IMPL_HPP_INCLUDED
00034 #define TORRENT_SESSION_IMPL_HPP_INCLUDED
00035
00036 #include <ctime>
00037 #include <algorithm>
00038 #include <vector>
00039 #include <set>
00040 #include <list>
00041 #include <deque>
00042
00043 #ifdef _MSC_VER
00044 #pragma warning(push, 1)
00045 #endif
00046
00047 #include <boost/limits.hpp>
00048 #include <boost/tuple/tuple.hpp>
00049 #include <boost/filesystem/path.hpp>
00050 #include <boost/thread.hpp>
00051 #include <boost/thread/recursive_mutex.hpp>
00052
00053 #ifdef _MSC_VER
00054 #pragma warning(pop)
00055 #endif
00056
00057 #include "libtorrent/torrent_handle.hpp"
00058 #include "libtorrent/entry.hpp"
00059 #include "libtorrent/torrent_info.hpp"
00060 #include "libtorrent/socket.hpp"
00061 #include "libtorrent/peer_connection.hpp"
00062 #include "libtorrent/peer_id.hpp"
00063 #include "libtorrent/policy.hpp"
00064 #include "libtorrent/tracker_manager.hpp"
00065 #include "libtorrent/peer_info.hpp"
00066 #include "libtorrent/alert.hpp"
00067 #include "libtorrent/fingerprint.hpp"
00068 #include "libtorrent/debug.hpp"
00069 #include "libtorrent/peer_request.hpp"
00070 #include "libtorrent/piece_block_progress.hpp"
00071 #include "libtorrent/ip_filter.hpp"
00072 #include "libtorrent/config.hpp"
00073 #include "libtorrent/session_settings.hpp"
00074 #include "libtorrent/kademlia/dht_tracker.hpp"
00075 #include "libtorrent/session_status.hpp"
00076 #include "libtorrent/session.hpp"
00077 #include "libtorrent/stat.hpp"
00078 #include "libtorrent/file_pool.hpp"
00079 #include "libtorrent/bandwidth_manager.hpp"
00080
00081 namespace libtorrent
00082 {
00083
00084 namespace aux
00085 {
00086 struct session_impl;
00087
00088
00089
00090 struct piece_checker_data
00091 {
00092 piece_checker_data()
00093 : processing(false), progress(0.f), abort(false) {}
00094
00095 boost::shared_ptr<torrent> torrent_ptr;
00096 boost::filesystem::path save_path;
00097
00098 sha1_hash info_hash;
00099
00100 void parse_resume_data(
00101 const entry& rd
00102 , const torrent_info& info
00103 , std::string& error);
00104
00105 std::vector<int> piece_map;
00106 std::vector<piece_picker::downloading_piece> unfinished_pieces;
00107 std::vector<tcp::endpoint> peers;
00108 entry resume_data;
00109
00110
00111
00112
00113
00114 bool processing;
00115
00116
00117
00118
00119 float progress;
00120
00121
00122
00123
00124 bool abort;
00125 };
00126
00127 struct checker_impl: boost::noncopyable
00128 {
00129 checker_impl(session_impl& s): m_ses(s), m_abort(false) {}
00130 void operator()();
00131 piece_checker_data* find_torrent(const sha1_hash& info_hash);
00132 void remove_torrent(sha1_hash const& info_hash);
00133
00134 #ifndef NDEBUG
00135 void check_invariant() const;
00136 #endif
00137
00138
00139
00140 session_impl& m_ses;
00141
00142 mutable boost::mutex m_mutex;
00143 boost::condition m_cond;
00144
00145
00146
00147 std::deque<boost::shared_ptr<piece_checker_data> > m_torrents;
00148 std::deque<boost::shared_ptr<piece_checker_data> > m_processing;
00149
00150 bool m_abort;
00151 };
00152
00153 #if defined(TORRENT_LOGGING) || defined(TORRENT_VERBOSE_LOGGING)
00154 struct tracker_logger;
00155 #endif
00156
00157
00158
00159 struct session_impl: boost::noncopyable
00160 {
00161 #ifndef NDEBUG
00162 friend class ::libtorrent::peer_connection;
00163 #endif
00164 friend struct checker_impl;
00165 friend class invariant_access;
00166 typedef std::map<boost::shared_ptr<stream_socket>
00167 , boost::intrusive_ptr<peer_connection> >
00168 connection_map;
00169 typedef std::map<sha1_hash, boost::shared_ptr<torrent> > torrent_map;
00170 typedef std::deque<boost::intrusive_ptr<peer_connection> >
00171 connection_queue;
00172
00173 session_impl(
00174 std::pair<int, int> listen_port_range
00175 , fingerprint const& cl_fprint
00176 , char const* listen_interface = "0.0.0.0");
00177 ~session_impl();
00178
00179 #ifndef TORRENT_DISABLE_EXTENSIONS
00180 void add_extension(boost::function<boost::shared_ptr<torrent_plugin>(torrent*)> ext);
00181 #endif
00182 void operator()();
00183
00184 void open_listen_port();
00185
00186 void async_accept();
00187 void on_incoming_connection(boost::shared_ptr<stream_socket> const& s
00188 , boost::weak_ptr<socket_acceptor> const& as, asio::error_code const& e);
00189
00190
00191
00192 typedef boost::recursive_mutex mutex_t;
00193 mutable mutex_t m_mutex;
00194
00195 boost::weak_ptr<torrent> find_torrent(const sha1_hash& info_hash);
00196 peer_id const& get_peer_id() const { return m_peer_id; }
00197
00198
00199
00200
00201 void process_connection_queue();
00202
00203 void close_connection(boost::intrusive_ptr<peer_connection> const& p);
00204 void connection_completed(boost::intrusive_ptr<peer_connection> const& p);
00205 void connection_failed(boost::shared_ptr<stream_socket> const& s
00206 , tcp::endpoint const& a, char const* message);
00207
00208 void set_settings(session_settings const& s);
00209 session_settings const& settings() const { return m_settings; }
00210
00211 #ifndef TORRENT_DISABLE_DHT
00212 void add_dht_node(std::pair<std::string, int> const& node);
00213 void add_dht_node(udp::endpoint n);
00214 void add_dht_router(std::pair<std::string, int> const& node);
00215 void set_dht_settings(dht_settings const& s);
00216 dht_settings const& kad_settings() const { return m_dht_settings; }
00217 void start_dht(entry const& startup_state);
00218 void stop_dht();
00219 entry dht_state() const;
00220 #endif
00221 bool is_aborted() const { return m_abort; }
00222
00223 void set_ip_filter(ip_filter const& f);
00224
00225 bool listen_on(
00226 std::pair<int, int> const& port_range
00227 , const char* net_interface = 0);
00228 bool is_listening() const;
00229
00230 torrent_handle add_torrent(
00231 torrent_info const& ti
00232 , boost::filesystem::path const& save_path
00233 , entry const& resume_data
00234 , bool compact_mode
00235 , int block_size);
00236
00237 torrent_handle add_torrent(
00238 char const* tracker_url
00239 , sha1_hash const& info_hash
00240 , char const* name
00241 , boost::filesystem::path const& save_path
00242 , entry const& resume_data
00243 , bool compact_mode
00244 , int block_size);
00245
00246 void remove_torrent(torrent_handle const& h);
00247
00248 std::vector<torrent_handle> get_torrents();
00249
00250 void set_severity_level(alert::severity_t s);
00251 std::auto_ptr<alert> pop_alert();
00252
00253 int upload_rate_limit() const;
00254 int download_rate_limit() const;
00255
00256 void set_download_rate_limit(int bytes_per_second);
00257 void set_upload_rate_limit(int bytes_per_second);
00258 void set_max_half_open_connections(int limit);
00259 void set_max_connections(int limit);
00260 void set_max_uploads(int limit);
00261
00262 int num_uploads() const;
00263 int num_connections() const;
00264
00265 session_status status() const;
00266 void set_peer_id(peer_id const& id);
00267 void set_key(int key);
00268 unsigned short listen_port() const;
00269
00270 void abort();
00271
00272 torrent_handle find_torrent_handle(sha1_hash const& info_hash);
00273
00274
00275
00276 alert_manager m_alerts;
00277
00278
00279
00280
00281
00282
00283 io_service m_io_service;
00284 asio::strand m_strand;
00285
00286
00287
00288
00289
00290 bandwidth_manager m_dl_bandwidth_manager;
00291 bandwidth_manager m_ul_bandwidth_manager;
00292
00293 tracker_manager m_tracker_manager;
00294 torrent_map m_torrents;
00295
00296
00297
00298
00299 connection_map m_connections;
00300
00301
00302
00303 connection_map m_half_open;
00304
00305
00306
00307
00308
00309 connection_queue m_connection_queue;
00310
00311
00312 ip_filter m_ip_filter;
00313
00314
00315 peer_id m_peer_id;
00316
00317
00318
00319
00320 int m_key;
00321
00322
00323 std::pair<int, int> m_listen_port_range;
00324
00325
00326
00327
00328
00329
00330 tcp::endpoint m_listen_interface;
00331
00332 boost::shared_ptr<socket_acceptor> m_listen_socket;
00333
00334
00335 session_settings m_settings;
00336
00337
00338
00339
00340 volatile bool m_abort;
00341
00342 int m_max_uploads;
00343 int m_max_connections;
00344
00345
00346 int m_half_open_limit;
00347
00348
00349 stat m_stat;
00350
00351
00352
00353
00354
00355 bool m_incoming_connection;
00356
00357
00358
00359
00360 file_pool m_files;
00361
00362 void second_tick(asio::error_code const& e);
00363 boost::posix_time::ptime m_last_tick;
00364
00365 #ifndef TORRENT_DISABLE_DHT
00366 boost::intrusive_ptr<dht::dht_tracker> m_dht;
00367 dht_settings m_dht_settings;
00368 #endif
00369
00370 deadline_timer m_timer;
00371 #ifndef NDEBUG
00372 void check_invariant(const char *place = 0);
00373 #endif
00374 #if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING)
00375 boost::shared_ptr<logger> create_log(std::string const& name
00376 , int instance, bool append = true);
00377
00378
00379
00380
00381 std::list<boost::shared_ptr<tracker_logger> > m_tracker_loggers;
00382
00383
00384 boost::shared_ptr<logger> m_stats_logger;
00385 int m_second_counter;
00386 public:
00387 boost::shared_ptr<logger> m_logger;
00388 private:
00389 #endif
00390
00391 #ifndef TORRENT_DISABLE_EXTENSIONS
00392 typedef std::list<boost::function<boost::shared_ptr<
00393 torrent_plugin>(torrent*)> > extension_list_t;
00394
00395 extension_list_t m_extensions;
00396 #endif
00397
00398
00399
00400 checker_impl m_checker_impl;
00401
00402
00403 boost::scoped_ptr<boost::thread> m_thread;
00404
00405
00406
00407 boost::scoped_ptr<boost::thread> m_checker_thread;
00408 };
00409
00410 #if defined(TORRENT_LOGGING) || defined(TORRENT_VERBOSE_LOGGING)
00411 struct tracker_logger : request_callback
00412 {
00413 tracker_logger(session_impl& ses): m_ses(ses) {}
00414 void tracker_warning(std::string const& str)
00415 {
00416 debug_log("*** tracker warning: " + str);
00417 }
00418
00419 void tracker_response(tracker_request const&
00420 , std::vector<peer_entry>& peers
00421 , int interval
00422 , int complete
00423 , int incomplete)
00424 {
00425 std::stringstream s;
00426 s << "TRACKER RESPONSE:\n"
00427 "interval: " << interval << "\n"
00428 "peers:\n";
00429 for (std::vector<peer_entry>::const_iterator i = peers.begin();
00430 i != peers.end(); ++i)
00431 {
00432 s << " " << std::setfill(' ') << std::setw(16) << i->ip
00433 << " " << std::setw(5) << std::dec << i->port << " ";
00434 if (!i->pid.is_all_zeros()) s << " " << i->pid;
00435 s << "\n";
00436 }
00437 debug_log(s.str());
00438 }
00439
00440 void tracker_request_timed_out(
00441 tracker_request const&)
00442 {
00443 debug_log("*** tracker timed out");
00444 }
00445
00446 void tracker_request_error(
00447 tracker_request const&
00448 , int response_code
00449 , const std::string& str)
00450 {
00451 debug_log(std::string("*** tracker error: ")
00452 + boost::lexical_cast<std::string>(response_code) + ": "
00453 + str);
00454 }
00455
00456 void debug_log(const std::string& line)
00457 {
00458 (*m_ses.m_logger) << line << "\n";
00459 }
00460 session_impl& m_ses;
00461 };
00462 #endif
00463
00464 }
00465 }
00466
00467
00468 #endif
00469