fixed race condition in peer_connection, fixed assert in torrent destructor, updated tests

This commit is contained in:
Arvid Norberg 2006-05-28 19:03:54 +00:00
parent 58698d6aea
commit 94628fa78d
20 changed files with 521 additions and 322 deletions

View File

@ -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

View File

@ -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 \

View File

@ -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&amp; print = libtorrent::fingerprint(&quot;LT&quot;, 0, 1, 0, 0)); session(fingerprint const&amp; print = libtorrent::fingerprint(&quot;LT&quot;, 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&lt;char&gt; const&amp; 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()

View File

@ -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
----------------------- -----------------------

View File

@ -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)
{ {

View File

@ -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 \

View File

@ -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:

View File

@ -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);

View File

@ -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; }

View File

@ -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

View File

@ -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)
{ {

View File

@ -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());

View File

@ -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)

View File

@ -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;
} }
}

View File

@ -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);

View File

@ -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 :

View File

@ -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@

65
test/setup_transfer.cpp Normal file
View File

@ -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);
}

14
test/setup_transfer.hpp Normal file
View File

@ -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

View File

@ -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;
} }