forked from premiere/premiere-libtorrent
fixed race condition in peer_connection, fixed assert in torrent destructor, updated tests
This commit is contained in:
parent
58698d6aea
commit
94628fa78d
6
Jamfile
6
Jamfile
|
@ -30,9 +30,9 @@ project torrent
|
||||||
<define>BOOST_ALL_NO_LIB
|
<define>BOOST_ALL_NO_LIB
|
||||||
<define>_FILE_OFFSET_BITS=64
|
<define>_FILE_OFFSET_BITS=64
|
||||||
<define>BOOST_THREAD_USE_LIB
|
<define>BOOST_THREAD_USE_LIB
|
||||||
<library>/boost/thread//boost_thread/<link>static
|
<library>/boost/thread//boost_thread #/<link>static
|
||||||
<library>/boost/filesystem//boost_filesystem/<link>static
|
<library>/boost/filesystem//boost_filesystem #/<link>static
|
||||||
<library>/boost/date_time//boost_date_time/<link>static
|
<library>/boost/date_time//boost_date_time #/<link>static
|
||||||
<threading>multi
|
<threading>multi
|
||||||
<toolset>msvc:<define>_WIN32_WINNT=0x0500
|
<toolset>msvc:<define>_WIN32_WINNT=0x0500
|
||||||
# WIN32 makes sure the win32 socket api is used
|
# WIN32 makes sure the win32 socket api is used
|
||||||
|
|
16
Makefile.am
16
Makefile.am
|
@ -4,7 +4,21 @@ docs/extension_protocol.html docs/udp_tracker_protocol.rst \
|
||||||
docs/udp_tracker_protocol.html docs/client_test.rst docs/client_test.html \
|
docs/udp_tracker_protocol.html docs/client_test.rst docs/client_test.html \
|
||||||
docs/unicode_support.png docs/client_test.png docs/style.css Jamfile project-root.jam \
|
docs/unicode_support.png docs/client_test.png docs/style.css Jamfile project-root.jam \
|
||||||
m4/ac_cxx_namespaces.m4 m4/acx_pthread.m4 m4/ax_boost_date-time.m4 \
|
m4/ac_cxx_namespaces.m4 m4/acx_pthread.m4 m4/ax_boost_date-time.m4 \
|
||||||
m4/ax_boost_filesystem.m4 m4/ax_boost_thread.m4 src/file_win.cpp libtorrent.pc \
|
m4/ax_boost_filesystem.m4 m4/ax_boost_thread.m4 src/file_win.cpp libtorrent.pc
|
||||||
|
|
||||||
|
pkginclude_HEADER = \
|
||||||
|
debian/changelog \
|
||||||
|
debian/compat \
|
||||||
|
debian/control \
|
||||||
|
debian/copyright \
|
||||||
|
debian/files \
|
||||||
|
debian/libtorrent0-dev.dirs \
|
||||||
|
debian/libtorrent0-dev.docs \
|
||||||
|
debian/libtorrent0-dev.install \
|
||||||
|
debian/libtorrent0.dirs \
|
||||||
|
debian/libtorrent0.docs \
|
||||||
|
debian/libtorrent0.install \
|
||||||
|
debian/rules \
|
||||||
asio/aclocal.m4 \
|
asio/aclocal.m4 \
|
||||||
asio/autogen.sh \
|
asio/autogen.sh \
|
||||||
asio/boostify.pl \
|
asio/boostify.pl \
|
||||||
|
|
248
docs/manual.html
248
docs/manual.html
|
@ -142,148 +142,148 @@ div.warning, div.note, div.important {
|
||||||
<div class="contents topic">
|
<div class="contents topic">
|
||||||
<p class="topic-title first"><a id="table-of-contents" name="table-of-contents">Table of contents</a></p>
|
<p class="topic-title first"><a id="table-of-contents" name="table-of-contents">Table of contents</a></p>
|
||||||
<ul class="simple">
|
<ul class="simple">
|
||||||
<li><a class="reference" href="#introduction" id="id24" name="id24">introduction</a></li>
|
<li><a class="reference" href="#introduction" id="id25" name="id25">introduction</a></li>
|
||||||
<li><a class="reference" href="#downloading-and-building" id="id25" name="id25">downloading and building</a><ul>
|
<li><a class="reference" href="#downloading-and-building" id="id26" name="id26">downloading and building</a><ul>
|
||||||
<li><a class="reference" href="#building-with-bbv2" id="id26" name="id26">building with BBv2</a></li>
|
<li><a class="reference" href="#building-with-bbv2" id="id27" name="id27">building with BBv2</a></li>
|
||||||
<li><a class="reference" href="#building-with-autotools" id="id27" name="id27">building with autotools</a></li>
|
<li><a class="reference" href="#building-with-autotools" id="id28" name="id28">building with autotools</a></li>
|
||||||
<li><a class="reference" href="#building-with-other-build-systems" id="id28" name="id28">building with other build systems</a></li>
|
<li><a class="reference" href="#building-with-other-build-systems" id="id29" name="id29">building with other build systems</a></li>
|
||||||
<li><a class="reference" href="#build-configurations" id="id29" name="id29">build configurations</a></li>
|
<li><a class="reference" href="#build-configurations" id="id30" name="id30">build configurations</a></li>
|
||||||
</ul>
|
</ul>
|
||||||
</li>
|
</li>
|
||||||
<li><a class="reference" href="#overview" id="id30" name="id30">overview</a></li>
|
<li><a class="reference" href="#overview" id="id31" name="id31">overview</a></li>
|
||||||
<li><a class="reference" href="#session" id="id31" name="id31">session</a><ul>
|
<li><a class="reference" href="#session" id="id32" name="id32">session</a><ul>
|
||||||
<li><a class="reference" href="#id8" id="id32" name="id32">session()</a></li>
|
<li><a class="reference" href="#id9" id="id33" name="id33">session()</a></li>
|
||||||
<li><a class="reference" href="#id9" id="id33" name="id33">~session()</a></li>
|
<li><a class="reference" href="#id10" id="id34" name="id34">~session()</a></li>
|
||||||
<li><a class="reference" href="#add-torrent" id="id34" name="id34">add_torrent()</a></li>
|
<li><a class="reference" href="#add-torrent" id="id35" name="id35">add_torrent()</a></li>
|
||||||
<li><a class="reference" href="#remove-torrent" id="id35" name="id35">remove_torrent()</a></li>
|
<li><a class="reference" href="#remove-torrent" id="id36" name="id36">remove_torrent()</a></li>
|
||||||
<li><a class="reference" href="#disable-extensions-enable-extension" id="id36" name="id36">disable_extensions() enable_extension()</a></li>
|
<li><a class="reference" href="#disable-extensions-enable-extension" id="id37" name="id37">disable_extensions() enable_extension()</a></li>
|
||||||
<li><a class="reference" href="#set-upload-rate-limit-set-download-rate-limit" id="id37" name="id37">set_upload_rate_limit() set_download_rate_limit()</a></li>
|
<li><a class="reference" href="#set-upload-rate-limit-set-download-rate-limit" id="id38" name="id38">set_upload_rate_limit() set_download_rate_limit()</a></li>
|
||||||
<li><a class="reference" href="#set-max-uploads-set-max-connections" id="id38" name="id38">set_max_uploads() set_max_connections()</a></li>
|
<li><a class="reference" href="#set-max-uploads-set-max-connections" id="id39" name="id39">set_max_uploads() set_max_connections()</a></li>
|
||||||
<li><a class="reference" href="#set-max-half-open-connections" id="id39" name="id39">set_max_half_open_connections()</a></li>
|
<li><a class="reference" href="#set-max-half-open-connections" id="id40" name="id40">set_max_half_open_connections()</a></li>
|
||||||
<li><a class="reference" href="#set-ip-filter" id="id40" name="id40">set_ip_filter()</a></li>
|
<li><a class="reference" href="#set-ip-filter" id="id41" name="id41">set_ip_filter()</a></li>
|
||||||
<li><a class="reference" href="#status" id="id41" name="id41">status()</a></li>
|
<li><a class="reference" href="#status" id="id42" name="id42">status()</a></li>
|
||||||
<li><a class="reference" href="#is-listening-listen-port-listen-on" id="id42" name="id42">is_listening() listen_port() listen_on()</a></li>
|
<li><a class="reference" href="#is-listening-listen-port-listen-on" id="id43" name="id43">is_listening() listen_port() listen_on()</a></li>
|
||||||
<li><a class="reference" href="#pop-alert-set-severity-level" id="id43" name="id43">pop_alert() set_severity_level()</a></li>
|
<li><a class="reference" href="#pop-alert-set-severity-level" id="id44" name="id44">pop_alert() set_severity_level()</a></li>
|
||||||
</ul>
|
</ul>
|
||||||
</li>
|
</li>
|
||||||
<li><a class="reference" href="#entry" id="id44" name="id44">entry</a><ul>
|
<li><a class="reference" href="#entry" id="id45" name="id45">entry</a><ul>
|
||||||
<li><a class="reference" href="#integer-string-list-dict-type" id="id45" name="id45">integer() string() list() dict() type()</a></li>
|
<li><a class="reference" href="#integer-string-list-dict-type" id="id46" name="id46">integer() string() list() dict() type()</a></li>
|
||||||
<li><a class="reference" href="#operator" id="id46" name="id46">operator[]</a></li>
|
<li><a class="reference" href="#operator" id="id47" name="id47">operator[]</a></li>
|
||||||
<li><a class="reference" href="#find-key" id="id47" name="id47">find_key()</a></li>
|
<li><a class="reference" href="#find-key" id="id48" name="id48">find_key()</a></li>
|
||||||
</ul>
|
</ul>
|
||||||
</li>
|
</li>
|
||||||
<li><a class="reference" href="#torrent-info" id="id48" name="id48">torrent_info</a><ul>
|
<li><a class="reference" href="#torrent-info" id="id49" name="id49">torrent_info</a><ul>
|
||||||
<li><a class="reference" href="#id10" id="id49" name="id49">torrent_info()</a></li>
|
<li><a class="reference" href="#id11" id="id50" name="id50">torrent_info()</a></li>
|
||||||
<li><a class="reference" href="#set-comment-set-piece-size-set-creator-set-hash-add-tracker-add-file" id="id50" name="id50">set_comment() set_piece_size() set_creator() set_hash() add_tracker() add_file()</a></li>
|
<li><a class="reference" href="#set-comment-set-piece-size-set-creator-set-hash-add-tracker-add-file" id="id51" name="id51">set_comment() set_piece_size() set_creator() set_hash() add_tracker() add_file()</a></li>
|
||||||
<li><a class="reference" href="#create-torrent" id="id51" name="id51">create_torrent()</a></li>
|
<li><a class="reference" href="#create-torrent" id="id52" name="id52">create_torrent()</a></li>
|
||||||
<li><a class="reference" href="#begin-files-end-files-rbegin-files-rend-files" id="id52" name="id52">begin_files() end_files() rbegin_files() rend_files()</a></li>
|
<li><a class="reference" href="#begin-files-end-files-rbegin-files-rend-files" id="id53" name="id53">begin_files() end_files() rbegin_files() rend_files()</a></li>
|
||||||
<li><a class="reference" href="#num-files-file-at" id="id53" name="id53">num_files() file_at()</a></li>
|
<li><a class="reference" href="#num-files-file-at" id="id54" name="id54">num_files() file_at()</a></li>
|
||||||
<li><a class="reference" href="#map-block" id="id54" name="id54">map_block()</a></li>
|
<li><a class="reference" href="#map-block" id="id55" name="id55">map_block()</a></li>
|
||||||
<li><a class="reference" href="#map-file" id="id55" name="id55">map_file()</a></li>
|
<li><a class="reference" href="#map-file" id="id56" name="id56">map_file()</a></li>
|
||||||
<li><a class="reference" href="#url-seeds" id="id56" name="id56">url_seeds()</a></li>
|
<li><a class="reference" href="#url-seeds" id="id57" name="id57">url_seeds()</a></li>
|
||||||
<li><a class="reference" href="#print" id="id57" name="id57">print()</a></li>
|
<li><a class="reference" href="#print" id="id58" name="id58">print()</a></li>
|
||||||
<li><a class="reference" href="#trackers" id="id58" name="id58">trackers()</a></li>
|
<li><a class="reference" href="#trackers" id="id59" name="id59">trackers()</a></li>
|
||||||
<li><a class="reference" href="#total-size-piece-length-piece-size-num-pieces" id="id59" name="id59">total_size() piece_length() piece_size() num_pieces()</a></li>
|
<li><a class="reference" href="#total-size-piece-length-piece-size-num-pieces" id="id60" name="id60">total_size() piece_length() piece_size() num_pieces()</a></li>
|
||||||
<li><a class="reference" href="#hash-for-piece-info-hash" id="id60" name="id60">hash_for_piece() info_hash()</a></li>
|
<li><a class="reference" href="#hash-for-piece-info-hash" id="id61" name="id61">hash_for_piece() info_hash()</a></li>
|
||||||
<li><a class="reference" href="#name-comment-creation-date-creator" id="id61" name="id61">name() comment() creation_date() creator()</a></li>
|
<li><a class="reference" href="#name-comment-creation-date-creator" id="id62" name="id62">name() comment() creation_date() creator()</a></li>
|
||||||
</ul>
|
</ul>
|
||||||
</li>
|
</li>
|
||||||
<li><a class="reference" href="#torrent-handle" id="id62" name="id62">torrent_handle</a><ul>
|
<li><a class="reference" href="#torrent-handle" id="id63" name="id63">torrent_handle</a><ul>
|
||||||
<li><a class="reference" href="#save-path" id="id63" name="id63">save_path()</a></li>
|
<li><a class="reference" href="#save-path" id="id64" name="id64">save_path()</a></li>
|
||||||
<li><a class="reference" href="#move-storage" id="id64" name="id64">move_storage()</a></li>
|
<li><a class="reference" href="#move-storage" id="id65" name="id65">move_storage()</a></li>
|
||||||
<li><a class="reference" href="#force-reannounce" id="id65" name="id65">force_reannounce()</a></li>
|
<li><a class="reference" href="#force-reannounce" id="id66" name="id66">force_reannounce()</a></li>
|
||||||
<li><a class="reference" href="#connect-peer" id="id66" name="id66">connect_peer()</a></li>
|
<li><a class="reference" href="#connect-peer" id="id67" name="id67">connect_peer()</a></li>
|
||||||
<li><a class="reference" href="#set-ratio" id="id67" name="id67">set_ratio()</a></li>
|
<li><a class="reference" href="#set-ratio" id="id68" name="id68">set_ratio()</a></li>
|
||||||
<li><a class="reference" href="#set-upload-limit-set-download-limit" id="id68" name="id68">set_upload_limit() set_download_limit()</a></li>
|
<li><a class="reference" href="#set-upload-limit-set-download-limit" id="id69" name="id69">set_upload_limit() set_download_limit()</a></li>
|
||||||
<li><a class="reference" href="#set-peer-upload-limit-set-peer-download-limit" id="id69" name="id69">set_peer_upload_limit() set_peer_download_limit()</a></li>
|
<li><a class="reference" href="#set-peer-upload-limit-set-peer-download-limit" id="id70" name="id70">set_peer_upload_limit() set_peer_download_limit()</a></li>
|
||||||
<li><a class="reference" href="#pause-resume-is-paused" id="id70" name="id70">pause() resume() is_paused()</a></li>
|
<li><a class="reference" href="#pause-resume-is-paused" id="id71" name="id71">pause() resume() is_paused()</a></li>
|
||||||
<li><a class="reference" href="#is-seed" id="id71" name="id71">is_seed()</a></li>
|
<li><a class="reference" href="#is-seed" id="id72" name="id72">is_seed()</a></li>
|
||||||
<li><a class="reference" href="#has-metadata" id="id72" name="id72">has_metadata()</a></li>
|
<li><a class="reference" href="#has-metadata" id="id73" name="id73">has_metadata()</a></li>
|
||||||
<li><a class="reference" href="#set-tracker-login" id="id73" name="id73">set_tracker_login()</a></li>
|
<li><a class="reference" href="#set-tracker-login" id="id74" name="id74">set_tracker_login()</a></li>
|
||||||
<li><a class="reference" href="#trackers-replace-trackers" id="id74" name="id74">trackers() replace_trackers()</a></li>
|
<li><a class="reference" href="#trackers-replace-trackers" id="id75" name="id75">trackers() replace_trackers()</a></li>
|
||||||
<li><a class="reference" href="#add-url-seed" id="id75" name="id75">add_url_seed()</a></li>
|
<li><a class="reference" href="#add-url-seed" id="id76" name="id76">add_url_seed()</a></li>
|
||||||
<li><a class="reference" href="#use-interface" id="id76" name="id76">use_interface()</a></li>
|
<li><a class="reference" href="#use-interface" id="id77" name="id77">use_interface()</a></li>
|
||||||
<li><a class="reference" href="#info-hash" id="id77" name="id77">info_hash()</a></li>
|
<li><a class="reference" href="#info-hash" id="id78" name="id78">info_hash()</a></li>
|
||||||
<li><a class="reference" href="#id12" id="id78" name="id78">set_max_uploads() set_max_connections()</a></li>
|
<li><a class="reference" href="#id13" id="id79" name="id79">set_max_uploads() set_max_connections()</a></li>
|
||||||
<li><a class="reference" href="#write-resume-data" id="id79" name="id79">write_resume_data()</a></li>
|
<li><a class="reference" href="#write-resume-data" id="id80" name="id80">write_resume_data()</a></li>
|
||||||
<li><a class="reference" href="#metadata" id="id80" name="id80">metadata()</a></li>
|
<li><a class="reference" href="#metadata" id="id81" name="id81">metadata()</a></li>
|
||||||
<li><a class="reference" href="#id13" id="id81" name="id81">status()</a></li>
|
<li><a class="reference" href="#id14" id="id82" name="id82">status()</a></li>
|
||||||
<li><a class="reference" href="#get-download-queue" id="id82" name="id82">get_download_queue()</a></li>
|
<li><a class="reference" href="#get-download-queue" id="id83" name="id83">get_download_queue()</a></li>
|
||||||
<li><a class="reference" href="#get-peer-info" id="id83" name="id83">get_peer_info()</a></li>
|
<li><a class="reference" href="#get-peer-info" id="id84" name="id84">get_peer_info()</a></li>
|
||||||
<li><a class="reference" href="#get-torrent-info" id="id84" name="id84">get_torrent_info()</a></li>
|
<li><a class="reference" href="#get-torrent-info" id="id85" name="id85">get_torrent_info()</a></li>
|
||||||
<li><a class="reference" href="#is-valid" id="id85" name="id85">is_valid()</a></li>
|
<li><a class="reference" href="#is-valid" id="id86" name="id86">is_valid()</a></li>
|
||||||
</ul>
|
</ul>
|
||||||
</li>
|
</li>
|
||||||
<li><a class="reference" href="#torrent-status" id="id86" name="id86">torrent_status</a></li>
|
<li><a class="reference" href="#torrent-status" id="id87" name="id87">torrent_status</a></li>
|
||||||
<li><a class="reference" href="#peer-info" id="id87" name="id87">peer_info</a></li>
|
<li><a class="reference" href="#peer-info" id="id88" name="id88">peer_info</a></li>
|
||||||
<li><a class="reference" href="#session-settings" id="id88" name="id88">session_settings</a></li>
|
<li><a class="reference" href="#session-settings" id="id89" name="id89">session_settings</a></li>
|
||||||
<li><a class="reference" href="#ip-filter" id="id89" name="id89">ip_filter</a><ul>
|
<li><a class="reference" href="#ip-filter" id="id90" name="id90">ip_filter</a><ul>
|
||||||
<li><a class="reference" href="#id16" id="id90" name="id90">ip_filter()</a></li>
|
<li><a class="reference" href="#id17" id="id91" name="id91">ip_filter()</a></li>
|
||||||
<li><a class="reference" href="#add-rule" id="id91" name="id91">add_rule()</a></li>
|
<li><a class="reference" href="#add-rule" id="id92" name="id92">add_rule()</a></li>
|
||||||
<li><a class="reference" href="#access" id="id92" name="id92">access()</a></li>
|
<li><a class="reference" href="#access" id="id93" name="id93">access()</a></li>
|
||||||
<li><a class="reference" href="#export-filter" id="id93" name="id93">export_filter()</a></li>
|
<li><a class="reference" href="#export-filter" id="id94" name="id94">export_filter()</a></li>
|
||||||
</ul>
|
</ul>
|
||||||
</li>
|
</li>
|
||||||
<li><a class="reference" href="#big-number" id="id94" name="id94">big_number</a></li>
|
<li><a class="reference" href="#big-number" id="id95" name="id95">big_number</a></li>
|
||||||
<li><a class="reference" href="#hasher" id="id95" name="id95">hasher</a></li>
|
<li><a class="reference" href="#hasher" id="id96" name="id96">hasher</a></li>
|
||||||
<li><a class="reference" href="#fingerprint" id="id96" name="id96">fingerprint</a></li>
|
<li><a class="reference" href="#fingerprint" id="id97" name="id97">fingerprint</a></li>
|
||||||
<li><a class="reference" href="#free-functions" id="id97" name="id97">free functions</a><ul>
|
<li><a class="reference" href="#free-functions" id="id98" name="id98">free functions</a><ul>
|
||||||
<li><a class="reference" href="#identify-client" id="id98" name="id98">identify_client()</a></li>
|
<li><a class="reference" href="#identify-client" id="id99" name="id99">identify_client()</a></li>
|
||||||
<li><a class="reference" href="#client-fingerprint" id="id99" name="id99">client_fingerprint()</a></li>
|
<li><a class="reference" href="#client-fingerprint" id="id100" name="id100">client_fingerprint()</a></li>
|
||||||
<li><a class="reference" href="#bdecode-bencode" id="id100" name="id100">bdecode() bencode()</a></li>
|
<li><a class="reference" href="#bdecode-bencode" id="id101" name="id101">bdecode() bencode()</a></li>
|
||||||
</ul>
|
</ul>
|
||||||
</li>
|
</li>
|
||||||
<li><a class="reference" href="#alerts" id="id101" name="id101">alerts</a><ul>
|
<li><a class="reference" href="#alerts" id="id102" name="id102">alerts</a><ul>
|
||||||
<li><a class="reference" href="#listen-failed-alert" id="id102" name="id102">listen_failed_alert</a></li>
|
<li><a class="reference" href="#listen-failed-alert" id="id103" name="id103">listen_failed_alert</a></li>
|
||||||
<li><a class="reference" href="#file-error-alert" id="id103" name="id103">file_error_alert</a></li>
|
<li><a class="reference" href="#file-error-alert" id="id104" name="id104">file_error_alert</a></li>
|
||||||
<li><a class="reference" href="#tracker-announce-alert" id="id104" name="id104">tracker_announce_alert</a></li>
|
<li><a class="reference" href="#tracker-announce-alert" id="id105" name="id105">tracker_announce_alert</a></li>
|
||||||
<li><a class="reference" href="#tracker-alert" id="id105" name="id105">tracker_alert</a></li>
|
<li><a class="reference" href="#tracker-alert" id="id106" name="id106">tracker_alert</a></li>
|
||||||
<li><a class="reference" href="#tracker-reply-alert" id="id106" name="id106">tracker_reply_alert</a></li>
|
<li><a class="reference" href="#tracker-reply-alert" id="id107" name="id107">tracker_reply_alert</a></li>
|
||||||
<li><a class="reference" href="#tracker-warning-alert" id="id107" name="id107">tracker_warning_alert</a></li>
|
<li><a class="reference" href="#tracker-warning-alert" id="id108" name="id108">tracker_warning_alert</a></li>
|
||||||
<li><a class="reference" href="#url-seed-alert" id="id108" name="id108">url_seed_alert</a></li>
|
<li><a class="reference" href="#url-seed-alert" id="id109" name="id109">url_seed_alert</a></li>
|
||||||
<li><a class="reference" href="#hash-failed-alert" id="id109" name="id109">hash_failed_alert</a></li>
|
<li><a class="reference" href="#hash-failed-alert" id="id110" name="id110">hash_failed_alert</a></li>
|
||||||
<li><a class="reference" href="#peer-ban-alert" id="id110" name="id110">peer_ban_alert</a></li>
|
<li><a class="reference" href="#peer-ban-alert" id="id111" name="id111">peer_ban_alert</a></li>
|
||||||
<li><a class="reference" href="#peer-error-alert" id="id111" name="id111">peer_error_alert</a></li>
|
<li><a class="reference" href="#peer-error-alert" id="id112" name="id112">peer_error_alert</a></li>
|
||||||
<li><a class="reference" href="#invalid-request-alert" id="id112" name="id112">invalid_request_alert</a></li>
|
<li><a class="reference" href="#invalid-request-alert" id="id113" name="id113">invalid_request_alert</a></li>
|
||||||
<li><a class="reference" href="#torrent-finished-alert" id="id113" name="id113">torrent_finished_alert</a></li>
|
<li><a class="reference" href="#torrent-finished-alert" id="id114" name="id114">torrent_finished_alert</a></li>
|
||||||
<li><a class="reference" href="#metadata-failed-alert" id="id114" name="id114">metadata_failed_alert</a></li>
|
<li><a class="reference" href="#metadata-failed-alert" id="id115" name="id115">metadata_failed_alert</a></li>
|
||||||
<li><a class="reference" href="#metadata-received-alert" id="id115" name="id115">metadata_received_alert</a></li>
|
<li><a class="reference" href="#metadata-received-alert" id="id116" name="id116">metadata_received_alert</a></li>
|
||||||
<li><a class="reference" href="#fastresume-rejected-alert" id="id116" name="id116">fastresume_rejected_alert</a></li>
|
<li><a class="reference" href="#fastresume-rejected-alert" id="id117" name="id117">fastresume_rejected_alert</a></li>
|
||||||
<li><a class="reference" href="#dispatcher" id="id117" name="id117">dispatcher</a></li>
|
<li><a class="reference" href="#dispatcher" id="id118" name="id118">dispatcher</a></li>
|
||||||
</ul>
|
</ul>
|
||||||
</li>
|
</li>
|
||||||
<li><a class="reference" href="#exceptions" id="id118" name="id118">exceptions</a><ul>
|
<li><a class="reference" href="#exceptions" id="id119" name="id119">exceptions</a><ul>
|
||||||
<li><a class="reference" href="#invalid-handle" id="id119" name="id119">invalid_handle</a></li>
|
<li><a class="reference" href="#invalid-handle" id="id120" name="id120">invalid_handle</a></li>
|
||||||
<li><a class="reference" href="#duplicate-torrent" id="id120" name="id120">duplicate_torrent</a></li>
|
<li><a class="reference" href="#duplicate-torrent" id="id121" name="id121">duplicate_torrent</a></li>
|
||||||
<li><a class="reference" href="#invalid-encoding" id="id121" name="id121">invalid_encoding</a></li>
|
<li><a class="reference" href="#invalid-encoding" id="id122" name="id122">invalid_encoding</a></li>
|
||||||
<li><a class="reference" href="#type-error" id="id122" name="id122">type_error</a></li>
|
<li><a class="reference" href="#type-error" id="id123" name="id123">type_error</a></li>
|
||||||
<li><a class="reference" href="#invalid-torrent-file" id="id123" name="id123">invalid_torrent_file</a></li>
|
<li><a class="reference" href="#invalid-torrent-file" id="id124" name="id124">invalid_torrent_file</a></li>
|
||||||
</ul>
|
</ul>
|
||||||
</li>
|
</li>
|
||||||
<li><a class="reference" href="#examples" id="id124" name="id124">examples</a><ul>
|
<li><a class="reference" href="#examples" id="id125" name="id125">examples</a><ul>
|
||||||
<li><a class="reference" href="#dump-torrent" id="id125" name="id125">dump_torrent</a></li>
|
<li><a class="reference" href="#dump-torrent" id="id126" name="id126">dump_torrent</a></li>
|
||||||
<li><a class="reference" href="#simple-client" id="id126" name="id126">simple client</a></li>
|
<li><a class="reference" href="#simple-client" id="id127" name="id127">simple client</a></li>
|
||||||
<li><a class="reference" href="#make-torrent" id="id127" name="id127">make_torrent</a></li>
|
<li><a class="reference" href="#make-torrent" id="id128" name="id128">make_torrent</a></li>
|
||||||
</ul>
|
</ul>
|
||||||
</li>
|
</li>
|
||||||
<li><a class="reference" href="#fast-resume" id="id128" name="id128">fast resume</a><ul>
|
<li><a class="reference" href="#fast-resume" id="id129" name="id129">fast resume</a><ul>
|
||||||
<li><a class="reference" href="#file-format" id="id129" name="id129">file format</a></li>
|
<li><a class="reference" href="#file-format" id="id130" name="id130">file format</a></li>
|
||||||
</ul>
|
</ul>
|
||||||
</li>
|
</li>
|
||||||
<li><a class="reference" href="#threads" id="id130" name="id130">threads</a></li>
|
<li><a class="reference" href="#threads" id="id131" name="id131">threads</a></li>
|
||||||
<li><a class="reference" href="#storage-allocation" id="id131" name="id131">storage allocation</a><ul>
|
<li><a class="reference" href="#storage-allocation" id="id132" name="id132">storage allocation</a><ul>
|
||||||
<li><a class="reference" href="#full-allocation" id="id132" name="id132">full allocation</a></li>
|
<li><a class="reference" href="#full-allocation" id="id133" name="id133">full allocation</a></li>
|
||||||
<li><a class="reference" href="#compact-allocation" id="id133" name="id133">compact allocation</a></li>
|
<li><a class="reference" href="#compact-allocation" id="id134" name="id134">compact allocation</a></li>
|
||||||
</ul>
|
</ul>
|
||||||
</li>
|
</li>
|
||||||
<li><a class="reference" href="#extensions" id="id134" name="id134">extensions</a><ul>
|
<li><a class="reference" href="#extensions" id="id135" name="id135">extensions</a><ul>
|
||||||
<li><a class="reference" href="#chat-messages" id="id135" name="id135">chat messages</a></li>
|
<li><a class="reference" href="#chat-messages" id="id136" name="id136">chat messages</a></li>
|
||||||
<li><a class="reference" href="#metadata-from-peers" id="id136" name="id136">metadata from peers</a></li>
|
<li><a class="reference" href="#metadata-from-peers" id="id137" name="id137">metadata from peers</a></li>
|
||||||
<li><a class="reference" href="#http-seeding" id="id137" name="id137">HTTP seeding</a></li>
|
<li><a class="reference" href="#http-seeding" id="id138" name="id138">HTTP seeding</a></li>
|
||||||
</ul>
|
</ul>
|
||||||
</li>
|
</li>
|
||||||
<li><a class="reference" href="#filename-checks" id="id138" name="id138">filename checks</a></li>
|
<li><a class="reference" href="#filename-checks" id="id139" name="id139">filename checks</a></li>
|
||||||
<li><a class="reference" href="#acknowledgments" id="id139" name="id139">acknowledgments</a></li>
|
<li><a class="reference" href="#acknowledgments" id="id140" name="id140">acknowledgments</a></li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
<div class="section">
|
<div class="section">
|
||||||
|
@ -356,7 +356,7 @@ epoll on linux and kqueue on MacOS X and BSD.</p>
|
||||||
<ul class="simple">
|
<ul class="simple">
|
||||||
<li>Windows 2000 vc7.1</li>
|
<li>Windows 2000 vc7.1</li>
|
||||||
<li>Linux x86 GCC 3.3, GCC 3.4.2</li>
|
<li>Linux x86 GCC 3.3, GCC 3.4.2</li>
|
||||||
<li>MacOS X (darwin), (Apple's) GCC 4.0</li>
|
<li>MacOS X (darwin), (Apple's) GCC 3.3, (Apple's) GCC 4.0</li>
|
||||||
<li>SunOS 5.8 GCC 3.1</li>
|
<li>SunOS 5.8 GCC 3.1</li>
|
||||||
<li>Cygwin GCC 3.3.3</li>
|
<li>Cygwin GCC 3.3.3</li>
|
||||||
</ul>
|
</ul>
|
||||||
|
@ -366,7 +366,6 @@ epoll on linux and kqueue on MacOS X and BSD.</p>
|
||||||
<ul class="simple">
|
<ul class="simple">
|
||||||
<li>GCC 2.95.4</li>
|
<li>GCC 2.95.4</li>
|
||||||
<li>msvc6</li>
|
<li>msvc6</li>
|
||||||
<li>(Apple's) GCC 3.3 (compiler crashes with the latest version of asio)</li>
|
|
||||||
</ul>
|
</ul>
|
||||||
</blockquote>
|
</blockquote>
|
||||||
<p>libtorrent is released under the <a class="reference" href="http://www.opensource.org/licenses/bsd-license.php">BSD-license</a>.</p>
|
<p>libtorrent is released under the <a class="reference" href="http://www.opensource.org/licenses/bsd-license.php">BSD-license</a>.</p>
|
||||||
|
@ -514,6 +513,7 @@ For more build configuration flags see <a class="reference" href="#build-configu
|
||||||
<p>When building the example client on windows, you need to build with
|
<p>When building the example client on windows, you need to build with
|
||||||
<tt class="docutils literal"><span class="pre">link=static</span></tt> otherwise you may get unresolved external symbols for some
|
<tt class="docutils literal"><span class="pre">link=static</span></tt> otherwise you may get unresolved external symbols for some
|
||||||
boost.program-options symbols.</p>
|
boost.program-options symbols.</p>
|
||||||
|
<p>For more information, see the <a class="reference" href="http://www.boost.org/tools/build/v2/index.html">Boost build v2 documentation</a>.</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="section">
|
<div class="section">
|
||||||
|
@ -793,7 +793,7 @@ class session: public boost::noncopyable
|
||||||
<p>Once it's created, the session object will spawn the main thread that will do all the work.
|
<p>Once it's created, the session object will spawn the main thread that will do all the work.
|
||||||
The main thread will be idle as long it doesn't have any torrents to participate in.</p>
|
The main thread will be idle as long it doesn't have any torrents to participate in.</p>
|
||||||
<div class="section">
|
<div class="section">
|
||||||
<h2><a id="id8" name="id8">session()</a></h2>
|
<h2><a id="id9" name="id9">session()</a></h2>
|
||||||
<blockquote>
|
<blockquote>
|
||||||
<pre class="literal-block">
|
<pre class="literal-block">
|
||||||
session(fingerprint const& print = libtorrent::fingerprint("LT", 0, 1, 0, 0));
|
session(fingerprint const& print = libtorrent::fingerprint("LT", 0, 1, 0, 0));
|
||||||
|
@ -812,7 +812,7 @@ will automatically try to listen on a port on the given interface. For more info
|
||||||
the parameters, see <tt class="docutils literal"><span class="pre">listen_on()</span></tt> function.</p>
|
the parameters, see <tt class="docutils literal"><span class="pre">listen_on()</span></tt> function.</p>
|
||||||
</div>
|
</div>
|
||||||
<div class="section">
|
<div class="section">
|
||||||
<h2><a id="id9" name="id9">~session()</a></h2>
|
<h2><a id="id10" name="id10">~session()</a></h2>
|
||||||
<p>The destructor of session will notify all trackers that our torrents have been shut down.
|
<p>The destructor of session will notify all trackers that our torrents have been shut down.
|
||||||
If some trackers are down, they will time out. All this before the destructor of session
|
If some trackers are down, they will time out. All this before the destructor of session
|
||||||
returns. So, it's advised that any kind of interface (such as windows) are closed before
|
returns. So, it's advised that any kind of interface (such as windows) are closed before
|
||||||
|
@ -1252,7 +1252,7 @@ public:
|
||||||
};
|
};
|
||||||
</pre>
|
</pre>
|
||||||
<div class="section">
|
<div class="section">
|
||||||
<h2><a id="id10" name="id10">torrent_info()</a></h2>
|
<h2><a id="id11" name="id11">torrent_info()</a></h2>
|
||||||
<blockquote>
|
<blockquote>
|
||||||
<pre class="literal-block">
|
<pre class="literal-block">
|
||||||
torrent_info();
|
torrent_info();
|
||||||
|
@ -1760,7 +1760,7 @@ sha1_hash info_hash() const;
|
||||||
<p><tt class="docutils literal"><span class="pre">info_hash()</span></tt> returns the info-hash for the torrent.</p>
|
<p><tt class="docutils literal"><span class="pre">info_hash()</span></tt> returns the info-hash for the torrent.</p>
|
||||||
</div>
|
</div>
|
||||||
<div class="section">
|
<div class="section">
|
||||||
<h2><a id="id12" name="id12">set_max_uploads() set_max_connections()</a></h2>
|
<h2><a id="id13" name="id13">set_max_uploads() set_max_connections()</a></h2>
|
||||||
<blockquote>
|
<blockquote>
|
||||||
<pre class="literal-block">
|
<pre class="literal-block">
|
||||||
void set_max_uploads(int max_uploads) const;
|
void set_max_uploads(int max_uploads) const;
|
||||||
|
@ -1809,7 +1809,7 @@ std::vector<char> const& metadata() const;
|
||||||
it will produce the same hash as the info-hash.</p>
|
it will produce the same hash as the info-hash.</p>
|
||||||
</div>
|
</div>
|
||||||
<div class="section">
|
<div class="section">
|
||||||
<h2><a id="id13" name="id13">status()</a></h2>
|
<h2><a id="id14" name="id14">status()</a></h2>
|
||||||
<blockquote>
|
<blockquote>
|
||||||
<pre class="literal-block">
|
<pre class="literal-block">
|
||||||
torrent_status status() const;
|
torrent_status status() const;
|
||||||
|
@ -2325,7 +2325,7 @@ public:
|
||||||
</pre>
|
</pre>
|
||||||
</blockquote>
|
</blockquote>
|
||||||
<div class="section">
|
<div class="section">
|
||||||
<h2><a id="id16" name="id16">ip_filter()</a></h2>
|
<h2><a id="id17" name="id17">ip_filter()</a></h2>
|
||||||
<blockquote>
|
<blockquote>
|
||||||
<pre class="literal-block">
|
<pre class="literal-block">
|
||||||
ip_filter()
|
ip_filter()
|
||||||
|
|
|
@ -86,7 +86,7 @@ libtorrent has been successfully compiled and tested on:
|
||||||
|
|
||||||
* Windows 2000 vc7.1
|
* Windows 2000 vc7.1
|
||||||
* Linux x86 GCC 3.3, GCC 3.4.2
|
* Linux x86 GCC 3.3, GCC 3.4.2
|
||||||
* MacOS X (darwin), (Apple's) GCC 4.0
|
* MacOS X (darwin), (Apple's) GCC 3.3, (Apple's) GCC 4.0
|
||||||
* SunOS 5.8 GCC 3.1
|
* SunOS 5.8 GCC 3.1
|
||||||
* Cygwin GCC 3.3.3
|
* Cygwin GCC 3.3.3
|
||||||
|
|
||||||
|
@ -94,7 +94,6 @@ Fails on:
|
||||||
|
|
||||||
* GCC 2.95.4
|
* GCC 2.95.4
|
||||||
* msvc6
|
* msvc6
|
||||||
* (Apple's) GCC 3.3 (compiler crashes with the latest version of asio)
|
|
||||||
|
|
||||||
libtorrent is released under the BSD-license_.
|
libtorrent is released under the BSD-license_.
|
||||||
|
|
||||||
|
@ -275,6 +274,9 @@ When building the example client on windows, you need to build with
|
||||||
``link=static`` otherwise you may get unresolved external symbols for some
|
``link=static`` otherwise you may get unresolved external symbols for some
|
||||||
boost.program-options symbols.
|
boost.program-options symbols.
|
||||||
|
|
||||||
|
For more information, see the `Boost build v2 documentation`__.
|
||||||
|
|
||||||
|
__ http://www.boost.org/tools/build/v2/index.html
|
||||||
|
|
||||||
building with autotools
|
building with autotools
|
||||||
-----------------------
|
-----------------------
|
||||||
|
|
|
@ -689,14 +689,17 @@ int main(int ac, char* av[])
|
||||||
{
|
{
|
||||||
if (torrent_finished_alert* p = dynamic_cast<torrent_finished_alert*>(a.get()))
|
if (torrent_finished_alert* p = dynamic_cast<torrent_finished_alert*>(a.get()))
|
||||||
{
|
{
|
||||||
// limit the bandwidth for all seeding torrents
|
|
||||||
p->handle.set_max_connections(60);
|
p->handle.set_max_connections(60);
|
||||||
//p->handle.set_max_uploads(5);
|
|
||||||
//p->handle.set_upload_limit(10000);
|
|
||||||
|
|
||||||
// all finished downloades are
|
// write resume data for the finished torrent
|
||||||
// moved into this directory
|
torrent_handle h = p->handle;
|
||||||
//p->handle.move_storage("finished");
|
entry data = h.write_resume_data();
|
||||||
|
std::stringstream s;
|
||||||
|
s << h.get_torrent_info().name() << ".fastresume";
|
||||||
|
boost::filesystem::ofstream out(h.save_path() / s.str(), std::ios_base::binary);
|
||||||
|
out.unsetf(std::ios_base::skipws);
|
||||||
|
bencode(std::ostream_iterator<char>(out), data);
|
||||||
|
|
||||||
events.push_back(now + ": "
|
events.push_back(now + ": "
|
||||||
+ p->handle.get_torrent_info().name() + ": " + a->msg());
|
+ p->handle.get_torrent_info().name() + ": " + a->msg());
|
||||||
}
|
}
|
||||||
|
@ -794,13 +797,8 @@ int main(int ac, char* av[])
|
||||||
out << "tracker: " << s.current_tracker << "\n";
|
out << "tracker: " << s.current_tracker << "\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
out << "___________________________________\n";
|
|
||||||
|
|
||||||
if (print_peers && !peers.empty())
|
if (print_peers && !peers.empty())
|
||||||
{
|
|
||||||
print_peer_info(out, peers);
|
print_peer_info(out, peers);
|
||||||
out << "___________________________________\n";
|
|
||||||
}
|
|
||||||
|
|
||||||
if (print_downloads && s.state != torrent_status::seeding)
|
if (print_downloads && s.state != torrent_status::seeding)
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
pkginclude_HEADERS = libtorrent/alert.hpp \
|
nobase_pkginclude_HEADERS = libtorrent/alert.hpp \
|
||||||
libtorrent/alert_types.hpp \
|
libtorrent/alert_types.hpp \
|
||||||
libtorrent/allocate_resources.hpp \
|
libtorrent/allocate_resources.hpp \
|
||||||
libtorrent/bencode.hpp \
|
libtorrent/bencode.hpp \
|
||||||
|
|
|
@ -52,6 +52,7 @@ POSSIBILITY OF SUCH DAMAGE.
|
||||||
#include <boost/date_time/posix_time/posix_time.hpp>
|
#include <boost/date_time/posix_time/posix_time.hpp>
|
||||||
#include <boost/optional.hpp>
|
#include <boost/optional.hpp>
|
||||||
#include <boost/cstdint.hpp>
|
#include <boost/cstdint.hpp>
|
||||||
|
#include <boost/detail/atomic_count.hpp>
|
||||||
|
|
||||||
#ifdef _MSC_VER
|
#ifdef _MSC_VER
|
||||||
#pragma warning(pop)
|
#pragma warning(pop)
|
||||||
|
@ -540,7 +541,7 @@ namespace libtorrent
|
||||||
bool m_reading;
|
bool m_reading;
|
||||||
int m_last_read_size;
|
int m_last_read_size;
|
||||||
// reference counter for intrusive_ptr
|
// reference counter for intrusive_ptr
|
||||||
mutable int m_refs;
|
mutable boost::detail::atomic_count m_refs;
|
||||||
|
|
||||||
#ifndef NDEBUG
|
#ifndef NDEBUG
|
||||||
public:
|
public:
|
||||||
|
|
|
@ -179,6 +179,10 @@ namespace libtorrent
|
||||||
return m_num_unchoked;
|
return m_num_unchoked;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
typedef std::vector<peer>::iterator iterator;
|
||||||
|
iterator begin_peer() { return m_peers.begin(); }
|
||||||
|
iterator end_peer() { return m_peers.end(); }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
bool unchoke_one_peer();
|
bool unchoke_one_peer();
|
||||||
|
@ -209,6 +213,7 @@ namespace libtorrent
|
||||||
|
|
||||||
ptime not_tried_yet(boost::gregorian::date(1970,boost::gregorian::Jan,1));
|
ptime not_tried_yet(boost::gregorian::date(1970,boost::gregorian::Jan,1));
|
||||||
|
|
||||||
|
// this timeout has to be customizable!
|
||||||
return p.connection == 0
|
return p.connection == 0
|
||||||
&& p.connected != not_tried_yet
|
&& p.connected != not_tried_yet
|
||||||
&& second_clock::universal_time() - p.connected > minutes(30);
|
&& second_clock::universal_time() - p.connected > minutes(30);
|
||||||
|
|
|
@ -360,9 +360,14 @@ namespace libtorrent
|
||||||
assert(m_picker.get());
|
assert(m_picker.get());
|
||||||
return *m_picker;
|
return *m_picker;
|
||||||
}
|
}
|
||||||
policy& get_policy() { return *m_policy; }
|
policy& get_policy()
|
||||||
|
{
|
||||||
|
assert(m_policy);
|
||||||
|
return *m_policy;
|
||||||
|
}
|
||||||
piece_manager& filesystem();
|
piece_manager& filesystem();
|
||||||
torrent_info const& torrent_file() const { return m_torrent_file; }
|
torrent_info const& torrent_file() const
|
||||||
|
{ return m_torrent_file; }
|
||||||
|
|
||||||
std::vector<announce_entry> const& trackers() const
|
std::vector<announce_entry> const& trackers() const
|
||||||
{ return m_trackers; }
|
{ return m_trackers; }
|
||||||
|
|
|
@ -375,7 +375,7 @@ namespace libtorrent
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
tcp::resolver::query q(*connect_to_host, "http");
|
tcp::resolver::query q(*connect_to_host, "https");
|
||||||
m_name_lookup.async_resolve(q
|
m_name_lookup.async_resolve(q
|
||||||
, boost::bind(&http_tracker_connection::name_lookup, self(), _1, _2));
|
, boost::bind(&http_tracker_connection::name_lookup, self(), _1, _2));
|
||||||
set_timeout(m_settings.tracker_completion_timeout
|
set_timeout(m_settings.tracker_completion_timeout
|
||||||
|
|
|
@ -65,8 +65,7 @@ namespace libtorrent
|
||||||
{
|
{
|
||||||
assert(c->m_refs > 0);
|
assert(c->m_refs > 0);
|
||||||
assert(c != 0);
|
assert(c != 0);
|
||||||
--c->m_refs;
|
if (--c->m_refs == 0)
|
||||||
if (c->m_refs == 0)
|
|
||||||
delete c;
|
delete c;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -467,7 +466,11 @@ namespace libtorrent
|
||||||
|
|
||||||
boost::shared_ptr<torrent> t = m_torrent.lock();
|
boost::shared_ptr<torrent> t = m_torrent.lock();
|
||||||
|
|
||||||
if (t && t->is_aborted()) { m_torrent.reset(); t.reset(); }
|
if (t && t->is_aborted())
|
||||||
|
{
|
||||||
|
m_torrent.reset();
|
||||||
|
t.reset();
|
||||||
|
}
|
||||||
|
|
||||||
if (!t)
|
if (!t)
|
||||||
{
|
{
|
||||||
|
@ -1669,6 +1672,7 @@ namespace libtorrent
|
||||||
assert(packet_size > 0);
|
assert(packet_size > 0);
|
||||||
m_recv_pos = 0;
|
m_recv_pos = 0;
|
||||||
m_packet_size = packet_size;
|
m_packet_size = packet_size;
|
||||||
|
if (int(m_recv_buffer.size()) < m_packet_size)
|
||||||
m_recv_buffer.resize(m_packet_size);
|
m_recv_buffer.resize(m_packet_size);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1830,6 +1834,11 @@ namespace libtorrent
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// the connection cannot time out while connecting
|
||||||
|
// so we don't need to check m_disconnecting
|
||||||
|
assert(m_disconnecting == false);
|
||||||
|
m_last_receive = second_clock::universal_time();
|
||||||
|
|
||||||
// this means the connection just succeeded
|
// this means the connection just succeeded
|
||||||
|
|
||||||
#if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING)
|
#if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING)
|
||||||
|
@ -1914,7 +1923,17 @@ namespace libtorrent
|
||||||
void peer_connection::check_invariant() const
|
void peer_connection::check_invariant() const
|
||||||
{
|
{
|
||||||
boost::shared_ptr<torrent> t = m_torrent.lock();
|
boost::shared_ptr<torrent> t = m_torrent.lock();
|
||||||
if (!t) return;
|
if (!t)
|
||||||
|
{
|
||||||
|
typedef detail::session_impl::torrent_map torrent_map;
|
||||||
|
torrent_map& m = m_ses.m_torrents;
|
||||||
|
for (torrent_map::iterator i = m.begin(), end(m.end()); i != end; ++i)
|
||||||
|
{
|
||||||
|
torrent& t = *i->second;
|
||||||
|
assert(t.connection_for(m_remote) != this);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (!m_in_constructor && t->connection_for(remote()) != this)
|
if (!m_in_constructor && t->connection_for(remote()) != this)
|
||||||
{
|
{
|
||||||
|
|
|
@ -829,7 +829,7 @@ namespace libtorrent
|
||||||
|
|
||||||
if (i == m_peers.end())
|
if (i == m_peers.end())
|
||||||
{
|
{
|
||||||
// this is probably a http seed
|
// this is probably an http seed
|
||||||
if (web_peer_connection const* p = dynamic_cast<web_peer_connection const*>(&c))
|
if (web_peer_connection const* p = dynamic_cast<web_peer_connection const*>(&c))
|
||||||
{
|
{
|
||||||
m_torrent->remove_url_seed(p->url());
|
m_torrent->remove_url_seed(p->url());
|
||||||
|
|
136
src/session.cpp
136
src/session.cpp
|
@ -117,21 +117,39 @@ namespace libtorrent { namespace detail
|
||||||
if (m_torrents.empty() && !m_abort && !processing)
|
if (m_torrents.empty() && !m_abort && !processing)
|
||||||
m_cond.wait(l);
|
m_cond.wait(l);
|
||||||
|
|
||||||
if (m_abort) return;
|
if (m_abort)
|
||||||
|
{
|
||||||
|
// no lock is needed here, because the main thread
|
||||||
|
// has already been shut down by now
|
||||||
|
processing.reset();
|
||||||
|
t.reset();
|
||||||
|
std::for_each(m_torrents.begin(), m_torrents.end()
|
||||||
|
, boost::bind(&torrent::abort
|
||||||
|
, boost::bind(&shared_ptr<torrent>::get
|
||||||
|
, boost::bind(&piece_checker_data::torrent_ptr, _1))));
|
||||||
|
m_torrents.clear();
|
||||||
|
std::for_each(m_processing.begin(), m_processing.end()
|
||||||
|
, boost::bind(&torrent::abort
|
||||||
|
, boost::bind(&shared_ptr<torrent>::get
|
||||||
|
, boost::bind(&piece_checker_data::torrent_ptr, _1))));
|
||||||
|
m_processing.clear();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (!m_torrents.empty())
|
if (!m_torrents.empty())
|
||||||
{
|
{
|
||||||
t = m_torrents.front();
|
t = m_torrents.front();
|
||||||
if (t->abort)
|
if (t->abort)
|
||||||
{
|
{
|
||||||
if (processing->torrent_ptr->num_peers())
|
// make sure the locking order is
|
||||||
{
|
// consistent to avoid dead locks
|
||||||
m_ses.m_torrents.insert(std::make_pair(
|
// we need to lock the session because closing
|
||||||
t->info_hash, t->torrent_ptr));
|
// torrents assume to have access to it
|
||||||
|
l.unlock();
|
||||||
|
session_impl::mutex_t::scoped_lock l2(m_ses.m_mutex);
|
||||||
|
l.lock();
|
||||||
|
|
||||||
t->torrent_ptr->abort();
|
t->torrent_ptr->abort();
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
m_torrents.pop_front();
|
m_torrents.pop_front();
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -145,12 +163,11 @@ namespace libtorrent { namespace detail
|
||||||
|
|
||||||
if (!error_msg.empty() && m_ses.m_alerts.should_post(alert::warning))
|
if (!error_msg.empty() && m_ses.m_alerts.should_post(alert::warning))
|
||||||
{
|
{
|
||||||
session_impl::mutex_t::scoped_lock l2(m_ses.m_mutex);
|
session_impl::mutex_t::scoped_lock l(m_ses.m_mutex);
|
||||||
m_ses.m_alerts.post_alert(fastresume_rejected_alert(
|
m_ses.m_alerts.post_alert(fastresume_rejected_alert(
|
||||||
t->torrent_ptr->get_handle()
|
t->torrent_ptr->get_handle()
|
||||||
, error_msg));
|
, error_msg));
|
||||||
#if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING)
|
#if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING)
|
||||||
session_impl::mutex_t::scoped_lock l(m_ses.m_mutex);
|
|
||||||
(*m_ses.m_logger) << "fastresume data for "
|
(*m_ses.m_logger) << "fastresume data for "
|
||||||
<< t->torrent_ptr->torrent_file().name() << " rejected: "
|
<< t->torrent_ptr->torrent_file().name() << " rejected: "
|
||||||
<< error_msg << "\n";
|
<< error_msg << "\n";
|
||||||
|
@ -172,6 +189,10 @@ namespace libtorrent { namespace detail
|
||||||
|
|
||||||
t->torrent_ptr->files_checked(t->unfinished_pieces);
|
t->torrent_ptr->files_checked(t->unfinished_pieces);
|
||||||
m_torrents.pop_front();
|
m_torrents.pop_front();
|
||||||
|
|
||||||
|
// we cannot add the torrent if the session is aborted.
|
||||||
|
if (!m_ses.m_abort)
|
||||||
|
{
|
||||||
m_ses.m_torrents.insert(std::make_pair(t->info_hash, t->torrent_ptr));
|
m_ses.m_torrents.insert(std::make_pair(t->info_hash, t->torrent_ptr));
|
||||||
if (t->torrent_ptr->is_seed() && m_ses.m_alerts.should_post(alert::info))
|
if (t->torrent_ptr->is_seed() && m_ses.m_alerts.should_post(alert::info))
|
||||||
{
|
{
|
||||||
|
@ -187,6 +208,12 @@ namespace libtorrent { namespace detail
|
||||||
{
|
{
|
||||||
t->torrent_ptr->get_policy().peer_from_tracker(*i, id);
|
t->torrent_ptr->get_policy().peer_from_tracker(*i, id);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
t->torrent_ptr->abort();
|
||||||
|
}
|
||||||
|
t.reset();
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -202,6 +229,7 @@ namespace libtorrent { namespace detail
|
||||||
{
|
{
|
||||||
processing = t;
|
processing = t;
|
||||||
processing->processing = true;
|
processing->processing = true;
|
||||||
|
t.reset();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -219,12 +247,7 @@ namespace libtorrent { namespace detail
|
||||||
t->torrent_ptr->get_handle()
|
t->torrent_ptr->get_handle()
|
||||||
, e.what()));
|
, e.what()));
|
||||||
}
|
}
|
||||||
if (t->torrent_ptr->num_peers())
|
|
||||||
{
|
|
||||||
m_ses.m_torrents.insert(std::make_pair(
|
|
||||||
t->info_hash, t->torrent_ptr));
|
|
||||||
t->torrent_ptr->abort();
|
t->torrent_ptr->abort();
|
||||||
}
|
|
||||||
|
|
||||||
assert(!m_torrents.empty());
|
assert(!m_torrents.empty());
|
||||||
m_torrents.pop_front();
|
m_torrents.pop_front();
|
||||||
|
@ -258,12 +281,7 @@ namespace libtorrent { namespace detail
|
||||||
assert(!m_processing.empty());
|
assert(!m_processing.empty());
|
||||||
assert(m_processing.front() == processing);
|
assert(m_processing.front() == processing);
|
||||||
|
|
||||||
if (processing->torrent_ptr->num_peers())
|
|
||||||
{
|
|
||||||
m_ses.m_torrents.insert(std::make_pair(
|
|
||||||
processing->info_hash, processing->torrent_ptr));
|
|
||||||
processing->torrent_ptr->abort();
|
processing->torrent_ptr->abort();
|
||||||
}
|
|
||||||
|
|
||||||
processing.reset();
|
processing.reset();
|
||||||
m_processing.pop_front();
|
m_processing.pop_front();
|
||||||
|
@ -284,6 +302,11 @@ namespace libtorrent { namespace detail
|
||||||
assert(!m_processing.empty());
|
assert(!m_processing.empty());
|
||||||
assert(m_processing.front() == processing);
|
assert(m_processing.front() == processing);
|
||||||
|
|
||||||
|
// TODO: factor out the adding of torrents to the session
|
||||||
|
// and to the checker thread to avoid duplicating the
|
||||||
|
// check for abortion.
|
||||||
|
if (!m_ses.m_abort)
|
||||||
|
{
|
||||||
processing->torrent_ptr->files_checked(processing->unfinished_pieces);
|
processing->torrent_ptr->files_checked(processing->unfinished_pieces);
|
||||||
m_ses.m_torrents.insert(std::make_pair(
|
m_ses.m_torrents.insert(std::make_pair(
|
||||||
processing->info_hash, processing->torrent_ptr));
|
processing->info_hash, processing->torrent_ptr));
|
||||||
|
@ -302,6 +325,11 @@ namespace libtorrent { namespace detail
|
||||||
{
|
{
|
||||||
processing->torrent_ptr->get_policy().peer_from_tracker(*i, id);
|
processing->torrent_ptr->get_policy().peer_from_tracker(*i, id);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
processing->torrent_ptr->abort();
|
||||||
|
}
|
||||||
processing.reset();
|
processing.reset();
|
||||||
m_processing.pop_front();
|
m_processing.pop_front();
|
||||||
if (!m_processing.empty())
|
if (!m_processing.empty())
|
||||||
|
@ -311,7 +339,7 @@ namespace libtorrent { namespace detail
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch(const std::exception& e)
|
catch(std::exception const& e)
|
||||||
{
|
{
|
||||||
// This will happen if the storage fails to initialize
|
// This will happen if the storage fails to initialize
|
||||||
session_impl::mutex_t::scoped_lock l(m_ses.m_mutex);
|
session_impl::mutex_t::scoped_lock l(m_ses.m_mutex);
|
||||||
|
@ -326,12 +354,7 @@ namespace libtorrent { namespace detail
|
||||||
}
|
}
|
||||||
assert(!m_processing.empty());
|
assert(!m_processing.empty());
|
||||||
|
|
||||||
if (processing->torrent_ptr->num_peers())
|
|
||||||
{
|
|
||||||
m_ses.m_torrents.insert(std::make_pair(
|
|
||||||
processing->info_hash, processing->torrent_ptr));
|
|
||||||
processing->torrent_ptr->abort();
|
processing->torrent_ptr->abort();
|
||||||
}
|
|
||||||
|
|
||||||
processing.reset();
|
processing.reset();
|
||||||
m_processing.pop_front();
|
m_processing.pop_front();
|
||||||
|
@ -604,6 +627,8 @@ namespace libtorrent { namespace detail
|
||||||
mutex_t::scoped_lock l(m_mutex);
|
mutex_t::scoped_lock l(m_mutex);
|
||||||
assert(listen_socket.lock() == m_listen_socket);
|
assert(listen_socket.lock() == m_listen_socket);
|
||||||
|
|
||||||
|
if (m_abort) return;
|
||||||
|
|
||||||
async_accept();
|
async_accept();
|
||||||
if (e)
|
if (e)
|
||||||
{
|
{
|
||||||
|
@ -715,6 +740,7 @@ namespace libtorrent { namespace detail
|
||||||
if (p->is_connecting())
|
if (p->is_connecting())
|
||||||
{
|
{
|
||||||
assert(p->is_local());
|
assert(p->is_local());
|
||||||
|
assert(m_connections.find(p->get_socket()) == m_connections.end());
|
||||||
// Since this peer is still connecting, will not be
|
// Since this peer is still connecting, will not be
|
||||||
// in the list of completed connections.
|
// in the list of completed connections.
|
||||||
connection_map::iterator i = m_half_open.find(p->get_socket());
|
connection_map::iterator i = m_half_open.find(p->get_socket());
|
||||||
|
@ -725,6 +751,7 @@ namespace libtorrent { namespace detail
|
||||||
connection_queue::iterator j = std::find(
|
connection_queue::iterator j = std::find(
|
||||||
m_connection_queue.begin(), m_connection_queue.end(), p);
|
m_connection_queue.begin(), m_connection_queue.end(), p);
|
||||||
|
|
||||||
|
assert(j != m_connection_queue.end());
|
||||||
if (j != m_connection_queue.end())
|
if (j != m_connection_queue.end())
|
||||||
m_connection_queue.erase(j);
|
m_connection_queue.erase(j);
|
||||||
}
|
}
|
||||||
|
@ -736,7 +763,11 @@ namespace libtorrent { namespace detail
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
assert(m_half_open.find(p->get_socket()) == m_half_open.end());
|
||||||
|
assert(std::find(m_connection_queue.begin()
|
||||||
|
, m_connection_queue.end(), p) == m_connection_queue.end());
|
||||||
connection_map::iterator i = m_connections.find(p->get_socket());
|
connection_map::iterator i = m_connections.find(p->get_socket());
|
||||||
|
// assert (i != m_connections.end());
|
||||||
if (i != m_connections.end())
|
if (i != m_connections.end())
|
||||||
m_connections.erase(i);
|
m_connections.erase(i);
|
||||||
}
|
}
|
||||||
|
@ -744,6 +775,8 @@ namespace libtorrent { namespace detail
|
||||||
|
|
||||||
void session_impl::second_tick(asio::error const& e) try
|
void session_impl::second_tick(asio::error const& e) try
|
||||||
{
|
{
|
||||||
|
session_impl::mutex_t::scoped_lock l(m_mutex);
|
||||||
|
|
||||||
if (e)
|
if (e)
|
||||||
{
|
{
|
||||||
#if defined(TORRENT_LOGGING)
|
#if defined(TORRENT_LOGGING)
|
||||||
|
@ -754,8 +787,6 @@ namespace libtorrent { namespace detail
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
session_impl::mutex_t::scoped_lock l(m_mutex);
|
|
||||||
|
|
||||||
if (m_abort) return;
|
if (m_abort) return;
|
||||||
float tick_interval = (microsec_clock::universal_time()
|
float tick_interval = (microsec_clock::universal_time()
|
||||||
- m_last_tick).total_milliseconds() / 1000.f;
|
- m_last_tick).total_milliseconds() / 1000.f;
|
||||||
|
@ -777,26 +808,27 @@ namespace libtorrent { namespace detail
|
||||||
++i;
|
++i;
|
||||||
// if this socket has timed out
|
// if this socket has timed out
|
||||||
// close it.
|
// close it.
|
||||||
if (j->second->has_timed_out())
|
peer_connection& c = *j->second;
|
||||||
|
if (c.has_timed_out())
|
||||||
{
|
{
|
||||||
if (m_alerts.should_post(alert::debug))
|
if (m_alerts.should_post(alert::debug))
|
||||||
{
|
{
|
||||||
m_alerts.post_alert(
|
m_alerts.post_alert(
|
||||||
peer_error_alert(
|
peer_error_alert(
|
||||||
j->second->remote()
|
c.remote()
|
||||||
, j->second->pid()
|
, c.pid()
|
||||||
, "connection timed out"));
|
, "connection timed out"));
|
||||||
}
|
}
|
||||||
#if defined(TORRENT_VERBOSE_LOGGING)
|
#if defined(TORRENT_VERBOSE_LOGGING)
|
||||||
(*j->second->m_logger) << "*** CONNECTION TIMED OUT\n";
|
(*c.m_logger) << "*** CONNECTION TIMED OUT\n";
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
j->second->set_failed();
|
c.set_failed();
|
||||||
j->second->disconnect();
|
c.disconnect();
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
j->second->keep_alive();
|
c.keep_alive();
|
||||||
}
|
}
|
||||||
|
|
||||||
// check each torrent for tracker updates
|
// check each torrent for tracker updates
|
||||||
|
@ -923,8 +955,8 @@ namespace libtorrent { namespace detail
|
||||||
}
|
}
|
||||||
catch (std::exception& e)
|
catch (std::exception& e)
|
||||||
{
|
{
|
||||||
std::cerr << e.what() << "\n";
|
|
||||||
#ifndef NDEBUG
|
#ifndef NDEBUG
|
||||||
|
std::cerr << e.what() << "\n";
|
||||||
std::string err = e.what();
|
std::string err = e.what();
|
||||||
#endif
|
#endif
|
||||||
assert(false);
|
assert(false);
|
||||||
|
@ -955,8 +987,23 @@ namespace libtorrent { namespace detail
|
||||||
m_selector.reset();
|
m_selector.reset();
|
||||||
m_selector.run();
|
m_selector.run();
|
||||||
|
|
||||||
m_torrents.clear();
|
session_impl::mutex_t::scoped_lock l(m_mutex);
|
||||||
|
assert(m_abort);
|
||||||
|
m_abort = true;
|
||||||
|
|
||||||
m_connections.clear();
|
m_connections.clear();
|
||||||
|
m_half_open.clear();
|
||||||
|
m_connection_queue.clear();
|
||||||
|
|
||||||
|
#ifndef NDEBUG
|
||||||
|
for (torrent_map::iterator i = m_torrents.begin();
|
||||||
|
i != m_torrents.end(); ++i)
|
||||||
|
{
|
||||||
|
assert(i->second->num_peers() == 0);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
m_torrents.clear();
|
||||||
|
|
||||||
assert(m_torrents.empty());
|
assert(m_torrents.empty());
|
||||||
assert(m_connections.empty());
|
assert(m_connections.empty());
|
||||||
|
@ -1263,6 +1310,9 @@ namespace libtorrent
|
||||||
if (!m_impl.find_torrent(info_hash).expired())
|
if (!m_impl.find_torrent(info_hash).expired())
|
||||||
throw duplicate_torrent();
|
throw duplicate_torrent();
|
||||||
|
|
||||||
|
// you cannot add new torrents to a session that is closing down
|
||||||
|
assert(!m_impl.m_abort);
|
||||||
|
|
||||||
// create the torrent and the data associated with
|
// create the torrent and the data associated with
|
||||||
// the checker thread and store it before starting
|
// the checker thread and store it before starting
|
||||||
// the thread
|
// the thread
|
||||||
|
@ -1407,6 +1457,14 @@ namespace libtorrent
|
||||||
m_impl.m_abort = true;
|
m_impl.m_abort = true;
|
||||||
m_impl.m_selector.interrupt();
|
m_impl.m_selector.interrupt();
|
||||||
}
|
}
|
||||||
|
m_thread.join();
|
||||||
|
|
||||||
|
// it's important that the main thread is closed completely before
|
||||||
|
// the checker thread is terminated. Because all the connections
|
||||||
|
// have to be closed and removed from the torrents before they
|
||||||
|
// can be destructed. (because the weak pointers in the
|
||||||
|
// peer_connections will be invalidated when the torrents are
|
||||||
|
// destructed and then the invariant will be broken).
|
||||||
|
|
||||||
{
|
{
|
||||||
mutex::scoped_lock l(m_checker_impl.m_mutex);
|
mutex::scoped_lock l(m_checker_impl.m_mutex);
|
||||||
|
@ -1421,8 +1479,10 @@ namespace libtorrent
|
||||||
m_checker_impl.m_cond.notify_one();
|
m_checker_impl.m_cond.notify_one();
|
||||||
}
|
}
|
||||||
|
|
||||||
m_thread.join();
|
|
||||||
m_checker_thread.join();
|
m_checker_thread.join();
|
||||||
|
|
||||||
|
assert(m_impl.m_torrents.empty());
|
||||||
|
assert(m_impl.m_connections.empty());
|
||||||
}
|
}
|
||||||
|
|
||||||
void session::set_max_uploads(int limit)
|
void session::set_max_uploads(int limit)
|
||||||
|
|
|
@ -372,6 +372,17 @@ namespace libtorrent
|
||||||
|
|
||||||
torrent::~torrent()
|
torrent::~torrent()
|
||||||
{
|
{
|
||||||
|
// The invariant can't be maintained here, since the torrent
|
||||||
|
// is being destructed, all weak references to it have been
|
||||||
|
// reset, which means that all its peers already have an
|
||||||
|
// invalidated torrent pointer (so it cannot be verified to be correct)
|
||||||
|
|
||||||
|
// i.e. the invariant can only be maintained if all connections have
|
||||||
|
// been closed by the time the torrent is destructed. And they are
|
||||||
|
// supposed to be closed. So we can still do the invariant check.
|
||||||
|
|
||||||
|
assert(m_connections.empty());
|
||||||
|
|
||||||
INVARIANT_CHECK;
|
INVARIANT_CHECK;
|
||||||
|
|
||||||
if (m_ses.m_abort)
|
if (m_ses.m_abort)
|
||||||
|
@ -523,6 +534,8 @@ namespace libtorrent
|
||||||
// been filtered as not wanted we have downloaded
|
// been filtered as not wanted we have downloaded
|
||||||
tuple<size_type, size_type> torrent::bytes_done() const
|
tuple<size_type, size_type> torrent::bytes_done() const
|
||||||
{
|
{
|
||||||
|
INVARIANT_CHECK;
|
||||||
|
|
||||||
if (!valid_metadata()) return tuple<size_type, size_type>(0,0);
|
if (!valid_metadata()) return tuple<size_type, size_type>(0,0);
|
||||||
|
|
||||||
assert(m_picker.get());
|
assert(m_picker.get());
|
||||||
|
@ -796,6 +809,8 @@ namespace libtorrent
|
||||||
|
|
||||||
void torrent::filtered_pieces(std::vector<bool>& bitmask) const
|
void torrent::filtered_pieces(std::vector<bool>& bitmask) const
|
||||||
{
|
{
|
||||||
|
INVARIANT_CHECK;
|
||||||
|
|
||||||
// this call is only valid on torrents with metadata
|
// this call is only valid on torrents with metadata
|
||||||
assert(m_picker.get());
|
assert(m_picker.get());
|
||||||
m_picker->filtered_pieces(bitmask);
|
m_picker->filtered_pieces(bitmask);
|
||||||
|
@ -803,6 +818,8 @@ namespace libtorrent
|
||||||
|
|
||||||
void torrent::filter_files(std::vector<bool> const& bitmask)
|
void torrent::filter_files(std::vector<bool> const& bitmask)
|
||||||
{
|
{
|
||||||
|
INVARIANT_CHECK;
|
||||||
|
|
||||||
// this call is only valid on torrents with metadata
|
// this call is only valid on torrents with metadata
|
||||||
if (!valid_metadata()) return;
|
if (!valid_metadata()) return;
|
||||||
|
|
||||||
|
@ -970,6 +987,8 @@ namespace libtorrent
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (m_ses.m_abort) return;
|
||||||
|
|
||||||
tcp::endpoint a(host->endpoint().address(), port);
|
tcp::endpoint a(host->endpoint().address(), port);
|
||||||
|
|
||||||
boost::shared_ptr<stream_socket> s(new stream_socket(m_ses.m_selector));
|
boost::shared_ptr<stream_socket> s(new stream_socket(m_ses.m_selector));
|
||||||
|
@ -1073,6 +1092,10 @@ namespace libtorrent
|
||||||
throw protocol_error("peer is not properly constructed");
|
throw protocol_error("peer is not properly constructed");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (m_ses.m_abort)
|
||||||
|
{
|
||||||
|
throw protocol_error("session is closing");
|
||||||
|
}
|
||||||
|
|
||||||
peer_iterator i = m_connections.insert(
|
peer_iterator i = m_connections.insert(
|
||||||
std::make_pair(p->remote(), p)).first;
|
std::make_pair(p->remote(), p)).first;
|
||||||
|
@ -1158,6 +1181,8 @@ namespace libtorrent
|
||||||
// called when torrent is complete (all pieces downloaded)
|
// called when torrent is complete (all pieces downloaded)
|
||||||
void torrent::completed()
|
void torrent::completed()
|
||||||
{
|
{
|
||||||
|
INVARIANT_CHECK;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
if (alerts().should_post(alert::info))
|
if (alerts().should_post(alert::info))
|
||||||
{
|
{
|
||||||
|
@ -1177,6 +1202,8 @@ namespace libtorrent
|
||||||
// the begining) and return the new index to the tracker.
|
// the begining) and return the new index to the tracker.
|
||||||
int torrent::prioritize_tracker(int index)
|
int torrent::prioritize_tracker(int index)
|
||||||
{
|
{
|
||||||
|
INVARIANT_CHECK;
|
||||||
|
|
||||||
assert(index >= 0);
|
assert(index >= 0);
|
||||||
if (index >= (int)m_trackers.size()) return (int)m_trackers.size()-1;
|
if (index >= (int)m_trackers.size()) return (int)m_trackers.size()-1;
|
||||||
|
|
||||||
|
@ -1294,6 +1321,8 @@ namespace libtorrent
|
||||||
|
|
||||||
bool torrent::move_storage(boost::filesystem::path const& save_path)
|
bool torrent::move_storage(boost::filesystem::path const& save_path)
|
||||||
{
|
{
|
||||||
|
INVARIANT_CHECK;
|
||||||
|
|
||||||
bool ret = true;
|
bool ret = true;
|
||||||
if (m_storage.get())
|
if (m_storage.get())
|
||||||
{
|
{
|
||||||
|
@ -1309,6 +1338,8 @@ namespace libtorrent
|
||||||
|
|
||||||
piece_manager& torrent::filesystem()
|
piece_manager& torrent::filesystem()
|
||||||
{
|
{
|
||||||
|
INVARIANT_CHECK;
|
||||||
|
|
||||||
assert(m_storage.get());
|
assert(m_storage.get());
|
||||||
return *m_storage;
|
return *m_storage;
|
||||||
}
|
}
|
||||||
|
@ -1316,11 +1347,15 @@ namespace libtorrent
|
||||||
|
|
||||||
torrent_handle torrent::get_handle() const
|
torrent_handle torrent::get_handle() const
|
||||||
{
|
{
|
||||||
|
INVARIANT_CHECK;
|
||||||
|
|
||||||
return torrent_handle(&m_ses, 0, m_torrent_file.info_hash());
|
return torrent_handle(&m_ses, 0, m_torrent_file.info_hash());
|
||||||
}
|
}
|
||||||
|
|
||||||
session_settings const& torrent::settings() const
|
session_settings const& torrent::settings() const
|
||||||
{
|
{
|
||||||
|
INVARIANT_CHECK;
|
||||||
|
|
||||||
return m_ses.m_settings;
|
return m_ses.m_settings;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1331,7 +1366,12 @@ namespace libtorrent
|
||||||
// size_type done = boost::get<0>(bytes_done());
|
// size_type done = boost::get<0>(bytes_done());
|
||||||
// assert(download >= done - m_initial_done);
|
// assert(download >= done - m_initial_done);
|
||||||
for (const_peer_iterator i = begin(); i != end(); ++i)
|
for (const_peer_iterator i = begin(); i != end(); ++i)
|
||||||
assert(i->second->associated_torrent().lock().get() == this);
|
{
|
||||||
|
peer_connection const& p = *i->second;
|
||||||
|
torrent* associated_torrent = p.associated_torrent().lock().get();
|
||||||
|
if (associated_torrent != this)
|
||||||
|
assert(false);
|
||||||
|
}
|
||||||
|
|
||||||
// This check is very expensive.
|
// This check is very expensive.
|
||||||
// assert(m_num_pieces
|
// assert(m_num_pieces
|
||||||
|
@ -1857,6 +1897,8 @@ namespace libtorrent
|
||||||
|
|
||||||
std::pair<int, int> torrent::metadata_request()
|
std::pair<int, int> torrent::metadata_request()
|
||||||
{
|
{
|
||||||
|
INVARIANT_CHECK;
|
||||||
|
|
||||||
// count the number of peers that supports the
|
// count the number of peers that supports the
|
||||||
// extension and that has metadata
|
// extension and that has metadata
|
||||||
int peers = 0;
|
int peers = 0;
|
||||||
|
@ -1909,6 +1951,8 @@ namespace libtorrent
|
||||||
|
|
||||||
void torrent::cancel_metadata_request(std::pair<int, int> req)
|
void torrent::cancel_metadata_request(std::pair<int, int> req)
|
||||||
{
|
{
|
||||||
|
INVARIANT_CHECK;
|
||||||
|
|
||||||
for (int i = req.first; i < req.first + req.second; ++i)
|
for (int i = req.first; i < req.first + req.second; ++i)
|
||||||
{
|
{
|
||||||
assert(m_requested_metadata[i] > 0);
|
assert(m_requested_metadata[i] > 0);
|
||||||
|
@ -1921,9 +1965,12 @@ namespace libtorrent
|
||||||
tracker_request const&)
|
tracker_request const&)
|
||||||
{
|
{
|
||||||
session_impl::mutex_t::scoped_lock l(m_ses.m_mutex);
|
session_impl::mutex_t::scoped_lock l(m_ses.m_mutex);
|
||||||
|
INVARIANT_CHECK;
|
||||||
|
|
||||||
#if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING)
|
#if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING)
|
||||||
debug_log("*** tracker timed out");
|
debug_log("*** tracker timed out");
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (m_ses.m_alerts.should_post(alert::warning))
|
if (m_ses.m_alerts.should_post(alert::warning))
|
||||||
{
|
{
|
||||||
std::stringstream s;
|
std::stringstream s;
|
||||||
|
@ -1942,6 +1989,8 @@ namespace libtorrent
|
||||||
void torrent::tracker_request_error(tracker_request const&
|
void torrent::tracker_request_error(tracker_request const&
|
||||||
, int response_code, const std::string& str)
|
, int response_code, const std::string& str)
|
||||||
{
|
{
|
||||||
|
INVARIANT_CHECK;
|
||||||
|
|
||||||
session_impl::mutex_t::scoped_lock l(m_ses.m_mutex);
|
session_impl::mutex_t::scoped_lock l(m_ses.m_mutex);
|
||||||
#if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING)
|
#if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING)
|
||||||
debug_log(std::string("*** tracker error: ") + str);
|
debug_log(std::string("*** tracker error: ") + str);
|
||||||
|
@ -1956,7 +2005,6 @@ namespace libtorrent
|
||||||
, m_failed_trackers + 1, response_code, s.str()));
|
, m_failed_trackers + 1, response_code, s.str()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
try_next_tracker();
|
try_next_tracker();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1968,11 +2016,11 @@ namespace libtorrent
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
void torrent::metadata_progress(int total_size, int received)
|
void torrent::metadata_progress(int total_size, int received)
|
||||||
{
|
{
|
||||||
m_metadata_progress += received;
|
m_metadata_progress += received;
|
||||||
m_metadata_size = total_size;
|
m_metadata_size = total_size;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
@ -460,17 +460,22 @@ namespace libtorrent
|
||||||
ret["peers"] = entry::list_type();
|
ret["peers"] = entry::list_type();
|
||||||
entry::list_type& peer_list = ret["peers"].list();
|
entry::list_type& peer_list = ret["peers"].list();
|
||||||
|
|
||||||
for (torrent::const_peer_iterator i = t->begin();
|
policy& pol = t->get_policy();
|
||||||
i != t->end(); ++i)
|
|
||||||
|
for (policy::iterator i = pol.begin_peer()
|
||||||
|
, end(pol.end_peer()); i != end; ++i)
|
||||||
{
|
{
|
||||||
// we cannot save remote connection
|
// we cannot save remote connection
|
||||||
// since we don't know their listen port
|
// since we don't know their listen port
|
||||||
// TODO: iterate the peers in the policy
|
// unless they gave us their listen port
|
||||||
// instead, since peers may be remote
|
// through the extension handshake
|
||||||
// but still connectable
|
// so, if the peer is not connectable (i.e. we
|
||||||
if (!i->second->is_local()) continue;
|
// don't know its listen port) or if it has
|
||||||
|
// been banned, don't save it.
|
||||||
|
if (i->type == policy::peer::not_connectable
|
||||||
|
|| i->banned) continue;
|
||||||
|
|
||||||
tcp::endpoint ip = i->second->remote();
|
tcp::endpoint ip = i->ip;
|
||||||
entry peer(entry::dictionary_t);
|
entry peer(entry::dictionary_t);
|
||||||
peer["ip"] = ip.address().to_string();
|
peer["ip"] = ip.address().to_string();
|
||||||
peer["port"] = ip.port();
|
peer["port"] = ip.port();
|
||||||
|
@ -520,9 +525,18 @@ namespace libtorrent
|
||||||
session_impl::mutex_t::scoped_lock l(m_ses->m_mutex);
|
session_impl::mutex_t::scoped_lock l(m_ses->m_mutex);
|
||||||
boost::shared_ptr<torrent> t = m_ses->find_torrent(m_info_hash).lock();
|
boost::shared_ptr<torrent> t = m_ses->find_torrent(m_info_hash).lock();
|
||||||
|
|
||||||
// TODO: if the torrent is being checked, put this peer in a queue and
|
if (!t)
|
||||||
// connect it once the checking is done
|
{
|
||||||
if (!t) throw_invalid_handle();
|
// the torrent is being checked. Add the peer to its
|
||||||
|
// peer list. The entries in there will be connected
|
||||||
|
// once the checking is complete.
|
||||||
|
mutex::scoped_lock l2(m_chk->m_mutex);
|
||||||
|
|
||||||
|
detail::piece_checker_data* d = m_chk->find_torrent(m_info_hash);
|
||||||
|
if (d == 0) throw_invalid_handle();
|
||||||
|
d->peers.push_back(adr);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
peer_id id;
|
peer_id id;
|
||||||
std::fill(id.begin(), id.end(), 0);
|
std::fill(id.begin(), id.end(), 0);
|
||||||
|
|
|
@ -5,6 +5,7 @@ project
|
||||||
requirements <threading>multi
|
requirements <threading>multi
|
||||||
<library>/torrent
|
<library>/torrent
|
||||||
<source>main.cpp
|
<source>main.cpp
|
||||||
|
<source>setup_transfer.cpp
|
||||||
;
|
;
|
||||||
|
|
||||||
test-suite libtorrent :
|
test-suite libtorrent :
|
||||||
|
|
|
@ -19,10 +19,10 @@ test_storage_LDADD = $(top_builddir)/src/libtorrent.la
|
||||||
test_buffer_SOURCES = main.cpp test_buffer.cpp
|
test_buffer_SOURCES = main.cpp test_buffer.cpp
|
||||||
test_buffer_LDADD = $(top_builddir)/src/libtorrent.la
|
test_buffer_LDADD = $(top_builddir)/src/libtorrent.la
|
||||||
|
|
||||||
test_metadata_extension_SOURCES = main.cpp test_metadata_extension.cpp
|
test_metadata_extension_SOURCES = main.cpp setup_transfer.cpp test_metadata_extension.cpp
|
||||||
test_metadata_extension_LDADD = $(top_builddir)/src/libtorrent.la
|
test_metadata_extension_LDADD = $(top_builddir)/src/libtorrent.la
|
||||||
|
|
||||||
noinst_HEADERS = test.hpp
|
noinst_HEADERS = test.hpp setup_transfer.hpp
|
||||||
|
|
||||||
AM_CXXFLAGS=-ftemplate-depth-50 -I$(top_srcdir)/include -I$(top_srcdir)/asio/include @DEBUGFLAGS@ @PTHREAD_CFLAGS@
|
AM_CXXFLAGS=-ftemplate-depth-50 -I$(top_srcdir)/include -I$(top_srcdir)/asio/include @DEBUGFLAGS@ @PTHREAD_CFLAGS@
|
||||||
AM_LDFLAGS= -L./ -l@BOOST_DATE_TIME_LIB@ -l@BOOST_FILESYSTEM_LIB@ -l@BOOST_THREAD_LIB@ @PTHREAD_LIBS@
|
AM_LDFLAGS= -L./ -l@BOOST_DATE_TIME_LIB@ -l@BOOST_FILESYSTEM_LIB@ -l@BOOST_THREAD_LIB@ @PTHREAD_LIBS@
|
||||||
|
|
|
@ -0,0 +1,65 @@
|
||||||
|
#include "libtorrent/session.hpp"
|
||||||
|
#include "libtorrent/hasher.hpp"
|
||||||
|
#include <boost/thread.hpp>
|
||||||
|
#include <boost/tuple/tuple.hpp>
|
||||||
|
|
||||||
|
#include "test.hpp"
|
||||||
|
|
||||||
|
void sleep(int msec)
|
||||||
|
{
|
||||||
|
boost::xtime xt;
|
||||||
|
boost::xtime_get(&xt, boost::TIME_UTC);
|
||||||
|
xt.nsec += msec * 1000000;
|
||||||
|
boost::thread::sleep(xt);
|
||||||
|
}
|
||||||
|
|
||||||
|
using namespace libtorrent;
|
||||||
|
|
||||||
|
boost::tuple<torrent_handle, torrent_handle> setup_transfer(
|
||||||
|
session& ses1, session& ses2, bool clear_files)
|
||||||
|
{
|
||||||
|
using namespace boost::filesystem;
|
||||||
|
|
||||||
|
char const* tracker_url = "http://non-existent-name.com/announce";
|
||||||
|
|
||||||
|
torrent_info t;
|
||||||
|
t.add_file(path("temporary"), 42);
|
||||||
|
t.set_piece_size(256 * 1024);
|
||||||
|
t.add_tracker(tracker_url);
|
||||||
|
|
||||||
|
std::vector<char> piece(42);
|
||||||
|
std::fill(piece.begin(), piece.end(), 0xfe);
|
||||||
|
|
||||||
|
// calculate the hash for all pieces
|
||||||
|
int num = t.num_pieces();
|
||||||
|
for (int i = 0; i < num; ++i)
|
||||||
|
{
|
||||||
|
t.set_hash(i, hasher(&piece[0], piece.size()).final());
|
||||||
|
}
|
||||||
|
|
||||||
|
create_directory("./tmp1");
|
||||||
|
std::ofstream file("./tmp1/temporary");
|
||||||
|
file.write(&piece[0], piece.size());
|
||||||
|
file.close();
|
||||||
|
if (clear_files) remove_all("./tmp2/temporary");
|
||||||
|
|
||||||
|
t.create_torrent();
|
||||||
|
|
||||||
|
|
||||||
|
ses1.set_severity_level(alert::debug);
|
||||||
|
ses2.set_severity_level(alert::debug);
|
||||||
|
|
||||||
|
// they should not use the same save dir, because the
|
||||||
|
// file pool will complain if two torrents are trying to
|
||||||
|
// use the same files
|
||||||
|
torrent_handle tor1 = ses1.add_torrent(t, "./tmp1");
|
||||||
|
torrent_handle tor2 = ses2.add_torrent(tracker_url
|
||||||
|
, t.info_hash(), "./tmp2");
|
||||||
|
|
||||||
|
std::cerr << "connecting peer\n";
|
||||||
|
tor1.connect_peer(tcp::endpoint(address::from_string("127.0.0.1")
|
||||||
|
, ses2.listen_port()));
|
||||||
|
|
||||||
|
return boost::make_tuple(tor1, tor2);
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,14 @@
|
||||||
|
#ifndef SETUP_TRANSFER_HPP
|
||||||
|
#define SETUP_TRANSFER_HPP
|
||||||
|
|
||||||
|
#include "libtorrent/session.hpp"
|
||||||
|
#include <boost/tuple/tuple.hpp>
|
||||||
|
|
||||||
|
|
||||||
|
void sleep(int msec);
|
||||||
|
boost::tuple<libtorrent::torrent_handle, libtorrent::torrent_handle>
|
||||||
|
setup_transfer(libtorrent::session& ses1, libtorrent::session& ses2
|
||||||
|
, bool clear_files);
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
|
@ -1,54 +1,27 @@
|
||||||
#include "libtorrent/session.hpp"
|
#include "libtorrent/session.hpp"
|
||||||
#include "libtorrent/hasher.hpp"
|
#include "libtorrent/hasher.hpp"
|
||||||
#include <boost/thread.hpp>
|
#include <boost/thread.hpp>
|
||||||
|
#include <boost/tuple/tuple.hpp>
|
||||||
|
|
||||||
#include "test.hpp"
|
#include "test.hpp"
|
||||||
|
#include "setup_transfer.hpp"
|
||||||
|
|
||||||
void sleep(int msec)
|
void test_transfer(bool clear_files = true, bool disconnect = false)
|
||||||
{
|
|
||||||
boost::xtime xt;
|
|
||||||
boost::xtime_get(&xt, boost::TIME_UTC);
|
|
||||||
xt.nsec += msec * 1000000;
|
|
||||||
boost::thread::sleep(xt);
|
|
||||||
}
|
|
||||||
|
|
||||||
void test_transfer(char const* tracker_url, libtorrent::torrent_info const& t)
|
|
||||||
{
|
{
|
||||||
using namespace libtorrent;
|
using namespace libtorrent;
|
||||||
|
|
||||||
session ses1;
|
session ses1;
|
||||||
ses1.set_severity_level(alert::debug);
|
|
||||||
session ses2(fingerprint("LT", 0, 1, 0, 0), std::make_pair(49000, 50000));
|
session ses2(fingerprint("LT", 0, 1, 0, 0), std::make_pair(49000, 50000));
|
||||||
ses2.set_severity_level(alert::debug);
|
torrent_handle tor1;
|
||||||
|
torrent_handle tor2;
|
||||||
|
|
||||||
// they should not use the same save dir, because the
|
boost::tie(tor1, tor2) = setup_transfer(ses1, ses2, clear_files);
|
||||||
// file pool will complain if two torrents are trying to
|
|
||||||
// use the same files
|
|
||||||
torrent_handle tor1 = ses1.add_torrent(t, "./tmp1");
|
|
||||||
torrent_handle tor2 = ses2.add_torrent(tracker_url
|
|
||||||
, t.info_hash(), "./tmp2");
|
|
||||||
|
|
||||||
std::cerr << "waiting for file check to complete\n";
|
|
||||||
|
|
||||||
// wait for 5 seconds or until the torrent is in a state
|
|
||||||
// were it can accept connections
|
|
||||||
for (int i = 0; i < 50; ++i)
|
|
||||||
{
|
|
||||||
torrent_status st = tor1.status();
|
|
||||||
if (st.state != torrent_status::queued_for_checking
|
|
||||||
&&st.state != torrent_status::checking_files)
|
|
||||||
break;
|
|
||||||
sleep(100);
|
|
||||||
}
|
|
||||||
|
|
||||||
std::cerr << "connecting peer\n";
|
|
||||||
tor1.connect_peer(tcp::endpoint(address::from_string("127.0.0.1"), ses2.listen_port()));
|
|
||||||
|
|
||||||
for (int i = 0; i < 50; ++i)
|
for (int i = 0; i < 50; ++i)
|
||||||
{
|
{
|
||||||
// make sure this function can be called on
|
// make sure this function can be called on
|
||||||
// torrents without metadata
|
// torrents without metadata
|
||||||
tor2.status();
|
if (!disconnect) tor2.status();
|
||||||
std::auto_ptr<alert> a;
|
std::auto_ptr<alert> a;
|
||||||
a = ses1.pop_alert();
|
a = ses1.pop_alert();
|
||||||
if (a.get())
|
if (a.get())
|
||||||
|
@ -58,12 +31,15 @@ void test_transfer(char const* tracker_url, libtorrent::torrent_info const& t)
|
||||||
if (a.get())
|
if (a.get())
|
||||||
std::cerr << "ses2: " << a->msg() << "\n";
|
std::cerr << "ses2: " << a->msg() << "\n";
|
||||||
|
|
||||||
if (tor2.has_metadata()) break;
|
if (disconnect && tor2.is_valid()) ses2.remove_torrent(tor2);
|
||||||
|
if (!disconnect && tor2.has_metadata()) break;
|
||||||
sleep(100);
|
sleep(100);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (disconnect) return;
|
||||||
|
|
||||||
TEST_CHECK(tor2.has_metadata());
|
TEST_CHECK(tor2.has_metadata());
|
||||||
std::cerr << "metadata received. waiting for transfer to complete\n";
|
std::cerr << "waiting for transfer to complete\n";
|
||||||
|
|
||||||
for (int i = 0; i < 50; ++i)
|
for (int i = 0; i < 50; ++i)
|
||||||
{
|
{
|
||||||
|
@ -73,44 +49,21 @@ void test_transfer(char const* tracker_url, libtorrent::torrent_info const& t)
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_CHECK(tor2.is_seed());
|
TEST_CHECK(tor2.is_seed());
|
||||||
std::cerr << "done\n";
|
if (tor2.is_seed()) std::cerr << "done\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
int test_main()
|
int test_main()
|
||||||
{
|
{
|
||||||
using namespace libtorrent;
|
using namespace libtorrent;
|
||||||
using namespace boost::filesystem;
|
|
||||||
|
|
||||||
char const* tracker_url = "http://non-existant-name.com/announce";
|
// test to disconnect one client prematurely
|
||||||
|
test_transfer(true, true);
|
||||||
torrent_info t;
|
|
||||||
t.add_file(path("temporary"), 42);
|
|
||||||
t.set_piece_size(256 * 1024);
|
|
||||||
t.add_tracker(tracker_url);
|
|
||||||
|
|
||||||
std::vector<char> piece(42);
|
|
||||||
std::fill(piece.begin(), piece.end(), 0xfe);
|
|
||||||
|
|
||||||
// calculate the hash for all pieces
|
|
||||||
int num = t.num_pieces();
|
|
||||||
for (int i = 0; i < num; ++i)
|
|
||||||
{
|
|
||||||
t.set_hash(i, hasher(&piece[0], piece.size()).final());
|
|
||||||
}
|
|
||||||
|
|
||||||
create_directory("./tmp1");
|
|
||||||
std::ofstream file("./tmp1/temporary");
|
|
||||||
file.write(&piece[0], piece.size());
|
|
||||||
file.close();
|
|
||||||
remove_all("./tmp2/temporary");
|
|
||||||
|
|
||||||
t.create_torrent();
|
|
||||||
|
|
||||||
// test where one has data and one doesn't
|
// test where one has data and one doesn't
|
||||||
test_transfer(tracker_url, t);
|
test_transfer(true);
|
||||||
|
|
||||||
// test where both have data (to trigger the file check)
|
// test where both have data (to trigger the file check)
|
||||||
test_transfer(tracker_url, t);
|
test_transfer(false);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue