diff --git a/libtorrent/AUTHORS b/libtorrent/AUTHORS deleted file mode 100644 index dd56b1e89..000000000 --- a/libtorrent/AUTHORS +++ /dev/null @@ -1,25 +0,0 @@ - -Written by Arvid Norberg. Copyright (c) 2003-2007 - -Lots of testing, suggestions and contributions by: -Massaroddel -Tianhao Qiu. - -Contributions by: -Shyam -Magnus Jonsson -Daniel Wallin -Cory Nelson -Stas Khirman -Ryan Norton - -Building and maintainance of the autotools scripts: -Michael Wojciechowski -Peter Koeleman - -Thanks to Reimond Retz for bugfixes, suggestions and testing - -Thanks to University of UmeŚ for providing development and test hardware. - -Project is hosted by sourceforge. - diff --git a/libtorrent/COPYING b/libtorrent/COPYING deleted file mode 100644 index f38f5cb2d..000000000 --- a/libtorrent/COPYING +++ /dev/null @@ -1,28 +0,0 @@ -Copyright (c) 2003 - 2007, Arvid Norberg -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions -are met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in - the documentation and/or other materials provided with the distribution. - * Neither the name of Rasterbar Software nor the names of its - contributors may be used to endorse or promote products derived - from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -POSSIBILITY OF SUCH DAMAGE. - diff --git a/libtorrent/ChangeLog b/libtorrent/ChangeLog deleted file mode 100644 index 3c1c6f14b..000000000 --- a/libtorrent/ChangeLog +++ /dev/null @@ -1,216 +0,0 @@ - * Fixed bug in URL parser that failed to parse IPv6 addresses - * added peer download rate approximation - * added port filter for outgoing connection (to prevent - triggering firewalls) - * made most parameters configurable via session_settings - * added encryption support - * added parole mode for peers whose data fails the hash check. - * optimized heap usage in piece-picker and web seed downloader. - * fixed bug in DHT where older write tokens weren't accepted. - * added support for sparse files. - * introduced speed categories for peers and pieces, to separate - slow and fast peers. - * added a half-open tcp connection limit that takes all connections - in to account, not just peer connections. - * added alerts for filtered IPs. - * added support for SOCKS4 and 5 proxies and HTTP CONNECT proxies. - * fixed proper distributed copies calculation. - * added option to use openssl for sha-1 calculations. - * optimized the piece picker in the case where a peer is a seed. - * added support for local peer discovery - * removed the dependency on the compiled boost.date_time library - * deprecated torrent_info::print() - * added UPnP support - * fixed problem where peer interested flags were not updated correctly - when pieces were filtered - * improvements to ut_pex messages, including support for seed flag - * prioritizes upload bandwidth to peers that might send back data - * the following functions have been deprecated: - void torrent_handle::filter_piece(int index, bool filter) const; - void torrent_handle::filter_pieces(std::vector const& pieces) const; - bool torrent_handle::is_piece_filtered(int index) const; - std::vector torrent_handle::filtered_pieces() const; - void torrent_handle::filter_files(std::vector const& files) const; - - instead, use the piece_priority functions. - - * added support for NAT-PMP - * added support for piece priorities. Piece filtering is now set as - a priority - -release 0.12 - - * fixes to make the DHT more compatible - * http seed improvements including error reporting and url encoding issues. - * fixed bug where directories would be left behind when moving storage - in some cases. - * fixed crashing bug when restarting or stopping the DHT. - * added python binding, using boost.python - * improved character conversion on windows when strings are not utf-8. - * metadata extension now respects the private flag in the torrent. - * made the DHT to only be used as a fallback to trackers by default. - * added support for HTTP redirection support for web seeds. - * fixed race condition when accessing a torrent that was checking its - fast resume data. - * fixed a bug in the DHT which could be triggered if the network was - dropped or extremely rare cases. - * if the download rate is limited, web seeds will now only use left-over - bandwidth after all bt peers have used up as much bandwidth as they can. - * added the possibility to have libtorrent resolve the countries of - the peers in torrents. - * improved the bandwidth limiter (it now implements a leaky bucket/node bucket). - * improved the HTTP seed downloader to report accurate progress. - * added more client peer-id signatures to be recognized. - * added support for HTTP servers that skip the CR before the NL at line breaks. - * fixed bug in the HTTP code that only accepted headers case sensitive. - * fixed bug where one of the session constructors didn't initialize boost.filesystem. - * fixed bug when the initial checking of a torrent fails with an exception. - * fixed bug in DHT code which would send incorrect announce messages. - * fixed bug where the http header parser was case sensitive to the header - names. - * Implemented an optmization which frees the piece_picker once a torrent - turns into a seed. - * Added support for uT peer exchange extension, implemented by Massaroddel. - * Modified the quota management to offer better bandwidth balancing - between peers. - * logging now supports multiple sessions (different sessions now log - to different directories). - * fixed random number generator seed problem, generating the same - peer-id for sessions constructed the same second. - * added an option to accept multiple connections from the same IP. - * improved tracker logging. - * moved the file_pool into session. The number of open files is now - limited per session. - * fixed uninitialized private flag in torrent_info - * fixed long standing issue with file.cpp on windows. Replaced the low level - io functions used on windows. - * made it possible to associate a name with torrents without metadata. - * improved http-downloading performance by requesting entire pieces via - http. - * added plugin interface for extensions. And changed the interface for - enabling extensions. - -release 0.11 - - * added support for incorrectly encoded paths in torrent files - (assumes Latin-1 encoding and converts to UTF-8). - * added support for destructing session objects asynchronously. - * fixed bug with file_progress() with files = 0 bytes - * fixed a race condition bug in udp_tracker_connection that could - cause a crash. - * fixed bug occuring when increasing the sequenced download threshold - with max availability lower than previous threshold. - * fixed an integer overflow bug occuring when built with gcc 4.1.x - * fixed crasing bug when closing while checking a torrent - * fixed bug causing a crash with a torrent with piece length 0 - * added an extension to the DHT network protocol to support the - exchange of nodes with IPv6 addresses. - * modified the ip_filter api slightly to support IPv6 - * modified the api slightly to make sequenced download threshold - a per torrent-setting. - * changed the address type to support IPv6 - * fixed bug in piece picker which would not behave as - expected with regard to sequenced download threshold. - * fixed bug with file_progress() with files > 2 GB. - * added --enable-examples option to configure script. - * fixed problem with the resource distribution algorithm - (controlling e.g upload/download rates). - * fixed incorrect asserts in storage related to torrents with - zero-sized files. - * added support for trackerless torrents (with kademlia DHT). - * support for torrents with the private flag set. - * support for torrents containing bootstrap nodes for the - DHT network. - * fixed problem with the configure script on FreeBSD. - * limits the pipelining used on url-seeds. - * fixed problem where the shutdown always would delay for - session_settings::stop_tracker_timeout seconds. - * session::listen_on() won't reopen the socket in case the port and - interface is the same as the one currently in use. - * added http proxy support for web seeds. - * fixed problem where upload and download stats could become incorrect - in case of high cpu load. - * added more clients to the identifiable list. - * fixed fingerprint parser to cope with latest Mainline versions. - -release 0.10 - - * fixed a bug where the requested number of peers in a tracker request could - be too big. - * fixed a bug where empty files were not created in full allocation mode. - * fixed a bug in storage that would, in rare cases, fail to do a - complete check. - * exposed more settings for tweaking parameters in the piece-picker, - downloader and uploader (http_settings replaced by session_settings). - * tweaked default settings to improve high bandwidth transfers. - * improved the piece picker performance and made it possible to download - popular pieces in sequence to improve disk performance. - * added the possibility to control upload and download limits per peer. - * fixed problem with re-requesting skipped pieces when peer was sending pieces - out of fifo-order. - * added support for http seeding (the GetRight protocol) - * renamed identifiers called 'id' in the public interface to support linking - with Objective.C++ - * changed the extensions protocol to use the new one, which is also - implemented by uTorrent. - * factorized the peer_connection and added web_peer_connection which is - able to download from http-sources. - * converted the network code to use asio (resulted in slight api changes - dealing with network addresses). - * made libtorrent build in vc7 (patches from Allen Zhao) - * fixed bug caused when binding outgoing connections to a non-local interface. - * add_torrent() will now throw if called while the session object is - being closed. - * added the ability to limit the number of simultaneous half-open - TCP connections. Flags in peer_info has been added. - -release 0.9.1 - - * made the session disable file name checks within the boost.filsystem library - * fixed race condition in the sockets - * strings that are invalid utf-8 strings are now decoded with the - local codepage on windows - * added the ability to build libtorrent both as a shared library - * client_test can now monitor a directory for torrent files and automatically - start and stop downloads while running - * fixed problem with file_size() when building on windows with unicode support - * added a new torrent state, allocating - * added a new alert, metadata_failed_alert - * changed the interface to session::add_torrent for some speed optimizations. - * greatly improved the command line control of the example client_test. - * fixed bug where upload rate limit was not being applied. - * files that are being checked will no longer stall files that don't need - checking. - * changed the way libtorrent identifies support for its excentions - to look for 'ext' at the end of the peer-id. - * improved performance by adding a circle buffer for the send buffer. - * fixed bugs in the http tracker connection when using an http proxy. - * fixed problem with storage's file pool when creating torrents and then - starting to seed them. - * hard limit on remote request queue and timeout on requests (a timeout - triggers rerequests). This makes libtorrent work much better with - "broken" clients like BitComet which may ignore requests. - -Initial release 0.9 - - * multitracker support - * serves multiple torrents on a single port and a single thread - * supports http proxies and proxy authentication - * gzipped tracker-responses - * block level piece picker - * queues torrents for file check, instead of checking all of them in parallel - * uses separate threads for checking files and for main downloader - * upload and download rate limits - * piece-wise, unordered, incremental file allocation - * fast resume support - * supports files > 2 gigabytes - * supports the no_peer_id=1 extension - * support for udp-tracker protocol - * number of connections limit - * delays sending have messages - * can resume pieces downloaded in any order - * adjusts the length of the request queue depending on download rate - * supports compact=1 - * selective downloading - * ip filter - diff --git a/libtorrent/NEWS b/libtorrent/NEWS deleted file mode 100644 index cd9658d6b..000000000 --- a/libtorrent/NEWS +++ /dev/null @@ -1,3 +0,0 @@ - -initial release of libtorrent 0.9 - diff --git a/libtorrent/README b/libtorrent/README deleted file mode 100644 index 0b19bf61f..000000000 --- a/libtorrent/README +++ /dev/null @@ -1,25 +0,0 @@ -libtorrent is a C++ library that aims to be a good alternative to all the -other bittorrent implementations around. It is a -library and not a full featured client, although it comes with a working -example client. - -The main goals of libtorrent are: - - * to be cpu efficient - * to be memory efficient - * to be very easy to use - -See docs/manual.html for more detailed build and usage instructions. - -To build with autotools, run: - - ./configure - -Followed by - - make - -When libtorrent is built, finish off by running the tests: - - make check - diff --git a/libtorrent/bindings/README.txt b/libtorrent/bindings/README.txt deleted file mode 100644 index 977ca8c1c..000000000 --- a/libtorrent/bindings/README.txt +++ /dev/null @@ -1,3 +0,0 @@ -Documentation covering building and using the python binding for libtorrent -is located in the main doc directory. See docs/python_binding.html - diff --git a/libtorrent/bindings/python/src/alert.cpp b/libtorrent/bindings/python/src/alert.cpp deleted file mode 100755 index 1fcb724c8..000000000 --- a/libtorrent/bindings/python/src/alert.cpp +++ /dev/null @@ -1,369 +0,0 @@ -// Copyright Daniel Wallin 2006. Use, modification and distribution is -// subject to the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) - -#include -#include -#include - -using namespace boost::python; -using namespace libtorrent; - -extern char const* alert_doc; -extern char const* alert_msg_doc; -extern char const* alert_severity_doc; -extern char const* torrent_alert_doc; -extern char const* tracker_alert_doc; -extern char const* tracker_error_alert_doc; -extern char const* tracker_warning_alert_doc; -extern char const* tracker_reply_alert_doc; -extern char const* tracker_announce_alert_doc; -extern char const* hash_failed_alert_doc; -extern char const* peer_ban_alert_doc; -extern char const* peer_error_alert_doc; -extern char const* invalid_request_alert_doc; -extern char const* peer_request_doc; -extern char const* torrent_finished_alert_doc; -extern char const* piece_finished_alert_doc; -extern char const* block_finished_alert_doc; -extern char const* block_downloading_alert_doc; -extern char const* storage_moved_alert_doc; -extern char const* torrent_deleted_alert_doc; -extern char const* torrent_paused_alert_doc; -extern char const* torrent_checked_alert_doc; -extern char const* url_seed_alert_doc; -extern char const* file_error_alert_doc; -extern char const* metadata_failed_alert_doc; -extern char const* metadata_received_alert_doc; -extern char const* listen_failed_alert_doc; -extern char const* listen_succeeded_alert_doc; -extern char const* portmap_error_alert_doc; -extern char const* portmap_alert_doc; -extern char const* fastresume_rejected_alert_doc; -extern char const* peer_blocked_alert_doc; -extern char const* scrape_reply_alert_doc; -extern char const* scrape_failed_alert_doc; -extern char const* udp_error_alert_doc; -extern char const* external_ip_alert_doc; -extern char const* save_resume_data_alert_doc; - -void bind_alert() -{ - using boost::noncopyable; - - { - scope alert_scope = class_("alert", alert_doc, no_init) - .def("message", &alert::message, alert_msg_doc) - .def("what", &alert::what) - .def("category", &alert::category) -#ifndef TORRENT_NO_DEPRECATE - .def("severity", &alert::severity, alert_severity_doc) -#endif - .def("__str__", &alert::message, alert_msg_doc) - ; - - enum_("severity_levels") - .value("debug", alert::debug) - .value("info", alert::info) - .value("warning", alert::warning) - .value("critical", alert::critical) - .value("fatal", alert::fatal) - .value("none", alert::none) - ; - - enum_("category_t") - .value("error_notification", alert::error_notification) - .value("peer_notification", alert::peer_notification) - .value("port_mapping_notification", alert::port_mapping_notification) - .value("storage_notification", alert::storage_notification) - .value("tracker_notification", alert::tracker_notification) - .value("debug_notification", alert::debug_notification) - .value("status_notification", alert::status_notification) - .value("progress_notification", alert::progress_notification) - .value("ip_block_notification", alert::ip_block_notification) - .value("performance_warning", alert::performance_warning) - .value("all_categories", alert::all_categories) - ; - - } - - class_, noncopyable>( - "torrent_alert", torrent_alert_doc, no_init - ) - .def_readonly("handle", &torrent_alert::handle) - ; - - class_, noncopyable>( - "tracker_alert", tracker_alert_doc, no_init - ) - .def_readonly("url", &tracker_alert::url) - ; - - class_, noncopyable>( - "peer_alert", no_init - ) - .def_readonly("ip", &peer_alert::ip) - .def_readonly("pid", &peer_alert::pid) - ; - class_, noncopyable>( - "tracker_error_alert", tracker_error_alert_doc, no_init - ) - .def_readonly("msg", &tracker_error_alert::msg) - .def_readonly("times_in_row", &tracker_error_alert::times_in_row) - .def_readonly("status_code", &tracker_error_alert::status_code) - ; - - class_, noncopyable>( - "tracker_warning_alert", tracker_warning_alert_doc, no_init - ); - - class_, noncopyable>( - "tracker_reply_alert", tracker_reply_alert_doc, no_init - ) - .def_readonly("num_peers", &tracker_reply_alert::num_peers) - ; - - class_, noncopyable>( - "tracker_announce_alert", tracker_announce_alert_doc, no_init - ); - - class_, noncopyable>( - "hash_failed_alert", hash_failed_alert_doc, no_init - ) - .def_readonly("piece_index", &hash_failed_alert::piece_index) - ; - - class_, noncopyable>( - "peer_ban_alert", peer_ban_alert_doc, no_init - ); - - class_, noncopyable>( - "peer_error_alert", peer_error_alert_doc, no_init - ); - - class_, noncopyable>( - "invalid_request_alert", invalid_request_alert_doc, no_init - ) - .def_readonly("request", &invalid_request_alert::request) - ; - - class_("peer_request", peer_request_doc) - .def_readonly("piece", &peer_request::piece) - .def_readonly("start", &peer_request::start) - .def_readonly("length", &peer_request::length) - .def(self == self) - ; - - class_, noncopyable>( - "torrent_finished_alert", torrent_finished_alert_doc, no_init - ); - - class_, noncopyable>( - "piece_finished_alert", piece_finished_alert_doc, no_init - ) - .def_readonly("piece_index", &piece_finished_alert::piece_index) - ; - - class_, noncopyable>( - "block_finished_alert", block_finished_alert_doc, no_init - ) - .def_readonly("block_index", &block_finished_alert::block_index) - .def_readonly("piece_index", &block_finished_alert::piece_index) - ; - - class_, noncopyable>( - "block_downloading_alert", block_downloading_alert_doc, no_init - ) - .def_readonly("peer_speedmsg", &block_downloading_alert::peer_speedmsg) - .def_readonly("block_index", &block_downloading_alert::block_index) - .def_readonly("piece_index", &block_downloading_alert::piece_index) - ; - - class_, noncopyable>( - "storage_moved_alert", storage_moved_alert_doc, no_init - ); - - class_, noncopyable>( - "torrent_deleted_alert", torrent_deleted_alert_doc, no_init - ); - - class_, noncopyable>( - "torrent_paused_alert", torrent_paused_alert_doc, no_init - ); - - class_, noncopyable>( - "torrent_checked_alert", torrent_checked_alert_doc, no_init - ); - - class_, noncopyable>( - "url_seed_alert", url_seed_alert_doc, no_init - ) - .def_readonly("url", &url_seed_alert::url) - ; - - class_, noncopyable>( - "file_error_alert", file_error_alert_doc, no_init - ) - .def_readonly("file", &file_error_alert::file) - ; - - class_, noncopyable>( - "metadata_failed_alert", metadata_failed_alert_doc, no_init - ); - - class_, noncopyable>( - "metadata_received_alert", metadata_received_alert_doc, no_init - ); - - class_, noncopyable>( - "listen_failed_alert", listen_failed_alert_doc, no_init - ); - - class_, noncopyable>( - "listen_succeeded_alert", listen_succeeded_alert_doc, no_init - ) - .def_readonly("endpoint", &listen_succeeded_alert::endpoint) - ; - - class_, noncopyable>( - "portmap_error_alert", portmap_error_alert_doc, no_init - ) - .def_readonly("mapping", &portmap_error_alert::mapping) - .def_readonly("type", &portmap_error_alert::type) - ; - - class_, noncopyable>( - "portmap_alert", portmap_alert_doc, no_init - ) - .def_readonly("mapping", &portmap_alert::mapping) - .def_readonly("external_port", &portmap_alert::external_port) - .def_readonly("type", &portmap_alert::type) - ; - - class_, noncopyable>( - "fastresume_rejected_alert", fastresume_rejected_alert_doc, no_init - ); - - class_, noncopyable>( - "peer_blocked_alert", peer_blocked_alert_doc, no_init - ) - .def_readonly("ip", &peer_blocked_alert::ip) - ; - - class_, noncopyable>( - "scrape_reply_alert", scrape_reply_alert_doc, no_init - ) - .def_readonly("incomplete", &scrape_reply_alert::incomplete) - .def_readonly("complete", &scrape_reply_alert::complete) - ; - - class_, noncopyable>( - "scrape_failed_alert", scrape_failed_alert_doc, no_init - ); - - class_, noncopyable>( - "udp_error_alert", udp_error_alert_doc, no_init - ) - .def_readonly("endpoint", &udp_error_alert::endpoint) - ; - - class_, noncopyable>( - "external_ip_alert", external_ip_alert_doc, no_init - ) - .def_readonly("external_address", &external_ip_alert::external_address) - ; - - class_, noncopyable>( - "save_resume_data_alert", save_resume_data_alert_doc, no_init - ) - .def_readonly("resume_data", &save_resume_data_alert::resume_data) - ; - - class_, noncopyable>( - "file_renamed_alert", no_init - ) - .def_readonly("index", &file_renamed_alert::index) - .def_readonly("name", &file_renamed_alert::name) - ; - - class_, noncopyable>( - "file_rename_failed_alert", no_init - ) - .def_readonly("index", &file_rename_failed_alert::index) - .def_readonly("msg", &file_rename_failed_alert::msg) - ; - - class_, noncopyable>( - "torrent_resumed_alert", no_init - ); - - class_, noncopyable>( - "state_changed_alert", no_init - ) - .def_readonly("state", &state_changed_alert::state) - ; - - class_, noncopyable>( - "dht_reply_alert", no_init - ) - .def_readonly("num_peers", &dht_reply_alert::num_peers) - ; - - class_, noncopyable>( - "peer_unsnubbed_alert", no_init - ); - - class_, noncopyable>( - "peer_snubbed_alert", no_init - ); - - class_, noncopyable>( - "peer_connect_alert", no_init - ); - - class_, noncopyable>( - "peer_disconnected_alert", no_init - ); - - class_, noncopyable>( - "request_dropped_alert", no_init - ) - .def_readonly("block_index", &request_dropped_alert::block_index) - .def_readonly("piece_index", &request_dropped_alert::piece_index) - ; - - class_, noncopyable>( - "block_timeout_alert", no_init - ) - .def_readonly("block_index", &block_timeout_alert::block_index) - .def_readonly("piece_index", &block_timeout_alert::piece_index) - ; - - class_, noncopyable>( - "unwanted_block_alert", no_init - ) - .def_readonly("block_index", &unwanted_block_alert::block_index) - .def_readonly("piece_index", &unwanted_block_alert::piece_index) - ; - - class_, noncopyable>( - "torrent_delete_failed_alert", no_init - ); - - class_, noncopyable>( - "save_resume_data_failed_alert", no_init - ); - - class_, noncopyable>( - "performance_alert", no_init - ) - .def_readonly("warning_code", &performance_alert::warning_code) - ; - enum_("performance_warning_t") - .value("outstanding_disk_buffer_limit_reached", performance_alert::outstanding_disk_buffer_limit_reached) - .value("outstanding_request_limit_reached", performance_alert::outstanding_request_limit_reached) - ; - - - -} diff --git a/libtorrent/bindings/python/src/big_number.cpp b/libtorrent/bindings/python/src/big_number.cpp deleted file mode 100755 index 4e41df521..000000000 --- a/libtorrent/bindings/python/src/big_number.cpp +++ /dev/null @@ -1,20 +0,0 @@ -// Copyright Daniel Wallin 2006. Use, modification and distribution is -// subject to the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) - -#include -#include - -void bind_big_number() -{ - using namespace boost::python; - using namespace libtorrent; - - class_("big_number") - .def(self == self) - .def(self != self) - .def(self < self) - .def(self_ns::str(self)) - ; -} - diff --git a/libtorrent/bindings/python/src/converters.cpp b/libtorrent/bindings/python/src/converters.cpp deleted file mode 100755 index cae84be75..000000000 --- a/libtorrent/bindings/python/src/converters.cpp +++ /dev/null @@ -1,51 +0,0 @@ -// Copyright Andrew Resch 2009. Use, modification and distribution is -// subject to the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) - -#include - -using namespace boost::python; - -template -struct pair_to_tuple -{ - static PyObject* convert(const std::pair& p) - { - return incref(make_tuple(p.first, p.second).ptr()); - } -}; - -template -struct tuple_to_pair -{ - tuple_to_pair() - { - converter::registry::push_back( - &convertible, &construct, type_id >() - ); - } - - static void* convertible(PyObject* x) - { - return PyTuple_Check(x) ? x: 0; - } - - static void construct(PyObject* x, converter::rvalue_from_python_stage1_data* data) - { - void* storage = ((converter::rvalue_from_python_storage< - std::pair >*)data)->storage.bytes; - - object o(borrowed(x)); - std::pair p; - p.first = extract(o[0]); - p.second = extract(o[1]); - new (storage) std::pair(p); - data->convertible = storage; - } -}; - -void bind_converters() -{ - to_python_converter, pair_to_tuple >(); - tuple_to_pair(); -} diff --git a/libtorrent/bindings/python/src/datetime.cpp b/libtorrent/bindings/python/src/datetime.cpp deleted file mode 100755 index da1347671..000000000 --- a/libtorrent/bindings/python/src/datetime.cpp +++ /dev/null @@ -1,81 +0,0 @@ -// Copyright Daniel Wallin 2006. Use, modification and distribution is -// subject to the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) - -#include -#include -#include "optional.hpp" -#include - -using namespace boost::python; - -#if BOOST_VERSION < 103400 - -// From Boost 1.34 -object import(str name) -{ - // should be 'char const *' but older python versions don't use 'const' yet. - char *n = extract(name); - handle<> module(borrowed(PyImport_ImportModule(n))); - return object(module); -} - -#endif - -object datetime_timedelta; -object datetime_datetime; - -struct time_duration_to_python -{ - static PyObject* convert(boost::posix_time::time_duration const& d) - { - object result = datetime_timedelta( - 0 // days - , 0 // seconds - , d.total_microseconds() - ); - - return incref(result.ptr()); - } -}; - -struct ptime_to_python -{ - static PyObject* convert(boost::posix_time::ptime const& pt) - { - boost::gregorian::date date = pt.date(); - boost::posix_time::time_duration td = pt.time_of_day(); - - object result = datetime_datetime( - (int)date.year() - , (int)date.month() - , (int)date.day() - , td.hours() - , td.minutes() - , td.seconds() - ); - - return incref(result.ptr()); - } -}; - -void bind_datetime() -{ - object datetime = import("datetime").attr("__dict__"); - - datetime_timedelta = datetime["timedelta"]; - datetime_datetime = datetime["datetime"]; - - to_python_converter< - boost::posix_time::time_duration - , time_duration_to_python - >(); - - to_python_converter< - boost::posix_time::ptime - , ptime_to_python - >(); - - optional_to_python(); -} - diff --git a/libtorrent/bindings/python/src/docstrings.cpp b/libtorrent/bindings/python/src/docstrings.cpp deleted file mode 100755 index b1d28670d..000000000 --- a/libtorrent/bindings/python/src/docstrings.cpp +++ /dev/null @@ -1,354 +0,0 @@ -// Copyright Daniel Wallin 2006. Use, modification and distribution is -// subject to the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) - -// -- torrent_status -------------------------------------------------------- - -char const* torrent_status_doc = - "Represents the current status for a torrent.\n" - "Returned by `torrent_handle.status()`."; - -char const* torrent_status_state_doc = - "The torrents current task. One of `torrent_status.states`."; - -char const* torrent_status_paused_doc = - "Indicates if this torrent is paused or not."; - -char const* torrent_status_progress_doc = - "A value in the range [0, 1], that represents the progress of\n" - "the torrent's current task."; - -char const* torrent_status_next_announce_doc = - "The time until the torrent will announce itself to the\n" - "tracker. An instance of `datetime.timedelta`."; - -char const* torrent_status_announce_interval_doc = - "The interval at which the torrent will reannounce itself to the\n" - "tracker. An instance of `datetime.timedelta`."; - -char const* torrent_status_current_tracker_doc = - "The URL of the last working tracker. If no tracker request has\n" - "been successful yet, it's set to an empty string."; - -char const* torrent_status_total_download_doc = ""; -char const* torrent_status_total_upload_doc = ""; -char const* torrent_status_total_payload_download_doc = ""; -char const* torrent_status_total_payload_upload_doc = ""; -char const* torrent_status_total_failed_bytes_doc = ""; - -// -- session_status -------------------------------------------------------- - -char const* session_status_doc = - ""; -char const* session_status_has_incoming_connections_doc = - ""; -char const* session_status_upload_rate_doc = - ""; -char const* session_status_download_rate_doc = - ""; -char const* session_status_payload_upload_rate_doc = - ""; -char const* session_status_payload_download_rate_doc = - ""; -char const* session_status_total_download_doc = - ""; -char const* session_status_total_upload_doc = - ""; -char const* session_status_total_payload_download_doc = - ""; -char const* session_status_total_payload_upload_doc = - ""; -char const* session_status_num_peers_doc = - ""; -char const* session_status_dht_nodes_doc = - ""; -char const* session_status_cache_nodes_doc = - ""; -char const* session_status_dht_torrents_doc = - ""; - -// -- session --------------------------------------------------------------- - -char const* session_doc = - ""; -char const* session_init_doc = - "The `fingerprint` is a short string that will be used in\n" - "the peer-id to identify the client and the client's version.\n" - "For more details see the `fingerprint` class.\n" - "The constructor that only takes a fingerprint will not open\n" - "a listen port for the session, to get it running you'll have\n" - "to call `session.listen_on()`."; - -char const* session_listen_on_doc = - ""; -char const* session_is_listening_doc = - ""; -char const* session_listen_port_doc = - ""; - -char const* session_status_m_doc = - "Returns an instance of `session_status` with session wide-statistics\n" - "and status"; - -char const* session_start_dht_doc = - ""; -char const* session_stop_dht_doc = - ""; -char const* session_dht_state_doc = - ""; -char const* session_add_dht_router_doc = - "add dht router"; - -char const* session_add_torrent_doc = - "Adds a new torrent to the session. Return a `torrent_handle`.\n" - "\n" - ":Parameters:\n" - " - `torrent_info`: `torrent_info` instance representing the torrent\n" - " you want to add.\n" - " - `save_path`: The path to the directory where files will be saved.\n" - " - `resume_data (optional)`: The resume data for this torrent, as decoded\n" - " with `bdecode()`. This can be acquired from a running torrent with\n" - " `torrent_handle.write_resume_data()`.\n" - " - `compact_mode (optional)`: If set to true (default), the storage\n" - " will grow as more pieces are downloaded, and pieces are rearranged\n" - " to finally be in their correct places once the entire torrent has\n" - " been downloaded. If it is false, the entire storage is allocated\n" - " before download begins. I.e. the files contained in the torrent\n" - " are filled with zeros, and each downloaded piece is put in its\n" - " final place directly when downloaded.\n" - " - `block_size (optional)`: Sets the preferred request size, i.e.\n" - " the number of bytes to request from a peer at a time. This block size\n" - " must be a divisor of the piece size, and since the piece size is an\n" - " even power of 2, so must the block size be. If the block size given\n" - " here turns out to be greater than the piece size, it will simply be\n" - " clamped to the piece size.\n" - "\n" - ":Exceptions:\n" - " - `duplicate_torrent`: If the torrent you are trying to add already\n" - " exists in the session (is either queued for checking, being checked\n" - " or downloading) `add_torrent()` will throw `duplicate_torrent`.\n"; - -char const* session_remove_torrent_doc = - "Close all peer connections associated with the torrent and tell the\n" - "tracker that we've stopped participating in the swarm."; - -char const* session_download_rate_limit_doc = - ""; -char const* session_upload_rate_limit_doc = - ""; -char const* session_set_download_rate_limit_doc = - ""; -char const* session_set_upload_rate_limit_doc = - ""; -char const* session_set_max_uploads_doc = - ""; -char const* session_set_max_connections_doc = - ""; -char const* session_set_max_half_open_connections_doc = - "Sets the maximum number of half-open connections libtorrent will\n" - "have when connecting to peers. A half-open connection is one where\n" - "connect() has been called, but the connection still hasn't been\n" - "established (nor failed). Windows XP Service Pack 2 sets a default,\n" - "system wide, limit of the number of half-open connections to 10. So, \n" - "this limit can be used to work nicer together with other network\n" - "applications on that system. The default is to have no limit, and passing\n" - "-1 as the limit, means to have no limit. When limiting the number of\n" - "simultaneous connection attempts, peers will be put in a queue waiting\n" - "for their turn to get connected."; -char const* session_num_connections_doc = - ""; -char const* session_set_settings_doc = - ""; -char const* session_set_pe_settings_doc = - ""; -char const* session_get_pe_settings_doc = - ""; -char const* session_set_severity_level_doc = - ""; -char const* session_pop_alert_doc = - ""; -char const* session_start_upnp_doc = - ""; -char const* session_stop_upnp_doc = - ""; -char const* session_start_lsd_doc = - ""; -char const* session_stop_lsd_doc = - ""; -char const* session_start_natpmp_doc = - ""; -char const* session_stop_natpmp_doc = - ""; -char const* session_set_ip_filter_doc = - ""; - -// -- alert ----------------------------------------------------------------- - -char const* alert_doc = - "Base class for all concrete alert classes."; - -char const* alert_msg_doc = - "Returns a string describing this alert."; - -char const* alert_severity_doc = - "Returns the severity level for this alert, one of `alert.severity_levels`."; - -char const* torrent_alert_doc = - ""; - -char const* tracker_alert_doc = - "This alert is generated on tracker time outs, premature\n" - "disconnects, invalid response or a HTTP response other than\n" - "\"200 OK\". From the alert you can get the handle to the torrent\n" - "the tracker belongs to. This alert is generated as severity level\n" - "`alert.severity_levels.warning`."; - -char const* tracker_error_alert_doc = - ""; - -char const* tracker_warning_alert_doc = - "This alert is triggered if the tracker reply contains a warning\n" - "field. Usually this means that the tracker announce was successful\n" - ", but the tracker has a message to the client. The message string in\n" - "the alert will contain the warning message from the tracker. It is\n" - "generated with severity level `alert.severity_levels.warning`."; - -char const* tracker_reply_alert_doc = - "This alert is only for informational purpose. It is generated when\n" - "a tracker announce succeeds. It is generated with severity level\n" - "`alert.severity_levels.info`."; - -char const* tracker_announce_alert_doc = - "This alert is generated each time a tracker announce is sent\n" - "(or attempted to be sent). It is generated at severity level `alert.severity_levels.info`."; - -char const* hash_failed_alert_doc = - "This alert is generated when a finished piece fails its hash check.\n" - "You can get the handle to the torrent which got the failed piece\n" - "and the index of the piece itself from the alert. This alert is\n" - "generated as severity level `alert.severity_levels.info`."; - -char const* peer_ban_alert_doc = - "This alert is generated when a peer is banned because it has sent\n" - "too many corrupt pieces to us. It is generated at severity level\n" - "`alert.severity_levels.info`. The handle member is a `torrent_handle` to the torrent that\n" - "this peer was a member of."; - -char const* peer_error_alert_doc = - "This alert is generated when a peer sends invalid data over the\n" - "peer-peer protocol. The peer will be disconnected, but you get its\n" - "ip address from the alert, to identify it. This alert is generated\n" - "is severity level `alert.severity_levels.debug`."; - -char const* invalid_request_alert_doc = - "This is a debug alert that is generated by an incoming invalid\n" - "piece request. The handle is a handle to the torrent the peer\n" - "is a member of. Ip is the address of the peer and the request is\n" - "the actual incoming request from the peer. The alert is generated\n" - "as severity level `alert.severity_levels.debug`."; - -char const* peer_request_doc = - "The `peer_request` contains the values the client sent in its\n" - "request message. ``piece`` is the index of the piece it want data\n" - "from, ``start`` is the offset within the piece where the data should be\n" - "read, and ``length`` is the amount of data it wants."; - -char const* torrent_finished_alert_doc = - "This alert is generated when a torrent switches from being a\n" - "downloader to a seed. It will only be generated once per torrent.\n" - "It contains a `torrent_handle` to the torrent in question. This alert\n" - "is generated as severity level `alert.severity_levels.info`."; - -char const* piece_finished_alert_doc = - ""; - -char const* block_finished_alert_doc = - ""; - -char const* block_downloading_alert_doc = - ""; - -char const* storage_moved_alert_doc = - "This alert is generated when a torrent moves storage.\n" - "It contains a `torrent_handle` to the torrent in question. This alert\n" - "is generated as severity level `alert.severity_levels.warning`."; - -char const* torrent_deleted_alert_doc = - ""; - -char const* torrent_paused_alert_doc = - "This alert is generated when a torrent switches from being a\n" - "active to paused.\n" - "It contains a `torrent_handle` to the torrent in question. This alert\n" - "is generated as severity level `alert.severity_levels.warning`."; - -char const* torrent_checked_alert_doc = - ""; - -char const* url_seed_alert_doc = - "This alert is generated when a HTTP seed name lookup fails. This\n" - "alert is generated as severity level `alert.severity_levels.warning`."; - -char const* file_error_alert_doc = - "If the storage fails to read or write files that it needs access\n" - "to, this alert is generated and the torrent is paused. It is\n" - "generated as severity level `alert.severity_levels.fatal`."; - -char const* metadata_failed_alert_doc = - "This alert is generated when the metadata has been completely\n" - "received and the info-hash failed to match it. i.e. the\n" - "metadata that was received was corrupt. libtorrent will\n" - "automatically retry to fetch it in this case. This is only\n" - "relevant when running a torrent-less download, with the metadata\n" - "extension provided by libtorrent. It is generated at severity\n" - "level `alert.severity_levels.info`."; - -char const* metadata_received_alert_doc = - "This alert is generated when the metadata has been completely\n" - "received and the torrent can start downloading. It is not generated\n" - "on torrents that are started with metadata, but only those that\n" - "needs to download it from peers (when utilizing the libtorrent\n" - "extension). It is generated at severity level `alert.severity_levels.info`."; - -char const* listen_failed_alert_doc = - "This alert is generated when none of the ports, given in the\n" - "port range, to `session` can be opened for listening. This alert\n" - "is generated as severity level `alert.severity_levels.fatal`."; - -char const* listen_succeeded_alert_doc = - ""; - -char const* portmap_error_alert_doc = - ""; - -char const* portmap_alert_doc = - ""; - -char const* fastresume_rejected_alert_doc = - "This alert is generated when a fastresume file has been passed\n" - "to `session.add_torrent` but the files on disk did not match the\n" - "fastresume file. The string explains the reason why the resume\n" - "file was rejected. It is generated at severity level `alert.severity_levels.warning`."; - -char const* peer_blocked_alert_doc = - ""; - -char const* scrape_reply_alert_doc = - "This alert is generated when a scrape request succeeds.\n" - "incomplete and complete is the data returned in the scrape\n" - "response. These numbers may be -1 if the reponse was malformed."; - -char const* scrape_failed_alert_doc = - "If a scrape request fails, this alert is generated. This might\n" - "be due to the tracker timing out, refusing connection or returning\n" - "an http response code indicating an error."; - -char const* udp_error_alert_doc = - ""; - -char const* external_ip_alert_doc = - ""; - -char const* save_resume_data_alert_doc = - ""; - diff --git a/libtorrent/bindings/python/src/entry.cpp b/libtorrent/bindings/python/src/entry.cpp deleted file mode 100755 index 861580708..000000000 --- a/libtorrent/bindings/python/src/entry.cpp +++ /dev/null @@ -1,140 +0,0 @@ -// Copyright Daniel Wallin 2006. Use, modification and distribution is -// subject to the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) - -#include -#include - -using namespace boost::python; -using namespace libtorrent; - -struct entry_to_python -{ - static object convert(entry::list_type const& l) - { - list result; - - for (entry::list_type::const_iterator i(l.begin()), e(l.end()); i != e; ++i) - { - result.append(*i); - } - - return result; - } - - static object convert(entry::dictionary_type const& d) - { - dict result; - - for (entry::dictionary_type::const_iterator i(d.begin()), e(d.end()); i != e; ++i) - result[i->first] = i->second; - - return result; - } - - static object convert0(entry const& e) - { - switch (e.type()) - { - case entry::int_t: - return object(e.integer()); - case entry::string_t: - return object(e.string()); - case entry::list_t: - return convert(e.list()); - case entry::dictionary_t: - return convert(e.dict()); - default: - return object(); - } - } - - static PyObject* convert(boost::shared_ptr const& e) - { - if (!e) - return incref(Py_None); - return convert(*e); - } - - static PyObject* convert(entry const& e) - { - return incref(convert0(e).ptr()); - } -}; - -struct entry_from_python -{ - entry_from_python() - { - converter::registry::push_back( - &convertible, &construct, type_id() - ); - } - - static void* convertible(PyObject* e) - { - return e; - } - - static entry construct0(object e) - { - if (extract(e).check()) - { - dict d = extract(e); - list items(d.items()); - std::size_t length = extract(items.attr("__len__")()); - entry result(entry::dictionary_t); - - for (std::size_t i = 0; i < length; ++i) - { - result.dict().insert( - std::make_pair( - extract(items[i][0])() - , construct0(items[i][1]) - ) - ); - } - - return result; - } - else if (extract(e).check()) - { - list l = extract(e); - - std::size_t length = extract(l.attr("__len__")()); - entry result(entry::list_t); - - for (std::size_t i = 0; i < length; ++i) - { - result.list().push_back(construct0(l[i])); - } - - return result; - } - else if (extract(e).check()) - { - return entry(extract(e)()); - } - else if (extract(e).check()) - { - return entry(extract(e)()); - } - - return entry(); - } - - static void construct(PyObject* e, converter::rvalue_from_python_stage1_data* data) - { - void* storage = ((converter::rvalue_from_python_storage*)data)->storage.bytes; - new (storage) entry(construct0(object(borrowed(e)))); - data->convertible = storage; - } -}; - -void bind_entry() -{ - to_python_converter, entry_to_python>(); - to_python_converter(); - entry_from_python(); -} - diff --git a/libtorrent/bindings/python/src/extensions.cpp b/libtorrent/bindings/python/src/extensions.cpp deleted file mode 100755 index 1221e7012..000000000 --- a/libtorrent/bindings/python/src/extensions.cpp +++ /dev/null @@ -1,171 +0,0 @@ -// Copyright Daniel Wallin, Arvid Norberg 2007. Use, modification and distribution is -// subject to the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "gil.hpp" - -using namespace boost::python; -using namespace libtorrent; - -namespace -{ - - struct torrent_plugin_wrap : torrent_plugin, wrapper - { - boost::shared_ptr new_connection(peer_connection* p) - { - lock_gil lock; - - if (override f = this->get_override("new_connection")) - return f(ptr(p)); - return torrent_plugin::new_connection(p); - } - - boost::shared_ptr default_new_connection(peer_connection* p) - { - return this->torrent_plugin::new_connection(p); - } - - void on_piece_pass(int index) - { - lock_gil lock; - - if (override f = this->get_override("on_piece_pass")) - f(index); - else - torrent_plugin::on_piece_pass(index); - } - - void default_on_piece_pass(int index) - { - this->torrent_plugin::on_piece_pass(index); - } - - void on_piece_failed(int index) - { - lock_gil lock; - - if (override f = this->get_override("on_piece_failed")) - f(index); - else - torrent_plugin::on_piece_failed(index); - } - - void default_on_piece_failed(int index) - { - return this->torrent_plugin::on_piece_failed(index); - } - - void tick() - { - lock_gil lock; - - if (override f = this->get_override("tick")) - f(); - else - torrent_plugin::tick(); - } - - void default_tick() - { - return this->torrent_plugin::tick(); - } - - bool on_pause() - { - lock_gil lock; - - if (override f = this->get_override("on_pause")) - return f(); - return torrent_plugin::on_pause(); - } - - bool default_on_pause() - { - return this->torrent_plugin::on_pause(); - } - - bool on_resume() - { - lock_gil lock; - - if (override f = this->get_override("on_resume")) - return f(); - return torrent_plugin::on_resume(); - } - - bool default_on_resume() - { - return this->torrent_plugin::on_resume(); - } - }; - -} // namespace unnamed - - -boost::shared_ptr create_metadata_plugin_wrapper(torrent* t) { - return create_metadata_plugin(t, NULL); -} - -boost::shared_ptr create_ut_metadata_plugin_wrapper(torrent *t) { - return create_ut_metadata_plugin(t, NULL); -} - -boost::shared_ptr create_ut_pex_plugin_wrapper(torrent* t) { - return create_ut_pex_plugin(t, NULL); -} - -boost::shared_ptr create_smart_ban_plugin_wrapper(torrent* t) { - return create_smart_ban_plugin(t, NULL); -} - -void bind_extensions() -{ - class_< - torrent_plugin_wrap, boost::shared_ptr, boost::noncopyable - >("torrent_plugin") - .def( - "new_connection" - , &torrent_plugin::new_connection, &torrent_plugin_wrap::default_new_connection - ) - .def( - "on_piece_pass" - , &torrent_plugin::on_piece_pass, &torrent_plugin_wrap::default_on_piece_pass - ) - .def( - "on_piece_failed" - , &torrent_plugin::on_piece_failed, &torrent_plugin_wrap::default_on_piece_failed - ) - .def( - "tick" - , &torrent_plugin::tick, &torrent_plugin_wrap::default_tick - ) - .def( - "on_pause" - , &torrent_plugin::on_pause, &torrent_plugin_wrap::default_on_pause - ) - .def( - "on_resume" - , &torrent_plugin::on_resume, &torrent_plugin_wrap::default_on_resume - ); - - // TODO move to it's own file - class_("peer_connection", no_init); - - class_ >("torrent_plugin", no_init); - def("create_ut_pex_plugin", create_ut_pex_plugin_wrapper); - def("create_metadata_plugin", create_metadata_plugin_wrapper); - def("create_ut_metadata_plugin", create_ut_metadata_plugin_wrapper); - def("create_smart_ban_plugin", create_smart_ban_plugin_wrapper); -} - - diff --git a/libtorrent/bindings/python/src/filesystem.cpp b/libtorrent/bindings/python/src/filesystem.cpp deleted file mode 100755 index 777294bbf..000000000 --- a/libtorrent/bindings/python/src/filesystem.cpp +++ /dev/null @@ -1,70 +0,0 @@ -// Copyright Daniel Wallin 2006. Use, modification and distribution is -// subject to the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) - -#include -#include -#include "libtorrent/utf8.hpp" - -using namespace boost::python; - -struct path_to_python -{ - static PyObject* convert(boost::filesystem::path const& p) - { - return incref(object(p.string()).ptr()); - } -}; - -struct path_from_python -{ - path_from_python() - { - converter::registry::push_back( - &convertible, &construct, type_id() - ); - } - - static void* convertible(PyObject* x) - { - return PyString_Check(x) ? x : PyUnicode_Check(x) ? x : 0; - } - - static void construct(PyObject* x, converter::rvalue_from_python_stage1_data* data) - { - using libtorrent::wchar_utf8; - void* storage = ((converter::rvalue_from_python_storage< - boost::filesystem::path - >*)data)->storage.bytes; - if (PyUnicode_Check(x)) - { - std::wstring str; - str.resize(PyUnicode_GetSize(x) + 1, 0); - int len = PyUnicode_AsWideChar((PyUnicodeObject*)x, &str[0], str.size()); - if (len > -1) - { - assert(len < str.size()); - str[len] = 0; - } - else str[str.size()-1] = 0; - std::string utf8 = wchar_utf8(str); - new (storage) boost::filesystem::path(utf8); - } - else - { - new (storage) boost::filesystem::path(PyString_AsString(x)); - } - data->convertible = storage; - } -}; - -void bind_filesystem() -{ - to_python_converter(); - path_from_python(); - - using namespace boost::filesystem; - if (path::default_name_check_writable()) - path::default_name_check(no_check); -} - diff --git a/libtorrent/bindings/python/src/fingerprint.cpp b/libtorrent/bindings/python/src/fingerprint.cpp deleted file mode 100755 index ca40f3d4d..000000000 --- a/libtorrent/bindings/python/src/fingerprint.cpp +++ /dev/null @@ -1,27 +0,0 @@ -// Copyright Daniel Wallin 2006. Use, modification and distribution is -// subject to the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) - -#include -#include - -void bind_fingerprint() -{ - using namespace boost::python; - using namespace libtorrent; - - class_("fingerprint", no_init) - .def( - init( - (arg("id"), "major", "minor", "revision", "tag") - ) - ) - .def("__str__", &fingerprint::to_string) - .def_readonly("name", &fingerprint::name) - .def_readonly("major_version", &fingerprint::major_version) - .def_readonly("minor_version", &fingerprint::minor_version) - .def_readonly("revision_version", &fingerprint::revision_version) - .def_readonly("tag_version", &fingerprint::tag_version) - ; -} - diff --git a/libtorrent/bindings/python/src/gil.hpp b/libtorrent/bindings/python/src/gil.hpp deleted file mode 100755 index d9534c92c..000000000 --- a/libtorrent/bindings/python/src/gil.hpp +++ /dev/null @@ -1,144 +0,0 @@ -// Copyright Daniel Wallin 2007. Use, modification and distribution is -// subject to the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) - -#ifndef GIL_070107_HPP -# define GIL_070107_HPP - -# include -# include -# include -# include - -//namespace libtorrent { namespace python { - -// RAII helper to release GIL. -struct allow_threading_guard -{ - allow_threading_guard() - : save(PyEval_SaveThread()) - {} - - ~allow_threading_guard() - { - PyEval_RestoreThread(save); - } - - PyThreadState* save; -}; - -struct lock_gil -{ - lock_gil() - : state(PyGILState_Ensure()) - {} - - ~lock_gil() - { - PyGILState_Release(state); - } - - PyGILState_STATE state; -}; - -template -struct allow_threading -{ - allow_threading(F fn) - : fn(fn) - {} - - template - R operator()(A0& a0) - { - allow_threading_guard guard; - return (a0.*fn)(); - } - - template - R operator()(A0& a0, A1& a1) - { - allow_threading_guard guard; - return (a0.*fn)(a1); - } - - template - R operator()(A0& a0, A1& a1, A2& a2) - { - allow_threading_guard guard; - return (a0.*fn)(a1,a2); - } - - template - R operator()(A0& a0, A1& a1, A2& a2, A3& a3) - { - allow_threading_guard guard; - return (a0.*fn)(a1,a2,a3); - } - - template - R operator()(A0& a0, A1& a1, A2& a2, A3& a3, A4& a4) - { - allow_threading_guard guard; - return (a0.*fn)(a1,a2,a3,a4); - } - - template - R operator()(A0& a0, A1& a1, A2& a2, A3& a3, A4& a4, A5& a5) - { - allow_threading_guard guard; - return (a0.*fn)(a1,a2,a3,a4,a5); - } - - F fn; -}; - -template -struct visitor : boost::python::def_visitor > -{ - visitor(F fn) - : fn(fn) - {} - - template - void visit_aux( - Class& cl, char const* name - , Options const& options, Signature const& signature) const - { - typedef typename boost::mpl::at_c::type return_type; - - cl.def( - name - , boost::python::make_function( - allow_threading(fn) - , options.policies() - , options.keywords() - , signature - ) - ); - } - - template - void visit(Class& cl, char const* name, Options const& options) const - { - this->visit_aux( - cl, name, options - , boost::python::detail::get_signature(fn, (typename Class::wrapped_type*)0) - ); - } - - F fn; -}; - -// Member function adaptor that releases and aqcuires the GIL -// around the function call. -template -visitor allow_threads(F fn) -{ - return visitor(fn); -} - -//}} // namespace libtorrent::python - -#endif // GIL_070107_HPP - diff --git a/libtorrent/bindings/python/src/ip_filter.cpp b/libtorrent/bindings/python/src/ip_filter.cpp deleted file mode 100644 index 74ef2e89e..000000000 --- a/libtorrent/bindings/python/src/ip_filter.cpp +++ /dev/null @@ -1,32 +0,0 @@ -// Copyright Andrew Resch 2008. Use, modification and distribution is -// subject to the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) - -#include -#include -#include "gil.hpp" - -using namespace boost::python; -using namespace libtorrent; - -namespace -{ - void add_rule(ip_filter& filter, std::string start, std::string end, int flags) - { - return filter.add_rule(address::from_string(start), address::from_string(end), flags); - } - - int access0(ip_filter& filter, std::string addr) - { - return filter.access(address::from_string(addr)); - } -} - -void bind_ip_filter() -{ - class_("ip_filter") - .def("add_rule", add_rule) - .def("access", access0) - .def("export_filter", allow_threads(&ip_filter::export_filter)) - ; -} diff --git a/libtorrent/bindings/python/src/magnet_uri.cpp b/libtorrent/bindings/python/src/magnet_uri.cpp deleted file mode 100644 index 89c128bb9..000000000 --- a/libtorrent/bindings/python/src/magnet_uri.cpp +++ /dev/null @@ -1,54 +0,0 @@ -// Copyright Andrew Resch 2008. Use, modification and distribution is -// subject to the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt - -#include -#include -#include -#include -#include "gil.hpp" - -using namespace boost::python; -using namespace libtorrent; - -namespace { - - torrent_handle _add_magnet_uri(session& s, std::string uri, dict params) - { - add_torrent_params p; - - std::string url; - if (params.has_key("tracker_url")) - { - url = extract(params["tracker_url"]); - p.tracker_url = url.c_str(); - } - std::string name; - if (params.has_key("name")) - { - name = extract(params["name"]); - p.name = name.c_str(); - } - p.save_path = fs::path(extract(params["save_path"])); - - std::vector resume_buf; - if (params.has_key("resume_data")) - { - std::string resume = extract(params["resume_data"]); - resume_buf.resize(resume.size()); - std::memcpy(&resume_buf[0], &resume[0], resume.size()); - p.resume_data = &resume_buf; - } - p.storage_mode = extract(params["storage_mode"]); - p.paused = params["paused"]; - p.auto_managed = params["auto_managed"]; - p.duplicate_is_error = params["duplicate_is_error"]; - - return add_magnet_uri(s, uri, p); - } -} - -void bind_magnet_uri() -{ - def("add_magnet_uri", &_add_magnet_uri); -} diff --git a/libtorrent/bindings/python/src/module.cpp b/libtorrent/bindings/python/src/module.cpp deleted file mode 100755 index c512e346a..000000000 --- a/libtorrent/bindings/python/src/module.cpp +++ /dev/null @@ -1,55 +0,0 @@ -// Copyright Daniel Wallin 2006. Use, modification and distribution is -// subject to the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) - -#include - -void bind_utility(); -void bind_fingerprint(); -void bind_big_number(); -void bind_session(); -void bind_entry(); -void bind_torrent_info(); -void bind_filesystem(); -void bind_torrent_handle(); -void bind_torrent_status(); -void bind_session_settings(); -void bind_version(); -void bind_alert(); -void bind_datetime(); -void bind_extensions(); -void bind_peer_plugin(); -void bind_torrent(); -void bind_peer_info(); -void bind_ip_filter(); -void bind_magnet_uri(); -void bind_converters(); - -BOOST_PYTHON_MODULE(libtorrent) -{ - Py_Initialize(); - PyEval_InitThreads(); - - bind_utility(); - bind_fingerprint(); - bind_big_number(); - bind_entry(); - bind_session(); - bind_torrent_info(); - bind_filesystem(); - bind_torrent_handle(); - bind_torrent_status(); - bind_session_settings(); - bind_version(); - bind_alert(); - bind_datetime(); - bind_extensions(); -#ifndef TORRENT_NO_PYTHON_PLUGINS - bind_peer_plugin(); -#endif - bind_torrent(); - bind_peer_info(); - bind_ip_filter(); - bind_magnet_uri(); - bind_converters(); -} diff --git a/libtorrent/bindings/python/src/optional.hpp b/libtorrent/bindings/python/src/optional.hpp deleted file mode 100755 index 63138cc68..000000000 --- a/libtorrent/bindings/python/src/optional.hpp +++ /dev/null @@ -1,31 +0,0 @@ -// Copyright Daniel Wallin 2007. Use, modification and distribution is -// subject to the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) - -#ifndef OPTIONAL_070108_HPP -# define OPTIONAL_070108_HPP - -# include -# include - -template -struct optional_to_python -{ - optional_to_python() - { - boost::python::to_python_converter< - boost::optional, optional_to_python - >(); - } - - static PyObject* convert(boost::optional const& x) - { - if (!x) - return boost::python::incref(Py_None); - - return boost::python::incref(boost::python::object(*x).ptr()); - } -}; - -#endif // OPTIONAL_070108_HPP - diff --git a/libtorrent/bindings/python/src/peer_info.cpp b/libtorrent/bindings/python/src/peer_info.cpp deleted file mode 100755 index e054401c1..000000000 --- a/libtorrent/bindings/python/src/peer_info.cpp +++ /dev/null @@ -1,129 +0,0 @@ -// Copyright Daniel Wallin 2007. Use, modification and distribution is -// subject to the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) - -#include -#include -#include -#include - -using namespace boost::python; -using namespace libtorrent; - -int get_last_active(peer_info const& pi) -{ - return total_seconds(pi.last_active); -} - -int get_last_request(peer_info const& pi) -{ - return total_seconds(pi.last_request); -} - -#ifndef TORRENT_DISABLE_RESOLVE_COUNTRIES -str get_country(peer_info const& pi) -{ - return str(pi.country, 2); -} -#endif - -tuple get_ip(peer_info const& pi) -{ - return make_tuple(boost::lexical_cast(pi.ip.address()), pi.ip.port()); -} - -list get_pieces(peer_info const& pi) -{ - list ret; - - for (bitfield::const_iterator i = pi.pieces.begin() - , end(pi.pieces.end()); i != end; ++i) - { - ret.append(*i); - } - return ret; -} - -void bind_peer_info() -{ - scope pi = class_("peer_info") - .def_readonly("flags", &peer_info::flags) - .def_readonly("source", &peer_info::source) - .def_readonly("read_state", &peer_info::read_state) - .def_readonly("write_state", &peer_info::write_state) - .add_property("ip", get_ip) - .def_readonly("up_speed", &peer_info::up_speed) - .def_readonly("down_speed", &peer_info::down_speed) - .def_readonly("payload_up_speed", &peer_info::payload_up_speed) - .def_readonly("payload_down_speed", &peer_info::payload_down_speed) - .def_readonly("total_download", &peer_info::total_download) - .def_readonly("total_upload", &peer_info::total_upload) - .def_readonly("pid", &peer_info::pid) - .add_property("pieces", get_pieces) - .def_readonly("upload_limit", &peer_info::upload_limit) - .def_readonly("download_limit", &peer_info::download_limit) - .add_property("last_request", get_last_request) - .add_property("last_active", get_last_active) - .def_readonly("send_buffer_size", &peer_info::send_buffer_size) - .def_readonly("used_send_buffer", &peer_info::used_send_buffer) - .def_readonly("num_hashfails", &peer_info::num_hashfails) -#ifndef TORRENT_DISABLE_RESOLVE_COUNTRIES - .add_property("country", get_country) -#endif -#ifndef TORRENT_DISABLE_GEO_IP - .def_readonly("inet_as_name", &peer_info::inet_as_name) - .def_readonly("inet_as", &peer_info::inet_as) -#endif - .def_readonly("load_balancing", &peer_info::load_balancing) - .def_readonly("download_queue_length", &peer_info::download_queue_length) - .def_readonly("upload_queue_length", &peer_info::upload_queue_length) - .def_readonly("failcount", &peer_info::failcount) - .def_readonly("downloading_piece_index", &peer_info::downloading_piece_index) - .def_readonly("downloading_block_index", &peer_info::downloading_block_index) - .def_readonly("downloading_progress", &peer_info::downloading_progress) - .def_readonly("downloading_total", &peer_info::downloading_total) - .def_readonly("client", &peer_info::client) - .def_readonly("connection_type", &peer_info::connection_type) - .def_readonly("remote_dl_rate", &peer_info::remote_dl_rate) - .def_readonly("pending_disk_bytes", &peer_info::pending_disk_bytes) - .def_readonly("send_quota", &peer_info::send_quota) - .def_readonly("receive_quota", &peer_info::receive_quota) - .def_readonly("rtt", &peer_info::rtt) - .def_readonly("progress", &peer_info::progress) - ; - - // flags - pi.attr("interesting") = (int)peer_info::interesting; - pi.attr("choked") = (int)peer_info::choked; - pi.attr("remote_interested") = (int)peer_info::remote_interested; - pi.attr("remote_choked") = (int)peer_info::remote_choked; - pi.attr("supports_extensions") = (int)peer_info::supports_extensions; - pi.attr("local_connection") = (int)peer_info::local_connection; - pi.attr("handshake") = (int)peer_info::handshake; - pi.attr("connecting") = (int)peer_info::connecting; - pi.attr("queued") = (int)peer_info::queued; - pi.attr("on_parole") = (int)peer_info::on_parole; - pi.attr("seed") = (int)peer_info::seed; -#ifndef TORRENT_DISABLE_ENCRYPTION - pi.attr("rc4_encrypted") = (int)peer_info::rc4_encrypted; - pi.attr("plaintext_encrypted") = (int)peer_info::plaintext_encrypted; -#endif - - // connection_type - pi.attr("standard_bittorrent") = (int)peer_info::standard_bittorrent; - pi.attr("web_seed") = (int)peer_info::web_seed; - - // source - pi.attr("tracker") = (int)peer_info::tracker; - pi.attr("dht") = (int)peer_info::dht; - pi.attr("pex") = (int)peer_info::pex; - pi.attr("lsd") = (int)peer_info::lsd; - pi.attr("resume_data") = (int)peer_info::resume_data; - - // read/write state - pi.attr("bw_idle") = (int)peer_info::bw_idle; - pi.attr("bw_torrent") = (int)peer_info::bw_torrent; - pi.attr("bw_global") = (int)peer_info::bw_global; - pi.attr("bw_network") = (int)peer_info::bw_network; -} - diff --git a/libtorrent/bindings/python/src/peer_plugin.cpp b/libtorrent/bindings/python/src/peer_plugin.cpp deleted file mode 100755 index 6ba48ff80..000000000 --- a/libtorrent/bindings/python/src/peer_plugin.cpp +++ /dev/null @@ -1,359 +0,0 @@ -// Copyright Daniel Wallin 2007. Use, modification and distribution is -// subject to the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) - -#include -#include - -#include -#include -#include -#include -#include -#include -#include - -using namespace boost::python; -using namespace libtorrent; - -namespace -{ - struct peer_plugin_wrap : peer_plugin, wrapper - { - void add_handshake(entry& e) - { - if (override f = this->get_override("add_handshake")) - e = call(f.ptr(), e); - else - peer_plugin::add_handshake(e); - } - - void default_add_handshake(entry& e) - { - this->peer_plugin::add_handshake(e); - } - - bool on_handshake(char const* reserved_bits) - { - if (override f = this->get_override("on_handshake")) - return f(); - else - return peer_plugin::on_handshake(reserved_bits); - } - - bool default_on_handshake(char const* reserved_bits) - { - return this->peer_plugin::on_handshake(reserved_bits); - } - - bool on_extension_handshake(lazy_entry const& e) - { - if (override f = this->get_override("on_extension_handshake")) - return f(e); - else - return peer_plugin::on_extension_handshake(e); - } - - bool default_on_extension_handshake(lazy_entry const& e) - { - return this->peer_plugin::on_extension_handshake(e); - } - - bool on_choke() - { - if (override f = this->get_override("on_choke")) - return f(); - else - return peer_plugin::on_choke(); - } - - bool default_on_choke() - { - return this->peer_plugin::on_choke(); - } - - bool on_unchoke() - { - if (override f = this->get_override("on_unchoke")) - return f(); - else - return peer_plugin::on_unchoke(); - } - - bool default_on_unchoke() - { - return this->peer_plugin::on_unchoke(); - } - - bool on_interested() - { - if (override f = this->get_override("on_interested")) - return f(); - else - return peer_plugin::on_interested(); - } - - bool default_on_interested() - { - return this->peer_plugin::on_interested(); - } - - bool on_not_interested() - { - if (override f = this->get_override("on_not_interested")) - return f(); - else - return peer_plugin::on_not_interested(); - } - - bool default_on_not_interested() - { - return this->peer_plugin::on_not_interested(); - } - - bool on_have(int index) - { - if (override f = this->get_override("on_have")) - return f(index); - else - return peer_plugin::on_have(index); - } - - bool default_on_have(int index) - { - return this->peer_plugin::on_have(index); - } - - bool on_bitfield(list _bf) - { - //Convert list to a bitfield - bitfield bf(len(_bf)); - for (int i = 0; i < len(_bf); ++i) - { - if (_bf[i]) - bf.set_bit(i); - else - bf.clear_bit(i); - } - if (override f = this->get_override("on_bitfield")) - return f(bf); - else - return peer_plugin::on_bitfield(bf); - } - - bool default_on_bitfield(const bitfield &bf) - { - return this->peer_plugin::on_bitfield(bf); - } - - bool on_request(peer_request const& req) - { - if (override f = this->get_override("on_request")) - return f(req); - else - return peer_plugin::on_request(req); - } - - bool default_on_request(peer_request const& req) - { - return this->peer_plugin::on_request(req); - } - - bool on_piece(peer_request const& piece, disk_buffer_holder& data) - { - if (override f = this->get_override("on_piece")) - return f(piece, data); - else - return peer_plugin::on_piece(piece, data); - } - - bool default_on_piece(peer_request const& piece, disk_buffer_holder& data) - { - return this->peer_plugin::on_piece(piece, data); - } - - bool on_cancel(peer_request const& req) - { - if (override f = this->get_override("on_cancel")) - return f(req); - else - return peer_plugin::on_cancel(req); - } - - bool default_on_cancel(peer_request const& req) - { - return this->peer_plugin::on_cancel(req); - } - - bool on_extended(int length, int msg, buffer::const_interval body) - { - if (override f = this->get_override("on_extended")) - return f(length, msg, body); - else - return peer_plugin::on_extended(length, msg, body); - } - - bool default_on_extended(int length, int msg, buffer::const_interval body) - { - return this->peer_plugin::on_extended(length, msg, body); - } - - bool on_unknown_message(int length, int msg, buffer::const_interval body) - { - if (override f = this->get_override("on_unknown_message")) - return f(length, msg, body); - else - return peer_plugin::on_unknown_message(length, msg, body); - } - - bool default_on_unknown_message(int length, int msg, buffer::const_interval body) - { - return this->peer_plugin::on_unknown_message(length, msg, body); - } - - void on_piece_pass(int index) - { - if (override f = this->get_override("on_piece_pass")) - f(index); - else - peer_plugin::on_piece_pass(index); - } - - void default_on_piece_pass(int index) - { - this->peer_plugin::on_piece_pass(index); - } - - void on_piece_failed(int index) - { - if (override f = this->get_override("on_piece_failed")) - f(index); - else - peer_plugin::on_piece_failed(index); - } - - void default_on_piece_failed(int index) - { - this->peer_plugin::on_piece_failed(index); - } - - void tick() - { - if (override f = this->get_override("tick")) - f(); - else - peer_plugin::tick(); - } - - void default_tick() - { - this->peer_plugin::tick(); - } - - bool write_request(peer_request const& req) - { - if (override f = this->get_override("write_request")) - return f(req); - else - return peer_plugin::write_request(req); - } - - bool default_write_request(peer_request const& req) - { - return this->peer_plugin::write_request(req); - } - }; - - object get_buffer() - { - static char const data[] = "foobar"; - return object(handle<>(PyBuffer_FromMemory((void*)data, 6))); - } - -} // namespace unnamed - -void bind_peer_plugin() -{ - class_< - peer_plugin_wrap, boost::shared_ptr, boost::noncopyable - >("peer_plugin") - .def( - "add_handshake" - , &peer_plugin::add_handshake, &peer_plugin_wrap::default_add_handshake - ) - .def( - "on_handshake" - , &peer_plugin::on_handshake, &peer_plugin_wrap::default_on_handshake - ) - .def( - "on_extension_handshake" - , &peer_plugin::on_extension_handshake - , &peer_plugin_wrap::default_on_extension_handshake - ) - .def( - "on_choke" - , &peer_plugin::on_choke, &peer_plugin_wrap::default_on_choke - ) - .def( - "on_unchoke" - , &peer_plugin::on_unchoke, &peer_plugin_wrap::default_on_unchoke - ) - .def( - "on_interested" - , &peer_plugin::on_interested, &peer_plugin_wrap::default_on_interested - ) - .def( - "on_not_interested" - , &peer_plugin::on_not_interested, &peer_plugin_wrap::default_on_not_interested - ) - .def( - "on_have" - , &peer_plugin::on_have, &peer_plugin_wrap::default_on_have - ) - .def( - "on_bitfield" - , &peer_plugin::on_bitfield, &peer_plugin_wrap::default_on_bitfield - ) - .def( - "on_request" - , &peer_plugin::on_request, &peer_plugin_wrap::default_on_request - ) - .def( - "on_piece" - , &peer_plugin::on_piece, &peer_plugin_wrap::default_on_piece - ) - .def( - "on_cancel" - , &peer_plugin::on_cancel, &peer_plugin_wrap::default_on_cancel - ) - .def( - "on_piece_pass" - , &peer_plugin::on_piece_pass, &peer_plugin_wrap::default_on_piece_pass - ) - .def( - "on_piece_failed" - , &peer_plugin::on_piece_failed, &peer_plugin_wrap::default_on_piece_failed - ) - .def( - "tick" - , &peer_plugin::tick, &peer_plugin_wrap::default_tick - ) - .def( - "write_request" - , &peer_plugin::write_request, &peer_plugin_wrap::default_write_request - ) - // These seem to make VC7.1 freeze. Needs special handling. - - /*.def( - "on_extended" - , &peer_plugin::on_extended, &peer_plugin_wrap::default_on_extended - ) - .def( - "on_unknown_message" - , &peer_plugin::on_unknown_message, &peer_plugin_wrap::default_on_unknown_message - )*/ - ; - - def("get_buffer", &get_buffer); -} - diff --git a/libtorrent/bindings/python/src/session.cpp b/libtorrent/bindings/python/src/session.cpp deleted file mode 100755 index bcb96eb9a..000000000 --- a/libtorrent/bindings/python/src/session.cpp +++ /dev/null @@ -1,396 +0,0 @@ -// Copyright Daniel Wallin, Arvid Norberg 2006. Use, modification and distribution is -// subject to the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) - -#include -#include -#include -#include -#include -#include "gil.hpp" - -using namespace boost::python; -using namespace libtorrent; - -extern char const* session_status_doc; -extern char const* session_status_has_incoming_connections_doc; -extern char const* session_status_upload_rate_doc; -extern char const* session_status_download_rate_doc; -extern char const* session_status_payload_upload_rate_doc; -extern char const* session_status_payload_download_rate_doc; -extern char const* session_status_total_download_doc; -extern char const* session_status_total_upload_doc; -extern char const* session_status_total_payload_download_doc; -extern char const* session_status_total_payload_upload_doc; -extern char const* session_status_num_peers_doc; -extern char const* session_status_dht_nodes_doc; -extern char const* session_status_cache_nodes_doc; -extern char const* session_status_dht_torrents_doc; - -extern char const* session_doc; -extern char const* session_init_doc; -extern char const* session_listen_on_doc; -extern char const* session_is_listening_doc; -extern char const* session_listen_port_doc; -extern char const* session_status_m_doc; -extern char const* session_start_dht_doc; -extern char const* session_stop_dht_doc; -extern char const* session_dht_state_doc; -extern char const* session_add_dht_router_doc; -extern char const* session_add_torrent_doc; -extern char const* session_remove_torrent_doc; -extern char const* session_set_download_rate_limit_doc; -extern char const* session_download_rate_limit_doc; -extern char const* session_set_upload_rate_limit_doc; -extern char const* session_upload_rate_limit_doc; -extern char const* session_set_max_uploads_doc; -extern char const* session_set_max_connections_doc; -extern char const* session_set_max_half_open_connections_doc; -extern char const* session_num_connections_doc; -extern char const* session_set_settings_doc; -extern char const* session_set_pe_settings_doc; -extern char const* session_get_pe_settings_doc; -extern char const* session_set_severity_level_doc; -extern char const* session_pop_alert_doc; -extern char const* session_start_upnp_doc; -extern char const* session_start_lsd_doc; -extern char const* session_stop_lsd_doc; -extern char const* session_stop_upnp_doc; -extern char const* session_start_natpmp_doc; -extern char const* session_stop_natpmp_doc; -extern char const* session_set_ip_filter_doc; - -namespace -{ - - bool listen_on(session& s, int min_, int max_, char const* interface) - { - allow_threading_guard guard; - return s.listen_on(std::make_pair(min_, max_), interface); - } - void outgoing_ports(session& s, int _min, int _max) - { - allow_threading_guard guard; - session_settings settings = s.settings(); - settings.outgoing_ports = std::make_pair(_min, _max); - s.set_settings(settings); - return; - } -#ifndef TORRENT_DISABLE_DHT - void add_dht_router(session& s, std::string router_, int port_) - { - allow_threading_guard guard; - return s.add_dht_router(std::make_pair(router_, port_)); - } -#endif - - struct invoke_extension_factory - { - invoke_extension_factory(object const& callback) - : cb(callback) - {} - - boost::shared_ptr operator()(torrent* t, void*) - { - lock_gil lock; - return extract >(cb(ptr(t)))(); - } - - object cb; - }; - - void add_extension(session& s, object const& e) - { - allow_threading_guard guard; - s.add_extension(invoke_extension_factory(e)); - } - -#ifndef TORRENT_NO_DEPRECATE - torrent_handle add_torrent_depr(session& s, torrent_info const& ti - , boost::filesystem::path const& save, entry const& resume - , storage_mode_t storage_mode, bool paused) - { - allow_threading_guard guard; - return s.add_torrent(ti, save, resume, storage_mode, paused, default_storage_constructor); - } -#endif - - torrent_handle add_torrent(session& s, dict params) - { - add_torrent_params p; - - if (params.has_key("ti")) - p.ti = new torrent_info(extract(params["ti"])); - - std::string url; - if (params.has_key("tracker_url")) - { - url = extract(params["tracker_url"]); - p.tracker_url = url.c_str(); - } - if (params.has_key("info_hash")) - p.info_hash = extract(params["info_hash"]); - std::string name; - if (params.has_key("name")) - { - name = extract(params["name"]); - p.name = name.c_str(); - } - p.save_path = fs::path(extract(params["save_path"])); - - std::vector resume_buf; - if (params.has_key("resume_data")) - { - std::string resume = extract(params["resume_data"]); - resume_buf.resize(resume.size()); - std::memcpy(&resume_buf[0], &resume[0], resume.size()); - p.resume_data = &resume_buf; - } - if (params.has_key("storage_mode")) - p.storage_mode = extract(params["storage_mode"]); - if (params.has_key("paused")) - p.paused = params["paused"]; - if (params.has_key("auto_managed")) - p.auto_managed = params["auto_managed"]; - if (params.has_key("duplicate_is_error")) - p.duplicate_is_error = params["duplicate_is_error"]; - - return s.add_torrent(p); - } - - void start_natpmp(session& s) - { - allow_threading_guard guard; - s.start_natpmp(); - return; - } - - void start_upnp(session& s) - { - allow_threading_guard guard; - s.start_upnp(); - return; - } - - list get_torrents(session& s) - { - list ret; - std::vector torrents = s.get_torrents(); - - for (std::vector::iterator i = torrents.begin(); i != torrents.end(); ++i) - { - ret.append(*i); - } - return ret; - } - -#ifndef TORRENT_DISABLE_GEO_IP - bool load_asnum_db(session& s, std::string file) - { - allow_threading_guard guard; - return s.load_asnum_db(file.c_str()); - } - - bool load_country_db(session& s, std::string file) - { - allow_threading_guard guard; - return s.load_country_db(file.c_str()); - } -#endif -} // namespace unnamed - -void bind_session() -{ - class_("session_status", session_status_doc) - .def_readonly( - "has_incoming_connections", &session_status::has_incoming_connections - , session_status_has_incoming_connections_doc - ) - .def_readonly( - "upload_rate", &session_status::upload_rate - , session_status_upload_rate_doc - ) - .def_readonly( - "download_rate", &session_status::download_rate - , session_status_download_rate_doc - ) - .def_readonly( - "payload_upload_rate", &session_status::payload_upload_rate - , session_status_payload_upload_rate_doc - ) - .def_readonly( - "payload_download_rate", &session_status::payload_download_rate - , session_status_payload_download_rate_doc - ) - .def_readonly( - "total_download", &session_status::total_download - , session_status_total_download_doc - ) - .def_readonly( - "total_upload", &session_status::total_upload - , session_status_total_upload_doc - ) - .def_readonly( - "total_payload_download", &session_status::total_payload_download - , session_status_total_payload_download_doc - ) - .def_readonly( - "total_payload_upload", &session_status::total_payload_upload - , session_status_total_payload_upload_doc - ) - .def_readonly( - "num_peers", &session_status::num_peers - , session_status_num_peers_doc - ) -#ifndef TORRENT_DISABLE_DHT - .def_readonly( - "dht_nodes", &session_status::dht_nodes - , session_status_dht_nodes_doc - ) - .def_readonly( - "dht_cache_nodes", &session_status::dht_node_cache - , session_status_cache_nodes_doc - ) - .def_readonly( - "dht_torrents", &session_status::dht_torrents - , session_status_dht_torrents_doc - ) -#endif - ; - - enum_("storage_mode_t") - .value("storage_mode_allocate", storage_mode_allocate) - .value("storage_mode_sparse", storage_mode_sparse) - .value("storage_mode_compact", storage_mode_compact) - ; - - enum_("options_t") - .value("none", session::none) - .value("delete_files", session::delete_files) - ; - - enum_("session_flags_t") - .value("add_default_plugins", session::add_default_plugins) - .value("start_default_features", session::start_default_features) - ; - - class_("session", session_doc, no_init) - .def( - init(( - arg("fingerprint")=fingerprint("LT",0,1,0,0) - , arg("flags")=session::start_default_features | session::add_default_plugins) - , session_init_doc) - ) - .def( - "listen_on", &listen_on - , (arg("min"), "max", arg("interface") = (char const*)0) - , session_listen_on_doc - ) - .def("outgoing_ports", &outgoing_ports) - .def("is_listening", allow_threads(&session::is_listening), session_is_listening_doc) - .def("listen_port", allow_threads(&session::listen_port), session_listen_port_doc) - .def("status", allow_threads(&session::status), session_status_m_doc) -#ifndef TORRENT_DISABLE_DHT - .def( - "add_dht_router", &add_dht_router - , (arg("router"), "port") - , session_add_dht_router_doc - ) - .def("start_dht", allow_threads(&session::start_dht), session_start_dht_doc) - .def("stop_dht", allow_threads(&session::stop_dht), session_stop_dht_doc) - .def("dht_state", allow_threads(&session::dht_state), session_dht_state_doc) - .def("set_dht_proxy", allow_threads(&session::set_dht_proxy)) - .def("dht_proxy", allow_threads(&session::dht_proxy), return_value_policy()) -#endif - .def("add_torrent", &add_torrent, session_add_torrent_doc) -#ifndef TORRENT_NO_DEPRECATE - .def( - "add_torrent", &add_torrent_depr - , ( - arg("resume_data") = entry(), arg("storage_mode") = storage_mode_sparse, - arg("paused") = false - ) - , session_add_torrent_doc - ) -#endif - .def("remove_torrent", allow_threads(&session::remove_torrent), arg("option") = session::none - - , session_remove_torrent_doc) - .def( - "set_download_rate_limit", allow_threads(&session::set_download_rate_limit) - , session_set_download_rate_limit_doc - ) - .def( - "download_rate_limit", allow_threads(&session::download_rate_limit) - , session_download_rate_limit_doc - ) - - .def( - "set_upload_rate_limit", allow_threads(&session::set_upload_rate_limit) - , session_set_upload_rate_limit_doc - ) - .def( - "upload_rate_limit", allow_threads(&session::upload_rate_limit) - , session_upload_rate_limit_doc - ) - - .def( - "set_max_uploads", allow_threads(&session::set_max_uploads) - , session_set_max_uploads_doc - ) - .def( - "set_max_connections", allow_threads(&session::set_max_connections) - , session_set_max_connections_doc - ) - .def( - "set_max_half_open_connections", allow_threads(&session::set_max_half_open_connections) - , session_set_max_half_open_connections_doc - ) - .def( - "num_connections", allow_threads(&session::num_connections) - , session_num_connections_doc - ) - .def("set_settings", allow_threads(&session::set_settings), session_set_settings_doc) - .def("settings", allow_threads(&session::settings), return_value_policy()) -#ifndef TORRENT_DISABLE_ENCRYPTION - .def("set_pe_settings", allow_threads(&session::set_pe_settings), session_set_pe_settings_doc) - .def("get_pe_settings", allow_threads(&session::get_pe_settings), return_value_policy()) -#endif -#ifndef TORRENT_DISABLE_GEO_IP - .def("load_asnum_db", &load_asnum_db) - .def("load_country_db", &load_country_db) -#endif - .def("load_state", allow_threads(&session::load_state)) - .def("state", allow_threads(&session::state)) -#ifndef TORRENT_NO_DEPRECATE - .def( - "set_severity_level", allow_threads(&session::set_severity_level) - , session_set_severity_level_doc - ) -#endif - .def("set_alert_mask", allow_threads(&session::set_alert_mask)) - .def("pop_alert", allow_threads(&session::pop_alert), session_pop_alert_doc) - .def("add_extension", &add_extension) - .def("set_peer_proxy", allow_threads(&session::set_peer_proxy)) - .def("set_tracker_proxy", allow_threads(&session::set_tracker_proxy)) - .def("set_web_seed_proxy", allow_threads(&session::set_web_seed_proxy)) - .def("peer_proxy", allow_threads(&session::peer_proxy), return_value_policy()) - .def("tracker_proxy", allow_threads(&session::tracker_proxy), return_value_policy()) - .def("web_seed_proxy", allow_threads(&session::web_seed_proxy), return_value_policy()) - .def("start_upnp", &start_upnp, session_start_upnp_doc) - .def("stop_upnp", allow_threads(&session::stop_upnp), session_stop_upnp_doc) - .def("start_lsd", allow_threads(&session::start_lsd), session_start_lsd_doc) - .def("stop_lsd", allow_threads(&session::stop_lsd), session_stop_lsd_doc) - .def("start_natpmp", &start_natpmp, session_start_natpmp_doc) - .def("stop_natpmp", allow_threads(&session::stop_natpmp), session_stop_natpmp_doc) - .def("set_ip_filter", allow_threads(&session::set_ip_filter), session_set_ip_filter_doc) - .def("find_torrent", allow_threads(&session::find_torrent)) - .def("get_torrents", &get_torrents) - .def("pause", allow_threads(&session::pause)) - .def("resume", allow_threads(&session::resume)) - .def("is_paused", allow_threads(&session::is_paused)) - .def("id", allow_threads(&session::id)) - ; - - register_ptr_to_python >(); -} diff --git a/libtorrent/bindings/python/src/session_settings.cpp b/libtorrent/bindings/python/src/session_settings.cpp deleted file mode 100755 index 8d4974936..000000000 --- a/libtorrent/bindings/python/src/session_settings.cpp +++ /dev/null @@ -1,91 +0,0 @@ -// Copyright Daniel Wallin 2006. Use, modification and distribution is -// subject to the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) - -#include -#include - -using namespace boost::python; -using namespace libtorrent; - -void bind_session_settings() -{ - class_("session_settings") - .def_readwrite("user_agent", &session_settings::user_agent) - .def_readwrite("tracker_completion_timeout", &session_settings::tracker_completion_timeout) - .def_readwrite("tracker_receive_timeout", &session_settings::tracker_receive_timeout) - .def_readwrite("tracker_maximum_response_length", &session_settings::tracker_maximum_response_length) - .def_readwrite("piece_timeout", &session_settings::piece_timeout) - .def_readwrite("request_queue_time", &session_settings::request_queue_time) - .def_readwrite("max_allowed_in_request_queue", &session_settings::max_allowed_in_request_queue) - .def_readwrite("max_out_request_queue", &session_settings::max_out_request_queue) - .def_readwrite("whole_pieces_threshold", &session_settings::whole_pieces_threshold) - .def_readwrite("peer_timeout", &session_settings::peer_timeout) - .def_readwrite("urlseed_timeout", &session_settings::urlseed_timeout) - .def_readwrite("urlseed_pipeline_size", &session_settings::urlseed_pipeline_size) - .def_readwrite("file_pool_size", &session_settings::file_pool_size) - .def_readwrite("allow_multiple_connections_per_ip", &session_settings::allow_multiple_connections_per_ip) - .def_readwrite("max_failcount", &session_settings::max_failcount) - .def_readwrite("min_reconnect_time", &session_settings::min_reconnect_time) - .def_readwrite("peer_connect_timeout", &session_settings::peer_connect_timeout) - .def_readwrite("ignore_limits_on_local_network", &session_settings::ignore_limits_on_local_network) - .def_readwrite("connection_speed", &session_settings::connection_speed) - .def_readwrite("send_redundant_have", &session_settings::send_redundant_have) - .def_readwrite("lazy_bitfields", &session_settings::lazy_bitfields) - .def_readwrite("inactivity_timeout", &session_settings::inactivity_timeout) - .def_readwrite("unchoke_interval", &session_settings::unchoke_interval) - .def_readwrite("active_downloads", &session_settings::active_downloads) - .def_readwrite("active_seeds", &session_settings::active_seeds) - .def_readwrite("active_limit", &session_settings::active_limit) - .def_readwrite("dont_count_slow_torrents", &session_settings::dont_count_slow_torrents) - .def_readwrite("auto_manage_interval", &session_settings::auto_manage_interval) - .def_readwrite("share_ratio_limit", &session_settings::share_ratio_limit) - .def_readwrite("seed_time_ratio_limit", &session_settings::seed_time_ratio_limit) - .def_readwrite("seed_time_limit", &session_settings::seed_time_limit) - .def_readwrite("auto_scraped_interval", &session_settings::auto_scrape_interval) - .def_readwrite("peer_tos", &session_settings::peer_tos) - .def_readwrite("rate_limit_ip_overhead", &session_settings::rate_limit_ip_overhead) - .def_readwrite("outgoing_ports", &session_settings::outgoing_ports) -#ifndef TORRENT_DISABLE_DHT - .def_readwrite("use_dht_as_fallback", &session_settings::use_dht_as_fallback) -#endif - ; - - enum_("proxy_type") - .value("none", proxy_settings::none) - .value("socks4", proxy_settings::socks4) - .value("socks5", proxy_settings::socks5) - .value("socks5_pw", proxy_settings::socks5_pw) - .value("http", proxy_settings::http) - .value("http_pw", proxy_settings::http_pw) - ; - class_("proxy_settings") - .def_readwrite("hostname", &proxy_settings::hostname) - .def_readwrite("port", &proxy_settings::port) - .def_readwrite("password", &proxy_settings::password) - .def_readwrite("username", &proxy_settings::username) - .def_readwrite("type", &proxy_settings::type) - ; - -#ifndef TORRENT_DISABLE_ENCRYPTION - enum_("enc_policy") - .value("forced", pe_settings::forced) - .value("enabled", pe_settings::enabled) - .value("disabled", pe_settings::disabled) - ; - - enum_("enc_level") - .value("rc4", pe_settings::rc4) - .value("plaintext", pe_settings::plaintext) - .value("both", pe_settings::both) - ; - - class_("pe_settings") - .def_readwrite("out_enc_policy", &pe_settings::out_enc_policy) - .def_readwrite("in_enc_policy", &pe_settings::in_enc_policy) - .def_readwrite("allowed_enc_level", &pe_settings::allowed_enc_level) - .def_readwrite("prefer_rc4", &pe_settings::prefer_rc4) - ; -#endif - -} diff --git a/libtorrent/bindings/python/src/torrent.cpp b/libtorrent/bindings/python/src/torrent.cpp deleted file mode 100755 index 7b2ba76b4..000000000 --- a/libtorrent/bindings/python/src/torrent.cpp +++ /dev/null @@ -1,15 +0,0 @@ -// Copyright Daniel Wallin 2007. Use, modification and distribution is -// subject to the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) - -#include -#include - -using namespace boost::python; -using namespace libtorrent; - -void bind_torrent() -{ - class_("torrent", no_init); -} - diff --git a/libtorrent/bindings/python/src/torrent_handle.cpp b/libtorrent/bindings/python/src/torrent_handle.cpp deleted file mode 100755 index 639fcf86d..000000000 --- a/libtorrent/bindings/python/src/torrent_handle.cpp +++ /dev/null @@ -1,334 +0,0 @@ -// Copyright Daniel Wallin 2006. Use, modification and distribution is -// subject to the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) - -#include -#include -#include -#include -#include "gil.hpp" - -using namespace boost::python; -using namespace libtorrent; - -namespace -{ - - list url_seeds(torrent_handle& handle) - { - list ret; - std::set urls; - { - allow_threading_guard guard; - urls = handle.url_seeds(); - } - - for (std::set::iterator i(urls.begin()) - , end(urls.end()); i != end; ++i) - ret.append(*i); - return ret; - } - - list piece_availability(torrent_handle& handle) - { - list ret; - std::vector avail; - { - allow_threading_guard guard; - handle.piece_availability(avail); - } - - for (std::vector::iterator i(avail.begin()) - , end(avail.end()); i != end; ++i) - ret.append(*i); - return ret; - } - - list piece_priorities(torrent_handle& handle) - { - list ret; - std::vector prio; - { - allow_threading_guard guard; - prio = handle.piece_priorities(); - } - - for (std::vector::iterator i(prio.begin()) - , end(prio.end()); i != end; ++i) - ret.append(*i); - return ret; - } - - std::vector::const_iterator begin_trackers(torrent_handle& i) - { - allow_threading_guard guard; - return i.trackers().begin(); - } - - std::vector::const_iterator end_trackers(torrent_handle& i) - { - allow_threading_guard guard; - return i.trackers().end(); - } - -} // namespace unnamed - -list file_progress(torrent_handle& handle) -{ - std::vector p; - - { - allow_threading_guard guard; - p.reserve(handle.get_torrent_info().num_files()); - handle.file_progress(p); - } - - list result; - - for (std::vector::iterator i(p.begin()), e(p.end()); i != e; ++i) - result.append(*i); - - return result; -} - -list get_peer_info(torrent_handle const& handle) -{ - std::vector pi; - - { - allow_threading_guard guard; - handle.get_peer_info(pi); - } - - list result; - - for (std::vector::iterator i = pi.begin(); i != pi.end(); ++i) - result.append(*i); - - return result; -} - -void prioritize_pieces(torrent_handle& info, object o) -{ - std::vector result; - try - { - object iter_obj = object( handle<>( PyObject_GetIter( o.ptr() ) )); - while( 1 ) - { - object obj = extract( iter_obj.attr( "next" )() ); - result.push_back(extract( obj )); - } - } - catch( error_already_set ) - { - PyErr_Clear(); - info.prioritize_pieces(result); - return; - } -} - -void prioritize_files(torrent_handle& info, object o) -{ - std::vector result; - try - { - object iter_obj = object( handle<>( PyObject_GetIter( o.ptr() ) )); - while( 1 ) - { - object obj = extract( iter_obj.attr( "next" )() ); - result.push_back(extract( obj )); - } - } - catch( error_already_set ) - { - PyErr_Clear(); - info.prioritize_files(result); - return; - } -} - -list file_priorities(torrent_handle& handle) -{ - list ret; - std::vector priorities = handle.file_priorities(); - - for (std::vector::iterator i = priorities.begin(); i != priorities.end(); ++i) - ret.append(*i); - - return ret; -} - -void replace_trackers(torrent_handle& info, object trackers) -{ - object iter(trackers.attr("__iter__")()); - - std::vector result; - - for (;;) - { - handle<> entry(allow_null(PyIter_Next(iter.ptr()))); - - if (entry == handle<>()) - break; - - result.push_back(extract(object(entry))); - } - - allow_threading_guard guard; - info.replace_trackers(result); -} - -list get_download_queue(torrent_handle& handle) -{ - using boost::python::make_tuple; - - list ret; - - std::vector downloading; - - { - allow_threading_guard guard; - handle.get_download_queue(downloading); - } - - for (std::vector::iterator i = downloading.begin() - , end(downloading.end()); i != end; ++i) - { - dict partial_piece; - partial_piece["piece_index"] = i->piece_index; - partial_piece["blocks_in_piece"] = i->blocks_in_piece; - list block_list; - for (int k = 0; k < i->blocks_in_piece; ++k) - { - dict block_info; - block_info["state"] = i->blocks[k].state; - block_info["num_peers"] = i->blocks[k].num_peers; - block_info["bytes_progress"] = i->blocks[k].bytes_progress; - block_info["block_size"] = i->blocks[k].block_size; - block_info["peer"] = make_tuple( - boost::lexical_cast(i->blocks[k].peer.address()), i->blocks[k].peer.port()); - block_list.append(block_info); - } - partial_piece["blocks"] = block_list; - - ret.append(partial_piece); - } - - return ret; -} - -namespace -{ - tcp::endpoint tuple_to_endpoint(tuple const& t) - { - return tcp::endpoint(address::from_string(extract(t[0])), extract(t[1])); - } -} - -void force_reannounce(torrent_handle& th, int s) -{ - th.force_reannounce(boost::posix_time::seconds(s)); -} - -void connect_peer(torrent_handle& th, tuple ip, int source) -{ - th.connect_peer(tuple_to_endpoint(ip), source); -} - -void set_peer_upload_limit(torrent_handle& th, tuple const& ip, int limit) -{ - th.set_peer_upload_limit(tuple_to_endpoint(ip), limit); -} - -void set_peer_download_limit(torrent_handle& th, tuple const& ip, int limit) -{ - th.set_peer_download_limit(tuple_to_endpoint(ip), limit); -} - -void bind_torrent_handle() -{ - void (torrent_handle::*force_reannounce0)() const = &torrent_handle::force_reannounce; - - int (torrent_handle::*piece_priority0)(int) const = &torrent_handle::piece_priority; - void (torrent_handle::*piece_priority1)(int, int) const = &torrent_handle::piece_priority; - -#ifndef TORRENT_DISABLE_RESOLVE_COUNTRIES - bool (torrent_handle::*resolve_countries0)() const = &torrent_handle::resolve_countries; - void (torrent_handle::*resolve_countries1)(bool) = &torrent_handle::resolve_countries; -#endif - - return_value_policy copy; - -#define _ allow_threads - - class_("torrent_handle") - .def("get_peer_info", get_peer_info) - .def("status", _(&torrent_handle::status)) - .def("get_download_queue", get_download_queue) - .def("file_progress", file_progress) - .def("trackers", range(begin_trackers, end_trackers)) - .def("replace_trackers", replace_trackers) - .def("add_url_seed", _(&torrent_handle::add_url_seed)) - .def("remove_url_seed", _(&torrent_handle::remove_url_seed)) - .def("url_seeds", url_seeds) - .def("has_metadata", _(&torrent_handle::has_metadata)) - .def("get_torrent_info", _(&torrent_handle::get_torrent_info), return_internal_reference<>()) - .def("is_valid", _(&torrent_handle::is_valid)) - .def("is_seed", _(&torrent_handle::is_seed)) - .def("is_finished", _(&torrent_handle::is_finished)) - .def("is_paused", _(&torrent_handle::is_paused)) - .def("pause", _(&torrent_handle::pause)) - .def("resume", _(&torrent_handle::resume)) - .def("clear_error", _(&torrent_handle::clear_error)) - - .def("is_auto_managed", _(&torrent_handle::is_auto_managed)) - .def("auto_managed", _(&torrent_handle::auto_managed)) - .def("queue_position", _(&torrent_handle::queue_position)) - .def("queue_position_up", _(&torrent_handle::queue_position_up)) - .def("queue_position_down", _(&torrent_handle::queue_position_down)) - .def("queue_position_top", _(&torrent_handle::queue_position_top)) - .def("queue_position_bottom", _(&torrent_handle::queue_position_bottom)) - -#ifndef TORRENT_DISABLE_RESOLVE_COUNTRIES - .def("resolve_countries", _(resolve_countries0)) - .def("resolve_countries", _(resolve_countries1)) -#endif - // deprecated -#ifndef TORRENT_NO_DEPRECATE - .def("filter_piece", _(&torrent_handle::filter_piece)) - .def("is_piece_filtered", _(&torrent_handle::is_piece_filtered)) - .def("write_resume_data", _(&torrent_handle::write_resume_data)) -#endif - .def("piece_availability", piece_availability) - .def("piece_priority", _(piece_priority0)) - .def("piece_priority", _(piece_priority1)) - .def("prioritize_pieces", prioritize_pieces) - .def("piece_priorities", piece_priorities) - .def("prioritize_files", prioritize_files) - .def("file_priorities", file_priorities) - .def("use_interface", &torrent_handle::use_interface) - .def("save_resume_data", _(&torrent_handle::save_resume_data)) - .def("force_reannounce", _(force_reannounce0)) - .def("force_reannounce", force_reannounce) - .def("scrape_tracker", _(&torrent_handle::scrape_tracker)) - .def("name", _(&torrent_handle::name)) - .def("set_upload_limit", _(&torrent_handle::set_upload_limit)) - .def("upload_limit", _(&torrent_handle::upload_limit)) - .def("set_download_limit", _(&torrent_handle::set_download_limit)) - .def("download_limit", _(&torrent_handle::download_limit)) - .def("set_sequential_download", _(&torrent_handle::set_sequential_download)) - .def("set_peer_upload_limit", set_peer_upload_limit) - .def("set_peer_download_limit", set_peer_download_limit) - .def("connect_peer", connect_peer) - .def("set_ratio", _(&torrent_handle::set_ratio)) - .def("save_path", _(&torrent_handle::save_path)) - .def("set_max_uploads", _(&torrent_handle::set_max_uploads)) - .def("set_max_connections", _(&torrent_handle::set_max_connections)) - .def("set_tracker_login", _(&torrent_handle::set_tracker_login)) - .def("move_storage", _(&torrent_handle::move_storage)) - .def("info_hash", _(&torrent_handle::info_hash)) - .def("force_recheck", _(&torrent_handle::force_recheck)) - .def("rename_file", _(&torrent_handle::rename_file)) - ; -} diff --git a/libtorrent/bindings/python/src/torrent_info.cpp b/libtorrent/bindings/python/src/torrent_info.cpp deleted file mode 100755 index bbe64fcd9..000000000 --- a/libtorrent/bindings/python/src/torrent_info.cpp +++ /dev/null @@ -1,154 +0,0 @@ -// Copyright Daniel Wallin 2006. Use, modification and distribution is -// subject to the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) - -#include -#include -#include "libtorrent/intrusive_ptr_base.hpp" - -using namespace boost::python; -using namespace libtorrent; - -namespace -{ - - std::vector::const_iterator begin_trackers(torrent_info& i) - { - return i.trackers().begin(); - } - - std::vector::const_iterator end_trackers(torrent_info& i) - { - return i.trackers().end(); - } - - void add_node(torrent_info& ti, char const* hostname, int port) - { - ti.add_node(std::make_pair(hostname, port)); - } - - list nodes(torrent_info const& ti) - { - list result; - - typedef std::vector > list_type; - - for (list_type::const_iterator i = ti.nodes().begin(); i != ti.nodes().end(); ++i) - { - result.append(make_tuple(i->first, i->second)); - } - - return result; - } - - file_storage::iterator begin_files(torrent_info& i) - { - return i.begin_files(); - } - - file_storage::iterator end_files(torrent_info& i) - { - return i.end_files(); - } - - //list files(torrent_info const& ti, bool storage) { - list files(torrent_info const& ti, bool storage) { - list result; - - typedef std::vector list_type; - - for (list_type::const_iterator i = ti.begin_files(); i != ti.end_files(); ++i) - result.append(*i); - - return result; - } - - std::string metadata(torrent_info const& ti) { - std::string result(ti.metadata().get(), ti.metadata_size()); - return result; - } - - torrent_info construct0(std::string path) { - return torrent_info(fs::path(path)); - } - - list map_block(torrent_info& ti, int piece, size_type offset, int size) - { - std::vector p = ti.map_block(piece, offset, size); - list result; - - for (std::vector::iterator i(p.begin()), e(p.end()); i != e; ++i) - result.append(*i); - - return result; - } - -} // namespace unnamed - -void bind_torrent_info() -{ - return_value_policy copy; - - class_("file_slice") - .def_readwrite("file_index", &file_slice::file_index) - .def_readwrite("offset", &file_slice::offset) - .def_readwrite("size", &file_slice::size) - ; - - class_ >("torrent_info", no_init) -#ifndef TORRENT_NO_DEPRECATE - .def(init()) -#endif - .def(init()) - .def(init()) - .def(init()) - - .def("add_tracker", &torrent_info::add_tracker, (arg("url"), arg("tier")=0)) - .def("add_url_seed", &torrent_info::add_url_seed) - - .def("name", &torrent_info::name, copy) - .def("comment", &torrent_info::comment, copy) - .def("creator", &torrent_info::creator, copy) - .def("total_size", &torrent_info::total_size) - .def("piece_length", &torrent_info::piece_length) - .def("num_pieces", &torrent_info::num_pieces) -#ifndef TORRENT_NO_DEPRECATE - .def("info_hash", &torrent_info::info_hash, copy) -#endif - .def("hash_for_piece", &torrent_info::hash_for_piece) - .def("piece_size", &torrent_info::piece_size) - - .def("num_files", &torrent_info::num_files, (arg("storage")=false)) - .def("file_at", &torrent_info::file_at, return_internal_reference<>()) - .def("file_at_offset", &torrent_info::file_at_offset) - .def("files", &files, (arg("storage")=false)) - - .def("priv", &torrent_info::priv) - .def("trackers", range(begin_trackers, end_trackers)) - - .def("creation_date", &torrent_info::creation_date) - - .def("add_node", &add_node) - .def("nodes", &nodes) - .def("metadata", &metadata) - .def("metadata_size", &torrent_info::metadata_size) - .def("map_block", map_block) - .def("map_file", &torrent_info::map_file) - ; - - class_("file_entry") - .add_property( - "path" - , make_getter( - &file_entry::path, return_value_policy() - ) - ) - .def_readonly("offset", &file_entry::offset) - .def_readonly("size", &file_entry::size) - ; - - class_("announce_entry", init()) - .def_readwrite("url", &announce_entry::url) - .def_readwrite("tier", &announce_entry::tier) - ; -} diff --git a/libtorrent/bindings/python/src/torrent_status.cpp b/libtorrent/bindings/python/src/torrent_status.cpp deleted file mode 100755 index 81e2bf3a6..000000000 --- a/libtorrent/bindings/python/src/torrent_status.cpp +++ /dev/null @@ -1,90 +0,0 @@ -// Copyright Daniel Wallin 2006. Use, modification and distribution is -// subject to the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) - -#include -#include -#include - -using namespace boost::python; -using namespace libtorrent; - -object pieces(torrent_status const& s) -{ - list result; - - for (bitfield::const_iterator i(s.pieces.begin()), e(s.pieces.end()); i != e; ++i) - result.append(*i); - - return result; -} - -void bind_torrent_status() -{ - scope status = class_("torrent_status") - .def_readonly("state", &torrent_status::state) - .def_readonly("paused", &torrent_status::paused) - .def_readonly("progress", &torrent_status::progress) - .add_property( - "next_announce" - , make_getter( - &torrent_status::next_announce, return_value_policy() - ) - ) - .add_property( - "announce_interval" - , make_getter( - &torrent_status::announce_interval, return_value_policy() - ) - ) - .def_readonly("current_tracker", &torrent_status::current_tracker) - .def_readonly("total_download", &torrent_status::total_download) - .def_readonly("total_upload", &torrent_status::total_upload) - .def_readonly("total_payload_download", &torrent_status::total_payload_download) - .def_readonly("total_payload_upload", &torrent_status::total_payload_upload) - .def_readonly("total_failed_bytes", &torrent_status::total_failed_bytes) - .def_readonly("total_redundant_bytes", &torrent_status::total_redundant_bytes) - .def_readonly("download_rate", &torrent_status::download_rate) - .def_readonly("upload_rate", &torrent_status::upload_rate) - .def_readonly("download_payload_rate", &torrent_status::download_payload_rate) - .def_readonly("upload_payload_rate", &torrent_status::upload_payload_rate) - .def_readonly("num_seeds", &torrent_status::num_seeds) - .def_readonly("num_peers", &torrent_status::num_peers) - .def_readonly("num_complete", &torrent_status::num_complete) - .def_readonly("num_incomplete", &torrent_status::num_incomplete) - .def_readonly("list_seeds", &torrent_status::list_seeds) - .def_readonly("list_peers", &torrent_status::list_peers) - .add_property("pieces", pieces) - .def_readonly("num_pieces", &torrent_status::num_pieces) - .def_readonly("total_done", &torrent_status::total_done) - .def_readonly("total_wanted_done", &torrent_status::total_wanted_done) - .def_readonly("total_wanted", &torrent_status::total_wanted) - .def_readonly("distributed_copies", &torrent_status::distributed_copies) - .def_readonly("block_size", &torrent_status::block_size) - .def_readonly("num_uploads", &torrent_status::num_uploads) - .def_readonly("num_connections", &torrent_status::num_connections) - .def_readonly("uploads_limit", &torrent_status::uploads_limit) - .def_readonly("connections_limit", &torrent_status::connections_limit) - .def_readonly("storage_mode", &torrent_status::storage_mode) - .def_readonly("up_bandwidth_queue", &torrent_status::up_bandwidth_queue) - .def_readonly("down_bandwidth_queue", &torrent_status::down_bandwidth_queue) - .def_readonly("all_time_upload", &torrent_status::all_time_upload) - .def_readonly("all_time_download", &torrent_status::all_time_download) - .def_readonly("active_time", &torrent_status::active_time) - .def_readonly("seeding_time", &torrent_status::seeding_time) - .def_readonly("seed_rank", &torrent_status::seed_rank) - .def_readonly("last_scrape", &torrent_status::last_scrape) - .def_readonly("error", &torrent_status::error) - ; - - enum_("states") - .value("queued_for_checking", torrent_status::queued_for_checking) - .value("checking_files", torrent_status::checking_files) - .value("downloading", torrent_status::downloading) - .value("finished", torrent_status::finished) - .value("seeding", torrent_status::seeding) - .value("allocating", torrent_status::allocating) - .export_values() - ; -} - diff --git a/libtorrent/bindings/python/src/utility.cpp b/libtorrent/bindings/python/src/utility.cpp deleted file mode 100755 index 9ae2d2a93..000000000 --- a/libtorrent/bindings/python/src/utility.cpp +++ /dev/null @@ -1,37 +0,0 @@ -// Copyright Daniel Wallin 2006. Use, modification and distribution is -// subject to the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) - -#include -#include -#include - -using namespace boost::python; -using namespace libtorrent; - -object client_fingerprint_(peer_id const& id) -{ - boost::optional result = client_fingerprint(id); - return result ? object(*result) : object(); -} - -entry bdecode_(std::string const& data) -{ - return bdecode(data.begin(), data.end()); -} - -std::string bencode_(entry const& e) -{ - std::string result; - bencode(std::back_inserter(result), e); - return result; -} - -void bind_utility() -{ - def("identify_client", &libtorrent::identify_client); - def("client_fingerprint", &client_fingerprint_); - def("bdecode", &bdecode_); - def("bencode", &bencode_); -} - diff --git a/libtorrent/bindings/python/src/version.cpp b/libtorrent/bindings/python/src/version.cpp deleted file mode 100755 index aaeafd900..000000000 --- a/libtorrent/bindings/python/src/version.cpp +++ /dev/null @@ -1,16 +0,0 @@ -// Copyright Daniel Wallin 2006. Use, modification and distribution is -// subject to the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) - -#include -#include - -using namespace boost::python; - -void bind_version() -{ - scope().attr("version") = LIBTORRENT_VERSION; - scope().attr("version_major") = LIBTORRENT_VERSION_MAJOR; - scope().attr("version_minor") = LIBTORRENT_VERSION_MINOR; -} - diff --git a/libtorrent/include/asio/COPYING b/libtorrent/include/asio/COPYING deleted file mode 100644 index 61f5a0b12..000000000 --- a/libtorrent/include/asio/COPYING +++ /dev/null @@ -1,4 +0,0 @@ -Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) - -Distributed under the Boost Software License, Version 1.0. (See accompanying -file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) diff --git a/libtorrent/include/asio/LICENSE_1_0.txt b/libtorrent/include/asio/LICENSE_1_0.txt deleted file mode 100644 index 36b7cd93c..000000000 --- a/libtorrent/include/asio/LICENSE_1_0.txt +++ /dev/null @@ -1,23 +0,0 @@ -Boost Software License - Version 1.0 - August 17th, 2003 - -Permission is hereby granted, free of charge, to any person or organization -obtaining a copy of the software and accompanying documentation covered by -this license (the "Software") to use, reproduce, display, distribute, -execute, and transmit the Software, and to prepare derivative works of the -Software, and to permit third-parties to whom the Software is furnished to -do so, all subject to the following: - -The copyright notices in the Software and this entire statement, including -the above license grant, this restriction and the following disclaimer, -must be included in all copies of the Software, in whole or in part, and -all derivative works of the Software, unless such copies or derivative -works are solely in the form of machine-executable object code generated by -a source language processor. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT -SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE -FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, -ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -DEALINGS IN THE SOFTWARE. diff --git a/libtorrent/include/asio/basic_datagram_socket.hpp b/libtorrent/include/asio/basic_datagram_socket.hpp deleted file mode 100644 index 0bfc512c2..000000000 --- a/libtorrent/include/asio/basic_datagram_socket.hpp +++ /dev/null @@ -1,803 +0,0 @@ -// -// basic_datagram_socket.hpp -// ~~~~~~~~~~~~~~~~~~~~~~~~~ -// -// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -#ifndef ASIO_BASIC_DATAGRAM_SOCKET_HPP -#define ASIO_BASIC_DATAGRAM_SOCKET_HPP - -#if defined(_MSC_VER) && (_MSC_VER >= 1200) -# pragma once -#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) - -#include "asio/detail/push_options.hpp" - -#include "asio/detail/push_options.hpp" -#include -#include -#include "asio/detail/pop_options.hpp" - -#include "asio/basic_socket.hpp" -#include "asio/datagram_socket_service.hpp" -#include "asio/error.hpp" -#include "asio/detail/throw_error.hpp" - -namespace asio { - -/// Provides datagram-oriented socket functionality. -/** - * The basic_datagram_socket class template provides asynchronous and blocking - * datagram-oriented socket functionality. - * - * @par Thread Safety - * @e Distinct @e objects: Safe.@n - * @e Shared @e objects: Unsafe. - */ -template > -class basic_datagram_socket - : public basic_socket -{ -public: - /// The native representation of a socket. - typedef typename DatagramSocketService::native_type native_type; - - /// The protocol type. - typedef Protocol protocol_type; - - /// The endpoint type. - typedef typename Protocol::endpoint endpoint_type; - - /// Construct a basic_datagram_socket without opening it. - /** - * This constructor creates a datagram socket without opening it. The open() - * function must be called before data can be sent or received on the socket. - * - * @param io_service The io_service object that the datagram socket will use - * to dispatch handlers for any asynchronous operations performed on the - * socket. - */ - explicit basic_datagram_socket(asio::io_service& io_service) - : basic_socket(io_service) - { - } - - /// Construct and open a basic_datagram_socket. - /** - * This constructor creates and opens a datagram socket. - * - * @param io_service The io_service object that the datagram socket will use - * to dispatch handlers for any asynchronous operations performed on the - * socket. - * - * @param protocol An object specifying protocol parameters to be used. - * - * @throws asio::system_error Thrown on failure. - */ - basic_datagram_socket(asio::io_service& io_service, - const protocol_type& protocol) - : basic_socket(io_service, protocol) - { - } - - /// Construct a basic_datagram_socket, opening it and binding it to the given - /// local endpoint. - /** - * This constructor creates a datagram socket and automatically opens it bound - * to the specified endpoint on the local machine. The protocol used is the - * protocol associated with the given endpoint. - * - * @param io_service The io_service object that the datagram socket will use - * to dispatch handlers for any asynchronous operations performed on the - * socket. - * - * @param endpoint An endpoint on the local machine to which the datagram - * socket will be bound. - * - * @throws asio::system_error Thrown on failure. - */ - basic_datagram_socket(asio::io_service& io_service, - const endpoint_type& endpoint) - : basic_socket(io_service, endpoint) - { - } - - /// Construct a basic_datagram_socket on an existing native socket. - /** - * This constructor creates a datagram socket object to hold an existing - * native socket. - * - * @param io_service The io_service object that the datagram socket will use - * to dispatch handlers for any asynchronous operations performed on the - * socket. - * - * @param protocol An object specifying protocol parameters to be used. - * - * @param native_socket The new underlying socket implementation. - * - * @throws asio::system_error Thrown on failure. - */ - basic_datagram_socket(asio::io_service& io_service, - const protocol_type& protocol, const native_type& native_socket) - : basic_socket( - io_service, protocol, native_socket) - { - } - - /// Send some data on a connected socket. - /** - * This function is used to send data on the datagram socket. The function - * call will block until the data has been sent successfully or an error - * occurs. - * - * @param buffers One ore more data buffers to be sent on the socket. - * - * @returns The number of bytes sent. - * - * @throws asio::system_error Thrown on failure. - * - * @note The send operation can only be used with a connected socket. Use - * the send_to function to send data on an unconnected datagram socket. - * - * @par Example - * To send a single data buffer use the @ref buffer function as follows: - * @code socket.send(asio::buffer(data, size)); @endcode - * See the @ref buffer documentation for information on sending multiple - * buffers in one go, and how to use it with arrays, boost::array or - * std::vector. - */ - template - std::size_t send(const ConstBufferSequence& buffers) - { - asio::error_code ec; - std::size_t s = this->service.send(this->implementation, buffers, 0, ec); - asio::detail::throw_error(ec); - return s; - } - - /// Send some data on a connected socket. - /** - * This function is used to send data on the datagram socket. The function - * call will block until the data has been sent successfully or an error - * occurs. - * - * @param buffers One ore more data buffers to be sent on the socket. - * - * @param flags Flags specifying how the send call is to be made. - * - * @returns The number of bytes sent. - * - * @throws asio::system_error Thrown on failure. - * - * @note The send operation can only be used with a connected socket. Use - * the send_to function to send data on an unconnected datagram socket. - */ - template - std::size_t send(const ConstBufferSequence& buffers, - socket_base::message_flags flags) - { - asio::error_code ec; - std::size_t s = this->service.send( - this->implementation, buffers, flags, ec); - asio::detail::throw_error(ec); - return s; - } - - /// Send some data on a connected socket. - /** - * This function is used to send data on the datagram socket. The function - * call will block until the data has been sent successfully or an error - * occurs. - * - * @param buffers One or more data buffers to be sent on the socket. - * - * @param flags Flags specifying how the send call is to be made. - * - * @param ec Set to indicate what error occurred, if any. - * - * @returns The number of bytes sent. - * - * @note The send operation can only be used with a connected socket. Use - * the send_to function to send data on an unconnected datagram socket. - */ - template - std::size_t send(const ConstBufferSequence& buffers, - socket_base::message_flags flags, asio::error_code& ec) - { - return this->service.send(this->implementation, buffers, flags, ec); - } - - /// Start an asynchronous send on a connected socket. - /** - * This function is used to send data on the datagram socket. The function - * call will block until the data has been sent successfully or an error - * occurs. - * - * @param buffers One or more data buffers to be sent on the socket. Although - * the buffers object may be copied as necessary, ownership of the underlying - * memory blocks is retained by the caller, which must guarantee that they - * remain valid until the handler is called. - * - * @param handler The handler to be called when the send operation completes. - * Copies will be made of the handler as required. The function signature of - * the handler must be: - * @code void handler( - * const asio::error_code& error, // Result of operation. - * std::size_t bytes_transferred // Number of bytes sent. - * ); @endcode - * Regardless of whether the asynchronous operation completes immediately or - * not, the handler will not be invoked from within this function. Invocation - * of the handler will be performed in a manner equivalent to using - * asio::io_service::post(). - * - * @note The async_send operation can only be used with a connected socket. - * Use the async_send_to function to send data on an unconnected datagram - * socket. - * - * @par Example - * To send a single data buffer use the @ref buffer function as follows: - * @code - * socket.async_send(asio::buffer(data, size), handler); - * @endcode - * See the @ref buffer documentation for information on sending multiple - * buffers in one go, and how to use it with arrays, boost::array or - * std::vector. - */ - template - void async_send(const ConstBufferSequence& buffers, WriteHandler handler) - { - this->service.async_send(this->implementation, buffers, 0, handler); - } - - /// Start an asynchronous send on a connected socket. - /** - * This function is used to send data on the datagram socket. The function - * call will block until the data has been sent successfully or an error - * occurs. - * - * @param buffers One or more data buffers to be sent on the socket. Although - * the buffers object may be copied as necessary, ownership of the underlying - * memory blocks is retained by the caller, which must guarantee that they - * remain valid until the handler is called. - * - * @param flags Flags specifying how the send call is to be made. - * - * @param handler The handler to be called when the send operation completes. - * Copies will be made of the handler as required. The function signature of - * the handler must be: - * @code void handler( - * const asio::error_code& error, // Result of operation. - * std::size_t bytes_transferred // Number of bytes sent. - * ); @endcode - * Regardless of whether the asynchronous operation completes immediately or - * not, the handler will not be invoked from within this function. Invocation - * of the handler will be performed in a manner equivalent to using - * asio::io_service::post(). - * - * @note The async_send operation can only be used with a connected socket. - * Use the async_send_to function to send data on an unconnected datagram - * socket. - */ - template - void async_send(const ConstBufferSequence& buffers, - socket_base::message_flags flags, WriteHandler handler) - { - this->service.async_send(this->implementation, buffers, flags, handler); - } - - /// Send a datagram to the specified endpoint. - /** - * This function is used to send a datagram to the specified remote endpoint. - * The function call will block until the data has been sent successfully or - * an error occurs. - * - * @param buffers One or more data buffers to be sent to the remote endpoint. - * - * @param destination The remote endpoint to which the data will be sent. - * - * @returns The number of bytes sent. - * - * @throws asio::system_error Thrown on failure. - * - * @par Example - * To send a single data buffer use the @ref buffer function as follows: - * @code - * asio::ip::udp::endpoint destination( - * asio::ip::address::from_string("1.2.3.4"), 12345); - * socket.send_to(asio::buffer(data, size), destination); - * @endcode - * See the @ref buffer documentation for information on sending multiple - * buffers in one go, and how to use it with arrays, boost::array or - * std::vector. - */ - template - std::size_t send_to(const ConstBufferSequence& buffers, - const endpoint_type& destination) - { - asio::error_code ec; - std::size_t s = this->service.send_to( - this->implementation, buffers, destination, 0, ec); - asio::detail::throw_error(ec); - return s; - } - - /// Send a datagram to the specified endpoint. - /** - * This function is used to send a datagram to the specified remote endpoint. - * The function call will block until the data has been sent successfully or - * an error occurs. - * - * @param buffers One or more data buffers to be sent to the remote endpoint. - * - * @param destination The remote endpoint to which the data will be sent. - * - * @param flags Flags specifying how the send call is to be made. - * - * @returns The number of bytes sent. - * - * @throws asio::system_error Thrown on failure. - */ - template - std::size_t send_to(const ConstBufferSequence& buffers, - const endpoint_type& destination, socket_base::message_flags flags) - { - asio::error_code ec; - std::size_t s = this->service.send_to( - this->implementation, buffers, destination, flags, ec); - asio::detail::throw_error(ec); - return s; - } - - /// Send a datagram to the specified endpoint. - /** - * This function is used to send a datagram to the specified remote endpoint. - * The function call will block until the data has been sent successfully or - * an error occurs. - * - * @param buffers One or more data buffers to be sent to the remote endpoint. - * - * @param destination The remote endpoint to which the data will be sent. - * - * @param flags Flags specifying how the send call is to be made. - * - * @param ec Set to indicate what error occurred, if any. - * - * @returns The number of bytes sent. - */ - template - std::size_t send_to(const ConstBufferSequence& buffers, - const endpoint_type& destination, socket_base::message_flags flags, - asio::error_code& ec) - { - return this->service.send_to(this->implementation, - buffers, destination, flags, ec); - } - - /// Start an asynchronous send. - /** - * This function is used to asynchronously send a datagram to the specified - * remote endpoint. The function call always returns immediately. - * - * @param buffers One or more data buffers to be sent to the remote endpoint. - * Although the buffers object may be copied as necessary, ownership of the - * underlying memory blocks is retained by the caller, which must guarantee - * that they remain valid until the handler is called. - * - * @param destination The remote endpoint to which the data will be sent. - * Copies will be made of the endpoint as required. - * - * @param handler The handler to be called when the send operation completes. - * Copies will be made of the handler as required. The function signature of - * the handler must be: - * @code void handler( - * const asio::error_code& error, // Result of operation. - * std::size_t bytes_transferred // Number of bytes sent. - * ); @endcode - * Regardless of whether the asynchronous operation completes immediately or - * not, the handler will not be invoked from within this function. Invocation - * of the handler will be performed in a manner equivalent to using - * asio::io_service::post(). - * - * @par Example - * To send a single data buffer use the @ref buffer function as follows: - * @code - * asio::ip::udp::endpoint destination( - * asio::ip::address::from_string("1.2.3.4"), 12345); - * socket.async_send_to( - * asio::buffer(data, size), destination, handler); - * @endcode - * See the @ref buffer documentation for information on sending multiple - * buffers in one go, and how to use it with arrays, boost::array or - * std::vector. - */ - template - void async_send_to(const ConstBufferSequence& buffers, - const endpoint_type& destination, WriteHandler handler) - { - this->service.async_send_to(this->implementation, buffers, destination, 0, - handler); - } - - /// Start an asynchronous send. - /** - * This function is used to asynchronously send a datagram to the specified - * remote endpoint. The function call always returns immediately. - * - * @param buffers One or more data buffers to be sent to the remote endpoint. - * Although the buffers object may be copied as necessary, ownership of the - * underlying memory blocks is retained by the caller, which must guarantee - * that they remain valid until the handler is called. - * - * @param flags Flags specifying how the send call is to be made. - * - * @param destination The remote endpoint to which the data will be sent. - * Copies will be made of the endpoint as required. - * - * @param handler The handler to be called when the send operation completes. - * Copies will be made of the handler as required. The function signature of - * the handler must be: - * @code void handler( - * const asio::error_code& error, // Result of operation. - * std::size_t bytes_transferred // Number of bytes sent. - * ); @endcode - * Regardless of whether the asynchronous operation completes immediately or - * not, the handler will not be invoked from within this function. Invocation - * of the handler will be performed in a manner equivalent to using - * asio::io_service::post(). - */ - template - void async_send_to(const ConstBufferSequence& buffers, - const endpoint_type& destination, socket_base::message_flags flags, - WriteHandler handler) - { - this->service.async_send_to(this->implementation, buffers, destination, - flags, handler); - } - - /// Receive some data on a connected socket. - /** - * This function is used to receive data on the datagram socket. The function - * call will block until data has been received successfully or an error - * occurs. - * - * @param buffers One or more buffers into which the data will be received. - * - * @returns The number of bytes received. - * - * @throws asio::system_error Thrown on failure. - * - * @note The receive operation can only be used with a connected socket. Use - * the receive_from function to receive data on an unconnected datagram - * socket. - * - * @par Example - * To receive into a single data buffer use the @ref buffer function as - * follows: - * @code socket.receive(asio::buffer(data, size)); @endcode - * See the @ref buffer documentation for information on receiving into - * multiple buffers in one go, and how to use it with arrays, boost::array or - * std::vector. - */ - template - std::size_t receive(const MutableBufferSequence& buffers) - { - asio::error_code ec; - std::size_t s = this->service.receive( - this->implementation, buffers, 0, ec); - asio::detail::throw_error(ec); - return s; - } - - /// Receive some data on a connected socket. - /** - * This function is used to receive data on the datagram socket. The function - * call will block until data has been received successfully or an error - * occurs. - * - * @param buffers One or more buffers into which the data will be received. - * - * @param flags Flags specifying how the receive call is to be made. - * - * @returns The number of bytes received. - * - * @throws asio::system_error Thrown on failure. - * - * @note The receive operation can only be used with a connected socket. Use - * the receive_from function to receive data on an unconnected datagram - * socket. - */ - template - std::size_t receive(const MutableBufferSequence& buffers, - socket_base::message_flags flags) - { - asio::error_code ec; - std::size_t s = this->service.receive( - this->implementation, buffers, flags, ec); - asio::detail::throw_error(ec); - return s; - } - - /// Receive some data on a connected socket. - /** - * This function is used to receive data on the datagram socket. The function - * call will block until data has been received successfully or an error - * occurs. - * - * @param buffers One or more buffers into which the data will be received. - * - * @param flags Flags specifying how the receive call is to be made. - * - * @param ec Set to indicate what error occurred, if any. - * - * @returns The number of bytes received. - * - * @note The receive operation can only be used with a connected socket. Use - * the receive_from function to receive data on an unconnected datagram - * socket. - */ - template - std::size_t receive(const MutableBufferSequence& buffers, - socket_base::message_flags flags, asio::error_code& ec) - { - return this->service.receive(this->implementation, buffers, flags, ec); - } - - /// Start an asynchronous receive on a connected socket. - /** - * This function is used to asynchronously receive data from the datagram - * socket. The function call always returns immediately. - * - * @param buffers One or more buffers into which the data will be received. - * Although the buffers object may be copied as necessary, ownership of the - * underlying memory blocks is retained by the caller, which must guarantee - * that they remain valid until the handler is called. - * - * @param handler The handler to be called when the receive operation - * completes. Copies will be made of the handler as required. The function - * signature of the handler must be: - * @code void handler( - * const asio::error_code& error, // Result of operation. - * std::size_t bytes_transferred // Number of bytes received. - * ); @endcode - * Regardless of whether the asynchronous operation completes immediately or - * not, the handler will not be invoked from within this function. Invocation - * of the handler will be performed in a manner equivalent to using - * asio::io_service::post(). - * - * @note The async_receive operation can only be used with a connected socket. - * Use the async_receive_from function to receive data on an unconnected - * datagram socket. - * - * @par Example - * To receive into a single data buffer use the @ref buffer function as - * follows: - * @code - * socket.async_receive(asio::buffer(data, size), handler); - * @endcode - * See the @ref buffer documentation for information on receiving into - * multiple buffers in one go, and how to use it with arrays, boost::array or - * std::vector. - */ - template - void async_receive(const MutableBufferSequence& buffers, ReadHandler handler) - { - this->service.async_receive(this->implementation, buffers, 0, handler); - } - - /// Start an asynchronous receive on a connected socket. - /** - * This function is used to asynchronously receive data from the datagram - * socket. The function call always returns immediately. - * - * @param buffers One or more buffers into which the data will be received. - * Although the buffers object may be copied as necessary, ownership of the - * underlying memory blocks is retained by the caller, which must guarantee - * that they remain valid until the handler is called. - * - * @param flags Flags specifying how the receive call is to be made. - * - * @param handler The handler to be called when the receive operation - * completes. Copies will be made of the handler as required. The function - * signature of the handler must be: - * @code void handler( - * const asio::error_code& error, // Result of operation. - * std::size_t bytes_transferred // Number of bytes received. - * ); @endcode - * Regardless of whether the asynchronous operation completes immediately or - * not, the handler will not be invoked from within this function. Invocation - * of the handler will be performed in a manner equivalent to using - * asio::io_service::post(). - * - * @note The async_receive operation can only be used with a connected socket. - * Use the async_receive_from function to receive data on an unconnected - * datagram socket. - */ - template - void async_receive(const MutableBufferSequence& buffers, - socket_base::message_flags flags, ReadHandler handler) - { - this->service.async_receive(this->implementation, buffers, flags, handler); - } - - /// Receive a datagram with the endpoint of the sender. - /** - * This function is used to receive a datagram. The function call will block - * until data has been received successfully or an error occurs. - * - * @param buffers One or more buffers into which the data will be received. - * - * @param sender_endpoint An endpoint object that receives the endpoint of - * the remote sender of the datagram. - * - * @returns The number of bytes received. - * - * @throws asio::system_error Thrown on failure. - * - * @par Example - * To receive into a single data buffer use the @ref buffer function as - * follows: - * @code - * asio::ip::udp::endpoint sender_endpoint; - * socket.receive_from( - * asio::buffer(data, size), sender_endpoint); - * @endcode - * See the @ref buffer documentation for information on receiving into - * multiple buffers in one go, and how to use it with arrays, boost::array or - * std::vector. - */ - template - std::size_t receive_from(const MutableBufferSequence& buffers, - endpoint_type& sender_endpoint) - { - asio::error_code ec; - std::size_t s = this->service.receive_from( - this->implementation, buffers, sender_endpoint, 0, ec); - asio::detail::throw_error(ec); - return s; - } - - /// Receive a datagram with the endpoint of the sender. - /** - * This function is used to receive a datagram. The function call will block - * until data has been received successfully or an error occurs. - * - * @param buffers One or more buffers into which the data will be received. - * - * @param sender_endpoint An endpoint object that receives the endpoint of - * the remote sender of the datagram. - * - * @param flags Flags specifying how the receive call is to be made. - * - * @returns The number of bytes received. - * - * @throws asio::system_error Thrown on failure. - */ - template - std::size_t receive_from(const MutableBufferSequence& buffers, - endpoint_type& sender_endpoint, socket_base::message_flags flags) - { - asio::error_code ec; - std::size_t s = this->service.receive_from( - this->implementation, buffers, sender_endpoint, flags, ec); - asio::detail::throw_error(ec); - return s; - } - - /// Receive a datagram with the endpoint of the sender. - /** - * This function is used to receive a datagram. The function call will block - * until data has been received successfully or an error occurs. - * - * @param buffers One or more buffers into which the data will be received. - * - * @param sender_endpoint An endpoint object that receives the endpoint of - * the remote sender of the datagram. - * - * @param flags Flags specifying how the receive call is to be made. - * - * @param ec Set to indicate what error occurred, if any. - * - * @returns The number of bytes received. - */ - template - std::size_t receive_from(const MutableBufferSequence& buffers, - endpoint_type& sender_endpoint, socket_base::message_flags flags, - asio::error_code& ec) - { - return this->service.receive_from(this->implementation, buffers, - sender_endpoint, flags, ec); - } - - /// Start an asynchronous receive. - /** - * This function is used to asynchronously receive a datagram. The function - * call always returns immediately. - * - * @param buffers One or more buffers into which the data will be received. - * Although the buffers object may be copied as necessary, ownership of the - * underlying memory blocks is retained by the caller, which must guarantee - * that they remain valid until the handler is called. - * - * @param sender_endpoint An endpoint object that receives the endpoint of - * the remote sender of the datagram. Ownership of the sender_endpoint object - * is retained by the caller, which must guarantee that it is valid until the - * handler is called. - * - * @param handler The handler to be called when the receive operation - * completes. Copies will be made of the handler as required. The function - * signature of the handler must be: - * @code void handler( - * const asio::error_code& error, // Result of operation. - * std::size_t bytes_transferred // Number of bytes received. - * ); @endcode - * Regardless of whether the asynchronous operation completes immediately or - * not, the handler will not be invoked from within this function. Invocation - * of the handler will be performed in a manner equivalent to using - * asio::io_service::post(). - * - * @par Example - * To receive into a single data buffer use the @ref buffer function as - * follows: - * @code socket.async_receive_from( - * asio::buffer(data, size), 0, sender_endpoint, handler); @endcode - * See the @ref buffer documentation for information on receiving into - * multiple buffers in one go, and how to use it with arrays, boost::array or - * std::vector. - */ - template - void async_receive_from(const MutableBufferSequence& buffers, - endpoint_type& sender_endpoint, ReadHandler handler) - { - this->service.async_receive_from(this->implementation, buffers, - sender_endpoint, 0, handler); - } - - /// Start an asynchronous receive. - /** - * This function is used to asynchronously receive a datagram. The function - * call always returns immediately. - * - * @param buffers One or more buffers into which the data will be received. - * Although the buffers object may be copied as necessary, ownership of the - * underlying memory blocks is retained by the caller, which must guarantee - * that they remain valid until the handler is called. - * - * @param sender_endpoint An endpoint object that receives the endpoint of - * the remote sender of the datagram. Ownership of the sender_endpoint object - * is retained by the caller, which must guarantee that it is valid until the - * handler is called. - * - * @param flags Flags specifying how the receive call is to be made. - * - * @param handler The handler to be called when the receive operation - * completes. Copies will be made of the handler as required. The function - * signature of the handler must be: - * @code void handler( - * const asio::error_code& error, // Result of operation. - * std::size_t bytes_transferred // Number of bytes received. - * ); @endcode - * Regardless of whether the asynchronous operation completes immediately or - * not, the handler will not be invoked from within this function. Invocation - * of the handler will be performed in a manner equivalent to using - * asio::io_service::post(). - */ - template - void async_receive_from(const MutableBufferSequence& buffers, - endpoint_type& sender_endpoint, socket_base::message_flags flags, - ReadHandler handler) - { - this->service.async_receive_from(this->implementation, buffers, - sender_endpoint, flags, handler); - } -}; - -} // namespace asio - -#include "asio/detail/pop_options.hpp" - -#endif // ASIO_BASIC_DATAGRAM_SOCKET_HPP diff --git a/libtorrent/include/asio/basic_deadline_timer.hpp b/libtorrent/include/asio/basic_deadline_timer.hpp deleted file mode 100644 index 75d33b950..000000000 --- a/libtorrent/include/asio/basic_deadline_timer.hpp +++ /dev/null @@ -1,381 +0,0 @@ -// -// basic_deadline_timer.hpp -// ~~~~~~~~~~~~~~~~~~~~~~~~ -// -// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -#ifndef ASIO_BASIC_DEADLINE_TIMER_HPP -#define ASIO_BASIC_DEADLINE_TIMER_HPP - -#if defined(_MSC_VER) && (_MSC_VER >= 1200) -# pragma once -#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) - -#include "asio/detail/push_options.hpp" - -#include "asio/detail/push_options.hpp" -#include -#include -#include "asio/detail/pop_options.hpp" - -#include "asio/basic_io_object.hpp" -#include "asio/deadline_timer_service.hpp" -#include "asio/error.hpp" -#include "asio/detail/throw_error.hpp" - -namespace asio { - -/// Provides waitable timer functionality. -/** - * The basic_deadline_timer class template provides the ability to perform a - * blocking or asynchronous wait for a timer to expire. - * - * Most applications will use the asio::deadline_timer typedef. - * - * @par Thread Safety - * @e Distinct @e objects: Safe.@n - * @e Shared @e objects: Unsafe. - * - * @par Examples - * Performing a blocking wait: - * @code - * // Construct a timer without setting an expiry time. - * asio::deadline_timer timer(io_service); - * - * // Set an expiry time relative to now. - * timer.expires_from_now(boost::posix_time::seconds(5)); - * - * // Wait for the timer to expire. - * timer.wait(); - * @endcode - * - * @par - * Performing an asynchronous wait: - * @code - * void handler(const asio::error_code& error) - * { - * if (!error) - * { - * // Timer expired. - * } - * } - * - * ... - * - * // Construct a timer with an absolute expiry time. - * asio::deadline_timer timer(io_service, - * boost::posix_time::time_from_string("2005-12-07 23:59:59.000")); - * - * // Start an asynchronous wait. - * timer.async_wait(handler); - * @endcode - * - * @par Changing an active deadline_timer's expiry time - * - * Changing the expiry time of a timer while there are pending asynchronous - * waits causes those wait operations to be cancelled. To ensure that the action - * associated with the timer is performed only once, use something like this: - * used: - * - * @code - * void on_some_event() - * { - * if (my_timer.expires_from_now(seconds(5)) > 0) - * { - * // We managed to cancel the timer. Start new asynchronous wait. - * my_timer.async_wait(on_timeout); - * } - * else - * { - * // Too late, timer has already expired! - * } - * } - * - * void on_timeout(const asio::error_code& e) - * { - * if (e != asio::error::operation_aborted) - * { - * // Timer was not cancelled, take necessary action. - * } - * } - * @endcode - * - * @li The asio::basic_deadline_timer::expires_from_now() function - * cancels any pending asynchronous waits, and returns the number of - * asynchronous waits that were cancelled. If it returns 0 then you were too - * late and the wait handler has already been executed, or will soon be - * executed. If it returns 1 then the wait handler was successfully cancelled. - * - * @li If a wait handler is cancelled, the asio::error_code passed to - * it contains the value asio::error::operation_aborted. - */ -template , - typename TimerService = deadline_timer_service > -class basic_deadline_timer - : public basic_io_object -{ -public: - /// The time traits type. - typedef TimeTraits traits_type; - - /// The time type. - typedef typename traits_type::time_type time_type; - - /// The duration type. - typedef typename traits_type::duration_type duration_type; - - /// Constructor. - /** - * This constructor creates a timer without setting an expiry time. The - * expires_at() or expires_from_now() functions must be called to set an - * expiry time before the timer can be waited on. - * - * @param io_service The io_service object that the timer will use to dispatch - * handlers for any asynchronous operations performed on the timer. - */ - explicit basic_deadline_timer(asio::io_service& io_service) - : basic_io_object(io_service) - { - } - - /// Constructor to set a particular expiry time as an absolute time. - /** - * This constructor creates a timer and sets the expiry time. - * - * @param io_service The io_service object that the timer will use to dispatch - * handlers for any asynchronous operations performed on the timer. - * - * @param expiry_time The expiry time to be used for the timer, expressed - * as an absolute time. - */ - basic_deadline_timer(asio::io_service& io_service, - const time_type& expiry_time) - : basic_io_object(io_service) - { - asio::error_code ec; - this->service.expires_at(this->implementation, expiry_time, ec); - asio::detail::throw_error(ec); - } - - /// Constructor to set a particular expiry time relative to now. - /** - * This constructor creates a timer and sets the expiry time. - * - * @param io_service The io_service object that the timer will use to dispatch - * handlers for any asynchronous operations performed on the timer. - * - * @param expiry_time The expiry time to be used for the timer, relative to - * now. - */ - basic_deadline_timer(asio::io_service& io_service, - const duration_type& expiry_time) - : basic_io_object(io_service) - { - asio::error_code ec; - this->service.expires_from_now(this->implementation, expiry_time, ec); - asio::detail::throw_error(ec); - } - - /// Cancel any asynchronous operations that are waiting on the timer. - /** - * This function forces the completion of any pending asynchronous wait - * operations against the timer. The handler for each cancelled operation will - * be invoked with the asio::error::operation_aborted error code. - * - * Cancelling the timer does not change the expiry time. - * - * @return The number of asynchronous operations that were cancelled. - * - * @throws asio::system_error Thrown on failure. - */ - std::size_t cancel() - { - asio::error_code ec; - std::size_t s = this->service.cancel(this->implementation, ec); - asio::detail::throw_error(ec); - return s; - } - - /// Cancel any asynchronous operations that are waiting on the timer. - /** - * This function forces the completion of any pending asynchronous wait - * operations against the timer. The handler for each cancelled operation will - * be invoked with the asio::error::operation_aborted error code. - * - * Cancelling the timer does not change the expiry time. - * - * @param ec Set to indicate what error occurred, if any. - * - * @return The number of asynchronous operations that were cancelled. - */ - std::size_t cancel(asio::error_code& ec) - { - return this->service.cancel(this->implementation, ec); - } - - /// Get the timer's expiry time as an absolute time. - /** - * This function may be used to obtain the timer's current expiry time. - * Whether the timer has expired or not does not affect this value. - */ - time_type expires_at() const - { - return this->service.expires_at(this->implementation); - } - - /// Set the timer's expiry time as an absolute time. - /** - * This function sets the expiry time. Any pending asynchronous wait - * operations will be cancelled. The handler for each cancelled operation will - * be invoked with the asio::error::operation_aborted error code. - * - * @param expiry_time The expiry time to be used for the timer. - * - * @return The number of asynchronous operations that were cancelled. - * - * @throws asio::system_error Thrown on failure. - */ - std::size_t expires_at(const time_type& expiry_time) - { - asio::error_code ec; - std::size_t s = this->service.expires_at( - this->implementation, expiry_time, ec); - asio::detail::throw_error(ec); - return s; - } - - /// Set the timer's expiry time as an absolute time. - /** - * This function sets the expiry time. Any pending asynchronous wait - * operations will be cancelled. The handler for each cancelled operation will - * be invoked with the asio::error::operation_aborted error code. - * - * @param expiry_time The expiry time to be used for the timer. - * - * @param ec Set to indicate what error occurred, if any. - * - * @return The number of asynchronous operations that were cancelled. - */ - std::size_t expires_at(const time_type& expiry_time, - asio::error_code& ec) - { - return this->service.expires_at(this->implementation, expiry_time, ec); - } - - /// Get the timer's expiry time relative to now. - /** - * This function may be used to obtain the timer's current expiry time. - * Whether the timer has expired or not does not affect this value. - */ - duration_type expires_from_now() const - { - return this->service.expires_from_now(this->implementation); - } - - /// Set the timer's expiry time relative to now. - /** - * This function sets the expiry time. Any pending asynchronous wait - * operations will be cancelled. The handler for each cancelled operation will - * be invoked with the asio::error::operation_aborted error code. - * - * @param expiry_time The expiry time to be used for the timer. - * - * @return The number of asynchronous operations that were cancelled. - * - * @throws asio::system_error Thrown on failure. - */ - std::size_t expires_from_now(const duration_type& expiry_time) - { - asio::error_code ec; - std::size_t s = this->service.expires_from_now( - this->implementation, expiry_time, ec); - asio::detail::throw_error(ec); - return s; - } - - /// Set the timer's expiry time relative to now. - /** - * This function sets the expiry time. Any pending asynchronous wait - * operations will be cancelled. The handler for each cancelled operation will - * be invoked with the asio::error::operation_aborted error code. - * - * @param expiry_time The expiry time to be used for the timer. - * - * @param ec Set to indicate what error occurred, if any. - * - * @return The number of asynchronous operations that were cancelled. - */ - std::size_t expires_from_now(const duration_type& expiry_time, - asio::error_code& ec) - { - return this->service.expires_from_now( - this->implementation, expiry_time, ec); - } - - /// Perform a blocking wait on the timer. - /** - * This function is used to wait for the timer to expire. This function - * blocks and does not return until the timer has expired. - * - * @throws asio::system_error Thrown on failure. - */ - void wait() - { - asio::error_code ec; - this->service.wait(this->implementation, ec); - asio::detail::throw_error(ec); - } - - /// Perform a blocking wait on the timer. - /** - * This function is used to wait for the timer to expire. This function - * blocks and does not return until the timer has expired. - * - * @param ec Set to indicate what error occurred, if any. - */ - void wait(asio::error_code& ec) - { - this->service.wait(this->implementation, ec); - } - - /// Start an asynchronous wait on the timer. - /** - * This function may be used to initiate an asynchronous wait against the - * timer. It always returns immediately. - * - * For each call to async_wait(), the supplied handler will be called exactly - * once. The handler will be called when: - * - * @li The timer has expired. - * - * @li The timer was cancelled, in which case the handler is passed the error - * code asio::error::operation_aborted. - * - * @param handler The handler to be called when the timer expires. Copies - * will be made of the handler as required. The function signature of the - * handler must be: - * @code void handler( - * const asio::error_code& error // Result of operation. - * ); @endcode - * Regardless of whether the asynchronous operation completes immediately or - * not, the handler will not be invoked from within this function. Invocation - * of the handler will be performed in a manner equivalent to using - * asio::io_service::post(). - */ - template - void async_wait(WaitHandler handler) - { - this->service.async_wait(this->implementation, handler); - } -}; - -} // namespace asio - -#include "asio/detail/pop_options.hpp" - -#endif // ASIO_BASIC_DEADLINE_TIMER_HPP diff --git a/libtorrent/include/asio/basic_io_object.hpp b/libtorrent/include/asio/basic_io_object.hpp deleted file mode 100644 index 6e369ab4d..000000000 --- a/libtorrent/include/asio/basic_io_object.hpp +++ /dev/null @@ -1,97 +0,0 @@ -// -// basic_io_object.hpp -// ~~~~~~~~~~~~~~~~~~~ -// -// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -#ifndef ASIO_BASIC_IO_OBJECT_HPP -#define ASIO_BASIC_IO_OBJECT_HPP - -#if defined(_MSC_VER) && (_MSC_VER >= 1200) -# pragma once -#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) - -#include "asio/detail/push_options.hpp" - -#include "asio/io_service.hpp" -#include "asio/detail/noncopyable.hpp" - -namespace asio { - -/// Base class for all I/O objects. -template -class basic_io_object - : private noncopyable -{ -public: - /// The type of the service that will be used to provide I/O operations. - typedef IoObjectService service_type; - - /// The underlying implementation type of I/O object. - typedef typename service_type::implementation_type implementation_type; - - /// (Deprecated: use get_io_service().) Get the io_service associated with - /// the object. - /** - * This function may be used to obtain the io_service object that the I/O - * object uses to dispatch handlers for asynchronous operations. - * - * @return A reference to the io_service object that the I/O object will use - * to dispatch handlers. Ownership is not transferred to the caller. - */ - asio::io_service& io_service() - { - return service.get_io_service(); - } - - /// Get the io_service associated with the object. - /** - * This function may be used to obtain the io_service object that the I/O - * object uses to dispatch handlers for asynchronous operations. - * - * @return A reference to the io_service object that the I/O object will use - * to dispatch handlers. Ownership is not transferred to the caller. - */ - asio::io_service& get_io_service() - { - return service.get_io_service(); - } - -protected: - /// Construct a basic_io_object. - /** - * Performs: - * @code service.construct(implementation); @endcode - */ - explicit basic_io_object(asio::io_service& io_service) - : service(asio::use_service(io_service)) - { - service.construct(implementation); - } - - /// Protected destructor to prevent deletion through this type. - /** - * Performs: - * @code service.destroy(implementation); @endcode - */ - ~basic_io_object() - { - service.destroy(implementation); - } - - /// The service associated with the I/O object. - service_type& service; - - /// The underlying implementation of the I/O object. - implementation_type implementation; -}; - -} // namespace asio - -#include "asio/detail/pop_options.hpp" - -#endif // ASIO_BASIC_IO_OBJECT_HPP diff --git a/libtorrent/include/asio/basic_raw_socket.hpp b/libtorrent/include/asio/basic_raw_socket.hpp deleted file mode 100644 index 5e2f033bd..000000000 --- a/libtorrent/include/asio/basic_raw_socket.hpp +++ /dev/null @@ -1,798 +0,0 @@ -// -// basic_raw_socket.hpp -// ~~~~~~~~~~~~~~~~~~~~ -// -// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -#ifndef ASIO_BASIC_RAW_SOCKET_HPP -#define ASIO_BASIC_RAW_SOCKET_HPP - -#if defined(_MSC_VER) && (_MSC_VER >= 1200) -# pragma once -#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) - -#include "asio/detail/push_options.hpp" - -#include "asio/detail/push_options.hpp" -#include -#include -#include "asio/detail/pop_options.hpp" - -#include "asio/basic_socket.hpp" -#include "asio/raw_socket_service.hpp" -#include "asio/error.hpp" -#include "asio/detail/throw_error.hpp" - -namespace asio { - -/// Provides raw-oriented socket functionality. -/** - * The basic_raw_socket class template provides asynchronous and blocking - * raw-oriented socket functionality. - * - * @par Thread Safety - * @e Distinct @e objects: Safe.@n - * @e Shared @e objects: Unsafe. - */ -template > -class basic_raw_socket - : public basic_socket -{ -public: - /// The native representation of a socket. - typedef typename RawSocketService::native_type native_type; - - /// The protocol type. - typedef Protocol protocol_type; - - /// The endpoint type. - typedef typename Protocol::endpoint endpoint_type; - - /// Construct a basic_raw_socket without opening it. - /** - * This constructor creates a raw socket without opening it. The open() - * function must be called before data can be sent or received on the socket. - * - * @param io_service The io_service object that the raw socket will use - * to dispatch handlers for any asynchronous operations performed on the - * socket. - */ - explicit basic_raw_socket(asio::io_service& io_service) - : basic_socket(io_service) - { - } - - /// Construct and open a basic_raw_socket. - /** - * This constructor creates and opens a raw socket. - * - * @param io_service The io_service object that the raw socket will use - * to dispatch handlers for any asynchronous operations performed on the - * socket. - * - * @param protocol An object specifying protocol parameters to be used. - * - * @throws asio::system_error Thrown on failure. - */ - basic_raw_socket(asio::io_service& io_service, - const protocol_type& protocol) - : basic_socket(io_service, protocol) - { - } - - /// Construct a basic_raw_socket, opening it and binding it to the given - /// local endpoint. - /** - * This constructor creates a raw socket and automatically opens it bound - * to the specified endpoint on the local machine. The protocol used is the - * protocol associated with the given endpoint. - * - * @param io_service The io_service object that the raw socket will use - * to dispatch handlers for any asynchronous operations performed on the - * socket. - * - * @param endpoint An endpoint on the local machine to which the raw - * socket will be bound. - * - * @throws asio::system_error Thrown on failure. - */ - basic_raw_socket(asio::io_service& io_service, - const endpoint_type& endpoint) - : basic_socket(io_service, endpoint) - { - } - - /// Construct a basic_raw_socket on an existing native socket. - /** - * This constructor creates a raw socket object to hold an existing - * native socket. - * - * @param io_service The io_service object that the raw socket will use - * to dispatch handlers for any asynchronous operations performed on the - * socket. - * - * @param protocol An object specifying protocol parameters to be used. - * - * @param native_socket The new underlying socket implementation. - * - * @throws asio::system_error Thrown on failure. - */ - basic_raw_socket(asio::io_service& io_service, - const protocol_type& protocol, const native_type& native_socket) - : basic_socket( - io_service, protocol, native_socket) - { - } - - /// Send some data on a connected socket. - /** - * This function is used to send data on the raw socket. The function call - * will block until the data has been sent successfully or an error occurs. - * - * @param buffers One ore more data buffers to be sent on the socket. - * - * @returns The number of bytes sent. - * - * @throws asio::system_error Thrown on failure. - * - * @note The send operation can only be used with a connected socket. Use - * the send_to function to send data on an unconnected raw socket. - * - * @par Example - * To send a single data buffer use the @ref buffer function as follows: - * @code socket.send(asio::buffer(data, size)); @endcode - * See the @ref buffer documentation for information on sending multiple - * buffers in one go, and how to use it with arrays, boost::array or - * std::vector. - */ - template - std::size_t send(const ConstBufferSequence& buffers) - { - asio::error_code ec; - std::size_t s = this->service.send(this->implementation, buffers, 0, ec); - asio::detail::throw_error(ec); - return s; - } - - /// Send some data on a connected socket. - /** - * This function is used to send data on the raw socket. The function call - * will block until the data has been sent successfully or an error occurs. - * - * @param buffers One ore more data buffers to be sent on the socket. - * - * @param flags Flags specifying how the send call is to be made. - * - * @returns The number of bytes sent. - * - * @throws asio::system_error Thrown on failure. - * - * @note The send operation can only be used with a connected socket. Use - * the send_to function to send data on an unconnected raw socket. - */ - template - std::size_t send(const ConstBufferSequence& buffers, - socket_base::message_flags flags) - { - asio::error_code ec; - std::size_t s = this->service.send( - this->implementation, buffers, flags, ec); - asio::detail::throw_error(ec); - return s; - } - - /// Send some data on a connected socket. - /** - * This function is used to send data on the raw socket. The function call - * will block until the data has been sent successfully or an error occurs. - * - * @param buffers One or more data buffers to be sent on the socket. - * - * @param flags Flags specifying how the send call is to be made. - * - * @param ec Set to indicate what error occurred, if any. - * - * @returns The number of bytes sent. - * - * @note The send operation can only be used with a connected socket. Use - * the send_to function to send data on an unconnected raw socket. - */ - template - std::size_t send(const ConstBufferSequence& buffers, - socket_base::message_flags flags, asio::error_code& ec) - { - return this->service.send(this->implementation, buffers, flags, ec); - } - - /// Start an asynchronous send on a connected socket. - /** - * This function is used to send data on the raw socket. The function call - * will block until the data has been sent successfully or an error occurs. - * - * @param buffers One or more data buffers to be sent on the socket. Although - * the buffers object may be copied as necessary, ownership of the underlying - * memory blocks is retained by the caller, which must guarantee that they - * remain valid until the handler is called. - * - * @param handler The handler to be called when the send operation completes. - * Copies will be made of the handler as required. The function signature of - * the handler must be: - * @code void handler( - * const asio::error_code& error, // Result of operation. - * std::size_t bytes_transferred // Number of bytes sent. - * ); @endcode - * Regardless of whether the asynchronous operation completes immediately or - * not, the handler will not be invoked from within this function. Invocation - * of the handler will be performed in a manner equivalent to using - * asio::io_service::post(). - * - * @note The async_send operation can only be used with a connected socket. - * Use the async_send_to function to send data on an unconnected raw - * socket. - * - * @par Example - * To send a single data buffer use the @ref buffer function as follows: - * @code - * socket.async_send(asio::buffer(data, size), handler); - * @endcode - * See the @ref buffer documentation for information on sending multiple - * buffers in one go, and how to use it with arrays, boost::array or - * std::vector. - */ - template - void async_send(const ConstBufferSequence& buffers, WriteHandler handler) - { - this->service.async_send(this->implementation, buffers, 0, handler); - } - - /// Start an asynchronous send on a connected socket. - /** - * This function is used to send data on the raw socket. The function call - * will block until the data has been sent successfully or an error occurs. - * - * @param buffers One or more data buffers to be sent on the socket. Although - * the buffers object may be copied as necessary, ownership of the underlying - * memory blocks is retained by the caller, which must guarantee that they - * remain valid until the handler is called. - * - * @param flags Flags specifying how the send call is to be made. - * - * @param handler The handler to be called when the send operation completes. - * Copies will be made of the handler as required. The function signature of - * the handler must be: - * @code void handler( - * const asio::error_code& error, // Result of operation. - * std::size_t bytes_transferred // Number of bytes sent. - * ); @endcode - * Regardless of whether the asynchronous operation completes immediately or - * not, the handler will not be invoked from within this function. Invocation - * of the handler will be performed in a manner equivalent to using - * asio::io_service::post(). - * - * @note The async_send operation can only be used with a connected socket. - * Use the async_send_to function to send data on an unconnected raw - * socket. - */ - template - void async_send(const ConstBufferSequence& buffers, - socket_base::message_flags flags, WriteHandler handler) - { - this->service.async_send(this->implementation, buffers, flags, handler); - } - - /// Send raw data to the specified endpoint. - /** - * This function is used to send raw data to the specified remote endpoint. - * The function call will block until the data has been sent successfully or - * an error occurs. - * - * @param buffers One or more data buffers to be sent to the remote endpoint. - * - * @param destination The remote endpoint to which the data will be sent. - * - * @returns The number of bytes sent. - * - * @throws asio::system_error Thrown on failure. - * - * @par Example - * To send a single data buffer use the @ref buffer function as follows: - * @code - * asio::ip::udp::endpoint destination( - * asio::ip::address::from_string("1.2.3.4"), 12345); - * socket.send_to(asio::buffer(data, size), destination); - * @endcode - * See the @ref buffer documentation for information on sending multiple - * buffers in one go, and how to use it with arrays, boost::array or - * std::vector. - */ - template - std::size_t send_to(const ConstBufferSequence& buffers, - const endpoint_type& destination) - { - asio::error_code ec; - std::size_t s = this->service.send_to( - this->implementation, buffers, destination, 0, ec); - asio::detail::throw_error(ec); - return s; - } - - /// Send raw data to the specified endpoint. - /** - * This function is used to send raw data to the specified remote endpoint. - * The function call will block until the data has been sent successfully or - * an error occurs. - * - * @param buffers One or more data buffers to be sent to the remote endpoint. - * - * @param destination The remote endpoint to which the data will be sent. - * - * @param flags Flags specifying how the send call is to be made. - * - * @returns The number of bytes sent. - * - * @throws asio::system_error Thrown on failure. - */ - template - std::size_t send_to(const ConstBufferSequence& buffers, - const endpoint_type& destination, socket_base::message_flags flags) - { - asio::error_code ec; - std::size_t s = this->service.send_to( - this->implementation, buffers, destination, flags, ec); - asio::detail::throw_error(ec); - return s; - } - - /// Send raw data to the specified endpoint. - /** - * This function is used to send raw data to the specified remote endpoint. - * The function call will block until the data has been sent successfully or - * an error occurs. - * - * @param buffers One or more data buffers to be sent to the remote endpoint. - * - * @param destination The remote endpoint to which the data will be sent. - * - * @param flags Flags specifying how the send call is to be made. - * - * @param ec Set to indicate what error occurred, if any. - * - * @returns The number of bytes sent. - */ - template - std::size_t send_to(const ConstBufferSequence& buffers, - const endpoint_type& destination, socket_base::message_flags flags, - asio::error_code& ec) - { - return this->service.send_to(this->implementation, - buffers, destination, flags, ec); - } - - /// Start an asynchronous send. - /** - * This function is used to asynchronously send raw data to the specified - * remote endpoint. The function call always returns immediately. - * - * @param buffers One or more data buffers to be sent to the remote endpoint. - * Although the buffers object may be copied as necessary, ownership of the - * underlying memory blocks is retained by the caller, which must guarantee - * that they remain valid until the handler is called. - * - * @param destination The remote endpoint to which the data will be sent. - * Copies will be made of the endpoint as required. - * - * @param handler The handler to be called when the send operation completes. - * Copies will be made of the handler as required. The function signature of - * the handler must be: - * @code void handler( - * const asio::error_code& error, // Result of operation. - * std::size_t bytes_transferred // Number of bytes sent. - * ); @endcode - * Regardless of whether the asynchronous operation completes immediately or - * not, the handler will not be invoked from within this function. Invocation - * of the handler will be performed in a manner equivalent to using - * asio::io_service::post(). - * - * @par Example - * To send a single data buffer use the @ref buffer function as follows: - * @code - * asio::ip::udp::endpoint destination( - * asio::ip::address::from_string("1.2.3.4"), 12345); - * socket.async_send_to( - * asio::buffer(data, size), destination, handler); - * @endcode - * See the @ref buffer documentation for information on sending multiple - * buffers in one go, and how to use it with arrays, boost::array or - * std::vector. - */ - template - void async_send_to(const ConstBufferSequence& buffers, - const endpoint_type& destination, WriteHandler handler) - { - this->service.async_send_to(this->implementation, buffers, destination, 0, - handler); - } - - /// Start an asynchronous send. - /** - * This function is used to asynchronously send raw data to the specified - * remote endpoint. The function call always returns immediately. - * - * @param buffers One or more data buffers to be sent to the remote endpoint. - * Although the buffers object may be copied as necessary, ownership of the - * underlying memory blocks is retained by the caller, which must guarantee - * that they remain valid until the handler is called. - * - * @param flags Flags specifying how the send call is to be made. - * - * @param destination The remote endpoint to which the data will be sent. - * Copies will be made of the endpoint as required. - * - * @param handler The handler to be called when the send operation completes. - * Copies will be made of the handler as required. The function signature of - * the handler must be: - * @code void handler( - * const asio::error_code& error, // Result of operation. - * std::size_t bytes_transferred // Number of bytes sent. - * ); @endcode - * Regardless of whether the asynchronous operation completes immediately or - * not, the handler will not be invoked from within this function. Invocation - * of the handler will be performed in a manner equivalent to using - * asio::io_service::post(). - */ - template - void async_send_to(const ConstBufferSequence& buffers, - const endpoint_type& destination, socket_base::message_flags flags, - WriteHandler handler) - { - this->service.async_send_to(this->implementation, buffers, destination, - flags, handler); - } - - /// Receive some data on a connected socket. - /** - * This function is used to receive data on the raw socket. The function - * call will block until data has been received successfully or an error - * occurs. - * - * @param buffers One or more buffers into which the data will be received. - * - * @returns The number of bytes received. - * - * @throws asio::system_error Thrown on failure. - * - * @note The receive operation can only be used with a connected socket. Use - * the receive_from function to receive data on an unconnected raw - * socket. - * - * @par Example - * To receive into a single data buffer use the @ref buffer function as - * follows: - * @code socket.receive(asio::buffer(data, size)); @endcode - * See the @ref buffer documentation for information on receiving into - * multiple buffers in one go, and how to use it with arrays, boost::array or - * std::vector. - */ - template - std::size_t receive(const MutableBufferSequence& buffers) - { - asio::error_code ec; - std::size_t s = this->service.receive( - this->implementation, buffers, 0, ec); - asio::detail::throw_error(ec); - return s; - } - - /// Receive some data on a connected socket. - /** - * This function is used to receive data on the raw socket. The function - * call will block until data has been received successfully or an error - * occurs. - * - * @param buffers One or more buffers into which the data will be received. - * - * @param flags Flags specifying how the receive call is to be made. - * - * @returns The number of bytes received. - * - * @throws asio::system_error Thrown on failure. - * - * @note The receive operation can only be used with a connected socket. Use - * the receive_from function to receive data on an unconnected raw - * socket. - */ - template - std::size_t receive(const MutableBufferSequence& buffers, - socket_base::message_flags flags) - { - asio::error_code ec; - std::size_t s = this->service.receive( - this->implementation, buffers, flags, ec); - asio::detail::throw_error(ec); - return s; - } - - /// Receive some data on a connected socket. - /** - * This function is used to receive data on the raw socket. The function - * call will block until data has been received successfully or an error - * occurs. - * - * @param buffers One or more buffers into which the data will be received. - * - * @param flags Flags specifying how the receive call is to be made. - * - * @param ec Set to indicate what error occurred, if any. - * - * @returns The number of bytes received. - * - * @note The receive operation can only be used with a connected socket. Use - * the receive_from function to receive data on an unconnected raw - * socket. - */ - template - std::size_t receive(const MutableBufferSequence& buffers, - socket_base::message_flags flags, asio::error_code& ec) - { - return this->service.receive(this->implementation, buffers, flags, ec); - } - - /// Start an asynchronous receive on a connected socket. - /** - * This function is used to asynchronously receive data from the raw - * socket. The function call always returns immediately. - * - * @param buffers One or more buffers into which the data will be received. - * Although the buffers object may be copied as necessary, ownership of the - * underlying memory blocks is retained by the caller, which must guarantee - * that they remain valid until the handler is called. - * - * @param handler The handler to be called when the receive operation - * completes. Copies will be made of the handler as required. The function - * signature of the handler must be: - * @code void handler( - * const asio::error_code& error, // Result of operation. - * std::size_t bytes_transferred // Number of bytes received. - * ); @endcode - * Regardless of whether the asynchronous operation completes immediately or - * not, the handler will not be invoked from within this function. Invocation - * of the handler will be performed in a manner equivalent to using - * asio::io_service::post(). - * - * @note The async_receive operation can only be used with a connected socket. - * Use the async_receive_from function to receive data on an unconnected - * raw socket. - * - * @par Example - * To receive into a single data buffer use the @ref buffer function as - * follows: - * @code - * socket.async_receive(asio::buffer(data, size), handler); - * @endcode - * See the @ref buffer documentation for information on receiving into - * multiple buffers in one go, and how to use it with arrays, boost::array or - * std::vector. - */ - template - void async_receive(const MutableBufferSequence& buffers, ReadHandler handler) - { - this->service.async_receive(this->implementation, buffers, 0, handler); - } - - /// Start an asynchronous receive on a connected socket. - /** - * This function is used to asynchronously receive data from the raw - * socket. The function call always returns immediately. - * - * @param buffers One or more buffers into which the data will be received. - * Although the buffers object may be copied as necessary, ownership of the - * underlying memory blocks is retained by the caller, which must guarantee - * that they remain valid until the handler is called. - * - * @param flags Flags specifying how the receive call is to be made. - * - * @param handler The handler to be called when the receive operation - * completes. Copies will be made of the handler as required. The function - * signature of the handler must be: - * @code void handler( - * const asio::error_code& error, // Result of operation. - * std::size_t bytes_transferred // Number of bytes received. - * ); @endcode - * Regardless of whether the asynchronous operation completes immediately or - * not, the handler will not be invoked from within this function. Invocation - * of the handler will be performed in a manner equivalent to using - * asio::io_service::post(). - * - * @note The async_receive operation can only be used with a connected socket. - * Use the async_receive_from function to receive data on an unconnected - * raw socket. - */ - template - void async_receive(const MutableBufferSequence& buffers, - socket_base::message_flags flags, ReadHandler handler) - { - this->service.async_receive(this->implementation, buffers, flags, handler); - } - - /// Receive raw data with the endpoint of the sender. - /** - * This function is used to receive raw data. The function call will block - * until data has been received successfully or an error occurs. - * - * @param buffers One or more buffers into which the data will be received. - * - * @param sender_endpoint An endpoint object that receives the endpoint of - * the remote sender of the data. - * - * @returns The number of bytes received. - * - * @throws asio::system_error Thrown on failure. - * - * @par Example - * To receive into a single data buffer use the @ref buffer function as - * follows: - * @code - * asio::ip::udp::endpoint sender_endpoint; - * socket.receive_from( - * asio::buffer(data, size), sender_endpoint); - * @endcode - * See the @ref buffer documentation for information on receiving into - * multiple buffers in one go, and how to use it with arrays, boost::array or - * std::vector. - */ - template - std::size_t receive_from(const MutableBufferSequence& buffers, - endpoint_type& sender_endpoint) - { - asio::error_code ec; - std::size_t s = this->service.receive_from( - this->implementation, buffers, sender_endpoint, 0, ec); - asio::detail::throw_error(ec); - return s; - } - - /// Receive raw data with the endpoint of the sender. - /** - * This function is used to receive raw data. The function call will block - * until data has been received successfully or an error occurs. - * - * @param buffers One or more buffers into which the data will be received. - * - * @param sender_endpoint An endpoint object that receives the endpoint of - * the remote sender of the data. - * - * @param flags Flags specifying how the receive call is to be made. - * - * @returns The number of bytes received. - * - * @throws asio::system_error Thrown on failure. - */ - template - std::size_t receive_from(const MutableBufferSequence& buffers, - endpoint_type& sender_endpoint, socket_base::message_flags flags) - { - asio::error_code ec; - std::size_t s = this->service.receive_from( - this->implementation, buffers, sender_endpoint, flags, ec); - asio::detail::throw_error(ec); - return s; - } - - /// Receive raw data with the endpoint of the sender. - /** - * This function is used to receive raw data. The function call will block - * until data has been received successfully or an error occurs. - * - * @param buffers One or more buffers into which the data will be received. - * - * @param sender_endpoint An endpoint object that receives the endpoint of - * the remote sender of the data. - * - * @param flags Flags specifying how the receive call is to be made. - * - * @param ec Set to indicate what error occurred, if any. - * - * @returns The number of bytes received. - */ - template - std::size_t receive_from(const MutableBufferSequence& buffers, - endpoint_type& sender_endpoint, socket_base::message_flags flags, - asio::error_code& ec) - { - return this->service.receive_from(this->implementation, buffers, - sender_endpoint, flags, ec); - } - - /// Start an asynchronous receive. - /** - * This function is used to asynchronously receive raw data. The function - * call always returns immediately. - * - * @param buffers One or more buffers into which the data will be received. - * Although the buffers object may be copied as necessary, ownership of the - * underlying memory blocks is retained by the caller, which must guarantee - * that they remain valid until the handler is called. - * - * @param sender_endpoint An endpoint object that receives the endpoint of - * the remote sender of the data. Ownership of the sender_endpoint object - * is retained by the caller, which must guarantee that it is valid until the - * handler is called. - * - * @param handler The handler to be called when the receive operation - * completes. Copies will be made of the handler as required. The function - * signature of the handler must be: - * @code void handler( - * const asio::error_code& error, // Result of operation. - * std::size_t bytes_transferred // Number of bytes received. - * ); @endcode - * Regardless of whether the asynchronous operation completes immediately or - * not, the handler will not be invoked from within this function. Invocation - * of the handler will be performed in a manner equivalent to using - * asio::io_service::post(). - * - * @par Example - * To receive into a single data buffer use the @ref buffer function as - * follows: - * @code socket.async_receive_from( - * asio::buffer(data, size), 0, sender_endpoint, handler); @endcode - * See the @ref buffer documentation for information on receiving into - * multiple buffers in one go, and how to use it with arrays, boost::array or - * std::vector. - */ - template - void async_receive_from(const MutableBufferSequence& buffers, - endpoint_type& sender_endpoint, ReadHandler handler) - { - this->service.async_receive_from(this->implementation, buffers, - sender_endpoint, 0, handler); - } - - /// Start an asynchronous receive. - /** - * This function is used to asynchronously receive raw data. The function - * call always returns immediately. - * - * @param buffers One or more buffers into which the data will be received. - * Although the buffers object may be copied as necessary, ownership of the - * underlying memory blocks is retained by the caller, which must guarantee - * that they remain valid until the handler is called. - * - * @param sender_endpoint An endpoint object that receives the endpoint of - * the remote sender of the data. Ownership of the sender_endpoint object - * is retained by the caller, which must guarantee that it is valid until the - * handler is called. - * - * @param flags Flags specifying how the receive call is to be made. - * - * @param handler The handler to be called when the receive operation - * completes. Copies will be made of the handler as required. The function - * signature of the handler must be: - * @code void handler( - * const asio::error_code& error, // Result of operation. - * std::size_t bytes_transferred // Number of bytes received. - * ); @endcode - * Regardless of whether the asynchronous operation completes immediately or - * not, the handler will not be invoked from within this function. Invocation - * of the handler will be performed in a manner equivalent to using - * asio::io_service::post(). - */ - template - void async_receive_from(const MutableBufferSequence& buffers, - endpoint_type& sender_endpoint, socket_base::message_flags flags, - ReadHandler handler) - { - this->service.async_receive_from(this->implementation, buffers, - sender_endpoint, flags, handler); - } -}; - -} // namespace asio - -#include "asio/detail/pop_options.hpp" - -#endif // ASIO_BASIC_RAW_SOCKET_HPP diff --git a/libtorrent/include/asio/basic_serial_port.hpp b/libtorrent/include/asio/basic_serial_port.hpp deleted file mode 100644 index ffe2b0213..000000000 --- a/libtorrent/include/asio/basic_serial_port.hpp +++ /dev/null @@ -1,608 +0,0 @@ -// -// basic_serial_port.hpp -// ~~~~~~~~~~~~~~~~~~~~~ -// -// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// Copyright (c) 2008 Rep Invariant Systems, Inc. (info@repinvariant.com) -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -#ifndef ASIO_BASIC_SERIAL_PORT_HPP -#define ASIO_BASIC_SERIAL_PORT_HPP - -#if defined(_MSC_VER) && (_MSC_VER >= 1200) -# pragma once -#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) - -#include "asio/detail/push_options.hpp" - -#include "asio/detail/push_options.hpp" -#include -#include -#include "asio/detail/pop_options.hpp" - -#include "asio/basic_io_object.hpp" -#include "asio/error.hpp" -#include "asio/serial_port_base.hpp" -#include "asio/serial_port_service.hpp" -#include "asio/detail/throw_error.hpp" - -#if defined(ASIO_HAS_SERIAL_PORT) \ - || defined(GENERATING_DOCUMENTATION) - -namespace asio { - -/// Provides serial port functionality. -/** - * The basic_serial_port class template provides functionality that is common - * to all serial ports. - * - * @par Thread Safety - * @e Distinct @e objects: Safe.@n - * @e Shared @e objects: Unsafe. - */ -template -class basic_serial_port - : public basic_io_object, - public serial_port_base -{ -public: - /// The native representation of a serial port. - typedef typename SerialPortService::native_type native_type; - - /// A basic_serial_port is always the lowest layer. - typedef basic_serial_port lowest_layer_type; - - /// Construct a basic_serial_port without opening it. - /** - * This constructor creates a serial port without opening it. - * - * @param io_service The io_service object that the serial port will use to - * dispatch handlers for any asynchronous operations performed on the port. - */ - explicit basic_serial_port(asio::io_service& io_service) - : basic_io_object(io_service) - { - } - - /// Construct and open a basic_serial_port. - /** - * This constructor creates and opens a serial port for the specified device - * name. - * - * @param io_service The io_service object that the serial port will use to - * dispatch handlers for any asynchronous operations performed on the port. - * - * @param device The platform-specific device name for this serial - * port. - */ - explicit basic_serial_port(asio::io_service& io_service, - const char* device) - : basic_io_object(io_service) - { - asio::error_code ec; - this->service.open(this->implementation, device, ec); - asio::detail::throw_error(ec); - } - - /// Construct and open a basic_serial_port. - /** - * This constructor creates and opens a serial port for the specified device - * name. - * - * @param io_service The io_service object that the serial port will use to - * dispatch handlers for any asynchronous operations performed on the port. - * - * @param device The platform-specific device name for this serial - * port. - */ - explicit basic_serial_port(asio::io_service& io_service, - const std::string& device) - : basic_io_object(io_service) - { - asio::error_code ec; - this->service.open(this->implementation, device, ec); - asio::detail::throw_error(ec); - } - - /// Construct a basic_serial_port on an existing native serial port. - /** - * This constructor creates a serial port object to hold an existing native - * serial port. - * - * @param io_service The io_service object that the serial port will use to - * dispatch handlers for any asynchronous operations performed on the port. - * - * @param native_serial_port A native serial port. - * - * @throws asio::system_error Thrown on failure. - */ - basic_serial_port(asio::io_service& io_service, - const native_type& native_serial_port) - : basic_io_object(io_service) - { - asio::error_code ec; - this->service.assign(this->implementation, native_serial_port, ec); - asio::detail::throw_error(ec); - } - - /// Get a reference to the lowest layer. - /** - * This function returns a reference to the lowest layer in a stack of - * layers. Since a basic_serial_port cannot contain any further layers, it - * simply returns a reference to itself. - * - * @return A reference to the lowest layer in the stack of layers. Ownership - * is not transferred to the caller. - */ - lowest_layer_type& lowest_layer() - { - return *this; - } - - /// Open the serial port using the specified device name. - /** - * This function opens the serial port for the specified device name. - * - * @param device The platform-specific device name. - * - * @throws asio::system_error Thrown on failure. - */ - void open(const std::string& device) - { - asio::error_code ec; - this->service.open(this->implementation, device, ec); - asio::detail::throw_error(ec); - } - - /// Open the serial port using the specified device name. - /** - * This function opens the serial port using the given platform-specific - * device name. - * - * @param device The platform-specific device name. - * - * @param ec Set the indicate what error occurred, if any. - */ - asio::error_code open(const std::string& device, - asio::error_code& ec) - { - return this->service.open(this->implementation, device, ec); - } - - /// Assign an existing native serial port to the serial port. - /* - * This function opens the serial port to hold an existing native serial port. - * - * @param native_serial_port A native serial port. - * - * @throws asio::system_error Thrown on failure. - */ - void assign(const native_type& native_serial_port) - { - asio::error_code ec; - this->service.assign(this->implementation, native_serial_port, ec); - asio::detail::throw_error(ec); - } - - /// Assign an existing native serial port to the serial port. - /* - * This function opens the serial port to hold an existing native serial port. - * - * @param native_serial_port A native serial port. - * - * @param ec Set to indicate what error occurred, if any. - */ - asio::error_code assign(const native_type& native_serial_port, - asio::error_code& ec) - { - return this->service.assign(this->implementation, native_serial_port, ec); - } - - /// Determine whether the serial port is open. - bool is_open() const - { - return this->service.is_open(this->implementation); - } - - /// Close the serial port. - /** - * This function is used to close the serial port. Any asynchronous read or - * write operations will be cancelled immediately, and will complete with the - * asio::error::operation_aborted error. - * - * @throws asio::system_error Thrown on failure. - */ - void close() - { - asio::error_code ec; - this->service.close(this->implementation, ec); - asio::detail::throw_error(ec); - } - - /// Close the serial port. - /** - * This function is used to close the serial port. Any asynchronous read or - * write operations will be cancelled immediately, and will complete with the - * asio::error::operation_aborted error. - * - * @param ec Set to indicate what error occurred, if any. - */ - asio::error_code close(asio::error_code& ec) - { - return this->service.close(this->implementation, ec); - } - - /// Get the native serial port representation. - /** - * This function may be used to obtain the underlying representation of the - * serial port. This is intended to allow access to native serial port - * functionality that is not otherwise provided. - */ - native_type native() - { - return this->service.native(this->implementation); - } - - /// Cancel all asynchronous operations associated with the serial port. - /** - * This function causes all outstanding asynchronous read or write operations - * to finish immediately, and the handlers for cancelled operations will be - * passed the asio::error::operation_aborted error. - * - * @throws asio::system_error Thrown on failure. - */ - void cancel() - { - asio::error_code ec; - this->service.cancel(this->implementation, ec); - asio::detail::throw_error(ec); - } - - /// Cancel all asynchronous operations associated with the serial port. - /** - * This function causes all outstanding asynchronous read or write operations - * to finish immediately, and the handlers for cancelled operations will be - * passed the asio::error::operation_aborted error. - * - * @param ec Set to indicate what error occurred, if any. - */ - asio::error_code cancel(asio::error_code& ec) - { - return this->service.cancel(this->implementation, ec); - } - - /// Send a break sequence to the serial port. - /** - * This function causes a break sequence of platform-specific duration to be - * sent out the serial port. - * - * @throws asio::system_error Thrown on failure. - */ - void send_break() - { - asio::error_code ec; - this->service.send_break(this->implementation, ec); - asio::detail::throw_error(ec); - } - - /// Send a break sequence to the serial port. - /** - * This function causes a break sequence of platform-specific duration to be - * sent out the serial port. - * - * @param ec Set to indicate what error occurred, if any. - */ - asio::error_code send_break(asio::error_code& ec) - { - return this->service.send_break(this->implementation, ec); - } - - /// Set an option on the serial port. - /** - * This function is used to set an option on the serial port. - * - * @param option The option value to be set on the serial port. - * - * @throws asio::system_error Thrown on failure. - * - * @sa SettableSerialPortOption @n - * asio::serial_port_base::baud_rate @n - * asio::serial_port_base::flow_control @n - * asio::serial_port_base::parity @n - * asio::serial_port_base::stop_bits @n - * asio::serial_port_base::character_size - */ - template - void set_option(const SettableSerialPortOption& option) - { - asio::error_code ec; - this->service.set_option(this->implementation, option, ec); - asio::detail::throw_error(ec); - } - - /// Set an option on the serial port. - /** - * This function is used to set an option on the serial port. - * - * @param option The option value to be set on the serial port. - * - * @param ec Set to indicate what error occurred, if any. - * - * @sa SettableSerialPortOption @n - * asio::serial_port_base::baud_rate @n - * asio::serial_port_base::flow_control @n - * asio::serial_port_base::parity @n - * asio::serial_port_base::stop_bits @n - * asio::serial_port_base::character_size - */ - template - asio::error_code set_option(const SettableSerialPortOption& option, - asio::error_code& ec) - { - return this->service.set_option(this->implementation, option, ec); - } - - /// Get an option from the serial port. - /** - * This function is used to get the current value of an option on the serial - * port. - * - * @param option The option value to be obtained from the serial port. - * - * @throws asio::system_error Thrown on failure. - * - * @sa GettableSerialPortOption @n - * asio::serial_port_base::baud_rate @n - * asio::serial_port_base::flow_control @n - * asio::serial_port_base::parity @n - * asio::serial_port_base::stop_bits @n - * asio::serial_port_base::character_size - */ - template - void get_option(GettableSerialPortOption& option) - { - asio::error_code ec; - this->service.get_option(this->implementation, option, ec); - asio::detail::throw_error(ec); - } - - /// Get an option from the serial port. - /** - * This function is used to get the current value of an option on the serial - * port. - * - * @param option The option value to be obtained from the serial port. - * - * @param ec Set to indicate what error occured, if any. - * - * @sa GettableSerialPortOption @n - * asio::serial_port_base::baud_rate @n - * asio::serial_port_base::flow_control @n - * asio::serial_port_base::parity @n - * asio::serial_port_base::stop_bits @n - * asio::serial_port_base::character_size - */ - template - asio::error_code get_option(GettableSerialPortOption& option, - asio::error_code& ec) - { - return this->service.get_option(this->implementation, option, ec); - } - - /// Write some data to the serial port. - /** - * This function is used to write data to the serial port. The function call - * will block until one or more bytes of the data has been written - * successfully, or until an error occurs. - * - * @param buffers One or more data buffers to be written to the serial port. - * - * @returns The number of bytes written. - * - * @throws asio::system_error Thrown on failure. An error code of - * asio::error::eof indicates that the connection was closed by the - * peer. - * - * @note The write_some operation may not transmit all of the data to the - * peer. Consider using the @ref write function if you need to ensure that - * all data is written before the blocking operation completes. - * - * @par Example - * To write a single data buffer use the @ref buffer function as follows: - * @code - * serial_port.write_some(asio::buffer(data, size)); - * @endcode - * See the @ref buffer documentation for information on writing multiple - * buffers in one go, and how to use it with arrays, boost::array or - * std::vector. - */ - template - std::size_t write_some(const ConstBufferSequence& buffers) - { - asio::error_code ec; - std::size_t s = this->service.write_some(this->implementation, buffers, ec); - asio::detail::throw_error(ec); - return s; - } - - /// Write some data to the serial port. - /** - * This function is used to write data to the serial port. The function call - * will block until one or more bytes of the data has been written - * successfully, or until an error occurs. - * - * @param buffers One or more data buffers to be written to the serial port. - * - * @param ec Set to indicate what error occurred, if any. - * - * @returns The number of bytes written. Returns 0 if an error occurred. - * - * @note The write_some operation may not transmit all of the data to the - * peer. Consider using the @ref write function if you need to ensure that - * all data is written before the blocking operation completes. - */ - template - std::size_t write_some(const ConstBufferSequence& buffers, - asio::error_code& ec) - { - return this->service.write_some(this->implementation, buffers, ec); - } - - /// Start an asynchronous write. - /** - * This function is used to asynchronously write data to the serial port. - * The function call always returns immediately. - * - * @param buffers One or more data buffers to be written to the serial port. - * Although the buffers object may be copied as necessary, ownership of the - * underlying memory blocks is retained by the caller, which must guarantee - * that they remain valid until the handler is called. - * - * @param handler The handler to be called when the write operation completes. - * Copies will be made of the handler as required. The function signature of - * the handler must be: - * @code void handler( - * const asio::error_code& error, // Result of operation. - * std::size_t bytes_transferred // Number of bytes written. - * ); @endcode - * Regardless of whether the asynchronous operation completes immediately or - * not, the handler will not be invoked from within this function. Invocation - * of the handler will be performed in a manner equivalent to using - * asio::io_service::post(). - * - * @note The write operation may not transmit all of the data to the peer. - * Consider using the @ref async_write function if you need to ensure that all - * data is written before the asynchronous operation completes. - * - * @par Example - * To write a single data buffer use the @ref buffer function as follows: - * @code - * serial_port.async_write_some(asio::buffer(data, size), handler); - * @endcode - * See the @ref buffer documentation for information on writing multiple - * buffers in one go, and how to use it with arrays, boost::array or - * std::vector. - */ - template - void async_write_some(const ConstBufferSequence& buffers, - WriteHandler handler) - { - this->service.async_write_some(this->implementation, buffers, handler); - } - - /// Read some data from the serial port. - /** - * This function is used to read data from the serial port. The function - * call will block until one or more bytes of data has been read successfully, - * or until an error occurs. - * - * @param buffers One or more buffers into which the data will be read. - * - * @returns The number of bytes read. - * - * @throws asio::system_error Thrown on failure. An error code of - * asio::error::eof indicates that the connection was closed by the - * peer. - * - * @note The read_some operation may not read all of the requested number of - * bytes. Consider using the @ref read function if you need to ensure that - * the requested amount of data is read before the blocking operation - * completes. - * - * @par Example - * To read into a single data buffer use the @ref buffer function as follows: - * @code - * serial_port.read_some(asio::buffer(data, size)); - * @endcode - * See the @ref buffer documentation for information on reading into multiple - * buffers in one go, and how to use it with arrays, boost::array or - * std::vector. - */ - template - std::size_t read_some(const MutableBufferSequence& buffers) - { - asio::error_code ec; - std::size_t s = this->service.read_some(this->implementation, buffers, ec); - asio::detail::throw_error(ec); - return s; - } - - /// Read some data from the serial port. - /** - * This function is used to read data from the serial port. The function - * call will block until one or more bytes of data has been read successfully, - * or until an error occurs. - * - * @param buffers One or more buffers into which the data will be read. - * - * @param ec Set to indicate what error occurred, if any. - * - * @returns The number of bytes read. Returns 0 if an error occurred. - * - * @note The read_some operation may not read all of the requested number of - * bytes. Consider using the @ref read function if you need to ensure that - * the requested amount of data is read before the blocking operation - * completes. - */ - template - std::size_t read_some(const MutableBufferSequence& buffers, - asio::error_code& ec) - { - return this->service.read_some(this->implementation, buffers, ec); - } - - /// Start an asynchronous read. - /** - * This function is used to asynchronously read data from the serial port. - * The function call always returns immediately. - * - * @param buffers One or more buffers into which the data will be read. - * Although the buffers object may be copied as necessary, ownership of the - * underlying memory blocks is retained by the caller, which must guarantee - * that they remain valid until the handler is called. - * - * @param handler The handler to be called when the read operation completes. - * Copies will be made of the handler as required. The function signature of - * the handler must be: - * @code void handler( - * const asio::error_code& error, // Result of operation. - * std::size_t bytes_transferred // Number of bytes read. - * ); @endcode - * Regardless of whether the asynchronous operation completes immediately or - * not, the handler will not be invoked from within this function. Invocation - * of the handler will be performed in a manner equivalent to using - * asio::io_service::post(). - * - * @note The read operation may not read all of the requested number of bytes. - * Consider using the @ref async_read function if you need to ensure that the - * requested amount of data is read before the asynchronous operation - * completes. - * - * @par Example - * To read into a single data buffer use the @ref buffer function as follows: - * @code - * serial_port.async_read_some(asio::buffer(data, size), handler); - * @endcode - * See the @ref buffer documentation for information on reading into multiple - * buffers in one go, and how to use it with arrays, boost::array or - * std::vector. - */ - template - void async_read_some(const MutableBufferSequence& buffers, - ReadHandler handler) - { - this->service.async_read_some(this->implementation, buffers, handler); - } -}; - -} // namespace asio - -#endif // defined(ASIO_HAS_SERIAL_PORT) - // || defined(GENERATING_DOCUMENTATION) - -#include "asio/detail/pop_options.hpp" - -#endif // ASIO_BASIC_SERIAL_PORT_HPP diff --git a/libtorrent/include/asio/basic_socket.hpp b/libtorrent/include/asio/basic_socket.hpp deleted file mode 100644 index f494c1725..000000000 --- a/libtorrent/include/asio/basic_socket.hpp +++ /dev/null @@ -1,1049 +0,0 @@ -// -// basic_socket.hpp -// ~~~~~~~~~~~~~~~~ -// -// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -#ifndef ASIO_BASIC_SOCKET_HPP -#define ASIO_BASIC_SOCKET_HPP - -#if defined(_MSC_VER) && (_MSC_VER >= 1200) -# pragma once -#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) - -#include "asio/detail/push_options.hpp" - -#include "asio/detail/push_options.hpp" -#include -#include "asio/detail/pop_options.hpp" - -#include "asio/basic_io_object.hpp" -#include "asio/error.hpp" -#include "asio/socket_base.hpp" -#include "asio/detail/throw_error.hpp" - -namespace asio { - -/// Provides socket functionality. -/** - * The basic_socket class template provides functionality that is common to both - * stream-oriented and datagram-oriented sockets. - * - * @par Thread Safety - * @e Distinct @e objects: Safe.@n - * @e Shared @e objects: Unsafe. - */ -template -class basic_socket - : public basic_io_object, - public socket_base -{ -public: - /// The native representation of a socket. - typedef typename SocketService::native_type native_type; - - /// The protocol type. - typedef Protocol protocol_type; - - /// The endpoint type. - typedef typename Protocol::endpoint endpoint_type; - - /// A basic_socket is always the lowest layer. - typedef basic_socket lowest_layer_type; - - /// Construct a basic_socket without opening it. - /** - * This constructor creates a socket without opening it. - * - * @param io_service The io_service object that the socket will use to - * dispatch handlers for any asynchronous operations performed on the socket. - */ - explicit basic_socket(asio::io_service& io_service) - : basic_io_object(io_service) - { - } - - /// Construct and open a basic_socket. - /** - * This constructor creates and opens a socket. - * - * @param io_service The io_service object that the socket will use to - * dispatch handlers for any asynchronous operations performed on the socket. - * - * @param protocol An object specifying protocol parameters to be used. - * - * @throws asio::system_error Thrown on failure. - */ - basic_socket(asio::io_service& io_service, - const protocol_type& protocol) - : basic_io_object(io_service) - { - asio::error_code ec; - this->service.open(this->implementation, protocol, ec); - asio::detail::throw_error(ec); - } - - /// Construct a basic_socket, opening it and binding it to the given local - /// endpoint. - /** - * This constructor creates a socket and automatically opens it bound to the - * specified endpoint on the local machine. The protocol used is the protocol - * associated with the given endpoint. - * - * @param io_service The io_service object that the socket will use to - * dispatch handlers for any asynchronous operations performed on the socket. - * - * @param endpoint An endpoint on the local machine to which the socket will - * be bound. - * - * @throws asio::system_error Thrown on failure. - */ - basic_socket(asio::io_service& io_service, - const endpoint_type& endpoint) - : basic_io_object(io_service) - { - asio::error_code ec; - this->service.open(this->implementation, endpoint.protocol(), ec); - asio::detail::throw_error(ec); - this->service.bind(this->implementation, endpoint, ec); - asio::detail::throw_error(ec); - } - - /// Construct a basic_socket on an existing native socket. - /** - * This constructor creates a socket object to hold an existing native socket. - * - * @param io_service The io_service object that the socket will use to - * dispatch handlers for any asynchronous operations performed on the socket. - * - * @param protocol An object specifying protocol parameters to be used. - * - * @param native_socket A native socket. - * - * @throws asio::system_error Thrown on failure. - */ - basic_socket(asio::io_service& io_service, - const protocol_type& protocol, const native_type& native_socket) - : basic_io_object(io_service) - { - asio::error_code ec; - this->service.assign(this->implementation, protocol, native_socket, ec); - asio::detail::throw_error(ec); - } - - /// Get a reference to the lowest layer. - /** - * This function returns a reference to the lowest layer in a stack of - * layers. Since a basic_socket cannot contain any further layers, it simply - * returns a reference to itself. - * - * @return A reference to the lowest layer in the stack of layers. Ownership - * is not transferred to the caller. - */ - lowest_layer_type& lowest_layer() - { - return *this; - } - - /// Open the socket using the specified protocol. - /** - * This function opens the socket so that it will use the specified protocol. - * - * @param protocol An object specifying protocol parameters to be used. - * - * @throws asio::system_error Thrown on failure. - * - * @par Example - * @code - * asio::ip::tcp::socket socket(io_service); - * socket.open(asio::ip::tcp::v4()); - * @endcode - */ - void open(const protocol_type& protocol = protocol_type()) - { - asio::error_code ec; - this->service.open(this->implementation, protocol, ec); - asio::detail::throw_error(ec); - } - - /// Open the socket using the specified protocol. - /** - * This function opens the socket so that it will use the specified protocol. - * - * @param protocol An object specifying which protocol is to be used. - * - * @param ec Set to indicate what error occurred, if any. - * - * @par Example - * @code - * asio::ip::tcp::socket socket(io_service); - * asio::error_code ec; - * socket.open(asio::ip::tcp::v4(), ec); - * if (ec) - * { - * // An error occurred. - * } - * @endcode - */ - asio::error_code open(const protocol_type& protocol, - asio::error_code& ec) - { - return this->service.open(this->implementation, protocol, ec); - } - - /// Assign an existing native socket to the socket. - /* - * This function opens the socket to hold an existing native socket. - * - * @param protocol An object specifying which protocol is to be used. - * - * @param native_socket A native socket. - * - * @throws asio::system_error Thrown on failure. - */ - void assign(const protocol_type& protocol, const native_type& native_socket) - { - asio::error_code ec; - this->service.assign(this->implementation, protocol, native_socket, ec); - asio::detail::throw_error(ec); - } - - /// Assign an existing native socket to the socket. - /* - * This function opens the socket to hold an existing native socket. - * - * @param protocol An object specifying which protocol is to be used. - * - * @param native_socket A native socket. - * - * @param ec Set to indicate what error occurred, if any. - */ - asio::error_code assign(const protocol_type& protocol, - const native_type& native_socket, asio::error_code& ec) - { - return this->service.assign(this->implementation, - protocol, native_socket, ec); - } - - /// Determine whether the socket is open. - bool is_open() const - { - return this->service.is_open(this->implementation); - } - - /// Close the socket. - /** - * This function is used to close the socket. Any asynchronous send, receive - * or connect operations will be cancelled immediately, and will complete - * with the asio::error::operation_aborted error. - * - * @throws asio::system_error Thrown on failure. - * - * @note For portable behaviour with respect to graceful closure of a - * connected socket, call shutdown() before closing the socket. - */ - void close() - { - asio::error_code ec; - this->service.close(this->implementation, ec); - asio::detail::throw_error(ec); - } - - /// Close the socket. - /** - * This function is used to close the socket. Any asynchronous send, receive - * or connect operations will be cancelled immediately, and will complete - * with the asio::error::operation_aborted error. - * - * @param ec Set to indicate what error occurred, if any. - * - * @par Example - * @code - * asio::ip::tcp::socket socket(io_service); - * ... - * asio::error_code ec; - * socket.close(ec); - * if (ec) - * { - * // An error occurred. - * } - * @endcode - * - * @note For portable behaviour with respect to graceful closure of a - * connected socket, call shutdown() before closing the socket. - */ - asio::error_code close(asio::error_code& ec) - { - return this->service.close(this->implementation, ec); - } - - /// Get the native socket representation. - /** - * This function may be used to obtain the underlying representation of the - * socket. This is intended to allow access to native socket functionality - * that is not otherwise provided. - */ - native_type native() - { - return this->service.native(this->implementation); - } - - /// Cancel all asynchronous operations associated with the socket. - /** - * This function causes all outstanding asynchronous connect, send and receive - * operations to finish immediately, and the handlers for cancelled operations - * will be passed the asio::error::operation_aborted error. - * - * @throws asio::system_error Thrown on failure. - * - * @note Calls to cancel() will always fail with - * asio::error::operation_not_supported when run on Windows XP, Windows - * Server 2003, and earlier versions of Windows, unless - * ASIO_ENABLE_CANCELIO is defined. However, the CancelIo function has - * two issues that should be considered before enabling its use: - * - * @li It will only cancel asynchronous operations that were initiated in the - * current thread. - * - * @li It can appear to complete without error, but the request to cancel the - * unfinished operations may be silently ignored by the operating system. - * Whether it works or not seems to depend on the drivers that are installed. - * - * For portable cancellation, consider using one of the following - * alternatives: - * - * @li Disable asio's I/O completion port backend by defining - * ASIO_DISABLE_IOCP. - * - * @li Use the close() function to simultaneously cancel the outstanding - * operations and close the socket. - * - * When running on Windows Vista, Windows Server 2008, and later, the - * CancelIoEx function is always used. This function does not have the - * problems described above. - */ -#if defined(BOOST_MSVC) && (BOOST_MSVC >= 1400) \ - && (!defined(_WIN32_WINNT) || _WIN32_WINNT < 0x0600) \ - && !defined(ASIO_ENABLE_CANCELIO) - __declspec(deprecated("By default, this function always fails with " - "operation_not_supported when used on Windows XP, Windows Server 2003, " - "or earlier. Consult documentation for details.")) -#endif - void cancel() - { - asio::error_code ec; - this->service.cancel(this->implementation, ec); - asio::detail::throw_error(ec); - } - - /// Cancel all asynchronous operations associated with the socket. - /** - * This function causes all outstanding asynchronous connect, send and receive - * operations to finish immediately, and the handlers for cancelled operations - * will be passed the asio::error::operation_aborted error. - * - * @param ec Set to indicate what error occurred, if any. - * - * @note Calls to cancel() will always fail with - * asio::error::operation_not_supported when run on Windows XP, Windows - * Server 2003, and earlier versions of Windows, unless - * ASIO_ENABLE_CANCELIO is defined. However, the CancelIo function has - * two issues that should be considered before enabling its use: - * - * @li It will only cancel asynchronous operations that were initiated in the - * current thread. - * - * @li It can appear to complete without error, but the request to cancel the - * unfinished operations may be silently ignored by the operating system. - * Whether it works or not seems to depend on the drivers that are installed. - * - * For portable cancellation, consider using one of the following - * alternatives: - * - * @li Disable asio's I/O completion port backend by defining - * ASIO_DISABLE_IOCP. - * - * @li Use the close() function to simultaneously cancel the outstanding - * operations and close the socket. - * - * When running on Windows Vista, Windows Server 2008, and later, the - * CancelIoEx function is always used. This function does not have the - * problems described above. - */ -#if defined(BOOST_MSVC) && (BOOST_MSVC >= 1400) \ - && (!defined(_WIN32_WINNT) || _WIN32_WINNT < 0x0600) \ - && !defined(ASIO_ENABLE_CANCELIO) - __declspec(deprecated("By default, this function always fails with " - "operation_not_supported when used on Windows XP, Windows Server 2003, " - "or earlier. Consult documentation for details.")) -#endif - asio::error_code cancel(asio::error_code& ec) - { - return this->service.cancel(this->implementation, ec); - } - - /// Determine whether the socket is at the out-of-band data mark. - /** - * This function is used to check whether the socket input is currently - * positioned at the out-of-band data mark. - * - * @return A bool indicating whether the socket is at the out-of-band data - * mark. - * - * @throws asio::system_error Thrown on failure. - */ - bool at_mark() const - { - asio::error_code ec; - bool b = this->service.at_mark(this->implementation, ec); - asio::detail::throw_error(ec); - return b; - } - - /// Determine whether the socket is at the out-of-band data mark. - /** - * This function is used to check whether the socket input is currently - * positioned at the out-of-band data mark. - * - * @param ec Set to indicate what error occurred, if any. - * - * @return A bool indicating whether the socket is at the out-of-band data - * mark. - */ - bool at_mark(asio::error_code& ec) const - { - return this->service.at_mark(this->implementation, ec); - } - - /// Determine the number of bytes available for reading. - /** - * This function is used to determine the number of bytes that may be read - * without blocking. - * - * @return The number of bytes that may be read without blocking, or 0 if an - * error occurs. - * - * @throws asio::system_error Thrown on failure. - */ - std::size_t available() const - { - asio::error_code ec; - std::size_t s = this->service.available(this->implementation, ec); - asio::detail::throw_error(ec); - return s; - } - - /// Determine the number of bytes available for reading. - /** - * This function is used to determine the number of bytes that may be read - * without blocking. - * - * @param ec Set to indicate what error occurred, if any. - * - * @return The number of bytes that may be read without blocking, or 0 if an - * error occurs. - */ - std::size_t available(asio::error_code& ec) const - { - return this->service.available(this->implementation, ec); - } - - /// Bind the socket to the given local endpoint. - /** - * This function binds the socket to the specified endpoint on the local - * machine. - * - * @param endpoint An endpoint on the local machine to which the socket will - * be bound. - * - * @throws asio::system_error Thrown on failure. - * - * @par Example - * @code - * asio::ip::tcp::socket socket(io_service); - * socket.open(asio::ip::tcp::v4()); - * socket.bind(asio::ip::tcp::endpoint( - * asio::ip::tcp::v4(), 12345)); - * @endcode - */ - void bind(const endpoint_type& endpoint) - { - asio::error_code ec; - this->service.bind(this->implementation, endpoint, ec); - asio::detail::throw_error(ec); - } - - /// Bind the socket to the given local endpoint. - /** - * This function binds the socket to the specified endpoint on the local - * machine. - * - * @param endpoint An endpoint on the local machine to which the socket will - * be bound. - * - * @param ec Set to indicate what error occurred, if any. - * - * @par Example - * @code - * asio::ip::tcp::socket socket(io_service); - * socket.open(asio::ip::tcp::v4()); - * asio::error_code ec; - * socket.bind(asio::ip::tcp::endpoint( - * asio::ip::tcp::v4(), 12345), ec); - * if (ec) - * { - * // An error occurred. - * } - * @endcode - */ - asio::error_code bind(const endpoint_type& endpoint, - asio::error_code& ec) - { - return this->service.bind(this->implementation, endpoint, ec); - } - - /// Connect the socket to the specified endpoint. - /** - * This function is used to connect a socket to the specified remote endpoint. - * The function call will block until the connection is successfully made or - * an error occurs. - * - * The socket is automatically opened if it is not already open. If the - * connect fails, and the socket was automatically opened, the socket is - * not returned to the closed state. - * - * @param peer_endpoint The remote endpoint to which the socket will be - * connected. - * - * @throws asio::system_error Thrown on failure. - * - * @par Example - * @code - * asio::ip::tcp::socket socket(io_service); - * asio::ip::tcp::endpoint endpoint( - * asio::ip::address::from_string("1.2.3.4"), 12345); - * socket.connect(endpoint); - * @endcode - */ - void connect(const endpoint_type& peer_endpoint) - { - asio::error_code ec; - if (!is_open()) - { - this->service.open(this->implementation, peer_endpoint.protocol(), ec); - asio::detail::throw_error(ec); - } - this->service.connect(this->implementation, peer_endpoint, ec); - asio::detail::throw_error(ec); - } - - /// Connect the socket to the specified endpoint. - /** - * This function is used to connect a socket to the specified remote endpoint. - * The function call will block until the connection is successfully made or - * an error occurs. - * - * The socket is automatically opened if it is not already open. If the - * connect fails, and the socket was automatically opened, the socket is - * not returned to the closed state. - * - * @param peer_endpoint The remote endpoint to which the socket will be - * connected. - * - * @param ec Set to indicate what error occurred, if any. - * - * @par Example - * @code - * asio::ip::tcp::socket socket(io_service); - * asio::ip::tcp::endpoint endpoint( - * asio::ip::address::from_string("1.2.3.4"), 12345); - * asio::error_code ec; - * socket.connect(endpoint, ec); - * if (ec) - * { - * // An error occurred. - * } - * @endcode - */ - asio::error_code connect(const endpoint_type& peer_endpoint, - asio::error_code& ec) - { - if (!is_open()) - { - if (this->service.open(this->implementation, - peer_endpoint.protocol(), ec)) - { - return ec; - } - } - - return this->service.connect(this->implementation, peer_endpoint, ec); - } - - /// Start an asynchronous connect. - /** - * This function is used to asynchronously connect a socket to the specified - * remote endpoint. The function call always returns immediately. - * - * The socket is automatically opened if it is not already open. If the - * connect fails, and the socket was automatically opened, the socket is - * not returned to the closed state. - * - * @param peer_endpoint The remote endpoint to which the socket will be - * connected. Copies will be made of the endpoint object as required. - * - * @param handler The handler to be called when the connection operation - * completes. Copies will be made of the handler as required. The function - * signature of the handler must be: - * @code void handler( - * const asio::error_code& error // Result of operation - * ); @endcode - * Regardless of whether the asynchronous operation completes immediately or - * not, the handler will not be invoked from within this function. Invocation - * of the handler will be performed in a manner equivalent to using - * asio::io_service::post(). - * - * @par Example - * @code - * void connect_handler(const asio::error_code& error) - * { - * if (!error) - * { - * // Connect succeeded. - * } - * } - * - * ... - * - * asio::ip::tcp::socket socket(io_service); - * asio::ip::tcp::endpoint endpoint( - * asio::ip::address::from_string("1.2.3.4"), 12345); - * socket.async_connect(endpoint, connect_handler); - * @endcode - */ - template - void async_connect(const endpoint_type& peer_endpoint, ConnectHandler handler) - { - if (!is_open()) - { - asio::error_code ec; - if (this->service.open(this->implementation, - peer_endpoint.protocol(), ec)) - { - this->get_io_service().post( - asio::detail::bind_handler(handler, ec)); - return; - } - } - - this->service.async_connect(this->implementation, peer_endpoint, handler); - } - - /// Set an option on the socket. - /** - * This function is used to set an option on the socket. - * - * @param option The new option value to be set on the socket. - * - * @throws asio::system_error Thrown on failure. - * - * @sa SettableSocketOption @n - * asio::socket_base::broadcast @n - * asio::socket_base::do_not_route @n - * asio::socket_base::keep_alive @n - * asio::socket_base::linger @n - * asio::socket_base::receive_buffer_size @n - * asio::socket_base::receive_low_watermark @n - * asio::socket_base::reuse_address @n - * asio::socket_base::send_buffer_size @n - * asio::socket_base::send_low_watermark @n - * asio::ip::multicast::join_group @n - * asio::ip::multicast::leave_group @n - * asio::ip::multicast::enable_loopback @n - * asio::ip::multicast::outbound_interface @n - * asio::ip::multicast::hops @n - * asio::ip::tcp::no_delay - * - * @par Example - * Setting the IPPROTO_TCP/TCP_NODELAY option: - * @code - * asio::ip::tcp::socket socket(io_service); - * ... - * asio::ip::tcp::no_delay option(true); - * socket.set_option(option); - * @endcode - */ - template - void set_option(const SettableSocketOption& option) - { - asio::error_code ec; - this->service.set_option(this->implementation, option, ec); - asio::detail::throw_error(ec); - } - - /// Set an option on the socket. - /** - * This function is used to set an option on the socket. - * - * @param option The new option value to be set on the socket. - * - * @param ec Set to indicate what error occurred, if any. - * - * @sa SettableSocketOption @n - * asio::socket_base::broadcast @n - * asio::socket_base::do_not_route @n - * asio::socket_base::keep_alive @n - * asio::socket_base::linger @n - * asio::socket_base::receive_buffer_size @n - * asio::socket_base::receive_low_watermark @n - * asio::socket_base::reuse_address @n - * asio::socket_base::send_buffer_size @n - * asio::socket_base::send_low_watermark @n - * asio::ip::multicast::join_group @n - * asio::ip::multicast::leave_group @n - * asio::ip::multicast::enable_loopback @n - * asio::ip::multicast::outbound_interface @n - * asio::ip::multicast::hops @n - * asio::ip::tcp::no_delay - * - * @par Example - * Setting the IPPROTO_TCP/TCP_NODELAY option: - * @code - * asio::ip::tcp::socket socket(io_service); - * ... - * asio::ip::tcp::no_delay option(true); - * asio::error_code ec; - * socket.set_option(option, ec); - * if (ec) - * { - * // An error occurred. - * } - * @endcode - */ - template - asio::error_code set_option(const SettableSocketOption& option, - asio::error_code& ec) - { - return this->service.set_option(this->implementation, option, ec); - } - - /// Get an option from the socket. - /** - * This function is used to get the current value of an option on the socket. - * - * @param option The option value to be obtained from the socket. - * - * @throws asio::system_error Thrown on failure. - * - * @sa GettableSocketOption @n - * asio::socket_base::broadcast @n - * asio::socket_base::do_not_route @n - * asio::socket_base::keep_alive @n - * asio::socket_base::linger @n - * asio::socket_base::receive_buffer_size @n - * asio::socket_base::receive_low_watermark @n - * asio::socket_base::reuse_address @n - * asio::socket_base::send_buffer_size @n - * asio::socket_base::send_low_watermark @n - * asio::ip::multicast::join_group @n - * asio::ip::multicast::leave_group @n - * asio::ip::multicast::enable_loopback @n - * asio::ip::multicast::outbound_interface @n - * asio::ip::multicast::hops @n - * asio::ip::tcp::no_delay - * - * @par Example - * Getting the value of the SOL_SOCKET/SO_KEEPALIVE option: - * @code - * asio::ip::tcp::socket socket(io_service); - * ... - * asio::ip::tcp::socket::keep_alive option; - * socket.get_option(option); - * bool is_set = option.get(); - * @endcode - */ - template - void get_option(GettableSocketOption& option) const - { - asio::error_code ec; - this->service.get_option(this->implementation, option, ec); - asio::detail::throw_error(ec); - } - - /// Get an option from the socket. - /** - * This function is used to get the current value of an option on the socket. - * - * @param option The option value to be obtained from the socket. - * - * @param ec Set to indicate what error occurred, if any. - * - * @sa GettableSocketOption @n - * asio::socket_base::broadcast @n - * asio::socket_base::do_not_route @n - * asio::socket_base::keep_alive @n - * asio::socket_base::linger @n - * asio::socket_base::receive_buffer_size @n - * asio::socket_base::receive_low_watermark @n - * asio::socket_base::reuse_address @n - * asio::socket_base::send_buffer_size @n - * asio::socket_base::send_low_watermark @n - * asio::ip::multicast::join_group @n - * asio::ip::multicast::leave_group @n - * asio::ip::multicast::enable_loopback @n - * asio::ip::multicast::outbound_interface @n - * asio::ip::multicast::hops @n - * asio::ip::tcp::no_delay - * - * @par Example - * Getting the value of the SOL_SOCKET/SO_KEEPALIVE option: - * @code - * asio::ip::tcp::socket socket(io_service); - * ... - * asio::ip::tcp::socket::keep_alive option; - * asio::error_code ec; - * socket.get_option(option, ec); - * if (ec) - * { - * // An error occurred. - * } - * bool is_set = option.get(); - * @endcode - */ - template - asio::error_code get_option(GettableSocketOption& option, - asio::error_code& ec) const - { - return this->service.get_option(this->implementation, option, ec); - } - - /// Perform an IO control command on the socket. - /** - * This function is used to execute an IO control command on the socket. - * - * @param command The IO control command to be performed on the socket. - * - * @throws asio::system_error Thrown on failure. - * - * @sa IoControlCommand @n - * asio::socket_base::bytes_readable @n - * asio::socket_base::non_blocking_io - * - * @par Example - * Getting the number of bytes ready to read: - * @code - * asio::ip::tcp::socket socket(io_service); - * ... - * asio::ip::tcp::socket::bytes_readable command; - * socket.io_control(command); - * std::size_t bytes_readable = command.get(); - * @endcode - */ - template - void io_control(IoControlCommand& command) - { - asio::error_code ec; - this->service.io_control(this->implementation, command, ec); - asio::detail::throw_error(ec); - } - - /// Perform an IO control command on the socket. - /** - * This function is used to execute an IO control command on the socket. - * - * @param command The IO control command to be performed on the socket. - * - * @param ec Set to indicate what error occurred, if any. - * - * @sa IoControlCommand @n - * asio::socket_base::bytes_readable @n - * asio::socket_base::non_blocking_io - * - * @par Example - * Getting the number of bytes ready to read: - * @code - * asio::ip::tcp::socket socket(io_service); - * ... - * asio::ip::tcp::socket::bytes_readable command; - * asio::error_code ec; - * socket.io_control(command, ec); - * if (ec) - * { - * // An error occurred. - * } - * std::size_t bytes_readable = command.get(); - * @endcode - */ - template - asio::error_code io_control(IoControlCommand& command, - asio::error_code& ec) - { - return this->service.io_control(this->implementation, command, ec); - } - - /// Get the local endpoint of the socket. - /** - * This function is used to obtain the locally bound endpoint of the socket. - * - * @returns An object that represents the local endpoint of the socket. - * - * @throws asio::system_error Thrown on failure. - * - * @par Example - * @code - * asio::ip::tcp::socket socket(io_service); - * ... - * asio::ip::tcp::endpoint endpoint = socket.local_endpoint(); - * @endcode - */ - endpoint_type local_endpoint() const - { - asio::error_code ec; - endpoint_type ep = this->service.local_endpoint(this->implementation, ec); - asio::detail::throw_error(ec); - return ep; - } - - /// Get the local endpoint of the socket. - /** - * This function is used to obtain the locally bound endpoint of the socket. - * - * @param ec Set to indicate what error occurred, if any. - * - * @returns An object that represents the local endpoint of the socket. - * Returns a default-constructed endpoint object if an error occurred. - * - * @par Example - * @code - * asio::ip::tcp::socket socket(io_service); - * ... - * asio::error_code ec; - * asio::ip::tcp::endpoint endpoint = socket.local_endpoint(ec); - * if (ec) - * { - * // An error occurred. - * } - * @endcode - */ - endpoint_type local_endpoint(asio::error_code& ec) const - { - return this->service.local_endpoint(this->implementation, ec); - } - - /// Get the remote endpoint of the socket. - /** - * This function is used to obtain the remote endpoint of the socket. - * - * @returns An object that represents the remote endpoint of the socket. - * - * @throws asio::system_error Thrown on failure. - * - * @par Example - * @code - * asio::ip::tcp::socket socket(io_service); - * ... - * asio::ip::tcp::endpoint endpoint = socket.remote_endpoint(); - * @endcode - */ - endpoint_type remote_endpoint() const - { - asio::error_code ec; - endpoint_type ep = this->service.remote_endpoint(this->implementation, ec); - asio::detail::throw_error(ec); - return ep; - } - - /// Get the remote endpoint of the socket. - /** - * This function is used to obtain the remote endpoint of the socket. - * - * @param ec Set to indicate what error occurred, if any. - * - * @returns An object that represents the remote endpoint of the socket. - * Returns a default-constructed endpoint object if an error occurred. - * - * @par Example - * @code - * asio::ip::tcp::socket socket(io_service); - * ... - * asio::error_code ec; - * asio::ip::tcp::endpoint endpoint = socket.remote_endpoint(ec); - * if (ec) - * { - * // An error occurred. - * } - * @endcode - */ - endpoint_type remote_endpoint(asio::error_code& ec) const - { - return this->service.remote_endpoint(this->implementation, ec); - } - - /// Disable sends or receives on the socket. - /** - * This function is used to disable send operations, receive operations, or - * both. - * - * @param what Determines what types of operation will no longer be allowed. - * - * @throws asio::system_error Thrown on failure. - * - * @par Example - * Shutting down the send side of the socket: - * @code - * asio::ip::tcp::socket socket(io_service); - * ... - * socket.shutdown(asio::ip::tcp::socket::shutdown_send); - * @endcode - */ - void shutdown(shutdown_type what) - { - asio::error_code ec; - this->service.shutdown(this->implementation, what, ec); - asio::detail::throw_error(ec); - } - - /// Disable sends or receives on the socket. - /** - * This function is used to disable send operations, receive operations, or - * both. - * - * @param what Determines what types of operation will no longer be allowed. - * - * @param ec Set to indicate what error occurred, if any. - * - * @par Example - * Shutting down the send side of the socket: - * @code - * asio::ip::tcp::socket socket(io_service); - * ... - * asio::error_code ec; - * socket.shutdown(asio::ip::tcp::socket::shutdown_send, ec); - * if (ec) - * { - * // An error occurred. - * } - * @endcode - */ - asio::error_code shutdown(shutdown_type what, - asio::error_code& ec) - { - return this->service.shutdown(this->implementation, what, ec); - } - -protected: - /// Protected destructor to prevent deletion through this type. - ~basic_socket() - { - } -}; - -} // namespace asio - -#include "asio/detail/pop_options.hpp" - -#endif // ASIO_BASIC_SOCKET_HPP diff --git a/libtorrent/include/asio/basic_socket_acceptor.hpp b/libtorrent/include/asio/basic_socket_acceptor.hpp deleted file mode 100644 index 43a4fa4f2..000000000 --- a/libtorrent/include/asio/basic_socket_acceptor.hpp +++ /dev/null @@ -1,824 +0,0 @@ -// -// basic_socket_acceptor.hpp -// ~~~~~~~~~~~~~~~~~~~~~~~~~ -// -// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -#ifndef ASIO_BASIC_SOCKET_ACCEPTOR_HPP -#define ASIO_BASIC_SOCKET_ACCEPTOR_HPP - -#if defined(_MSC_VER) && (_MSC_VER >= 1200) -# pragma once -#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) - -#include "asio/detail/push_options.hpp" - -#include "asio/basic_io_object.hpp" -#include "asio/basic_socket.hpp" -#include "asio/error.hpp" -#include "asio/socket_acceptor_service.hpp" -#include "asio/socket_base.hpp" -#include "asio/detail/throw_error.hpp" - -namespace asio { - -/// Provides the ability to accept new connections. -/** - * The basic_socket_acceptor class template is used for accepting new socket - * connections. - * - * @par Thread Safety - * @e Distinct @e objects: Safe.@n - * @e Shared @e objects: Unsafe. - * - * @par Example - * Opening a socket acceptor with the SO_REUSEADDR option enabled: - * @code - * asio::ip::tcp::acceptor acceptor(io_service); - * asio::ip::tcp::endpoint endpoint(asio::ip::tcp::v4(), port); - * acceptor.open(endpoint.protocol()); - * acceptor.set_option(asio::ip::tcp::acceptor::reuse_address(true)); - * acceptor.bind(endpoint); - * acceptor.listen(); - * @endcode - */ -template > -class basic_socket_acceptor - : public basic_io_object, - public socket_base -{ -public: - /// The native representation of an acceptor. - typedef typename SocketAcceptorService::native_type native_type; - - /// The protocol type. - typedef Protocol protocol_type; - - /// The endpoint type. - typedef typename Protocol::endpoint endpoint_type; - - /// Construct an acceptor without opening it. - /** - * This constructor creates an acceptor without opening it to listen for new - * connections. The open() function must be called before the acceptor can - * accept new socket connections. - * - * @param io_service The io_service object that the acceptor will use to - * dispatch handlers for any asynchronous operations performed on the - * acceptor. - */ - explicit basic_socket_acceptor(asio::io_service& io_service) - : basic_io_object(io_service) - { - } - - /// Construct an open acceptor. - /** - * This constructor creates an acceptor and automatically opens it. - * - * @param io_service The io_service object that the acceptor will use to - * dispatch handlers for any asynchronous operations performed on the - * acceptor. - * - * @param protocol An object specifying protocol parameters to be used. - * - * @throws asio::system_error Thrown on failure. - */ - basic_socket_acceptor(asio::io_service& io_service, - const protocol_type& protocol) - : basic_io_object(io_service) - { - asio::error_code ec; - this->service.open(this->implementation, protocol, ec); - asio::detail::throw_error(ec); - } - - /// Construct an acceptor opened on the given endpoint. - /** - * This constructor creates an acceptor and automatically opens it to listen - * for new connections on the specified endpoint. - * - * @param io_service The io_service object that the acceptor will use to - * dispatch handlers for any asynchronous operations performed on the - * acceptor. - * - * @param endpoint An endpoint on the local machine on which the acceptor - * will listen for new connections. - * - * @param reuse_addr Whether the constructor should set the socket option - * socket_base::reuse_address. - * - * @throws asio::system_error Thrown on failure. - * - * @note This constructor is equivalent to the following code: - * @code - * basic_socket_acceptor acceptor(io_service); - * acceptor.open(endpoint.protocol()); - * if (reuse_addr) - * acceptor.set_option(socket_base::reuse_address(true)); - * acceptor.bind(endpoint); - * acceptor.listen(listen_backlog); - * @endcode - */ - basic_socket_acceptor(asio::io_service& io_service, - const endpoint_type& endpoint, bool reuse_addr = true) - : basic_io_object(io_service) - { - asio::error_code ec; - this->service.open(this->implementation, endpoint.protocol(), ec); - asio::detail::throw_error(ec); - if (reuse_addr) - { - this->service.set_option(this->implementation, - socket_base::reuse_address(true), ec); - asio::detail::throw_error(ec); - } - this->service.bind(this->implementation, endpoint, ec); - asio::detail::throw_error(ec); - this->service.listen(this->implementation, - socket_base::max_connections, ec); - asio::detail::throw_error(ec); - } - - /// Construct a basic_socket_acceptor on an existing native acceptor. - /** - * This constructor creates an acceptor object to hold an existing native - * acceptor. - * - * @param io_service The io_service object that the acceptor will use to - * dispatch handlers for any asynchronous operations performed on the - * acceptor. - * - * @param protocol An object specifying protocol parameters to be used. - * - * @param native_acceptor A native acceptor. - * - * @throws asio::system_error Thrown on failure. - */ - basic_socket_acceptor(asio::io_service& io_service, - const protocol_type& protocol, const native_type& native_acceptor) - : basic_io_object(io_service) - { - asio::error_code ec; - this->service.assign(this->implementation, protocol, native_acceptor, ec); - asio::detail::throw_error(ec); - } - - /// Open the acceptor using the specified protocol. - /** - * This function opens the socket acceptor so that it will use the specified - * protocol. - * - * @param protocol An object specifying which protocol is to be used. - * - * @throws asio::system_error Thrown on failure. - * - * @par Example - * @code - * asio::ip::tcp::acceptor acceptor(io_service); - * acceptor.open(asio::ip::tcp::v4()); - * @endcode - */ - void open(const protocol_type& protocol = protocol_type()) - { - asio::error_code ec; - this->service.open(this->implementation, protocol, ec); - asio::detail::throw_error(ec); - } - - /// Open the acceptor using the specified protocol. - /** - * This function opens the socket acceptor so that it will use the specified - * protocol. - * - * @param protocol An object specifying which protocol is to be used. - * - * @param ec Set to indicate what error occurred, if any. - * - * @par Example - * @code - * asio::ip::tcp::acceptor acceptor(io_service); - * asio::error_code ec; - * acceptor.open(asio::ip::tcp::v4(), ec); - * if (ec) - * { - * // An error occurred. - * } - * @endcode - */ - asio::error_code open(const protocol_type& protocol, - asio::error_code& ec) - { - return this->service.open(this->implementation, protocol, ec); - } - - /// Assigns an existing native acceptor to the acceptor. - /* - * This function opens the acceptor to hold an existing native acceptor. - * - * @param protocol An object specifying which protocol is to be used. - * - * @param native_acceptor A native acceptor. - * - * @throws asio::system_error Thrown on failure. - */ - void assign(const protocol_type& protocol, const native_type& native_acceptor) - { - asio::error_code ec; - this->service.assign(this->implementation, protocol, native_acceptor, ec); - asio::detail::throw_error(ec); - } - - /// Assigns an existing native acceptor to the acceptor. - /* - * This function opens the acceptor to hold an existing native acceptor. - * - * @param protocol An object specifying which protocol is to be used. - * - * @param native_acceptor A native acceptor. - * - * @param ec Set to indicate what error occurred, if any. - */ - asio::error_code assign(const protocol_type& protocol, - const native_type& native_acceptor, asio::error_code& ec) - { - return this->service.assign(this->implementation, - protocol, native_acceptor, ec); - } - - /// Determine whether the acceptor is open. - bool is_open() const - { - return this->service.is_open(this->implementation); - } - - /// Bind the acceptor to the given local endpoint. - /** - * This function binds the socket acceptor to the specified endpoint on the - * local machine. - * - * @param endpoint An endpoint on the local machine to which the socket - * acceptor will be bound. - * - * @throws asio::system_error Thrown on failure. - * - * @par Example - * @code - * asio::ip::tcp::acceptor acceptor(io_service); - * acceptor.open(asio::ip::tcp::v4()); - * acceptor.bind(asio::ip::tcp::endpoint(12345)); - * @endcode - */ - void bind(const endpoint_type& endpoint) - { - asio::error_code ec; - this->service.bind(this->implementation, endpoint, ec); - asio::detail::throw_error(ec); - } - - /// Bind the acceptor to the given local endpoint. - /** - * This function binds the socket acceptor to the specified endpoint on the - * local machine. - * - * @param endpoint An endpoint on the local machine to which the socket - * acceptor will be bound. - * - * @param ec Set to indicate what error occurred, if any. - * - * @par Example - * @code - * asio::ip::tcp::acceptor acceptor(io_service); - * acceptor.open(asio::ip::tcp::v4()); - * asio::error_code ec; - * acceptor.bind(asio::ip::tcp::endpoint(12345), ec); - * if (ec) - * { - * // An error occurred. - * } - * @endcode - */ - asio::error_code bind(const endpoint_type& endpoint, - asio::error_code& ec) - { - return this->service.bind(this->implementation, endpoint, ec); - } - - /// Place the acceptor into the state where it will listen for new - /// connections. - /** - * This function puts the socket acceptor into the state where it may accept - * new connections. - * - * @param backlog The maximum length of the queue of pending connections. - * - * @throws asio::system_error Thrown on failure. - */ - void listen(int backlog = socket_base::max_connections) - { - asio::error_code ec; - this->service.listen(this->implementation, backlog, ec); - asio::detail::throw_error(ec); - } - - /// Place the acceptor into the state where it will listen for new - /// connections. - /** - * This function puts the socket acceptor into the state where it may accept - * new connections. - * - * @param backlog The maximum length of the queue of pending connections. - * - * @param ec Set to indicate what error occurred, if any. - * - * @par Example - * @code - * asio::ip::tcp::acceptor acceptor(io_service); - * ... - * asio::error_code ec; - * acceptor.listen(asio::socket_base::max_connections, ec); - * if (ec) - * { - * // An error occurred. - * } - * @endcode - */ - asio::error_code listen(int backlog, asio::error_code& ec) - { - return this->service.listen(this->implementation, backlog, ec); - } - - /// Close the acceptor. - /** - * This function is used to close the acceptor. Any asynchronous accept - * operations will be cancelled immediately. - * - * A subsequent call to open() is required before the acceptor can again be - * used to again perform socket accept operations. - * - * @throws asio::system_error Thrown on failure. - */ - void close() - { - asio::error_code ec; - this->service.close(this->implementation, ec); - asio::detail::throw_error(ec); - } - - /// Close the acceptor. - /** - * This function is used to close the acceptor. Any asynchronous accept - * operations will be cancelled immediately. - * - * A subsequent call to open() is required before the acceptor can again be - * used to again perform socket accept operations. - * - * @param ec Set to indicate what error occurred, if any. - * - * @par Example - * @code - * asio::ip::tcp::acceptor acceptor(io_service); - * ... - * asio::error_code ec; - * acceptor.close(ec); - * if (ec) - * { - * // An error occurred. - * } - * @endcode - */ - asio::error_code close(asio::error_code& ec) - { - return this->service.close(this->implementation, ec); - } - - /// Get the native acceptor representation. - /** - * This function may be used to obtain the underlying representation of the - * acceptor. This is intended to allow access to native acceptor functionality - * that is not otherwise provided. - */ - native_type native() - { - return this->service.native(this->implementation); - } - - /// Cancel all asynchronous operations associated with the acceptor. - /** - * This function causes all outstanding asynchronous connect, send and receive - * operations to finish immediately, and the handlers for cancelled operations - * will be passed the asio::error::operation_aborted error. - * - * @throws asio::system_error Thrown on failure. - */ - void cancel() - { - asio::error_code ec; - this->service.cancel(this->implementation, ec); - asio::detail::throw_error(ec); - } - - /// Cancel all asynchronous operations associated with the acceptor. - /** - * This function causes all outstanding asynchronous connect, send and receive - * operations to finish immediately, and the handlers for cancelled operations - * will be passed the asio::error::operation_aborted error. - * - * @param ec Set to indicate what error occurred, if any. - */ - asio::error_code cancel(asio::error_code& ec) - { - return this->service.cancel(this->implementation, ec); - } - - /// Set an option on the acceptor. - /** - * This function is used to set an option on the acceptor. - * - * @param option The new option value to be set on the acceptor. - * - * @throws asio::system_error Thrown on failure. - * - * @sa SettableSocketOption @n - * asio::socket_base::reuse_address - * asio::socket_base::enable_connection_aborted - * - * @par Example - * Setting the SOL_SOCKET/SO_REUSEADDR option: - * @code - * asio::ip::tcp::acceptor acceptor(io_service); - * ... - * asio::ip::tcp::acceptor::reuse_address option(true); - * acceptor.set_option(option); - * @endcode - */ - template - void set_option(const SettableSocketOption& option) - { - asio::error_code ec; - this->service.set_option(this->implementation, option, ec); - asio::detail::throw_error(ec); - } - - /// Set an option on the acceptor. - /** - * This function is used to set an option on the acceptor. - * - * @param option The new option value to be set on the acceptor. - * - * @param ec Set to indicate what error occurred, if any. - * - * @sa SettableSocketOption @n - * asio::socket_base::reuse_address - * asio::socket_base::enable_connection_aborted - * - * @par Example - * Setting the SOL_SOCKET/SO_REUSEADDR option: - * @code - * asio::ip::tcp::acceptor acceptor(io_service); - * ... - * asio::ip::tcp::acceptor::reuse_address option(true); - * asio::error_code ec; - * acceptor.set_option(option, ec); - * if (ec) - * { - * // An error occurred. - * } - * @endcode - */ - template - asio::error_code set_option(const SettableSocketOption& option, - asio::error_code& ec) - { - return this->service.set_option(this->implementation, option, ec); - } - - /// Get an option from the acceptor. - /** - * This function is used to get the current value of an option on the - * acceptor. - * - * @param option The option value to be obtained from the acceptor. - * - * @throws asio::system_error Thrown on failure. - * - * @sa GettableSocketOption @n - * asio::socket_base::reuse_address - * - * @par Example - * Getting the value of the SOL_SOCKET/SO_REUSEADDR option: - * @code - * asio::ip::tcp::acceptor acceptor(io_service); - * ... - * asio::ip::tcp::acceptor::reuse_address option; - * acceptor.get_option(option); - * bool is_set = option.get(); - * @endcode - */ - template - void get_option(GettableSocketOption& option) - { - asio::error_code ec; - this->service.get_option(this->implementation, option, ec); - asio::detail::throw_error(ec); - } - - /// Get an option from the acceptor. - /** - * This function is used to get the current value of an option on the - * acceptor. - * - * @param option The option value to be obtained from the acceptor. - * - * @param ec Set to indicate what error occurred, if any. - * - * @sa GettableSocketOption @n - * asio::socket_base::reuse_address - * - * @par Example - * Getting the value of the SOL_SOCKET/SO_REUSEADDR option: - * @code - * asio::ip::tcp::acceptor acceptor(io_service); - * ... - * asio::ip::tcp::acceptor::reuse_address option; - * asio::error_code ec; - * acceptor.get_option(option, ec); - * if (ec) - * { - * // An error occurred. - * } - * bool is_set = option.get(); - * @endcode - */ - template - asio::error_code get_option(GettableSocketOption& option, - asio::error_code& ec) - { - return this->service.get_option(this->implementation, option, ec); - } - - /// Get the local endpoint of the acceptor. - /** - * This function is used to obtain the locally bound endpoint of the acceptor. - * - * @returns An object that represents the local endpoint of the acceptor. - * - * @throws asio::system_error Thrown on failure. - * - * @par Example - * @code - * asio::ip::tcp::acceptor acceptor(io_service); - * ... - * asio::ip::tcp::endpoint endpoint = acceptor.local_endpoint(); - * @endcode - */ - endpoint_type local_endpoint() const - { - asio::error_code ec; - endpoint_type ep = this->service.local_endpoint(this->implementation, ec); - asio::detail::throw_error(ec); - return ep; - } - - /// Get the local endpoint of the acceptor. - /** - * This function is used to obtain the locally bound endpoint of the acceptor. - * - * @param ec Set to indicate what error occurred, if any. - * - * @returns An object that represents the local endpoint of the acceptor. - * Returns a default-constructed endpoint object if an error occurred and the - * error handler did not throw an exception. - * - * @par Example - * @code - * asio::ip::tcp::acceptor acceptor(io_service); - * ... - * asio::error_code ec; - * asio::ip::tcp::endpoint endpoint = acceptor.local_endpoint(ec); - * if (ec) - * { - * // An error occurred. - * } - * @endcode - */ - endpoint_type local_endpoint(asio::error_code& ec) const - { - return this->service.local_endpoint(this->implementation, ec); - } - - /// Accept a new connection. - /** - * This function is used to accept a new connection from a peer into the - * given socket. The function call will block until a new connection has been - * accepted successfully or an error occurs. - * - * @param peer The socket into which the new connection will be accepted. - * - * @throws asio::system_error Thrown on failure. - * - * @par Example - * @code - * asio::ip::tcp::acceptor acceptor(io_service); - * ... - * asio::ip::tcp::socket socket(io_service); - * acceptor.accept(socket); - * @endcode - */ - template - void accept(basic_socket& peer) - { - asio::error_code ec; - this->service.accept(this->implementation, peer, 0, ec); - asio::detail::throw_error(ec); - } - - /// Accept a new connection. - /** - * This function is used to accept a new connection from a peer into the - * given socket. The function call will block until a new connection has been - * accepted successfully or an error occurs. - * - * @param peer The socket into which the new connection will be accepted. - * - * @param ec Set to indicate what error occurred, if any. - * - * @par Example - * @code - * asio::ip::tcp::acceptor acceptor(io_service); - * ... - * asio::ip::tcp::soocket socket(io_service); - * asio::error_code ec; - * acceptor.accept(socket, ec); - * if (ec) - * { - * // An error occurred. - * } - * @endcode - */ - template - asio::error_code accept( - basic_socket& peer, - asio::error_code& ec) - { - return this->service.accept(this->implementation, peer, 0, ec); - } - - /// Start an asynchronous accept. - /** - * This function is used to asynchronously accept a new connection into a - * socket. The function call always returns immediately. - * - * @param peer The socket into which the new connection will be accepted. - * Ownership of the peer object is retained by the caller, which must - * guarantee that it is valid until the handler is called. - * - * @param handler The handler to be called when the accept operation - * completes. Copies will be made of the handler as required. The function - * signature of the handler must be: - * @code void handler( - * const asio::error_code& error // Result of operation. - * ); @endcode - * Regardless of whether the asynchronous operation completes immediately or - * not, the handler will not be invoked from within this function. Invocation - * of the handler will be performed in a manner equivalent to using - * asio::io_service::post(). - * - * @par Example - * @code - * void accept_handler(const asio::error_code& error) - * { - * if (!error) - * { - * // Accept succeeded. - * } - * } - * - * ... - * - * asio::ip::tcp::acceptor acceptor(io_service); - * ... - * asio::ip::tcp::socket socket(io_service); - * acceptor.async_accept(socket, accept_handler); - * @endcode - */ - template - void async_accept(basic_socket& peer, - AcceptHandler handler) - { - this->service.async_accept(this->implementation, peer, 0, handler); - } - - /// Accept a new connection and obtain the endpoint of the peer - /** - * This function is used to accept a new connection from a peer into the - * given socket, and additionally provide the endpoint of the remote peer. - * The function call will block until a new connection has been accepted - * successfully or an error occurs. - * - * @param peer The socket into which the new connection will be accepted. - * - * @param peer_endpoint An endpoint object which will receive the endpoint of - * the remote peer. - * - * @throws asio::system_error Thrown on failure. - * - * @par Example - * @code - * asio::ip::tcp::acceptor acceptor(io_service); - * ... - * asio::ip::tcp::socket socket(io_service); - * asio::ip::tcp::endpoint endpoint; - * acceptor.accept(socket, endpoint); - * @endcode - */ - template - void accept(basic_socket& peer, - endpoint_type& peer_endpoint) - { - asio::error_code ec; - this->service.accept(this->implementation, peer, &peer_endpoint, ec); - asio::detail::throw_error(ec); - } - - /// Accept a new connection and obtain the endpoint of the peer - /** - * This function is used to accept a new connection from a peer into the - * given socket, and additionally provide the endpoint of the remote peer. - * The function call will block until a new connection has been accepted - * successfully or an error occurs. - * - * @param peer The socket into which the new connection will be accepted. - * - * @param peer_endpoint An endpoint object which will receive the endpoint of - * the remote peer. - * - * @param ec Set to indicate what error occurred, if any. - * - * @par Example - * @code - * asio::ip::tcp::acceptor acceptor(io_service); - * ... - * asio::ip::tcp::socket socket(io_service); - * asio::ip::tcp::endpoint endpoint; - * asio::error_code ec; - * acceptor.accept(socket, endpoint, ec); - * if (ec) - * { - * // An error occurred. - * } - * @endcode - */ - template - asio::error_code accept( - basic_socket& peer, - endpoint_type& peer_endpoint, asio::error_code& ec) - { - return this->service.accept(this->implementation, peer, &peer_endpoint, ec); - } - - /// Start an asynchronous accept. - /** - * This function is used to asynchronously accept a new connection into a - * socket, and additionally obtain the endpoint of the remote peer. The - * function call always returns immediately. - * - * @param peer The socket into which the new connection will be accepted. - * Ownership of the peer object is retained by the caller, which must - * guarantee that it is valid until the handler is called. - * - * @param peer_endpoint An endpoint object into which the endpoint of the - * remote peer will be written. Ownership of the peer_endpoint object is - * retained by the caller, which must guarantee that it is valid until the - * handler is called. - * - * @param handler The handler to be called when the accept operation - * completes. Copies will be made of the handler as required. The function - * signature of the handler must be: - * @code void handler( - * const asio::error_code& error // Result of operation. - * ); @endcode - * Regardless of whether the asynchronous operation completes immediately or - * not, the handler will not be invoked from within this function. Invocation - * of the handler will be performed in a manner equivalent to using - * asio::io_service::post(). - */ - template - void async_accept(basic_socket& peer, - endpoint_type& peer_endpoint, AcceptHandler handler) - { - this->service.async_accept(this->implementation, - peer, &peer_endpoint, handler); - } -}; - -} // namespace asio - -#include "asio/detail/pop_options.hpp" - -#endif // ASIO_BASIC_SOCKET_ACCEPTOR_HPP diff --git a/libtorrent/include/asio/basic_socket_iostream.hpp b/libtorrent/include/asio/basic_socket_iostream.hpp deleted file mode 100644 index 1d705ff77..000000000 --- a/libtorrent/include/asio/basic_socket_iostream.hpp +++ /dev/null @@ -1,148 +0,0 @@ -// -// basic_socket_iostream.hpp -// ~~~~~~~~~~~~~~~~~~~~~~~~~ -// -// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -#ifndef ASIO_BASIC_SOCKET_IOSTREAM_HPP -#define ASIO_BASIC_SOCKET_IOSTREAM_HPP - -#if defined(_MSC_VER) && (_MSC_VER >= 1200) -# pragma once -#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) - -#include "asio/detail/push_options.hpp" - -#include "asio/detail/push_options.hpp" -#include -#include -#include -#include -#include -#include "asio/detail/pop_options.hpp" - -#include "asio/basic_socket_streambuf.hpp" -#include "asio/stream_socket_service.hpp" - -#if !defined(ASIO_SOCKET_IOSTREAM_MAX_ARITY) -#define ASIO_SOCKET_IOSTREAM_MAX_ARITY 5 -#endif // !defined(ASIO_SOCKET_IOSTREAM_MAX_ARITY) - -// A macro that should expand to: -// template -// explicit basic_socket_iostream(T1 x1, ..., Tn xn) -// : basic_iostream(&this->boost::base_from_member< -// basic_socket_streambuf >::member) -// { -// if (rdbuf()->connect(x1, ..., xn) == 0) -// this->setstate(std::ios_base::failbit); -// } -// This macro should only persist within this file. - -#define ASIO_PRIVATE_CTR_DEF(z, n, data) \ - template \ - explicit basic_socket_iostream(BOOST_PP_ENUM_BINARY_PARAMS(n, T, x)) \ - : std::basic_iostream(&this->boost::base_from_member< \ - basic_socket_streambuf >::member) \ - { \ - tie(this); \ - if (rdbuf()->connect(BOOST_PP_ENUM_PARAMS(n, x)) == 0) \ - this->setstate(std::ios_base::failbit); \ - } \ - /**/ - -// A macro that should expand to: -// template -// void connect(T1 x1, ..., Tn xn) -// { -// if (rdbuf()->connect(x1, ..., xn) == 0) -// this->setstate(std::ios_base::failbit); -// } -// This macro should only persist within this file. - -#define ASIO_PRIVATE_CONNECT_DEF(z, n, data) \ - template \ - void connect(BOOST_PP_ENUM_BINARY_PARAMS(n, T, x)) \ - { \ - if (rdbuf()->connect(BOOST_PP_ENUM_PARAMS(n, x)) == 0) \ - this->setstate(std::ios_base::failbit); \ - } \ - /**/ - -namespace asio { - -/// Iostream interface for a socket. -template > -class basic_socket_iostream - : public boost::base_from_member< - basic_socket_streambuf >, - public std::basic_iostream -{ -public: - /// Construct a basic_socket_iostream without establishing a connection. - basic_socket_iostream() - : std::basic_iostream(&this->boost::base_from_member< - basic_socket_streambuf >::member) - { - tie(this); - } - -#if defined(GENERATING_DOCUMENTATION) - /// Establish a connection to an endpoint corresponding to a resolver query. - /** - * This constructor automatically establishes a connection based on the - * supplied resolver query parameters. The arguments are used to construct - * a resolver query object. - */ - template - explicit basic_socket_iostream(T1 t1, ..., TN tn); -#else - BOOST_PP_REPEAT_FROM_TO( - 1, BOOST_PP_INC(ASIO_SOCKET_IOSTREAM_MAX_ARITY), - ASIO_PRIVATE_CTR_DEF, _ ) -#endif - -#if defined(GENERATING_DOCUMENTATION) - /// Establish a connection to an endpoint corresponding to a resolver query. - /** - * This function automatically establishes a connection based on the supplied - * resolver query parameters. The arguments are used to construct a resolver - * query object. - */ - template - void connect(T1 t1, ..., TN tn); -#else - BOOST_PP_REPEAT_FROM_TO( - 1, BOOST_PP_INC(ASIO_SOCKET_IOSTREAM_MAX_ARITY), - ASIO_PRIVATE_CONNECT_DEF, _ ) -#endif - - /// Close the connection. - void close() - { - if (rdbuf()->close() == 0) - this->setstate(std::ios_base::failbit); - } - - /// Return a pointer to the underlying streambuf. - basic_socket_streambuf* rdbuf() const - { - return const_cast*>( - &this->boost::base_from_member< - basic_socket_streambuf >::member); - } -}; - -} // namespace asio - -#undef ASIO_PRIVATE_CTR_DEF -#undef ASIO_PRIVATE_CONNECT_DEF - -#include "asio/detail/pop_options.hpp" - -#endif // ASIO_BASIC_SOCKET_IOSTREAM_HPP diff --git a/libtorrent/include/asio/basic_socket_streambuf.hpp b/libtorrent/include/asio/basic_socket_streambuf.hpp deleted file mode 100644 index 0bcd3b7a9..000000000 --- a/libtorrent/include/asio/basic_socket_streambuf.hpp +++ /dev/null @@ -1,284 +0,0 @@ -// -// basic_socket_streambuf.hpp -// ~~~~~~~~~~~~~~~~~~~~~~~~~~ -// -// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -#ifndef ASIO_BASIC_SOCKET_STREAMBUF_HPP -#define ASIO_BASIC_SOCKET_STREAMBUF_HPP - -#if defined(_MSC_VER) && (_MSC_VER >= 1200) -# pragma once -#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) - -#include "asio/detail/push_options.hpp" - -#include "asio/detail/push_options.hpp" -#include -#include -#include -#include -#include -#include -#include -#include "asio/detail/pop_options.hpp" - -#include "asio/basic_socket.hpp" -#include "asio/io_service.hpp" -#include "asio/stream_socket_service.hpp" -#include "asio/detail/throw_error.hpp" - -#if !defined(ASIO_SOCKET_STREAMBUF_MAX_ARITY) -#define ASIO_SOCKET_STREAMBUF_MAX_ARITY 5 -#endif // !defined(ASIO_SOCKET_STREAMBUF_MAX_ARITY) - -// A macro that should expand to: -// template -// basic_socket_streambuf* connect( -// T1 x1, ..., Tn xn) -// { -// init_buffers(); -// asio::error_code ec; -// this->basic_socket::close(ec); -// typedef typename Protocol::resolver_query resolver_query; -// resolver_query query(x1, ..., xn); -// resolve_and_connect(query, ec); -// return !ec ? this : 0; -// } -// This macro should only persist within this file. - -#define ASIO_PRIVATE_CONNECT_DEF( z, n, data ) \ - template \ - basic_socket_streambuf* connect( \ - BOOST_PP_ENUM_BINARY_PARAMS(n, T, x)) \ - { \ - init_buffers(); \ - asio::error_code ec; \ - this->basic_socket::close(ec); \ - typedef typename Protocol::resolver_query resolver_query; \ - resolver_query query(BOOST_PP_ENUM_PARAMS(n, x)); \ - resolve_and_connect(query, ec); \ - return !ec ? this : 0; \ - } \ - /**/ - -namespace asio { - -/// Iostream streambuf for a socket. -template > -class basic_socket_streambuf - : public std::streambuf, - private boost::base_from_member, - public basic_socket -{ -public: - /// The endpoint type. - typedef typename Protocol::endpoint endpoint_type; - - /// Construct a basic_socket_streambuf without establishing a connection. - basic_socket_streambuf() - : basic_socket( - boost::base_from_member::member), - unbuffered_(false) - { - init_buffers(); - } - - /// Destructor flushes buffered data. - virtual ~basic_socket_streambuf() - { - if (pptr() != pbase()) - overflow(traits_type::eof()); - } - - /// Establish a connection. - /** - * This function establishes a connection to the specified endpoint. - * - * @return \c this if a connection was successfully established, a null - * pointer otherwise. - */ - basic_socket_streambuf* connect( - const endpoint_type& endpoint) - { - init_buffers(); - asio::error_code ec; - this->basic_socket::close(ec); - this->basic_socket::connect(endpoint, ec); - return !ec ? this : 0; - } - -#if defined(GENERATING_DOCUMENTATION) - /// Establish a connection. - /** - * This function automatically establishes a connection based on the supplied - * resolver query parameters. The arguments are used to construct a resolver - * query object. - * - * @return \c this if a connection was successfully established, a null - * pointer otherwise. - */ - template - basic_socket_streambuf* connect( - T1 t1, ..., TN tn); -#else - BOOST_PP_REPEAT_FROM_TO( - 1, BOOST_PP_INC(ASIO_SOCKET_STREAMBUF_MAX_ARITY), - ASIO_PRIVATE_CONNECT_DEF, _ ) -#endif - - /// Close the connection. - /** - * @return \c this if a connection was successfully established, a null - * pointer otherwise. - */ - basic_socket_streambuf* close() - { - asio::error_code ec; - sync(); - this->basic_socket::close(ec); - if (!ec) - init_buffers(); - return !ec ? this : 0; - } - -protected: - int_type underflow() - { - if (gptr() == egptr()) - { - asio::error_code ec; - std::size_t bytes_transferred = this->service.receive( - this->implementation, - asio::buffer(asio::buffer(get_buffer_) + putback_max), - 0, ec); - if (ec) - return traits_type::eof(); - setg(get_buffer_.begin(), get_buffer_.begin() + putback_max, - get_buffer_.begin() + putback_max + bytes_transferred); - return traits_type::to_int_type(*gptr()); - } - else - { - return traits_type::eof(); - } - } - - int_type overflow(int_type c) - { - if (unbuffered_) - { - if (traits_type::eq_int_type(c, traits_type::eof())) - { - // Nothing to do. - return traits_type::not_eof(c); - } - else - { - // Send the single character immediately. - asio::error_code ec; - char_type ch = traits_type::to_char_type(c); - this->service.send(this->implementation, - asio::buffer(&ch, sizeof(char_type)), 0, ec); - if (ec) - return traits_type::eof(); - return c; - } - } - else - { - // Send all data in the output buffer. - asio::const_buffer buffer = - asio::buffer(pbase(), pptr() - pbase()); - while (asio::buffer_size(buffer) > 0) - { - asio::error_code ec; - std::size_t bytes_transferred = this->service.send( - this->implementation, asio::buffer(buffer), - 0, ec); - if (ec) - return traits_type::eof(); - buffer = buffer + bytes_transferred; - } - setp(put_buffer_.begin(), put_buffer_.end()); - - // If the new character is eof then our work here is done. - if (traits_type::eq_int_type(c, traits_type::eof())) - return traits_type::not_eof(c); - - // Add the new character to the output buffer. - *pptr() = traits_type::to_char_type(c); - pbump(1); - return c; - } - } - - int sync() - { - return overflow(traits_type::eof()); - } - - std::streambuf* setbuf(char_type* s, std::streamsize n) - { - if (pptr() == pbase() && s == 0 && n == 0) - { - unbuffered_ = true; - setp(0, 0); - return this; - } - - return 0; - } - -private: - void init_buffers() - { - setg(get_buffer_.begin(), - get_buffer_.begin() + putback_max, - get_buffer_.begin() + putback_max); - if (unbuffered_) - setp(0, 0); - else - setp(put_buffer_.begin(), put_buffer_.end()); - } - - void resolve_and_connect(const typename Protocol::resolver_query& query, - asio::error_code& ec) - { - typedef typename Protocol::resolver resolver_type; - typedef typename Protocol::resolver_iterator iterator_type; - resolver_type resolver( - boost::base_from_member::member); - iterator_type i = resolver.resolve(query, ec); - if (!ec) - { - iterator_type end; - ec = asio::error::host_not_found; - while (ec && i != end) - { - this->basic_socket::close(); - this->basic_socket::connect(*i, ec); - ++i; - } - } - } - - enum { putback_max = 8 }; - enum { buffer_size = 512 }; - boost::array get_buffer_; - boost::array put_buffer_; - bool unbuffered_; -}; - -} // namespace asio - -#undef ASIO_PRIVATE_CONNECT_DEF - -#include "asio/detail/pop_options.hpp" - -#endif // ASIO_BASIC_SOCKET_STREAMBUF_HPP diff --git a/libtorrent/include/asio/basic_stream_socket.hpp b/libtorrent/include/asio/basic_stream_socket.hpp deleted file mode 100644 index c1e0ef039..000000000 --- a/libtorrent/include/asio/basic_stream_socket.hpp +++ /dev/null @@ -1,718 +0,0 @@ -// -// basic_stream_socket.hpp -// ~~~~~~~~~~~~~~~~~~~~~~~ -// -// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -#ifndef ASIO_BASIC_STREAM_SOCKET_HPP -#define ASIO_BASIC_STREAM_SOCKET_HPP - -#if defined(_MSC_VER) && (_MSC_VER >= 1200) -# pragma once -#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) - -#include "asio/detail/push_options.hpp" - -#include "asio/detail/push_options.hpp" -#include -#include -#include "asio/detail/pop_options.hpp" - -#include "asio/basic_socket.hpp" -#include "asio/error.hpp" -#include "asio/stream_socket_service.hpp" -#include "asio/detail/throw_error.hpp" - -namespace asio { - -/// Provides stream-oriented socket functionality. -/** - * The basic_stream_socket class template provides asynchronous and blocking - * stream-oriented socket functionality. - * - * @par Thread Safety - * @e Distinct @e objects: Safe.@n - * @e Shared @e objects: Unsafe. - * - * @par Concepts: - * AsyncReadStream, AsyncWriteStream, Stream, SyncReadStream, SyncWriteStream. - */ -template > -class basic_stream_socket - : public basic_socket -{ -public: - /// The native representation of a socket. - typedef typename StreamSocketService::native_type native_type; - - /// The protocol type. - typedef Protocol protocol_type; - - /// The endpoint type. - typedef typename Protocol::endpoint endpoint_type; - - /// Construct a basic_stream_socket without opening it. - /** - * This constructor creates a stream socket without opening it. The socket - * needs to be opened and then connected or accepted before data can be sent - * or received on it. - * - * @param io_service The io_service object that the stream socket will use to - * dispatch handlers for any asynchronous operations performed on the socket. - */ - explicit basic_stream_socket(asio::io_service& io_service) - : basic_socket(io_service) - { - } - - /// Construct and open a basic_stream_socket. - /** - * This constructor creates and opens a stream socket. The socket needs to be - * connected or accepted before data can be sent or received on it. - * - * @param io_service The io_service object that the stream socket will use to - * dispatch handlers for any asynchronous operations performed on the socket. - * - * @param protocol An object specifying protocol parameters to be used. - * - * @throws asio::system_error Thrown on failure. - */ - basic_stream_socket(asio::io_service& io_service, - const protocol_type& protocol) - : basic_socket(io_service, protocol) - { - } - - /// Construct a basic_stream_socket, opening it and binding it to the given - /// local endpoint. - /** - * This constructor creates a stream socket and automatically opens it bound - * to the specified endpoint on the local machine. The protocol used is the - * protocol associated with the given endpoint. - * - * @param io_service The io_service object that the stream socket will use to - * dispatch handlers for any asynchronous operations performed on the socket. - * - * @param endpoint An endpoint on the local machine to which the stream - * socket will be bound. - * - * @throws asio::system_error Thrown on failure. - */ - basic_stream_socket(asio::io_service& io_service, - const endpoint_type& endpoint) - : basic_socket(io_service, endpoint) - { - } - - /// Construct a basic_stream_socket on an existing native socket. - /** - * This constructor creates a stream socket object to hold an existing native - * socket. - * - * @param io_service The io_service object that the stream socket will use to - * dispatch handlers for any asynchronous operations performed on the socket. - * - * @param protocol An object specifying protocol parameters to be used. - * - * @param native_socket The new underlying socket implementation. - * - * @throws asio::system_error Thrown on failure. - */ - basic_stream_socket(asio::io_service& io_service, - const protocol_type& protocol, const native_type& native_socket) - : basic_socket( - io_service, protocol, native_socket) - { - } - - /// Send some data on the socket. - /** - * This function is used to send data on the stream socket. The function - * call will block until one or more bytes of the data has been sent - * successfully, or an until error occurs. - * - * @param buffers One or more data buffers to be sent on the socket. - * - * @returns The number of bytes sent. - * - * @throws asio::system_error Thrown on failure. - * - * @note The send operation may not transmit all of the data to the peer. - * Consider using the @ref write function if you need to ensure that all data - * is written before the blocking operation completes. - * - * @par Example - * To send a single data buffer use the @ref buffer function as follows: - * @code - * socket.send(asio::buffer(data, size)); - * @endcode - * See the @ref buffer documentation for information on sending multiple - * buffers in one go, and how to use it with arrays, boost::array or - * std::vector. - */ - template - std::size_t send(const ConstBufferSequence& buffers) - { - asio::error_code ec; - std::size_t s = this->service.send( - this->implementation, buffers, 0, ec); - asio::detail::throw_error(ec); - return s; - } - - /// Send some data on the socket. - /** - * This function is used to send data on the stream socket. The function - * call will block until one or more bytes of the data has been sent - * successfully, or an until error occurs. - * - * @param buffers One or more data buffers to be sent on the socket. - * - * @param flags Flags specifying how the send call is to be made. - * - * @returns The number of bytes sent. - * - * @throws asio::system_error Thrown on failure. - * - * @note The send operation may not transmit all of the data to the peer. - * Consider using the @ref write function if you need to ensure that all data - * is written before the blocking operation completes. - * - * @par Example - * To send a single data buffer use the @ref buffer function as follows: - * @code - * socket.send(asio::buffer(data, size), 0); - * @endcode - * See the @ref buffer documentation for information on sending multiple - * buffers in one go, and how to use it with arrays, boost::array or - * std::vector. - */ - template - std::size_t send(const ConstBufferSequence& buffers, - socket_base::message_flags flags) - { - asio::error_code ec; - std::size_t s = this->service.send( - this->implementation, buffers, flags, ec); - asio::detail::throw_error(ec); - return s; - } - - /// Send some data on the socket. - /** - * This function is used to send data on the stream socket. The function - * call will block until one or more bytes of the data has been sent - * successfully, or an until error occurs. - * - * @param buffers One or more data buffers to be sent on the socket. - * - * @param flags Flags specifying how the send call is to be made. - * - * @param ec Set to indicate what error occurred, if any. - * - * @returns The number of bytes sent. Returns 0 if an error occurred. - * - * @note The send operation may not transmit all of the data to the peer. - * Consider using the @ref write function if you need to ensure that all data - * is written before the blocking operation completes. - */ - template - std::size_t send(const ConstBufferSequence& buffers, - socket_base::message_flags flags, asio::error_code& ec) - { - return this->service.send(this->implementation, buffers, flags, ec); - } - - /// Start an asynchronous send. - /** - * This function is used to asynchronously send data on the stream socket. - * The function call always returns immediately. - * - * @param buffers One or more data buffers to be sent on the socket. Although - * the buffers object may be copied as necessary, ownership of the underlying - * memory blocks is retained by the caller, which must guarantee that they - * remain valid until the handler is called. - * - * @param handler The handler to be called when the send operation completes. - * Copies will be made of the handler as required. The function signature of - * the handler must be: - * @code void handler( - * const asio::error_code& error, // Result of operation. - * std::size_t bytes_transferred // Number of bytes sent. - * ); @endcode - * Regardless of whether the asynchronous operation completes immediately or - * not, the handler will not be invoked from within this function. Invocation - * of the handler will be performed in a manner equivalent to using - * asio::io_service::post(). - * - * @note The send operation may not transmit all of the data to the peer. - * Consider using the @ref async_write function if you need to ensure that all - * data is written before the asynchronous operation completes. - * - * @par Example - * To send a single data buffer use the @ref buffer function as follows: - * @code - * socket.async_send(asio::buffer(data, size), handler); - * @endcode - * See the @ref buffer documentation for information on sending multiple - * buffers in one go, and how to use it with arrays, boost::array or - * std::vector. - */ - template - void async_send(const ConstBufferSequence& buffers, WriteHandler handler) - { - this->service.async_send(this->implementation, buffers, 0, handler); - } - - /// Start an asynchronous send. - /** - * This function is used to asynchronously send data on the stream socket. - * The function call always returns immediately. - * - * @param buffers One or more data buffers to be sent on the socket. Although - * the buffers object may be copied as necessary, ownership of the underlying - * memory blocks is retained by the caller, which must guarantee that they - * remain valid until the handler is called. - * - * @param flags Flags specifying how the send call is to be made. - * - * @param handler The handler to be called when the send operation completes. - * Copies will be made of the handler as required. The function signature of - * the handler must be: - * @code void handler( - * const asio::error_code& error, // Result of operation. - * std::size_t bytes_transferred // Number of bytes sent. - * ); @endcode - * Regardless of whether the asynchronous operation completes immediately or - * not, the handler will not be invoked from within this function. Invocation - * of the handler will be performed in a manner equivalent to using - * asio::io_service::post(). - * - * @note The send operation may not transmit all of the data to the peer. - * Consider using the @ref async_write function if you need to ensure that all - * data is written before the asynchronous operation completes. - * - * @par Example - * To send a single data buffer use the @ref buffer function as follows: - * @code - * socket.async_send(asio::buffer(data, size), 0, handler); - * @endcode - * See the @ref buffer documentation for information on sending multiple - * buffers in one go, and how to use it with arrays, boost::array or - * std::vector. - */ - template - void async_send(const ConstBufferSequence& buffers, - socket_base::message_flags flags, WriteHandler handler) - { - this->service.async_send(this->implementation, buffers, flags, handler); - } - - /// Receive some data on the socket. - /** - * This function is used to receive data on the stream socket. The function - * call will block until one or more bytes of data has been received - * successfully, or until an error occurs. - * - * @param buffers One or more buffers into which the data will be received. - * - * @returns The number of bytes received. - * - * @throws asio::system_error Thrown on failure. An error code of - * asio::error::eof indicates that the connection was closed by the - * peer. - * - * @note The receive operation may not receive all of the requested number of - * bytes. Consider using the @ref read function if you need to ensure that the - * requested amount of data is read before the blocking operation completes. - * - * @par Example - * To receive into a single data buffer use the @ref buffer function as - * follows: - * @code - * socket.receive(asio::buffer(data, size)); - * @endcode - * See the @ref buffer documentation for information on receiving into - * multiple buffers in one go, and how to use it with arrays, boost::array or - * std::vector. - */ - template - std::size_t receive(const MutableBufferSequence& buffers) - { - asio::error_code ec; - std::size_t s = this->service.receive(this->implementation, buffers, 0, ec); - asio::detail::throw_error(ec); - return s; - } - - /// Receive some data on the socket. - /** - * This function is used to receive data on the stream socket. The function - * call will block until one or more bytes of data has been received - * successfully, or until an error occurs. - * - * @param buffers One or more buffers into which the data will be received. - * - * @param flags Flags specifying how the receive call is to be made. - * - * @returns The number of bytes received. - * - * @throws asio::system_error Thrown on failure. An error code of - * asio::error::eof indicates that the connection was closed by the - * peer. - * - * @note The receive operation may not receive all of the requested number of - * bytes. Consider using the @ref read function if you need to ensure that the - * requested amount of data is read before the blocking operation completes. - * - * @par Example - * To receive into a single data buffer use the @ref buffer function as - * follows: - * @code - * socket.receive(asio::buffer(data, size), 0); - * @endcode - * See the @ref buffer documentation for information on receiving into - * multiple buffers in one go, and how to use it with arrays, boost::array or - * std::vector. - */ - template - std::size_t receive(const MutableBufferSequence& buffers, - socket_base::message_flags flags) - { - asio::error_code ec; - std::size_t s = this->service.receive( - this->implementation, buffers, flags, ec); - asio::detail::throw_error(ec); - return s; - } - - /// Receive some data on a connected socket. - /** - * This function is used to receive data on the stream socket. The function - * call will block until one or more bytes of data has been received - * successfully, or until an error occurs. - * - * @param buffers One or more buffers into which the data will be received. - * - * @param flags Flags specifying how the receive call is to be made. - * - * @param ec Set to indicate what error occurred, if any. - * - * @returns The number of bytes received. Returns 0 if an error occurred. - * - * @note The receive operation may not receive all of the requested number of - * bytes. Consider using the @ref read function if you need to ensure that the - * requested amount of data is read before the blocking operation completes. - */ - template - std::size_t receive(const MutableBufferSequence& buffers, - socket_base::message_flags flags, asio::error_code& ec) - { - return this->service.receive(this->implementation, buffers, flags, ec); - } - - /// Start an asynchronous receive. - /** - * This function is used to asynchronously receive data from the stream - * socket. The function call always returns immediately. - * - * @param buffers One or more buffers into which the data will be received. - * Although the buffers object may be copied as necessary, ownership of the - * underlying memory blocks is retained by the caller, which must guarantee - * that they remain valid until the handler is called. - * - * @param handler The handler to be called when the receive operation - * completes. Copies will be made of the handler as required. The function - * signature of the handler must be: - * @code void handler( - * const asio::error_code& error, // Result of operation. - * std::size_t bytes_transferred // Number of bytes received. - * ); @endcode - * Regardless of whether the asynchronous operation completes immediately or - * not, the handler will not be invoked from within this function. Invocation - * of the handler will be performed in a manner equivalent to using - * asio::io_service::post(). - * - * @note The receive operation may not receive all of the requested number of - * bytes. Consider using the @ref async_read function if you need to ensure - * that the requested amount of data is received before the asynchronous - * operation completes. - * - * @par Example - * To receive into a single data buffer use the @ref buffer function as - * follows: - * @code - * socket.async_receive(asio::buffer(data, size), handler); - * @endcode - * See the @ref buffer documentation for information on receiving into - * multiple buffers in one go, and how to use it with arrays, boost::array or - * std::vector. - */ - template - void async_receive(const MutableBufferSequence& buffers, ReadHandler handler) - { - this->service.async_receive(this->implementation, buffers, 0, handler); - } - - /// Start an asynchronous receive. - /** - * This function is used to asynchronously receive data from the stream - * socket. The function call always returns immediately. - * - * @param buffers One or more buffers into which the data will be received. - * Although the buffers object may be copied as necessary, ownership of the - * underlying memory blocks is retained by the caller, which must guarantee - * that they remain valid until the handler is called. - * - * @param flags Flags specifying how the receive call is to be made. - * - * @param handler The handler to be called when the receive operation - * completes. Copies will be made of the handler as required. The function - * signature of the handler must be: - * @code void handler( - * const asio::error_code& error, // Result of operation. - * std::size_t bytes_transferred // Number of bytes received. - * ); @endcode - * Regardless of whether the asynchronous operation completes immediately or - * not, the handler will not be invoked from within this function. Invocation - * of the handler will be performed in a manner equivalent to using - * asio::io_service::post(). - * - * @note The receive operation may not receive all of the requested number of - * bytes. Consider using the @ref async_read function if you need to ensure - * that the requested amount of data is received before the asynchronous - * operation completes. - * - * @par Example - * To receive into a single data buffer use the @ref buffer function as - * follows: - * @code - * socket.async_receive(asio::buffer(data, size), 0, handler); - * @endcode - * See the @ref buffer documentation for information on receiving into - * multiple buffers in one go, and how to use it with arrays, boost::array or - * std::vector. - */ - template - void async_receive(const MutableBufferSequence& buffers, - socket_base::message_flags flags, ReadHandler handler) - { - this->service.async_receive(this->implementation, buffers, flags, handler); - } - - /// Write some data to the socket. - /** - * This function is used to write data to the stream socket. The function call - * will block until one or more bytes of the data has been written - * successfully, or until an error occurs. - * - * @param buffers One or more data buffers to be written to the socket. - * - * @returns The number of bytes written. - * - * @throws asio::system_error Thrown on failure. An error code of - * asio::error::eof indicates that the connection was closed by the - * peer. - * - * @note The write_some operation may not transmit all of the data to the - * peer. Consider using the @ref write function if you need to ensure that - * all data is written before the blocking operation completes. - * - * @par Example - * To write a single data buffer use the @ref buffer function as follows: - * @code - * socket.write_some(asio::buffer(data, size)); - * @endcode - * See the @ref buffer documentation for information on writing multiple - * buffers in one go, and how to use it with arrays, boost::array or - * std::vector. - */ - template - std::size_t write_some(const ConstBufferSequence& buffers) - { - asio::error_code ec; - std::size_t s = this->service.send(this->implementation, buffers, 0, ec); - asio::detail::throw_error(ec); - return s; - } - - /// Write some data to the socket. - /** - * This function is used to write data to the stream socket. The function call - * will block until one or more bytes of the data has been written - * successfully, or until an error occurs. - * - * @param buffers One or more data buffers to be written to the socket. - * - * @param ec Set to indicate what error occurred, if any. - * - * @returns The number of bytes written. Returns 0 if an error occurred. - * - * @note The write_some operation may not transmit all of the data to the - * peer. Consider using the @ref write function if you need to ensure that - * all data is written before the blocking operation completes. - */ - template - std::size_t write_some(const ConstBufferSequence& buffers, - asio::error_code& ec) - { - return this->service.send(this->implementation, buffers, 0, ec); - } - - /// Start an asynchronous write. - /** - * This function is used to asynchronously write data to the stream socket. - * The function call always returns immediately. - * - * @param buffers One or more data buffers to be written to the socket. - * Although the buffers object may be copied as necessary, ownership of the - * underlying memory blocks is retained by the caller, which must guarantee - * that they remain valid until the handler is called. - * - * @param handler The handler to be called when the write operation completes. - * Copies will be made of the handler as required. The function signature of - * the handler must be: - * @code void handler( - * const asio::error_code& error, // Result of operation. - * std::size_t bytes_transferred // Number of bytes written. - * ); @endcode - * Regardless of whether the asynchronous operation completes immediately or - * not, the handler will not be invoked from within this function. Invocation - * of the handler will be performed in a manner equivalent to using - * asio::io_service::post(). - * - * @note The write operation may not transmit all of the data to the peer. - * Consider using the @ref async_write function if you need to ensure that all - * data is written before the asynchronous operation completes. - * - * @par Example - * To write a single data buffer use the @ref buffer function as follows: - * @code - * socket.async_write_some(asio::buffer(data, size), handler); - * @endcode - * See the @ref buffer documentation for information on writing multiple - * buffers in one go, and how to use it with arrays, boost::array or - * std::vector. - */ - template - void async_write_some(const ConstBufferSequence& buffers, - WriteHandler handler) - { - this->service.async_send(this->implementation, buffers, 0, handler); - } - - /// Read some data from the socket. - /** - * This function is used to read data from the stream socket. The function - * call will block until one or more bytes of data has been read successfully, - * or until an error occurs. - * - * @param buffers One or more buffers into which the data will be read. - * - * @returns The number of bytes read. - * - * @throws asio::system_error Thrown on failure. An error code of - * asio::error::eof indicates that the connection was closed by the - * peer. - * - * @note The read_some operation may not read all of the requested number of - * bytes. Consider using the @ref read function if you need to ensure that - * the requested amount of data is read before the blocking operation - * completes. - * - * @par Example - * To read into a single data buffer use the @ref buffer function as follows: - * @code - * socket.read_some(asio::buffer(data, size)); - * @endcode - * See the @ref buffer documentation for information on reading into multiple - * buffers in one go, and how to use it with arrays, boost::array or - * std::vector. - */ - template - std::size_t read_some(const MutableBufferSequence& buffers) - { - asio::error_code ec; - std::size_t s = this->service.receive(this->implementation, buffers, 0, ec); - asio::detail::throw_error(ec); - return s; - } - - /// Read some data from the socket. - /** - * This function is used to read data from the stream socket. The function - * call will block until one or more bytes of data has been read successfully, - * or until an error occurs. - * - * @param buffers One or more buffers into which the data will be read. - * - * @param ec Set to indicate what error occurred, if any. - * - * @returns The number of bytes read. Returns 0 if an error occurred. - * - * @note The read_some operation may not read all of the requested number of - * bytes. Consider using the @ref read function if you need to ensure that - * the requested amount of data is read before the blocking operation - * completes. - */ - template - std::size_t read_some(const MutableBufferSequence& buffers, - asio::error_code& ec) - { - return this->service.receive(this->implementation, buffers, 0, ec); - } - - /// Start an asynchronous read. - /** - * This function is used to asynchronously read data from the stream socket. - * The function call always returns immediately. - * - * @param buffers One or more buffers into which the data will be read. - * Although the buffers object may be copied as necessary, ownership of the - * underlying memory blocks is retained by the caller, which must guarantee - * that they remain valid until the handler is called. - * - * @param handler The handler to be called when the read operation completes. - * Copies will be made of the handler as required. The function signature of - * the handler must be: - * @code void handler( - * const asio::error_code& error, // Result of operation. - * std::size_t bytes_transferred // Number of bytes read. - * ); @endcode - * Regardless of whether the asynchronous operation completes immediately or - * not, the handler will not be invoked from within this function. Invocation - * of the handler will be performed in a manner equivalent to using - * asio::io_service::post(). - * - * @note The read operation may not read all of the requested number of bytes. - * Consider using the @ref async_read function if you need to ensure that the - * requested amount of data is read before the asynchronous operation - * completes. - * - * @par Example - * To read into a single data buffer use the @ref buffer function as follows: - * @code - * socket.async_read_some(asio::buffer(data, size), handler); - * @endcode - * See the @ref buffer documentation for information on reading into multiple - * buffers in one go, and how to use it with arrays, boost::array or - * std::vector. - */ - template - void async_read_some(const MutableBufferSequence& buffers, - ReadHandler handler) - { - this->service.async_receive(this->implementation, buffers, 0, handler); - } -}; - -} // namespace asio - -#include "asio/detail/pop_options.hpp" - -#endif // ASIO_BASIC_STREAM_SOCKET_HPP diff --git a/libtorrent/include/asio/basic_streambuf.hpp b/libtorrent/include/asio/basic_streambuf.hpp deleted file mode 100644 index 41649cc43..000000000 --- a/libtorrent/include/asio/basic_streambuf.hpp +++ /dev/null @@ -1,198 +0,0 @@ -// -// basic_streambuf.hpp -// ~~~~~~~~~~~~~~~~~~~ -// -// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -#ifndef ASIO_BASIC_STREAMBUF_HPP -#define ASIO_BASIC_STREAMBUF_HPP - -#if defined(_MSC_VER) && (_MSC_VER >= 1200) -# pragma once -#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) - -#include "asio/detail/push_options.hpp" - -#include "asio/detail/push_options.hpp" -#include -#include -#include -#include -#include -#include -#include "asio/detail/pop_options.hpp" - -#include "asio/buffer.hpp" -#include "asio/detail/noncopyable.hpp" - -namespace asio { - -/// Automatically resizable buffer class based on std::streambuf. -template > -class basic_streambuf - : public std::streambuf, - private noncopyable -{ -public: -#if defined(GENERATING_DOCUMENTATION) - /// The type used to represent the get area as a list of buffers. - typedef implementation_defined const_buffers_type; - - /// The type used to represent the put area as a list of buffers. - typedef implementation_defined mutable_buffers_type; -#else - typedef asio::const_buffers_1 const_buffers_type; - typedef asio::mutable_buffers_1 mutable_buffers_type; -#endif - - /// Construct a buffer with a specified maximum size. - explicit basic_streambuf( - std::size_t max_size = (std::numeric_limits::max)(), - const Allocator& allocator = Allocator()) - : max_size_(max_size), - buffer_(allocator) - { - std::size_t pend = (std::min)(max_size_, buffer_delta); - buffer_.resize((std::max)(pend, 1)); - setg(&buffer_[0], &buffer_[0], &buffer_[0]); - setp(&buffer_[0], &buffer_[0] + pend); - } - - /// Return the size of the get area in characters. - std::size_t size() const - { - return pptr() - gptr(); - } - - /// Return the maximum size of the buffer. - std::size_t max_size() const - { - return max_size_; - } - - /// Get a list of buffers that represents the get area. - const_buffers_type data() const - { - return asio::buffer(asio::const_buffer(gptr(), - (pptr() - gptr()) * sizeof(char_type))); - } - - /// Get a list of buffers that represents the put area, with the given size. - mutable_buffers_type prepare(std::size_t size) - { - reserve(size); - return asio::buffer(asio::mutable_buffer( - pptr(), size * sizeof(char_type))); - } - - /// Move the start of the put area by the specified number of characters. - void commit(std::size_t n) - { - if (pptr() + n > epptr()) - n = epptr() - pptr(); - pbump(static_cast(n)); - } - - /// Move the start of the get area by the specified number of characters. - void consume(std::size_t n) - { - if (gptr() + n > pptr()) - n = pptr() - gptr(); - gbump(static_cast(n)); - } - -protected: - enum { buffer_delta = 128 }; - - int_type underflow() - { - if (gptr() < pptr()) - { - setg(&buffer_[0], gptr(), pptr()); - return traits_type::to_int_type(*gptr()); - } - else - { - return traits_type::eof(); - } - } - - int_type overflow(int_type c) - { - if (!traits_type::eq_int_type(c, traits_type::eof())) - { - if (pptr() == epptr()) - { - std::size_t buffer_size = pptr() - gptr(); - if (buffer_size < max_size_ && max_size_ - buffer_size < buffer_delta) - { - reserve(max_size_ - buffer_size); - } - else - { - reserve(buffer_delta); - } - } - - *pptr() = traits_type::to_char_type(c); - pbump(1); - return c; - } - - return traits_type::not_eof(c); - } - - void reserve(std::size_t n) - { - // Get current stream positions as offsets. - std::size_t gnext = gptr() - &buffer_[0]; - std::size_t gend = egptr() - &buffer_[0]; - std::size_t pnext = pptr() - &buffer_[0]; - std::size_t pend = epptr() - &buffer_[0]; - - // Check if there is already enough space in the put area. - if (n <= pend - pnext) - { - return; - } - - // Shift existing contents of get area to start of buffer. - if (gnext > 0) - { - std::rotate(&buffer_[0], &buffer_[0] + gnext, &buffer_[0] + pend); - gend -= gnext; - pnext -= gnext; - } - - // Ensure buffer is large enough to hold at least the specified size. - if (n > pend - pnext) - { - if (n <= max_size_ && pnext <= max_size_ - n) - { - buffer_.resize((std::max)(pnext + n, 1)); - } - else - { - throw std::length_error("asio::streambuf too long"); - } - } - - // Update stream positions. - setg(&buffer_[0], &buffer_[0], &buffer_[0] + gend); - setp(&buffer_[0] + pnext, &buffer_[0] + pnext + n); - } - -private: - std::size_t max_size_; - std::vector buffer_; -}; - -} // namespace asio - -#include "asio/detail/pop_options.hpp" - -#endif // ASIO_BASIC_STREAMBUF_HPP diff --git a/libtorrent/include/asio/buffer.hpp b/libtorrent/include/asio/buffer.hpp deleted file mode 100644 index 7bd04a811..000000000 --- a/libtorrent/include/asio/buffer.hpp +++ /dev/null @@ -1,1040 +0,0 @@ -// -// buffer.hpp -// ~~~~~~~~~~ -// -// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -#ifndef ASIO_BUFFER_HPP -#define ASIO_BUFFER_HPP - -#if defined(_MSC_VER) && (_MSC_VER >= 1200) -# pragma once -#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) - -#include "asio/detail/push_options.hpp" - -#include "asio/detail/push_options.hpp" -#include -#include -#include -#include -#include -#include -#include "asio/detail/pop_options.hpp" - -#if defined(BOOST_MSVC) -# if defined(_HAS_ITERATOR_DEBUGGING) && (_HAS_ITERATOR_DEBUGGING != 0) -# if !defined(ASIO_DISABLE_BUFFER_DEBUGGING) -# define ASIO_ENABLE_BUFFER_DEBUGGING -# endif // !defined(ASIO_DISABLE_BUFFER_DEBUGGING) -# endif // defined(_HAS_ITERATOR_DEBUGGING) -#endif // defined(BOOST_MSVC) - -#if defined(__GNUC__) -# if defined(_GLIBCXX_DEBUG) -# if !defined(ASIO_DISABLE_BUFFER_DEBUGGING) -# define ASIO_ENABLE_BUFFER_DEBUGGING -# endif // !defined(ASIO_DISABLE_BUFFER_DEBUGGING) -# endif // defined(_GLIBCXX_DEBUG) -#endif // defined(__GNUC__) - -#if defined(ASIO_ENABLE_BUFFER_DEBUGGING) -# include "asio/detail/push_options.hpp" -# include -# include "asio/detail/pop_options.hpp" -#endif // ASIO_ENABLE_BUFFER_DEBUGGING - -namespace asio { - -class mutable_buffer; -class const_buffer; - -namespace detail { -void* buffer_cast_helper(const mutable_buffer&); -const void* buffer_cast_helper(const const_buffer&); -std::size_t buffer_size_helper(const mutable_buffer&); -std::size_t buffer_size_helper(const const_buffer&); -} // namespace detail - -/// Holds a buffer that can be modified. -/** - * The mutable_buffer class provides a safe representation of a buffer that can - * be modified. It does not own the underlying data, and so is cheap to copy or - * assign. - */ -class mutable_buffer -{ -public: - /// Construct an empty buffer. - mutable_buffer() - : data_(0), - size_(0) - { - } - - /// Construct a buffer to represent a given memory range. - mutable_buffer(void* data, std::size_t size) - : data_(data), - size_(size) - { - } - -#if defined(ASIO_ENABLE_BUFFER_DEBUGGING) - mutable_buffer(void* data, std::size_t size, - boost::function debug_check) - : data_(data), - size_(size), - debug_check_(debug_check) - { - } - - const boost::function& get_debug_check() const - { - return debug_check_; - } -#endif // ASIO_ENABLE_BUFFER_DEBUGGING - -private: - friend void* asio::detail::buffer_cast_helper( - const mutable_buffer& b); - friend std::size_t asio::detail::buffer_size_helper( - const mutable_buffer& b); - - void* data_; - std::size_t size_; - -#if defined(ASIO_ENABLE_BUFFER_DEBUGGING) - boost::function debug_check_; -#endif // ASIO_ENABLE_BUFFER_DEBUGGING -}; - -namespace detail { - -inline void* buffer_cast_helper(const mutable_buffer& b) -{ -#if defined(ASIO_ENABLE_BUFFER_DEBUGGING) - if (b.size_ && b.debug_check_) - b.debug_check_(); -#endif // ASIO_ENABLE_BUFFER_DEBUGGING - return b.data_; -} - -inline std::size_t buffer_size_helper(const mutable_buffer& b) -{ - return b.size_; -} - -} // namespace detail - -/// Cast a non-modifiable buffer to a specified pointer to POD type. -/** - * @relates mutable_buffer - */ -template -inline PointerToPodType buffer_cast(const mutable_buffer& b) -{ - return static_cast(detail::buffer_cast_helper(b)); -} - -/// Get the number of bytes in a non-modifiable buffer. -/** - * @relates mutable_buffer - */ -inline std::size_t buffer_size(const mutable_buffer& b) -{ - return detail::buffer_size_helper(b); -} - -/// Create a new modifiable buffer that is offset from the start of another. -/** - * @relates mutable_buffer - */ -inline mutable_buffer operator+(const mutable_buffer& b, std::size_t start) -{ - if (start > buffer_size(b)) - return mutable_buffer(); - char* new_data = buffer_cast(b) + start; - std::size_t new_size = buffer_size(b) - start; - return mutable_buffer(new_data, new_size -#if defined(ASIO_ENABLE_BUFFER_DEBUGGING) - , b.get_debug_check() -#endif // ASIO_ENABLE_BUFFER_DEBUGGING - ); -} - -/// Create a new modifiable buffer that is offset from the start of another. -/** - * @relates mutable_buffer - */ -inline mutable_buffer operator+(std::size_t start, const mutable_buffer& b) -{ - if (start > buffer_size(b)) - return mutable_buffer(); - char* new_data = buffer_cast(b) + start; - std::size_t new_size = buffer_size(b) - start; - return mutable_buffer(new_data, new_size -#if defined(ASIO_ENABLE_BUFFER_DEBUGGING) - , b.get_debug_check() -#endif // ASIO_ENABLE_BUFFER_DEBUGGING - ); -} - -/// Adapts a single modifiable buffer so that it meets the requirements of the -/// MutableBufferSequence concept. -class mutable_buffers_1 - : public mutable_buffer -{ -public: - /// The type for each element in the list of buffers. - typedef mutable_buffer value_type; - - /// A random-access iterator type that may be used to read elements. - typedef const mutable_buffer* const_iterator; - - /// Construct to represent a given memory range. - mutable_buffers_1(void* data, std::size_t size) - : mutable_buffer(data, size) - { - } - - /// Construct to represent a single modifiable buffer. - explicit mutable_buffers_1(const mutable_buffer& b) - : mutable_buffer(b) - { - } - - /// Get a random-access iterator to the first element. - const_iterator begin() const - { - return this; - } - - /// Get a random-access iterator for one past the last element. - const_iterator end() const - { - return begin() + 1; - } -}; - -/// Holds a buffer that cannot be modified. -/** - * The const_buffer class provides a safe representation of a buffer that cannot - * be modified. It does not own the underlying data, and so is cheap to copy or - * assign. - */ -class const_buffer -{ -public: - /// Construct an empty buffer. - const_buffer() - : data_(0), - size_(0) - { - } - - /// Construct a buffer to represent a given memory range. - const_buffer(const void* data, std::size_t size) - : data_(data), - size_(size) - { - } - - /// Construct a non-modifiable buffer from a modifiable one. - const_buffer(const mutable_buffer& b) - : data_(asio::detail::buffer_cast_helper(b)), - size_(asio::detail::buffer_size_helper(b)) -#if defined(ASIO_ENABLE_BUFFER_DEBUGGING) - , debug_check_(b.get_debug_check()) -#endif // ASIO_ENABLE_BUFFER_DEBUGGING - { - } - -#if defined(ASIO_ENABLE_BUFFER_DEBUGGING) - const_buffer(const void* data, std::size_t size, - boost::function debug_check) - : data_(data), - size_(size), - debug_check_(debug_check) - { - } - - const boost::function& get_debug_check() const - { - return debug_check_; - } -#endif // ASIO_ENABLE_BUFFER_DEBUGGING - -private: - friend const void* asio::detail::buffer_cast_helper( - const const_buffer& b); - friend std::size_t asio::detail::buffer_size_helper( - const const_buffer& b); - - const void* data_; - std::size_t size_; - -#if defined(ASIO_ENABLE_BUFFER_DEBUGGING) - boost::function debug_check_; -#endif // ASIO_ENABLE_BUFFER_DEBUGGING -}; - -namespace detail { - -inline const void* buffer_cast_helper(const const_buffer& b) -{ -#if defined(ASIO_ENABLE_BUFFER_DEBUGGING) - if (b.size_ && b.debug_check_) - b.debug_check_(); -#endif // ASIO_ENABLE_BUFFER_DEBUGGING - return b.data_; -} - -inline std::size_t buffer_size_helper(const const_buffer& b) -{ - return b.size_; -} - -} // namespace detail - -/// Cast a non-modifiable buffer to a specified pointer to POD type. -/** - * @relates const_buffer - */ -template -inline PointerToPodType buffer_cast(const const_buffer& b) -{ - return static_cast(detail::buffer_cast_helper(b)); -} - -/// Get the number of bytes in a non-modifiable buffer. -/** - * @relates const_buffer - */ -inline std::size_t buffer_size(const const_buffer& b) -{ - return detail::buffer_size_helper(b); -} - -/// Create a new non-modifiable buffer that is offset from the start of another. -/** - * @relates const_buffer - */ -inline const_buffer operator+(const const_buffer& b, std::size_t start) -{ - if (start > buffer_size(b)) - return const_buffer(); - const char* new_data = buffer_cast(b) + start; - std::size_t new_size = buffer_size(b) - start; - return const_buffer(new_data, new_size -#if defined(ASIO_ENABLE_BUFFER_DEBUGGING) - , b.get_debug_check() -#endif // ASIO_ENABLE_BUFFER_DEBUGGING - ); -} - -/// Create a new non-modifiable buffer that is offset from the start of another. -/** - * @relates const_buffer - */ -inline const_buffer operator+(std::size_t start, const const_buffer& b) -{ - if (start > buffer_size(b)) - return const_buffer(); - const char* new_data = buffer_cast(b) + start; - std::size_t new_size = buffer_size(b) - start; - return const_buffer(new_data, new_size -#if defined(ASIO_ENABLE_BUFFER_DEBUGGING) - , b.get_debug_check() -#endif // ASIO_ENABLE_BUFFER_DEBUGGING - ); -} - -/// Adapts a single non-modifiable buffer so that it meets the requirements of -/// the ConstBufferSequence concept. -class const_buffers_1 - : public const_buffer -{ -public: - /// The type for each element in the list of buffers. - typedef const_buffer value_type; - - /// A random-access iterator type that may be used to read elements. - typedef const const_buffer* const_iterator; - - /// Construct to represent a given memory range. - const_buffers_1(const void* data, std::size_t size) - : const_buffer(data, size) - { - } - - /// Construct to represent a single non-modifiable buffer. - explicit const_buffers_1(const const_buffer& b) - : const_buffer(b) - { - } - - /// Get a random-access iterator to the first element. - const_iterator begin() const - { - return this; - } - - /// Get a random-access iterator for one past the last element. - const_iterator end() const - { - return begin() + 1; - } -}; - -/// An implementation of both the ConstBufferSequence and MutableBufferSequence -/// concepts to represent a null buffer sequence. -class null_buffers -{ -public: - /// The type for each element in the list of buffers. - typedef mutable_buffer value_type; - - /// A random-access iterator type that may be used to read elements. - typedef const mutable_buffer* const_iterator; - - /// Get a random-access iterator to the first element. - const_iterator begin() const - { - return &buf_; - } - - /// Get a random-access iterator for one past the last element. - const_iterator end() const - { - return &buf_; - } - -private: - mutable_buffer buf_; -}; - -#if defined(ASIO_ENABLE_BUFFER_DEBUGGING) -namespace detail { - -template -class buffer_debug_check -{ -public: - buffer_debug_check(Iterator iter) - : iter_(iter) - { - } - - ~buffer_debug_check() - { -#if BOOST_WORKAROUND(BOOST_MSVC, >= 1400) - // MSVC's string iterator checking may crash in a std::string::iterator - // object's destructor when the iterator points to an already-destroyed - // std::string object, unless the iterator is cleared first. - iter_ = Iterator(); -#endif // BOOST_WORKAROUND(BOOST_MSVC, >= 1400) - } - - void operator()() - { - *iter_; - } - -private: - Iterator iter_; -}; - -} // namespace detail -#endif // ASIO_ENABLE_BUFFER_DEBUGGING - -/** @defgroup buffer asio::buffer - * - * @brief The asio::buffer function is used to create a buffer object to - * represent raw memory, an array of POD elements, a vector of POD elements, - * or a std::string. - * - * A buffer object represents a contiguous region of memory as a 2-tuple - * consisting of a pointer and size in bytes. A tuple of the form {void*, - * size_t} specifies a mutable (modifiable) region of memory. Similarly, a - * tuple of the form {const void*, size_t} specifies a const - * (non-modifiable) region of memory. These two forms correspond to the classes - * mutable_buffer and const_buffer, respectively. To mirror C++'s conversion - * rules, a mutable_buffer is implicitly convertible to a const_buffer, and the - * opposite conversion is not permitted. - * - * The simplest use case involves reading or writing a single buffer of a - * specified size: - * - * @code sock.send(asio::buffer(data, size)); @endcode - * - * In the above example, the return value of asio::buffer meets the - * requirements of the ConstBufferSequence concept so that it may be directly - * passed to the socket's write function. A buffer created for modifiable - * memory also meets the requirements of the MutableBufferSequence concept. - * - * An individual buffer may be created from a builtin array, std::vector or - * boost::array of POD elements. This helps prevent buffer overruns by - * automatically determining the size of the buffer: - * - * @code char d1[128]; - * size_t bytes_transferred = sock.receive(asio::buffer(d1)); - * - * std::vector d2(128); - * bytes_transferred = sock.receive(asio::buffer(d2)); - * - * boost::array d3; - * bytes_transferred = sock.receive(asio::buffer(d3)); @endcode - * - * In all three cases above, the buffers created are exactly 128 bytes long. - * Note that a vector is @e never automatically resized when creating or using - * a buffer. The buffer size is determined using the vector's size() - * member function, and not its capacity. - * - * @par Accessing Buffer Contents - * - * The contents of a buffer may be accessed using the asio::buffer_size - * and asio::buffer_cast functions: - * - * @code asio::mutable_buffer b1 = ...; - * std::size_t s1 = asio::buffer_size(b1); - * unsigned char* p1 = asio::buffer_cast(b1); - * - * asio::const_buffer b2 = ...; - * std::size_t s2 = asio::buffer_size(b2); - * const void* p2 = asio::buffer_cast(b2); @endcode - * - * The asio::buffer_cast function permits violations of type safety, so - * uses of it in application code should be carefully considered. - * - * @par Buffer Invalidation - * - * A buffer object does not have any ownership of the memory it refers to. It - * is the responsibility of the application to ensure the memory region remains - * valid until it is no longer required for an I/O operation. When the memory - * is no longer available, the buffer is said to have been invalidated. - * - * For the asio::buffer overloads that accept an argument of type - * std::vector, the buffer objects returned are invalidated by any vector - * operation that also invalidates all references, pointers and iterators - * referring to the elements in the sequence (C++ Std, 23.2.4) - * - * For the asio::buffer overloads that accept an argument of type - * std::string, the buffer objects returned are invalidated according to the - * rules defined for invalidation of references, pointers and iterators - * referring to elements of the sequence (C++ Std, 21.3). - * - * @par Buffer Arithmetic - * - * Buffer objects may be manipulated using simple arithmetic in a safe way - * which helps prevent buffer overruns. Consider an array initialised as - * follows: - * - * @code boost::array a = { 'a', 'b', 'c', 'd', 'e' }; @endcode - * - * A buffer object @c b1 created using: - * - * @code b1 = asio::buffer(a); @endcode - * - * represents the entire array, { 'a', 'b', 'c', 'd', 'e' }. An - * optional second argument to the asio::buffer function may be used to - * limit the size, in bytes, of the buffer: - * - * @code b2 = asio::buffer(a, 3); @endcode - * - * such that @c b2 represents the data { 'a', 'b', 'c' }. Even if the - * size argument exceeds the actual size of the array, the size of the buffer - * object created will be limited to the array size. - * - * An offset may be applied to an existing buffer to create a new one: - * - * @code b3 = b1 + 2; @endcode - * - * where @c b3 will set to represent { 'c', 'd', 'e' }. If the offset - * exceeds the size of the existing buffer, the newly created buffer will be - * empty. - * - * Both an offset and size may be specified to create a buffer that corresponds - * to a specific range of bytes within an existing buffer: - * - * @code b4 = asio::buffer(b1 + 1, 3); @endcode - * - * so that @c b4 will refer to the bytes { 'b', 'c', 'd' }. - * - * @par Buffers and Scatter-Gather I/O - * - * To read or write using multiple buffers (i.e. scatter-gather I/O), multiple - * buffer objects may be assigned into a container that supports the - * MutableBufferSequence (for read) or ConstBufferSequence (for write) concepts: - * - * @code - * char d1[128]; - * std::vector d2(128); - * boost::array d3; - * - * boost::array bufs1 = { - * asio::buffer(d1), - * asio::buffer(d2), - * asio::buffer(d3) }; - * bytes_transferred = sock.receive(bufs1); - * - * std::vector bufs2; - * bufs2.push_back(asio::buffer(d1)); - * bufs2.push_back(asio::buffer(d2)); - * bufs2.push_back(asio::buffer(d3)); - * bytes_transferred = sock.send(bufs2); @endcode - */ -/*@{*/ - -/// Create a new modifiable buffer from an existing buffer. -/** - * @returns mutable_buffers_1(b). - */ -inline mutable_buffers_1 buffer(const mutable_buffer& b) -{ - return mutable_buffers_1(b); -} - -/// Create a new modifiable buffer from an existing buffer. -/** - * @returns A mutable_buffers_1 value equivalent to: - * @code mutable_buffers_1( - * buffer_cast(b), - * min(buffer_size(b), max_size_in_bytes)); @endcode - */ -inline mutable_buffers_1 buffer(const mutable_buffer& b, - std::size_t max_size_in_bytes) -{ - return mutable_buffers_1( - mutable_buffer(buffer_cast(b), - buffer_size(b) < max_size_in_bytes - ? buffer_size(b) : max_size_in_bytes -#if defined(ASIO_ENABLE_BUFFER_DEBUGGING) - , b.get_debug_check() -#endif // ASIO_ENABLE_BUFFER_DEBUGGING - )); -} - -/// Create a new non-modifiable buffer from an existing buffer. -/** - * @returns const_buffers_1(b). - */ -inline const_buffers_1 buffer(const const_buffer& b) -{ - return const_buffers_1(b); -} - -/// Create a new non-modifiable buffer from an existing buffer. -/** - * @returns A const_buffers_1 value equivalent to: - * @code const_buffers_1( - * buffer_cast(b), - * min(buffer_size(b), max_size_in_bytes)); @endcode - */ -inline const_buffers_1 buffer(const const_buffer& b, - std::size_t max_size_in_bytes) -{ - return const_buffers_1( - const_buffer(buffer_cast(b), - buffer_size(b) < max_size_in_bytes - ? buffer_size(b) : max_size_in_bytes -#if defined(ASIO_ENABLE_BUFFER_DEBUGGING) - , b.get_debug_check() -#endif // ASIO_ENABLE_BUFFER_DEBUGGING - )); -} - -/// Create a new modifiable buffer that represents the given memory range. -/** - * @returns mutable_buffers_1(data, size_in_bytes). - */ -inline mutable_buffers_1 buffer(void* data, std::size_t size_in_bytes) -{ - return mutable_buffers_1(mutable_buffer(data, size_in_bytes)); -} - -/// Create a new non-modifiable buffer that represents the given memory range. -/** - * @returns const_buffers_1(data, size_in_bytes). - */ -inline const_buffers_1 buffer(const void* data, - std::size_t size_in_bytes) -{ - return const_buffers_1(const_buffer(data, size_in_bytes)); -} - -/// Create a new modifiable buffer that represents the given POD array. -/** - * @returns A mutable_buffers_1 value equivalent to: - * @code mutable_buffers_1( - * static_cast(data), - * N * sizeof(PodType)); @endcode - */ -template -inline mutable_buffers_1 buffer(PodType (&data)[N]) -{ - return mutable_buffers_1(mutable_buffer(data, N * sizeof(PodType))); -} - -/// Create a new modifiable buffer that represents the given POD array. -/** - * @returns A mutable_buffers_1 value equivalent to: - * @code mutable_buffers_1( - * static_cast(data), - * min(N * sizeof(PodType), max_size_in_bytes)); @endcode - */ -template -inline mutable_buffers_1 buffer(PodType (&data)[N], - std::size_t max_size_in_bytes) -{ - return mutable_buffers_1( - mutable_buffer(data, - N * sizeof(PodType) < max_size_in_bytes - ? N * sizeof(PodType) : max_size_in_bytes)); -} - -/// Create a new non-modifiable buffer that represents the given POD array. -/** - * @returns A const_buffers_1 value equivalent to: - * @code const_buffers_1( - * static_cast(data), - * N * sizeof(PodType)); @endcode - */ -template -inline const_buffers_1 buffer(const PodType (&data)[N]) -{ - return const_buffers_1(const_buffer(data, N * sizeof(PodType))); -} - -/// Create a new non-modifiable buffer that represents the given POD array. -/** - * @returns A const_buffers_1 value equivalent to: - * @code const_buffers_1( - * static_cast(data), - * min(N * sizeof(PodType), max_size_in_bytes)); @endcode - */ -template -inline const_buffers_1 buffer(const PodType (&data)[N], - std::size_t max_size_in_bytes) -{ - return const_buffers_1( - const_buffer(data, - N * sizeof(PodType) < max_size_in_bytes - ? N * sizeof(PodType) : max_size_in_bytes)); -} - -#if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x582)) \ - || BOOST_WORKAROUND(__SUNPRO_CC, BOOST_TESTED_AT(0x590)) - -// Borland C++ and Sun Studio think the overloads: -// -// unspecified buffer(boost::array& array ...); -// -// and -// -// unspecified buffer(boost::array& array ...); -// -// are ambiguous. This will be worked around by using a buffer_types traits -// class that contains typedefs for the appropriate buffer and container -// classes, based on whether PodType is const or non-const. - -namespace detail { - -template -struct buffer_types_base; - -template <> -struct buffer_types_base -{ - typedef mutable_buffer buffer_type; - typedef mutable_buffers_1 container_type; -}; - -template <> -struct buffer_types_base -{ - typedef const_buffer buffer_type; - typedef const_buffers_1 container_type; -}; - -template -struct buffer_types - : public buffer_types_base::value> -{ -}; - -} // namespace detail - -template -inline typename detail::buffer_types::container_type -buffer(boost::array& data) -{ - typedef typename asio::detail::buffer_types::buffer_type - buffer_type; - typedef typename asio::detail::buffer_types::container_type - container_type; - return container_type( - buffer_type(data.c_array(), data.size() * sizeof(PodType))); -} - -template -inline typename detail::buffer_types::container_type -buffer(boost::array& data, std::size_t max_size_in_bytes) -{ - typedef typename asio::detail::buffer_types::buffer_type - buffer_type; - typedef typename asio::detail::buffer_types::container_type - container_type; - return container_type( - buffer_type(data.c_array(), - data.size() * sizeof(PodType) < max_size_in_bytes - ? data.size() * sizeof(PodType) : max_size_in_bytes)); -} - -#else // BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x582)) - // || BOOST_WORKAROUND(__SUNPRO_CC, BOOST_TESTED_AT(0x590)) - -/// Create a new modifiable buffer that represents the given POD array. -/** - * @returns A mutable_buffers_1 value equivalent to: - * @code mutable_buffers_1( - * data.data(), - * data.size() * sizeof(PodType)); @endcode - */ -template -inline mutable_buffers_1 buffer(boost::array& data) -{ - return mutable_buffers_1( - mutable_buffer(data.c_array(), data.size() * sizeof(PodType))); -} - -/// Create a new modifiable buffer that represents the given POD array. -/** - * @returns A mutable_buffers_1 value equivalent to: - * @code mutable_buffers_1( - * data.data(), - * min(data.size() * sizeof(PodType), max_size_in_bytes)); @endcode - */ -template -inline mutable_buffers_1 buffer(boost::array& data, - std::size_t max_size_in_bytes) -{ - return mutable_buffers_1( - mutable_buffer(data.c_array(), - data.size() * sizeof(PodType) < max_size_in_bytes - ? data.size() * sizeof(PodType) : max_size_in_bytes)); -} - -/// Create a new non-modifiable buffer that represents the given POD array. -/** - * @returns A const_buffers_1 value equivalent to: - * @code const_buffers_1( - * data.data(), - * data.size() * sizeof(PodType)); @endcode - */ -template -inline const_buffers_1 buffer(boost::array& data) -{ - return const_buffers_1( - const_buffer(data.data(), data.size() * sizeof(PodType))); -} - -/// Create a new non-modifiable buffer that represents the given POD array. -/** - * @returns A const_buffers_1 value equivalent to: - * @code const_buffers_1( - * data.data(), - * min(data.size() * sizeof(PodType), max_size_in_bytes)); @endcode - */ -template -inline const_buffers_1 buffer(boost::array& data, - std::size_t max_size_in_bytes) -{ - return const_buffers_1( - const_buffer(data.data(), - data.size() * sizeof(PodType) < max_size_in_bytes - ? data.size() * sizeof(PodType) : max_size_in_bytes)); -} - -#endif // BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x582)) - // || BOOST_WORKAROUND(__SUNPRO_CC, BOOST_TESTED_AT(0x590)) - -/// Create a new non-modifiable buffer that represents the given POD array. -/** - * @returns A const_buffers_1 value equivalent to: - * @code const_buffers_1( - * data.data(), - * data.size() * sizeof(PodType)); @endcode - */ -template -inline const_buffers_1 buffer(const boost::array& data) -{ - return const_buffers_1( - const_buffer(data.data(), data.size() * sizeof(PodType))); -} - -/// Create a new non-modifiable buffer that represents the given POD array. -/** - * @returns A const_buffers_1 value equivalent to: - * @code const_buffers_1( - * data.data(), - * min(data.size() * sizeof(PodType), max_size_in_bytes)); @endcode - */ -template -inline const_buffers_1 buffer(const boost::array& data, - std::size_t max_size_in_bytes) -{ - return const_buffers_1( - const_buffer(data.data(), - data.size() * sizeof(PodType) < max_size_in_bytes - ? data.size() * sizeof(PodType) : max_size_in_bytes)); -} - -/// Create a new modifiable buffer that represents the given POD vector. -/** - * @returns A mutable_buffers_1 value equivalent to: - * @code mutable_buffers_1( - * data.size() ? &data[0] : 0, - * data.size() * sizeof(PodType)); @endcode - * - * @note The buffer is invalidated by any vector operation that would also - * invalidate iterators. - */ -template -inline mutable_buffers_1 buffer(std::vector& data) -{ - return mutable_buffers_1( - mutable_buffer(data.size() ? &data[0] : 0, data.size() * sizeof(PodType) -#if defined(ASIO_ENABLE_BUFFER_DEBUGGING) - , detail::buffer_debug_check< - typename std::vector::iterator - >(data.begin()) -#endif // ASIO_ENABLE_BUFFER_DEBUGGING - )); -} - -/// Create a new modifiable buffer that represents the given POD vector. -/** - * @returns A mutable_buffers_1 value equivalent to: - * @code mutable_buffers_1( - * data.size() ? &data[0] : 0, - * min(data.size() * sizeof(PodType), max_size_in_bytes)); @endcode - * - * @note The buffer is invalidated by any vector operation that would also - * invalidate iterators. - */ -template -inline mutable_buffers_1 buffer(std::vector& data, - std::size_t max_size_in_bytes) -{ - return mutable_buffers_1( - mutable_buffer(data.size() ? &data[0] : 0, - data.size() * sizeof(PodType) < max_size_in_bytes - ? data.size() * sizeof(PodType) : max_size_in_bytes -#if defined(ASIO_ENABLE_BUFFER_DEBUGGING) - , detail::buffer_debug_check< - typename std::vector::iterator - >(data.begin()) -#endif // ASIO_ENABLE_BUFFER_DEBUGGING - )); -} - -/// Create a new non-modifiable buffer that represents the given POD vector. -/** - * @returns A const_buffers_1 value equivalent to: - * @code const_buffers_1( - * data.size() ? &data[0] : 0, - * data.size() * sizeof(PodType)); @endcode - * - * @note The buffer is invalidated by any vector operation that would also - * invalidate iterators. - */ -template -inline const_buffers_1 buffer( - const std::vector& data) -{ - return const_buffers_1( - const_buffer(data.size() ? &data[0] : 0, data.size() * sizeof(PodType) -#if defined(ASIO_ENABLE_BUFFER_DEBUGGING) - , detail::buffer_debug_check< - typename std::vector::const_iterator - >(data.begin()) -#endif // ASIO_ENABLE_BUFFER_DEBUGGING - )); -} - -/// Create a new non-modifiable buffer that represents the given POD vector. -/** - * @returns A const_buffers_1 value equivalent to: - * @code const_buffers_1( - * data.size() ? &data[0] : 0, - * min(data.size() * sizeof(PodType), max_size_in_bytes)); @endcode - * - * @note The buffer is invalidated by any vector operation that would also - * invalidate iterators. - */ -template -inline const_buffers_1 buffer( - const std::vector& data, std::size_t max_size_in_bytes) -{ - return const_buffers_1( - const_buffer(data.size() ? &data[0] : 0, - data.size() * sizeof(PodType) < max_size_in_bytes - ? data.size() * sizeof(PodType) : max_size_in_bytes -#if defined(ASIO_ENABLE_BUFFER_DEBUGGING) - , detail::buffer_debug_check< - typename std::vector::const_iterator - >(data.begin()) -#endif // ASIO_ENABLE_BUFFER_DEBUGGING - )); -} - -/// Create a new non-modifiable buffer that represents the given string. -/** - * @returns const_buffers_1(data.data(), data.size()). - * - * @note The buffer is invalidated by any non-const operation called on the - * given string object. - */ -inline const_buffers_1 buffer(const std::string& data) -{ - return const_buffers_1(const_buffer(data.data(), data.size() -#if defined(ASIO_ENABLE_BUFFER_DEBUGGING) - , detail::buffer_debug_check(data.begin()) -#endif // ASIO_ENABLE_BUFFER_DEBUGGING - )); -} - -/// Create a new non-modifiable buffer that represents the given string. -/** - * @returns A const_buffers_1 value equivalent to: - * @code const_buffers_1( - * data.data(), - * min(data.size(), max_size_in_bytes)); @endcode - * - * @note The buffer is invalidated by any non-const operation called on the - * given string object. - */ -inline const_buffers_1 buffer(const std::string& data, - std::size_t max_size_in_bytes) -{ - return const_buffers_1( - const_buffer(data.data(), - data.size() < max_size_in_bytes - ? data.size() : max_size_in_bytes -#if defined(ASIO_ENABLE_BUFFER_DEBUGGING) - , detail::buffer_debug_check(data.begin()) -#endif // ASIO_ENABLE_BUFFER_DEBUGGING - )); -} - -/*@}*/ - -} // namespace asio - -#include "asio/detail/pop_options.hpp" - -#endif // ASIO_BUFFER_HPP diff --git a/libtorrent/include/asio/buffered_read_stream.hpp b/libtorrent/include/asio/buffered_read_stream.hpp deleted file mode 100644 index 673cce38d..000000000 --- a/libtorrent/include/asio/buffered_read_stream.hpp +++ /dev/null @@ -1,414 +0,0 @@ -// -// buffered_read_stream.hpp -// ~~~~~~~~~~~~~~~~~~~~~~~~ -// -// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -#ifndef ASIO_BUFFERED_READ_STREAM_HPP -#define ASIO_BUFFERED_READ_STREAM_HPP - -#if defined(_MSC_VER) && (_MSC_VER >= 1200) -# pragma once -#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) - -#include "asio/detail/push_options.hpp" - -#include "asio/detail/push_options.hpp" -#include -#include -#include -#include -#include "asio/detail/pop_options.hpp" - -#include "asio/buffered_read_stream_fwd.hpp" -#include "asio/buffer.hpp" -#include "asio/error.hpp" -#include "asio/io_service.hpp" -#include "asio/detail/bind_handler.hpp" -#include "asio/detail/buffer_resize_guard.hpp" -#include "asio/detail/buffered_stream_storage.hpp" -#include "asio/detail/noncopyable.hpp" - -namespace asio { - -/// Adds buffering to the read-related operations of a stream. -/** - * The buffered_read_stream class template can be used to add buffering to the - * synchronous and asynchronous read operations of a stream. - * - * @par Thread Safety - * @e Distinct @e objects: Safe.@n - * @e Shared @e objects: Unsafe. - * - * @par Concepts: - * AsyncReadStream, AsyncWriteStream, Stream, Sync_Read_Stream, SyncWriteStream. - */ -template -class buffered_read_stream - : private noncopyable -{ -public: - /// The type of the next layer. - typedef typename boost::remove_reference::type next_layer_type; - - /// The type of the lowest layer. - typedef typename next_layer_type::lowest_layer_type lowest_layer_type; - -#if defined(GENERATING_DOCUMENTATION) - /// The default buffer size. - static const std::size_t default_buffer_size = implementation_defined; -#else - BOOST_STATIC_CONSTANT(std::size_t, default_buffer_size = 1024); -#endif - - /// Construct, passing the specified argument to initialise the next layer. - template - explicit buffered_read_stream(Arg& a) - : next_layer_(a), - storage_(default_buffer_size) - { - } - - /// Construct, passing the specified argument to initialise the next layer. - template - buffered_read_stream(Arg& a, std::size_t buffer_size) - : next_layer_(a), - storage_(buffer_size) - { - } - - /// Get a reference to the next layer. - next_layer_type& next_layer() - { - return next_layer_; - } - - /// Get a reference to the lowest layer. - lowest_layer_type& lowest_layer() - { - return next_layer_.lowest_layer(); - } - - /// (Deprecated: use get_io_service().) Get the io_service associated with - /// the object. - asio::io_service& io_service() - { - return next_layer_.get_io_service(); - } - - /// Get the io_service associated with the object. - asio::io_service& get_io_service() - { - return next_layer_.get_io_service(); - } - - /// Close the stream. - void close() - { - next_layer_.close(); - } - - /// Close the stream. - asio::error_code close(asio::error_code& ec) - { - return next_layer_.close(ec); - } - - /// Write the given data to the stream. Returns the number of bytes written. - /// Throws an exception on failure. - template - std::size_t write_some(const ConstBufferSequence& buffers) - { - return next_layer_.write_some(buffers); - } - - /// Write the given data to the stream. Returns the number of bytes written, - /// or 0 if an error occurred. - template - std::size_t write_some(const ConstBufferSequence& buffers, - asio::error_code& ec) - { - return next_layer_.write_some(buffers, ec); - } - - /// Start an asynchronous write. The data being written must be valid for the - /// lifetime of the asynchronous operation. - template - void async_write_some(const ConstBufferSequence& buffers, - WriteHandler handler) - { - next_layer_.async_write_some(buffers, handler); - } - - /// Fill the buffer with some data. Returns the number of bytes placed in the - /// buffer as a result of the operation. Throws an exception on failure. - std::size_t fill() - { - detail::buffer_resize_guard - resize_guard(storage_); - std::size_t previous_size = storage_.size(); - storage_.resize(storage_.capacity()); - storage_.resize(previous_size + next_layer_.read_some(buffer( - storage_.data() + previous_size, - storage_.size() - previous_size))); - resize_guard.commit(); - return storage_.size() - previous_size; - } - - /// Fill the buffer with some data. Returns the number of bytes placed in the - /// buffer as a result of the operation, or 0 if an error occurred. - std::size_t fill(asio::error_code& ec) - { - detail::buffer_resize_guard - resize_guard(storage_); - std::size_t previous_size = storage_.size(); - storage_.resize(storage_.capacity()); - storage_.resize(previous_size + next_layer_.read_some(buffer( - storage_.data() + previous_size, - storage_.size() - previous_size), - ec)); - resize_guard.commit(); - return storage_.size() - previous_size; - } - - template - class fill_handler - { - public: - fill_handler(asio::io_service& io_service, - detail::buffered_stream_storage& storage, - std::size_t previous_size, ReadHandler handler) - : io_service_(io_service), - storage_(storage), - previous_size_(previous_size), - handler_(handler) - { - } - - void operator()(const asio::error_code& ec, - std::size_t bytes_transferred) - { - storage_.resize(previous_size_ + bytes_transferred); - io_service_.dispatch(detail::bind_handler( - handler_, ec, bytes_transferred)); - } - - private: - asio::io_service& io_service_; - detail::buffered_stream_storage& storage_; - std::size_t previous_size_; - ReadHandler handler_; - }; - - /// Start an asynchronous fill. - template - void async_fill(ReadHandler handler) - { - std::size_t previous_size = storage_.size(); - storage_.resize(storage_.capacity()); - next_layer_.async_read_some( - buffer( - storage_.data() + previous_size, - storage_.size() - previous_size), - fill_handler(get_io_service(), - storage_, previous_size, handler)); - } - - /// Read some data from the stream. Returns the number of bytes read. Throws - /// an exception on failure. - template - std::size_t read_some(const MutableBufferSequence& buffers) - { - if (storage_.empty()) - fill(); - return copy(buffers); - } - - /// Read some data from the stream. Returns the number of bytes read or 0 if - /// an error occurred. - template - std::size_t read_some(const MutableBufferSequence& buffers, - asio::error_code& ec) - { - ec = asio::error_code(); - if (storage_.empty() && !fill(ec)) - return 0; - return copy(buffers); - } - - template - class read_some_handler - { - public: - read_some_handler(asio::io_service& io_service, - detail::buffered_stream_storage& storage, - const MutableBufferSequence& buffers, ReadHandler handler) - : io_service_(io_service), - storage_(storage), - buffers_(buffers), - handler_(handler) - { - } - - void operator()(const asio::error_code& ec, std::size_t) - { - if (ec || storage_.empty()) - { - std::size_t length = 0; - io_service_.dispatch(detail::bind_handler(handler_, ec, length)); - } - else - { - using namespace std; // For memcpy. - - std::size_t bytes_avail = storage_.size(); - std::size_t bytes_copied = 0; - - typename MutableBufferSequence::const_iterator iter = buffers_.begin(); - typename MutableBufferSequence::const_iterator end = buffers_.end(); - for (; iter != end && bytes_avail > 0; ++iter) - { - std::size_t max_length = buffer_size(*iter); - std::size_t length = (max_length < bytes_avail) - ? max_length : bytes_avail; - memcpy(buffer_cast(*iter), - storage_.data() + bytes_copied, length); - bytes_copied += length; - bytes_avail -= length; - } - - storage_.consume(bytes_copied); - io_service_.dispatch(detail::bind_handler(handler_, ec, bytes_copied)); - } - } - - private: - asio::io_service& io_service_; - detail::buffered_stream_storage& storage_; - MutableBufferSequence buffers_; - ReadHandler handler_; - }; - - /// Start an asynchronous read. The buffer into which the data will be read - /// must be valid for the lifetime of the asynchronous operation. - template - void async_read_some(const MutableBufferSequence& buffers, - ReadHandler handler) - { - if (storage_.empty()) - { - async_fill(read_some_handler( - get_io_service(), storage_, buffers, handler)); - } - else - { - std::size_t length = copy(buffers); - get_io_service().post(detail::bind_handler( - handler, asio::error_code(), length)); - } - } - - /// Peek at the incoming data on the stream. Returns the number of bytes read. - /// Throws an exception on failure. - template - std::size_t peek(const MutableBufferSequence& buffers) - { - if (storage_.empty()) - fill(); - return peek_copy(buffers); - } - - /// Peek at the incoming data on the stream. Returns the number of bytes read, - /// or 0 if an error occurred. - template - std::size_t peek(const MutableBufferSequence& buffers, - asio::error_code& ec) - { - ec = asio::error_code(); - if (storage_.empty() && !fill(ec)) - return 0; - return peek_copy(buffers); - } - - /// Determine the amount of data that may be read without blocking. - std::size_t in_avail() - { - return storage_.size(); - } - - /// Determine the amount of data that may be read without blocking. - std::size_t in_avail(asio::error_code& ec) - { - ec = asio::error_code(); - return storage_.size(); - } - -private: - /// Copy data out of the internal buffer to the specified target buffer. - /// Returns the number of bytes copied. - template - std::size_t copy(const MutableBufferSequence& buffers) - { - using namespace std; // For memcpy. - - std::size_t bytes_avail = storage_.size(); - std::size_t bytes_copied = 0; - - typename MutableBufferSequence::const_iterator iter = buffers.begin(); - typename MutableBufferSequence::const_iterator end = buffers.end(); - for (; iter != end && bytes_avail > 0; ++iter) - { - std::size_t max_length = buffer_size(*iter); - std::size_t length = (max_length < bytes_avail) - ? max_length : bytes_avail; - memcpy(buffer_cast(*iter), storage_.data() + bytes_copied, length); - bytes_copied += length; - bytes_avail -= length; - } - - storage_.consume(bytes_copied); - return bytes_copied; - } - - /// Copy data from the internal buffer to the specified target buffer, without - /// removing the data from the internal buffer. Returns the number of bytes - /// copied. - template - std::size_t peek_copy(const MutableBufferSequence& buffers) - { - using namespace std; // For memcpy. - - std::size_t bytes_avail = storage_.size(); - std::size_t bytes_copied = 0; - - typename MutableBufferSequence::const_iterator iter = buffers.begin(); - typename MutableBufferSequence::const_iterator end = buffers.end(); - for (; iter != end && bytes_avail > 0; ++iter) - { - std::size_t max_length = buffer_size(*iter); - std::size_t length = (max_length < bytes_avail) - ? max_length : bytes_avail; - memcpy(buffer_cast(*iter), storage_.data() + bytes_copied, length); - bytes_copied += length; - bytes_avail -= length; - } - - return bytes_copied; - } - - /// The next layer. - Stream next_layer_; - - // The data in the buffer. - detail::buffered_stream_storage storage_; -}; - -} // namespace asio - -#include "asio/detail/pop_options.hpp" - -#endif // ASIO_BUFFERED_READ_STREAM_HPP diff --git a/libtorrent/include/asio/buffered_read_stream_fwd.hpp b/libtorrent/include/asio/buffered_read_stream_fwd.hpp deleted file mode 100644 index 2f646a601..000000000 --- a/libtorrent/include/asio/buffered_read_stream_fwd.hpp +++ /dev/null @@ -1,29 +0,0 @@ -// -// buffered_read_stream_fwd.hpp -// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -// -// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -#ifndef ASIO_BUFFERED_READ_STREAM_FWD_HPP -#define ASIO_BUFFERED_READ_STREAM_FWD_HPP - -#if defined(_MSC_VER) && (_MSC_VER >= 1200) -# pragma once -#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) - -#include "asio/detail/push_options.hpp" - -namespace asio { - -template -class buffered_read_stream; - -} // namespace asio - -#include "asio/detail/pop_options.hpp" - -#endif // ASIO_BUFFERED_READ_STREAM_FWD_HPP diff --git a/libtorrent/include/asio/buffered_stream.hpp b/libtorrent/include/asio/buffered_stream.hpp deleted file mode 100644 index a02dc88c1..000000000 --- a/libtorrent/include/asio/buffered_stream.hpp +++ /dev/null @@ -1,250 +0,0 @@ -// -// buffered_stream.hpp -// ~~~~~~~~~~~~~~~~~~~ -// -// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -#ifndef ASIO_BUFFERED_STREAM_HPP -#define ASIO_BUFFERED_STREAM_HPP - -#if defined(_MSC_VER) && (_MSC_VER >= 1200) -# pragma once -#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) - -#include "asio/detail/push_options.hpp" - -#include "asio/detail/push_options.hpp" -#include -#include -#include "asio/detail/pop_options.hpp" - -#include "asio/buffered_read_stream.hpp" -#include "asio/buffered_write_stream.hpp" -#include "asio/buffered_stream_fwd.hpp" -#include "asio/error.hpp" -#include "asio/io_service.hpp" -#include "asio/detail/noncopyable.hpp" - -namespace asio { - -/// Adds buffering to the read- and write-related operations of a stream. -/** - * The buffered_stream class template can be used to add buffering to the - * synchronous and asynchronous read and write operations of a stream. - * - * @par Thread Safety - * @e Distinct @e objects: Safe.@n - * @e Shared @e objects: Unsafe. - * - * @par Concepts: - * AsyncReadStream, AsyncWriteStream, Stream, SyncReadStream, SyncWriteStream. - */ -template -class buffered_stream - : private noncopyable -{ -public: - /// The type of the next layer. - typedef typename boost::remove_reference::type next_layer_type; - - /// The type of the lowest layer. - typedef typename next_layer_type::lowest_layer_type lowest_layer_type; - - /// Construct, passing the specified argument to initialise the next layer. - template - explicit buffered_stream(Arg& a) - : inner_stream_impl_(a), - stream_impl_(inner_stream_impl_) - { - } - - /// Construct, passing the specified argument to initialise the next layer. - template - explicit buffered_stream(Arg& a, std::size_t read_buffer_size, - std::size_t write_buffer_size) - : inner_stream_impl_(a, write_buffer_size), - stream_impl_(inner_stream_impl_, read_buffer_size) - { - } - - /// Get a reference to the next layer. - next_layer_type& next_layer() - { - return stream_impl_.next_layer().next_layer(); - } - - /// Get a reference to the lowest layer. - lowest_layer_type& lowest_layer() - { - return stream_impl_.lowest_layer(); - } - - /// (Deprecated: use get_io_service().) Get the io_service associated with - /// the object. - asio::io_service& io_service() - { - return stream_impl_.get_io_service(); - } - - /// Get the io_service associated with the object. - asio::io_service& get_io_service() - { - return stream_impl_.get_io_service(); - } - - /// Close the stream. - void close() - { - stream_impl_.close(); - } - - /// Close the stream. - asio::error_code close(asio::error_code& ec) - { - return stream_impl_.close(ec); - } - - /// Flush all data from the buffer to the next layer. Returns the number of - /// bytes written to the next layer on the last write operation. Throws an - /// exception on failure. - std::size_t flush() - { - return stream_impl_.next_layer().flush(); - } - - /// Flush all data from the buffer to the next layer. Returns the number of - /// bytes written to the next layer on the last write operation, or 0 if an - /// error occurred. - std::size_t flush(asio::error_code& ec) - { - return stream_impl_.next_layer().flush(ec); - } - - /// Start an asynchronous flush. - template - void async_flush(WriteHandler handler) - { - return stream_impl_.next_layer().async_flush(handler); - } - - /// Write the given data to the stream. Returns the number of bytes written. - /// Throws an exception on failure. - template - std::size_t write_some(const ConstBufferSequence& buffers) - { - return stream_impl_.write_some(buffers); - } - - /// Write the given data to the stream. Returns the number of bytes written, - /// or 0 if an error occurred. - template - std::size_t write_some(const ConstBufferSequence& buffers, - asio::error_code& ec) - { - return stream_impl_.write_some(buffers, ec); - } - - /// Start an asynchronous write. The data being written must be valid for the - /// lifetime of the asynchronous operation. - template - void async_write_some(const ConstBufferSequence& buffers, - WriteHandler handler) - { - stream_impl_.async_write_some(buffers, handler); - } - - /// Fill the buffer with some data. Returns the number of bytes placed in the - /// buffer as a result of the operation. Throws an exception on failure. - std::size_t fill() - { - return stream_impl_.fill(); - } - - /// Fill the buffer with some data. Returns the number of bytes placed in the - /// buffer as a result of the operation, or 0 if an error occurred. - std::size_t fill(asio::error_code& ec) - { - return stream_impl_.fill(ec); - } - - /// Start an asynchronous fill. - template - void async_fill(ReadHandler handler) - { - stream_impl_.async_fill(handler); - } - - /// Read some data from the stream. Returns the number of bytes read. Throws - /// an exception on failure. - template - std::size_t read_some(const MutableBufferSequence& buffers) - { - return stream_impl_.read_some(buffers); - } - - /// Read some data from the stream. Returns the number of bytes read or 0 if - /// an error occurred. - template - std::size_t read_some(const MutableBufferSequence& buffers, - asio::error_code& ec) - { - return stream_impl_.read_some(buffers, ec); - } - - /// Start an asynchronous read. The buffer into which the data will be read - /// must be valid for the lifetime of the asynchronous operation. - template - void async_read_some(const MutableBufferSequence& buffers, - ReadHandler handler) - { - stream_impl_.async_read_some(buffers, handler); - } - - /// Peek at the incoming data on the stream. Returns the number of bytes read. - /// Throws an exception on failure. - template - std::size_t peek(const MutableBufferSequence& buffers) - { - return stream_impl_.peek(buffers); - } - - /// Peek at the incoming data on the stream. Returns the number of bytes read, - /// or 0 if an error occurred. - template - std::size_t peek(const MutableBufferSequence& buffers, - asio::error_code& ec) - { - return stream_impl_.peek(buffers, ec); - } - - /// Determine the amount of data that may be read without blocking. - std::size_t in_avail() - { - return stream_impl_.in_avail(); - } - - /// Determine the amount of data that may be read without blocking. - std::size_t in_avail(asio::error_code& ec) - { - return stream_impl_.in_avail(ec); - } - -private: - // The buffered write stream. - typedef buffered_write_stream write_stream_type; - write_stream_type inner_stream_impl_; - - // The buffered read stream. - typedef buffered_read_stream read_stream_type; - read_stream_type stream_impl_; -}; - -} // namespace asio - -#include "asio/detail/pop_options.hpp" - -#endif // ASIO_BUFFERED_STREAM_HPP diff --git a/libtorrent/include/asio/buffered_stream_fwd.hpp b/libtorrent/include/asio/buffered_stream_fwd.hpp deleted file mode 100644 index 987e11374..000000000 --- a/libtorrent/include/asio/buffered_stream_fwd.hpp +++ /dev/null @@ -1,29 +0,0 @@ -// -// buffered_stream_fwd.hpp -// ~~~~~~~~~~~~~~~~~~~~~~~ -// -// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -#ifndef ASIO_BUFFERED_STREAM_FWD_HPP -#define ASIO_BUFFERED_STREAM_FWD_HPP - -#if defined(_MSC_VER) && (_MSC_VER >= 1200) -# pragma once -#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) - -#include "asio/detail/push_options.hpp" - -namespace asio { - -template -class buffered_stream; - -} // namespace asio - -#include "asio/detail/pop_options.hpp" - -#endif // ASIO_BUFFERED_STREAM_FWD_HPP diff --git a/libtorrent/include/asio/buffered_write_stream.hpp b/libtorrent/include/asio/buffered_write_stream.hpp deleted file mode 100644 index 0ebd3454e..000000000 --- a/libtorrent/include/asio/buffered_write_stream.hpp +++ /dev/null @@ -1,368 +0,0 @@ -// -// buffered_write_stream.hpp -// ~~~~~~~~~~~~~~~~~~~~~~~~~ -// -// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -#ifndef ASIO_BUFFERED_WRITE_STREAM_HPP -#define ASIO_BUFFERED_WRITE_STREAM_HPP - -#if defined(_MSC_VER) && (_MSC_VER >= 1200) -# pragma once -#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) - -#include "asio/detail/push_options.hpp" - -#include "asio/detail/push_options.hpp" -#include -#include -#include -#include -#include "asio/detail/pop_options.hpp" - -#include "asio/buffered_write_stream_fwd.hpp" -#include "asio/buffer.hpp" -#include "asio/completion_condition.hpp" -#include "asio/error.hpp" -#include "asio/io_service.hpp" -#include "asio/write.hpp" -#include "asio/detail/bind_handler.hpp" -#include "asio/detail/buffered_stream_storage.hpp" -#include "asio/detail/noncopyable.hpp" - -namespace asio { - -/// Adds buffering to the write-related operations of a stream. -/** - * The buffered_write_stream class template can be used to add buffering to the - * synchronous and asynchronous write operations of a stream. - * - * @par Thread Safety - * @e Distinct @e objects: Safe.@n - * @e Shared @e objects: Unsafe. - * - * @par Concepts: - * AsyncReadStream, AsyncWriteStream, Stream, SyncReadStream, SyncWriteStream. - */ -template -class buffered_write_stream - : private noncopyable -{ -public: - /// The type of the next layer. - typedef typename boost::remove_reference::type next_layer_type; - - /// The type of the lowest layer. - typedef typename next_layer_type::lowest_layer_type lowest_layer_type; - -#if defined(GENERATING_DOCUMENTATION) - /// The default buffer size. - static const std::size_t default_buffer_size = implementation_defined; -#else - BOOST_STATIC_CONSTANT(std::size_t, default_buffer_size = 1024); -#endif - - /// Construct, passing the specified argument to initialise the next layer. - template - explicit buffered_write_stream(Arg& a) - : next_layer_(a), - storage_(default_buffer_size) - { - } - - /// Construct, passing the specified argument to initialise the next layer. - template - buffered_write_stream(Arg& a, std::size_t buffer_size) - : next_layer_(a), - storage_(buffer_size) - { - } - - /// Get a reference to the next layer. - next_layer_type& next_layer() - { - return next_layer_; - } - - /// Get a reference to the lowest layer. - lowest_layer_type& lowest_layer() - { - return next_layer_.lowest_layer(); - } - - /// (Deprecated: use get_io_service().) Get the io_service associated with - /// the object. - asio::io_service& io_service() - { - return next_layer_.get_io_service(); - } - - /// Get the io_service associated with the object. - asio::io_service& get_io_service() - { - return next_layer_.get_io_service(); - } - - /// Close the stream. - void close() - { - next_layer_.close(); - } - - /// Close the stream. - asio::error_code close(asio::error_code& ec) - { - return next_layer_.close(ec); - } - - /// Flush all data from the buffer to the next layer. Returns the number of - /// bytes written to the next layer on the last write operation. Throws an - /// exception on failure. - std::size_t flush() - { - std::size_t bytes_written = write(next_layer_, - buffer(storage_.data(), storage_.size())); - storage_.consume(bytes_written); - return bytes_written; - } - - /// Flush all data from the buffer to the next layer. Returns the number of - /// bytes written to the next layer on the last write operation, or 0 if an - /// error occurred. - std::size_t flush(asio::error_code& ec) - { - std::size_t bytes_written = write(next_layer_, - buffer(storage_.data(), storage_.size()), - transfer_all(), ec); - storage_.consume(bytes_written); - return bytes_written; - } - - template - class flush_handler - { - public: - flush_handler(asio::io_service& io_service, - detail::buffered_stream_storage& storage, WriteHandler handler) - : io_service_(io_service), - storage_(storage), - handler_(handler) - { - } - - void operator()(const asio::error_code& ec, - std::size_t bytes_written) - { - storage_.consume(bytes_written); - io_service_.dispatch(detail::bind_handler(handler_, ec, bytes_written)); - } - - private: - asio::io_service& io_service_; - detail::buffered_stream_storage& storage_; - WriteHandler handler_; - }; - - /// Start an asynchronous flush. - template - void async_flush(WriteHandler handler) - { - async_write(next_layer_, buffer(storage_.data(), storage_.size()), - flush_handler(get_io_service(), storage_, handler)); - } - - /// Write the given data to the stream. Returns the number of bytes written. - /// Throws an exception on failure. - template - std::size_t write_some(const ConstBufferSequence& buffers) - { - if (storage_.size() == storage_.capacity()) - flush(); - return copy(buffers); - } - - /// Write the given data to the stream. Returns the number of bytes written, - /// or 0 if an error occurred and the error handler did not throw. - template - std::size_t write_some(const ConstBufferSequence& buffers, - asio::error_code& ec) - { - ec = asio::error_code(); - if (storage_.size() == storage_.capacity() && !flush(ec)) - return 0; - return copy(buffers); - } - - template - class write_some_handler - { - public: - write_some_handler(asio::io_service& io_service, - detail::buffered_stream_storage& storage, - const ConstBufferSequence& buffers, WriteHandler handler) - : io_service_(io_service), - storage_(storage), - buffers_(buffers), - handler_(handler) - { - } - - void operator()(const asio::error_code& ec, std::size_t) - { - if (ec) - { - std::size_t length = 0; - io_service_.dispatch(detail::bind_handler(handler_, ec, length)); - } - else - { - using namespace std; // For memcpy. - - std::size_t orig_size = storage_.size(); - std::size_t space_avail = storage_.capacity() - orig_size; - std::size_t bytes_copied = 0; - - typename ConstBufferSequence::const_iterator iter = buffers_.begin(); - typename ConstBufferSequence::const_iterator end = buffers_.end(); - for (; iter != end && space_avail > 0; ++iter) - { - std::size_t bytes_avail = buffer_size(*iter); - std::size_t length = (bytes_avail < space_avail) - ? bytes_avail : space_avail; - storage_.resize(orig_size + bytes_copied + length); - memcpy(storage_.data() + orig_size + bytes_copied, - buffer_cast(*iter), length); - bytes_copied += length; - space_avail -= length; - } - - io_service_.dispatch(detail::bind_handler(handler_, ec, bytes_copied)); - } - } - - private: - asio::io_service& io_service_; - detail::buffered_stream_storage& storage_; - ConstBufferSequence buffers_; - WriteHandler handler_; - }; - - /// Start an asynchronous write. The data being written must be valid for the - /// lifetime of the asynchronous operation. - template - void async_write_some(const ConstBufferSequence& buffers, - WriteHandler handler) - { - if (storage_.size() == storage_.capacity()) - { - async_flush(write_some_handler( - get_io_service(), storage_, buffers, handler)); - } - else - { - std::size_t bytes_copied = copy(buffers); - get_io_service().post(detail::bind_handler( - handler, asio::error_code(), bytes_copied)); - } - } - - /// Read some data from the stream. Returns the number of bytes read. Throws - /// an exception on failure. - template - std::size_t read_some(const MutableBufferSequence& buffers) - { - return next_layer_.read_some(buffers); - } - - /// Read some data from the stream. Returns the number of bytes read or 0 if - /// an error occurred. - template - std::size_t read_some(const MutableBufferSequence& buffers, - asio::error_code& ec) - { - return next_layer_.read_some(buffers, ec); - } - - /// Start an asynchronous read. The buffer into which the data will be read - /// must be valid for the lifetime of the asynchronous operation. - template - void async_read_some(const MutableBufferSequence& buffers, - ReadHandler handler) - { - next_layer_.async_read_some(buffers, handler); - } - - /// Peek at the incoming data on the stream. Returns the number of bytes read. - /// Throws an exception on failure. - template - std::size_t peek(const MutableBufferSequence& buffers) - { - return next_layer_.peek(buffers); - } - - /// Peek at the incoming data on the stream. Returns the number of bytes read, - /// or 0 if an error occurred. - template - std::size_t peek(const MutableBufferSequence& buffers, - asio::error_code& ec) - { - return next_layer_.peek(buffers, ec); - } - - /// Determine the amount of data that may be read without blocking. - std::size_t in_avail() - { - return next_layer_.in_avail(); - } - - /// Determine the amount of data that may be read without blocking. - std::size_t in_avail(asio::error_code& ec) - { - return next_layer_.in_avail(ec); - } - -private: - /// Copy data into the internal buffer from the specified source buffer. - /// Returns the number of bytes copied. - template - std::size_t copy(const ConstBufferSequence& buffers) - { - using namespace std; // For memcpy. - - std::size_t orig_size = storage_.size(); - std::size_t space_avail = storage_.capacity() - orig_size; - std::size_t bytes_copied = 0; - - typename ConstBufferSequence::const_iterator iter = buffers.begin(); - typename ConstBufferSequence::const_iterator end = buffers.end(); - for (; iter != end && space_avail > 0; ++iter) - { - std::size_t bytes_avail = buffer_size(*iter); - std::size_t length = (bytes_avail < space_avail) - ? bytes_avail : space_avail; - storage_.resize(orig_size + bytes_copied + length); - memcpy(storage_.data() + orig_size + bytes_copied, - buffer_cast(*iter), length); - bytes_copied += length; - space_avail -= length; - } - - return bytes_copied; - } - - /// The next layer. - Stream next_layer_; - - // The data in the buffer. - detail::buffered_stream_storage storage_; -}; - -} // namespace asio - -#include "asio/detail/pop_options.hpp" - -#endif // ASIO_BUFFERED_WRITE_STREAM_HPP diff --git a/libtorrent/include/asio/buffered_write_stream_fwd.hpp b/libtorrent/include/asio/buffered_write_stream_fwd.hpp deleted file mode 100644 index 4e33c8a3d..000000000 --- a/libtorrent/include/asio/buffered_write_stream_fwd.hpp +++ /dev/null @@ -1,29 +0,0 @@ -// -// buffered_write_stream_fwd.hpp -// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -// -// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -#ifndef ASIO_BUFFERED_WRITE_STREAM_FWD_HPP -#define ASIO_BUFFERED_WRITE_STREAM_FWD_HPP - -#if defined(_MSC_VER) && (_MSC_VER >= 1200) -# pragma once -#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) - -#include "asio/detail/push_options.hpp" - -namespace asio { - -template -class buffered_write_stream; - -} // namespace asio - -#include "asio/detail/pop_options.hpp" - -#endif // ASIO_BUFFERED_WRITE_STREAM_FWD_HPP diff --git a/libtorrent/include/asio/buffers_iterator.hpp b/libtorrent/include/asio/buffers_iterator.hpp deleted file mode 100644 index cc13bb5e2..000000000 --- a/libtorrent/include/asio/buffers_iterator.hpp +++ /dev/null @@ -1,318 +0,0 @@ -// -// buffers_iterator.hpp -// ~~~~~~~~~~~~~~~~~~~~ -// -// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -#ifndef ASIO_BUFFERS_ITERATOR_HPP -#define ASIO_BUFFERS_ITERATOR_HPP - -#if defined(_MSC_VER) && (_MSC_VER >= 1200) -# pragma once -#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) - -#include "asio/detail/push_options.hpp" - -#include "asio/detail/push_options.hpp" -#include -#include -#include -#include -#include -#include -#include "asio/detail/pop_options.hpp" - -#include "asio/buffer.hpp" - -namespace asio { - -namespace detail -{ - template - struct buffers_iterator_types_helper; - - template <> - struct buffers_iterator_types_helper - { - typedef const_buffer buffer_type; - template - struct byte_type - { - typedef typename boost::add_const::type type; - }; - }; - - template <> - struct buffers_iterator_types_helper - { - typedef mutable_buffer buffer_type; - template - struct byte_type - { - typedef ByteType type; - }; - }; - - template - struct buffers_iterator_types - { - enum - { - is_mutable = boost::is_convertible< - typename BufferSequence::value_type, mutable_buffer>::value - }; - typedef buffers_iterator_types_helper helper; - typedef typename helper::buffer_type buffer_type; - typedef typename helper::template byte_type::type byte_type; - }; -} - -/// A random access iterator over the bytes in a buffer sequence. -template -class buffers_iterator - : public boost::iterator_facade< - buffers_iterator, - typename detail::buffers_iterator_types< - BufferSequence, ByteType>::byte_type, - boost::random_access_traversal_tag> -{ -private: - typedef typename detail::buffers_iterator_types< - BufferSequence, ByteType>::buffer_type buffer_type; - typedef typename detail::buffers_iterator_types< - BufferSequence, ByteType>::byte_type byte_type; - -public: - /// Default constructor. Creates an iterator in an undefined state. - buffers_iterator() - : current_buffer_(), - current_buffer_position_(0), - begin_(), - current_(), - end_(), - position_(0) - { - } - - /// Construct an iterator representing the beginning of the buffers' data. - static buffers_iterator begin(const BufferSequence& buffers) - { - buffers_iterator new_iter; - new_iter.begin_ = buffers.begin(); - new_iter.current_ = buffers.begin(); - new_iter.end_ = buffers.end(); - while (new_iter.current_ != new_iter.end_) - { - new_iter.current_buffer_ = *new_iter.current_; - if (asio::buffer_size(new_iter.current_buffer_) > 0) - break; - ++new_iter.current_; - } - return new_iter; - } - - /// Construct an iterator representing the end of the buffers' data. - static buffers_iterator end(const BufferSequence& buffers) - { - buffers_iterator new_iter; - new_iter.begin_ = buffers.begin(); - new_iter.current_ = buffers.begin(); - new_iter.end_ = buffers.end(); - while (new_iter.current_ != new_iter.end_) - { - buffer_type buffer = *new_iter.current_; - new_iter.position_ += asio::buffer_size(buffer); - ++new_iter.current_; - } - return new_iter; - } - -private: - friend class boost::iterator_core_access; - - // Dereference the iterator. - byte_type& dereference() const - { - return buffer_cast(current_buffer_)[current_buffer_position_]; - } - - // Compare two iterators for equality. - bool equal(const buffers_iterator& other) const - { - return position_ == other.position_; - } - - // Increment the iterator. - void increment() - { - BOOST_ASSERT(current_ != end_ && "iterator out of bounds"); - ++position_; - - // Check if the increment can be satisfied by the current buffer. - ++current_buffer_position_; - if (current_buffer_position_ != asio::buffer_size(current_buffer_)) - return; - - // Find the next non-empty buffer. - ++current_; - current_buffer_position_ = 0; - while (current_ != end_) - { - current_buffer_ = *current_; - if (asio::buffer_size(current_buffer_) > 0) - return; - ++current_; - } - } - - // Decrement the iterator. - void decrement() - { - BOOST_ASSERT(position_ > 0 && "iterator out of bounds"); - --position_; - - // Check if the decrement can be satisfied by the current buffer. - if (current_buffer_position_ != 0) - { - --current_buffer_position_; - return; - } - - // Find the previous non-empty buffer. - typename BufferSequence::const_iterator iter = current_; - while (iter != begin_) - { - --iter; - buffer_type buffer = *iter; - std::size_t buffer_size = asio::buffer_size(buffer); - if (buffer_size > 0) - { - current_ = iter; - current_buffer_ = buffer; - current_buffer_position_ = buffer_size - 1; - return; - } - } - } - - // Advance the iterator by the specified distance. - void advance(std::ptrdiff_t n) - { - if (n > 0) - { - BOOST_ASSERT(current_ != end_ && "iterator out of bounds"); - for (;;) - { - std::ptrdiff_t current_buffer_balance - = asio::buffer_size(current_buffer_) - - current_buffer_position_; - - // Check if the advance can be satisfied by the current buffer. - if (current_buffer_balance > n) - { - position_ += n; - current_buffer_position_ += n; - return; - } - - // Update position. - n -= current_buffer_balance; - position_ += current_buffer_balance; - - // Move to next buffer. If it is empty then it will be skipped on the - // next iteration of this loop. - if (++current_ == end_) - { - BOOST_ASSERT(n == 0 && "iterator out of bounds"); - current_buffer_ = buffer_type(); - current_buffer_position_ = 0; - return; - } - current_buffer_ = *current_; - current_buffer_position_ = 0; - } - } - else if (n < 0) - { - std::size_t abs_n = -n; - BOOST_ASSERT(position_ >= abs_n && "iterator out of bounds"); - for (;;) - { - // Check if the advance can be satisfied by the current buffer. - if (current_buffer_position_ >= abs_n) - { - position_ -= abs_n; - current_buffer_position_ -= abs_n; - return; - } - - // Update position. - abs_n -= current_buffer_position_; - position_ -= current_buffer_position_; - - // Check if we've reached the beginning of the buffers. - if (current_ == begin_) - { - BOOST_ASSERT(abs_n == 0 && "iterator out of bounds"); - current_buffer_position_ = 0; - return; - } - - // Find the previous non-empty buffer. - typename BufferSequence::const_iterator iter = current_; - while (iter != begin_) - { - --iter; - buffer_type buffer = *iter; - std::size_t buffer_size = asio::buffer_size(buffer); - if (buffer_size > 0) - { - current_ = iter; - current_buffer_ = buffer; - current_buffer_position_ = buffer_size; - break; - } - } - } - } - } - - // Determine the distance between two iterators. - std::ptrdiff_t distance_to(const buffers_iterator& other) const - { - return other.position_ - position_; - } - - buffer_type current_buffer_; - std::size_t current_buffer_position_; - typename BufferSequence::const_iterator begin_; - typename BufferSequence::const_iterator current_; - typename BufferSequence::const_iterator end_; - std::size_t position_; -}; - -/// Construct an iterator representing the beginning of the buffers' data. -template -inline buffers_iterator buffers_begin( - const BufferSequence& buffers) -{ - return buffers_iterator::begin(buffers); -} - -/// Construct an iterator representing the end of the buffers' data. -template -inline buffers_iterator buffers_end( - const BufferSequence& buffers) -{ - return buffers_iterator::end(buffers); -} - -} // namespace asio - -#include "asio/detail/pop_options.hpp" - -#endif // ASIO_BUFFERS_ITERATOR_HPP diff --git a/libtorrent/include/asio/completion_condition.hpp b/libtorrent/include/asio/completion_condition.hpp deleted file mode 100644 index b4d59089a..000000000 --- a/libtorrent/include/asio/completion_condition.hpp +++ /dev/null @@ -1,145 +0,0 @@ -// -// completion_condition.hpp -// ~~~~~~~~~~~~~~~~~~~~~~~~ -// -// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -#ifndef ASIO_COMPLETION_CONDITION_HPP -#define ASIO_COMPLETION_CONDITION_HPP - -#if defined(_MSC_VER) && (_MSC_VER >= 1200) -# pragma once -#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) - -#include "asio/detail/push_options.hpp" - -#include "asio/detail/push_options.hpp" -#include -#include -#include "asio/detail/pop_options.hpp" - -namespace asio { - -namespace detail { - -class transfer_all_t -{ -public: - typedef bool result_type; - - template - bool operator()(const Error& err, std::size_t) - { - return !!err; - } -}; - -class transfer_at_least_t -{ -public: - typedef bool result_type; - - explicit transfer_at_least_t(std::size_t minimum) - : minimum_(minimum) - { - } - - template - bool operator()(const Error& err, std::size_t bytes_transferred) - { - return !!err || bytes_transferred >= minimum_; - } - -private: - std::size_t minimum_; -}; - -} // namespace detail - -/** - * @defgroup completion_condition Completion Condition Function Objects - * - * Function objects used for determining when a read or write operation should - * complete. - */ -/*@{*/ - -/// Return a completion condition function object that indicates that a read or -/// write operation should continue until all of the data has been transferred, -/// or until an error occurs. -/** - * This function is used to create an object, of unspecified type, that meets - * CompletionCondition requirements. - * - * @par Example - * Reading until a buffer is full: - * @code - * boost::array buf; - * asio::error_code ec; - * std::size_t n = asio::read( - * sock, asio::buffer(buf), - * asio::transfer_all(), ec); - * if (ec) - * { - * // An error occurred. - * } - * else - * { - * // n == 128 - * } - * @endcode - */ -#if defined(GENERATING_DOCUMENTATION) -unspecified transfer_all(); -#else -inline detail::transfer_all_t transfer_all() -{ - return detail::transfer_all_t(); -} -#endif - -/// Return a completion condition function object that indicates that a read or -/// write operation should continue until a minimum number of bytes has been -/// transferred, or until an error occurs. -/** - * This function is used to create an object, of unspecified type, that meets - * CompletionCondition requirements. - * - * @par Example - * Reading until a buffer is full or contains at least 64 bytes: - * @code - * boost::array buf; - * asio::error_code ec; - * std::size_t n = asio::read( - * sock, asio::buffer(buf), - * asio::transfer_at_least(64), ec); - * if (ec) - * { - * // An error occurred. - * } - * else - * { - * // n >= 64 && n <= 128 - * } - * @endcode - */ -#if defined(GENERATING_DOCUMENTATION) -unspecified transfer_at_least(std::size_t minimum); -#else -inline detail::transfer_at_least_t transfer_at_least(std::size_t minimum) -{ - return detail::transfer_at_least_t(minimum); -} -#endif - -/*@}*/ - -} // namespace asio - -#include "asio/detail/pop_options.hpp" - -#endif // ASIO_COMPLETION_CONDITION_HPP diff --git a/libtorrent/include/asio/datagram_socket_service.hpp b/libtorrent/include/asio/datagram_socket_service.hpp deleted file mode 100644 index 9328f3607..000000000 --- a/libtorrent/include/asio/datagram_socket_service.hpp +++ /dev/null @@ -1,323 +0,0 @@ -// -// datagram_socket_service.hpp -// ~~~~~~~~~~~~~~~~~~~~~~~~~~~ -// -// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -#ifndef ASIO_DATAGRAM_SOCKET_SERVICE_HPP -#define ASIO_DATAGRAM_SOCKET_SERVICE_HPP - -#if defined(_MSC_VER) && (_MSC_VER >= 1200) -# pragma once -#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) - -#include "asio/detail/push_options.hpp" - -#include "asio/detail/push_options.hpp" -#include -#include -#include "asio/detail/pop_options.hpp" - -#include "asio/error.hpp" -#include "asio/io_service.hpp" -#include "asio/detail/epoll_reactor.hpp" -#include "asio/detail/kqueue_reactor.hpp" -#include "asio/detail/select_reactor.hpp" -#include "asio/detail/service_base.hpp" -#include "asio/detail/reactive_socket_service.hpp" -#include "asio/detail/win_iocp_socket_service.hpp" - -namespace asio { - -/// Default service implementation for a datagram socket. -template -class datagram_socket_service -#if defined(GENERATING_DOCUMENTATION) - : public asio::io_service::service -#else - : public asio::detail::service_base > -#endif -{ -public: -#if defined(GENERATING_DOCUMENTATION) - /// The unique service identifier. - static asio::io_service::id id; -#endif - - /// The protocol type. - typedef Protocol protocol_type; - - /// The endpoint type. - typedef typename Protocol::endpoint endpoint_type; - -private: - // The type of the platform-specific implementation. -#if defined(ASIO_HAS_IOCP) - typedef detail::win_iocp_socket_service service_impl_type; -#elif defined(ASIO_HAS_EPOLL) - typedef detail::reactive_socket_service< - Protocol, detail::epoll_reactor > service_impl_type; -#elif defined(ASIO_HAS_KQUEUE) - typedef detail::reactive_socket_service< - Protocol, detail::kqueue_reactor > service_impl_type; -#elif defined(ASIO_HAS_DEV_POLL) - typedef detail::reactive_socket_service< - Protocol, detail::dev_poll_reactor > service_impl_type; -#else - typedef detail::reactive_socket_service< - Protocol, detail::select_reactor > service_impl_type; -#endif - -public: - /// The type of a datagram socket. -#if defined(GENERATING_DOCUMENTATION) - typedef implementation_defined implementation_type; -#else - typedef typename service_impl_type::implementation_type implementation_type; -#endif - - /// The native socket type. -#if defined(GENERATING_DOCUMENTATION) - typedef implementation_defined native_type; -#else - typedef typename service_impl_type::native_type native_type; -#endif - - /// Construct a new datagram socket service for the specified io_service. - explicit datagram_socket_service(asio::io_service& io_service) - : asio::detail::service_base< - datagram_socket_service >(io_service), - service_impl_(asio::use_service(io_service)) - { - } - - /// Destroy all user-defined handler objects owned by the service. - void shutdown_service() - { - } - - /// Construct a new datagram socket implementation. - void construct(implementation_type& impl) - { - service_impl_.construct(impl); - } - - /// Destroy a datagram socket implementation. - void destroy(implementation_type& impl) - { - service_impl_.destroy(impl); - } - - // Open a new datagram socket implementation. - asio::error_code open(implementation_type& impl, - const protocol_type& protocol, asio::error_code& ec) - { - if (protocol.type() == SOCK_DGRAM) - service_impl_.open(impl, protocol, ec); - else - ec = asio::error::invalid_argument; - return ec; - } - - /// Assign an existing native socket to a datagram socket. - asio::error_code assign(implementation_type& impl, - const protocol_type& protocol, const native_type& native_socket, - asio::error_code& ec) - { - return service_impl_.assign(impl, protocol, native_socket, ec); - } - - /// Determine whether the socket is open. - bool is_open(const implementation_type& impl) const - { - return service_impl_.is_open(impl); - } - - /// Close a datagram socket implementation. - asio::error_code close(implementation_type& impl, - asio::error_code& ec) - { - return service_impl_.close(impl, ec); - } - - /// Get the native socket implementation. - native_type native(implementation_type& impl) - { - return service_impl_.native(impl); - } - - /// Cancel all asynchronous operations associated with the socket. - asio::error_code cancel(implementation_type& impl, - asio::error_code& ec) - { - return service_impl_.cancel(impl, ec); - } - - /// Determine whether the socket is at the out-of-band data mark. - bool at_mark(const implementation_type& impl, - asio::error_code& ec) const - { - return service_impl_.at_mark(impl, ec); - } - - /// Determine the number of bytes available for reading. - std::size_t available(const implementation_type& impl, - asio::error_code& ec) const - { - return service_impl_.available(impl, ec); - } - - // Bind the datagram socket to the specified local endpoint. - asio::error_code bind(implementation_type& impl, - const endpoint_type& endpoint, asio::error_code& ec) - { - return service_impl_.bind(impl, endpoint, ec); - } - - /// Connect the datagram socket to the specified endpoint. - asio::error_code connect(implementation_type& impl, - const endpoint_type& peer_endpoint, asio::error_code& ec) - { - return service_impl_.connect(impl, peer_endpoint, ec); - } - - /// Start an asynchronous connect. - template - void async_connect(implementation_type& impl, - const endpoint_type& peer_endpoint, ConnectHandler handler) - { - service_impl_.async_connect(impl, peer_endpoint, handler); - } - - /// Set a socket option. - template - asio::error_code set_option(implementation_type& impl, - const SettableSocketOption& option, asio::error_code& ec) - { - return service_impl_.set_option(impl, option, ec); - } - - /// Get a socket option. - template - asio::error_code get_option(const implementation_type& impl, - GettableSocketOption& option, asio::error_code& ec) const - { - return service_impl_.get_option(impl, option, ec); - } - - /// Perform an IO control command on the socket. - template - asio::error_code io_control(implementation_type& impl, - IoControlCommand& command, asio::error_code& ec) - { - return service_impl_.io_control(impl, command, ec); - } - - /// Get the local endpoint. - endpoint_type local_endpoint(const implementation_type& impl, - asio::error_code& ec) const - { - return service_impl_.local_endpoint(impl, ec); - } - - /// Get the remote endpoint. - endpoint_type remote_endpoint(const implementation_type& impl, - asio::error_code& ec) const - { - return service_impl_.remote_endpoint(impl, ec); - } - - /// Disable sends or receives on the socket. - asio::error_code shutdown(implementation_type& impl, - socket_base::shutdown_type what, asio::error_code& ec) - { - return service_impl_.shutdown(impl, what, ec); - } - - /// Send the given data to the peer. - template - std::size_t send(implementation_type& impl, - const ConstBufferSequence& buffers, - socket_base::message_flags flags, asio::error_code& ec) - { - return service_impl_.send(impl, buffers, flags, ec); - } - - /// Start an asynchronous send. - template - void async_send(implementation_type& impl, const ConstBufferSequence& buffers, - socket_base::message_flags flags, WriteHandler handler) - { - service_impl_.async_send(impl, buffers, flags, handler); - } - - /// Send a datagram to the specified endpoint. - template - std::size_t send_to(implementation_type& impl, - const ConstBufferSequence& buffers, const endpoint_type& destination, - socket_base::message_flags flags, asio::error_code& ec) - { - return service_impl_.send_to(impl, buffers, destination, flags, ec); - } - - /// Start an asynchronous send. - template - void async_send_to(implementation_type& impl, - const ConstBufferSequence& buffers, const endpoint_type& destination, - socket_base::message_flags flags, WriteHandler handler) - { - service_impl_.async_send_to(impl, buffers, destination, flags, handler); - } - - /// Receive some data from the peer. - template - std::size_t receive(implementation_type& impl, - const MutableBufferSequence& buffers, - socket_base::message_flags flags, asio::error_code& ec) - { - return service_impl_.receive(impl, buffers, flags, ec); - } - - /// Start an asynchronous receive. - template - void async_receive(implementation_type& impl, - const MutableBufferSequence& buffers, - socket_base::message_flags flags, ReadHandler handler) - { - service_impl_.async_receive(impl, buffers, flags, handler); - } - - /// Receive a datagram with the endpoint of the sender. - template - std::size_t receive_from(implementation_type& impl, - const MutableBufferSequence& buffers, endpoint_type& sender_endpoint, - socket_base::message_flags flags, asio::error_code& ec) - { - return service_impl_.receive_from(impl, buffers, sender_endpoint, flags, - ec); - } - - /// Start an asynchronous receive that will get the endpoint of the sender. - template - void async_receive_from(implementation_type& impl, - const MutableBufferSequence& buffers, endpoint_type& sender_endpoint, - socket_base::message_flags flags, ReadHandler handler) - { - service_impl_.async_receive_from(impl, buffers, sender_endpoint, flags, - handler); - } - -private: - // The service that provides the platform-specific implementation. - service_impl_type& service_impl_; -}; - -} // namespace asio - -#include "asio/detail/pop_options.hpp" - -#endif // ASIO_DATAGRAM_SOCKET_SERVICE_HPP diff --git a/libtorrent/include/asio/deadline_timer.hpp b/libtorrent/include/asio/deadline_timer.hpp deleted file mode 100644 index 0ea373787..000000000 --- a/libtorrent/include/asio/deadline_timer.hpp +++ /dev/null @@ -1,37 +0,0 @@ -// -// deadline_timer.hpp -// ~~~~~~~~~~~~~~~~~~ -// -// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -#ifndef ASIO_DEADLINE_TIMER_HPP -#define ASIO_DEADLINE_TIMER_HPP - -#if defined(_MSC_VER) && (_MSC_VER >= 1200) -# pragma once -#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) - -#include "asio/detail/push_options.hpp" - -#include "asio/detail/socket_types.hpp" // Must come before posix_time. - -#include "asio/detail/push_options.hpp" -#include -#include "asio/detail/pop_options.hpp" - -#include "asio/basic_deadline_timer.hpp" - -namespace asio { - -/// Typedef for the typical usage of timer. -typedef basic_deadline_timer deadline_timer; - -} // namespace asio - -#include "asio/detail/pop_options.hpp" - -#endif // ASIO_DEADLINE_TIMER_HPP diff --git a/libtorrent/include/asio/deadline_timer_service.hpp b/libtorrent/include/asio/deadline_timer_service.hpp deleted file mode 100644 index 2a79b4909..000000000 --- a/libtorrent/include/asio/deadline_timer_service.hpp +++ /dev/null @@ -1,168 +0,0 @@ -// -// deadline_timer_service.hpp -// ~~~~~~~~~~~~~~~~~~~~~~~~~~ -// -// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -#ifndef ASIO_DEADLINE_TIMER_SERVICE_HPP -#define ASIO_DEADLINE_TIMER_SERVICE_HPP - -#if defined(_MSC_VER) && (_MSC_VER >= 1200) -# pragma once -#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) - -#include "asio/detail/push_options.hpp" - -#include "asio/detail/push_options.hpp" -#include -#include -#include "asio/detail/pop_options.hpp" - -#include "asio/io_service.hpp" -#include "asio/time_traits.hpp" -#include "asio/detail/deadline_timer_service.hpp" -#include "asio/detail/epoll_reactor.hpp" -#include "asio/detail/kqueue_reactor.hpp" -#include "asio/detail/select_reactor.hpp" -#include "asio/detail/service_base.hpp" -#include "asio/detail/win_iocp_io_service.hpp" - -namespace asio { - -/// Default service implementation for a timer. -template > -class deadline_timer_service -#if defined(GENERATING_DOCUMENTATION) - : public asio::io_service::service -#else - : public asio::detail::service_base< - deadline_timer_service > -#endif -{ -public: -#if defined(GENERATING_DOCUMENTATION) - /// The unique service identifier. - static asio::io_service::id id; -#endif - - /// The time traits type. - typedef TimeTraits traits_type; - - /// The time type. - typedef typename traits_type::time_type time_type; - - /// The duration type. - typedef typename traits_type::duration_type duration_type; - -private: - // The type of the platform-specific implementation. -#if defined(ASIO_HAS_IOCP) - typedef detail::deadline_timer_service< - traits_type, detail::win_iocp_io_service> service_impl_type; -#elif defined(ASIO_HAS_EPOLL) - typedef detail::deadline_timer_service< - traits_type, detail::epoll_reactor > service_impl_type; -#elif defined(ASIO_HAS_KQUEUE) - typedef detail::deadline_timer_service< - traits_type, detail::kqueue_reactor > service_impl_type; -#elif defined(ASIO_HAS_DEV_POLL) - typedef detail::deadline_timer_service< - traits_type, detail::dev_poll_reactor > service_impl_type; -#else - typedef detail::deadline_timer_service< - traits_type, detail::select_reactor > service_impl_type; -#endif - -public: - /// The implementation type of the deadline timer. -#if defined(GENERATING_DOCUMENTATION) - typedef implementation_defined implementation_type; -#else - typedef typename service_impl_type::implementation_type implementation_type; -#endif - - /// Construct a new timer service for the specified io_service. - explicit deadline_timer_service(asio::io_service& io_service) - : asio::detail::service_base< - deadline_timer_service >(io_service), - service_impl_(asio::use_service(io_service)) - { - } - - /// Destroy all user-defined handler objects owned by the service. - void shutdown_service() - { - } - - /// Construct a new timer implementation. - void construct(implementation_type& impl) - { - service_impl_.construct(impl); - } - - /// Destroy a timer implementation. - void destroy(implementation_type& impl) - { - service_impl_.destroy(impl); - } - - /// Cancel any asynchronous wait operations associated with the timer. - std::size_t cancel(implementation_type& impl, asio::error_code& ec) - { - return service_impl_.cancel(impl, ec); - } - - /// Get the expiry time for the timer as an absolute time. - time_type expires_at(const implementation_type& impl) const - { - return service_impl_.expires_at(impl); - } - - /// Set the expiry time for the timer as an absolute time. - std::size_t expires_at(implementation_type& impl, - const time_type& expiry_time, asio::error_code& ec) - { - return service_impl_.expires_at(impl, expiry_time, ec); - } - - /// Get the expiry time for the timer relative to now. - duration_type expires_from_now(const implementation_type& impl) const - { - return service_impl_.expires_from_now(impl); - } - - /// Set the expiry time for the timer relative to now. - std::size_t expires_from_now(implementation_type& impl, - const duration_type& expiry_time, asio::error_code& ec) - { - return service_impl_.expires_from_now(impl, expiry_time, ec); - } - - // Perform a blocking wait on the timer. - void wait(implementation_type& impl, asio::error_code& ec) - { - service_impl_.wait(impl, ec); - } - - // Start an asynchronous wait on the timer. - template - void async_wait(implementation_type& impl, WaitHandler handler) - { - service_impl_.async_wait(impl, handler); - } - -private: - // The service that provides the platform-specific implementation. - service_impl_type& service_impl_; -}; - -} // namespace asio - -#include "asio/detail/pop_options.hpp" - -#endif // ASIO_DEADLINE_TIMER_SERVICE_HPP diff --git a/libtorrent/include/asio/detail/bind_handler.hpp b/libtorrent/include/asio/detail/bind_handler.hpp deleted file mode 100644 index f6200f2bf..000000000 --- a/libtorrent/include/asio/detail/bind_handler.hpp +++ /dev/null @@ -1,349 +0,0 @@ -// -// bind_handler.hpp -// ~~~~~~~~~~~~~~~~ -// -// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -#ifndef ASIO_DETAIL_BIND_HANDLER_HPP -#define ASIO_DETAIL_BIND_HANDLER_HPP - -#if defined(_MSC_VER) && (_MSC_VER >= 1200) -# pragma once -#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) - -#include "asio/detail/push_options.hpp" - -#include "asio/detail/handler_alloc_helpers.hpp" -#include "asio/detail/handler_invoke_helpers.hpp" - -namespace asio { -namespace detail { - -template -class binder1 -{ -public: - binder1(const Handler& handler, const Arg1& arg1) - : handler_(handler), - arg1_(arg1) - { - } - - void operator()() - { - handler_(arg1_); - } - - void operator()() const - { - handler_(arg1_); - } - -//private: - Handler handler_; - Arg1 arg1_; -}; - -template -inline void* asio_handler_allocate(std::size_t size, - binder1* this_handler) -{ - return asio_handler_alloc_helpers::allocate( - size, &this_handler->handler_); -} - -template -inline void asio_handler_deallocate(void* pointer, std::size_t size, - binder1* this_handler) -{ - asio_handler_alloc_helpers::deallocate( - pointer, size, &this_handler->handler_); -} - -template -inline void asio_handler_invoke(const Function& function, - binder1* this_handler) -{ - asio_handler_invoke_helpers::invoke( - function, &this_handler->handler_); -} - -template -inline binder1 bind_handler(const Handler& handler, - const Arg1& arg1) -{ - return binder1(handler, arg1); -} - -template -class binder2 -{ -public: - binder2(const Handler& handler, const Arg1& arg1, const Arg2& arg2) - : handler_(handler), - arg1_(arg1), - arg2_(arg2) - { - } - - void operator()() - { - handler_(arg1_, arg2_); - } - - void operator()() const - { - handler_(arg1_, arg2_); - } - -//private: - Handler handler_; - Arg1 arg1_; - Arg2 arg2_; -}; - -template -inline void* asio_handler_allocate(std::size_t size, - binder2* this_handler) -{ - return asio_handler_alloc_helpers::allocate( - size, &this_handler->handler_); -} - -template -inline void asio_handler_deallocate(void* pointer, std::size_t size, - binder2* this_handler) -{ - asio_handler_alloc_helpers::deallocate( - pointer, size, &this_handler->handler_); -} - -template -inline void asio_handler_invoke(const Function& function, - binder2* this_handler) -{ - asio_handler_invoke_helpers::invoke( - function, &this_handler->handler_); -} - -template -inline binder2 bind_handler(const Handler& handler, - const Arg1& arg1, const Arg2& arg2) -{ - return binder2(handler, arg1, arg2); -} - -template -class binder3 -{ -public: - binder3(const Handler& handler, const Arg1& arg1, const Arg2& arg2, - const Arg3& arg3) - : handler_(handler), - arg1_(arg1), - arg2_(arg2), - arg3_(arg3) - { - } - - void operator()() - { - handler_(arg1_, arg2_, arg3_); - } - - void operator()() const - { - handler_(arg1_, arg2_, arg3_); - } - -//private: - Handler handler_; - Arg1 arg1_; - Arg2 arg2_; - Arg3 arg3_; -}; - -template -inline void* asio_handler_allocate(std::size_t size, - binder3* this_handler) -{ - return asio_handler_alloc_helpers::allocate( - size, &this_handler->handler_); -} - -template -inline void asio_handler_deallocate(void* pointer, std::size_t size, - binder3* this_handler) -{ - asio_handler_alloc_helpers::deallocate( - pointer, size, &this_handler->handler_); -} - -template -inline void asio_handler_invoke(const Function& function, - binder3* this_handler) -{ - asio_handler_invoke_helpers::invoke( - function, &this_handler->handler_); -} - -template -inline binder3 bind_handler(const Handler& handler, - const Arg1& arg1, const Arg2& arg2, const Arg3& arg3) -{ - return binder3(handler, arg1, arg2, arg3); -} - -template -class binder4 -{ -public: - binder4(const Handler& handler, const Arg1& arg1, const Arg2& arg2, - const Arg3& arg3, const Arg4& arg4) - : handler_(handler), - arg1_(arg1), - arg2_(arg2), - arg3_(arg3), - arg4_(arg4) - { - } - - void operator()() - { - handler_(arg1_, arg2_, arg3_, arg4_); - } - - void operator()() const - { - handler_(arg1_, arg2_, arg3_, arg4_); - } - -//private: - Handler handler_; - Arg1 arg1_; - Arg2 arg2_; - Arg3 arg3_; - Arg4 arg4_; -}; - -template -inline void* asio_handler_allocate(std::size_t size, - binder4* this_handler) -{ - return asio_handler_alloc_helpers::allocate( - size, &this_handler->handler_); -} - -template -inline void asio_handler_deallocate(void* pointer, std::size_t size, - binder4* this_handler) -{ - asio_handler_alloc_helpers::deallocate( - pointer, size, &this_handler->handler_); -} - -template -inline void asio_handler_invoke(const Function& function, - binder4* this_handler) -{ - asio_handler_invoke_helpers::invoke( - function, &this_handler->handler_); -} - -template -inline binder4 bind_handler( - const Handler& handler, const Arg1& arg1, const Arg2& arg2, - const Arg3& arg3, const Arg4& arg4) -{ - return binder4(handler, arg1, arg2, arg3, - arg4); -} - -template -class binder5 -{ -public: - binder5(const Handler& handler, const Arg1& arg1, const Arg2& arg2, - const Arg3& arg3, const Arg4& arg4, const Arg5& arg5) - : handler_(handler), - arg1_(arg1), - arg2_(arg2), - arg3_(arg3), - arg4_(arg4), - arg5_(arg5) - { - } - - void operator()() - { - handler_(arg1_, arg2_, arg3_, arg4_, arg5_); - } - - void operator()() const - { - handler_(arg1_, arg2_, arg3_, arg4_, arg5_); - } - -//private: - Handler handler_; - Arg1 arg1_; - Arg2 arg2_; - Arg3 arg3_; - Arg4 arg4_; - Arg5 arg5_; -}; - -template -inline void* asio_handler_allocate(std::size_t size, - binder5* this_handler) -{ - return asio_handler_alloc_helpers::allocate( - size, &this_handler->handler_); -} - -template -inline void asio_handler_deallocate(void* pointer, std::size_t size, - binder5* this_handler) -{ - asio_handler_alloc_helpers::deallocate( - pointer, size, &this_handler->handler_); -} - -template -inline void asio_handler_invoke(const Function& function, - binder5* this_handler) -{ - asio_handler_invoke_helpers::invoke( - function, &this_handler->handler_); -} - -template -inline binder5 bind_handler( - const Handler& handler, const Arg1& arg1, const Arg2& arg2, - const Arg3& arg3, const Arg4& arg4, const Arg5& arg5) -{ - return binder5(handler, arg1, arg2, - arg3, arg4, arg5); -} - -} // namespace detail -} // namespace asio - -#include "asio/detail/pop_options.hpp" - -#endif // ASIO_DETAIL_BIND_HANDLER_HPP diff --git a/libtorrent/include/asio/detail/buffer_resize_guard.hpp b/libtorrent/include/asio/detail/buffer_resize_guard.hpp deleted file mode 100644 index c40d2b26b..000000000 --- a/libtorrent/include/asio/detail/buffer_resize_guard.hpp +++ /dev/null @@ -1,70 +0,0 @@ -// -// buffer_resize_guard.hpp -// ~~~~~~~~~~~~~~~~~~~~~~~ -// -// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -#ifndef ASIO_DETAIL_BUFFER_RESIZE_GUARD_HPP -#define ASIO_DETAIL_BUFFER_RESIZE_GUARD_HPP - -#if defined(_MSC_VER) && (_MSC_VER >= 1200) -# pragma once -#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) - -#include "asio/detail/push_options.hpp" - -#include "asio/detail/push_options.hpp" -#include -#include -#include "asio/detail/pop_options.hpp" - -namespace asio { -namespace detail { - -// Helper class to manage buffer resizing in an exception safe way. -template -class buffer_resize_guard -{ -public: - // Constructor. - buffer_resize_guard(Buffer& buffer) - : buffer_(buffer), - old_size_(buffer.size()) - { - } - - // Destructor rolls back the buffer resize unless commit was called. - ~buffer_resize_guard() - { - if (old_size_ - != std::numeric_limits::max BOOST_PREVENT_MACRO_SUBSTITUTION()) - { - buffer_.resize(old_size_); - } - } - - // Commit the resize transaction. - void commit() - { - old_size_ - = std::numeric_limits::max BOOST_PREVENT_MACRO_SUBSTITUTION(); - } - -private: - // The buffer being managed. - Buffer& buffer_; - - // The size of the buffer at the time the guard was constructed. - size_t old_size_; -}; - -} // namespace detail -} // namespace asio - -#include "asio/detail/pop_options.hpp" - -#endif // ASIO_DETAIL_BUFFER_RESIZE_GUARD_HPP diff --git a/libtorrent/include/asio/detail/buffered_stream_storage.hpp b/libtorrent/include/asio/detail/buffered_stream_storage.hpp deleted file mode 100644 index 072377ae4..000000000 --- a/libtorrent/include/asio/detail/buffered_stream_storage.hpp +++ /dev/null @@ -1,127 +0,0 @@ -// -// buffered_stream_storage.hpp -// ~~~~~~~~~~~~~~~~~~~~~~~~~~~ -// -// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -#ifndef ASIO_DETAIL_BUFFERED_STREAM_STORAGE_HPP -#define ASIO_DETAIL_BUFFERED_STREAM_STORAGE_HPP - -#if defined(_MSC_VER) && (_MSC_VER >= 1200) -# pragma once -#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) - -#include "asio/detail/push_options.hpp" - -#include "asio/detail/push_options.hpp" -#include -#include -#include -#include -#include -#include "asio/detail/pop_options.hpp" - -namespace asio { -namespace detail { - -class buffered_stream_storage -{ -public: - // The type of the bytes stored in the buffer. - typedef unsigned char byte_type; - - // The type used for offsets into the buffer. - typedef std::size_t size_type; - - // Constructor. - explicit buffered_stream_storage(std::size_t capacity) - : begin_offset_(0), - end_offset_(0), - buffer_(capacity) - { - } - - /// Clear the buffer. - void clear() - { - begin_offset_ = 0; - end_offset_ = 0; - } - - // Return a pointer to the beginning of the unread data. - byte_type* data() - { - return &buffer_[0] + begin_offset_; - } - - // Return a pointer to the beginning of the unread data. - const byte_type* data() const - { - return &buffer_[0] + begin_offset_; - } - - // Is there no unread data in the buffer. - bool empty() const - { - return begin_offset_ == end_offset_; - } - - // Return the amount of unread data the is in the buffer. - size_type size() const - { - return end_offset_ - begin_offset_; - } - - // Resize the buffer to the specified length. - void resize(size_type length) - { - assert(length <= capacity()); - if (begin_offset_ + length <= capacity()) - { - end_offset_ = begin_offset_ + length; - } - else - { - using namespace std; // For memmove. - memmove(&buffer_[0], &buffer_[0] + begin_offset_, size()); - end_offset_ = length; - begin_offset_ = 0; - } - } - - // Return the maximum size for data in the buffer. - size_type capacity() const - { - return buffer_.size(); - } - - // Consume multiple bytes from the beginning of the buffer. - void consume(size_type count) - { - assert(begin_offset_ + count <= end_offset_); - begin_offset_ += count; - if (empty()) - clear(); - } - -private: - // The offset to the beginning of the unread data. - size_type begin_offset_; - - // The offset to the end of the unread data. - size_type end_offset_; - - // The data in the buffer. - std::vector buffer_; -}; - -} // namespace detail -} // namespace asio - -#include "asio/detail/pop_options.hpp" - -#endif // ASIO_DETAIL_BUFFERED_STREAM_STORAGE_HPP diff --git a/libtorrent/include/asio/detail/call_stack.hpp b/libtorrent/include/asio/detail/call_stack.hpp deleted file mode 100644 index 738769927..000000000 --- a/libtorrent/include/asio/detail/call_stack.hpp +++ /dev/null @@ -1,90 +0,0 @@ -// -// call_stack.hpp -// ~~~~~~~~~~~~~~ -// -// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -#ifndef ASIO_DETAIL_CALL_STACK_HPP -#define ASIO_DETAIL_CALL_STACK_HPP - -#if defined(_MSC_VER) && (_MSC_VER >= 1200) -# pragma once -#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) - -#include "asio/detail/push_options.hpp" - -#include "asio/detail/noncopyable.hpp" -#include "asio/detail/tss_ptr.hpp" - -namespace asio { -namespace detail { - -// Helper class to determine whether or not the current thread is inside an -// invocation of io_service::run() for a specified io_service object. -template -class call_stack -{ -public: - // Context class automatically pushes an owner on to the stack. - class context - : private noncopyable - { - public: - // Push the owner on to the stack. - explicit context(Owner* d) - : owner_(d), - next_(call_stack::top_) - { - call_stack::top_ = this; - } - - // Pop the owner from the stack. - ~context() - { - call_stack::top_ = next_; - } - - private: - friend class call_stack; - - // The owner associated with the context. - Owner* owner_; - - // The next element in the stack. - context* next_; - }; - - friend class context; - - // Determine whether the specified owner is on the stack. - static bool contains(Owner* d) - { - context* elem = top_; - while (elem) - { - if (elem->owner_ == d) - return true; - elem = elem->next_; - } - return false; - } - -private: - // The top of the stack of calls for the current thread. - static tss_ptr top_; -}; - -template -tss_ptr::context> -call_stack::top_; - -} // namespace detail -} // namespace asio - -#include "asio/detail/pop_options.hpp" - -#endif // ASIO_DETAIL_CALL_STACK_HPP diff --git a/libtorrent/include/asio/detail/const_buffers_iterator.hpp b/libtorrent/include/asio/detail/const_buffers_iterator.hpp deleted file mode 100644 index 6ac3ac593..000000000 --- a/libtorrent/include/asio/detail/const_buffers_iterator.hpp +++ /dev/null @@ -1,151 +0,0 @@ -// -// const_buffers_iterator.hpp -// ~~~~~~~~~~~~~~~~~~~~~~~~~~ -// -// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -#ifndef ASIO_DETAIL_CONST_BUFFERS_ITERATOR_HPP -#define ASIO_DETAIL_CONST_BUFFERS_ITERATOR_HPP - -#if defined(_MSC_VER) && (_MSC_VER >= 1200) -# pragma once -#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) - -#include "asio/detail/push_options.hpp" - -#include "asio/detail/push_options.hpp" -#include -#include -#include -#include "asio/detail/pop_options.hpp" - -#include "asio/buffer.hpp" - -namespace asio { -namespace detail { - -// A proxy iterator for a sub-range in a list of buffers. -template -class const_buffers_iterator - : public boost::iterator_facade, - const char, boost::bidirectional_traversal_tag> -{ -public: - // Default constructor creates an iterator in an undefined state. - const_buffers_iterator() - { - } - - // Create an iterator for the specified position. - const_buffers_iterator(const ConstBufferSequence& buffers, - std::size_t position) - : begin_(buffers.begin()), - current_(buffers.begin()), - end_(buffers.end()), - position_(0) - { - while (current_ != end_) - { - current_buffer_ = *current_; - std::size_t buffer_size = asio::buffer_size(current_buffer_); - if (position - position_ < buffer_size) - { - current_buffer_position_ = position - position_; - position_ = position; - return; - } - position_ += buffer_size; - ++current_; - } - current_buffer_ = asio::const_buffer(); - current_buffer_position_ = 0; - } - - std::size_t position() const - { - return position_; - } - -private: - friend class boost::iterator_core_access; - - void increment() - { - if (current_ == end_) - return; - - ++position_; - - ++current_buffer_position_; - if (current_buffer_position_ != asio::buffer_size(current_buffer_)) - return; - - ++current_; - current_buffer_position_ = 0; - while (current_ != end_) - { - current_buffer_ = *current_; - if (asio::buffer_size(current_buffer_) > 0) - return; - ++current_; - } - } - - void decrement() - { - if (position_ == 0) - return; - - --position_; - - if (current_buffer_position_ != 0) - { - --current_buffer_position_; - return; - } - - typename ConstBufferSequence::const_iterator iter = current_; - while (iter != begin_) - { - --iter; - asio::const_buffer buffer = *iter; - std::size_t buffer_size = asio::buffer_size(buffer); - if (buffer_size > 0) - { - current_ = iter; - current_buffer_ = buffer; - current_buffer_position_ = buffer_size - 1; - return; - } - } - } - - bool equal(const const_buffers_iterator& other) const - { - return position_ == other.position_; - } - - const char& dereference() const - { - return asio::buffer_cast( - current_buffer_)[current_buffer_position_]; - } - - asio::const_buffer current_buffer_; - std::size_t current_buffer_position_; - typename ConstBufferSequence::const_iterator begin_; - typename ConstBufferSequence::const_iterator current_; - typename ConstBufferSequence::const_iterator end_; - std::size_t position_; -}; - -} // namespace detail -} // namespace asio - -#include "asio/detail/pop_options.hpp" - -#endif // ASIO_DETAIL_CONST_BUFFERS_ITERATOR_HPP diff --git a/libtorrent/include/asio/detail/consuming_buffers.hpp b/libtorrent/include/asio/detail/consuming_buffers.hpp deleted file mode 100644 index 8e88e361d..000000000 --- a/libtorrent/include/asio/detail/consuming_buffers.hpp +++ /dev/null @@ -1,225 +0,0 @@ -// -// consuming_buffers.hpp -// ~~~~~~~~~~~~~~~~~~~~~ -// -// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -#ifndef ASIO_DETAIL_CONSUMING_BUFFERS_HPP -#define ASIO_DETAIL_CONSUMING_BUFFERS_HPP - -#if defined(_MSC_VER) && (_MSC_VER >= 1200) -# pragma once -#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) - -#include "asio/detail/push_options.hpp" - -#include "asio/detail/push_options.hpp" -#include -#include -#include -#include -#include "asio/detail/pop_options.hpp" - -#include "asio/buffer.hpp" - -namespace asio { -namespace detail { - -// A proxy iterator for a sub-range in a list of buffers. -template -class consuming_buffers_iterator - : public boost::iterator_facade< - consuming_buffers_iterator, - const Buffer, boost::forward_traversal_tag> -{ -public: - // Default constructor creates an end iterator. - consuming_buffers_iterator() - : at_end_(true) - { - } - - // Construct with a buffer for the first entry and an iterator - // range for the remaining entries. - consuming_buffers_iterator(bool at_end, const Buffer& first, - Buffer_Iterator begin_remainder, Buffer_Iterator end_remainder) - : at_end_(at_end), - first_(buffer(first, max_size)), - begin_remainder_(begin_remainder), - end_remainder_(end_remainder), - offset_(0) - { - } - -private: - friend class boost::iterator_core_access; - - enum { max_size = 65536 }; - - void increment() - { - if (!at_end_) - { - if (begin_remainder_ == end_remainder_ - || offset_ + buffer_size(first_) >= max_size) - { - at_end_ = true; - } - else - { - offset_ += buffer_size(first_); - first_ = buffer(*begin_remainder_++, max_size - offset_); - } - } - } - - bool equal(const consuming_buffers_iterator& other) const - { - if (at_end_ && other.at_end_) - return true; - return !at_end_ && !other.at_end_ - && buffer_cast(first_) - == buffer_cast(other.first_) - && buffer_size(first_) == buffer_size(other.first_) - && begin_remainder_ == other.begin_remainder_ - && end_remainder_ == other.end_remainder_; - } - - const Buffer& dereference() const - { - return first_; - } - - bool at_end_; - Buffer first_; - Buffer_Iterator begin_remainder_; - Buffer_Iterator end_remainder_; - std::size_t offset_; -}; - -// A proxy for a sub-range in a list of buffers. -template -class consuming_buffers -{ -public: - // The type for each element in the list of buffers. - typedef Buffer value_type; - - // A forward-only iterator type that may be used to read elements. - typedef consuming_buffers_iterator - const_iterator; - - // Construct to represent the entire list of buffers. - consuming_buffers(const Buffers& buffers) - : buffers_(buffers), - at_end_(buffers_.begin() == buffers_.end()), - first_(*buffers_.begin()), - begin_remainder_(buffers_.begin()) - { - if (!at_end_) - ++begin_remainder_; - } - - // Copy constructor. - consuming_buffers(const consuming_buffers& other) - : buffers_(other.buffers_), - at_end_(other.at_end_), - first_(other.first_), - begin_remainder_(buffers_.begin()) - { - typename Buffers::const_iterator first = other.buffers_.begin(); - typename Buffers::const_iterator second = other.begin_remainder_; - std::advance(begin_remainder_, std::distance(first, second)); - } - - // Assignment operator. - consuming_buffers& operator=(const consuming_buffers& other) - { - buffers_ = other.buffers_; - at_end_ = other.at_end_; - first_ = other.first_; - begin_remainder_ = buffers_.begin(); - typename Buffers::const_iterator first = other.buffers_.begin(); - typename Buffers::const_iterator second = other.begin_remainder_; - std::advance(begin_remainder_, std::distance(first, second)); - return *this; - } - - // Get a forward-only iterator to the first element. - const_iterator begin() const - { - return const_iterator(at_end_, first_, begin_remainder_, buffers_.end()); - } - - // Get a forward-only iterator for one past the last element. - const_iterator end() const - { - return const_iterator(); - } - - // Consume the specified number of bytes from the buffers. - void consume(std::size_t size) - { - // Remove buffers from the start until the specified size is reached. - while (size > 0 && !at_end_) - { - if (buffer_size(first_) <= size) - { - size -= buffer_size(first_); - if (begin_remainder_ == buffers_.end()) - at_end_ = true; - else - first_ = *begin_remainder_++; - } - else - { - first_ = first_ + size; - size = 0; - } - } - - // Remove any more empty buffers at the start. - while (!at_end_ && buffer_size(first_) == 0) - { - if (begin_remainder_ == buffers_.end()) - at_end_ = true; - else - first_ = *begin_remainder_++; - } - } - -private: - Buffers buffers_; - bool at_end_; - Buffer first_; - typename Buffers::const_iterator begin_remainder_; -}; - -// Specialisation for null_buffers to ensure that the null_buffers type is -// always passed through to the underlying read or write operation. -template -class consuming_buffers - : public asio::null_buffers -{ -public: - consuming_buffers(const asio::null_buffers&) - { - // No-op. - } - - void consume(std::size_t) - { - // No-op. - } -}; - -} // namespace detail -} // namespace asio - -#include "asio/detail/pop_options.hpp" - -#endif // ASIO_DETAIL_CONSUMING_BUFFERS_HPP diff --git a/libtorrent/include/asio/detail/deadline_timer_service.hpp b/libtorrent/include/asio/detail/deadline_timer_service.hpp deleted file mode 100644 index 6f30d7546..000000000 --- a/libtorrent/include/asio/detail/deadline_timer_service.hpp +++ /dev/null @@ -1,200 +0,0 @@ -// -// deadline_timer_service.hpp -// ~~~~~~~~~~~~~~~~~~~~~~~~~~ -// -// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -#ifndef ASIO_DETAIL_DEADLINE_TIMER_SERVICE_HPP -#define ASIO_DETAIL_DEADLINE_TIMER_SERVICE_HPP - -#if defined(_MSC_VER) && (_MSC_VER >= 1200) -# pragma once -#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) - -#include "asio/detail/push_options.hpp" - -#include "asio/detail/push_options.hpp" -#include -#include -#include -#include "asio/detail/pop_options.hpp" - -#include "asio/error.hpp" -#include "asio/io_service.hpp" -#include "asio/detail/bind_handler.hpp" -#include "asio/detail/handler_base_from_member.hpp" -#include "asio/detail/noncopyable.hpp" -#include "asio/detail/service_base.hpp" -#include "asio/detail/socket_ops.hpp" -#include "asio/detail/socket_types.hpp" -#include "asio/detail/timer_queue.hpp" - -namespace asio { -namespace detail { - -template -class deadline_timer_service - : public asio::detail::service_base< - deadline_timer_service > -{ -public: - // The time type. - typedef typename Time_Traits::time_type time_type; - - // The duration type. - typedef typename Time_Traits::duration_type duration_type; - - // The implementation type of the timer. This type is dependent on the - // underlying implementation of the timer service. - struct implementation_type - : private asio::detail::noncopyable - { - time_type expiry; - bool might_have_pending_waits; - }; - - // Constructor. - deadline_timer_service(asio::io_service& io_service) - : asio::detail::service_base< - deadline_timer_service >(io_service), - scheduler_(asio::use_service(io_service)) - { - scheduler_.add_timer_queue(timer_queue_); - } - - // Destructor. - ~deadline_timer_service() - { - scheduler_.remove_timer_queue(timer_queue_); - } - - // Destroy all user-defined handler objects owned by the service. - void shutdown_service() - { - } - - // Construct a new timer implementation. - void construct(implementation_type& impl) - { - impl.expiry = time_type(); - impl.might_have_pending_waits = false; - } - - // Destroy a timer implementation. - void destroy(implementation_type& impl) - { - asio::error_code ec; - cancel(impl, ec); - } - - // Cancel any asynchronous wait operations associated with the timer. - std::size_t cancel(implementation_type& impl, asio::error_code& ec) - { - if (!impl.might_have_pending_waits) - { - ec = asio::error_code(); - return 0; - } - std::size_t count = scheduler_.cancel_timer(timer_queue_, &impl); - impl.might_have_pending_waits = false; - ec = asio::error_code(); - return count; - } - - // Get the expiry time for the timer as an absolute time. - time_type expires_at(const implementation_type& impl) const - { - return impl.expiry; - } - - // Set the expiry time for the timer as an absolute time. - std::size_t expires_at(implementation_type& impl, - const time_type& expiry_time, asio::error_code& ec) - { - std::size_t count = cancel(impl, ec); - impl.expiry = expiry_time; - ec = asio::error_code(); - return count; - } - - // Get the expiry time for the timer relative to now. - duration_type expires_from_now(const implementation_type& impl) const - { - return Time_Traits::subtract(expires_at(impl), Time_Traits::now()); - } - - // Set the expiry time for the timer relative to now. - std::size_t expires_from_now(implementation_type& impl, - const duration_type& expiry_time, asio::error_code& ec) - { - return expires_at(impl, - Time_Traits::add(Time_Traits::now(), expiry_time), ec); - } - - // Perform a blocking wait on the timer. - void wait(implementation_type& impl, asio::error_code& ec) - { - time_type now = Time_Traits::now(); - while (Time_Traits::less_than(now, impl.expiry)) - { - boost::posix_time::time_duration timeout = - Time_Traits::to_posix_duration(Time_Traits::subtract(impl.expiry, now)); - ::timeval tv; - tv.tv_sec = timeout.total_seconds(); - tv.tv_usec = timeout.total_microseconds() % 1000000; - asio::error_code ec; - socket_ops::select(0, 0, 0, 0, &tv, ec); - now = Time_Traits::now(); - } - ec = asio::error_code(); - } - - template - class wait_handler : - public handler_base_from_member - { - public: - wait_handler(asio::io_service& io_service, Handler handler) - : handler_base_from_member(handler), - io_service_(io_service), - work_(io_service) - { - } - - void operator()(const asio::error_code& result) - { - io_service_.post(detail::bind_handler(this->handler_, result)); - } - - private: - asio::io_service& io_service_; - asio::io_service::work work_; - }; - - // Start an asynchronous wait on the timer. - template - void async_wait(implementation_type& impl, Handler handler) - { - impl.might_have_pending_waits = true; - scheduler_.schedule_timer(timer_queue_, impl.expiry, - wait_handler(this->get_io_service(), handler), &impl); - } - -private: - // The queue of timers. - timer_queue timer_queue_; - - // The object that schedules and executes timers. Usually a reactor. - Timer_Scheduler& scheduler_; -}; - -} // namespace detail -} // namespace asio - -#include "asio/detail/pop_options.hpp" - -#endif // ASIO_DETAIL_DEADLINE_TIMER_SERVICE_HPP diff --git a/libtorrent/include/asio/detail/descriptor_ops.hpp b/libtorrent/include/asio/detail/descriptor_ops.hpp deleted file mode 100644 index 6de34f621..000000000 --- a/libtorrent/include/asio/detail/descriptor_ops.hpp +++ /dev/null @@ -1,138 +0,0 @@ -// -// descriptor_ops.hpp -// ~~~~~~~~~~~~~~~~~~ -// -// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -#ifndef ASIO_DETAIL_DESCRIPTOR_OPS_HPP -#define ASIO_DETAIL_DESCRIPTOR_OPS_HPP - -#if defined(_MSC_VER) && (_MSC_VER >= 1200) -# pragma once -#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) - -#include "asio/detail/push_options.hpp" - -#include "asio/detail/push_options.hpp" -#include -#include -#include "asio/detail/pop_options.hpp" - -#include "asio/error.hpp" -#include "asio/detail/socket_types.hpp" - -#if !defined(BOOST_WINDOWS) && !defined(__CYGWIN__) - -namespace asio { -namespace detail { -namespace descriptor_ops { - -inline void clear_error(asio::error_code& ec) -{ - errno = 0; - ec = asio::error_code(); -} - -template -inline ReturnType error_wrapper(ReturnType return_value, - asio::error_code& ec) -{ - ec = asio::error_code(errno, - asio::error::get_system_category()); - return return_value; -} - -inline int open(const char* path, int flags, asio::error_code& ec) -{ - clear_error(ec); - return error_wrapper(::open(path, flags), ec); -} - -inline int close(int d, asio::error_code& ec) -{ - clear_error(ec); - return error_wrapper(::close(d), ec); -} - -typedef iovec buf; - -inline void init_buf(buf& b, void* data, size_t size) -{ - b.iov_base = data; - b.iov_len = size; -} - -inline void init_buf(buf& b, const void* data, size_t size) -{ - b.iov_base = const_cast(data); - b.iov_len = size; -} - -inline int scatter_read(int d, buf* bufs, size_t count, - asio::error_code& ec) -{ - clear_error(ec); - return error_wrapper(::readv(d, bufs, static_cast(count)), ec); -} - -inline int gather_write(int d, const buf* bufs, size_t count, - asio::error_code& ec) -{ - clear_error(ec); - return error_wrapper(::writev(d, bufs, static_cast(count)), ec); -} - -inline int ioctl(int d, long cmd, ioctl_arg_type* arg, - asio::error_code& ec) -{ - clear_error(ec); - return error_wrapper(::ioctl(d, cmd, arg), ec); -} - -inline int fcntl(int d, long cmd, asio::error_code& ec) -{ - clear_error(ec); - return error_wrapper(::fcntl(d, cmd), ec); -} - -inline int fcntl(int d, long cmd, long arg, asio::error_code& ec) -{ - clear_error(ec); - return error_wrapper(::fcntl(d, cmd, arg), ec); -} - -inline int poll_read(int d, asio::error_code& ec) -{ - clear_error(ec); - pollfd fds; - fds.fd = d; - fds.events = POLLIN; - fds.revents = 0; - clear_error(ec); - return error_wrapper(::poll(&fds, 1, -1), ec); -} - -inline int poll_write(int d, asio::error_code& ec) -{ - clear_error(ec); - pollfd fds; - fds.fd = d; - fds.events = POLLOUT; - fds.revents = 0; - clear_error(ec); - return error_wrapper(::poll(&fds, 1, -1), ec); -} - -} // namespace descriptor_ops -} // namespace detail -} // namespace asio - -#endif // !defined(BOOST_WINDOWS) && !defined(__CYGWIN__) - -#include "asio/detail/pop_options.hpp" - -#endif // ASIO_DETAIL_DESCRIPTOR_OPS_HPP diff --git a/libtorrent/include/asio/detail/dev_poll_reactor.hpp b/libtorrent/include/asio/detail/dev_poll_reactor.hpp deleted file mode 100644 index 4eb387eb1..000000000 --- a/libtorrent/include/asio/detail/dev_poll_reactor.hpp +++ /dev/null @@ -1,664 +0,0 @@ -// -// dev_poll_reactor.hpp -// ~~~~~~~~~~~~~~~~~~~~ -// -// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -#ifndef ASIO_DETAIL_DEV_POLL_REACTOR_HPP -#define ASIO_DETAIL_DEV_POLL_REACTOR_HPP - -#if defined(_MSC_VER) && (_MSC_VER >= 1200) -# pragma once -#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) - -#include "asio/detail/push_options.hpp" - -#include "asio/detail/dev_poll_reactor_fwd.hpp" - -#if defined(ASIO_HAS_DEV_POLL) - -#include "asio/detail/push_options.hpp" -#include -#include -#include -#include -#include -#include -#include "asio/detail/pop_options.hpp" - -#include "asio/error.hpp" -#include "asio/io_service.hpp" -#include "asio/system_error.hpp" -#include "asio/detail/bind_handler.hpp" -#include "asio/detail/hash_map.hpp" -#include "asio/detail/mutex.hpp" -#include "asio/detail/task_io_service.hpp" -#include "asio/detail/thread.hpp" -#include "asio/detail/reactor_op_queue.hpp" -#include "asio/detail/select_interrupter.hpp" -#include "asio/detail/service_base.hpp" -#include "asio/detail/signal_blocker.hpp" -#include "asio/detail/socket_types.hpp" -#include "asio/detail/timer_queue.hpp" - -namespace asio { -namespace detail { - -template -class dev_poll_reactor - : public asio::detail::service_base > -{ -public: - // Per-descriptor data. - struct per_descriptor_data - { - }; - - // Constructor. - dev_poll_reactor(asio::io_service& io_service) - : asio::detail::service_base< - dev_poll_reactor >(io_service), - mutex_(), - dev_poll_fd_(do_dev_poll_create()), - wait_in_progress_(false), - interrupter_(), - read_op_queue_(), - write_op_queue_(), - except_op_queue_(), - pending_cancellations_(), - stop_thread_(false), - thread_(0), - shutdown_(false) - { - // Start the reactor's internal thread only if needed. - if (Own_Thread) - { - asio::detail::signal_blocker sb; - thread_ = new asio::detail::thread( - bind_handler(&dev_poll_reactor::call_run_thread, this)); - } - - // Add the interrupter's descriptor to /dev/poll. - ::pollfd ev = { 0 }; - ev.fd = interrupter_.read_descriptor(); - ev.events = POLLIN | POLLERR; - ev.revents = 0; - ::write(dev_poll_fd_, &ev, sizeof(ev)); - } - - // Destructor. - ~dev_poll_reactor() - { - shutdown_service(); - ::close(dev_poll_fd_); - } - - // Destroy all user-defined handler objects owned by the service. - void shutdown_service() - { - asio::detail::mutex::scoped_lock lock(mutex_); - shutdown_ = true; - stop_thread_ = true; - lock.unlock(); - - if (thread_) - { - interrupter_.interrupt(); - thread_->join(); - delete thread_; - thread_ = 0; - } - - read_op_queue_.destroy_operations(); - write_op_queue_.destroy_operations(); - except_op_queue_.destroy_operations(); - - for (std::size_t i = 0; i < timer_queues_.size(); ++i) - timer_queues_[i]->destroy_timers(); - timer_queues_.clear(); - } - - // Register a socket with the reactor. Returns 0 on success, system error - // code on failure. - int register_descriptor(socket_type, per_descriptor_data&) - { - return 0; - } - - // Start a new read operation. The handler object will be invoked when the - // given descriptor is ready to be read, or an error has occurred. - template - void start_read_op(socket_type descriptor, per_descriptor_data&, - Handler handler, bool allow_speculative_read = true) - { - asio::detail::mutex::scoped_lock lock(mutex_); - - if (shutdown_) - return; - - if (allow_speculative_read) - { - if (!read_op_queue_.has_operation(descriptor)) - { - asio::error_code ec; - std::size_t bytes_transferred = 0; - if (handler.perform(ec, bytes_transferred)) - { - handler.complete(ec, bytes_transferred); - return; - } - } - } - - if (read_op_queue_.enqueue_operation(descriptor, handler)) - { - ::pollfd& ev = add_pending_event_change(descriptor); - ev.events = POLLIN | POLLERR | POLLHUP; - if (write_op_queue_.has_operation(descriptor)) - ev.events |= POLLOUT; - if (except_op_queue_.has_operation(descriptor)) - ev.events |= POLLPRI; - interrupter_.interrupt(); - } - } - - // Start a new write operation. The handler object will be invoked when the - // given descriptor is ready to be written, or an error has occurred. - template - void start_write_op(socket_type descriptor, per_descriptor_data&, - Handler handler, bool allow_speculative_write = true) - { - asio::detail::mutex::scoped_lock lock(mutex_); - - if (shutdown_) - return; - - if (allow_speculative_write) - { - if (!write_op_queue_.has_operation(descriptor)) - { - asio::error_code ec; - std::size_t bytes_transferred = 0; - if (handler.perform(ec, bytes_transferred)) - { - handler.complete(ec, bytes_transferred); - return; - } - } - } - - if (write_op_queue_.enqueue_operation(descriptor, handler)) - { - ::pollfd& ev = add_pending_event_change(descriptor); - ev.events = POLLOUT | POLLERR | POLLHUP; - if (read_op_queue_.has_operation(descriptor)) - ev.events |= POLLIN; - if (except_op_queue_.has_operation(descriptor)) - ev.events |= POLLPRI; - interrupter_.interrupt(); - } - } - - // Start a new exception operation. The handler object will be invoked when - // the given descriptor has exception information, or an error has occurred. - template - void start_except_op(socket_type descriptor, - per_descriptor_data&, Handler handler) - { - asio::detail::mutex::scoped_lock lock(mutex_); - - if (shutdown_) - return; - - if (except_op_queue_.enqueue_operation(descriptor, handler)) - { - ::pollfd& ev = add_pending_event_change(descriptor); - ev.events = POLLPRI | POLLERR | POLLHUP; - if (read_op_queue_.has_operation(descriptor)) - ev.events |= POLLIN; - if (write_op_queue_.has_operation(descriptor)) - ev.events |= POLLOUT; - interrupter_.interrupt(); - } - } - - // Start a new write operation. The handler object will be invoked when the - // information available, or an error has occurred. - template - void start_connect_op(socket_type descriptor, - per_descriptor_data&, Handler handler) - { - asio::detail::mutex::scoped_lock lock(mutex_); - - if (shutdown_) - return; - - if (write_op_queue_.enqueue_operation(descriptor, handler)) - { - ::pollfd& ev = add_pending_event_change(descriptor); - ev.events = POLLOUT | POLLERR | POLLHUP; - if (read_op_queue_.has_operation(descriptor)) - ev.events |= POLLIN; - if (except_op_queue_.has_operation(descriptor)) - ev.events |= POLLPRI; - interrupter_.interrupt(); - } - } - - // Cancel all operations associated with the given descriptor. The - // handlers associated with the descriptor will be invoked with the - // operation_aborted error. - void cancel_ops(socket_type descriptor, per_descriptor_data&) - { - asio::detail::mutex::scoped_lock lock(mutex_); - cancel_ops_unlocked(descriptor); - } - - // Cancel any operations that are running against the descriptor and remove - // its registration from the reactor. - void close_descriptor(socket_type descriptor, per_descriptor_data&) - { - asio::detail::mutex::scoped_lock lock(mutex_); - - // Remove the descriptor from /dev/poll. - ::pollfd& ev = add_pending_event_change(descriptor); - ev.events = POLLREMOVE; - interrupter_.interrupt(); - - // Cancel any outstanding operations associated with the descriptor. - cancel_ops_unlocked(descriptor); - } - - // Add a new timer queue to the reactor. - template - void add_timer_queue(timer_queue& timer_queue) - { - asio::detail::mutex::scoped_lock lock(mutex_); - timer_queues_.push_back(&timer_queue); - } - - // Remove a timer queue from the reactor. - template - void remove_timer_queue(timer_queue& timer_queue) - { - asio::detail::mutex::scoped_lock lock(mutex_); - for (std::size_t i = 0; i < timer_queues_.size(); ++i) - { - if (timer_queues_[i] == &timer_queue) - { - timer_queues_.erase(timer_queues_.begin() + i); - return; - } - } - } - - // Schedule a timer in the given timer queue to expire at the specified - // absolute time. The handler object will be invoked when the timer expires. - template - void schedule_timer(timer_queue& timer_queue, - const typename Time_Traits::time_type& time, Handler handler, void* token) - { - asio::detail::mutex::scoped_lock lock(mutex_); - if (!shutdown_) - if (timer_queue.enqueue_timer(time, handler, token)) - interrupter_.interrupt(); - } - - // Cancel the timer associated with the given token. Returns the number of - // handlers that have been posted or dispatched. - template - std::size_t cancel_timer(timer_queue& timer_queue, void* token) - { - asio::detail::mutex::scoped_lock lock(mutex_); - std::size_t n = timer_queue.cancel_timer(token); - if (n > 0) - interrupter_.interrupt(); - return n; - } - -private: - friend class task_io_service >; - - // Run /dev/poll once until interrupted or events are ready to be dispatched. - void run(bool block) - { - asio::detail::mutex::scoped_lock lock(mutex_); - - // Dispatch any operation cancellations that were made while the select - // loop was not running. - read_op_queue_.perform_cancellations(); - write_op_queue_.perform_cancellations(); - except_op_queue_.perform_cancellations(); - for (std::size_t i = 0; i < timer_queues_.size(); ++i) - timer_queues_[i]->dispatch_cancellations(); - - // Check if the thread is supposed to stop. - if (stop_thread_) - { - complete_operations_and_timers(lock); - return; - } - - // We can return immediately if there's no work to do and the reactor is - // not supposed to block. - if (!block && read_op_queue_.empty() && write_op_queue_.empty() - && except_op_queue_.empty() && all_timer_queues_are_empty()) - { - complete_operations_and_timers(lock); - return; - } - - // Write the pending event registration changes to the /dev/poll descriptor. - std::size_t events_size = sizeof(::pollfd) * pending_event_changes_.size(); - errno = 0; - int result = ::write(dev_poll_fd_, - &pending_event_changes_[0], events_size); - if (result != static_cast(events_size)) - { - for (std::size_t i = 0; i < pending_event_changes_.size(); ++i) - { - int descriptor = pending_event_changes_[i].fd; - asio::error_code ec = asio::error_code( - errno, asio::error::get_system_category()); - read_op_queue_.perform_all_operations(descriptor, ec); - write_op_queue_.perform_all_operations(descriptor, ec); - except_op_queue_.perform_all_operations(descriptor, ec); - } - } - pending_event_changes_.clear(); - pending_event_change_index_.clear(); - - int timeout = block ? get_timeout() : 0; - wait_in_progress_ = true; - lock.unlock(); - - // Block on the /dev/poll descriptor. - ::pollfd events[128] = { { 0 } }; - ::dvpoll dp = { 0 }; - dp.dp_fds = events; - dp.dp_nfds = 128; - dp.dp_timeout = timeout; - int num_events = ::ioctl(dev_poll_fd_, DP_POLL, &dp); - - lock.lock(); - wait_in_progress_ = false; - - // Block signals while performing operations. - asio::detail::signal_blocker sb; - - // Dispatch the waiting events. - for (int i = 0; i < num_events; ++i) - { - int descriptor = events[i].fd; - if (descriptor == interrupter_.read_descriptor()) - { - interrupter_.reset(); - } - else - { - bool more_reads = false; - bool more_writes = false; - bool more_except = false; - asio::error_code ec; - - // Exception operations must be processed first to ensure that any - // out-of-band data is read before normal data. - if (events[i].events & (POLLPRI | POLLERR | POLLHUP)) - more_except = except_op_queue_.perform_operation(descriptor, ec); - else - more_except = except_op_queue_.has_operation(descriptor); - - if (events[i].events & (POLLIN | POLLERR | POLLHUP)) - more_reads = read_op_queue_.perform_operation(descriptor, ec); - else - more_reads = read_op_queue_.has_operation(descriptor); - - if (events[i].events & (POLLOUT | POLLERR | POLLHUP)) - more_writes = write_op_queue_.perform_operation(descriptor, ec); - else - more_writes = write_op_queue_.has_operation(descriptor); - if ((events[i].events & (POLLERR | POLLHUP)) != 0 - && (events[i].events & ~(POLLERR | POLLHUP)) == 0 - && !more_except && !more_reads && !more_writes) - { - // If we have an event and no operations associated with the - // descriptor then we need to delete the descriptor from /dev/poll. - // The poll operation can produce POLLHUP or POLLERR events when there - // is no operation pending, so if we do not remove the descriptor we - // can end up in a tight polling loop. - ::pollfd ev = { 0 }; - ev.fd = descriptor; - ev.events = POLLREMOVE; - ev.revents = 0; - ::write(dev_poll_fd_, &ev, sizeof(ev)); - } - else - { - ::pollfd ev = { 0 }; - ev.fd = descriptor; - ev.events = POLLERR | POLLHUP; - if (more_reads) - ev.events |= POLLIN; - if (more_writes) - ev.events |= POLLOUT; - if (more_except) - ev.events |= POLLPRI; - ev.revents = 0; - int result = ::write(dev_poll_fd_, &ev, sizeof(ev)); - if (result != sizeof(ev)) - { - ec = asio::error_code(errno, - asio::error::get_system_category()); - read_op_queue_.perform_all_operations(descriptor, ec); - write_op_queue_.perform_all_operations(descriptor, ec); - except_op_queue_.perform_all_operations(descriptor, ec); - } - } - } - } - read_op_queue_.perform_cancellations(); - write_op_queue_.perform_cancellations(); - except_op_queue_.perform_cancellations(); - for (std::size_t i = 0; i < timer_queues_.size(); ++i) - { - timer_queues_[i]->dispatch_timers(); - timer_queues_[i]->dispatch_cancellations(); - } - - // Issue any pending cancellations. - for (size_t i = 0; i < pending_cancellations_.size(); ++i) - cancel_ops_unlocked(pending_cancellations_[i]); - pending_cancellations_.clear(); - - complete_operations_and_timers(lock); - } - - // Run the select loop in the thread. - void run_thread() - { - asio::detail::mutex::scoped_lock lock(mutex_); - while (!stop_thread_) - { - lock.unlock(); - run(true); - lock.lock(); - } - } - - // Entry point for the select loop thread. - static void call_run_thread(dev_poll_reactor* reactor) - { - reactor->run_thread(); - } - - // Interrupt the select loop. - void interrupt() - { - interrupter_.interrupt(); - } - - // Create the /dev/poll file descriptor. Throws an exception if the descriptor - // cannot be created. - static int do_dev_poll_create() - { - int fd = ::open("/dev/poll", O_RDWR); - if (fd == -1) - { - boost::throw_exception( - asio::system_error( - asio::error_code(errno, - asio::error::get_system_category()), - "/dev/poll")); - } - return fd; - } - - // Check if all timer queues are empty. - bool all_timer_queues_are_empty() const - { - for (std::size_t i = 0; i < timer_queues_.size(); ++i) - if (!timer_queues_[i]->empty()) - return false; - return true; - } - - // Get the timeout value for the /dev/poll DP_POLL operation. The timeout - // value is returned as a number of milliseconds. A return value of -1 - // indicates that the poll should block indefinitely. - int get_timeout() - { - if (all_timer_queues_are_empty()) - return -1; - - // By default we will wait no longer than 5 minutes. This will ensure that - // any changes to the system clock are detected after no longer than this. - boost::posix_time::time_duration minimum_wait_duration - = boost::posix_time::minutes(5); - - for (std::size_t i = 0; i < timer_queues_.size(); ++i) - { - boost::posix_time::time_duration wait_duration - = timer_queues_[i]->wait_duration(); - if (wait_duration < minimum_wait_duration) - minimum_wait_duration = wait_duration; - } - - if (minimum_wait_duration > boost::posix_time::time_duration()) - { - int milliseconds = minimum_wait_duration.total_milliseconds(); - return milliseconds > 0 ? milliseconds : 1; - } - else - { - return 0; - } - } - - // Cancel all operations associated with the given descriptor. The do_cancel - // function of the handler objects will be invoked. This function does not - // acquire the dev_poll_reactor's mutex. - void cancel_ops_unlocked(socket_type descriptor) - { - bool interrupt = read_op_queue_.cancel_operations(descriptor); - interrupt = write_op_queue_.cancel_operations(descriptor) || interrupt; - interrupt = except_op_queue_.cancel_operations(descriptor) || interrupt; - if (interrupt) - interrupter_.interrupt(); - } - - // Clean up operations and timers. We must not hold the lock since the - // destructors may make calls back into this reactor. We make a copy of the - // vector of timer queues since the original may be modified while the lock - // is not held. - void complete_operations_and_timers( - asio::detail::mutex::scoped_lock& lock) - { - timer_queues_for_cleanup_ = timer_queues_; - lock.unlock(); - read_op_queue_.complete_operations(); - write_op_queue_.complete_operations(); - except_op_queue_.complete_operations(); - for (std::size_t i = 0; i < timer_queues_for_cleanup_.size(); ++i) - timer_queues_for_cleanup_[i]->complete_timers(); - } - - // Add a pending event entry for the given descriptor. - ::pollfd& add_pending_event_change(int descriptor) - { - hash_map::iterator iter - = pending_event_change_index_.find(descriptor); - if (iter == pending_event_change_index_.end()) - { - std::size_t index = pending_event_changes_.size(); - pending_event_changes_.reserve(pending_event_changes_.size() + 1); - pending_event_change_index_.insert(std::make_pair(descriptor, index)); - pending_event_changes_.push_back(::pollfd()); - pending_event_changes_[index].fd = descriptor; - pending_event_changes_[index].revents = 0; - return pending_event_changes_[index]; - } - else - { - return pending_event_changes_[iter->second]; - } - } - - // Mutex to protect access to internal data. - asio::detail::mutex mutex_; - - // The /dev/poll file descriptor. - int dev_poll_fd_; - - // Vector of /dev/poll events waiting to be written to the descriptor. - std::vector< ::pollfd> pending_event_changes_; - - // Hash map to associate a descriptor with a pending event change index. - hash_map pending_event_change_index_; - - // Whether the DP_POLL operation is currently in progress - bool wait_in_progress_; - - // The interrupter is used to break a blocking DP_POLL operation. - select_interrupter interrupter_; - - // The queue of read operations. - reactor_op_queue read_op_queue_; - - // The queue of write operations. - reactor_op_queue write_op_queue_; - - // The queue of except operations. - reactor_op_queue except_op_queue_; - - // The timer queues. - std::vector timer_queues_; - - // A copy of the timer queues, used when cleaning up timers. The copy is - // stored as a class data member to avoid unnecessary memory allocation. - std::vector timer_queues_for_cleanup_; - - // The descriptors that are pending cancellation. - std::vector pending_cancellations_; - - // Does the reactor loop thread need to stop. - bool stop_thread_; - - // The thread that is running the reactor loop. - asio::detail::thread* thread_; - - // Whether the service has been shut down. - bool shutdown_; -}; - -} // namespace detail -} // namespace asio - -#endif // defined(ASIO_HAS_DEV_POLL) - -#include "asio/detail/pop_options.hpp" - -#endif // ASIO_DETAIL_DEV_POLL_REACTOR_HPP diff --git a/libtorrent/include/asio/detail/dev_poll_reactor_fwd.hpp b/libtorrent/include/asio/detail/dev_poll_reactor_fwd.hpp deleted file mode 100644 index f3c6da181..000000000 --- a/libtorrent/include/asio/detail/dev_poll_reactor_fwd.hpp +++ /dev/null @@ -1,40 +0,0 @@ -// -// dev_poll_reactor_fwd.hpp -// ~~~~~~~~~~~~~~~~~~~~~~~~ -// -// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -#ifndef ASIO_DETAIL_DEV_POLL_REACTOR_FWD_HPP -#define ASIO_DETAIL_DEV_POLL_REACTOR_FWD_HPP - -#if defined(_MSC_VER) && (_MSC_VER >= 1200) -# pragma once -#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) - -#include "asio/detail/push_options.hpp" - -#if !defined(ASIO_DISABLE_DEV_POLL) -#if defined(__sun) // This service is only supported on Solaris. - -// Define this to indicate that /dev/poll is supported on the target platform. -#define ASIO_HAS_DEV_POLL 1 - -namespace asio { -namespace detail { - -template -class dev_poll_reactor; - -} // namespace detail -} // namespace asio - -#endif // defined(__sun) -#endif // !defined(ASIO_DISABLE_DEV_POLL) - -#include "asio/detail/pop_options.hpp" - -#endif // ASIO_DETAIL_DEV_POLL_REACTOR_FWD_HPP diff --git a/libtorrent/include/asio/detail/epoll_reactor.hpp b/libtorrent/include/asio/detail/epoll_reactor.hpp deleted file mode 100644 index 07bd7e1b6..000000000 --- a/libtorrent/include/asio/detail/epoll_reactor.hpp +++ /dev/null @@ -1,720 +0,0 @@ -// -// epoll_reactor.hpp -// ~~~~~~~~~~~~~~~~~ -// -// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -#ifndef ASIO_DETAIL_EPOLL_REACTOR_HPP -#define ASIO_DETAIL_EPOLL_REACTOR_HPP - -#if defined(_MSC_VER) && (_MSC_VER >= 1200) -# pragma once -#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) - -#include "asio/detail/push_options.hpp" - -#include "asio/detail/epoll_reactor_fwd.hpp" - -#if defined(ASIO_HAS_EPOLL) - -#include "asio/detail/push_options.hpp" -#include -#include -#include -#include -#include -#include -#include "asio/detail/pop_options.hpp" - -#include "asio/error.hpp" -#include "asio/io_service.hpp" -#include "asio/system_error.hpp" -#include "asio/detail/bind_handler.hpp" -#include "asio/detail/hash_map.hpp" -#include "asio/detail/mutex.hpp" -#include "asio/detail/task_io_service.hpp" -#include "asio/detail/thread.hpp" -#include "asio/detail/reactor_op_queue.hpp" -#include "asio/detail/select_interrupter.hpp" -#include "asio/detail/service_base.hpp" -#include "asio/detail/signal_blocker.hpp" -#include "asio/detail/socket_types.hpp" -#include "asio/detail/timer_queue.hpp" - -namespace asio { -namespace detail { - -template -class epoll_reactor - : public asio::detail::service_base > -{ -public: - // Per-descriptor data. - struct per_descriptor_data - { - bool allow_speculative_read; - bool allow_speculative_write; - }; - - // Constructor. - epoll_reactor(asio::io_service& io_service) - : asio::detail::service_base >(io_service), - mutex_(), - epoll_fd_(do_epoll_create()), - wait_in_progress_(false), - interrupter_(), - read_op_queue_(), - write_op_queue_(), - except_op_queue_(), - pending_cancellations_(), - stop_thread_(false), - thread_(0), - shutdown_(false), - need_epoll_wait_(true) - { - // Start the reactor's internal thread only if needed. - if (Own_Thread) - { - asio::detail::signal_blocker sb; - thread_ = new asio::detail::thread( - bind_handler(&epoll_reactor::call_run_thread, this)); - } - - // Add the interrupter's descriptor to epoll. - epoll_event ev = { 0, { 0 } }; - ev.events = EPOLLIN | EPOLLERR; - ev.data.fd = interrupter_.read_descriptor(); - epoll_ctl(epoll_fd_, EPOLL_CTL_ADD, interrupter_.read_descriptor(), &ev); - } - - // Destructor. - ~epoll_reactor() - { - shutdown_service(); - close(epoll_fd_); - } - - // Destroy all user-defined handler objects owned by the service. - void shutdown_service() - { - asio::detail::mutex::scoped_lock lock(mutex_); - shutdown_ = true; - stop_thread_ = true; - lock.unlock(); - - if (thread_) - { - interrupter_.interrupt(); - thread_->join(); - delete thread_; - thread_ = 0; - } - - read_op_queue_.destroy_operations(); - write_op_queue_.destroy_operations(); - except_op_queue_.destroy_operations(); - - for (std::size_t i = 0; i < timer_queues_.size(); ++i) - timer_queues_[i]->destroy_timers(); - timer_queues_.clear(); - } - - // Register a socket with the reactor. Returns 0 on success, system error - // code on failure. - int register_descriptor(socket_type descriptor, - per_descriptor_data& descriptor_data) - { - // No need to lock according to epoll documentation. - - descriptor_data.allow_speculative_read = true; - descriptor_data.allow_speculative_write = true; - - epoll_event ev = { 0, { 0 } }; - ev.events = 0; - ev.data.fd = descriptor; - int result = epoll_ctl(epoll_fd_, EPOLL_CTL_ADD, descriptor, &ev); - if (result != 0) - return errno; - return 0; - } - - // Start a new read operation. The handler object will be invoked when the - // given descriptor is ready to be read, or an error has occurred. - template - void start_read_op(socket_type descriptor, - per_descriptor_data& descriptor_data, - Handler handler, bool allow_speculative_read = true) - { - if (allow_speculative_read && descriptor_data.allow_speculative_read) - { - asio::error_code ec; - std::size_t bytes_transferred = 0; - if (handler.perform(ec, bytes_transferred)) - { - handler.complete(ec, bytes_transferred); - return; - } - - // We only get one shot at a speculative read in this function. - allow_speculative_read = false; - } - - asio::detail::mutex::scoped_lock lock(mutex_); - - if (shutdown_) - return; - - if (!allow_speculative_read) - need_epoll_wait_ = true; - else if (!read_op_queue_.has_operation(descriptor)) - { - // Speculative reads are ok as there are no queued read operations. - descriptor_data.allow_speculative_read = true; - - asio::error_code ec; - std::size_t bytes_transferred = 0; - if (handler.perform(ec, bytes_transferred)) - { - handler.complete(ec, bytes_transferred); - return; - } - } - - // Speculative reads are not ok as there will be queued read operations. - descriptor_data.allow_speculative_read = false; - - if (read_op_queue_.enqueue_operation(descriptor, handler)) - { - epoll_event ev = { 0, { 0 } }; - ev.events = EPOLLIN | EPOLLERR | EPOLLHUP; - if (write_op_queue_.has_operation(descriptor)) - ev.events |= EPOLLOUT; - if (except_op_queue_.has_operation(descriptor)) - ev.events |= EPOLLPRI; - ev.data.fd = descriptor; - - int result = epoll_ctl(epoll_fd_, EPOLL_CTL_MOD, descriptor, &ev); - if (result != 0 && errno == ENOENT) - result = epoll_ctl(epoll_fd_, EPOLL_CTL_ADD, descriptor, &ev); - if (result != 0) - { - asio::error_code ec(errno, - asio::error::get_system_category()); - read_op_queue_.perform_all_operations(descriptor, ec); - } - } - } - - // Start a new write operation. The handler object will be invoked when the - // given descriptor is ready to be written, or an error has occurred. - template - void start_write_op(socket_type descriptor, - per_descriptor_data& descriptor_data, - Handler handler, bool allow_speculative_write = true) - { - if (allow_speculative_write && descriptor_data.allow_speculative_write) - { - asio::error_code ec; - std::size_t bytes_transferred = 0; - if (handler.perform(ec, bytes_transferred)) - { - handler.complete(ec, bytes_transferred); - return; - } - - // We only get one shot at a speculative write in this function. - allow_speculative_write = false; - } - - asio::detail::mutex::scoped_lock lock(mutex_); - - if (shutdown_) - return; - - if (!allow_speculative_write) - need_epoll_wait_ = true; - else if (!write_op_queue_.has_operation(descriptor)) - { - // Speculative writes are ok as there are no queued write operations. - descriptor_data.allow_speculative_write = true; - - asio::error_code ec; - std::size_t bytes_transferred = 0; - if (handler.perform(ec, bytes_transferred)) - { - handler.complete(ec, bytes_transferred); - return; - } - } - - // Speculative writes are not ok as there will be queued write operations. - descriptor_data.allow_speculative_write = false; - - if (write_op_queue_.enqueue_operation(descriptor, handler)) - { - epoll_event ev = { 0, { 0 } }; - ev.events = EPOLLOUT | EPOLLERR | EPOLLHUP; - if (read_op_queue_.has_operation(descriptor)) - ev.events |= EPOLLIN; - if (except_op_queue_.has_operation(descriptor)) - ev.events |= EPOLLPRI; - ev.data.fd = descriptor; - - int result = epoll_ctl(epoll_fd_, EPOLL_CTL_MOD, descriptor, &ev); - if (result != 0 && errno == ENOENT) - result = epoll_ctl(epoll_fd_, EPOLL_CTL_ADD, descriptor, &ev); - if (result != 0) - { - asio::error_code ec(errno, - asio::error::get_system_category()); - write_op_queue_.perform_all_operations(descriptor, ec); - } - } - } - - // Start a new exception operation. The handler object will be invoked when - // the given descriptor has exception information, or an error has occurred. - template - void start_except_op(socket_type descriptor, - per_descriptor_data&, Handler handler) - { - asio::detail::mutex::scoped_lock lock(mutex_); - - if (shutdown_) - return; - - if (except_op_queue_.enqueue_operation(descriptor, handler)) - { - epoll_event ev = { 0, { 0 } }; - ev.events = EPOLLPRI | EPOLLERR | EPOLLHUP; - if (read_op_queue_.has_operation(descriptor)) - ev.events |= EPOLLIN; - if (write_op_queue_.has_operation(descriptor)) - ev.events |= EPOLLOUT; - ev.data.fd = descriptor; - - int result = epoll_ctl(epoll_fd_, EPOLL_CTL_MOD, descriptor, &ev); - if (result != 0 && errno == ENOENT) - result = epoll_ctl(epoll_fd_, EPOLL_CTL_ADD, descriptor, &ev); - if (result != 0) - { - asio::error_code ec(errno, - asio::error::get_system_category()); - except_op_queue_.perform_all_operations(descriptor, ec); - } - } - } - - // Start a new write operation. The handler object will be invoked when the - // given descriptor is ready for writing or an error has occurred. Speculative - // writes are not allowed. - template - void start_connect_op(socket_type descriptor, - per_descriptor_data& descriptor_data, Handler handler) - { - asio::detail::mutex::scoped_lock lock(mutex_); - - if (shutdown_) - return; - - // Speculative writes are not ok as there will be queued write operations. - descriptor_data.allow_speculative_write = false; - - if (write_op_queue_.enqueue_operation(descriptor, handler)) - { - epoll_event ev = { 0, { 0 } }; - ev.events = EPOLLOUT | EPOLLERR | EPOLLHUP; - if (read_op_queue_.has_operation(descriptor)) - ev.events |= EPOLLIN; - if (except_op_queue_.has_operation(descriptor)) - ev.events |= EPOLLPRI; - ev.data.fd = descriptor; - - int result = epoll_ctl(epoll_fd_, EPOLL_CTL_MOD, descriptor, &ev); - if (result != 0 && errno == ENOENT) - result = epoll_ctl(epoll_fd_, EPOLL_CTL_ADD, descriptor, &ev); - if (result != 0) - { - asio::error_code ec(errno, - asio::error::get_system_category()); - write_op_queue_.perform_all_operations(descriptor, ec); - } - } - } - - // Cancel all operations associated with the given descriptor. The - // handlers associated with the descriptor will be invoked with the - // operation_aborted error. - void cancel_ops(socket_type descriptor, per_descriptor_data&) - { - asio::detail::mutex::scoped_lock lock(mutex_); - cancel_ops_unlocked(descriptor); - } - - // Cancel any operations that are running against the descriptor and remove - // its registration from the reactor. - void close_descriptor(socket_type descriptor, per_descriptor_data&) - { - asio::detail::mutex::scoped_lock lock(mutex_); - - // Remove the descriptor from epoll. - epoll_event ev = { 0, { 0 } }; - epoll_ctl(epoll_fd_, EPOLL_CTL_DEL, descriptor, &ev); - - // Cancel any outstanding operations associated with the descriptor. - cancel_ops_unlocked(descriptor); - } - - // Add a new timer queue to the reactor. - template - void add_timer_queue(timer_queue& timer_queue) - { - asio::detail::mutex::scoped_lock lock(mutex_); - timer_queues_.push_back(&timer_queue); - } - - // Remove a timer queue from the reactor. - template - void remove_timer_queue(timer_queue& timer_queue) - { - asio::detail::mutex::scoped_lock lock(mutex_); - for (std::size_t i = 0; i < timer_queues_.size(); ++i) - { - if (timer_queues_[i] == &timer_queue) - { - timer_queues_.erase(timer_queues_.begin() + i); - return; - } - } - } - - // Schedule a timer in the given timer queue to expire at the specified - // absolute time. The handler object will be invoked when the timer expires. - template - void schedule_timer(timer_queue& timer_queue, - const typename Time_Traits::time_type& time, Handler handler, void* token) - { - asio::detail::mutex::scoped_lock lock(mutex_); - if (!shutdown_) - if (timer_queue.enqueue_timer(time, handler, token)) - interrupter_.interrupt(); - } - - // Cancel the timer associated with the given token. Returns the number of - // handlers that have been posted or dispatched. - template - std::size_t cancel_timer(timer_queue& timer_queue, void* token) - { - asio::detail::mutex::scoped_lock lock(mutex_); - std::size_t n = timer_queue.cancel_timer(token); - if (n > 0) - interrupter_.interrupt(); - return n; - } - -private: - friend class task_io_service >; - - // Run epoll once until interrupted or events are ready to be dispatched. - void run(bool block) - { - asio::detail::mutex::scoped_lock lock(mutex_); - - // Dispatch any operation cancellations that were made while the select - // loop was not running. - read_op_queue_.perform_cancellations(); - write_op_queue_.perform_cancellations(); - except_op_queue_.perform_cancellations(); - for (std::size_t i = 0; i < timer_queues_.size(); ++i) - timer_queues_[i]->dispatch_cancellations(); - - // Check if the thread is supposed to stop. - if (stop_thread_) - { - complete_operations_and_timers(lock); - return; - } - - // We can return immediately if there's no work to do and the reactor is - // not supposed to block. - if (!block && read_op_queue_.empty() && write_op_queue_.empty() - && except_op_queue_.empty() && all_timer_queues_are_empty()) - { - complete_operations_and_timers(lock); - return; - } - - int timeout = block ? get_timeout() : 0; - wait_in_progress_ = true; - lock.unlock(); - - // Block on the epoll descriptor. - epoll_event events[128]; - int num_events = (block || need_epoll_wait_) - ? epoll_wait(epoll_fd_, events, 128, timeout) - : 0; - - lock.lock(); - wait_in_progress_ = false; - - // Block signals while performing operations. - asio::detail::signal_blocker sb; - - // Dispatch the waiting events. - for (int i = 0; i < num_events; ++i) - { - int descriptor = events[i].data.fd; - if (descriptor == interrupter_.read_descriptor()) - { - interrupter_.reset(); - } - else - { - bool more_reads = false; - bool more_writes = false; - bool more_except = false; - asio::error_code ec; - - // Exception operations must be processed first to ensure that any - // out-of-band data is read before normal data. - if (events[i].events & (EPOLLPRI | EPOLLERR | EPOLLHUP)) - more_except = except_op_queue_.perform_operation(descriptor, ec); - else - more_except = except_op_queue_.has_operation(descriptor); - - if (events[i].events & (EPOLLIN | EPOLLERR | EPOLLHUP)) - more_reads = read_op_queue_.perform_operation(descriptor, ec); - else - more_reads = read_op_queue_.has_operation(descriptor); - - if (events[i].events & (EPOLLOUT | EPOLLERR | EPOLLHUP)) - more_writes = write_op_queue_.perform_operation(descriptor, ec); - else - more_writes = write_op_queue_.has_operation(descriptor); - if ((events[i].events & (EPOLLERR | EPOLLHUP)) != 0 - && (events[i].events & ~(EPOLLERR | EPOLLHUP)) == 0 - && !more_except && !more_reads && !more_writes) - { - // If we have an event and no operations associated with the - // descriptor then we need to delete the descriptor from epoll. The - // epoll_wait system call can produce EPOLLHUP or EPOLLERR events - // when there is no operation pending, so if we do not remove the - // descriptor we can end up in a tight loop of repeated - // calls to epoll_wait. - epoll_event ev = { 0, { 0 } }; - epoll_ctl(epoll_fd_, EPOLL_CTL_DEL, descriptor, &ev); - } - else - { - epoll_event ev = { 0, { 0 } }; - ev.events = EPOLLERR | EPOLLHUP; - if (more_reads) - ev.events |= EPOLLIN; - if (more_writes) - ev.events |= EPOLLOUT; - if (more_except) - ev.events |= EPOLLPRI; - ev.data.fd = descriptor; - int result = epoll_ctl(epoll_fd_, EPOLL_CTL_MOD, descriptor, &ev); - if (result != 0 && errno == ENOENT) - result = epoll_ctl(epoll_fd_, EPOLL_CTL_ADD, descriptor, &ev); - if (result != 0) - { - ec = asio::error_code(errno, - asio::error::get_system_category()); - read_op_queue_.perform_all_operations(descriptor, ec); - write_op_queue_.perform_all_operations(descriptor, ec); - except_op_queue_.perform_all_operations(descriptor, ec); - } - } - } - } - read_op_queue_.perform_cancellations(); - write_op_queue_.perform_cancellations(); - except_op_queue_.perform_cancellations(); - for (std::size_t i = 0; i < timer_queues_.size(); ++i) - { - timer_queues_[i]->dispatch_timers(); - timer_queues_[i]->dispatch_cancellations(); - } - - // Issue any pending cancellations. - for (size_t i = 0; i < pending_cancellations_.size(); ++i) - cancel_ops_unlocked(pending_cancellations_[i]); - pending_cancellations_.clear(); - - // Determine whether epoll_wait should be called when the reactor next runs. - need_epoll_wait_ = !read_op_queue_.empty() - || !write_op_queue_.empty() || !except_op_queue_.empty(); - - complete_operations_and_timers(lock); - } - - // Run the select loop in the thread. - void run_thread() - { - asio::detail::mutex::scoped_lock lock(mutex_); - while (!stop_thread_) - { - lock.unlock(); - run(true); - lock.lock(); - } - } - - // Entry point for the select loop thread. - static void call_run_thread(epoll_reactor* reactor) - { - reactor->run_thread(); - } - - // Interrupt the select loop. - void interrupt() - { - interrupter_.interrupt(); - } - - // The hint to pass to epoll_create to size its data structures. - enum { epoll_size = 20000 }; - - // Create the epoll file descriptor. Throws an exception if the descriptor - // cannot be created. - static int do_epoll_create() - { - int fd = epoll_create(epoll_size); - if (fd == -1) - { - boost::throw_exception( - asio::system_error( - asio::error_code(errno, - asio::error::get_system_category()), - "epoll")); - } - return fd; - } - - // Check if all timer queues are empty. - bool all_timer_queues_are_empty() const - { - for (std::size_t i = 0; i < timer_queues_.size(); ++i) - if (!timer_queues_[i]->empty()) - return false; - return true; - } - - // Get the timeout value for the epoll_wait call. The timeout value is - // returned as a number of milliseconds. A return value of -1 indicates - // that epoll_wait should block indefinitely. - int get_timeout() - { - if (all_timer_queues_are_empty()) - return -1; - - // By default we will wait no longer than 5 minutes. This will ensure that - // any changes to the system clock are detected after no longer than this. - boost::posix_time::time_duration minimum_wait_duration - = boost::posix_time::minutes(5); - - for (std::size_t i = 0; i < timer_queues_.size(); ++i) - { - boost::posix_time::time_duration wait_duration - = timer_queues_[i]->wait_duration(); - if (wait_duration < minimum_wait_duration) - minimum_wait_duration = wait_duration; - } - - if (minimum_wait_duration > boost::posix_time::time_duration()) - { - int milliseconds = minimum_wait_duration.total_milliseconds(); - return milliseconds > 0 ? milliseconds : 1; - } - else - { - return 0; - } - } - - // Cancel all operations associated with the given descriptor. The do_cancel - // function of the handler objects will be invoked. This function does not - // acquire the epoll_reactor's mutex. - void cancel_ops_unlocked(socket_type descriptor) - { - bool interrupt = read_op_queue_.cancel_operations(descriptor); - interrupt = write_op_queue_.cancel_operations(descriptor) || interrupt; - interrupt = except_op_queue_.cancel_operations(descriptor) || interrupt; - if (interrupt) - interrupter_.interrupt(); - } - - // Clean up operations and timers. We must not hold the lock since the - // destructors may make calls back into this reactor. We make a copy of the - // vector of timer queues since the original may be modified while the lock - // is not held. - void complete_operations_and_timers( - asio::detail::mutex::scoped_lock& lock) - { - timer_queues_for_cleanup_ = timer_queues_; - lock.unlock(); - read_op_queue_.complete_operations(); - write_op_queue_.complete_operations(); - except_op_queue_.complete_operations(); - for (std::size_t i = 0; i < timer_queues_for_cleanup_.size(); ++i) - timer_queues_for_cleanup_[i]->complete_timers(); - } - - // Mutex to protect access to internal data. - asio::detail::mutex mutex_; - - // The epoll file descriptor. - int epoll_fd_; - - // Whether the epoll_wait call is currently in progress - bool wait_in_progress_; - - // The interrupter is used to break a blocking epoll_wait call. - select_interrupter interrupter_; - - // The queue of read operations. - reactor_op_queue read_op_queue_; - - // The queue of write operations. - reactor_op_queue write_op_queue_; - - // The queue of except operations. - reactor_op_queue except_op_queue_; - - // The timer queues. - std::vector timer_queues_; - - // A copy of the timer queues, used when cleaning up timers. The copy is - // stored as a class data member to avoid unnecessary memory allocation. - std::vector timer_queues_for_cleanup_; - - // The descriptors that are pending cancellation. - std::vector pending_cancellations_; - - // Does the reactor loop thread need to stop. - bool stop_thread_; - - // The thread that is running the reactor loop. - asio::detail::thread* thread_; - - // Whether the service has been shut down. - bool shutdown_; - - // Whether we need to call epoll_wait the next time the reactor is run. - bool need_epoll_wait_; -}; - -} // namespace detail -} // namespace asio - -#endif // defined(ASIO_HAS_EPOLL) - -#include "asio/detail/pop_options.hpp" - -#endif // ASIO_DETAIL_EPOLL_REACTOR_HPP diff --git a/libtorrent/include/asio/detail/epoll_reactor_fwd.hpp b/libtorrent/include/asio/detail/epoll_reactor_fwd.hpp deleted file mode 100644 index 601ce818d..000000000 --- a/libtorrent/include/asio/detail/epoll_reactor_fwd.hpp +++ /dev/null @@ -1,47 +0,0 @@ -// -// epoll_reactor_fwd.hpp -// ~~~~~~~~~~~~~~~~~~~~~ -// -// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -#ifndef ASIO_DETAIL_EPOLL_REACTOR_FWD_HPP -#define ASIO_DETAIL_EPOLL_REACTOR_FWD_HPP - -#if defined(_MSC_VER) && (_MSC_VER >= 1200) -# pragma once -#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) - -#include "asio/detail/push_options.hpp" - -#if !defined(ASIO_DISABLE_EPOLL) -#if defined(__linux__) // This service is only supported on Linux. - -#include "asio/detail/push_options.hpp" -#include -#include "asio/detail/pop_options.hpp" - -#if LINUX_VERSION_CODE >= KERNEL_VERSION (2,5,45) // Only kernels >= 2.5.45. - -// Define this to indicate that epoll is supported on the target platform. -#define ASIO_HAS_EPOLL 1 - -namespace asio { -namespace detail { - -template -class epoll_reactor; - -} // namespace detail -} // namespace asio - -#endif // LINUX_VERSION_CODE >= KERNEL_VERSION (2,5,45) -#endif // defined(__linux__) -#endif // !defined(ASIO_DISABLE_EPOLL) - -#include "asio/detail/pop_options.hpp" - -#endif // ASIO_DETAIL_EPOLL_REACTOR_FWD_HPP diff --git a/libtorrent/include/asio/detail/event.hpp b/libtorrent/include/asio/detail/event.hpp deleted file mode 100644 index 1f959d7cc..000000000 --- a/libtorrent/include/asio/detail/event.hpp +++ /dev/null @@ -1,50 +0,0 @@ -// -// event.hpp -// ~~~~~~~~~ -// -// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -#ifndef ASIO_DETAIL_EVENT_HPP -#define ASIO_DETAIL_EVENT_HPP - -#if defined(_MSC_VER) && (_MSC_VER >= 1200) -# pragma once -#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) - -#include "asio/detail/push_options.hpp" - -#include "asio/detail/push_options.hpp" -#include -#include "asio/detail/pop_options.hpp" - -#if !defined(BOOST_HAS_THREADS) -# include "asio/detail/null_event.hpp" -#elif defined(BOOST_WINDOWS) -# include "asio/detail/win_event.hpp" -#elif defined(BOOST_HAS_PTHREADS) -# include "asio/detail/posix_event.hpp" -#else -# error Only Windows and POSIX are supported! -#endif - -namespace asio { -namespace detail { - -#if !defined(BOOST_HAS_THREADS) -typedef null_event event; -#elif defined(BOOST_WINDOWS) -typedef win_event event; -#elif defined(BOOST_HAS_PTHREADS) -typedef posix_event event; -#endif - -} // namespace detail -} // namespace asio - -#include "asio/detail/pop_options.hpp" - -#endif // ASIO_DETAIL_EVENT_HPP diff --git a/libtorrent/include/asio/detail/fd_set_adapter.hpp b/libtorrent/include/asio/detail/fd_set_adapter.hpp deleted file mode 100644 index 5ae31b15a..000000000 --- a/libtorrent/include/asio/detail/fd_set_adapter.hpp +++ /dev/null @@ -1,41 +0,0 @@ -// -// fd_set_adapter.hpp -// ~~~~~~~~~~~~~~~~~~ -// -// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -#ifndef ASIO_DETAIL_FD_SET_ADAPTER_HPP -#define ASIO_DETAIL_FD_SET_ADAPTER_HPP - -#if defined(_MSC_VER) && (_MSC_VER >= 1200) -# pragma once -#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) - -#include "asio/detail/push_options.hpp" - -#include "asio/detail/push_options.hpp" -#include -#include "asio/detail/pop_options.hpp" - -#include "asio/detail/posix_fd_set_adapter.hpp" -#include "asio/detail/win_fd_set_adapter.hpp" - -namespace asio { -namespace detail { - -#if defined(BOOST_WINDOWS) || defined(__CYGWIN__) -typedef win_fd_set_adapter fd_set_adapter; -#else -typedef posix_fd_set_adapter fd_set_adapter; -#endif - -} // namespace detail -} // namespace asio - -#include "asio/detail/pop_options.hpp" - -#endif // ASIO_DETAIL_FD_SET_ADAPTER_HPP diff --git a/libtorrent/include/asio/detail/handler_alloc_helpers.hpp b/libtorrent/include/asio/detail/handler_alloc_helpers.hpp deleted file mode 100644 index 22b54e7ec..000000000 --- a/libtorrent/include/asio/detail/handler_alloc_helpers.hpp +++ /dev/null @@ -1,256 +0,0 @@ -// -// handler_alloc_helpers.hpp -// ~~~~~~~~~~~~~~~~~~~~~~~~~ -// -// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -#ifndef ASIO_DETAIL_HANDLER_ALLOC_HELPERS_HPP -#define ASIO_DETAIL_HANDLER_ALLOC_HELPERS_HPP - -#if defined(_MSC_VER) && (_MSC_VER >= 1200) -# pragma once -#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) - -#include "asio/detail/push_options.hpp" - -#include "asio/detail/push_options.hpp" -#include -#include "asio/detail/pop_options.hpp" - -#include "asio/handler_alloc_hook.hpp" -#include "asio/detail/noncopyable.hpp" - -// Calls to asio_handler_allocate and asio_handler_deallocate must be made from -// a namespace that does not contain any overloads of these functions. The -// asio_handler_alloc_helpers namespace is defined here for that purpose. -namespace asio_handler_alloc_helpers { - -template -inline void* allocate(std::size_t s, Handler* h) -{ -#if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564)) - return ::operator new(s); -#else - using namespace asio; - return asio_handler_allocate(s, h); -#endif -} - -template -inline void deallocate(void* p, std::size_t s, Handler* h) -{ -#if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564)) - ::operator delete(p); -#else - using namespace asio; - asio_handler_deallocate(p, s, h); -#endif -} - -} // namespace asio_handler_alloc_helpers - -namespace asio { -namespace detail { - -// Traits for handler allocation. -template -struct handler_alloc_traits -{ - typedef Handler handler_type; - typedef Object value_type; - typedef Object* pointer_type; - BOOST_STATIC_CONSTANT(std::size_t, value_size = sizeof(Object)); -}; - -template -class handler_ptr; - -// Helper class to provide RAII on uninitialised handler memory. -template -class raw_handler_ptr - : private noncopyable -{ -public: - typedef typename Alloc_Traits::handler_type handler_type; - typedef typename Alloc_Traits::value_type value_type; - typedef typename Alloc_Traits::pointer_type pointer_type; - BOOST_STATIC_CONSTANT(std::size_t, value_size = Alloc_Traits::value_size); - - // Constructor allocates the memory. - raw_handler_ptr(handler_type& handler) - : handler_(handler), - pointer_(static_cast( - asio_handler_alloc_helpers::allocate(value_size, &handler_))) - { - } - - // Destructor automatically deallocates memory, unless it has been stolen by - // a handler_ptr object. - ~raw_handler_ptr() - { - if (pointer_) - asio_handler_alloc_helpers::deallocate( - pointer_, value_size, &handler_); - } - -private: - friend class handler_ptr; - handler_type& handler_; - pointer_type pointer_; -}; - -// Helper class to provide RAII on uninitialised handler memory. -template -class handler_ptr - : private noncopyable -{ -public: - typedef typename Alloc_Traits::handler_type handler_type; - typedef typename Alloc_Traits::value_type value_type; - typedef typename Alloc_Traits::pointer_type pointer_type; - BOOST_STATIC_CONSTANT(std::size_t, value_size = Alloc_Traits::value_size); - typedef raw_handler_ptr raw_ptr_type; - - // Take ownership of existing memory. - handler_ptr(handler_type& handler, pointer_type pointer) - : handler_(handler), - pointer_(pointer) - { - } - - // Construct object in raw memory and take ownership if construction succeeds. - handler_ptr(raw_ptr_type& raw_ptr) - : handler_(raw_ptr.handler_), - pointer_(new (raw_ptr.pointer_) value_type) - { - raw_ptr.pointer_ = 0; - } - - // Construct object in raw memory and take ownership if construction succeeds. - template - handler_ptr(raw_ptr_type& raw_ptr, Arg1& a1) - : handler_(raw_ptr.handler_), - pointer_(new (raw_ptr.pointer_) value_type(a1)) - { - raw_ptr.pointer_ = 0; - } - - // Construct object in raw memory and take ownership if construction succeeds. - template - handler_ptr(raw_ptr_type& raw_ptr, Arg1& a1, Arg2& a2) - : handler_(raw_ptr.handler_), - pointer_(new (raw_ptr.pointer_) value_type(a1, a2)) - { - raw_ptr.pointer_ = 0; - } - - // Construct object in raw memory and take ownership if construction succeeds. - template - handler_ptr(raw_ptr_type& raw_ptr, Arg1& a1, Arg2& a2, Arg3& a3) - : handler_(raw_ptr.handler_), - pointer_(new (raw_ptr.pointer_) value_type(a1, a2, a3)) - { - raw_ptr.pointer_ = 0; - } - - // Construct object in raw memory and take ownership if construction succeeds. - template - handler_ptr(raw_ptr_type& raw_ptr, Arg1& a1, Arg2& a2, Arg3& a3, Arg4& a4) - : handler_(raw_ptr.handler_), - pointer_(new (raw_ptr.pointer_) value_type(a1, a2, a3, a4)) - { - raw_ptr.pointer_ = 0; - } - - // Construct object in raw memory and take ownership if construction succeeds. - template - handler_ptr(raw_ptr_type& raw_ptr, Arg1& a1, Arg2& a2, Arg3& a3, Arg4& a4, - Arg5& a5) - : handler_(raw_ptr.handler_), - pointer_(new (raw_ptr.pointer_) value_type(a1, a2, a3, a4, a5)) - { - raw_ptr.pointer_ = 0; - } - - // Construct object in raw memory and take ownership if construction succeeds. - template - handler_ptr(raw_ptr_type& raw_ptr, Arg1& a1, Arg2& a2, Arg3& a3, Arg4& a4, - Arg5& a5, Arg6& a6) - : handler_(raw_ptr.handler_), - pointer_(new (raw_ptr.pointer_) value_type(a1, a2, a3, a4, a5, a6)) - { - raw_ptr.pointer_ = 0; - } - - // Construct object in raw memory and take ownership if construction succeeds. - template - handler_ptr(raw_ptr_type& raw_ptr, Arg1& a1, Arg2& a2, Arg3& a3, Arg4& a4, - Arg5& a5, Arg6& a6, Arg7& a7) - : handler_(raw_ptr.handler_), - pointer_(new (raw_ptr.pointer_) value_type(a1, a2, a3, a4, a5, a6, a7)) - { - raw_ptr.pointer_ = 0; - } - - // Construct object in raw memory and take ownership if construction succeeds. - template - handler_ptr(raw_ptr_type& raw_ptr, Arg1& a1, Arg2& a2, Arg3& a3, Arg4& a4, - Arg5& a5, Arg6& a6, Arg7& a7, Arg8& a8) - : handler_(raw_ptr.handler_), - pointer_(new (raw_ptr.pointer_) value_type( - a1, a2, a3, a4, a5, a6, a7, a8)) - { - raw_ptr.pointer_ = 0; - } - - // Destructor automatically deallocates memory, unless it has been released. - ~handler_ptr() - { - reset(); - } - - // Get the memory. - pointer_type get() const - { - return pointer_; - } - - // Release ownership of the memory. - pointer_type release() - { - pointer_type tmp = pointer_; - pointer_ = 0; - return tmp; - } - - // Explicitly destroy and deallocate the memory. - void reset() - { - if (pointer_) - { - pointer_->value_type::~value_type(); - asio_handler_alloc_helpers::deallocate( - pointer_, value_size, &handler_); - pointer_ = 0; - } - } - -private: - handler_type& handler_; - pointer_type pointer_; -}; - -} // namespace detail -} // namespace asio - -#include "asio/detail/pop_options.hpp" - -#endif // ASIO_DETAIL_HANDLER_ALLOC_HELPERS_HPP diff --git a/libtorrent/include/asio/detail/handler_base_from_member.hpp b/libtorrent/include/asio/detail/handler_base_from_member.hpp deleted file mode 100644 index 87e16c14b..000000000 --- a/libtorrent/include/asio/detail/handler_base_from_member.hpp +++ /dev/null @@ -1,76 +0,0 @@ -// -// handler_base_from_member.hpp -// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -// -// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -#ifndef ASIO_DETAIL_HANDLER_BASE_FROM_MEMBER_HPP -#define ASIO_DETAIL_HANDLER_BASE_FROM_MEMBER_HPP - -#if defined(_MSC_VER) && (_MSC_VER >= 1200) -# pragma once -#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) - -#include "asio/detail/push_options.hpp" - -#include "asio/detail/handler_alloc_helpers.hpp" -#include "asio/detail/handler_invoke_helpers.hpp" - -namespace asio { -namespace detail { - -// Base class for classes that need a handler data member. Forwards the custom -// allocation and invocation hooks to the contained handler. -template -class handler_base_from_member -{ -public: - handler_base_from_member(Handler handler) - : handler_(handler) - { - } - -//protected: - Handler handler_; - -protected: - // Protected destructor to prevent deletion through this type. - ~handler_base_from_member() - { - } -}; - -template -inline void* asio_handler_allocate(std::size_t size, - handler_base_from_member* this_handler) -{ - return asio_handler_alloc_helpers::allocate( - size, &this_handler->handler_); -} - -template -inline void asio_handler_deallocate(void* pointer, std::size_t size, - handler_base_from_member* this_handler) -{ - asio_handler_alloc_helpers::deallocate( - pointer, size, &this_handler->handler_); -} - -template -inline void asio_handler_invoke(const Function& function, - handler_base_from_member* this_handler) -{ - asio_handler_invoke_helpers::invoke( - function, &this_handler->handler_); -} - -} // namespace detail -} // namespace asio - -#include "asio/detail/pop_options.hpp" - -#endif // ASIO_DETAIL_HANDLER_BASE_FROM_MEMBER_HPP diff --git a/libtorrent/include/asio/detail/handler_invoke_helpers.hpp b/libtorrent/include/asio/detail/handler_invoke_helpers.hpp deleted file mode 100644 index 9bdb049e0..000000000 --- a/libtorrent/include/asio/detail/handler_invoke_helpers.hpp +++ /dev/null @@ -1,47 +0,0 @@ -// -// handler_invoke_helpers.hpp -// ~~~~~~~~~~~~~~~~~~~~~~~~~~ -// -// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -#ifndef ASIO_DETAIL_HANDLER_INVOKE_HELPERS_HPP -#define ASIO_DETAIL_HANDLER_INVOKE_HELPERS_HPP - -#if defined(_MSC_VER) && (_MSC_VER >= 1200) -# pragma once -#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) - -#include "asio/detail/push_options.hpp" - -#include "asio/detail/push_options.hpp" -#include -#include "asio/detail/pop_options.hpp" - -#include "asio/handler_invoke_hook.hpp" - -// Calls to asio_handler_invoke must be made from a namespace that does not -// contain overloads of this function. The asio_handler_invoke_helpers -// namespace is defined here for that purpose. -namespace asio_handler_invoke_helpers { - -template -inline void invoke(const Function& function, Context* context) -{ -#if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564)) - Function tmp(function); - tmp(); -#else - using namespace asio; - asio_handler_invoke(function, context); -#endif -} - -} // namespace asio_handler_invoke_helpers - -#include "asio/detail/pop_options.hpp" - -#endif // ASIO_DETAIL_HANDLER_INVOKE_HELPERS_HPP diff --git a/libtorrent/include/asio/detail/handler_queue.hpp b/libtorrent/include/asio/detail/handler_queue.hpp deleted file mode 100644 index 989f976b2..000000000 --- a/libtorrent/include/asio/detail/handler_queue.hpp +++ /dev/null @@ -1,229 +0,0 @@ -// -// handler_queue.hpp -// ~~~~~~~~~~~~~~~~~ -// -// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -#ifndef ASIO_DETAIL_HANDLER_QUEUE_HPP -#define ASIO_DETAIL_HANDLER_QUEUE_HPP - -#if defined(_MSC_VER) && (_MSC_VER >= 1200) -# pragma once -#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) - -#include "asio/detail/push_options.hpp" - -#include "asio/detail/handler_alloc_helpers.hpp" -#include "asio/detail/handler_invoke_helpers.hpp" -#include "asio/detail/noncopyable.hpp" - -namespace asio { -namespace detail { - -class handler_queue - : private noncopyable -{ -public: - // Base class for handlers in the queue. - class handler - : private noncopyable - { - public: - void invoke() - { - invoke_func_(this); - } - - void destroy() - { - destroy_func_(this); - } - - protected: - typedef void (*invoke_func_type)(handler*); - typedef void (*destroy_func_type)(handler*); - - handler(invoke_func_type invoke_func, - destroy_func_type destroy_func) - : next_(0), - invoke_func_(invoke_func), - destroy_func_(destroy_func) - { - } - - ~handler() - { - } - - private: - friend class handler_queue; - handler* next_; - invoke_func_type invoke_func_; - destroy_func_type destroy_func_; - }; - - // Smart point to manager handler lifetimes. - class scoped_ptr - : private noncopyable - { - public: - explicit scoped_ptr(handler* h) - : handler_(h) - { - } - - ~scoped_ptr() - { - if (handler_) - handler_->destroy(); - } - - handler* get() const - { - return handler_; - } - - handler* release() - { - handler* tmp = handler_; - handler_ = 0; - return tmp; - } - - private: - handler* handler_; - }; - - // Constructor. - handler_queue() - : front_(0), - back_(0) - { - } - - // Wrap a handler to be pushed into the queue. - template - static handler* wrap(Handler h) - { - // Allocate and construct an object to wrap the handler. - typedef handler_wrapper value_type; - typedef handler_alloc_traits alloc_traits; - raw_handler_ptr raw_ptr(h); - handler_ptr ptr(raw_ptr, h); - return ptr.release(); - } - - // Get the handler at the front of the queue. - handler* front() - { - return front_; - } - - // Pop a handler from the front of the queue. - void pop() - { - if (front_) - { - handler* tmp = front_; - front_ = front_->next_; - if (front_ == 0) - back_ = 0; - tmp->next_= 0; - } - } - - // Push a handler on to the back of the queue. - void push(handler* h) - { - h->next_ = 0; - if (back_) - { - back_->next_ = h; - back_ = h; - } - else - { - front_ = back_ = h; - } - } - - // Whether the queue is empty. - bool empty() const - { - return front_ == 0; - } - -private: - // Template wrapper for handlers. - template - class handler_wrapper - : public handler - { - public: - handler_wrapper(Handler h) - : handler( - &handler_wrapper::do_call, - &handler_wrapper::do_destroy), - handler_(h) - { - } - - static void do_call(handler* base) - { - // Take ownership of the handler object. - typedef handler_wrapper this_type; - this_type* h(static_cast(base)); - typedef handler_alloc_traits alloc_traits; - handler_ptr ptr(h->handler_, h); - - // Make a copy of the handler so that the memory can be deallocated before - // the upcall is made. - Handler handler(h->handler_); - - // Free the memory associated with the handler. - ptr.reset(); - - // Make the upcall. - asio_handler_invoke_helpers::invoke(handler, &handler); - } - - static void do_destroy(handler* base) - { - // Take ownership of the handler object. - typedef handler_wrapper this_type; - this_type* h(static_cast(base)); - typedef handler_alloc_traits alloc_traits; - handler_ptr ptr(h->handler_, h); - - // A sub-object of the handler may be the true owner of the memory - // associated with the handler. Consequently, a local copy of the handler - // is required to ensure that any owning sub-object remains valid until - // after we have deallocated the memory here. - Handler handler(h->handler_); - (void)handler; - - // Free the memory associated with the handler. - ptr.reset(); - } - - private: - Handler handler_; - }; - - // The front of the queue. - handler* front_; - - // The back of the queue. - handler* back_; -}; - -} // namespace detail -} // namespace asio - -#include "asio/detail/pop_options.hpp" - -#endif // ASIO_DETAIL_HANDLER_QUEUE_HPP diff --git a/libtorrent/include/asio/detail/hash_map.hpp b/libtorrent/include/asio/detail/hash_map.hpp deleted file mode 100644 index bbbb406f8..000000000 --- a/libtorrent/include/asio/detail/hash_map.hpp +++ /dev/null @@ -1,237 +0,0 @@ -// -// hash_map.hpp -// ~~~~~~~~~~~~ -// -// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -#ifndef ASIO_DETAIL_HASH_MAP_HPP -#define ASIO_DETAIL_HASH_MAP_HPP - -#if defined(_MSC_VER) && (_MSC_VER >= 1200) -# pragma once -#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) - -#include "asio/detail/push_options.hpp" - -#include "asio/detail/push_options.hpp" -#include -#include -#include -#include -#include "asio/detail/pop_options.hpp" - -#include "asio/detail/noncopyable.hpp" -#include "asio/detail/socket_types.hpp" - -namespace asio { -namespace detail { - -template -inline std::size_t calculate_hash_value(const T& t) -{ - return boost::hash_value(t); -} - -#if defined(_WIN64) -inline std::size_t calculate_hash_value(SOCKET s) -{ - return static_cast(s); -} -#endif // defined(_WIN64) - -// Note: assumes K and V are POD types. -template -class hash_map - : private noncopyable -{ -public: - // The type of a value in the map. - typedef std::pair value_type; - - // The type of a non-const iterator over the hash map. - typedef typename std::list::iterator iterator; - - // The type of a const iterator over the hash map. - typedef typename std::list::const_iterator const_iterator; - - // Constructor. - hash_map() - { - // Initialise all buckets to empty. - for (size_t i = 0; i < num_buckets; ++i) - buckets_[i].first = buckets_[i].last = values_.end(); - } - - // Get an iterator for the beginning of the map. - iterator begin() - { - return values_.begin(); - } - - // Get an iterator for the beginning of the map. - const_iterator begin() const - { - return values_.begin(); - } - - // Get an iterator for the end of the map. - iterator end() - { - return values_.end(); - } - - // Get an iterator for the end of the map. - const_iterator end() const - { - return values_.end(); - } - - // Check whether the map is empty. - bool empty() const - { - return values_.empty(); - } - - // Find an entry in the map. - iterator find(const K& k) - { - size_t bucket = calculate_hash_value(k) % num_buckets; - iterator it = buckets_[bucket].first; - if (it == values_.end()) - return values_.end(); - iterator end = buckets_[bucket].last; - ++end; - while (it != end) - { - if (it->first == k) - return it; - ++it; - } - return values_.end(); - } - - // Find an entry in the map. - const_iterator find(const K& k) const - { - size_t bucket = calculate_hash_value(k) % num_buckets; - const_iterator it = buckets_[bucket].first; - if (it == values_.end()) - return it; - const_iterator end = buckets_[bucket].last; - ++end; - while (it != end) - { - if (it->first == k) - return it; - ++it; - } - return values_.end(); - } - - // Insert a new entry into the map. - std::pair insert(const value_type& v) - { - size_t bucket = calculate_hash_value(v.first) % num_buckets; - iterator it = buckets_[bucket].first; - if (it == values_.end()) - { - buckets_[bucket].first = buckets_[bucket].last = - values_insert(values_.end(), v); - return std::pair(buckets_[bucket].last, true); - } - iterator end = buckets_[bucket].last; - ++end; - while (it != end) - { - if (it->first == v.first) - return std::pair(it, false); - ++it; - } - buckets_[bucket].last = values_insert(end, v); - return std::pair(buckets_[bucket].last, true); - } - - // Erase an entry from the map. - void erase(iterator it) - { - assert(it != values_.end()); - - size_t bucket = calculate_hash_value(it->first) % num_buckets; - bool is_first = (it == buckets_[bucket].first); - bool is_last = (it == buckets_[bucket].last); - if (is_first && is_last) - buckets_[bucket].first = buckets_[bucket].last = values_.end(); - else if (is_first) - ++buckets_[bucket].first; - else if (is_last) - --buckets_[bucket].last; - - values_erase(it); - } - - // Remove all entries from the map. - void clear() - { - // Clear the values. - values_.clear(); - - // Initialise all buckets to empty. - for (size_t i = 0; i < num_buckets; ++i) - buckets_[i].first = buckets_[i].last = values_.end(); - } - -private: - // Insert an element into the values list by splicing from the spares list, - // if a spare is available, and otherwise by inserting a new element. - iterator values_insert(iterator it, const value_type& v) - { - if (spares_.empty()) - { - return values_.insert(it, v); - } - else - { - spares_.front() = v; - values_.splice(it, spares_, spares_.begin()); - return --it; - } - } - - // Erase an element from the values list by splicing it to the spares list. - void values_erase(iterator it) - { - *it = value_type(); - spares_.splice(spares_.begin(), values_, it); - } - - // The list of all values in the hash map. - std::list values_; - - // The list of spare nodes waiting to be recycled. Assumes that POD types only - // are stored in the hash map. - std::list spares_; - - // The type for a bucket in the hash table. - struct bucket_type - { - iterator first; - iterator last; - }; - - // The number of buckets in the hash. - enum { num_buckets = 1021 }; - - // The buckets in the hash. - bucket_type buckets_[num_buckets]; -}; - -} // namespace detail -} // namespace asio - -#include "asio/detail/pop_options.hpp" - -#endif // ASIO_DETAIL_HASH_MAP_HPP diff --git a/libtorrent/include/asio/detail/indirect_handler_queue.hpp b/libtorrent/include/asio/detail/indirect_handler_queue.hpp deleted file mode 100644 index d08a7df4d..000000000 --- a/libtorrent/include/asio/detail/indirect_handler_queue.hpp +++ /dev/null @@ -1,291 +0,0 @@ -// -// indirect_handler_queue.hpp -// ~~~~~~~~~~~~~~~~~~~~~~~~~~ -// -// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -#ifndef ASIO_DETAIL_INDIRECT_HANDLER_QUEUE_HPP -#define ASIO_DETAIL_INDIRECT_HANDLER_QUEUE_HPP - -#if defined(_MSC_VER) && (_MSC_VER >= 1200) -# pragma once -#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) - -#include "asio/detail/push_options.hpp" - -#include "asio/detail/handler_alloc_helpers.hpp" -#include "asio/detail/handler_invoke_helpers.hpp" -#include "asio/detail/noncopyable.hpp" - -#if defined(_MSC_VER) && (_MSC_VER >= 1310) -extern "C" void _ReadWriteBarrier(); -# pragma intrinsic(_ReadWriteBarrier) -#endif // defined(_MSC_VER) && (_MSC_VER >= 1310) - -namespace asio { -namespace detail { - -class indirect_handler_queue - : private noncopyable -{ -public: - class handler; - - // Element for a node in the queue. - class node - { - public: - node() - : version_(0), - handler_(0), - next_(0) - { - } - - private: - friend class indirect_handler_queue; - unsigned long version_; - handler* handler_; - node* next_; - }; - - // Base class for handlers in the queue. - class handler - : private noncopyable - { - public: - void invoke() - { - invoke_func_(this); - } - - void destroy() - { - destroy_func_(this); - } - - protected: - typedef void (*invoke_func_type)(handler*); - typedef void (*destroy_func_type)(handler*); - - handler(invoke_func_type invoke_func, - destroy_func_type destroy_func) - : node_(new node), - invoke_func_(invoke_func), - destroy_func_(destroy_func) - { - } - - ~handler() - { - if (node_) - delete node_; - } - - private: - friend class indirect_handler_queue; - node* node_; - invoke_func_type invoke_func_; - destroy_func_type destroy_func_; - }; - - // Smart point to manager handler lifetimes. - class scoped_ptr - : private noncopyable - { - public: - explicit scoped_ptr(handler* h) - : handler_(h) - { - } - - ~scoped_ptr() - { - if (handler_) - handler_->destroy(); - } - - handler* get() const - { - return handler_; - } - - handler* release() - { - handler* tmp = handler_; - handler_ = 0; - return tmp; - } - - private: - handler* handler_; - }; - - // Constructor. - indirect_handler_queue() - : front_(new node), - back_(front_), - next_version_(1) - { - } - - // Destructor. - ~indirect_handler_queue() - { - while (front_) - { - node* tmp = front_; - front_ = front_->next_; - delete tmp; - } - } - - // Wrap a handler to be pushed into the queue. - template - static handler* wrap(Handler h) - { - // Allocate and construct an object to wrap the handler. - typedef handler_wrapper value_type; - typedef handler_alloc_traits alloc_traits; - raw_handler_ptr raw_ptr(h); - handler_ptr ptr(raw_ptr, h); - return ptr.release(); - } - - // Determine whether the queue has something ready to pop. - bool poppable() - { - return front_->next_ != 0; - } - - // The version number at the front of the queue. - unsigned long front_version() - { - return front_->version_; - } - - // The version number at the back of the queue. - unsigned long back_version() - { - return back_->version_; - } - - // Pop a handler from the front of the queue. - handler* pop() - { - node* n = front_; - node* new_front = n->next_; - if (new_front) - { - handler* h = new_front->handler_; - h->node_ = n; - new_front->handler_ = 0; - front_ = new_front; - return h; - } - return 0; - } - - // Push a handler on to the back of the queue. - void push(handler* h) - { - node* n = h->node_; - h->node_ = 0; - n->version_ = next_version_; - next_version_ += 2; - n->handler_ = h; - n->next_ = 0; - memory_barrier(); - back_->next_ = n; - back_ = n; - } - -private: - // Template wrapper for handlers. - template - class handler_wrapper - : public handler - { - public: - handler_wrapper(Handler h) - : handler( - &handler_wrapper::do_call, - &handler_wrapper::do_destroy), - handler_(h) - { - } - - static void do_call(handler* base) - { - // Take ownership of the handler object. - typedef handler_wrapper this_type; - this_type* h(static_cast(base)); - typedef handler_alloc_traits alloc_traits; - handler_ptr ptr(h->handler_, h); - - // Make a copy of the handler so that the memory can be deallocated before - // the upcall is made. - Handler handler(h->handler_); - - // Free the memory associated with the handler. - ptr.reset(); - - // Make the upcall. - asio_handler_invoke_helpers::invoke(handler, &handler); - } - - static void do_destroy(handler* base) - { - // Take ownership of the handler object. - typedef handler_wrapper this_type; - this_type* h(static_cast(base)); - typedef handler_alloc_traits alloc_traits; - handler_ptr ptr(h->handler_, h); - - // A sub-object of the handler may be the true owner of the memory - // associated with the handler. Consequently, a local copy of the handler - // is required to ensure that any owning sub-object remains valid until - // after we have deallocated the memory here. - Handler handler(h->handler_); - (void)handler; - - // Free the memory associated with the handler. - ptr.reset(); - } - - private: - Handler handler_; - }; - - // Helper function to create a memory barrier. - static void memory_barrier() - { -#if defined(_GLIBCXX_WRITE_MEM_BARRIER) - _GLIBCXX_WRITE_MEM_BARRIER; -#elif defined(_MSC_VER) && (_MSC_VER >= 1310) - _ReadWriteBarrier(); -#else -# error memory barrier required -#endif - } - - // The front of the queue. - node* front_; - - // The back of the queue. - node* back_; - - // The next version counter to be assigned to a node. - unsigned long next_version_; -}; - -} // namespace detail -} // namespace asio - -#include "asio/detail/pop_options.hpp" - -#endif // ASIO_DETAIL_INDIRECT_HANDLER_QUEUE_HPP diff --git a/libtorrent/include/asio/detail/io_control.hpp b/libtorrent/include/asio/detail/io_control.hpp deleted file mode 100644 index cc1867857..000000000 --- a/libtorrent/include/asio/detail/io_control.hpp +++ /dev/null @@ -1,137 +0,0 @@ -// -// io_control.hpp -// ~~~~~~~~~~~~~~ -// -// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -#ifndef ASIO_DETAIL_IO_CONTROL_HPP -#define ASIO_DETAIL_IO_CONTROL_HPP - -#if defined(_MSC_VER) && (_MSC_VER >= 1200) -# pragma once -#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) - -#include "asio/detail/push_options.hpp" - -#include "asio/detail/push_options.hpp" -#include -#include -#include "asio/detail/pop_options.hpp" - -#include "asio/detail/socket_types.hpp" - -namespace asio { -namespace detail { -namespace io_control { - -// IO control command for non-blocking I/O. -class non_blocking_io -{ -public: - // Default constructor. - non_blocking_io() - : value_(0) - { - } - - // Construct with a specific command value. - non_blocking_io(bool value) - : value_(value ? 1 : 0) - { - } - - // Get the name of the IO control command. - int name() const - { - return FIONBIO; - } - - // Set the value of the I/O control command. - void set(bool value) - { - value_ = value ? 1 : 0; - } - - // Get the current value of the I/O control command. - bool get() const - { - return value_ != 0; - } - - // Get the address of the command data. - detail::ioctl_arg_type* data() - { - return &value_; - } - - // Get the address of the command data. - const detail::ioctl_arg_type* data() const - { - return &value_; - } - -private: - detail::ioctl_arg_type value_; -}; - -// I/O control command for getting number of bytes available. -class bytes_readable -{ -public: - // Default constructor. - bytes_readable() - : value_(0) - { - } - - // Construct with a specific command value. - bytes_readable(std::size_t value) - : value_(static_cast(value)) - { - } - - // Get the name of the IO control command. - int name() const - { - return FIONREAD; - } - - // Set the value of the I/O control command. - void set(std::size_t value) - { - value_ = static_cast(value); - } - - // Get the current value of the I/O control command. - std::size_t get() const - { - return static_cast(value_); - } - - // Get the address of the command data. - detail::ioctl_arg_type* data() - { - return &value_; - } - - // Get the address of the command data. - const detail::ioctl_arg_type* data() const - { - return &value_; - } - -private: - detail::ioctl_arg_type value_; -}; - -} // namespace io_control -} // namespace detail -} // namespace asio - -#include "asio/detail/pop_options.hpp" - -#endif // ASIO_DETAIL_IO_CONTROL_HPP diff --git a/libtorrent/include/asio/detail/kqueue_reactor.hpp b/libtorrent/include/asio/detail/kqueue_reactor.hpp deleted file mode 100644 index 1d0d21aba..000000000 --- a/libtorrent/include/asio/detail/kqueue_reactor.hpp +++ /dev/null @@ -1,702 +0,0 @@ -// -// kqueue_reactor.hpp -// ~~~~~~~~~~~~~~~~~~ -// -// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// Copyright (c) 2005 Stefan Arentz (stefan at soze dot com) -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -#ifndef ASIO_DETAIL_KQUEUE_REACTOR_HPP -#define ASIO_DETAIL_KQUEUE_REACTOR_HPP - -#if defined(_MSC_VER) && (_MSC_VER >= 1200) -# pragma once -#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) - -#include "asio/detail/push_options.hpp" - -#include "asio/detail/kqueue_reactor_fwd.hpp" - -#if defined(ASIO_HAS_KQUEUE) - -#include "asio/detail/push_options.hpp" -#include -#include -#include -#include -#include -#include -#include -#include -#include "asio/detail/pop_options.hpp" - -#include "asio/error.hpp" -#include "asio/io_service.hpp" -#include "asio/system_error.hpp" -#include "asio/detail/bind_handler.hpp" -#include "asio/detail/mutex.hpp" -#include "asio/detail/task_io_service.hpp" -#include "asio/detail/thread.hpp" -#include "asio/detail/reactor_op_queue.hpp" -#include "asio/detail/select_interrupter.hpp" -#include "asio/detail/service_base.hpp" -#include "asio/detail/signal_blocker.hpp" -#include "asio/detail/socket_types.hpp" -#include "asio/detail/timer_queue.hpp" - -// Older versions of Mac OS X may not define EV_OOBAND. -#if !defined(EV_OOBAND) -# define EV_OOBAND EV_FLAG1 -#endif // !defined(EV_OOBAND) - -namespace asio { -namespace detail { - -template -class kqueue_reactor - : public asio::detail::service_base > -{ -public: - // Per-descriptor data. - struct per_descriptor_data - { - bool allow_speculative_read; - bool allow_speculative_write; - }; - - // Constructor. - kqueue_reactor(asio::io_service& io_service) - : asio::detail::service_base< - kqueue_reactor >(io_service), - mutex_(), - kqueue_fd_(do_kqueue_create()), - wait_in_progress_(false), - interrupter_(), - read_op_queue_(), - write_op_queue_(), - except_op_queue_(), - pending_cancellations_(), - stop_thread_(false), - thread_(0), - shutdown_(false), - need_kqueue_wait_(true) - { - // Start the reactor's internal thread only if needed. - if (Own_Thread) - { - asio::detail::signal_blocker sb; - thread_ = new asio::detail::thread( - bind_handler(&kqueue_reactor::call_run_thread, this)); - } - - // Add the interrupter's descriptor to the kqueue. - struct kevent event; - EV_SET(&event, interrupter_.read_descriptor(), - EVFILT_READ, EV_ADD, 0, 0, 0); - ::kevent(kqueue_fd_, &event, 1, 0, 0, 0); - } - - // Destructor. - ~kqueue_reactor() - { - shutdown_service(); - close(kqueue_fd_); - } - - // Destroy all user-defined handler objects owned by the service. - void shutdown_service() - { - asio::detail::mutex::scoped_lock lock(mutex_); - shutdown_ = true; - stop_thread_ = true; - lock.unlock(); - - if (thread_) - { - interrupter_.interrupt(); - thread_->join(); - delete thread_; - thread_ = 0; - } - - read_op_queue_.destroy_operations(); - write_op_queue_.destroy_operations(); - except_op_queue_.destroy_operations(); - - for (std::size_t i = 0; i < timer_queues_.size(); ++i) - timer_queues_[i]->destroy_timers(); - timer_queues_.clear(); - } - - // Register a socket with the reactor. Returns 0 on success, system error - // code on failure. - int register_descriptor(socket_type, per_descriptor_data& descriptor_data) - { - descriptor_data.allow_speculative_read = true; - descriptor_data.allow_speculative_write = true; - - return 0; - } - - // Start a new read operation. The handler object will be invoked when the - // given descriptor is ready to be read, or an error has occurred. - template - void start_read_op(socket_type descriptor, - per_descriptor_data& descriptor_data, Handler handler, - bool allow_speculative_read = true) - { - if (allow_speculative_read && descriptor_data.allow_speculative_read) - { - asio::error_code ec; - std::size_t bytes_transferred = 0; - if (handler.perform(ec, bytes_transferred)) - { - handler.complete(ec, bytes_transferred); - return; - } - - // We only get one shot at a speculative read in this function. - allow_speculative_read = false; - } - - asio::detail::mutex::scoped_lock lock(mutex_); - - if (shutdown_) - return; - - if (!allow_speculative_read) - need_kqueue_wait_ = true; - else if (!read_op_queue_.has_operation(descriptor)) - { - // Speculative reads are ok as there are no queued read operations. - descriptor_data.allow_speculative_read = true; - - asio::error_code ec; - std::size_t bytes_transferred = 0; - if (handler.perform(ec, bytes_transferred)) - { - handler.complete(ec, bytes_transferred); - return; - } - } - - // Speculative reads are not ok as there will be queued read operations. - descriptor_data.allow_speculative_read = false; - - if (read_op_queue_.enqueue_operation(descriptor, handler)) - { - struct kevent event; - EV_SET(&event, descriptor, EVFILT_READ, EV_ADD, 0, 0, 0); - if (::kevent(kqueue_fd_, &event, 1, 0, 0, 0) == -1) - { - asio::error_code ec(errno, - asio::error::get_system_category()); - read_op_queue_.perform_all_operations(descriptor, ec); - } - } - } - - // Start a new write operation. The handler object will be invoked when the - // given descriptor is ready to be written, or an error has occurred. - template - void start_write_op(socket_type descriptor, - per_descriptor_data& descriptor_data, Handler handler, - bool allow_speculative_write = true) - { - if (allow_speculative_write && descriptor_data.allow_speculative_write) - { - asio::error_code ec; - std::size_t bytes_transferred = 0; - if (handler.perform(ec, bytes_transferred)) - { - handler.complete(ec, bytes_transferred); - return; - } - - // We only get one shot at a speculative write in this function. - allow_speculative_write = false; - } - - asio::detail::mutex::scoped_lock lock(mutex_); - - if (shutdown_) - return; - - if (!allow_speculative_write) - need_kqueue_wait_ = true; - else if (!write_op_queue_.has_operation(descriptor)) - { - // Speculative writes are ok as there are no queued write operations. - descriptor_data.allow_speculative_write = true; - - asio::error_code ec; - std::size_t bytes_transferred = 0; - if (handler.perform(ec, bytes_transferred)) - { - handler.complete(ec, bytes_transferred); - return; - } - } - - // Speculative writes are not ok as there will be queued write operations. - descriptor_data.allow_speculative_write = false; - - if (write_op_queue_.enqueue_operation(descriptor, handler)) - { - struct kevent event; - EV_SET(&event, descriptor, EVFILT_WRITE, EV_ADD, 0, 0, 0); - if (::kevent(kqueue_fd_, &event, 1, 0, 0, 0) == -1) - { - asio::error_code ec(errno, - asio::error::get_system_category()); - write_op_queue_.perform_all_operations(descriptor, ec); - } - } - } - - // Start a new exception operation. The handler object will be invoked when - // the given descriptor has exception information, or an error has occurred. - template - void start_except_op(socket_type descriptor, - per_descriptor_data&, Handler handler) - { - asio::detail::mutex::scoped_lock lock(mutex_); - - if (shutdown_) - return; - - if (except_op_queue_.enqueue_operation(descriptor, handler)) - { - struct kevent event; - if (read_op_queue_.has_operation(descriptor)) - EV_SET(&event, descriptor, EVFILT_READ, EV_ADD, 0, 0, 0); - else - EV_SET(&event, descriptor, EVFILT_READ, EV_ADD, EV_OOBAND, 0, 0); - if (::kevent(kqueue_fd_, &event, 1, 0, 0, 0) == -1) - { - asio::error_code ec(errno, - asio::error::get_system_category()); - except_op_queue_.perform_all_operations(descriptor, ec); - } - } - } - - // Start a new write operation. The handler object will be invoked when the - // given descriptor is ready to be written, or an error has occurred. - template - void start_connect_op(socket_type descriptor, - per_descriptor_data& descriptor_data, Handler handler) - { - asio::detail::mutex::scoped_lock lock(mutex_); - - if (shutdown_) - return; - - // Speculative writes are not ok as there will be queued write operations. - descriptor_data.allow_speculative_write = false; - - if (write_op_queue_.enqueue_operation(descriptor, handler)) - { - struct kevent event; - EV_SET(&event, descriptor, EVFILT_WRITE, EV_ADD, 0, 0, 0); - if (::kevent(kqueue_fd_, &event, 1, 0, 0, 0) == -1) - { - asio::error_code ec(errno, - asio::error::get_system_category()); - write_op_queue_.perform_all_operations(descriptor, ec); - } - } - } - - // Cancel all operations associated with the given descriptor. The - // handlers associated with the descriptor will be invoked with the - // operation_aborted error. - void cancel_ops(socket_type descriptor, per_descriptor_data&) - { - asio::detail::mutex::scoped_lock lock(mutex_); - cancel_ops_unlocked(descriptor); - } - - // Cancel any operations that are running against the descriptor and remove - // its registration from the reactor. - void close_descriptor(socket_type descriptor, per_descriptor_data&) - { - asio::detail::mutex::scoped_lock lock(mutex_); - - // Remove the descriptor from kqueue. - struct kevent event[2]; - EV_SET(&event[0], descriptor, EVFILT_READ, EV_DELETE, 0, 0, 0); - EV_SET(&event[1], descriptor, EVFILT_WRITE, EV_DELETE, 0, 0, 0); - ::kevent(kqueue_fd_, event, 2, 0, 0, 0); - - // Cancel any outstanding operations associated with the descriptor. - cancel_ops_unlocked(descriptor); - } - - // Add a new timer queue to the reactor. - template - void add_timer_queue(timer_queue& timer_queue) - { - asio::detail::mutex::scoped_lock lock(mutex_); - timer_queues_.push_back(&timer_queue); - } - - // Remove a timer queue from the reactor. - template - void remove_timer_queue(timer_queue& timer_queue) - { - asio::detail::mutex::scoped_lock lock(mutex_); - for (std::size_t i = 0; i < timer_queues_.size(); ++i) - { - if (timer_queues_[i] == &timer_queue) - { - timer_queues_.erase(timer_queues_.begin() + i); - return; - } - } - } - - // Schedule a timer in the given timer queue to expire at the specified - // absolute time. The handler object will be invoked when the timer expires. - template - void schedule_timer(timer_queue& timer_queue, - const typename Time_Traits::time_type& time, Handler handler, void* token) - { - asio::detail::mutex::scoped_lock lock(mutex_); - if (!shutdown_) - if (timer_queue.enqueue_timer(time, handler, token)) - interrupter_.interrupt(); - } - - // Cancel the timer associated with the given token. Returns the number of - // handlers that have been posted or dispatched. - template - std::size_t cancel_timer(timer_queue& timer_queue, void* token) - { - asio::detail::mutex::scoped_lock lock(mutex_); - std::size_t n = timer_queue.cancel_timer(token); - if (n > 0) - interrupter_.interrupt(); - return n; - } - -private: - friend class task_io_service >; - - // Run the kqueue loop. - void run(bool block) - { - asio::detail::mutex::scoped_lock lock(mutex_); - - // Dispatch any operation cancellations that were made while the select - // loop was not running. - read_op_queue_.perform_cancellations(); - write_op_queue_.perform_cancellations(); - except_op_queue_.perform_cancellations(); - for (std::size_t i = 0; i < timer_queues_.size(); ++i) - timer_queues_[i]->dispatch_cancellations(); - - // Check if the thread is supposed to stop. - if (stop_thread_) - { - complete_operations_and_timers(lock); - return; - } - - // We can return immediately if there's no work to do and the reactor is - // not supposed to block. - if (!block && read_op_queue_.empty() && write_op_queue_.empty() - && except_op_queue_.empty() && all_timer_queues_are_empty()) - { - complete_operations_and_timers(lock); - return; - } - - // Determine how long to block while waiting for events. - timespec timeout_buf = { 0, 0 }; - timespec* timeout = block ? get_timeout(timeout_buf) : &timeout_buf; - - wait_in_progress_ = true; - lock.unlock(); - - // Block on the kqueue descriptor. - struct kevent events[128]; - int num_events = (block || need_kqueue_wait_) - ? kevent(kqueue_fd_, 0, 0, events, 128, timeout) - : 0; - - lock.lock(); - wait_in_progress_ = false; - - // Block signals while performing operations. - asio::detail::signal_blocker sb; - - // Dispatch the waiting events. - for (int i = 0; i < num_events; ++i) - { - int descriptor = events[i].ident; - if (descriptor == interrupter_.read_descriptor()) - { - interrupter_.reset(); - } - else if (events[i].filter == EVFILT_READ) - { - // Dispatch operations associated with the descriptor. - bool more_reads = false; - bool more_except = false; - if (events[i].flags & EV_ERROR) - { - asio::error_code error( - events[i].data, asio::error::get_system_category()); - except_op_queue_.perform_all_operations(descriptor, error); - read_op_queue_.perform_all_operations(descriptor, error); - } - else if (events[i].flags & EV_OOBAND) - { - asio::error_code error; - more_except = except_op_queue_.perform_operation(descriptor, error); - if (events[i].data > 0) - more_reads = read_op_queue_.perform_operation(descriptor, error); - else - more_reads = read_op_queue_.has_operation(descriptor); - } - else - { - asio::error_code error; - more_reads = read_op_queue_.perform_operation(descriptor, error); - more_except = except_op_queue_.has_operation(descriptor); - } - - // Update the descriptor in the kqueue. - struct kevent event; - if (more_reads) - EV_SET(&event, descriptor, EVFILT_READ, EV_ADD, 0, 0, 0); - else if (more_except) - EV_SET(&event, descriptor, EVFILT_READ, EV_ADD, EV_OOBAND, 0, 0); - else - EV_SET(&event, descriptor, EVFILT_READ, EV_DELETE, 0, 0, 0); - if (::kevent(kqueue_fd_, &event, 1, 0, 0, 0) == -1) - { - asio::error_code error(errno, - asio::error::get_system_category()); - except_op_queue_.perform_all_operations(descriptor, error); - read_op_queue_.perform_all_operations(descriptor, error); - } - } - else if (events[i].filter == EVFILT_WRITE) - { - // Dispatch operations associated with the descriptor. - bool more_writes = false; - if (events[i].flags & EV_ERROR) - { - asio::error_code error( - events[i].data, asio::error::get_system_category()); - write_op_queue_.perform_all_operations(descriptor, error); - } - else - { - asio::error_code error; - more_writes = write_op_queue_.perform_operation(descriptor, error); - } - - // Update the descriptor in the kqueue. - struct kevent event; - if (more_writes) - EV_SET(&event, descriptor, EVFILT_WRITE, EV_ADD, 0, 0, 0); - else - EV_SET(&event, descriptor, EVFILT_WRITE, EV_DELETE, 0, 0, 0); - if (::kevent(kqueue_fd_, &event, 1, 0, 0, 0) == -1) - { - asio::error_code error(errno, - asio::error::get_system_category()); - write_op_queue_.perform_all_operations(descriptor, error); - } - } - } - - read_op_queue_.perform_cancellations(); - write_op_queue_.perform_cancellations(); - except_op_queue_.perform_cancellations(); - for (std::size_t i = 0; i < timer_queues_.size(); ++i) - { - timer_queues_[i]->dispatch_timers(); - timer_queues_[i]->dispatch_cancellations(); - } - - // Issue any pending cancellations. - for (std::size_t i = 0; i < pending_cancellations_.size(); ++i) - cancel_ops_unlocked(pending_cancellations_[i]); - pending_cancellations_.clear(); - - // Determine whether kqueue needs to be called next time the reactor is run. - need_kqueue_wait_ = !read_op_queue_.empty() - || !write_op_queue_.empty() || !except_op_queue_.empty(); - - complete_operations_and_timers(lock); - } - - // Run the select loop in the thread. - void run_thread() - { - asio::detail::mutex::scoped_lock lock(mutex_); - while (!stop_thread_) - { - lock.unlock(); - run(true); - lock.lock(); - } - } - - // Entry point for the select loop thread. - static void call_run_thread(kqueue_reactor* reactor) - { - reactor->run_thread(); - } - - // Interrupt the select loop. - void interrupt() - { - interrupter_.interrupt(); - } - - // Create the kqueue file descriptor. Throws an exception if the descriptor - // cannot be created. - static int do_kqueue_create() - { - int fd = kqueue(); - if (fd == -1) - { - boost::throw_exception( - asio::system_error( - asio::error_code(errno, - asio::error::get_system_category()), - "kqueue")); - } - return fd; - } - - // Check if all timer queues are empty. - bool all_timer_queues_are_empty() const - { - for (std::size_t i = 0; i < timer_queues_.size(); ++i) - if (!timer_queues_[i]->empty()) - return false; - return true; - } - - // Get the timeout value for the kevent call. - timespec* get_timeout(timespec& ts) - { - if (all_timer_queues_are_empty()) - return 0; - - // By default we will wait no longer than 5 minutes. This will ensure that - // any changes to the system clock are detected after no longer than this. - boost::posix_time::time_duration minimum_wait_duration - = boost::posix_time::minutes(5); - - for (std::size_t i = 0; i < timer_queues_.size(); ++i) - { - boost::posix_time::time_duration wait_duration - = timer_queues_[i]->wait_duration(); - if (wait_duration < minimum_wait_duration) - minimum_wait_duration = wait_duration; - } - - if (minimum_wait_duration > boost::posix_time::time_duration()) - { - ts.tv_sec = minimum_wait_duration.total_seconds(); - ts.tv_nsec = minimum_wait_duration.total_nanoseconds() % 1000000000; - } - else - { - ts.tv_sec = 0; - ts.tv_nsec = 0; - } - - return &ts; - } - - // Cancel all operations associated with the given descriptor. The do_cancel - // function of the handler objects will be invoked. This function does not - // acquire the kqueue_reactor's mutex. - void cancel_ops_unlocked(socket_type descriptor) - { - bool interrupt = read_op_queue_.cancel_operations(descriptor); - interrupt = write_op_queue_.cancel_operations(descriptor) || interrupt; - interrupt = except_op_queue_.cancel_operations(descriptor) || interrupt; - if (interrupt) - interrupter_.interrupt(); - } - - // Clean up operations and timers. We must not hold the lock since the - // destructors may make calls back into this reactor. We make a copy of the - // vector of timer queues since the original may be modified while the lock - // is not held. - void complete_operations_and_timers( - asio::detail::mutex::scoped_lock& lock) - { - timer_queues_for_cleanup_ = timer_queues_; - lock.unlock(); - read_op_queue_.complete_operations(); - write_op_queue_.complete_operations(); - except_op_queue_.complete_operations(); - for (std::size_t i = 0; i < timer_queues_for_cleanup_.size(); ++i) - timer_queues_for_cleanup_[i]->complete_timers(); - } - - // Mutex to protect access to internal data. - asio::detail::mutex mutex_; - - // The kqueue file descriptor. - int kqueue_fd_; - - // Whether the kqueue wait call is currently in progress - bool wait_in_progress_; - - // The interrupter is used to break a blocking kevent call. - select_interrupter interrupter_; - - // The queue of read operations. - reactor_op_queue read_op_queue_; - - // The queue of write operations. - reactor_op_queue write_op_queue_; - - // The queue of except operations. - reactor_op_queue except_op_queue_; - - // The timer queues. - std::vector timer_queues_; - - // A copy of the timer queues, used when cleaning up timers. The copy is - // stored as a class data member to avoid unnecessary memory allocation. - std::vector timer_queues_for_cleanup_; - - // The descriptors that are pending cancellation. - std::vector pending_cancellations_; - - // Does the reactor loop thread need to stop. - bool stop_thread_; - - // The thread that is running the reactor loop. - asio::detail::thread* thread_; - - // Whether the service has been shut down. - bool shutdown_; - - // Whether we need to call kqueue the next time the reactor is run. - bool need_kqueue_wait_; -}; - -} // namespace detail -} // namespace asio - -#endif // defined(ASIO_HAS_KQUEUE) - -#include "asio/detail/pop_options.hpp" - -#endif // ASIO_DETAIL_KQUEUE_REACTOR_HPP diff --git a/libtorrent/include/asio/detail/kqueue_reactor_fwd.hpp b/libtorrent/include/asio/detail/kqueue_reactor_fwd.hpp deleted file mode 100644 index c81858f3b..000000000 --- a/libtorrent/include/asio/detail/kqueue_reactor_fwd.hpp +++ /dev/null @@ -1,41 +0,0 @@ -// -// kqueue_reactor_fwd.hpp -// ~~~~~~~~~~~~~~~~~~~~~~ -// -// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// Copyright (c) 2005 Stefan Arentz (stefan at soze dot com) -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -#ifndef ASIO_DETAIL_KQUEUE_REACTOR_FWD_HPP -#define ASIO_DETAIL_KQUEUE_REACTOR_FWD_HPP - -#if defined(_MSC_VER) && (_MSC_VER >= 1200) -# pragma once -#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) - -#include "asio/detail/push_options.hpp" - -#if !defined(ASIO_DISABLE_KQUEUE) -#if defined(__MACH__) && defined(__APPLE__) - -// Define this to indicate that epoll is supported on the target platform. -#define ASIO_HAS_KQUEUE 1 - -namespace asio { -namespace detail { - -template -class kqueue_reactor; - -} // namespace detail -} // namespace asio - -#endif // defined(__MACH__) && defined(__APPLE__) -#endif // !defined(ASIO_DISABLE_KQUEUE) - -#include "asio/detail/pop_options.hpp" - -#endif // ASIO_DETAIL_KQUEUE_REACTOR_FWD_HPP diff --git a/libtorrent/include/asio/detail/local_free_on_block_exit.hpp b/libtorrent/include/asio/detail/local_free_on_block_exit.hpp deleted file mode 100644 index e5e7a4d60..000000000 --- a/libtorrent/include/asio/detail/local_free_on_block_exit.hpp +++ /dev/null @@ -1,59 +0,0 @@ -// -// local_free_on_block_exit.hpp -// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -// -// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -#ifndef ASIO_DETAIL_LOCAL_FREE_ON_BLOCK_EXIT_HPP -#define ASIO_DETAIL_LOCAL_FREE_ON_BLOCK_EXIT_HPP - -#if defined(_MSC_VER) && (_MSC_VER >= 1200) -# pragma once -#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) - -#include "asio/detail/push_options.hpp" - -#include "asio/detail/push_options.hpp" -#include -#include "asio/detail/pop_options.hpp" - -#if defined(BOOST_WINDOWS) || defined(__CYGWIN__) - -#include "asio/detail/noncopyable.hpp" -#include "asio/detail/socket_types.hpp" - -namespace asio { -namespace detail { - -class local_free_on_block_exit - : private noncopyable -{ -public: - // Constructor blocks all signals for the calling thread. - explicit local_free_on_block_exit(void* p) - : p_(p) - { - } - - // Destructor restores the previous signal mask. - ~local_free_on_block_exit() - { - ::LocalFree(p_); - } - -private: - void* p_; -}; - -} // namespace detail -} // namespace asio - -#endif // defined(BOOST_WINDOWS) || defined(__CYGWIN__) - -#include "asio/detail/pop_options.hpp" - -#endif // ASIO_DETAIL_LOCAL_FREE_ON_BLOCK_EXIT_HPP diff --git a/libtorrent/include/asio/detail/mutex.hpp b/libtorrent/include/asio/detail/mutex.hpp deleted file mode 100644 index 9c083f661..000000000 --- a/libtorrent/include/asio/detail/mutex.hpp +++ /dev/null @@ -1,50 +0,0 @@ -// -// mutex.hpp -// ~~~~~~~~~ -// -// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -#ifndef ASIO_DETAIL_MUTEX_HPP -#define ASIO_DETAIL_MUTEX_HPP - -#if defined(_MSC_VER) && (_MSC_VER >= 1200) -# pragma once -#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) - -#include "asio/detail/push_options.hpp" - -#include "asio/detail/push_options.hpp" -#include -#include "asio/detail/pop_options.hpp" - -#if !defined(BOOST_HAS_THREADS) -# include "asio/detail/null_mutex.hpp" -#elif defined(BOOST_WINDOWS) -# include "asio/detail/win_mutex.hpp" -#elif defined(BOOST_HAS_PTHREADS) -# include "asio/detail/posix_mutex.hpp" -#else -# error Only Windows and POSIX are supported! -#endif - -namespace asio { -namespace detail { - -#if !defined(BOOST_HAS_THREADS) -typedef null_mutex mutex; -#elif defined(BOOST_WINDOWS) -typedef win_mutex mutex; -#elif defined(BOOST_HAS_PTHREADS) -typedef posix_mutex mutex; -#endif - -} // namespace detail -} // namespace asio - -#include "asio/detail/pop_options.hpp" - -#endif // ASIO_DETAIL_MUTEX_HPP diff --git a/libtorrent/include/asio/detail/noncopyable.hpp b/libtorrent/include/asio/detail/noncopyable.hpp deleted file mode 100644 index 5164e07e6..000000000 --- a/libtorrent/include/asio/detail/noncopyable.hpp +++ /dev/null @@ -1,55 +0,0 @@ -// -// noncopyable.hpp -// ~~~~~~~~~~~~~~~ -// -// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -#ifndef ASIO_DETAIL_NONCOPYABLE_HPP -#define ASIO_DETAIL_NONCOPYABLE_HPP - -#if defined(_MSC_VER) && (_MSC_VER >= 1200) -# pragma once -#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) - -#include "asio/detail/push_options.hpp" - -#include "asio/detail/push_options.hpp" -#include -#include -#include -#include "asio/detail/pop_options.hpp" - -namespace asio { -namespace detail { - -#if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564)) -// Redefine the noncopyable class for Borland C++ since that compiler does not -// apply the empty base optimisation unless the base class contains a dummy -// char data member. -class noncopyable -{ -protected: - noncopyable() {} - ~noncopyable() {} -private: - noncopyable(const noncopyable&); - const noncopyable& operator=(const noncopyable&); - char dummy_; -}; -#else -using boost::noncopyable; -#endif - -} // namespace detail - -using asio::detail::noncopyable; - -} // namespace asio - -#include "asio/detail/pop_options.hpp" - -#endif // ASIO_DETAIL_NONCOPYABLE_HPP diff --git a/libtorrent/include/asio/detail/null_event.hpp b/libtorrent/include/asio/detail/null_event.hpp deleted file mode 100644 index 51529e47b..000000000 --- a/libtorrent/include/asio/detail/null_event.hpp +++ /dev/null @@ -1,71 +0,0 @@ -// -// null_event.hpp -// ~~~~~~~~~~~~~~ -// -// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -#ifndef ASIO_DETAIL_NULL_EVENT_HPP -#define ASIO_DETAIL_NULL_EVENT_HPP - -#if defined(_MSC_VER) && (_MSC_VER >= 1200) -# pragma once -#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) - -#include "asio/detail/push_options.hpp" - -#include "asio/detail/push_options.hpp" -#include -#include "asio/detail/pop_options.hpp" - -#if !defined(BOOST_HAS_THREADS) - -#include "asio/detail/noncopyable.hpp" - -namespace asio { -namespace detail { - -class null_event - : private noncopyable -{ -public: - // Constructor. - null_event() - { - } - - // Destructor. - ~null_event() - { - } - - // Signal the event. - template - void signal(Lock&) - { - } - - // Reset the event. - template - void clear(Lock&) - { - } - - // Wait for the event to become signalled. - template - void wait(Lock&) - { - } -}; - -} // namespace detail -} // namespace asio - -#endif // !defined(BOOST_HAS_THREADS) - -#include "asio/detail/pop_options.hpp" - -#endif // ASIO_DETAIL_NULL_EVENT_HPP diff --git a/libtorrent/include/asio/detail/null_mutex.hpp b/libtorrent/include/asio/detail/null_mutex.hpp deleted file mode 100644 index d29aafca9..000000000 --- a/libtorrent/include/asio/detail/null_mutex.hpp +++ /dev/null @@ -1,66 +0,0 @@ -// -// null_mutex.hpp -// ~~~~~~~~~~~~~~ -// -// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -#ifndef ASIO_DETAIL_NULL_MUTEX_HPP -#define ASIO_DETAIL_NULL_MUTEX_HPP - -#if defined(_MSC_VER) && (_MSC_VER >= 1200) -# pragma once -#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) - -#include "asio/detail/push_options.hpp" - -#include "asio/detail/push_options.hpp" -#include -#include "asio/detail/pop_options.hpp" - -#if !defined(BOOST_HAS_THREADS) - -#include "asio/detail/noncopyable.hpp" -#include "asio/detail/scoped_lock.hpp" - -namespace asio { -namespace detail { - -class null_mutex - : private noncopyable -{ -public: - typedef asio::detail::scoped_lock scoped_lock; - - // Constructor. - null_mutex() - { - } - - // Destructor. - ~null_mutex() - { - } - - // Lock the mutex. - void lock() - { - } - - // Unlock the mutex. - void unlock() - { - } -}; - -} // namespace detail -} // namespace asio - -#endif // !defined(BOOST_HAS_THREADS) - -#include "asio/detail/pop_options.hpp" - -#endif // ASIO_DETAIL_NULL_MUTEX_HPP diff --git a/libtorrent/include/asio/detail/null_signal_blocker.hpp b/libtorrent/include/asio/detail/null_signal_blocker.hpp deleted file mode 100644 index 33f23cabe..000000000 --- a/libtorrent/include/asio/detail/null_signal_blocker.hpp +++ /dev/null @@ -1,63 +0,0 @@ -// -// null_signal_blocker.hpp -// ~~~~~~~~~~~~~~~~~~~~~~~ -// -// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -#ifndef ASIO_DETAIL_NULL_SIGNAL_BLOCKER_HPP -#define ASIO_DETAIL_NULL_SIGNAL_BLOCKER_HPP - -#if defined(_MSC_VER) && (_MSC_VER >= 1200) -# pragma once -#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) - -#include "asio/detail/push_options.hpp" - -#include "asio/detail/push_options.hpp" -#include -#include "asio/detail/pop_options.hpp" - -#if !defined(BOOST_HAS_THREADS) - -#include "asio/detail/noncopyable.hpp" - -namespace asio { -namespace detail { - -class null_signal_blocker - : private noncopyable -{ -public: - // Constructor blocks all signals for the calling thread. - null_signal_blocker() - { - } - - // Destructor restores the previous signal mask. - ~null_signal_blocker() - { - } - - // Block all signals for the calling thread. - void block() - { - } - - // Restore the previous signal mask. - void unblock() - { - } -}; - -} // namespace detail -} // namespace asio - -#endif // !defined(BOOST_HAS_THREADS) - -#include "asio/detail/pop_options.hpp" - -#endif // ASIO_DETAIL_NULL_SIGNAL_BLOCKER_HPP diff --git a/libtorrent/include/asio/detail/null_thread.hpp b/libtorrent/include/asio/detail/null_thread.hpp deleted file mode 100644 index f08b7b378..000000000 --- a/libtorrent/include/asio/detail/null_thread.hpp +++ /dev/null @@ -1,71 +0,0 @@ -// -// null_thread.hpp -// ~~~~~~~~~~~~~~~ -// -// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -#ifndef ASIO_DETAIL_NULL_THREAD_HPP -#define ASIO_DETAIL_NULL_THREAD_HPP - -#if defined(_MSC_VER) && (_MSC_VER >= 1200) -# pragma once -#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) - -#include "asio/detail/push_options.hpp" - -#include "asio/detail/push_options.hpp" -#include -#include "asio/detail/pop_options.hpp" - -#if !defined(BOOST_HAS_THREADS) - -#include "asio/detail/push_options.hpp" -#include -#include "asio/detail/pop_options.hpp" - -#include "asio/error.hpp" -#include "asio/system_error.hpp" -#include "asio/detail/noncopyable.hpp" - -namespace asio { -namespace detail { - -class null_thread - : private noncopyable -{ -public: - // The purpose of the thread. - enum purpose { internal, external }; - - // Constructor. - template - null_thread(Function f, purpose = internal) - { - asio::system_error e( - asio::error::operation_not_supported, "thread"); - boost::throw_exception(e); - } - - // Destructor. - ~null_thread() - { - } - - // Wait for the thread to exit. - void join() - { - } -}; - -} // namespace detail -} // namespace asio - -#endif // !defined(BOOST_HAS_THREADS) - -#include "asio/detail/pop_options.hpp" - -#endif // ASIO_DETAIL_NULL_THREAD_HPP diff --git a/libtorrent/include/asio/detail/null_tss_ptr.hpp b/libtorrent/include/asio/detail/null_tss_ptr.hpp deleted file mode 100644 index 0cbdae612..000000000 --- a/libtorrent/include/asio/detail/null_tss_ptr.hpp +++ /dev/null @@ -1,70 +0,0 @@ -// -// null_tss_ptr.hpp -// ~~~~~~~~~~~~~~~~ -// -// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -#ifndef ASIO_DETAIL_NULL_TSS_PTR_HPP -#define ASIO_DETAIL_NULL_TSS_PTR_HPP - -#if defined(_MSC_VER) && (_MSC_VER >= 1200) -# pragma once -#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) - -#include "asio/detail/push_options.hpp" - -#include "asio/detail/push_options.hpp" -#include -#include "asio/detail/pop_options.hpp" - -#if !defined(BOOST_HAS_THREADS) - -#include "asio/detail/noncopyable.hpp" - -namespace asio { -namespace detail { - -template -class null_tss_ptr - : private noncopyable -{ -public: - // Constructor. - null_tss_ptr() - : value_(0) - { - } - - // Destructor. - ~null_tss_ptr() - { - } - - // Get the value. - operator T*() const - { - return value_; - } - - // Set the value. - void operator=(T* value) - { - value_ = value; - } - -private: - T* value_; -}; - -} // namespace detail -} // namespace asio - -#endif // !defined(BOOST_HAS_THREADS) - -#include "asio/detail/pop_options.hpp" - -#endif // ASIO_DETAIL_NULL_TSS_PTR_HPP diff --git a/libtorrent/include/asio/detail/old_win_sdk_compat.hpp b/libtorrent/include/asio/detail/old_win_sdk_compat.hpp deleted file mode 100644 index b73a09012..000000000 --- a/libtorrent/include/asio/detail/old_win_sdk_compat.hpp +++ /dev/null @@ -1,340 +0,0 @@ -// -// old_win_sdk_compat.hpp -// ~~~~~~~~~~~~~~~~~~~~~~ -// -// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -#ifndef ASIO_DETAIL_OLD_WIN_SDK_COMPAT_HPP -#define ASIO_DETAIL_OLD_WIN_SDK_COMPAT_HPP - -#if defined(_MSC_VER) && (_MSC_VER >= 1200) -# pragma once -#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) - -#include "asio/detail/push_options.hpp" - -#include "asio/detail/push_options.hpp" -#include -#include "asio/detail/pop_options.hpp" - -#if defined(BOOST_WINDOWS) || defined(__CYGWIN__) - -// Guess whether we are building against on old Platform SDK. -#if !defined(IN6ADDR_ANY_INIT) -#define ASIO_HAS_OLD_WIN_SDK 1 -#endif // !defined(IN6ADDR_ANY_INIT) - -#if defined(ASIO_HAS_OLD_WIN_SDK) - -// Emulation of types that are missing from old Platform SDKs. -// -// N.B. this emulation is also used if building for a Windows 2000 target with -// a recent (i.e. Vista or later) SDK, as the SDK does not provide IPv6 support -// in that case. - -namespace asio { -namespace detail { - -enum -{ - sockaddr_storage_maxsize = 128, // Maximum size. - sockaddr_storage_alignsize = (sizeof(__int64)), // Desired alignment. - sockaddr_storage_pad1size = (sockaddr_storage_alignsize - sizeof(short)), - sockaddr_storage_pad2size = (sockaddr_storage_maxsize - - (sizeof(short) + sockaddr_storage_pad1size + sockaddr_storage_alignsize)) -}; - -struct sockaddr_storage_emulation -{ - short ss_family; - char __ss_pad1[sockaddr_storage_pad1size]; - __int64 __ss_align; - char __ss_pad2[sockaddr_storage_pad2size]; -}; - -struct in6_addr_emulation -{ - union - { - u_char Byte[16]; - u_short Word[8]; - } u; -}; - -#if !defined(s6_addr) -# define _S6_un u -# define _S6_u8 Byte -# define s6_addr _S6_un._S6_u8 -#endif // !defined(s6_addr) - -struct sockaddr_in6_emulation -{ - short sin6_family; - u_short sin6_port; - u_long sin6_flowinfo; - in6_addr_emulation sin6_addr; - u_long sin6_scope_id; -}; - -struct ipv6_mreq_emulation -{ - in6_addr_emulation ipv6mr_multiaddr; - unsigned int ipv6mr_interface; -}; - -#if !defined(IN6ADDR_ANY_INIT) -# define IN6ADDR_ANY_INIT { 0 } -#endif - -#if !defined(IN6ADDR_LOOPBACK_INIT) -# define IN6ADDR_LOOPBACK_INIT { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1 } -#endif - -struct addrinfo_emulation -{ - int ai_flags; - int ai_family; - int ai_socktype; - int ai_protocol; - size_t ai_addrlen; - char* ai_canonname; - sockaddr* ai_addr; - addrinfo_emulation* ai_next; -}; - -#if !defined(AI_PASSIVE) -# define AI_PASSIVE 0x1 -#endif - -#if !defined(AI_CANONNAME) -# define AI_CANONNAME 0x2 -#endif - -#if !defined(AI_NUMERICHOST) -# define AI_NUMERICHOST 0x4 -#endif - -#if !defined(EAI_AGAIN) -# define EAI_AGAIN WSATRY_AGAIN -#endif - -#if !defined(EAI_BADFLAGS) -# define EAI_BADFLAGS WSAEINVAL -#endif - -#if !defined(EAI_FAIL) -# define EAI_FAIL WSANO_RECOVERY -#endif - -#if !defined(EAI_FAMILY) -# define EAI_FAMILY WSAEAFNOSUPPORT -#endif - -#if !defined(EAI_MEMORY) -# define EAI_MEMORY WSA_NOT_ENOUGH_MEMORY -#endif - -#if !defined(EAI_NODATA) -# define EAI_NODATA WSANO_DATA -#endif - -#if !defined(EAI_NONAME) -# define EAI_NONAME WSAHOST_NOT_FOUND -#endif - -#if !defined(EAI_SERVICE) -# define EAI_SERVICE WSATYPE_NOT_FOUND -#endif - -#if !defined(EAI_SOCKTYPE) -# define EAI_SOCKTYPE WSAESOCKTNOSUPPORT -#endif - -#if !defined(NI_NOFQDN) -# define NI_NOFQDN 0x01 -#endif - -#if !defined(NI_NUMERICHOST) -# define NI_NUMERICHOST 0x02 -#endif - -#if !defined(NI_NAMEREQD) -# define NI_NAMEREQD 0x04 -#endif - -#if !defined(NI_NUMERICSERV) -# define NI_NUMERICSERV 0x08 -#endif - -#if !defined(NI_DGRAM) -# define NI_DGRAM 0x10 -#endif - -#if !defined(IPPROTO_IPV6) -# define IPPROTO_IPV6 41 -#endif - -#if !defined(IPV6_UNICAST_HOPS) -# define IPV6_UNICAST_HOPS 4 -#endif - -#if !defined(IPV6_MULTICAST_IF) -# define IPV6_MULTICAST_IF 9 -#endif - -#if !defined(IPV6_MULTICAST_HOPS) -# define IPV6_MULTICAST_HOPS 10 -#endif - -#if !defined(IPV6_MULTICAST_LOOP) -# define IPV6_MULTICAST_LOOP 11 -#endif - -#if !defined(IPV6_JOIN_GROUP) -# define IPV6_JOIN_GROUP 12 -#endif - -#if !defined(IPV6_LEAVE_GROUP) -# define IPV6_LEAVE_GROUP 13 -#endif - -inline int IN6_IS_ADDR_UNSPECIFIED(const in6_addr_emulation* a) -{ - return ((a->s6_addr[0] == 0) - && (a->s6_addr[1] == 0) - && (a->s6_addr[2] == 0) - && (a->s6_addr[3] == 0) - && (a->s6_addr[4] == 0) - && (a->s6_addr[5] == 0) - && (a->s6_addr[6] == 0) - && (a->s6_addr[7] == 0) - && (a->s6_addr[8] == 0) - && (a->s6_addr[9] == 0) - && (a->s6_addr[10] == 0) - && (a->s6_addr[11] == 0) - && (a->s6_addr[12] == 0) - && (a->s6_addr[13] == 0) - && (a->s6_addr[14] == 0) - && (a->s6_addr[15] == 0)); -} - -inline int IN6_IS_ADDR_LOOPBACK(const in6_addr_emulation* a) -{ - return ((a->s6_addr[0] == 0) - && (a->s6_addr[1] == 0) - && (a->s6_addr[2] == 0) - && (a->s6_addr[3] == 0) - && (a->s6_addr[4] == 0) - && (a->s6_addr[5] == 0) - && (a->s6_addr[6] == 0) - && (a->s6_addr[7] == 0) - && (a->s6_addr[8] == 0) - && (a->s6_addr[9] == 0) - && (a->s6_addr[10] == 0) - && (a->s6_addr[11] == 0) - && (a->s6_addr[12] == 0) - && (a->s6_addr[13] == 0) - && (a->s6_addr[14] == 0) - && (a->s6_addr[15] == 1)); -} - -inline int IN6_IS_ADDR_MULTICAST(const in6_addr_emulation* a) -{ - return (a->s6_addr[0] == 0xff); -} - -inline int IN6_IS_ADDR_LINKLOCAL(const in6_addr_emulation* a) -{ - return ((a->s6_addr[0] == 0xfe) && ((a->s6_addr[1] & 0xc0) == 0x80)); -} - -inline int IN6_IS_ADDR_SITELOCAL(const in6_addr_emulation* a) -{ - return ((a->s6_addr[0] == 0xfe) && ((a->s6_addr[1] & 0xc0) == 0xc0)); -} - -inline int IN6_IS_ADDR_V4MAPPED(const in6_addr_emulation* a) -{ - return ((a->s6_addr[0] == 0) - && (a->s6_addr[1] == 0) - && (a->s6_addr[2] == 0) - && (a->s6_addr[3] == 0) - && (a->s6_addr[4] == 0) - && (a->s6_addr[5] == 0) - && (a->s6_addr[6] == 0) - && (a->s6_addr[7] == 0) - && (a->s6_addr[8] == 0) - && (a->s6_addr[9] == 0) - && (a->s6_addr[10] == 0xff) - && (a->s6_addr[11] == 0xff)); -} - -inline int IN6_IS_ADDR_V4COMPAT(const in6_addr_emulation* a) -{ - return ((a->s6_addr[0] == 0) - && (a->s6_addr[1] == 0) - && (a->s6_addr[2] == 0) - && (a->s6_addr[3] == 0) - && (a->s6_addr[4] == 0) - && (a->s6_addr[5] == 0) - && (a->s6_addr[6] == 0) - && (a->s6_addr[7] == 0) - && (a->s6_addr[8] == 0) - && (a->s6_addr[9] == 0) - && (a->s6_addr[10] == 0xff) - && (a->s6_addr[11] == 0xff) - && !((a->s6_addr[12] == 0) - && (a->s6_addr[13] == 0) - && (a->s6_addr[14] == 0) - && ((a->s6_addr[15] == 0) || (a->s6_addr[15] == 1)))); -} - -inline int IN6_IS_ADDR_MC_NODELOCAL(const in6_addr_emulation* a) -{ - return IN6_IS_ADDR_MULTICAST(a) && ((a->s6_addr[1] & 0xf) == 1); -} - -inline int IN6_IS_ADDR_MC_LINKLOCAL(const in6_addr_emulation* a) -{ - return IN6_IS_ADDR_MULTICAST(a) && ((a->s6_addr[1] & 0xf) == 2); -} - -inline int IN6_IS_ADDR_MC_SITELOCAL(const in6_addr_emulation* a) -{ - return IN6_IS_ADDR_MULTICAST(a) && ((a->s6_addr[1] & 0xf) == 5); -} - -inline int IN6_IS_ADDR_MC_ORGLOCAL(const in6_addr_emulation* a) -{ - return IN6_IS_ADDR_MULTICAST(a) && ((a->s6_addr[1] & 0xf) == 8); -} - -inline int IN6_IS_ADDR_MC_GLOBAL(const in6_addr_emulation* a) -{ - return IN6_IS_ADDR_MULTICAST(a) && ((a->s6_addr[1] & 0xf) == 0xe); -} - -} // namespace detail -} // namespace asio - -#endif // defined(ASIO_HAS_OLD_WIN_SDK) - -// Even newer Platform SDKs that support IPv6 may not define IPV6_V6ONLY. -#if !defined(IPV6_V6ONLY) -# define IPV6_V6ONLY 27 -#endif - -// Some SDKs (e.g. Windows CE) don't define IPPROTO_ICMPV6. -#if !defined(IPPROTO_ICMPV6) -# define IPPROTO_ICMPV6 58 -#endif - -#endif // defined(BOOST_WINDOWS) || defined(__CYGWIN__) - -#include "asio/detail/pop_options.hpp" - -#endif // ASIO_DETAIL_OLD_WIN_SDK_COMPAT_HPP diff --git a/libtorrent/include/asio/detail/pipe_select_interrupter.hpp b/libtorrent/include/asio/detail/pipe_select_interrupter.hpp deleted file mode 100644 index e0a224e33..000000000 --- a/libtorrent/include/asio/detail/pipe_select_interrupter.hpp +++ /dev/null @@ -1,114 +0,0 @@ -// -// pipe_select_interrupter.hpp -// ~~~~~~~~~~~~~~~~~~~~~~~~~~~ -// -// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -#ifndef ASIO_DETAIL_PIPE_SELECT_INTERRUPTER_HPP -#define ASIO_DETAIL_PIPE_SELECT_INTERRUPTER_HPP - -#if defined(_MSC_VER) && (_MSC_VER >= 1200) -# pragma once -#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) - -#include "asio/detail/push_options.hpp" - -#include "asio/detail/push_options.hpp" -#include -#include -#include "asio/detail/pop_options.hpp" - -#if !defined(BOOST_WINDOWS) && !defined(__CYGWIN__) - -#include "asio/detail/push_options.hpp" -#include -#include "asio/detail/pop_options.hpp" - -#include "asio/error.hpp" -#include "asio/system_error.hpp" -#include "asio/detail/socket_types.hpp" - -namespace asio { -namespace detail { - -class pipe_select_interrupter -{ -public: - // Constructor. - pipe_select_interrupter() - { - int pipe_fds[2]; - if (pipe(pipe_fds) == 0) - { - read_descriptor_ = pipe_fds[0]; - ::fcntl(read_descriptor_, F_SETFL, O_NONBLOCK); - write_descriptor_ = pipe_fds[1]; - ::fcntl(write_descriptor_, F_SETFL, O_NONBLOCK); - } - else - { - asio::error_code ec(errno, - asio::error::get_system_category()); - asio::system_error e(ec, "pipe_select_interrupter"); - boost::throw_exception(e); - } - } - - // Destructor. - ~pipe_select_interrupter() - { - if (read_descriptor_ != -1) - ::close(read_descriptor_); - if (write_descriptor_ != -1) - ::close(write_descriptor_); - } - - // Interrupt the select call. - void interrupt() - { - char byte = 0; - ::write(write_descriptor_, &byte, 1); - } - - // Reset the select interrupt. Returns true if the call was interrupted. - bool reset() - { - char data[1024]; - int bytes_read = ::read(read_descriptor_, data, sizeof(data)); - bool was_interrupted = (bytes_read > 0); - while (bytes_read == sizeof(data)) - bytes_read = ::read(read_descriptor_, data, sizeof(data)); - return was_interrupted; - } - - // Get the read descriptor to be passed to select. - int read_descriptor() const - { - return read_descriptor_; - } - -private: - // The read end of a connection used to interrupt the select call. This file - // descriptor is passed to select such that when it is time to stop, a single - // byte will be written on the other end of the connection and this - // descriptor will become readable. - int read_descriptor_; - - // The write end of a connection used to interrupt the select call. A single - // byte may be written to this to wake up the select which is waiting for the - // other end to become readable. - int write_descriptor_; -}; - -} // namespace detail -} // namespace asio - -#endif // !defined(BOOST_WINDOWS) && !defined(__CYGWIN__) - -#include "asio/detail/pop_options.hpp" - -#endif // ASIO_DETAIL_PIPE_SELECT_INTERRUPTER_HPP diff --git a/libtorrent/include/asio/detail/pop_options.hpp b/libtorrent/include/asio/detail/pop_options.hpp deleted file mode 100644 index 7f5666211..000000000 --- a/libtorrent/include/asio/detail/pop_options.hpp +++ /dev/null @@ -1,88 +0,0 @@ -// -// pop_options.hpp -// ~~~~~~~~~~~~~~~ -// -// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -// No header guard - -#if defined(__COMO__) - -// Comeau C++ - -#elif defined(__DMC__) - -// Digital Mars C++ - -#elif defined(__INTEL_COMPILER) || defined(__ICL) \ - || defined(__ICC) || defined(__ECC) - -// Intel C++ - -#elif defined(__GNUC__) - -// GNU C++ - -# if defined(__MINGW32__) || defined(__CYGWIN__) -# pragma pack (pop) -# endif - -#elif defined(__KCC) - -// Kai C++ - -#elif defined(__sgi) - -// SGI MIPSpro C++ - -#elif defined(__DECCXX) - -// Compaq Tru64 Unix cxx - -#elif defined(__ghs) - -// Greenhills C++ - -#elif defined(__BORLANDC__) - -// Borland C++ - -# pragma option pop -# pragma nopushoptwarn -# pragma nopackwarning - -#elif defined(__MWERKS__) - -// Metrowerks CodeWarrior - -#elif defined(__SUNPRO_CC) - -// Sun Workshop Compiler C++ - -#elif defined(__HP_aCC) - -// HP aCC - -#elif defined(__MRC__) || defined(__SC__) - -// MPW MrCpp or SCpp - -#elif defined(__IBMCPP__) - -// IBM Visual Age - -#elif defined(_MSC_VER) - -// Microsoft Visual C++ -// -// Must remain the last #elif since some other vendors (Metrowerks, for example) -// also #define _MSC_VER - -# pragma warning (pop) -# pragma pack (pop) - -#endif diff --git a/libtorrent/include/asio/detail/posix_event.hpp b/libtorrent/include/asio/detail/posix_event.hpp deleted file mode 100644 index 958a5e02e..000000000 --- a/libtorrent/include/asio/detail/posix_event.hpp +++ /dev/null @@ -1,104 +0,0 @@ -// -// posix_event.hpp -// ~~~~~~~~~~~~~~~ -// -// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -#ifndef ASIO_DETAIL_POSIX_EVENT_HPP -#define ASIO_DETAIL_POSIX_EVENT_HPP - -#if defined(_MSC_VER) && (_MSC_VER >= 1200) -# pragma once -#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) - -#include "asio/detail/push_options.hpp" - -#include "asio/detail/push_options.hpp" -#include -#include "asio/detail/pop_options.hpp" - -#if defined(BOOST_HAS_PTHREADS) - -#include "asio/detail/push_options.hpp" -#include -#include -#include -#include "asio/detail/pop_options.hpp" - -#include "asio/error.hpp" -#include "asio/system_error.hpp" -#include "asio/detail/noncopyable.hpp" - -namespace asio { -namespace detail { - -class posix_event - : private noncopyable -{ -public: - // Constructor. - posix_event() - : signalled_(false) - { - int error = ::pthread_cond_init(&cond_, 0); - if (error != 0) - { - asio::system_error e( - asio::error_code(error, - asio::error::get_system_category()), - "event"); - boost::throw_exception(e); - } - } - - // Destructor. - ~posix_event() - { - ::pthread_cond_destroy(&cond_); - } - - // Signal the event. - template - void signal(Lock& lock) - { - BOOST_ASSERT(lock.locked()); - (void)lock; - signalled_ = true; - ::pthread_cond_signal(&cond_); // Ignore EINVAL. - } - - // Reset the event. - template - void clear(Lock& lock) - { - BOOST_ASSERT(lock.locked()); - (void)lock; - signalled_ = false; - } - - // Wait for the event to become signalled. - template - void wait(Lock& lock) - { - BOOST_ASSERT(lock.locked()); - while (!signalled_) - ::pthread_cond_wait(&cond_, &lock.mutex().mutex_); // Ignore EINVAL. - } - -private: - ::pthread_cond_t cond_; - bool signalled_; -}; - -} // namespace detail -} // namespace asio - -#endif // defined(BOOST_HAS_PTHREADS) - -#include "asio/detail/pop_options.hpp" - -#endif // ASIO_DETAIL_POSIX_EVENT_HPP diff --git a/libtorrent/include/asio/detail/posix_fd_set_adapter.hpp b/libtorrent/include/asio/detail/posix_fd_set_adapter.hpp deleted file mode 100644 index 5519b9abc..000000000 --- a/libtorrent/include/asio/detail/posix_fd_set_adapter.hpp +++ /dev/null @@ -1,77 +0,0 @@ -// -// posix_fd_set_adapter.hpp -// ~~~~~~~~~~~~~~~~~~~~~~~~ -// -// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -#ifndef ASIO_DETAIL_POSIX_FD_SET_ADAPTER_HPP -#define ASIO_DETAIL_POSIX_FD_SET_ADAPTER_HPP - -#if defined(_MSC_VER) && (_MSC_VER >= 1200) -# pragma once -#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) - -#include "asio/detail/push_options.hpp" - -#include "asio/detail/socket_types.hpp" - -#if !defined(BOOST_WINDOWS) && !defined(__CYGWIN__) - -namespace asio { -namespace detail { - -// Adapts the FD_SET type to meet the Descriptor_Set concept's requirements. -class posix_fd_set_adapter -{ -public: - posix_fd_set_adapter() - : max_descriptor_(invalid_socket) - { - using namespace std; // Needed for memset on Solaris. - FD_ZERO(&fd_set_); - } - - bool set(socket_type descriptor) - { - if (descriptor < (socket_type)FD_SETSIZE) - { - if (max_descriptor_ == invalid_socket || descriptor > max_descriptor_) - max_descriptor_ = descriptor; - FD_SET(descriptor, &fd_set_); - return true; - } - return false; - } - - bool is_set(socket_type descriptor) const - { - return FD_ISSET(descriptor, &fd_set_) != 0; - } - - operator fd_set*() - { - return &fd_set_; - } - - socket_type max_descriptor() const - { - return max_descriptor_; - } - -private: - mutable fd_set fd_set_; - socket_type max_descriptor_; -}; - -} // namespace detail -} // namespace asio - -#endif // !defined(BOOST_WINDOWS) && !defined(__CYGWIN__) - -#include "asio/detail/pop_options.hpp" - -#endif // ASIO_DETAIL_POSIX_FD_SET_ADAPTER_HPP diff --git a/libtorrent/include/asio/detail/posix_mutex.hpp b/libtorrent/include/asio/detail/posix_mutex.hpp deleted file mode 100644 index 4f6cbba9f..000000000 --- a/libtorrent/include/asio/detail/posix_mutex.hpp +++ /dev/null @@ -1,107 +0,0 @@ -// -// posix_mutex.hpp -// ~~~~~~~~~~~~~~~ -// -// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -#ifndef ASIO_DETAIL_POSIX_MUTEX_HPP -#define ASIO_DETAIL_POSIX_MUTEX_HPP - -#if defined(_MSC_VER) && (_MSC_VER >= 1200) -# pragma once -#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) - -#include "asio/detail/push_options.hpp" - -#include "asio/detail/push_options.hpp" -#include -#include "asio/detail/pop_options.hpp" - -#if defined(BOOST_HAS_PTHREADS) - -#include "asio/detail/push_options.hpp" -#include -#include -#include "asio/detail/pop_options.hpp" - -#include "asio/error.hpp" -#include "asio/system_error.hpp" -#include "asio/detail/noncopyable.hpp" -#include "asio/detail/scoped_lock.hpp" - -namespace asio { -namespace detail { - -class posix_event; - -class posix_mutex - : private noncopyable -{ -public: - typedef asio::detail::scoped_lock scoped_lock; - - // Constructor. - posix_mutex() - { - int error = ::pthread_mutex_init(&mutex_, 0); - if (error != 0) - { - asio::system_error e( - asio::error_code(error, - asio::error::get_system_category()), - "mutex"); - boost::throw_exception(e); - } - } - - // Destructor. - ~posix_mutex() - { - ::pthread_mutex_destroy(&mutex_); - } - - // Lock the mutex. - void lock() - { - int error = ::pthread_mutex_lock(&mutex_); - if (error != 0) - { - asio::system_error e( - asio::error_code(error, - asio::error::get_system_category()), - "mutex"); - boost::throw_exception(e); - } - } - - // Unlock the mutex. - void unlock() - { - int error = ::pthread_mutex_unlock(&mutex_); - if (error != 0) - { - asio::system_error e( - asio::error_code(error, - asio::error::get_system_category()), - "mutex"); - boost::throw_exception(e); - } - } - -private: - friend class posix_event; - ::pthread_mutex_t mutex_; -}; - -} // namespace detail -} // namespace asio - -#endif // defined(BOOST_HAS_PTHREADS) - -#include "asio/detail/pop_options.hpp" - -#endif // ASIO_DETAIL_POSIX_MUTEX_HPP diff --git a/libtorrent/include/asio/detail/posix_signal_blocker.hpp b/libtorrent/include/asio/detail/posix_signal_blocker.hpp deleted file mode 100644 index 5ab6e7ad2..000000000 --- a/libtorrent/include/asio/detail/posix_signal_blocker.hpp +++ /dev/null @@ -1,90 +0,0 @@ -// -// posix_signal_blocker.hpp -// ~~~~~~~~~~~~~~~~~~~~~~~~ -// -// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -#ifndef ASIO_DETAIL_POSIX_SIGNAL_BLOCKER_HPP -#define ASIO_DETAIL_POSIX_SIGNAL_BLOCKER_HPP - -#if defined(_MSC_VER) && (_MSC_VER >= 1200) -# pragma once -#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) - -#include "asio/detail/push_options.hpp" - -#include "asio/detail/push_options.hpp" -#include -#include "asio/detail/pop_options.hpp" - -#if defined(BOOST_HAS_PTHREADS) - -#include "asio/detail/push_options.hpp" -#include -#include -#include -#include "asio/detail/pop_options.hpp" - -#include "asio/detail/noncopyable.hpp" - -namespace asio { -namespace detail { - -class posix_signal_blocker - : private noncopyable -{ -public: - // Constructor blocks all signals for the calling thread. - posix_signal_blocker() - : blocked_(false) - { - sigset_t new_mask; - sigfillset(&new_mask); - blocked_ = (pthread_sigmask(SIG_BLOCK, &new_mask, &old_mask_) == 0); - } - - // Destructor restores the previous signal mask. - ~posix_signal_blocker() - { - if (blocked_) - pthread_sigmask(SIG_SETMASK, &old_mask_, 0); - } - - // Block all signals for the calling thread. - void block() - { - if (!blocked_) - { - sigset_t new_mask; - sigfillset(&new_mask); - blocked_ = (pthread_sigmask(SIG_BLOCK, &new_mask, &old_mask_) == 0); - } - } - - // Restore the previous signal mask. - void unblock() - { - if (blocked_) - blocked_ = (pthread_sigmask(SIG_SETMASK, &old_mask_, 0) != 0); - } - -private: - // Have signals been blocked. - bool blocked_; - - // The previous signal mask. - sigset_t old_mask_; -}; - -} // namespace detail -} // namespace asio - -#endif // defined(BOOST_HAS_PTHREADS) - -#include "asio/detail/pop_options.hpp" - -#endif // ASIO_DETAIL_POSIX_SIGNAL_BLOCKER_HPP diff --git a/libtorrent/include/asio/detail/posix_thread.hpp b/libtorrent/include/asio/detail/posix_thread.hpp deleted file mode 100644 index fe5f82905..000000000 --- a/libtorrent/include/asio/detail/posix_thread.hpp +++ /dev/null @@ -1,132 +0,0 @@ -// -// posix_thread.hpp -// ~~~~~~~~~~~~~~~~ -// -// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -#ifndef ASIO_DETAIL_POSIX_THREAD_HPP -#define ASIO_DETAIL_POSIX_THREAD_HPP - -#if defined(_MSC_VER) && (_MSC_VER >= 1200) -# pragma once -#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) - -#include "asio/detail/push_options.hpp" - -#include "asio/detail/push_options.hpp" -#include -#include "asio/detail/pop_options.hpp" - -#if defined(BOOST_HAS_PTHREADS) - -#include "asio/detail/push_options.hpp" -#include -#include -#include -#include "asio/detail/pop_options.hpp" - -#include "asio/error.hpp" -#include "asio/system_error.hpp" -#include "asio/detail/noncopyable.hpp" - -namespace asio { -namespace detail { - -extern "C" void* asio_detail_posix_thread_function(void* arg); - -class posix_thread - : private noncopyable -{ -public: - // The purpose of the thread. - enum purpose { internal, external }; - - // Constructor. - template - posix_thread(Function f, purpose = internal) - : joined_(false) - { - std::auto_ptr arg(new func(f)); - int error = ::pthread_create(&thread_, 0, - asio_detail_posix_thread_function, arg.get()); - if (error != 0) - { - asio::system_error e( - asio::error_code(error, - asio::error::get_system_category()), - "thread"); - boost::throw_exception(e); - } - arg.release(); - } - - // Destructor. - ~posix_thread() - { - if (!joined_) - ::pthread_detach(thread_); - } - - // Wait for the thread to exit. - void join() - { - if (!joined_) - { - ::pthread_join(thread_, 0); - joined_ = true; - } - } - -private: - friend void* asio_detail_posix_thread_function(void* arg); - - class func_base - { - public: - virtual ~func_base() {} - virtual void run() = 0; - }; - - template - class func - : public func_base - { - public: - func(Function f) - : f_(f) - { - } - - virtual void run() - { - f_(); - } - - private: - Function f_; - }; - - ::pthread_t thread_; - bool joined_; -}; - -inline void* asio_detail_posix_thread_function(void* arg) -{ - std::auto_ptr f( - static_cast(arg)); - f->run(); - return 0; -} - -} // namespace detail -} // namespace asio - -#endif // defined(BOOST_HAS_PTHREADS) - -#include "asio/detail/pop_options.hpp" - -#endif // ASIO_DETAIL_POSIX_THREAD_HPP diff --git a/libtorrent/include/asio/detail/posix_tss_ptr.hpp b/libtorrent/include/asio/detail/posix_tss_ptr.hpp deleted file mode 100644 index 0944d3dbf..000000000 --- a/libtorrent/include/asio/detail/posix_tss_ptr.hpp +++ /dev/null @@ -1,88 +0,0 @@ -// -// posix_tss_ptr.hpp -// ~~~~~~~~~~~~~~~~~ -// -// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -#ifndef ASIO_DETAIL_POSIX_TSS_PTR_HPP -#define ASIO_DETAIL_POSIX_TSS_PTR_HPP - -#if defined(_MSC_VER) && (_MSC_VER >= 1200) -# pragma once -#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) - -#include "asio/detail/push_options.hpp" - -#include "asio/detail/push_options.hpp" -#include -#include "asio/detail/pop_options.hpp" - -#if defined(BOOST_HAS_PTHREADS) - -#include "asio/detail/push_options.hpp" -#include -#include -#include "asio/detail/pop_options.hpp" - -#include "asio/error.hpp" -#include "asio/system_error.hpp" -#include "asio/detail/noncopyable.hpp" - -namespace asio { -namespace detail { - -template -class posix_tss_ptr - : private noncopyable -{ -public: - // Constructor. - posix_tss_ptr() - { - int error = ::pthread_key_create(&tss_key_, 0); - if (error != 0) - { - asio::system_error e( - asio::error_code(error, - asio::error::get_system_category()), - "tss"); - boost::throw_exception(e); - } - } - - // Destructor. - ~posix_tss_ptr() - { - ::pthread_key_delete(tss_key_); - } - - // Get the value. - operator T*() const - { - return static_cast(::pthread_getspecific(tss_key_)); - } - - // Set the value. - void operator=(T* value) - { - ::pthread_setspecific(tss_key_, value); - } - -private: - // Thread-specific storage to allow unlocked access to determine whether a - // thread is a member of the pool. - pthread_key_t tss_key_; -}; - -} // namespace detail -} // namespace asio - -#endif // defined(BOOST_HAS_PTHREADS) - -#include "asio/detail/pop_options.hpp" - -#endif // ASIO_DETAIL_POSIX_TSS_PTR_HPP diff --git a/libtorrent/include/asio/detail/push_options.hpp b/libtorrent/include/asio/detail/push_options.hpp deleted file mode 100644 index 47524b255..000000000 --- a/libtorrent/include/asio/detail/push_options.hpp +++ /dev/null @@ -1,114 +0,0 @@ -// -// push_options.hpp -// ~~~~~~~~~~~~~~~~ -// -// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -// No header guard - -#if defined(__COMO__) - -// Comeau C++ - -#elif defined(__DMC__) - -// Digital Mars C++ - -#elif defined(__INTEL_COMPILER) || defined(__ICL) \ - || defined(__ICC) || defined(__ECC) - -// Intel C++ - -#elif defined(__GNUC__) - -// GNU C++ - -# if defined(__MINGW32__) || defined(__CYGWIN__) -# pragma pack (push, 8) -# endif - -#elif defined(__KCC) - -// Kai C++ - -#elif defined(__sgi) - -// SGI MIPSpro C++ - -#elif defined(__DECCXX) - -// Compaq Tru64 Unix cxx - -#elif defined(__ghs) - -// Greenhills C++ - -#elif defined(__BORLANDC__) - -// Borland C++ - -# pragma option push -a8 -b -Ve- -Vx- -w-inl -vi- -# pragma nopushoptwarn -# pragma nopackwarning -# if !defined(__MT__) -# error Multithreaded RTL must be selected. -# endif // !defined(__MT__) - -#elif defined(__MWERKS__) - -// Metrowerks CodeWarrior - -#elif defined(__SUNPRO_CC) - -// Sun Workshop Compiler C++ - -#elif defined(__HP_aCC) - -// HP aCC - -#elif defined(__MRC__) || defined(__SC__) - -// MPW MrCpp or SCpp - -#elif defined(__IBMCPP__) - -// IBM Visual Age - -#elif defined(_MSC_VER) - -// Microsoft Visual C++ -// -// Must remain the last #elif since some other vendors (Metrowerks, for example) -// also #define _MSC_VER - -# pragma warning (disable:4103) -# pragma warning (push) -# pragma warning (disable:4127) -# pragma warning (disable:4244) -# pragma warning (disable:4355) -# pragma warning (disable:4512) -# pragma warning (disable:4675) -# if defined(_M_IX86) && defined(_Wp64) -// The /Wp64 option is broken. If you want to check 64 bit portability, use a -// 64 bit compiler! -# pragma warning (disable:4311) -# pragma warning (disable:4312) -# endif // defined(_M_IX86) && defined(_Wp64) -# pragma pack (push, 8) -// Note that if the /Og optimisation flag is enabled with MSVC6, the compiler -// has a tendency to incorrectly optimise away some calls to member template -// functions, even though those functions contain code that should not be -// optimised away! Therefore we will always disable this optimisation option -// for the MSVC6 compiler. -# if (_MSC_VER < 1300) -# pragma optimize ("g", off) -# endif -# if !defined(_MT) -# error Multithreaded RTL must be selected. -# endif // !defined(_MT) - -#endif diff --git a/libtorrent/include/asio/detail/reactive_descriptor_service.hpp b/libtorrent/include/asio/detail/reactive_descriptor_service.hpp deleted file mode 100644 index 12a0c36b4..000000000 --- a/libtorrent/include/asio/detail/reactive_descriptor_service.hpp +++ /dev/null @@ -1,709 +0,0 @@ -// -// reactive_descriptor_service.hpp -// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -// -// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -#ifndef ASIO_DETAIL_REACTIVE_DESCRIPTOR_SERVICE_HPP -#define ASIO_DETAIL_REACTIVE_DESCRIPTOR_SERVICE_HPP - -#if defined(_MSC_VER) && (_MSC_VER >= 1200) -# pragma once -#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) - -#include "asio/detail/push_options.hpp" - -#include "asio/buffer.hpp" -#include "asio/error.hpp" -#include "asio/io_service.hpp" -#include "asio/detail/bind_handler.hpp" -#include "asio/detail/handler_base_from_member.hpp" -#include "asio/detail/noncopyable.hpp" -#include "asio/detail/service_base.hpp" -#include "asio/detail/descriptor_ops.hpp" - -#if !defined(BOOST_WINDOWS) && !defined(__CYGWIN__) - -namespace asio { -namespace detail { - -template -class reactive_descriptor_service - : public asio::detail::service_base< - reactive_descriptor_service > -{ -public: - // The native type of a descriptor. - typedef int native_type; - - // The implementation type of the descriptor. - class implementation_type - : private asio::detail::noncopyable - { - public: - // Default constructor. - implementation_type() - : descriptor_(-1), - flags_(0) - { - } - - private: - // Only this service will have access to the internal values. - friend class reactive_descriptor_service; - - // The native descriptor representation. - int descriptor_; - - enum - { - user_set_non_blocking = 1, // The user wants a non-blocking descriptor. - internal_non_blocking = 2 // The descriptor has been set non-blocking. - }; - - // Flags indicating the current state of the descriptor. - unsigned char flags_; - - // Per-descriptor data used by the reactor. - typename Reactor::per_descriptor_data reactor_data_; - }; - - // The maximum number of buffers to support in a single operation. - enum { max_buffers = 64 < max_iov_len ? 64 : max_iov_len }; - - // Constructor. - reactive_descriptor_service(asio::io_service& io_service) - : asio::detail::service_base< - reactive_descriptor_service >(io_service), - reactor_(asio::use_service(io_service)) - { - } - - // Destroy all user-defined handler objects owned by the service. - void shutdown_service() - { - } - - // Construct a new descriptor implementation. - void construct(implementation_type& impl) - { - impl.descriptor_ = -1; - impl.flags_ = 0; - } - - // Destroy a descriptor implementation. - void destroy(implementation_type& impl) - { - if (impl.descriptor_ != -1) - { - reactor_.close_descriptor(impl.descriptor_, impl.reactor_data_); - - if (impl.flags_ & implementation_type::internal_non_blocking) - { - ioctl_arg_type non_blocking = 0; - asio::error_code ignored_ec; - descriptor_ops::ioctl(impl.descriptor_, - FIONBIO, &non_blocking, ignored_ec); - impl.flags_ &= ~implementation_type::internal_non_blocking; - } - - asio::error_code ignored_ec; - descriptor_ops::close(impl.descriptor_, ignored_ec); - - impl.descriptor_ = -1; - } - } - - // Assign a native descriptor to a descriptor implementation. - asio::error_code assign(implementation_type& impl, - const native_type& native_descriptor, asio::error_code& ec) - { - if (is_open(impl)) - { - ec = asio::error::already_open; - return ec; - } - - if (int err = reactor_.register_descriptor( - native_descriptor, impl.reactor_data_)) - { - ec = asio::error_code(err, - asio::error::get_system_category()); - return ec; - } - - impl.descriptor_ = native_descriptor; - impl.flags_ = 0; - ec = asio::error_code(); - return ec; - } - - // Determine whether the descriptor is open. - bool is_open(const implementation_type& impl) const - { - return impl.descriptor_ != -1; - } - - // Destroy a descriptor implementation. - asio::error_code close(implementation_type& impl, - asio::error_code& ec) - { - if (is_open(impl)) - { - reactor_.close_descriptor(impl.descriptor_, impl.reactor_data_); - - if (impl.flags_ & implementation_type::internal_non_blocking) - { - ioctl_arg_type non_blocking = 0; - asio::error_code ignored_ec; - descriptor_ops::ioctl(impl.descriptor_, - FIONBIO, &non_blocking, ignored_ec); - impl.flags_ &= ~implementation_type::internal_non_blocking; - } - - if (descriptor_ops::close(impl.descriptor_, ec) == -1) - return ec; - - impl.descriptor_ = -1; - } - - ec = asio::error_code(); - return ec; - } - - // Get the native descriptor representation. - native_type native(const implementation_type& impl) const - { - return impl.descriptor_; - } - - // Cancel all operations associated with the descriptor. - asio::error_code cancel(implementation_type& impl, - asio::error_code& ec) - { - if (!is_open(impl)) - { - ec = asio::error::bad_descriptor; - return ec; - } - - reactor_.cancel_ops(impl.descriptor_, impl.reactor_data_); - ec = asio::error_code(); - return ec; - } - - // Perform an IO control command on the descriptor. - template - asio::error_code io_control(implementation_type& impl, - IO_Control_Command& command, asio::error_code& ec) - { - if (!is_open(impl)) - { - ec = asio::error::bad_descriptor; - return ec; - } - - if (command.name() == static_cast(FIONBIO)) - { - if (command.get()) - impl.flags_ |= implementation_type::user_set_non_blocking; - else - impl.flags_ &= ~implementation_type::user_set_non_blocking; - ec = asio::error_code(); - } - else - { - descriptor_ops::ioctl(impl.descriptor_, command.name(), - static_cast(command.data()), ec); - } - return ec; - } - - // Write some data to the descriptor. - template - size_t write_some(implementation_type& impl, - const ConstBufferSequence& buffers, asio::error_code& ec) - { - if (!is_open(impl)) - { - ec = asio::error::bad_descriptor; - return 0; - } - - // Copy buffers into array. - descriptor_ops::buf bufs[max_buffers]; - typename ConstBufferSequence::const_iterator iter = buffers.begin(); - typename ConstBufferSequence::const_iterator end = buffers.end(); - size_t i = 0; - size_t total_buffer_size = 0; - for (; iter != end && i < max_buffers; ++iter, ++i) - { - asio::const_buffer buffer(*iter); - descriptor_ops::init_buf(bufs[i], - asio::buffer_cast(buffer), - asio::buffer_size(buffer)); - total_buffer_size += asio::buffer_size(buffer); - } - - // A request to read_some 0 bytes on a stream is a no-op. - if (total_buffer_size == 0) - { - ec = asio::error_code(); - return 0; - } - - // Make descriptor non-blocking if user wants non-blocking. - if (impl.flags_ & implementation_type::user_set_non_blocking) - { - if (!(impl.flags_ & implementation_type::internal_non_blocking)) - { - ioctl_arg_type non_blocking = 1; - if (descriptor_ops::ioctl(impl.descriptor_, - FIONBIO, &non_blocking, ec)) - return 0; - impl.flags_ |= implementation_type::internal_non_blocking; - } - } - - // Send the data. - for (;;) - { - // Try to complete the operation without blocking. - int bytes_sent = descriptor_ops::gather_write( - impl.descriptor_, bufs, i, ec); - - // Check if operation succeeded. - if (bytes_sent >= 0) - return bytes_sent; - - // Operation failed. - if ((impl.flags_ & implementation_type::user_set_non_blocking) - || (ec != asio::error::would_block - && ec != asio::error::try_again)) - return 0; - - // Wait for descriptor to become ready. - if (descriptor_ops::poll_write(impl.descriptor_, ec) < 0) - return 0; - } - } - - // Wait until data can be written without blocking. - size_t write_some(implementation_type& impl, - const null_buffers&, asio::error_code& ec) - { - if (!is_open(impl)) - { - ec = asio::error::bad_descriptor; - return 0; - } - - // Wait for descriptor to become ready. - descriptor_ops::poll_write(impl.descriptor_, ec); - - return 0; - } - - template - class write_operation : - public handler_base_from_member - { - public: - write_operation(int descriptor, asio::io_service& io_service, - const ConstBufferSequence& buffers, Handler handler) - : handler_base_from_member(handler), - descriptor_(descriptor), - io_service_(io_service), - work_(io_service), - buffers_(buffers) - { - } - - bool perform(asio::error_code& ec, - std::size_t& bytes_transferred) - { - // Check whether the operation was successful. - if (ec) - { - bytes_transferred = 0; - return true; - } - - // Copy buffers into array. - descriptor_ops::buf bufs[max_buffers]; - typename ConstBufferSequence::const_iterator iter = buffers_.begin(); - typename ConstBufferSequence::const_iterator end = buffers_.end(); - size_t i = 0; - for (; iter != end && i < max_buffers; ++iter, ++i) - { - asio::const_buffer buffer(*iter); - descriptor_ops::init_buf(bufs[i], - asio::buffer_cast(buffer), - asio::buffer_size(buffer)); - } - - // Write the data. - int bytes = descriptor_ops::gather_write(descriptor_, bufs, i, ec); - - // Check if we need to run the operation again. - if (ec == asio::error::would_block - || ec == asio::error::try_again) - return false; - - bytes_transferred = (bytes < 0 ? 0 : bytes); - return true; - } - - void complete(const asio::error_code& ec, - std::size_t bytes_transferred) - { - io_service_.post(bind_handler(this->handler_, ec, bytes_transferred)); - } - - private: - int descriptor_; - asio::io_service& io_service_; - asio::io_service::work work_; - ConstBufferSequence buffers_; - }; - - // Start an asynchronous write. The data being sent must be valid for the - // lifetime of the asynchronous operation. - template - void async_write_some(implementation_type& impl, - const ConstBufferSequence& buffers, Handler handler) - { - if (!is_open(impl)) - { - this->get_io_service().post(bind_handler(handler, - asio::error::bad_descriptor, 0)); - } - else - { - // Determine total size of buffers. - typename ConstBufferSequence::const_iterator iter = buffers.begin(); - typename ConstBufferSequence::const_iterator end = buffers.end(); - size_t i = 0; - size_t total_buffer_size = 0; - for (; iter != end && i < max_buffers; ++iter, ++i) - { - asio::const_buffer buffer(*iter); - total_buffer_size += asio::buffer_size(buffer); - } - - // A request to read_some 0 bytes on a stream is a no-op. - if (total_buffer_size == 0) - { - this->get_io_service().post(bind_handler(handler, - asio::error_code(), 0)); - return; - } - - // Make descriptor non-blocking. - if (!(impl.flags_ & implementation_type::internal_non_blocking)) - { - ioctl_arg_type non_blocking = 1; - asio::error_code ec; - if (descriptor_ops::ioctl(impl.descriptor_, FIONBIO, &non_blocking, ec)) - { - this->get_io_service().post(bind_handler(handler, ec, 0)); - return; - } - impl.flags_ |= implementation_type::internal_non_blocking; - } - - reactor_.start_write_op(impl.descriptor_, impl.reactor_data_, - write_operation( - impl.descriptor_, this->get_io_service(), buffers, handler)); - } - } - - template - class null_buffers_operation : - public handler_base_from_member - { - public: - null_buffers_operation(asio::io_service& io_service, Handler handler) - : handler_base_from_member(handler), - work_(io_service) - { - } - - bool perform(asio::error_code&, - std::size_t& bytes_transferred) - { - bytes_transferred = 0; - return true; - } - - void complete(const asio::error_code& ec, - std::size_t bytes_transferred) - { - work_.get_io_service().post(bind_handler( - this->handler_, ec, bytes_transferred)); - } - - private: - asio::io_service::work work_; - }; - - // Start an asynchronous wait until data can be written without blocking. - template - void async_write_some(implementation_type& impl, - const null_buffers&, Handler handler) - { - if (!is_open(impl)) - { - this->get_io_service().post(bind_handler(handler, - asio::error::bad_descriptor, 0)); - } - else - { - reactor_.start_write_op(impl.descriptor_, impl.reactor_data_, - null_buffers_operation(this->get_io_service(), handler), - false); - } - } - - // Read some data from the stream. Returns the number of bytes read. - template - size_t read_some(implementation_type& impl, - const MutableBufferSequence& buffers, asio::error_code& ec) - { - if (!is_open(impl)) - { - ec = asio::error::bad_descriptor; - return 0; - } - - // Copy buffers into array. - descriptor_ops::buf bufs[max_buffers]; - typename MutableBufferSequence::const_iterator iter = buffers.begin(); - typename MutableBufferSequence::const_iterator end = buffers.end(); - size_t i = 0; - size_t total_buffer_size = 0; - for (; iter != end && i < max_buffers; ++iter, ++i) - { - asio::mutable_buffer buffer(*iter); - descriptor_ops::init_buf(bufs[i], - asio::buffer_cast(buffer), - asio::buffer_size(buffer)); - total_buffer_size += asio::buffer_size(buffer); - } - - // A request to read_some 0 bytes on a stream is a no-op. - if (total_buffer_size == 0) - { - ec = asio::error_code(); - return 0; - } - - // Make descriptor non-blocking if user wants non-blocking. - if (impl.flags_ & implementation_type::user_set_non_blocking) - { - if (!(impl.flags_ & implementation_type::internal_non_blocking)) - { - ioctl_arg_type non_blocking = 1; - if (descriptor_ops::ioctl(impl.descriptor_, FIONBIO, &non_blocking, ec)) - return 0; - impl.flags_ |= implementation_type::internal_non_blocking; - } - } - - // Read some data. - for (;;) - { - // Try to complete the operation without blocking. - int bytes_read = descriptor_ops::scatter_read( - impl.descriptor_, bufs, i, ec); - - // Check if operation succeeded. - if (bytes_read > 0) - return bytes_read; - - // Check for EOF. - if (bytes_read == 0) - { - ec = asio::error::eof; - return 0; - } - - // Operation failed. - if ((impl.flags_ & implementation_type::user_set_non_blocking) - || (ec != asio::error::would_block - && ec != asio::error::try_again)) - return 0; - - // Wait for descriptor to become ready. - if (descriptor_ops::poll_read(impl.descriptor_, ec) < 0) - return 0; - } - } - - // Wait until data can be read without blocking. - size_t read_some(implementation_type& impl, - const null_buffers&, asio::error_code& ec) - { - if (!is_open(impl)) - { - ec = asio::error::bad_descriptor; - return 0; - } - - // Wait for descriptor to become ready. - descriptor_ops::poll_read(impl.descriptor_, ec); - - return 0; - } - - template - class read_operation : - public handler_base_from_member - { - public: - read_operation(int descriptor, asio::io_service& io_service, - const MutableBufferSequence& buffers, Handler handler) - : handler_base_from_member(handler), - descriptor_(descriptor), - io_service_(io_service), - work_(io_service), - buffers_(buffers) - { - } - - bool perform(asio::error_code& ec, - std::size_t& bytes_transferred) - { - // Check whether the operation was successful. - if (ec) - { - bytes_transferred = 0; - return true; - } - - // Copy buffers into array. - descriptor_ops::buf bufs[max_buffers]; - typename MutableBufferSequence::const_iterator iter = buffers_.begin(); - typename MutableBufferSequence::const_iterator end = buffers_.end(); - size_t i = 0; - for (; iter != end && i < max_buffers; ++iter, ++i) - { - asio::mutable_buffer buffer(*iter); - descriptor_ops::init_buf(bufs[i], - asio::buffer_cast(buffer), - asio::buffer_size(buffer)); - } - - // Read some data. - int bytes = descriptor_ops::scatter_read(descriptor_, bufs, i, ec); - if (bytes == 0) - ec = asio::error::eof; - - // Check if we need to run the operation again. - if (ec == asio::error::would_block - || ec == asio::error::try_again) - return false; - - bytes_transferred = (bytes < 0 ? 0 : bytes); - return true; - } - - void complete(const asio::error_code& ec, - std::size_t bytes_transferred) - { - io_service_.post(bind_handler(this->handler_, ec, bytes_transferred)); - } - - private: - int descriptor_; - asio::io_service& io_service_; - asio::io_service::work work_; - MutableBufferSequence buffers_; - }; - - // Start an asynchronous read. The buffer for the data being read must be - // valid for the lifetime of the asynchronous operation. - template - void async_read_some(implementation_type& impl, - const MutableBufferSequence& buffers, Handler handler) - { - if (!is_open(impl)) - { - this->get_io_service().post(bind_handler(handler, - asio::error::bad_descriptor, 0)); - } - else - { - // Determine total size of buffers. - typename MutableBufferSequence::const_iterator iter = buffers.begin(); - typename MutableBufferSequence::const_iterator end = buffers.end(); - size_t i = 0; - size_t total_buffer_size = 0; - for (; iter != end && i < max_buffers; ++iter, ++i) - { - asio::mutable_buffer buffer(*iter); - total_buffer_size += asio::buffer_size(buffer); - } - - // A request to read_some 0 bytes on a stream is a no-op. - if (total_buffer_size == 0) - { - this->get_io_service().post(bind_handler(handler, - asio::error_code(), 0)); - return; - } - - // Make descriptor non-blocking. - if (!(impl.flags_ & implementation_type::internal_non_blocking)) - { - ioctl_arg_type non_blocking = 1; - asio::error_code ec; - if (descriptor_ops::ioctl(impl.descriptor_, FIONBIO, &non_blocking, ec)) - { - this->get_io_service().post(bind_handler(handler, ec, 0)); - return; - } - impl.flags_ |= implementation_type::internal_non_blocking; - } - - reactor_.start_read_op(impl.descriptor_, impl.reactor_data_, - read_operation( - impl.descriptor_, this->get_io_service(), buffers, handler)); - } - } - - // Wait until data can be read without blocking. - template - void async_read_some(implementation_type& impl, - const null_buffers&, Handler handler) - { - if (!is_open(impl)) - { - this->get_io_service().post(bind_handler(handler, - asio::error::bad_descriptor, 0)); - } - else - { - reactor_.start_read_op(impl.descriptor_, impl.reactor_data_, - null_buffers_operation(this->get_io_service(), handler), - false); - } - } - -private: - // The selector that performs event demultiplexing for the service. - Reactor& reactor_; -}; - -} // namespace detail -} // namespace asio - -#endif // !defined(BOOST_WINDOWS) && !defined(__CYGWIN__) - -#include "asio/detail/pop_options.hpp" - -#endif // ASIO_DETAIL_REACTIVE_DESCRIPTOR_SERVICE_HPP diff --git a/libtorrent/include/asio/detail/reactive_serial_port_service.hpp b/libtorrent/include/asio/detail/reactive_serial_port_service.hpp deleted file mode 100644 index 5db94a2dd..000000000 --- a/libtorrent/include/asio/detail/reactive_serial_port_service.hpp +++ /dev/null @@ -1,267 +0,0 @@ -// -// reactive_serial_port_service.hpp -// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -// -// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// Copyright (c) 2008 Rep Invariant Systems, Inc. (info@repinvariant.com) -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -#ifndef ASIO_DETAIL_REACTIVE_SERIAL_PORT_SERVICE_HPP -#define ASIO_DETAIL_REACTIVE_SERIAL_PORT_SERVICE_HPP - -#if defined(_MSC_VER) && (_MSC_VER >= 1200) -# pragma once -#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) - -#include "asio/detail/push_options.hpp" - -#include "asio/detail/push_options.hpp" -#include -#include -#include "asio/detail/pop_options.hpp" - -#if !defined(BOOST_WINDOWS) && !defined(__CYGWIN__) - -#include "asio/detail/push_options.hpp" -#include -#include "asio/detail/pop_options.hpp" - -#include "asio/error.hpp" -#include "asio/io_service.hpp" -#include "asio/detail/descriptor_ops.hpp" -#include "asio/detail/reactive_descriptor_service.hpp" - -namespace asio { -namespace detail { - -// Extend reactive_descriptor_service to provide serial port support. -template -class reactive_serial_port_service - : public asio::detail::service_base< - reactive_serial_port_service > -{ -public: - // The native type of a stream handle. - typedef typename reactive_descriptor_service::native_type - native_type; - - // The implementation type of the stream handle. - typedef typename reactive_descriptor_service::implementation_type - implementation_type; - - reactive_serial_port_service(asio::io_service& io_service) - : asio::detail::service_base< - reactive_serial_port_service>(io_service), - descriptor_service_(asio::use_service< - reactive_descriptor_service >(io_service)) - { - } - - // Destroy all user-defined handler objects owned by the service. - void shutdown_service() - { - } - - // Construct a new handle implementation. - void construct(implementation_type& impl) - { - descriptor_service_.construct(impl); - } - - // Destroy a handle implementation. - void destroy(implementation_type& impl) - { - descriptor_service_.destroy(impl); - } - - // Open the serial port using the specified device name. - asio::error_code open(implementation_type& impl, - const std::string& device, asio::error_code& ec) - { - if (is_open(impl)) - { - ec = asio::error::already_open; - return ec; - } - - int fd = descriptor_ops::open(device.c_str(), - O_RDWR | O_NONBLOCK | O_NOCTTY, ec); - if (fd < 0) - return ec; - - int s = descriptor_ops::fcntl(fd, F_GETFL, ec); - if (s >= 0) - s = descriptor_ops::fcntl(fd, F_SETFL, s | O_NONBLOCK, ec); - if (s < 0) - { - asio::error_code ignored_ec; - descriptor_ops::close(fd, ignored_ec); - return ec; - } - - // Set up default serial port options. - termios ios; - descriptor_ops::clear_error(ec); - s = descriptor_ops::error_wrapper(::tcgetattr(fd, &ios), ec); - if (s >= 0) - { -#if defined(_BSD_SOURCE) - ::cfmakeraw(&ios); -#else - ios.c_iflag &= ~(IGNBRK | BRKINT | PARMRK - | ISTRIP | INLCR | IGNCR | ICRNL | IXON); - ios.c_oflag &= ~OPOST; - ios.c_lflag &= ~(ECHO | ECHONL | ICANON | ISIG | IEXTEN); - ios.c_cflag &= ~(CSIZE | PARENB); - ios.c_cflag |= CS8; -#endif - ios.c_iflag |= IGNPAR; - descriptor_ops::clear_error(ec); - s = descriptor_ops::error_wrapper(::tcsetattr(fd, TCSANOW, &ios), ec); - } - if (s < 0) - { - asio::error_code ignored_ec; - descriptor_ops::close(fd, ignored_ec); - return ec; - } - - // We're done. Take ownership of the serial port descriptor. - if (descriptor_service_.assign(impl, fd, ec)) - { - asio::error_code ignored_ec; - descriptor_ops::close(fd, ignored_ec); - } - - return ec; - } - - // Assign a native handle to a handle implementation. - asio::error_code assign(implementation_type& impl, - const native_type& native_descriptor, asio::error_code& ec) - { - return descriptor_service_.assign(impl, native_descriptor, ec); - } - - // Determine whether the handle is open. - bool is_open(const implementation_type& impl) const - { - return descriptor_service_.is_open(impl); - } - - // Destroy a handle implementation. - asio::error_code close(implementation_type& impl, - asio::error_code& ec) - { - return descriptor_service_.close(impl, ec); - } - - // Get the native handle representation. - native_type native(implementation_type& impl) - { - return descriptor_service_.native(impl); - } - - // Cancel all operations associated with the handle. - asio::error_code cancel(implementation_type& impl, - asio::error_code& ec) - { - return descriptor_service_.cancel(impl, ec); - } - - // Set an option on the serial port. - template - asio::error_code set_option(implementation_type& impl, - const SettableSerialPortOption& option, asio::error_code& ec) - { - termios ios; - descriptor_ops::clear_error(ec); - descriptor_ops::error_wrapper(::tcgetattr( - descriptor_service_.native(impl), &ios), ec); - if (ec) - return ec; - - if (option.store(ios, ec)) - return ec; - - descriptor_ops::clear_error(ec); - descriptor_ops::error_wrapper(::tcsetattr( - descriptor_service_.native(impl), TCSANOW, &ios), ec); - return ec; - } - - // Get an option from the serial port. - template - asio::error_code get_option(const implementation_type& impl, - GettableSerialPortOption& option, asio::error_code& ec) const - { - termios ios; - descriptor_ops::clear_error(ec); - descriptor_ops::error_wrapper(::tcgetattr( - descriptor_service_.native(impl), &ios), ec); - if (ec) - return ec; - - return option.load(ios, ec); - } - - // Send a break sequence to the serial port. - asio::error_code send_break(implementation_type& impl, - asio::error_code& ec) - { - descriptor_ops::clear_error(ec); - descriptor_ops::error_wrapper(::tcsendbreak( - descriptor_service_.native(impl), 0), ec); - return ec; - } - - // Write the given data. Returns the number of bytes sent. - template - size_t write_some(implementation_type& impl, - const ConstBufferSequence& buffers, asio::error_code& ec) - { - return descriptor_service_.write_some(impl, buffers, ec); - } - - // Start an asynchronous write. The data being written must be valid for the - // lifetime of the asynchronous operation. - template - void async_write_some(implementation_type& impl, - const ConstBufferSequence& buffers, Handler handler) - { - descriptor_service_.async_write_some(impl, buffers, handler); - } - - // Read some data. Returns the number of bytes received. - template - size_t read_some(implementation_type& impl, - const MutableBufferSequence& buffers, asio::error_code& ec) - { - return descriptor_service_.read_some(impl, buffers, ec); - } - - // Start an asynchronous read. The buffer for the data being received must be - // valid for the lifetime of the asynchronous operation. - template - void async_read_some(implementation_type& impl, - const MutableBufferSequence& buffers, Handler handler) - { - descriptor_service_.async_read_some(impl, buffers, handler); - } - -private: - // The handle service used for initiating asynchronous operations. - reactive_descriptor_service& descriptor_service_; -}; - -} // namespace detail -} // namespace asio - -#endif // !defined(BOOST_WINDOWS) && !defined(__CYGWIN__) - -#include "asio/detail/pop_options.hpp" - -#endif // ASIO_DETAIL_REACTIVE_SERIAL_PORT_SERVICE_HPP diff --git a/libtorrent/include/asio/detail/reactive_socket_service.hpp b/libtorrent/include/asio/detail/reactive_socket_service.hpp deleted file mode 100644 index c7aedf88e..000000000 --- a/libtorrent/include/asio/detail/reactive_socket_service.hpp +++ /dev/null @@ -1,1780 +0,0 @@ -// -// reactive_socket_service.hpp -// ~~~~~~~~~~~~~~~~~~~~~~~~~~~ -// -// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -#ifndef ASIO_DETAIL_REACTIVE_SOCKET_SERVICE_HPP -#define ASIO_DETAIL_REACTIVE_SOCKET_SERVICE_HPP - -#if defined(_MSC_VER) && (_MSC_VER >= 1200) -# pragma once -#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) - -#include "asio/detail/push_options.hpp" - -#include "asio/detail/push_options.hpp" -#include -#include "asio/detail/pop_options.hpp" - -#include "asio/buffer.hpp" -#include "asio/error.hpp" -#include "asio/io_service.hpp" -#include "asio/socket_base.hpp" -#include "asio/detail/bind_handler.hpp" -#include "asio/detail/handler_base_from_member.hpp" -#include "asio/detail/noncopyable.hpp" -#include "asio/detail/service_base.hpp" -#include "asio/detail/socket_holder.hpp" -#include "asio/detail/socket_ops.hpp" -#include "asio/detail/socket_types.hpp" - -namespace asio { -namespace detail { - -template -class reactive_socket_service - : public asio::detail::service_base< - reactive_socket_service > -{ -public: - // The protocol type. - typedef Protocol protocol_type; - - // The endpoint type. - typedef typename Protocol::endpoint endpoint_type; - - // The native type of a socket. - typedef socket_type native_type; - - // The implementation type of the socket. - class implementation_type - : private asio::detail::noncopyable - { - public: - // Default constructor. - implementation_type() - : socket_(invalid_socket), - flags_(0), - protocol_(endpoint_type().protocol()) - { - } - - private: - // Only this service will have access to the internal values. - friend class reactive_socket_service; - - // The native socket representation. - socket_type socket_; - - enum - { - user_set_non_blocking = 1, // The user wants a non-blocking socket. - internal_non_blocking = 2, // The socket has been set non-blocking. - enable_connection_aborted = 4, // User wants connection_aborted errors. - user_set_linger = 8 // The user set the linger option. - }; - - // Flags indicating the current state of the socket. - unsigned char flags_; - - // The protocol associated with the socket. - protocol_type protocol_; - - // Per-descriptor data used by the reactor. - typename Reactor::per_descriptor_data reactor_data_; - }; - - // The maximum number of buffers to support in a single operation. - enum { max_buffers = 64 < max_iov_len ? 64 : max_iov_len }; - - // Constructor. - reactive_socket_service(asio::io_service& io_service) - : asio::detail::service_base< - reactive_socket_service >(io_service), - reactor_(asio::use_service(io_service)) - { - } - - // Destroy all user-defined handler objects owned by the service. - void shutdown_service() - { - } - - // Construct a new socket implementation. - void construct(implementation_type& impl) - { - impl.socket_ = invalid_socket; - impl.flags_ = 0; - } - - // Destroy a socket implementation. - void destroy(implementation_type& impl) - { - if (impl.socket_ != invalid_socket) - { - reactor_.close_descriptor(impl.socket_, impl.reactor_data_); - - if (impl.flags_ & implementation_type::internal_non_blocking) - { - ioctl_arg_type non_blocking = 0; - asio::error_code ignored_ec; - socket_ops::ioctl(impl.socket_, FIONBIO, &non_blocking, ignored_ec); - impl.flags_ &= ~implementation_type::internal_non_blocking; - } - - if (impl.flags_ & implementation_type::user_set_linger) - { - ::linger opt; - opt.l_onoff = 0; - opt.l_linger = 0; - asio::error_code ignored_ec; - socket_ops::setsockopt(impl.socket_, - SOL_SOCKET, SO_LINGER, &opt, sizeof(opt), ignored_ec); - } - - asio::error_code ignored_ec; - socket_ops::close(impl.socket_, ignored_ec); - - impl.socket_ = invalid_socket; - } - } - - // Open a new socket implementation. - asio::error_code open(implementation_type& impl, - const protocol_type& protocol, asio::error_code& ec) - { - if (is_open(impl)) - { - ec = asio::error::already_open; - return ec; - } - - socket_holder sock(socket_ops::socket(protocol.family(), - protocol.type(), protocol.protocol(), ec)); - if (sock.get() == invalid_socket) - return ec; - - if (int err = reactor_.register_descriptor(sock.get(), impl.reactor_data_)) - { - ec = asio::error_code(err, - asio::error::get_system_category()); - return ec; - } - - impl.socket_ = sock.release(); - impl.flags_ = 0; - impl.protocol_ = protocol; - ec = asio::error_code(); - return ec; - } - - // Assign a native socket to a socket implementation. - asio::error_code assign(implementation_type& impl, - const protocol_type& protocol, const native_type& native_socket, - asio::error_code& ec) - { - if (is_open(impl)) - { - ec = asio::error::already_open; - return ec; - } - - if (int err = reactor_.register_descriptor( - native_socket, impl.reactor_data_)) - { - ec = asio::error_code(err, - asio::error::get_system_category()); - return ec; - } - - impl.socket_ = native_socket; - impl.flags_ = 0; - impl.protocol_ = protocol; - ec = asio::error_code(); - return ec; - } - - // Determine whether the socket is open. - bool is_open(const implementation_type& impl) const - { - return impl.socket_ != invalid_socket; - } - - // Destroy a socket implementation. - asio::error_code close(implementation_type& impl, - asio::error_code& ec) - { - if (is_open(impl)) - { - reactor_.close_descriptor(impl.socket_, impl.reactor_data_); - - if (impl.flags_ & implementation_type::internal_non_blocking) - { - ioctl_arg_type non_blocking = 0; - asio::error_code ignored_ec; - socket_ops::ioctl(impl.socket_, FIONBIO, &non_blocking, ignored_ec); - impl.flags_ &= ~implementation_type::internal_non_blocking; - } - - if (socket_ops::close(impl.socket_, ec) == socket_error_retval) - return ec; - - impl.socket_ = invalid_socket; - } - - ec = asio::error_code(); - return ec; - } - - // Get the native socket representation. - native_type native(implementation_type& impl) - { - return impl.socket_; - } - - // Cancel all operations associated with the socket. - asio::error_code cancel(implementation_type& impl, - asio::error_code& ec) - { - if (!is_open(impl)) - { - ec = asio::error::bad_descriptor; - return ec; - } - - reactor_.cancel_ops(impl.socket_, impl.reactor_data_); - ec = asio::error_code(); - return ec; - } - - // Determine whether the socket is at the out-of-band data mark. - bool at_mark(const implementation_type& impl, - asio::error_code& ec) const - { - if (!is_open(impl)) - { - ec = asio::error::bad_descriptor; - return false; - } - - asio::detail::ioctl_arg_type value = 0; - socket_ops::ioctl(impl.socket_, SIOCATMARK, &value, ec); -#if defined(ENOTTY) - if (ec.value() == ENOTTY) - ec = asio::error::not_socket; -#endif // defined(ENOTTY) - return ec ? false : value != 0; - } - - // Determine the number of bytes available for reading. - std::size_t available(const implementation_type& impl, - asio::error_code& ec) const - { - if (!is_open(impl)) - { - ec = asio::error::bad_descriptor; - return 0; - } - - asio::detail::ioctl_arg_type value = 0; - socket_ops::ioctl(impl.socket_, FIONREAD, &value, ec); -#if defined(ENOTTY) - if (ec.value() == ENOTTY) - ec = asio::error::not_socket; -#endif // defined(ENOTTY) - return ec ? static_cast(0) : static_cast(value); - } - - // Bind the socket to the specified local endpoint. - asio::error_code bind(implementation_type& impl, - const endpoint_type& endpoint, asio::error_code& ec) - { - if (!is_open(impl)) - { - ec = asio::error::bad_descriptor; - return ec; - } - - socket_ops::bind(impl.socket_, endpoint.data(), endpoint.size(), ec); - return ec; - } - - // Place the socket into the state where it will listen for new connections. - asio::error_code listen(implementation_type& impl, int backlog, - asio::error_code& ec) - { - if (!is_open(impl)) - { - ec = asio::error::bad_descriptor; - return ec; - } - - socket_ops::listen(impl.socket_, backlog, ec); - return ec; - } - - // Set a socket option. - template - asio::error_code set_option(implementation_type& impl, - const Option& option, asio::error_code& ec) - { - if (!is_open(impl)) - { - ec = asio::error::bad_descriptor; - return ec; - } - - if (option.level(impl.protocol_) == custom_socket_option_level - && option.name(impl.protocol_) == enable_connection_aborted_option) - { - if (option.size(impl.protocol_) != sizeof(int)) - { - ec = asio::error::invalid_argument; - } - else - { - if (*reinterpret_cast(option.data(impl.protocol_))) - impl.flags_ |= implementation_type::enable_connection_aborted; - else - impl.flags_ &= ~implementation_type::enable_connection_aborted; - ec = asio::error_code(); - } - return ec; - } - else - { - if (option.level(impl.protocol_) == SOL_SOCKET - && option.name(impl.protocol_) == SO_LINGER) - { - impl.flags_ |= implementation_type::user_set_linger; - } - - socket_ops::setsockopt(impl.socket_, - option.level(impl.protocol_), option.name(impl.protocol_), - option.data(impl.protocol_), option.size(impl.protocol_), ec); - -#if defined(__MACH__) && defined(__APPLE__) \ -|| defined(__NetBSD__) || defined(__FreeBSD__) || defined(__OpenBSD__) - // To implement portable behaviour for SO_REUSEADDR with UDP sockets we - // need to also set SO_REUSEPORT on BSD-based platforms. - if (!ec && impl.protocol_.type() == SOCK_DGRAM - && option.level(impl.protocol_) == SOL_SOCKET - && option.name(impl.protocol_) == SO_REUSEADDR) - { - asio::error_code ignored_ec; - socket_ops::setsockopt(impl.socket_, SOL_SOCKET, SO_REUSEPORT, - option.data(impl.protocol_), option.size(impl.protocol_), - ignored_ec); - } -#endif - - return ec; - } - } - - // Set a socket option. - template - asio::error_code get_option(const implementation_type& impl, - Option& option, asio::error_code& ec) const - { - if (!is_open(impl)) - { - ec = asio::error::bad_descriptor; - return ec; - } - - if (option.level(impl.protocol_) == custom_socket_option_level - && option.name(impl.protocol_) == enable_connection_aborted_option) - { - if (option.size(impl.protocol_) != sizeof(int)) - { - ec = asio::error::invalid_argument; - } - else - { - int* target = reinterpret_cast(option.data(impl.protocol_)); - if (impl.flags_ & implementation_type::enable_connection_aborted) - *target = 1; - else - *target = 0; - option.resize(impl.protocol_, sizeof(int)); - ec = asio::error_code(); - } - return ec; - } - else - { - size_t size = option.size(impl.protocol_); - socket_ops::getsockopt(impl.socket_, - option.level(impl.protocol_), option.name(impl.protocol_), - option.data(impl.protocol_), &size, ec); - if (!ec) - option.resize(impl.protocol_, size); - return ec; - } - } - - // Perform an IO control command on the socket. - template - asio::error_code io_control(implementation_type& impl, - IO_Control_Command& command, asio::error_code& ec) - { - if (!is_open(impl)) - { - ec = asio::error::bad_descriptor; - return ec; - } - - if (command.name() == static_cast(FIONBIO)) - { - if (command.get()) - impl.flags_ |= implementation_type::user_set_non_blocking; - else - impl.flags_ &= ~implementation_type::user_set_non_blocking; - ec = asio::error_code(); - } - else - { - socket_ops::ioctl(impl.socket_, command.name(), - static_cast(command.data()), ec); - } - return ec; - } - - // Get the local endpoint. - endpoint_type local_endpoint(const implementation_type& impl, - asio::error_code& ec) const - { - if (!is_open(impl)) - { - ec = asio::error::bad_descriptor; - return endpoint_type(); - } - - endpoint_type endpoint; - std::size_t addr_len = endpoint.capacity(); - if (socket_ops::getsockname(impl.socket_, endpoint.data(), &addr_len, ec)) - return endpoint_type(); - endpoint.resize(addr_len); - return endpoint; - } - - // Get the remote endpoint. - endpoint_type remote_endpoint(const implementation_type& impl, - asio::error_code& ec) const - { - if (!is_open(impl)) - { - ec = asio::error::bad_descriptor; - return endpoint_type(); - } - - endpoint_type endpoint; - std::size_t addr_len = endpoint.capacity(); - if (socket_ops::getpeername(impl.socket_, endpoint.data(), &addr_len, ec)) - return endpoint_type(); - endpoint.resize(addr_len); - return endpoint; - } - - /// Disable sends or receives on the socket. - asio::error_code shutdown(implementation_type& impl, - socket_base::shutdown_type what, asio::error_code& ec) - { - if (!is_open(impl)) - { - ec = asio::error::bad_descriptor; - return ec; - } - - socket_ops::shutdown(impl.socket_, what, ec); - return ec; - } - - // Send the given data to the peer. - template - size_t send(implementation_type& impl, const ConstBufferSequence& buffers, - socket_base::message_flags flags, asio::error_code& ec) - { - if (!is_open(impl)) - { - ec = asio::error::bad_descriptor; - return 0; - } - - // Copy buffers into array. - socket_ops::buf bufs[max_buffers]; - typename ConstBufferSequence::const_iterator iter = buffers.begin(); - typename ConstBufferSequence::const_iterator end = buffers.end(); - size_t i = 0; - size_t total_buffer_size = 0; - for (; iter != end && i < max_buffers; ++iter, ++i) - { - asio::const_buffer buffer(*iter); - socket_ops::init_buf(bufs[i], - asio::buffer_cast(buffer), - asio::buffer_size(buffer)); - total_buffer_size += asio::buffer_size(buffer); - } - - // A request to receive 0 bytes on a stream socket is a no-op. - if (impl.protocol_.type() == SOCK_STREAM && total_buffer_size == 0) - { - ec = asio::error_code(); - return 0; - } - - // Make socket non-blocking if user wants non-blocking. - if (impl.flags_ & implementation_type::user_set_non_blocking) - { - if (!(impl.flags_ & implementation_type::internal_non_blocking)) - { - ioctl_arg_type non_blocking = 1; - if (socket_ops::ioctl(impl.socket_, FIONBIO, &non_blocking, ec)) - return 0; - impl.flags_ |= implementation_type::internal_non_blocking; - } - } - - // Send the data. - for (;;) - { - // Try to complete the operation without blocking. - int bytes_sent = socket_ops::send(impl.socket_, bufs, i, flags, ec); - - // Check if operation succeeded. - if (bytes_sent >= 0) - return bytes_sent; - - // Operation failed. - if ((impl.flags_ & implementation_type::user_set_non_blocking) - || (ec != asio::error::would_block - && ec != asio::error::try_again)) - return 0; - - // Wait for socket to become ready. - if (socket_ops::poll_write(impl.socket_, ec) < 0) - return 0; - } - } - - // Wait until data can be sent without blocking. - size_t send(implementation_type& impl, const null_buffers&, - socket_base::message_flags, asio::error_code& ec) - { - if (!is_open(impl)) - { - ec = asio::error::bad_descriptor; - return 0; - } - - // Wait for socket to become ready. - socket_ops::poll_write(impl.socket_, ec); - - return 0; - } - - template - class send_operation : - public handler_base_from_member - { - public: - send_operation(socket_type socket, asio::io_service& io_service, - const ConstBufferSequence& buffers, socket_base::message_flags flags, - Handler handler) - : handler_base_from_member(handler), - socket_(socket), - io_service_(io_service), - work_(io_service), - buffers_(buffers), - flags_(flags) - { - } - - bool perform(asio::error_code& ec, - std::size_t& bytes_transferred) - { - // Check whether the operation was successful. - if (ec) - { - bytes_transferred = 0; - return true; - } - - // Copy buffers into array. - socket_ops::buf bufs[max_buffers]; - typename ConstBufferSequence::const_iterator iter = buffers_.begin(); - typename ConstBufferSequence::const_iterator end = buffers_.end(); - size_t i = 0; - for (; iter != end && i < max_buffers; ++iter, ++i) - { - asio::const_buffer buffer(*iter); - socket_ops::init_buf(bufs[i], - asio::buffer_cast(buffer), - asio::buffer_size(buffer)); - } - - // Send the data. - int bytes = socket_ops::send(socket_, bufs, i, flags_, ec); - - // Check if we need to run the operation again. - if (ec == asio::error::would_block - || ec == asio::error::try_again) - return false; - - bytes_transferred = (bytes < 0 ? 0 : bytes); - return true; - } - - void complete(const asio::error_code& ec, - std::size_t bytes_transferred) - { - io_service_.post(bind_handler(this->handler_, ec, bytes_transferred)); - } - - private: - socket_type socket_; - asio::io_service& io_service_; - asio::io_service::work work_; - ConstBufferSequence buffers_; - socket_base::message_flags flags_; - }; - - // Start an asynchronous send. The data being sent must be valid for the - // lifetime of the asynchronous operation. - template - void async_send(implementation_type& impl, const ConstBufferSequence& buffers, - socket_base::message_flags flags, Handler handler) - { - if (!is_open(impl)) - { - this->get_io_service().post(bind_handler(handler, - asio::error::bad_descriptor, 0)); - } - else - { - if (impl.protocol_.type() == SOCK_STREAM) - { - // Determine total size of buffers. - typename ConstBufferSequence::const_iterator iter = buffers.begin(); - typename ConstBufferSequence::const_iterator end = buffers.end(); - size_t i = 0; - size_t total_buffer_size = 0; - for (; iter != end && i < max_buffers; ++iter, ++i) - { - asio::const_buffer buffer(*iter); - total_buffer_size += asio::buffer_size(buffer); - } - - // A request to receive 0 bytes on a stream socket is a no-op. - if (total_buffer_size == 0) - { - this->get_io_service().post(bind_handler(handler, - asio::error_code(), 0)); - return; - } - } - - // Make socket non-blocking. - if (!(impl.flags_ & implementation_type::internal_non_blocking)) - { - ioctl_arg_type non_blocking = 1; - asio::error_code ec; - if (socket_ops::ioctl(impl.socket_, FIONBIO, &non_blocking, ec)) - { - this->get_io_service().post(bind_handler(handler, ec, 0)); - return; - } - impl.flags_ |= implementation_type::internal_non_blocking; - } - - reactor_.start_write_op(impl.socket_, impl.reactor_data_, - send_operation( - impl.socket_, this->get_io_service(), buffers, flags, handler)); - } - } - - template - class null_buffers_operation : - public handler_base_from_member - { - public: - null_buffers_operation(asio::io_service& io_service, Handler handler) - : handler_base_from_member(handler), - work_(io_service) - { - } - - bool perform(asio::error_code&, - std::size_t& bytes_transferred) - { - bytes_transferred = 0; - return true; - } - - void complete(const asio::error_code& ec, - std::size_t bytes_transferred) - { - work_.get_io_service().post(bind_handler( - this->handler_, ec, bytes_transferred)); - } - - private: - asio::io_service::work work_; - }; - - // Start an asynchronous wait until data can be sent without blocking. - template - void async_send(implementation_type& impl, const null_buffers&, - socket_base::message_flags, Handler handler) - { - if (!is_open(impl)) - { - this->get_io_service().post(bind_handler(handler, - asio::error::bad_descriptor, 0)); - } - else - { - reactor_.start_write_op(impl.socket_, impl.reactor_data_, - null_buffers_operation(this->get_io_service(), handler), - false); - } - } - - // Send a datagram to the specified endpoint. Returns the number of bytes - // sent. - template - size_t send_to(implementation_type& impl, const ConstBufferSequence& buffers, - const endpoint_type& destination, socket_base::message_flags flags, - asio::error_code& ec) - { - if (!is_open(impl)) - { - ec = asio::error::bad_descriptor; - return 0; - } - - // Copy buffers into array. - socket_ops::buf bufs[max_buffers]; - typename ConstBufferSequence::const_iterator iter = buffers.begin(); - typename ConstBufferSequence::const_iterator end = buffers.end(); - size_t i = 0; - for (; iter != end && i < max_buffers; ++iter, ++i) - { - asio::const_buffer buffer(*iter); - socket_ops::init_buf(bufs[i], - asio::buffer_cast(buffer), - asio::buffer_size(buffer)); - } - - // Make socket non-blocking if user wants non-blocking. - if (impl.flags_ & implementation_type::user_set_non_blocking) - { - if (!(impl.flags_ & implementation_type::internal_non_blocking)) - { - ioctl_arg_type non_blocking = 1; - if (socket_ops::ioctl(impl.socket_, FIONBIO, &non_blocking, ec)) - return 0; - impl.flags_ |= implementation_type::internal_non_blocking; - } - } - - // Send the data. - for (;;) - { - // Try to complete the operation without blocking. - int bytes_sent = socket_ops::sendto(impl.socket_, bufs, i, flags, - destination.data(), destination.size(), ec); - - // Check if operation succeeded. - if (bytes_sent >= 0) - return bytes_sent; - - // Operation failed. - if ((impl.flags_ & implementation_type::user_set_non_blocking) - || (ec != asio::error::would_block - && ec != asio::error::try_again)) - return 0; - - // Wait for socket to become ready. - if (socket_ops::poll_write(impl.socket_, ec) < 0) - return 0; - } - } - - // Wait until data can be sent without blocking. - size_t send_to(implementation_type& impl, const null_buffers&, - socket_base::message_flags, const endpoint_type&, - asio::error_code& ec) - { - if (!is_open(impl)) - { - ec = asio::error::bad_descriptor; - return 0; - } - - // Wait for socket to become ready. - socket_ops::poll_write(impl.socket_, ec); - - return 0; - } - - template - class send_to_operation : - public handler_base_from_member - { - public: - send_to_operation(socket_type socket, asio::io_service& io_service, - const ConstBufferSequence& buffers, const endpoint_type& endpoint, - socket_base::message_flags flags, Handler handler) - : handler_base_from_member(handler), - socket_(socket), - io_service_(io_service), - work_(io_service), - buffers_(buffers), - destination_(endpoint), - flags_(flags) - { - } - - bool perform(asio::error_code& ec, - std::size_t& bytes_transferred) - { - // Check whether the operation was successful. - if (ec) - { - bytes_transferred = 0; - return true; - } - - // Copy buffers into array. - socket_ops::buf bufs[max_buffers]; - typename ConstBufferSequence::const_iterator iter = buffers_.begin(); - typename ConstBufferSequence::const_iterator end = buffers_.end(); - size_t i = 0; - for (; iter != end && i < max_buffers; ++iter, ++i) - { - asio::const_buffer buffer(*iter); - socket_ops::init_buf(bufs[i], - asio::buffer_cast(buffer), - asio::buffer_size(buffer)); - } - - // Send the data. - int bytes = socket_ops::sendto(socket_, bufs, i, flags_, - destination_.data(), destination_.size(), ec); - - // Check if we need to run the operation again. - if (ec == asio::error::would_block - || ec == asio::error::try_again) - return false; - - bytes_transferred = (bytes < 0 ? 0 : bytes); - return true; - } - - void complete(const asio::error_code& ec, - std::size_t bytes_transferred) - { - io_service_.post(bind_handler(this->handler_, ec, bytes_transferred)); - } - - private: - socket_type socket_; - asio::io_service& io_service_; - asio::io_service::work work_; - ConstBufferSequence buffers_; - endpoint_type destination_; - socket_base::message_flags flags_; - }; - - // Start an asynchronous send. The data being sent must be valid for the - // lifetime of the asynchronous operation. - template - void async_send_to(implementation_type& impl, - const ConstBufferSequence& buffers, - const endpoint_type& destination, socket_base::message_flags flags, - Handler handler) - { - if (!is_open(impl)) - { - this->get_io_service().post(bind_handler(handler, - asio::error::bad_descriptor, 0)); - } - else - { - // Make socket non-blocking. - if (!(impl.flags_ & implementation_type::internal_non_blocking)) - { - ioctl_arg_type non_blocking = 1; - asio::error_code ec; - if (socket_ops::ioctl(impl.socket_, FIONBIO, &non_blocking, ec)) - { - this->get_io_service().post(bind_handler(handler, ec, 0)); - return; - } - impl.flags_ |= implementation_type::internal_non_blocking; - } - - reactor_.start_write_op(impl.socket_, impl.reactor_data_, - send_to_operation( - impl.socket_, this->get_io_service(), buffers, - destination, flags, handler)); - } - } - - // Start an asynchronous wait until data can be sent without blocking. - template - void async_send_to(implementation_type& impl, const null_buffers&, - socket_base::message_flags, const endpoint_type&, Handler handler) - { - if (!is_open(impl)) - { - this->get_io_service().post(bind_handler(handler, - asio::error::bad_descriptor, 0)); - } - else - { - reactor_.start_write_op(impl.socket_, impl.reactor_data_, - null_buffers_operation(this->get_io_service(), handler), - false); - } - } - - // Receive some data from the peer. Returns the number of bytes received. - template - size_t receive(implementation_type& impl, - const MutableBufferSequence& buffers, - socket_base::message_flags flags, asio::error_code& ec) - { - if (!is_open(impl)) - { - ec = asio::error::bad_descriptor; - return 0; - } - - // Copy buffers into array. - socket_ops::buf bufs[max_buffers]; - typename MutableBufferSequence::const_iterator iter = buffers.begin(); - typename MutableBufferSequence::const_iterator end = buffers.end(); - size_t i = 0; - size_t total_buffer_size = 0; - for (; iter != end && i < max_buffers; ++iter, ++i) - { - asio::mutable_buffer buffer(*iter); - socket_ops::init_buf(bufs[i], - asio::buffer_cast(buffer), - asio::buffer_size(buffer)); - total_buffer_size += asio::buffer_size(buffer); - } - - // A request to receive 0 bytes on a stream socket is a no-op. - if (impl.protocol_.type() == SOCK_STREAM && total_buffer_size == 0) - { - ec = asio::error_code(); - return 0; - } - - // Make socket non-blocking if user wants non-blocking. - if (impl.flags_ & implementation_type::user_set_non_blocking) - { - if (!(impl.flags_ & implementation_type::internal_non_blocking)) - { - ioctl_arg_type non_blocking = 1; - if (socket_ops::ioctl(impl.socket_, FIONBIO, &non_blocking, ec)) - return 0; - impl.flags_ |= implementation_type::internal_non_blocking; - } - } - - // Receive some data. - for (;;) - { - // Try to complete the operation without blocking. - int bytes_recvd = socket_ops::recv(impl.socket_, bufs, i, flags, ec); - - // Check if operation succeeded. - if (bytes_recvd > 0) - return bytes_recvd; - - // Check for EOF. - if (bytes_recvd == 0 && impl.protocol_.type() == SOCK_STREAM) - { - ec = asio::error::eof; - return 0; - } - - // Operation failed. - if ((impl.flags_ & implementation_type::user_set_non_blocking) - || (ec != asio::error::would_block - && ec != asio::error::try_again)) - return 0; - - // Wait for socket to become ready. - if (socket_ops::poll_read(impl.socket_, ec) < 0) - return 0; - } - } - - // Wait until data can be received without blocking. - size_t receive(implementation_type& impl, const null_buffers&, - socket_base::message_flags, asio::error_code& ec) - { - if (!is_open(impl)) - { - ec = asio::error::bad_descriptor; - return 0; - } - - // Wait for socket to become ready. - socket_ops::poll_read(impl.socket_, ec); - - return 0; - } - - template - class receive_operation : - public handler_base_from_member - { - public: - receive_operation(socket_type socket, int protocol_type, - asio::io_service& io_service, - const MutableBufferSequence& buffers, - socket_base::message_flags flags, Handler handler) - : handler_base_from_member(handler), - socket_(socket), - protocol_type_(protocol_type), - io_service_(io_service), - work_(io_service), - buffers_(buffers), - flags_(flags) - { - } - - bool perform(asio::error_code& ec, - std::size_t& bytes_transferred) - { - // Check whether the operation was successful. - if (ec) - { - bytes_transferred = 0; - return true; - } - - // Copy buffers into array. - socket_ops::buf bufs[max_buffers]; - typename MutableBufferSequence::const_iterator iter = buffers_.begin(); - typename MutableBufferSequence::const_iterator end = buffers_.end(); - size_t i = 0; - for (; iter != end && i < max_buffers; ++iter, ++i) - { - asio::mutable_buffer buffer(*iter); - socket_ops::init_buf(bufs[i], - asio::buffer_cast(buffer), - asio::buffer_size(buffer)); - } - - // Receive some data. - int bytes = socket_ops::recv(socket_, bufs, i, flags_, ec); - if (bytes == 0 && protocol_type_ == SOCK_STREAM) - ec = asio::error::eof; - - // Check if we need to run the operation again. - if (ec == asio::error::would_block - || ec == asio::error::try_again) - return false; - - bytes_transferred = (bytes < 0 ? 0 : bytes); - return true; - } - - void complete(const asio::error_code& ec, - std::size_t bytes_transferred) - { - io_service_.post(bind_handler(this->handler_, ec, bytes_transferred)); - } - - private: - socket_type socket_; - int protocol_type_; - asio::io_service& io_service_; - asio::io_service::work work_; - MutableBufferSequence buffers_; - socket_base::message_flags flags_; - }; - - // Start an asynchronous receive. The buffer for the data being received - // must be valid for the lifetime of the asynchronous operation. - template - void async_receive(implementation_type& impl, - const MutableBufferSequence& buffers, - socket_base::message_flags flags, Handler handler) - { - if (!is_open(impl)) - { - this->get_io_service().post(bind_handler(handler, - asio::error::bad_descriptor, 0)); - } - else - { - if (impl.protocol_.type() == SOCK_STREAM) - { - // Determine total size of buffers. - typename MutableBufferSequence::const_iterator iter = buffers.begin(); - typename MutableBufferSequence::const_iterator end = buffers.end(); - size_t i = 0; - size_t total_buffer_size = 0; - for (; iter != end && i < max_buffers; ++iter, ++i) - { - asio::mutable_buffer buffer(*iter); - total_buffer_size += asio::buffer_size(buffer); - } - - // A request to receive 0 bytes on a stream socket is a no-op. - if (total_buffer_size == 0) - { - this->get_io_service().post(bind_handler(handler, - asio::error_code(), 0)); - return; - } - } - - // Make socket non-blocking. - if (!(impl.flags_ & implementation_type::internal_non_blocking)) - { - ioctl_arg_type non_blocking = 1; - asio::error_code ec; - if (socket_ops::ioctl(impl.socket_, FIONBIO, &non_blocking, ec)) - { - this->get_io_service().post(bind_handler(handler, ec, 0)); - return; - } - impl.flags_ |= implementation_type::internal_non_blocking; - } - - if (flags & socket_base::message_out_of_band) - { - reactor_.start_except_op(impl.socket_, impl.reactor_data_, - receive_operation( - impl.socket_, impl.protocol_.type(), - this->get_io_service(), buffers, flags, handler)); - } - else - { - reactor_.start_read_op(impl.socket_, impl.reactor_data_, - receive_operation( - impl.socket_, impl.protocol_.type(), - this->get_io_service(), buffers, flags, handler)); - } - } - } - - // Wait until data can be received without blocking. - template - void async_receive(implementation_type& impl, const null_buffers&, - socket_base::message_flags flags, Handler handler) - { - if (!is_open(impl)) - { - this->get_io_service().post(bind_handler(handler, - asio::error::bad_descriptor, 0)); - } - else if (flags & socket_base::message_out_of_band) - { - reactor_.start_except_op(impl.socket_, impl.reactor_data_, - null_buffers_operation(this->get_io_service(), handler)); - } - else - { - reactor_.start_read_op(impl.socket_, impl.reactor_data_, - null_buffers_operation(this->get_io_service(), handler), - false); - } - } - - // Receive a datagram with the endpoint of the sender. Returns the number of - // bytes received. - template - size_t receive_from(implementation_type& impl, - const MutableBufferSequence& buffers, - endpoint_type& sender_endpoint, socket_base::message_flags flags, - asio::error_code& ec) - { - if (!is_open(impl)) - { - ec = asio::error::bad_descriptor; - return 0; - } - - // Copy buffers into array. - socket_ops::buf bufs[max_buffers]; - typename MutableBufferSequence::const_iterator iter = buffers.begin(); - typename MutableBufferSequence::const_iterator end = buffers.end(); - size_t i = 0; - for (; iter != end && i < max_buffers; ++iter, ++i) - { - asio::mutable_buffer buffer(*iter); - socket_ops::init_buf(bufs[i], - asio::buffer_cast(buffer), - asio::buffer_size(buffer)); - } - - // Make socket non-blocking if user wants non-blocking. - if (impl.flags_ & implementation_type::user_set_non_blocking) - { - if (!(impl.flags_ & implementation_type::internal_non_blocking)) - { - ioctl_arg_type non_blocking = 1; - if (socket_ops::ioctl(impl.socket_, FIONBIO, &non_blocking, ec)) - return 0; - impl.flags_ |= implementation_type::internal_non_blocking; - } - } - - // Receive some data. - for (;;) - { - // Try to complete the operation without blocking. - std::size_t addr_len = sender_endpoint.capacity(); - int bytes_recvd = socket_ops::recvfrom(impl.socket_, bufs, i, flags, - sender_endpoint.data(), &addr_len, ec); - - // Check if operation succeeded. - if (bytes_recvd > 0) - { - sender_endpoint.resize(addr_len); - return bytes_recvd; - } - - // Check for EOF. - if (bytes_recvd == 0 && impl.protocol_.type() == SOCK_STREAM) - { - ec = asio::error::eof; - return 0; - } - - // Operation failed. - if ((impl.flags_ & implementation_type::user_set_non_blocking) - || (ec != asio::error::would_block - && ec != asio::error::try_again)) - return 0; - - // Wait for socket to become ready. - if (socket_ops::poll_read(impl.socket_, ec) < 0) - return 0; - } - } - - // Wait until data can be received without blocking. - size_t receive_from(implementation_type& impl, const null_buffers&, - endpoint_type& sender_endpoint, socket_base::message_flags, - asio::error_code& ec) - { - if (!is_open(impl)) - { - ec = asio::error::bad_descriptor; - return 0; - } - - // Wait for socket to become ready. - socket_ops::poll_read(impl.socket_, ec); - - // Reset endpoint since it can be given no sensible value at this time. - sender_endpoint = endpoint_type(); - - return 0; - } - - template - class receive_from_operation : - public handler_base_from_member - { - public: - receive_from_operation(socket_type socket, int protocol_type, - asio::io_service& io_service, - const MutableBufferSequence& buffers, endpoint_type& endpoint, - socket_base::message_flags flags, Handler handler) - : handler_base_from_member(handler), - socket_(socket), - protocol_type_(protocol_type), - io_service_(io_service), - work_(io_service), - buffers_(buffers), - sender_endpoint_(endpoint), - flags_(flags) - { - } - - bool perform(asio::error_code& ec, - std::size_t& bytes_transferred) - { - // Check whether the operation was successful. - if (ec) - { - bytes_transferred = 0; - return true; - } - - // Copy buffers into array. - socket_ops::buf bufs[max_buffers]; - typename MutableBufferSequence::const_iterator iter = buffers_.begin(); - typename MutableBufferSequence::const_iterator end = buffers_.end(); - size_t i = 0; - for (; iter != end && i < max_buffers; ++iter, ++i) - { - asio::mutable_buffer buffer(*iter); - socket_ops::init_buf(bufs[i], - asio::buffer_cast(buffer), - asio::buffer_size(buffer)); - } - - // Receive some data. - std::size_t addr_len = sender_endpoint_.capacity(); - int bytes = socket_ops::recvfrom(socket_, bufs, i, flags_, - sender_endpoint_.data(), &addr_len, ec); - if (bytes == 0 && protocol_type_ == SOCK_STREAM) - ec = asio::error::eof; - - // Check if we need to run the operation again. - if (ec == asio::error::would_block - || ec == asio::error::try_again) - return false; - - sender_endpoint_.resize(addr_len); - bytes_transferred = (bytes < 0 ? 0 : bytes); - return true; - } - - void complete(const asio::error_code& ec, - std::size_t bytes_transferred) - { - io_service_.post(bind_handler(this->handler_, ec, bytes_transferred)); - } - - private: - socket_type socket_; - int protocol_type_; - asio::io_service& io_service_; - asio::io_service::work work_; - MutableBufferSequence buffers_; - endpoint_type& sender_endpoint_; - socket_base::message_flags flags_; - }; - - // Start an asynchronous receive. The buffer for the data being received and - // the sender_endpoint object must both be valid for the lifetime of the - // asynchronous operation. - template - void async_receive_from(implementation_type& impl, - const MutableBufferSequence& buffers, endpoint_type& sender_endpoint, - socket_base::message_flags flags, Handler handler) - { - if (!is_open(impl)) - { - this->get_io_service().post(bind_handler(handler, - asio::error::bad_descriptor, 0)); - } - else - { - // Make socket non-blocking. - if (!(impl.flags_ & implementation_type::internal_non_blocking)) - { - ioctl_arg_type non_blocking = 1; - asio::error_code ec; - if (socket_ops::ioctl(impl.socket_, FIONBIO, &non_blocking, ec)) - { - this->get_io_service().post(bind_handler(handler, ec, 0)); - return; - } - impl.flags_ |= implementation_type::internal_non_blocking; - } - - reactor_.start_read_op(impl.socket_, impl.reactor_data_, - receive_from_operation( - impl.socket_, impl.protocol_.type(), this->get_io_service(), - buffers, sender_endpoint, flags, handler)); - } - } - - // Wait until data can be received without blocking. - template - void async_receive_from(implementation_type& impl, - const null_buffers&, endpoint_type& sender_endpoint, - socket_base::message_flags flags, Handler handler) - { - if (!is_open(impl)) - { - this->get_io_service().post(bind_handler(handler, - asio::error::bad_descriptor, 0)); - } - else - { - // Reset endpoint since it can be given no sensible value at this time. - sender_endpoint = endpoint_type(); - - if (flags & socket_base::message_out_of_band) - { - reactor_.start_except_op(impl.socket_, impl.reactor_data_, - null_buffers_operation(this->get_io_service(), handler)); - } - else - { - reactor_.start_read_op(impl.socket_, impl.reactor_data_, - null_buffers_operation(this->get_io_service(), handler), - false); - } - } - } - - // Accept a new connection. - template - asio::error_code accept(implementation_type& impl, - Socket& peer, endpoint_type* peer_endpoint, asio::error_code& ec) - { - if (!is_open(impl)) - { - ec = asio::error::bad_descriptor; - return ec; - } - - // We cannot accept a socket that is already open. - if (peer.is_open()) - { - ec = asio::error::already_open; - return ec; - } - - // Make socket non-blocking if user wants non-blocking. - if (impl.flags_ & implementation_type::user_set_non_blocking) - { - if (!(impl.flags_ & implementation_type::internal_non_blocking)) - { - ioctl_arg_type non_blocking = 1; - if (socket_ops::ioctl(impl.socket_, FIONBIO, &non_blocking, ec)) - return ec; - impl.flags_ |= implementation_type::internal_non_blocking; - } - } - - // Accept a socket. - for (;;) - { - // Try to complete the operation without blocking. - asio::error_code ec; - socket_holder new_socket; - std::size_t addr_len = 0; - if (peer_endpoint) - { - addr_len = peer_endpoint->capacity(); - new_socket.reset(socket_ops::accept(impl.socket_, - peer_endpoint->data(), &addr_len, ec)); - } - else - { - new_socket.reset(socket_ops::accept(impl.socket_, 0, 0, ec)); - } - - // Check if operation succeeded. - if (new_socket.get() >= 0) - { - if (peer_endpoint) - peer_endpoint->resize(addr_len); - peer.assign(impl.protocol_, new_socket.get(), ec); - if (!ec) - new_socket.release(); - return ec; - } - - // Operation failed. - if (ec == asio::error::would_block - || ec == asio::error::try_again) - { - if (impl.flags_ & implementation_type::user_set_non_blocking) - return ec; - // Fall through to retry operation. - } - else if (ec == asio::error::connection_aborted) - { - if (impl.flags_ & implementation_type::enable_connection_aborted) - return ec; - // Fall through to retry operation. - } -#if defined(EPROTO) - else if (ec.value() == EPROTO) - { - if (impl.flags_ & implementation_type::enable_connection_aborted) - return ec; - // Fall through to retry operation. - } -#endif // defined(EPROTO) - else - return ec; - - // Wait for socket to become ready. - if (socket_ops::poll_read(impl.socket_, ec) < 0) - return ec; - } - } - - template - class accept_operation : - public handler_base_from_member - { - public: - accept_operation(socket_type socket, asio::io_service& io_service, - Socket& peer, const protocol_type& protocol, - endpoint_type* peer_endpoint, bool enable_connection_aborted, - Handler handler) - : handler_base_from_member(handler), - socket_(socket), - io_service_(io_service), - work_(io_service), - peer_(peer), - protocol_(protocol), - peer_endpoint_(peer_endpoint), - enable_connection_aborted_(enable_connection_aborted) - { - } - - bool perform(asio::error_code& ec, std::size_t&) - { - // Check whether the operation was successful. - if (ec) - return true; - - // Accept the waiting connection. - socket_holder new_socket; - std::size_t addr_len = 0; - if (peer_endpoint_) - { - addr_len = peer_endpoint_->capacity(); - new_socket.reset(socket_ops::accept(socket_, - peer_endpoint_->data(), &addr_len, ec)); - } - else - { - new_socket.reset(socket_ops::accept(socket_, 0, 0, ec)); - } - - // Check if we need to run the operation again. - if (ec == asio::error::would_block - || ec == asio::error::try_again) - return false; - if (ec == asio::error::connection_aborted - && !enable_connection_aborted_) - return false; -#if defined(EPROTO) - if (ec.value() == EPROTO && !enable_connection_aborted_) - return false; -#endif // defined(EPROTO) - - // Transfer ownership of the new socket to the peer object. - if (!ec) - { - if (peer_endpoint_) - peer_endpoint_->resize(addr_len); - peer_.assign(protocol_, new_socket.get(), ec); - if (!ec) - new_socket.release(); - } - - return true; - } - - void complete(const asio::error_code& ec, std::size_t) - { - io_service_.post(bind_handler(this->handler_, ec)); - } - - private: - socket_type socket_; - asio::io_service& io_service_; - asio::io_service::work work_; - Socket& peer_; - protocol_type protocol_; - endpoint_type* peer_endpoint_; - bool enable_connection_aborted_; - }; - - // Start an asynchronous accept. The peer and peer_endpoint objects - // must be valid until the accept's handler is invoked. - template - void async_accept(implementation_type& impl, Socket& peer, - endpoint_type* peer_endpoint, Handler handler) - { - if (!is_open(impl)) - { - this->get_io_service().post(bind_handler(handler, - asio::error::bad_descriptor)); - } - else if (peer.is_open()) - { - this->get_io_service().post(bind_handler(handler, - asio::error::already_open)); - } - else - { - // Make socket non-blocking. - if (!(impl.flags_ & implementation_type::internal_non_blocking)) - { - ioctl_arg_type non_blocking = 1; - asio::error_code ec; - if (socket_ops::ioctl(impl.socket_, FIONBIO, &non_blocking, ec)) - { - this->get_io_service().post(bind_handler(handler, ec)); - return; - } - impl.flags_ |= implementation_type::internal_non_blocking; - } - - reactor_.start_read_op(impl.socket_, impl.reactor_data_, - accept_operation( - impl.socket_, this->get_io_service(), - peer, impl.protocol_, peer_endpoint, - (impl.flags_ & implementation_type::enable_connection_aborted) != 0, - handler)); - } - } - - // Connect the socket to the specified endpoint. - asio::error_code connect(implementation_type& impl, - const endpoint_type& peer_endpoint, asio::error_code& ec) - { - if (!is_open(impl)) - { - ec = asio::error::bad_descriptor; - return ec; - } - - if (impl.flags_ & implementation_type::internal_non_blocking) - { - // Mark the socket as blocking while we perform the connect. - ioctl_arg_type non_blocking = 0; - if (socket_ops::ioctl(impl.socket_, FIONBIO, &non_blocking, ec)) - return ec; - impl.flags_ &= ~implementation_type::internal_non_blocking; - } - - // Perform the connect operation. - socket_ops::connect(impl.socket_, - peer_endpoint.data(), peer_endpoint.size(), ec); - return ec; - } - - template - class connect_operation : - public handler_base_from_member - { - public: - connect_operation(socket_type socket, - asio::io_service& io_service, Handler handler) - : handler_base_from_member(handler), - socket_(socket), - io_service_(io_service), - work_(io_service) - { - } - - bool perform(asio::error_code& ec, std::size_t&) - { - // Check whether the operation was successful. - if (ec) - return true; - - // Get the error code from the connect operation. - int connect_error = 0; - size_t connect_error_len = sizeof(connect_error); - if (socket_ops::getsockopt(socket_, SOL_SOCKET, SO_ERROR, - &connect_error, &connect_error_len, ec) == socket_error_retval) - return true; - - // The connection failed so the handler will be posted with an error code. - if (connect_error) - { - ec = asio::error_code(connect_error, - asio::error::get_system_category()); - return true; - } - - return true; - } - - void complete(const asio::error_code& ec, std::size_t) - { - io_service_.post(bind_handler(this->handler_, ec)); - } - - private: - socket_type socket_; - asio::io_service& io_service_; - asio::io_service::work work_; - }; - - // Start an asynchronous connect. - template - void async_connect(implementation_type& impl, - const endpoint_type& peer_endpoint, Handler handler) - { - if (!is_open(impl)) - { - this->get_io_service().post(bind_handler(handler, - asio::error::bad_descriptor)); - return; - } - - // Make socket non-blocking. - if (!(impl.flags_ & implementation_type::internal_non_blocking)) - { - ioctl_arg_type non_blocking = 1; - asio::error_code ec; - if (socket_ops::ioctl(impl.socket_, FIONBIO, &non_blocking, ec)) - { - this->get_io_service().post(bind_handler(handler, ec)); - return; - } - impl.flags_ |= implementation_type::internal_non_blocking; - } - - // Start the connect operation. The socket is already marked as non-blocking - // so the connection will take place asynchronously. - asio::error_code ec; - if (socket_ops::connect(impl.socket_, peer_endpoint.data(), - peer_endpoint.size(), ec) == 0) - { - // The connect operation has finished successfully so we need to post the - // handler immediately. - this->get_io_service().post(bind_handler(handler, - asio::error_code())); - } - else if (ec == asio::error::in_progress - || ec == asio::error::would_block) - { - // The connection is happening in the background, and we need to wait - // until the socket becomes writeable. - reactor_.start_connect_op(impl.socket_, impl.reactor_data_, - connect_operation(impl.socket_, - this->get_io_service(), handler)); - } - else - { - // The connect operation has failed, so post the handler immediately. - this->get_io_service().post(bind_handler(handler, ec)); - } - } - -private: - // The selector that performs event demultiplexing for the service. - Reactor& reactor_; -}; - -} // namespace detail -} // namespace asio - -#include "asio/detail/pop_options.hpp" - -#endif // ASIO_DETAIL_REACTIVE_SOCKET_SERVICE_HPP diff --git a/libtorrent/include/asio/detail/reactor_op_queue.hpp b/libtorrent/include/asio/detail/reactor_op_queue.hpp deleted file mode 100644 index 034591d0d..000000000 --- a/libtorrent/include/asio/detail/reactor_op_queue.hpp +++ /dev/null @@ -1,454 +0,0 @@ -// -// reactor_op_queue.hpp -// ~~~~~~~~~~~~~~~~~~~~ -// -// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -#ifndef ASIO_DETAIL_REACTOR_OP_QUEUE_HPP -#define ASIO_DETAIL_REACTOR_OP_QUEUE_HPP - -#if defined(_MSC_VER) && (_MSC_VER >= 1200) -# pragma once -#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) - -#include "asio/detail/push_options.hpp" - -#include "asio/detail/push_options.hpp" -#include -#include "asio/detail/pop_options.hpp" - -#include "asio/error.hpp" -#include "asio/detail/handler_alloc_helpers.hpp" -#include "asio/detail/hash_map.hpp" -#include "asio/detail/noncopyable.hpp" - -namespace asio { -namespace detail { - -template -class reactor_op_queue - : private noncopyable -{ -public: - // Constructor. - reactor_op_queue() - : operations_(), - cancelled_operations_(0), - complete_operations_(0) - { - } - - // Add a new operation to the queue. Returns true if this is the only - // operation for the given descriptor, in which case the reactor's event - // demultiplexing function call may need to be interrupted and restarted. - template - bool enqueue_operation(Descriptor descriptor, Operation operation) - { - // Allocate and construct an object to wrap the handler. - typedef handler_alloc_traits > alloc_traits; - raw_handler_ptr raw_ptr(operation); - handler_ptr ptr(raw_ptr, descriptor, operation); - - typedef typename operation_map::iterator iterator; - typedef typename operation_map::value_type value_type; - std::pair entry = - operations_.insert(value_type(descriptor, ptr.get())); - if (entry.second) - { - ptr.release(); - return true; - } - - op_base* current_op = entry.first->second; - while (current_op->next_) - current_op = current_op->next_; - current_op->next_ = ptr.release(); - - return false; - } - - // Cancel all operations associated with the descriptor. Any operations - // pending for the descriptor will be notified that they have been cancelled - // next time perform_cancellations is called. Returns true if any operations - // were cancelled, in which case the reactor's event demultiplexing function - // may need to be interrupted and restarted. - bool cancel_operations(Descriptor descriptor) - { - typename operation_map::iterator i = operations_.find(descriptor); - if (i != operations_.end()) - { - op_base* last_op = i->second; - while (last_op->next_) - last_op = last_op->next_; - last_op->next_ = cancelled_operations_; - cancelled_operations_ = i->second; - operations_.erase(i); - return true; - } - - return false; - } - - // Whether there are no operations in the queue. - bool empty() const - { - return operations_.empty(); - } - - // Determine whether there are any operations associated with the descriptor. - bool has_operation(Descriptor descriptor) const - { - return operations_.find(descriptor) != operations_.end(); - } - - // Perform the first operation corresponding to the descriptor. Returns true - // if there are more operations queued for the descriptor. - bool perform_operation(Descriptor descriptor, - const asio::error_code& result) - { - typename operation_map::iterator i = operations_.find(descriptor); - if (i != operations_.end()) - { - op_base* this_op = i->second; - i->second = this_op->next_; - this_op->next_ = complete_operations_; - complete_operations_ = this_op; - bool done = this_op->perform(result); - if (done) - { - // Operation has finished. - if (i->second) - { - return true; - } - else - { - operations_.erase(i); - return false; - } - } - else - { - // Operation wants to be called again. Leave it at the front of the - // queue for this descriptor, and remove from the completed list. - complete_operations_ = this_op->next_; - this_op->next_ = i->second; - i->second = this_op; - return true; - } - } - return false; - } - - // Perform all operations corresponding to the descriptor. - void perform_all_operations(Descriptor descriptor, - const asio::error_code& result) - { - typename operation_map::iterator i = operations_.find(descriptor); - if (i != operations_.end()) - { - while (i->second) - { - op_base* this_op = i->second; - i->second = this_op->next_; - this_op->next_ = complete_operations_; - complete_operations_ = this_op; - bool done = this_op->perform(result); - if (!done) - { - // Operation has not finished yet, so leave at front of queue, and - // remove from the completed list. - complete_operations_ = this_op->next_; - this_op->next_ = i->second; - i->second = this_op; - return; - } - } - operations_.erase(i); - } - } - - // Fill a descriptor set with the descriptors corresponding to each active - // operation. - template - void get_descriptors(Descriptor_Set& descriptors) - { - typename operation_map::iterator i = operations_.begin(); - while (i != operations_.end()) - { - Descriptor descriptor = i->first; - ++i; - if (!descriptors.set(descriptor)) - { - asio::error_code ec(error::fd_set_failure); - perform_all_operations(descriptor, ec); - } - } - } - - // Perform the operations corresponding to the ready file descriptors - // contained in the given descriptor set. - template - void perform_operations_for_descriptors(const Descriptor_Set& descriptors, - const asio::error_code& result) - { - typename operation_map::iterator i = operations_.begin(); - while (i != operations_.end()) - { - typename operation_map::iterator op_iter = i++; - if (descriptors.is_set(op_iter->first)) - { - op_base* this_op = op_iter->second; - op_iter->second = this_op->next_; - this_op->next_ = complete_operations_; - complete_operations_ = this_op; - bool done = this_op->perform(result); - if (done) - { - if (!op_iter->second) - operations_.erase(op_iter); - } - else - { - // Operation has not finished yet, so leave at front of queue, and - // remove from the completed list. - complete_operations_ = this_op->next_; - this_op->next_ = op_iter->second; - op_iter->second = this_op; - } - } - } - } - - // Perform any pending cancels for operations. - void perform_cancellations() - { - while (cancelled_operations_) - { - op_base* this_op = cancelled_operations_; - cancelled_operations_ = this_op->next_; - this_op->next_ = complete_operations_; - complete_operations_ = this_op; - this_op->perform(asio::error::operation_aborted); - } - } - - // Complete all operations that are waiting to be completed. - void complete_operations() - { - while (complete_operations_) - { - op_base* next_op = complete_operations_->next_; - complete_operations_->next_ = 0; - complete_operations_->complete(); - complete_operations_ = next_op; - } - } - - // Destroy all operations owned by the queue. - void destroy_operations() - { - while (cancelled_operations_) - { - op_base* next_op = cancelled_operations_->next_; - cancelled_operations_->next_ = 0; - cancelled_operations_->destroy(); - cancelled_operations_ = next_op; - } - - while (complete_operations_) - { - op_base* next_op = complete_operations_->next_; - complete_operations_->next_ = 0; - complete_operations_->destroy(); - complete_operations_ = next_op; - } - - typename operation_map::iterator i = operations_.begin(); - while (i != operations_.end()) - { - typename operation_map::iterator op_iter = i++; - op_base* curr_op = op_iter->second; - operations_.erase(op_iter); - while (curr_op) - { - op_base* next_op = curr_op->next_; - curr_op->next_ = 0; - curr_op->destroy(); - curr_op = next_op; - } - } - } - -private: - // Base class for reactor operations. A function pointer is used instead of - // virtual functions to avoid the associated overhead. - class op_base - { - public: - // Get the descriptor associated with the operation. - Descriptor descriptor() const - { - return descriptor_; - } - - // Perform the operation. - bool perform(const asio::error_code& result) - { - result_ = result; - return perform_func_(this, result_, bytes_transferred_); - } - - // Destroy the operation and post the handler. - void complete() - { - complete_func_(this, result_, bytes_transferred_); - } - - // Destroy the operation. - void destroy() - { - destroy_func_(this); - } - - protected: - typedef bool (*perform_func_type)(op_base*, - asio::error_code&, std::size_t&); - typedef void (*complete_func_type)(op_base*, - const asio::error_code&, std::size_t); - typedef void (*destroy_func_type)(op_base*); - - // Construct an operation for the given descriptor. - op_base(perform_func_type perform_func, complete_func_type complete_func, - destroy_func_type destroy_func, Descriptor descriptor) - : perform_func_(perform_func), - complete_func_(complete_func), - destroy_func_(destroy_func), - descriptor_(descriptor), - result_(), - bytes_transferred_(0), - next_(0) - { - } - - // Prevent deletion through this type. - ~op_base() - { - } - - private: - friend class reactor_op_queue; - - // The function to be called to perform the operation. - perform_func_type perform_func_; - - // The function to be called to delete the operation and post the handler. - complete_func_type complete_func_; - - // The function to be called to delete the operation. - destroy_func_type destroy_func_; - - // The descriptor associated with the operation. - Descriptor descriptor_; - - // The result of the operation. - asio::error_code result_; - - // The number of bytes transferred in the operation. - std::size_t bytes_transferred_; - - // The next operation for the same file descriptor. - op_base* next_; - }; - - // Adaptor class template for operations. - template - class op - : public op_base - { - public: - // Constructor. - op(Descriptor descriptor, Operation operation) - : op_base(&op::do_perform, &op::do_complete, - &op::do_destroy, descriptor), - operation_(operation) - { - } - - // Perform the operation. - static bool do_perform(op_base* base, - asio::error_code& result, std::size_t& bytes_transferred) - { - return static_cast*>(base)->operation_.perform( - result, bytes_transferred); - } - - // Destroy the operation and post the handler. - static void do_complete(op_base* base, - const asio::error_code& result, std::size_t bytes_transferred) - { - // Take ownership of the operation object. - typedef op this_type; - this_type* this_op(static_cast(base)); - typedef handler_alloc_traits alloc_traits; - handler_ptr ptr(this_op->operation_, this_op); - - // Make a copy of the error_code and the operation so that the memory can - // be deallocated before the upcall is made. - asio::error_code ec(result); - Operation operation(this_op->operation_); - - // Free the memory associated with the operation. - ptr.reset(); - - // Make the upcall. - operation.complete(ec, bytes_transferred); - } - - // Destroy the operation. - static void do_destroy(op_base* base) - { - // Take ownership of the operation object. - typedef op this_type; - this_type* this_op(static_cast(base)); - typedef handler_alloc_traits alloc_traits; - handler_ptr ptr(this_op->operation_, this_op); - - // A sub-object of the operation may be the true owner of the memory - // associated with the operation. Consequently, a local copy of the - // operation is required to ensure that any owning sub-object remains - // valid until after we have deallocated the memory here. - Operation operation(this_op->operation_); - (void)operation; - - // Free the memory associated with the operation. - ptr.reset(); - } - - private: - Operation operation_; - }; - - // The type for a map of operations. - typedef hash_map operation_map; - - // The operations that are currently executing asynchronously. - operation_map operations_; - - // The list of operations that have been cancelled. - op_base* cancelled_operations_; - - // The list of operations waiting to be completed. - op_base* complete_operations_; -}; - -} // namespace detail -} // namespace asio - -#include "asio/detail/pop_options.hpp" - -#endif // ASIO_DETAIL_REACTOR_OP_QUEUE_HPP diff --git a/libtorrent/include/asio/detail/resolver_service.hpp b/libtorrent/include/asio/detail/resolver_service.hpp deleted file mode 100644 index 172a8fc6d..000000000 --- a/libtorrent/include/asio/detail/resolver_service.hpp +++ /dev/null @@ -1,357 +0,0 @@ -// -// resolver_service.hpp -// ~~~~~~~~~~~~~~~~~~~~ -// -// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -#ifndef ASIO_DETAIL_RESOLVER_SERVICE_HPP -#define ASIO_DETAIL_RESOLVER_SERVICE_HPP - -#if defined(_MSC_VER) && (_MSC_VER >= 1200) -# pragma once -#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) - -#include "asio/detail/push_options.hpp" - -#include "asio/detail/push_options.hpp" -#include -#include -#include -#include -#include "asio/detail/pop_options.hpp" - -#include "asio/error.hpp" -#include "asio/io_service.hpp" -#include "asio/detail/bind_handler.hpp" -#include "asio/detail/mutex.hpp" -#include "asio/detail/noncopyable.hpp" -#include "asio/detail/service_base.hpp" -#include "asio/detail/socket_ops.hpp" -#include "asio/detail/socket_types.hpp" -#include "asio/detail/thread.hpp" - -namespace asio { -namespace detail { - -template -class resolver_service - : public asio::detail::service_base > -{ -private: - // Helper class to perform exception-safe cleanup of addrinfo objects. - class auto_addrinfo - : private asio::detail::noncopyable - { - public: - explicit auto_addrinfo(asio::detail::addrinfo_type* ai) - : ai_(ai) - { - } - - ~auto_addrinfo() - { - if (ai_) - socket_ops::freeaddrinfo(ai_); - } - - operator asio::detail::addrinfo_type*() - { - return ai_; - } - - private: - asio::detail::addrinfo_type* ai_; - }; - -public: - // The implementation type of the resolver. The shared pointer is used as a - // cancellation token to indicate to the background thread that the operation - // has been cancelled. - typedef boost::shared_ptr implementation_type; - struct noop_deleter { void operator()(void*) {} }; - - // The endpoint type. - typedef typename Protocol::endpoint endpoint_type; - - // The query type. - typedef typename Protocol::resolver_query query_type; - - // The iterator type. - typedef typename Protocol::resolver_iterator iterator_type; - - // Constructor. - resolver_service(asio::io_service& io_service) - : asio::detail::service_base< - resolver_service >(io_service), - mutex_(), - work_io_service_(new asio::io_service), - work_(new asio::io_service::work(*work_io_service_)), - work_thread_(0) - { - } - - // Destructor. - ~resolver_service() - { - shutdown_service(); - } - - // Destroy all user-defined handler objects owned by the service. - void shutdown_service() - { - work_.reset(); - if (work_io_service_) - { - work_io_service_->stop(); - if (work_thread_) - { - work_thread_->join(); - work_thread_.reset(); - } - work_io_service_.reset(); - } - } - - // Construct a new resolver implementation. - void construct(implementation_type& impl) - { - impl.reset(static_cast(0), noop_deleter()); - } - - // Destroy a resolver implementation. - void destroy(implementation_type&) - { - } - - // Cancel pending asynchronous operations. - void cancel(implementation_type& impl) - { - impl.reset(static_cast(0), noop_deleter()); - } - - // Resolve a query to a list of entries. - iterator_type resolve(implementation_type&, const query_type& query, - asio::error_code& ec) - { - asio::detail::addrinfo_type* address_info = 0; - std::string host_name = query.host_name(); - std::string service_name = query.service_name(); - asio::detail::addrinfo_type hints = query.hints(); - - socket_ops::getaddrinfo(host_name.length() ? host_name.c_str() : 0, - service_name.c_str(), &hints, &address_info, ec); - auto_addrinfo auto_address_info(address_info); - - if (ec) - return iterator_type(); - - return iterator_type::create(address_info, host_name, service_name); - } - - template - class resolve_query_handler - { - public: - resolve_query_handler(implementation_type impl, const query_type& query, - asio::io_service& io_service, Handler handler) - : impl_(impl), - query_(query), - io_service_(io_service), - work_(io_service), - handler_(handler) - { - } - - void operator()() - { - // Check if the operation has been cancelled. - if (impl_.expired()) - { - iterator_type iterator; - io_service_.post(asio::detail::bind_handler(handler_, - asio::error::operation_aborted, iterator)); - return; - } - - // Perform the blocking host resolution operation. - asio::detail::addrinfo_type* address_info = 0; - std::string host_name = query_.host_name(); - std::string service_name = query_.service_name(); - asio::detail::addrinfo_type hints = query_.hints(); - asio::error_code ec; - socket_ops::getaddrinfo(host_name.length() ? host_name.c_str() : 0, - service_name.c_str(), &hints, &address_info, ec); - auto_addrinfo auto_address_info(address_info); - - // Invoke the handler and pass the result. - iterator_type iterator; - if (!ec) - iterator = iterator_type::create(address_info, host_name, service_name); - io_service_.post(asio::detail::bind_handler( - handler_, ec, iterator)); - } - - private: - boost::weak_ptr impl_; - query_type query_; - asio::io_service& io_service_; - asio::io_service::work work_; - Handler handler_; - }; - - // Asynchronously resolve a query to a list of entries. - template - void async_resolve(implementation_type& impl, const query_type& query, - Handler handler) - { - if (work_io_service_) - { - start_work_thread(); - work_io_service_->post( - resolve_query_handler( - impl, query, this->get_io_service(), handler)); - } - } - - // Resolve an endpoint to a list of entries. - iterator_type resolve(implementation_type&, - const endpoint_type& endpoint, asio::error_code& ec) - { - // First try resolving with the service name. If that fails try resolving - // but allow the service to be returned as a number. - char host_name[NI_MAXHOST]; - char service_name[NI_MAXSERV]; - int flags = endpoint.protocol().type() == SOCK_DGRAM ? NI_DGRAM : 0; - socket_ops::getnameinfo(endpoint.data(), endpoint.size(), - host_name, NI_MAXHOST, service_name, NI_MAXSERV, flags, ec); - if (ec) - { - flags |= NI_NUMERICSERV; - socket_ops::getnameinfo(endpoint.data(), endpoint.size(), - host_name, NI_MAXHOST, service_name, NI_MAXSERV, flags, ec); - } - - if (ec) - return iterator_type(); - - return iterator_type::create(endpoint, host_name, service_name); - } - - template - class resolve_endpoint_handler - { - public: - resolve_endpoint_handler(implementation_type impl, - const endpoint_type& endpoint, asio::io_service& io_service, - Handler handler) - : impl_(impl), - endpoint_(endpoint), - io_service_(io_service), - work_(io_service), - handler_(handler) - { - } - - void operator()() - { - // Check if the operation has been cancelled. - if (impl_.expired()) - { - iterator_type iterator; - io_service_.post(asio::detail::bind_handler(handler_, - asio::error::operation_aborted, iterator)); - return; - } - - - // First try resolving with the service name. If that fails try resolving - // but allow the service to be returned as a number. - char host_name[NI_MAXHOST]; - char service_name[NI_MAXSERV]; - int flags = endpoint_.protocol().type() == SOCK_DGRAM ? NI_DGRAM : 0; - asio::error_code ec; - socket_ops::getnameinfo(endpoint_.data(), endpoint_.size(), - host_name, NI_MAXHOST, service_name, NI_MAXSERV, flags, ec); - if (ec) - { - flags |= NI_NUMERICSERV; - socket_ops::getnameinfo(endpoint_.data(), endpoint_.size(), - host_name, NI_MAXHOST, service_name, NI_MAXSERV, flags, ec); - } - - // Invoke the handler and pass the result. - iterator_type iterator; - if (!ec) - iterator = iterator_type::create(endpoint_, host_name, service_name); - io_service_.post(asio::detail::bind_handler( - handler_, ec, iterator)); - } - - private: - boost::weak_ptr impl_; - endpoint_type endpoint_; - asio::io_service& io_service_; - asio::io_service::work work_; - Handler handler_; - }; - - // Asynchronously resolve an endpoint to a list of entries. - template - void async_resolve(implementation_type& impl, const endpoint_type& endpoint, - Handler handler) - { - if (work_io_service_) - { - start_work_thread(); - work_io_service_->post( - resolve_endpoint_handler( - impl, endpoint, this->get_io_service(), handler)); - } - } - -private: - // Helper class to run the work io_service in a thread. - class work_io_service_runner - { - public: - work_io_service_runner(asio::io_service& io_service) - : io_service_(io_service) {} - void operator()() { io_service_.run(); } - private: - asio::io_service& io_service_; - }; - - // Start the work thread if it's not already running. - void start_work_thread() - { - asio::detail::mutex::scoped_lock lock(mutex_); - if (work_thread_ == 0) - { - work_thread_.reset(new asio::detail::thread( - work_io_service_runner(*work_io_service_))); - } - } - - // Mutex to protect access to internal data. - asio::detail::mutex mutex_; - - // Private io_service used for performing asynchronous host resolution. - boost::scoped_ptr work_io_service_; - - // Work for the private io_service to perform. - boost::scoped_ptr work_; - - // Thread used for running the work io_service's run loop. - boost::scoped_ptr work_thread_; -}; - -} // namespace detail -} // namespace asio - -#include "asio/detail/pop_options.hpp" - -#endif // ASIO_DETAIL_RESOLVER_SERVICE_HPP diff --git a/libtorrent/include/asio/detail/scoped_lock.hpp b/libtorrent/include/asio/detail/scoped_lock.hpp deleted file mode 100644 index 70b672985..000000000 --- a/libtorrent/include/asio/detail/scoped_lock.hpp +++ /dev/null @@ -1,91 +0,0 @@ -// -// scoped_lock.hpp -// ~~~~~~~~~~~~~~~ -// -// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -#ifndef ASIO_DETAIL_SCOPED_LOCK_HPP -#define ASIO_DETAIL_SCOPED_LOCK_HPP - -#if defined(_MSC_VER) && (_MSC_VER >= 1200) -# pragma once -#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) - -#include "asio/detail/push_options.hpp" - -#include "asio/detail/noncopyable.hpp" - -namespace asio { -namespace detail { - -// Helper class to lock and unlock a mutex automatically. -template -class scoped_lock - : private noncopyable -{ -public: - // Constructor acquires the lock. - scoped_lock(Mutex& m) - : mutex_(m) - { - mutex_.lock(); - locked_ = true; - } - - // Destructor releases the lock. - ~scoped_lock() - { - if (locked_) - mutex_.unlock(); - } - - // Explicitly acquire the lock. - void lock() - { - if (!locked_) - { - mutex_.lock(); - locked_ = true; - } - } - - // Explicitly release the lock. - void unlock() - { - if (locked_) - { - mutex_.unlock(); - locked_ = false; - } - } - - // Test whether the lock is held. - bool locked() const - { - return locked_; - } - - // Get the underlying mutex. - Mutex& mutex() - { - return mutex_; - } - -private: - // The underlying mutex. - Mutex& mutex_; - - // Whether the mutex is currently locked or unlocked. - bool locked_; -}; - -} // namespace detail -} // namespace asio - -#include "asio/detail/pop_options.hpp" - -#endif // ASIO_DETAIL_SCOPED_LOCK_HPP diff --git a/libtorrent/include/asio/detail/select_interrupter.hpp b/libtorrent/include/asio/detail/select_interrupter.hpp deleted file mode 100644 index 4277e4758..000000000 --- a/libtorrent/include/asio/detail/select_interrupter.hpp +++ /dev/null @@ -1,41 +0,0 @@ -// -// select_interrupter.hpp -// ~~~~~~~~~~~~~~~~~~~~~~ -// -// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -#ifndef ASIO_DETAIL_SELECT_INTERRUPTER_HPP -#define ASIO_DETAIL_SELECT_INTERRUPTER_HPP - -#if defined(_MSC_VER) && (_MSC_VER >= 1200) -# pragma once -#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) - -#include "asio/detail/push_options.hpp" - -#include "asio/detail/push_options.hpp" -#include -#include "asio/detail/pop_options.hpp" - -#include "asio/detail/pipe_select_interrupter.hpp" -#include "asio/detail/socket_select_interrupter.hpp" - -namespace asio { -namespace detail { - -#if defined(BOOST_WINDOWS) || defined(__CYGWIN__) -typedef socket_select_interrupter select_interrupter; -#else -typedef pipe_select_interrupter select_interrupter; -#endif - -} // namespace detail -} // namespace asio - -#include "asio/detail/pop_options.hpp" - -#endif // ASIO_DETAIL_SELECT_INTERRUPTER_HPP diff --git a/libtorrent/include/asio/detail/select_reactor.hpp b/libtorrent/include/asio/detail/select_reactor.hpp deleted file mode 100644 index 78a364ee0..000000000 --- a/libtorrent/include/asio/detail/select_reactor.hpp +++ /dev/null @@ -1,534 +0,0 @@ -// -// select_reactor.hpp -// ~~~~~~~~~~~~~~~~~~ -// -// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -#ifndef ASIO_DETAIL_SELECT_REACTOR_HPP -#define ASIO_DETAIL_SELECT_REACTOR_HPP - -#if defined(_MSC_VER) && (_MSC_VER >= 1200) -# pragma once -#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) - -#include "asio/detail/push_options.hpp" - -#include "asio/detail/socket_types.hpp" // Must come before posix_time. - -#include "asio/detail/push_options.hpp" -#include -#include -#include -#include -#include -#include "asio/detail/pop_options.hpp" - -#include "asio/io_service.hpp" -#include "asio/detail/bind_handler.hpp" -#include "asio/detail/fd_set_adapter.hpp" -#include "asio/detail/mutex.hpp" -#include "asio/detail/noncopyable.hpp" -#include "asio/detail/reactor_op_queue.hpp" -#include "asio/detail/select_interrupter.hpp" -#include "asio/detail/select_reactor_fwd.hpp" -#include "asio/detail/service_base.hpp" -#include "asio/detail/signal_blocker.hpp" -#include "asio/detail/socket_ops.hpp" -#include "asio/detail/socket_types.hpp" -#include "asio/detail/task_io_service.hpp" -#include "asio/detail/thread.hpp" -#include "asio/detail/timer_queue.hpp" - -namespace asio { -namespace detail { - -template -class select_reactor - : public asio::detail::service_base > -{ -public: - // Per-descriptor data. - struct per_descriptor_data - { - }; - - // Constructor. - select_reactor(asio::io_service& io_service) - : asio::detail::service_base< - select_reactor >(io_service), - mutex_(), - select_in_progress_(false), - interrupter_(), - read_op_queue_(), - write_op_queue_(), - except_op_queue_(), - pending_cancellations_(), - stop_thread_(false), - thread_(0), - shutdown_(false) - { - if (Own_Thread) - { - asio::detail::signal_blocker sb; - thread_ = new asio::detail::thread( - bind_handler(&select_reactor::call_run_thread, this)); - } - } - - // Destructor. - ~select_reactor() - { - shutdown_service(); - } - - // Destroy all user-defined handler objects owned by the service. - void shutdown_service() - { - asio::detail::mutex::scoped_lock lock(mutex_); - shutdown_ = true; - stop_thread_ = true; - lock.unlock(); - - if (thread_) - { - interrupter_.interrupt(); - thread_->join(); - delete thread_; - thread_ = 0; - } - - read_op_queue_.destroy_operations(); - write_op_queue_.destroy_operations(); - except_op_queue_.destroy_operations(); - - for (std::size_t i = 0; i < timer_queues_.size(); ++i) - timer_queues_[i]->destroy_timers(); - timer_queues_.clear(); - } - - // Register a socket with the reactor. Returns 0 on success, system error - // code on failure. - int register_descriptor(socket_type, per_descriptor_data&) - { - return 0; - } - - // Start a new read operation. The handler object will be invoked when the - // given descriptor is ready to be read, or an error has occurred. - template - void start_read_op(socket_type descriptor, per_descriptor_data&, - Handler handler, bool /*allow_speculative_read*/ = true) - { - asio::detail::mutex::scoped_lock lock(mutex_); - if (!shutdown_) - if (read_op_queue_.enqueue_operation(descriptor, handler)) - interrupter_.interrupt(); - } - - // Start a new write operation. The handler object will be invoked when the - // given descriptor is ready to be written, or an error has occurred. - template - void start_write_op(socket_type descriptor, per_descriptor_data&, - Handler handler, bool /*allow_speculative_write*/ = true) - { - asio::detail::mutex::scoped_lock lock(mutex_); - if (!shutdown_) - if (write_op_queue_.enqueue_operation(descriptor, handler)) - interrupter_.interrupt(); - } - - // Start a new exception operation. The handler object will be invoked when - // the given descriptor has exception information, or an error has occurred. - template - void start_except_op(socket_type descriptor, - per_descriptor_data&, Handler handler) - { - asio::detail::mutex::scoped_lock lock(mutex_); - if (!shutdown_) - if (except_op_queue_.enqueue_operation(descriptor, handler)) - interrupter_.interrupt(); - } - - // Wrapper for connect handlers to enable the handler object to be placed - // in both the write and the except operation queues, but ensure that only - // one of the handlers is called. - template - class connect_handler_wrapper - { - public: - connect_handler_wrapper(socket_type descriptor, - boost::shared_ptr completed, - select_reactor& reactor, Handler handler) - : descriptor_(descriptor), - completed_(completed), - reactor_(reactor), - handler_(handler) - { - } - - bool perform(asio::error_code& ec, - std::size_t& bytes_transferred) - { - // Check whether one of the handlers has already been called. If it has, - // then we don't want to do anything in this handler. - if (*completed_) - { - completed_.reset(); // Indicate that this handler should not complete. - return true; - } - - // Cancel the other reactor operation for the connection. - *completed_ = true; - reactor_.enqueue_cancel_ops_unlocked(descriptor_); - - // Call the contained handler. - return handler_.perform(ec, bytes_transferred); - } - - void complete(const asio::error_code& ec, - std::size_t bytes_transferred) - { - if (completed_.get()) - handler_.complete(ec, bytes_transferred); - } - - private: - socket_type descriptor_; - boost::shared_ptr completed_; - select_reactor& reactor_; - Handler handler_; - }; - - // Start new write and exception operations. The handler object will be - // invoked when the given descriptor is ready for writing or has exception - // information available, or an error has occurred. The handler will be called - // only once. - template - void start_connect_op(socket_type descriptor, - per_descriptor_data&, Handler handler) - { - asio::detail::mutex::scoped_lock lock(mutex_); - if (!shutdown_) - { - boost::shared_ptr completed(new bool(false)); - connect_handler_wrapper wrapped_handler( - descriptor, completed, *this, handler); - bool interrupt = write_op_queue_.enqueue_operation( - descriptor, wrapped_handler); - interrupt = except_op_queue_.enqueue_operation( - descriptor, wrapped_handler) || interrupt; - if (interrupt) - interrupter_.interrupt(); - } - } - - // Cancel all operations associated with the given descriptor. The - // handlers associated with the descriptor will be invoked with the - // operation_aborted error. - void cancel_ops(socket_type descriptor, per_descriptor_data&) - { - asio::detail::mutex::scoped_lock lock(mutex_); - cancel_ops_unlocked(descriptor); - } - - // Enqueue cancellation of all operations associated with the given - // descriptor. The handlers associated with the descriptor will be invoked - // with the operation_aborted error. This function does not acquire the - // select_reactor's mutex, and so should only be used when the reactor lock is - // already held. - void enqueue_cancel_ops_unlocked(socket_type descriptor) - { - pending_cancellations_.push_back(descriptor); - } - - // Cancel any operations that are running against the descriptor and remove - // its registration from the reactor. - void close_descriptor(socket_type descriptor, per_descriptor_data&) - { - asio::detail::mutex::scoped_lock lock(mutex_); - cancel_ops_unlocked(descriptor); - } - - // Add a new timer queue to the reactor. - template - void add_timer_queue(timer_queue& timer_queue) - { - asio::detail::mutex::scoped_lock lock(mutex_); - timer_queues_.push_back(&timer_queue); - } - - // Remove a timer queue from the reactor. - template - void remove_timer_queue(timer_queue& timer_queue) - { - asio::detail::mutex::scoped_lock lock(mutex_); - for (std::size_t i = 0; i < timer_queues_.size(); ++i) - { - if (timer_queues_[i] == &timer_queue) - { - timer_queues_.erase(timer_queues_.begin() + i); - return; - } - } - } - - // Schedule a timer in the given timer queue to expire at the specified - // absolute time. The handler object will be invoked when the timer expires. - template - void schedule_timer(timer_queue& timer_queue, - const typename Time_Traits::time_type& time, Handler handler, void* token) - { - asio::detail::mutex::scoped_lock lock(mutex_); - if (!shutdown_) - if (timer_queue.enqueue_timer(time, handler, token)) - interrupter_.interrupt(); - } - - // Cancel the timer associated with the given token. Returns the number of - // handlers that have been posted or dispatched. - template - std::size_t cancel_timer(timer_queue& timer_queue, void* token) - { - asio::detail::mutex::scoped_lock lock(mutex_); - std::size_t n = timer_queue.cancel_timer(token); - if (n > 0) - interrupter_.interrupt(); - return n; - } - -private: - friend class task_io_service >; - - // Run select once until interrupted or events are ready to be dispatched. - void run(bool block) - { - asio::detail::mutex::scoped_lock lock(mutex_); - - // Dispatch any operation cancellations that were made while the select - // loop was not running. - read_op_queue_.perform_cancellations(); - write_op_queue_.perform_cancellations(); - except_op_queue_.perform_cancellations(); - for (std::size_t i = 0; i < timer_queues_.size(); ++i) - timer_queues_[i]->dispatch_cancellations(); - - // Check if the thread is supposed to stop. - if (stop_thread_) - { - complete_operations_and_timers(lock); - return; - } - - // We can return immediately if there's no work to do and the reactor is - // not supposed to block. - if (!block && read_op_queue_.empty() && write_op_queue_.empty() - && except_op_queue_.empty() && all_timer_queues_are_empty()) - { - complete_operations_and_timers(lock); - return; - } - - // Set up the descriptor sets. - fd_set_adapter read_fds; - read_fds.set(interrupter_.read_descriptor()); - read_op_queue_.get_descriptors(read_fds); - fd_set_adapter write_fds; - write_op_queue_.get_descriptors(write_fds); - fd_set_adapter except_fds; - except_op_queue_.get_descriptors(except_fds); - socket_type max_fd = read_fds.max_descriptor(); - if (write_fds.max_descriptor() > max_fd) - max_fd = write_fds.max_descriptor(); - if (except_fds.max_descriptor() > max_fd) - max_fd = except_fds.max_descriptor(); - - // Block on the select call without holding the lock so that new - // operations can be started while the call is executing. - timeval tv_buf = { 0, 0 }; - timeval* tv = block ? get_timeout(tv_buf) : &tv_buf; - select_in_progress_ = true; - lock.unlock(); - asio::error_code ec; - int retval = socket_ops::select(static_cast(max_fd + 1), - read_fds, write_fds, except_fds, tv, ec); - lock.lock(); - select_in_progress_ = false; - - // Block signals while dispatching operations. - asio::detail::signal_blocker sb; - - // Reset the interrupter. - if (retval > 0 && read_fds.is_set(interrupter_.read_descriptor())) - interrupter_.reset(); - - // Dispatch all ready operations. - if (retval > 0) - { - // Exception operations must be processed first to ensure that any - // out-of-band data is read before normal data. - except_op_queue_.perform_operations_for_descriptors( - except_fds, asio::error_code()); - read_op_queue_.perform_operations_for_descriptors( - read_fds, asio::error_code()); - write_op_queue_.perform_operations_for_descriptors( - write_fds, asio::error_code()); - except_op_queue_.perform_cancellations(); - read_op_queue_.perform_cancellations(); - write_op_queue_.perform_cancellations(); - } - for (std::size_t i = 0; i < timer_queues_.size(); ++i) - { - timer_queues_[i]->dispatch_timers(); - timer_queues_[i]->dispatch_cancellations(); - } - - // Issue any pending cancellations. - for (size_t i = 0; i < pending_cancellations_.size(); ++i) - cancel_ops_unlocked(pending_cancellations_[i]); - pending_cancellations_.clear(); - - complete_operations_and_timers(lock); - } - - // Run the select loop in the thread. - void run_thread() - { - asio::detail::mutex::scoped_lock lock(mutex_); - while (!stop_thread_) - { - lock.unlock(); - run(true); - lock.lock(); - } - } - - // Entry point for the select loop thread. - static void call_run_thread(select_reactor* reactor) - { - reactor->run_thread(); - } - - // Interrupt the select loop. - void interrupt() - { - interrupter_.interrupt(); - } - - // Check if all timer queues are empty. - bool all_timer_queues_are_empty() const - { - for (std::size_t i = 0; i < timer_queues_.size(); ++i) - if (!timer_queues_[i]->empty()) - return false; - return true; - } - - // Get the timeout value for the select call. - timeval* get_timeout(timeval& tv) - { - if (all_timer_queues_are_empty()) - return 0; - - // By default we will wait no longer than 5 minutes. This will ensure that - // any changes to the system clock are detected after no longer than this. - boost::posix_time::time_duration minimum_wait_duration - = boost::posix_time::minutes(5); - - for (std::size_t i = 0; i < timer_queues_.size(); ++i) - { - boost::posix_time::time_duration wait_duration - = timer_queues_[i]->wait_duration(); - if (wait_duration < minimum_wait_duration) - minimum_wait_duration = wait_duration; - } - - if (minimum_wait_duration > boost::posix_time::time_duration()) - { - tv.tv_sec = minimum_wait_duration.total_seconds(); - tv.tv_usec = minimum_wait_duration.total_microseconds() % 1000000; - } - else - { - tv.tv_sec = 0; - tv.tv_usec = 0; - } - - return &tv; - } - - // Cancel all operations associated with the given descriptor. The do_cancel - // function of the handler objects will be invoked. This function does not - // acquire the select_reactor's mutex. - void cancel_ops_unlocked(socket_type descriptor) - { - bool interrupt = read_op_queue_.cancel_operations(descriptor); - interrupt = write_op_queue_.cancel_operations(descriptor) || interrupt; - interrupt = except_op_queue_.cancel_operations(descriptor) || interrupt; - if (interrupt) - interrupter_.interrupt(); - } - - // Clean up operations and timers. We must not hold the lock since the - // destructors may make calls back into this reactor. We make a copy of the - // vector of timer queues since the original may be modified while the lock - // is not held. - void complete_operations_and_timers( - asio::detail::mutex::scoped_lock& lock) - { - timer_queues_for_cleanup_ = timer_queues_; - lock.unlock(); - read_op_queue_.complete_operations(); - write_op_queue_.complete_operations(); - except_op_queue_.complete_operations(); - for (std::size_t i = 0; i < timer_queues_for_cleanup_.size(); ++i) - timer_queues_for_cleanup_[i]->complete_timers(); - } - - // Mutex to protect access to internal data. - asio::detail::mutex mutex_; - - // Whether the select loop is currently running or not. - bool select_in_progress_; - - // The interrupter is used to break a blocking select call. - select_interrupter interrupter_; - - // The queue of read operations. - reactor_op_queue read_op_queue_; - - // The queue of write operations. - reactor_op_queue write_op_queue_; - - // The queue of exception operations. - reactor_op_queue except_op_queue_; - - // The timer queues. - std::vector timer_queues_; - - // A copy of the timer queues, used when cleaning up timers. The copy is - // stored as a class data member to avoid unnecessary memory allocation. - std::vector timer_queues_for_cleanup_; - - // The descriptors that are pending cancellation. - std::vector pending_cancellations_; - - // Does the reactor loop thread need to stop. - bool stop_thread_; - - // The thread that is running the reactor loop. - asio::detail::thread* thread_; - - // Whether the service has been shut down. - bool shutdown_; -}; - -} // namespace detail -} // namespace asio - -#include "asio/detail/pop_options.hpp" - -#endif // ASIO_DETAIL_SELECT_REACTOR_HPP diff --git a/libtorrent/include/asio/detail/select_reactor_fwd.hpp b/libtorrent/include/asio/detail/select_reactor_fwd.hpp deleted file mode 100644 index d43bc8aaf..000000000 --- a/libtorrent/include/asio/detail/select_reactor_fwd.hpp +++ /dev/null @@ -1,31 +0,0 @@ -// -// select_reactor_fwd.hpp -// ~~~~~~~~~~~~~~~~~~~~~~ -// -// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -#ifndef ASIO_DETAIL_SELECT_REACTOR_FWD_HPP -#define ASIO_DETAIL_SELECT_REACTOR_FWD_HPP - -#if defined(_MSC_VER) && (_MSC_VER >= 1200) -# pragma once -#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) - -#include "asio/detail/push_options.hpp" - -namespace asio { -namespace detail { - -template -class select_reactor; - -} // namespace detail -} // namespace asio - -#include "asio/detail/pop_options.hpp" - -#endif // ASIO_DETAIL_SELECT_REACTOR_FWD_HPP diff --git a/libtorrent/include/asio/detail/service_base.hpp b/libtorrent/include/asio/detail/service_base.hpp deleted file mode 100644 index 906a3546c..000000000 --- a/libtorrent/include/asio/detail/service_base.hpp +++ /dev/null @@ -1,49 +0,0 @@ -// -// service_base.hpp -// ~~~~~~~~~~~~~~~~ -// -// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -#ifndef ASIO_DETAIL_SERVICE_BASE_HPP -#define ASIO_DETAIL_SERVICE_BASE_HPP - -#if defined(_MSC_VER) && (_MSC_VER >= 1200) -# pragma once -#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) - -#include "asio/detail/push_options.hpp" - -#include "asio/io_service.hpp" -#include "asio/detail/service_id.hpp" - -namespace asio { -namespace detail { - -// Special service base class to keep classes header-file only. -template -class service_base - : public asio::io_service::service -{ -public: - static asio::detail::service_id id; - - // Constructor. - service_base(asio::io_service& io_service) - : asio::io_service::service(io_service) - { - } -}; - -template -asio::detail::service_id service_base::id; - -} // namespace detail -} // namespace asio - -#include "asio/detail/pop_options.hpp" - -#endif // ASIO_DETAIL_SERVICE_BASE_HPP diff --git a/libtorrent/include/asio/detail/service_id.hpp b/libtorrent/include/asio/detail/service_id.hpp deleted file mode 100644 index e60406441..000000000 --- a/libtorrent/include/asio/detail/service_id.hpp +++ /dev/null @@ -1,37 +0,0 @@ -// -// service_id.hpp -// ~~~~~~~~~~~~~~ -// -// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -#ifndef ASIO_DETAIL_SERVICE_ID_HPP -#define ASIO_DETAIL_SERVICE_ID_HPP - -#if defined(_MSC_VER) && (_MSC_VER >= 1200) -# pragma once -#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) - -#include "asio/detail/push_options.hpp" - -#include "asio/io_service.hpp" - -namespace asio { -namespace detail { - -// Special derived service id type to keep classes header-file only. -template -class service_id - : public asio::io_service::id -{ -}; - -} // namespace detail -} // namespace asio - -#include "asio/detail/pop_options.hpp" - -#endif // ASIO_DETAIL_SERVICE_ID_HPP diff --git a/libtorrent/include/asio/detail/service_registry.hpp b/libtorrent/include/asio/detail/service_registry.hpp deleted file mode 100644 index f517cbbf1..000000000 --- a/libtorrent/include/asio/detail/service_registry.hpp +++ /dev/null @@ -1,210 +0,0 @@ -// -// service_registry.hpp -// ~~~~~~~~~~~~~~~~~~~~ -// -// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -#ifndef ASIO_DETAIL_SERVICE_REGISTRY_HPP -#define ASIO_DETAIL_SERVICE_REGISTRY_HPP - -#if defined(_MSC_VER) && (_MSC_VER >= 1200) -# pragma once -#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) - -#include "asio/detail/push_options.hpp" - -#include "asio/detail/push_options.hpp" -#include -#include -#include "asio/detail/pop_options.hpp" - -#include "asio/io_service.hpp" -#include "asio/detail/mutex.hpp" -#include "asio/detail/noncopyable.hpp" -#include "asio/detail/service_id.hpp" - -#if defined(BOOST_NO_TYPEID) -# if !defined(ASIO_NO_TYPEID) -# define ASIO_NO_TYPEID -# endif // !defined(ASIO_NO_TYPEID) -#endif // defined(BOOST_NO_TYPEID) - -namespace asio { -namespace detail { - -class service_registry - : private noncopyable -{ -public: - // Constructor. - service_registry(asio::io_service& o) - : owner_(o), - first_service_(0) - { - } - - // Destructor. - ~service_registry() - { - // Shutdown all services. This must be done in a separate loop before the - // services are destroyed since the destructors of user-defined handler - // objects may try to access other service objects. - asio::io_service::service* service = first_service_; - while (service) - { - service->shutdown_service(); - service = service->next_; - } - - // Destroy all services. - while (first_service_) - { - asio::io_service::service* next_service = first_service_->next_; - delete first_service_; - first_service_ = next_service; - } - } - - // Get the service object corresponding to the specified service type. Will - // create a new service object automatically if no such object already - // exists. Ownership of the service object is not transferred to the caller. - template - Service& use_service() - { - asio::detail::mutex::scoped_lock lock(mutex_); - - // First see if there is an existing service object for the given type. - asio::io_service::service* service = first_service_; - while (service) - { - if (service_id_matches(*service, Service::id)) - return *static_cast(service); - service = service->next_; - } - - // Create a new service object. The service registry's mutex is not locked - // at this time to allow for nested calls into this function from the new - // service's constructor. - lock.unlock(); - std::auto_ptr new_service(new Service(owner_)); - init_service_id(*new_service, Service::id); - Service& new_service_ref = *new_service; - lock.lock(); - - // Check that nobody else created another service object of the same type - // while the lock was released. - service = first_service_; - while (service) - { - if (service_id_matches(*service, Service::id)) - return *static_cast(service); - service = service->next_; - } - - // Service was successfully initialised, pass ownership to registry. - new_service->next_ = first_service_; - first_service_ = new_service.release(); - - return new_service_ref; - } - - // Add a service object. Returns false on error, in which case ownership of - // the object is retained by the caller. - template - bool add_service(Service* new_service) - { - asio::detail::mutex::scoped_lock lock(mutex_); - - // Check if there is an existing service object for the given type. - asio::io_service::service* service = first_service_; - while (service) - { - if (service_id_matches(*service, Service::id)) - return false; - service = service->next_; - } - - // Take ownership of the service object. - init_service_id(*new_service, Service::id); - new_service->next_ = first_service_; - first_service_ = new_service; - - return true; - } - - // Check whether a service object of the specified type already exists. - template - bool has_service() const - { - asio::detail::mutex::scoped_lock lock(mutex_); - - asio::io_service::service* service = first_service_; - while (service) - { - if (service_id_matches(*service, Service::id)) - return true; - service = service->next_; - } - - return false; - } - -private: - // Set a service's id. - void init_service_id(asio::io_service::service& service, - const asio::io_service::id& id) - { - service.type_info_ = 0; - service.id_ = &id; - } - -#if !defined(ASIO_NO_TYPEID) - // Set a service's id. - template - void init_service_id(asio::io_service::service& service, - const asio::detail::service_id& /*id*/) - { - service.type_info_ = &typeid(Service); - service.id_ = 0; - } -#endif // !defined(ASIO_NO_TYPEID) - - // Check if a service matches the given id. - static bool service_id_matches( - const asio::io_service::service& service, - const asio::io_service::id& id) - { - return service.id_ == &id; - } - -#if !defined(ASIO_NO_TYPEID) - // Check if a service matches the given id. - template - static bool service_id_matches( - const asio::io_service::service& service, - const asio::detail::service_id& /*id*/) - { - return service.type_info_ != 0 && *service.type_info_ == typeid(Service); - } -#endif // !defined(ASIO_NO_TYPEID) - - // Mutex to protect access to internal data. - mutable asio::detail::mutex mutex_; - - // The owner of this service registry and the services it contains. - asio::io_service& owner_; - - // The first service in the list of contained services. - asio::io_service::service* first_service_; -}; - -} // namespace detail -} // namespace asio - -#include "asio/detail/pop_options.hpp" - -#endif // ASIO_DETAIL_SERVICE_REGISTRY_HPP diff --git a/libtorrent/include/asio/detail/service_registry_fwd.hpp b/libtorrent/include/asio/detail/service_registry_fwd.hpp deleted file mode 100644 index 136c0e9a3..000000000 --- a/libtorrent/include/asio/detail/service_registry_fwd.hpp +++ /dev/null @@ -1,30 +0,0 @@ -// -// service_registry_fwd.hpp -// ~~~~~~~~~~~~~~~~~~~~~~~~ -// -// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -#ifndef ASIO_DETAIL_SERVICE_REGISTRY_FWD_HPP -#define ASIO_DETAIL_SERVICE_REGISTRY_FWD_HPP - -#if defined(_MSC_VER) && (_MSC_VER >= 1200) -# pragma once -#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) - -#include "asio/detail/push_options.hpp" - -namespace asio { -namespace detail { - -class service_registry; - -} // namespace detail -} // namespace asio - -#include "asio/detail/pop_options.hpp" - -#endif // ASIO_DETAIL_SERVICE_REGISTRY_FWD_HPP diff --git a/libtorrent/include/asio/detail/signal_blocker.hpp b/libtorrent/include/asio/detail/signal_blocker.hpp deleted file mode 100644 index e2148d763..000000000 --- a/libtorrent/include/asio/detail/signal_blocker.hpp +++ /dev/null @@ -1,50 +0,0 @@ -// -// signal_blocker.hpp -// ~~~~~~~~~~~~~~~~~~ -// -// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -#ifndef ASIO_DETAIL_SIGNAL_BLOCKER_HPP -#define ASIO_DETAIL_SIGNAL_BLOCKER_HPP - -#if defined(_MSC_VER) && (_MSC_VER >= 1200) -# pragma once -#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) - -#include "asio/detail/push_options.hpp" - -#include "asio/detail/push_options.hpp" -#include -#include "asio/detail/pop_options.hpp" - -#if !defined(BOOST_HAS_THREADS) -# include "asio/detail/null_signal_blocker.hpp" -#elif defined(BOOST_WINDOWS) || defined(__CYGWIN__) -# include "asio/detail/win_signal_blocker.hpp" -#elif defined(BOOST_HAS_PTHREADS) -# include "asio/detail/posix_signal_blocker.hpp" -#else -# error Only Windows and POSIX are supported! -#endif - -namespace asio { -namespace detail { - -#if !defined(BOOST_HAS_THREADS) -typedef null_signal_blocker signal_blocker; -#elif defined(BOOST_WINDOWS) || defined(__CYGWIN__) -typedef win_signal_blocker signal_blocker; -#elif defined(BOOST_HAS_PTHREADS) -typedef posix_signal_blocker signal_blocker; -#endif - -} // namespace detail -} // namespace asio - -#include "asio/detail/pop_options.hpp" - -#endif // ASIO_DETAIL_SIGNAL_BLOCKER_HPP diff --git a/libtorrent/include/asio/detail/signal_init.hpp b/libtorrent/include/asio/detail/signal_init.hpp deleted file mode 100644 index 620182b34..000000000 --- a/libtorrent/include/asio/detail/signal_init.hpp +++ /dev/null @@ -1,51 +0,0 @@ -// -// signal_init.hpp -// ~~~~~~~~~~~~~~~ -// -// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -#ifndef ASIO_DETAIL_SIGNAL_INIT_HPP -#define ASIO_DETAIL_SIGNAL_INIT_HPP - -#if defined(_MSC_VER) && (_MSC_VER >= 1200) -# pragma once -#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) - -#include "asio/detail/push_options.hpp" - -#include "asio/detail/push_options.hpp" -#include -#include "asio/detail/pop_options.hpp" - -#if !defined(BOOST_WINDOWS) && !defined(__CYGWIN__) - -#include "asio/detail/push_options.hpp" -#include -#include "asio/detail/pop_options.hpp" - -namespace asio { -namespace detail { - -template -class signal_init -{ -public: - // Constructor. - signal_init() - { - std::signal(Signal, SIG_IGN); - } -}; - -} // namespace detail -} // namespace asio - -#endif // !defined(BOOST_WINDOWS) && !defined(__CYGWIN__) - -#include "asio/detail/pop_options.hpp" - -#endif // ASIO_DETAIL_SIGNAL_INIT_HPP diff --git a/libtorrent/include/asio/detail/socket_holder.hpp b/libtorrent/include/asio/detail/socket_holder.hpp deleted file mode 100644 index c60d21eef..000000000 --- a/libtorrent/include/asio/detail/socket_holder.hpp +++ /dev/null @@ -1,95 +0,0 @@ -// -// socket_holder.hpp -// ~~~~~~~~~~~~~~~~~ -// -// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -#ifndef ASIO_DETAIL_SOCKET_HOLDER_HPP -#define ASIO_DETAIL_SOCKET_HOLDER_HPP - -#if defined(_MSC_VER) && (_MSC_VER >= 1200) -# pragma once -#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) - -#include "asio/detail/push_options.hpp" - -#include "asio/detail/noncopyable.hpp" -#include "asio/detail/socket_ops.hpp" - -namespace asio { -namespace detail { - -// Implement the resource acquisition is initialisation idiom for sockets. -class socket_holder - : private noncopyable -{ -public: - // Construct as an uninitialised socket. - socket_holder() - : socket_(invalid_socket) - { - } - - // Construct to take ownership of the specified socket. - explicit socket_holder(socket_type s) - : socket_(s) - { - } - - // Destructor. - ~socket_holder() - { - if (socket_ != invalid_socket) - { - asio::error_code ec; - socket_ops::close(socket_, ec); - } - } - - // Get the underlying socket. - socket_type get() const - { - return socket_; - } - - // Reset to an uninitialised socket. - void reset() - { - if (socket_ != invalid_socket) - { - asio::error_code ec; - socket_ops::close(socket_, ec); - socket_ = invalid_socket; - } - } - - // Reset to take ownership of the specified socket. - void reset(socket_type s) - { - reset(); - socket_ = s; - } - - // Release ownership of the socket. - socket_type release() - { - socket_type tmp = socket_; - socket_ = invalid_socket; - return tmp; - } - -private: - // The underlying socket. - socket_type socket_; -}; - -} // namespace detail -} // namespace asio - -#include "asio/detail/pop_options.hpp" - -#endif // ASIO_DETAIL_SOCKET_HOLDER_HPP diff --git a/libtorrent/include/asio/detail/socket_ops.hpp b/libtorrent/include/asio/detail/socket_ops.hpp deleted file mode 100644 index 231bc61c5..000000000 --- a/libtorrent/include/asio/detail/socket_ops.hpp +++ /dev/null @@ -1,1893 +0,0 @@ -// -// socket_ops.hpp -// ~~~~~~~~~~~~~~ -// -// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -#ifndef ASIO_DETAIL_SOCKET_OPS_HPP -#define ASIO_DETAIL_SOCKET_OPS_HPP - -#if defined(_MSC_VER) && (_MSC_VER >= 1200) -# pragma once -#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) - -#include "asio/detail/push_options.hpp" - -#include "asio/detail/push_options.hpp" -#include -#include -#include -#include -#include -#include -#include -#include -#include "asio/detail/pop_options.hpp" - -#include "asio/error.hpp" -#include "asio/detail/socket_types.hpp" - -namespace asio { -namespace detail { -namespace socket_ops { - -#if defined(BOOST_WINDOWS) || defined(__CYGWIN__) -struct msghdr { int msg_namelen; }; -#endif // defined(BOOST_WINDOWS) || defined(__CYGWIN__) - -#if defined(__hpux) -// HP-UX doesn't declare these functions extern "C", so they are declared again -// here to avoid linker errors about undefined symbols. -extern "C" char* if_indextoname(unsigned int, char*); -extern "C" unsigned int if_nametoindex(const char*); -#endif // defined(__hpux) - -inline void clear_error(asio::error_code& ec) -{ -#if defined(BOOST_WINDOWS) || defined(__CYGWIN__) - WSASetLastError(0); -#else - errno = 0; -#endif - ec = asio::error_code(); -} - -template -inline ReturnType error_wrapper(ReturnType return_value, - asio::error_code& ec) -{ -#if defined(BOOST_WINDOWS) || defined(__CYGWIN__) - ec = asio::error_code(WSAGetLastError(), - asio::error::get_system_category()); -#else - ec = asio::error_code(errno, - asio::error::get_system_category()); -#endif - return return_value; -} - -template -inline socket_type call_accept(SockLenType msghdr::*, - socket_type s, socket_addr_type* addr, std::size_t* addrlen) -{ - SockLenType tmp_addrlen = addrlen ? (SockLenType)*addrlen : 0; - socket_type result = ::accept(s, addr, addrlen ? &tmp_addrlen : 0); - if (addrlen) - *addrlen = (std::size_t)tmp_addrlen; - return result; -} - -inline socket_type accept(socket_type s, socket_addr_type* addr, - std::size_t* addrlen, asio::error_code& ec) -{ - clear_error(ec); - - socket_type new_s = error_wrapper(call_accept( - &msghdr::msg_namelen, s, addr, addrlen), ec); - if (new_s == invalid_socket) - return new_s; - -#if defined(__MACH__) && defined(__APPLE__) || defined(__FreeBSD__) - int optval = 1; - int result = error_wrapper(::setsockopt(new_s, - SOL_SOCKET, SO_NOSIGPIPE, &optval, sizeof(optval)), ec); - if (result != 0) - { - ::close(new_s); - return invalid_socket; - } -#endif - -#if defined(BOOST_WINDOWS) && defined(UNDER_CE) - clear_error(ec); -#endif - - return new_s; -} - -template -inline int call_bind(SockLenType msghdr::*, - socket_type s, const socket_addr_type* addr, std::size_t addrlen) -{ - return ::bind(s, addr, (SockLenType)addrlen); -} - -inline int bind(socket_type s, const socket_addr_type* addr, - std::size_t addrlen, asio::error_code& ec) -{ - clear_error(ec); - int result = error_wrapper(call_bind( - &msghdr::msg_namelen, s, addr, addrlen), ec); -#if defined(BOOST_WINDOWS) && defined(UNDER_CE) - if (result == 0) - clear_error(ec); -#endif - return result; -} - -inline int close(socket_type s, asio::error_code& ec) -{ - clear_error(ec); -#if defined(BOOST_WINDOWS) || defined(__CYGWIN__) - int result = error_wrapper(::closesocket(s), ec); -# if defined(UNDER_CE) - if (result == 0) - clear_error(ec); -# endif - return result; -#else // defined(BOOST_WINDOWS) || defined(__CYGWIN__) - return error_wrapper(::close(s), ec); -#endif // defined(BOOST_WINDOWS) || defined(__CYGWIN__) -} - -inline int shutdown(socket_type s, int what, asio::error_code& ec) -{ - clear_error(ec); - int result = error_wrapper(::shutdown(s, what), ec); -#if defined(BOOST_WINDOWS) && defined(UNDER_CE) - if (result == 0) - clear_error(ec); -#endif - return result; -} - -template -inline int call_connect(SockLenType msghdr::*, - socket_type s, const socket_addr_type* addr, std::size_t addrlen) -{ - return ::connect(s, addr, (SockLenType)addrlen); -} - -inline int connect(socket_type s, const socket_addr_type* addr, - std::size_t addrlen, asio::error_code& ec) -{ - clear_error(ec); - int result = error_wrapper(call_connect( - &msghdr::msg_namelen, s, addr, addrlen), ec); -#if defined(BOOST_WINDOWS) && defined(UNDER_CE) - if (result == 0) - clear_error(ec); -#endif - return result; -} - -inline int socketpair(int af, int type, int protocol, - socket_type sv[2], asio::error_code& ec) -{ -#if defined(BOOST_WINDOWS) || defined(__CYGWIN__) - (void)(af); - (void)(type); - (void)(protocol); - (void)(sv); - ec = asio::error::operation_not_supported; - return -1; -#else - clear_error(ec); - return error_wrapper(::socketpair(af, type, protocol, sv), ec); -#endif -} - -inline int listen(socket_type s, int backlog, asio::error_code& ec) -{ - clear_error(ec); - int result = error_wrapper(::listen(s, backlog), ec); -#if defined(BOOST_WINDOWS) && defined(UNDER_CE) - if (result == 0) - clear_error(ec); -#endif - return result; -} - -#if defined(BOOST_WINDOWS) || defined(__CYGWIN__) -typedef WSABUF buf; -#else // defined(BOOST_WINDOWS) || defined(__CYGWIN__) -typedef iovec buf; -#endif // defined(BOOST_WINDOWS) || defined(__CYGWIN__) - -inline void init_buf(buf& b, void* data, size_t size) -{ -#if defined(BOOST_WINDOWS) || defined(__CYGWIN__) - b.buf = static_cast(data); - b.len = static_cast(size); -#else // defined(BOOST_WINDOWS) || defined(__CYGWIN__) - b.iov_base = data; - b.iov_len = size; -#endif // defined(BOOST_WINDOWS) || defined(__CYGWIN__) -} - -inline void init_buf(buf& b, const void* data, size_t size) -{ -#if defined(BOOST_WINDOWS) || defined(__CYGWIN__) - b.buf = static_cast(const_cast(data)); - b.len = static_cast(size); -#else // defined(BOOST_WINDOWS) || defined(__CYGWIN__) - b.iov_base = const_cast(data); - b.iov_len = size; -#endif // defined(BOOST_WINDOWS) || defined(__CYGWIN__) -} - -inline void init_msghdr_msg_name(void*& name, socket_addr_type* addr) -{ - name = addr; -} - -inline void init_msghdr_msg_name(void*& name, const socket_addr_type* addr) -{ - name = const_cast(addr); -} - -template -inline void init_msghdr_msg_name(T& name, socket_addr_type* addr) -{ - name = reinterpret_cast(addr); -} - -template -inline void init_msghdr_msg_name(T& name, const socket_addr_type* addr) -{ - name = reinterpret_cast(const_cast(addr)); -} - -inline int recv(socket_type s, buf* bufs, size_t count, int flags, - asio::error_code& ec) -{ - clear_error(ec); -#if defined(BOOST_WINDOWS) || defined(__CYGWIN__) - // Receive some data. - DWORD recv_buf_count = static_cast(count); - DWORD bytes_transferred = 0; - DWORD recv_flags = flags; - int result = error_wrapper(::WSARecv(s, bufs, - recv_buf_count, &bytes_transferred, &recv_flags, 0, 0), ec); - if (result != 0) - return -1; -# if defined(UNDER_CE) - clear_error(ec); -# endif - return bytes_transferred; -#else // defined(BOOST_WINDOWS) || defined(__CYGWIN__) - msghdr msg = msghdr(); - msg.msg_iov = bufs; - msg.msg_iovlen = count; - return error_wrapper(::recvmsg(s, &msg, flags), ec); -#endif // defined(BOOST_WINDOWS) || defined(__CYGWIN__) -} - -inline int recvfrom(socket_type s, buf* bufs, size_t count, int flags, - socket_addr_type* addr, std::size_t* addrlen, - asio::error_code& ec) -{ - clear_error(ec); -#if defined(BOOST_WINDOWS) || defined(__CYGWIN__) - // Receive some data. - DWORD recv_buf_count = static_cast(count); - DWORD bytes_transferred = 0; - DWORD recv_flags = flags; - int tmp_addrlen = (int)*addrlen; - int result = error_wrapper(::WSARecvFrom(s, bufs, recv_buf_count, - &bytes_transferred, &recv_flags, addr, &tmp_addrlen, 0, 0), ec); - *addrlen = (std::size_t)tmp_addrlen; - if (result != 0) - return -1; -# if defined(UNDER_CE) - clear_error(ec); -# endif - return bytes_transferred; -#else // defined(BOOST_WINDOWS) || defined(__CYGWIN__) - msghdr msg = msghdr(); - init_msghdr_msg_name(msg.msg_name, addr); - msg.msg_namelen = *addrlen; - msg.msg_iov = bufs; - msg.msg_iovlen = count; - int result = error_wrapper(::recvmsg(s, &msg, flags), ec); - *addrlen = msg.msg_namelen; - return result; -#endif // defined(BOOST_WINDOWS) || defined(__CYGWIN__) -} - -inline int send(socket_type s, const buf* bufs, size_t count, int flags, - asio::error_code& ec) -{ - clear_error(ec); -#if defined(BOOST_WINDOWS) || defined(__CYGWIN__) - // Send the data. - DWORD send_buf_count = static_cast(count); - DWORD bytes_transferred = 0; - DWORD send_flags = flags; - int result = error_wrapper(::WSASend(s, const_cast(bufs), - send_buf_count, &bytes_transferred, send_flags, 0, 0), ec); - if (result != 0) - return -1; -# if defined(UNDER_CE) - clear_error(ec); -# endif - return bytes_transferred; -#else // defined(BOOST_WINDOWS) || defined(__CYGWIN__) - msghdr msg = msghdr(); - msg.msg_iov = const_cast(bufs); - msg.msg_iovlen = count; -#if defined(__linux__) - flags |= MSG_NOSIGNAL; -#endif // defined(__linux__) - return error_wrapper(::sendmsg(s, &msg, flags), ec); -#endif // defined(BOOST_WINDOWS) || defined(__CYGWIN__) -} - -inline int sendto(socket_type s, const buf* bufs, size_t count, int flags, - const socket_addr_type* addr, std::size_t addrlen, - asio::error_code& ec) -{ - clear_error(ec); -#if defined(BOOST_WINDOWS) || defined(__CYGWIN__) - // Send the data. - DWORD send_buf_count = static_cast(count); - DWORD bytes_transferred = 0; - int result = error_wrapper(::WSASendTo(s, const_cast(bufs), - send_buf_count, &bytes_transferred, flags, addr, - static_cast(addrlen), 0, 0), ec); - if (result != 0) - return -1; -# if defined(UNDER_CE) - clear_error(ec); -# endif - return bytes_transferred; -#else // defined(BOOST_WINDOWS) || defined(__CYGWIN__) - msghdr msg = msghdr(); - init_msghdr_msg_name(msg.msg_name, addr); - msg.msg_namelen = addrlen; - msg.msg_iov = const_cast(bufs); - msg.msg_iovlen = count; -#if defined(__linux__) - flags |= MSG_NOSIGNAL; -#endif // defined(__linux__) - return error_wrapper(::sendmsg(s, &msg, flags), ec); -#endif // defined(BOOST_WINDOWS) || defined(__CYGWIN__) -} - -inline socket_type socket(int af, int type, int protocol, - asio::error_code& ec) -{ - clear_error(ec); -#if defined(BOOST_WINDOWS) || defined(__CYGWIN__) - socket_type s = error_wrapper(::WSASocket(af, type, protocol, 0, 0, - WSA_FLAG_OVERLAPPED), ec); - if (s == invalid_socket) - return s; - - if (af == AF_INET6) - { - // Try to enable the POSIX default behaviour of having IPV6_V6ONLY set to - // false. This will only succeed on Windows Vista and later versions of - // Windows, where a dual-stack IPv4/v6 implementation is available. - DWORD optval = 0; - ::setsockopt(s, IPPROTO_IPV6, IPV6_V6ONLY, - reinterpret_cast(&optval), sizeof(optval)); - } - -# if defined(UNDER_CE) - clear_error(ec); -# endif - - return s; -#elif defined(__MACH__) && defined(__APPLE__) || defined(__FreeBSD__) - socket_type s = error_wrapper(::socket(af, type, protocol), ec); - if (s == invalid_socket) - return s; - - int optval = 1; - int result = error_wrapper(::setsockopt(s, - SOL_SOCKET, SO_NOSIGPIPE, &optval, sizeof(optval)), ec); - if (result != 0) - { - ::close(s); - return invalid_socket; - } - - return s; -#else - return error_wrapper(::socket(af, type, protocol), ec); -#endif -} - -template -inline int call_setsockopt(SockLenType msghdr::*, - socket_type s, int level, int optname, - const void* optval, std::size_t optlen) -{ - return ::setsockopt(s, level, optname, - (const char*)optval, (SockLenType)optlen); -} - -inline int setsockopt(socket_type s, int level, int optname, - const void* optval, std::size_t optlen, asio::error_code& ec) -{ - if (level == custom_socket_option_level && optname == always_fail_option) - { - ec = asio::error::invalid_argument; - return -1; - } - -#if defined(__BORLANDC__) - // Mysteriously, using the getsockopt and setsockopt functions directly with - // Borland C++ results in incorrect values being set and read. The bug can be - // worked around by using function addresses resolved with GetProcAddress. - if (HMODULE winsock_module = ::GetModuleHandleA("ws2_32")) - { - typedef int (WSAAPI *sso_t)(SOCKET, int, int, const char*, int); - if (sso_t sso = (sso_t)::GetProcAddress(winsock_module, "setsockopt")) - { - clear_error(ec); - return error_wrapper(sso(s, level, optname, - reinterpret_cast(optval), - static_cast(optlen)), ec); - } - } - ec = asio::error::fault; - return -1; -#else // defined(__BORLANDC__) - clear_error(ec); - int result = error_wrapper(call_setsockopt(&msghdr::msg_namelen, - s, level, optname, optval, optlen), ec); -# if defined(BOOST_WINDOWS) && defined(UNDER_CE) - if (result == 0) - clear_error(ec); -# endif - return result; -#endif // defined(__BORLANDC__) -} - -template -inline int call_getsockopt(SockLenType msghdr::*, - socket_type s, int level, int optname, - void* optval, std::size_t* optlen) -{ - SockLenType tmp_optlen = (SockLenType)*optlen; - int result = ::getsockopt(s, level, optname, (char*)optval, &tmp_optlen); - *optlen = (std::size_t)tmp_optlen; - return result; -} - -inline int getsockopt(socket_type s, int level, int optname, void* optval, - size_t* optlen, asio::error_code& ec) -{ - if (level == custom_socket_option_level && optname == always_fail_option) - { - ec = asio::error::invalid_argument; - return -1; - } - -#if defined(__BORLANDC__) - // Mysteriously, using the getsockopt and setsockopt functions directly with - // Borland C++ results in incorrect values being set and read. The bug can be - // worked around by using function addresses resolved with GetProcAddress. - if (HMODULE winsock_module = ::GetModuleHandleA("ws2_32")) - { - typedef int (WSAAPI *gso_t)(SOCKET, int, int, char*, int*); - if (gso_t gso = (gso_t)::GetProcAddress(winsock_module, "getsockopt")) - { - clear_error(ec); - int tmp_optlen = static_cast(*optlen); - int result = error_wrapper(gso(s, level, optname, - reinterpret_cast(optval), &tmp_optlen), ec); - *optlen = static_cast(tmp_optlen); - if (result != 0 && level == IPPROTO_IPV6 && optname == IPV6_V6ONLY - && ec.value() == WSAENOPROTOOPT && *optlen == sizeof(DWORD)) - { - // Dual-stack IPv4/v6 sockets, and the IPV6_V6ONLY socket option, are - // only supported on Windows Vista and later. To simplify program logic - // we will fake success of getting this option and specify that the - // value is non-zero (i.e. true). This corresponds to the behavior of - // IPv6 sockets on Windows platforms pre-Vista. - *static_cast(optval) = 1; - clear_error(ec); - } - return result; - } - } - ec = asio::error::fault; - return -1; -#elif defined(BOOST_WINDOWS) || defined(__CYGWIN__) - clear_error(ec); - int result = error_wrapper(call_getsockopt(&msghdr::msg_namelen, - s, level, optname, optval, optlen), ec); - if (result != 0 && level == IPPROTO_IPV6 && optname == IPV6_V6ONLY - && ec.value() == WSAENOPROTOOPT && *optlen == sizeof(DWORD)) - { - // Dual-stack IPv4/v6 sockets, and the IPV6_V6ONLY socket option, are only - // supported on Windows Vista and later. To simplify program logic we will - // fake success of getting this option and specify that the value is - // non-zero (i.e. true). This corresponds to the behavior of IPv6 sockets - // on Windows platforms pre-Vista. - *static_cast(optval) = 1; - clear_error(ec); - } -# if defined(UNDER_CE) - if (result == 0) - clear_error(ec); -# endif - return result; -#else // defined(BOOST_WINDOWS) || defined(__CYGWIN__) - clear_error(ec); - int result = error_wrapper(call_getsockopt(&msghdr::msg_namelen, - s, level, optname, optval, optlen), ec); -#if defined(__linux__) - if (result == 0 && level == SOL_SOCKET && *optlen == sizeof(int) - && (optname == SO_SNDBUF || optname == SO_RCVBUF)) - { - // On Linux, setting SO_SNDBUF or SO_RCVBUF to N actually causes the kernel - // to set the buffer size to N*2. Linux puts additional stuff into the - // buffers so that only about half is actually available to the application. - // The retrieved value is divided by 2 here to make it appear as though the - // correct value has been set. - *static_cast(optval) /= 2; - } -#endif // defined(__linux__) - return result; -#endif // defined(BOOST_WINDOWS) || defined(__CYGWIN__) -} - -template -inline int call_getpeername(SockLenType msghdr::*, - socket_type s, socket_addr_type* addr, std::size_t* addrlen) -{ - SockLenType tmp_addrlen = (SockLenType)*addrlen; - int result = ::getpeername(s, addr, &tmp_addrlen); - *addrlen = (std::size_t)tmp_addrlen; - return result; -} - -inline int getpeername(socket_type s, socket_addr_type* addr, - std::size_t* addrlen, asio::error_code& ec) -{ - clear_error(ec); - int result = error_wrapper(call_getpeername( - &msghdr::msg_namelen, s, addr, addrlen), ec); -#if defined(BOOST_WINDOWS) && defined(UNDER_CE) - if (result == 0) - clear_error(ec); -#endif - return result; -} - -template -inline int call_getsockname(SockLenType msghdr::*, - socket_type s, socket_addr_type* addr, std::size_t* addrlen) -{ - SockLenType tmp_addrlen = (SockLenType)*addrlen; - int result = ::getsockname(s, addr, &tmp_addrlen); - *addrlen = (std::size_t)tmp_addrlen; - return result; -} - -inline int getsockname(socket_type s, socket_addr_type* addr, - std::size_t* addrlen, asio::error_code& ec) -{ - clear_error(ec); - int result = error_wrapper(call_getsockname( - &msghdr::msg_namelen, s, addr, addrlen), ec); -#if defined(BOOST_WINDOWS) && defined(UNDER_CE) - if (result == 0) - clear_error(ec); -#endif - return result; -} - -inline int ioctl(socket_type s, long cmd, ioctl_arg_type* arg, - asio::error_code& ec) -{ - clear_error(ec); -#if defined(BOOST_WINDOWS) || defined(__CYGWIN__) - int result = error_wrapper(::ioctlsocket(s, cmd, arg), ec); -# if defined(UNDER_CE) - if (result == 0) - clear_error(ec); -# endif - return result; -#else // defined(BOOST_WINDOWS) || defined(__CYGWIN__) - return error_wrapper(::ioctl(s, cmd, arg), ec); -#endif // defined(BOOST_WINDOWS) || defined(__CYGWIN__) -} - -inline int select(int nfds, fd_set* readfds, fd_set* writefds, - fd_set* exceptfds, timeval* timeout, asio::error_code& ec) -{ - clear_error(ec); -#if defined(BOOST_WINDOWS) || defined(__CYGWIN__) - if (!readfds && !writefds && !exceptfds && timeout) - { - DWORD milliseconds = timeout->tv_sec * 1000 + timeout->tv_usec / 1000; - if (milliseconds == 0) - milliseconds = 1; // Force context switch. - ::Sleep(milliseconds); - ec = asio::error_code(); - return 0; - } - - // The select() call allows timeout values measured in microseconds, but the - // system clock (as wrapped by boost::posix_time::microsec_clock) typically - // has a resolution of 10 milliseconds. This can lead to a spinning select - // reactor, meaning increased CPU usage, when waiting for the earliest - // scheduled timeout if it's less than 10 milliseconds away. To avoid a tight - // spin we'll use a minimum timeout of 1 millisecond. - if (timeout && timeout->tv_sec == 0 - && timeout->tv_usec > 0 && timeout->tv_usec < 1000) - timeout->tv_usec = 1000; -#endif // defined(BOOST_WINDOWS) || defined(__CYGWIN__) - -#if defined(__hpux) && defined(__HP_aCC) - timespec ts; - ts.tv_sec = timeout ? timeout->tv_sec : 0; - ts.tv_nsec = timeout ? timeout->tv_usec * 1000 : 0; - return error_wrapper(::pselect(nfds, readfds, - writefds, exceptfds, timeout ? &ts : 0, 0), ec); -#else - int result = error_wrapper(::select(nfds, readfds, - writefds, exceptfds, timeout), ec); -# if defined(BOOST_WINDOWS) && defined(UNDER_CE) - if (result >= 0) - clear_error(ec); -# endif - return result; -#endif -} - -inline int poll_read(socket_type s, asio::error_code& ec) -{ -#if defined(BOOST_WINDOWS) || defined(__CYGWIN__) - FD_SET fds; - FD_ZERO(&fds); - FD_SET(s, &fds); - clear_error(ec); - int result = error_wrapper(::select(s, &fds, 0, 0, 0), ec); -# if defined(UNDER_CE) - if (result >= 0) - clear_error(ec); -# endif - return result; -#else // defined(BOOST_WINDOWS) || defined(__CYGWIN__) - pollfd fds; - fds.fd = s; - fds.events = POLLIN; - fds.revents = 0; - clear_error(ec); - return error_wrapper(::poll(&fds, 1, -1), ec); -#endif // defined(BOOST_WINDOWS) || defined(__CYGWIN__) -} - -inline int poll_write(socket_type s, asio::error_code& ec) -{ -#if defined(BOOST_WINDOWS) || defined(__CYGWIN__) - FD_SET fds; - FD_ZERO(&fds); - FD_SET(s, &fds); - clear_error(ec); - int result = error_wrapper(::select(s, 0, &fds, 0, 0), ec); -# if defined(UNDER_CE) - if (result >= 0) - clear_error(ec); -# endif - return result; -#else // defined(BOOST_WINDOWS) || defined(__CYGWIN__) - pollfd fds; - fds.fd = s; - fds.events = POLLOUT; - fds.revents = 0; - clear_error(ec); - return error_wrapper(::poll(&fds, 1, -1), ec); -#endif // defined(BOOST_WINDOWS) || defined(__CYGWIN__) -} - -inline const char* inet_ntop(int af, const void* src, char* dest, size_t length, - unsigned long scope_id, asio::error_code& ec) -{ - clear_error(ec); -#if defined(BOOST_WINDOWS) || defined(__CYGWIN__) - using namespace std; // For memcpy. - - if (af != AF_INET && af != AF_INET6) - { - ec = asio::error::address_family_not_supported; - return 0; - } - - union - { - socket_addr_type base; - sockaddr_storage_type storage; - sockaddr_in4_type v4; - sockaddr_in6_type v6; - } address; - DWORD address_length; - if (af == AF_INET) - { - address_length = sizeof(sockaddr_in4_type); - address.v4.sin_family = AF_INET; - address.v4.sin_port = 0; - memcpy(&address.v4.sin_addr, src, sizeof(in4_addr_type)); - } - else // AF_INET6 - { - address_length = sizeof(sockaddr_in6_type); - address.v6.sin6_family = AF_INET6; - address.v6.sin6_port = 0; - address.v6.sin6_flowinfo = 0; - address.v6.sin6_scope_id = scope_id; - memcpy(&address.v6.sin6_addr, src, sizeof(in6_addr_type)); - } - - DWORD string_length = static_cast(length); -#if defined(BOOST_NO_ANSI_APIS) - LPWSTR string_buffer = (LPWSTR)_alloca(length * sizeof(WCHAR)); - int result = error_wrapper(::WSAAddressToStringW(&address.base, - address_length, 0, string_buffer, &string_length), ec); - ::WideCharToMultiByte(CP_ACP, 0, string_buffer, -1, dest, length, 0, 0); -#else - int result = error_wrapper(::WSAAddressToStringA( - &address.base, address_length, 0, dest, &string_length), ec); -#endif - - // Windows may set error code on success. - if (result != socket_error_retval) - clear_error(ec); - - // Windows may not set an error code on failure. - else if (result == socket_error_retval && !ec) - ec = asio::error::invalid_argument; - - return result == socket_error_retval ? 0 : dest; -#else // defined(BOOST_WINDOWS) || defined(__CYGWIN__) - const char* result = error_wrapper(::inet_ntop(af, src, dest, length), ec); - if (result == 0 && !ec) - ec = asio::error::invalid_argument; - if (result != 0 && af == AF_INET6 && scope_id != 0) - { - using namespace std; // For strcat and sprintf. - char if_name[IF_NAMESIZE + 1] = "%"; - const in6_addr_type* ipv6_address = static_cast(src); - bool is_link_local = IN6_IS_ADDR_LINKLOCAL(ipv6_address); - if (!is_link_local || if_indextoname(scope_id, if_name + 1) == 0) - sprintf(if_name + 1, "%lu", scope_id); - strcat(dest, if_name); - } - return result; -#endif // defined(BOOST_WINDOWS) || defined(__CYGWIN__) -} - -inline int inet_pton(int af, const char* src, void* dest, - unsigned long* scope_id, asio::error_code& ec) -{ - clear_error(ec); -#if defined(BOOST_WINDOWS) || defined(__CYGWIN__) - using namespace std; // For memcpy and strcmp. - - if (af != AF_INET && af != AF_INET6) - { - ec = asio::error::address_family_not_supported; - return -1; - } - - union - { - socket_addr_type base; - sockaddr_storage_type storage; - sockaddr_in4_type v4; - sockaddr_in6_type v6; - } address; - int address_length = sizeof(sockaddr_storage_type); -#if defined(BOOST_NO_ANSI_APIS) - int num_wide_chars = strlen(src) + 1; - LPWSTR wide_buffer = (LPWSTR)_alloca(num_wide_chars * sizeof(WCHAR)); - ::MultiByteToWideChar(CP_ACP, 0, src, -1, wide_buffer, num_wide_chars); - int result = error_wrapper(::WSAStringToAddressW( - wide_buffer, af, 0, &address.base, &address_length), ec); -#else - int result = error_wrapper(::WSAStringToAddressA( - const_cast(src), af, 0, &address.base, &address_length), ec); -#endif - - if (af == AF_INET) - { - if (result != socket_error_retval) - { - memcpy(dest, &address.v4.sin_addr, sizeof(in4_addr_type)); - clear_error(ec); - } - else if (strcmp(src, "255.255.255.255") == 0) - { - static_cast(dest)->s_addr = INADDR_NONE; - clear_error(ec); - } - } - else // AF_INET6 - { - if (result != socket_error_retval) - { - memcpy(dest, &address.v6.sin6_addr, sizeof(in6_addr_type)); - if (scope_id) - *scope_id = address.v6.sin6_scope_id; - clear_error(ec); - } - } - - // Windows may not set an error code on failure. - if (result == socket_error_retval && !ec) - ec = asio::error::invalid_argument; - -#if defined(UNDER_CE) - if (result != socket_error_retval) - clear_error(ec); -#endif - - return result == socket_error_retval ? -1 : 1; -#else // defined(BOOST_WINDOWS) || defined(__CYGWIN__) - int result = error_wrapper(::inet_pton(af, src, dest), ec); - if (result <= 0 && !ec) - ec = asio::error::invalid_argument; - if (result > 0 && af == AF_INET6 && scope_id) - { - using namespace std; // For strchr and atoi. - *scope_id = 0; - if (const char* if_name = strchr(src, '%')) - { - in6_addr_type* ipv6_address = static_cast(dest); - bool is_link_local = IN6_IS_ADDR_LINKLOCAL(ipv6_address); - if (is_link_local) - *scope_id = if_nametoindex(if_name + 1); - if (*scope_id == 0) - *scope_id = atoi(if_name + 1); - } - } - return result; -#endif // defined(BOOST_WINDOWS) || defined(__CYGWIN__) -} - -inline int gethostname(char* name, int namelen, asio::error_code& ec) -{ - clear_error(ec); - int result = error_wrapper(::gethostname(name, namelen), ec); -#if defined(BOOST_WINDOWS) && defined(UNDER_CE) - if (result == 0) - clear_error(ec); -#endif - return result; -} - -#if defined(BOOST_WINDOWS) || defined(__CYGWIN__) \ - || defined(__MACH__) && defined(__APPLE__) - -// The following functions are only needed for emulation of getaddrinfo and -// getnameinfo. - -inline asio::error_code translate_netdb_error(int error) -{ - switch (error) - { - case 0: - return asio::error_code(); - case HOST_NOT_FOUND: - return asio::error::host_not_found; - case TRY_AGAIN: - return asio::error::host_not_found_try_again; - case NO_RECOVERY: - return asio::error::no_recovery; - case NO_DATA: - return asio::error::no_data; - default: - BOOST_ASSERT(false); - return asio::error::invalid_argument; - } -} - -inline hostent* gethostbyaddr(const char* addr, int length, int af, - hostent* result, char* buffer, int buflength, asio::error_code& ec) -{ - clear_error(ec); -#if defined(BOOST_WINDOWS) || defined(__CYGWIN__) - (void)(buffer); - (void)(buflength); - hostent* retval = error_wrapper(::gethostbyaddr(addr, length, af), ec); - if (!retval) - return 0; -# if defined(UNDER_CE) - clear_error(ec); -# endif - *result = *retval; - return retval; -#elif defined(__sun) || defined(__QNX__) - int error = 0; - hostent* retval = error_wrapper(::gethostbyaddr_r(addr, length, af, result, - buffer, buflength, &error), ec); - if (error) - ec = translate_netdb_error(error); - return retval; -#elif defined(__MACH__) && defined(__APPLE__) - (void)(buffer); - (void)(buflength); - int error = 0; - hostent* retval = error_wrapper(::getipnodebyaddr( - addr, length, af, &error), ec); - if (error) - ec = translate_netdb_error(error); - if (!retval) - return 0; - *result = *retval; - return retval; -#else - hostent* retval = 0; - int error = 0; - error_wrapper(::gethostbyaddr_r(addr, length, af, result, buffer, - buflength, &retval, &error), ec); - if (error) - ec = translate_netdb_error(error); - return retval; -#endif -} - -inline hostent* gethostbyname(const char* name, int af, struct hostent* result, - char* buffer, int buflength, int ai_flags, asio::error_code& ec) -{ - clear_error(ec); -#if defined(BOOST_WINDOWS) || defined(__CYGWIN__) - (void)(buffer); - (void)(buflength); - (void)(ai_flags); - if (af != AF_INET) - { - ec = asio::error::address_family_not_supported; - return 0; - } - hostent* retval = error_wrapper(::gethostbyname(name), ec); - if (!retval) - return 0; -# if defined(UNDER_CE) - clear_error(ec); -# endif - *result = *retval; - return result; -#elif defined(__sun) || defined(__QNX__) - (void)(ai_flags); - if (af != AF_INET) - { - ec = asio::error::address_family_not_supported; - return 0; - } - int error = 0; - hostent* retval = error_wrapper(::gethostbyname_r(name, result, buffer, - buflength, &error), ec); - if (error) - ec = translate_netdb_error(error); - return retval; -#elif defined(__MACH__) && defined(__APPLE__) - (void)(buffer); - (void)(buflength); - int error = 0; - hostent* retval = error_wrapper(::getipnodebyname( - name, af, ai_flags, &error), ec); - if (error) - ec = translate_netdb_error(error); - if (!retval) - return 0; - *result = *retval; - return retval; -#else - (void)(ai_flags); - if (af != AF_INET) - { - ec = asio::error::address_family_not_supported; - return 0; - } - hostent* retval = 0; - int error = 0; - error_wrapper(::gethostbyname_r(name, result, - buffer, buflength, &retval, &error), ec); - if (error) - ec = translate_netdb_error(error); - return retval; -#endif -} - -inline void freehostent(hostent* h) -{ -#if defined(__MACH__) && defined(__APPLE__) - if (h) - ::freehostent(h); -#else - (void)(h); -#endif -} - -// Emulation of getaddrinfo based on implementation in: -// Stevens, W. R., UNIX Network Programming Vol. 1, 2nd Ed., Prentice-Hall 1998. - -struct gai_search -{ - const char* host; - int family; -}; - -inline int gai_nsearch(const char* host, - const addrinfo_type* hints, gai_search (&search)[2]) -{ - int search_count = 0; - if (host == 0 || host[0] == '\0') - { - if (hints->ai_flags & AI_PASSIVE) - { - // No host and AI_PASSIVE implies wildcard bind. - switch (hints->ai_family) - { - case AF_INET: - search[search_count].host = "0.0.0.0"; - search[search_count].family = AF_INET; - ++search_count; - break; - case AF_INET6: - search[search_count].host = "0::0"; - search[search_count].family = AF_INET6; - ++search_count; - break; - case AF_UNSPEC: - search[search_count].host = "0::0"; - search[search_count].family = AF_INET6; - ++search_count; - search[search_count].host = "0.0.0.0"; - search[search_count].family = AF_INET; - ++search_count; - break; - default: - break; - } - } - else - { - // No host and not AI_PASSIVE means connect to local host. - switch (hints->ai_family) - { - case AF_INET: - search[search_count].host = "localhost"; - search[search_count].family = AF_INET; - ++search_count; - break; - case AF_INET6: - search[search_count].host = "localhost"; - search[search_count].family = AF_INET6; - ++search_count; - break; - case AF_UNSPEC: - search[search_count].host = "localhost"; - search[search_count].family = AF_INET6; - ++search_count; - search[search_count].host = "localhost"; - search[search_count].family = AF_INET; - ++search_count; - break; - default: - break; - } - } - } - else - { - // Host is specified. - switch (hints->ai_family) - { - case AF_INET: - search[search_count].host = host; - search[search_count].family = AF_INET; - ++search_count; - break; - case AF_INET6: - search[search_count].host = host; - search[search_count].family = AF_INET6; - ++search_count; - break; - case AF_UNSPEC: - search[search_count].host = host; - search[search_count].family = AF_INET6; - ++search_count; - search[search_count].host = host; - search[search_count].family = AF_INET; - ++search_count; - break; - default: - break; - } - } - return search_count; -} - -template -inline T* gai_alloc(std::size_t size = sizeof(T)) -{ - using namespace std; - T* p = static_cast(::operator new(size, std::nothrow)); - if (p) - memset(p, 0, size); - return p; -} - -inline void gai_free(void* p) -{ - ::operator delete(p); -} - -inline void gai_strcpy(char* target, const char* source, std::size_t max_size) -{ - using namespace std; -#if BOOST_WORKAROUND(BOOST_MSVC, >= 1400) && !defined(UNDER_CE) - strcpy_s(target, max_size, source); -#else - *target = 0; - strncat(target, source, max_size); -#endif -} - -enum { gai_clone_flag = 1 << 30 }; - -inline int gai_aistruct(addrinfo_type*** next, const addrinfo_type* hints, - const void* addr, int family) -{ - using namespace std; - - addrinfo_type* ai = gai_alloc(); - if (ai == 0) - return EAI_MEMORY; - - ai->ai_next = 0; - **next = ai; - *next = &ai->ai_next; - - ai->ai_canonname = 0; - ai->ai_socktype = hints->ai_socktype; - if (ai->ai_socktype == 0) - ai->ai_flags |= gai_clone_flag; - ai->ai_protocol = hints->ai_protocol; - ai->ai_family = family; - - switch (ai->ai_family) - { - case AF_INET: - { - sockaddr_in4_type* sinptr = gai_alloc(); - if (sinptr == 0) - return EAI_MEMORY; - sinptr->sin_family = AF_INET; - memcpy(&sinptr->sin_addr, addr, sizeof(in4_addr_type)); - ai->ai_addr = reinterpret_cast(sinptr); - ai->ai_addrlen = sizeof(sockaddr_in4_type); - break; - } - case AF_INET6: - { - sockaddr_in6_type* sin6ptr = gai_alloc(); - if (sin6ptr == 0) - return EAI_MEMORY; - sin6ptr->sin6_family = AF_INET6; - memcpy(&sin6ptr->sin6_addr, addr, sizeof(in6_addr_type)); - ai->ai_addr = reinterpret_cast(sin6ptr); - ai->ai_addrlen = sizeof(sockaddr_in6_type); - break; - } - default: - break; - } - - return 0; -} - -inline addrinfo_type* gai_clone(addrinfo_type* ai) -{ - using namespace std; - - addrinfo_type* new_ai = gai_alloc(); - if (new_ai == 0) - return new_ai; - - new_ai->ai_next = ai->ai_next; - ai->ai_next = new_ai; - - new_ai->ai_flags = 0; - new_ai->ai_family = ai->ai_family; - new_ai->ai_socktype = ai->ai_socktype; - new_ai->ai_protocol = ai->ai_protocol; - new_ai->ai_canonname = 0; - new_ai->ai_addrlen = ai->ai_addrlen; - new_ai->ai_addr = gai_alloc(ai->ai_addrlen); - memcpy(new_ai->ai_addr, ai->ai_addr, ai->ai_addrlen); - - return new_ai; -} - -inline int gai_port(addrinfo_type* aihead, int port, int socktype) -{ - int num_found = 0; - - for (addrinfo_type* ai = aihead; ai; ai = ai->ai_next) - { - if (ai->ai_flags & gai_clone_flag) - { - if (ai->ai_socktype != 0) - { - ai = gai_clone(ai); - if (ai == 0) - return -1; - // ai now points to newly cloned entry. - } - } - else if (ai->ai_socktype != socktype) - { - // Ignore if mismatch on socket type. - continue; - } - - ai->ai_socktype = socktype; - - switch (ai->ai_family) - { - case AF_INET: - { - sockaddr_in4_type* sinptr = - reinterpret_cast(ai->ai_addr); - sinptr->sin_port = port; - ++num_found; - break; - } - case AF_INET6: - { - sockaddr_in6_type* sin6ptr = - reinterpret_cast(ai->ai_addr); - sin6ptr->sin6_port = port; - ++num_found; - break; - } - default: - break; - } - } - - return num_found; -} - -inline int gai_serv(addrinfo_type* aihead, - const addrinfo_type* hints, const char* serv) -{ - using namespace std; - - int num_found = 0; - - if ( -#if defined(AI_NUMERICSERV) - (hints->ai_flags & AI_NUMERICSERV) || -#endif - isdigit(serv[0])) - { - int port = htons(atoi(serv)); - if (hints->ai_socktype) - { - // Caller specifies socket type. - int rc = gai_port(aihead, port, hints->ai_socktype); - if (rc < 0) - return EAI_MEMORY; - num_found += rc; - } - else - { - // Caller does not specify socket type. - int rc = gai_port(aihead, port, SOCK_STREAM); - if (rc < 0) - return EAI_MEMORY; - num_found += rc; - rc = gai_port(aihead, port, SOCK_DGRAM); - if (rc < 0) - return EAI_MEMORY; - num_found += rc; - } - } - else - { - // Try service name with TCP first, then UDP. - if (hints->ai_socktype == 0 || hints->ai_socktype == SOCK_STREAM) - { - servent* sptr = getservbyname(serv, "tcp"); - if (sptr != 0) - { - int rc = gai_port(aihead, sptr->s_port, SOCK_STREAM); - if (rc < 0) - return EAI_MEMORY; - num_found += rc; - } - } - if (hints->ai_socktype == 0 || hints->ai_socktype == SOCK_DGRAM) - { - servent* sptr = getservbyname(serv, "udp"); - if (sptr != 0) - { - int rc = gai_port(aihead, sptr->s_port, SOCK_DGRAM); - if (rc < 0) - return EAI_MEMORY; - num_found += rc; - } - } - } - - if (num_found == 0) - { - if (hints->ai_socktype == 0) - { - // All calls to getservbyname() failed. - return EAI_NONAME; - } - else - { - // Service not supported for socket type. - return EAI_SERVICE; - } - } - - return 0; -} - -inline int gai_echeck(const char* host, const char* service, - int flags, int family, int socktype, int protocol) -{ - (void)(flags); - (void)(protocol); - - // Host or service must be specified. - if (host == 0 || host[0] == '\0') - if (service == 0 || service[0] == '\0') - return EAI_NONAME; - - // Check combination of family and socket type. - switch (family) - { - case AF_UNSPEC: - break; - case AF_INET: - case AF_INET6: - if (socktype != 0 && socktype != SOCK_STREAM && socktype != SOCK_DGRAM) - return EAI_SOCKTYPE; - break; - default: - return EAI_FAMILY; - } - - return 0; -} - -inline void freeaddrinfo_emulation(addrinfo_type* aihead) -{ - addrinfo_type* ai = aihead; - while (ai) - { - gai_free(ai->ai_addr); - gai_free(ai->ai_canonname); - addrinfo_type* ainext = ai->ai_next; - gai_free(ai); - ai = ainext; - } -} - -inline int getaddrinfo_emulation(const char* host, const char* service, - const addrinfo_type* hintsp, addrinfo_type** result) -{ - // Set up linked list of addrinfo structures. - addrinfo_type* aihead = 0; - addrinfo_type** ainext = &aihead; - char* canon = 0; - - // Supply default hints if not specified by caller. - addrinfo_type hints = addrinfo_type(); - hints.ai_family = AF_UNSPEC; - if (hintsp) - hints = *hintsp; - - // If the resolution is not specifically for AF_INET6, remove the AI_V4MAPPED - // and AI_ALL flags. -#if defined(AI_V4MAPPED) - if (hints.ai_family != AF_INET6) - hints.ai_flags &= ~AI_V4MAPPED; -#endif -#if defined(AI_ALL) - if (hints.ai_family != AF_INET6) - hints.ai_flags &= ~AI_ALL; -#endif - - // Basic error checking. - int rc = gai_echeck(host, service, hints.ai_flags, hints.ai_family, - hints.ai_socktype, hints.ai_protocol); - if (rc != 0) - { - freeaddrinfo_emulation(aihead); - return rc; - } - - gai_search search[2]; - int search_count = gai_nsearch(host, &hints, search); - for (gai_search* sptr = search; sptr < search + search_count; ++sptr) - { - // Check for IPv4 dotted decimal string. - in4_addr_type inaddr; - asio::error_code ec; - if (socket_ops::inet_pton(AF_INET, sptr->host, &inaddr, 0, ec) == 1) - { - if (hints.ai_family != AF_UNSPEC && hints.ai_family != AF_INET) - { - freeaddrinfo_emulation(aihead); - gai_free(canon); - return EAI_FAMILY; - } - if (sptr->family == AF_INET) - { - rc = gai_aistruct(&ainext, &hints, &inaddr, AF_INET); - if (rc != 0) - { - freeaddrinfo_emulation(aihead); - gai_free(canon); - return rc; - } - } - continue; - } - - // Check for IPv6 hex string. - in6_addr_type in6addr; - if (socket_ops::inet_pton(AF_INET6, sptr->host, &in6addr, 0, ec) == 1) - { - if (hints.ai_family != AF_UNSPEC && hints.ai_family != AF_INET6) - { - freeaddrinfo_emulation(aihead); - gai_free(canon); - return EAI_FAMILY; - } - if (sptr->family == AF_INET6) - { - rc = gai_aistruct(&ainext, &hints, &in6addr, AF_INET6); - if (rc != 0) - { - freeaddrinfo_emulation(aihead); - gai_free(canon); - return rc; - } - } - continue; - } - - // Look up hostname. - hostent hent; - char hbuf[8192] = ""; - hostent* hptr = socket_ops::gethostbyname(sptr->host, - sptr->family, &hent, hbuf, sizeof(hbuf), hints.ai_flags, ec); - if (hptr == 0) - { - if (search_count == 2) - { - // Failure is OK if there are multiple searches. - continue; - } - freeaddrinfo_emulation(aihead); - gai_free(canon); - if (ec == asio::error::host_not_found) - return EAI_NONAME; - if (ec == asio::error::host_not_found_try_again) - return EAI_AGAIN; - if (ec == asio::error::no_recovery) - return EAI_FAIL; - if (ec == asio::error::no_data) - return EAI_NONAME; - return EAI_NONAME; - } - - // Check for address family mismatch if one was specified. - if (hints.ai_family != AF_UNSPEC && hints.ai_family != hptr->h_addrtype) - { - freeaddrinfo_emulation(aihead); - gai_free(canon); - socket_ops::freehostent(hptr); - return EAI_FAMILY; - } - - // Save canonical name first time. - if (host != 0 && host[0] != '\0' && hptr->h_name && hptr->h_name[0] - && (hints.ai_flags & AI_CANONNAME) && canon == 0) - { - std::size_t canon_len = strlen(hptr->h_name) + 1; - canon = gai_alloc(canon_len); - if (canon == 0) - { - freeaddrinfo_emulation(aihead); - socket_ops::freehostent(hptr); - return EAI_MEMORY; - } - gai_strcpy(canon, hptr->h_name, canon_len); - } - - // Create an addrinfo structure for each returned address. - for (char** ap = hptr->h_addr_list; *ap; ++ap) - { - rc = gai_aistruct(&ainext, &hints, *ap, hptr->h_addrtype); - if (rc != 0) - { - freeaddrinfo_emulation(aihead); - gai_free(canon); - socket_ops::freehostent(hptr); - return EAI_FAMILY; - } - } - - socket_ops::freehostent(hptr); - } - - // Check if we found anything. - if (aihead == 0) - { - gai_free(canon); - return EAI_NONAME; - } - - // Return canonical name in first entry. - if (host != 0 && host[0] != '\0' && (hints.ai_flags & AI_CANONNAME)) - { - if (canon) - { - aihead->ai_canonname = canon; - canon = 0; - } - else - { - std::size_t canonname_len = strlen(search[0].host) + 1; - aihead->ai_canonname = gai_alloc(canonname_len); - if (aihead->ai_canonname == 0) - { - freeaddrinfo_emulation(aihead); - return EAI_MEMORY; - } - gai_strcpy(aihead->ai_canonname, search[0].host, canonname_len); - } - } - gai_free(canon); - - // Process the service name. - if (service != 0 && service[0] != '\0') - { - rc = gai_serv(aihead, &hints, service); - if (rc != 0) - { - freeaddrinfo_emulation(aihead); - return rc; - } - } - - // Return result to caller. - *result = aihead; - return 0; -} - -inline asio::error_code getnameinfo_emulation( - const socket_addr_type* sa, std::size_t salen, char* host, - std::size_t hostlen, char* serv, std::size_t servlen, int flags, - asio::error_code& ec) -{ - using namespace std; - - const char* addr; - size_t addr_len; - unsigned short port; - switch (sa->sa_family) - { - case AF_INET: - if (salen != sizeof(sockaddr_in4_type)) - { - return ec = asio::error::invalid_argument; - } - addr = reinterpret_cast( - &reinterpret_cast(sa)->sin_addr); - addr_len = sizeof(in4_addr_type); - port = reinterpret_cast(sa)->sin_port; - break; - case AF_INET6: - if (salen != sizeof(sockaddr_in6_type)) - { - return ec = asio::error::invalid_argument; - } - addr = reinterpret_cast( - &reinterpret_cast(sa)->sin6_addr); - addr_len = sizeof(in6_addr_type); - port = reinterpret_cast(sa)->sin6_port; - break; - default: - return ec = asio::error::address_family_not_supported; - } - - if (host && hostlen > 0) - { - if (flags & NI_NUMERICHOST) - { - if (socket_ops::inet_ntop(sa->sa_family, addr, host, hostlen, 0, ec) == 0) - { - return ec; - } - } - else - { - hostent hent; - char hbuf[8192] = ""; - hostent* hptr = socket_ops::gethostbyaddr(addr, - static_cast(addr_len), sa->sa_family, - &hent, hbuf, sizeof(hbuf), ec); - if (hptr && hptr->h_name && hptr->h_name[0] != '\0') - { - if (flags & NI_NOFQDN) - { - char* dot = strchr(hptr->h_name, '.'); - if (dot) - { - *dot = 0; - } - } - gai_strcpy(host, hptr->h_name, hostlen); - socket_ops::freehostent(hptr); - } - else - { - socket_ops::freehostent(hptr); - if (flags & NI_NAMEREQD) - { - return ec = asio::error::host_not_found; - } - if (socket_ops::inet_ntop(sa->sa_family, - addr, host, hostlen, 0, ec) == 0) - { - return ec; - } - } - } - } - - if (serv && servlen > 0) - { - if (flags & NI_NUMERICSERV) - { - if (servlen < 6) - { - return ec = asio::error::no_buffer_space; - } -#if BOOST_WORKAROUND(BOOST_MSVC, >= 1400) && !defined(UNDER_CE) - sprintf_s(serv, servlen, "%u", ntohs(port)); -#else - sprintf(serv, "%u", ntohs(port)); -#endif - } - else - { -#if defined(BOOST_HAS_THREADS) && defined(BOOST_HAS_PTHREADS) - static ::pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; - ::pthread_mutex_lock(&mutex); -#endif // defined(BOOST_HAS_THREADS) && defined(BOOST_HAS_PTHREADS) - servent* sptr = ::getservbyport(port, (flags & NI_DGRAM) ? "udp" : 0); - if (sptr && sptr->s_name && sptr->s_name[0] != '\0') - { - gai_strcpy(serv, sptr->s_name, servlen); - } - else - { - if (servlen < 6) - { - return ec = asio::error::no_buffer_space; - } -#if BOOST_WORKAROUND(BOOST_MSVC, >= 1400) && !defined(UNDER_CE) - sprintf_s(serv, servlen, "%u", ntohs(port)); -#else - sprintf(serv, "%u", ntohs(port)); -#endif - } -#if defined(BOOST_HAS_THREADS) && defined(BOOST_HAS_PTHREADS) - ::pthread_mutex_unlock(&mutex); -#endif // defined(BOOST_HAS_THREADS) && defined(BOOST_HAS_PTHREADS) - } - } - - clear_error(ec); - return ec; -} - -#endif // defined(BOOST_WINDOWS) || defined(__CYGWIN__) - // || defined(__MACH__) && defined(__APPLE__) - -inline asio::error_code translate_addrinfo_error(int error) -{ - switch (error) - { - case 0: - return asio::error_code(); - case EAI_AGAIN: - return asio::error::host_not_found_try_again; - case EAI_BADFLAGS: - return asio::error::invalid_argument; - case EAI_FAIL: - return asio::error::no_recovery; - case EAI_FAMILY: - return asio::error::address_family_not_supported; - case EAI_MEMORY: - return asio::error::no_memory; - case EAI_NONAME: -#if defined(EAI_ADDRFAMILY) - case EAI_ADDRFAMILY: -#endif -#if defined(EAI_NODATA) && (EAI_NODATA != EAI_NONAME) - case EAI_NODATA: -#endif - return asio::error::host_not_found; - case EAI_SERVICE: - return asio::error::service_not_found; - case EAI_SOCKTYPE: - return asio::error::socket_type_not_supported; - default: // Possibly the non-portable EAI_SYSTEM. -#if defined(BOOST_WINDOWS) || defined(__CYGWIN__) - return asio::error_code( - WSAGetLastError(), asio::error::get_system_category()); -#else - return asio::error_code( - errno, asio::error::get_system_category()); -#endif - } -} - -inline asio::error_code getaddrinfo(const char* host, - const char* service, const addrinfo_type* hints, addrinfo_type** result, - asio::error_code& ec) -{ - clear_error(ec); -#if defined(BOOST_WINDOWS) || defined(__CYGWIN__) -# if defined(_WIN32_WINNT) && (_WIN32_WINNT >= 0x0501) || defined(UNDER_CE) - // Building for Windows XP, Windows Server 2003, or later. - int error = ::getaddrinfo(host, service, hints, result); - return ec = translate_addrinfo_error(error); -# else - // Building for Windows 2000 or earlier. - typedef int (WSAAPI *gai_t)(const char*, - const char*, const addrinfo_type*, addrinfo_type**); - if (HMODULE winsock_module = ::GetModuleHandleA("ws2_32")) - { - if (gai_t gai = (gai_t)::GetProcAddress(winsock_module, "getaddrinfo")) - { - int error = gai(host, service, hints, result); - return ec = translate_addrinfo_error(error); - } - } - int error = getaddrinfo_emulation(host, service, hints, result); - return ec = translate_addrinfo_error(error); -# endif -#elif defined(__MACH__) && defined(__APPLE__) - int error = getaddrinfo_emulation(host, service, hints, result); - return ec = translate_addrinfo_error(error); -#else - int error = ::getaddrinfo(host, service, hints, result); - return ec = translate_addrinfo_error(error); -#endif -} - -inline void freeaddrinfo(addrinfo_type* ai) -{ -#if defined(BOOST_WINDOWS) || defined(__CYGWIN__) -# if defined(_WIN32_WINNT) && (_WIN32_WINNT >= 0x0501) || defined(UNDER_CE) - // Building for Windows XP, Windows Server 2003, or later. - ::freeaddrinfo(ai); -# else - // Building for Windows 2000 or earlier. - typedef int (WSAAPI *fai_t)(addrinfo_type*); - if (HMODULE winsock_module = ::GetModuleHandleA("ws2_32")) - { - if (fai_t fai = (fai_t)::GetProcAddress(winsock_module, "freeaddrinfo")) - { - fai(ai); - return; - } - } - freeaddrinfo_emulation(ai); -# endif -#elif defined(__MACH__) && defined(__APPLE__) - freeaddrinfo_emulation(ai); -#else - ::freeaddrinfo(ai); -#endif -} - -inline asio::error_code getnameinfo(const socket_addr_type* addr, - std::size_t addrlen, char* host, std::size_t hostlen, - char* serv, std::size_t servlen, int flags, asio::error_code& ec) -{ -#if defined(BOOST_WINDOWS) || defined(__CYGWIN__) -# if defined(_WIN32_WINNT) && (_WIN32_WINNT >= 0x0501) || defined(UNDER_CE) - // Building for Windows XP, Windows Server 2003, or later. - clear_error(ec); - int error = ::getnameinfo(addr, static_cast(addrlen), - host, static_cast(hostlen), - serv, static_cast(servlen), flags); - return ec = translate_addrinfo_error(error); -# else - // Building for Windows 2000 or earlier. - typedef int (WSAAPI *gni_t)(const socket_addr_type*, - int, char*, DWORD, char*, DWORD, int); - if (HMODULE winsock_module = ::GetModuleHandleA("ws2_32")) - { - if (gni_t gni = (gni_t)::GetProcAddress(winsock_module, "getnameinfo")) - { - clear_error(ec); - int error = gni(addr, static_cast(addrlen), - host, static_cast(hostlen), - serv, static_cast(servlen), flags); - return ec = translate_addrinfo_error(error); - } - } - clear_error(ec); - return getnameinfo_emulation(addr, addrlen, - host, hostlen, serv, servlen, flags, ec); -# endif -#elif defined(__MACH__) && defined(__APPLE__) - using namespace std; // For memcpy. - sockaddr_storage_type tmp_addr; - memcpy(&tmp_addr, addr, addrlen); - tmp_addr.ss_len = addrlen; - addr = reinterpret_cast(&tmp_addr); - clear_error(ec); - return getnameinfo_emulation(addr, addrlen, - host, hostlen, serv, servlen, flags, ec); -#else - clear_error(ec); - int error = ::getnameinfo(addr, addrlen, host, hostlen, serv, servlen, flags); - return ec = translate_addrinfo_error(error); -#endif -} - -inline u_long_type network_to_host_long(u_long_type value) -{ - return ntohl(value); -} - -inline u_long_type host_to_network_long(u_long_type value) -{ - return htonl(value); -} - -inline u_short_type network_to_host_short(u_short_type value) -{ - return ntohs(value); -} - -inline u_short_type host_to_network_short(u_short_type value) -{ - return htons(value); -} - -} // namespace socket_ops -} // namespace detail -} // namespace asio - -#include "asio/detail/pop_options.hpp" - -#endif // ASIO_DETAIL_SOCKET_OPS_HPP diff --git a/libtorrent/include/asio/detail/socket_option.hpp b/libtorrent/include/asio/detail/socket_option.hpp deleted file mode 100644 index 27c898a49..000000000 --- a/libtorrent/include/asio/detail/socket_option.hpp +++ /dev/null @@ -1,309 +0,0 @@ -// -// socket_option.hpp -// ~~~~~~~~~~~~~~~~~ -// -// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -#ifndef ASIO_DETAIL_SOCKET_OPTION_HPP -#define ASIO_DETAIL_SOCKET_OPTION_HPP - -#if defined(_MSC_VER) && (_MSC_VER >= 1200) -# pragma once -#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) - -#include "asio/detail/push_options.hpp" - -#include "asio/detail/push_options.hpp" -#include -#include -#include -#include "asio/detail/pop_options.hpp" - -#include "asio/detail/socket_types.hpp" - -namespace asio { -namespace detail { -namespace socket_option { - -// Helper template for implementing boolean-based options. -template -class boolean -{ -public: - // Default constructor. - boolean() - : value_(0) - { - } - - // Construct with a specific option value. - explicit boolean(bool v) - : value_(v ? 1 : 0) - { - } - - // Set the current value of the boolean. - boolean& operator=(bool v) - { - value_ = v ? 1 : 0; - return *this; - } - - // Get the current value of the boolean. - bool value() const - { - return !!value_; - } - - // Convert to bool. - operator bool() const - { - return !!value_; - } - - // Test for false. - bool operator!() const - { - return !value_; - } - - // Get the level of the socket option. - template - int level(const Protocol&) const - { - return Level; - } - - // Get the name of the socket option. - template - int name(const Protocol&) const - { - return Name; - } - - // Get the address of the boolean data. - template - int* data(const Protocol&) - { - return &value_; - } - - // Get the address of the boolean data. - template - const int* data(const Protocol&) const - { - return &value_; - } - - // Get the size of the boolean data. - template - std::size_t size(const Protocol&) const - { - return sizeof(value_); - } - - // Set the size of the boolean data. - template - void resize(const Protocol&, std::size_t s) - { - // On some platforms (e.g. Windows Vista), the getsockopt function will - // return the size of a boolean socket option as one byte, even though a - // four byte integer was passed in. - switch (s) - { - case sizeof(char): - value_ = *reinterpret_cast(&value_) ? 1 : 0; - break; - case sizeof(value_): - break; - default: - throw std::length_error("boolean socket option resize"); - } - } - -private: - int value_; -}; - -// Helper template for implementing integer options. -template -class integer -{ -public: - // Default constructor. - integer() - : value_(0) - { - } - - // Construct with a specific option value. - explicit integer(int v) - : value_(v) - { - } - - // Set the value of the int option. - integer& operator=(int v) - { - value_ = v; - return *this; - } - - // Get the current value of the int option. - int value() const - { - return value_; - } - - // Get the level of the socket option. - template - int level(const Protocol&) const - { - return Level; - } - - // Get the name of the socket option. - template - int name(const Protocol&) const - { - return Name; - } - - // Get the address of the int data. - template - int* data(const Protocol&) - { - return &value_; - } - - // Get the address of the int data. - template - const int* data(const Protocol&) const - { - return &value_; - } - - // Get the size of the int data. - template - std::size_t size(const Protocol&) const - { - return sizeof(value_); - } - - // Set the size of the int data. - template - void resize(const Protocol&, std::size_t s) - { - if (s != sizeof(value_)) - throw std::length_error("integer socket option resize"); - } - -private: - int value_; -}; - -// Helper template for implementing linger options. -template -class linger -{ -public: - // Default constructor. - linger() - { - value_.l_onoff = 0; - value_.l_linger = 0; - } - - // Construct with specific option values. - linger(bool e, int t) - { - enabled(e); - timeout(t); - } - - // Set the value for whether linger is enabled. - void enabled(bool value) - { - value_.l_onoff = value ? 1 : 0; - } - - // Get the value for whether linger is enabled. - bool enabled() const - { - return value_.l_onoff != 0; - } - - // Set the value for the linger timeout. - void timeout(int value) - { -#if defined(WIN32) - value_.l_linger = static_cast(value); -#else - value_.l_linger = value; -#endif - } - - // Get the value for the linger timeout. - int timeout() const - { - return static_cast(value_.l_linger); - } - - // Get the level of the socket option. - template - int level(const Protocol&) const - { - return Level; - } - - // Get the name of the socket option. - template - int name(const Protocol&) const - { - return Name; - } - - // Get the address of the linger data. - template - ::linger* data(const Protocol&) - { - return &value_; - } - - // Get the address of the linger data. - template - const ::linger* data(const Protocol&) const - { - return &value_; - } - - // Get the size of the linger data. - template - std::size_t size(const Protocol&) const - { - return sizeof(value_); - } - - // Set the size of the int data. - template - void resize(const Protocol&, std::size_t s) - { - if (s != sizeof(value_)) - throw std::length_error("linger socket option resize"); - } - -private: - ::linger value_; -}; - -} // namespace socket_option -} // namespace detail -} // namespace asio - -#include "asio/detail/pop_options.hpp" - -#endif // ASIO_DETAIL_SOCKET_OPTION_HPP diff --git a/libtorrent/include/asio/detail/socket_select_interrupter.hpp b/libtorrent/include/asio/detail/socket_select_interrupter.hpp deleted file mode 100644 index f978f7c67..000000000 --- a/libtorrent/include/asio/detail/socket_select_interrupter.hpp +++ /dev/null @@ -1,187 +0,0 @@ -// -// socket_select_interrupter.hpp -// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -// -// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -#ifndef ASIO_DETAIL_SOCKET_SELECT_INTERRUPTER_HPP -#define ASIO_DETAIL_SOCKET_SELECT_INTERRUPTER_HPP - -#if defined(_MSC_VER) && (_MSC_VER >= 1200) -# pragma once -#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) - -#include "asio/detail/push_options.hpp" - -#include "asio/detail/push_options.hpp" -#include -#include -#include "asio/detail/pop_options.hpp" - -#include "asio/error.hpp" -#include "asio/system_error.hpp" -#include "asio/detail/socket_holder.hpp" -#include "asio/detail/socket_ops.hpp" -#include "asio/detail/socket_types.hpp" - -namespace asio { -namespace detail { - -class socket_select_interrupter -{ -public: - // Constructor. - socket_select_interrupter() - { - asio::error_code ec; - socket_holder acceptor(socket_ops::socket( - AF_INET, SOCK_STREAM, IPPROTO_TCP, ec)); - if (acceptor.get() == invalid_socket) - { - asio::system_error e(ec, "socket_select_interrupter"); - boost::throw_exception(e); - } - - int opt = 1; - socket_ops::setsockopt(acceptor.get(), - SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt), ec); - - using namespace std; // For memset. - sockaddr_in4_type addr; - std::size_t addr_len = sizeof(addr); - memset(&addr, 0, sizeof(addr)); - addr.sin_family = AF_INET; - addr.sin_addr.s_addr = inet_addr("127.0.0.1"); - addr.sin_port = 0; - if (socket_ops::bind(acceptor.get(), (const socket_addr_type*)&addr, - addr_len, ec) == socket_error_retval) - { - asio::system_error e(ec, "socket_select_interrupter"); - boost::throw_exception(e); - } - - if (socket_ops::getsockname(acceptor.get(), (socket_addr_type*)&addr, - &addr_len, ec) == socket_error_retval) - { - asio::system_error e(ec, "socket_select_interrupter"); - boost::throw_exception(e); - } - - if (socket_ops::listen(acceptor.get(), - SOMAXCONN, ec) == socket_error_retval) - { - asio::system_error e(ec, "socket_select_interrupter"); - boost::throw_exception(e); - } - - socket_holder client(socket_ops::socket( - AF_INET, SOCK_STREAM, IPPROTO_TCP, ec)); - if (client.get() == invalid_socket) - { - asio::system_error e(ec, "socket_select_interrupter"); - boost::throw_exception(e); - } - - if (socket_ops::connect(client.get(), (const socket_addr_type*)&addr, - addr_len, ec) == socket_error_retval) - { - asio::system_error e(ec, "socket_select_interrupter"); - boost::throw_exception(e); - } - - socket_holder server(socket_ops::accept(acceptor.get(), 0, 0, ec)); - if (server.get() == invalid_socket) - { - asio::system_error e(ec, "socket_select_interrupter"); - boost::throw_exception(e); - } - - ioctl_arg_type non_blocking = 1; - if (socket_ops::ioctl(client.get(), FIONBIO, &non_blocking, ec)) - { - asio::system_error e(ec, "socket_select_interrupter"); - boost::throw_exception(e); - } - - opt = 1; - socket_ops::setsockopt(client.get(), - IPPROTO_TCP, TCP_NODELAY, &opt, sizeof(opt), ec); - - non_blocking = 1; - if (socket_ops::ioctl(server.get(), FIONBIO, &non_blocking, ec)) - { - asio::system_error e(ec, "socket_select_interrupter"); - boost::throw_exception(e); - } - - opt = 1; - socket_ops::setsockopt(server.get(), - IPPROTO_TCP, TCP_NODELAY, &opt, sizeof(opt), ec); - - read_descriptor_ = server.release(); - write_descriptor_ = client.release(); - } - - // Destructor. - ~socket_select_interrupter() - { - asio::error_code ec; - if (read_descriptor_ != invalid_socket) - socket_ops::close(read_descriptor_, ec); - if (write_descriptor_ != invalid_socket) - socket_ops::close(write_descriptor_, ec); - } - - // Interrupt the select call. - void interrupt() - { - char byte = 0; - socket_ops::buf b; - socket_ops::init_buf(b, &byte, 1); - asio::error_code ec; - socket_ops::send(write_descriptor_, &b, 1, 0, ec); - } - - // Reset the select interrupt. Returns true if the call was interrupted. - bool reset() - { - char data[1024]; - socket_ops::buf b; - socket_ops::init_buf(b, data, sizeof(data)); - asio::error_code ec; - int bytes_read = socket_ops::recv(read_descriptor_, &b, 1, 0, ec); - bool was_interrupted = (bytes_read > 0); - while (bytes_read == sizeof(data)) - bytes_read = socket_ops::recv(read_descriptor_, &b, 1, 0, ec); - return was_interrupted; - } - - // Get the read descriptor to be passed to select. - socket_type read_descriptor() const - { - return read_descriptor_; - } - -private: - // The read end of a connection used to interrupt the select call. This file - // descriptor is passed to select such that when it is time to stop, a single - // byte will be written on the other end of the connection and this - // descriptor will become readable. - socket_type read_descriptor_; - - // The write end of a connection used to interrupt the select call. A single - // byte may be written to this to wake up the select which is waiting for the - // other end to become readable. - socket_type write_descriptor_; -}; - -} // namespace detail -} // namespace asio - -#include "asio/detail/pop_options.hpp" - -#endif // ASIO_DETAIL_SOCKET_SELECT_INTERRUPTER_HPP diff --git a/libtorrent/include/asio/detail/socket_types.hpp b/libtorrent/include/asio/detail/socket_types.hpp deleted file mode 100644 index b2acb6931..000000000 --- a/libtorrent/include/asio/detail/socket_types.hpp +++ /dev/null @@ -1,201 +0,0 @@ -// -// socket_types.hpp -// ~~~~~~~~~~~~~~~~ -// -// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -#ifndef ASIO_DETAIL_SOCKET_TYPES_HPP -#define ASIO_DETAIL_SOCKET_TYPES_HPP - -#if defined(_MSC_VER) && (_MSC_VER >= 1200) -# pragma once -#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) - -#include "asio/detail/push_options.hpp" - -#include "asio/detail/push_options.hpp" -#include -#include "asio/detail/pop_options.hpp" - -#include "asio/detail/push_options.hpp" -#if defined(BOOST_WINDOWS) || defined(__CYGWIN__) -# if defined(_WINSOCKAPI_) && !defined(_WINSOCK2API_) -# error WinSock.h has already been included -# endif // defined(_WINSOCKAPI_) && !defined(_WINSOCK2API_) -# if !defined(_WIN32_WINNT) && !defined(_WIN32_WINDOWS) -# if defined(_MSC_VER) || defined(__BORLANDC__) -# pragma message("Please define _WIN32_WINNT or _WIN32_WINDOWS appropriately") -# pragma message("Assuming _WIN32_WINNT=0x0501 (i.e. Windows XP target)") -# else // defined(_MSC_VER) || defined(__BORLANDC__) -# warning Please define _WIN32_WINNT or _WIN32_WINDOWS appropriately -# warning Assuming _WIN32_WINNT=0x0501 (i.e. Windows XP target) -# endif // defined(_MSC_VER) || defined(__BORLANDC__) -# define _WIN32_WINNT 0x0501 -# endif // !defined(_WIN32_WINNT) && !defined(_WIN32_WINDOWS) -# if defined(_MSC_VER) -# if defined(_WIN32) && !defined(WIN32) -# if !defined(_WINSOCK2API_) -# define WIN32 // Needed for correct types in winsock2.h -# else // !defined(_WINSOCK2API_) -# error Please define the macro WIN32 in your compiler options -# endif // !defined(_WINSOCK2API_) -# endif // defined(_WIN32) && !defined(WIN32) -# endif // defined(_MSC_VER) -# if defined(__BORLANDC__) -# include // Needed for __errno -# if defined(__WIN32__) && !defined(WIN32) -# if !defined(_WINSOCK2API_) -# define WIN32 // Needed for correct types in winsock2.h -# else // !defined(_WINSOCK2API_) -# error Please define the macro WIN32 in your compiler options -# endif // !defined(_WINSOCK2API_) -# endif // defined(__WIN32__) && !defined(WIN32) -# if !defined(_WSPIAPI_H_) -# define _WSPIAPI_H_ -# define ASIO_WSPIAPI_H_DEFINED -# endif // !defined(_WSPIAPI_H_) -# endif // defined(__BORLANDC__) -# if !defined(ASIO_NO_WIN32_LEAN_AND_MEAN) -# if !defined(WIN32_LEAN_AND_MEAN) -# define WIN32_LEAN_AND_MEAN -# endif // !defined(WIN32_LEAN_AND_MEAN) -# endif // !defined(ASIO_NO_WIN32_LEAN_AND_MEAN) -# if defined(__CYGWIN__) -# if !defined(__USE_W32_SOCKETS) -# error You must add -D__USE_W32_SOCKETS to your compiler options. -# endif // !defined(__USE_W32_SOCKETS) -# if !defined(NOMINMAX) -# define NOMINMAX 1 -# endif // !defined(NOMINMAX) -# endif // defined(__CYGWIN__) -# include -# include -# include -# if defined(ASIO_WSPIAPI_H_DEFINED) -# undef _WSPIAPI_H_ -# undef ASIO_WSPIAPI_H_DEFINED -# endif // defined(ASIO_WSPIAPI_H_DEFINED) -# if !defined(ASIO_NO_DEFAULT_LINKED_LIBS) -# if defined(UNDER_CE) -# pragma comment(lib, "ws2.lib") -# elif defined(_MSC_VER) || defined(__BORLANDC__) -# pragma comment(lib, "ws2_32.lib") -# pragma comment(lib, "mswsock.lib") -# endif // defined(_MSC_VER) || defined(__BORLANDC__) -# endif // !defined(ASIO_NO_DEFAULT_LINKED_LIBS) -# include "asio/detail/old_win_sdk_compat.hpp" -#else -# include -# include -# include -# if defined(__hpux) && !defined(__HP_aCC) -# include -# else -# include -# endif -# include -# include -# include -# include -# include -# include -# include -# include -# include -# if defined(__sun) -# include -# include -# endif -#endif -#include "asio/detail/pop_options.hpp" - -namespace asio { -namespace detail { - -#if defined(BOOST_WINDOWS) || defined(__CYGWIN__) -typedef SOCKET socket_type; -const SOCKET invalid_socket = INVALID_SOCKET; -const int socket_error_retval = SOCKET_ERROR; -const int max_addr_v4_str_len = 256; -const int max_addr_v6_str_len = 256; -typedef sockaddr socket_addr_type; -typedef in_addr in4_addr_type; -typedef ip_mreq in4_mreq_type; -typedef sockaddr_in sockaddr_in4_type; -# if defined(ASIO_HAS_OLD_WIN_SDK) -typedef in6_addr_emulation in6_addr_type; -typedef ipv6_mreq_emulation in6_mreq_type; -typedef sockaddr_in6_emulation sockaddr_in6_type; -typedef sockaddr_storage_emulation sockaddr_storage_type; -typedef addrinfo_emulation addrinfo_type; -# else -typedef in6_addr in6_addr_type; -typedef ipv6_mreq in6_mreq_type; -typedef sockaddr_in6 sockaddr_in6_type; -typedef sockaddr_storage sockaddr_storage_type; -typedef addrinfo addrinfo_type; -# endif -typedef unsigned long ioctl_arg_type; -typedef u_long u_long_type; -typedef u_short u_short_type; -const int shutdown_receive = SD_RECEIVE; -const int shutdown_send = SD_SEND; -const int shutdown_both = SD_BOTH; -const int message_peek = MSG_PEEK; -const int message_out_of_band = MSG_OOB; -const int message_do_not_route = MSG_DONTROUTE; -# if defined (_WIN32_WINNT) -const int max_iov_len = 64; -# else -const int max_iov_len = 16; -# endif -#else -typedef int socket_type; -const int invalid_socket = -1; -const int socket_error_retval = -1; -const int max_addr_v4_str_len = INET_ADDRSTRLEN; -const int max_addr_v6_str_len = INET6_ADDRSTRLEN + 1 + IF_NAMESIZE; -typedef sockaddr socket_addr_type; -typedef in_addr in4_addr_type; -# if defined(__hpux) -// HP-UX doesn't provide ip_mreq when _XOPEN_SOURCE_EXTENDED is defined. -struct in4_mreq_type -{ - struct in_addr imr_multiaddr; - struct in_addr imr_interface; -}; -# else -typedef ip_mreq in4_mreq_type; -# endif -typedef sockaddr_in sockaddr_in4_type; -typedef in6_addr in6_addr_type; -typedef ipv6_mreq in6_mreq_type; -typedef sockaddr_in6 sockaddr_in6_type; -typedef sockaddr_storage sockaddr_storage_type; -typedef sockaddr_un sockaddr_un_type; -typedef addrinfo addrinfo_type; -typedef int ioctl_arg_type; -typedef uint32_t u_long_type; -typedef uint16_t u_short_type; -const int shutdown_receive = SHUT_RD; -const int shutdown_send = SHUT_WR; -const int shutdown_both = SHUT_RDWR; -const int message_peek = MSG_PEEK; -const int message_out_of_band = MSG_OOB; -const int message_do_not_route = MSG_DONTROUTE; -const int max_iov_len = IOV_MAX; -#endif -const int custom_socket_option_level = 0xA5100000; -const int enable_connection_aborted_option = 1; -const int always_fail_option = 2; - -} // namespace detail -} // namespace asio - -#include "asio/detail/pop_options.hpp" - -#endif // ASIO_DETAIL_SOCKET_TYPES_HPP diff --git a/libtorrent/include/asio/detail/strand_service.hpp b/libtorrent/include/asio/detail/strand_service.hpp deleted file mode 100644 index 6deb040f6..000000000 --- a/libtorrent/include/asio/detail/strand_service.hpp +++ /dev/null @@ -1,530 +0,0 @@ -// -// strand_service.hpp -// ~~~~~~~~~~~~~~~~~~ -// -// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -#ifndef ASIO_DETAIL_STRAND_SERVICE_HPP -#define ASIO_DETAIL_STRAND_SERVICE_HPP - -#if defined(_MSC_VER) && (_MSC_VER >= 1200) -# pragma once -#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) - -#include "asio/detail/push_options.hpp" - -#include "asio/detail/push_options.hpp" -#include -#include -#include -#include -#include "asio/detail/pop_options.hpp" - -#include "asio/io_service.hpp" -#include "asio/detail/bind_handler.hpp" -#include "asio/detail/call_stack.hpp" -#include "asio/detail/handler_alloc_helpers.hpp" -#include "asio/detail/handler_invoke_helpers.hpp" -#include "asio/detail/mutex.hpp" -#include "asio/detail/noncopyable.hpp" -#include "asio/detail/service_base.hpp" - -namespace asio { -namespace detail { - -// Default service implementation for a strand. -class strand_service - : public asio::detail::service_base -{ -public: - class handler_base; - class invoke_current_handler; - class post_next_waiter_on_exit; - - // The underlying implementation of a strand. - class strand_impl - { -#if defined (__BORLANDC__) - public: -#else - private: -#endif - void add_ref() - { - ++ref_count_; - } - - void release() - { - if (--ref_count_ == 0) - delete this; - } - - private: - // Only this service will have access to the internal values. - friend class strand_service; - friend class post_next_waiter_on_exit; - friend class invoke_current_handler; - - strand_impl(strand_service& owner) - : owner_(owner), - current_handler_(0), - first_waiter_(0), - last_waiter_(0), - ref_count_(0) - { - // Insert implementation into linked list of all implementations. - asio::detail::mutex::scoped_lock lock(owner_.mutex_); - next_ = owner_.impl_list_; - prev_ = 0; - if (owner_.impl_list_) - owner_.impl_list_->prev_ = this; - owner_.impl_list_ = this; - } - - ~strand_impl() - { - // Remove implementation from linked list of all implementations. - asio::detail::mutex::scoped_lock lock(owner_.mutex_); - if (owner_.impl_list_ == this) - owner_.impl_list_ = next_; - if (prev_) - prev_->next_ = next_; - if (next_) - next_->prev_= prev_; - next_ = 0; - prev_ = 0; - lock.unlock(); - - if (current_handler_) - { - current_handler_->destroy(); - } - - while (first_waiter_) - { - handler_base* next = first_waiter_->next_; - first_waiter_->destroy(); - first_waiter_ = next; - } - } - - // Mutex to protect access to internal data. - asio::detail::mutex mutex_; - - // The service that owns this implementation. - strand_service& owner_; - - // The handler that is ready to execute. If this pointer is non-null then it - // indicates that a handler holds the lock. - handler_base* current_handler_; - - // The start of the list of waiting handlers for the strand. - handler_base* first_waiter_; - - // The end of the list of waiting handlers for the strand. - handler_base* last_waiter_; - - // Storage for posted handlers. - typedef boost::aligned_storage<128> handler_storage_type; -#if defined(__BORLANDC__) - boost::aligned_storage<128> handler_storage_; -#else - handler_storage_type handler_storage_; -#endif - - // Pointers to adjacent socket implementations in linked list. - strand_impl* next_; - strand_impl* prev_; - - // The reference count on the strand implementation. - boost::detail::atomic_count ref_count_; - -#if !defined(__BORLANDC__) - friend void intrusive_ptr_add_ref(strand_impl* p) - { - p->add_ref(); - } - - friend void intrusive_ptr_release(strand_impl* p) - { - p->release(); - } -#endif - }; - - friend class strand_impl; - - typedef boost::intrusive_ptr implementation_type; - - // Base class for all handler types. - class handler_base - { - public: - typedef void (*invoke_func_type)(handler_base*, - strand_service&, implementation_type&); - typedef void (*destroy_func_type)(handler_base*); - - handler_base(invoke_func_type invoke_func, destroy_func_type destroy_func) - : next_(0), - invoke_func_(invoke_func), - destroy_func_(destroy_func) - { - } - - void invoke(strand_service& service_impl, implementation_type& impl) - { - invoke_func_(this, service_impl, impl); - } - - void destroy() - { - destroy_func_(this); - } - - protected: - ~handler_base() - { - } - - private: - friend class strand_service; - friend class strand_impl; - friend class post_next_waiter_on_exit; - handler_base* next_; - invoke_func_type invoke_func_; - destroy_func_type destroy_func_; - }; - - // Helper class to allow handlers to be dispatched. - class invoke_current_handler - { - public: - invoke_current_handler(strand_service& service_impl, - const implementation_type& impl) - : service_impl_(service_impl), - impl_(impl) - { - } - - void operator()() - { - impl_->current_handler_->invoke(service_impl_, impl_); - } - - friend void* asio_handler_allocate(std::size_t size, - invoke_current_handler* this_handler) - { - return this_handler->do_handler_allocate(size); - } - - friend void asio_handler_deallocate(void*, std::size_t, - invoke_current_handler*) - { - } - - void* do_handler_allocate(std::size_t size) - { -#if defined(__BORLANDC__) - BOOST_ASSERT(size <= boost::aligned_storage<128>::size); -#else - BOOST_ASSERT(size <= strand_impl::handler_storage_type::size); -#endif - (void)size; - return impl_->handler_storage_.address(); - } - - // The asio_handler_invoke hook is not defined here since the default one - // provides the correct behaviour, and including it here breaks MSVC 7.1 - // in some situations. - - private: - strand_service& service_impl_; - implementation_type impl_; - }; - - // Helper class to automatically enqueue next waiter on block exit. - class post_next_waiter_on_exit - { - public: - post_next_waiter_on_exit(strand_service& service_impl, - implementation_type& impl) - : service_impl_(service_impl), - impl_(impl), - cancelled_(false) - { - } - - ~post_next_waiter_on_exit() - { - if (!cancelled_) - { - asio::detail::mutex::scoped_lock lock(impl_->mutex_); - impl_->current_handler_ = impl_->first_waiter_; - if (impl_->current_handler_) - { - impl_->first_waiter_ = impl_->first_waiter_->next_; - if (impl_->first_waiter_ == 0) - impl_->last_waiter_ = 0; - lock.unlock(); - service_impl_.get_io_service().post( - invoke_current_handler(service_impl_, impl_)); - } - } - } - - void cancel() - { - cancelled_ = true; - } - - private: - strand_service& service_impl_; - implementation_type& impl_; - bool cancelled_; - }; - - // Class template for a waiter. - template - class handler_wrapper - : public handler_base - { - public: - handler_wrapper(Handler handler) - : handler_base(&handler_wrapper::do_invoke, - &handler_wrapper::do_destroy), - handler_(handler) - { - } - - static void do_invoke(handler_base* base, - strand_service& service_impl, implementation_type& impl) - { - // Take ownership of the handler object. - typedef handler_wrapper this_type; - this_type* h(static_cast(base)); - typedef handler_alloc_traits alloc_traits; - handler_ptr ptr(h->handler_, h); - - post_next_waiter_on_exit p1(service_impl, impl); - - // Make a copy of the handler so that the memory can be deallocated before - // the upcall is made. - Handler handler(h->handler_); - - // A handler object must still be valid when the next waiter is posted - // since destroying the last handler might cause the strand object to be - // destroyed. Therefore we create a second post_next_waiter_on_exit object - // that will be destroyed before the handler object. - p1.cancel(); - post_next_waiter_on_exit p2(service_impl, impl); - - // Free the memory associated with the handler. - ptr.reset(); - - // Indicate that this strand is executing on the current thread. - call_stack::context ctx(impl.get()); - - // Make the upcall. - asio_handler_invoke_helpers::invoke(handler, &handler); - } - - static void do_destroy(handler_base* base) - { - // Take ownership of the handler object. - typedef handler_wrapper this_type; - this_type* h(static_cast(base)); - typedef handler_alloc_traits alloc_traits; - handler_ptr ptr(h->handler_, h); - - // A sub-object of the handler may be the true owner of the memory - // associated with the handler. Consequently, a local copy of the handler - // is required to ensure that any owning sub-object remains valid until - // after we have deallocated the memory here. - Handler handler(h->handler_); - (void)handler; - - // Free the memory associated with the handler. - ptr.reset(); - } - - private: - Handler handler_; - }; - - // Construct a new strand service for the specified io_service. - explicit strand_service(asio::io_service& io_service) - : asio::detail::service_base(io_service), - mutex_(), - impl_list_(0) - { - } - - // Destroy all user-defined handler objects owned by the service. - void shutdown_service() - { - // Construct a list of all handlers to be destroyed. - asio::detail::mutex::scoped_lock lock(mutex_); - strand_impl* impl = impl_list_; - handler_base* first_handler = 0; - while (impl) - { - if (impl->current_handler_) - { - impl->current_handler_->next_ = first_handler; - first_handler = impl->current_handler_; - impl->current_handler_ = 0; - } - if (impl->first_waiter_) - { - impl->last_waiter_->next_ = first_handler; - first_handler = impl->first_waiter_; - impl->first_waiter_ = 0; - impl->last_waiter_ = 0; - } - impl = impl->next_; - } - - // Destroy all handlers without holding the lock. - lock.unlock(); - while (first_handler) - { - handler_base* next = first_handler->next_; - first_handler->destroy(); - first_handler = next; - } - } - - // Construct a new strand implementation. - void construct(implementation_type& impl) - { - impl = implementation_type(new strand_impl(*this)); - } - - // Destroy a strand implementation. - void destroy(implementation_type& impl) - { - implementation_type().swap(impl); - } - - // Request the io_service to invoke the given handler. - template - void dispatch(implementation_type& impl, Handler handler) - { - if (call_stack::contains(impl.get())) - { - asio_handler_invoke_helpers::invoke(handler, &handler); - } - else - { - // Allocate and construct an object to wrap the handler. - typedef handler_wrapper value_type; - typedef handler_alloc_traits alloc_traits; - raw_handler_ptr raw_ptr(handler); - handler_ptr ptr(raw_ptr, handler); - - asio::detail::mutex::scoped_lock lock(impl->mutex_); - - if (impl->current_handler_ == 0) - { - // This handler now has the lock, so can be dispatched immediately. - impl->current_handler_ = ptr.release(); - lock.unlock(); - this->get_io_service().dispatch(invoke_current_handler(*this, impl)); - } - else - { - // Another handler already holds the lock, so this handler must join - // the list of waiters. The handler will be posted automatically when - // its turn comes. - if (impl->last_waiter_) - { - impl->last_waiter_->next_ = ptr.get(); - impl->last_waiter_ = impl->last_waiter_->next_; - } - else - { - impl->first_waiter_ = ptr.get(); - impl->last_waiter_ = ptr.get(); - } - ptr.release(); - } - } - } - - // Request the io_service to invoke the given handler and return immediately. - template - void post(implementation_type& impl, Handler handler) - { - // Allocate and construct an object to wrap the handler. - typedef handler_wrapper value_type; - typedef handler_alloc_traits alloc_traits; - raw_handler_ptr raw_ptr(handler); - handler_ptr ptr(raw_ptr, handler); - - asio::detail::mutex::scoped_lock lock(impl->mutex_); - - if (impl->current_handler_ == 0) - { - // This handler now has the lock, so can be dispatched immediately. - impl->current_handler_ = ptr.release(); - lock.unlock(); - this->get_io_service().post(invoke_current_handler(*this, impl)); - } - else - { - // Another handler already holds the lock, so this handler must join the - // list of waiters. The handler will be posted automatically when its turn - // comes. - if (impl->last_waiter_) - { - impl->last_waiter_->next_ = ptr.get(); - impl->last_waiter_ = impl->last_waiter_->next_; - } - else - { - impl->first_waiter_ = ptr.get(); - impl->last_waiter_ = ptr.get(); - } - ptr.release(); - } - } - -private: - // Mutex to protect access to the linked list of implementations. - asio::detail::mutex mutex_; - - // The head of a linked list of all implementations. - strand_impl* impl_list_; -}; - -} // namespace detail -} // namespace asio - -#if defined(__BORLANDC__) - -namespace boost { - -inline void intrusive_ptr_add_ref( - asio::detail::strand_service::strand_impl* p) -{ - p->add_ref(); -} - -inline void intrusive_ptr_release( - asio::detail::strand_service::strand_impl* p) -{ - p->release(); -} - -} // namespace boost - -#endif // defined(__BORLANDC__) - -#include "asio/detail/pop_options.hpp" - -#endif // ASIO_DETAIL_STRAND_SERVICE_HPP diff --git a/libtorrent/include/asio/detail/task_io_service.hpp b/libtorrent/include/asio/detail/task_io_service.hpp deleted file mode 100644 index beba1f251..000000000 --- a/libtorrent/include/asio/detail/task_io_service.hpp +++ /dev/null @@ -1,425 +0,0 @@ -// -// task_io_service.hpp -// ~~~~~~~~~~~~~~~~~~~ -// -// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -#ifndef ASIO_DETAIL_TASK_IO_SERVICE_HPP -#define ASIO_DETAIL_TASK_IO_SERVICE_HPP - -#if defined(_MSC_VER) && (_MSC_VER >= 1200) -# pragma once -#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) - -#if defined(ASIO_ENABLE_TWO_LOCK_QUEUE) -#include "asio/detail/task_io_service_2lock.hpp" -#else // defined(ASIO_ENABLE_TWO_LOCK_QUEUE) - -#include "asio/detail/push_options.hpp" - -#include "asio/error_code.hpp" -#include "asio/io_service.hpp" -#include "asio/detail/call_stack.hpp" -#include "asio/detail/event.hpp" -#include "asio/detail/handler_alloc_helpers.hpp" -#include "asio/detail/handler_invoke_helpers.hpp" -#include "asio/detail/handler_queue.hpp" -#include "asio/detail/mutex.hpp" -#include "asio/detail/service_base.hpp" -#include "asio/detail/task_io_service_fwd.hpp" - -namespace asio { -namespace detail { - -template -class task_io_service - : public asio::detail::service_base > -{ -public: - // Constructor. - task_io_service(asio::io_service& io_service) - : asio::detail::service_base >(io_service), - mutex_(), - task_(use_service(io_service)), - task_interrupted_(true), - outstanding_work_(0), - stopped_(false), - shutdown_(false), - first_idle_thread_(0) - { - handler_queue_.push(&task_handler_); - } - - void init(size_t /*concurrency_hint*/) - { - } - - // Destroy all user-defined handler objects owned by the service. - void shutdown_service() - { - asio::detail::mutex::scoped_lock lock(mutex_); - shutdown_ = true; - lock.unlock(); - - // Destroy handler objects. - while (!handler_queue_.empty()) - { - handler_queue::handler* h = handler_queue_.front(); - handler_queue_.pop(); - if (h != &task_handler_) - h->destroy(); - } - - // Reset handler queue to initial state. - handler_queue_.push(&task_handler_); - } - - // Run the event loop until interrupted or no more work. - size_t run(asio::error_code& ec) - { - typename call_stack::context ctx(this); - - idle_thread_info this_idle_thread; - this_idle_thread.next = 0; - - asio::detail::mutex::scoped_lock lock(mutex_); - - size_t n = 0; - while (do_one(lock, &this_idle_thread, ec)) - if (n != (std::numeric_limits::max)()) - ++n; - return n; - } - - // Run until interrupted or one operation is performed. - size_t run_one(asio::error_code& ec) - { - typename call_stack::context ctx(this); - - idle_thread_info this_idle_thread; - this_idle_thread.next = 0; - - asio::detail::mutex::scoped_lock lock(mutex_); - - return do_one(lock, &this_idle_thread, ec); - } - - // Poll for operations without blocking. - size_t poll(asio::error_code& ec) - { - typename call_stack::context ctx(this); - - asio::detail::mutex::scoped_lock lock(mutex_); - - size_t n = 0; - while (do_one(lock, 0, ec)) - if (n != (std::numeric_limits::max)()) - ++n; - return n; - } - - // Poll for one operation without blocking. - size_t poll_one(asio::error_code& ec) - { - typename call_stack::context ctx(this); - - asio::detail::mutex::scoped_lock lock(mutex_); - - return do_one(lock, 0, ec); - } - - // Interrupt the event processing loop. - void stop() - { - asio::detail::mutex::scoped_lock lock(mutex_); - stop_all_threads(lock); - } - - // Reset in preparation for a subsequent run invocation. - void reset() - { - asio::detail::mutex::scoped_lock lock(mutex_); - stopped_ = false; - } - - // Notify that some work has started. - void work_started() - { - asio::detail::mutex::scoped_lock lock(mutex_); - ++outstanding_work_; - } - - // Notify that some work has finished. - void work_finished() - { - asio::detail::mutex::scoped_lock lock(mutex_); - if (--outstanding_work_ == 0) - stop_all_threads(lock); - } - - // Request invocation of the given handler. - template - void dispatch(Handler handler) - { - if (call_stack::contains(this)) - asio_handler_invoke_helpers::invoke(handler, &handler); - else - post(handler); - } - - // Request invocation of the given handler and return immediately. - template - void post(Handler handler) - { - // Allocate and construct an operation to wrap the handler. - handler_queue::scoped_ptr ptr(handler_queue::wrap(handler)); - - asio::detail::mutex::scoped_lock lock(mutex_); - - // If the service has been shut down we silently discard the handler. - if (shutdown_) - return; - - // Add the handler to the end of the queue. - handler_queue_.push(ptr.get()); - ptr.release(); - - // An undelivered handler is treated as unfinished work. - ++outstanding_work_; - - // Wake up a thread to execute the handler. - if (!interrupt_one_idle_thread(lock)) - { - if (!task_interrupted_) - { - task_interrupted_ = true; - task_.interrupt(); - } - } - } - -private: - struct idle_thread_info; - - size_t do_one(asio::detail::mutex::scoped_lock& lock, - idle_thread_info* this_idle_thread, asio::error_code& ec) - { - if (outstanding_work_ == 0 && !stopped_) - { - stop_all_threads(lock); - ec = asio::error_code(); - return 0; - } - - bool polling = !this_idle_thread; - bool task_has_run = false; - while (!stopped_) - { - if (!handler_queue_.empty()) - { - // Prepare to execute first handler from queue. - handler_queue::handler* h = handler_queue_.front(); - handler_queue_.pop(); - - if (h == &task_handler_) - { - bool more_handlers = (!handler_queue_.empty()); - task_interrupted_ = more_handlers || polling; - - // If the task has already run and we're polling then we're done. - if (task_has_run && polling) - { - task_interrupted_ = true; - handler_queue_.push(&task_handler_); - ec = asio::error_code(); - return 0; - } - task_has_run = true; - - lock.unlock(); - task_cleanup c(lock, *this); - - // Run the task. May throw an exception. Only block if the handler - // queue is empty and we have an idle_thread_info object, otherwise - // we want to return as soon as possible. - task_.run(!more_handlers && !polling); - } - else - { - lock.unlock(); - handler_cleanup c(lock, *this); - - // Invoke the handler. May throw an exception. - h->invoke(); // invoke() deletes the handler object - - ec = asio::error_code(); - return 1; - } - } - else if (this_idle_thread) - { - // Nothing to run right now, so just wait for work to do. - this_idle_thread->next = first_idle_thread_; - first_idle_thread_ = this_idle_thread; - this_idle_thread->wakeup_event.clear(lock); - this_idle_thread->wakeup_event.wait(lock); - } - else - { - ec = asio::error_code(); - return 0; - } - } - - ec = asio::error_code(); - return 0; - } - - // Stop the task and all idle threads. - void stop_all_threads( - asio::detail::mutex::scoped_lock& lock) - { - stopped_ = true; - interrupt_all_idle_threads(lock); - if (!task_interrupted_) - { - task_interrupted_ = true; - task_.interrupt(); - } - } - - // Interrupt a single idle thread. Returns true if a thread was interrupted, - // false if no running thread could be found to interrupt. - bool interrupt_one_idle_thread( - asio::detail::mutex::scoped_lock& lock) - { - if (first_idle_thread_) - { - idle_thread_info* idle_thread = first_idle_thread_; - first_idle_thread_ = idle_thread->next; - idle_thread->next = 0; - idle_thread->wakeup_event.signal(lock); - return true; - } - return false; - } - - // Interrupt all idle threads. - void interrupt_all_idle_threads( - asio::detail::mutex::scoped_lock& lock) - { - while (first_idle_thread_) - { - idle_thread_info* idle_thread = first_idle_thread_; - first_idle_thread_ = idle_thread->next; - idle_thread->next = 0; - idle_thread->wakeup_event.signal(lock); - } - } - - // Helper class to perform task-related operations on block exit. - class task_cleanup; - friend class task_cleanup; - class task_cleanup - { - public: - task_cleanup(asio::detail::mutex::scoped_lock& lock, - task_io_service& task_io_svc) - : lock_(lock), - task_io_service_(task_io_svc) - { - } - - ~task_cleanup() - { - // Reinsert the task at the end of the handler queue. - lock_.lock(); - task_io_service_.task_interrupted_ = true; - task_io_service_.handler_queue_.push(&task_io_service_.task_handler_); - } - - private: - asio::detail::mutex::scoped_lock& lock_; - task_io_service& task_io_service_; - }; - - // Helper class to perform handler-related operations on block exit. - class handler_cleanup; - friend class handler_cleanup; - class handler_cleanup - { - public: - handler_cleanup(asio::detail::mutex::scoped_lock& lock, - task_io_service& task_io_svc) - : lock_(lock), - task_io_service_(task_io_svc) - { - } - - ~handler_cleanup() - { - lock_.lock(); - if (--task_io_service_.outstanding_work_ == 0) - task_io_service_.stop_all_threads(lock_); - } - - private: - asio::detail::mutex::scoped_lock& lock_; - task_io_service& task_io_service_; - }; - - // Mutex to protect access to internal data. - asio::detail::mutex mutex_; - - // The task to be run by this service. - Task& task_; - - // Handler object to represent the position of the task in the queue. - class task_handler - : public handler_queue::handler - { - public: - task_handler() - : handler_queue::handler(0, 0) - { - } - } task_handler_; - - // Whether the task has been interrupted. - bool task_interrupted_; - - // The count of unfinished work. - int outstanding_work_; - - // The queue of handlers that are ready to be delivered. - handler_queue handler_queue_; - - // Flag to indicate that the dispatcher has been stopped. - bool stopped_; - - // Flag to indicate that the dispatcher has been shut down. - bool shutdown_; - - // Structure containing information about an idle thread. - struct idle_thread_info - { - event wakeup_event; - idle_thread_info* next; - }; - - // The number of threads that are currently idle. - idle_thread_info* first_idle_thread_; -}; - -} // namespace detail -} // namespace asio - -#include "asio/detail/pop_options.hpp" - -#endif // defined(ASIO_ENABLE_TWO_LOCK_QUEUE) - -#endif // ASIO_DETAIL_TASK_IO_SERVICE_HPP diff --git a/libtorrent/include/asio/detail/task_io_service_2lock.hpp b/libtorrent/include/asio/detail/task_io_service_2lock.hpp deleted file mode 100644 index 9b0221bbb..000000000 --- a/libtorrent/include/asio/detail/task_io_service_2lock.hpp +++ /dev/null @@ -1,462 +0,0 @@ -// -// task_io_service_2lock.hpp -// ~~~~~~~~~~~~~~~~~~~~~~~~~ -// -// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -#ifndef ASIO_DETAIL_TASK_IO_SERVICE_2LOCK_HPP -#define ASIO_DETAIL_TASK_IO_SERVICE_2LOCK_HPP - -#if defined(_MSC_VER) && (_MSC_VER >= 1200) -# pragma once -#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) - -#include "asio/detail/push_options.hpp" - -#include "asio/error_code.hpp" -#include "asio/io_service.hpp" -#include "asio/detail/call_stack.hpp" -#include "asio/detail/event.hpp" -#include "asio/detail/handler_alloc_helpers.hpp" -#include "asio/detail/handler_invoke_helpers.hpp" -#include "asio/detail/indirect_handler_queue.hpp" -#include "asio/detail/mutex.hpp" -#include "asio/detail/service_base.hpp" -#include "asio/detail/task_io_service_fwd.hpp" - -#include "asio/detail/push_options.hpp" -#include -#include "asio/detail/pop_options.hpp" - -namespace asio { -namespace detail { - -// An alternative task_io_service implementation based on a two-lock queue. - -template -class task_io_service - : public asio::detail::service_base > -{ -public: - typedef indirect_handler_queue handler_queue; - - // Constructor. - task_io_service(asio::io_service& io_service) - : asio::detail::service_base >(io_service), - front_mutex_(), - back_mutex_(), - task_(use_service(io_service)), - outstanding_work_(0), - front_stopped_(false), - back_stopped_(false), - back_shutdown_(false), - back_first_idle_thread_(0), - back_task_thread_(0) - { - handler_queue_.push(&task_handler_); - } - - void init(size_t /*concurrency_hint*/) - { - } - - // Destroy all user-defined handler objects owned by the service. - void shutdown_service() - { - asio::detail::mutex::scoped_lock back_lock(back_mutex_); - back_shutdown_ = true; - back_lock.unlock(); - - // Destroy handler objects. - while (handler_queue::handler* h = handler_queue_.pop()) - if (h != &task_handler_) - h->destroy(); - - // Reset handler queue to initial state. - handler_queue_.push(&task_handler_); - } - - // Run the event loop until interrupted or no more work. - size_t run(asio::error_code& ec) - { - if (outstanding_work_ == 0) - { - stop(); - ec = asio::error_code(); - return 0; - } - - typename call_stack::context ctx(this); - - idle_thread_info this_idle_thread; - this_idle_thread.next = 0; - - size_t n = 0; - while (do_one(&this_idle_thread, ec)) - if (n != (std::numeric_limits::max)()) - ++n; - return n; - } - - // Run until interrupted or one operation is performed. - size_t run_one(asio::error_code& ec) - { - if (outstanding_work_ == 0) - { - stop(); - ec = asio::error_code(); - return 0; - } - - typename call_stack::context ctx(this); - - idle_thread_info this_idle_thread; - this_idle_thread.next = 0; - - return do_one(&this_idle_thread, ec); - } - - // Poll for operations without blocking. - size_t poll(asio::error_code& ec) - { - if (outstanding_work_ == 0) - { - stop(); - ec = asio::error_code(); - return 0; - } - - typename call_stack::context ctx(this); - - size_t n = 0; - while (do_one(0, ec)) - if (n != (std::numeric_limits::max)()) - ++n; - return n; - } - - // Poll for one operation without blocking. - size_t poll_one(asio::error_code& ec) - { - if (outstanding_work_ == 0) - { - stop(); - ec = asio::error_code(); - return 0; - } - - typename call_stack::context ctx(this); - - return do_one(0, ec); - } - - // Interrupt the event processing loop. - void stop() - { - asio::detail::mutex::scoped_lock front_lock(front_mutex_); - front_stopped_ = true; - front_lock.unlock(); - - asio::detail::mutex::scoped_lock back_lock(back_mutex_); - back_stopped_ = true; - interrupt_all_idle_threads(back_lock); - } - - // Reset in preparation for a subsequent run invocation. - void reset() - { - asio::detail::mutex::scoped_lock front_lock(front_mutex_); - front_stopped_ = false; - front_lock.unlock(); - - asio::detail::mutex::scoped_lock back_lock(back_mutex_); - back_stopped_ = false; - } - - // Notify that some work has started. - void work_started() - { - ++outstanding_work_; - } - - // Notify that some work has finished. - void work_finished() - { - if (--outstanding_work_ == 0) - stop(); - } - - // Request invocation of the given handler. - template - void dispatch(Handler handler) - { - if (call_stack::contains(this)) - asio_handler_invoke_helpers::invoke(handler, &handler); - else - post(handler); - } - - // Request invocation of the given handler and return immediately. - template - void post(Handler handler) - { - // Allocate and construct an operation to wrap the handler. - handler_queue::scoped_ptr ptr(handler_queue::wrap(handler)); - - asio::detail::mutex::scoped_lock back_lock(back_mutex_); - - // If the service has been shut down we silently discard the handler. - if (back_shutdown_) - return; - - // Add the handler to the end of the queue. - handler_queue_.push(ptr.get()); - ptr.release(); - - // An undelivered handler is treated as unfinished work. - ++outstanding_work_; - - // Wake up a thread to execute the handler. - interrupt_one_idle_thread(back_lock); - } - -private: - struct idle_thread_info; - - size_t do_one(idle_thread_info* this_idle_thread, - asio::error_code& ec) - { - bool task_has_run = false; - for (;;) - { - // The front lock must be held before we can pop items from the queue. - asio::detail::mutex::scoped_lock front_lock(front_mutex_); - if (front_stopped_) - { - ec = asio::error_code(); - return 0; - } - - if (handler_queue::handler* h = handler_queue_.pop()) - { - if (h == &task_handler_) - { - bool more_handlers = handler_queue_.poppable(); - unsigned long front_version = handler_queue_.front_version(); - front_lock.unlock(); - - // The task is always added to the back of the queue when we exit - // this block. - task_cleanup c(*this); - - // If we're polling and the task has already run then we're done. - bool polling = !this_idle_thread; - if (task_has_run && polling) - { - ec = asio::error_code(); - return 0; - } - - // If we're considering going idle we need to check whether the queue - // is still empty. If it is, add the thread to the list of idle - // threads. - if (!more_handlers && !polling) - { - asio::detail::mutex::scoped_lock back_lock(back_mutex_); - if (back_stopped_) - { - ec = asio::error_code(); - return 0; - } - else if (front_version == handler_queue_.back_version()) - { - back_task_thread_ = this_idle_thread; - } - else - { - more_handlers = true; - } - } - - // Run the task. May throw an exception. Only block if the handler - // queue is empty and we're not polling, otherwise we want to return - // as soon as possible. - task_has_run = true; - task_.run(!more_handlers && !polling); - } - else - { - front_lock.unlock(); - handler_cleanup c(*this); - - // Invoke the handler. May throw an exception. - h->invoke(); // invoke() deletes the handler object - - ec = asio::error_code(); - return 1; - } - } - else if (this_idle_thread) - { - unsigned long front_version = handler_queue_.front_version(); - front_lock.unlock(); - - // If we're considering going idle we need to check whether the queue - // is still empty. If it is, add the thread to the list of idle - // threads. - asio::detail::mutex::scoped_lock back_lock(back_mutex_); - if (back_stopped_) - { - ec = asio::error_code(); - return 0; - } - else if (front_version == handler_queue_.back_version()) - { - this_idle_thread->next = back_first_idle_thread_; - back_first_idle_thread_ = this_idle_thread; - this_idle_thread->wakeup_event.clear(back_lock); - this_idle_thread->wakeup_event.wait(back_lock); - } - } - else - { - ec = asio::error_code(); - return 0; - } - } - } - - // Interrupt a single idle thread. - void interrupt_one_idle_thread( - asio::detail::mutex::scoped_lock& back_lock) - { - if (back_first_idle_thread_) - { - idle_thread_info* idle_thread = back_first_idle_thread_; - back_first_idle_thread_ = idle_thread->next; - idle_thread->next = 0; - idle_thread->wakeup_event.signal(back_lock); - } - else if (back_task_thread_) - { - back_task_thread_ = 0; - task_.interrupt(); - } - } - - // Interrupt all idle threads. - void interrupt_all_idle_threads( - asio::detail::mutex::scoped_lock& back_lock) - { - while (back_first_idle_thread_) - { - idle_thread_info* idle_thread = back_first_idle_thread_; - back_first_idle_thread_ = idle_thread->next; - idle_thread->next = 0; - idle_thread->wakeup_event.signal(back_lock); - } - - if (back_task_thread_) - { - back_task_thread_ = 0; - task_.interrupt(); - } - } - - // Helper class to perform task-related operations on block exit. - class task_cleanup; - friend class task_cleanup; - class task_cleanup - { - public: - task_cleanup(task_io_service& task_io_svc) - : task_io_service_(task_io_svc) - { - } - - ~task_cleanup() - { - // Reinsert the task at the end of the handler queue. - asio::detail::mutex::scoped_lock back_lock( - task_io_service_.back_mutex_); - task_io_service_.back_task_thread_ = 0; - task_io_service_.handler_queue_.push(&task_io_service_.task_handler_); - } - - private: - task_io_service& task_io_service_; - }; - - // Helper class to perform handler-related operations on block exit. - class handler_cleanup - { - public: - handler_cleanup(task_io_service& task_io_svc) - : task_io_service_(task_io_svc) - { - } - - ~handler_cleanup() - { - task_io_service_.work_finished(); - } - - private: - task_io_service& task_io_service_; - }; - - // Mutexes to protect access to internal data. - asio::detail::mutex front_mutex_; - asio::detail::mutex back_mutex_; - - // The task to be run by this service. - Task& task_; - - // Handler object to represent the position of the task in the queue. - class task_handler - : public handler_queue::handler - { - public: - task_handler() - : handler_queue::handler(0, 0) - { - } - } task_handler_; - - // The count of unfinished work. - boost::detail::atomic_count outstanding_work_; - - // The queue of handlers that are ready to be delivered. - handler_queue handler_queue_; - - // Flag to indicate that the dispatcher has been stopped. - bool front_stopped_; - bool back_stopped_; - - // Flag to indicate that the dispatcher has been shut down. - bool back_shutdown_; - - // Structure containing information about an idle thread. - struct idle_thread_info - { - event wakeup_event; - idle_thread_info* next; - }; - - // The number of threads that are currently idle. - idle_thread_info* back_first_idle_thread_; - - // The thread that is currently blocked on the task. - idle_thread_info* back_task_thread_; -}; - -} // namespace detail -} // namespace asio - -#include "asio/detail/pop_options.hpp" - -#endif // ASIO_DETAIL_TASK_IO_SERVICE_2LOCK_HPP diff --git a/libtorrent/include/asio/detail/task_io_service_fwd.hpp b/libtorrent/include/asio/detail/task_io_service_fwd.hpp deleted file mode 100644 index 02ccdc21e..000000000 --- a/libtorrent/include/asio/detail/task_io_service_fwd.hpp +++ /dev/null @@ -1,31 +0,0 @@ -// -// task_io_service_fwd.hpp -// ~~~~~~~~~~~~~~~~~~~~~~~ -// -// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -#ifndef ASIO_DETAIL_TASK_IO_SERVICE_FWD_HPP -#define ASIO_DETAIL_TASK_IO_SERVICE_FWD_HPP - -#if defined(_MSC_VER) && (_MSC_VER >= 1200) -# pragma once -#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) - -#include "asio/detail/push_options.hpp" - -namespace asio { -namespace detail { - -template -class task_io_service; - -} // namespace detail -} // namespace asio - -#include "asio/detail/pop_options.hpp" - -#endif // ASIO_DETAIL_TASK_IO_SERVICE_FWD_HPP diff --git a/libtorrent/include/asio/detail/thread.hpp b/libtorrent/include/asio/detail/thread.hpp deleted file mode 100644 index 66b701ca5..000000000 --- a/libtorrent/include/asio/detail/thread.hpp +++ /dev/null @@ -1,58 +0,0 @@ -// -// thread.hpp -// ~~~~~~~~~~ -// -// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -#ifndef ASIO_DETAIL_THREAD_HPP -#define ASIO_DETAIL_THREAD_HPP - -#if defined(_MSC_VER) && (_MSC_VER >= 1200) -# pragma once -#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) - -#include "asio/detail/push_options.hpp" - -#include "asio/detail/push_options.hpp" -#include -#include "asio/detail/pop_options.hpp" - -#if !defined(BOOST_HAS_THREADS) -# include "asio/detail/null_thread.hpp" -#elif defined(BOOST_WINDOWS) -# if defined(UNDER_CE) -# include "asio/detail/wince_thread.hpp" -# else -# include "asio/detail/win_thread.hpp" -# endif -#elif defined(BOOST_HAS_PTHREADS) -# include "asio/detail/posix_thread.hpp" -#else -# error Only Windows and POSIX are supported! -#endif - -namespace asio { -namespace detail { - -#if !defined(BOOST_HAS_THREADS) -typedef null_thread thread; -#elif defined(BOOST_WINDOWS) -# if defined(UNDER_CE) -typedef wince_thread thread; -# else -typedef win_thread thread; -# endif -#elif defined(BOOST_HAS_PTHREADS) -typedef posix_thread thread; -#endif - -} // namespace detail -} // namespace asio - -#include "asio/detail/pop_options.hpp" - -#endif // ASIO_DETAIL_THREAD_HPP diff --git a/libtorrent/include/asio/detail/throw_error.hpp b/libtorrent/include/asio/detail/throw_error.hpp deleted file mode 100644 index bf2356c0a..000000000 --- a/libtorrent/include/asio/detail/throw_error.hpp +++ /dev/null @@ -1,44 +0,0 @@ -// -// throw_error.hpp -// ~~~~~~~~~~~~~~~ -// -// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -#ifndef ASIO_DETAIL_THROW_ERROR_HPP -#define ASIO_DETAIL_THROW_ERROR_HPP - -#if defined(_MSC_VER) && (_MSC_VER >= 1200) -# pragma once -#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) - -#include "asio/detail/push_options.hpp" - -#include "asio/detail/push_options.hpp" -#include -#include "asio/detail/pop_options.hpp" - -#include "asio/error_code.hpp" -#include "asio/system_error.hpp" - -namespace asio { -namespace detail { - -inline void throw_error(const asio::error_code& err) -{ - if (err) - { - asio::system_error e(err); - boost::throw_exception(e); - } -} - -} // namespace detail -} // namespace asio - -#include "asio/detail/pop_options.hpp" - -#endif // ASIO_DETAIL_THROW_ERROR_HPP diff --git a/libtorrent/include/asio/detail/timer_queue.hpp b/libtorrent/include/asio/detail/timer_queue.hpp deleted file mode 100644 index cdc94ab7a..000000000 --- a/libtorrent/include/asio/detail/timer_queue.hpp +++ /dev/null @@ -1,436 +0,0 @@ -// -// timer_queue.hpp -// ~~~~~~~~~~~~~~~ -// -// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -#ifndef ASIO_DETAIL_TIMER_QUEUE_HPP -#define ASIO_DETAIL_TIMER_QUEUE_HPP - -#if defined(_MSC_VER) && (_MSC_VER >= 1200) -# pragma once -#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) - -#include "asio/detail/push_options.hpp" - -#include "asio/detail/push_options.hpp" -#include -#include -#include -#include -#include -#include -#include "asio/detail/pop_options.hpp" - -#include "asio/error.hpp" -#include "asio/detail/handler_alloc_helpers.hpp" -#include "asio/detail/hash_map.hpp" -#include "asio/detail/noncopyable.hpp" -#include "asio/detail/timer_queue_base.hpp" - -namespace asio { -namespace detail { - -template -class timer_queue - : public timer_queue_base -{ -public: - // The time type. - typedef typename Time_Traits::time_type time_type; - - // The duration type. - typedef typename Time_Traits::duration_type duration_type; - - // Constructor. - timer_queue() - : timers_(), - heap_(), - cancelled_timers_(0), - complete_timers_(0) - { - } - - // Add a new timer to the queue. Returns true if this is the timer that is - // earliest in the queue, in which case the reactor's event demultiplexing - // function call may need to be interrupted and restarted. - template - bool enqueue_timer(const time_type& time, Handler handler, void* token) - { - // Ensure that there is space for the timer in the heap. We reserve here so - // that the push_back below will not throw due to a reallocation failure. - heap_.reserve(heap_.size() + 1); - - // Create a new timer object. - std::auto_ptr > new_timer( - new timer(time, handler, token)); - - // Insert the new timer into the hash. - typedef typename hash_map::iterator iterator; - typedef typename hash_map::value_type value_type; - std::pair result = - timers_.insert(value_type(token, new_timer.get())); - if (!result.second) - { - result.first->second->prev_ = new_timer.get(); - new_timer->next_ = result.first->second; - result.first->second = new_timer.get(); - } - - // Put the timer at the correct position in the heap. - new_timer->heap_index_ = heap_.size(); - heap_.push_back(new_timer.get()); - up_heap(heap_.size() - 1); - bool is_first = (heap_[0] == new_timer.get()); - - // Ownership of the timer is transferred to the timer queue. - new_timer.release(); - - return is_first; - } - - // Whether there are no timers in the queue. - virtual bool empty() const - { - return heap_.empty(); - } - - // Get the time for the timer that is earliest in the queue. - virtual boost::posix_time::time_duration wait_duration() const - { - if (heap_.empty()) - return boost::posix_time::pos_infin; - return Time_Traits::to_posix_duration( - Time_Traits::subtract(heap_[0]->time_, Time_Traits::now())); - } - - // Dispatch the timers that are earlier than the specified time. - virtual void dispatch_timers() - { - const time_type now = Time_Traits::now(); - while (!heap_.empty() && !Time_Traits::less_than(now, heap_[0]->time_)) - { - timer_base* t = heap_[0]; - remove_timer(t); - t->result_ = asio::error_code(); - t->prev_ = 0; - t->next_ = complete_timers_; - complete_timers_ = t; - } - } - - // Cancel the timers with the given token. Any timers pending for the token - // will be notified that they have been cancelled next time - // dispatch_cancellations is called. Returns the number of timers that were - // cancelled. - std::size_t cancel_timer(void* timer_token) - { - std::size_t num_cancelled = 0; - typedef typename hash_map::iterator iterator; - iterator it = timers_.find(timer_token); - if (it != timers_.end()) - { - timer_base* t = it->second; - while (t) - { - timer_base* next = t->next_; - remove_timer(t); - t->prev_ = 0; - t->next_ = cancelled_timers_; - cancelled_timers_ = t; - t = next; - ++num_cancelled; - } - } - return num_cancelled; - } - - // Dispatch any pending cancels for timers. - virtual void dispatch_cancellations() - { - while (cancelled_timers_) - { - timer_base* this_timer = cancelled_timers_; - this_timer->result_ = asio::error::operation_aborted; - cancelled_timers_ = this_timer->next_; - this_timer->next_ = complete_timers_; - complete_timers_ = this_timer; - } - } - - // Complete any timers that are waiting to be completed. - virtual void complete_timers() - { - while (complete_timers_) - { - timer_base* this_timer = complete_timers_; - complete_timers_ = this_timer->next_; - this_timer->next_ = 0; - this_timer->complete(); - } - } - - // Destroy all timers. - virtual void destroy_timers() - { - typename hash_map::iterator i = timers_.begin(); - typename hash_map::iterator end = timers_.end(); - while (i != end) - { - timer_base* t = i->second; - typename hash_map::iterator old_i = i++; - timers_.erase(old_i); - destroy_timer_list(t); - } - heap_.clear(); - timers_.clear(); - destroy_timer_list(cancelled_timers_); - destroy_timer_list(complete_timers_); - } - -private: - // Base class for timer operations. Function pointers are used instead of - // virtual functions to avoid the associated overhead. - class timer_base - { - public: - // Delete the timer and post the handler. - void complete() - { - complete_func_(this, result_); - } - - // Delete the timer. - void destroy() - { - destroy_func_(this); - } - - protected: - typedef void (*complete_func_type)(timer_base*, - const asio::error_code&); - typedef void (*destroy_func_type)(timer_base*); - - // Constructor. - timer_base(complete_func_type complete_func, destroy_func_type destroy_func, - const time_type& time, void* token) - : complete_func_(complete_func), - destroy_func_(destroy_func), - time_(time), - token_(token), - next_(0), - prev_(0), - heap_index_( - std::numeric_limits::max BOOST_PREVENT_MACRO_SUBSTITUTION()) - { - } - - // Prevent deletion through this type. - ~timer_base() - { - } - - private: - friend class timer_queue; - - // The function to be called to delete the timer and post the handler. - complete_func_type complete_func_; - - // The function to be called to delete the timer. - destroy_func_type destroy_func_; - - // The result of the timer operation. - asio::error_code result_; - - // The time when the timer should fire. - time_type time_; - - // The token associated with the timer. - void* token_; - - // The next timer known to the queue. - timer_base* next_; - - // The previous timer known to the queue. - timer_base* prev_; - - // The index of the timer in the heap. - size_t heap_index_; - }; - - // Adaptor class template for using handlers in timers. - template - class timer - : public timer_base - { - public: - // Constructor. - timer(const time_type& time, Handler handler, void* token) - : timer_base(&timer::complete_handler, - &timer::destroy_handler, time, token), - handler_(handler) - { - } - - // Delete the timer and post the handler. - static void complete_handler(timer_base* base, - const asio::error_code& result) - { - // Take ownership of the timer object. - typedef timer this_type; - this_type* this_timer(static_cast(base)); - typedef handler_alloc_traits alloc_traits; - handler_ptr ptr(this_timer->handler_, this_timer); - - // Make a copy of the error_code and the handler so that the memory can - // be deallocated before the upcall is made. - asio::error_code ec(result); - Handler handler(this_timer->handler_); - - // Free the memory associated with the handler. - ptr.reset(); - - // Make the upcall. - handler(ec); - } - - // Delete the timer. - static void destroy_handler(timer_base* base) - { - // Take ownership of the timer object. - typedef timer this_type; - this_type* this_timer(static_cast(base)); - typedef handler_alloc_traits alloc_traits; - handler_ptr ptr(this_timer->handler_, this_timer); - - // A sub-object of the handler may be the true owner of the memory - // associated with the handler. Consequently, a local copy of the handler - // is required to ensure that any owning sub-object remains valid until - // after we have deallocated the memory here. - Handler handler(this_timer->handler_); - (void)handler; - - // Free the memory associated with the handler. - ptr.reset(); - } - - private: - Handler handler_; - }; - - // Move the item at the given index up the heap to its correct position. - void up_heap(size_t index) - { - size_t parent = (index - 1) / 2; - while (index > 0 - && Time_Traits::less_than(heap_[index]->time_, heap_[parent]->time_)) - { - swap_heap(index, parent); - index = parent; - parent = (index - 1) / 2; - } - } - - // Move the item at the given index down the heap to its correct position. - void down_heap(size_t index) - { - size_t child = index * 2 + 1; - while (child < heap_.size()) - { - size_t min_child = (child + 1 == heap_.size() - || Time_Traits::less_than( - heap_[child]->time_, heap_[child + 1]->time_)) - ? child : child + 1; - if (Time_Traits::less_than(heap_[index]->time_, heap_[min_child]->time_)) - break; - swap_heap(index, min_child); - index = min_child; - child = index * 2 + 1; - } - } - - // Swap two entries in the heap. - void swap_heap(size_t index1, size_t index2) - { - timer_base* tmp = heap_[index1]; - heap_[index1] = heap_[index2]; - heap_[index2] = tmp; - heap_[index1]->heap_index_ = index1; - heap_[index2]->heap_index_ = index2; - } - - // Remove a timer from the heap and list of timers. - void remove_timer(timer_base* t) - { - // Remove the timer from the heap. - size_t index = t->heap_index_; - if (!heap_.empty() && index < heap_.size()) - { - if (index == heap_.size() - 1) - { - heap_.pop_back(); - } - else - { - swap_heap(index, heap_.size() - 1); - heap_.pop_back(); - size_t parent = (index - 1) / 2; - if (index > 0 && Time_Traits::less_than( - heap_[index]->time_, heap_[parent]->time_)) - up_heap(index); - else - down_heap(index); - } - } - - // Remove the timer from the hash. - typedef typename hash_map::iterator iterator; - iterator it = timers_.find(t->token_); - if (it != timers_.end()) - { - if (it->second == t) - it->second = t->next_; - if (t->prev_) - t->prev_->next_ = t->next_; - if (t->next_) - t->next_->prev_ = t->prev_; - if (it->second == 0) - timers_.erase(it); - } - } - - // Destroy all timers in a linked list. - void destroy_timer_list(timer_base*& t) - { - while (t) - { - timer_base* next = t->next_; - t->next_ = 0; - t->destroy(); - t = next; - } - } - - // A hash of timer token to linked lists of timers. - hash_map timers_; - - // The heap of timers, with the earliest timer at the front. - std::vector heap_; - - // The list of timers to be cancelled. - timer_base* cancelled_timers_; - - // The list of timers waiting to be completed. - timer_base* complete_timers_; -}; - -} // namespace detail -} // namespace asio - -#include "asio/detail/pop_options.hpp" - -#endif // ASIO_DETAIL_TIMER_QUEUE_HPP diff --git a/libtorrent/include/asio/detail/timer_queue_base.hpp b/libtorrent/include/asio/detail/timer_queue_base.hpp deleted file mode 100644 index 57f212b05..000000000 --- a/libtorrent/include/asio/detail/timer_queue_base.hpp +++ /dev/null @@ -1,62 +0,0 @@ -// -// timer_queue_base.hpp -// ~~~~~~~~~~~~~~~~~~~~ -// -// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -#ifndef ASIO_DETAIL_TIMER_QUEUE_BASE_HPP -#define ASIO_DETAIL_TIMER_QUEUE_BASE_HPP - -#if defined(_MSC_VER) && (_MSC_VER >= 1200) -# pragma once -#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) - -#include "asio/detail/push_options.hpp" - -#include "asio/detail/socket_types.hpp" // Must come before posix_time. - -#include "asio/detail/push_options.hpp" -#include -#include "asio/detail/pop_options.hpp" - -#include "asio/detail/noncopyable.hpp" - -namespace asio { -namespace detail { - -class timer_queue_base - : private noncopyable -{ -public: - // Destructor. - virtual ~timer_queue_base() {} - - // Whether there are no timers in the queue. - virtual bool empty() const = 0; - - // Get the time to wait until the next timer. - virtual boost::posix_time::time_duration wait_duration() const = 0; - - // Dispatch all ready timers. - virtual void dispatch_timers() = 0; - - // Dispatch any pending cancels for timers. - virtual void dispatch_cancellations() = 0; - - // Complete all timers that are waiting to be completed. - virtual void complete_timers() = 0; - - // Destroy all timers. - virtual void destroy_timers() = 0; -}; - -} // namespace detail -} // namespace asio - -#include "asio/detail/pop_options.hpp" - -#endif // ASIO_DETAIL_TIMER_QUEUE_BASE_HPP diff --git a/libtorrent/include/asio/detail/tss_ptr.hpp b/libtorrent/include/asio/detail/tss_ptr.hpp deleted file mode 100644 index 5e5f8a01e..000000000 --- a/libtorrent/include/asio/detail/tss_ptr.hpp +++ /dev/null @@ -1,65 +0,0 @@ -// -// tss_ptr.hpp -// ~~~~~~~~~~~ -// -// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -#ifndef ASIO_DETAIL_TSS_PTR_HPP -#define ASIO_DETAIL_TSS_PTR_HPP - -#if defined(_MSC_VER) && (_MSC_VER >= 1200) -# pragma once -#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) - -#include "asio/detail/push_options.hpp" - -#include "asio/detail/push_options.hpp" -#include -#include "asio/detail/pop_options.hpp" - -#if !defined(BOOST_HAS_THREADS) -# include "asio/detail/null_tss_ptr.hpp" -#elif defined(BOOST_WINDOWS) -# include "asio/detail/win_tss_ptr.hpp" -#elif defined(BOOST_HAS_PTHREADS) -# include "asio/detail/posix_tss_ptr.hpp" -#else -# error Only Windows and POSIX are supported! -#endif - -namespace asio { -namespace detail { - -template -class tss_ptr -#if !defined(BOOST_HAS_THREADS) - : public null_tss_ptr -#elif defined(BOOST_WINDOWS) - : public win_tss_ptr -#elif defined(BOOST_HAS_PTHREADS) - : public posix_tss_ptr -#endif -{ -public: - void operator=(T* value) - { -#if !defined(BOOST_HAS_THREADS) - null_tss_ptr::operator=(value); -#elif defined(BOOST_WINDOWS) - win_tss_ptr::operator=(value); -#elif defined(BOOST_HAS_PTHREADS) - posix_tss_ptr::operator=(value); -#endif - } -}; - -} // namespace detail -} // namespace asio - -#include "asio/detail/pop_options.hpp" - -#endif // ASIO_DETAIL_TSS_PTR_HPP diff --git a/libtorrent/include/asio/detail/win_event.hpp b/libtorrent/include/asio/detail/win_event.hpp deleted file mode 100644 index 2f057cdd7..000000000 --- a/libtorrent/include/asio/detail/win_event.hpp +++ /dev/null @@ -1,103 +0,0 @@ -// -// win_event.hpp -// ~~~~~~~~~~~~~ -// -// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -#ifndef ASIO_DETAIL_WIN_EVENT_HPP -#define ASIO_DETAIL_WIN_EVENT_HPP - -#if defined(_MSC_VER) && (_MSC_VER >= 1200) -# pragma once -#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) - -#include "asio/detail/push_options.hpp" - -#include "asio/detail/push_options.hpp" -#include -#include "asio/detail/pop_options.hpp" - -#if defined(BOOST_WINDOWS) - -#include "asio/error.hpp" -#include "asio/system_error.hpp" -#include "asio/detail/noncopyable.hpp" -#include "asio/detail/socket_types.hpp" - -#include "asio/detail/push_options.hpp" -#include -#include -#include "asio/detail/pop_options.hpp" - -namespace asio { -namespace detail { - -class win_event - : private noncopyable -{ -public: - // Constructor. - win_event() - : event_(::CreateEvent(0, true, false, 0)) - { - if (!event_) - { - DWORD last_error = ::GetLastError(); - asio::system_error e( - asio::error_code(last_error, - asio::error::get_system_category()), - "event"); - boost::throw_exception(e); - } - } - - // Destructor. - ~win_event() - { - ::CloseHandle(event_); - } - - // Signal the event. - template - void signal(Lock& lock) - { - BOOST_ASSERT(lock.locked()); - (void)lock; - ::SetEvent(event_); - } - - // Reset the event. - template - void clear(Lock& lock) - { - BOOST_ASSERT(lock.locked()); - (void)lock; - ::ResetEvent(event_); - } - - // Wait for the event to become signalled. - template - void wait(Lock& lock) - { - BOOST_ASSERT(lock.locked()); - lock.unlock(); - ::WaitForSingleObject(event_, INFINITE); - lock.lock(); - } - -private: - HANDLE event_; -}; - -} // namespace detail -} // namespace asio - -#endif // defined(BOOST_WINDOWS) - -#include "asio/detail/pop_options.hpp" - -#endif // ASIO_DETAIL_WIN_EVENT_HPP diff --git a/libtorrent/include/asio/detail/win_fd_set_adapter.hpp b/libtorrent/include/asio/detail/win_fd_set_adapter.hpp deleted file mode 100644 index ea5254294..000000000 --- a/libtorrent/include/asio/detail/win_fd_set_adapter.hpp +++ /dev/null @@ -1,88 +0,0 @@ -// -// win_fd_set_adapter.hpp -// ~~~~~~~~~~~~~~~~~~~~~~ -// -// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -#ifndef ASIO_DETAIL_WIN_FD_SET_ADAPTER_HPP -#define ASIO_DETAIL_WIN_FD_SET_ADAPTER_HPP - -#if defined(_MSC_VER) && (_MSC_VER >= 1200) -# pragma once -#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) - -#include "asio/detail/push_options.hpp" - -#include "asio/detail/socket_types.hpp" - -#if defined(BOOST_WINDOWS) || defined(__CYGWIN__) - -namespace asio { -namespace detail { - -// Adapts the FD_SET type to meet the Descriptor_Set concept's requirements. -class win_fd_set_adapter -{ -public: - enum { win_fd_set_size = 1024 }; - - win_fd_set_adapter() - : max_descriptor_(invalid_socket) - { - fd_set_.fd_count = 0; - } - - bool set(socket_type descriptor) - { - for (u_int i = 0; i < fd_set_.fd_count; ++i) - if (fd_set_.fd_array[i] == descriptor) - return true; - if (fd_set_.fd_count < win_fd_set_size) - { - fd_set_.fd_array[fd_set_.fd_count++] = descriptor; - return true; - } - return false; - } - - bool is_set(socket_type descriptor) const - { - return !!__WSAFDIsSet(descriptor, - const_cast(reinterpret_cast(&fd_set_))); - } - - operator fd_set*() - { - return reinterpret_cast(&fd_set_); - } - - socket_type max_descriptor() const - { - return max_descriptor_; - } - -private: - // This structure is defined to be compatible with the Windows API fd_set - // structure, but without being dependent on the value of FD_SETSIZE. - struct win_fd_set - { - u_int fd_count; - SOCKET fd_array[win_fd_set_size]; - }; - - win_fd_set fd_set_; - socket_type max_descriptor_; -}; - -} // namespace detail -} // namespace asio - -#endif // defined(BOOST_WINDOWS) || defined(__CYGWIN__) - -#include "asio/detail/pop_options.hpp" - -#endif // ASIO_DETAIL_WIN_FD_SET_ADAPTER_HPP diff --git a/libtorrent/include/asio/detail/win_iocp_handle_service.hpp b/libtorrent/include/asio/detail/win_iocp_handle_service.hpp deleted file mode 100644 index 99c472c34..000000000 --- a/libtorrent/include/asio/detail/win_iocp_handle_service.hpp +++ /dev/null @@ -1,832 +0,0 @@ -// -// win_iocp_handle_service.hpp -// ~~~~~~~~~~~~~~~~~~~~~~~~~~~ -// -// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// Copyright (c) 2008 Rep Invariant Systems, Inc. (info@repinvariant.com) -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -#ifndef ASIO_DETAIL_WIN_IOCP_HANDLE_SERVICE_HPP -#define ASIO_DETAIL_WIN_IOCP_HANDLE_SERVICE_HPP - -#if defined(_MSC_VER) && (_MSC_VER >= 1200) -# pragma once -#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) - -#include "asio/detail/push_options.hpp" - -#include "asio/detail/win_iocp_io_service_fwd.hpp" - -#if defined(ASIO_HAS_IOCP) - -#include "asio/detail/push_options.hpp" -#include -#include "asio/detail/pop_options.hpp" - -#include "asio/buffer.hpp" -#include "asio/error.hpp" -#include "asio/io_service.hpp" -#include "asio/detail/bind_handler.hpp" -#include "asio/detail/handler_alloc_helpers.hpp" -#include "asio/detail/handler_invoke_helpers.hpp" -#include "asio/detail/mutex.hpp" -#include "asio/detail/win_iocp_io_service.hpp" - -namespace asio { -namespace detail { - -class win_iocp_handle_service - : public asio::detail::service_base -{ -public: - // Base class for all operations. - typedef win_iocp_io_service::operation operation; - - // The native type of a stream handle. - typedef HANDLE native_type; - - // The implementation type of the stream handle. - class implementation_type - { - public: - // Default constructor. - implementation_type() - : handle_(INVALID_HANDLE_VALUE), - safe_cancellation_thread_id_(0), - next_(0), - prev_(0) - { - } - - private: - // Only this service will have access to the internal values. - friend class win_iocp_handle_service; - - // The native stream handle representation. - native_type handle_; - - // The ID of the thread from which it is safe to cancel asynchronous - // operations. 0 means no asynchronous operations have been started yet. - // ~0 means asynchronous operations have been started from more than one - // thread, and cancellation is not supported for the handle. - DWORD safe_cancellation_thread_id_; - - // Pointers to adjacent handle implementations in linked list. - implementation_type* next_; - implementation_type* prev_; - }; - - win_iocp_handle_service(asio::io_service& io_service) - : asio::detail::service_base(io_service), - iocp_service_(asio::use_service(io_service)), - mutex_(), - impl_list_(0) - { - } - - // Destroy all user-defined handler objects owned by the service. - void shutdown_service() - { - // Close all implementations, causing all operations to complete. - asio::detail::mutex::scoped_lock lock(mutex_); - implementation_type* impl = impl_list_; - while (impl) - { - close_for_destruction(*impl); - impl = impl->next_; - } - } - - // Construct a new handle implementation. - void construct(implementation_type& impl) - { - impl.handle_ = INVALID_HANDLE_VALUE; - impl.safe_cancellation_thread_id_ = 0; - - // Insert implementation into linked list of all implementations. - asio::detail::mutex::scoped_lock lock(mutex_); - impl.next_ = impl_list_; - impl.prev_ = 0; - if (impl_list_) - impl_list_->prev_ = &impl; - impl_list_ = &impl; - } - - // Destroy a handle implementation. - void destroy(implementation_type& impl) - { - close_for_destruction(impl); - - // Remove implementation from linked list of all implementations. - asio::detail::mutex::scoped_lock lock(mutex_); - if (impl_list_ == &impl) - impl_list_ = impl.next_; - if (impl.prev_) - impl.prev_->next_ = impl.next_; - if (impl.next_) - impl.next_->prev_= impl.prev_; - impl.next_ = 0; - impl.prev_ = 0; - } - - // Assign a native handle to a handle implementation. - asio::error_code assign(implementation_type& impl, - const native_type& native_handle, asio::error_code& ec) - { - if (is_open(impl)) - { - ec = asio::error::already_open; - return ec; - } - - if (iocp_service_.register_handle(native_handle, ec)) - return ec; - - impl.handle_ = native_handle; - ec = asio::error_code(); - return ec; - } - - // Determine whether the handle is open. - bool is_open(const implementation_type& impl) const - { - return impl.handle_ != INVALID_HANDLE_VALUE; - } - - // Destroy a handle implementation. - asio::error_code close(implementation_type& impl, - asio::error_code& ec) - { - if (is_open(impl)) - { - if (!::CloseHandle(impl.handle_)) - { - DWORD last_error = ::GetLastError(); - ec = asio::error_code(last_error, - asio::error::get_system_category()); - return ec; - } - - impl.handle_ = INVALID_HANDLE_VALUE; - impl.safe_cancellation_thread_id_ = 0; - } - - ec = asio::error_code(); - return ec; - } - - // Get the native handle representation. - native_type native(const implementation_type& impl) const - { - return impl.handle_; - } - - // Cancel all operations associated with the handle. - asio::error_code cancel(implementation_type& impl, - asio::error_code& ec) - { - if (!is_open(impl)) - { - ec = asio::error::bad_descriptor; - } - else if (FARPROC cancel_io_ex_ptr = ::GetProcAddress( - ::GetModuleHandleA("KERNEL32"), "CancelIoEx")) - { - // The version of Windows supports cancellation from any thread. - typedef BOOL (WINAPI* cancel_io_ex_t)(HANDLE, LPOVERLAPPED); - cancel_io_ex_t cancel_io_ex = (cancel_io_ex_t)cancel_io_ex_ptr; - if (!cancel_io_ex(impl.handle_, 0)) - { - DWORD last_error = ::GetLastError(); - if (last_error == ERROR_NOT_FOUND) - { - // ERROR_NOT_FOUND means that there were no operations to be - // cancelled. We swallow this error to match the behaviour on other - // platforms. - ec = asio::error_code(); - } - else - { - ec = asio::error_code(last_error, - asio::error::get_system_category()); - } - } - else - { - ec = asio::error_code(); - } - } - else if (impl.safe_cancellation_thread_id_ == 0) - { - // No operations have been started, so there's nothing to cancel. - ec = asio::error_code(); - } - else if (impl.safe_cancellation_thread_id_ == ::GetCurrentThreadId()) - { - // Asynchronous operations have been started from the current thread only, - // so it is safe to try to cancel them using CancelIo. - if (!::CancelIo(impl.handle_)) - { - DWORD last_error = ::GetLastError(); - ec = asio::error_code(last_error, - asio::error::get_system_category()); - } - else - { - ec = asio::error_code(); - } - } - else - { - // Asynchronous operations have been started from more than one thread, - // so cancellation is not safe. - ec = asio::error::operation_not_supported; - } - - return ec; - } - - class overlapped_wrapper - : public OVERLAPPED - { - public: - explicit overlapped_wrapper(asio::error_code& ec) - { - Internal = 0; - InternalHigh = 0; - Offset = 0; - OffsetHigh = 0; - - // Create a non-signalled manual-reset event, for GetOverlappedResult. - hEvent = ::CreateEvent(0, TRUE, FALSE, 0); - if (hEvent) - { - // As documented in GetQueuedCompletionStatus, setting the low order - // bit of this event prevents our synchronous writes from being treated - // as completion port events. - *reinterpret_cast(&hEvent) |= 1; - } - else - { - DWORD last_error = ::GetLastError(); - ec = asio::error_code(last_error, - asio::error::get_system_category()); - } - } - - ~overlapped_wrapper() - { - if (hEvent) - { - ::CloseHandle(hEvent); - } - } - }; - - // Write the given data. Returns the number of bytes written. - template - size_t write_some(implementation_type& impl, - const ConstBufferSequence& buffers, asio::error_code& ec) - { - return write_some_at(impl, 0, buffers, ec); - } - - // Write the given data at the specified offset. Returns the number of bytes - // written. - template - size_t write_some_at(implementation_type& impl, boost::uint64_t offset, - const ConstBufferSequence& buffers, asio::error_code& ec) - { - if (!is_open(impl)) - { - ec = asio::error::bad_descriptor; - return 0; - } - - // Find first buffer of non-zero length. - asio::const_buffer buffer; - typename ConstBufferSequence::const_iterator iter = buffers.begin(); - typename ConstBufferSequence::const_iterator end = buffers.end(); - for (DWORD i = 0; iter != end; ++iter, ++i) - { - buffer = asio::const_buffer(*iter); - if (asio::buffer_size(buffer) != 0) - break; - } - - // A request to write 0 bytes on a handle is a no-op. - if (asio::buffer_size(buffer) == 0) - { - ec = asio::error_code(); - return 0; - } - - overlapped_wrapper overlapped(ec); - if (ec) - { - return 0; - } - - // Write the data. - overlapped.Offset = offset & 0xFFFFFFFF; - overlapped.OffsetHigh = (offset >> 32) & 0xFFFFFFFF; - BOOL ok = ::WriteFile(impl.handle_, - asio::buffer_cast(buffer), - static_cast(asio::buffer_size(buffer)), 0, &overlapped); - if (!ok) - { - DWORD last_error = ::GetLastError(); - if (last_error != ERROR_IO_PENDING) - { - ec = asio::error_code(last_error, - asio::error::get_system_category()); - return 0; - } - } - - // Wait for the operation to complete. - DWORD bytes_transferred = 0; - ok = ::GetOverlappedResult(impl.handle_, - &overlapped, &bytes_transferred, TRUE); - if (!ok) - { - DWORD last_error = ::GetLastError(); - ec = asio::error_code(last_error, - asio::error::get_system_category()); - } - - ec = asio::error_code(); - return bytes_transferred; - } - - template - class write_operation - : public operation - { - public: - write_operation(win_iocp_io_service& io_service, - const ConstBufferSequence& buffers, Handler handler) - : operation(io_service, - &write_operation::do_completion_impl, - &write_operation::destroy_impl), - work_(io_service.get_io_service()), - buffers_(buffers), - handler_(handler) - { - } - - private: - static void do_completion_impl(operation* op, - DWORD last_error, size_t bytes_transferred) - { - // Take ownership of the operation object. - typedef write_operation op_type; - op_type* handler_op(static_cast(op)); - typedef handler_alloc_traits alloc_traits; - handler_ptr ptr(handler_op->handler_, handler_op); - -#if defined(ASIO_ENABLE_BUFFER_DEBUGGING) - // Check whether buffers are still valid. - typename ConstBufferSequence::const_iterator iter - = handler_op->buffers_.begin(); - typename ConstBufferSequence::const_iterator end - = handler_op->buffers_.end(); - while (iter != end) - { - asio::const_buffer buffer(*iter); - asio::buffer_cast(buffer); - ++iter; - } -#endif // defined(ASIO_ENABLE_BUFFER_DEBUGGING) - - // Make a copy of the handler so that the memory can be deallocated before - // the upcall is made. - Handler handler(handler_op->handler_); - - // Free the memory associated with the handler. - ptr.reset(); - - // Call the handler. - asio::error_code ec(last_error, - asio::error::get_system_category()); - asio_handler_invoke_helpers::invoke( - bind_handler(handler, ec, bytes_transferred), &handler); - } - - static void destroy_impl(operation* op) - { - // Take ownership of the operation object. - typedef write_operation op_type; - op_type* handler_op(static_cast(op)); - typedef handler_alloc_traits alloc_traits; - handler_ptr ptr(handler_op->handler_, handler_op); - - // A sub-object of the handler may be the true owner of the memory - // associated with the handler. Consequently, a local copy of the handler - // is required to ensure that any owning sub-object remains valid until - // after we have deallocated the memory here. - Handler handler(handler_op->handler_); - (void)handler; - - // Free the memory associated with the handler. - ptr.reset(); - } - - asio::io_service::work work_; - ConstBufferSequence buffers_; - Handler handler_; - }; - - // Start an asynchronous write. The data being written must be valid for the - // lifetime of the asynchronous operation. - template - void async_write_some(implementation_type& impl, - const ConstBufferSequence& buffers, Handler handler) - { - async_write_some_at(impl, 0, buffers, handler); - } - - // Start an asynchronous write at a specified offset. The data being written - // must be valid for the lifetime of the asynchronous operation. - template - void async_write_some_at(implementation_type& impl, boost::uint64_t offset, - const ConstBufferSequence& buffers, Handler handler) - { - if (!is_open(impl)) - { - this->get_io_service().post(bind_handler(handler, - asio::error::bad_descriptor, 0)); - return; - } - - // Update the ID of the thread from which cancellation is safe. - if (impl.safe_cancellation_thread_id_ == 0) - impl.safe_cancellation_thread_id_ = ::GetCurrentThreadId(); - else if (impl.safe_cancellation_thread_id_ != ::GetCurrentThreadId()) - impl.safe_cancellation_thread_id_ = ~DWORD(0); - - // Allocate and construct an operation to wrap the handler. - typedef write_operation value_type; - typedef handler_alloc_traits alloc_traits; - raw_handler_ptr raw_ptr(handler); - handler_ptr ptr(raw_ptr, iocp_service_, buffers, handler); - - // Find first buffer of non-zero length. - asio::const_buffer buffer; - typename ConstBufferSequence::const_iterator iter = buffers.begin(); - typename ConstBufferSequence::const_iterator end = buffers.end(); - for (DWORD i = 0; iter != end; ++iter, ++i) - { - buffer = asio::const_buffer(*iter); - if (asio::buffer_size(buffer) != 0) - break; - } - - // A request to write 0 bytes on a handle is a no-op. - if (asio::buffer_size(buffer) == 0) - { - asio::io_service::work work(this->get_io_service()); - ptr.reset(); - asio::error_code error; - iocp_service_.post(bind_handler(handler, error, 0)); - return; - } - - // Write the data. - DWORD bytes_transferred = 0; - ptr.get()->Offset = offset & 0xFFFFFFFF; - ptr.get()->OffsetHigh = (offset >> 32) & 0xFFFFFFFF; - BOOL ok = ::WriteFile(impl.handle_, - asio::buffer_cast(buffer), - static_cast(asio::buffer_size(buffer)), - &bytes_transferred, ptr.get()); - DWORD last_error = ::GetLastError(); - - // Check if the operation completed immediately. - if (!ok && last_error != ERROR_IO_PENDING) - { - asio::io_service::work work(this->get_io_service()); - ptr.reset(); - asio::error_code ec(last_error, - asio::error::get_system_category()); - iocp_service_.post(bind_handler(handler, ec, bytes_transferred)); - } - else - { - ptr.release(); - } - } - - // Read some data. Returns the number of bytes received. - template - size_t read_some(implementation_type& impl, - const MutableBufferSequence& buffers, asio::error_code& ec) - { - return read_some_at(impl, 0, buffers, ec); - } - - // Read some data at a specified offset. Returns the number of bytes received. - template - size_t read_some_at(implementation_type& impl, boost::uint64_t offset, - const MutableBufferSequence& buffers, asio::error_code& ec) - { - if (!is_open(impl)) - { - ec = asio::error::bad_descriptor; - return 0; - } - - // Find first buffer of non-zero length. - asio::mutable_buffer buffer; - typename MutableBufferSequence::const_iterator iter = buffers.begin(); - typename MutableBufferSequence::const_iterator end = buffers.end(); - for (DWORD i = 0; iter != end; ++iter, ++i) - { - buffer = asio::mutable_buffer(*iter); - if (asio::buffer_size(buffer) != 0) - break; - } - - // A request to read 0 bytes on a stream handle is a no-op. - if (asio::buffer_size(buffer) == 0) - { - ec = asio::error_code(); - return 0; - } - - overlapped_wrapper overlapped(ec); - if (ec) - { - return 0; - } - - // Read some data. - overlapped.Offset = offset & 0xFFFFFFFF; - overlapped.OffsetHigh = (offset >> 32) & 0xFFFFFFFF; - BOOL ok = ::ReadFile(impl.handle_, - asio::buffer_cast(buffer), - static_cast(asio::buffer_size(buffer)), 0, &overlapped); - if (!ok) - { - DWORD last_error = ::GetLastError(); - if (last_error != ERROR_IO_PENDING) - { - if (last_error == ERROR_HANDLE_EOF) - { - ec = asio::error::eof; - } - else - { - ec = asio::error_code(last_error, - asio::error::get_system_category()); - } - return 0; - } - } - - // Wait for the operation to complete. - DWORD bytes_transferred = 0; - ok = ::GetOverlappedResult(impl.handle_, - &overlapped, &bytes_transferred, TRUE); - if (!ok) - { - DWORD last_error = ::GetLastError(); - if (last_error == ERROR_HANDLE_EOF) - { - ec = asio::error::eof; - } - else - { - ec = asio::error_code(last_error, - asio::error::get_system_category()); - } - } - - ec = asio::error_code(); - return bytes_transferred; - } - - template - class read_operation - : public operation - { - public: - read_operation(win_iocp_io_service& io_service, - const MutableBufferSequence& buffers, Handler handler) - : operation(io_service, - &read_operation< - MutableBufferSequence, Handler>::do_completion_impl, - &read_operation< - MutableBufferSequence, Handler>::destroy_impl), - work_(io_service.get_io_service()), - buffers_(buffers), - handler_(handler) - { - } - - private: - static void do_completion_impl(operation* op, - DWORD last_error, size_t bytes_transferred) - { - // Take ownership of the operation object. - typedef read_operation op_type; - op_type* handler_op(static_cast(op)); - typedef handler_alloc_traits alloc_traits; - handler_ptr ptr(handler_op->handler_, handler_op); - -#if defined(ASIO_ENABLE_BUFFER_DEBUGGING) - // Check whether buffers are still valid. - typename MutableBufferSequence::const_iterator iter - = handler_op->buffers_.begin(); - typename MutableBufferSequence::const_iterator end - = handler_op->buffers_.end(); - while (iter != end) - { - asio::mutable_buffer buffer(*iter); - asio::buffer_cast(buffer); - ++iter; - } -#endif // defined(ASIO_ENABLE_BUFFER_DEBUGGING) - - // Check for the end-of-file condition. - asio::error_code ec(last_error, - asio::error::get_system_category()); - if (!ec && bytes_transferred == 0 || last_error == ERROR_HANDLE_EOF) - { - ec = asio::error::eof; - } - - // Make a copy of the handler so that the memory can be deallocated before - // the upcall is made. - Handler handler(handler_op->handler_); - - // Free the memory associated with the handler. - ptr.reset(); - - // Call the handler. - asio_handler_invoke_helpers::invoke( - bind_handler(handler, ec, bytes_transferred), &handler); - } - - static void destroy_impl(operation* op) - { - // Take ownership of the operation object. - typedef read_operation op_type; - op_type* handler_op(static_cast(op)); - typedef asio::detail::handler_alloc_traits< - Handler, op_type> alloc_traits; - asio::detail::handler_ptr ptr( - handler_op->handler_, handler_op); - - // A sub-object of the handler may be the true owner of the memory - // associated with the handler. Consequently, a local copy of the handler - // is required to ensure that any owning sub-object remains valid until - // after we have deallocated the memory here. - Handler handler(handler_op->handler_); - (void)handler; - - // Free the memory associated with the handler. - ptr.reset(); - } - - asio::io_service::work work_; - MutableBufferSequence buffers_; - Handler handler_; - }; - - // Start an asynchronous read. The buffer for the data being received must be - // valid for the lifetime of the asynchronous operation. - template - void async_read_some(implementation_type& impl, - const MutableBufferSequence& buffers, Handler handler) - { - async_read_some_at(impl, 0, buffers, handler); - } - - // Start an asynchronous read at a specified offset. The buffer for the data - // being received must be valid for the lifetime of the asynchronous - // operation. - template - void async_read_some_at(implementation_type& impl, boost::uint64_t offset, - const MutableBufferSequence& buffers, Handler handler) - { - if (!is_open(impl)) - { - this->get_io_service().post(bind_handler(handler, - asio::error::bad_descriptor, 0)); - return; - } - - // Update the ID of the thread from which cancellation is safe. - if (impl.safe_cancellation_thread_id_ == 0) - impl.safe_cancellation_thread_id_ = ::GetCurrentThreadId(); - else if (impl.safe_cancellation_thread_id_ != ::GetCurrentThreadId()) - impl.safe_cancellation_thread_id_ = ~DWORD(0); - - // Allocate and construct an operation to wrap the handler. - typedef read_operation value_type; - typedef handler_alloc_traits alloc_traits; - raw_handler_ptr raw_ptr(handler); - handler_ptr ptr(raw_ptr, iocp_service_, buffers, handler); - - // Find first buffer of non-zero length. - asio::mutable_buffer buffer; - typename MutableBufferSequence::const_iterator iter = buffers.begin(); - typename MutableBufferSequence::const_iterator end = buffers.end(); - for (DWORD i = 0; iter != end; ++iter, ++i) - { - buffer = asio::mutable_buffer(*iter); - if (asio::buffer_size(buffer) != 0) - break; - } - - // A request to receive 0 bytes on a stream handle is a no-op. - if (asio::buffer_size(buffer) == 0) - { - asio::io_service::work work(this->get_io_service()); - ptr.reset(); - asio::error_code error; - iocp_service_.post(bind_handler(handler, error, 0)); - return; - } - - // Read some data. - DWORD bytes_transferred = 0; - ptr.get()->Offset = offset & 0xFFFFFFFF; - ptr.get()->OffsetHigh = (offset >> 32) & 0xFFFFFFFF; - BOOL ok = ::ReadFile(impl.handle_, - asio::buffer_cast(buffer), - static_cast(asio::buffer_size(buffer)), - &bytes_transferred, ptr.get()); - DWORD last_error = ::GetLastError(); - if (!ok && last_error != ERROR_IO_PENDING) - { - asio::io_service::work work(this->get_io_service()); - ptr.reset(); - asio::error_code ec(last_error, - asio::error::get_system_category()); - iocp_service_.post(bind_handler(handler, ec, bytes_transferred)); - } - else - { - ptr.release(); - } - } - -private: - // Prevent the use of the null_buffers type with this service. - size_t write_some(implementation_type& impl, - const null_buffers& buffers, asio::error_code& ec); - size_t write_some_at(implementation_type& impl, boost::uint64_t offset, - const null_buffers& buffers, asio::error_code& ec); - template - void async_write_some(implementation_type& impl, - const null_buffers& buffers, Handler handler); - template - void async_write_some_at(implementation_type& impl, boost::uint64_t offset, - const null_buffers& buffers, Handler handler); - size_t read_some(implementation_type& impl, - const null_buffers& buffers, asio::error_code& ec); - size_t read_some_at(implementation_type& impl, boost::uint64_t offset, - const null_buffers& buffers, asio::error_code& ec); - template - void async_read_some(implementation_type& impl, - const null_buffers& buffers, Handler handler); - template - void async_read_some_at(implementation_type& impl, boost::uint64_t offset, - const null_buffers& buffers, Handler handler); - - // Helper function to close a handle when the associated object is being - // destroyed. - void close_for_destruction(implementation_type& impl) - { - if (is_open(impl)) - { - ::CloseHandle(impl.handle_); - impl.handle_ = INVALID_HANDLE_VALUE; - impl.safe_cancellation_thread_id_ = 0; - } - } - - // The IOCP service used for running asynchronous operations and dispatching - // handlers. - win_iocp_io_service& iocp_service_; - - // Mutex to protect access to the linked list of implementations. - asio::detail::mutex mutex_; - - // The head of a linked list of all implementations. - implementation_type* impl_list_; -}; - -} // namespace detail -} // namespace asio - -#endif // defined(ASIO_HAS_IOCP) - -#include "asio/detail/pop_options.hpp" - -#endif // ASIO_DETAIL_WIN_IOCP_HANDLE_SERVICE_HPP diff --git a/libtorrent/include/asio/detail/win_iocp_io_service.hpp b/libtorrent/include/asio/detail/win_iocp_io_service.hpp deleted file mode 100644 index 7f6d631c0..000000000 --- a/libtorrent/include/asio/detail/win_iocp_io_service.hpp +++ /dev/null @@ -1,728 +0,0 @@ -// -// win_iocp_io_service.hpp -// ~~~~~~~~~~~~~~~~~~~~~~~ -// -// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -#ifndef ASIO_DETAIL_WIN_IOCP_IO_SERVICE_HPP -#define ASIO_DETAIL_WIN_IOCP_IO_SERVICE_HPP - -#if defined(_MSC_VER) && (_MSC_VER >= 1200) -# pragma once -#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) - -#include "asio/detail/push_options.hpp" - -#include "asio/detail/win_iocp_io_service_fwd.hpp" - -#if defined(ASIO_HAS_IOCP) - -#include "asio/detail/push_options.hpp" -#include -#include -#include "asio/detail/pop_options.hpp" - -#include "asio/io_service.hpp" -#include "asio/system_error.hpp" -#include "asio/detail/call_stack.hpp" -#include "asio/detail/handler_alloc_helpers.hpp" -#include "asio/detail/handler_invoke_helpers.hpp" -#include "asio/detail/service_base.hpp" -#include "asio/detail/socket_types.hpp" -#include "asio/detail/timer_queue.hpp" -#include "asio/detail/mutex.hpp" - -namespace asio { -namespace detail { - -class win_iocp_io_service - : public asio::detail::service_base -{ -public: - // Base class for all operations. A function pointer is used instead of - // virtual functions to avoid the associated overhead. - // - // This class inherits from OVERLAPPED so that we can downcast to get back to - // the operation pointer from the LPOVERLAPPED out parameter of - // GetQueuedCompletionStatus. - class operation - : public OVERLAPPED - { - public: - typedef void (*invoke_func_type)(operation*, DWORD, size_t); - typedef void (*destroy_func_type)(operation*); - - operation(win_iocp_io_service& iocp_service, - invoke_func_type invoke_func, destroy_func_type destroy_func) - : outstanding_operations_(&iocp_service.outstanding_operations_), - invoke_func_(invoke_func), - destroy_func_(destroy_func) - { - Internal = 0; - InternalHigh = 0; - Offset = 0; - OffsetHigh = 0; - hEvent = 0; - - ::InterlockedIncrement(outstanding_operations_); - } - - void do_completion(DWORD last_error, size_t bytes_transferred) - { - invoke_func_(this, last_error, bytes_transferred); - } - - void destroy() - { - destroy_func_(this); - } - - protected: - // Prevent deletion through this type. - ~operation() - { - ::InterlockedDecrement(outstanding_operations_); - } - - private: - long* outstanding_operations_; - invoke_func_type invoke_func_; - destroy_func_type destroy_func_; - }; - - - // Constructor. - win_iocp_io_service(asio::io_service& io_service) - : asio::detail::service_base(io_service), - iocp_(), - outstanding_work_(0), - outstanding_operations_(0), - stopped_(0), - shutdown_(0), - timer_thread_(0), - timer_interrupt_issued_(false) - { - } - - void init(size_t concurrency_hint) - { - iocp_.handle = ::CreateIoCompletionPort(INVALID_HANDLE_VALUE, 0, 0, - static_cast((std::min)(concurrency_hint, DWORD(~0)))); - if (!iocp_.handle) - { - DWORD last_error = ::GetLastError(); - asio::system_error e( - asio::error_code(last_error, - asio::error::get_system_category()), - "iocp"); - boost::throw_exception(e); - } - } - - // Destroy all user-defined handler objects owned by the service. - void shutdown_service() - { - ::InterlockedExchange(&shutdown_, 1); - - while (::InterlockedExchangeAdd(&outstanding_operations_, 0) > 0) - { - DWORD bytes_transferred = 0; -#if (WINVER < 0x0500) - DWORD completion_key = 0; -#else - DWORD_PTR completion_key = 0; -#endif - LPOVERLAPPED overlapped = 0; - ::GetQueuedCompletionStatus(iocp_.handle, &bytes_transferred, - &completion_key, &overlapped, INFINITE); - if (overlapped) - static_cast(overlapped)->destroy(); - } - - for (std::size_t i = 0; i < timer_queues_.size(); ++i) - timer_queues_[i]->destroy_timers(); - timer_queues_.clear(); - } - - // Register a handle with the IO completion port. - asio::error_code register_handle( - HANDLE handle, asio::error_code& ec) - { - if (::CreateIoCompletionPort(handle, iocp_.handle, 0, 0) == 0) - { - DWORD last_error = ::GetLastError(); - ec = asio::error_code(last_error, - asio::error::get_system_category()); - } - else - { - ec = asio::error_code(); - } - return ec; - } - - // Run the event loop until stopped or no more work. - size_t run(asio::error_code& ec) - { - if (::InterlockedExchangeAdd(&outstanding_work_, 0) == 0) - { - ec = asio::error_code(); - return 0; - } - - call_stack::context ctx(this); - - size_t n = 0; - while (do_one(true, ec)) - if (n != (std::numeric_limits::max)()) - ++n; - return n; - } - - // Run until stopped or one operation is performed. - size_t run_one(asio::error_code& ec) - { - if (::InterlockedExchangeAdd(&outstanding_work_, 0) == 0) - { - ec = asio::error_code(); - return 0; - } - - call_stack::context ctx(this); - - return do_one(true, ec); - } - - // Poll for operations without blocking. - size_t poll(asio::error_code& ec) - { - if (::InterlockedExchangeAdd(&outstanding_work_, 0) == 0) - { - ec = asio::error_code(); - return 0; - } - - call_stack::context ctx(this); - - size_t n = 0; - while (do_one(false, ec)) - if (n != (std::numeric_limits::max)()) - ++n; - return n; - } - - // Poll for one operation without blocking. - size_t poll_one(asio::error_code& ec) - { - if (::InterlockedExchangeAdd(&outstanding_work_, 0) == 0) - { - ec = asio::error_code(); - return 0; - } - - call_stack::context ctx(this); - - return do_one(false, ec); - } - - // Stop the event processing loop. - void stop() - { - if (::InterlockedExchange(&stopped_, 1) == 0) - { - if (!::PostQueuedCompletionStatus(iocp_.handle, 0, 0, 0)) - { - DWORD last_error = ::GetLastError(); - asio::system_error e( - asio::error_code(last_error, - asio::error::get_system_category()), - "pqcs"); - boost::throw_exception(e); - } - } - } - - // Reset in preparation for a subsequent run invocation. - void reset() - { - ::InterlockedExchange(&stopped_, 0); - } - - // Notify that some work has started. - void work_started() - { - ::InterlockedIncrement(&outstanding_work_); - } - - // Notify that some work has finished. - void work_finished() - { - if (::InterlockedDecrement(&outstanding_work_) == 0) - stop(); - } - - // Request invocation of the given handler. - template - void dispatch(Handler handler) - { - if (call_stack::contains(this)) - asio_handler_invoke_helpers::invoke(handler, &handler); - else - post(handler); - } - - // Request invocation of the given handler and return immediately. - template - void post(Handler handler) - { - // If the service has been shut down we silently discard the handler. - if (::InterlockedExchangeAdd(&shutdown_, 0) != 0) - return; - - // Allocate and construct an operation to wrap the handler. - typedef handler_operation value_type; - typedef handler_alloc_traits alloc_traits; - raw_handler_ptr raw_ptr(handler); - handler_ptr ptr(raw_ptr, *this, handler); - - // Enqueue the operation on the I/O completion port. - if (!::PostQueuedCompletionStatus(iocp_.handle, 0, 0, ptr.get())) - { - DWORD last_error = ::GetLastError(); - asio::system_error e( - asio::error_code(last_error, - asio::error::get_system_category()), - "pqcs"); - boost::throw_exception(e); - } - - // Operation has been successfully posted. - ptr.release(); - } - - // Request invocation of the given OVERLAPPED-derived operation. - void post_completion(operation* op, DWORD op_last_error, - DWORD bytes_transferred) - { - // Enqueue the operation on the I/O completion port. - if (!::PostQueuedCompletionStatus(iocp_.handle, - bytes_transferred, op_last_error, op)) - { - DWORD last_error = ::GetLastError(); - asio::system_error e( - asio::error_code(last_error, - asio::error::get_system_category()), - "pqcs"); - boost::throw_exception(e); - } - } - - // Add a new timer queue to the service. - template - void add_timer_queue(timer_queue& timer_queue) - { - asio::detail::mutex::scoped_lock lock(timer_mutex_); - timer_queues_.push_back(&timer_queue); - } - - // Remove a timer queue from the service. - template - void remove_timer_queue(timer_queue& timer_queue) - { - asio::detail::mutex::scoped_lock lock(timer_mutex_); - for (std::size_t i = 0; i < timer_queues_.size(); ++i) - { - if (timer_queues_[i] == &timer_queue) - { - timer_queues_.erase(timer_queues_.begin() + i); - return; - } - } - } - - // Schedule a timer in the given timer queue to expire at the specified - // absolute time. The handler object will be invoked when the timer expires. - template - void schedule_timer(timer_queue& timer_queue, - const typename Time_Traits::time_type& time, Handler handler, void* token) - { - // If the service has been shut down we silently discard the timer. - if (::InterlockedExchangeAdd(&shutdown_, 0) != 0) - return; - - asio::detail::mutex::scoped_lock lock(timer_mutex_); - if (timer_queue.enqueue_timer(time, handler, token)) - { - if (!timer_interrupt_issued_) - { - timer_interrupt_issued_ = true; - lock.unlock(); - ::PostQueuedCompletionStatus(iocp_.handle, - 0, steal_timer_dispatching, 0); - } - } - } - - // Cancel the timer associated with the given token. Returns the number of - // handlers that have been posted or dispatched. - template - std::size_t cancel_timer(timer_queue& timer_queue, void* token) - { - // If the service has been shut down we silently ignore the cancellation. - if (::InterlockedExchangeAdd(&shutdown_, 0) != 0) - return 0; - - asio::detail::mutex::scoped_lock lock(timer_mutex_); - std::size_t n = timer_queue.cancel_timer(token); - if (n > 0 && !timer_interrupt_issued_) - { - timer_interrupt_issued_ = true; - lock.unlock(); - ::PostQueuedCompletionStatus(iocp_.handle, - 0, steal_timer_dispatching, 0); - } - return n; - } - -private: - // Dequeues at most one operation from the I/O completion port, and then - // executes it. Returns the number of operations that were dequeued (i.e. - // either 0 or 1). - size_t do_one(bool block, asio::error_code& ec) - { - long this_thread_id = static_cast(::GetCurrentThreadId()); - - for (;;) - { - // Try to acquire responsibility for dispatching timers. - bool dispatching_timers = (::InterlockedCompareExchange( - &timer_thread_, this_thread_id, 0) == 0); - - // Calculate timeout for GetQueuedCompletionStatus call. - DWORD timeout = max_timeout; - if (dispatching_timers) - { - asio::detail::mutex::scoped_lock lock(timer_mutex_); - timer_interrupt_issued_ = false; - timeout = get_timeout(); - } - - // Get the next operation from the queue. - DWORD bytes_transferred = 0; -#if (WINVER < 0x0500) - DWORD completion_key = 0; -#else - DWORD_PTR completion_key = 0; -#endif - LPOVERLAPPED overlapped = 0; - ::SetLastError(0); - BOOL ok = ::GetQueuedCompletionStatus(iocp_.handle, &bytes_transferred, - &completion_key, &overlapped, block ? timeout : 0); - DWORD last_error = ::GetLastError(); - - // Dispatch any pending timers. - if (dispatching_timers) - { - try - { - asio::detail::mutex::scoped_lock lock(timer_mutex_); - timer_queues_copy_ = timer_queues_; - for (std::size_t i = 0; i < timer_queues_copy_.size(); ++i) - { - timer_queues_copy_[i]->dispatch_timers(); - timer_queues_copy_[i]->dispatch_cancellations(); - timer_queues_copy_[i]->complete_timers(); - } - } - catch (...) - { - // Transfer responsibility for dispatching timers to another thread. - if (::InterlockedCompareExchange(&timer_thread_, - 0, this_thread_id) == this_thread_id) - { - ::PostQueuedCompletionStatus(iocp_.handle, - 0, transfer_timer_dispatching, 0); - } - - throw; - } - } - - if (!ok && overlapped == 0) - { - if (block && last_error == WAIT_TIMEOUT) - { - // Relinquish responsibility for dispatching timers. - if (dispatching_timers) - { - ::InterlockedCompareExchange(&timer_thread_, 0, this_thread_id); - } - - continue; - } - - // Transfer responsibility for dispatching timers to another thread. - if (dispatching_timers && ::InterlockedCompareExchange( - &timer_thread_, 0, this_thread_id) == this_thread_id) - { - ::PostQueuedCompletionStatus(iocp_.handle, - 0, transfer_timer_dispatching, 0); - } - - ec = asio::error_code(); - return 0; - } - else if (overlapped) - { - // We may have been passed a last_error value in the completion_key. - if (last_error == 0) - { - last_error = completion_key; - } - - // Transfer responsibility for dispatching timers to another thread. - if (dispatching_timers && ::InterlockedCompareExchange( - &timer_thread_, 0, this_thread_id) == this_thread_id) - { - ::PostQueuedCompletionStatus(iocp_.handle, - 0, transfer_timer_dispatching, 0); - } - - // Ensure that the io_service does not exit due to running out of work - // while we make the upcall. - auto_work work(*this); - - // Dispatch the operation. - operation* op = static_cast(overlapped); - op->do_completion(last_error, bytes_transferred); - - ec = asio::error_code(); - return 1; - } - else if (completion_key == transfer_timer_dispatching) - { - // Woken up to try to acquire responsibility for dispatching timers. - ::InterlockedCompareExchange(&timer_thread_, 0, this_thread_id); - } - else if (completion_key == steal_timer_dispatching) - { - // Woken up to steal responsibility for dispatching timers. - ::InterlockedExchange(&timer_thread_, 0); - } - else - { - // Relinquish responsibility for dispatching timers. If the io_service - // is not being stopped then the thread will get an opportunity to - // reacquire timer responsibility on the next loop iteration. - if (dispatching_timers) - { - ::InterlockedCompareExchange(&timer_thread_, 0, this_thread_id); - } - - // The stopped_ flag is always checked to ensure that any leftover - // interrupts from a previous run invocation are ignored. - if (::InterlockedExchangeAdd(&stopped_, 0) != 0) - { - // Wake up next thread that is blocked on GetQueuedCompletionStatus. - if (!::PostQueuedCompletionStatus(iocp_.handle, 0, 0, 0)) - { - DWORD last_error = ::GetLastError(); - ec = asio::error_code(last_error, - asio::error::get_system_category()); - return 0; - } - - ec = asio::error_code(); - return 0; - } - } - } - } - - // Check if all timer queues are empty. - bool all_timer_queues_are_empty() const - { - for (std::size_t i = 0; i < timer_queues_.size(); ++i) - if (!timer_queues_[i]->empty()) - return false; - return true; - } - - // Get the timeout value for the GetQueuedCompletionStatus call. The timeout - // value is returned as a number of milliseconds. We will wait no longer than - // 1000 milliseconds. - DWORD get_timeout() - { - if (all_timer_queues_are_empty()) - return max_timeout; - - boost::posix_time::time_duration minimum_wait_duration - = boost::posix_time::milliseconds(max_timeout); - - for (std::size_t i = 0; i < timer_queues_.size(); ++i) - { - boost::posix_time::time_duration wait_duration - = timer_queues_[i]->wait_duration(); - if (wait_duration < minimum_wait_duration) - minimum_wait_duration = wait_duration; - } - - if (minimum_wait_duration > boost::posix_time::time_duration()) - { - int milliseconds = minimum_wait_duration.total_milliseconds(); - return static_cast(milliseconds > 0 ? milliseconds : 1); - } - else - { - return 0; - } - } - - struct auto_work - { - auto_work(win_iocp_io_service& io_service) - : io_service_(io_service) - { - io_service_.work_started(); - } - - ~auto_work() - { - io_service_.work_finished(); - } - - private: - win_iocp_io_service& io_service_; - }; - - template - struct handler_operation - : public operation - { - handler_operation(win_iocp_io_service& io_service, - Handler handler) - : operation(io_service, &handler_operation::do_completion_impl, - &handler_operation::destroy_impl), - io_service_(io_service), - handler_(handler) - { - io_service_.work_started(); - } - - ~handler_operation() - { - io_service_.work_finished(); - } - - private: - // Prevent copying and assignment. - handler_operation(const handler_operation&); - void operator=(const handler_operation&); - - static void do_completion_impl(operation* op, DWORD, size_t) - { - // Take ownership of the operation object. - typedef handler_operation op_type; - op_type* handler_op(static_cast(op)); - typedef handler_alloc_traits alloc_traits; - handler_ptr ptr(handler_op->handler_, handler_op); - - // Make a copy of the handler so that the memory can be deallocated before - // the upcall is made. - Handler handler(handler_op->handler_); - - // Free the memory associated with the handler. - ptr.reset(); - - // Make the upcall. - asio_handler_invoke_helpers::invoke(handler, &handler); - } - - static void destroy_impl(operation* op) - { - // Take ownership of the operation object. - typedef handler_operation op_type; - op_type* handler_op(static_cast(op)); - typedef handler_alloc_traits alloc_traits; - handler_ptr ptr(handler_op->handler_, handler_op); - - // A sub-object of the handler may be the true owner of the memory - // associated with the handler. Consequently, a local copy of the handler - // is required to ensure that any owning sub-object remains valid until - // after we have deallocated the memory here. - Handler handler(handler_op->handler_); - (void)handler; - - // Free the memory associated with the handler. - ptr.reset(); - } - - win_iocp_io_service& io_service_; - Handler handler_; - }; - - // The IO completion port used for queueing operations. - struct iocp_holder - { - HANDLE handle; - iocp_holder() : handle(0) {} - ~iocp_holder() { if (handle) ::CloseHandle(handle); } - } iocp_; - - // The count of unfinished work. - long outstanding_work_; - - // The count of unfinished operations. - long outstanding_operations_; - friend class operation; - - // Flag to indicate whether the event loop has been stopped. - long stopped_; - - // Flag to indicate whether the service has been shut down. - long shutdown_; - - enum - { - // Maximum GetQueuedCompletionStatus timeout, in milliseconds. - max_timeout = 500, - - // Completion key value to indicate that responsibility for dispatching - // timers is being cooperatively transferred from one thread to another. - transfer_timer_dispatching = 1, - - // Completion key value to indicate that responsibility for dispatching - // timers should be stolen from another thread. - steal_timer_dispatching = 2 - }; - - // The thread that's currently in charge of dispatching timers. - long timer_thread_; - - // Mutex for protecting access to the timer queues. - mutex timer_mutex_; - - // Whether a thread has been interrupted to process a new timeout. - bool timer_interrupt_issued_; - - // The timer queues. - std::vector timer_queues_; - - // A copy of the timer queues, used when dispatching, cancelling and cleaning - // up timers. The copy is stored as a class data member to avoid unnecessary - // memory allocation. - std::vector timer_queues_copy_; -}; - -} // namespace detail -} // namespace asio - -#endif // defined(ASIO_HAS_IOCP) - -#include "asio/detail/pop_options.hpp" - -#endif // ASIO_DETAIL_WIN_IOCP_IO_SERVICE_HPP diff --git a/libtorrent/include/asio/detail/win_iocp_io_service_fwd.hpp b/libtorrent/include/asio/detail/win_iocp_io_service_fwd.hpp deleted file mode 100644 index a40c6a871..000000000 --- a/libtorrent/include/asio/detail/win_iocp_io_service_fwd.hpp +++ /dev/null @@ -1,50 +0,0 @@ -// -// win_iocp_io_service_fwd.hpp -// ~~~~~~~~~~~~~~~~~~~~~~~~~~~ -// -// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -#ifndef ASIO_DETAIL_WIN_IOCP_IO_SERVICE_FWD_HPP -#define ASIO_DETAIL_WIN_IOCP_IO_SERVICE_FWD_HPP - -#if defined(_MSC_VER) && (_MSC_VER >= 1200) -# pragma once -#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) - -#include "asio/detail/push_options.hpp" - -#include "asio/detail/push_options.hpp" -#include -#include "asio/detail/pop_options.hpp" - -#include "asio/detail/socket_types.hpp" - -// This service is only supported on Win32 (NT4 and later). -#if !defined(ASIO_DISABLE_IOCP) -#if defined(BOOST_WINDOWS) || defined(__CYGWIN__) -#if defined(_WIN32_WINNT) && (_WIN32_WINNT >= 0x0400) -#if !defined(UNDER_CE) - -// Define this to indicate that IOCP is supported on the target platform. -#define ASIO_HAS_IOCP 1 - -namespace asio { -namespace detail { - -class win_iocp_io_service; - -} // namespace detail -} // namespace asio - -#endif // !defined(UNDER_CE) -#endif // defined(_WIN32_WINNT) && (_WIN32_WINNT >= 0x0400) -#endif // defined(BOOST_WINDOWS) || defined(__CYGWIN__) -#endif // !defined(ASIO_DISABLE_IOCP) - -#include "asio/detail/pop_options.hpp" - -#endif // ASIO_DETAIL_WIN_IOCP_IO_SERVICE_FWD_HPP diff --git a/libtorrent/include/asio/detail/win_iocp_serial_port_service.hpp b/libtorrent/include/asio/detail/win_iocp_serial_port_service.hpp deleted file mode 100644 index 55f32ae18..000000000 --- a/libtorrent/include/asio/detail/win_iocp_serial_port_service.hpp +++ /dev/null @@ -1,292 +0,0 @@ -// -// win_iocp_serial_port_service.hpp -// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -// -// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// Copyright (c) 2008 Rep Invariant Systems, Inc. (info@repinvariant.com) -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -#ifndef ASIO_DETAIL_WIN_IOCP_SERIAL_PORT_SERVICE_HPP -#define ASIO_DETAIL_WIN_IOCP_SERIAL_PORT_SERVICE_HPP - -#if defined(_MSC_VER) && (_MSC_VER >= 1200) -# pragma once -#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) - -#include "asio/detail/push_options.hpp" - -#include "asio/detail/push_options.hpp" -#include -#include -#include "asio/detail/pop_options.hpp" - -#include "asio/detail/win_iocp_io_service_fwd.hpp" - -#if defined(ASIO_HAS_IOCP) - -#include "asio/error.hpp" -#include "asio/io_service.hpp" -#include "asio/detail/win_iocp_handle_service.hpp" - -namespace asio { -namespace detail { - -// Extend win_iocp_handle_service to provide serial port support. -class win_iocp_serial_port_service - : public asio::detail::service_base -{ -public: - // The native type of a stream handle. - typedef win_iocp_handle_service::native_type native_type; - - // The implementation type of the stream handle. - typedef win_iocp_handle_service::implementation_type implementation_type; - - win_iocp_serial_port_service(asio::io_service& io_service) - : asio::detail::service_base< - win_iocp_serial_port_service>(io_service), - handle_service_( - asio::use_service(io_service)) - { - } - - // Destroy all user-defined handler objects owned by the service. - void shutdown_service() - { - } - - // Construct a new handle implementation. - void construct(implementation_type& impl) - { - handle_service_.construct(impl); - } - - // Destroy a handle implementation. - void destroy(implementation_type& impl) - { - handle_service_.destroy(impl); - } - - // Open the serial port using the specified device name. - asio::error_code open(implementation_type& impl, - const std::string& device, asio::error_code& ec) - { - if (is_open(impl)) - { - ec = asio::error::already_open; - return ec; - } - - // For convenience, add a leading \\.\ sequence if not already present. - std::string name = (device[0] == '\\') ? device : "\\\\.\\" + device; - - // Open a handle to the serial port. - ::HANDLE handle = ::CreateFileA(name.c_str(), - GENERIC_READ | GENERIC_WRITE, 0, 0, - OPEN_EXISTING, FILE_FLAG_OVERLAPPED, 0); - if (handle == INVALID_HANDLE_VALUE) - { - DWORD last_error = ::GetLastError(); - ec = asio::error_code(last_error, - asio::error::get_system_category()); - return ec; - } - - // Determine the initial serial port parameters. - using namespace std; // For memcpy. - ::DCB dcb; - memset(&dcb, 0, sizeof(DCB)); - dcb.DCBlength = sizeof(DCB); - if (!::GetCommState(handle, &dcb)) - { - DWORD last_error = ::GetLastError(); - ::CloseHandle(handle); - ec = asio::error_code(last_error, - asio::error::get_system_category()); - return ec; - } - - // Set some default serial port parameters. This implementation does not - // support changing these, so they might as well be in a known state. - dcb.fBinary = TRUE; // Win32 only supports binary mode. - dcb.fDsrSensitivity = FALSE; - dcb.fNull = FALSE; // Do not ignore NULL characters. - dcb.fAbortOnError = FALSE; // Ignore serial framing errors. - if (!::SetCommState(handle, &dcb)) - { - DWORD last_error = ::GetLastError(); - ::CloseHandle(handle); - ec = asio::error_code(last_error, - asio::error::get_system_category()); - return ec; - } - - // Set up timeouts so that the serial port will behave similarly to a - // network socket. Reads wait for at least one byte, then return with - // whatever they have. Writes return once everything is out the door. - ::COMMTIMEOUTS timeouts; - timeouts.ReadIntervalTimeout = 1; - timeouts.ReadTotalTimeoutMultiplier = 0; - timeouts.ReadTotalTimeoutConstant = 0; - timeouts.WriteTotalTimeoutMultiplier = 0; - timeouts.WriteTotalTimeoutConstant = 0; - if (!::SetCommTimeouts(handle, &timeouts)) - { - DWORD last_error = ::GetLastError(); - ::CloseHandle(handle); - ec = asio::error_code(last_error, - asio::error::get_system_category()); - return ec; - } - - // We're done. Take ownership of the serial port handle. - if (handle_service_.assign(impl, handle, ec)) - ::CloseHandle(handle); - return ec; - } - - // Assign a native handle to a handle implementation. - asio::error_code assign(implementation_type& impl, - const native_type& native_handle, asio::error_code& ec) - { - return handle_service_.assign(impl, native_handle, ec); - } - - // Determine whether the handle is open. - bool is_open(const implementation_type& impl) const - { - return handle_service_.is_open(impl); - } - - // Destroy a handle implementation. - asio::error_code close(implementation_type& impl, - asio::error_code& ec) - { - return handle_service_.close(impl, ec); - } - - // Get the native handle representation. - native_type native(implementation_type& impl) - { - return handle_service_.native(impl); - } - - // Cancel all operations associated with the handle. - asio::error_code cancel(implementation_type& impl, - asio::error_code& ec) - { - return handle_service_.cancel(impl, ec); - } - - // Set an option on the serial port. - template - asio::error_code set_option(implementation_type& impl, - const SettableSerialPortOption& option, asio::error_code& ec) - { - using namespace std; // For memcpy. - - ::DCB dcb; - memset(&dcb, 0, sizeof(DCB)); - dcb.DCBlength = sizeof(DCB); - if (!::GetCommState(handle_service_.native(impl), &dcb)) - { - DWORD last_error = ::GetLastError(); - ec = asio::error_code(last_error, - asio::error::get_system_category()); - return ec; - } - - if (option.store(dcb, ec)) - return ec; - - if (!::SetCommState(handle_service_.native(impl), &dcb)) - { - DWORD last_error = ::GetLastError(); - ec = asio::error_code(last_error, - asio::error::get_system_category()); - return ec; - } - - ec = asio::error_code(); - return ec; - } - - // Get an option from the serial port. - template - asio::error_code get_option(const implementation_type& impl, - GettableSerialPortOption& option, asio::error_code& ec) const - { - using namespace std; // For memcpy. - - ::DCB dcb; - memset(&dcb, 0, sizeof(DCB)); - dcb.DCBlength = sizeof(DCB); - if (!::GetCommState(handle_service_.native(impl), &dcb)) - { - DWORD last_error = ::GetLastError(); - ec = asio::error_code(last_error, - asio::error::get_system_category()); - return ec; - } - - return option.load(dcb, ec); - } - - // Send a break sequence to the serial port. - asio::error_code send_break(implementation_type& impl, - asio::error_code& ec) - { - ec = asio::error::operation_not_supported; - return ec; - } - - // Write the given data. Returns the number of bytes sent. - template - size_t write_some(implementation_type& impl, - const ConstBufferSequence& buffers, asio::error_code& ec) - { - return handle_service_.write_some(impl, buffers, ec); - } - - // Start an asynchronous write. The data being written must be valid for the - // lifetime of the asynchronous operation. - template - void async_write_some(implementation_type& impl, - const ConstBufferSequence& buffers, Handler handler) - { - handle_service_.async_write_some(impl, buffers, handler); - } - - // Read some data. Returns the number of bytes received. - template - size_t read_some(implementation_type& impl, - const MutableBufferSequence& buffers, asio::error_code& ec) - { - return handle_service_.read_some(impl, buffers, ec); - } - - // Start an asynchronous read. The buffer for the data being received must be - // valid for the lifetime of the asynchronous operation. - template - void async_read_some(implementation_type& impl, - const MutableBufferSequence& buffers, Handler handler) - { - handle_service_.async_read_some(impl, buffers, handler); - } - -private: - // The handle service used for initiating asynchronous operations. - win_iocp_handle_service& handle_service_; -}; - -} // namespace detail -} // namespace asio - -#endif // defined(ASIO_HAS_IOCP) - -#include "asio/detail/pop_options.hpp" - -#endif // ASIO_DETAIL_WIN_IOCP_SERIAL_PORT_SERVICE_HPP diff --git a/libtorrent/include/asio/detail/win_iocp_socket_service.hpp b/libtorrent/include/asio/detail/win_iocp_socket_service.hpp deleted file mode 100644 index 13943bab0..000000000 --- a/libtorrent/include/asio/detail/win_iocp_socket_service.hpp +++ /dev/null @@ -1,2413 +0,0 @@ -// -// win_iocp_socket_service.hpp -// ~~~~~~~~~~~~~~~~~~~~~~~~~~~ -// -// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -#ifndef ASIO_DETAIL_WIN_IOCP_SOCKET_SERVICE_HPP -#define ASIO_DETAIL_WIN_IOCP_SOCKET_SERVICE_HPP - -#if defined(_MSC_VER) && (_MSC_VER >= 1200) -# pragma once -#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) - -#include "asio/detail/push_options.hpp" - -#include "asio/detail/win_iocp_io_service_fwd.hpp" - -#if defined(ASIO_HAS_IOCP) - -#include "asio/detail/push_options.hpp" -#include -#include -#include -#include -#include "asio/detail/pop_options.hpp" - -#include "asio/buffer.hpp" -#include "asio/error.hpp" -#include "asio/io_service.hpp" -#include "asio/socket_base.hpp" -#include "asio/detail/bind_handler.hpp" -#include "asio/detail/handler_alloc_helpers.hpp" -#include "asio/detail/handler_invoke_helpers.hpp" -#include "asio/detail/mutex.hpp" -#include "asio/detail/select_reactor.hpp" -#include "asio/detail/socket_holder.hpp" -#include "asio/detail/socket_ops.hpp" -#include "asio/detail/socket_types.hpp" -#include "asio/detail/win_iocp_io_service.hpp" - -namespace asio { -namespace detail { - -template -class win_iocp_socket_service - : public asio::detail::service_base > -{ -public: - // The protocol type. - typedef Protocol protocol_type; - - // The endpoint type. - typedef typename Protocol::endpoint endpoint_type; - - // Base class for all operations. - typedef win_iocp_io_service::operation operation; - - struct noop_deleter { void operator()(void*) {} }; - typedef boost::shared_ptr shared_cancel_token_type; - typedef boost::weak_ptr weak_cancel_token_type; - - // The native type of a socket. - class native_type - { - public: - native_type(socket_type s) - : socket_(s), - have_remote_endpoint_(false) - { - } - - native_type(socket_type s, const endpoint_type& ep) - : socket_(s), - have_remote_endpoint_(true), - remote_endpoint_(ep) - { - } - - void operator=(socket_type s) - { - socket_ = s; - have_remote_endpoint_ = false; - remote_endpoint_ = endpoint_type(); - } - - operator socket_type() const - { - return socket_; - } - - HANDLE as_handle() const - { - return reinterpret_cast(socket_); - } - - bool have_remote_endpoint() const - { - return have_remote_endpoint_; - } - - endpoint_type remote_endpoint() const - { - return remote_endpoint_; - } - - private: - socket_type socket_; - bool have_remote_endpoint_; - endpoint_type remote_endpoint_; - }; - - // The type of the reactor used for connect operations. - typedef detail::select_reactor reactor_type; - - // The implementation type of the socket. - class implementation_type - { - public: - // Default constructor. - implementation_type() - : socket_(invalid_socket), - flags_(0), - cancel_token_(), - protocol_(endpoint_type().protocol()), - next_(0), - prev_(0) - { - } - - private: - // Only this service will have access to the internal values. - friend class win_iocp_socket_service; - - // The native socket representation. - native_type socket_; - - enum - { - enable_connection_aborted = 1, // User wants connection_aborted errors. - close_might_block = 2, // User set linger option for blocking close. - user_set_non_blocking = 4 // The user wants a non-blocking socket. - }; - - // Flags indicating the current state of the socket. - unsigned char flags_; - - // We use a shared pointer as a cancellation token here to work around the - // broken Windows support for cancellation. MSDN says that when you call - // closesocket any outstanding WSARecv or WSASend operations will complete - // with the error ERROR_OPERATION_ABORTED. In practice they complete with - // ERROR_NETNAME_DELETED, which means you can't tell the difference between - // a local cancellation and the socket being hard-closed by the peer. - shared_cancel_token_type cancel_token_; - - // The protocol associated with the socket. - protocol_type protocol_; - - // Per-descriptor data used by the reactor. - reactor_type::per_descriptor_data reactor_data_; - -#if defined(ASIO_ENABLE_CANCELIO) - // The ID of the thread from which it is safe to cancel asynchronous - // operations. 0 means no asynchronous operations have been started yet. - // ~0 means asynchronous operations have been started from more than one - // thread, and cancellation is not supported for the socket. - DWORD safe_cancellation_thread_id_; -#endif // defined(ASIO_ENABLE_CANCELIO) - - // Pointers to adjacent socket implementations in linked list. - implementation_type* next_; - implementation_type* prev_; - }; - - // The maximum number of buffers to support in a single operation. - enum { max_buffers = 64 < max_iov_len ? 64 : max_iov_len }; - - // Constructor. - win_iocp_socket_service(asio::io_service& io_service) - : asio::detail::service_base< - win_iocp_socket_service >(io_service), - iocp_service_(asio::use_service(io_service)), - reactor_(0), - mutex_(), - impl_list_(0) - { - } - - // Destroy all user-defined handler objects owned by the service. - void shutdown_service() - { - // Close all implementations, causing all operations to complete. - asio::detail::mutex::scoped_lock lock(mutex_); - implementation_type* impl = impl_list_; - while (impl) - { - asio::error_code ignored_ec; - close_for_destruction(*impl); - impl = impl->next_; - } - } - - // Construct a new socket implementation. - void construct(implementation_type& impl) - { - impl.socket_ = invalid_socket; - impl.flags_ = 0; - impl.cancel_token_.reset(); -#if defined(ASIO_ENABLE_CANCELIO) - impl.safe_cancellation_thread_id_ = 0; -#endif // defined(ASIO_ENABLE_CANCELIO) - - // Insert implementation into linked list of all implementations. - asio::detail::mutex::scoped_lock lock(mutex_); - impl.next_ = impl_list_; - impl.prev_ = 0; - if (impl_list_) - impl_list_->prev_ = &impl; - impl_list_ = &impl; - } - - // Destroy a socket implementation. - void destroy(implementation_type& impl) - { - close_for_destruction(impl); - - // Remove implementation from linked list of all implementations. - asio::detail::mutex::scoped_lock lock(mutex_); - if (impl_list_ == &impl) - impl_list_ = impl.next_; - if (impl.prev_) - impl.prev_->next_ = impl.next_; - if (impl.next_) - impl.next_->prev_= impl.prev_; - impl.next_ = 0; - impl.prev_ = 0; - } - - // Open a new socket implementation. - asio::error_code open(implementation_type& impl, - const protocol_type& protocol, asio::error_code& ec) - { - if (is_open(impl)) - { - ec = asio::error::already_open; - return ec; - } - - socket_holder sock(socket_ops::socket(protocol.family(), protocol.type(), - protocol.protocol(), ec)); - if (sock.get() == invalid_socket) - return ec; - - HANDLE sock_as_handle = reinterpret_cast(sock.get()); - if (iocp_service_.register_handle(sock_as_handle, ec)) - return ec; - - impl.socket_ = sock.release(); - impl.flags_ = 0; - impl.cancel_token_.reset(static_cast(0), noop_deleter()); - impl.protocol_ = protocol; - ec = asio::error_code(); - return ec; - } - - // Assign a native socket to a socket implementation. - asio::error_code assign(implementation_type& impl, - const protocol_type& protocol, const native_type& native_socket, - asio::error_code& ec) - { - if (is_open(impl)) - { - ec = asio::error::already_open; - return ec; - } - - if (iocp_service_.register_handle(native_socket.as_handle(), ec)) - return ec; - - impl.socket_ = native_socket; - impl.flags_ = 0; - impl.cancel_token_.reset(static_cast(0), noop_deleter()); - impl.protocol_ = protocol; - ec = asio::error_code(); - return ec; - } - - // Determine whether the socket is open. - bool is_open(const implementation_type& impl) const - { - return impl.socket_ != invalid_socket; - } - - // Destroy a socket implementation. - asio::error_code close(implementation_type& impl, - asio::error_code& ec) - { - if (is_open(impl)) - { - // Check if the reactor was created, in which case we need to close the - // socket on the reactor as well to cancel any operations that might be - // running there. - reactor_type* reactor = static_cast( - interlocked_compare_exchange_pointer( - reinterpret_cast(&reactor_), 0, 0)); - if (reactor) - reactor->close_descriptor(impl.socket_, impl.reactor_data_); - - if (socket_ops::close(impl.socket_, ec) == socket_error_retval) - return ec; - - impl.socket_ = invalid_socket; - impl.flags_ = 0; - impl.cancel_token_.reset(); -#if defined(ASIO_ENABLE_CANCELIO) - impl.safe_cancellation_thread_id_ = 0; -#endif // defined(ASIO_ENABLE_CANCELIO) - } - - ec = asio::error_code(); - return ec; - } - - // Get the native socket representation. - native_type native(implementation_type& impl) - { - return impl.socket_; - } - - // Cancel all operations associated with the socket. - asio::error_code cancel(implementation_type& impl, - asio::error_code& ec) - { - if (!is_open(impl)) - { - ec = asio::error::bad_descriptor; - return ec; - } - else if (FARPROC cancel_io_ex_ptr = ::GetProcAddress( - ::GetModuleHandleA("KERNEL32"), "CancelIoEx")) - { - // The version of Windows supports cancellation from any thread. - typedef BOOL (WINAPI* cancel_io_ex_t)(HANDLE, LPOVERLAPPED); - cancel_io_ex_t cancel_io_ex = (cancel_io_ex_t)cancel_io_ex_ptr; - socket_type sock = impl.socket_; - HANDLE sock_as_handle = reinterpret_cast(sock); - if (!cancel_io_ex(sock_as_handle, 0)) - { - DWORD last_error = ::GetLastError(); - if (last_error == ERROR_NOT_FOUND) - { - // ERROR_NOT_FOUND means that there were no operations to be - // cancelled. We swallow this error to match the behaviour on other - // platforms. - ec = asio::error_code(); - } - else - { - ec = asio::error_code(last_error, - asio::error::get_system_category()); - } - } - else - { - ec = asio::error_code(); - } - } -#if defined(ASIO_ENABLE_CANCELIO) - else if (impl.safe_cancellation_thread_id_ == 0) - { - // No operations have been started, so there's nothing to cancel. - ec = asio::error_code(); - } - else if (impl.safe_cancellation_thread_id_ == ::GetCurrentThreadId()) - { - // Asynchronous operations have been started from the current thread only, - // so it is safe to try to cancel them using CancelIo. - socket_type sock = impl.socket_; - HANDLE sock_as_handle = reinterpret_cast(sock); - if (!::CancelIo(sock_as_handle)) - { - DWORD last_error = ::GetLastError(); - ec = asio::error_code(last_error, - asio::error::get_system_category()); - } - else - { - ec = asio::error_code(); - } - } - else - { - // Asynchronous operations have been started from more than one thread, - // so cancellation is not safe. - ec = asio::error::operation_not_supported; - } -#else // defined(ASIO_ENABLE_CANCELIO) - else - { - // Cancellation is not supported as CancelIo may not be used. - ec = asio::error::operation_not_supported; - } -#endif // defined(ASIO_ENABLE_CANCELIO) - - return ec; - } - - // Determine whether the socket is at the out-of-band data mark. - bool at_mark(const implementation_type& impl, - asio::error_code& ec) const - { - if (!is_open(impl)) - { - ec = asio::error::bad_descriptor; - return false; - } - - asio::detail::ioctl_arg_type value = 0; - socket_ops::ioctl(impl.socket_, SIOCATMARK, &value, ec); - return ec ? false : value != 0; - } - - // Determine the number of bytes available for reading. - std::size_t available(const implementation_type& impl, - asio::error_code& ec) const - { - if (!is_open(impl)) - { - ec = asio::error::bad_descriptor; - return 0; - } - - asio::detail::ioctl_arg_type value = 0; - socket_ops::ioctl(impl.socket_, FIONREAD, &value, ec); - return ec ? static_cast(0) : static_cast(value); - } - - // Bind the socket to the specified local endpoint. - asio::error_code bind(implementation_type& impl, - const endpoint_type& endpoint, asio::error_code& ec) - { - if (!is_open(impl)) - { - ec = asio::error::bad_descriptor; - return ec; - } - - socket_ops::bind(impl.socket_, endpoint.data(), endpoint.size(), ec); - return ec; - } - - // Place the socket into the state where it will listen for new connections. - asio::error_code listen(implementation_type& impl, int backlog, - asio::error_code& ec) - { - if (!is_open(impl)) - { - ec = asio::error::bad_descriptor; - return ec; - } - - socket_ops::listen(impl.socket_, backlog, ec); - return ec; - } - - // Set a socket option. - template - asio::error_code set_option(implementation_type& impl, - const Option& option, asio::error_code& ec) - { - if (!is_open(impl)) - { - ec = asio::error::bad_descriptor; - return ec; - } - - if (option.level(impl.protocol_) == custom_socket_option_level - && option.name(impl.protocol_) == enable_connection_aborted_option) - { - if (option.size(impl.protocol_) != sizeof(int)) - { - ec = asio::error::invalid_argument; - } - else - { - if (*reinterpret_cast(option.data(impl.protocol_))) - impl.flags_ |= implementation_type::enable_connection_aborted; - else - impl.flags_ &= ~implementation_type::enable_connection_aborted; - ec = asio::error_code(); - } - return ec; - } - else - { - if (option.level(impl.protocol_) == SOL_SOCKET - && option.name(impl.protocol_) == SO_LINGER) - { - const ::linger* linger_option = - reinterpret_cast(option.data(impl.protocol_)); - if (linger_option->l_onoff != 0 && linger_option->l_linger != 0) - impl.flags_ |= implementation_type::close_might_block; - else - impl.flags_ &= ~implementation_type::close_might_block; - } - - socket_ops::setsockopt(impl.socket_, - option.level(impl.protocol_), option.name(impl.protocol_), - option.data(impl.protocol_), option.size(impl.protocol_), ec); - return ec; - } - } - - // Set a socket option. - template - asio::error_code get_option(const implementation_type& impl, - Option& option, asio::error_code& ec) const - { - if (!is_open(impl)) - { - ec = asio::error::bad_descriptor; - return ec; - } - - if (option.level(impl.protocol_) == custom_socket_option_level - && option.name(impl.protocol_) == enable_connection_aborted_option) - { - if (option.size(impl.protocol_) != sizeof(int)) - { - ec = asio::error::invalid_argument; - } - else - { - int* target = reinterpret_cast(option.data(impl.protocol_)); - if (impl.flags_ & implementation_type::enable_connection_aborted) - *target = 1; - else - *target = 0; - option.resize(impl.protocol_, sizeof(int)); - ec = asio::error_code(); - } - return ec; - } - else - { - size_t size = option.size(impl.protocol_); - socket_ops::getsockopt(impl.socket_, - option.level(impl.protocol_), option.name(impl.protocol_), - option.data(impl.protocol_), &size, ec); - if (!ec) - option.resize(impl.protocol_, size); - return ec; - } - } - - // Perform an IO control command on the socket. - template - asio::error_code io_control(implementation_type& impl, - IO_Control_Command& command, asio::error_code& ec) - { - if (!is_open(impl)) - { - ec = asio::error::bad_descriptor; - return ec; - } - - socket_ops::ioctl(impl.socket_, command.name(), - static_cast(command.data()), ec); - - if (!ec && command.name() == static_cast(FIONBIO)) - { - if (command.get()) - impl.flags_ |= implementation_type::user_set_non_blocking; - else - impl.flags_ &= ~implementation_type::user_set_non_blocking; - } - - return ec; - } - - // Get the local endpoint. - endpoint_type local_endpoint(const implementation_type& impl, - asio::error_code& ec) const - { - if (!is_open(impl)) - { - ec = asio::error::bad_descriptor; - return endpoint_type(); - } - - endpoint_type endpoint; - std::size_t addr_len = endpoint.capacity(); - if (socket_ops::getsockname(impl.socket_, endpoint.data(), &addr_len, ec)) - return endpoint_type(); - endpoint.resize(addr_len); - return endpoint; - } - - // Get the remote endpoint. - endpoint_type remote_endpoint(const implementation_type& impl, - asio::error_code& ec) const - { - if (!is_open(impl)) - { - ec = asio::error::bad_descriptor; - return endpoint_type(); - } - - if (impl.socket_.have_remote_endpoint()) - { - // Check if socket is still connected. - DWORD connect_time = 0; - size_t connect_time_len = sizeof(connect_time); - if (socket_ops::getsockopt(impl.socket_, SOL_SOCKET, SO_CONNECT_TIME, - &connect_time, &connect_time_len, ec) == socket_error_retval) - { - return endpoint_type(); - } - if (connect_time == 0xFFFFFFFF) - { - ec = asio::error::not_connected; - return endpoint_type(); - } - - ec = asio::error_code(); - return impl.socket_.remote_endpoint(); - } - else - { - endpoint_type endpoint; - std::size_t addr_len = endpoint.capacity(); - if (socket_ops::getpeername(impl.socket_, endpoint.data(), &addr_len, ec)) - return endpoint_type(); - endpoint.resize(addr_len); - return endpoint; - } - } - - /// Disable sends or receives on the socket. - asio::error_code shutdown(implementation_type& impl, - socket_base::shutdown_type what, asio::error_code& ec) - { - if (!is_open(impl)) - { - ec = asio::error::bad_descriptor; - return ec; - } - - socket_ops::shutdown(impl.socket_, what, ec); - return ec; - } - - // Send the given data to the peer. Returns the number of bytes sent. - template - size_t send(implementation_type& impl, const ConstBufferSequence& buffers, - socket_base::message_flags flags, asio::error_code& ec) - { - if (!is_open(impl)) - { - ec = asio::error::bad_descriptor; - return 0; - } - - // Copy buffers into WSABUF array. - ::WSABUF bufs[max_buffers]; - typename ConstBufferSequence::const_iterator iter = buffers.begin(); - typename ConstBufferSequence::const_iterator end = buffers.end(); - DWORD i = 0; - size_t total_buffer_size = 0; - for (; iter != end && i < max_buffers; ++iter, ++i) - { - asio::const_buffer buffer(*iter); - bufs[i].len = static_cast(asio::buffer_size(buffer)); - bufs[i].buf = const_cast( - asio::buffer_cast(buffer)); - total_buffer_size += asio::buffer_size(buffer); - } - - // A request to receive 0 bytes on a stream socket is a no-op. - if (impl.protocol_.type() == SOCK_STREAM && total_buffer_size == 0) - { - ec = asio::error_code(); - return 0; - } - - // Send the data. - DWORD bytes_transferred = 0; - int result = ::WSASend(impl.socket_, bufs, - i, &bytes_transferred, flags, 0, 0); - if (result != 0) - { - DWORD last_error = ::WSAGetLastError(); - if (last_error == ERROR_NETNAME_DELETED) - last_error = WSAECONNRESET; - else if (last_error == ERROR_PORT_UNREACHABLE) - last_error = WSAECONNREFUSED; - ec = asio::error_code(last_error, - asio::error::get_system_category()); - return 0; - } - - ec = asio::error_code(); - return bytes_transferred; - } - - // Wait until data can be sent without blocking. - size_t send(implementation_type& impl, const null_buffers&, - socket_base::message_flags, asio::error_code& ec) - { - if (!is_open(impl)) - { - ec = asio::error::bad_descriptor; - return 0; - } - - // Wait for socket to become ready. - socket_ops::poll_write(impl.socket_, ec); - - return 0; - } - - template - class send_operation - : public operation - { - public: - send_operation(win_iocp_io_service& io_service, - weak_cancel_token_type cancel_token, - const ConstBufferSequence& buffers, Handler handler) - : operation(io_service, - &send_operation::do_completion_impl, - &send_operation::destroy_impl), - work_(io_service.get_io_service()), - cancel_token_(cancel_token), - buffers_(buffers), - handler_(handler) - { - } - - private: - static void do_completion_impl(operation* op, - DWORD last_error, size_t bytes_transferred) - { - // Take ownership of the operation object. - typedef send_operation op_type; - op_type* handler_op(static_cast(op)); - typedef handler_alloc_traits alloc_traits; - handler_ptr ptr(handler_op->handler_, handler_op); - -#if defined(ASIO_ENABLE_BUFFER_DEBUGGING) - // Check whether buffers are still valid. - typename ConstBufferSequence::const_iterator iter - = handler_op->buffers_.begin(); - typename ConstBufferSequence::const_iterator end - = handler_op->buffers_.end(); - while (iter != end) - { - asio::const_buffer buffer(*iter); - asio::buffer_cast(buffer); - ++iter; - } -#endif // defined(ASIO_ENABLE_BUFFER_DEBUGGING) - - // Map non-portable errors to their portable counterparts. - asio::error_code ec(last_error, - asio::error::get_system_category()); - if (ec.value() == ERROR_NETNAME_DELETED) - { - if (handler_op->cancel_token_.expired()) - ec = asio::error::operation_aborted; - else - ec = asio::error::connection_reset; - } - else if (ec.value() == ERROR_PORT_UNREACHABLE) - { - ec = asio::error::connection_refused; - } - - // Make a copy of the handler so that the memory can be deallocated before - // the upcall is made. - Handler handler(handler_op->handler_); - - // Free the memory associated with the handler. - ptr.reset(); - - // Call the handler. - asio_handler_invoke_helpers::invoke( - detail::bind_handler(handler, ec, bytes_transferred), &handler); - } - - static void destroy_impl(operation* op) - { - // Take ownership of the operation object. - typedef send_operation op_type; - op_type* handler_op(static_cast(op)); - typedef handler_alloc_traits alloc_traits; - handler_ptr ptr(handler_op->handler_, handler_op); - - // A sub-object of the handler may be the true owner of the memory - // associated with the handler. Consequently, a local copy of the handler - // is required to ensure that any owning sub-object remains valid until - // after we have deallocated the memory here. - Handler handler(handler_op->handler_); - (void)handler; - - // Free the memory associated with the handler. - ptr.reset(); - } - - asio::io_service::work work_; - weak_cancel_token_type cancel_token_; - ConstBufferSequence buffers_; - Handler handler_; - }; - - // Start an asynchronous send. The data being sent must be valid for the - // lifetime of the asynchronous operation. - template - void async_send(implementation_type& impl, const ConstBufferSequence& buffers, - socket_base::message_flags flags, Handler handler) - { - if (!is_open(impl)) - { - this->get_io_service().post(bind_handler(handler, - asio::error::bad_descriptor, 0)); - return; - } - -#if defined(ASIO_ENABLE_CANCELIO) - // Update the ID of the thread from which cancellation is safe. - if (impl.safe_cancellation_thread_id_ == 0) - impl.safe_cancellation_thread_id_ = ::GetCurrentThreadId(); - else if (impl.safe_cancellation_thread_id_ != ::GetCurrentThreadId()) - impl.safe_cancellation_thread_id_ = ~DWORD(0); -#endif // defined(ASIO_ENABLE_CANCELIO) - - // Allocate and construct an operation to wrap the handler. - typedef send_operation value_type; - typedef handler_alloc_traits alloc_traits; - raw_handler_ptr raw_ptr(handler); - handler_ptr ptr(raw_ptr, iocp_service_, - impl.cancel_token_, buffers, handler); - - // Copy buffers into WSABUF array. - ::WSABUF bufs[max_buffers]; - typename ConstBufferSequence::const_iterator iter = buffers.begin(); - typename ConstBufferSequence::const_iterator end = buffers.end(); - DWORD i = 0; - size_t total_buffer_size = 0; - for (; iter != end && i < max_buffers; ++iter, ++i) - { - asio::const_buffer buffer(*iter); - bufs[i].len = static_cast(asio::buffer_size(buffer)); - bufs[i].buf = const_cast( - asio::buffer_cast(buffer)); - total_buffer_size += asio::buffer_size(buffer); - } - - // A request to receive 0 bytes on a stream socket is a no-op. - if (impl.protocol_.type() == SOCK_STREAM && total_buffer_size == 0) - { - asio::io_service::work work(this->get_io_service()); - ptr.reset(); - asio::error_code error; - iocp_service_.post(bind_handler(handler, error, 0)); - return; - } - - // Send the data. - DWORD bytes_transferred = 0; - int result = ::WSASend(impl.socket_, bufs, i, - &bytes_transferred, flags, ptr.get(), 0); - DWORD last_error = ::WSAGetLastError(); - - // Check if the operation completed immediately. - if (result != 0 && last_error != WSA_IO_PENDING) - { - asio::io_service::work work(this->get_io_service()); - ptr.reset(); - asio::error_code ec(last_error, - asio::error::get_system_category()); - iocp_service_.post(bind_handler(handler, ec, bytes_transferred)); - } - else - { - ptr.release(); - } - } - - template - class null_buffers_operation - { - public: - null_buffers_operation(asio::io_service& io_service, Handler handler) - : work_(io_service), - handler_(handler) - { - } - - bool perform(asio::error_code&, - std::size_t& bytes_transferred) - { - bytes_transferred = 0; - return true; - } - - void complete(const asio::error_code& ec, - std::size_t bytes_transferred) - { - work_.get_io_service().post(bind_handler( - handler_, ec, bytes_transferred)); - } - - private: - asio::io_service::work work_; - Handler handler_; - }; - - // Start an asynchronous wait until data can be sent without blocking. - template - void async_send(implementation_type& impl, const null_buffers&, - socket_base::message_flags, Handler handler) - { - if (!is_open(impl)) - { - this->get_io_service().post(bind_handler(handler, - asio::error::bad_descriptor, 0)); - } - else - { - // Check if the reactor was already obtained from the io_service. - reactor_type* reactor = static_cast( - interlocked_compare_exchange_pointer( - reinterpret_cast(&reactor_), 0, 0)); - if (!reactor) - { - reactor = &(asio::use_service( - this->get_io_service())); - interlocked_exchange_pointer( - reinterpret_cast(&reactor_), reactor); - } - - reactor->start_write_op(impl.socket_, impl.reactor_data_, - null_buffers_operation(this->get_io_service(), handler), - false); - } - } - - // Send a datagram to the specified endpoint. Returns the number of bytes - // sent. - template - size_t send_to(implementation_type& impl, const ConstBufferSequence& buffers, - const endpoint_type& destination, socket_base::message_flags flags, - asio::error_code& ec) - { - if (!is_open(impl)) - { - ec = asio::error::bad_descriptor; - return 0; - } - - // Copy buffers into WSABUF array. - ::WSABUF bufs[max_buffers]; - typename ConstBufferSequence::const_iterator iter = buffers.begin(); - typename ConstBufferSequence::const_iterator end = buffers.end(); - DWORD i = 0; - for (; iter != end && i < max_buffers; ++iter, ++i) - { - asio::const_buffer buffer(*iter); - bufs[i].len = static_cast(asio::buffer_size(buffer)); - bufs[i].buf = const_cast( - asio::buffer_cast(buffer)); - } - - // Send the data. - DWORD bytes_transferred = 0; - int result = ::WSASendTo(impl.socket_, bufs, i, &bytes_transferred, - flags, destination.data(), static_cast(destination.size()), 0, 0); - if (result != 0) - { - DWORD last_error = ::WSAGetLastError(); - if (last_error == ERROR_PORT_UNREACHABLE) - last_error = WSAECONNREFUSED; - ec = asio::error_code(last_error, - asio::error::get_system_category()); - return 0; - } - - ec = asio::error_code(); - return bytes_transferred; - } - - // Wait until data can be sent without blocking. - size_t send_to(implementation_type& impl, const null_buffers&, - socket_base::message_flags, const endpoint_type&, - asio::error_code& ec) - { - if (!is_open(impl)) - { - ec = asio::error::bad_descriptor; - return 0; - } - - // Wait for socket to become ready. - socket_ops::poll_write(impl.socket_, ec); - - return 0; - } - - template - class send_to_operation - : public operation - { - public: - send_to_operation(win_iocp_io_service& io_service, - const ConstBufferSequence& buffers, Handler handler) - : operation(io_service, - &send_to_operation::do_completion_impl, - &send_to_operation::destroy_impl), - work_(io_service.get_io_service()), - buffers_(buffers), - handler_(handler) - { - } - - private: - static void do_completion_impl(operation* op, - DWORD last_error, size_t bytes_transferred) - { - // Take ownership of the operation object. - typedef send_to_operation op_type; - op_type* handler_op(static_cast(op)); - typedef handler_alloc_traits alloc_traits; - handler_ptr ptr(handler_op->handler_, handler_op); - -#if defined(ASIO_ENABLE_BUFFER_DEBUGGING) - // Check whether buffers are still valid. - typename ConstBufferSequence::const_iterator iter - = handler_op->buffers_.begin(); - typename ConstBufferSequence::const_iterator end - = handler_op->buffers_.end(); - while (iter != end) - { - asio::const_buffer buffer(*iter); - asio::buffer_cast(buffer); - ++iter; - } -#endif // defined(ASIO_ENABLE_BUFFER_DEBUGGING) - - // Map non-portable errors to their portable counterparts. - asio::error_code ec(last_error, - asio::error::get_system_category()); - if (ec.value() == ERROR_PORT_UNREACHABLE) - { - ec = asio::error::connection_refused; - } - - // Make a copy of the handler so that the memory can be deallocated before - // the upcall is made. - Handler handler(handler_op->handler_); - - // Free the memory associated with the handler. - ptr.reset(); - - // Call the handler. - asio_handler_invoke_helpers::invoke( - detail::bind_handler(handler, ec, bytes_transferred), &handler); - } - - static void destroy_impl(operation* op) - { - // Take ownership of the operation object. - typedef send_to_operation op_type; - op_type* handler_op(static_cast(op)); - typedef handler_alloc_traits alloc_traits; - handler_ptr ptr(handler_op->handler_, handler_op); - - // A sub-object of the handler may be the true owner of the memory - // associated with the handler. Consequently, a local copy of the handler - // is required to ensure that any owning sub-object remains valid until - // after we have deallocated the memory here. - Handler handler(handler_op->handler_); - (void)handler; - - // Free the memory associated with the handler. - ptr.reset(); - } - - asio::io_service::work work_; - ConstBufferSequence buffers_; - Handler handler_; - }; - - // Start an asynchronous send. The data being sent must be valid for the - // lifetime of the asynchronous operation. - template - void async_send_to(implementation_type& impl, - const ConstBufferSequence& buffers, const endpoint_type& destination, - socket_base::message_flags flags, Handler handler) - { - if (!is_open(impl)) - { - this->get_io_service().post(bind_handler(handler, - asio::error::bad_descriptor, 0)); - return; - } - -#if defined(ASIO_ENABLE_CANCELIO) - // Update the ID of the thread from which cancellation is safe. - if (impl.safe_cancellation_thread_id_ == 0) - impl.safe_cancellation_thread_id_ = ::GetCurrentThreadId(); - else if (impl.safe_cancellation_thread_id_ != ::GetCurrentThreadId()) - impl.safe_cancellation_thread_id_ = ~DWORD(0); -#endif // defined(ASIO_ENABLE_CANCELIO) - - // Allocate and construct an operation to wrap the handler. - typedef send_to_operation value_type; - typedef handler_alloc_traits alloc_traits; - raw_handler_ptr raw_ptr(handler); - handler_ptr ptr(raw_ptr, iocp_service_, buffers, handler); - - // Copy buffers into WSABUF array. - ::WSABUF bufs[max_buffers]; - typename ConstBufferSequence::const_iterator iter = buffers.begin(); - typename ConstBufferSequence::const_iterator end = buffers.end(); - DWORD i = 0; - for (; iter != end && i < max_buffers; ++iter, ++i) - { - asio::const_buffer buffer(*iter); - bufs[i].len = static_cast(asio::buffer_size(buffer)); - bufs[i].buf = const_cast( - asio::buffer_cast(buffer)); - } - - // Send the data. - DWORD bytes_transferred = 0; - int result = ::WSASendTo(impl.socket_, bufs, i, &bytes_transferred, flags, - destination.data(), static_cast(destination.size()), ptr.get(), 0); - DWORD last_error = ::WSAGetLastError(); - - // Check if the operation completed immediately. - if (result != 0 && last_error != WSA_IO_PENDING) - { - asio::io_service::work work(this->get_io_service()); - ptr.reset(); - asio::error_code ec(last_error, - asio::error::get_system_category()); - iocp_service_.post(bind_handler(handler, ec, bytes_transferred)); - } - else - { - ptr.release(); - } - } - - // Start an asynchronous wait until data can be sent without blocking. - template - void async_send_to(implementation_type& impl, const null_buffers&, - socket_base::message_flags, const endpoint_type&, Handler handler) - { - if (!is_open(impl)) - { - this->get_io_service().post(bind_handler(handler, - asio::error::bad_descriptor, 0)); - } - else - { - // Check if the reactor was already obtained from the io_service. - reactor_type* reactor = static_cast( - interlocked_compare_exchange_pointer( - reinterpret_cast(&reactor_), 0, 0)); - if (!reactor) - { - reactor = &(asio::use_service( - this->get_io_service())); - interlocked_exchange_pointer( - reinterpret_cast(&reactor_), reactor); - } - - reactor->start_write_op(impl.socket_, impl.reactor_data_, - null_buffers_operation(this->get_io_service(), handler), - false); - } - } - - // Receive some data from the peer. Returns the number of bytes received. - template - size_t receive(implementation_type& impl, - const MutableBufferSequence& buffers, - socket_base::message_flags flags, asio::error_code& ec) - { - if (!is_open(impl)) - { - ec = asio::error::bad_descriptor; - return 0; - } - - // Copy buffers into WSABUF array. - ::WSABUF bufs[max_buffers]; - typename MutableBufferSequence::const_iterator iter = buffers.begin(); - typename MutableBufferSequence::const_iterator end = buffers.end(); - DWORD i = 0; - size_t total_buffer_size = 0; - for (; iter != end && i < max_buffers; ++iter, ++i) - { - asio::mutable_buffer buffer(*iter); - bufs[i].len = static_cast(asio::buffer_size(buffer)); - bufs[i].buf = asio::buffer_cast(buffer); - total_buffer_size += asio::buffer_size(buffer); - } - - // A request to receive 0 bytes on a stream socket is a no-op. - if (impl.protocol_.type() == SOCK_STREAM && total_buffer_size == 0) - { - ec = asio::error_code(); - return 0; - } - - // Receive some data. - DWORD bytes_transferred = 0; - DWORD recv_flags = flags; - int result = ::WSARecv(impl.socket_, bufs, i, - &bytes_transferred, &recv_flags, 0, 0); - if (result != 0) - { - DWORD last_error = ::WSAGetLastError(); - if (last_error == ERROR_NETNAME_DELETED) - last_error = WSAECONNRESET; - else if (last_error == ERROR_PORT_UNREACHABLE) - last_error = WSAECONNREFUSED; - ec = asio::error_code(last_error, - asio::error::get_system_category()); - return 0; - } - if (bytes_transferred == 0 && impl.protocol_.type() == SOCK_STREAM) - { - ec = asio::error::eof; - return 0; - } - - ec = asio::error_code(); - return bytes_transferred; - } - - // Wait until data can be received without blocking. - size_t receive(implementation_type& impl, const null_buffers&, - socket_base::message_flags, asio::error_code& ec) - { - if (!is_open(impl)) - { - ec = asio::error::bad_descriptor; - return 0; - } - - // Wait for socket to become ready. - socket_ops::poll_read(impl.socket_, ec); - - return 0; - } - - template - class receive_operation - : public operation - { - public: - receive_operation(int protocol_type, win_iocp_io_service& io_service, - weak_cancel_token_type cancel_token, - const MutableBufferSequence& buffers, Handler handler) - : operation(io_service, - &receive_operation< - MutableBufferSequence, Handler>::do_completion_impl, - &receive_operation< - MutableBufferSequence, Handler>::destroy_impl), - protocol_type_(protocol_type), - work_(io_service.get_io_service()), - cancel_token_(cancel_token), - buffers_(buffers), - handler_(handler) - { - } - - private: - static void do_completion_impl(operation* op, - DWORD last_error, size_t bytes_transferred) - { - // Take ownership of the operation object. - typedef receive_operation op_type; - op_type* handler_op(static_cast(op)); - typedef handler_alloc_traits alloc_traits; - handler_ptr ptr(handler_op->handler_, handler_op); - -#if defined(ASIO_ENABLE_BUFFER_DEBUGGING) - // Check whether buffers are still valid. - typename MutableBufferSequence::const_iterator iter - = handler_op->buffers_.begin(); - typename MutableBufferSequence::const_iterator end - = handler_op->buffers_.end(); - while (iter != end) - { - asio::mutable_buffer buffer(*iter); - asio::buffer_cast(buffer); - ++iter; - } -#endif // defined(ASIO_ENABLE_BUFFER_DEBUGGING) - - // Map non-portable errors to their portable counterparts. - asio::error_code ec(last_error, - asio::error::get_system_category()); - if (ec.value() == ERROR_NETNAME_DELETED) - { - if (handler_op->cancel_token_.expired()) - ec = asio::error::operation_aborted; - else - ec = asio::error::connection_reset; - } - else if (ec.value() == ERROR_PORT_UNREACHABLE) - { - ec = asio::error::connection_refused; - } - - // Check for connection closed. - else if (!ec && bytes_transferred == 0 - && handler_op->protocol_type_ == SOCK_STREAM - && !boost::is_same::value) - { - ec = asio::error::eof; - } - - // Make a copy of the handler so that the memory can be deallocated before - // the upcall is made. - Handler handler(handler_op->handler_); - - // Free the memory associated with the handler. - ptr.reset(); - - // Call the handler. - asio_handler_invoke_helpers::invoke( - detail::bind_handler(handler, ec, bytes_transferred), &handler); - } - - static void destroy_impl(operation* op) - { - // Take ownership of the operation object. - typedef receive_operation op_type; - op_type* handler_op(static_cast(op)); - typedef handler_alloc_traits alloc_traits; - handler_ptr ptr(handler_op->handler_, handler_op); - - // A sub-object of the handler may be the true owner of the memory - // associated with the handler. Consequently, a local copy of the handler - // is required to ensure that any owning sub-object remains valid until - // after we have deallocated the memory here. - Handler handler(handler_op->handler_); - (void)handler; - - // Free the memory associated with the handler. - ptr.reset(); - } - - int protocol_type_; - asio::io_service::work work_; - weak_cancel_token_type cancel_token_; - MutableBufferSequence buffers_; - Handler handler_; - }; - - // Start an asynchronous receive. The buffer for the data being received - // must be valid for the lifetime of the asynchronous operation. - template - void async_receive(implementation_type& impl, - const MutableBufferSequence& buffers, - socket_base::message_flags flags, Handler handler) - { - if (!is_open(impl)) - { - this->get_io_service().post(bind_handler(handler, - asio::error::bad_descriptor, 0)); - return; - } - -#if defined(ASIO_ENABLE_CANCELIO) - // Update the ID of the thread from which cancellation is safe. - if (impl.safe_cancellation_thread_id_ == 0) - impl.safe_cancellation_thread_id_ = ::GetCurrentThreadId(); - else if (impl.safe_cancellation_thread_id_ != ::GetCurrentThreadId()) - impl.safe_cancellation_thread_id_ = ~DWORD(0); -#endif // defined(ASIO_ENABLE_CANCELIO) - - // Allocate and construct an operation to wrap the handler. - typedef receive_operation value_type; - typedef handler_alloc_traits alloc_traits; - raw_handler_ptr raw_ptr(handler); - int protocol_type = impl.protocol_.type(); - handler_ptr ptr(raw_ptr, protocol_type, - iocp_service_, impl.cancel_token_, buffers, handler); - - // Copy buffers into WSABUF array. - ::WSABUF bufs[max_buffers]; - typename MutableBufferSequence::const_iterator iter = buffers.begin(); - typename MutableBufferSequence::const_iterator end = buffers.end(); - DWORD i = 0; - size_t total_buffer_size = 0; - for (; iter != end && i < max_buffers; ++iter, ++i) - { - asio::mutable_buffer buffer(*iter); - bufs[i].len = static_cast(asio::buffer_size(buffer)); - bufs[i].buf = asio::buffer_cast(buffer); - total_buffer_size += asio::buffer_size(buffer); - } - - // A request to receive 0 bytes on a stream socket is a no-op. - if (impl.protocol_.type() == SOCK_STREAM && total_buffer_size == 0) - { - asio::io_service::work work(this->get_io_service()); - ptr.reset(); - asio::error_code error; - iocp_service_.post(bind_handler(handler, error, 0)); - return; - } - - // Receive some data. - DWORD bytes_transferred = 0; - DWORD recv_flags = flags; - int result = ::WSARecv(impl.socket_, bufs, i, - &bytes_transferred, &recv_flags, ptr.get(), 0); - DWORD last_error = ::WSAGetLastError(); - if (result != 0 && last_error != WSA_IO_PENDING) - { - asio::io_service::work work(this->get_io_service()); - ptr.reset(); - asio::error_code ec(last_error, - asio::error::get_system_category()); - iocp_service_.post(bind_handler(handler, ec, bytes_transferred)); - } - else - { - ptr.release(); - } - } - - // Wait until data can be received without blocking. - template - void async_receive(implementation_type& impl, const null_buffers& buffers, - socket_base::message_flags flags, Handler handler) - { - if (!is_open(impl)) - { - this->get_io_service().post(bind_handler(handler, - asio::error::bad_descriptor, 0)); - } - else if (impl.protocol_.type() == SOCK_STREAM) - { - // For stream sockets on Windows, we may issue a 0-byte overlapped - // WSARecv to wait until there is data available on the socket. - -#if defined(ASIO_ENABLE_CANCELIO) - // Update the ID of the thread from which cancellation is safe. - if (impl.safe_cancellation_thread_id_ == 0) - impl.safe_cancellation_thread_id_ = ::GetCurrentThreadId(); - else if (impl.safe_cancellation_thread_id_ != ::GetCurrentThreadId()) - impl.safe_cancellation_thread_id_ = ~DWORD(0); -#endif // defined(ASIO_ENABLE_CANCELIO) - - // Allocate and construct an operation to wrap the handler. - typedef receive_operation value_type; - typedef handler_alloc_traits alloc_traits; - raw_handler_ptr raw_ptr(handler); - int protocol_type = impl.protocol_.type(); - handler_ptr ptr(raw_ptr, protocol_type, - iocp_service_, impl.cancel_token_, buffers, handler); - - // Issue a receive operation with an empty buffer. - ::WSABUF buf = { 0, 0 }; - DWORD bytes_transferred = 0; - DWORD recv_flags = flags; - int result = ::WSARecv(impl.socket_, &buf, 1, - &bytes_transferred, &recv_flags, ptr.get(), 0); - DWORD last_error = ::WSAGetLastError(); - if (result != 0 && last_error != WSA_IO_PENDING) - { - asio::io_service::work work(this->get_io_service()); - ptr.reset(); - asio::error_code ec(last_error, - asio::error::get_system_category()); - iocp_service_.post(bind_handler(handler, ec, bytes_transferred)); - } - else - { - ptr.release(); - } - } - else - { - // Check if the reactor was already obtained from the io_service. - reactor_type* reactor = static_cast( - interlocked_compare_exchange_pointer( - reinterpret_cast(&reactor_), 0, 0)); - if (!reactor) - { - reactor = &(asio::use_service( - this->get_io_service())); - interlocked_exchange_pointer( - reinterpret_cast(&reactor_), reactor); - } - - if (flags & socket_base::message_out_of_band) - { - reactor->start_except_op(impl.socket_, impl.reactor_data_, - null_buffers_operation(this->get_io_service(), handler)); - } - else - { - reactor->start_read_op(impl.socket_, impl.reactor_data_, - null_buffers_operation(this->get_io_service(), handler), - false); - } - } - } - - // Receive a datagram with the endpoint of the sender. Returns the number of - // bytes received. - template - size_t receive_from(implementation_type& impl, - const MutableBufferSequence& buffers, - endpoint_type& sender_endpoint, socket_base::message_flags flags, - asio::error_code& ec) - { - if (!is_open(impl)) - { - ec = asio::error::bad_descriptor; - return 0; - } - - // Copy buffers into WSABUF array. - ::WSABUF bufs[max_buffers]; - typename MutableBufferSequence::const_iterator iter = buffers.begin(); - typename MutableBufferSequence::const_iterator end = buffers.end(); - DWORD i = 0; - for (; iter != end && i < max_buffers; ++iter, ++i) - { - asio::mutable_buffer buffer(*iter); - bufs[i].len = static_cast(asio::buffer_size(buffer)); - bufs[i].buf = asio::buffer_cast(buffer); - } - - // Receive some data. - DWORD bytes_transferred = 0; - DWORD recv_flags = flags; - int endpoint_size = static_cast(sender_endpoint.capacity()); - int result = ::WSARecvFrom(impl.socket_, bufs, i, &bytes_transferred, - &recv_flags, sender_endpoint.data(), &endpoint_size, 0, 0); - if (result != 0) - { - DWORD last_error = ::WSAGetLastError(); - if (last_error == ERROR_PORT_UNREACHABLE) - last_error = WSAECONNREFUSED; - ec = asio::error_code(last_error, - asio::error::get_system_category()); - return 0; - } - if (bytes_transferred == 0 && impl.protocol_.type() == SOCK_STREAM) - { - ec = asio::error::eof; - return 0; - } - - sender_endpoint.resize(static_cast(endpoint_size)); - - ec = asio::error_code(); - return bytes_transferred; - } - - // Wait until data can be received without blocking. - size_t receive_from(implementation_type& impl, - const null_buffers&, endpoint_type& sender_endpoint, - socket_base::message_flags, asio::error_code& ec) - { - if (!is_open(impl)) - { - ec = asio::error::bad_descriptor; - return 0; - } - - // Wait for socket to become ready. - socket_ops::poll_read(impl.socket_, ec); - - // Reset endpoint since it can be given no sensible value at this time. - sender_endpoint = endpoint_type(); - - return 0; - } - - template - class receive_from_operation - : public operation - { - public: - receive_from_operation(int protocol_type, win_iocp_io_service& io_service, - endpoint_type& endpoint, const MutableBufferSequence& buffers, - Handler handler) - : operation(io_service, - &receive_from_operation< - MutableBufferSequence, Handler>::do_completion_impl, - &receive_from_operation< - MutableBufferSequence, Handler>::destroy_impl), - protocol_type_(protocol_type), - endpoint_(endpoint), - endpoint_size_(static_cast(endpoint.capacity())), - work_(io_service.get_io_service()), - buffers_(buffers), - handler_(handler) - { - } - - int& endpoint_size() - { - return endpoint_size_; - } - - private: - static void do_completion_impl(operation* op, - DWORD last_error, size_t bytes_transferred) - { - // Take ownership of the operation object. - typedef receive_from_operation op_type; - op_type* handler_op(static_cast(op)); - typedef handler_alloc_traits alloc_traits; - handler_ptr ptr(handler_op->handler_, handler_op); - -#if defined(ASIO_ENABLE_BUFFER_DEBUGGING) - // Check whether buffers are still valid. - typename MutableBufferSequence::const_iterator iter - = handler_op->buffers_.begin(); - typename MutableBufferSequence::const_iterator end - = handler_op->buffers_.end(); - while (iter != end) - { - asio::mutable_buffer buffer(*iter); - asio::buffer_cast(buffer); - ++iter; - } -#endif // defined(ASIO_ENABLE_BUFFER_DEBUGGING) - - // Map non-portable errors to their portable counterparts. - asio::error_code ec(last_error, - asio::error::get_system_category()); - if (ec.value() == ERROR_PORT_UNREACHABLE) - { - ec = asio::error::connection_refused; - } - - // Check for connection closed. - if (!ec && bytes_transferred == 0 - && handler_op->protocol_type_ == SOCK_STREAM) - { - ec = asio::error::eof; - } - - // Record the size of the endpoint returned by the operation. - handler_op->endpoint_.resize(handler_op->endpoint_size_); - - // Make a copy of the handler so that the memory can be deallocated before - // the upcall is made. - Handler handler(handler_op->handler_); - - // Free the memory associated with the handler. - ptr.reset(); - - // Call the handler. - asio_handler_invoke_helpers::invoke( - detail::bind_handler(handler, ec, bytes_transferred), &handler); - } - - static void destroy_impl(operation* op) - { - // Take ownership of the operation object. - typedef receive_from_operation op_type; - op_type* handler_op(static_cast(op)); - typedef handler_alloc_traits alloc_traits; - handler_ptr ptr(handler_op->handler_, handler_op); - - // A sub-object of the handler may be the true owner of the memory - // associated with the handler. Consequently, a local copy of the handler - // is required to ensure that any owning sub-object remains valid until - // after we have deallocated the memory here. - Handler handler(handler_op->handler_); - (void)handler; - - // Free the memory associated with the handler. - ptr.reset(); - } - - int protocol_type_; - endpoint_type& endpoint_; - int endpoint_size_; - asio::io_service::work work_; - MutableBufferSequence buffers_; - Handler handler_; - }; - - // Start an asynchronous receive. The buffer for the data being received and - // the sender_endpoint object must both be valid for the lifetime of the - // asynchronous operation. - template - void async_receive_from(implementation_type& impl, - const MutableBufferSequence& buffers, endpoint_type& sender_endp, - socket_base::message_flags flags, Handler handler) - { - if (!is_open(impl)) - { - this->get_io_service().post(bind_handler(handler, - asio::error::bad_descriptor, 0)); - return; - } - -#if defined(ASIO_ENABLE_CANCELIO) - // Update the ID of the thread from which cancellation is safe. - if (impl.safe_cancellation_thread_id_ == 0) - impl.safe_cancellation_thread_id_ = ::GetCurrentThreadId(); - else if (impl.safe_cancellation_thread_id_ != ::GetCurrentThreadId()) - impl.safe_cancellation_thread_id_ = ~DWORD(0); -#endif // defined(ASIO_ENABLE_CANCELIO) - - // Allocate and construct an operation to wrap the handler. - typedef receive_from_operation value_type; - typedef handler_alloc_traits alloc_traits; - raw_handler_ptr raw_ptr(handler); - int protocol_type = impl.protocol_.type(); - handler_ptr ptr(raw_ptr, protocol_type, - iocp_service_, sender_endp, buffers, handler); - - // Copy buffers into WSABUF array. - ::WSABUF bufs[max_buffers]; - typename MutableBufferSequence::const_iterator iter = buffers.begin(); - typename MutableBufferSequence::const_iterator end = buffers.end(); - DWORD i = 0; - for (; iter != end && i < max_buffers; ++iter, ++i) - { - asio::mutable_buffer buffer(*iter); - bufs[i].len = static_cast(asio::buffer_size(buffer)); - bufs[i].buf = asio::buffer_cast(buffer); - } - - // Receive some data. - DWORD bytes_transferred = 0; - DWORD recv_flags = flags; - int result = ::WSARecvFrom(impl.socket_, bufs, i, &bytes_transferred, - &recv_flags, sender_endp.data(), &ptr.get()->endpoint_size(), - ptr.get(), 0); - DWORD last_error = ::WSAGetLastError(); - if (result != 0 && last_error != WSA_IO_PENDING) - { - asio::io_service::work work(this->get_io_service()); - ptr.reset(); - asio::error_code ec(last_error, - asio::error::get_system_category()); - iocp_service_.post(bind_handler(handler, ec, bytes_transferred)); - } - else - { - ptr.release(); - } - } - - // Wait until data can be received without blocking. - template - void async_receive_from(implementation_type& impl, - const null_buffers&, endpoint_type& sender_endpoint, - socket_base::message_flags flags, Handler handler) - { - if (!is_open(impl)) - { - this->get_io_service().post(bind_handler(handler, - asio::error::bad_descriptor, 0)); - } - else - { - // Check if the reactor was already obtained from the io_service. - reactor_type* reactor = static_cast( - interlocked_compare_exchange_pointer( - reinterpret_cast(&reactor_), 0, 0)); - if (!reactor) - { - reactor = &(asio::use_service( - this->get_io_service())); - interlocked_exchange_pointer( - reinterpret_cast(&reactor_), reactor); - } - - // Reset endpoint since it can be given no sensible value at this time. - sender_endpoint = endpoint_type(); - - if (flags & socket_base::message_out_of_band) - { - reactor->start_except_op(impl.socket_, impl.reactor_data_, - null_buffers_operation(this->get_io_service(), handler)); - } - else - { - reactor->start_read_op(impl.socket_, impl.reactor_data_, - null_buffers_operation(this->get_io_service(), handler), - false); - } - } - } - - // Accept a new connection. - template - asio::error_code accept(implementation_type& impl, Socket& peer, - endpoint_type* peer_endpoint, asio::error_code& ec) - { - if (!is_open(impl)) - { - ec = asio::error::bad_descriptor; - return ec; - } - - // We cannot accept a socket that is already open. - if (peer.is_open()) - { - ec = asio::error::already_open; - return ec; - } - - for (;;) - { - socket_holder new_socket; - std::size_t addr_len = 0; - if (peer_endpoint) - { - addr_len = peer_endpoint->capacity(); - new_socket.reset(socket_ops::accept(impl.socket_, - peer_endpoint->data(), &addr_len, ec)); - } - else - { - new_socket.reset(socket_ops::accept(impl.socket_, 0, 0, ec)); - } - - if (ec) - { - if (ec == asio::error::connection_aborted - && !(impl.flags_ & implementation_type::enable_connection_aborted)) - { - // Retry accept operation. - continue; - } - else - { - return ec; - } - } - - if (peer_endpoint) - peer_endpoint->resize(addr_len); - - peer.assign(impl.protocol_, new_socket.get(), ec); - if (!ec) - new_socket.release(); - return ec; - } - } - - template - class accept_operation - : public operation - { - public: - accept_operation(win_iocp_io_service& io_service, - socket_type socket, socket_type new_socket, Socket& peer, - const protocol_type& protocol, endpoint_type* peer_endpoint, - bool enable_connection_aborted, Handler handler) - : operation(io_service, - &accept_operation::do_completion_impl, - &accept_operation::destroy_impl), - io_service_(io_service), - socket_(socket), - new_socket_(new_socket), - peer_(peer), - protocol_(protocol), - peer_endpoint_(peer_endpoint), - work_(io_service.get_io_service()), - enable_connection_aborted_(enable_connection_aborted), - handler_(handler) - { - } - - socket_type new_socket() - { - return new_socket_.get(); - } - - void* output_buffer() - { - return output_buffer_; - } - - DWORD address_length() - { - return sizeof(sockaddr_storage_type) + 16; - } - - private: - static void do_completion_impl(operation* op, DWORD last_error, size_t) - { - // Take ownership of the operation object. - typedef accept_operation op_type; - op_type* handler_op(static_cast(op)); - typedef handler_alloc_traits alloc_traits; - handler_ptr ptr(handler_op->handler_, handler_op); - - // Map Windows error ERROR_NETNAME_DELETED to connection_aborted. - if (last_error == ERROR_NETNAME_DELETED) - { - last_error = WSAECONNABORTED; - } - - // Restart the accept operation if we got the connection_aborted error - // and the enable_connection_aborted socket option is not set. - if (last_error == WSAECONNABORTED - && !ptr.get()->enable_connection_aborted_) - { - // Reset OVERLAPPED structure. - ptr.get()->Internal = 0; - ptr.get()->InternalHigh = 0; - ptr.get()->Offset = 0; - ptr.get()->OffsetHigh = 0; - ptr.get()->hEvent = 0; - - // Create a new socket for the next connection, since the AcceptEx call - // fails with WSAEINVAL if we try to reuse the same socket. - asio::error_code ec; - ptr.get()->new_socket_.reset(); - ptr.get()->new_socket_.reset(socket_ops::socket( - ptr.get()->protocol_.family(), ptr.get()->protocol_.type(), - ptr.get()->protocol_.protocol(), ec)); - if (ptr.get()->new_socket() != invalid_socket) - { - // Accept a connection. - DWORD bytes_read = 0; - BOOL result = ::AcceptEx(ptr.get()->socket_, ptr.get()->new_socket(), - ptr.get()->output_buffer(), 0, ptr.get()->address_length(), - ptr.get()->address_length(), &bytes_read, ptr.get()); - last_error = ::WSAGetLastError(); - - // Check if the operation completed immediately. - if (!result && last_error != WSA_IO_PENDING) - { - if (last_error == ERROR_NETNAME_DELETED - || last_error == WSAECONNABORTED) - { - // Post this handler so that operation will be restarted again. - ptr.get()->io_service_.post_completion(ptr.get(), last_error, 0); - ptr.release(); - return; - } - else - { - // Operation already complete. Continue with rest of this handler. - } - } - else - { - // Asynchronous operation has been successfully restarted. - ptr.release(); - return; - } - } - } - - // Get the address of the peer. - endpoint_type peer_endpoint; - if (last_error == 0) - { - LPSOCKADDR local_addr = 0; - int local_addr_length = 0; - LPSOCKADDR remote_addr = 0; - int remote_addr_length = 0; - GetAcceptExSockaddrs(handler_op->output_buffer(), 0, - handler_op->address_length(), handler_op->address_length(), - &local_addr, &local_addr_length, &remote_addr, &remote_addr_length); - if (static_cast(remote_addr_length) - > peer_endpoint.capacity()) - { - last_error = WSAEINVAL; - } - else - { - using namespace std; // For memcpy. - memcpy(peer_endpoint.data(), remote_addr, remote_addr_length); - peer_endpoint.resize(static_cast(remote_addr_length)); - } - } - - // Need to set the SO_UPDATE_ACCEPT_CONTEXT option so that getsockname - // and getpeername will work on the accepted socket. - if (last_error == 0) - { - SOCKET update_ctx_param = handler_op->socket_; - asio::error_code ec; - if (socket_ops::setsockopt(handler_op->new_socket_.get(), - SOL_SOCKET, SO_UPDATE_ACCEPT_CONTEXT, - &update_ctx_param, sizeof(SOCKET), ec) != 0) - { - last_error = ec.value(); - } - } - - // If the socket was successfully accepted, transfer ownership of the - // socket to the peer object. - if (last_error == 0) - { - asio::error_code ec; - handler_op->peer_.assign(handler_op->protocol_, - native_type(handler_op->new_socket_.get(), peer_endpoint), ec); - if (ec) - last_error = ec.value(); - else - handler_op->new_socket_.release(); - } - - // Pass endpoint back to caller. - if (handler_op->peer_endpoint_) - *handler_op->peer_endpoint_ = peer_endpoint; - - // Make a copy of the handler so that the memory can be deallocated before - // the upcall is made. - Handler handler(handler_op->handler_); - - // Free the memory associated with the handler. - ptr.reset(); - - // Call the handler. - asio::error_code ec(last_error, - asio::error::get_system_category()); - asio_handler_invoke_helpers::invoke( - detail::bind_handler(handler, ec), &handler); - } - - static void destroy_impl(operation* op) - { - // Take ownership of the operation object. - typedef accept_operation op_type; - op_type* handler_op(static_cast(op)); - typedef handler_alloc_traits alloc_traits; - handler_ptr ptr(handler_op->handler_, handler_op); - - // A sub-object of the handler may be the true owner of the memory - // associated with the handler. Consequently, a local copy of the handler - // is required to ensure that any owning sub-object remains valid until - // after we have deallocated the memory here. - Handler handler(handler_op->handler_); - (void)handler; - - // Free the memory associated with the handler. - ptr.reset(); - } - - win_iocp_io_service& io_service_; - socket_type socket_; - socket_holder new_socket_; - Socket& peer_; - protocol_type protocol_; - endpoint_type* peer_endpoint_; - asio::io_service::work work_; - unsigned char output_buffer_[(sizeof(sockaddr_storage_type) + 16) * 2]; - bool enable_connection_aborted_; - Handler handler_; - }; - - // Start an asynchronous accept. The peer and peer_endpoint objects - // must be valid until the accept's handler is invoked. - template - void async_accept(implementation_type& impl, Socket& peer, - endpoint_type* peer_endpoint, Handler handler) - { - // Check whether acceptor has been initialised. - if (!is_open(impl)) - { - this->get_io_service().post(bind_handler(handler, - asio::error::bad_descriptor)); - return; - } - - // Check that peer socket has not already been opened. - if (peer.is_open()) - { - this->get_io_service().post(bind_handler(handler, - asio::error::already_open)); - return; - } - -#if defined(ASIO_ENABLE_CANCELIO) - // Update the ID of the thread from which cancellation is safe. - if (impl.safe_cancellation_thread_id_ == 0) - impl.safe_cancellation_thread_id_ = ::GetCurrentThreadId(); - else if (impl.safe_cancellation_thread_id_ != ::GetCurrentThreadId()) - impl.safe_cancellation_thread_id_ = ~DWORD(0); -#endif // defined(ASIO_ENABLE_CANCELIO) - - // Create a new socket for the connection. - asio::error_code ec; - socket_holder sock(socket_ops::socket(impl.protocol_.family(), - impl.protocol_.type(), impl.protocol_.protocol(), ec)); - if (sock.get() == invalid_socket) - { - this->get_io_service().post(bind_handler(handler, ec)); - return; - } - - // Allocate and construct an operation to wrap the handler. - typedef accept_operation value_type; - typedef handler_alloc_traits alloc_traits; - raw_handler_ptr raw_ptr(handler); - socket_type new_socket = sock.get(); - bool enable_connection_aborted = - (impl.flags_ & implementation_type::enable_connection_aborted); - handler_ptr ptr(raw_ptr, - iocp_service_, impl.socket_, new_socket, peer, impl.protocol_, - peer_endpoint, enable_connection_aborted, handler); - sock.release(); - - // Accept a connection. - DWORD bytes_read = 0; - BOOL result = ::AcceptEx(impl.socket_, ptr.get()->new_socket(), - ptr.get()->output_buffer(), 0, ptr.get()->address_length(), - ptr.get()->address_length(), &bytes_read, ptr.get()); - DWORD last_error = ::WSAGetLastError(); - - // Check if the operation completed immediately. - if (!result && last_error != WSA_IO_PENDING) - { - if (!enable_connection_aborted - && (last_error == ERROR_NETNAME_DELETED - || last_error == WSAECONNABORTED)) - { - // Post handler so that operation will be restarted again. We do not - // perform the AcceptEx again here to avoid the possibility of starving - // other handlers. - iocp_service_.post_completion(ptr.get(), last_error, 0); - ptr.release(); - } - else - { - asio::io_service::work work(this->get_io_service()); - ptr.reset(); - asio::error_code ec(last_error, - asio::error::get_system_category()); - iocp_service_.post(bind_handler(handler, ec)); - } - } - else - { - ptr.release(); - } - } - - // Connect the socket to the specified endpoint. - asio::error_code connect(implementation_type& impl, - const endpoint_type& peer_endpoint, asio::error_code& ec) - { - if (!is_open(impl)) - { - ec = asio::error::bad_descriptor; - return ec; - } - - // Perform the connect operation. - socket_ops::connect(impl.socket_, - peer_endpoint.data(), peer_endpoint.size(), ec); - return ec; - } - - template - class connect_operation - { - public: - connect_operation(socket_type socket, bool user_set_non_blocking, - asio::io_service& io_service, Handler handler) - : socket_(socket), - user_set_non_blocking_(user_set_non_blocking), - io_service_(io_service), - work_(io_service), - handler_(handler) - { - } - - bool perform(asio::error_code& ec, - std::size_t& bytes_transferred) - { - // Check whether the operation was successful. - if (ec) - return true; - - // Get the error code from the connect operation. - int connect_error = 0; - size_t connect_error_len = sizeof(connect_error); - if (socket_ops::getsockopt(socket_, SOL_SOCKET, SO_ERROR, - &connect_error, &connect_error_len, ec) == socket_error_retval) - return true; - - // If connection failed then post the handler with the error code. - if (connect_error) - { - ec = asio::error_code(connect_error, - asio::error::get_system_category()); - return true; - } - - // Revert socket to blocking mode unless the user requested otherwise. - if (!user_set_non_blocking_) - { - ioctl_arg_type non_blocking = 0; - if (socket_ops::ioctl(socket_, FIONBIO, &non_blocking, ec)) - return true; - } - - // Post the result of the successful connection operation. - ec = asio::error_code(); - return true; - } - - void complete(const asio::error_code& ec, std::size_t) - { - io_service_.post(bind_handler(handler_, ec)); - } - - private: - socket_type socket_; - bool user_set_non_blocking_; - asio::io_service& io_service_; - asio::io_service::work work_; - Handler handler_; - }; - - // Start an asynchronous connect. - template - void async_connect(implementation_type& impl, - const endpoint_type& peer_endpoint, Handler handler) - { - if (!is_open(impl)) - { - this->get_io_service().post(bind_handler(handler, - asio::error::bad_descriptor)); - return; - } - -#if defined(ASIO_ENABLE_CANCELIO) - // Update the ID of the thread from which cancellation is safe. - if (impl.safe_cancellation_thread_id_ == 0) - impl.safe_cancellation_thread_id_ = ::GetCurrentThreadId(); - else if (impl.safe_cancellation_thread_id_ != ::GetCurrentThreadId()) - impl.safe_cancellation_thread_id_ = ~DWORD(0); -#endif // defined(ASIO_ENABLE_CANCELIO) - - // Check if the reactor was already obtained from the io_service. - reactor_type* reactor = static_cast( - interlocked_compare_exchange_pointer( - reinterpret_cast(&reactor_), 0, 0)); - if (!reactor) - { - reactor = &(asio::use_service( - this->get_io_service())); - interlocked_exchange_pointer( - reinterpret_cast(&reactor_), reactor); - } - - // Mark the socket as non-blocking so that the connection will take place - // asynchronously. - ioctl_arg_type non_blocking = 1; - asio::error_code ec; - if (socket_ops::ioctl(impl.socket_, FIONBIO, &non_blocking, ec)) - { - this->get_io_service().post(bind_handler(handler, ec)); - return; - } - - // Start the connect operation. - if (socket_ops::connect(impl.socket_, peer_endpoint.data(), - peer_endpoint.size(), ec) == 0) - { - // Revert socket to blocking mode unless the user requested otherwise. - if (!(impl.flags_ & implementation_type::user_set_non_blocking)) - { - non_blocking = 0; - socket_ops::ioctl(impl.socket_, FIONBIO, &non_blocking, ec); - } - - // The connect operation has finished successfully so we need to post the - // handler immediately. - this->get_io_service().post(bind_handler(handler, ec)); - } - else if (ec == asio::error::in_progress - || ec == asio::error::would_block) - { - // The connection is happening in the background, and we need to wait - // until the socket becomes writeable. - boost::shared_ptr completed(new bool(false)); - reactor->start_connect_op(impl.socket_, impl.reactor_data_, - connect_operation( - impl.socket_, - (impl.flags_ & implementation_type::user_set_non_blocking) != 0, - this->get_io_service(), handler)); - } - else - { - // Revert socket to blocking mode unless the user requested otherwise. - if (!(impl.flags_ & implementation_type::user_set_non_blocking)) - { - non_blocking = 0; - asio::error_code ignored_ec; - socket_ops::ioctl(impl.socket_, FIONBIO, &non_blocking, ignored_ec); - } - - // The connect operation has failed, so post the handler immediately. - this->get_io_service().post(bind_handler(handler, ec)); - } - } - -private: - // Helper function to close a socket when the associated object is being - // destroyed. - void close_for_destruction(implementation_type& impl) - { - if (is_open(impl)) - { - // Check if the reactor was created, in which case we need to close the - // socket on the reactor as well to cancel any operations that might be - // running there. - reactor_type* reactor = static_cast( - interlocked_compare_exchange_pointer( - reinterpret_cast(&reactor_), 0, 0)); - if (reactor) - reactor->close_descriptor(impl.socket_, impl.reactor_data_); - - // The socket destructor must not block. If the user has changed the - // linger option to block in the foreground, we will change it back to the - // default so that the closure is performed in the background. - if (impl.flags_ & implementation_type::close_might_block) - { - ::linger opt; - opt.l_onoff = 0; - opt.l_linger = 0; - asio::error_code ignored_ec; - socket_ops::setsockopt(impl.socket_, - SOL_SOCKET, SO_LINGER, &opt, sizeof(opt), ignored_ec); - } - - asio::error_code ignored_ec; - socket_ops::close(impl.socket_, ignored_ec); - impl.socket_ = invalid_socket; - impl.flags_ = 0; - impl.cancel_token_.reset(); -#if defined(ASIO_ENABLE_CANCELIO) - impl.safe_cancellation_thread_id_ = 0; -#endif // defined(ASIO_ENABLE_CANCELIO) - } - } - - // Helper function to emulate InterlockedCompareExchangePointer functionality - // for: - // - very old Platform SDKs; and - // - platform SDKs where MSVC's /Wp64 option causes spurious warnings. - void* interlocked_compare_exchange_pointer(void** dest, void* exch, void* cmp) - { -#if defined(_M_IX86) - return reinterpret_cast(InterlockedCompareExchange( - reinterpret_cast(dest), reinterpret_cast(exch), - reinterpret_cast(cmp))); -#else - return InterlockedCompareExchangePointer(dest, exch, cmp); -#endif - } - - // Helper function to emulate InterlockedExchangePointer functionality for: - // - very old Platform SDKs; and - // - platform SDKs where MSVC's /Wp64 option causes spurious warnings. - void* interlocked_exchange_pointer(void** dest, void* val) - { -#if defined(_M_IX86) - return reinterpret_cast(InterlockedExchange( - reinterpret_cast(dest), reinterpret_cast(val))); -#else - return InterlockedExchangePointer(dest, val); -#endif - } - - // The IOCP service used for running asynchronous operations and dispatching - // handlers. - win_iocp_io_service& iocp_service_; - - // The reactor used for performing connect operations. This object is created - // only if needed. - reactor_type* reactor_; - - // Mutex to protect access to the linked list of implementations. - asio::detail::mutex mutex_; - - // The head of a linked list of all implementations. - implementation_type* impl_list_; -}; - -} // namespace detail -} // namespace asio - -#endif // defined(ASIO_HAS_IOCP) - -#include "asio/detail/pop_options.hpp" - -#endif // ASIO_DETAIL_WIN_IOCP_SOCKET_SERVICE_HPP diff --git a/libtorrent/include/asio/detail/win_mutex.hpp b/libtorrent/include/asio/detail/win_mutex.hpp deleted file mode 100644 index 4fdb5973b..000000000 --- a/libtorrent/include/asio/detail/win_mutex.hpp +++ /dev/null @@ -1,149 +0,0 @@ -// -// win_mutex.hpp -// ~~~~~~~~~~~~~ -// -// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -#ifndef ASIO_DETAIL_WIN_MUTEX_HPP -#define ASIO_DETAIL_WIN_MUTEX_HPP - -#if defined(_MSC_VER) && (_MSC_VER >= 1200) -# pragma once -#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) - -#include "asio/detail/push_options.hpp" - -#include "asio/detail/push_options.hpp" -#include -#include "asio/detail/pop_options.hpp" - -#if defined(BOOST_WINDOWS) - -#include "asio/error.hpp" -#include "asio/system_error.hpp" -#include "asio/detail/noncopyable.hpp" -#include "asio/detail/socket_types.hpp" -#include "asio/detail/scoped_lock.hpp" - -#include "asio/detail/push_options.hpp" -#include -#include "asio/detail/pop_options.hpp" - -namespace asio { -namespace detail { - -class win_mutex - : private noncopyable -{ -public: - typedef asio::detail::scoped_lock scoped_lock; - - // Constructor. - win_mutex() - { - int error = do_init(); - if (error != 0) - { - asio::system_error e( - asio::error_code(error, - asio::error::get_system_category()), - "mutex"); - boost::throw_exception(e); - } - } - - // Destructor. - ~win_mutex() - { - ::DeleteCriticalSection(&crit_section_); - } - - // Lock the mutex. - void lock() - { - int error = do_lock(); - if (error != 0) - { - asio::system_error e( - asio::error_code(error, - asio::error::get_system_category()), - "mutex"); - boost::throw_exception(e); - } - } - - // Unlock the mutex. - void unlock() - { - ::LeaveCriticalSection(&crit_section_); - } - -private: - // Initialisation must be performed in a separate function to the constructor - // since the compiler does not support the use of structured exceptions and - // C++ exceptions in the same function. - int do_init() - { -#if defined(__MINGW32__) - // Not sure if MinGW supports structured exception handling, so for now - // we'll just call the Windows API and hope. - ::InitializeCriticalSection(&crit_section_); - return 0; -#else - __try - { - ::InitializeCriticalSection(&crit_section_); - } - __except(GetExceptionCode() == STATUS_NO_MEMORY - ? EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH) - { - return ERROR_OUTOFMEMORY; - } - - return 0; -#endif - } - - // Locking must be performed in a separate function to lock() since the - // compiler does not support the use of structured exceptions and C++ - // exceptions in the same function. - int do_lock() - { -#if defined(__MINGW32__) - // Not sure if MinGW supports structured exception handling, so for now - // we'll just call the Windows API and hope. - ::EnterCriticalSection(&crit_section_); - return 0; -#else - __try - { - ::EnterCriticalSection(&crit_section_); - } - __except(GetExceptionCode() == STATUS_INVALID_HANDLE - || GetExceptionCode() == STATUS_NO_MEMORY - ? EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH) - { - if (GetExceptionCode() == STATUS_NO_MEMORY) - return ERROR_OUTOFMEMORY; - return ERROR_INVALID_HANDLE; - } - - return 0; -#endif - } - - ::CRITICAL_SECTION crit_section_; -}; - -} // namespace detail -} // namespace asio - -#endif // defined(BOOST_WINDOWS) - -#include "asio/detail/pop_options.hpp" - -#endif // ASIO_DETAIL_WIN_MUTEX_HPP diff --git a/libtorrent/include/asio/detail/win_signal_blocker.hpp b/libtorrent/include/asio/detail/win_signal_blocker.hpp deleted file mode 100644 index 5c3c9f4d2..000000000 --- a/libtorrent/include/asio/detail/win_signal_blocker.hpp +++ /dev/null @@ -1,67 +0,0 @@ -// -// win_signal_blocker.hpp -// ~~~~~~~~~~~~~~~~~~~~~~ -// -// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -#ifndef ASIO_DETAIL_WIN_SIGNAL_BLOCKER_HPP -#define ASIO_DETAIL_WIN_SIGNAL_BLOCKER_HPP - -#if defined(_MSC_VER) && (_MSC_VER >= 1200) -# pragma once -#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) - -#include "asio/detail/push_options.hpp" - -#include "asio/detail/push_options.hpp" -#include -#include "asio/detail/pop_options.hpp" - -#if defined(BOOST_WINDOWS) || defined(__CYGWIN__) - -#include "asio/detail/noncopyable.hpp" - -namespace asio { -namespace detail { - -class win_signal_blocker - : private noncopyable -{ -public: - // Constructor blocks all signals for the calling thread. - win_signal_blocker() - { - // No-op. - } - - // Destructor restores the previous signal mask. - ~win_signal_blocker() - { - // No-op. - } - - // Block all signals for the calling thread. - void block() - { - // No-op. - } - - // Restore the previous signal mask. - void unblock() - { - // No-op. - } -}; - -} // namespace detail -} // namespace asio - -#endif // defined(BOOST_WINDOWS) || defined(__CYGWIN__) - -#include "asio/detail/pop_options.hpp" - -#endif // ASIO_DETAIL_WIN_SIGNAL_BLOCKER_HPP diff --git a/libtorrent/include/asio/detail/win_thread.hpp b/libtorrent/include/asio/detail/win_thread.hpp deleted file mode 100644 index 17d912565..000000000 --- a/libtorrent/include/asio/detail/win_thread.hpp +++ /dev/null @@ -1,194 +0,0 @@ -// -// win_thread.hpp -// ~~~~~~~~~~~~~~ -// -// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -#ifndef ASIO_DETAIL_WIN_THREAD_HPP -#define ASIO_DETAIL_WIN_THREAD_HPP - -#if defined(_MSC_VER) && (_MSC_VER >= 1200) -# pragma once -#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) - -#include "asio/detail/push_options.hpp" - -#include "asio/detail/push_options.hpp" -#include -#include "asio/detail/pop_options.hpp" - -#if defined(BOOST_WINDOWS) && !defined(UNDER_CE) - -#include "asio/error.hpp" -#include "asio/system_error.hpp" -#include "asio/detail/noncopyable.hpp" -#include "asio/detail/socket_types.hpp" - -#include "asio/detail/push_options.hpp" -#include -#include -#include -#include "asio/detail/pop_options.hpp" - -namespace asio { -namespace detail { - -unsigned int __stdcall win_thread_function(void* arg); - -class win_thread - : private noncopyable -{ -public: - // The purpose of the thread. - enum purpose { internal, external }; - - // Constructor. - template - win_thread(Function f, purpose p = internal) - : exit_event_(0) - { - std::auto_ptr arg(new func(f)); - - ::HANDLE entry_event = 0; - if (p == internal) - { - arg->entry_event_ = entry_event = ::CreateEvent(0, true, false, 0); - if (!entry_event) - { - DWORD last_error = ::GetLastError(); - asio::system_error e( - asio::error_code(last_error, - asio::error::get_system_category()), - "thread.entry_event"); - boost::throw_exception(e); - } - - arg->exit_event_ = exit_event_ = ::CreateEvent(0, true, false, 0); - if (!exit_event_) - { - DWORD last_error = ::GetLastError(); - ::CloseHandle(entry_event); - asio::system_error e( - asio::error_code(last_error, - asio::error::get_system_category()), - "thread.exit_event"); - boost::throw_exception(e); - } - } - - unsigned int thread_id = 0; - thread_ = reinterpret_cast(::_beginthreadex(0, 0, - win_thread_function, arg.get(), 0, &thread_id)); - if (!thread_) - { - DWORD last_error = ::GetLastError(); - if (entry_event) - ::CloseHandle(entry_event); - if (exit_event_) - ::CloseHandle(exit_event_); - asio::system_error e( - asio::error_code(last_error, - asio::error::get_system_category()), - "thread"); - boost::throw_exception(e); - } - arg.release(); - - if (entry_event) - { - ::WaitForSingleObject(entry_event, INFINITE); - ::CloseHandle(entry_event); - } - } - - // Destructor. - ~win_thread() - { - ::CloseHandle(thread_); - - // The exit_event_ handle is deliberately allowed to leak here since it - // is an error for the owner of an internal thread not to join() it. - } - - // Wait for the thread to exit. - void join() - { - if (exit_event_) - { - ::WaitForSingleObject(exit_event_, INFINITE); - ::CloseHandle(exit_event_); - ::TerminateThread(thread_, 0); - } - else - { - ::WaitForSingleObject(thread_, INFINITE); - } - } - -private: - friend unsigned int __stdcall win_thread_function(void* arg); - - class func_base - { - public: - virtual ~func_base() {} - virtual void run() = 0; - ::HANDLE entry_event_; - ::HANDLE exit_event_; - }; - - template - class func - : public func_base - { - public: - func(Function f) - : f_(f) - { - } - - virtual void run() - { - f_(); - } - - private: - Function f_; - }; - - ::HANDLE thread_; - ::HANDLE exit_event_; -}; - -inline unsigned int __stdcall win_thread_function(void* arg) -{ - std::auto_ptr func( - static_cast(arg)); - - if (func->entry_event_) - ::SetEvent(func->entry_event_); - - func->run(); - - if (HANDLE exit_event = func->exit_event_) - { - func.reset(); - ::SetEvent(exit_event); - ::Sleep(INFINITE); - } - - return 0; -} - -} // namespace detail -} // namespace asio - -#endif // defined(BOOST_WINDOWS) && !defined(UNDER_CE) - -#include "asio/detail/pop_options.hpp" - -#endif // ASIO_DETAIL_WIN_THREAD_HPP diff --git a/libtorrent/include/asio/detail/win_tss_ptr.hpp b/libtorrent/include/asio/detail/win_tss_ptr.hpp deleted file mode 100644 index 40b411543..000000000 --- a/libtorrent/include/asio/detail/win_tss_ptr.hpp +++ /dev/null @@ -1,95 +0,0 @@ -// -// win_tss_ptr.hpp -// ~~~~~~~~~~~~~~~ -// -// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -#ifndef ASIO_DETAIL_WIN_TSS_PTR_HPP -#define ASIO_DETAIL_WIN_TSS_PTR_HPP - -#if defined(_MSC_VER) && (_MSC_VER >= 1200) -# pragma once -#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) - -#include "asio/detail/push_options.hpp" - -#include "asio/detail/push_options.hpp" -#include -#include "asio/detail/pop_options.hpp" - -#if defined(BOOST_WINDOWS) - -#include "asio/error.hpp" -#include "asio/system_error.hpp" -#include "asio/detail/noncopyable.hpp" -#include "asio/detail/socket_types.hpp" - -#include "asio/detail/push_options.hpp" -#include -#include "asio/detail/pop_options.hpp" - -namespace asio { -namespace detail { - -template -class win_tss_ptr - : private noncopyable -{ -public: -#if defined(UNDER_CE) - enum { out_of_indexes = 0xFFFFFFFF }; -#else - enum { out_of_indexes = TLS_OUT_OF_INDEXES }; -#endif - - // Constructor. - win_tss_ptr() - { - tss_key_ = ::TlsAlloc(); - if (tss_key_ == out_of_indexes) - { - DWORD last_error = ::GetLastError(); - asio::system_error e( - asio::error_code(last_error, - asio::error::get_system_category()), - "tss"); - boost::throw_exception(e); - } - } - - // Destructor. - ~win_tss_ptr() - { - ::TlsFree(tss_key_); - } - - // Get the value. - operator T*() const - { - return static_cast(::TlsGetValue(tss_key_)); - } - - // Set the value. - void operator=(T* value) - { - ::TlsSetValue(tss_key_, value); - } - -private: - // Thread-specific storage to allow unlocked access to determine whether a - // thread is a member of the pool. - DWORD tss_key_; -}; - -} // namespace detail -} // namespace asio - -#endif // defined(BOOST_WINDOWS) - -#include "asio/detail/pop_options.hpp" - -#endif // ASIO_DETAIL_WIN_TSS_PTR_HPP diff --git a/libtorrent/include/asio/detail/wince_thread.hpp b/libtorrent/include/asio/detail/wince_thread.hpp deleted file mode 100644 index 5a558b9ef..000000000 --- a/libtorrent/include/asio/detail/wince_thread.hpp +++ /dev/null @@ -1,127 +0,0 @@ -// -// wince_thread.hpp -// ~~~~~~~~~~~~~~~~ -// -// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -#ifndef ASIO_DETAIL_WINCE_THREAD_HPP -#define ASIO_DETAIL_WINCE_THREAD_HPP - -#if defined(_MSC_VER) && (_MSC_VER >= 1200) -# pragma once -#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) - -#include "asio/detail/push_options.hpp" - -#include "asio/detail/push_options.hpp" -#include -#include "asio/detail/pop_options.hpp" - -#if defined(BOOST_WINDOWS) && defined(UNDER_CE) - -#include "asio/error.hpp" -#include "asio/system_error.hpp" -#include "asio/detail/noncopyable.hpp" -#include "asio/detail/socket_types.hpp" - -#include "asio/detail/push_options.hpp" -#include -#include -#include "asio/detail/pop_options.hpp" - -namespace asio { -namespace detail { - -DWORD WINAPI wince_thread_function(LPVOID arg); - -class wince_thread - : private noncopyable -{ -public: - // The purpose of the thread. - enum purpose { internal, external }; - - // Constructor. - template - wince_thread(Function f, purpose = internal) - { - std::auto_ptr arg(new func(f)); - DWORD thread_id = 0; - thread_ = ::CreateThread(0, 0, wince_thread_function, - arg.get(), 0, &thread_id); - if (!thread_) - { - DWORD last_error = ::GetLastError(); - asio::system_error e( - asio::error_code(last_error, - asio::error::get_system_category()), - "thread"); - boost::throw_exception(e); - } - arg.release(); - } - - // Destructor. - ~wince_thread() - { - ::CloseHandle(thread_); - } - - // Wait for the thread to exit. - void join() - { - ::WaitForSingleObject(thread_, INFINITE); - } - -private: - friend DWORD WINAPI wince_thread_function(LPVOID arg); - - class func_base - { - public: - virtual ~func_base() {} - virtual void run() = 0; - }; - - template - class func - : public func_base - { - public: - func(Function f) - : f_(f) - { - } - - virtual void run() - { - f_(); - } - - private: - Function f_; - }; - - ::HANDLE thread_; -}; - -inline DWORD WINAPI wince_thread_function(LPVOID arg) -{ - std::auto_ptr func( - static_cast(arg)); - func->run(); - return 0; -} - -} // namespace detail -} // namespace asio - -#endif // defined(BOOST_WINDOWS) && defined(UNDER_CE) - -#include "asio/detail/pop_options.hpp" - -#endif // ASIO_DETAIL_WINCE_THREAD_HPP diff --git a/libtorrent/include/asio/detail/winsock_init.hpp b/libtorrent/include/asio/detail/winsock_init.hpp deleted file mode 100644 index f5ca1a9df..000000000 --- a/libtorrent/include/asio/detail/winsock_init.hpp +++ /dev/null @@ -1,120 +0,0 @@ -// -// winsock_init.hpp -// ~~~~~~~~~~~~~~~~ -// -// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -#ifndef ASIO_DETAIL_WINSOCK_INIT_HPP -#define ASIO_DETAIL_WINSOCK_INIT_HPP - -#if defined(_MSC_VER) && (_MSC_VER >= 1200) -# pragma once -#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) - -#include "asio/detail/push_options.hpp" - -#include "asio/detail/push_options.hpp" -#include -#include "asio/detail/pop_options.hpp" - -#if defined(BOOST_WINDOWS) || defined(__CYGWIN__) - -#include "asio/detail/push_options.hpp" -#include -#include -#include "asio/detail/pop_options.hpp" - -#include "asio/error.hpp" -#include "asio/system_error.hpp" -#include "asio/detail/noncopyable.hpp" -#include "asio/detail/socket_types.hpp" - -namespace asio { -namespace detail { - -template -class winsock_init - : private noncopyable -{ -private: - // Structure to perform the actual initialisation. - struct do_init - { - do_init() - { - WSADATA wsa_data; - result_ = ::WSAStartup(MAKEWORD(Major, Minor), &wsa_data); - } - - ~do_init() - { - ::WSACleanup(); - } - - int result() const - { - return result_; - } - - // Helper function to manage a do_init singleton. The static instance of the - // winsock_init object ensures that this function is always called before - // main, and therefore before any other threads can get started. The do_init - // instance must be static in this function to ensure that it gets - // initialised before any other global objects try to use it. - static boost::shared_ptr instance() - { - static boost::shared_ptr init(new do_init); - return init; - } - - private: - int result_; - }; - -public: - // Constructor. - winsock_init() - : ref_(do_init::instance()) - { - // Check whether winsock was successfully initialised. This check is not - // performed for the global instance since there will be nobody around to - // catch the exception. - if (this != &instance_ && ref_->result() != 0) - { - asio::system_error e( - asio::error_code(ref_->result(), - asio::error::get_system_category()), - "winsock"); - boost::throw_exception(e); - } - } - - // Destructor. - ~winsock_init() - { - } - -private: - // Instance to force initialisation of winsock at global scope. - static winsock_init instance_; - - // Reference to singleton do_init object to ensure that winsock does not get - // cleaned up until the last user has finished with it. - boost::shared_ptr ref_; -}; - -template -winsock_init winsock_init::instance_; - -} // namespace detail -} // namespace asio - -#endif // defined(BOOST_WINDOWS) || defined(__CYGWIN__) - -#include "asio/detail/pop_options.hpp" - -#endif // ASIO_DETAIL_WINSOCK_INIT_HPP diff --git a/libtorrent/include/asio/detail/wrapped_handler.hpp b/libtorrent/include/asio/detail/wrapped_handler.hpp deleted file mode 100644 index 1b2e4dafc..000000000 --- a/libtorrent/include/asio/detail/wrapped_handler.hpp +++ /dev/null @@ -1,209 +0,0 @@ -// -// wrapped_handler.hpp -// ~~~~~~~~~~~~~~~~~~~ -// -// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -#ifndef ASIO_DETAIL_WRAPPED_HANDLER_HPP -#define ASIO_DETAIL_WRAPPED_HANDLER_HPP - -#if defined(_MSC_VER) && (_MSC_VER >= 1200) -# pragma once -#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) - -#include "asio/detail/push_options.hpp" - -#include "asio/detail/push_options.hpp" -#include -#include "asio/detail/pop_options.hpp" - -#include "asio/detail/bind_handler.hpp" -#include "asio/detail/handler_alloc_helpers.hpp" -#include "asio/detail/handler_invoke_helpers.hpp" - -namespace asio { -namespace detail { - -template -class wrapped_handler -{ -public: - typedef void result_type; - - wrapped_handler( - typename boost::add_reference::type dispatcher, - Handler handler) - : dispatcher_(dispatcher), - handler_(handler) - { - } - - void operator()() - { - dispatcher_.dispatch(handler_); - } - - void operator()() const - { - dispatcher_.dispatch(handler_); - } - - template - void operator()(const Arg1& arg1) - { - dispatcher_.dispatch(detail::bind_handler(handler_, arg1)); - } - - template - void operator()(const Arg1& arg1) const - { - dispatcher_.dispatch(detail::bind_handler(handler_, arg1)); - } - - template - void operator()(const Arg1& arg1, const Arg2& arg2) - { - dispatcher_.dispatch(detail::bind_handler(handler_, arg1, arg2)); - } - - template - void operator()(const Arg1& arg1, const Arg2& arg2) const - { - dispatcher_.dispatch(detail::bind_handler(handler_, arg1, arg2)); - } - - template - void operator()(const Arg1& arg1, const Arg2& arg2, const Arg3& arg3) - { - dispatcher_.dispatch(detail::bind_handler(handler_, arg1, arg2, arg3)); - } - - template - void operator()(const Arg1& arg1, const Arg2& arg2, const Arg3& arg3) const - { - dispatcher_.dispatch(detail::bind_handler(handler_, arg1, arg2, arg3)); - } - - template - void operator()(const Arg1& arg1, const Arg2& arg2, const Arg3& arg3, - const Arg4& arg4) - { - dispatcher_.dispatch( - detail::bind_handler(handler_, arg1, arg2, arg3, arg4)); - } - - template - void operator()(const Arg1& arg1, const Arg2& arg2, const Arg3& arg3, - const Arg4& arg4) const - { - dispatcher_.dispatch( - detail::bind_handler(handler_, arg1, arg2, arg3, arg4)); - } - - template - void operator()(const Arg1& arg1, const Arg2& arg2, const Arg3& arg3, - const Arg4& arg4, const Arg5& arg5) - { - dispatcher_.dispatch( - detail::bind_handler(handler_, arg1, arg2, arg3, arg4, arg5)); - } - - template - void operator()(const Arg1& arg1, const Arg2& arg2, const Arg3& arg3, - const Arg4& arg4, const Arg5& arg5) const - { - dispatcher_.dispatch( - detail::bind_handler(handler_, arg1, arg2, arg3, arg4, arg5)); - } - -//private: - Dispatcher dispatcher_; - Handler handler_; -}; - -template -class rewrapped_handler -{ -public: - explicit rewrapped_handler(const Handler& handler, const Context& context) - : handler_(handler), - context_(context) - { - } - - void operator()() - { - handler_(); - } - - void operator()() const - { - handler_(); - } - -//private: - Handler handler_; - Context context_; -}; - -template -inline void* asio_handler_allocate(std::size_t size, - wrapped_handler* this_handler) -{ - return asio_handler_alloc_helpers::allocate( - size, &this_handler->handler_); -} - -template -inline void asio_handler_deallocate(void* pointer, std::size_t size, - wrapped_handler* this_handler) -{ - asio_handler_alloc_helpers::deallocate( - pointer, size, &this_handler->handler_); -} - -template -inline void asio_handler_invoke(const Function& function, - wrapped_handler* this_handler) -{ - this_handler->dispatcher_.dispatch( - rewrapped_handler( - function, this_handler->handler_)); -} - -template -inline void* asio_handler_allocate(std::size_t size, - rewrapped_handler* this_handler) -{ - return asio_handler_alloc_helpers::allocate( - size, &this_handler->context_); -} - -template -inline void asio_handler_deallocate(void* pointer, std::size_t size, - rewrapped_handler* this_handler) -{ - asio_handler_alloc_helpers::deallocate( - pointer, size, &this_handler->context_); -} - -template -inline void asio_handler_invoke(const Function& function, - rewrapped_handler* this_handler) -{ - asio_handler_invoke_helpers::invoke( - function, &this_handler->context_); -} - -} // namespace detail -} // namespace asio - -#include "asio/detail/pop_options.hpp" - -#endif // ASIO_DETAIL_WRAPPED_HANDLER_HPP diff --git a/libtorrent/include/asio/error.hpp b/libtorrent/include/asio/error.hpp deleted file mode 100644 index 7a82a8849..000000000 --- a/libtorrent/include/asio/error.hpp +++ /dev/null @@ -1,260 +0,0 @@ -// -// error.hpp -// ~~~~~~~~~ -// -// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -#ifndef ASIO_ERROR_HPP -#define ASIO_ERROR_HPP - -#if defined(_MSC_VER) && (_MSC_VER >= 1200) -# pragma once -#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) - -#include "asio/detail/push_options.hpp" - -#include "asio/detail/push_options.hpp" -#include -#include -#include "asio/detail/pop_options.hpp" - -#include "asio/error_code.hpp" -#include "asio/detail/socket_types.hpp" - -#if defined(GENERATING_DOCUMENTATION) -/// INTERNAL ONLY. -# define ASIO_NATIVE_ERROR(e) implementation_defined -/// INTERNAL ONLY. -# define ASIO_SOCKET_ERROR(e) implementation_defined -/// INTERNAL ONLY. -# define ASIO_NETDB_ERROR(e) implementation_defined -/// INTERNAL ONLY. -# define ASIO_GETADDRINFO_ERROR(e) implementation_defined -/// INTERNAL ONLY. -# define ASIO_WIN_OR_POSIX(e_win, e_posix) implementation_defined -#elif defined(BOOST_WINDOWS) || defined(__CYGWIN__) -# define ASIO_NATIVE_ERROR(e) e -# define ASIO_SOCKET_ERROR(e) WSA ## e -# define ASIO_NETDB_ERROR(e) WSA ## e -# define ASIO_GETADDRINFO_ERROR(e) WSA ## e -# define ASIO_WIN_OR_POSIX(e_win, e_posix) e_win -#else -# define ASIO_NATIVE_ERROR(e) e -# define ASIO_SOCKET_ERROR(e) e -# define ASIO_NETDB_ERROR(e) e -# define ASIO_GETADDRINFO_ERROR(e) e -# define ASIO_WIN_OR_POSIX(e_win, e_posix) e_posix -#endif - -namespace asio { -namespace error { - -enum basic_errors -{ - /// Permission denied. - access_denied = ASIO_SOCKET_ERROR(EACCES), - - /// Address family not supported by protocol. - address_family_not_supported = ASIO_SOCKET_ERROR(EAFNOSUPPORT), - - /// Address already in use. - address_in_use = ASIO_SOCKET_ERROR(EADDRINUSE), - - /// Transport endpoint is already connected. - already_connected = ASIO_SOCKET_ERROR(EISCONN), - - /// Operation already in progress. - already_started = ASIO_SOCKET_ERROR(EALREADY), - - /// Broken pipe. - broken_pipe = ASIO_WIN_OR_POSIX( - ASIO_NATIVE_ERROR(ERROR_BROKEN_PIPE), - ASIO_NATIVE_ERROR(EPIPE)), - - /// A connection has been aborted. - connection_aborted = ASIO_SOCKET_ERROR(ECONNABORTED), - - /// Connection refused. - connection_refused = ASIO_SOCKET_ERROR(ECONNREFUSED), - - /// Connection reset by peer. - connection_reset = ASIO_SOCKET_ERROR(ECONNRESET), - - /// Bad file descriptor. - bad_descriptor = ASIO_SOCKET_ERROR(EBADF), - - /// Bad address. - fault = ASIO_SOCKET_ERROR(EFAULT), - - /// No route to host. - host_unreachable = ASIO_SOCKET_ERROR(EHOSTUNREACH), - - /// Operation now in progress. - in_progress = ASIO_SOCKET_ERROR(EINPROGRESS), - - /// Interrupted system call. - interrupted = ASIO_SOCKET_ERROR(EINTR), - - /// Invalid argument. - invalid_argument = ASIO_SOCKET_ERROR(EINVAL), - - /// Message too long. - message_size = ASIO_SOCKET_ERROR(EMSGSIZE), - - /// The name was too long. - name_too_long = ASIO_SOCKET_ERROR(ENAMETOOLONG), - - /// Network is down. - network_down = ASIO_SOCKET_ERROR(ENETDOWN), - - /// Network dropped connection on reset. - network_reset = ASIO_SOCKET_ERROR(ENETRESET), - - /// Network is unreachable. - network_unreachable = ASIO_SOCKET_ERROR(ENETUNREACH), - - /// Too many open files. - no_descriptors = ASIO_SOCKET_ERROR(EMFILE), - - /// No buffer space available. - no_buffer_space = ASIO_SOCKET_ERROR(ENOBUFS), - - /// Cannot allocate memory. - no_memory = ASIO_WIN_OR_POSIX( - ASIO_NATIVE_ERROR(ERROR_OUTOFMEMORY), - ASIO_NATIVE_ERROR(ENOMEM)), - - /// Operation not permitted. - no_permission = ASIO_WIN_OR_POSIX( - ASIO_NATIVE_ERROR(ERROR_ACCESS_DENIED), - ASIO_NATIVE_ERROR(EPERM)), - - /// Protocol not available. - no_protocol_option = ASIO_SOCKET_ERROR(ENOPROTOOPT), - - /// Transport endpoint is not connected. - not_connected = ASIO_SOCKET_ERROR(ENOTCONN), - - /// Socket operation on non-socket. - not_socket = ASIO_SOCKET_ERROR(ENOTSOCK), - - /// Operation cancelled. - operation_aborted = ASIO_WIN_OR_POSIX( - ASIO_NATIVE_ERROR(ERROR_OPERATION_ABORTED), - ASIO_NATIVE_ERROR(ECANCELED)), - - /// Operation not supported. - operation_not_supported = ASIO_SOCKET_ERROR(EOPNOTSUPP), - - /// Cannot send after transport endpoint shutdown. - shut_down = ASIO_SOCKET_ERROR(ESHUTDOWN), - - /// Connection timed out. - timed_out = ASIO_SOCKET_ERROR(ETIMEDOUT), - - /// Resource temporarily unavailable. - try_again = ASIO_WIN_OR_POSIX( - ASIO_NATIVE_ERROR(ERROR_RETRY), - ASIO_NATIVE_ERROR(EAGAIN)), - - /// The socket is marked non-blocking and the requested operation would block. - would_block = ASIO_SOCKET_ERROR(EWOULDBLOCK) -}; - -enum netdb_errors -{ - /// Host not found (authoritative). - host_not_found = ASIO_NETDB_ERROR(HOST_NOT_FOUND), - - /// Host not found (non-authoritative). - host_not_found_try_again = ASIO_NETDB_ERROR(TRY_AGAIN), - - /// The query is valid but does not have associated address data. - no_data = ASIO_NETDB_ERROR(NO_DATA), - - /// A non-recoverable error occurred. - no_recovery = ASIO_NETDB_ERROR(NO_RECOVERY) -}; - -enum addrinfo_errors -{ - /// The service is not supported for the given socket type. - service_not_found = ASIO_WIN_OR_POSIX( - ASIO_NATIVE_ERROR(WSATYPE_NOT_FOUND), - ASIO_GETADDRINFO_ERROR(EAI_SERVICE)), - - /// The socket type is not supported. - socket_type_not_supported = ASIO_WIN_OR_POSIX( - ASIO_NATIVE_ERROR(WSAESOCKTNOSUPPORT), - ASIO_GETADDRINFO_ERROR(EAI_SOCKTYPE)) -}; - -enum misc_errors -{ - /// Already open. - already_open = 1, - - /// End of file or stream. - eof, - - /// Element not found. - not_found, - - /// The descriptor cannot fit into the select system call's fd_set. - fd_set_failure -}; - -enum ssl_errors -{ -}; - -// boostify: error category definitions go here. - -inline asio::error_code make_error_code(basic_errors e) -{ - return asio::error_code( - static_cast(e), get_system_category()); -} - -inline asio::error_code make_error_code(netdb_errors e) -{ - return asio::error_code( - static_cast(e), get_netdb_category()); -} - -inline asio::error_code make_error_code(addrinfo_errors e) -{ - return asio::error_code( - static_cast(e), get_addrinfo_category()); -} - -inline asio::error_code make_error_code(misc_errors e) -{ - return asio::error_code( - static_cast(e), get_misc_category()); -} - -inline asio::error_code make_error_code(ssl_errors e) -{ - return asio::error_code( - static_cast(e), get_ssl_category()); -} - -} // namespace error -} // namespace asio - -#undef ASIO_NATIVE_ERROR -#undef ASIO_SOCKET_ERROR -#undef ASIO_NETDB_ERROR -#undef ASIO_GETADDRINFO_ERROR -#undef ASIO_WIN_OR_POSIX - -#include "asio/impl/error_code.ipp" - -#include "asio/detail/pop_options.hpp" - -#endif // ASIO_ERROR_HPP diff --git a/libtorrent/include/asio/error_code.hpp b/libtorrent/include/asio/error_code.hpp deleted file mode 100644 index 9e67fca82..000000000 --- a/libtorrent/include/asio/error_code.hpp +++ /dev/null @@ -1,164 +0,0 @@ -// -// error_code.hpp -// ~~~~~~~~~~~~~~ -// -// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -#ifndef ASIO_ERROR_CODE_HPP -#define ASIO_ERROR_CODE_HPP - -#if defined(_MSC_VER) && (_MSC_VER >= 1200) -# pragma once -#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) - -#include "asio/detail/push_options.hpp" - -#include "asio/detail/push_options.hpp" -#include -#include -#include "asio/detail/pop_options.hpp" - -#if defined(GENERATING_DOCUMENTATION) -# define ASIO_WIN_OR_POSIX(e_win, e_posix) implementation_defined -#elif defined(BOOST_WINDOWS) || defined(__CYGWIN__) -# define ASIO_WIN_OR_POSIX(e_win, e_posix) e_win -#else -# define ASIO_WIN_OR_POSIX(e_win, e_posix) e_posix -#endif - -namespace asio { - -namespace error -{ - /// Available error code categories. - enum error_category - { - /// System error codes. - system_category = ASIO_WIN_OR_POSIX(0, 0), - - /// Error codes from NetDB functions. - netdb_category = ASIO_WIN_OR_POSIX(system_category, 1), - - /// Error codes from getaddrinfo. - addrinfo_category = ASIO_WIN_OR_POSIX(system_category, 2), - - /// Miscellaneous error codes. - misc_category = ASIO_WIN_OR_POSIX(3, 3), - - /// SSL error codes. - ssl_category = ASIO_WIN_OR_POSIX(4, 4) - }; - - // Category getters. - inline error_category get_system_category() { return system_category; } - inline error_category get_netdb_category() { return netdb_category; } - inline error_category get_addrinfo_category() { return addrinfo_category; } - inline error_category get_misc_category() { return misc_category; } - inline error_category get_ssl_category() { return ssl_category; } - -} // namespace error - -/// Bring error category type into the asio namespace. -typedef asio::error::error_category error_category; - -/// Class to represent an error code value. -class error_code -{ -public: - /// The underlying representation of an error code. - typedef int value_type; - - /// Default constructor. - error_code() - : value_(0), - category_(error::system_category) - { - } - - /// Construct with specific error code and category. - error_code(value_type v, error_category c) - : value_(v), - category_(c) - { - } - - /// Construct from an error code enum. - template - error_code(ErrorEnum e) - { - *this = make_error_code(e); - } - - /// Get the error value. - value_type value() const - { - return value_; - } - - /// Get the error category. - error_category category() const - { - return category_; - } - - /// Get the message associated with the error. - std::string message() const; - - struct unspecified_bool_type_t - { - }; - - typedef void (*unspecified_bool_type)(unspecified_bool_type_t); - - static void unspecified_bool_true(unspecified_bool_type_t) - { - } - - /// Operator returns non-null if there is a non-success error code. - operator unspecified_bool_type() const - { - if (value_ == 0) - return 0; - else - return &error_code::unspecified_bool_true; - } - - /// Operator to test if the error represents success. - bool operator!() const - { - return value_ == 0; - } - - /// Equality operator to compare two error objects. - friend bool operator==(const error_code& e1, const error_code& e2) - { - return e1.value_ == e2.value_ && e1.category_ == e2.category_; - } - - /// Inequality operator to compare two error objects. - friend bool operator!=(const error_code& e1, const error_code& e2) - { - return e1.value_ != e2.value_ || e1.category_ != e2.category_; - } - -private: - // The value associated with the error code. - value_type value_; - - // The category associated with the error code. - error_category category_; -}; - -} // namespace asio - -#undef ASIO_WIN_OR_POSIX - -#include "asio/error.hpp" - -#include "asio/detail/pop_options.hpp" - -#endif // ASIO_ERROR_CODE_HPP diff --git a/libtorrent/include/asio/handler_alloc_hook.hpp b/libtorrent/include/asio/handler_alloc_hook.hpp deleted file mode 100644 index 8666cfb31..000000000 --- a/libtorrent/include/asio/handler_alloc_hook.hpp +++ /dev/null @@ -1,88 +0,0 @@ -// -// handler_alloc_hook.hpp -// ~~~~~~~~~~~~~~~~~~~~~~ -// -// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -#ifndef ASIO_HANDLER_ALLOC_HOOK_HPP -#define ASIO_HANDLER_ALLOC_HOOK_HPP - -#if defined(_MSC_VER) && (_MSC_VER >= 1200) -# pragma once -#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) - -#include "asio/detail/push_options.hpp" - -#include "asio/detail/push_options.hpp" -#include -#include -#include "asio/detail/pop_options.hpp" - -namespace asio { - -/// Default allocation function for handlers. -/** - * Asynchronous operations may need to allocate temporary objects. Since - * asynchronous operations have a handler function object, these temporary - * objects can be said to be associated with the handler. - * - * Implement asio_handler_allocate and asio_handler_deallocate for your own - * handlers to provide custom allocation for these temporary objects. - * - * This default implementation is simply: - * @code - * return ::operator new(size); - * @endcode - * - * @note All temporary objects associated with a handler will be deallocated - * before the upcall to the handler is performed. This allows the same memory to - * be reused for a subsequent asynchronous operation initiated by the handler. - * - * @par Example - * @code - * class my_handler; - * - * void* asio_handler_allocate(std::size_t size, my_handler* context) - * { - * return ::operator new(size); - * } - * - * void asio_handler_deallocate(void* pointer, std::size_t size, - * my_handler* context) - * { - * ::operator delete(pointer); - * } - * @endcode - */ -inline void* asio_handler_allocate(std::size_t size, ...) -{ - return ::operator new(size); -} - -/// Default deallocation function for handlers. -/** - * Implement asio_handler_allocate and asio_handler_deallocate for your own - * handlers to provide custom allocation for the associated temporary objects. - * - * This default implementation is simply: - * @code - * ::operator delete(pointer); - * @endcode - * - * @sa asio_handler_allocate. - */ -inline void asio_handler_deallocate(void* pointer, std::size_t size, ...) -{ - (void)(size); - ::operator delete(pointer); -} - -} // namespace asio - -#include "asio/detail/pop_options.hpp" - -#endif // ASIO_HANDLER_ALLOC_HOOK_HPP diff --git a/libtorrent/include/asio/handler_invoke_hook.hpp b/libtorrent/include/asio/handler_invoke_hook.hpp deleted file mode 100644 index 0c6587ded..000000000 --- a/libtorrent/include/asio/handler_invoke_hook.hpp +++ /dev/null @@ -1,69 +0,0 @@ -// -// handler_invoke_hook.hpp -// ~~~~~~~~~~~~~~~~~~~~~~~ -// -// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -#ifndef ASIO_HANDLER_INVOKE_HOOK_HPP -#define ASIO_HANDLER_INVOKE_HOOK_HPP - -#if defined(_MSC_VER) && (_MSC_VER >= 1200) -# pragma once -#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) - -#include "asio/detail/push_options.hpp" - -namespace asio { - -/// Default invoke function for handlers. -/** - * Completion handlers for asynchronous operations are invoked by the - * io_service associated with the corresponding object (e.g. a socket or - * deadline_timer). Certain guarantees are made on when the handler may be - * invoked, in particular that a handler can only be invoked from a thread that - * is currently calling asio::io_service::run() on the corresponding - * io_service object. Handlers may subsequently be invoked through other - * objects (such as asio::strand objects) that provide additional - * guarantees. - * - * When asynchronous operations are composed from other asynchronous - * operations, all intermediate handlers should be invoked using the same - * method as the final handler. This is required to ensure that user-defined - * objects are not accessed in a way that may violate the guarantees. This - * hooking function ensures that the invoked method used for the final handler - * is accessible at each intermediate step. - * - * Implement asio_handler_invoke for your own handlers to specify a custom - * invocation strategy. - * - * This default implementation is simply: - * @code - * function(); - * @endcode - * - * @par Example - * @code - * class my_handler; - * - * template - * void asio_handler_invoke(Function function, my_handler* context) - * { - * context->strand_.dispatch(function); - * } - * @endcode - */ -template -inline void asio_handler_invoke(Function function, ...) -{ - function(); -} - -} // namespace asio - -#include "asio/detail/pop_options.hpp" - -#endif // ASIO_HANDLER_INVOKE_HOOK_HPP diff --git a/libtorrent/include/asio/impl/error_code.ipp b/libtorrent/include/asio/impl/error_code.ipp deleted file mode 100644 index fa0520a9f..000000000 --- a/libtorrent/include/asio/impl/error_code.ipp +++ /dev/null @@ -1,104 +0,0 @@ -// -// error_code.ipp -// ~~~~~~~~~~~~~~ -// -// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -#ifndef ASIO_ERROR_CODE_IPP -#define ASIO_ERROR_CODE_IPP - -#if defined(_MSC_VER) && (_MSC_VER >= 1200) -# pragma once -#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) - -#include "asio/detail/push_options.hpp" - -#include "asio/detail/push_options.hpp" -#include -#include -#include -#include "asio/detail/pop_options.hpp" - -#include "asio/error.hpp" -#include "asio/detail/local_free_on_block_exit.hpp" -#include "asio/detail/socket_types.hpp" - -namespace asio { - -inline std::string error_code::message() const -{ - if (*this == error::already_open) - return "Already open."; - if (*this == error::not_found) - return "Not found."; - if (*this == error::fd_set_failure) - return "The descriptor does not fit into the select call's fd_set."; - if (category_ == error::get_ssl_category()) - return "SSL error."; -#if defined(BOOST_WINDOWS) || defined(__CYGWIN__) - value_type value = value_; - if (category() != error::get_system_category() && *this != error::eof) - return "asio error"; - if (*this == error::eof) - value = ERROR_HANDLE_EOF; - char* msg = 0; - DWORD length = ::FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER - | FORMAT_MESSAGE_FROM_SYSTEM - | FORMAT_MESSAGE_IGNORE_INSERTS, 0, value, - MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (char*)&msg, 0, 0); - detail::local_free_on_block_exit local_free_obj(msg); - if (length && msg[length - 1] == '\n') - msg[--length] = '\0'; - if (length && msg[length - 1] == '\r') - msg[--length] = '\0'; - if (length) - return msg; - else - return "asio error"; -#else // defined(BOOST_WINDOWS) - if (*this == error::eof) - return "End of file."; - if (*this == error::host_not_found) - return "Host not found (authoritative)."; - if (*this == error::host_not_found_try_again) - return "Host not found (non-authoritative), try again later."; - if (*this == error::no_recovery) - return "A non-recoverable error occurred during database lookup."; - if (*this == error::no_data) - return "The query is valid, but it does not have associated data."; - if (*this == error::not_found) - return "Element not found."; -#if !defined(__sun) - if (*this == error::operation_aborted) - return "Operation aborted."; -#endif // !defined(__sun) - if (*this == error::service_not_found) - return "Service not found."; - if (*this == error::socket_type_not_supported) - return "Socket type not supported."; - if (category() != error::get_system_category()) - return "asio error"; -#if defined(__sun) || defined(__QNX__) - return strerror(value_); -#elif defined(__MACH__) && defined(__APPLE__) \ -|| defined(__NetBSD__) || defined(__FreeBSD__) || defined(__OpenBSD__) \ -|| defined(_AIX) || defined(__hpux) || defined(__osf__) - char buf[256] = ""; - strerror_r(value_, buf, sizeof(buf)); - return buf; -#else - char buf[256] = ""; - return strerror_r(value_, buf, sizeof(buf)); -#endif -#endif // defined(BOOST_WINDOWS) -} - -} // namespace asio - -#include "asio/detail/pop_options.hpp" - -#endif // ASIO_ERROR_CODE_IPP diff --git a/libtorrent/include/asio/impl/io_service.ipp b/libtorrent/include/asio/impl/io_service.ipp deleted file mode 100644 index e548055fa..000000000 --- a/libtorrent/include/asio/impl/io_service.ipp +++ /dev/null @@ -1,224 +0,0 @@ -// -// io_service.ipp -// ~~~~~~~~~~~~~~ -// -// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -#ifndef ASIO_IO_SERVICE_IPP -#define ASIO_IO_SERVICE_IPP - -#if defined(_MSC_VER) && (_MSC_VER >= 1200) -# pragma once -#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) - -#include "asio/detail/push_options.hpp" - -#include "asio/detail/push_options.hpp" -#include -#include "asio/detail/pop_options.hpp" - -#include "asio/detail/dev_poll_reactor.hpp" -#include "asio/detail/epoll_reactor.hpp" -#include "asio/detail/kqueue_reactor.hpp" -#include "asio/detail/select_reactor.hpp" -#include "asio/detail/service_registry.hpp" -#include "asio/detail/task_io_service.hpp" -#include "asio/detail/throw_error.hpp" -#include "asio/detail/win_iocp_io_service.hpp" - -namespace asio { - -inline io_service::io_service() - : service_registry_(new asio::detail::service_registry(*this)), - impl_(service_registry_->use_service()) -{ - impl_.init((std::numeric_limits::max)()); -} - -inline io_service::io_service(std::size_t concurrency_hint) - : service_registry_(new asio::detail::service_registry(*this)), - impl_(service_registry_->use_service()) -{ - impl_.init(concurrency_hint); -} - -inline io_service::~io_service() -{ - delete service_registry_; -} - -inline std::size_t io_service::run() -{ - asio::error_code ec; - std::size_t s = impl_.run(ec); - asio::detail::throw_error(ec); - return s; -} - -inline std::size_t io_service::run(asio::error_code& ec) -{ - return impl_.run(ec); -} - -inline std::size_t io_service::run_one() -{ - asio::error_code ec; - std::size_t s = impl_.run_one(ec); - asio::detail::throw_error(ec); - return s; -} - -inline std::size_t io_service::run_one(asio::error_code& ec) -{ - return impl_.run_one(ec); -} - -inline std::size_t io_service::poll() -{ - asio::error_code ec; - std::size_t s = impl_.poll(ec); - asio::detail::throw_error(ec); - return s; -} - -inline std::size_t io_service::poll(asio::error_code& ec) -{ - return impl_.poll(ec); -} - -inline std::size_t io_service::poll_one() -{ - asio::error_code ec; - std::size_t s = impl_.poll_one(ec); - asio::detail::throw_error(ec); - return s; -} - -inline std::size_t io_service::poll_one(asio::error_code& ec) -{ - return impl_.poll_one(ec); -} - -inline void io_service::stop() -{ - impl_.stop(); -} - -inline void io_service::reset() -{ - impl_.reset(); -} - -template -inline void io_service::dispatch(Handler handler) -{ - impl_.dispatch(handler); -} - -template -inline void io_service::post(Handler handler) -{ - impl_.post(handler); -} - -template -#if defined(GENERATING_DOCUMENTATION) -unspecified -#else -inline detail::wrapped_handler -#endif -io_service::wrap(Handler handler) -{ - return detail::wrapped_handler(*this, handler); -} - -inline io_service::work::work(asio::io_service& io_service) - : io_service_(io_service) -{ - io_service_.impl_.work_started(); -} - -inline io_service::work::work(const work& other) - : io_service_(other.io_service_) -{ - io_service_.impl_.work_started(); -} - -inline io_service::work::~work() -{ - io_service_.impl_.work_finished(); -} - -inline asio::io_service& io_service::work::io_service() -{ - return io_service_; -} - -inline asio::io_service& io_service::work::get_io_service() -{ - return io_service_; -} - -inline io_service::service::service(asio::io_service& owner) - : owner_(owner), - type_info_(0), - next_(0) -{ -} - -inline io_service::service::~service() -{ -} - -inline asio::io_service& io_service::service::io_service() -{ - return owner_; -} - -inline asio::io_service& io_service::service::get_io_service() -{ - return owner_; -} - -template -inline Service& use_service(io_service& ios) -{ - // Check that Service meets the necessary type requirements. - (void)static_cast(static_cast(0)); - (void)static_cast(&Service::id); - - return ios.service_registry_->template use_service(); -} - -template -void add_service(io_service& ios, Service* svc) -{ - // Check that Service meets the necessary type requirements. - (void)static_cast(static_cast(0)); - (void)static_cast(&Service::id); - - if (&ios != &svc->io_service()) - boost::throw_exception(invalid_service_owner()); - if (!ios.service_registry_->template add_service(svc)) - boost::throw_exception(service_already_exists()); -} - -template -bool has_service(io_service& ios) -{ - // Check that Service meets the necessary type requirements. - (void)static_cast(static_cast(0)); - (void)static_cast(&Service::id); - - return ios.service_registry_->template has_service(); -} - -} // namespace asio - -#include "asio/detail/pop_options.hpp" - -#endif // ASIO_IO_SERVICE_IPP diff --git a/libtorrent/include/asio/impl/read.ipp b/libtorrent/include/asio/impl/read.ipp deleted file mode 100644 index b3d573905..000000000 --- a/libtorrent/include/asio/impl/read.ipp +++ /dev/null @@ -1,314 +0,0 @@ -// -// read.ipp -// ~~~~~~~~ -// -// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -#ifndef ASIO_READ_IPP -#define ASIO_READ_IPP - -#if defined(_MSC_VER) && (_MSC_VER >= 1200) -# pragma once -#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) - -#include "asio/detail/push_options.hpp" - -#include "asio/detail/push_options.hpp" -#include -#include "asio/detail/pop_options.hpp" - -#include "asio/buffer.hpp" -#include "asio/completion_condition.hpp" -#include "asio/error.hpp" -#include "asio/detail/bind_handler.hpp" -#include "asio/detail/consuming_buffers.hpp" -#include "asio/detail/handler_alloc_helpers.hpp" -#include "asio/detail/handler_invoke_helpers.hpp" -#include "asio/detail/throw_error.hpp" - -namespace asio { - -template -std::size_t read(SyncReadStream& s, const MutableBufferSequence& buffers, - CompletionCondition completion_condition, asio::error_code& ec) -{ - asio::detail::consuming_buffers< - mutable_buffer, MutableBufferSequence> tmp(buffers); - std::size_t total_transferred = 0; - while (tmp.begin() != tmp.end()) - { - std::size_t bytes_transferred = s.read_some(tmp, ec); - tmp.consume(bytes_transferred); - total_transferred += bytes_transferred; - if (completion_condition(ec, total_transferred)) - return total_transferred; - } - ec = asio::error_code(); - return total_transferred; -} - -template -inline std::size_t read(SyncReadStream& s, const MutableBufferSequence& buffers) -{ - asio::error_code ec; - std::size_t bytes_transferred = read(s, buffers, transfer_all(), ec); - asio::detail::throw_error(ec); - return bytes_transferred; -} - -template -inline std::size_t read(SyncReadStream& s, const MutableBufferSequence& buffers, - CompletionCondition completion_condition) -{ - asio::error_code ec; - std::size_t bytes_transferred = read(s, buffers, completion_condition, ec); - asio::detail::throw_error(ec); - return bytes_transferred; -} - -template -std::size_t read(SyncReadStream& s, - asio::basic_streambuf& b, - CompletionCondition completion_condition, asio::error_code& ec) -{ - std::size_t total_transferred = 0; - for (;;) - { - std::size_t bytes_available = - std::min(512, b.max_size() - b.size()); - std::size_t bytes_transferred = s.read_some(b.prepare(bytes_available), ec); - b.commit(bytes_transferred); - total_transferred += bytes_transferred; - if (b.size() == b.max_size() - || completion_condition(ec, total_transferred)) - return total_transferred; - } -} - -template -inline std::size_t read(SyncReadStream& s, - asio::basic_streambuf& b) -{ - asio::error_code ec; - std::size_t bytes_transferred = read(s, b, transfer_all(), ec); - asio::detail::throw_error(ec); - return bytes_transferred; -} - -template -inline std::size_t read(SyncReadStream& s, - asio::basic_streambuf& b, - CompletionCondition completion_condition) -{ - asio::error_code ec; - std::size_t bytes_transferred = read(s, b, completion_condition, ec); - asio::detail::throw_error(ec); - return bytes_transferred; -} - -namespace detail -{ - template - class read_handler - { - public: - typedef asio::detail::consuming_buffers< - mutable_buffer, MutableBufferSequence> buffers_type; - - read_handler(AsyncReadStream& stream, const buffers_type& buffers, - CompletionCondition completion_condition, ReadHandler handler) - : stream_(stream), - buffers_(buffers), - total_transferred_(0), - completion_condition_(completion_condition), - handler_(handler) - { - } - - void operator()(const asio::error_code& ec, - std::size_t bytes_transferred) - { - total_transferred_ += bytes_transferred; - buffers_.consume(bytes_transferred); - if (completion_condition_(ec, total_transferred_) - || buffers_.begin() == buffers_.end()) - { - handler_(ec, total_transferred_); - } - else - { - stream_.async_read_some(buffers_, *this); - } - } - - //private: - AsyncReadStream& stream_; - buffers_type buffers_; - std::size_t total_transferred_; - CompletionCondition completion_condition_; - ReadHandler handler_; - }; - - template - inline void* asio_handler_allocate(std::size_t size, - read_handler* this_handler) - { - return asio_handler_alloc_helpers::allocate( - size, &this_handler->handler_); - } - - template - inline void asio_handler_deallocate(void* pointer, std::size_t size, - read_handler* this_handler) - { - asio_handler_alloc_helpers::deallocate( - pointer, size, &this_handler->handler_); - } - - template - inline void asio_handler_invoke(const Function& function, - read_handler* this_handler) - { - asio_handler_invoke_helpers::invoke( - function, &this_handler->handler_); - } -} // namespace detail - -template -inline void async_read(AsyncReadStream& s, const MutableBufferSequence& buffers, - CompletionCondition completion_condition, ReadHandler handler) -{ - asio::detail::consuming_buffers< - mutable_buffer, MutableBufferSequence> tmp(buffers); - s.async_read_some(tmp, - detail::read_handler( - s, tmp, completion_condition, handler)); -} - -template -inline void async_read(AsyncReadStream& s, const MutableBufferSequence& buffers, - ReadHandler handler) -{ - async_read(s, buffers, transfer_all(), handler); -} - -namespace detail -{ - template - class read_streambuf_handler - { - public: - read_streambuf_handler(AsyncReadStream& stream, - basic_streambuf& streambuf, - CompletionCondition completion_condition, ReadHandler handler) - : stream_(stream), - streambuf_(streambuf), - total_transferred_(0), - completion_condition_(completion_condition), - handler_(handler) - { - } - - void operator()(const asio::error_code& ec, - std::size_t bytes_transferred) - { - total_transferred_ += bytes_transferred; - streambuf_.commit(bytes_transferred); - if (streambuf_.size() == streambuf_.max_size() - || completion_condition_(ec, total_transferred_)) - { - handler_(ec, total_transferred_); - } - else - { - std::size_t bytes_available = - std::min(512, streambuf_.max_size() - streambuf_.size()); - stream_.async_read_some(streambuf_.prepare(bytes_available), *this); - } - } - - //private: - AsyncReadStream& stream_; - asio::basic_streambuf& streambuf_; - std::size_t total_transferred_; - CompletionCondition completion_condition_; - ReadHandler handler_; - }; - - template - inline void* asio_handler_allocate(std::size_t size, - read_streambuf_handler* this_handler) - { - return asio_handler_alloc_helpers::allocate( - size, &this_handler->handler_); - } - - template - inline void asio_handler_deallocate(void* pointer, std::size_t size, - read_streambuf_handler* this_handler) - { - asio_handler_alloc_helpers::deallocate( - pointer, size, &this_handler->handler_); - } - - template - inline void asio_handler_invoke(const Function& function, - read_streambuf_handler* this_handler) - { - asio_handler_invoke_helpers::invoke( - function, &this_handler->handler_); - } -} // namespace detail - -template -inline void async_read(AsyncReadStream& s, - asio::basic_streambuf& b, - CompletionCondition completion_condition, ReadHandler handler) -{ - std::size_t bytes_available = - std::min(512, b.max_size() - b.size()); - s.async_read_some(b.prepare(bytes_available), - detail::read_streambuf_handler( - s, b, completion_condition, handler)); -} - -template -inline void async_read(AsyncReadStream& s, - asio::basic_streambuf& b, ReadHandler handler) -{ - async_read(s, b, transfer_all(), handler); -} - -} // namespace asio - -#include "asio/detail/pop_options.hpp" - -#endif // ASIO_READ_IPP diff --git a/libtorrent/include/asio/impl/read_at.ipp b/libtorrent/include/asio/impl/read_at.ipp deleted file mode 100644 index 2412487b5..000000000 --- a/libtorrent/include/asio/impl/read_at.ipp +++ /dev/null @@ -1,337 +0,0 @@ -// -// read_at.ipp -// ~~~~~~~~~~~ -// -// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -#ifndef ASIO_READ_AT_IPP -#define ASIO_READ_AT_IPP - -#if defined(_MSC_VER) && (_MSC_VER >= 1200) -# pragma once -#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) - -#include "asio/detail/push_options.hpp" - -#include "asio/detail/push_options.hpp" -#include -#include "asio/detail/pop_options.hpp" - -#include "asio/buffer.hpp" -#include "asio/completion_condition.hpp" -#include "asio/error.hpp" -#include "asio/detail/bind_handler.hpp" -#include "asio/detail/consuming_buffers.hpp" -#include "asio/detail/handler_alloc_helpers.hpp" -#include "asio/detail/handler_invoke_helpers.hpp" -#include "asio/detail/throw_error.hpp" - -namespace asio { - -template -std::size_t read_at(SyncRandomAccessReadDevice& d, - boost::uint64_t offset, const MutableBufferSequence& buffers, - CompletionCondition completion_condition, asio::error_code& ec) -{ - asio::detail::consuming_buffers< - mutable_buffer, MutableBufferSequence> tmp(buffers); - std::size_t total_transferred = 0; - while (tmp.begin() != tmp.end()) - { - std::size_t bytes_transferred = d.read_some_at( - offset + total_transferred, tmp, ec); - tmp.consume(bytes_transferred); - total_transferred += bytes_transferred; - if (completion_condition(ec, total_transferred)) - return total_transferred; - } - ec = asio::error_code(); - return total_transferred; -} - -template -inline std::size_t read_at(SyncRandomAccessReadDevice& d, - boost::uint64_t offset, const MutableBufferSequence& buffers) -{ - asio::error_code ec; - std::size_t bytes_transferred = read_at( - d, offset, buffers, transfer_all(), ec); - asio::detail::throw_error(ec); - return bytes_transferred; -} - -template -inline std::size_t read_at(SyncRandomAccessReadDevice& d, - boost::uint64_t offset, const MutableBufferSequence& buffers, - CompletionCondition completion_condition) -{ - asio::error_code ec; - std::size_t bytes_transferred = read_at( - d, offset, buffers, completion_condition, ec); - asio::detail::throw_error(ec); - return bytes_transferred; -} - -template -std::size_t read_at(SyncRandomAccessReadDevice& d, - boost::uint64_t offset, asio::basic_streambuf& b, - CompletionCondition completion_condition, asio::error_code& ec) -{ - std::size_t total_transferred = 0; - for (;;) - { - std::size_t bytes_available = - std::min(512, b.max_size() - b.size()); - std::size_t bytes_transferred = d.read_some_at( - offset + total_transferred, b.prepare(bytes_available), ec); - b.commit(bytes_transferred); - total_transferred += bytes_transferred; - if (b.size() == b.max_size() - || completion_condition(ec, total_transferred)) - return total_transferred; - } -} - -template -inline std::size_t read_at(SyncRandomAccessReadDevice& d, - boost::uint64_t offset, asio::basic_streambuf& b) -{ - asio::error_code ec; - std::size_t bytes_transferred = read_at( - d, offset, b, transfer_all(), ec); - asio::detail::throw_error(ec); - return bytes_transferred; -} - -template -inline std::size_t read_at(SyncRandomAccessReadDevice& d, - boost::uint64_t offset, asio::basic_streambuf& b, - CompletionCondition completion_condition) -{ - asio::error_code ec; - std::size_t bytes_transferred = read_at( - d, offset, b, completion_condition, ec); - asio::detail::throw_error(ec); - return bytes_transferred; -} - -namespace detail -{ - template - class read_at_handler - { - public: - typedef asio::detail::consuming_buffers< - mutable_buffer, MutableBufferSequence> buffers_type; - - read_at_handler(AsyncRandomAccessReadDevice& stream, - boost::uint64_t offset, const buffers_type& buffers, - CompletionCondition completion_condition, ReadHandler handler) - : stream_(stream), - offset_(offset), - buffers_(buffers), - total_transferred_(0), - completion_condition_(completion_condition), - handler_(handler) - { - } - - void operator()(const asio::error_code& ec, - std::size_t bytes_transferred) - { - total_transferred_ += bytes_transferred; - buffers_.consume(bytes_transferred); - if (completion_condition_(ec, total_transferred_) - || buffers_.begin() == buffers_.end()) - { - handler_(ec, total_transferred_); - } - else - { - stream_.async_read_some_at( - offset_ + total_transferred_, buffers_, *this); - } - } - - //private: - AsyncRandomAccessReadDevice& stream_; - boost::uint64_t offset_; - buffers_type buffers_; - std::size_t total_transferred_; - CompletionCondition completion_condition_; - ReadHandler handler_; - }; - - template - inline void* asio_handler_allocate(std::size_t size, - read_at_handler* this_handler) - { - return asio_handler_alloc_helpers::allocate( - size, &this_handler->handler_); - } - - template - inline void asio_handler_deallocate(void* pointer, std::size_t size, - read_at_handler* this_handler) - { - asio_handler_alloc_helpers::deallocate( - pointer, size, &this_handler->handler_); - } - - template - inline void asio_handler_invoke(const Function& function, - read_at_handler* this_handler) - { - asio_handler_invoke_helpers::invoke( - function, &this_handler->handler_); - } -} // namespace detail - -template -inline void async_read_at(AsyncRandomAccessReadDevice& d, - boost::uint64_t offset, const MutableBufferSequence& buffers, - CompletionCondition completion_condition, ReadHandler handler) -{ - asio::detail::consuming_buffers< - mutable_buffer, MutableBufferSequence> tmp(buffers); - d.async_read_some_at(offset, tmp, - detail::read_at_handler( - d, offset, tmp, completion_condition, handler)); -} - -template -inline void async_read_at(AsyncRandomAccessReadDevice& d, - boost::uint64_t offset, const MutableBufferSequence& buffers, - ReadHandler handler) -{ - async_read_at(d, offset, buffers, transfer_all(), handler); -} - -namespace detail -{ - template - class read_at_streambuf_handler - { - public: - read_at_streambuf_handler(AsyncRandomAccessReadDevice& stream, - boost::uint64_t offset, basic_streambuf& streambuf, - CompletionCondition completion_condition, ReadHandler handler) - : stream_(stream), - offset_(offset), - streambuf_(streambuf), - total_transferred_(0), - completion_condition_(completion_condition), - handler_(handler) - { - } - - void operator()(const asio::error_code& ec, - std::size_t bytes_transferred) - { - total_transferred_ += bytes_transferred; - streambuf_.commit(bytes_transferred); - if (streambuf_.size() == streambuf_.max_size() - || completion_condition_(ec, total_transferred_)) - { - handler_(ec, total_transferred_); - } - else - { - std::size_t bytes_available = - std::min(512, streambuf_.max_size() - streambuf_.size()); - stream_.async_read_some_at(offset_ + total_transferred_, - streambuf_.prepare(bytes_available), *this); - } - } - - //private: - AsyncRandomAccessReadDevice& stream_; - boost::uint64_t offset_; - asio::basic_streambuf& streambuf_; - std::size_t total_transferred_; - CompletionCondition completion_condition_; - ReadHandler handler_; - }; - - template - inline void* asio_handler_allocate(std::size_t size, - read_at_streambuf_handler* this_handler) - { - return asio_handler_alloc_helpers::allocate( - size, &this_handler->handler_); - } - - template - inline void asio_handler_deallocate(void* pointer, std::size_t size, - read_at_streambuf_handler* this_handler) - { - asio_handler_alloc_helpers::deallocate( - pointer, size, &this_handler->handler_); - } - - template - inline void asio_handler_invoke(const Function& function, - read_at_streambuf_handler* this_handler) - { - asio_handler_invoke_helpers::invoke( - function, &this_handler->handler_); - } -} // namespace detail - -template -inline void async_read_at(AsyncRandomAccessReadDevice& d, - boost::uint64_t offset, asio::basic_streambuf& b, - CompletionCondition completion_condition, ReadHandler handler) -{ - std::size_t bytes_available = - std::min(512, b.max_size() - b.size()); - d.async_read_some_at(offset, b.prepare(bytes_available), - detail::read_at_streambuf_handler( - d, offset, b, completion_condition, handler)); -} - -template -inline void async_read_at(AsyncRandomAccessReadDevice& d, - boost::uint64_t offset, asio::basic_streambuf& b, - ReadHandler handler) -{ - async_read_at(d, offset, b, transfer_all(), handler); -} - -} // namespace asio - -#include "asio/detail/pop_options.hpp" - -#endif // ASIO_READ_AT_IPP diff --git a/libtorrent/include/asio/impl/read_until.ipp b/libtorrent/include/asio/impl/read_until.ipp deleted file mode 100644 index b88b14194..000000000 --- a/libtorrent/include/asio/impl/read_until.ipp +++ /dev/null @@ -1,996 +0,0 @@ -// -// read_until.ipp -// ~~~~~~~~~~~~~~ -// -// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -#ifndef ASIO_READ_UNTIL_IPP -#define ASIO_READ_UNTIL_IPP - -#if defined(_MSC_VER) && (_MSC_VER >= 1200) -# pragma once -#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) - -#include "asio/detail/push_options.hpp" - -#include "asio/detail/push_options.hpp" -#include -#include -#include -#include -#include "asio/detail/pop_options.hpp" - -#include "asio/buffer.hpp" -#include "asio/buffers_iterator.hpp" -#include "asio/detail/bind_handler.hpp" -#include "asio/detail/handler_alloc_helpers.hpp" -#include "asio/detail/handler_invoke_helpers.hpp" -#include "asio/detail/throw_error.hpp" - -namespace asio { - -template -inline std::size_t read_until(SyncReadStream& s, - asio::basic_streambuf& b, char delim) -{ - asio::error_code ec; - std::size_t bytes_transferred = read_until(s, b, delim, ec); - asio::detail::throw_error(ec); - return bytes_transferred; -} - -template -std::size_t read_until(SyncReadStream& s, - asio::basic_streambuf& b, char delim, - asio::error_code& ec) -{ - std::size_t next_search_start = 0; - for (;;) - { - // Determine the range of the data to be searched. - typedef typename asio::basic_streambuf< - Allocator>::const_buffers_type const_buffers_type; - typedef asio::buffers_iterator iterator; - const_buffers_type buffers = b.data(); - iterator begin = iterator::begin(buffers); - iterator start = begin + next_search_start; - iterator end = iterator::end(buffers); - - // Look for a match. - iterator iter = std::find(start, end, delim); - if (iter != end) - { - // Found a match. We're done. - ec = asio::error_code(); - return iter - begin + 1; - } - else - { - // No match. Next search can start with the new data. - next_search_start = end - begin; - } - - // Check if buffer is full. - if (b.size() == b.max_size()) - { - ec = error::not_found; - return 0; - } - - // Need more data. - std::size_t bytes_available = - std::min(512, b.max_size() - b.size()); - b.commit(s.read_some(b.prepare(bytes_available), ec)); - if (ec) - return 0; - } -} - -template -inline std::size_t read_until(SyncReadStream& s, - asio::basic_streambuf& b, const std::string& delim) -{ - asio::error_code ec; - std::size_t bytes_transferred = read_until(s, b, delim, ec); - asio::detail::throw_error(ec); - return bytes_transferred; -} - -namespace detail -{ - // Algorithm that finds a subsequence of equal values in a sequence. Returns - // (iterator,true) if a full match was found, in which case the iterator - // points to the beginning of the match. Returns (iterator,false) if a - // partial match was found at the end of the first sequence, in which case - // the iterator points to the beginning of the partial match. Returns - // (last1,false) if no full or partial match was found. - template - std::pair partial_search( - Iterator1 first1, Iterator1 last1, Iterator2 first2, Iterator2 last2) - { - for (Iterator1 iter1 = first1; iter1 != last1; ++iter1) - { - Iterator1 test_iter1 = iter1; - Iterator2 test_iter2 = first2; - for (;; ++test_iter1, ++test_iter2) - { - if (test_iter2 == last2) - return std::make_pair(iter1, true); - if (test_iter1 == last1) - { - if (test_iter2 != first2) - return std::make_pair(iter1, false); - else - break; - } - if (*test_iter1 != *test_iter2) - break; - } - } - return std::make_pair(last1, false); - } -} // namespace detail - -template -std::size_t read_until(SyncReadStream& s, - asio::basic_streambuf& b, const std::string& delim, - asio::error_code& ec) -{ - std::size_t next_search_start = 0; - for (;;) - { - // Determine the range of the data to be searched. - typedef typename asio::basic_streambuf< - Allocator>::const_buffers_type const_buffers_type; - typedef asio::buffers_iterator iterator; - const_buffers_type buffers = b.data(); - iterator begin = iterator::begin(buffers); - iterator start = begin + next_search_start; - iterator end = iterator::end(buffers); - - // Look for a match. - std::pair result = asio::detail::partial_search( - start, end, delim.begin(), delim.end()); - if (result.first != end) - { - if (result.second) - { - // Full match. We're done. - ec = asio::error_code(); - return result.first - begin + delim.length(); - } - else - { - // Partial match. Next search needs to start from beginning of match. - next_search_start = result.first - begin; - } - } - else - { - // No match. Next search can start with the new data. - next_search_start = end - begin; - } - - // Check if buffer is full. - if (b.size() == b.max_size()) - { - ec = error::not_found; - return 0; - } - - // Need more data. - std::size_t bytes_available = - std::min(512, b.max_size() - b.size()); - b.commit(s.read_some(b.prepare(bytes_available), ec)); - if (ec) - return 0; - } -} - -template -inline std::size_t read_until(SyncReadStream& s, - asio::basic_streambuf& b, const boost::regex& expr) -{ - asio::error_code ec; - std::size_t bytes_transferred = read_until(s, b, expr, ec); - asio::detail::throw_error(ec); - return bytes_transferred; -} - -template -std::size_t read_until(SyncReadStream& s, - asio::basic_streambuf& b, const boost::regex& expr, - asio::error_code& ec) -{ - std::size_t next_search_start = 0; - for (;;) - { - // Determine the range of the data to be searched. - typedef typename asio::basic_streambuf< - Allocator>::const_buffers_type const_buffers_type; - typedef asio::buffers_iterator iterator; - const_buffers_type buffers = b.data(); - iterator begin = iterator::begin(buffers); - iterator start = begin + next_search_start; - iterator end = iterator::end(buffers); - - // Look for a match. - boost::match_results match_results; - if (boost::regex_search(start, end, match_results, expr, - boost::match_default | boost::match_partial)) - { - if (match_results[0].matched) - { - // Full match. We're done. - ec = asio::error_code(); - return match_results[0].second - begin; - } - else - { - // Partial match. Next search needs to start from beginning of match. - next_search_start = match_results[0].first - begin; - } - } - else - { - // No match. Next search can start with the new data. - next_search_start = end - begin; - } - - // Check if buffer is full. - if (b.size() == b.max_size()) - { - ec = error::not_found; - return 0; - } - - // Need more data. - std::size_t bytes_available = - std::min(512, b.max_size() - b.size()); - b.commit(s.read_some(b.prepare(bytes_available), ec)); - if (ec) - return 0; - } -} - -template -std::size_t read_until(SyncReadStream& s, - asio::basic_streambuf& b, - MatchCondition match_condition, asio::error_code& ec, - typename boost::enable_if >::type*) -{ - std::size_t next_search_start = 0; - for (;;) - { - // Determine the range of the data to be searched. - typedef typename asio::basic_streambuf< - Allocator>::const_buffers_type const_buffers_type; - typedef asio::buffers_iterator iterator; - const_buffers_type buffers = b.data(); - iterator begin = iterator::begin(buffers); - iterator start = begin + next_search_start; - iterator end = iterator::end(buffers); - - // Look for a match. - std::pair result = match_condition(start, end); - if (result.first != end) - { - if (result.second) - { - // Full match. We're done. - ec = asio::error_code(); - return result.first - begin; - } - else - { - // Partial match. Next search needs to start from beginning of match. - next_search_start = result.first - begin; - } - } - else - { - // No match. Next search can start with the new data. - next_search_start = end - begin; - } - - // Check if buffer is full. - if (b.size() == b.max_size()) - { - ec = error::not_found; - return 0; - } - - // Need more data. - std::size_t bytes_available = - std::min(512, b.max_size() - b.size()); - b.commit(s.read_some(b.prepare(bytes_available), ec)); - if (ec) - return 0; - } -} - -template -inline std::size_t read_until(SyncReadStream& s, - asio::basic_streambuf& b, MatchCondition match_condition, - typename boost::enable_if >::type*) -{ - asio::error_code ec; - std::size_t bytes_transferred = read_until(s, b, match_condition, ec); - asio::detail::throw_error(ec); - return bytes_transferred; -} - -namespace detail -{ - template - class read_until_delim_handler - { - public: - read_until_delim_handler(AsyncReadStream& stream, - asio::basic_streambuf& streambuf, char delim, - std::size_t next_search_start, ReadHandler handler) - : stream_(stream), - streambuf_(streambuf), - delim_(delim), - next_search_start_(next_search_start), - handler_(handler) - { - } - - void operator()(const asio::error_code& ec, - std::size_t bytes_transferred) - { - // Check for errors. - if (ec) - { - std::size_t bytes = 0; - handler_(ec, bytes); - return; - } - - // Commit received data to streambuf's get area. - streambuf_.commit(bytes_transferred); - - // Determine the range of the data to be searched. - typedef typename asio::basic_streambuf< - Allocator>::const_buffers_type const_buffers_type; - typedef asio::buffers_iterator iterator; - const_buffers_type buffers = streambuf_.data(); - iterator begin = iterator::begin(buffers); - iterator start = begin + next_search_start_; - iterator end = iterator::end(buffers); - - // Look for a match. - iterator iter = std::find(start, end, delim_); - if (iter != end) - { - // Found a match. We're done. - std::size_t bytes = iter - begin + 1; - handler_(ec, bytes); - return; - } - - // No match. Check if buffer is full. - if (streambuf_.size() == streambuf_.max_size()) - { - std::size_t bytes = 0; - asio::error_code ec(error::not_found); - handler_(ec, bytes); - return; - } - - // Next search can start with the new data. - next_search_start_ = end - begin; - - // Start a new asynchronous read operation to obtain more data. - std::size_t bytes_available = - std::min(512, streambuf_.max_size() - streambuf_.size()); - stream_.async_read_some(streambuf_.prepare(bytes_available), *this); - } - - //private: - AsyncReadStream& stream_; - asio::basic_streambuf& streambuf_; - char delim_; - std::size_t next_search_start_; - ReadHandler handler_; - }; - - template - inline void* asio_handler_allocate(std::size_t size, - read_until_delim_handler* this_handler) - { - return asio_handler_alloc_helpers::allocate( - size, &this_handler->handler_); - } - - template - inline void asio_handler_deallocate(void* pointer, std::size_t size, - read_until_delim_handler* this_handler) - { - asio_handler_alloc_helpers::deallocate( - pointer, size, &this_handler->handler_); - } - - template - inline void asio_handler_invoke(const Function& function, - read_until_delim_handler* this_handler) - { - asio_handler_invoke_helpers::invoke( - function, &this_handler->handler_); - } -} // namespace detail - -template -void async_read_until(AsyncReadStream& s, - asio::basic_streambuf& b, char delim, ReadHandler handler) -{ - // Determine the range of the data to be searched. - typedef typename asio::basic_streambuf< - Allocator>::const_buffers_type const_buffers_type; - typedef asio::buffers_iterator iterator; - const_buffers_type buffers = b.data(); - iterator begin = iterator::begin(buffers); - iterator end = iterator::end(buffers); - - // Look for a match. - iterator iter = std::find(begin, end, delim); - if (iter != end) - { - // Found a match. We're done. - asio::error_code ec; - std::size_t bytes = iter - begin + 1; - s.io_service().post(detail::bind_handler(handler, ec, bytes)); - return; - } - - // No match. Check if buffer is full. - if (b.size() == b.max_size()) - { - asio::error_code ec(error::not_found); - s.io_service().post(detail::bind_handler(handler, ec, 0)); - return; - } - - // Start a new asynchronous read operation to obtain more data. - std::size_t bytes_available = - std::min(512, b.max_size() - b.size()); - s.async_read_some(b.prepare(bytes_available), - detail::read_until_delim_handler( - s, b, delim, end - begin, handler)); -} - -namespace detail -{ - template - class read_until_delim_string_handler - { - public: - read_until_delim_string_handler(AsyncReadStream& stream, - asio::basic_streambuf& streambuf, - const std::string& delim, std::size_t next_search_start, - ReadHandler handler) - : stream_(stream), - streambuf_(streambuf), - delim_(delim), - next_search_start_(next_search_start), - handler_(handler) - { - } - - void operator()(const asio::error_code& ec, - std::size_t bytes_transferred) - { - // Check for errors. - if (ec) - { - std::size_t bytes = 0; - handler_(ec, bytes); - return; - } - - // Commit received data to streambuf's get area. - streambuf_.commit(bytes_transferred); - - // Determine the range of the data to be searched. - typedef typename asio::basic_streambuf< - Allocator>::const_buffers_type const_buffers_type; - typedef asio::buffers_iterator iterator; - const_buffers_type buffers = streambuf_.data(); - iterator begin = iterator::begin(buffers); - iterator start = begin + next_search_start_; - iterator end = iterator::end(buffers); - - // Look for a match. - std::pair result = asio::detail::partial_search( - start, end, delim_.begin(), delim_.end()); - if (result.first != end) - { - if (result.second) - { - // Full match. We're done. - std::size_t bytes = result.first - begin + delim_.length(); - handler_(ec, bytes); - return; - } - else - { - // Partial match. Next search needs to start from beginning of match. - next_search_start_ = result.first - begin; - } - } - else - { - // No match. Next search can start with the new data. - next_search_start_ = end - begin; - } - - // Check if buffer is full. - if (streambuf_.size() == streambuf_.max_size()) - { - std::size_t bytes = 0; - asio::error_code ec(error::not_found); - handler_(ec, bytes); - return; - } - - // Start a new asynchronous read operation to obtain more data. - std::size_t bytes_available = - std::min(512, streambuf_.max_size() - streambuf_.size()); - stream_.async_read_some(streambuf_.prepare(bytes_available), *this); - } - - //private: - AsyncReadStream& stream_; - asio::basic_streambuf& streambuf_; - std::string delim_; - std::size_t next_search_start_; - ReadHandler handler_; - }; - - template - inline void* asio_handler_allocate(std::size_t size, - read_until_delim_string_handler* this_handler) - { - return asio_handler_alloc_helpers::allocate( - size, &this_handler->handler_); - } - - template - inline void asio_handler_deallocate(void* pointer, std::size_t size, - read_until_delim_string_handler* this_handler) - { - asio_handler_alloc_helpers::deallocate( - pointer, size, &this_handler->handler_); - } - - template - inline void asio_handler_invoke(const Function& function, - read_until_delim_string_handler* this_handler) - { - asio_handler_invoke_helpers::invoke( - function, &this_handler->handler_); - } -} // namespace detail - -template -void async_read_until(AsyncReadStream& s, - asio::basic_streambuf& b, const std::string& delim, - ReadHandler handler) -{ - // Determine the range of the data to be searched. - typedef typename asio::basic_streambuf< - Allocator>::const_buffers_type const_buffers_type; - typedef asio::buffers_iterator iterator; - const_buffers_type buffers = b.data(); - iterator begin = iterator::begin(buffers); - iterator end = iterator::end(buffers); - - // Look for a match. - std::size_t next_search_start; - std::pair result = asio::detail::partial_search( - begin, end, delim.begin(), delim.end()); - if (result.first != end) - { - if (result.second) - { - // Full match. We're done. - asio::error_code ec; - std::size_t bytes = result.first - begin + delim.length(); - s.io_service().post(detail::bind_handler(handler, ec, bytes)); - return; - } - else - { - // Partial match. Next search needs to start from beginning of match. - next_search_start = result.first - begin; - } - } - else - { - // No match. Next search can start with the new data. - next_search_start = end - begin; - } - - // Check if buffer is full. - if (b.size() == b.max_size()) - { - asio::error_code ec(error::not_found); - s.io_service().post(detail::bind_handler(handler, ec, 0)); - return; - } - - // Start a new asynchronous read operation to obtain more data. - std::size_t bytes_available = - std::min(512, b.max_size() - b.size()); - s.async_read_some(b.prepare(bytes_available), - detail::read_until_delim_string_handler< - AsyncReadStream, Allocator, ReadHandler>( - s, b, delim, next_search_start, handler)); -} - -namespace detail -{ - template - class read_until_expr_handler - { - public: - read_until_expr_handler(AsyncReadStream& stream, - asio::basic_streambuf& streambuf, - const boost::regex& expr, std::size_t next_search_start, - ReadHandler handler) - : stream_(stream), - streambuf_(streambuf), - expr_(expr), - next_search_start_(next_search_start), - handler_(handler) - { - } - - void operator()(const asio::error_code& ec, - std::size_t bytes_transferred) - { - // Check for errors. - if (ec) - { - std::size_t bytes = 0; - handler_(ec, bytes); - return; - } - - // Commit received data to streambuf's get area. - streambuf_.commit(bytes_transferred); - - // Determine the range of the data to be searched. - typedef typename asio::basic_streambuf< - Allocator>::const_buffers_type const_buffers_type; - typedef asio::buffers_iterator iterator; - const_buffers_type buffers = streambuf_.data(); - iterator begin = iterator::begin(buffers); - iterator start = begin + next_search_start_; - iterator end = iterator::end(buffers); - - // Look for a match. - boost::match_results match_results; - if (boost::regex_search(start, end, match_results, expr_, - boost::match_default | boost::match_partial)) - { - if (match_results[0].matched) - { - // Full match. We're done. - std::size_t bytes = match_results[0].second - begin; - handler_(ec, bytes); - return; - } - else - { - // Partial match. Next search needs to start from beginning of match. - next_search_start_ = match_results[0].first - begin; - } - } - else - { - // No match. Next search can start with the new data. - next_search_start_ = end - begin; - } - - // Check if buffer is full. - if (streambuf_.size() == streambuf_.max_size()) - { - std::size_t bytes = 0; - asio::error_code ec(error::not_found); - handler_(ec, bytes); - return; - } - - // Start a new asynchronous read operation to obtain more data. - std::size_t bytes_available = - std::min(512, streambuf_.max_size() - streambuf_.size()); - stream_.async_read_some(streambuf_.prepare(bytes_available), *this); - } - - //private: - AsyncReadStream& stream_; - asio::basic_streambuf& streambuf_; - boost::regex expr_; - std::size_t next_search_start_; - ReadHandler handler_; - }; - - template - inline void* asio_handler_allocate(std::size_t size, - read_until_expr_handler* this_handler) - { - return asio_handler_alloc_helpers::allocate( - size, &this_handler->handler_); - } - - template - inline void asio_handler_deallocate(void* pointer, std::size_t size, - read_until_expr_handler* this_handler) - { - asio_handler_alloc_helpers::deallocate( - pointer, size, &this_handler->handler_); - } - - template - inline void asio_handler_invoke(const Function& function, - read_until_expr_handler* this_handler) - { - asio_handler_invoke_helpers::invoke( - function, &this_handler->handler_); - } -} // namespace detail - -template -void async_read_until(AsyncReadStream& s, - asio::basic_streambuf& b, const boost::regex& expr, - ReadHandler handler) -{ - // Determine the range of the data to be searched. - typedef typename asio::basic_streambuf< - Allocator>::const_buffers_type const_buffers_type; - typedef asio::buffers_iterator iterator; - const_buffers_type buffers = b.data(); - iterator begin = iterator::begin(buffers); - iterator end = iterator::end(buffers); - - // Look for a match. - std::size_t next_search_start; - boost::match_results match_results; - if (boost::regex_search(begin, end, match_results, expr, - boost::match_default | boost::match_partial)) - { - if (match_results[0].matched) - { - // Full match. We're done. - asio::error_code ec; - std::size_t bytes = match_results[0].second - begin; - s.io_service().post(detail::bind_handler(handler, ec, bytes)); - return; - } - else - { - // Partial match. Next search needs to start from beginning of match. - next_search_start = match_results[0].first - begin; - } - } - else - { - // No match. Next search can start with the new data. - next_search_start = end - begin; - } - - // Check if buffer is full. - if (b.size() == b.max_size()) - { - asio::error_code ec(error::not_found); - s.io_service().post(detail::bind_handler(handler, ec, 0)); - return; - } - - // Start a new asynchronous read operation to obtain more data. - std::size_t bytes_available = - std::min(512, b.max_size() - b.size()); - s.async_read_some(b.prepare(bytes_available), - detail::read_until_expr_handler( - s, b, expr, next_search_start, handler)); -} - -namespace detail -{ - template - class read_until_match_handler - { - public: - read_until_match_handler(AsyncReadStream& stream, - asio::basic_streambuf& streambuf, - MatchCondition match_condition, std::size_t next_search_start, - ReadHandler handler) - : stream_(stream), - streambuf_(streambuf), - match_condition_(match_condition), - next_search_start_(next_search_start), - handler_(handler) - { - } - - void operator()(const asio::error_code& ec, - std::size_t bytes_transferred) - { - // Check for errors. - if (ec) - { - std::size_t bytes = 0; - handler_(ec, bytes); - return; - } - - // Commit received data to streambuf's get area. - streambuf_.commit(bytes_transferred); - - // Determine the range of the data to be searched. - typedef typename asio::basic_streambuf< - Allocator>::const_buffers_type const_buffers_type; - typedef asio::buffers_iterator iterator; - const_buffers_type buffers = streambuf_.data(); - iterator begin = iterator::begin(buffers); - iterator start = begin + next_search_start_; - iterator end = iterator::end(buffers); - - // Look for a match. - std::pair result = match_condition_(start, end); - if (result.first != end) - { - if (result.second) - { - // Full match. We're done. - std::size_t bytes = result.first - begin; - handler_(ec, bytes); - return; - } - else - { - // Partial match. Next search needs to start from beginning of match. - next_search_start_ = result.first - begin; - } - } - else - { - // No match. Next search can start with the new data. - next_search_start_ = end - begin; - } - - // Check if buffer is full. - if (streambuf_.size() == streambuf_.max_size()) - { - std::size_t bytes = 0; - asio::error_code ec(error::not_found); - handler_(ec, bytes); - return; - } - - // Start a new asynchronous read operation to obtain more data. - std::size_t bytes_available = - std::min(512, streambuf_.max_size() - streambuf_.size()); - stream_.async_read_some(streambuf_.prepare(bytes_available), *this); - } - - //private: - AsyncReadStream& stream_; - asio::basic_streambuf& streambuf_; - MatchCondition match_condition_; - std::size_t next_search_start_; - ReadHandler handler_; - }; - - template - inline void* asio_handler_allocate(std::size_t size, - read_until_match_handler* this_handler) - { - return asio_handler_alloc_helpers::allocate( - size, &this_handler->handler_); - } - - template - inline void asio_handler_deallocate(void* pointer, std::size_t size, - read_until_match_handler* this_handler) - { - asio_handler_alloc_helpers::deallocate( - pointer, size, &this_handler->handler_); - } - - template - inline void asio_handler_invoke(const Function& function, - read_until_match_handler* this_handler) - { - asio_handler_invoke_helpers::invoke( - function, &this_handler->handler_); - } -} // namespace detail - -template -void async_read_until(AsyncReadStream& s, - asio::basic_streambuf& b, - MatchCondition match_condition, ReadHandler handler, - typename boost::enable_if >::type*) -{ - // Determine the range of the data to be searched. - typedef typename asio::basic_streambuf< - Allocator>::const_buffers_type const_buffers_type; - typedef asio::buffers_iterator iterator; - const_buffers_type buffers = b.data(); - iterator begin = iterator::begin(buffers); - iterator end = iterator::end(buffers); - - // Look for a match. - std::size_t next_search_start; - std::pair result = match_condition(begin, end); - if (result.first != end) - { - if (result.second) - { - // Full match. We're done. - asio::error_code ec; - std::size_t bytes = result.first - begin; - s.io_service().post(detail::bind_handler(handler, ec, bytes)); - return; - } - else - { - // Partial match. Next search needs to start from beginning of match. - next_search_start = result.first - begin; - } - } - else - { - // No match. Next search can start with the new data. - next_search_start = end - begin; - } - - // Check if buffer is full. - if (b.size() == b.max_size()) - { - asio::error_code ec(error::not_found); - s.io_service().post(detail::bind_handler(handler, ec, 0)); - return; - } - - // Start a new asynchronous read operation to obtain more data. - std::size_t bytes_available = - std::min(512, b.max_size() - b.size()); - s.async_read_some(b.prepare(bytes_available), - detail::read_until_match_handler< - AsyncReadStream, Allocator, MatchCondition, ReadHandler>( - s, b, match_condition, next_search_start, handler)); -} - -} // namespace asio - -#include "asio/detail/pop_options.hpp" - -#endif // ASIO_READ_UNTIL_IPP diff --git a/libtorrent/include/asio/impl/serial_port_base.ipp b/libtorrent/include/asio/impl/serial_port_base.ipp deleted file mode 100644 index 8dd6083ee..000000000 --- a/libtorrent/include/asio/impl/serial_port_base.ipp +++ /dev/null @@ -1,541 +0,0 @@ -// -// serial_port_base.ipp -// ~~~~~~~~~~~~~~~~~~~~ -// -// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// Copyright (c) 2008 Rep Invariant Systems, Inc. (info@repinvariant.com) -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -#ifndef ASIO_SERIAL_PORT_BASE_IPP -#define ASIO_SERIAL_PORT_BASE_IPP - -#if defined(_MSC_VER) && (_MSC_VER >= 1200) -# pragma once -#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) - -#include "asio/detail/push_options.hpp" - -namespace asio { - -inline serial_port_base::baud_rate::baud_rate(unsigned int rate) - : value_(rate) -{ -} - -inline unsigned int serial_port_base::baud_rate::value() const -{ - return value_; -} - -inline asio::error_code serial_port_base::baud_rate::store( - ASIO_OPTION_STORAGE& storage, asio::error_code& ec) const -{ -#if defined(BOOST_WINDOWS) || defined(__CYGWIN__) - storage.BaudRate = value_; -#else - speed_t baud; - switch (value_) - { - // Do POSIX-specified rates first. - case 0: baud = B0; break; - case 50: baud = B50; break; - case 75: baud = B75; break; - case 110: baud = B110; break; - case 134: baud = B134; break; - case 150: baud = B150; break; - case 200: baud = B200; break; - case 300: baud = B300; break; - case 600: baud = B600; break; - case 1200: baud = B1200; break; - case 1800: baud = B1800; break; - case 2400: baud = B2400; break; - case 4800: baud = B4800; break; - case 9600: baud = B9600; break; - case 19200: baud = B19200; break; - case 38400: baud = B38400; break; - // And now the extended ones conditionally. -# ifdef B7200 - case 7200: baud = B7200; break; -# endif -# ifdef B14400 - case 14400: baud = B14400; break; -# endif -# ifdef B57600 - case 57600: baud = B57600; break; -# endif -# ifdef B115200 - case 115200: baud = B115200; break; -# endif -# ifdef B230400 - case 230400: baud = B230400; break; -# endif -# ifdef B460800 - case 460800: baud = B460800; break; -# endif -# ifdef B500000 - case 500000: baud = B500000; break; -# endif -# ifdef B576000 - case 576000: baud = B576000; break; -# endif -# ifdef B921600 - case 921600: baud = B921600; break; -# endif -# ifdef B1000000 - case 1000000: baud = B1000000; break; -# endif -# ifdef B1152000 - case 1152000: baud = B1152000; break; -# endif -# ifdef B2000000 - case 2000000: baud = B2000000; break; -# endif -# ifdef B3000000 - case 3000000: baud = B3000000; break; -# endif -# ifdef B3500000 - case 3500000: baud = B3500000; break; -# endif -# ifdef B4000000 - case 4000000: baud = B4000000; break; -# endif - default: - baud = B0; - ec = asio::error::invalid_argument; - return ec; - } -# if defined(_BSD_SOURCE) - ::cfsetspeed(&storage, baud); -# else - ::cfsetispeed(&storage, baud); - ::cfsetospeed(&storage, baud); -# endif -#endif - ec = asio::error_code(); - return ec; -} - -inline asio::error_code serial_port_base::baud_rate::load( - const ASIO_OPTION_STORAGE& storage, asio::error_code& ec) -{ -#if defined(BOOST_WINDOWS) || defined(__CYGWIN__) - value_ = storage.BaudRate; -#else - speed_t baud = ::cfgetospeed(&storage); - switch (baud) - { - // First do those specified by POSIX. - case B0: value_ = 0; break; - case B50: value_ = 50; break; - case B75: value_ = 75; break; - case B110: value_ = 110; break; - case B134: value_ = 134; break; - case B150: value_ = 150; break; - case B200: value_ = 200; break; - case B300: value_ = 300; break; - case B600: value_ = 600; break; - case B1200: value_ = 1200; break; - case B1800: value_ = 1800; break; - case B2400: value_ = 2400; break; - case B4800: value_ = 4800; break; - case B9600: value_ = 9600; break; - case B19200: value_ = 19200; break; - case B38400: value_ = 38400; break; - // Now conditionally handle a bunch of extended rates. -# ifdef B7200 - case B7200: value_ = 7200; break; -# endif -# ifdef B14400 - case B14400: value_ = 14400; break; -# endif -# ifdef B57600 - case B57600: value_ = 57600; break; -# endif -# ifdef B115200 - case B115200: value_ = 115200; break; -# endif -# ifdef B230400 - case B230400: value_ = 230400; break; -# endif -# ifdef B460800 - case B460800: value_ = 460800; break; -# endif -# ifdef B500000 - case B500000: value_ = 500000; break; -# endif -# ifdef B576000 - case B576000: value_ = 576000; break; -# endif -# ifdef B921600 - case B921600: value_ = 921600; break; -# endif -# ifdef B1000000 - case B1000000: value_ = 1000000; break; -# endif -# ifdef B1152000 - case B1152000: value_ = 1152000; break; -# endif -# ifdef B2000000 - case B2000000: value_ = 2000000; break; -# endif -# ifdef B3000000 - case B3000000: value_ = 3000000; break; -# endif -# ifdef B3500000 - case B3500000: value_ = 3500000; break; -# endif -# ifdef B4000000 - case B4000000: value_ = 4000000; break; -# endif - default: - value_ = 0; - ec = asio::error::invalid_argument; - return ec; - } -#endif - ec = asio::error_code(); - return ec; -} - -inline serial_port_base::flow_control::flow_control( - serial_port_base::flow_control::type t) - : value_(t) -{ - if (t != none && t != software && t != hardware) - throw std::out_of_range("invalid flow_control value"); -} - -inline serial_port_base::flow_control::type -serial_port_base::flow_control::value() const -{ - return value_; -} - -inline asio::error_code serial_port_base::flow_control::store( - ASIO_OPTION_STORAGE& storage, asio::error_code& ec) const -{ -#if defined(BOOST_WINDOWS) || defined(__CYGWIN__) - storage.fOutxCtsFlow = FALSE; - storage.fOutxDsrFlow = FALSE; - storage.fTXContinueOnXoff = TRUE; - storage.fDtrControl = DTR_CONTROL_ENABLE; - storage.fDsrSensitivity = FALSE; - storage.fOutX = FALSE; - storage.fInX = FALSE; - storage.fRtsControl = RTS_CONTROL_ENABLE; - switch (value_) - { - case none: - break; - case software: - storage.fOutX = TRUE; - storage.fInX = TRUE; - break; - case hardware: - storage.fOutxCtsFlow = TRUE; - storage.fRtsControl = RTS_CONTROL_HANDSHAKE; - break; - default: - break; - } -#else - switch (value_) - { - case none: - storage.c_iflag &= ~(IXOFF | IXON); -# if defined(_BSD_SOURCE) - storage.c_cflag &= ~CRTSCTS; -# endif - break; - case software: - storage.c_iflag |= IXOFF | IXON; -# if defined(_BSD_SOURCE) - storage.c_cflag &= ~CRTSCTS; -# endif - break; - case hardware: -# if defined(_BSD_SOURCE) - storage.c_iflag &= ~(IXOFF | IXON); - storage.c_cflag |= CRTSCTS; - break; -# else - ec = asio::error::operation_not_supported; - return ec; -# endif - default: - break; - } -#endif - ec = asio::error_code(); - return ec; -} - -inline asio::error_code serial_port_base::flow_control::load( - const ASIO_OPTION_STORAGE& storage, asio::error_code& ec) -{ -#if defined(BOOST_WINDOWS) || defined(__CYGWIN__) - if (storage.fOutX && storage.fInX) - { - value_ = software; - } - else if (storage.fOutxCtsFlow && storage.fRtsControl == RTS_CONTROL_HANDSHAKE) - { - value_ = hardware; - } - else - { - value_ = none; - } -#else - if (storage.c_iflag & (IXOFF | IXON)) - { - value_ = software; - } -# if defined(_BSD_SOURCE) - else if (storage.c_cflag & CRTSCTS) - { - value_ = hardware; - } -# endif - else - { - value_ = none; - } -#endif - ec = asio::error_code(); - return ec; -} - -inline serial_port_base::parity::parity(serial_port_base::parity::type t) - : value_(t) -{ - if (t != none && t != odd && t != even) - throw std::out_of_range("invalid parity value"); -} - -inline serial_port_base::parity::type serial_port_base::parity::value() const -{ - return value_; -} - -inline asio::error_code serial_port_base::parity::store( - ASIO_OPTION_STORAGE& storage, asio::error_code& ec) const -{ -#if defined(BOOST_WINDOWS) || defined(__CYGWIN__) - switch (value_) - { - case none: - storage.fParity = FALSE; - storage.Parity = NOPARITY; - break; - case odd: - storage.fParity = TRUE; - storage.Parity = ODDPARITY; - break; - case even: - storage.fParity = TRUE; - storage.Parity = EVENPARITY; - break; - default: - break; - } -#else - switch (value_) - { - case none: - storage.c_iflag |= IGNPAR; - storage.c_cflag &= ~(PARENB | PARODD); - break; - case even: - storage.c_iflag &= ~(IGNPAR | PARMRK); - storage.c_iflag |= INPCK; - storage.c_cflag |= PARENB; - storage.c_cflag &= ~PARODD; - break; - case odd: - storage.c_iflag &= ~(IGNPAR | PARMRK); - storage.c_iflag |= INPCK; - storage.c_cflag |= (PARENB | PARODD); - break; - default: - break; - } -#endif - ec = asio::error_code(); - return ec; -} - -inline asio::error_code serial_port_base::parity::load( - const ASIO_OPTION_STORAGE& storage, asio::error_code& ec) -{ -#if defined(BOOST_WINDOWS) || defined(__CYGWIN__) - if (storage.Parity == EVENPARITY) - { - value_ = even; - } - else if (storage.Parity == ODDPARITY) - { - value_ = odd; - } - else - { - value_ = none; - } -#else - if (storage.c_cflag & PARENB) - { - if (storage.c_cflag & PARODD) - { - value_ = odd; - } - else - { - value_ = even; - } - } - else - { - value_ = none; - } -#endif - ec = asio::error_code(); - return ec; -} - -inline serial_port_base::stop_bits::stop_bits( - serial_port_base::stop_bits::type t) - : value_(t) -{ - if (t != one && t != onepointfive && t != two) - throw std::out_of_range("invalid stop_bits value"); -} - -inline serial_port_base::stop_bits::type -serial_port_base::stop_bits::value() const -{ - return value_; -} - -inline asio::error_code serial_port_base::stop_bits::store( - ASIO_OPTION_STORAGE& storage, asio::error_code& ec) const -{ -#if defined(BOOST_WINDOWS) || defined(__CYGWIN__) - switch (value_) - { - case one: - storage.StopBits = ONESTOPBIT; - break; - case onepointfive: - storage.StopBits = ONE5STOPBITS; - break; - case two: - storage.StopBits = TWOSTOPBITS; - break; - default: - break; - } -#else - switch (value_) - { - case one: - storage.c_cflag &= ~CSTOPB; - break; - case two: - storage.c_cflag |= CSTOPB; - break; - default: - ec = asio::error::operation_not_supported; - return ec; - } -#endif - ec = asio::error_code(); - return ec; -} - -inline asio::error_code serial_port_base::stop_bits::load( - const ASIO_OPTION_STORAGE& storage, asio::error_code& ec) -{ -#if defined(BOOST_WINDOWS) || defined(__CYGWIN__) - if (storage.StopBits == ONESTOPBIT) - { - value_ = one; - } - else if (storage.StopBits == ONE5STOPBITS) - { - value_ = onepointfive; - } - else if (storage.StopBits == TWOSTOPBITS) - { - value_ = two; - } - else - { - value_ = one; - } -#else - value_ = (storage.c_cflag & CSTOPB) ? two : one; -#endif - ec = asio::error_code(); - return ec; -} - -inline serial_port_base::character_size::character_size(unsigned int t) - : value_(t) -{ - if (t < 5 || t > 8) - throw std::out_of_range("invalid character_size value"); -} - -inline unsigned int serial_port_base::character_size::value() const -{ - return value_; -} - -inline asio::error_code serial_port_base::character_size::store( - ASIO_OPTION_STORAGE& storage, asio::error_code& ec) const -{ -#if defined(BOOST_WINDOWS) || defined(__CYGWIN__) - storage.ByteSize = value_; -#else - storage.c_cflag &= ~CSIZE; - switch (value_) - { - case 5: storage.c_cflag |= CS5; break; - case 6: storage.c_cflag |= CS6; break; - case 7: storage.c_cflag |= CS7; break; - case 8: storage.c_cflag |= CS8; break; - default: break; - } -#endif - ec = asio::error_code(); - return ec; -} - -inline asio::error_code serial_port_base::character_size::load( - const ASIO_OPTION_STORAGE& storage, asio::error_code& ec) -{ -#if defined(BOOST_WINDOWS) || defined(__CYGWIN__) - value_ = storage.ByteSize; -#else - if ((storage.c_cflag & CSIZE) == CS5) { value_ = 5; } - else if ((storage.c_cflag & CSIZE) == CS6) { value_ = 6; } - else if ((storage.c_cflag & CSIZE) == CS7) { value_ = 7; } - else if ((storage.c_cflag & CSIZE) == CS8) { value_ = 8; } - else - { - // Hmmm, use 8 for now. - value_ = 8; - } -#endif - ec = asio::error_code(); - return ec; -} - -} // namespace asio - -#include "asio/detail/pop_options.hpp" - -#endif // ASIO_SERIAL_PORT_BASE_IPP diff --git a/libtorrent/include/asio/impl/write.ipp b/libtorrent/include/asio/impl/write.ipp deleted file mode 100644 index 43bc2972a..000000000 --- a/libtorrent/include/asio/impl/write.ipp +++ /dev/null @@ -1,279 +0,0 @@ -// -// write.ipp -// ~~~~~~~~~ -// -// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -#ifndef ASIO_WRITE_IPP -#define ASIO_WRITE_IPP - -#if defined(_MSC_VER) && (_MSC_VER >= 1200) -# pragma once -#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) - -#include "asio/detail/push_options.hpp" - -#include "asio/buffer.hpp" -#include "asio/completion_condition.hpp" -#include "asio/detail/bind_handler.hpp" -#include "asio/detail/consuming_buffers.hpp" -#include "asio/detail/handler_alloc_helpers.hpp" -#include "asio/detail/handler_invoke_helpers.hpp" -#include "asio/detail/throw_error.hpp" - -namespace asio { - -template -std::size_t write(SyncWriteStream& s, const ConstBufferSequence& buffers, - CompletionCondition completion_condition, asio::error_code& ec) -{ - asio::detail::consuming_buffers< - const_buffer, ConstBufferSequence> tmp(buffers); - std::size_t total_transferred = 0; - while (tmp.begin() != tmp.end()) - { - std::size_t bytes_transferred = s.write_some(tmp, ec); - tmp.consume(bytes_transferred); - total_transferred += bytes_transferred; - if (completion_condition(ec, total_transferred)) - return total_transferred; - } - ec = asio::error_code(); - return total_transferred; -} - -template -inline std::size_t write(SyncWriteStream& s, const ConstBufferSequence& buffers) -{ - asio::error_code ec; - std::size_t bytes_transferred = write(s, buffers, transfer_all(), ec); - asio::detail::throw_error(ec); - return bytes_transferred; -} - -template -inline std::size_t write(SyncWriteStream& s, const ConstBufferSequence& buffers, - CompletionCondition completion_condition) -{ - asio::error_code ec; - std::size_t bytes_transferred = write(s, buffers, completion_condition, ec); - asio::detail::throw_error(ec); - return bytes_transferred; -} - -template -std::size_t write(SyncWriteStream& s, - asio::basic_streambuf& b, - CompletionCondition completion_condition, asio::error_code& ec) -{ - std::size_t bytes_transferred = write(s, b.data(), completion_condition, ec); - b.consume(bytes_transferred); - return bytes_transferred; -} - -template -inline std::size_t write(SyncWriteStream& s, - asio::basic_streambuf& b) -{ - asio::error_code ec; - std::size_t bytes_transferred = write(s, b, transfer_all(), ec); - asio::detail::throw_error(ec); - return bytes_transferred; -} - -template -inline std::size_t write(SyncWriteStream& s, - asio::basic_streambuf& b, - CompletionCondition completion_condition) -{ - asio::error_code ec; - std::size_t bytes_transferred = write(s, b, completion_condition, ec); - asio::detail::throw_error(ec); - return bytes_transferred; -} - -namespace detail -{ - template - class write_handler - { - public: - typedef asio::detail::consuming_buffers< - const_buffer, ConstBufferSequence> buffers_type; - - write_handler(AsyncWriteStream& stream, const buffers_type& buffers, - CompletionCondition completion_condition, WriteHandler handler) - : stream_(stream), - buffers_(buffers), - total_transferred_(0), - completion_condition_(completion_condition), - handler_(handler) - { - } - - void operator()(const asio::error_code& ec, - std::size_t bytes_transferred) - { - total_transferred_ += bytes_transferred; - buffers_.consume(bytes_transferred); - if (completion_condition_(ec, total_transferred_) - || buffers_.begin() == buffers_.end()) - { - handler_(ec, total_transferred_); - } - else - { - stream_.async_write_some(buffers_, *this); - } - } - - //private: - AsyncWriteStream& stream_; - buffers_type buffers_; - std::size_t total_transferred_; - CompletionCondition completion_condition_; - WriteHandler handler_; - }; - - template - inline void* asio_handler_allocate(std::size_t size, - write_handler* this_handler) - { - return asio_handler_alloc_helpers::allocate( - size, &this_handler->handler_); - } - - template - inline void asio_handler_deallocate(void* pointer, std::size_t size, - write_handler* this_handler) - { - asio_handler_alloc_helpers::deallocate( - pointer, size, &this_handler->handler_); - } - - template - inline void asio_handler_invoke(const Function& function, - write_handler* this_handler) - { - asio_handler_invoke_helpers::invoke( - function, &this_handler->handler_); - } -} // namespace detail - -template -inline void async_write(AsyncWriteStream& s, const ConstBufferSequence& buffers, - CompletionCondition completion_condition, WriteHandler handler) -{ - asio::detail::consuming_buffers< - const_buffer, ConstBufferSequence> tmp(buffers); - s.async_write_some(tmp, - detail::write_handler( - s, tmp, completion_condition, handler)); -} - -template -inline void async_write(AsyncWriteStream& s, const ConstBufferSequence& buffers, - WriteHandler handler) -{ - async_write(s, buffers, transfer_all(), handler); -} - -namespace detail -{ - template - class write_streambuf_handler - { - public: - write_streambuf_handler(asio::basic_streambuf& streambuf, - WriteHandler handler) - : streambuf_(streambuf), - handler_(handler) - { - } - - void operator()(const asio::error_code& ec, - std::size_t bytes_transferred) - { - streambuf_.consume(bytes_transferred); - handler_(ec, bytes_transferred); - } - - //private: - asio::basic_streambuf& streambuf_; - WriteHandler handler_; - }; - - template - inline void* asio_handler_allocate(std::size_t size, - write_streambuf_handler* this_handler) - { - return asio_handler_alloc_helpers::allocate( - size, &this_handler->handler_); - } - - template - inline void asio_handler_deallocate(void* pointer, std::size_t size, - write_streambuf_handler* this_handler) - { - asio_handler_alloc_helpers::deallocate( - pointer, size, &this_handler->handler_); - } - - template - inline void asio_handler_invoke(const Function& function, - write_streambuf_handler* this_handler) - { - asio_handler_invoke_helpers::invoke( - function, &this_handler->handler_); - } -} // namespace detail - -template -inline void async_write(AsyncWriteStream& s, - asio::basic_streambuf& b, - CompletionCondition completion_condition, WriteHandler handler) -{ - async_write(s, b.data(), completion_condition, - detail::write_streambuf_handler< - AsyncWriteStream, Allocator, WriteHandler>(b, handler)); -} - -template -inline void async_write(AsyncWriteStream& s, - asio::basic_streambuf& b, WriteHandler handler) -{ - async_write(s, b, transfer_all(), handler); -} - -} // namespace asio - -#include "asio/detail/pop_options.hpp" - -#endif // ASIO_WRITE_IPP diff --git a/libtorrent/include/asio/impl/write_at.ipp b/libtorrent/include/asio/impl/write_at.ipp deleted file mode 100644 index c6fa3078c..000000000 --- a/libtorrent/include/asio/impl/write_at.ipp +++ /dev/null @@ -1,296 +0,0 @@ -// -// write_at.ipp -// ~~~~~~~~~~~~ -// -// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -#ifndef ASIO_WRITE_AT_IPP -#define ASIO_WRITE_AT_IPP - -#if defined(_MSC_VER) && (_MSC_VER >= 1200) -# pragma once -#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) - -#include "asio/detail/push_options.hpp" - -#include "asio/buffer.hpp" -#include "asio/completion_condition.hpp" -#include "asio/detail/bind_handler.hpp" -#include "asio/detail/consuming_buffers.hpp" -#include "asio/detail/handler_alloc_helpers.hpp" -#include "asio/detail/handler_invoke_helpers.hpp" -#include "asio/detail/throw_error.hpp" - -namespace asio { - -template -std::size_t write_at(SyncRandomAccessWriteDevice& d, - boost::uint64_t offset, const ConstBufferSequence& buffers, - CompletionCondition completion_condition, asio::error_code& ec) -{ - asio::detail::consuming_buffers< - const_buffer, ConstBufferSequence> tmp(buffers); - std::size_t total_transferred = 0; - while (tmp.begin() != tmp.end()) - { - std::size_t bytes_transferred = d.write_some_at( - offset + total_transferred, tmp, ec); - tmp.consume(bytes_transferred); - total_transferred += bytes_transferred; - if (completion_condition(ec, total_transferred)) - return total_transferred; - } - ec = asio::error_code(); - return total_transferred; -} - -template -inline std::size_t write_at(SyncRandomAccessWriteDevice& d, - boost::uint64_t offset, const ConstBufferSequence& buffers) -{ - asio::error_code ec; - std::size_t bytes_transferred = write_at( - d, offset, buffers, transfer_all(), ec); - asio::detail::throw_error(ec); - return bytes_transferred; -} - -template -inline std::size_t write_at(SyncRandomAccessWriteDevice& d, - boost::uint64_t offset, const ConstBufferSequence& buffers, - CompletionCondition completion_condition) -{ - asio::error_code ec; - std::size_t bytes_transferred = write_at( - d, offset, buffers, completion_condition, ec); - asio::detail::throw_error(ec); - return bytes_transferred; -} - -template -std::size_t write_at(SyncRandomAccessWriteDevice& d, - boost::uint64_t offset, asio::basic_streambuf& b, - CompletionCondition completion_condition, asio::error_code& ec) -{ - std::size_t bytes_transferred = write_at( - d, offset, b.data(), completion_condition, ec); - b.consume(bytes_transferred); - return bytes_transferred; -} - -template -inline std::size_t write_at(SyncRandomAccessWriteDevice& d, - boost::uint64_t offset, asio::basic_streambuf& b) -{ - asio::error_code ec; - std::size_t bytes_transferred = write_at(d, offset, b, transfer_all(), ec); - asio::detail::throw_error(ec); - return bytes_transferred; -} - -template -inline std::size_t write_at(SyncRandomAccessWriteDevice& d, - boost::uint64_t offset, asio::basic_streambuf& b, - CompletionCondition completion_condition) -{ - asio::error_code ec; - std::size_t bytes_transferred = write_at( - d, offset, b, completion_condition, ec); - asio::detail::throw_error(ec); - return bytes_transferred; -} - -namespace detail -{ - template - class write_at_handler - { - public: - typedef asio::detail::consuming_buffers< - const_buffer, ConstBufferSequence> buffers_type; - - write_at_handler(AsyncRandomAccessWriteDevice& stream, - boost::uint64_t offset, const buffers_type& buffers, - CompletionCondition completion_condition, WriteHandler handler) - : stream_(stream), - buffers_(buffers), - offset_(offset), - total_transferred_(0), - completion_condition_(completion_condition), - handler_(handler) - { - } - - void operator()(const asio::error_code& ec, - std::size_t bytes_transferred) - { - total_transferred_ += bytes_transferred; - buffers_.consume(bytes_transferred); - if (completion_condition_(ec, total_transferred_) - || buffers_.begin() == buffers_.end()) - { - handler_(ec, total_transferred_); - } - else - { - stream_.async_write_some_at( - offset_ + total_transferred_, buffers_, *this); - } - } - - //private: - AsyncRandomAccessWriteDevice& stream_; - buffers_type buffers_; - boost::uint64_t offset_; - std::size_t total_transferred_; - CompletionCondition completion_condition_; - WriteHandler handler_; - }; - - template - inline void* asio_handler_allocate(std::size_t size, - write_at_handler* this_handler) - { - return asio_handler_alloc_helpers::allocate( - size, &this_handler->handler_); - } - - template - inline void asio_handler_deallocate(void* pointer, std::size_t size, - write_at_handler* this_handler) - { - asio_handler_alloc_helpers::deallocate( - pointer, size, &this_handler->handler_); - } - - template - inline void asio_handler_invoke(const Function& function, - write_at_handler* this_handler) - { - asio_handler_invoke_helpers::invoke( - function, &this_handler->handler_); - } -} // namespace detail - -template -inline void async_write_at(AsyncRandomAccessWriteDevice& d, - boost::uint64_t offset, const ConstBufferSequence& buffers, - CompletionCondition completion_condition, WriteHandler handler) -{ - asio::detail::consuming_buffers< - const_buffer, ConstBufferSequence> tmp(buffers); - d.async_write_some_at(offset, tmp, - detail::write_at_handler( - d, offset, tmp, completion_condition, handler)); -} - -template -inline void async_write_at(AsyncRandomAccessWriteDevice& d, - boost::uint64_t offset, const ConstBufferSequence& buffers, - WriteHandler handler) -{ - async_write_at(d, offset, buffers, transfer_all(), handler); -} - -namespace detail -{ - template - class write_at_streambuf_handler - { - public: - write_at_streambuf_handler( - asio::basic_streambuf& streambuf, - WriteHandler handler) - : streambuf_(streambuf), - handler_(handler) - { - } - - void operator()(const asio::error_code& ec, - std::size_t bytes_transferred) - { - streambuf_.consume(bytes_transferred); - handler_(ec, bytes_transferred); - } - - //private: - asio::basic_streambuf& streambuf_; - WriteHandler handler_; - }; - - template - inline void* asio_handler_allocate(std::size_t size, - write_at_streambuf_handler* this_handler) - { - return asio_handler_alloc_helpers::allocate( - size, &this_handler->handler_); - } - - template - inline void asio_handler_deallocate(void* pointer, std::size_t size, - write_at_streambuf_handler* this_handler) - { - asio_handler_alloc_helpers::deallocate( - pointer, size, &this_handler->handler_); - } - - template - inline void asio_handler_invoke(const Function& function, - write_at_streambuf_handler* this_handler) - { - asio_handler_invoke_helpers::invoke( - function, &this_handler->handler_); - } -} // namespace detail - -template -inline void async_write_at(AsyncRandomAccessWriteDevice& d, - boost::uint64_t offset, asio::basic_streambuf& b, - CompletionCondition completion_condition, WriteHandler handler) -{ - async_write_at(d, offset, b.data(), completion_condition, - detail::write_at_streambuf_handler< - AsyncRandomAccessWriteDevice, Allocator, WriteHandler>(b, handler)); -} - -template -inline void async_write_at(AsyncRandomAccessWriteDevice& d, - boost::uint64_t offset, asio::basic_streambuf& b, - WriteHandler handler) -{ - async_write_at(d, offset, b, transfer_all(), handler); -} - -} // namespace asio - -#include "asio/detail/pop_options.hpp" - -#endif // ASIO_WRITE_AT_IPP diff --git a/libtorrent/include/asio/io_service.hpp b/libtorrent/include/asio/io_service.hpp deleted file mode 100644 index b6a34fdc4..000000000 --- a/libtorrent/include/asio/io_service.hpp +++ /dev/null @@ -1,551 +0,0 @@ -// -// io_service.hpp -// ~~~~~~~~~~~~~~ -// -// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -#ifndef ASIO_IO_SERVICE_HPP -#define ASIO_IO_SERVICE_HPP - -#if defined(_MSC_VER) && (_MSC_VER >= 1200) -# pragma once -#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) - -#include "asio/detail/push_options.hpp" - -#include "asio/detail/push_options.hpp" -#include -#include -#include -#include -#include -#include "asio/detail/pop_options.hpp" - -#include "asio/error_code.hpp" -#include "asio/detail/dev_poll_reactor_fwd.hpp" -#include "asio/detail/epoll_reactor_fwd.hpp" -#include "asio/detail/kqueue_reactor_fwd.hpp" -#include "asio/detail/noncopyable.hpp" -#include "asio/detail/select_reactor_fwd.hpp" -#include "asio/detail/service_registry_fwd.hpp" -#include "asio/detail/signal_init.hpp" -#include "asio/detail/task_io_service_fwd.hpp" -#include "asio/detail/win_iocp_io_service_fwd.hpp" -#include "asio/detail/winsock_init.hpp" -#include "asio/detail/wrapped_handler.hpp" - -namespace asio { - -class io_service; -template Service& use_service(io_service& ios); -template void add_service(io_service& ios, Service* svc); -template bool has_service(io_service& ios); - -/// Provides core I/O functionality. -/** - * The io_service class provides the core I/O functionality for users of the - * asynchronous I/O objects, including: - * - * @li asio::ip::tcp::socket - * @li asio::ip::tcp::acceptor - * @li asio::ip::udp::socket - * @li asio::deadline_timer. - * - * The io_service class also includes facilities intended for developers of - * custom asynchronous services. - * - * @par Thread Safety - * @e Distinct @e objects: Safe.@n - * @e Shared @e objects: Safe, with the exception that calling reset() - * while there are unfinished run() calls results in undefined behaviour. - * - * @par Concepts: - * Dispatcher. - * - * @par Effect of exceptions thrown from handlers - * - * If an exception is thrown from a handler, the exception is allowed to - * propagate through the throwing thread's invocation of - * asio::io_service::run(), asio::io_service::run_one(), - * asio::io_service::poll() or asio::io_service::poll_one(). - * No other threads that are calling any of these functions are affected. It is - * then the responsibility of the application to catch the exception. - * - * After the exception has been caught, the - * asio::io_service::run(), asio::io_service::run_one(), - * asio::io_service::poll() or asio::io_service::poll_one() - * call may be restarted @em without the need for an intervening call to - * asio::io_service::reset(). This allows the thread to rejoin the - * io_service's thread pool without impacting any other threads in the pool. - * - * For example: - * - * @code - * asio::io_service io_service; - * ... - * for (;;) - * { - * try - * { - * io_service.run(); - * break; // run() exited normally - * } - * catch (my_exception& e) - * { - * // Deal with exception as appropriate. - * } - * } - * @endcode - * - * @par Stopping the io_service from running out of work - * - * Some applications may need to prevent an io_service's run() call from - * returning when there is no more work to do. For example, the io_service may - * be being run in a background thread that is launched prior to the - * application's asynchronous operations. The run() call may be kept running by - * creating an object of type asio::io_service::work: - * - * @code asio::io_service io_service; - * asio::io_service::work work(io_service); - * ... @endcode - * - * To effect a shutdown, the application will then need to call the io_service's - * stop() member function. This will cause the io_service run() call to return - * as soon as possible, abandoning unfinished operations and without permitting - * ready handlers to be dispatched. - * - * Alternatively, if the application requires that all operations and handlers - * be allowed to finish normally, the work object may be explicitly destroyed. - * - * @code asio::io_service io_service; - * auto_ptr work( - * new asio::io_service::work(io_service)); - * ... - * work.reset(); // Allow run() to exit. @endcode - */ -class io_service - : private noncopyable -{ -private: - // The type of the platform-specific implementation. -#if defined(ASIO_HAS_IOCP) - typedef detail::win_iocp_io_service impl_type; -#elif defined(ASIO_HAS_EPOLL) - typedef detail::task_io_service > impl_type; -#elif defined(ASIO_HAS_KQUEUE) - typedef detail::task_io_service > impl_type; -#elif defined(ASIO_HAS_DEV_POLL) - typedef detail::task_io_service > impl_type; -#else - typedef detail::task_io_service > impl_type; -#endif - -public: - class work; - friend class work; - - class id; - - class service; - - class strand; - - /// Constructor. - io_service(); - - /// Constructor. - /** - * Construct with a hint about the required level of concurrency. - * - * @param concurrency_hint A suggestion to the implementation on how many - * threads it should allow to run simultaneously. - */ - explicit io_service(std::size_t concurrency_hint); - - /// Destructor. - ~io_service(); - - /// Run the io_service's event processing loop. - /** - * The run() function blocks until all work has finished and there are no - * more handlers to be dispatched, or until the io_service has been stopped. - * - * Multiple threads may call the run() function to set up a pool of threads - * from which the io_service may execute handlers. All threads that are - * waiting in the pool are equivalent and the io_service may choose any one - * of them to invoke a handler. - * - * The run() function may be safely called again once it has completed only - * after a call to reset(). - * - * @return The number of handlers that were executed. - * - * @throws asio::system_error Thrown on failure. - * - * @note The poll() function may also be used to dispatch ready handlers, - * but without blocking. - */ - std::size_t run(); - - /// Run the io_service's event processing loop. - /** - * The run() function blocks until all work has finished and there are no - * more handlers to be dispatched, or until the io_service has been stopped. - * - * Multiple threads may call the run() function to set up a pool of threads - * from which the io_service may execute handlers. All threads that are - * waiting in the pool are equivalent and the io_service may choose any one - * of them to invoke a handler. - * - * The run() function may be safely called again once it has completed only - * after a call to reset(). - * - * @param ec Set to indicate what error occurred, if any. - * - * @return The number of handlers that were executed. - * - * @note The poll() function may also be used to dispatch ready handlers, - * but without blocking. - */ - std::size_t run(asio::error_code& ec); - - /// Run the io_service's event processing loop to execute at most one handler. - /** - * The run_one() function blocks until one handler has been dispatched, or - * until the io_service has been stopped. - * - * @return The number of handlers that were executed. - * - * @throws asio::system_error Thrown on failure. - */ - std::size_t run_one(); - - /// Run the io_service's event processing loop to execute at most one handler. - /** - * The run_one() function blocks until one handler has been dispatched, or - * until the io_service has been stopped. - * - * @param ec Set to indicate what error occurred, if any. - * - * @return The number of handlers that were executed. - */ - std::size_t run_one(asio::error_code& ec); - - /// Run the io_service's event processing loop to execute ready handlers. - /** - * The poll() function runs handlers that are ready to run, without blocking, - * until the io_service has been stopped or there are no more ready handlers. - * - * @return The number of handlers that were executed. - * - * @throws asio::system_error Thrown on failure. - */ - std::size_t poll(); - - /// Run the io_service's event processing loop to execute ready handlers. - /** - * The poll() function runs handlers that are ready to run, without blocking, - * until the io_service has been stopped or there are no more ready handlers. - * - * @param ec Set to indicate what error occurred, if any. - * - * @return The number of handlers that were executed. - */ - std::size_t poll(asio::error_code& ec); - - /// Run the io_service's event processing loop to execute one ready handler. - /** - * The poll_one() function runs at most one handler that is ready to run, - * without blocking. - * - * @return The number of handlers that were executed. - * - * @throws asio::system_error Thrown on failure. - */ - std::size_t poll_one(); - - /// Run the io_service's event processing loop to execute one ready handler. - /** - * The poll_one() function runs at most one handler that is ready to run, - * without blocking. - * - * @param ec Set to indicate what error occurred, if any. - * - * @return The number of handlers that were executed. - */ - std::size_t poll_one(asio::error_code& ec); - - /// Stop the io_service's event processing loop. - /** - * This function does not block, but instead simply signals the io_service to - * stop. All invocations of its run() or run_one() member functions should - * return as soon as possible. Subsequent calls to run(), run_one(), poll() - * or poll_one() will return immediately until reset() is called. - */ - void stop(); - - /// Reset the io_service in preparation for a subsequent run() invocation. - /** - * This function must be called prior to any second or later set of - * invocations of the run(), run_one(), poll() or poll_one() functions when a - * previous invocation of these functions returned due to the io_service - * being stopped or running out of work. This function allows the io_service - * to reset any internal state, such as a "stopped" flag. - * - * This function must not be called while there are any unfinished calls to - * the run(), run_one(), poll() or poll_one() functions. - */ - void reset(); - - /// Request the io_service to invoke the given handler. - /** - * This function is used to ask the io_service to execute the given handler. - * - * The io_service guarantees that the handler will only be called in a thread - * in which the run(), run_one(), poll() or poll_one() member functions is - * currently being invoked. The handler may be executed inside this function - * if the guarantee can be met. - * - * @param handler The handler to be called. The io_service will make - * a copy of the handler object as required. The function signature of the - * handler must be: @code void handler(); @endcode - */ - template - void dispatch(CompletionHandler handler); - - /// Request the io_service to invoke the given handler and return immediately. - /** - * This function is used to ask the io_service to execute the given handler, - * but without allowing the io_service to call the handler from inside this - * function. - * - * The io_service guarantees that the handler will only be called in a thread - * in which the run(), run_one(), poll() or poll_one() member functions is - * currently being invoked. - * - * @param handler The handler to be called. The io_service will make - * a copy of the handler object as required. The function signature of the - * handler must be: @code void handler(); @endcode - */ - template - void post(CompletionHandler handler); - - /// Create a new handler that automatically dispatches the wrapped handler - /// on the io_service. - /** - * This function is used to create a new handler function object that, when - * invoked, will automatically pass the wrapped handler to the io_service's - * dispatch function. - * - * @param handler The handler to be wrapped. The io_service will make a copy - * of the handler object as required. The function signature of the handler - * must be: @code void handler(A1 a1, ... An an); @endcode - * - * @return A function object that, when invoked, passes the wrapped handler to - * the io_service's dispatch function. Given a function object with the - * signature: - * @code R f(A1 a1, ... An an); @endcode - * If this function object is passed to the wrap function like so: - * @code io_service.wrap(f); @endcode - * then the return value is a function object with the signature - * @code void g(A1 a1, ... An an); @endcode - * that, when invoked, executes code equivalent to: - * @code io_service.dispatch(boost::bind(f, a1, ... an)); @endcode - */ - template -#if defined(GENERATING_DOCUMENTATION) - unspecified -#else - detail::wrapped_handler -#endif - wrap(Handler handler); - - /// Obtain the service object corresponding to the given type. - /** - * This function is used to locate a service object that corresponds to - * the given service type. If there is no existing implementation of the - * service, then the io_service will create a new instance of the service. - * - * @param ios The io_service object that owns the service. - * - * @return The service interface implementing the specified service type. - * Ownership of the service interface is not transferred to the caller. - */ - template - friend Service& use_service(io_service& ios); - - /// Add a service object to the io_service. - /** - * This function is used to add a service to the io_service. - * - * @param ios The io_service object that owns the service. - * - * @param svc The service object. On success, ownership of the service object - * is transferred to the io_service. When the io_service object is destroyed, - * it will destroy the service object by performing: - * @code delete static_cast(svc) @endcode - * - * @throws asio::service_already_exists Thrown if a service of the - * given type is already present in the io_service. - * - * @throws asio::invalid_service_owner Thrown if the service's owning - * io_service is not the io_service object specified by the ios parameter. - */ - template - friend void add_service(io_service& ios, Service* svc); - - /// Determine if an io_service contains a specified service type. - /** - * This function is used to determine whether the io_service contains a - * service object corresponding to the given service type. - * - * @param ios The io_service object that owns the service. - * - * @return A boolean indicating whether the io_service contains the service. - */ - template - friend bool has_service(io_service& ios); - -private: -#if defined(BOOST_WINDOWS) || defined(__CYGWIN__) - detail::winsock_init<> init_; -#elif defined(__sun) || defined(__QNX__) || defined(__hpux) || defined(_AIX) \ - || defined(__osf__) - detail::signal_init<> init_; -#endif - - // The service registry. - asio::detail::service_registry* service_registry_; - - // The implementation. - impl_type& impl_; -}; - -/// Class to inform the io_service when it has work to do. -/** - * The work class is used to inform the io_service when work starts and - * finishes. This ensures that the io_service's run() function will not exit - * while work is underway, and that it does exit when there is no unfinished - * work remaining. - * - * The work class is copy-constructible so that it may be used as a data member - * in a handler class. It is not assignable. - */ -class io_service::work -{ -public: - /// Constructor notifies the io_service that work is starting. - /** - * The constructor is used to inform the io_service that some work has begun. - * This ensures that the io_service's run() function will not exit while the - * work is underway. - */ - explicit work(asio::io_service& io_service); - - /// Copy constructor notifies the io_service that work is starting. - /** - * The constructor is used to inform the io_service that some work has begun. - * This ensures that the io_service's run() function will not exit while the - * work is underway. - */ - work(const work& other); - - /// Destructor notifies the io_service that the work is complete. - /** - * The destructor is used to inform the io_service that some work has - * finished. Once the count of unfinished work reaches zero, the io_service's - * run() function is permitted to exit. - */ - ~work(); - - /// (Deprecated: use get_io_service().) Get the io_service associated with the - /// work. - asio::io_service& io_service(); - - /// Get the io_service associated with the work. - asio::io_service& get_io_service(); - -private: - // Prevent assignment. - void operator=(const work& other); - - // The io_service. - asio::io_service& io_service_; -}; - -/// Class used to uniquely identify a service. -class io_service::id - : private noncopyable -{ -public: - /// Constructor. - id() {} -}; - -/// Base class for all io_service services. -class io_service::service - : private noncopyable -{ -public: - /// (Deprecated: use get_io_service().) Get the io_service object that owns - /// the service. - asio::io_service& io_service(); - - /// Get the io_service object that owns the service. - asio::io_service& get_io_service(); - -protected: - /// Constructor. - /** - * @param owner The io_service object that owns the service. - */ - service(asio::io_service& owner); - - /// Destructor. - virtual ~service(); - -private: - /// Destroy all user-defined handler objects owned by the service. - virtual void shutdown_service() = 0; - - friend class asio::detail::service_registry; - asio::io_service& owner_; - const std::type_info* type_info_; - const asio::io_service::id* id_; - service* next_; -}; - -/// Exception thrown when trying to add a duplicate service to an io_service. -class service_already_exists - : public std::logic_error -{ -public: - service_already_exists() - : std::logic_error("Service already exists.") - { - } -}; - -/// Exception thrown when trying to add a service object to an io_service where -/// the service has a different owner. -class invalid_service_owner - : public std::logic_error -{ -public: - invalid_service_owner() - : std::logic_error("Invalid service owner.") - { - } -}; - -} // namespace asio - -#include "asio/impl/io_service.ipp" - -#include "asio/detail/pop_options.hpp" - -#endif // ASIO_IO_SERVICE_HPP diff --git a/libtorrent/include/asio/ip/address.hpp b/libtorrent/include/asio/ip/address.hpp deleted file mode 100644 index a96fcc5e7..000000000 --- a/libtorrent/include/asio/ip/address.hpp +++ /dev/null @@ -1,277 +0,0 @@ -// -// address.hpp -// ~~~~~~~~~~~ -// -// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -#ifndef ASIO_IP_ADDRESS_HPP -#define ASIO_IP_ADDRESS_HPP - -#if defined(_MSC_VER) && (_MSC_VER >= 1200) -# pragma once -#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) - -#include "asio/detail/push_options.hpp" - -#include "asio/detail/push_options.hpp" -#include -#include -#include -#include "asio/detail/pop_options.hpp" - -#include "asio/error.hpp" -#include "asio/ip/address_v4.hpp" -#include "asio/ip/address_v6.hpp" -#include "asio/detail/throw_error.hpp" - -namespace asio { -namespace ip { - -/// Implements version-independent IP addresses. -/** - * The asio::ip::address class provides the ability to use either IP - * version 4 or version 6 addresses. - * - * @par Thread Safety - * @e Distinct @e objects: Safe.@n - * @e Shared @e objects: Unsafe. - */ -class address -{ -public: - /// Default constructor. - address() - : type_(ipv4), - ipv4_address_(), - ipv6_address_() - { - } - - /// Construct an address from an IPv4 address. - address(const asio::ip::address_v4& ipv4_address) - : type_(ipv4), - ipv4_address_(ipv4_address), - ipv6_address_() - { - } - - /// Construct an address from an IPv6 address. - address(const asio::ip::address_v6& ipv6_address) - : type_(ipv6), - ipv4_address_(), - ipv6_address_(ipv6_address) - { - } - - /// Copy constructor. - address(const address& other) - : type_(other.type_), - ipv4_address_(other.ipv4_address_), - ipv6_address_(other.ipv6_address_) - { - } - - /// Assign from another address. - address& operator=(const address& other) - { - type_ = other.type_; - ipv4_address_ = other.ipv4_address_; - ipv6_address_ = other.ipv6_address_; - return *this; - } - - /// Assign from an IPv4 address. - address& operator=(const asio::ip::address_v4& ipv4_address) - { - type_ = ipv4; - ipv4_address_ = ipv4_address; - ipv6_address_ = asio::ip::address_v6(); - return *this; - } - - /// Assign from an IPv6 address. - address& operator=(const asio::ip::address_v6& ipv6_address) - { - type_ = ipv6; - ipv4_address_ = asio::ip::address_v4(); - ipv6_address_ = ipv6_address; - return *this; - } - - /// Get whether the address is an IP version 4 address. - bool is_v4() const - { - return type_ == ipv4; - } - - /// Get whether the address is an IP version 6 address. - bool is_v6() const - { - return type_ == ipv6; - } - - /// Get the address as an IP version 4 address. - asio::ip::address_v4 to_v4() const - { - if (type_ != ipv4) - { - asio::system_error e( - asio::error::address_family_not_supported); - boost::throw_exception(e); - } - return ipv4_address_; - } - - /// Get the address as an IP version 6 address. - asio::ip::address_v6 to_v6() const - { - if (type_ != ipv6) - { - asio::system_error e( - asio::error::address_family_not_supported); - boost::throw_exception(e); - } - return ipv6_address_; - } - - /// Get the address as a string in dotted decimal format. - std::string to_string() const - { - if (type_ == ipv6) - return ipv6_address_.to_string(); - return ipv4_address_.to_string(); - } - - /// Get the address as a string in dotted decimal format. - std::string to_string(asio::error_code& ec) const - { - if (type_ == ipv6) - return ipv6_address_.to_string(ec); - return ipv4_address_.to_string(ec); - } - - /// Create an address from an IPv4 address string in dotted decimal form, - /// or from an IPv6 address in hexadecimal notation. - static address from_string(const char* str) - { - asio::error_code ec; - address addr = from_string(str, ec); - asio::detail::throw_error(ec); - return addr; - } - - /// Create an address from an IPv4 address string in dotted decimal form, - /// or from an IPv6 address in hexadecimal notation. - static address from_string(const char* str, asio::error_code& ec) - { - asio::ip::address_v6 ipv6_address = - asio::ip::address_v6::from_string(str, ec); - if (!ec) - { - address tmp; - tmp.type_ = ipv6; - tmp.ipv6_address_ = ipv6_address; - return tmp; - } - - asio::ip::address_v4 ipv4_address = - asio::ip::address_v4::from_string(str, ec); - if (!ec) - { - address tmp; - tmp.type_ = ipv4; - tmp.ipv4_address_ = ipv4_address; - return tmp; - } - - return address(); - } - - /// Create an address from an IPv4 address string in dotted decimal form, - /// or from an IPv6 address in hexadecimal notation. - static address from_string(const std::string& str) - { - return from_string(str.c_str()); - } - - /// Create an address from an IPv4 address string in dotted decimal form, - /// or from an IPv6 address in hexadecimal notation. - static address from_string(const std::string& str, - asio::error_code& ec) - { - return from_string(str.c_str(), ec); - } - - /// Compare two addresses for equality. - friend bool operator==(const address& a1, const address& a2) - { - if (a1.type_ != a2.type_) - return false; - if (a1.type_ == ipv6) - return a1.ipv6_address_ == a2.ipv6_address_; - return a1.ipv4_address_ == a2.ipv4_address_; - } - - /// Compare two addresses for inequality. - friend bool operator!=(const address& a1, const address& a2) - { - if (a1.type_ != a2.type_) - return true; - if (a1.type_ == ipv6) - return a1.ipv6_address_ != a2.ipv6_address_; - return a1.ipv4_address_ != a2.ipv4_address_; - } - - /// Compare addresses for ordering. - friend bool operator<(const address& a1, const address& a2) - { - if (a1.type_ < a2.type_) - return true; - if (a1.type_ > a2.type_) - return false; - if (a1.type_ == ipv6) - return a1.ipv6_address_ < a2.ipv6_address_; - return a1.ipv4_address_ < a2.ipv4_address_; - } - -private: - // The type of the address. - enum { ipv4, ipv6 } type_; - - // The underlying IPv4 address. - asio::ip::address_v4 ipv4_address_; - - // The underlying IPv6 address. - asio::ip::address_v6 ipv6_address_; -}; - -/// Output an address as a string. -/** - * Used to output a human-readable string for a specified address. - * - * @param os The output stream to which the string will be written. - * - * @param addr The address to be written. - * - * @return The output stream. - * - * @relates asio::ip::address - */ -template -std::basic_ostream& operator<<( - std::basic_ostream& os, const address& addr) -{ - os << addr.to_string(); - return os; -} - -} // namespace ip -} // namespace asio - -#include "asio/detail/pop_options.hpp" - -#endif // ASIO_IP_ADDRESS_HPP diff --git a/libtorrent/include/asio/ip/address_v4.hpp b/libtorrent/include/asio/ip/address_v4.hpp deleted file mode 100644 index cda2a11c0..000000000 --- a/libtorrent/include/asio/ip/address_v4.hpp +++ /dev/null @@ -1,288 +0,0 @@ -// -// address_v4.hpp -// ~~~~~~~~~~~~~~ -// -// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -#ifndef ASIO_IP_ADDRESS_V4_HPP -#define ASIO_IP_ADDRESS_V4_HPP - -#if defined(_MSC_VER) && (_MSC_VER >= 1200) -# pragma once -#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) - -#include "asio/detail/push_options.hpp" - -#include "asio/detail/push_options.hpp" -#include -#include -#include -#include "asio/detail/pop_options.hpp" - -#include "asio/error.hpp" -#include "asio/detail/socket_ops.hpp" -#include "asio/detail/socket_types.hpp" -#include "asio/detail/throw_error.hpp" - -namespace asio { -namespace ip { - -/// Implements IP version 4 style addresses. -/** - * The asio::ip::address_v4 class provides the ability to use and - * manipulate IP version 4 addresses. - * - * @par Thread Safety - * @e Distinct @e objects: Safe.@n - * @e Shared @e objects: Unsafe. - */ -class address_v4 -{ -public: - /// The type used to represent an address as an array of bytes. - typedef boost::array bytes_type; - - /// Default constructor. - address_v4() - { - addr_.s_addr = 0; - } - - /// Construct an address from raw bytes. - explicit address_v4(const bytes_type& bytes) - { - using namespace std; // For memcpy. - memcpy(&addr_.s_addr, bytes.elems, 4); - } - - /// Construct an address from a unsigned long in host byte order. - explicit address_v4(unsigned long addr) - { - addr_.s_addr = asio::detail::socket_ops::host_to_network_long(addr); - } - - /// Copy constructor. - address_v4(const address_v4& other) - : addr_(other.addr_) - { - } - - /// Assign from another address. - address_v4& operator=(const address_v4& other) - { - addr_ = other.addr_; - return *this; - } - - /// Get the address in bytes. - bytes_type to_bytes() const - { - using namespace std; // For memcpy. - bytes_type bytes; - memcpy(bytes.elems, &addr_.s_addr, 4); - return bytes; - } - - /// Get the address as an unsigned long in host byte order - unsigned long to_ulong() const - { - return asio::detail::socket_ops::network_to_host_long(addr_.s_addr); - } - - /// Get the address as a string in dotted decimal format. - std::string to_string() const - { - asio::error_code ec; - std::string addr = to_string(ec); - asio::detail::throw_error(ec); - return addr; - } - - /// Get the address as a string in dotted decimal format. - std::string to_string(asio::error_code& ec) const - { - char addr_str[asio::detail::max_addr_v4_str_len]; - const char* addr = - asio::detail::socket_ops::inet_ntop(AF_INET, &addr_, addr_str, - asio::detail::max_addr_v4_str_len, 0, ec); - if (addr == 0) - return std::string(); - return addr; - } - - /// Create an address from an IP address string in dotted decimal form. - static address_v4 from_string(const char* str) - { - asio::error_code ec; - address_v4 addr = from_string(str, ec); - asio::detail::throw_error(ec); - return addr; - } - - /// Create an address from an IP address string in dotted decimal form. - static address_v4 from_string(const char* str, asio::error_code& ec) - { - address_v4 tmp; - if (asio::detail::socket_ops::inet_pton( - AF_INET, str, &tmp.addr_, 0, ec) <= 0) - return address_v4(); - return tmp; - } - - /// Create an address from an IP address string in dotted decimal form. - static address_v4 from_string(const std::string& str) - { - return from_string(str.c_str()); - } - - /// Create an address from an IP address string in dotted decimal form. - static address_v4 from_string(const std::string& str, - asio::error_code& ec) - { - return from_string(str.c_str(), ec); - } - - /// Determine whether the address is a class A address. - bool is_class_a() const - { - return IN_CLASSA(to_ulong()); - } - - /// Determine whether the address is a class B address. - bool is_class_b() const - { - return IN_CLASSB(to_ulong()); - } - - /// Determine whether the address is a class C address. - bool is_class_c() const - { - return IN_CLASSC(to_ulong()); - } - - /// Determine whether the address is a multicast address. - bool is_multicast() const - { - return IN_MULTICAST(to_ulong()); - } - - /// Compare two addresses for equality. - friend bool operator==(const address_v4& a1, const address_v4& a2) - { - return a1.addr_.s_addr == a2.addr_.s_addr; - } - - /// Compare two addresses for inequality. - friend bool operator!=(const address_v4& a1, const address_v4& a2) - { - return a1.addr_.s_addr != a2.addr_.s_addr; - } - - /// Compare addresses for ordering. - friend bool operator<(const address_v4& a1, const address_v4& a2) - { - return a1.to_ulong() < a2.to_ulong(); - } - - /// Compare addresses for ordering. - friend bool operator>(const address_v4& a1, const address_v4& a2) - { - return a1.to_ulong() > a2.to_ulong(); - } - - /// Compare addresses for ordering. - friend bool operator<=(const address_v4& a1, const address_v4& a2) - { - return a1.to_ulong() <= a2.to_ulong(); - } - - /// Compare addresses for ordering. - friend bool operator>=(const address_v4& a1, const address_v4& a2) - { - return a1.to_ulong() >= a2.to_ulong(); - } - - /// Obtain an address object that represents any address. - static address_v4 any() - { - return address_v4(static_cast(INADDR_ANY)); - } - - /// Obtain an address object that represents the loopback address. - static address_v4 loopback() - { - return address_v4(static_cast(INADDR_LOOPBACK)); - } - - /// Obtain an address object that represents the broadcast address. - static address_v4 broadcast() - { - return address_v4(static_cast(INADDR_BROADCAST)); - } - - /// Obtain an address object that represents the broadcast address that - /// corresponds to the specified address and netmask. - static address_v4 broadcast(const address_v4& addr, const address_v4& mask) - { - return address_v4(addr.to_ulong() | ~mask.to_ulong()); - } - - /// Obtain the netmask that corresponds to the address, based on its address - /// class. - static address_v4 netmask(const address_v4& addr) - { - if (addr.is_class_a()) - return address_v4(0xFF000000); - if (addr.is_class_b()) - return address_v4(0xFFFF0000); - if (addr.is_class_c()) - return address_v4(0xFFFFFF00); - return address_v4(0xFFFFFFFF); - } - -private: - // The underlying IPv4 address. - asio::detail::in4_addr_type addr_; -}; - -/// Output an address as a string. -/** - * Used to output a human-readable string for a specified address. - * - * @param os The output stream to which the string will be written. - * - * @param addr The address to be written. - * - * @return The output stream. - * - * @relates asio::ip::address_v4 - */ -template -std::basic_ostream& operator<<( - std::basic_ostream& os, const address_v4& addr) -{ - asio::error_code ec; - std::string s = addr.to_string(ec); - if (ec) - { - if (os.exceptions() & std::ios::failbit) - asio::detail::throw_error(ec); - else - os.setstate(std::ios_base::failbit); - } - else - for (std::string::iterator i = s.begin(); i != s.end(); ++i) - os << os.widen(*i); - return os; -} - -} // namespace ip -} // namespace asio - -#include "asio/detail/pop_options.hpp" - -#endif // ASIO_IP_ADDRESS_V4_HPP diff --git a/libtorrent/include/asio/ip/address_v6.hpp b/libtorrent/include/asio/ip/address_v6.hpp deleted file mode 100644 index c317fe487..000000000 --- a/libtorrent/include/asio/ip/address_v6.hpp +++ /dev/null @@ -1,406 +0,0 @@ -// -// address_v6.hpp -// ~~~~~~~~~~~~~~ -// -// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -#ifndef ASIO_IP_ADDRESS_V6_HPP -#define ASIO_IP_ADDRESS_V6_HPP - -#if defined(_MSC_VER) && (_MSC_VER >= 1200) -# pragma once -#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) - -#include "asio/detail/push_options.hpp" - -#include "asio/detail/push_options.hpp" -#include -#include -#include -#include -#include -#include -#include "asio/detail/pop_options.hpp" - -#include "asio/error.hpp" -#include "asio/detail/socket_ops.hpp" -#include "asio/detail/socket_types.hpp" -#include "asio/detail/throw_error.hpp" -#include "asio/ip/address_v4.hpp" - -namespace asio { -namespace ip { - -/// Implements IP version 6 style addresses. -/** - * The asio::ip::address_v6 class provides the ability to use and - * manipulate IP version 6 addresses. - * - * @par Thread Safety - * @e Distinct @e objects: Safe.@n - * @e Shared @e objects: Unsafe. - */ -class address_v6 -{ -public: - /// The type used to represent an address as an array of bytes. - typedef boost::array bytes_type; - - /// Default constructor. - address_v6() - : scope_id_(0) - { - asio::detail::in6_addr_type tmp_addr = IN6ADDR_ANY_INIT; - addr_ = tmp_addr; - } - - /// Construct an address from raw bytes and scope ID. - explicit address_v6(const bytes_type& bytes, unsigned long scope_id = 0) - : scope_id_(scope_id) - { - using namespace std; // For memcpy. - memcpy(addr_.s6_addr, bytes.elems, 16); - } - - /// Copy constructor. - address_v6(const address_v6& other) - : addr_(other.addr_), - scope_id_(other.scope_id_) - { - } - - /// Assign from another address. - address_v6& operator=(const address_v6& other) - { - addr_ = other.addr_; - scope_id_ = other.scope_id_; - return *this; - } - - /// The scope ID of the address. - /** - * Returns the scope ID associated with the IPv6 address. - */ - unsigned long scope_id() const - { - return scope_id_; - } - - /// The scope ID of the address. - /** - * Modifies the scope ID associated with the IPv6 address. - */ - void scope_id(unsigned long id) - { - scope_id_ = id; - } - - /// Get the address in bytes. - bytes_type to_bytes() const - { - using namespace std; // For memcpy. - bytes_type bytes; - memcpy(bytes.elems, addr_.s6_addr, 16); - return bytes; - } - - /// Get the address as a string. - std::string to_string() const - { - asio::error_code ec; - std::string addr = to_string(ec); - asio::detail::throw_error(ec); - return addr; - } - - /// Get the address as a string. - std::string to_string(asio::error_code& ec) const - { - char addr_str[asio::detail::max_addr_v6_str_len]; - const char* addr = - asio::detail::socket_ops::inet_ntop(AF_INET6, &addr_, addr_str, - asio::detail::max_addr_v6_str_len, scope_id_, ec); - if (addr == 0) - return std::string(); - return addr; - } - - /// Create an address from an IP address string. - static address_v6 from_string(const char* str) - { - asio::error_code ec; - address_v6 addr = from_string(str, ec); - asio::detail::throw_error(ec); - return addr; - } - - /// Create an address from an IP address string. - static address_v6 from_string(const char* str, asio::error_code& ec) - { - address_v6 tmp; - if (asio::detail::socket_ops::inet_pton( - AF_INET6, str, &tmp.addr_, &tmp.scope_id_, ec) <= 0) - return address_v6(); - return tmp; - } - - /// Create an address from an IP address string. - static address_v6 from_string(const std::string& str) - { - return from_string(str.c_str()); - } - - /// Create an address from an IP address string. - static address_v6 from_string(const std::string& str, - asio::error_code& ec) - { - return from_string(str.c_str(), ec); - } - - /// Converts an IPv4-mapped or IPv4-compatible address to an IPv4 address. - address_v4 to_v4() const - { - if (!is_v4_mapped() && !is_v4_compatible()) - throw std::bad_cast(); - address_v4::bytes_type v4_bytes = { { addr_.s6_addr[12], - addr_.s6_addr[13], addr_.s6_addr[14], addr_.s6_addr[15] } }; - return address_v4(v4_bytes); - } - - /// Determine whether the address is a loopback address. - bool is_loopback() const - { -#if defined(__BORLANDC__) - return ((addr_.s6_addr[0] == 0) && (addr_.s6_addr[1] == 0) - && (addr_.s6_addr[2] == 0) && (addr_.s6_addr[3] == 0) - && (addr_.s6_addr[4] == 0) && (addr_.s6_addr[5] == 0) - && (addr_.s6_addr[6] == 0) && (addr_.s6_addr[7] == 0) - && (addr_.s6_addr[8] == 0) && (addr_.s6_addr[9] == 0) - && (addr_.s6_addr[10] == 0) && (addr_.s6_addr[11] == 0) - && (addr_.s6_addr[12] == 0) && (addr_.s6_addr[13] == 0) - && (addr_.s6_addr[14] == 0) && (addr_.s6_addr[15] == 1)); -#else - using namespace asio::detail; - return IN6_IS_ADDR_LOOPBACK(&addr_) != 0; -#endif - } - - /// Determine whether the address is unspecified. - bool is_unspecified() const - { -#if defined(__BORLANDC__) - return ((addr_.s6_addr[0] == 0) && (addr_.s6_addr[1] == 0) - && (addr_.s6_addr[2] == 0) && (addr_.s6_addr[3] == 0) - && (addr_.s6_addr[4] == 0) && (addr_.s6_addr[5] == 0) - && (addr_.s6_addr[6] == 0) && (addr_.s6_addr[7] == 0) - && (addr_.s6_addr[8] == 0) && (addr_.s6_addr[9] == 0) - && (addr_.s6_addr[10] == 0) && (addr_.s6_addr[11] == 0) - && (addr_.s6_addr[12] == 0) && (addr_.s6_addr[13] == 0) - && (addr_.s6_addr[14] == 0) && (addr_.s6_addr[15] == 0)); -#else - using namespace asio::detail; - return IN6_IS_ADDR_UNSPECIFIED(&addr_) != 0; -#endif - } - - /// Determine whether the address is link local. - bool is_link_local() const - { - using namespace asio::detail; - return IN6_IS_ADDR_LINKLOCAL(&addr_) != 0; - } - - /// Determine whether the address is site local. - bool is_site_local() const - { - using namespace asio::detail; - return IN6_IS_ADDR_SITELOCAL(&addr_) != 0; - } - - /// Determine whether the address is a mapped IPv4 address. - bool is_v4_mapped() const - { - using namespace asio::detail; - return IN6_IS_ADDR_V4MAPPED(&addr_) != 0; - } - - /// Determine whether the address is an IPv4-compatible address. - bool is_v4_compatible() const - { - using namespace asio::detail; - return IN6_IS_ADDR_V4COMPAT(&addr_) != 0; - } - - /// Determine whether the address is a multicast address. - bool is_multicast() const - { - using namespace asio::detail; - return IN6_IS_ADDR_MULTICAST(&addr_) != 0; - } - - /// Determine whether the address is a global multicast address. - bool is_multicast_global() const - { - using namespace asio::detail; - return IN6_IS_ADDR_MC_GLOBAL(&addr_) != 0; - } - - /// Determine whether the address is a link-local multicast address. - bool is_multicast_link_local() const - { - using namespace asio::detail; - return IN6_IS_ADDR_MC_LINKLOCAL(&addr_) != 0; - } - - /// Determine whether the address is a node-local multicast address. - bool is_multicast_node_local() const - { - using namespace asio::detail; - return IN6_IS_ADDR_MC_NODELOCAL(&addr_) != 0; - } - - /// Determine whether the address is a org-local multicast address. - bool is_multicast_org_local() const - { - using namespace asio::detail; - return IN6_IS_ADDR_MC_ORGLOCAL(&addr_) != 0; - } - - /// Determine whether the address is a site-local multicast address. - bool is_multicast_site_local() const - { - using namespace asio::detail; - return IN6_IS_ADDR_MC_SITELOCAL(&addr_) != 0; - } - - /// Compare two addresses for equality. - friend bool operator==(const address_v6& a1, const address_v6& a2) - { - using namespace std; // For memcmp. - return memcmp(&a1.addr_, &a2.addr_, - sizeof(asio::detail::in6_addr_type)) == 0 - && a1.scope_id_ == a2.scope_id_; - } - - /// Compare two addresses for inequality. - friend bool operator!=(const address_v6& a1, const address_v6& a2) - { - using namespace std; // For memcmp. - return memcmp(&a1.addr_, &a2.addr_, - sizeof(asio::detail::in6_addr_type)) != 0 - || a1.scope_id_ != a2.scope_id_; - } - - /// Compare addresses for ordering. - friend bool operator<(const address_v6& a1, const address_v6& a2) - { - using namespace std; // For memcmp. - int memcmp_result = memcmp(&a1.addr_, &a2.addr_, - sizeof(asio::detail::in6_addr_type)); - if (memcmp_result < 0) - return true; - if (memcmp_result > 0) - return false; - return a1.scope_id_ < a2.scope_id_; - } - - /// Compare addresses for ordering. - friend bool operator>(const address_v6& a1, const address_v6& a2) - { - return a2 < a1; - } - - /// Compare addresses for ordering. - friend bool operator<=(const address_v6& a1, const address_v6& a2) - { - return !(a2 < a1); - } - - /// Compare addresses for ordering. - friend bool operator>=(const address_v6& a1, const address_v6& a2) - { - return !(a1 < a2); - } - - /// Obtain an address object that represents any address. - static address_v6 any() - { - return address_v6(); - } - - /// Obtain an address object that represents the loopback address. - static address_v6 loopback() - { - address_v6 tmp; - asio::detail::in6_addr_type tmp_addr = IN6ADDR_LOOPBACK_INIT; - tmp.addr_ = tmp_addr; - return tmp; - } - - /// Create an IPv4-mapped IPv6 address. - static address_v6 v4_mapped(const address_v4& addr) - { - address_v4::bytes_type v4_bytes = addr.to_bytes(); - bytes_type v6_bytes = { { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xFF, 0xFF, - v4_bytes[0], v4_bytes[1], v4_bytes[2], v4_bytes[3] } }; - return address_v6(v6_bytes); - } - - /// Create an IPv4-compatible IPv6 address. - static address_v6 v4_compatible(const address_v4& addr) - { - address_v4::bytes_type v4_bytes = addr.to_bytes(); - bytes_type v6_bytes = { { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - v4_bytes[0], v4_bytes[1], v4_bytes[2], v4_bytes[3] } }; - return address_v6(v6_bytes); - } - -private: - // The underlying IPv6 address. - asio::detail::in6_addr_type addr_; - - // The scope ID associated with the address. - unsigned long scope_id_; -}; - -/// Output an address as a string. -/** - * Used to output a human-readable string for a specified address. - * - * @param os The output stream to which the string will be written. - * - * @param addr The address to be written. - * - * @return The output stream. - * - * @relates asio::ip::address_v6 - */ -template -std::basic_ostream& operator<<( - std::basic_ostream& os, const address_v6& addr) -{ - asio::error_code ec; - std::string s = addr.to_string(ec); - if (ec) - { - if (os.exceptions() & std::ios::failbit) - asio::detail::throw_error(ec); - else - os.setstate(std::ios_base::failbit); - } - else - for (std::string::iterator i = s.begin(); i != s.end(); ++i) - os << os.widen(*i); - return os; -} - -} // namespace ip -} // namespace asio - -#include "asio/detail/pop_options.hpp" - -#endif // ASIO_IP_ADDRESS_V6_HPP diff --git a/libtorrent/include/asio/ip/basic_endpoint.hpp b/libtorrent/include/asio/ip/basic_endpoint.hpp deleted file mode 100644 index c83228539..000000000 --- a/libtorrent/include/asio/ip/basic_endpoint.hpp +++ /dev/null @@ -1,368 +0,0 @@ -// -// basic_endpoint.hpp -// ~~~~~~~~~~~~~~~~~~ -// -// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -#ifndef ASIO_IP_BASIC_ENDPOINT_HPP -#define ASIO_IP_BASIC_ENDPOINT_HPP - -#if defined(_MSC_VER) && (_MSC_VER >= 1200) -# pragma once -#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) - -#include "asio/detail/push_options.hpp" - -#include "asio/detail/push_options.hpp" -#include -#include -#include -#if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564)) -# include -#endif // BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564)) -#include "asio/detail/pop_options.hpp" - -#include "asio/error.hpp" -#include "asio/ip/address.hpp" -#include "asio/detail/socket_ops.hpp" -#include "asio/detail/socket_types.hpp" - -namespace asio { -namespace ip { - -/// Describes an endpoint for a version-independent IP socket. -/** - * The asio::ip::basic_endpoint class template describes an endpoint that - * may be associated with a particular socket. - * - * @par Thread Safety - * @e Distinct @e objects: Safe.@n - * @e Shared @e objects: Unsafe. - * - * @par Concepts: - * Endpoint. - */ -template -class basic_endpoint -{ -public: - /// The protocol type associated with the endpoint. - typedef InternetProtocol protocol_type; - - /// The type of the endpoint structure. This type is dependent on the - /// underlying implementation of the socket layer. -#if defined(GENERATING_DOCUMENTATION) - typedef implementation_defined data_type; -#else - typedef asio::detail::socket_addr_type data_type; -#endif - - /// Default constructor. - basic_endpoint() - : data_() - { - data_.v4.sin_family = AF_INET; - data_.v4.sin_port = 0; - data_.v4.sin_addr.s_addr = INADDR_ANY; - } - - /// Construct an endpoint using a port number, specified in the host's byte - /// order. The IP address will be the any address (i.e. INADDR_ANY or - /// in6addr_any). This constructor would typically be used for accepting new - /// connections. - /** - * @par Examples - * To initialise an IPv4 TCP endpoint for port 1234, use: - * @code - * asio::ip::tcp::endpoint ep(asio::ip::tcp::v4(), 1234); - * @endcode - * - * To specify an IPv6 UDP endpoint for port 9876, use: - * @code - * asio::ip::udp::endpoint ep(asio::ip::udp::v6(), 9876); - * @endcode - */ - basic_endpoint(const InternetProtocol& protocol, unsigned short port_num) - : data_() - { - using namespace std; // For memcpy. - if (protocol.family() == PF_INET) - { - data_.v4.sin_family = AF_INET; - data_.v4.sin_port = - asio::detail::socket_ops::host_to_network_short(port_num); - data_.v4.sin_addr.s_addr = INADDR_ANY; - } - else - { - data_.v6.sin6_family = AF_INET6; - data_.v6.sin6_port = - asio::detail::socket_ops::host_to_network_short(port_num); - data_.v6.sin6_flowinfo = 0; - asio::detail::in6_addr_type tmp_addr = IN6ADDR_ANY_INIT; - data_.v6.sin6_addr = tmp_addr; - data_.v6.sin6_scope_id = 0; - } - } - - /// Construct an endpoint using a port number and an IP address. This - /// constructor may be used for accepting connections on a specific interface - /// or for making a connection to a remote endpoint. - basic_endpoint(const asio::ip::address& addr, unsigned short port_num) - : data_() - { - using namespace std; // For memcpy. - if (addr.is_v4()) - { - data_.v4.sin_family = AF_INET; - data_.v4.sin_port = - asio::detail::socket_ops::host_to_network_short(port_num); - data_.v4.sin_addr.s_addr = - asio::detail::socket_ops::host_to_network_long( - addr.to_v4().to_ulong()); - } - else - { - data_.v6.sin6_family = AF_INET6; - data_.v6.sin6_port = - asio::detail::socket_ops::host_to_network_short(port_num); - data_.v6.sin6_flowinfo = 0; - asio::ip::address_v6 v6_addr = addr.to_v6(); - asio::ip::address_v6::bytes_type bytes = v6_addr.to_bytes(); - memcpy(data_.v6.sin6_addr.s6_addr, bytes.elems, 16); - data_.v6.sin6_scope_id = v6_addr.scope_id(); - } - } - - /// Copy constructor. - basic_endpoint(const basic_endpoint& other) - : data_(other.data_) - { - } - - /// Assign from another endpoint. - basic_endpoint& operator=(const basic_endpoint& other) - { - data_ = other.data_; - return *this; - } - - /// The protocol associated with the endpoint. - protocol_type protocol() const - { - if (is_v4()) - return InternetProtocol::v4(); - return InternetProtocol::v6(); - } - - /// Get the underlying endpoint in the native type. - data_type* data() - { - return &data_.base; - } - - /// Get the underlying endpoint in the native type. - const data_type* data() const - { - return &data_.base; - } - - /// Get the underlying size of the endpoint in the native type. - std::size_t size() const - { - if (is_v4()) - return sizeof(asio::detail::sockaddr_in4_type); - else - return sizeof(asio::detail::sockaddr_in6_type); - } - - /// Set the underlying size of the endpoint in the native type. - void resize(std::size_t size) - { - if (size > sizeof(asio::detail::sockaddr_storage_type)) - { - asio::system_error e(asio::error::invalid_argument); - boost::throw_exception(e); - } - } - - /// Get the capacity of the endpoint in the native type. - std::size_t capacity() const - { - return sizeof(asio::detail::sockaddr_storage_type); - } - - /// Get the port associated with the endpoint. The port number is always in - /// the host's byte order. - unsigned short port() const - { - if (is_v4()) - { - return asio::detail::socket_ops::network_to_host_short( - data_.v4.sin_port); - } - else - { - return asio::detail::socket_ops::network_to_host_short( - data_.v6.sin6_port); - } - } - - /// Set the port associated with the endpoint. The port number is always in - /// the host's byte order. - void port(unsigned short port_num) - { - if (is_v4()) - { - data_.v4.sin_port - = asio::detail::socket_ops::host_to_network_short(port_num); - } - else - { - data_.v6.sin6_port - = asio::detail::socket_ops::host_to_network_short(port_num); - } - } - - /// Get the IP address associated with the endpoint. - asio::ip::address address() const - { - using namespace std; // For memcpy. - if (is_v4()) - { - return asio::ip::address_v4( - asio::detail::socket_ops::network_to_host_long( - data_.v4.sin_addr.s_addr)); - } - else - { - asio::ip::address_v6::bytes_type bytes; - memcpy(bytes.elems, data_.v6.sin6_addr.s6_addr, 16); - return asio::ip::address_v6(bytes, data_.v6.sin6_scope_id); - } - } - - /// Set the IP address associated with the endpoint. - void address(const asio::ip::address& addr) - { - basic_endpoint tmp_endpoint(addr, port()); - data_ = tmp_endpoint.data_; - } - - /// Compare two endpoints for equality. - friend bool operator==(const basic_endpoint& e1, - const basic_endpoint& e2) - { - return e1.address() == e2.address() && e1.port() == e2.port(); - } - - /// Compare two endpoints for inequality. - friend bool operator!=(const basic_endpoint& e1, - const basic_endpoint& e2) - { - return e1.address() != e2.address() || e1.port() != e2.port(); - } - - /// Compare endpoints for ordering. - friend bool operator<(const basic_endpoint& e1, - const basic_endpoint& e2) - { - if (e1.address() < e2.address()) - return true; - if (e1.address() != e2.address()) - return false; - return e1.port() < e2.port(); - } - -private: - // Helper function to determine whether the endpoint is IPv4. - bool is_v4() const - { - return data_.base.sa_family == AF_INET; - } - - // The underlying IP socket address. - union data_union - { - asio::detail::socket_addr_type base; - asio::detail::sockaddr_storage_type storage; - asio::detail::sockaddr_in4_type v4; - asio::detail::sockaddr_in6_type v6; - } data_; -}; - -/// Output an endpoint as a string. -/** - * Used to output a human-readable string for a specified endpoint. - * - * @param os The output stream to which the string will be written. - * - * @param endpoint The endpoint to be written. - * - * @return The output stream. - * - * @relates asio::ip::basic_endpoint - */ -#if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564)) -template -std::ostream& operator<<(std::ostream& os, - const basic_endpoint& endpoint) -{ - const address& addr = endpoint.address(); - asio::error_code ec; - std::string a = addr.to_string(ec); - if (ec) - { - if (os.exceptions() & std::ios::failbit) - asio::detail::throw_error(ec); - else - os.setstate(std::ios_base::failbit); - } - else - { - if (addr.is_v4()) - os << a; - else - os << '[' << a << ']'; - os << ':' << endpoint.port(); - } - return os; -} -#else // BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564)) -template -std::basic_ostream& operator<<( - std::basic_ostream& os, - const basic_endpoint& endpoint) -{ - const address& addr = endpoint.address(); - asio::error_code ec; - std::string a = addr.to_string(ec); - if (ec) - { - if (os.exceptions() & std::ios::failbit) - asio::detail::throw_error(ec); - else - os.setstate(std::ios_base::failbit); - } - else - { - if (addr.is_v4()) - os << a; - else - os << '[' << a << ']'; - os << ':' << endpoint.port(); - } - return os; -} -#endif // BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564)) - -} // namespace ip -} // namespace asio - -#include "asio/detail/pop_options.hpp" - -#endif // ASIO_IP_BASIC_ENDPOINT_HPP diff --git a/libtorrent/include/asio/ip/basic_resolver.hpp b/libtorrent/include/asio/ip/basic_resolver.hpp deleted file mode 100644 index d5593778d..000000000 --- a/libtorrent/include/asio/ip/basic_resolver.hpp +++ /dev/null @@ -1,245 +0,0 @@ -// -// basic_resolver.hpp -// ~~~~~~~~~~~~~~~~~~ -// -// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -#ifndef ASIO_IP_BASIC_RESOLVER_HPP -#define ASIO_IP_BASIC_RESOLVER_HPP - -#if defined(_MSC_VER) && (_MSC_VER >= 1200) -# pragma once -#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) - -#include "asio/detail/push_options.hpp" - -#include "asio/basic_io_object.hpp" -#include "asio/error.hpp" -#include "asio/ip/resolver_service.hpp" -#include "asio/detail/throw_error.hpp" - -namespace asio { -namespace ip { - -/// Provides endpoint resolution functionality. -/** - * The basic_resolver class template provides the ability to resolve a query - * to a list of endpoints. - * - * @par Thread Safety - * @e Distinct @e objects: Safe.@n - * @e Shared @e objects: Unsafe. - */ -template > -class basic_resolver - : public basic_io_object -{ -public: - /// The protocol type. - typedef InternetProtocol protocol_type; - - /// The endpoint type. - typedef typename InternetProtocol::endpoint endpoint_type; - - /// The query type. - typedef typename InternetProtocol::resolver_query query; - - /// The iterator type. - typedef typename InternetProtocol::resolver_iterator iterator; - - /// Constructor. - /** - * This constructor creates a basic_resolver. - * - * @param io_service The io_service object that the resolver will use to - * dispatch handlers for any asynchronous operations performed on the timer. - */ - explicit basic_resolver(asio::io_service& io_service) - : basic_io_object(io_service) - { - } - - /// Cancel any asynchronous operations that are waiting on the resolver. - /** - * This function forces the completion of any pending asynchronous - * operations on the host resolver. The handler for each cancelled operation - * will be invoked with the asio::error::operation_aborted error code. - */ - void cancel() - { - return this->service.cancel(this->implementation); - } - - /// Resolve a query to a list of entries. - /** - * This function is used to resolve a query into a list of endpoint entries. - * - * @param q A query object that determines what endpoints will be returned. - * - * @returns A forward-only iterator that can be used to traverse the list - * of endpoint entries. - * - * @throws asio::system_error Thrown on failure. - * - * @note A default constructed iterator represents the end of the list. - * - * A successful call to this function is guaranteed to return at least one - * entry. - */ - iterator resolve(const query& q) - { - asio::error_code ec; - iterator i = this->service.resolve(this->implementation, q, ec); - asio::detail::throw_error(ec); - return i; - } - - /// Resolve a query to a list of entries. - /** - * This function is used to resolve a query into a list of endpoint entries. - * - * @param q A query object that determines what endpoints will be returned. - * - * @param ec Set to indicate what error occurred, if any. - * - * @returns A forward-only iterator that can be used to traverse the list - * of endpoint entries. Returns a default constructed iterator if an error - * occurs. - * - * @note A default constructed iterator represents the end of the list. - * - * A successful call to this function is guaranteed to return at least one - * entry. - */ - iterator resolve(const query& q, asio::error_code& ec) - { - return this->service.resolve(this->implementation, q, ec); - } - - /// Asynchronously resolve a query to a list of entries. - /** - * This function is used to asynchronously resolve a query into a list of - * endpoint entries. - * - * @param q A query object that determines what endpoints will be returned. - * - * @param handler The handler to be called when the resolve operation - * completes. Copies will be made of the handler as required. The function - * signature of the handler must be: - * @code void handler( - * const asio::error_code& error, // Result of operation. - * resolver::iterator iterator // Forward-only iterator that can - * // be used to traverse the list - * // of endpoint entries. - * ); @endcode - * Regardless of whether the asynchronous operation completes immediately or - * not, the handler will not be invoked from within this function. Invocation - * of the handler will be performed in a manner equivalent to using - * asio::io_service::post(). - * - * @note A default constructed iterator represents the end of the list. - * - * A successful resolve operation is guaranteed to pass at least one entry to - * the handler. - */ - template - void async_resolve(const query& q, ResolveHandler handler) - { - return this->service.async_resolve(this->implementation, q, handler); - } - - /// Resolve an endpoint to a list of entries. - /** - * This function is used to resolve an endpoint into a list of endpoint - * entries. - * - * @param e An endpoint object that determines what endpoints will be - * returned. - * - * @returns A forward-only iterator that can be used to traverse the list - * of endpoint entries. - * - * @throws asio::system_error Thrown on failure. - * - * @note A default constructed iterator represents the end of the list. - * - * A successful call to this function is guaranteed to return at least one - * entry. - */ - iterator resolve(const endpoint_type& e) - { - asio::error_code ec; - iterator i = this->service.resolve(this->implementation, e, ec); - asio::detail::throw_error(ec); - return i; - } - - /// Resolve an endpoint to a list of entries. - /** - * This function is used to resolve an endpoint into a list of endpoint - * entries. - * - * @param e An endpoint object that determines what endpoints will be - * returned. - * - * @param ec Set to indicate what error occurred, if any. - * - * @returns A forward-only iterator that can be used to traverse the list - * of endpoint entries. Returns a default constructed iterator if an error - * occurs. - * - * @note A default constructed iterator represents the end of the list. - * - * A successful call to this function is guaranteed to return at least one - * entry. - */ - iterator resolve(const endpoint_type& e, asio::error_code& ec) - { - return this->service.resolve(this->implementation, e, ec); - } - - /// Asynchronously resolve an endpoint to a list of entries. - /** - * This function is used to asynchronously resolve an endpoint into a list of - * endpoint entries. - * - * @param e An endpoint object that determines what endpoints will be - * returned. - * - * @param handler The handler to be called when the resolve operation - * completes. Copies will be made of the handler as required. The function - * signature of the handler must be: - * @code void handler( - * const asio::error_code& error, // Result of operation. - * resolver::iterator iterator // Forward-only iterator that can - * // be used to traverse the list - * // of endpoint entries. - * ); @endcode - * Regardless of whether the asynchronous operation completes immediately or - * not, the handler will not be invoked from within this function. Invocation - * of the handler will be performed in a manner equivalent to using - * asio::io_service::post(). - * - * @note A default constructed iterator represents the end of the list. - * - * A successful resolve operation is guaranteed to pass at least one entry to - * the handler. - */ - template - void async_resolve(const endpoint_type& e, ResolveHandler handler) - { - return this->service.async_resolve(this->implementation, e, handler); - } -}; - -} // namespace ip -} // namespace asio - -#include "asio/detail/pop_options.hpp" - -#endif // ASIO_IP_BASIC_RESOLVER_HPP diff --git a/libtorrent/include/asio/ip/basic_resolver_entry.hpp b/libtorrent/include/asio/ip/basic_resolver_entry.hpp deleted file mode 100644 index b29f9573b..000000000 --- a/libtorrent/include/asio/ip/basic_resolver_entry.hpp +++ /dev/null @@ -1,95 +0,0 @@ -// -// basic_resolver_entry.hpp -// ~~~~~~~~~~~~~~~~~~~~~~~~ -// -// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -#ifndef ASIO_IP_BASIC_RESOLVER_ENTRY_HPP -#define ASIO_IP_BASIC_RESOLVER_ENTRY_HPP - -#if defined(_MSC_VER) && (_MSC_VER >= 1200) -# pragma once -#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) - -#include "asio/detail/push_options.hpp" - -#include "asio/detail/push_options.hpp" -#include -#include "asio/detail/pop_options.hpp" - -namespace asio { -namespace ip { - -/// An entry produced by a resolver. -/** - * The asio::ip::basic_resolver_entry class template describes an entry - * as returned by a resolver. - * - * @par Thread Safety - * @e Distinct @e objects: Safe.@n - * @e Shared @e objects: Unsafe. - */ -template -class basic_resolver_entry -{ -public: - /// The protocol type associated with the endpoint entry. - typedef InternetProtocol protocol_type; - - /// The endpoint type associated with the endpoint entry. - typedef typename InternetProtocol::endpoint endpoint_type; - - /// Default constructor. - basic_resolver_entry() - { - } - - /// Construct with specified endpoint, host name and service name. - basic_resolver_entry(const endpoint_type& endpoint, - const std::string& host_name, const std::string& service_name) - : endpoint_(endpoint), - host_name_(host_name), - service_name_(service_name) - { - } - - /// Get the endpoint associated with the entry. - endpoint_type endpoint() const - { - return endpoint_; - } - - /// Convert to the endpoint associated with the entry. - operator endpoint_type() const - { - return endpoint_; - } - - /// Get the host name associated with the entry. - std::string host_name() const - { - return host_name_; - } - - /// Get the service name associated with the entry. - std::string service_name() const - { - return service_name_; - } - -private: - endpoint_type endpoint_; - std::string host_name_; - std::string service_name_; -}; - -} // namespace ip -} // namespace asio - -#include "asio/detail/pop_options.hpp" - -#endif // ASIO_IP_BASIC_RESOLVER_ENTRY_HPP diff --git a/libtorrent/include/asio/ip/basic_resolver_iterator.hpp b/libtorrent/include/asio/ip/basic_resolver_iterator.hpp deleted file mode 100644 index fe04ffcae..000000000 --- a/libtorrent/include/asio/ip/basic_resolver_iterator.hpp +++ /dev/null @@ -1,154 +0,0 @@ -// -// basic_resolver_iterator.hpp -// ~~~~~~~~~~~~~~~~~~~~~~~~~~~ -// -// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -#ifndef ASIO_IP_BASIC_RESOLVER_ITERATOR_HPP -#define ASIO_IP_BASIC_RESOLVER_ITERATOR_HPP - -#if defined(_MSC_VER) && (_MSC_VER >= 1200) -# pragma once -#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) - -#include "asio/detail/push_options.hpp" - -#include "asio/detail/push_options.hpp" -#include -#include -#include -#include -#include -#include -#include "asio/detail/pop_options.hpp" - -#include "asio/detail/socket_ops.hpp" -#include "asio/detail/socket_types.hpp" -#include "asio/ip/basic_resolver_entry.hpp" - -namespace asio { -namespace ip { - -/// An iterator over the entries produced by a resolver. -/** - * The asio::ip::basic_resolver_iterator class template is used to define - * iterators over the results returned by a resolver. - * - * The iterator's value_type, obtained when the iterator is dereferenced, is: - * @code const basic_resolver_entry @endcode - * - * @par Thread Safety - * @e Distinct @e objects: Safe.@n - * @e Shared @e objects: Unsafe. - */ -template -class basic_resolver_iterator - : public boost::iterator_facade< - basic_resolver_iterator, - const basic_resolver_entry, - boost::forward_traversal_tag> -{ -public: - /// Default constructor creates an end iterator. - basic_resolver_iterator() - { - } - - /// Create an iterator from an addrinfo list returned by getaddrinfo. - static basic_resolver_iterator create( - asio::detail::addrinfo_type* address_info, - const std::string& host_name, const std::string& service_name) - { - basic_resolver_iterator iter; - if (!address_info) - return iter; - - std::string actual_host_name = host_name; - if (address_info->ai_canonname) - actual_host_name = address_info->ai_canonname; - - iter.values_.reset(new values_type); - - while (address_info) - { - if (address_info->ai_family == PF_INET - || address_info->ai_family == PF_INET6) - { - using namespace std; // For memcpy. - typename InternetProtocol::endpoint endpoint; - endpoint.resize(static_cast(address_info->ai_addrlen)); - memcpy(endpoint.data(), address_info->ai_addr, - address_info->ai_addrlen); - iter.values_->push_back( - basic_resolver_entry(endpoint, - actual_host_name, service_name)); - } - address_info = address_info->ai_next; - } - - if (iter.values_->size()) - iter.iter_ = iter.values_->begin(); - else - iter.values_.reset(); - - return iter; - } - - /// Create an iterator from an endpoint, host name and service name. - static basic_resolver_iterator create( - const typename InternetProtocol::endpoint& endpoint, - const std::string& host_name, const std::string& service_name) - { - basic_resolver_iterator iter; - iter.values_.reset(new values_type); - iter.values_->push_back( - basic_resolver_entry( - endpoint, host_name, service_name)); - iter.iter_ = iter.values_->begin(); - return iter; - } - -private: - friend class boost::iterator_core_access; - - void increment() - { - if (++*iter_ == values_->end()) - { - // Reset state to match a default constructed end iterator. - values_.reset(); - typedef typename values_type::const_iterator values_iterator_type; - iter_.reset(); - } - } - - bool equal(const basic_resolver_iterator& other) const - { - if (!values_ && !other.values_) - return true; - if (values_ != other.values_) - return false; - return *iter_ == *other.iter_; - } - - const basic_resolver_entry& dereference() const - { - return **iter_; - } - - typedef std::vector > values_type; - typedef typename values_type::const_iterator values_iter_type; - boost::shared_ptr values_; - boost::optional iter_; -}; - -} // namespace ip -} // namespace asio - -#include "asio/detail/pop_options.hpp" - -#endif // ASIO_IP_BASIC_RESOLVER_ITERATOR_HPP diff --git a/libtorrent/include/asio/ip/basic_resolver_query.hpp b/libtorrent/include/asio/ip/basic_resolver_query.hpp deleted file mode 100644 index bf43a44e7..000000000 --- a/libtorrent/include/asio/ip/basic_resolver_query.hpp +++ /dev/null @@ -1,149 +0,0 @@ -// -// basic_resolver_query.hpp -// ~~~~~~~~~~~~~~~~~~~~~~~~ -// -// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -#ifndef ASIO_IP_BASIC_RESOLVER_QUERY_HPP -#define ASIO_IP_BASIC_RESOLVER_QUERY_HPP - -#if defined(_MSC_VER) && (_MSC_VER >= 1200) -# pragma once -#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) - -#include "asio/detail/push_options.hpp" - -#include "asio/detail/push_options.hpp" -#include -#include -#include "asio/detail/pop_options.hpp" - -#include "asio/detail/socket_ops.hpp" -#include "asio/ip/resolver_query_base.hpp" - -namespace asio { -namespace ip { - -/// An query to be passed to a resolver. -/** - * The asio::ip::basic_resolver_query class template describes a query - * that can be passed to a resolver. - * - * @par Thread Safety - * @e Distinct @e objects: Safe.@n - * @e Shared @e objects: Unsafe. - */ -template -class basic_resolver_query - : public resolver_query_base -{ -public: - /// The protocol type associated with the endpoint query. - typedef InternetProtocol protocol_type; - - /// Construct with specified service name for any protocol. - basic_resolver_query(const std::string& service_name, - int flags = passive | address_configured) - : hints_(), - host_name_(), - service_name_(service_name) - { - typename InternetProtocol::endpoint endpoint; - hints_.ai_flags = flags; - hints_.ai_family = PF_UNSPEC; - hints_.ai_socktype = endpoint.protocol().type(); - hints_.ai_protocol = endpoint.protocol().protocol(); - hints_.ai_addrlen = 0; - hints_.ai_canonname = 0; - hints_.ai_addr = 0; - hints_.ai_next = 0; - } - - /// Construct with specified service name for a given protocol. - basic_resolver_query(const protocol_type& protocol, - const std::string& service_name, - int flags = passive | address_configured) - : hints_(), - host_name_(), - service_name_(service_name) - { - hints_.ai_flags = flags; - hints_.ai_family = protocol.family(); - hints_.ai_socktype = protocol.type(); - hints_.ai_protocol = protocol.protocol(); - hints_.ai_addrlen = 0; - hints_.ai_canonname = 0; - hints_.ai_addr = 0; - hints_.ai_next = 0; - } - - /// Construct with specified host name and service name for any protocol. - basic_resolver_query(const std::string& host_name, - const std::string& service_name, int flags = address_configured) - : hints_(), - host_name_(host_name), - service_name_(service_name) - { - typename InternetProtocol::endpoint endpoint; - hints_.ai_flags = flags; - hints_.ai_family = PF_UNSPEC; - hints_.ai_socktype = endpoint.protocol().type(); - hints_.ai_protocol = endpoint.protocol().protocol(); - hints_.ai_addrlen = 0; - hints_.ai_canonname = 0; - hints_.ai_addr = 0; - hints_.ai_next = 0; - } - - /// Construct with specified host name and service name for a given protocol. - basic_resolver_query(const protocol_type& protocol, - const std::string& host_name, const std::string& service_name, - int flags = address_configured) - : hints_(), - host_name_(host_name), - service_name_(service_name) - { - hints_.ai_flags = flags; - hints_.ai_family = protocol.family(); - hints_.ai_socktype = protocol.type(); - hints_.ai_protocol = protocol.protocol(); - hints_.ai_addrlen = 0; - hints_.ai_canonname = 0; - hints_.ai_addr = 0; - hints_.ai_next = 0; - } - - /// Get the hints associated with the query. - const asio::detail::addrinfo_type& hints() const - { - return hints_; - } - - /// Get the host name associated with the query. - std::string host_name() const - { - return host_name_; - } - - /// Get the service name associated with the query. - std::string service_name() const - { - return service_name_; - } - -private: - asio::detail::addrinfo_type hints_; - std::string host_name_; - std::string service_name_; -}; - -} // namespace ip -} // namespace asio - -#include "asio/detail/pop_options.hpp" - -#endif // ASIO_IP_BASIC_RESOLVER_QUERY_HPP diff --git a/libtorrent/include/asio/ip/detail/socket_option.hpp b/libtorrent/include/asio/ip/detail/socket_option.hpp deleted file mode 100644 index a3496fd56..000000000 --- a/libtorrent/include/asio/ip/detail/socket_option.hpp +++ /dev/null @@ -1,578 +0,0 @@ -// -// socket_option.hpp -// ~~~~~~~~~~~~~~~~~ -// -// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -#ifndef ASIO_IP_DETAIL_SOCKET_OPTION_HPP -#define ASIO_IP_DETAIL_SOCKET_OPTION_HPP - -#if defined(_MSC_VER) && (_MSC_VER >= 1200) -# pragma once -#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) - -#include "asio/detail/push_options.hpp" - -#include "asio/detail/push_options.hpp" -#include -#include -#include -#include "asio/detail/pop_options.hpp" - -#include "asio/ip/address.hpp" -#include "asio/detail/socket_ops.hpp" -#include "asio/detail/socket_types.hpp" - -namespace asio { -namespace ip { -namespace detail { -namespace socket_option { - -// Helper template for implementing multicast enable loopback options. -template -class multicast_enable_loopback -{ -public: -#if defined(__sun) || defined(__osf__) - typedef unsigned char ipv4_value_type; - typedef unsigned char ipv6_value_type; -#elif defined(_AIX) || defined(__hpux) - typedef unsigned char ipv4_value_type; - typedef unsigned int ipv6_value_type; -#else - typedef int ipv4_value_type; - typedef int ipv6_value_type; -#endif - - // Default constructor. - multicast_enable_loopback() - : ipv4_value_(0), - ipv6_value_(0) - { - } - - // Construct with a specific option value. - explicit multicast_enable_loopback(bool v) - : ipv4_value_(v ? 1 : 0), - ipv6_value_(v ? 1 : 0) - { - } - - // Set the value of the boolean. - multicast_enable_loopback& operator=(bool v) - { - ipv4_value_ = v ? 1 : 0; - ipv6_value_ = v ? 1 : 0; - return *this; - } - - // Get the current value of the boolean. - bool value() const - { - return !!ipv4_value_; - } - - // Convert to bool. - operator bool() const - { - return !!ipv4_value_; - } - - // Test for false. - bool operator!() const - { - return !ipv4_value_; - } - - // Get the level of the socket option. - template - int level(const Protocol& protocol) const - { - if (protocol.family() == PF_INET6) - return IPv6_Level; - return IPv4_Level; - } - - // Get the name of the socket option. - template - int name(const Protocol& protocol) const - { - if (protocol.family() == PF_INET6) - return IPv6_Name; - return IPv4_Name; - } - - // Get the address of the boolean data. - template - void* data(const Protocol& protocol) - { - if (protocol.family() == PF_INET6) - return &ipv6_value_; - return &ipv4_value_; - } - - // Get the address of the boolean data. - template - const void* data(const Protocol& protocol) const - { - if (protocol.family() == PF_INET6) - return &ipv6_value_; - return &ipv4_value_; - } - - // Get the size of the boolean data. - template - std::size_t size(const Protocol& protocol) const - { - if (protocol.family() == PF_INET6) - return sizeof(ipv6_value_); - return sizeof(ipv4_value_); - } - - // Set the size of the boolean data. - template - void resize(const Protocol& protocol, std::size_t s) - { - if (protocol.family() == PF_INET6) - { - if (s != sizeof(ipv6_value_)) - { - throw std::length_error( - "multicast_enable_loopback socket option resize"); - } - ipv4_value_ = ipv6_value_ ? 1 : 0; - } - else - { - if (s != sizeof(ipv4_value_)) - { - throw std::length_error( - "multicast_enable_loopback socket option resize"); - } - ipv6_value_ = ipv4_value_ ? 1 : 0; - } - } - -private: - ipv4_value_type ipv4_value_; - ipv6_value_type ipv6_value_; -}; - -// Helper template for implementing unicast hops options. -template -class unicast_hops -{ -public: - // Default constructor. - unicast_hops() - : value_(0) - { - } - - // Construct with a specific option value. - explicit unicast_hops(int v) - : value_(v) - { - } - - // Set the value of the option. - unicast_hops& operator=(int v) - { - value_ = v; - return *this; - } - - // Get the current value of the option. - int value() const - { - return value_; - } - - // Get the level of the socket option. - template - int level(const Protocol& protocol) const - { - if (protocol.family() == PF_INET6) - return IPv6_Level; - return IPv4_Level; - } - - // Get the name of the socket option. - template - int name(const Protocol& protocol) const - { - if (protocol.family() == PF_INET6) - return IPv6_Name; - return IPv4_Name; - } - - // Get the address of the data. - template - int* data(const Protocol&) - { - return &value_; - } - - // Get the address of the data. - template - const int* data(const Protocol&) const - { - return &value_; - } - - // Get the size of the data. - template - std::size_t size(const Protocol&) const - { - return sizeof(value_); - } - - // Set the size of the data. - template - void resize(const Protocol&, std::size_t s) - { - if (s != sizeof(value_)) - throw std::length_error("unicast hops socket option resize"); -#if defined(__hpux) - if (value_ < 0) - value_ = value_ & 0xFF; -#endif - } - -private: - int value_; -}; - -// Helper template for implementing multicast hops options. -template -class multicast_hops -{ -public: -#if defined(BOOST_WINDOWS) && defined(UNDER_CE) - typedef int ipv4_value_type; -#else - typedef unsigned char ipv4_value_type; -#endif - typedef int ipv6_value_type; - - // Default constructor. - multicast_hops() - : ipv4_value_(0), - ipv6_value_(0) - { - } - - // Construct with a specific option value. - explicit multicast_hops(int v) - { - if (v < 0 || v > 255) - throw std::out_of_range("multicast hops value out of range"); - ipv4_value_ = (ipv4_value_type)v; - ipv6_value_ = v; - } - - // Set the value of the option. - multicast_hops& operator=(int v) - { - if (v < 0 || v > 255) - throw std::out_of_range("multicast hops value out of range"); - ipv4_value_ = (ipv4_value_type)v; - ipv6_value_ = v; - return *this; - } - - // Get the current value of the option. - int value() const - { - return ipv6_value_; - } - - // Get the level of the socket option. - template - int level(const Protocol& protocol) const - { - if (protocol.family() == PF_INET6) - return IPv6_Level; - return IPv4_Level; - } - - // Get the name of the socket option. - template - int name(const Protocol& protocol) const - { - if (protocol.family() == PF_INET6) - return IPv6_Name; - return IPv4_Name; - } - - // Get the address of the data. - template - void* data(const Protocol& protocol) - { - if (protocol.family() == PF_INET6) - return &ipv6_value_; - return &ipv4_value_; - } - - // Get the address of the data. - template - const void* data(const Protocol& protocol) const - { - if (protocol.family() == PF_INET6) - return &ipv6_value_; - return &ipv4_value_; - } - - // Get the size of the data. - template - std::size_t size(const Protocol& protocol) const - { - if (protocol.family() == PF_INET6) - return sizeof(ipv6_value_); - return sizeof(ipv4_value_); - } - - // Set the size of the data. - template - void resize(const Protocol& protocol, std::size_t s) - { - if (protocol.family() == PF_INET6) - { - if (s != sizeof(ipv6_value_)) - throw std::length_error("multicast hops socket option resize"); - if (ipv6_value_ < 0) - ipv4_value_ = 0; - else if (ipv6_value_ > 255) - ipv4_value_ = 255; - else - ipv4_value_ = (ipv4_value_type)ipv6_value_; - } - else - { - if (s != sizeof(ipv4_value_)) - throw std::length_error("multicast hops socket option resize"); - ipv6_value_ = ipv4_value_; - } - } - -private: - ipv4_value_type ipv4_value_; - ipv6_value_type ipv6_value_; -}; - -// Helper template for implementing ip_mreq-based options. -template -class multicast_request -{ -public: - // Default constructor. - multicast_request() - { - ipv4_value_.imr_multiaddr.s_addr = - asio::detail::socket_ops::host_to_network_long( - asio::ip::address_v4::any().to_ulong()); - ipv4_value_.imr_interface.s_addr = - asio::detail::socket_ops::host_to_network_long( - asio::ip::address_v4::any().to_ulong()); - - asio::detail::in6_addr_type tmp_addr = IN6ADDR_ANY_INIT; - ipv6_value_.ipv6mr_multiaddr = tmp_addr; - ipv6_value_.ipv6mr_interface = 0; - } - - // Construct with multicast address only. - explicit multicast_request(const asio::ip::address& multicast_address) - { - if (multicast_address.is_v6()) - { - ipv4_value_.imr_multiaddr.s_addr = - asio::detail::socket_ops::host_to_network_long( - asio::ip::address_v4::any().to_ulong()); - ipv4_value_.imr_interface.s_addr = - asio::detail::socket_ops::host_to_network_long( - asio::ip::address_v4::any().to_ulong()); - - using namespace std; // For memcpy. - asio::ip::address_v6 ipv6_address = multicast_address.to_v6(); - asio::ip::address_v6::bytes_type bytes = ipv6_address.to_bytes(); - memcpy(ipv6_value_.ipv6mr_multiaddr.s6_addr, bytes.elems, 16); - ipv6_value_.ipv6mr_interface = 0; - } - else - { - ipv4_value_.imr_multiaddr.s_addr = - asio::detail::socket_ops::host_to_network_long( - multicast_address.to_v4().to_ulong()); - ipv4_value_.imr_interface.s_addr = - asio::detail::socket_ops::host_to_network_long( - asio::ip::address_v4::any().to_ulong()); - - asio::detail::in6_addr_type tmp_addr = IN6ADDR_ANY_INIT; - ipv6_value_.ipv6mr_multiaddr = tmp_addr; - ipv6_value_.ipv6mr_interface = 0; - } - } - - // Construct with multicast address and IPv4 address specifying an interface. - explicit multicast_request( - const asio::ip::address_v4& multicast_address, - const asio::ip::address_v4& network_interface - = asio::ip::address_v4::any()) - { - ipv4_value_.imr_multiaddr.s_addr = - asio::detail::socket_ops::host_to_network_long( - multicast_address.to_ulong()); - ipv4_value_.imr_interface.s_addr = - asio::detail::socket_ops::host_to_network_long( - network_interface.to_ulong()); - - asio::detail::in6_addr_type tmp_addr = IN6ADDR_ANY_INIT; - ipv6_value_.ipv6mr_multiaddr = tmp_addr; - ipv6_value_.ipv6mr_interface = 0; - } - - // Construct with multicast address and IPv6 network interface index. - explicit multicast_request( - const asio::ip::address_v6& multicast_address, - unsigned long network_interface = 0) - { - ipv4_value_.imr_multiaddr.s_addr = - asio::detail::socket_ops::host_to_network_long( - asio::ip::address_v4::any().to_ulong()); - ipv4_value_.imr_interface.s_addr = - asio::detail::socket_ops::host_to_network_long( - asio::ip::address_v4::any().to_ulong()); - - using namespace std; // For memcpy. - asio::ip::address_v6::bytes_type bytes = - multicast_address.to_bytes(); - memcpy(ipv6_value_.ipv6mr_multiaddr.s6_addr, bytes.elems, 16); - ipv6_value_.ipv6mr_interface = network_interface; - } - - // Get the level of the socket option. - template - int level(const Protocol& protocol) const - { - if (protocol.family() == PF_INET6) - return IPv6_Level; - return IPv4_Level; - } - - // Get the name of the socket option. - template - int name(const Protocol& protocol) const - { - if (protocol.family() == PF_INET6) - return IPv6_Name; - return IPv4_Name; - } - - // Get the address of the option data. - template - const void* data(const Protocol& protocol) const - { - if (protocol.family() == PF_INET6) - return &ipv6_value_; - return &ipv4_value_; - } - - // Get the size of the option data. - template - std::size_t size(const Protocol& protocol) const - { - if (protocol.family() == PF_INET6) - return sizeof(ipv6_value_); - return sizeof(ipv4_value_); - } - -private: - asio::detail::in4_mreq_type ipv4_value_; - asio::detail::in6_mreq_type ipv6_value_; -}; - -// Helper template for implementing options that specify a network interface. -template -class network_interface -{ -public: - // Default constructor. - network_interface() - { - ipv4_value_.s_addr = - asio::detail::socket_ops::host_to_network_long( - asio::ip::address_v4::any().to_ulong()); - ipv6_value_ = 0; - } - - // Construct with IPv4 interface. - explicit network_interface(const asio::ip::address_v4& ipv4_interface) - { - ipv4_value_.s_addr = - asio::detail::socket_ops::host_to_network_long( - ipv4_interface.to_ulong()); - ipv6_value_ = 0; - } - - // Construct with IPv6 interface. - explicit network_interface(unsigned int ipv6_interface) - { - ipv4_value_.s_addr = - asio::detail::socket_ops::host_to_network_long( - asio::ip::address_v4::any().to_ulong()); - ipv6_value_ = ipv6_interface; - } - - // Get the level of the socket option. - template - int level(const Protocol& protocol) const - { - if (protocol.family() == PF_INET6) - return IPv6_Level; - return IPv4_Level; - } - - // Get the name of the socket option. - template - int name(const Protocol& protocol) const - { - if (protocol.family() == PF_INET6) - return IPv6_Name; - return IPv4_Name; - } - - // Get the address of the option data. - template - const void* data(const Protocol& protocol) const - { - if (protocol.family() == PF_INET6) - return &ipv6_value_; - return &ipv4_value_; - } - - // Get the size of the option data. - template - std::size_t size(const Protocol& protocol) const - { - if (protocol.family() == PF_INET6) - return sizeof(ipv6_value_); - return sizeof(ipv4_value_); - } - -private: - asio::detail::in4_addr_type ipv4_value_; - unsigned int ipv6_value_; -}; - -} // namespace socket_option -} // namespace detail -} // namespace ip -} // namespace asio - -#include "asio/detail/pop_options.hpp" - -#endif // ASIO_IP_DETAIL_SOCKET_OPTION_HPP diff --git a/libtorrent/include/asio/ip/host_name.hpp b/libtorrent/include/asio/ip/host_name.hpp deleted file mode 100644 index 852801397..000000000 --- a/libtorrent/include/asio/ip/host_name.hpp +++ /dev/null @@ -1,62 +0,0 @@ -// -// host_name.hpp -// ~~~~~~~~~~~~~ -// -// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -#ifndef ASIO_IP_HOST_NAME_HPP -#define ASIO_IP_HOST_NAME_HPP - -#if defined(_MSC_VER) && (_MSC_VER >= 1200) -# pragma once -#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) - -#include "asio/detail/push_options.hpp" - -#include "asio/detail/push_options.hpp" -#include -#include "asio/detail/pop_options.hpp" - -#include "asio/error.hpp" -#include "asio/detail/socket_ops.hpp" -#include "asio/detail/throw_error.hpp" - -namespace asio { -namespace ip { - -/// Get the current host name. -std::string host_name(); - -/// Get the current host name. -std::string host_name(asio::error_code& ec); - -inline std::string host_name() -{ - char name[1024]; - asio::error_code ec; - if (asio::detail::socket_ops::gethostname(name, sizeof(name), ec) != 0) - { - asio::detail::throw_error(ec); - return std::string(); - } - return std::string(name); -} - -inline std::string host_name(asio::error_code& ec) -{ - char name[1024]; - if (asio::detail::socket_ops::gethostname(name, sizeof(name), ec) != 0) - return std::string(); - return std::string(name); -} - -} // namespace ip -} // namespace asio - -#include "asio/detail/pop_options.hpp" - -#endif // ASIO_IP_HOST_NAME_HPP diff --git a/libtorrent/include/asio/ip/icmp.hpp b/libtorrent/include/asio/ip/icmp.hpp deleted file mode 100644 index c36ed2785..000000000 --- a/libtorrent/include/asio/ip/icmp.hpp +++ /dev/null @@ -1,118 +0,0 @@ -// -// icmp.hpp -// ~~~~~~~~ -// -// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -#ifndef ASIO_IP_ICMP_HPP -#define ASIO_IP_ICMP_HPP - -#if defined(_MSC_VER) && (_MSC_VER >= 1200) -# pragma once -#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) - -#include "asio/detail/push_options.hpp" - -#include "asio/basic_raw_socket.hpp" -#include "asio/ip/basic_endpoint.hpp" -#include "asio/ip/basic_resolver.hpp" -#include "asio/ip/basic_resolver_iterator.hpp" -#include "asio/ip/basic_resolver_query.hpp" -#include "asio/detail/socket_types.hpp" - -namespace asio { -namespace ip { - -/// Encapsulates the flags needed for ICMP. -/** - * The asio::ip::icmp class contains flags necessary for ICMP sockets. - * - * @par Thread Safety - * @e Distinct @e objects: Safe.@n - * @e Shared @e objects: Safe. - * - * @par Concepts: - * Protocol, InternetProtocol. - */ -class icmp -{ -public: - /// The type of a ICMP endpoint. - typedef basic_endpoint endpoint; - - /// The type of a resolver query. - typedef basic_resolver_query resolver_query; - - /// The type of a resolver iterator. - typedef basic_resolver_iterator resolver_iterator; - - /// Construct to represent the IPv4 ICMP protocol. - static icmp v4() - { - return icmp(IPPROTO_ICMP, PF_INET); - } - - /// Construct to represent the IPv6 ICMP protocol. - static icmp v6() - { - return icmp(IPPROTO_ICMPV6, PF_INET6); - } - - /// Obtain an identifier for the type of the protocol. - int type() const - { - return SOCK_RAW; - } - - /// Obtain an identifier for the protocol. - int protocol() const - { - return protocol_; - } - - /// Obtain an identifier for the protocol family. - int family() const - { - return family_; - } - - /// The ICMP socket type. - typedef basic_raw_socket socket; - - /// The ICMP resolver type. - typedef basic_resolver resolver; - - /// Compare two protocols for equality. - friend bool operator==(const icmp& p1, const icmp& p2) - { - return p1.protocol_ == p2.protocol_ && p1.family_ == p2.family_; - } - - /// Compare two protocols for inequality. - friend bool operator!=(const icmp& p1, const icmp& p2) - { - return p1.protocol_ != p2.protocol_ || p1.family_ != p2.family_; - } - -private: - // Construct with a specific family. - explicit icmp(int protocol, int family) - : protocol_(protocol), - family_(family) - { - } - - int protocol_; - int family_; -}; - -} // namespace ip -} // namespace asio - -#include "asio/detail/pop_options.hpp" - -#endif // ASIO_IP_ICMP_HPP diff --git a/libtorrent/include/asio/ip/multicast.hpp b/libtorrent/include/asio/ip/multicast.hpp deleted file mode 100644 index c8b84f5d3..000000000 --- a/libtorrent/include/asio/ip/multicast.hpp +++ /dev/null @@ -1,181 +0,0 @@ -// -// multicast.hpp -// ~~~~~~~~~~~~~ -// -// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -#ifndef ASIO_IP_MULTICAST_HPP -#define ASIO_IP_MULTICAST_HPP - -#if defined(_MSC_VER) && (_MSC_VER >= 1200) -# pragma once -#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) - -#include "asio/detail/push_options.hpp" - -#include "asio/detail/push_options.hpp" -#include -#include -#include "asio/detail/pop_options.hpp" - -#include "asio/ip/detail/socket_option.hpp" - -namespace asio { -namespace ip { -namespace multicast { - -/// Socket option to join a multicast group on a specified interface. -/** - * Implements the IPPROTO_IP/IP_ADD_MEMBERSHIP socket option. - * - * @par Examples - * Setting the option to join a multicast group: - * @code - * asio::ip::udp::socket socket(io_service); - * ... - * asio::ip::address multicast_address = - * asio::ip::address::from_string("225.0.0.1"); - * asio::ip::multicast::join_group option(multicast_address); - * socket.set_option(option); - * @endcode - * - * @par Concepts: - * SettableSocketOption. - */ -#if defined(GENERATING_DOCUMENTATION) -typedef implementation_defined join_group; -#else -typedef asio::ip::detail::socket_option::multicast_request< - IPPROTO_IP, IP_ADD_MEMBERSHIP, IPPROTO_IPV6, IPV6_JOIN_GROUP> join_group; -#endif - -/// Socket option to leave a multicast group on a specified interface. -/** - * Implements the IPPROTO_IP/IP_DROP_MEMBERSHIP socket option. - * - * @par Examples - * Setting the option to leave a multicast group: - * @code - * asio::ip::udp::socket socket(io_service); - * ... - * asio::ip::address multicast_address = - * asio::ip::address::from_string("225.0.0.1"); - * asio::ip::multicast::leave_group option(multicast_address); - * socket.set_option(option); - * @endcode - * - * @par Concepts: - * SettableSocketOption. - */ -#if defined(GENERATING_DOCUMENTATION) -typedef implementation_defined leave_group; -#else -typedef asio::ip::detail::socket_option::multicast_request< - IPPROTO_IP, IP_DROP_MEMBERSHIP, IPPROTO_IPV6, IPV6_LEAVE_GROUP> leave_group; -#endif - -/// Socket option for local interface to use for outgoing multicast packets. -/** - * Implements the IPPROTO_IP/IP_MULTICAST_IF socket option. - * - * @par Examples - * Setting the option: - * @code - * asio::ip::udp::socket socket(io_service); - * ... - * asio::ip::address_v4 local_interface = - * asio::ip::address_v4::from_string("1.2.3.4"); - * asio::ip::multicast::outbound_interface option(local_interface); - * socket.set_option(option); - * @endcode - * - * @par Concepts: - * SettableSocketOption. - */ -#if defined(GENERATING_DOCUMENTATION) -typedef implementation_defined outbound_interface; -#else -typedef asio::ip::detail::socket_option::network_interface< - IPPROTO_IP, IP_MULTICAST_IF, IPPROTO_IPV6, IPV6_MULTICAST_IF> - outbound_interface; -#endif - -/// Socket option for time-to-live associated with outgoing multicast packets. -/** - * Implements the IPPROTO_IP/IP_MULTICAST_TTL socket option. - * - * @par Examples - * Setting the option: - * @code - * asio::ip::udp::socket socket(io_service); - * ... - * asio::ip::multicast::hops option(4); - * socket.set_option(option); - * @endcode - * - * @par - * Getting the current option value: - * @code - * asio::ip::udp::socket socket(io_service); - * ... - * asio::ip::multicast::hops option; - * socket.get_option(option); - * int ttl = option.value(); - * @endcode - * - * @par Concepts: - * GettableSocketOption, SettableSocketOption. - */ -#if defined(GENERATING_DOCUMENTATION) -typedef implementation_defined hops; -#else -typedef asio::ip::detail::socket_option::multicast_hops< - IPPROTO_IP, IP_MULTICAST_TTL, IPPROTO_IPV6, IPV6_MULTICAST_HOPS> hops; -#endif - -/// Socket option determining whether outgoing multicast packets will be -/// received on the same socket if it is a member of the multicast group. -/** - * Implements the IPPROTO_IP/IP_MULTICAST_LOOP socket option. - * - * @par Examples - * Setting the option: - * @code - * asio::ip::udp::socket socket(io_service); - * ... - * asio::ip::multicast::enable_loopback option(true); - * socket.set_option(option); - * @endcode - * - * @par - * Getting the current option value: - * @code - * asio::ip::udp::socket socket(io_service); - * ... - * asio::ip::multicast::enable_loopback option; - * socket.get_option(option); - * bool is_set = option.value(); - * @endcode - * - * @par Concepts: - * GettableSocketOption, SettableSocketOption. - */ -#if defined(GENERATING_DOCUMENTATION) -typedef implementation_defined enable_loopback; -#else -typedef asio::ip::detail::socket_option::multicast_enable_loopback< - IPPROTO_IP, IP_MULTICAST_LOOP, IPPROTO_IPV6, IPV6_MULTICAST_LOOP> - enable_loopback; -#endif - -} // namespace multicast -} // namespace ip -} // namespace asio - -#include "asio/detail/pop_options.hpp" - -#endif // ASIO_IP_MULTICAST_HPP diff --git a/libtorrent/include/asio/ip/resolver_query_base.hpp b/libtorrent/include/asio/ip/resolver_query_base.hpp deleted file mode 100644 index 16f846642..000000000 --- a/libtorrent/include/asio/ip/resolver_query_base.hpp +++ /dev/null @@ -1,107 +0,0 @@ -// -// resolver_query_base.hpp -// ~~~~~~~~~~~~~~~~~~~~~~~ -// -// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -#ifndef ASIO_IP_RESOLVER_QUERY_BASE_HPP -#define ASIO_IP_RESOLVER_QUERY_BASE_HPP - -#if defined(_MSC_VER) && (_MSC_VER >= 1200) -# pragma once -#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) - -#include "asio/detail/push_options.hpp" - -#include "asio/detail/push_options.hpp" -#include -#include -#include "asio/detail/pop_options.hpp" - -#include "asio/detail/socket_types.hpp" - -namespace asio { -namespace ip { - -/// The resolver_query_base class is used as a base for the -/// basic_resolver_query class templates to provide a common place to define -/// the flag constants. -class resolver_query_base -{ -public: -#if defined(GENERATING_DOCUMENTATION) - /// Determine the canonical name of the host specified in the query. - static const int canonical_name = implementation_defined; - - /// Indicate that returned endpoint is intended for use as a locally bound - /// socket endpoint. - static const int passive = implementation_defined; - - /// Host name should be treated as a numeric string defining an IPv4 or IPv6 - /// address and no name resolution should be attempted. - static const int numeric_host = implementation_defined; - - /// Service name should be treated as a numeric string defining a port number - /// and no name resolution should be attempted. - static const int numeric_service = implementation_defined; - - /// If the query protocol family is specified as IPv6, return IPv4-mapped - /// IPv6 addresses on finding no IPv6 addresses. - static const int v4_mapped = implementation_defined; - - /// If used with v4_mapped, return all matching IPv6 and IPv4 addresses. - static const int all_matching = implementation_defined; - - /// Only return IPv4 addresses if a non-loopback IPv4 address is configured - /// for the system. Only return IPv6 addresses if a non-loopback IPv6 address - /// is configured for the system. - static const int address_configured = implementation_defined; -#else - BOOST_STATIC_CONSTANT(int, canonical_name = AI_CANONNAME); - BOOST_STATIC_CONSTANT(int, passive = AI_PASSIVE); - BOOST_STATIC_CONSTANT(int, numeric_host = AI_NUMERICHOST); -# if defined(AI_NUMERICSERV) - BOOST_STATIC_CONSTANT(int, numeric_service = AI_NUMERICSERV); -# else - BOOST_STATIC_CONSTANT(int, numeric_service = 0); -# endif -# if defined(AI_V4MAPPED) - BOOST_STATIC_CONSTANT(int, v4_mapped = AI_V4MAPPED); -# else - BOOST_STATIC_CONSTANT(int, v4_mapped = 0); -# endif -# if defined(AI_ALL) - BOOST_STATIC_CONSTANT(int, all_matching = AI_ALL); -# else - BOOST_STATIC_CONSTANT(int, all_matching = 0); -# endif -# if defined(AI_ADDRCONFIG) - BOOST_STATIC_CONSTANT(int, address_configured = AI_ADDRCONFIG); -# else - BOOST_STATIC_CONSTANT(int, address_configured = 0); -# endif -#endif - -protected: - /// Protected destructor to prevent deletion through this type. - ~resolver_query_base() - { - } - -#if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564)) -private: - // Workaround to enable the empty base optimisation with Borland C++. - char dummy_; -#endif -}; - -} // namespace ip -} // namespace asio - -#include "asio/detail/pop_options.hpp" - -#endif // ASIO_IP_RESOLVER_QUERY_BASE_HPP diff --git a/libtorrent/include/asio/ip/resolver_service.hpp b/libtorrent/include/asio/ip/resolver_service.hpp deleted file mode 100644 index 01b0a8e3e..000000000 --- a/libtorrent/include/asio/ip/resolver_service.hpp +++ /dev/null @@ -1,140 +0,0 @@ -// -// resolver_service.hpp -// ~~~~~~~~~~~~~~~~~~~~ -// -// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -#ifndef ASIO_IP_RESOLVER_SERVICE_HPP -#define ASIO_IP_RESOLVER_SERVICE_HPP - -#if defined(_MSC_VER) && (_MSC_VER >= 1200) -# pragma once -#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) - -#include "asio/detail/push_options.hpp" - -#include "asio/error.hpp" -#include "asio/io_service.hpp" -#include "asio/detail/resolver_service.hpp" -#include "asio/detail/service_base.hpp" - -namespace asio { -namespace ip { - -/// Default service implementation for a resolver. -template -class resolver_service -#if defined(GENERATING_DOCUMENTATION) - : public asio::io_service::service -#else - : public asio::detail::service_base< - resolver_service > -#endif -{ -public: -#if defined(GENERATING_DOCUMENTATION) - /// The unique service identifier. - static asio::io_service::id id; -#endif - - /// The protocol type. - typedef InternetProtocol protocol_type; - - /// The endpoint type. - typedef typename InternetProtocol::endpoint endpoint_type; - - /// The query type. - typedef typename InternetProtocol::resolver_query query_type; - - /// The iterator type. - typedef typename InternetProtocol::resolver_iterator iterator_type; - -private: - // The type of the platform-specific implementation. - typedef asio::detail::resolver_service - service_impl_type; - -public: - /// The type of a resolver implementation. -#if defined(GENERATING_DOCUMENTATION) - typedef implementation_defined implementation_type; -#else - typedef typename service_impl_type::implementation_type implementation_type; -#endif - - /// Construct a new resolver service for the specified io_service. - explicit resolver_service(asio::io_service& io_service) - : asio::detail::service_base< - resolver_service >(io_service), - service_impl_(asio::use_service(io_service)) - { - } - - /// Destroy all user-defined handler objects owned by the service. - void shutdown_service() - { - } - - /// Construct a new resolver implementation. - void construct(implementation_type& impl) - { - service_impl_.construct(impl); - } - - /// Destroy a resolver implementation. - void destroy(implementation_type& impl) - { - service_impl_.destroy(impl); - } - - /// Cancel pending asynchronous operations. - void cancel(implementation_type& impl) - { - service_impl_.cancel(impl); - } - - /// Resolve a query to a list of entries. - iterator_type resolve(implementation_type& impl, const query_type& query, - asio::error_code& ec) - { - return service_impl_.resolve(impl, query, ec); - } - - /// Asynchronously resolve a query to a list of entries. - template - void async_resolve(implementation_type& impl, const query_type& query, - Handler handler) - { - service_impl_.async_resolve(impl, query, handler); - } - - /// Resolve an endpoint to a list of entries. - iterator_type resolve(implementation_type& impl, - const endpoint_type& endpoint, asio::error_code& ec) - { - return service_impl_.resolve(impl, endpoint, ec); - } - - /// Asynchronously resolve an endpoint to a list of entries. - template - void async_resolve(implementation_type& impl, const endpoint_type& endpoint, - ResolveHandler handler) - { - return service_impl_.async_resolve(impl, endpoint, handler); - } - -private: - // The service that provides the platform-specific implementation. - service_impl_type& service_impl_; -}; - -} // namespace ip -} // namespace asio - -#include "asio/detail/pop_options.hpp" - -#endif // ASIO_IP_RESOLVER_SERVICE_HPP diff --git a/libtorrent/include/asio/ip/tcp.hpp b/libtorrent/include/asio/ip/tcp.hpp deleted file mode 100644 index 2dd229298..000000000 --- a/libtorrent/include/asio/ip/tcp.hpp +++ /dev/null @@ -1,158 +0,0 @@ -// -// tcp.hpp -// ~~~~~~~ -// -// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -#ifndef ASIO_IP_TCP_HPP -#define ASIO_IP_TCP_HPP - -#if defined(_MSC_VER) && (_MSC_VER >= 1200) -# pragma once -#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) - -#include "asio/detail/push_options.hpp" - -#include "asio/basic_socket_acceptor.hpp" -#include "asio/basic_socket_iostream.hpp" -#include "asio/basic_stream_socket.hpp" -#include "asio/ip/basic_endpoint.hpp" -#include "asio/ip/basic_resolver.hpp" -#include "asio/ip/basic_resolver_iterator.hpp" -#include "asio/ip/basic_resolver_query.hpp" -#include "asio/detail/socket_option.hpp" -#include "asio/detail/socket_types.hpp" - -namespace asio { -namespace ip { - -/// Encapsulates the flags needed for TCP. -/** - * The asio::ip::tcp class contains flags necessary for TCP sockets. - * - * @par Thread Safety - * @e Distinct @e objects: Safe.@n - * @e Shared @e objects: Safe. - * - * @par Concepts: - * Protocol, InternetProtocol. - */ -class tcp -{ -public: - /// The type of a TCP endpoint. - typedef basic_endpoint endpoint; - - /// The type of a resolver query. - typedef basic_resolver_query resolver_query; - - /// The type of a resolver iterator. - typedef basic_resolver_iterator resolver_iterator; - - /// Construct to represent the IPv4 TCP protocol. - static tcp v4() - { - return tcp(PF_INET); - } - - /// Construct to represent the IPv6 TCP protocol. - static tcp v6() - { - return tcp(PF_INET6); - } - - /// Obtain an identifier for the type of the protocol. - int type() const - { - return SOCK_STREAM; - } - - /// Obtain an identifier for the protocol. - int protocol() const - { - return IPPROTO_TCP; - } - - /// Obtain an identifier for the protocol family. - int family() const - { - return family_; - } - - /// The TCP socket type. - typedef basic_stream_socket socket; - - /// The TCP acceptor type. - typedef basic_socket_acceptor acceptor; - - /// The TCP resolver type. - typedef basic_resolver resolver; - - /// The TCP iostream type. - typedef basic_socket_iostream iostream; - - /// Socket option for disabling the Nagle algorithm. - /** - * Implements the IPPROTO_TCP/TCP_NODELAY socket option. - * - * @par Examples - * Setting the option: - * @code - * asio::ip::tcp::socket socket(io_service); - * ... - * asio::ip::tcp::no_delay option(true); - * socket.set_option(option); - * @endcode - * - * @par - * Getting the current option value: - * @code - * asio::ip::tcp::socket socket(io_service); - * ... - * asio::ip::tcp::no_delay option; - * socket.get_option(option); - * bool is_set = option.value(); - * @endcode - * - * @par Concepts: - * Socket_Option, Boolean_Socket_Option. - */ -#if defined(GENERATING_DOCUMENTATION) - typedef implementation_defined no_delay; -#else - typedef asio::detail::socket_option::boolean< - IPPROTO_TCP, TCP_NODELAY> no_delay; -#endif - - /// Compare two protocols for equality. - friend bool operator==(const tcp& p1, const tcp& p2) - { - return p1.family_ == p2.family_; - } - - /// Compare two protocols for inequality. - friend bool operator!=(const tcp& p1, const tcp& p2) - { - return p1.family_ != p2.family_; - } - -private: - // Construct with a specific family. - explicit tcp(int family) - : family_(family) - { - } - - int family_; -}; - -} // namespace ip -} // namespace asio - -#include "asio/detail/pop_options.hpp" - -#endif // ASIO_IP_TCP_HPP diff --git a/libtorrent/include/asio/ip/udp.hpp b/libtorrent/include/asio/ip/udp.hpp deleted file mode 100644 index 47d6e41b1..000000000 --- a/libtorrent/include/asio/ip/udp.hpp +++ /dev/null @@ -1,116 +0,0 @@ -// -// udp.hpp -// ~~~~~~~ -// -// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -#ifndef ASIO_IP_UDP_HPP -#define ASIO_IP_UDP_HPP - -#if defined(_MSC_VER) && (_MSC_VER >= 1200) -# pragma once -#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) - -#include "asio/detail/push_options.hpp" - -#include "asio/basic_datagram_socket.hpp" -#include "asio/ip/basic_endpoint.hpp" -#include "asio/ip/basic_resolver.hpp" -#include "asio/ip/basic_resolver_iterator.hpp" -#include "asio/ip/basic_resolver_query.hpp" -#include "asio/detail/socket_types.hpp" - -namespace asio { -namespace ip { - -/// Encapsulates the flags needed for UDP. -/** - * The asio::ip::udp class contains flags necessary for UDP sockets. - * - * @par Thread Safety - * @e Distinct @e objects: Safe.@n - * @e Shared @e objects: Safe. - * - * @par Concepts: - * Protocol, InternetProtocol. - */ -class udp -{ -public: - /// The type of a UDP endpoint. - typedef basic_endpoint endpoint; - - /// The type of a resolver query. - typedef basic_resolver_query resolver_query; - - /// The type of a resolver iterator. - typedef basic_resolver_iterator resolver_iterator; - - /// Construct to represent the IPv4 UDP protocol. - static udp v4() - { - return udp(PF_INET); - } - - /// Construct to represent the IPv6 UDP protocol. - static udp v6() - { - return udp(PF_INET6); - } - - /// Obtain an identifier for the type of the protocol. - int type() const - { - return SOCK_DGRAM; - } - - /// Obtain an identifier for the protocol. - int protocol() const - { - return IPPROTO_UDP; - } - - /// Obtain an identifier for the protocol family. - int family() const - { - return family_; - } - - /// The UDP socket type. - typedef basic_datagram_socket socket; - - /// The UDP resolver type. - typedef basic_resolver resolver; - - /// Compare two protocols for equality. - friend bool operator==(const udp& p1, const udp& p2) - { - return p1.family_ == p2.family_; - } - - /// Compare two protocols for inequality. - friend bool operator!=(const udp& p1, const udp& p2) - { - return p1.family_ != p2.family_; - } - -private: - // Construct with a specific family. - explicit udp(int family) - : family_(family) - { - } - - int family_; -}; - -} // namespace ip -} // namespace asio - -#include "asio/detail/pop_options.hpp" - -#endif // ASIO_IP_UDP_HPP diff --git a/libtorrent/include/asio/ip/unicast.hpp b/libtorrent/include/asio/ip/unicast.hpp deleted file mode 100644 index dd0707d18..000000000 --- a/libtorrent/include/asio/ip/unicast.hpp +++ /dev/null @@ -1,70 +0,0 @@ -// -// unicast.hpp -// ~~~~~~~~~~~ -// -// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -#ifndef ASIO_IP_UNICAST_HPP -#define ASIO_IP_UNICAST_HPP - -#if defined(_MSC_VER) && (_MSC_VER >= 1200) -# pragma once -#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) - -#include "asio/detail/push_options.hpp" - -#include "asio/detail/push_options.hpp" -#include -#include -#include "asio/detail/pop_options.hpp" - -#include "asio/ip/detail/socket_option.hpp" - -namespace asio { -namespace ip { -namespace unicast { - -/// Socket option for time-to-live associated with outgoing unicast packets. -/** - * Implements the IPPROTO_IP/IP_UNICAST_TTL socket option. - * - * @par Examples - * Setting the option: - * @code - * asio::ip::udp::socket socket(io_service); - * ... - * asio::ip::unicast::hops option(4); - * socket.set_option(option); - * @endcode - * - * @par - * Getting the current option value: - * @code - * asio::ip::udp::socket socket(io_service); - * ... - * asio::ip::unicast::hops option; - * socket.get_option(option); - * int ttl = option.value(); - * @endcode - * - * @par Concepts: - * GettableSocketOption, SettableSocketOption. - */ -#if defined(GENERATING_DOCUMENTATION) -typedef implementation_defined hops; -#else -typedef asio::ip::detail::socket_option::unicast_hops< - IPPROTO_IP, IP_TTL, IPPROTO_IPV6, IPV6_UNICAST_HOPS> hops; -#endif - -} // namespace unicast -} // namespace ip -} // namespace asio - -#include "asio/detail/pop_options.hpp" - -#endif // ASIO_IP_UNICAST_HPP diff --git a/libtorrent/include/asio/ip/v6_only.hpp b/libtorrent/include/asio/ip/v6_only.hpp deleted file mode 100644 index d730fc77c..000000000 --- a/libtorrent/include/asio/ip/v6_only.hpp +++ /dev/null @@ -1,68 +0,0 @@ -// -// v6_only.hpp -// ~~~~~~~~~~~ -// -// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -#ifndef ASIO_IP_V6_ONLY_HPP -#define ASIO_IP_V6_ONLY_HPP - -#if defined(_MSC_VER) && (_MSC_VER >= 1200) -# pragma once -#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) - -#include "asio/detail/push_options.hpp" - -#include "asio/detail/socket_option.hpp" - -namespace asio { -namespace ip { - -/// Socket option for determining whether an IPv6 socket supports IPv6 -/// communication only. -/** - * Implements the IPPROTO_IPV6/IP_V6ONLY socket option. - * - * @par Examples - * Setting the option: - * @code - * asio::ip::tcp::socket socket(io_service); - * ... - * asio::ip::v6_only option(true); - * socket.set_option(option); - * @endcode - * - * @par - * Getting the current option value: - * @code - * asio::ip::tcp::socket socket(io_service); - * ... - * asio::ip::v6_only option; - * socket.get_option(option); - * bool v6_only = option.value(); - * @endcode - * - * @par Concepts: - * GettableSocketOption, SettableSocketOption. - */ -#if defined(GENERATING_DOCUMENTATION) -typedef implementation_defined v6_only; -#elif defined(IPV6_V6ONLY) -typedef asio::detail::socket_option::boolean< - IPPROTO_IPV6, IPV6_V6ONLY> v6_only; -#else -typedef asio::detail::socket_option::boolean< - asio::detail::custom_socket_option_level, - asio::detail::always_fail_option> v6_only; -#endif - -} // namespace ip -} // namespace asio - -#include "asio/detail/pop_options.hpp" - -#endif // ASIO_IP_V6_ONLY_HPP diff --git a/libtorrent/include/asio/is_read_buffered.hpp b/libtorrent/include/asio/is_read_buffered.hpp deleted file mode 100644 index 53b8f34d1..000000000 --- a/libtorrent/include/asio/is_read_buffered.hpp +++ /dev/null @@ -1,62 +0,0 @@ -// -// is_read_buffered.hpp -// ~~~~~~~~~~~~~~~~~~~~ -// -// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -#ifndef ASIO_IS_READ_BUFFERED_HPP -#define ASIO_IS_READ_BUFFERED_HPP - -#if defined(_MSC_VER) && (_MSC_VER >= 1200) -# pragma once -#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) - -#include "asio/detail/push_options.hpp" - -#include "asio/detail/push_options.hpp" -#include -#include "asio/detail/pop_options.hpp" - -#include "asio/buffered_read_stream_fwd.hpp" -#include "asio/buffered_stream_fwd.hpp" - -namespace asio { - -namespace detail { - -template -char is_read_buffered_helper(buffered_stream* s); - -template -char is_read_buffered_helper(buffered_read_stream* s); - -struct is_read_buffered_big_type { char data[10]; }; -is_read_buffered_big_type is_read_buffered_helper(...); - -} // namespace detail - -/// The is_read_buffered class is a traits class that may be used to determine -/// whether a stream type supports buffering of read data. -template -class is_read_buffered -{ -public: -#if defined(GENERATING_DOCUMENTATION) - /// The value member is true only if the Stream type supports buffering of - /// read data. - static const bool value; -#else - BOOST_STATIC_CONSTANT(bool, - value = sizeof(detail::is_read_buffered_helper((Stream*)0)) == 1); -#endif -}; - -} // namespace asio - -#include "asio/detail/pop_options.hpp" - -#endif // ASIO_IS_READ_BUFFERED_HPP diff --git a/libtorrent/include/asio/is_write_buffered.hpp b/libtorrent/include/asio/is_write_buffered.hpp deleted file mode 100644 index 423155415..000000000 --- a/libtorrent/include/asio/is_write_buffered.hpp +++ /dev/null @@ -1,62 +0,0 @@ -// -// is_write_buffered.hpp -// ~~~~~~~~~~~~~~~~~~~~~ -// -// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -#ifndef ASIO_IS_WRITE_BUFFERED_HPP -#define ASIO_IS_WRITE_BUFFERED_HPP - -#if defined(_MSC_VER) && (_MSC_VER >= 1200) -# pragma once -#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) - -#include "asio/detail/push_options.hpp" - -#include "asio/detail/push_options.hpp" -#include -#include "asio/detail/pop_options.hpp" - -#include "asio/buffered_stream_fwd.hpp" -#include "asio/buffered_write_stream_fwd.hpp" - -namespace asio { - -namespace detail { - -template -char is_write_buffered_helper(buffered_stream* s); - -template -char is_write_buffered_helper(buffered_write_stream* s); - -struct is_write_buffered_big_type { char data[10]; }; -is_write_buffered_big_type is_write_buffered_helper(...); - -} // namespace detail - -/// The is_write_buffered class is a traits class that may be used to determine -/// whether a stream type supports buffering of written data. -template -class is_write_buffered -{ -public: -#if defined(GENERATING_DOCUMENTATION) - /// The value member is true only if the Stream type supports buffering of - /// written data. - static const bool value; -#else - BOOST_STATIC_CONSTANT(bool, - value = sizeof(detail::is_write_buffered_helper((Stream*)0)) == 1); -#endif -}; - -} // namespace asio - -#include "asio/detail/pop_options.hpp" - -#endif // ASIO_IS_WRITE_BUFFERED_HPP diff --git a/libtorrent/include/asio/local/basic_endpoint.hpp b/libtorrent/include/asio/local/basic_endpoint.hpp deleted file mode 100644 index 75dd092e3..000000000 --- a/libtorrent/include/asio/local/basic_endpoint.hpp +++ /dev/null @@ -1,265 +0,0 @@ -// -// basic_endpoint.hpp -// ~~~~~~~~~~~~~~~~~~ -// -// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// Derived from a public domain implementation written by Daniel Casimiro. -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -#ifndef ASIO_LOCAL_BASIC_ENDPOINT_HPP -#define ASIO_LOCAL_BASIC_ENDPOINT_HPP - -#if defined(_MSC_VER) && (_MSC_VER >= 1200) -# pragma once -#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) - -#include "asio/detail/push_options.hpp" - -#include "asio/detail/push_options.hpp" -#include -#include -#include -#include -#include "asio/detail/pop_options.hpp" - -#include "asio/error.hpp" -#include "asio/system_error.hpp" -#include "asio/detail/socket_ops.hpp" -#include "asio/detail/socket_types.hpp" -#include "asio/detail/throw_error.hpp" - -#if !defined(ASIO_DISABLE_LOCAL_SOCKETS) -# if !defined(BOOST_WINDOWS) && !defined(__CYGWIN__) -# define ASIO_HAS_LOCAL_SOCKETS 1 -# endif // !defined(BOOST_WINDOWS) && !defined(__CYGWIN__) -#endif // !defined(ASIO_DISABLE_LOCAL_SOCKETS) - -#if defined(ASIO_HAS_LOCAL_SOCKETS) \ - || defined(GENERATING_DOCUMENTATION) - - -namespace asio { -namespace local { - -/// Describes an endpoint for a UNIX socket. -/** - * The asio::local::basic_endpoint class template describes an endpoint - * that may be associated with a particular UNIX socket. - * - * @par Thread Safety - * @e Distinct @e objects: Safe.@n - * @e Shared @e objects: Unsafe. - * - * @par Concepts: - * Endpoint. - */ -template -class basic_endpoint -{ -public: - /// The protocol type associated with the endpoint. - typedef Protocol protocol_type; - - /// The type of the endpoint structure. This type is dependent on the - /// underlying implementation of the socket layer. -#if defined(GENERATING_DOCUMENTATION) - typedef implementation_defined data_type; -#else - typedef asio::detail::socket_addr_type data_type; -#endif - - /// Default constructor. - basic_endpoint() - { - init("", 0); - } - - /// Construct an endpoint using the specified path name. - basic_endpoint(const char* path) - { - using namespace std; // For strlen. - init(path, strlen(path)); - } - - /// Construct an endpoint using the specified path name. - basic_endpoint(const std::string& path) - { - init(path.data(), path.length()); - } - - /// Copy constructor. - basic_endpoint(const basic_endpoint& other) - : data_(other.data_), - path_length_(other.path_length_) - { - } - - /// Assign from another endpoint. - basic_endpoint& operator=(const basic_endpoint& other) - { - data_ = other.data_; - path_length_ = other.path_length_; - return *this; - } - - /// The protocol associated with the endpoint. - protocol_type protocol() const - { - return protocol_type(); - } - - /// Get the underlying endpoint in the native type. - data_type* data() - { - return &data_.base; - } - - /// Get the underlying endpoint in the native type. - const data_type* data() const - { - return &data_.base; - } - - /// Get the underlying size of the endpoint in the native type. - std::size_t size() const - { - return path_length_ - + offsetof(asio::detail::sockaddr_un_type, sun_path); - } - - /// Set the underlying size of the endpoint in the native type. - void resize(std::size_t size) - { - if (size > sizeof(asio::detail::sockaddr_un_type)) - { - asio::system_error e(asio::error::invalid_argument); - boost::throw_exception(e); - } - else if (size == 0) - { - path_length_ = 0; - } - else - { - path_length_ = size - - offsetof(asio::detail::sockaddr_un_type, sun_path); - - // The path returned by the operating system may be NUL-terminated. - if (path_length_ > 0 && data_.local.sun_path[path_length_] == 0) - --path_length_; - } - } - - /// Get the capacity of the endpoint in the native type. - std::size_t capacity() const - { - return sizeof(asio::detail::sockaddr_un_type); - } - - /// Get the path associated with the endpoint. - std::string path() const - { - return std::string(data_.local.sun_path, path_length_); - } - - /// Set the path associated with the endpoint. - void path(const char* p) - { - using namespace std; // For strlen. - init(p, strlen(p)); - } - - /// Set the path associated with the endpoint. - void path(const std::string& p) - { - init(p.data(), p.length()); - } - - /// Compare two endpoints for equality. - friend bool operator==(const basic_endpoint& e1, - const basic_endpoint& e2) - { - return e1.path() == e2.path(); - } - - /// Compare two endpoints for inequality. - friend bool operator!=(const basic_endpoint& e1, - const basic_endpoint& e2) - { - return e1.path() != e2.path(); - } - - /// Compare endpoints for ordering. - friend bool operator<(const basic_endpoint& e1, - const basic_endpoint& e2) - { - return e1.path() < e2.path(); - } - -private: - // The underlying UNIX socket address. - union data_union - { - asio::detail::socket_addr_type base; - asio::detail::sockaddr_un_type local; - } data_; - - // The length of the path associated with the endpoint. - std::size_t path_length_; - - // Initialise with a specified path. - void init(const char* path, std::size_t path_length) - { - if (path_length > sizeof(data_.local.sun_path) - 1) - { - // The buffer is not large enough to store this address. - asio::error_code ec(asio::error::name_too_long); - asio::detail::throw_error(ec); - } - - using namespace std; // For memcpy. - data_.local = asio::detail::sockaddr_un_type(); - data_.local.sun_family = AF_UNIX; - memcpy(data_.local.sun_path, path, path_length); - path_length_ = path_length; - - // NUL-terminate normal path names. Names that start with a NUL are in the - // UNIX domain protocol's "abstract namespace" and are not NUL-terminated. - if (path_length > 0 && data_.local.sun_path[0] == 0) - data_.local.sun_path[path_length] = 0; - } -}; - -/// Output an endpoint as a string. -/** - * Used to output a human-readable string for a specified endpoint. - * - * @param os The output stream to which the string will be written. - * - * @param endpoint The endpoint to be written. - * - * @return The output stream. - * - * @relates asio::local::basic_endpoint - */ -template -std::basic_ostream& operator<<( - std::basic_ostream& os, - const basic_endpoint& endpoint) -{ - os << endpoint.path(); - return os; -} - -} // namespace local -} // namespace asio - -#endif // defined(ASIO_HAS_LOCAL_SOCKETS) - // || defined(GENERATING_DOCUMENTATION) - -#include "asio/detail/pop_options.hpp" - -#endif // ASIO_LOCAL_BASIC_ENDPOINT_HPP diff --git a/libtorrent/include/asio/local/connect_pair.hpp b/libtorrent/include/asio/local/connect_pair.hpp deleted file mode 100644 index e4f73f91b..000000000 --- a/libtorrent/include/asio/local/connect_pair.hpp +++ /dev/null @@ -1,100 +0,0 @@ -// -// connect_pair.hpp -// ~~~~~~~~~~~~~~~~ -// -// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -#ifndef ASIO_LOCAL_CONNECT_PAIR_HPP -#define ASIO_LOCAL_CONNECT_PAIR_HPP - -#if defined(_MSC_VER) && (_MSC_VER >= 1200) -# pragma once -#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) - -#include "asio/detail/push_options.hpp" - -#include "asio/basic_socket.hpp" -#include "asio/error.hpp" -#include "asio/local/basic_endpoint.hpp" -#include "asio/detail/socket_ops.hpp" -#include "asio/detail/throw_error.hpp" - -#if defined(ASIO_HAS_LOCAL_SOCKETS) \ - || defined(GENERATING_DOCUMENTATION) - -namespace asio { -namespace local { - -/// Create a pair of connected sockets. -template -void connect_pair( - basic_socket& socket1, - basic_socket& socket2); - -/// Create a pair of connected sockets. -template -asio::error_code connect_pair( - basic_socket& socket1, - basic_socket& socket2, - asio::error_code& ec); - -template -inline void connect_pair( - basic_socket& socket1, - basic_socket& socket2) -{ - asio::error_code ec; - connect_pair(socket1, socket2, ec); - asio::detail::throw_error(ec); -} - -template -inline asio::error_code connect_pair( - basic_socket& socket1, - basic_socket& socket2, - asio::error_code& ec) -{ - // Check that this function is only being used with a UNIX domain socket. - asio::local::basic_endpoint* tmp - = static_cast(0); - (void)tmp; - - Protocol protocol; - asio::detail::socket_type sv[2]; - if (asio::detail::socket_ops::socketpair(protocol.family(), - protocol.type(), protocol.protocol(), sv, ec) - == asio::detail::socket_error_retval) - return ec; - - if (socket1.assign(protocol, sv[0], ec)) - { - asio::error_code temp_ec; - asio::detail::socket_ops::close(sv[0], temp_ec); - asio::detail::socket_ops::close(sv[1], temp_ec); - return ec; - } - - if (socket2.assign(protocol, sv[1], ec)) - { - asio::error_code temp_ec; - socket1.close(temp_ec); - asio::detail::socket_ops::close(sv[1], temp_ec); - return ec; - } - - return ec; -} - -} // namespace local -} // namespace asio - -#endif // defined(ASIO_HAS_LOCAL_SOCKETS) - // || defined(GENERATING_DOCUMENTATION) - -#include "asio/detail/pop_options.hpp" - -#endif // ASIO_LOCAL_CONNECT_PAIR_HPP diff --git a/libtorrent/include/asio/local/datagram_protocol.hpp b/libtorrent/include/asio/local/datagram_protocol.hpp deleted file mode 100644 index c7adacfc9..000000000 --- a/libtorrent/include/asio/local/datagram_protocol.hpp +++ /dev/null @@ -1,78 +0,0 @@ -// -// datagram_protocol.hpp -// ~~~~~~~~~~~~~~~~~~~~~ -// -// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -#ifndef ASIO_LOCAL_DATAGRAM_PROTOCOL_HPP -#define ASIO_LOCAL_DATAGRAM_PROTOCOL_HPP - -#if defined(_MSC_VER) && (_MSC_VER >= 1200) -# pragma once -#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) - -#include "asio/detail/push_options.hpp" - -#include "asio/basic_datagram_socket.hpp" -#include "asio/local/basic_endpoint.hpp" -#include "asio/detail/socket_types.hpp" - -#if defined(ASIO_HAS_LOCAL_SOCKETS) \ - || defined(GENERATING_DOCUMENTATION) - -namespace asio { -namespace local { - -/// Encapsulates the flags needed for datagram-oriented UNIX sockets. -/** - * The asio::local::datagram_protocol class contains flags necessary for - * datagram-oriented UNIX domain sockets. - * - * @par Thread Safety - * @e Distinct @e objects: Safe.@n - * @e Shared @e objects: Safe. - * - * @par Concepts: - * Protocol. - */ -class datagram_protocol -{ -public: - /// Obtain an identifier for the type of the protocol. - int type() const - { - return SOCK_DGRAM; - } - - /// Obtain an identifier for the protocol. - int protocol() const - { - return 0; - } - - /// Obtain an identifier for the protocol family. - int family() const - { - return AF_UNIX; - } - - /// The type of a UNIX domain endpoint. - typedef basic_endpoint endpoint; - - /// The UNIX domain socket type. - typedef basic_datagram_socket socket; -}; - -} // namespace local -} // namespace asio - -#endif // defined(ASIO_HAS_LOCAL_SOCKETS) - // || defined(GENERATING_DOCUMENTATION) - -#include "asio/detail/pop_options.hpp" - -#endif // ASIO_LOCAL_DATAGRAM_PROTOCOL_HPP diff --git a/libtorrent/include/asio/local/stream_protocol.hpp b/libtorrent/include/asio/local/stream_protocol.hpp deleted file mode 100644 index 91813e8e0..000000000 --- a/libtorrent/include/asio/local/stream_protocol.hpp +++ /dev/null @@ -1,86 +0,0 @@ -// -// stream_protocol.hpp -// ~~~~~~~~~~~~~~~~~~~ -// -// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -#ifndef ASIO_LOCAL_STREAM_PROTOCOL_HPP -#define ASIO_LOCAL_STREAM_PROTOCOL_HPP - -#if defined(_MSC_VER) && (_MSC_VER >= 1200) -# pragma once -#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) - -#include "asio/detail/push_options.hpp" - -#include "asio/basic_socket_acceptor.hpp" -#include "asio/basic_socket_iostream.hpp" -#include "asio/basic_stream_socket.hpp" -#include "asio/local/basic_endpoint.hpp" -#include "asio/detail/socket_types.hpp" - -#if defined(ASIO_HAS_LOCAL_SOCKETS) \ - || defined(GENERATING_DOCUMENTATION) - -namespace asio { -namespace local { - -/// Encapsulates the flags needed for stream-oriented UNIX sockets. -/** - * The asio::local::stream_protocol class contains flags necessary for - * stream-oriented UNIX domain sockets. - * - * @par Thread Safety - * @e Distinct @e objects: Safe.@n - * @e Shared @e objects: Safe. - * - * @par Concepts: - * Protocol. - */ -class stream_protocol -{ -public: - /// Obtain an identifier for the type of the protocol. - int type() const - { - return SOCK_STREAM; - } - - /// Obtain an identifier for the protocol. - int protocol() const - { - return 0; - } - - /// Obtain an identifier for the protocol family. - int family() const - { - return AF_UNIX; - } - - /// The type of a UNIX domain endpoint. - typedef basic_endpoint endpoint; - - /// The UNIX domain socket type. - typedef basic_stream_socket socket; - - /// The UNIX domain acceptor type. - typedef basic_socket_acceptor acceptor; - - /// The UNIX domain iostream type. - typedef basic_socket_iostream iostream; -}; - -} // namespace local -} // namespace asio - -#endif // defined(ASIO_HAS_LOCAL_SOCKETS) - // || defined(GENERATING_DOCUMENTATION) - -#include "asio/detail/pop_options.hpp" - -#endif // ASIO_LOCAL_STREAM_PROTOCOL_HPP diff --git a/libtorrent/include/asio/placeholders.hpp b/libtorrent/include/asio/placeholders.hpp deleted file mode 100644 index bf93c7df1..000000000 --- a/libtorrent/include/asio/placeholders.hpp +++ /dev/null @@ -1,107 +0,0 @@ -// -// placeholders.hpp -// ~~~~~~~~~~~~~~~~ -// -// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -#ifndef ASIO_PLACEHOLDERS_HPP -#define ASIO_PLACEHOLDERS_HPP - -#if defined(_MSC_VER) && (_MSC_VER >= 1200) -# pragma once -#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) - -#include "asio/detail/push_options.hpp" - -#include "asio/detail/push_options.hpp" -#include -#include -#include "asio/detail/pop_options.hpp" - -namespace asio { -namespace placeholders { - -#if defined(GENERATING_DOCUMENTATION) - -/// An argument placeholder, for use with boost::bind(), that corresponds to -/// the error argument of a handler for any of the asynchronous functions. -unspecified error; - -/// An argument placeholder, for use with boost::bind(), that corresponds to -/// the bytes_transferred argument of a handler for asynchronous functions such -/// as asio::basic_stream_socket::async_write_some or -/// asio::async_write. -unspecified bytes_transferred; - -/// An argument placeholder, for use with boost::bind(), that corresponds to -/// the iterator argument of a handler for asynchronous functions such as -/// asio::basic_resolver::resolve. -unspecified iterator; - -#elif defined(__BORLANDC__) || defined(__GNUC__) - -inline boost::arg<1> error() -{ - return boost::arg<1>(); -} - -inline boost::arg<2> bytes_transferred() -{ - return boost::arg<2>(); -} - -inline boost::arg<2> iterator() -{ - return boost::arg<2>(); -} - -#else - -namespace detail -{ - template - struct placeholder - { - static boost::arg& get() - { - static boost::arg result; - return result; - } - }; -} - -#if BOOST_WORKAROUND(BOOST_MSVC, < 1400) - -static boost::arg<1>& error - = asio::placeholders::detail::placeholder<1>::get(); -static boost::arg<2>& bytes_transferred - = asio::placeholders::detail::placeholder<2>::get(); -static boost::arg<2>& iterator - = asio::placeholders::detail::placeholder<2>::get(); - -#else - -namespace -{ - boost::arg<1>& error - = asio::placeholders::detail::placeholder<1>::get(); - boost::arg<2>& bytes_transferred - = asio::placeholders::detail::placeholder<2>::get(); - boost::arg<2>& iterator - = asio::placeholders::detail::placeholder<2>::get(); -} // namespace - -#endif - -#endif - -} // namespace placeholders -} // namespace asio - -#include "asio/detail/pop_options.hpp" - -#endif // ASIO_PLACEHOLDERS_HPP diff --git a/libtorrent/include/asio/posix/basic_descriptor.hpp b/libtorrent/include/asio/posix/basic_descriptor.hpp deleted file mode 100644 index 241a3e315..000000000 --- a/libtorrent/include/asio/posix/basic_descriptor.hpp +++ /dev/null @@ -1,280 +0,0 @@ -// -// basic_descriptor.hpp -// ~~~~~~~~~~~~~~~~~~~~ -// -// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -#ifndef ASIO_POSIX_BASIC_DESCRIPTOR_HPP -#define ASIO_POSIX_BASIC_DESCRIPTOR_HPP - -#if defined(_MSC_VER) && (_MSC_VER >= 1200) -# pragma once -#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) - -#include "asio/detail/push_options.hpp" - -#include "asio/detail/push_options.hpp" -#include -#include "asio/detail/pop_options.hpp" - -#include "asio/basic_io_object.hpp" -#include "asio/error.hpp" -#include "asio/posix/descriptor_base.hpp" -#include "asio/detail/throw_error.hpp" - -namespace asio { -namespace posix { - -/// Provides POSIX descriptor functionality. -/** - * The posix::basic_descriptor class template provides the ability to wrap a - * POSIX descriptor. - * - * @par Thread Safety - * @e Distinct @e objects: Safe.@n - * @e Shared @e objects: Unsafe. - */ -template -class basic_descriptor - : public basic_io_object, - public descriptor_base -{ -public: - /// The native representation of a descriptor. - typedef typename DescriptorService::native_type native_type; - - /// A basic_descriptor is always the lowest layer. - typedef basic_descriptor lowest_layer_type; - - /// Construct a basic_descriptor without opening it. - /** - * This constructor creates a descriptor without opening it. - * - * @param io_service The io_service object that the descriptor will use to - * dispatch handlers for any asynchronous operations performed on the - * descriptor. - */ - explicit basic_descriptor(asio::io_service& io_service) - : basic_io_object(io_service) - { - } - - /// Construct a basic_descriptor on an existing native descriptor. - /** - * This constructor creates a descriptor object to hold an existing native - * descriptor. - * - * @param io_service The io_service object that the descriptor will use to - * dispatch handlers for any asynchronous operations performed on the - * descriptor. - * - * @param native_descriptor A native descriptor. - * - * @throws asio::system_error Thrown on failure. - */ - basic_descriptor(asio::io_service& io_service, - const native_type& native_descriptor) - : basic_io_object(io_service) - { - asio::error_code ec; - this->service.assign(this->implementation, native_descriptor, ec); - asio::detail::throw_error(ec); - } - - /// Get a reference to the lowest layer. - /** - * This function returns a reference to the lowest layer in a stack of - * layers. Since a basic_descriptor cannot contain any further layers, it - * simply returns a reference to itself. - * - * @return A reference to the lowest layer in the stack of layers. Ownership - * is not transferred to the caller. - */ - lowest_layer_type& lowest_layer() - { - return *this; - } - - /// Assign an existing native descriptor to the descriptor. - /* - * This function opens the descriptor to hold an existing native descriptor. - * - * @param native_descriptor A native descriptor. - * - * @throws asio::system_error Thrown on failure. - */ - void assign(const native_type& native_descriptor) - { - asio::error_code ec; - this->service.assign(this->implementation, native_descriptor, ec); - asio::detail::throw_error(ec); - } - - /// Assign an existing native descriptor to the descriptor. - /* - * This function opens the descriptor to hold an existing native descriptor. - * - * @param native_descriptor A native descriptor. - * - * @param ec Set to indicate what error occurred, if any. - */ - asio::error_code assign(const native_type& native_descriptor, - asio::error_code& ec) - { - return this->service.assign(this->implementation, native_descriptor, ec); - } - - /// Determine whether the descriptor is open. - bool is_open() const - { - return this->service.is_open(this->implementation); - } - - /// Close the descriptor. - /** - * This function is used to close the descriptor. Any asynchronous read or - * write operations will be cancelled immediately, and will complete with the - * asio::error::operation_aborted error. - * - * @throws asio::system_error Thrown on failure. - */ - void close() - { - asio::error_code ec; - this->service.close(this->implementation, ec); - asio::detail::throw_error(ec); - } - - /// Close the descriptor. - /** - * This function is used to close the descriptor. Any asynchronous read or - * write operations will be cancelled immediately, and will complete with the - * asio::error::operation_aborted error. - * - * @param ec Set to indicate what error occurred, if any. - */ - asio::error_code close(asio::error_code& ec) - { - return this->service.close(this->implementation, ec); - } - - /// Get the native descriptor representation. - /** - * This function may be used to obtain the underlying representation of the - * descriptor. This is intended to allow access to native descriptor - * functionality that is not otherwise provided. - */ - native_type native() - { - return this->service.native(this->implementation); - } - - /// Cancel all asynchronous operations associated with the descriptor. - /** - * This function causes all outstanding asynchronous read or write operations - * to finish immediately, and the handlers for cancelled operations will be - * passed the asio::error::operation_aborted error. - * - * @throws asio::system_error Thrown on failure. - */ - void cancel() - { - asio::error_code ec; - this->service.cancel(this->implementation, ec); - asio::detail::throw_error(ec); - } - - /// Cancel all asynchronous operations associated with the descriptor. - /** - * This function causes all outstanding asynchronous read or write operations - * to finish immediately, and the handlers for cancelled operations will be - * passed the asio::error::operation_aborted error. - * - * @param ec Set to indicate what error occurred, if any. - */ - asio::error_code cancel(asio::error_code& ec) - { - return this->service.cancel(this->implementation, ec); - } - - /// Perform an IO control command on the descriptor. - /** - * This function is used to execute an IO control command on the descriptor. - * - * @param command The IO control command to be performed on the descriptor. - * - * @throws asio::system_error Thrown on failure. - * - * @sa IoControlCommand @n - * asio::posix::descriptor_base::bytes_readable @n - * asio::posix::descriptor_base::non_blocking_io - * - * @par Example - * Getting the number of bytes ready to read: - * @code - * asio::posix::stream_descriptor descriptor(io_service); - * ... - * asio::posix::stream_descriptor::bytes_readable command; - * descriptor.io_control(command); - * std::size_t bytes_readable = command.get(); - * @endcode - */ - template - void io_control(IoControlCommand& command) - { - asio::error_code ec; - this->service.io_control(this->implementation, command, ec); - asio::detail::throw_error(ec); - } - - /// Perform an IO control command on the descriptor. - /** - * This function is used to execute an IO control command on the descriptor. - * - * @param command The IO control command to be performed on the descriptor. - * - * @param ec Set to indicate what error occurred, if any. - * - * @sa IoControlCommand @n - * asio::posix::descriptor_base::bytes_readable @n - * asio::posix::descriptor_base::non_blocking_io - * - * @par Example - * Getting the number of bytes ready to read: - * @code - * asio::posix::stream_descriptor descriptor(io_service); - * ... - * asio::posix::stream_descriptor::bytes_readable command; - * asio::error_code ec; - * descriptor.io_control(command, ec); - * if (ec) - * { - * // An error occurred. - * } - * std::size_t bytes_readable = command.get(); - * @endcode - */ - template - asio::error_code io_control(IoControlCommand& command, - asio::error_code& ec) - { - return this->service.io_control(this->implementation, command, ec); - } - -protected: - /// Protected destructor to prevent deletion through this type. - ~basic_descriptor() - { - } -}; - -} // namespace posix -} // namespace asio - -#include "asio/detail/pop_options.hpp" - -#endif // ASIO_POSIX_BASIC_DESCRIPTOR_HPP diff --git a/libtorrent/include/asio/posix/basic_stream_descriptor.hpp b/libtorrent/include/asio/posix/basic_stream_descriptor.hpp deleted file mode 100644 index 62185eaa0..000000000 --- a/libtorrent/include/asio/posix/basic_stream_descriptor.hpp +++ /dev/null @@ -1,304 +0,0 @@ -// -// basic_stream_descriptor.hpp -// ~~~~~~~~~~~~~~~~~~~~~~~~~~~ -// -// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -#ifndef ASIO_POSIX_BASIC_STREAM_DESCRIPTOR_HPP -#define ASIO_POSIX_BASIC_STREAM_DESCRIPTOR_HPP - -#if defined(_MSC_VER) && (_MSC_VER >= 1200) -# pragma once -#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) - -#include "asio/detail/push_options.hpp" - -#include "asio/detail/push_options.hpp" -#include -#include -#include "asio/detail/pop_options.hpp" - -#include "asio/error.hpp" -#include "asio/posix/basic_descriptor.hpp" -#include "asio/posix/stream_descriptor_service.hpp" -#include "asio/detail/throw_error.hpp" - -#if defined(ASIO_HAS_POSIX_STREAM_DESCRIPTOR) \ - || defined(GENERATING_DOCUMENTATION) - -namespace asio { -namespace posix { - -/// Provides stream-oriented descriptor functionality. -/** - * The posix::basic_stream_descriptor class template provides asynchronous and - * blocking stream-oriented descriptor functionality. - * - * @par Thread Safety - * @e Distinct @e objects: Safe.@n - * @e Shared @e objects: Unsafe. - * - * @par Concepts: - * AsyncReadStream, AsyncWriteStream, Stream, SyncReadStream, SyncWriteStream. - */ -template -class basic_stream_descriptor - : public basic_descriptor -{ -public: - /// The native representation of a descriptor. - typedef typename StreamDescriptorService::native_type native_type; - - /// Construct a basic_stream_descriptor without opening it. - /** - * This constructor creates a stream descriptor without opening it. The - * descriptor needs to be opened and then connected or accepted before data - * can be sent or received on it. - * - * @param io_service The io_service object that the stream descriptor will - * use to dispatch handlers for any asynchronous operations performed on the - * descriptor. - */ - explicit basic_stream_descriptor(asio::io_service& io_service) - : basic_descriptor(io_service) - { - } - - /// Construct a basic_stream_descriptor on an existing native descriptor. - /** - * This constructor creates a stream descriptor object to hold an existing - * native descriptor. - * - * @param io_service The io_service object that the stream descriptor will - * use to dispatch handlers for any asynchronous operations performed on the - * descriptor. - * - * @param native_descriptor The new underlying descriptor implementation. - * - * @throws asio::system_error Thrown on failure. - */ - basic_stream_descriptor(asio::io_service& io_service, - const native_type& native_descriptor) - : basic_descriptor(io_service, native_descriptor) - { - } - - /// Write some data to the descriptor. - /** - * This function is used to write data to the stream descriptor. The function - * call will block until one or more bytes of the data has been written - * successfully, or until an error occurs. - * - * @param buffers One or more data buffers to be written to the descriptor. - * - * @returns The number of bytes written. - * - * @throws asio::system_error Thrown on failure. An error code of - * asio::error::eof indicates that the connection was closed by the - * peer. - * - * @note The write_some operation may not transmit all of the data to the - * peer. Consider using the @ref write function if you need to ensure that - * all data is written before the blocking operation completes. - * - * @par Example - * To write a single data buffer use the @ref buffer function as follows: - * @code - * descriptor.write_some(asio::buffer(data, size)); - * @endcode - * See the @ref buffer documentation for information on writing multiple - * buffers in one go, and how to use it with arrays, boost::array or - * std::vector. - */ - template - std::size_t write_some(const ConstBufferSequence& buffers) - { - asio::error_code ec; - std::size_t s = this->service.write_some(this->implementation, buffers, ec); - asio::detail::throw_error(ec); - return s; - } - - /// Write some data to the descriptor. - /** - * This function is used to write data to the stream descriptor. The function - * call will block until one or more bytes of the data has been written - * successfully, or until an error occurs. - * - * @param buffers One or more data buffers to be written to the descriptor. - * - * @param ec Set to indicate what error occurred, if any. - * - * @returns The number of bytes written. Returns 0 if an error occurred. - * - * @note The write_some operation may not transmit all of the data to the - * peer. Consider using the @ref write function if you need to ensure that - * all data is written before the blocking operation completes. - */ - template - std::size_t write_some(const ConstBufferSequence& buffers, - asio::error_code& ec) - { - return this->service.write_some(this->implementation, buffers, ec); - } - - /// Start an asynchronous write. - /** - * This function is used to asynchronously write data to the stream - * descriptor. The function call always returns immediately. - * - * @param buffers One or more data buffers to be written to the descriptor. - * Although the buffers object may be copied as necessary, ownership of the - * underlying memory blocks is retained by the caller, which must guarantee - * that they remain valid until the handler is called. - * - * @param handler The handler to be called when the write operation completes. - * Copies will be made of the handler as required. The function signature of - * the handler must be: - * @code void handler( - * const asio::error_code& error, // Result of operation. - * std::size_t bytes_transferred // Number of bytes written. - * ); @endcode - * Regardless of whether the asynchronous operation completes immediately or - * not, the handler will not be invoked from within this function. Invocation - * of the handler will be performed in a manner equivalent to using - * asio::io_service::post(). - * - * @note The write operation may not transmit all of the data to the peer. - * Consider using the @ref async_write function if you need to ensure that all - * data is written before the asynchronous operation completes. - * - * @par Example - * To write a single data buffer use the @ref buffer function as follows: - * @code - * descriptor.async_write_some(asio::buffer(data, size), handler); - * @endcode - * See the @ref buffer documentation for information on writing multiple - * buffers in one go, and how to use it with arrays, boost::array or - * std::vector. - */ - template - void async_write_some(const ConstBufferSequence& buffers, - WriteHandler handler) - { - this->service.async_write_some(this->implementation, buffers, handler); - } - - /// Read some data from the descriptor. - /** - * This function is used to read data from the stream descriptor. The function - * call will block until one or more bytes of data has been read successfully, - * or until an error occurs. - * - * @param buffers One or more buffers into which the data will be read. - * - * @returns The number of bytes read. - * - * @throws asio::system_error Thrown on failure. An error code of - * asio::error::eof indicates that the connection was closed by the - * peer. - * - * @note The read_some operation may not read all of the requested number of - * bytes. Consider using the @ref read function if you need to ensure that - * the requested amount of data is read before the blocking operation - * completes. - * - * @par Example - * To read into a single data buffer use the @ref buffer function as follows: - * @code - * descriptor.read_some(asio::buffer(data, size)); - * @endcode - * See the @ref buffer documentation for information on reading into multiple - * buffers in one go, and how to use it with arrays, boost::array or - * std::vector. - */ - template - std::size_t read_some(const MutableBufferSequence& buffers) - { - asio::error_code ec; - std::size_t s = this->service.read_some(this->implementation, buffers, ec); - asio::detail::throw_error(ec); - return s; - } - - /// Read some data from the descriptor. - /** - * This function is used to read data from the stream descriptor. The function - * call will block until one or more bytes of data has been read successfully, - * or until an error occurs. - * - * @param buffers One or more buffers into which the data will be read. - * - * @param ec Set to indicate what error occurred, if any. - * - * @returns The number of bytes read. Returns 0 if an error occurred. - * - * @note The read_some operation may not read all of the requested number of - * bytes. Consider using the @ref read function if you need to ensure that - * the requested amount of data is read before the blocking operation - * completes. - */ - template - std::size_t read_some(const MutableBufferSequence& buffers, - asio::error_code& ec) - { - return this->service.read_some(this->implementation, buffers, ec); - } - - /// Start an asynchronous read. - /** - * This function is used to asynchronously read data from the stream - * descriptor. The function call always returns immediately. - * - * @param buffers One or more buffers into which the data will be read. - * Although the buffers object may be copied as necessary, ownership of the - * underlying memory blocks is retained by the caller, which must guarantee - * that they remain valid until the handler is called. - * - * @param handler The handler to be called when the read operation completes. - * Copies will be made of the handler as required. The function signature of - * the handler must be: - * @code void handler( - * const asio::error_code& error, // Result of operation. - * std::size_t bytes_transferred // Number of bytes read. - * ); @endcode - * Regardless of whether the asynchronous operation completes immediately or - * not, the handler will not be invoked from within this function. Invocation - * of the handler will be performed in a manner equivalent to using - * asio::io_service::post(). - * - * @note The read operation may not read all of the requested number of bytes. - * Consider using the @ref async_read function if you need to ensure that the - * requested amount of data is read before the asynchronous operation - * completes. - * - * @par Example - * To read into a single data buffer use the @ref buffer function as follows: - * @code - * descriptor.async_read_some(asio::buffer(data, size), handler); - * @endcode - * See the @ref buffer documentation for information on reading into multiple - * buffers in one go, and how to use it with arrays, boost::array or - * std::vector. - */ - template - void async_read_some(const MutableBufferSequence& buffers, - ReadHandler handler) - { - this->service.async_read_some(this->implementation, buffers, handler); - } -}; - -} // namespace posix -} // namespace asio - -#endif // defined(ASIO_HAS_POSIX_STREAM_DESCRIPTOR) - // || defined(GENERATING_DOCUMENTATION) - -#include "asio/detail/pop_options.hpp" - -#endif // ASIO_POSIX_BASIC_STREAM_DESCRIPTOR_HPP diff --git a/libtorrent/include/asio/posix/descriptor_base.hpp b/libtorrent/include/asio/posix/descriptor_base.hpp deleted file mode 100644 index 6ea2738df..000000000 --- a/libtorrent/include/asio/posix/descriptor_base.hpp +++ /dev/null @@ -1,93 +0,0 @@ -// -// descriptor_base.hpp -// ~~~~~~~~~~~~~~~~~~~ -// -// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -#ifndef ASIO_POSIX_DESCRIPTOR_BASE_HPP -#define ASIO_POSIX_DESCRIPTOR_BASE_HPP - -#if defined(_MSC_VER) && (_MSC_VER >= 1200) -# pragma once -#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) - -#include "asio/detail/push_options.hpp" - -#include "asio/detail/push_options.hpp" -#include -#include -#include "asio/detail/pop_options.hpp" - -#include "asio/detail/io_control.hpp" -#include "asio/detail/socket_option.hpp" - -namespace asio { -namespace posix { - -/// The descriptor_base class is used as a base for the basic_stream_descriptor -/// class template so that we have a common place to define the associated -/// IO control commands. -class descriptor_base -{ -public: - /// IO control command to set the blocking mode of the descriptor. - /** - * Implements the FIONBIO IO control command. - * - * @par Example - * @code - * asio::posix::stream_descriptor descriptor(io_service); - * ... - * asio::descriptor_base::non_blocking_io command(true); - * descriptor.io_control(command); - * @endcode - * - * @par Concepts: - * IoControlCommand. - */ -#if defined(GENERATING_DOCUMENTATION) - typedef implementation_defined non_blocking_io; -#else - typedef asio::detail::io_control::non_blocking_io non_blocking_io; -#endif - - /// IO control command to get the amount of data that can be read without - /// blocking. - /** - * Implements the FIONREAD IO control command. - * - * @par Example - * @code - * asio::posix::stream_descriptor descriptor(io_service); - * ... - * asio::descriptor_base::bytes_readable command(true); - * descriptor.io_control(command); - * std::size_t bytes_readable = command.get(); - * @endcode - * - * @par Concepts: - * IoControlCommand. - */ -#if defined(GENERATING_DOCUMENTATION) - typedef implementation_defined bytes_readable; -#else - typedef asio::detail::io_control::bytes_readable bytes_readable; -#endif - -protected: - /// Protected destructor to prevent deletion through this type. - ~descriptor_base() - { - } -}; - -} // namespace posix -} // namespace asio - -#include "asio/detail/pop_options.hpp" - -#endif // ASIO_POSIX_DESCRIPTOR_BASE_HPP diff --git a/libtorrent/include/asio/posix/stream_descriptor.hpp b/libtorrent/include/asio/posix/stream_descriptor.hpp deleted file mode 100644 index ccf697726..000000000 --- a/libtorrent/include/asio/posix/stream_descriptor.hpp +++ /dev/null @@ -1,39 +0,0 @@ -// -// stream_descriptor.hpp -// ~~~~~~~~~~~~~~~~~~~~~ -// -// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -#ifndef ASIO_POSIX_STREAM_DESCRIPTOR_HPP -#define ASIO_POSIX_STREAM_DESCRIPTOR_HPP - -#if defined(_MSC_VER) && (_MSC_VER >= 1200) -# pragma once -#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) - -#include "asio/detail/push_options.hpp" - -#include "asio/posix/basic_stream_descriptor.hpp" - -#if defined(ASIO_HAS_POSIX_STREAM_DESCRIPTOR) \ - || defined(GENERATING_DOCUMENTATION) - -namespace asio { -namespace posix { - -/// Typedef for the typical usage of a stream-oriented descriptor. -typedef basic_stream_descriptor<> stream_descriptor; - -} // namespace posix -} // namespace asio - -#endif // defined(ASIO_HAS_POSIX_STREAM_DESCRIPTOR) - // || defined(GENERATING_DOCUMENTATION) - -#include "asio/detail/pop_options.hpp" - -#endif // ASIO_POSIX_STREAM_DESCRIPTOR_HPP diff --git a/libtorrent/include/asio/posix/stream_descriptor_service.hpp b/libtorrent/include/asio/posix/stream_descriptor_service.hpp deleted file mode 100644 index df8ccbfcb..000000000 --- a/libtorrent/include/asio/posix/stream_descriptor_service.hpp +++ /dev/null @@ -1,200 +0,0 @@ -// -// stream_descriptor_service.hpp -// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -// -// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -#ifndef ASIO_POSIX_STREAM_DESCRIPTOR_SERVICE_HPP -#define ASIO_POSIX_STREAM_DESCRIPTOR_SERVICE_HPP - -#if defined(_MSC_VER) && (_MSC_VER >= 1200) -# pragma once -#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) - -#include "asio/detail/push_options.hpp" - -#include "asio/detail/push_options.hpp" -#include -#include -#include "asio/detail/pop_options.hpp" - -#include "asio/error.hpp" -#include "asio/io_service.hpp" -#include "asio/detail/epoll_reactor.hpp" -#include "asio/detail/kqueue_reactor.hpp" -#include "asio/detail/select_reactor.hpp" -#include "asio/detail/service_base.hpp" -#include "asio/detail/reactive_descriptor_service.hpp" - -#if !defined(ASIO_DISABLE_POSIX_STREAM_DESCRIPTOR) -# if !defined(BOOST_WINDOWS) && !defined(__CYGWIN__) -# define ASIO_HAS_POSIX_STREAM_DESCRIPTOR 1 -# endif // !defined(BOOST_WINDOWS) && !defined(__CYGWIN__) -#endif // !defined(ASIO_DISABLE_POSIX_STREAM_DESCRIPTOR) - -#if defined(ASIO_HAS_POSIX_STREAM_DESCRIPTOR) \ - || defined(GENERATING_DOCUMENTATION) - -namespace asio { -namespace posix { - -/// Default service implementation for a stream descriptor. -class stream_descriptor_service -#if defined(GENERATING_DOCUMENTATION) - : public asio::io_service::service -#else - : public asio::detail::service_base -#endif -{ -public: -#if defined(GENERATING_DOCUMENTATION) - /// The unique service identifier. - static asio::io_service::id id; -#endif - -private: - // The type of the platform-specific implementation. -#if defined(ASIO_HAS_EPOLL) - typedef detail::reactive_descriptor_service< - detail::epoll_reactor > service_impl_type; -#elif defined(ASIO_HAS_KQUEUE) - typedef detail::reactive_descriptor_service< - detail::kqueue_reactor > service_impl_type; -#elif defined(ASIO_HAS_DEV_POLL) - typedef detail::reactive_descriptor_service< - detail::dev_poll_reactor > service_impl_type; -#else - typedef detail::reactive_descriptor_service< - detail::select_reactor > service_impl_type; -#endif - -public: - /// The type of a stream descriptor implementation. -#if defined(GENERATING_DOCUMENTATION) - typedef implementation_defined implementation_type; -#else - typedef service_impl_type::implementation_type implementation_type; -#endif - - /// The native descriptor type. -#if defined(GENERATING_DOCUMENTATION) - typedef implementation_defined native_type; -#else - typedef service_impl_type::native_type native_type; -#endif - - /// Construct a new stream descriptor service for the specified io_service. - explicit stream_descriptor_service(asio::io_service& io_service) - : asio::detail::service_base(io_service), - service_impl_(asio::use_service(io_service)) - { - } - - /// Destroy all user-defined descriptorr objects owned by the service. - void shutdown_service() - { - } - - /// Construct a new stream descriptor implementation. - void construct(implementation_type& impl) - { - service_impl_.construct(impl); - } - - /// Destroy a stream descriptor implementation. - void destroy(implementation_type& impl) - { - service_impl_.destroy(impl); - } - - /// Assign an existing native descriptor to a stream descriptor. - asio::error_code assign(implementation_type& impl, - const native_type& native_descriptor, asio::error_code& ec) - { - return service_impl_.assign(impl, native_descriptor, ec); - } - - /// Determine whether the descriptor is open. - bool is_open(const implementation_type& impl) const - { - return service_impl_.is_open(impl); - } - - /// Close a stream descriptor implementation. - asio::error_code close(implementation_type& impl, - asio::error_code& ec) - { - return service_impl_.close(impl, ec); - } - - /// Get the native descriptor implementation. - native_type native(implementation_type& impl) - { - return service_impl_.native(impl); - } - - /// Cancel all asynchronous operations associated with the descriptor. - asio::error_code cancel(implementation_type& impl, - asio::error_code& ec) - { - return service_impl_.cancel(impl, ec); - } - - /// Perform an IO control command on the descriptor. - template - asio::error_code io_control(implementation_type& impl, - IoControlCommand& command, asio::error_code& ec) - { - return service_impl_.io_control(impl, command, ec); - } - - /// Write the given data to the stream. - template - std::size_t write_some(implementation_type& impl, - const ConstBufferSequence& buffers, asio::error_code& ec) - { - return service_impl_.write_some(impl, buffers, ec); - } - - /// Start an asynchronous write. - template - void async_write_some(implementation_type& impl, - const ConstBufferSequence& buffers, WriteHandler descriptorr) - { - service_impl_.async_write_some(impl, buffers, descriptorr); - } - - /// Read some data from the stream. - template - std::size_t read_some(implementation_type& impl, - const MutableBufferSequence& buffers, asio::error_code& ec) - { - return service_impl_.read_some(impl, buffers, ec); - } - - /// Start an asynchronous read. - template - void async_read_some(implementation_type& impl, - const MutableBufferSequence& buffers, ReadHandler descriptorr) - { - service_impl_.async_read_some(impl, buffers, descriptorr); - } - -private: - // The service that provides the platform-specific implementation. - service_impl_type& service_impl_; -}; - -} // namespace posix -} // namespace asio - -#endif // defined(ASIO_HAS_POSIX_STREAM_DESCRIPTOR) - // || defined(GENERATING_DOCUMENTATION) - -#include "asio/detail/pop_options.hpp" - -#endif // ASIO_POSIX_STREAM_DESCRIPTOR_SERVICE_HPP diff --git a/libtorrent/include/asio/raw_socket_service.hpp b/libtorrent/include/asio/raw_socket_service.hpp deleted file mode 100644 index c9d251581..000000000 --- a/libtorrent/include/asio/raw_socket_service.hpp +++ /dev/null @@ -1,323 +0,0 @@ -// -// raw_socket_service.hpp -// ~~~~~~~~~~~~~~~~~~~~~~ -// -// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -#ifndef ASIO_RAW_SOCKET_SERVICE_HPP -#define ASIO_RAW_SOCKET_SERVICE_HPP - -#if defined(_MSC_VER) && (_MSC_VER >= 1200) -# pragma once -#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) - -#include "asio/detail/push_options.hpp" - -#include "asio/detail/push_options.hpp" -#include -#include -#include "asio/detail/pop_options.hpp" - -#include "asio/error.hpp" -#include "asio/io_service.hpp" -#include "asio/detail/epoll_reactor.hpp" -#include "asio/detail/kqueue_reactor.hpp" -#include "asio/detail/select_reactor.hpp" -#include "asio/detail/service_base.hpp" -#include "asio/detail/reactive_socket_service.hpp" -#include "asio/detail/win_iocp_socket_service.hpp" - -namespace asio { - -/// Default service implementation for a raw socket. -template -class raw_socket_service -#if defined(GENERATING_DOCUMENTATION) - : public asio::io_service::service -#else - : public asio::detail::service_base > -#endif -{ -public: -#if defined(GENERATING_DOCUMENTATION) - /// The unique service identifier. - static asio::io_service::id id; -#endif - - /// The protocol type. - typedef Protocol protocol_type; - - /// The endpoint type. - typedef typename Protocol::endpoint endpoint_type; - -private: - // The type of the platform-specific implementation. -#if defined(ASIO_HAS_IOCP) - typedef detail::win_iocp_socket_service service_impl_type; -#elif defined(ASIO_HAS_EPOLL) - typedef detail::reactive_socket_service< - Protocol, detail::epoll_reactor > service_impl_type; -#elif defined(ASIO_HAS_KQUEUE) - typedef detail::reactive_socket_service< - Protocol, detail::kqueue_reactor > service_impl_type; -#elif defined(ASIO_HAS_DEV_POLL) - typedef detail::reactive_socket_service< - Protocol, detail::dev_poll_reactor > service_impl_type; -#else - typedef detail::reactive_socket_service< - Protocol, detail::select_reactor > service_impl_type; -#endif - -public: - /// The type of a raw socket. -#if defined(GENERATING_DOCUMENTATION) - typedef implementation_defined implementation_type; -#else - typedef typename service_impl_type::implementation_type implementation_type; -#endif - - /// The native socket type. -#if defined(GENERATING_DOCUMENTATION) - typedef implementation_defined native_type; -#else - typedef typename service_impl_type::native_type native_type; -#endif - - /// Construct a new raw socket service for the specified io_service. - explicit raw_socket_service(asio::io_service& io_service) - : asio::detail::service_base< - raw_socket_service >(io_service), - service_impl_(asio::use_service(io_service)) - { - } - - /// Destroy all user-defined handler objects owned by the service. - void shutdown_service() - { - } - - /// Construct a new raw socket implementation. - void construct(implementation_type& impl) - { - service_impl_.construct(impl); - } - - /// Destroy a raw socket implementation. - void destroy(implementation_type& impl) - { - service_impl_.destroy(impl); - } - - // Open a new raw socket implementation. - asio::error_code open(implementation_type& impl, - const protocol_type& protocol, asio::error_code& ec) - { - if (protocol.type() == SOCK_RAW) - service_impl_.open(impl, protocol, ec); - else - ec = asio::error::invalid_argument; - return ec; - } - - /// Assign an existing native socket to a raw socket. - asio::error_code assign(implementation_type& impl, - const protocol_type& protocol, const native_type& native_socket, - asio::error_code& ec) - { - return service_impl_.assign(impl, protocol, native_socket, ec); - } - - /// Determine whether the socket is open. - bool is_open(const implementation_type& impl) const - { - return service_impl_.is_open(impl); - } - - /// Close a raw socket implementation. - asio::error_code close(implementation_type& impl, - asio::error_code& ec) - { - return service_impl_.close(impl, ec); - } - - /// Get the native socket implementation. - native_type native(implementation_type& impl) - { - return service_impl_.native(impl); - } - - /// Cancel all asynchronous operations associated with the socket. - asio::error_code cancel(implementation_type& impl, - asio::error_code& ec) - { - return service_impl_.cancel(impl, ec); - } - - /// Determine whether the socket is at the out-of-band data mark. - bool at_mark(const implementation_type& impl, - asio::error_code& ec) const - { - return service_impl_.at_mark(impl, ec); - } - - /// Determine the number of bytes available for reading. - std::size_t available(const implementation_type& impl, - asio::error_code& ec) const - { - return service_impl_.available(impl, ec); - } - - // Bind the raw socket to the specified local endpoint. - asio::error_code bind(implementation_type& impl, - const endpoint_type& endpoint, asio::error_code& ec) - { - return service_impl_.bind(impl, endpoint, ec); - } - - /// Connect the raw socket to the specified endpoint. - asio::error_code connect(implementation_type& impl, - const endpoint_type& peer_endpoint, asio::error_code& ec) - { - return service_impl_.connect(impl, peer_endpoint, ec); - } - - /// Start an asynchronous connect. - template - void async_connect(implementation_type& impl, - const endpoint_type& peer_endpoint, ConnectHandler handler) - { - service_impl_.async_connect(impl, peer_endpoint, handler); - } - - /// Set a socket option. - template - asio::error_code set_option(implementation_type& impl, - const SettableSocketOption& option, asio::error_code& ec) - { - return service_impl_.set_option(impl, option, ec); - } - - /// Get a socket option. - template - asio::error_code get_option(const implementation_type& impl, - GettableSocketOption& option, asio::error_code& ec) const - { - return service_impl_.get_option(impl, option, ec); - } - - /// Perform an IO control command on the socket. - template - asio::error_code io_control(implementation_type& impl, - IoControlCommand& command, asio::error_code& ec) - { - return service_impl_.io_control(impl, command, ec); - } - - /// Get the local endpoint. - endpoint_type local_endpoint(const implementation_type& impl, - asio::error_code& ec) const - { - return service_impl_.local_endpoint(impl, ec); - } - - /// Get the remote endpoint. - endpoint_type remote_endpoint(const implementation_type& impl, - asio::error_code& ec) const - { - return service_impl_.remote_endpoint(impl, ec); - } - - /// Disable sends or receives on the socket. - asio::error_code shutdown(implementation_type& impl, - socket_base::shutdown_type what, asio::error_code& ec) - { - return service_impl_.shutdown(impl, what, ec); - } - - /// Send the given data to the peer. - template - std::size_t send(implementation_type& impl, - const ConstBufferSequence& buffers, - socket_base::message_flags flags, asio::error_code& ec) - { - return service_impl_.send(impl, buffers, flags, ec); - } - - /// Start an asynchronous send. - template - void async_send(implementation_type& impl, const ConstBufferSequence& buffers, - socket_base::message_flags flags, WriteHandler handler) - { - service_impl_.async_send(impl, buffers, flags, handler); - } - - /// Send raw data to the specified endpoint. - template - std::size_t send_to(implementation_type& impl, - const ConstBufferSequence& buffers, const endpoint_type& destination, - socket_base::message_flags flags, asio::error_code& ec) - { - return service_impl_.send_to(impl, buffers, destination, flags, ec); - } - - /// Start an asynchronous send. - template - void async_send_to(implementation_type& impl, - const ConstBufferSequence& buffers, const endpoint_type& destination, - socket_base::message_flags flags, WriteHandler handler) - { - service_impl_.async_send_to(impl, buffers, destination, flags, handler); - } - - /// Receive some data from the peer. - template - std::size_t receive(implementation_type& impl, - const MutableBufferSequence& buffers, - socket_base::message_flags flags, asio::error_code& ec) - { - return service_impl_.receive(impl, buffers, flags, ec); - } - - /// Start an asynchronous receive. - template - void async_receive(implementation_type& impl, - const MutableBufferSequence& buffers, - socket_base::message_flags flags, ReadHandler handler) - { - service_impl_.async_receive(impl, buffers, flags, handler); - } - - /// Receive raw data with the endpoint of the sender. - template - std::size_t receive_from(implementation_type& impl, - const MutableBufferSequence& buffers, endpoint_type& sender_endpoint, - socket_base::message_flags flags, asio::error_code& ec) - { - return service_impl_.receive_from(impl, buffers, sender_endpoint, flags, - ec); - } - - /// Start an asynchronous receive that will get the endpoint of the sender. - template - void async_receive_from(implementation_type& impl, - const MutableBufferSequence& buffers, endpoint_type& sender_endpoint, - socket_base::message_flags flags, ReadHandler handler) - { - service_impl_.async_receive_from(impl, buffers, sender_endpoint, flags, - handler); - } - -private: - // The service that provides the platform-specific implementation. - service_impl_type& service_impl_; -}; - -} // namespace asio - -#include "asio/detail/pop_options.hpp" - -#endif // ASIO_RAW_SOCKET_SERVICE_HPP diff --git a/libtorrent/include/asio/read.hpp b/libtorrent/include/asio/read.hpp deleted file mode 100644 index 7c0b82247..000000000 --- a/libtorrent/include/asio/read.hpp +++ /dev/null @@ -1,522 +0,0 @@ -// -// read.hpp -// ~~~~~~~~ -// -// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -#ifndef ASIO_READ_HPP -#define ASIO_READ_HPP - -#if defined(_MSC_VER) && (_MSC_VER >= 1200) -# pragma once -#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) - -#include "asio/detail/push_options.hpp" - -#include "asio/detail/push_options.hpp" -#include -#include -#include "asio/detail/pop_options.hpp" - -#include "asio/basic_streambuf.hpp" -#include "asio/error.hpp" - -namespace asio { - -/** - * @defgroup read asio::read - * - * @brief Attempt to read a certain amount of data from a stream before - * returning. - */ -/*@{*/ - -/// Attempt to read a certain amount of data from a stream before returning. -/** - * This function is used to read a certain number of bytes of data from a - * stream. The call will block until one of the following conditions is true: - * - * @li The supplied buffers are full. That is, the bytes transferred is equal to - * the sum of the buffer sizes. - * - * @li An error occurred. - * - * This operation is implemented in terms of one or more calls to the stream's - * read_some function. - * - * @param s The stream from which the data is to be read. The type must support - * the SyncReadStream concept. - * - * @param buffers One or more buffers into which the data will be read. The sum - * of the buffer sizes indicates the maximum number of bytes to read from the - * stream. - * - * @returns The number of bytes transferred. - * - * @throws asio::system_error Thrown on failure. - * - * @par Example - * To read into a single data buffer use the @ref buffer function as follows: - * @code asio::read(s, asio::buffer(data, size)); @endcode - * See the @ref buffer documentation for information on reading into multiple - * buffers in one go, and how to use it with arrays, boost::array or - * std::vector. - * - * @note This overload is equivalent to calling: - * @code asio::read( - * s, buffers, - * asio::transfer_all()); @endcode - */ -template -std::size_t read(SyncReadStream& s, const MutableBufferSequence& buffers); - -/// Attempt to read a certain amount of data from a stream before returning. -/** - * This function is used to read a certain number of bytes of data from a - * stream. The call will block until one of the following conditions is true: - * - * @li The supplied buffers are full. That is, the bytes transferred is equal to - * the sum of the buffer sizes. - * - * @li The completion_condition function object returns true. - * - * This operation is implemented in terms of one or more calls to the stream's - * read_some function. - * - * @param s The stream from which the data is to be read. The type must support - * the SyncReadStream concept. - * - * @param buffers One or more buffers into which the data will be read. The sum - * of the buffer sizes indicates the maximum number of bytes to read from the - * stream. - * - * @param completion_condition The function object to be called to determine - * whether the read operation is complete. The signature of the function object - * must be: - * @code bool completion_condition( - * const asio::error_code& error, // Result of latest read_some - * // operation. - * - * std::size_t bytes_transferred // Number of bytes transferred - * // so far. - * ); @endcode - * A return value of true indicates that the read operation is complete. False - * indicates that further calls to the stream's read_some function are required. - * - * @returns The number of bytes transferred. - * - * @throws asio::system_error Thrown on failure. - * - * @par Example - * To read into a single data buffer use the @ref buffer function as follows: - * @code asio::read(s, asio::buffer(data, size), - * asio::transfer_at_least(32)); @endcode - * See the @ref buffer documentation for information on reading into multiple - * buffers in one go, and how to use it with arrays, boost::array or - * std::vector. - */ -template -std::size_t read(SyncReadStream& s, const MutableBufferSequence& buffers, - CompletionCondition completion_condition); - -/// Attempt to read a certain amount of data from a stream before returning. -/** - * This function is used to read a certain number of bytes of data from a - * stream. The call will block until one of the following conditions is true: - * - * @li The supplied buffers are full. That is, the bytes transferred is equal to - * the sum of the buffer sizes. - * - * @li The completion_condition function object returns true. - * - * This operation is implemented in terms of one or more calls to the stream's - * read_some function. - * - * @param s The stream from which the data is to be read. The type must support - * the SyncReadStream concept. - * - * @param buffers One or more buffers into which the data will be read. The sum - * of the buffer sizes indicates the maximum number of bytes to read from the - * stream. - * - * @param completion_condition The function object to be called to determine - * whether the read operation is complete. The signature of the function object - * must be: - * @code bool completion_condition( - * const asio::error_code& error, // Result of latest read_some - * // operation. - * - * std::size_t bytes_transferred // Number of bytes transferred - * // so far. - * ); @endcode - * A return value of true indicates that the read operation is complete. False - * indicates that further calls to the stream's read_some function are required. - * - * @param ec Set to indicate what error occurred, if any. - * - * @returns The number of bytes read. If an error occurs, returns the total - * number of bytes successfully transferred prior to the error. - */ -template -std::size_t read(SyncReadStream& s, const MutableBufferSequence& buffers, - CompletionCondition completion_condition, asio::error_code& ec); - -/// Attempt to read a certain amount of data from a stream before returning. -/** - * This function is used to read a certain number of bytes of data from a - * stream. The call will block until one of the following conditions is true: - * - * @li An error occurred. - * - * This operation is implemented in terms of one or more calls to the stream's - * read_some function. - * - * @param s The stream from which the data is to be read. The type must support - * the SyncReadStream concept. - * - * @param b The basic_streambuf object into which the data will be read. - * - * @returns The number of bytes transferred. - * - * @throws asio::system_error Thrown on failure. - * - * @note This overload is equivalent to calling: - * @code asio::read( - * s, b, - * asio::transfer_all()); @endcode - */ -template -std::size_t read(SyncReadStream& s, basic_streambuf& b); - -/// Attempt to read a certain amount of data from a stream before returning. -/** - * This function is used to read a certain number of bytes of data from a - * stream. The call will block until one of the following conditions is true: - * - * @li The completion_condition function object returns true. - * - * This operation is implemented in terms of one or more calls to the stream's - * read_some function. - * - * @param s The stream from which the data is to be read. The type must support - * the SyncReadStream concept. - * - * @param b The basic_streambuf object into which the data will be read. - * - * @param completion_condition The function object to be called to determine - * whether the read operation is complete. The signature of the function object - * must be: - * @code bool completion_condition( - * const asio::error_code& error, // Result of latest read_some - * // operation. - * - * std::size_t bytes_transferred // Number of bytes transferred - * // so far. - * ); @endcode - * A return value of true indicates that the read operation is complete. False - * indicates that further calls to the stream's read_some function are required. - * - * @returns The number of bytes transferred. - * - * @throws asio::system_error Thrown on failure. - */ -template -std::size_t read(SyncReadStream& s, basic_streambuf& b, - CompletionCondition completion_condition); - -/// Attempt to read a certain amount of data from a stream before returning. -/** - * This function is used to read a certain number of bytes of data from a - * stream. The call will block until one of the following conditions is true: - * - * @li The completion_condition function object returns true. - * - * This operation is implemented in terms of one or more calls to the stream's - * read_some function. - * - * @param s The stream from which the data is to be read. The type must support - * the SyncReadStream concept. - * - * @param b The basic_streambuf object into which the data will be read. - * - * @param completion_condition The function object to be called to determine - * whether the read operation is complete. The signature of the function object - * must be: - * @code bool completion_condition( - * const asio::error_code& error, // Result of latest read_some - * // operation. - * - * std::size_t bytes_transferred // Number of bytes transferred - * // so far. - * ); @endcode - * A return value of true indicates that the read operation is complete. False - * indicates that further calls to the stream's read_some function are required. - * - * @param ec Set to indicate what error occurred, if any. - * - * @returns The number of bytes read. If an error occurs, returns the total - * number of bytes successfully transferred prior to the error. - */ -template -std::size_t read(SyncReadStream& s, basic_streambuf& b, - CompletionCondition completion_condition, asio::error_code& ec); - -/*@}*/ -/** - * @defgroup async_read asio::async_read - * - * @brief Start an asynchronous operation to read a certain amount of data from - * a stream. - */ -/*@{*/ - -/// Start an asynchronous operation to read a certain amount of data from a -/// stream. -/** - * This function is used to asynchronously read a certain number of bytes of - * data from a stream. The function call always returns immediately. The - * asynchronous operation will continue until one of the following conditions is - * true: - * - * @li The supplied buffers are full. That is, the bytes transferred is equal to - * the sum of the buffer sizes. - * - * @li An error occurred. - * - * This operation is implemented in terms of one or more calls to the stream's - * async_read_some function. - * - * @param s The stream from which the data is to be read. The type must support - * the AsyncReadStream concept. - * - * @param buffers One or more buffers into which the data will be read. The sum - * of the buffer sizes indicates the maximum number of bytes to read from the - * stream. Although the buffers object may be copied as necessary, ownership of - * the underlying memory blocks is retained by the caller, which must guarantee - * that they remain valid until the handler is called. - * - * @param handler The handler to be called when the read operation completes. - * Copies will be made of the handler as required. The function signature of the - * handler must be: - * @code void handler( - * const asio::error_code& error, // Result of operation. - * - * std::size_t bytes_transferred // Number of bytes copied into the - * // buffers. If an error occurred, - * // this will be the number of - * // bytes successfully transferred - * // prior to the error. - * ); @endcode - * Regardless of whether the asynchronous operation completes immediately or - * not, the handler will not be invoked from within this function. Invocation of - * the handler will be performed in a manner equivalent to using - * asio::io_service::post(). - * - * @par Example - * To read into a single data buffer use the @ref buffer function as follows: - * @code - * asio::async_read(s, asio::buffer(data, size), handler); - * @endcode - * See the @ref buffer documentation for information on reading into multiple - * buffers in one go, and how to use it with arrays, boost::array or - * std::vector. - * - * @note This overload is equivalent to calling: - * @code asio::async_read( - * s, buffers, - * asio::transfer_all(), - * handler); @endcode - */ -template -void async_read(AsyncReadStream& s, const MutableBufferSequence& buffers, - ReadHandler handler); - -/// Start an asynchronous operation to read a certain amount of data from a -/// stream. -/** - * This function is used to asynchronously read a certain number of bytes of - * data from a stream. The function call always returns immediately. The - * asynchronous operation will continue until one of the following conditions is - * true: - * - * @li The supplied buffers are full. That is, the bytes transferred is equal to - * the sum of the buffer sizes. - * - * @li The completion_condition function object returns true. - * - * @param s The stream from which the data is to be read. The type must support - * the AsyncReadStream concept. - * - * @param buffers One or more buffers into which the data will be read. The sum - * of the buffer sizes indicates the maximum number of bytes to read from the - * stream. Although the buffers object may be copied as necessary, ownership of - * the underlying memory blocks is retained by the caller, which must guarantee - * that they remain valid until the handler is called. - * - * @param completion_condition The function object to be called to determine - * whether the read operation is complete. The signature of the function object - * must be: - * @code bool completion_condition( - * const asio::error_code& error, // Result of latest read_some - * // operation. - * - * std::size_t bytes_transferred // Number of bytes transferred - * // so far. - * ); @endcode - * A return value of true indicates that the read operation is complete. False - * indicates that further calls to the stream's async_read_some function are - * required. - * - * @param handler The handler to be called when the read operation completes. - * Copies will be made of the handler as required. The function signature of the - * handler must be: - * @code void handler( - * const asio::error_code& error, // Result of operation. - * - * std::size_t bytes_transferred // Number of bytes copied into the - * // buffers. If an error occurred, - * // this will be the number of - * // bytes successfully transferred - * // prior to the error. - * ); @endcode - * Regardless of whether the asynchronous operation completes immediately or - * not, the handler will not be invoked from within this function. Invocation of - * the handler will be performed in a manner equivalent to using - * asio::io_service::post(). - * - * @par Example - * To read into a single data buffer use the @ref buffer function as follows: - * @code asio::async_read(s, - * asio::buffer(data, size), - * asio::transfer_at_least(32), - * handler); @endcode - * See the @ref buffer documentation for information on reading into multiple - * buffers in one go, and how to use it with arrays, boost::array or - * std::vector. - */ -template -void async_read(AsyncReadStream& s, const MutableBufferSequence& buffers, - CompletionCondition completion_condition, ReadHandler handler); - -/// Start an asynchronous operation to read a certain amount of data from a -/// stream. -/** - * This function is used to asynchronously read a certain number of bytes of - * data from a stream. The function call always returns immediately. The - * asynchronous operation will continue until one of the following conditions is - * true: - * - * @li An error occurred. - * - * This operation is implemented in terms of one or more calls to the stream's - * async_read_some function. - * - * @param s The stream from which the data is to be read. The type must support - * the AsyncReadStream concept. - * - * @param b A basic_streambuf object into which the data will be read. Ownership - * of the streambuf is retained by the caller, which must guarantee that it - * remains valid until the handler is called. - * - * @param handler The handler to be called when the read operation completes. - * Copies will be made of the handler as required. The function signature of the - * handler must be: - * @code void handler( - * const asio::error_code& error, // Result of operation. - * - * std::size_t bytes_transferred // Number of bytes copied into the - * // buffers. If an error occurred, - * // this will be the number of - * // bytes successfully transferred - * // prior to the error. - * ); @endcode - * Regardless of whether the asynchronous operation completes immediately or - * not, the handler will not be invoked from within this function. Invocation of - * the handler will be performed in a manner equivalent to using - * asio::io_service::post(). - * - * @note This overload is equivalent to calling: - * @code asio::async_read( - * s, b, - * asio::transfer_all(), - * handler); @endcode - */ -template -void async_read(AsyncReadStream& s, basic_streambuf& b, - ReadHandler handler); - -/// Start an asynchronous operation to read a certain amount of data from a -/// stream. -/** - * This function is used to asynchronously read a certain number of bytes of - * data from a stream. The function call always returns immediately. The - * asynchronous operation will continue until one of the following conditions is - * true: - * - * @li The completion_condition function object returns true. - * - * This operation is implemented in terms of one or more calls to the stream's - * async_read_some function. - * - * @param s The stream from which the data is to be read. The type must support - * the AsyncReadStream concept. - * - * @param b A basic_streambuf object into which the data will be read. Ownership - * of the streambuf is retained by the caller, which must guarantee that it - * remains valid until the handler is called. - * - * @param completion_condition The function object to be called to determine - * whether the read operation is complete. The signature of the function object - * must be: - * @code bool completion_condition( - * const asio::error_code& error, // Result of latest read_some - * // operation. - * - * std::size_t bytes_transferred // Number of bytes transferred - * // so far. - * ); @endcode - * A return value of true indicates that the read operation is complete. False - * indicates that further calls to the stream's async_read_some function are - * required. - * - * @param handler The handler to be called when the read operation completes. - * Copies will be made of the handler as required. The function signature of the - * handler must be: - * @code void handler( - * const asio::error_code& error, // Result of operation. - * - * std::size_t bytes_transferred // Number of bytes copied into the - * // buffers. If an error occurred, - * // this will be the number of - * // bytes successfully transferred - * // prior to the error. - * ); @endcode - * Regardless of whether the asynchronous operation completes immediately or - * not, the handler will not be invoked from within this function. Invocation of - * the handler will be performed in a manner equivalent to using - * asio::io_service::post(). - */ -template -void async_read(AsyncReadStream& s, basic_streambuf& b, - CompletionCondition completion_condition, ReadHandler handler); - -/*@}*/ - -} // namespace asio - -#include "asio/impl/read.ipp" - -#include "asio/detail/pop_options.hpp" - -#endif // ASIO_READ_HPP diff --git a/libtorrent/include/asio/read_at.hpp b/libtorrent/include/asio/read_at.hpp deleted file mode 100644 index bcc247a0f..000000000 --- a/libtorrent/include/asio/read_at.hpp +++ /dev/null @@ -1,568 +0,0 @@ -// -// read_at.hpp -// ~~~~~~~~~~~ -// -// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -#ifndef ASIO_READ_AT_HPP -#define ASIO_READ_AT_HPP - -#if defined(_MSC_VER) && (_MSC_VER >= 1200) -# pragma once -#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) - -#include "asio/detail/push_options.hpp" - -#include "asio/detail/push_options.hpp" -#include -#include -#include -#include "asio/detail/pop_options.hpp" - -#include "asio/basic_streambuf.hpp" -#include "asio/error.hpp" - -namespace asio { - -/** - * @defgroup read_at asio::read_at - * - * @brief Attempt to read a certain amount of data at the specified offset - * before returning. - */ -/*@{*/ - -/// Attempt to read a certain amount of data at the specified offset before -/// returning. -/** - * This function is used to read a certain number of bytes of data from a - * random access device at the specified offset. The call will block until one - * of the following conditions is true: - * - * @li The supplied buffers are full. That is, the bytes transferred is equal to - * the sum of the buffer sizes. - * - * @li An error occurred. - * - * This operation is implemented in terms of one or more calls to the device's - * read_some_at function. - * - * @param d The device from which the data is to be read. The type must support - * the SyncRandomAccessReadDevice concept. - * - * @param offset The offset at which the data will be read. - * - * @param buffers One or more buffers into which the data will be read. The sum - * of the buffer sizes indicates the maximum number of bytes to read from the - * device. - * - * @returns The number of bytes transferred. - * - * @throws asio::system_error Thrown on failure. - * - * @par Example - * To read into a single data buffer use the @ref buffer function as follows: - * @code asio::read_at(d, 42, asio::buffer(data, size)); @endcode - * See the @ref buffer documentation for information on reading into multiple - * buffers in one go, and how to use it with arrays, boost::array or - * std::vector. - * - * @note This overload is equivalent to calling: - * @code asio::read_at( - * d, 42, buffers, - * asio::transfer_all()); @endcode - */ -template -std::size_t read_at(SyncRandomAccessReadDevice& d, - boost::uint64_t offset, const MutableBufferSequence& buffers); - -/// Attempt to read a certain amount of data at the specified offset before -/// returning. -/** - * This function is used to read a certain number of bytes of data from a - * random access device at the specified offset. The call will block until one - * of the following conditions is true: - * - * @li The supplied buffers are full. That is, the bytes transferred is equal to - * the sum of the buffer sizes. - * - * @li The completion_condition function object returns true. - * - * This operation is implemented in terms of one or more calls to the device's - * read_some_at function. - * - * @param d The device from which the data is to be read. The type must support - * the SyncRandomAccessReadDevice concept. - * - * @param offset The offset at which the data will be read. - * - * @param buffers One or more buffers into which the data will be read. The sum - * of the buffer sizes indicates the maximum number of bytes to read from the - * device. - * - * @param completion_condition The function object to be called to determine - * whether the read operation is complete. The signature of the function object - * must be: - * @code bool completion_condition( - * // Result of latest read_some_at operation. - * const asio::error_code& error, - * - * // Number of bytes transferred so far. - * std::size_t bytes_transferred - * ); @endcode - * A return value of true indicates that the read operation is complete. False - * indicates that further calls to the device's read_some_at function are - * required. - * - * @returns The number of bytes transferred. - * - * @throws asio::system_error Thrown on failure. - * - * @par Example - * To read into a single data buffer use the @ref buffer function as follows: - * @code asio::read_at(d, 42, asio::buffer(data, size), - * asio::transfer_at_least(32)); @endcode - * See the @ref buffer documentation for information on reading into multiple - * buffers in one go, and how to use it with arrays, boost::array or - * std::vector. - */ -template -std::size_t read_at(SyncRandomAccessReadDevice& d, - boost::uint64_t offset, const MutableBufferSequence& buffers, - CompletionCondition completion_condition); - -/// Attempt to read a certain amount of data at the specified offset before -/// returning. -/** - * This function is used to read a certain number of bytes of data from a - * random access device at the specified offset. The call will block until one - * of the following conditions is true: - * - * @li The supplied buffers are full. That is, the bytes transferred is equal to - * the sum of the buffer sizes. - * - * @li The completion_condition function object returns true. - * - * This operation is implemented in terms of one or more calls to the device's - * read_some_at function. - * - * @param d The device from which the data is to be read. The type must support - * the SyncRandomAccessReadDevice concept. - * - * @param offset The offset at which the data will be read. - * - * @param buffers One or more buffers into which the data will be read. The sum - * of the buffer sizes indicates the maximum number of bytes to read from the - * device. - * - * @param completion_condition The function object to be called to determine - * whether the read operation is complete. The signature of the function object - * must be: - * @code bool completion_condition( - * const asio::error_code& error, // Result of latest read_some_at - * // operation. - * - * std::size_t bytes_transferred // Number of bytes transferred - * // so far. - * ); @endcode - * A return value of true indicates that the read operation is complete. False - * indicates that further calls to the device's read_some_at function are - * required. - * - * @param ec Set to indicate what error occurred, if any. - * - * @returns The number of bytes read. If an error occurs, returns the total - * number of bytes successfully transferred prior to the error. - */ -template -std::size_t read_at(SyncRandomAccessReadDevice& d, - boost::uint64_t offset, const MutableBufferSequence& buffers, - CompletionCondition completion_condition, asio::error_code& ec); - -/// Attempt to read a certain amount of data at the specified offset before -/// returning. -/** - * This function is used to read a certain number of bytes of data from a - * random access device at the specified offset. The call will block until one - * of the following conditions is true: - * - * @li An error occurred. - * - * This operation is implemented in terms of one or more calls to the device's - * read_some_at function. - * - * @param d The device from which the data is to be read. The type must support - * the SyncRandomAccessReadDevice concept. - * - * @param offset The offset at which the data will be read. - * - * @param b The basic_streambuf object into which the data will be read. - * - * @returns The number of bytes transferred. - * - * @throws asio::system_error Thrown on failure. - * - * @note This overload is equivalent to calling: - * @code asio::read_at( - * d, 42, b, - * asio::transfer_all()); @endcode - */ -template -std::size_t read_at(SyncRandomAccessReadDevice& d, - boost::uint64_t offset, basic_streambuf& b); - -/// Attempt to read a certain amount of data at the specified offset before -/// returning. -/** - * This function is used to read a certain number of bytes of data from a - * random access device at the specified offset. The call will block until one - * of the following conditions is true: - * - * @li The completion_condition function object returns true. - * - * This operation is implemented in terms of one or more calls to the device's - * read_some_at function. - * - * @param d The device from which the data is to be read. The type must support - * the SyncRandomAccessReadDevice concept. - * - * @param offset The offset at which the data will be read. - * - * @param b The basic_streambuf object into which the data will be read. - * - * @param completion_condition The function object to be called to determine - * whether the read operation is complete. The signature of the function object - * must be: - * @code bool completion_condition( - * // Result of latest read_some_at operation. - * const asio::error_code& error, - * - * // Number of bytes transferred so far. - * std::size_t bytes_transferred - * ); @endcode - * A return value of true indicates that the read operation is complete. False - * indicates that further calls to the device's read_some_at function are - * required. - * - * @returns The number of bytes transferred. - * - * @throws asio::system_error Thrown on failure. - */ -template -std::size_t read_at(SyncRandomAccessReadDevice& d, - boost::uint64_t offset, basic_streambuf& b, - CompletionCondition completion_condition); - -/// Attempt to read a certain amount of data at the specified offset before -/// returning. -/** - * This function is used to read a certain number of bytes of data from a - * random access device at the specified offset. The call will block until one - * of the following conditions is true: - * - * @li The completion_condition function object returns true. - * - * This operation is implemented in terms of one or more calls to the device's - * read_some_at function. - * - * @param d The device from which the data is to be read. The type must support - * the SyncRandomAccessReadDevice concept. - * - * @param offset The offset at which the data will be read. - * - * @param b The basic_streambuf object into which the data will be read. - * - * @param completion_condition The function object to be called to determine - * whether the read operation is complete. The signature of the function object - * must be: - * @code bool completion_condition( - * // Result of latest read_some_at operation. - * const asio::error_code& error, - * - * // Number of bytes transferred so far. - * std::size_t bytes_transferred - * ); @endcode - * A return value of true indicates that the read operation is complete. False - * indicates that further calls to the device's read_some_at function are - * required. - * - * @param ec Set to indicate what error occurred, if any. - * - * @returns The number of bytes read. If an error occurs, returns the total - * number of bytes successfully transferred prior to the error. - */ -template -std::size_t read_at(SyncRandomAccessReadDevice& d, - boost::uint64_t offset, basic_streambuf& b, - CompletionCondition completion_condition, asio::error_code& ec); - -/*@}*/ -/** - * @defgroup async_read_at asio::async_read_at - * - * @brief Start an asynchronous operation to read a certain amount of data at - * the specified offset. - */ -/*@{*/ - -/// Start an asynchronous operation to read a certain amount of data at the -/// specified offset. -/** - * This function is used to asynchronously read a certain number of bytes of - * data from a random access device at the specified offset. The function call - * always returns immediately. The asynchronous operation will continue until - * one of the following conditions is true: - * - * @li The supplied buffers are full. That is, the bytes transferred is equal to - * the sum of the buffer sizes. - * - * @li An error occurred. - * - * This operation is implemented in terms of one or more calls to the device's - * async_read_some_at function. - * - * @param d The device from which the data is to be read. The type must support - * the AsyncRandomAccessReadDevice concept. - * - * @param offset The offset at which the data will be read. - * - * @param buffers One or more buffers into which the data will be read. The sum - * of the buffer sizes indicates the maximum number of bytes to read from the - * device. Although the buffers object may be copied as necessary, ownership of - * the underlying memory blocks is retained by the caller, which must guarantee - * that they remain valid until the handler is called. - * - * @param handler The handler to be called when the read operation completes. - * Copies will be made of the handler as required. The function signature of the - * handler must be: - * @code void handler( - * // Result of operation. - * const asio::error_code& error, - * - * // Number of bytes copied into the buffers. If an error - * // occurred, this will be the number of bytes successfully - * // transferred prior to the error. - * std::size_t bytes_transferred - * ); @endcode - * Regardless of whether the asynchronous operation completes immediately or - * not, the handler will not be invoked from within this function. Invocation of - * the handler will be performed in a manner equivalent to using - * asio::io_service::post(). - * - * @par Example - * To read into a single data buffer use the @ref buffer function as follows: - * @code - * asio::async_read_at(d, 42, asio::buffer(data, size), handler); - * @endcode - * See the @ref buffer documentation for information on reading into multiple - * buffers in one go, and how to use it with arrays, boost::array or - * std::vector. - * - * @note This overload is equivalent to calling: - * @code asio::async_read_at( - * d, 42, buffers, - * asio::transfer_all(), - * handler); @endcode - */ -template -void async_read_at(AsyncRandomAccessReadDevice& d, boost::uint64_t offset, - const MutableBufferSequence& buffers, ReadHandler handler); - -/// Start an asynchronous operation to read a certain amount of data at the -/// specified offset. -/** - * This function is used to asynchronously read a certain number of bytes of - * data from a random access device at the specified offset. The function call - * always returns immediately. The asynchronous operation will continue until - * one of the following conditions is true: - * - * @li The supplied buffers are full. That is, the bytes transferred is equal to - * the sum of the buffer sizes. - * - * @li The completion_condition function object returns true. - * - * @param d The device from which the data is to be read. The type must support - * the AsyncRandomAccessReadDevice concept. - * - * @param offset The offset at which the data will be read. - * - * @param buffers One or more buffers into which the data will be read. The sum - * of the buffer sizes indicates the maximum number of bytes to read from the - * device. Although the buffers object may be copied as necessary, ownership of - * the underlying memory blocks is retained by the caller, which must guarantee - * that they remain valid until the handler is called. - * - * @param completion_condition The function object to be called to determine - * whether the read operation is complete. The signature of the function object - * must be: - * @code bool completion_condition( - * // Result of latest read_some_at operation. - * const asio::error_code& error, - * - * // Number of bytes transferred so far. - * std::size_t bytes_transferred - * ); @endcode - * A return value of true indicates that the read operation is complete. False - * indicates that further calls to the device's async_read_some_at function are - * required. - * - * @param handler The handler to be called when the read operation completes. - * Copies will be made of the handler as required. The function signature of the - * handler must be: - * @code void handler( - * // Result of operation. - * const asio::error_code& error, - * - * // Number of bytes copied into the buffers. If an error - * // occurred, this will be the number of bytes successfully - * // transferred prior to the error. - * std::size_t bytes_transferred - * ); @endcode - * Regardless of whether the asynchronous operation completes immediately or - * not, the handler will not be invoked from within this function. Invocation of - * the handler will be performed in a manner equivalent to using - * asio::io_service::post(). - * - * @par Example - * To read into a single data buffer use the @ref buffer function as follows: - * @code asio::async_read_at(d, 42, - * asio::buffer(data, size), - * asio::transfer_at_least(32), - * handler); @endcode - * See the @ref buffer documentation for information on reading into multiple - * buffers in one go, and how to use it with arrays, boost::array or - * std::vector. - */ -template -void async_read_at(AsyncRandomAccessReadDevice& d, - boost::uint64_t offset, const MutableBufferSequence& buffers, - CompletionCondition completion_condition, ReadHandler handler); - -/// Start an asynchronous operation to read a certain amount of data at the -/// specified offset. -/** - * This function is used to asynchronously read a certain number of bytes of - * data from a random access device at the specified offset. The function call - * always returns immediately. The asynchronous operation will continue until - * one of the following conditions is true: - * - * @li An error occurred. - * - * This operation is implemented in terms of one or more calls to the device's - * async_read_some_at function. - * - * @param d The device from which the data is to be read. The type must support - * the AsyncRandomAccessReadDevice concept. - * - * @param offset The offset at which the data will be read. - * - * @param b A basic_streambuf object into which the data will be read. Ownership - * of the streambuf is retained by the caller, which must guarantee that it - * remains valid until the handler is called. - * - * @param handler The handler to be called when the read operation completes. - * Copies will be made of the handler as required. The function signature of the - * handler must be: - * @code void handler( - * // Result of operation. - * const asio::error_code& error, - * - * // Number of bytes copied into the buffers. If an error - * // occurred, this will be the number of bytes successfully - * // transferred prior to the error. - * std::size_t bytes_transferred - * ); @endcode - * Regardless of whether the asynchronous operation completes immediately or - * not, the handler will not be invoked from within this function. Invocation of - * the handler will be performed in a manner equivalent to using - * asio::io_service::post(). - * - * @note This overload is equivalent to calling: - * @code asio::async_read_at( - * d, 42, b, - * asio::transfer_all(), - * handler); @endcode - */ -template -void async_read_at(AsyncRandomAccessReadDevice& d, boost::uint64_t offset, - basic_streambuf& b, ReadHandler handler); - -/// Start an asynchronous operation to read a certain amount of data at the -/// specified offset. -/** - * This function is used to asynchronously read a certain number of bytes of - * data from a random access device at the specified offset. The function call - * always returns immediately. The asynchronous operation will continue until - * one of the following conditions is true: - * - * @li The completion_condition function object returns true. - * - * This operation is implemented in terms of one or more calls to the device's - * async_read_some_at function. - * - * @param d The device from which the data is to be read. The type must support - * the AsyncRandomAccessReadDevice concept. - * - * @param offset The offset at which the data will be read. - * - * @param b A basic_streambuf object into which the data will be read. Ownership - * of the streambuf is retained by the caller, which must guarantee that it - * remains valid until the handler is called. - * - * @param completion_condition The function object to be called to determine - * whether the read operation is complete. The signature of the function object - * must be: - * @code bool completion_condition( - * // Result of latest read_some_at operation. - * const asio::error_code& error, - * - * // Number of bytes transferred so far. - * std::size_t bytes_transferred - * ); @endcode - * A return value of true indicates that the read operation is complete. False - * indicates that further calls to the device's async_read_some_at function are - * required. - * - * @param handler The handler to be called when the read operation completes. - * Copies will be made of the handler as required. The function signature of the - * handler must be: - * @code void handler( - * // Result of operation. - * const asio::error_code& error, - * - * // Number of bytes copied into the buffers. If an error - * // occurred, this will be the number of bytes successfully - * // transferred prior to the error. - * std::size_t bytes_transferred - * ); @endcode - * Regardless of whether the asynchronous operation completes immediately or - * not, the handler will not be invoked from within this function. Invocation of - * the handler will be performed in a manner equivalent to using - * asio::io_service::post(). - */ -template -void async_read_at(AsyncRandomAccessReadDevice& d, - boost::uint64_t offset, basic_streambuf& b, - CompletionCondition completion_condition, ReadHandler handler); - -/*@}*/ - -} // namespace asio - -#include "asio/impl/read_at.ipp" - -#include "asio/detail/pop_options.hpp" - -#endif // ASIO_READ_AT_HPP diff --git a/libtorrent/include/asio/read_until.hpp b/libtorrent/include/asio/read_until.hpp deleted file mode 100644 index 69922e266..000000000 --- a/libtorrent/include/asio/read_until.hpp +++ /dev/null @@ -1,823 +0,0 @@ -// -// read_until.hpp -// ~~~~~~~~~~~~~~ -// -// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -#ifndef ASIO_READ_UNTIL_HPP -#define ASIO_READ_UNTIL_HPP - -#if defined(_MSC_VER) && (_MSC_VER >= 1200) -# pragma once -#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) - -#include "asio/detail/push_options.hpp" - -#include "asio/detail/push_options.hpp" -#include -#include -#include -#include -#include -#include -#include -#include "asio/detail/pop_options.hpp" - -#include "asio/basic_streambuf.hpp" -#include "asio/error.hpp" - -namespace asio { - -namespace detail -{ - template - struct has_result_type - { - struct big { char a[100]; }; - template static big helper(U, ...); - template static char helper(U, typename U::result_type* = 0); - static const T& ref(); - enum { value = (sizeof((helper)((ref)())) == 1) }; - }; -} // namespace detail - -/// Type trait used to determine whether a type can be used as a match condition -/// function with read_until and async_read_until. -template -struct is_match_condition -{ -#if defined(GENERATING_DOCUMENTATION) - /// The value member is true if the type may be used as a match condition. - static const bool value; -#else - enum - { - value = boost::is_function::type>::value - || detail::has_result_type::value - }; -#endif -}; - -/** - * @defgroup read_until asio::read_until - * - * @brief Read data into a streambuf until it contains a delimiter, matches a - * regular expression, or a function object indicates a match. - */ -/*@{*/ - -/// Read data into a streambuf until it contains a specified delimiter. -/** - * This function is used to read data into the specified streambuf until the - * streambuf's get area contains the specified delimiter. The call will block - * until one of the following conditions is true: - * - * @li The get area of the streambuf contains the specified delimiter. - * - * @li An error occurred. - * - * This operation is implemented in terms of zero or more calls to the stream's - * read_some function. If the streambuf's get area already contains the - * delimiter, the function returns immediately. - * - * @param s The stream from which the data is to be read. The type must support - * the SyncReadStream concept. - * - * @param b A streambuf object into which the data will be read. - * - * @param delim The delimiter character. - * - * @returns The number of bytes in the streambuf's get area up to and including - * the delimiter. - * - * @throws asio::system_error Thrown on failure. - * - * @note After a successful read_until operation, the streambuf may contain - * additional data beyond the delimiter. An application will typically leave - * that data in the streambuf for a subsequent read_until operation to examine. - * - * @par Example - * To read data into a streambuf until a newline is encountered: - * @code asio::streambuf b; - * asio::read_until(s, b, '\n'); - * std::istream is(&b); - * std::string line; - * std::getline(is, line); @endcode - */ -template -std::size_t read_until(SyncReadStream& s, - asio::basic_streambuf& b, char delim); - -/// Read data into a streambuf until it contains a specified delimiter. -/** - * This function is used to read data into the specified streambuf until the - * streambuf's get area contains the specified delimiter. The call will block - * until one of the following conditions is true: - * - * @li The get area of the streambuf contains the specified delimiter. - * - * @li An error occurred. - * - * This operation is implemented in terms of zero or more calls to the stream's - * read_some function. If the streambuf's get area already contains the - * delimiter, the function returns immediately. - * - * @param s The stream from which the data is to be read. The type must support - * the SyncReadStream concept. - * - * @param b A streambuf object into which the data will be read. - * - * @param delim The delimiter character. - * - * @param ec Set to indicate what error occurred, if any. - * - * @returns The number of bytes in the streambuf's get area up to and including - * the delimiter. Returns 0 if an error occurred. - * - * @note After a successful read_until operation, the streambuf may contain - * additional data beyond the delimiter. An application will typically leave - * that data in the streambuf for a subsequent read_until operation to examine. - */ -template -std::size_t read_until(SyncReadStream& s, - asio::basic_streambuf& b, char delim, - asio::error_code& ec); - -/// Read data into a streambuf until it contains a specified delimiter. -/** - * This function is used to read data into the specified streambuf until the - * streambuf's get area contains the specified delimiter. The call will block - * until one of the following conditions is true: - * - * @li The get area of the streambuf contains the specified delimiter. - * - * @li An error occurred. - * - * This operation is implemented in terms of zero or more calls to the stream's - * read_some function. If the streambuf's get area already contains the - * delimiter, the function returns immediately. - * - * @param s The stream from which the data is to be read. The type must support - * the SyncReadStream concept. - * - * @param b A streambuf object into which the data will be read. - * - * @param delim The delimiter string. - * - * @returns The number of bytes in the streambuf's get area up to and including - * the delimiter. - * - * @throws asio::system_error Thrown on failure. - * - * @note After a successful read_until operation, the streambuf may contain - * additional data beyond the delimiter. An application will typically leave - * that data in the streambuf for a subsequent read_until operation to examine. - * - * @par Example - * To read data into a streambuf until a newline is encountered: - * @code asio::streambuf b; - * asio::read_until(s, b, "\r\n"); - * std::istream is(&b); - * std::string line; - * std::getline(is, line); @endcode - */ -template -std::size_t read_until(SyncReadStream& s, - asio::basic_streambuf& b, const std::string& delim); - -/// Read data into a streambuf until it contains a specified delimiter. -/** - * This function is used to read data into the specified streambuf until the - * streambuf's get area contains the specified delimiter. The call will block - * until one of the following conditions is true: - * - * @li The get area of the streambuf contains the specified delimiter. - * - * @li An error occurred. - * - * This operation is implemented in terms of zero or more calls to the stream's - * read_some function. If the streambuf's get area already contains the - * delimiter, the function returns immediately. - * - * @param s The stream from which the data is to be read. The type must support - * the SyncReadStream concept. - * - * @param b A streambuf object into which the data will be read. - * - * @param delim The delimiter string. - * - * @param ec Set to indicate what error occurred, if any. - * - * @returns The number of bytes in the streambuf's get area up to and including - * the delimiter. Returns 0 if an error occurred. - * - * @note After a successful read_until operation, the streambuf may contain - * additional data beyond the delimiter. An application will typically leave - * that data in the streambuf for a subsequent read_until operation to examine. - */ -template -std::size_t read_until(SyncReadStream& s, - asio::basic_streambuf& b, const std::string& delim, - asio::error_code& ec); - -/// Read data into a streambuf until some part of the data it contains matches -/// a regular expression. -/** - * This function is used to read data into the specified streambuf until the - * streambuf's get area contains some data that matches a regular expression. - * The call will block until one of the following conditions is true: - * - * @li A substring of the streambuf's get area matches the regular expression. - * - * @li An error occurred. - * - * This operation is implemented in terms of zero or more calls to the stream's - * read_some function. If the streambuf's get area already contains data that - * matches the regular expression, the function returns immediately. - * - * @param s The stream from which the data is to be read. The type must support - * the SyncReadStream concept. - * - * @param b A streambuf object into which the data will be read. - * - * @param expr The regular expression. - * - * @returns The number of bytes in the streambuf's get area up to and including - * the substring that matches the regular expression. - * - * @throws asio::system_error Thrown on failure. - * - * @note After a successful read_until operation, the streambuf may contain - * additional data beyond that which matched the regular expression. An - * application will typically leave that data in the streambuf for a subsequent - * read_until operation to examine. - * - * @par Example - * To read data into a streambuf until a CR-LF sequence is encountered: - * @code asio::streambuf b; - * asio::read_until(s, b, boost::regex("\r\n")); - * std::istream is(&b); - * std::string line; - * std::getline(is, line); @endcode - */ -template -std::size_t read_until(SyncReadStream& s, - asio::basic_streambuf& b, const boost::regex& expr); - -/// Read data into a streambuf until some part of the data it contains matches -/// a regular expression. -/** - * This function is used to read data into the specified streambuf until the - * streambuf's get area contains some data that matches a regular expression. - * The call will block until one of the following conditions is true: - * - * @li A substring of the streambuf's get area matches the regular expression. - * - * @li An error occurred. - * - * This operation is implemented in terms of zero or more calls to the stream's - * read_some function. If the streambuf's get area already contains data that - * matches the regular expression, the function returns immediately. - * - * @param s The stream from which the data is to be read. The type must support - * the SyncReadStream concept. - * - * @param b A streambuf object into which the data will be read. - * - * @param expr The regular expression. - * - * @param ec Set to indicate what error occurred, if any. - * - * @returns The number of bytes in the streambuf's get area up to and including - * the substring that matches the regular expression. Returns 0 if an error - * occurred. - * - * @note After a successful read_until operation, the streambuf may contain - * additional data beyond that which matched the regular expression. An - * application will typically leave that data in the streambuf for a subsequent - * read_until operation to examine. - */ -template -std::size_t read_until(SyncReadStream& s, - asio::basic_streambuf& b, const boost::regex& expr, - asio::error_code& ec); - -/// Read data into a streambuf until a function object indicates a match. -/** - * This function is used to read data into the specified streambuf until a - * user-defined match condition function object, when applied to the data - * contained in the streambuf, indicates a successful match. The call will - * block until one of the following conditions is true: - * - * @li The match condition function object returns a std::pair where the second - * element evaluates to true. - * - * @li An error occurred. - * - * This operation is implemented in terms of zero or more calls to the stream's - * read_some function. If the match condition function object already indicates - * a match, the function returns immediately. - * - * @param s The stream from which the data is to be read. The type must support - * the SyncReadStream concept. - * - * @param b A streambuf object into which the data will be read. - * - * @param match_condition The function object to be called to determine whether - * a match exists. The signature of the function object must be: - * @code pair match_condition(iterator begin, iterator end); - * @endcode - * where @c iterator represents the type: - * @code buffers_iterator::const_buffers_type> - * @endcode - * The iterator parameters @c begin and @c end define the range of bytes to be - * scanned to determine whether there is a match. The @c first member of the - * return value is an iterator marking one-past-the-end of the bytes that have - * been consumed by the match function. This iterator is used to calculate the - * @c begin parameter for any subsequent invocation of the match condition. The - * @c second member of the return value is true if a match has been found, false - * otherwise. - * - * @returns The number of bytes in the streambuf's get area that have been fully - * consumed by the match function. - * - * @throws asio::system_error Thrown on failure. - * - * @note After a successful read_until operation, the streambuf may contain - * additional data beyond that which matched the function object. An application - * will typically leave that data in the streambuf for a subsequent - * - * @note The default implementation of the @c is_match_condition type trait - * evaluates to true for function pointers and function objects with a - * @c result_type typedef. It must be specialised for other user-defined - * function objects. - * - * @par Examples - * To read data into a streambuf until whitespace is encountered: - * @code typedef asio::buffers_iterator< - * asio::streambuf::const_buffers_type> iterator; - * - * std::pair - * match_whitespace(iterator begin, iterator end) - * { - * iterator i = begin; - * while (i != end) - * if (std::isspace(*i++)) - * return std::make_pair(i, true); - * return std::make_pair(i, false); - * } - * ... - * asio::streambuf b; - * asio::read_until(s, b, match_whitespace); - * @endcode - * - * To read data into a streambuf until a matching character is found: - * @code class match_char - * { - * public: - * explicit match_char(char c) : c_(c) {} - * - * template - * std::pair operator()( - * Iterator begin, Iterator end) const - * { - * Iterator i = begin; - * while (i != end) - * if (c_ == *i++) - * return std::make_pair(i, true); - * return std::make_pair(i, false); - * } - * - * private: - * char c_; - * }; - * - * namespace asio { - * template <> struct is_match_condition - * : public boost::true_type {}; - * } // namespace asio - * ... - * asio::streambuf b; - * asio::read_until(s, b, match_char('a')); - * @endcode - */ -template -std::size_t read_until(SyncReadStream& s, - asio::basic_streambuf& b, MatchCondition match_condition, - typename boost::enable_if >::type* = 0); - -/// Read data into a streambuf until a function object indicates a match. -/** - * This function is used to read data into the specified streambuf until a - * user-defined match condition function object, when applied to the data - * contained in the streambuf, indicates a successful match. The call will - * block until one of the following conditions is true: - * - * @li The match condition function object returns a std::pair where the second - * element evaluates to true. - * - * @li An error occurred. - * - * This operation is implemented in terms of zero or more calls to the stream's - * read_some function. If the match condition function object already indicates - * a match, the function returns immediately. - * - * @param s The stream from which the data is to be read. The type must support - * the SyncReadStream concept. - * - * @param b A streambuf object into which the data will be read. - * - * @param match_condition The function object to be called to determine whether - * a match exists. The signature of the function object must be: - * @code pair match_condition(iterator begin, iterator end); - * @endcode - * where @c iterator represents the type: - * @code buffers_iterator::const_buffers_type> - * @endcode - * The iterator parameters @c begin and @c end define the range of bytes to be - * scanned to determine whether there is a match. The @c first member of the - * return value is an iterator marking one-past-the-end of the bytes that have - * been consumed by the match function. This iterator is used to calculate the - * @c begin parameter for any subsequent invocation of the match condition. The - * @c second member of the return value is true if a match has been found, false - * otherwise. - * - * @param ec Set to indicate what error occurred, if any. - * - * @returns The number of bytes in the streambuf's get area that have been fully - * consumed by the match function. Returns 0 if an error occurred. - * - * @note After a successful read_until operation, the streambuf may contain - * additional data beyond that which matched the function object. An application - * will typically leave that data in the streambuf for a subsequent - * - * @note The default implementation of the @c is_match_condition type trait - * evaluates to true for function pointers and function objects with a - * @c result_type typedef. It must be specialised for other user-defined - * function objects. - */ -template -std::size_t read_until(SyncReadStream& s, - asio::basic_streambuf& b, - MatchCondition match_condition, asio::error_code& ec, - typename boost::enable_if >::type* = 0); - -/*@}*/ -/** - * @defgroup async_read_until asio::async_read_until - * - * @brief Start an asynchronous operation to read data into a streambuf until it - * contains a delimiter, matches a regular expression, or a function object - * indicates a match. - */ -/*@{*/ - -/// Start an asynchronous operation to read data into a streambuf until it -/// contains a specified delimiter. -/** - * This function is used to asynchronously read data into the specified - * streambuf until the streambuf's get area contains the specified delimiter. - * The function call always returns immediately. The asynchronous operation - * will continue until one of the following conditions is true: - * - * @li The get area of the streambuf contains the specified delimiter. - * - * @li An error occurred. - * - * This operation is implemented in terms of zero or more calls to the stream's - * async_read_some function. If the streambuf's get area already contains the - * delimiter, the asynchronous operation completes immediately. - * - * @param s The stream from which the data is to be read. The type must support - * the AsyncReadStream concept. - * - * @param b A streambuf object into which the data will be read. Ownership of - * the streambuf is retained by the caller, which must guarantee that it remains - * valid until the handler is called. - * - * @param delim The delimiter character. - * - * @param handler The handler to be called when the read operation completes. - * Copies will be made of the handler as required. The function signature of the - * handler must be: - * @code void handler( - * // Result of operation. - * const asio::error_code& error, - * - * // The number of bytes in the streambuf's get - * // area up to and including the delimiter. - * // 0 if an error occurred. - * std::size_t bytes_transferred - * ); @endcode - * Regardless of whether the asynchronous operation completes immediately or - * not, the handler will not be invoked from within this function. Invocation of - * the handler will be performed in a manner equivalent to using - * asio::io_service::post(). - * - * @note After a successful async_read_until operation, the streambuf may - * contain additional data beyond the delimiter. An application will typically - * leave that data in the streambuf for a subsequent async_read_until operation - * to examine. - * - * @par Example - * To asynchronously read data into a streambuf until a newline is encountered: - * @code asio::streambuf b; - * ... - * void handler(const asio::error_code& e, std::size_t size) - * { - * if (!e) - * { - * std::istream is(&b); - * std::string line; - * std::getline(is, line); - * ... - * } - * } - * ... - * asio::async_read_until(s, b, '\n', handler); @endcode - */ -template -void async_read_until(AsyncReadStream& s, - asio::basic_streambuf& b, - char delim, ReadHandler handler); - -/// Start an asynchronous operation to read data into a streambuf until it -/// contains a specified delimiter. -/** - * This function is used to asynchronously read data into the specified - * streambuf until the streambuf's get area contains the specified delimiter. - * The function call always returns immediately. The asynchronous operation - * will continue until one of the following conditions is true: - * - * @li The get area of the streambuf contains the specified delimiter. - * - * @li An error occurred. - * - * This operation is implemented in terms of zero or more calls to the stream's - * async_read_some function. If the streambuf's get area already contains the - * delimiter, the asynchronous operation completes immediately. - * - * @param s The stream from which the data is to be read. The type must support - * the AsyncReadStream concept. - * - * @param b A streambuf object into which the data will be read. Ownership of - * the streambuf is retained by the caller, which must guarantee that it remains - * valid until the handler is called. - * - * @param delim The delimiter string. - * - * @param handler The handler to be called when the read operation completes. - * Copies will be made of the handler as required. The function signature of the - * handler must be: - * @code void handler( - * // Result of operation. - * const asio::error_code& error, - * - * // The number of bytes in the streambuf's get - * // area up to and including the delimiter. - * // 0 if an error occurred. - * std::size_t bytes_transferred - * ); @endcode - * Regardless of whether the asynchronous operation completes immediately or - * not, the handler will not be invoked from within this function. Invocation of - * the handler will be performed in a manner equivalent to using - * asio::io_service::post(). - * - * @note After a successful async_read_until operation, the streambuf may - * contain additional data beyond the delimiter. An application will typically - * leave that data in the streambuf for a subsequent async_read_until operation - * to examine. - * - * @par Example - * To asynchronously read data into a streambuf until a newline is encountered: - * @code asio::streambuf b; - * ... - * void handler(const asio::error_code& e, std::size_t size) - * { - * if (!e) - * { - * std::istream is(&b); - * std::string line; - * std::getline(is, line); - * ... - * } - * } - * ... - * asio::async_read_until(s, b, "\r\n", handler); @endcode - */ -template -void async_read_until(AsyncReadStream& s, - asio::basic_streambuf& b, const std::string& delim, - ReadHandler handler); - -/// Start an asynchronous operation to read data into a streambuf until some -/// part of its data matches a regular expression. -/** - * This function is used to asynchronously read data into the specified - * streambuf until the streambuf's get area contains some data that matches a - * regular expression. The function call always returns immediately. The - * asynchronous operation will continue until one of the following conditions - * is true: - * - * @li A substring of the streambuf's get area matches the regular expression. - * - * @li An error occurred. - * - * This operation is implemented in terms of zero or more calls to the stream's - * async_read_some function. If the streambuf's get area already contains data - * that matches the regular expression, the function returns immediately. - * - * @param s The stream from which the data is to be read. The type must support - * the AsyncReadStream concept. - * - * @param b A streambuf object into which the data will be read. Ownership of - * the streambuf is retained by the caller, which must guarantee that it remains - * valid until the handler is called. - * - * @param expr The regular expression. - * - * @param handler The handler to be called when the read operation completes. - * Copies will be made of the handler as required. The function signature of the - * handler must be: - * @code void handler( - * // Result of operation. - * const asio::error_code& error, - * - * // The number of bytes in the streambuf's get - * // area up to and including the substring - * // that matches the regular. expression. - * // 0 if an error occurred. - * std::size_t bytes_transferred - * ); @endcode - * Regardless of whether the asynchronous operation completes immediately or - * not, the handler will not be invoked from within this function. Invocation of - * the handler will be performed in a manner equivalent to using - * asio::io_service::post(). - * - * @note After a successful async_read_until operation, the streambuf may - * contain additional data beyond that which matched the regular expression. An - * application will typically leave that data in the streambuf for a subsequent - * async_read_until operation to examine. - * - * @par Example - * To asynchronously read data into a streambuf until a CR-LF sequence is - * encountered: - * @code asio::streambuf b; - * ... - * void handler(const asio::error_code& e, std::size_t size) - * { - * if (!e) - * { - * std::istream is(&b); - * std::string line; - * std::getline(is, line); - * ... - * } - * } - * ... - * asio::async_read_until(s, b, boost::regex("\r\n"), handler); @endcode - */ -template -void async_read_until(AsyncReadStream& s, - asio::basic_streambuf& b, const boost::regex& expr, - ReadHandler handler); - -/// Start an asynchronous operation to read data into a streambuf until a -/// function object indicates a match. -/** - * This function is used to asynchronously read data into the specified - * streambuf until a user-defined match condition function object, when applied - * to the data contained in the streambuf, indicates a successful match. The - * function call always returns immediately. The asynchronous operation will - * continue until one of the following conditions is true: - * - * @li The match condition function object returns a std::pair where the second - * element evaluates to true. - * - * @li An error occurred. - * - * This operation is implemented in terms of zero or more calls to the stream's - * async_read_some function. If the match condition function object already - * indicates a match, the operation completes immediately. - * - * @param s The stream from which the data is to be read. The type must support - * the AsyncReadStream concept. - * - * @param b A streambuf object into which the data will be read. - * - * @param match_condition The function object to be called to determine whether - * a match exists. The signature of the function object must be: - * @code pair match_condition(iterator begin, iterator end); - * @endcode - * where @c iterator represents the type: - * @code buffers_iterator::const_buffers_type> - * @endcode - * The iterator parameters @c begin and @c end define the range of bytes to be - * scanned to determine whether there is a match. The @c first member of the - * return value is an iterator marking one-past-the-end of the bytes that have - * been consumed by the match function. This iterator is used to calculate the - * @c begin parameter for any subsequent invocation of the match condition. The - * @c second member of the return value is true if a match has been found, false - * otherwise. - * - * @param handler The handler to be called when the read operation completes. - * Copies will be made of the handler as required. The function signature of the - * handler must be: - * @code void handler( - * // Result of operation. - * const asio::error_code& error, - * - * // The number of bytes in the streambuf's get - * // area that have been fully consumed by the - * // match function. O if an error occurred. - * std::size_t bytes_transferred - * ); @endcode - * Regardless of whether the asynchronous operation completes immediately or - * not, the handler will not be invoked from within this function. Invocation of - * the handler will be performed in a manner equivalent to using - * asio::io_service::post(). - * - * @note After a successful async_read_until operation, the streambuf may - * contain additional data beyond that which matched the function object. An - * application will typically leave that data in the streambuf for a subsequent - * async_read_until operation to examine. - * - * @note The default implementation of the @c is_match_condition type trait - * evaluates to true for function pointers and function objects with a - * @c result_type typedef. It must be specialised for other user-defined - * function objects. - * - * @par Examples - * To asynchronously read data into a streambuf until whitespace is encountered: - * @code typedef asio::buffers_iterator< - * asio::streambuf::const_buffers_type> iterator; - * - * std::pair - * match_whitespace(iterator begin, iterator end) - * { - * iterator i = begin; - * while (i != end) - * if (std::isspace(*i++)) - * return std::make_pair(i, true); - * return std::make_pair(i, false); - * } - * ... - * void handler(const asio::error_code& e, std::size_t size); - * ... - * asio::streambuf b; - * asio::async_read_until(s, b, match_whitespace, handler); - * @endcode - * - * To asynchronously read data into a streambuf until a matching character is - * found: - * @code class match_char - * { - * public: - * explicit match_char(char c) : c_(c) {} - * - * template - * std::pair operator()( - * Iterator begin, Iterator end) const - * { - * Iterator i = begin; - * while (i != end) - * if (c_ == *i++) - * return std::make_pair(i, true); - * return std::make_pair(i, false); - * } - * - * private: - * char c_; - * }; - * - * namespace asio { - * template <> struct is_match_condition - * : public boost::true_type {}; - * } // namespace asio - * ... - * void handler(const asio::error_code& e, std::size_t size); - * ... - * asio::streambuf b; - * asio::async_read_until(s, b, match_char('a'), handler); - * @endcode - */ -template -void async_read_until(AsyncReadStream& s, - asio::basic_streambuf& b, - MatchCondition match_condition, ReadHandler handler, - typename boost::enable_if >::type* = 0); - -/*@}*/ - -} // namespace asio - -#include "asio/impl/read_until.ipp" - -#include "asio/detail/pop_options.hpp" - -#endif // ASIO_READ_UNTIL_HPP diff --git a/libtorrent/include/asio/serial_port.hpp b/libtorrent/include/asio/serial_port.hpp deleted file mode 100644 index 608ba299a..000000000 --- a/libtorrent/include/asio/serial_port.hpp +++ /dev/null @@ -1,38 +0,0 @@ -// -// serial_port.hpp -// ~~~~~~~~~~~~~~~ -// -// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// Copyright (c) 2008 Rep Invariant Systems, Inc. (info@repinvariant.com) -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -#ifndef ASIO_SERIAL_PORT_HPP -#define ASIO_SERIAL_PORT_HPP - -#if defined(_MSC_VER) && (_MSC_VER >= 1200) -# pragma once -#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) - -#include "asio/detail/push_options.hpp" - -#include "asio/basic_serial_port.hpp" - -#if defined(ASIO_HAS_SERIAL_PORT) \ - || defined(GENERATING_DOCUMENTATION) - -namespace asio { - -/// Typedef for the typical usage of a serial port. -typedef basic_serial_port<> serial_port; - -} // namespace asio - -#endif // defined(ASIO_HAS_SERIAL_PORT) - // || defined(GENERATING_DOCUMENTATION) - -#include "asio/detail/pop_options.hpp" - -#endif // ASIO_SERIAL_PORT_HPP diff --git a/libtorrent/include/asio/serial_port_base.hpp b/libtorrent/include/asio/serial_port_base.hpp deleted file mode 100644 index 2f3d7025b..000000000 --- a/libtorrent/include/asio/serial_port_base.hpp +++ /dev/null @@ -1,157 +0,0 @@ -// -// serial_port_base.hpp -// ~~~~~~~~~~~~~~~~~~~~ -// -// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// Copyright (c) 2008 Rep Invariant Systems, Inc. (info@repinvariant.com) -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -#ifndef ASIO_SERIAL_PORT_BASE_HPP -#define ASIO_SERIAL_PORT_BASE_HPP - -#if defined(_MSC_VER) && (_MSC_VER >= 1200) -# pragma once -#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) - -#include "asio/detail/push_options.hpp" - -#include "asio/detail/push_options.hpp" -#include -#include -#include -#if !defined(BOOST_WINDOWS) && !defined(__CYGWIN__) -# include -#endif -#include "asio/detail/pop_options.hpp" - -#include "asio/error_code.hpp" -#include "asio/detail/socket_types.hpp" - -#if defined(GENERATING_DOCUMENTATION) -# define ASIO_OPTION_STORAGE implementation_defined -#elif defined(BOOST_WINDOWS) || defined(__CYGWIN__) -# define ASIO_OPTION_STORAGE DCB -#else -# define ASIO_OPTION_STORAGE termios -#endif - -namespace asio { - -/// The serial_port_base class is used as a base for the basic_serial_port class -/// template so that we have a common place to define the serial port options. -class serial_port_base -{ -public: - /// Serial port option to permit changing the baud rate. - /** - * Implements changing the baud rate for a given serial port. - */ - class baud_rate - { - public: - explicit baud_rate(unsigned int rate = 0); - unsigned int value() const; - asio::error_code store(ASIO_OPTION_STORAGE& storage, - asio::error_code& ec) const; - asio::error_code load(const ASIO_OPTION_STORAGE& storage, - asio::error_code& ec); - private: - unsigned int value_; - }; - - /// Serial port option to permit changing the flow control. - /** - * Implements changing the flow control for a given serial port. - */ - class flow_control - { - public: - enum type { none, software, hardware }; - explicit flow_control(type t = none); - type value() const; - asio::error_code store(ASIO_OPTION_STORAGE& storage, - asio::error_code& ec) const; - asio::error_code load(const ASIO_OPTION_STORAGE& storage, - asio::error_code& ec); - private: - type value_; - }; - - /// Serial port option to permit changing the parity. - /** - * Implements changing the parity for a given serial port. - */ - class parity - { - public: - enum type { none, odd, even }; - explicit parity(type t = none); - type value() const; - asio::error_code store(ASIO_OPTION_STORAGE& storage, - asio::error_code& ec) const; - asio::error_code load(const ASIO_OPTION_STORAGE& storage, - asio::error_code& ec); - private: - type value_; - }; - - /// Serial port option to permit changing the number of stop bits. - /** - * Implements changing the number of stop bits for a given serial port. - */ - class stop_bits - { - public: - enum type { one, onepointfive, two }; - explicit stop_bits(type t = one); - type value() const; - asio::error_code store(ASIO_OPTION_STORAGE& storage, - asio::error_code& ec) const; - asio::error_code load(const ASIO_OPTION_STORAGE& storage, - asio::error_code& ec); - private: - type value_; - }; - - /// Serial port option to permit changing the character size. - /** - * Implements changing the character size for a given serial port. - */ - class character_size - { - public: - explicit character_size(unsigned int t = 8); - unsigned int value() const; - asio::error_code store(ASIO_OPTION_STORAGE& storage, - asio::error_code& ec) const; - asio::error_code load(const ASIO_OPTION_STORAGE& storage, - asio::error_code& ec); - private: - unsigned int value_; - }; - -protected: - /// Protected destructor to prevent deletion through this type. - ~serial_port_base() - { - } - -#if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564)) -private: - // Workaround to enable the empty base optimisation with Borland C++. - char dummy_; -#endif -}; - -} // namespace asio - -#include "asio/impl/serial_port_base.ipp" - -#undef ASIO_OPTION_STORAGE - -#include "asio/detail/pop_options.hpp" - -#endif // ASIO_SERIAL_PORT_BASE_HPP diff --git a/libtorrent/include/asio/serial_port_service.hpp b/libtorrent/include/asio/serial_port_service.hpp deleted file mode 100644 index e77a53ee4..000000000 --- a/libtorrent/include/asio/serial_port_service.hpp +++ /dev/null @@ -1,222 +0,0 @@ -// -// serial_port_service.hpp -// ~~~~~~~~~~~~~~~~~~~~~~~ -// -// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -#ifndef ASIO_SERIAL_PORT_SERVICE_HPP -#define ASIO_SERIAL_PORT_SERVICE_HPP - -#if defined(_MSC_VER) && (_MSC_VER >= 1200) -# pragma once -#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) - -#include "asio/detail/push_options.hpp" - -#include "asio/detail/push_options.hpp" -#include -#include -#include -#include "asio/detail/pop_options.hpp" - -#include "asio/error.hpp" -#include "asio/io_service.hpp" -#include "asio/detail/service_base.hpp" -#include "asio/detail/reactive_serial_port_service.hpp" -#include "asio/detail/win_iocp_serial_port_service.hpp" - -#if !defined(ASIO_DISABLE_SERIAL_PORT) -# if defined(ASIO_HAS_IOCP) \ - || !defined(BOOST_WINDOWS) && !defined(__CYGWIN__) -# define ASIO_HAS_SERIAL_PORT 1 -# endif // defined(ASIO_HAS_IOCP) -#endif // !defined(ASIO_DISABLE_STREAM_HANDLE) - -#if defined(ASIO_HAS_SERIAL_PORT) \ - || defined(GENERATING_DOCUMENTATION) - -namespace asio { - -/// Default service implementation for a serial port. -class serial_port_service -#if defined(GENERATING_DOCUMENTATION) - : public asio::io_service::service -#else - : public asio::detail::service_base -#endif -{ -public: -#if defined(GENERATING_DOCUMENTATION) - /// The unique service identifier. - static asio::io_service::id id; -#endif - -private: - // The type of the platform-specific implementation. -#if defined(ASIO_HAS_IOCP) - typedef detail::win_iocp_serial_port_service service_impl_type; -#elif defined(ASIO_HAS_EPOLL) - typedef detail::reactive_serial_port_service< - detail::epoll_reactor > service_impl_type; -#elif defined(ASIO_HAS_KQUEUE) - typedef detail::reactive_serial_port_service< - detail::kqueue_reactor > service_impl_type; -#elif defined(ASIO_HAS_DEV_POLL) - typedef detail::reactive_serial_port_service< - detail::dev_poll_reactor > service_impl_type; -#else - typedef detail::reactive_serial_port_service< - detail::select_reactor > service_impl_type; -#endif - -public: - /// The type of a serial port implementation. -#if defined(GENERATING_DOCUMENTATION) - typedef implementation_defined implementation_type; -#else - typedef service_impl_type::implementation_type implementation_type; -#endif - - /// The native handle type. -#if defined(GENERATING_DOCUMENTATION) - typedef implementation_defined native_type; -#else - typedef service_impl_type::native_type native_type; -#endif - - /// Construct a new serial port service for the specified io_service. - explicit serial_port_service(asio::io_service& io_service) - : asio::detail::service_base(io_service), - service_impl_(asio::use_service(io_service)) - { - } - - /// Destroy all user-defined handler objects owned by the service. - void shutdown_service() - { - } - - /// Construct a new serial port implementation. - void construct(implementation_type& impl) - { - service_impl_.construct(impl); - } - - /// Destroy a serial port implementation. - void destroy(implementation_type& impl) - { - service_impl_.destroy(impl); - } - - /// Open a serial port. - asio::error_code open(implementation_type& impl, - const std::string& device, asio::error_code& ec) - { - return service_impl_.open(impl, device, ec); - } - - /// Assign an existing native handle to a serial port. - asio::error_code assign(implementation_type& impl, - const native_type& native_handle, asio::error_code& ec) - { - return service_impl_.assign(impl, native_handle, ec); - } - - /// Determine whether the handle is open. - bool is_open(const implementation_type& impl) const - { - return service_impl_.is_open(impl); - } - - /// Close a serial port implementation. - asio::error_code close(implementation_type& impl, - asio::error_code& ec) - { - return service_impl_.close(impl, ec); - } - - /// Get the native handle implementation. - native_type native(implementation_type& impl) - { - return service_impl_.native(impl); - } - - /// Cancel all asynchronous operations associated with the handle. - asio::error_code cancel(implementation_type& impl, - asio::error_code& ec) - { - return service_impl_.cancel(impl, ec); - } - - /// Set a serial port option. - template - asio::error_code set_option(implementation_type& impl, - const SettableSerialPortOption& option, asio::error_code& ec) - { - return service_impl_.set_option(impl, option, ec); - } - - /// Get a serial port option. - template - asio::error_code get_option(const implementation_type& impl, - GettableSerialPortOption& option, asio::error_code& ec) const - { - return service_impl_.get_option(impl, option, ec); - } - - /// Send a break sequence to the serial port. - asio::error_code send_break(implementation_type& impl, - asio::error_code& ec) - { - return service_impl_.send_break(impl, ec); - } - - /// Write the given data to the stream. - template - std::size_t write_some(implementation_type& impl, - const ConstBufferSequence& buffers, asio::error_code& ec) - { - return service_impl_.write_some(impl, buffers, ec); - } - - /// Start an asynchronous write. - template - void async_write_some(implementation_type& impl, - const ConstBufferSequence& buffers, WriteHandler handler) - { - service_impl_.async_write_some(impl, buffers, handler); - } - - /// Read some data from the stream. - template - std::size_t read_some(implementation_type& impl, - const MutableBufferSequence& buffers, asio::error_code& ec) - { - return service_impl_.read_some(impl, buffers, ec); - } - - /// Start an asynchronous read. - template - void async_read_some(implementation_type& impl, - const MutableBufferSequence& buffers, ReadHandler handler) - { - service_impl_.async_read_some(impl, buffers, handler); - } - -private: - // The service that provides the platform-specific implementation. - service_impl_type& service_impl_; -}; - -} // namespace asio - -#endif // defined(ASIO_HAS_SERIAL_PORT) - // || defined(GENERATING_DOCUMENTATION) - -#include "asio/detail/pop_options.hpp" - -#endif // ASIO_SERIAL_PORT_SERVICE_HPP diff --git a/libtorrent/include/asio/socket_acceptor_service.hpp b/libtorrent/include/asio/socket_acceptor_service.hpp deleted file mode 100644 index 48a6df256..000000000 --- a/libtorrent/include/asio/socket_acceptor_service.hpp +++ /dev/null @@ -1,225 +0,0 @@ -// -// socket_acceptor_service.hpp -// ~~~~~~~~~~~~~~~~~~~~~~~~~~~ -// -// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -#ifndef ASIO_SOCKET_ACCEPTOR_SERVICE_HPP -#define ASIO_SOCKET_ACCEPTOR_SERVICE_HPP - -#if defined(_MSC_VER) && (_MSC_VER >= 1200) -# pragma once -#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) - -#include "asio/detail/push_options.hpp" - -#include "asio/basic_socket.hpp" -#include "asio/error.hpp" -#include "asio/io_service.hpp" -#include "asio/detail/epoll_reactor.hpp" -#include "asio/detail/kqueue_reactor.hpp" -#include "asio/detail/select_reactor.hpp" -#include "asio/detail/service_base.hpp" -#include "asio/detail/reactive_socket_service.hpp" -#include "asio/detail/win_iocp_socket_service.hpp" - -namespace asio { - -/// Default service implementation for a socket acceptor. -template -class socket_acceptor_service -#if defined(GENERATING_DOCUMENTATION) - : public asio::io_service::service -#else - : public asio::detail::service_base > -#endif -{ -public: -#if defined(GENERATING_DOCUMENTATION) - /// The unique service identifier. - static asio::io_service::id id; -#endif - - /// The protocol type. - typedef Protocol protocol_type; - - /// The endpoint type. - typedef typename protocol_type::endpoint endpoint_type; - -private: - // The type of the platform-specific implementation. -#if defined(ASIO_HAS_IOCP) - typedef detail::win_iocp_socket_service service_impl_type; -#elif defined(ASIO_HAS_EPOLL) - typedef detail::reactive_socket_service< - Protocol, detail::epoll_reactor > service_impl_type; -#elif defined(ASIO_HAS_KQUEUE) - typedef detail::reactive_socket_service< - Protocol, detail::kqueue_reactor > service_impl_type; -#elif defined(ASIO_HAS_DEV_POLL) - typedef detail::reactive_socket_service< - Protocol, detail::dev_poll_reactor > service_impl_type; -#else - typedef detail::reactive_socket_service< - Protocol, detail::select_reactor > service_impl_type; -#endif - -public: - /// The native type of the socket acceptor. -#if defined(GENERATING_DOCUMENTATION) - typedef implementation_defined implementation_type; -#else - typedef typename service_impl_type::implementation_type implementation_type; -#endif - - /// The native acceptor type. -#if defined(GENERATING_DOCUMENTATION) - typedef implementation_defined native_type; -#else - typedef typename service_impl_type::native_type native_type; -#endif - - /// Construct a new socket acceptor service for the specified io_service. - explicit socket_acceptor_service(asio::io_service& io_service) - : asio::detail::service_base< - socket_acceptor_service >(io_service), - service_impl_(asio::use_service(io_service)) - { - } - - /// Destroy all user-defined handler objects owned by the service. - void shutdown_service() - { - } - - /// Construct a new socket acceptor implementation. - void construct(implementation_type& impl) - { - service_impl_.construct(impl); - } - - /// Destroy a socket acceptor implementation. - void destroy(implementation_type& impl) - { - service_impl_.destroy(impl); - } - - /// Open a new socket acceptor implementation. - asio::error_code open(implementation_type& impl, - const protocol_type& protocol, asio::error_code& ec) - { - return service_impl_.open(impl, protocol, ec); - } - - /// Assign an existing native acceptor to a socket acceptor. - asio::error_code assign(implementation_type& impl, - const protocol_type& protocol, const native_type& native_acceptor, - asio::error_code& ec) - { - return service_impl_.assign(impl, protocol, native_acceptor, ec); - } - - /// Determine whether the acceptor is open. - bool is_open(const implementation_type& impl) const - { - return service_impl_.is_open(impl); - } - - /// Cancel all asynchronous operations associated with the acceptor. - asio::error_code cancel(implementation_type& impl, - asio::error_code& ec) - { - return service_impl_.cancel(impl, ec); - } - - /// Bind the socket acceptor to the specified local endpoint. - asio::error_code bind(implementation_type& impl, - const endpoint_type& endpoint, asio::error_code& ec) - { - return service_impl_.bind(impl, endpoint, ec); - } - - /// Place the socket acceptor into the state where it will listen for new - /// connections. - asio::error_code listen(implementation_type& impl, int backlog, - asio::error_code& ec) - { - return service_impl_.listen(impl, backlog, ec); - } - - /// Close a socket acceptor implementation. - asio::error_code close(implementation_type& impl, - asio::error_code& ec) - { - return service_impl_.close(impl, ec); - } - - /// Get the native acceptor implementation. - native_type native(implementation_type& impl) - { - return service_impl_.native(impl); - } - - /// Set a socket option. - template - asio::error_code set_option(implementation_type& impl, - const SettableSocketOption& option, asio::error_code& ec) - { - return service_impl_.set_option(impl, option, ec); - } - - /// Get a socket option. - template - asio::error_code get_option(const implementation_type& impl, - GettableSocketOption& option, asio::error_code& ec) const - { - return service_impl_.get_option(impl, option, ec); - } - - /// Perform an IO control command on the socket. - template - asio::error_code io_control(implementation_type& impl, - IoControlCommand& command, asio::error_code& ec) - { - return service_impl_.io_control(impl, command, ec); - } - - /// Get the local endpoint. - endpoint_type local_endpoint(const implementation_type& impl, - asio::error_code& ec) const - { - return service_impl_.local_endpoint(impl, ec); - } - - /// Accept a new connection. - template - asio::error_code accept(implementation_type& impl, - basic_socket& peer, - endpoint_type* peer_endpoint, asio::error_code& ec) - { - return service_impl_.accept(impl, peer, peer_endpoint, ec); - } - - /// Start an asynchronous accept. - template - void async_accept(implementation_type& impl, - basic_socket& peer, - endpoint_type* peer_endpoint, AcceptHandler handler) - { - service_impl_.async_accept(impl, peer, peer_endpoint, handler); - } - -private: - // The service that provides the platform-specific implementation. - service_impl_type& service_impl_; -}; - -} // namespace asio - -#include "asio/detail/pop_options.hpp" - -#endif // ASIO_SOCKET_ACCEPTOR_SERVICE_HPP diff --git a/libtorrent/include/asio/socket_base.hpp b/libtorrent/include/asio/socket_base.hpp deleted file mode 100644 index 67fe6887d..000000000 --- a/libtorrent/include/asio/socket_base.hpp +++ /dev/null @@ -1,515 +0,0 @@ -// -// socket_base.hpp -// ~~~~~~~~~~~~~~~ -// -// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -#ifndef ASIO_SOCKET_BASE_HPP -#define ASIO_SOCKET_BASE_HPP - -#if defined(_MSC_VER) && (_MSC_VER >= 1200) -# pragma once -#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) - -#include "asio/detail/push_options.hpp" - -#include "asio/detail/push_options.hpp" -#include -#include -#include "asio/detail/pop_options.hpp" - -#include "asio/detail/io_control.hpp" -#include "asio/detail/socket_option.hpp" -#include "asio/detail/socket_types.hpp" - -namespace asio { - -/// The socket_base class is used as a base for the basic_stream_socket and -/// basic_datagram_socket class templates so that we have a common place to -/// define the shutdown_type and enum. -class socket_base -{ -public: - /// Different ways a socket may be shutdown. - enum shutdown_type - { -#if defined(GENERATING_DOCUMENTATION) - /// Shutdown the receive side of the socket. - shutdown_receive = implementation_defined, - - /// Shutdown the send side of the socket. - shutdown_send = implementation_defined, - - /// Shutdown both send and receive on the socket. - shutdown_both = implementation_defined -#else - shutdown_receive = asio::detail::shutdown_receive, - shutdown_send = asio::detail::shutdown_send, - shutdown_both = asio::detail::shutdown_both -#endif - }; - - /// Bitmask type for flags that can be passed to send and receive operations. - typedef int message_flags; - -#if defined(GENERATING_DOCUMENTATION) - /// Peek at incoming data without removing it from the input queue. - static const int message_peek = implementation_defined; - - /// Process out-of-band data. - static const int message_out_of_band = implementation_defined; - - /// Specify that the data should not be subject to routing. - static const int message_do_not_route = implementation_defined; -#else - BOOST_STATIC_CONSTANT(int, - message_peek = asio::detail::message_peek); - BOOST_STATIC_CONSTANT(int, - message_out_of_band = asio::detail::message_out_of_band); - BOOST_STATIC_CONSTANT(int, - message_do_not_route = asio::detail::message_do_not_route); -#endif - - /// Socket option to permit sending of broadcast messages. - /** - * Implements the SOL_SOCKET/SO_BROADCAST socket option. - * - * @par Examples - * Setting the option: - * @code - * asio::ip::udp::socket socket(io_service); - * ... - * asio::socket_base::broadcast option(true); - * socket.set_option(option); - * @endcode - * - * @par - * Getting the current option value: - * @code - * asio::ip::udp::socket socket(io_service); - * ... - * asio::socket_base::broadcast option; - * socket.get_option(option); - * bool is_set = option.value(); - * @endcode - * - * @par Concepts: - * Socket_Option, Boolean_Socket_Option. - */ -#if defined(GENERATING_DOCUMENTATION) - typedef implementation_defined broadcast; -#else - typedef asio::detail::socket_option::boolean< - SOL_SOCKET, SO_BROADCAST> broadcast; -#endif - - /// Socket option to enable socket-level debugging. - /** - * Implements the SOL_SOCKET/SO_DEBUG socket option. - * - * @par Examples - * Setting the option: - * @code - * asio::ip::tcp::socket socket(io_service); - * ... - * asio::socket_base::debug option(true); - * socket.set_option(option); - * @endcode - * - * @par - * Getting the current option value: - * @code - * asio::ip::tcp::socket socket(io_service); - * ... - * asio::socket_base::debug option; - * socket.get_option(option); - * bool is_set = option.value(); - * @endcode - * - * @par Concepts: - * Socket_Option, Boolean_Socket_Option. - */ -#if defined(GENERATING_DOCUMENTATION) - typedef implementation_defined debug; -#else - typedef asio::detail::socket_option::boolean< - SOL_SOCKET, SO_DEBUG> debug; -#endif - - /// Socket option to prevent routing, use local interfaces only. - /** - * Implements the SOL_SOCKET/SO_DONTROUTE socket option. - * - * @par Examples - * Setting the option: - * @code - * asio::ip::udp::socket socket(io_service); - * ... - * asio::socket_base::do_not_route option(true); - * socket.set_option(option); - * @endcode - * - * @par - * Getting the current option value: - * @code - * asio::ip::udp::socket socket(io_service); - * ... - * asio::socket_base::do_not_route option; - * socket.get_option(option); - * bool is_set = option.value(); - * @endcode - * - * @par Concepts: - * Socket_Option, Boolean_Socket_Option. - */ -#if defined(GENERATING_DOCUMENTATION) - typedef implementation_defined do_not_route; -#else - typedef asio::detail::socket_option::boolean< - SOL_SOCKET, SO_DONTROUTE> do_not_route; -#endif - - /// Socket option to send keep-alives. - /** - * Implements the SOL_SOCKET/SO_KEEPALIVE socket option. - * - * @par Examples - * Setting the option: - * @code - * asio::ip::tcp::socket socket(io_service); - * ... - * asio::socket_base::keep_alive option(true); - * socket.set_option(option); - * @endcode - * - * @par - * Getting the current option value: - * @code - * asio::ip::tcp::socket socket(io_service); - * ... - * asio::socket_base::keep_alive option; - * socket.get_option(option); - * bool is_set = option.value(); - * @endcode - * - * @par Concepts: - * Socket_Option, Boolean_Socket_Option. - */ -#if defined(GENERATING_DOCUMENTATION) - typedef implementation_defined keep_alive; -#else - typedef asio::detail::socket_option::boolean< - SOL_SOCKET, SO_KEEPALIVE> keep_alive; -#endif - - /// Socket option for the send buffer size of a socket. - /** - * Implements the SOL_SOCKET/SO_SNDBUF socket option. - * - * @par Examples - * Setting the option: - * @code - * asio::ip::tcp::socket socket(io_service); - * ... - * asio::socket_base::send_buffer_size option(8192); - * socket.set_option(option); - * @endcode - * - * @par - * Getting the current option value: - * @code - * asio::ip::tcp::socket socket(io_service); - * ... - * asio::socket_base::send_buffer_size option; - * socket.get_option(option); - * int size = option.value(); - * @endcode - * - * @par Concepts: - * Socket_Option, Integer_Socket_Option. - */ -#if defined(GENERATING_DOCUMENTATION) - typedef implementation_defined send_buffer_size; -#else - typedef asio::detail::socket_option::integer< - SOL_SOCKET, SO_SNDBUF> send_buffer_size; -#endif - - /// Socket option for the send low watermark. - /** - * Implements the SOL_SOCKET/SO_SNDLOWAT socket option. - * - * @par Examples - * Setting the option: - * @code - * asio::ip::tcp::socket socket(io_service); - * ... - * asio::socket_base::send_low_watermark option(1024); - * socket.set_option(option); - * @endcode - * - * @par - * Getting the current option value: - * @code - * asio::ip::tcp::socket socket(io_service); - * ... - * asio::socket_base::send_low_watermark option; - * socket.get_option(option); - * int size = option.value(); - * @endcode - * - * @par Concepts: - * Socket_Option, Integer_Socket_Option. - */ -#if defined(GENERATING_DOCUMENTATION) - typedef implementation_defined send_low_watermark; -#else - typedef asio::detail::socket_option::integer< - SOL_SOCKET, SO_SNDLOWAT> send_low_watermark; -#endif - - /// Socket option for the receive buffer size of a socket. - /** - * Implements the SOL_SOCKET/SO_RCVBUF socket option. - * - * @par Examples - * Setting the option: - * @code - * asio::ip::tcp::socket socket(io_service); - * ... - * asio::socket_base::receive_buffer_size option(8192); - * socket.set_option(option); - * @endcode - * - * @par - * Getting the current option value: - * @code - * asio::ip::tcp::socket socket(io_service); - * ... - * asio::socket_base::receive_buffer_size option; - * socket.get_option(option); - * int size = option.value(); - * @endcode - * - * @par Concepts: - * Socket_Option, Integer_Socket_Option. - */ -#if defined(GENERATING_DOCUMENTATION) - typedef implementation_defined receive_buffer_size; -#else - typedef asio::detail::socket_option::integer< - SOL_SOCKET, SO_RCVBUF> receive_buffer_size; -#endif - - /// Socket option for the receive low watermark. - /** - * Implements the SOL_SOCKET/SO_RCVLOWAT socket option. - * - * @par Examples - * Setting the option: - * @code - * asio::ip::tcp::socket socket(io_service); - * ... - * asio::socket_base::receive_low_watermark option(1024); - * socket.set_option(option); - * @endcode - * - * @par - * Getting the current option value: - * @code - * asio::ip::tcp::socket socket(io_service); - * ... - * asio::socket_base::receive_low_watermark option; - * socket.get_option(option); - * int size = option.value(); - * @endcode - * - * @par Concepts: - * Socket_Option, Integer_Socket_Option. - */ -#if defined(GENERATING_DOCUMENTATION) - typedef implementation_defined receive_low_watermark; -#else - typedef asio::detail::socket_option::integer< - SOL_SOCKET, SO_RCVLOWAT> receive_low_watermark; -#endif - - /// Socket option to allow the socket to be bound to an address that is - /// already in use. - /** - * Implements the SOL_SOCKET/SO_REUSEADDR socket option. - * - * @par Examples - * Setting the option: - * @code - * asio::ip::tcp::acceptor acceptor(io_service); - * ... - * asio::socket_base::reuse_address option(true); - * acceptor.set_option(option); - * @endcode - * - * @par - * Getting the current option value: - * @code - * asio::ip::tcp::acceptor acceptor(io_service); - * ... - * asio::socket_base::reuse_address option; - * acceptor.get_option(option); - * bool is_set = option.value(); - * @endcode - * - * @par Concepts: - * Socket_Option, Boolean_Socket_Option. - */ -#if defined(GENERATING_DOCUMENTATION) - typedef implementation_defined reuse_address; -#else - typedef asio::detail::socket_option::boolean< - SOL_SOCKET, SO_REUSEADDR> reuse_address; -#endif - - /// Socket option to specify whether the socket lingers on close if unsent - /// data is present. - /** - * Implements the SOL_SOCKET/SO_LINGER socket option. - * - * @par Examples - * Setting the option: - * @code - * asio::ip::tcp::socket socket(io_service); - * ... - * asio::socket_base::linger option(true, 30); - * socket.set_option(option); - * @endcode - * - * @par - * Getting the current option value: - * @code - * asio::ip::tcp::socket socket(io_service); - * ... - * asio::socket_base::linger option; - * socket.get_option(option); - * bool is_set = option.enabled(); - * unsigned short timeout = option.timeout(); - * @endcode - * - * @par Concepts: - * Socket_Option, Linger_Socket_Option. - */ -#if defined(GENERATING_DOCUMENTATION) - typedef implementation_defined linger; -#else - typedef asio::detail::socket_option::linger< - SOL_SOCKET, SO_LINGER> linger; -#endif - - /// Socket option to report aborted connections on accept. - /** - * Implements a custom socket option that determines whether or not an accept - * operation is permitted to fail with asio::error::connection_aborted. - * By default the option is false. - * - * @par Examples - * Setting the option: - * @code - * asio::ip::tcp::acceptor acceptor(io_service); - * ... - * asio::socket_base::enable_connection_aborted option(true); - * acceptor.set_option(option); - * @endcode - * - * @par - * Getting the current option value: - * @code - * asio::ip::tcp::acceptor acceptor(io_service); - * ... - * asio::socket_base::enable_connection_aborted option; - * acceptor.get_option(option); - * bool is_set = option.value(); - * @endcode - * - * @par Concepts: - * Socket_Option, Boolean_Socket_Option. - */ -#if defined(GENERATING_DOCUMENTATION) - typedef implementation_defined enable_connection_aborted; -#else - typedef asio::detail::socket_option::boolean< - asio::detail::custom_socket_option_level, - asio::detail::enable_connection_aborted_option> - enable_connection_aborted; -#endif - - /// IO control command to set the blocking mode of the socket. - /** - * Implements the FIONBIO IO control command. - * - * @par Example - * @code - * asio::ip::tcp::socket socket(io_service); - * ... - * asio::socket_base::non_blocking_io command(true); - * socket.io_control(command); - * @endcode - * - * @par Concepts: - * IO_Control_Command, Boolean_IO_Control_Command. - */ -#if defined(GENERATING_DOCUMENTATION) - typedef implementation_defined non_blocking_io; -#else - typedef asio::detail::io_control::non_blocking_io non_blocking_io; -#endif - - /// IO control command to get the amount of data that can be read without - /// blocking. - /** - * Implements the FIONREAD IO control command. - * - * @par Example - * @code - * asio::ip::tcp::socket socket(io_service); - * ... - * asio::socket_base::bytes_readable command(true); - * socket.io_control(command); - * std::size_t bytes_readable = command.get(); - * @endcode - * - * @par Concepts: - * IO_Control_Command, Size_IO_Control_Command. - */ -#if defined(GENERATING_DOCUMENTATION) - typedef implementation_defined bytes_readable; -#else - typedef asio::detail::io_control::bytes_readable bytes_readable; -#endif - - /// The maximum length of the queue of pending incoming connections. -#if defined(GENERATING_DOCUMENTATION) - static const int max_connections = implementation_defined; -#else - BOOST_STATIC_CONSTANT(int, max_connections = SOMAXCONN); -#endif - -protected: - /// Protected destructor to prevent deletion through this type. - ~socket_base() - { - } - -#if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564)) -private: - // Workaround to enable the empty base optimisation with Borland C++. - char dummy_; -#endif -}; - -} // namespace asio - -#include "asio/detail/pop_options.hpp" - -#endif // ASIO_SOCKET_BASE_HPP diff --git a/libtorrent/include/asio/ssl.hpp b/libtorrent/include/asio/ssl.hpp deleted file mode 100644 index c66113704..000000000 --- a/libtorrent/include/asio/ssl.hpp +++ /dev/null @@ -1,26 +0,0 @@ -// -// ssl.hpp -// ~~~~~~~ -// -// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -#ifndef ASIO_SSL_HPP -#define ASIO_SSL_HPP - -#if defined(_MSC_VER) && (_MSC_VER >= 1200) -# pragma once -#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) - -#include "asio/ssl/basic_context.hpp" -#include "asio/ssl/context.hpp" -#include "asio/ssl/context_base.hpp" -#include "asio/ssl/context_service.hpp" -#include "asio/ssl/stream.hpp" -#include "asio/ssl/stream_base.hpp" -#include "asio/ssl/stream_service.hpp" - -#endif // ASIO_SSL_HPP diff --git a/libtorrent/include/asio/ssl/basic_context.hpp b/libtorrent/include/asio/ssl/basic_context.hpp deleted file mode 100644 index c1346e6e5..000000000 --- a/libtorrent/include/asio/ssl/basic_context.hpp +++ /dev/null @@ -1,434 +0,0 @@ -// -// basic_context.hpp -// ~~~~~~~~~~~~~~~~~ -// -// Copyright (c) 2005 Voipster / Indrek dot Juhani at voipster dot com -// Copyright (c) 2005-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -#ifndef ASIO_SSL_BASIC_CONTEXT_HPP -#define ASIO_SSL_BASIC_CONTEXT_HPP - -#if defined(_MSC_VER) && (_MSC_VER >= 1200) -# pragma once -#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) - -#include "asio/detail/push_options.hpp" - -#include "asio/detail/push_options.hpp" -#include -#include -#include "asio/detail/pop_options.hpp" - -#include "asio/error.hpp" -#include "asio/io_service.hpp" -#include "asio/ssl/context_base.hpp" -#include "asio/detail/throw_error.hpp" - -namespace asio { -namespace ssl { - -/// SSL context. -template -class basic_context - : public context_base, - private boost::noncopyable -{ -public: - /// The type of the service that will be used to provide context operations. - typedef Service service_type; - - /// The native implementation type of the locking dispatcher. - typedef typename service_type::impl_type impl_type; - - /// Constructor. - basic_context(asio::io_service& io_service, method m) - : service_(asio::use_service(io_service)), - impl_(service_.null()) - { - service_.create(impl_, m); - } - - /// Destructor. - ~basic_context() - { - service_.destroy(impl_); - } - - /// Get the underlying implementation in the native type. - /** - * This function may be used to obtain the underlying implementation of the - * context. This is intended to allow access to context functionality that is - * not otherwise provided. - */ - impl_type impl() - { - return impl_; - } - - /// Set options on the context. - /** - * This function may be used to configure the SSL options used by the context. - * - * @param o A bitmask of options. The available option values are defined in - * the context_base class. The options are bitwise-ored with any existing - * value for the options. - * - * @throws asio::system_error Thrown on failure. - */ - void set_options(options o) - { - asio::error_code ec; - service_.set_options(impl_, o, ec); - asio::detail::throw_error(ec); - } - - /// Set options on the context. - /** - * This function may be used to configure the SSL options used by the context. - * - * @param o A bitmask of options. The available option values are defined in - * the context_base class. The options are bitwise-ored with any existing - * value for the options. - * - * @param ec Set to indicate what error occurred, if any. - */ - asio::error_code set_options(options o, - asio::error_code& ec) - { - return service_.set_options(impl_, o, ec); - } - - /// Set the peer verification mode. - /** - * This function may be used to configure the peer verification mode used by - * the context. - * - * @param v A bitmask of peer verification modes. The available verify_mode - * values are defined in the context_base class. - * - * @throws asio::system_error Thrown on failure. - */ - void set_verify_mode(verify_mode v) - { - asio::error_code ec; - service_.set_verify_mode(impl_, v, ec); - asio::detail::throw_error(ec); - } - - /// Set the peer verification mode. - /** - * This function may be used to configure the peer verification mode used by - * the context. - * - * @param v A bitmask of peer verification modes. The available verify_mode - * values are defined in the context_base class. - * - * @param ec Set to indicate what error occurred, if any. - */ - asio::error_code set_verify_mode(verify_mode v, - asio::error_code& ec) - { - return service_.set_verify_mode(impl_, v, ec); - } - - /// Load a certification authority file for performing verification. - /** - * This function is used to load one or more trusted certification authorities - * from a file. - * - * @param filename The name of a file containing certification authority - * certificates in PEM format. - * - * @throws asio::system_error Thrown on failure. - */ - void load_verify_file(const std::string& filename) - { - asio::error_code ec; - service_.load_verify_file(impl_, filename, ec); - asio::detail::throw_error(ec); - } - - /// Load a certification authority file for performing verification. - /** - * This function is used to load the certificates for one or more trusted - * certification authorities from a file. - * - * @param filename The name of a file containing certification authority - * certificates in PEM format. - * - * @param ec Set to indicate what error occurred, if any. - */ - asio::error_code load_verify_file(const std::string& filename, - asio::error_code& ec) - { - return service_.load_verify_file(impl_, filename, ec); - } - - /// Add a directory containing certificate authority files to be used for - /// performing verification. - /** - * This function is used to specify the name of a directory containing - * certification authority certificates. Each file in the directory must - * contain a single certificate. The files must be named using the subject - * name's hash and an extension of ".0". - * - * @param path The name of a directory containing the certificates. - * - * @throws asio::system_error Thrown on failure. - */ - void add_verify_path(const std::string& path) - { - asio::error_code ec; - service_.add_verify_path(impl_, path, ec); - asio::detail::throw_error(ec); - } - - /// Add a directory containing certificate authority files to be used for - /// performing verification. - /** - * This function is used to specify the name of a directory containing - * certification authority certificates. Each file in the directory must - * contain a single certificate. The files must be named using the subject - * name's hash and an extension of ".0". - * - * @param path The name of a directory containing the certificates. - * - * @param ec Set to indicate what error occurred, if any. - */ - asio::error_code add_verify_path(const std::string& path, - asio::error_code& ec) - { - return service_.add_verify_path(impl_, path, ec); - } - - /// Use a certificate from a file. - /** - * This function is used to load a certificate into the context from a file. - * - * @param filename The name of the file containing the certificate. - * - * @param format The file format (ASN.1 or PEM). - * - * @throws asio::system_error Thrown on failure. - */ - void use_certificate_file(const std::string& filename, file_format format) - { - asio::error_code ec; - service_.use_certificate_file(impl_, filename, format, ec); - asio::detail::throw_error(ec); - } - - /// Use a certificate from a file. - /** - * This function is used to load a certificate into the context from a file. - * - * @param filename The name of the file containing the certificate. - * - * @param format The file format (ASN.1 or PEM). - * - * @param ec Set to indicate what error occurred, if any. - */ - asio::error_code use_certificate_file(const std::string& filename, - file_format format, asio::error_code& ec) - { - return service_.use_certificate_file(impl_, filename, format, ec); - } - - /// Use a certificate chain from a file. - /** - * This function is used to load a certificate chain into the context from a - * file. - * - * @param filename The name of the file containing the certificate. The file - * must use the PEM format. - * - * @throws asio::system_error Thrown on failure. - */ - void use_certificate_chain_file(const std::string& filename) - { - asio::error_code ec; - service_.use_certificate_chain_file(impl_, filename, ec); - asio::detail::throw_error(ec); - } - - /// Use a certificate chain from a file. - /** - * This function is used to load a certificate chain into the context from a - * file. - * - * @param filename The name of the file containing the certificate. The file - * must use the PEM format. - * - * @param ec Set to indicate what error occurred, if any. - */ - asio::error_code use_certificate_chain_file( - const std::string& filename, asio::error_code& ec) - { - return service_.use_certificate_chain_file(impl_, filename, ec); - } - - /// Use a private key from a file. - /** - * This function is used to load a private key into the context from a file. - * - * @param filename The name of the file containing the private key. - * - * @param format The file format (ASN.1 or PEM). - * - * @throws asio::system_error Thrown on failure. - */ - void use_private_key_file(const std::string& filename, file_format format) - { - asio::error_code ec; - service_.use_private_key_file(impl_, filename, format, ec); - asio::detail::throw_error(ec); - } - - /// Use a private key from a file. - /** - * This function is used to load a private key into the context from a file. - * - * @param filename The name of the file containing the private key. - * - * @param format The file format (ASN.1 or PEM). - * - * @param ec Set to indicate what error occurred, if any. - */ - asio::error_code use_private_key_file(const std::string& filename, - file_format format, asio::error_code& ec) - { - return service_.use_private_key_file(impl_, filename, format, ec); - } - - /// Use an RSA private key from a file. - /** - * This function is used to load an RSA private key into the context from a - * file. - * - * @param filename The name of the file containing the RSA private key. - * - * @param format The file format (ASN.1 or PEM). - * - * @throws asio::system_error Thrown on failure. - */ - void use_rsa_private_key_file(const std::string& filename, file_format format) - { - asio::error_code ec; - service_.use_rsa_private_key_file(impl_, filename, format, ec); - asio::detail::throw_error(ec); - } - - /// Use an RSA private key from a file. - /** - * This function is used to load an RSA private key into the context from a - * file. - * - * @param filename The name of the file containing the RSA private key. - * - * @param format The file format (ASN.1 or PEM). - * - * @param ec Set to indicate what error occurred, if any. - */ - asio::error_code use_rsa_private_key_file( - const std::string& filename, file_format format, - asio::error_code& ec) - { - return service_.use_rsa_private_key_file(impl_, filename, format, ec); - } - - /// Use the specified file to obtain the temporary Diffie-Hellman parameters. - /** - * This function is used to load Diffie-Hellman parameters into the context - * from a file. - * - * @param filename The name of the file containing the Diffie-Hellman - * parameters. The file must use the PEM format. - * - * @throws asio::system_error Thrown on failure. - */ - void use_tmp_dh_file(const std::string& filename) - { - asio::error_code ec; - service_.use_tmp_dh_file(impl_, filename, ec); - asio::detail::throw_error(ec); - } - - /// Use the specified file to obtain the temporary Diffie-Hellman parameters. - /** - * This function is used to load Diffie-Hellman parameters into the context - * from a file. - * - * @param filename The name of the file containing the Diffie-Hellman - * parameters. The file must use the PEM format. - * - * @param ec Set to indicate what error occurred, if any. - */ - asio::error_code use_tmp_dh_file(const std::string& filename, - asio::error_code& ec) - { - return service_.use_tmp_dh_file(impl_, filename, ec); - } - - /// Set the password callback. - /** - * This function is used to specify a callback function to obtain password - * information about an encrypted key in PEM format. - * - * @param callback The function object to be used for obtaining the password. - * The function signature of the handler must be: - * @code std::string password_callback( - * std::size_t max_length, // The maximum size for a password. - * password_purpose purpose // Whether password is for reading or writing. - * ); @endcode - * The return value of the callback is a string containing the password. - * - * @throws asio::system_error Thrown on failure. - */ - template - void set_password_callback(PasswordCallback callback) - { - asio::error_code ec; - service_.set_password_callback(impl_, callback, ec); - asio::detail::throw_error(ec); - } - - /// Set the password callback. - /** - * This function is used to specify a callback function to obtain password - * information about an encrypted key in PEM format. - * - * @param callback The function object to be used for obtaining the password. - * The function signature of the handler must be: - * @code std::string password_callback( - * std::size_t max_length, // The maximum size for a password. - * password_purpose purpose // Whether password is for reading or writing. - * ); @endcode - * The return value of the callback is a string containing the password. - * - * @param ec Set to indicate what error occurred, if any. - */ - template - asio::error_code set_password_callback(PasswordCallback callback, - asio::error_code& ec) - { - return service_.set_password_callback(impl_, callback, ec); - } - -private: - /// The backend service implementation. - service_type& service_; - - /// The underlying native implementation. - impl_type impl_; -}; - -} // namespace ssl -} // namespace asio - -#include "asio/detail/pop_options.hpp" - -#endif // ASIO_SSL_BASIC_CONTEXT_HPP diff --git a/libtorrent/include/asio/ssl/context.hpp b/libtorrent/include/asio/ssl/context.hpp deleted file mode 100644 index 7c29e017a..000000000 --- a/libtorrent/include/asio/ssl/context.hpp +++ /dev/null @@ -1,35 +0,0 @@ -// -// context.hpp -// ~~~~~~~~~~~ -// -// Copyright (c) 2005 Voipster / Indrek dot Juhani at voipster dot com -// Copyright (c) 2005-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -#ifndef ASIO_SSL_CONTEXT_HPP -#define ASIO_SSL_CONTEXT_HPP - -#if defined(_MSC_VER) && (_MSC_VER >= 1200) -# pragma once -#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) - -#include "asio/detail/push_options.hpp" - -#include "asio/ssl/basic_context.hpp" -#include "asio/ssl/context_service.hpp" - -namespace asio { -namespace ssl { - -/// Typedef for the typical usage of context. -typedef basic_context context; - -} // namespace ssl -} // namespace asio - -#include "asio/detail/pop_options.hpp" - -#endif // ASIO_SSL_CONTEXT_HPP diff --git a/libtorrent/include/asio/ssl/context_base.hpp b/libtorrent/include/asio/ssl/context_base.hpp deleted file mode 100644 index cc8a2a5df..000000000 --- a/libtorrent/include/asio/ssl/context_base.hpp +++ /dev/null @@ -1,164 +0,0 @@ -// -// context_base.hpp -// ~~~~~~~~~~~~~~~~ -// -// Copyright (c) 2005-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -#ifndef ASIO_SSL_CONTEXT_BASE_HPP -#define ASIO_SSL_CONTEXT_BASE_HPP - -#if defined(_MSC_VER) && (_MSC_VER >= 1200) -# pragma once -#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) - -#include "asio/detail/push_options.hpp" - -#include "asio/detail/push_options.hpp" -#include -#include -#include "asio/detail/pop_options.hpp" - -#include "asio/ssl/detail/openssl_types.hpp" - -namespace asio { -namespace ssl { - -/// The context_base class is used as a base for the basic_context class -/// template so that we have a common place to define various enums. -class context_base -{ -public: - /// Different methods supported by a context. - enum method - { - /// Generic SSL version 2. - sslv2, - - /// SSL version 2 client. - sslv2_client, - - /// SSL version 2 server. - sslv2_server, - - /// Generic SSL version 3. - sslv3, - - /// SSL version 3 client. - sslv3_client, - - /// SSL version 3 server. - sslv3_server, - - /// Generic TLS version 1. - tlsv1, - - /// TLS version 1 client. - tlsv1_client, - - /// TLS version 1 server. - tlsv1_server, - - /// Generic SSL/TLS. - sslv23, - - /// SSL/TLS client. - sslv23_client, - - /// SSL/TLS server. - sslv23_server - }; - - /// Bitmask type for SSL options. - typedef int options; - -#if defined(GENERATING_DOCUMENTATION) - /// Implement various bug workarounds. - static const int default_workarounds = implementation_defined; - - /// Always create a new key when using tmp_dh parameters. - static const int single_dh_use = implementation_defined; - - /// Disable SSL v2. - static const int no_sslv2 = implementation_defined; - - /// Disable SSL v3. - static const int no_sslv3 = implementation_defined; - - /// Disable TLS v1. - static const int no_tlsv1 = implementation_defined; -#else - BOOST_STATIC_CONSTANT(int, default_workarounds = SSL_OP_ALL); - BOOST_STATIC_CONSTANT(int, single_dh_use = SSL_OP_SINGLE_DH_USE); - BOOST_STATIC_CONSTANT(int, no_sslv2 = SSL_OP_NO_SSLv2); - BOOST_STATIC_CONSTANT(int, no_sslv3 = SSL_OP_NO_SSLv3); - BOOST_STATIC_CONSTANT(int, no_tlsv1 = SSL_OP_NO_TLSv1); -#endif - - /// File format types. - enum file_format - { - /// ASN.1 file. - asn1, - - /// PEM file. - pem - }; - - /// Bitmask type for peer verification. - typedef int verify_mode; - -#if defined(GENERATING_DOCUMENTATION) - /// No verification. - static const int verify_none = implementation_defined; - - /// Verify the peer. - static const int verify_peer = implementation_defined; - - /// Fail verification if the peer has no certificate. Ignored unless - /// verify_peer is set. - static const int verify_fail_if_no_peer_cert = implementation_defined; - - /// Do not request client certificate on renegotiation. Ignored unless - /// verify_peer is set. - static const int verify_client_once = implementation_defined; -#else - BOOST_STATIC_CONSTANT(int, verify_none = SSL_VERIFY_NONE); - BOOST_STATIC_CONSTANT(int, verify_peer = SSL_VERIFY_PEER); - BOOST_STATIC_CONSTANT(int, - verify_fail_if_no_peer_cert = SSL_VERIFY_FAIL_IF_NO_PEER_CERT); - BOOST_STATIC_CONSTANT(int, verify_client_once = SSL_VERIFY_CLIENT_ONCE); -#endif - - /// Purpose of PEM password. - enum password_purpose - { - /// The password is needed for reading/decryption. - for_reading, - - /// The password is needed for writing/encryption. - for_writing - }; - -protected: - /// Protected destructor to prevent deletion through this type. - ~context_base() - { - } - -#if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564)) -private: - // Workaround to enable the empty base optimisation with Borland C++. - char dummy_; -#endif -}; - -} // namespace ssl -} // namespace asio - -#include "asio/detail/pop_options.hpp" - -#endif // ASIO_SSL_CONTEXT_BASE_HPP diff --git a/libtorrent/include/asio/ssl/context_service.hpp b/libtorrent/include/asio/ssl/context_service.hpp deleted file mode 100644 index 0bdaf75d4..000000000 --- a/libtorrent/include/asio/ssl/context_service.hpp +++ /dev/null @@ -1,175 +0,0 @@ -// -// context_service.hpp -// ~~~~~~~~~~~~~~~~~~~ -// -// Copyright (c) 2005 Voipster / Indrek dot Juhani at voipster dot com -// Copyright (c) 2005-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -#ifndef ASIO_SSL_CONTEXT_SERVICE_HPP -#define ASIO_SSL_CONTEXT_SERVICE_HPP - -#if defined(_MSC_VER) && (_MSC_VER >= 1200) -# pragma once -#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) - -#include "asio/detail/push_options.hpp" - -#include "asio/detail/push_options.hpp" -#include -#include -#include "asio/detail/pop_options.hpp" - -#include "asio/error.hpp" -#include "asio/io_service.hpp" -#include "asio/detail/service_base.hpp" -#include "asio/ssl/context_base.hpp" -#include "asio/ssl/detail/openssl_context_service.hpp" - -namespace asio { -namespace ssl { - -/// Default service implementation for a context. -class context_service -#if defined(GENERATING_DOCUMENTATION) - : public asio::io_service::service -#else - : public asio::detail::service_base -#endif -{ -private: - // The type of the platform-specific implementation. - typedef detail::openssl_context_service service_impl_type; - -public: -#if defined(GENERATING_DOCUMENTATION) - /// The unique service identifier. - static asio::io_service::id id; -#endif - - /// The type of the context. -#if defined(GENERATING_DOCUMENTATION) - typedef implementation_defined impl_type; -#else - typedef service_impl_type::impl_type impl_type; -#endif - - /// Constructor. - explicit context_service(asio::io_service& io_service) - : asio::detail::service_base(io_service), - service_impl_(asio::use_service(io_service)) - { - } - - /// Destroy all user-defined handler objects owned by the service. - void shutdown_service() - { - } - - /// Return a null context implementation. - impl_type null() const - { - return service_impl_.null(); - } - - /// Create a new context implementation. - void create(impl_type& impl, context_base::method m) - { - service_impl_.create(impl, m); - } - - /// Destroy a context implementation. - void destroy(impl_type& impl) - { - service_impl_.destroy(impl); - } - - /// Set options on the context. - asio::error_code set_options(impl_type& impl, - context_base::options o, asio::error_code& ec) - { - return service_impl_.set_options(impl, o, ec); - } - - /// Set peer verification mode. - asio::error_code set_verify_mode(impl_type& impl, - context_base::verify_mode v, asio::error_code& ec) - { - return service_impl_.set_verify_mode(impl, v, ec); - } - - /// Load a certification authority file for performing verification. - asio::error_code load_verify_file(impl_type& impl, - const std::string& filename, asio::error_code& ec) - { - return service_impl_.load_verify_file(impl, filename, ec); - } - - /// Add a directory containing certification authority files to be used for - /// performing verification. - asio::error_code add_verify_path(impl_type& impl, - const std::string& path, asio::error_code& ec) - { - return service_impl_.add_verify_path(impl, path, ec); - } - - /// Use a certificate from a file. - asio::error_code use_certificate_file(impl_type& impl, - const std::string& filename, context_base::file_format format, - asio::error_code& ec) - { - return service_impl_.use_certificate_file(impl, filename, format, ec); - } - - /// Use a certificate chain from a file. - asio::error_code use_certificate_chain_file(impl_type& impl, - const std::string& filename, asio::error_code& ec) - { - return service_impl_.use_certificate_chain_file(impl, filename, ec); - } - - /// Use a private key from a file. - asio::error_code use_private_key_file(impl_type& impl, - const std::string& filename, context_base::file_format format, - asio::error_code& ec) - { - return service_impl_.use_private_key_file(impl, filename, format, ec); - } - - /// Use an RSA private key from a file. - asio::error_code use_rsa_private_key_file(impl_type& impl, - const std::string& filename, context_base::file_format format, - asio::error_code& ec) - { - return service_impl_.use_rsa_private_key_file(impl, filename, format, ec); - } - - /// Use the specified file to obtain the temporary Diffie-Hellman parameters. - asio::error_code use_tmp_dh_file(impl_type& impl, - const std::string& filename, asio::error_code& ec) - { - return service_impl_.use_tmp_dh_file(impl, filename, ec); - } - - /// Set the password callback. - template - asio::error_code set_password_callback(impl_type& impl, - PasswordCallback callback, asio::error_code& ec) - { - return service_impl_.set_password_callback(impl, callback, ec); - } - -private: - // The service that provides the platform-specific implementation. - service_impl_type& service_impl_; -}; - -} // namespace ssl -} // namespace asio - -#include "asio/detail/pop_options.hpp" - -#endif // ASIO_SSL_CONTEXT_SERVICE_HPP diff --git a/libtorrent/include/asio/ssl/detail/openssl_context_service.hpp b/libtorrent/include/asio/ssl/detail/openssl_context_service.hpp deleted file mode 100644 index 5a90d5a2f..000000000 --- a/libtorrent/include/asio/ssl/detail/openssl_context_service.hpp +++ /dev/null @@ -1,379 +0,0 @@ -// -// openssl_context_service.hpp -// ~~~~~~~~~~~~~~~~~~~~~~~~~~~ -// -// Copyright (c) 2005 Voipster / Indrek dot Juhani at voipster dot com -// Copyright (c) 2005-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -#ifndef ASIO_SSL_DETAIL_OPENSSL_CONTEXT_SERVICE_HPP -#define ASIO_SSL_DETAIL_OPENSSL_CONTEXT_SERVICE_HPP - -#if defined(_MSC_VER) && (_MSC_VER >= 1200) -# pragma once -#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) - -#include "asio/detail/push_options.hpp" - -#include "asio/detail/push_options.hpp" -#include -#include -#include -#include "asio/detail/pop_options.hpp" - -#include "asio/error.hpp" -#include "asio/io_service.hpp" -#include "asio/detail/service_base.hpp" -#include "asio/ssl/context_base.hpp" -#include "asio/ssl/detail/openssl_init.hpp" -#include "asio/ssl/detail/openssl_types.hpp" - -namespace asio { -namespace ssl { -namespace detail { - -class openssl_context_service - : public asio::detail::service_base -{ -public: - // The native type of the context. - typedef ::SSL_CTX* impl_type; - - // The type for the password callback function object. - typedef boost::function password_callback_type; - - // Constructor. - openssl_context_service(asio::io_service& io_service) - : asio::detail::service_base(io_service) - { - } - - // Destroy all user-defined handler objects owned by the service. - void shutdown_service() - { - } - - // Return a null context implementation. - static impl_type null() - { - return 0; - } - - // Create a new context implementation. - void create(impl_type& impl, context_base::method m) - { - ::SSL_METHOD* ssl_method = 0; - switch (m) - { - case context_base::sslv2: - ssl_method = ::SSLv2_method(); - break; - case context_base::sslv2_client: - ssl_method = ::SSLv2_client_method(); - break; - case context_base::sslv2_server: - ssl_method = ::SSLv2_server_method(); - break; - case context_base::sslv3: - ssl_method = ::SSLv3_method(); - break; - case context_base::sslv3_client: - ssl_method = ::SSLv3_client_method(); - break; - case context_base::sslv3_server: - ssl_method = ::SSLv3_server_method(); - break; - case context_base::tlsv1: - ssl_method = ::TLSv1_method(); - break; - case context_base::tlsv1_client: - ssl_method = ::TLSv1_client_method(); - break; - case context_base::tlsv1_server: - ssl_method = ::TLSv1_server_method(); - break; - case context_base::sslv23: - ssl_method = ::SSLv23_method(); - break; - case context_base::sslv23_client: - ssl_method = ::SSLv23_client_method(); - break; - case context_base::sslv23_server: - ssl_method = ::SSLv23_server_method(); - break; - default: - break; - } - impl = ::SSL_CTX_new(ssl_method); - } - - // Destroy a context implementation. - void destroy(impl_type& impl) - { - if (impl != null()) - { - if (impl->default_passwd_callback_userdata) - { - password_callback_type* callback = - static_cast( - impl->default_passwd_callback_userdata); - delete callback; - impl->default_passwd_callback_userdata = 0; - } - - ::SSL_CTX_free(impl); - impl = null(); - } - } - - // Set options on the context. - asio::error_code set_options(impl_type& impl, - context_base::options o, asio::error_code& ec) - { - ::SSL_CTX_set_options(impl, o); - - ec = asio::error_code(); - return ec; - } - - // Set peer verification mode. - asio::error_code set_verify_mode(impl_type& impl, - context_base::verify_mode v, asio::error_code& ec) - { - ::SSL_CTX_set_verify(impl, v, 0); - - ec = asio::error_code(); - return ec; - } - - // Load a certification authority file for performing verification. - asio::error_code load_verify_file(impl_type& impl, - const std::string& filename, asio::error_code& ec) - { - if (::SSL_CTX_load_verify_locations(impl, filename.c_str(), 0) != 1) - { - ec = asio::error::invalid_argument; - return ec; - } - - ec = asio::error_code(); - return ec; - } - - // Add a directory containing certification authority files to be used for - // performing verification. - asio::error_code add_verify_path(impl_type& impl, - const std::string& path, asio::error_code& ec) - { - if (::SSL_CTX_load_verify_locations(impl, 0, path.c_str()) != 1) - { - ec = asio::error::invalid_argument; - return ec; - } - - ec = asio::error_code(); - return ec; - } - - // Use a certificate from a file. - asio::error_code use_certificate_file(impl_type& impl, - const std::string& filename, context_base::file_format format, - asio::error_code& ec) - { - int file_type; - switch (format) - { - case context_base::asn1: - file_type = SSL_FILETYPE_ASN1; - break; - case context_base::pem: - file_type = SSL_FILETYPE_PEM; - break; - default: - { - ec = asio::error::invalid_argument; - return ec; - } - } - - if (::SSL_CTX_use_certificate_file(impl, filename.c_str(), file_type) != 1) - { - ec = asio::error::invalid_argument; - return ec; - } - - ec = asio::error_code(); - return ec; - } - - // Use a certificate chain from a file. - asio::error_code use_certificate_chain_file(impl_type& impl, - const std::string& filename, asio::error_code& ec) - { - if (::SSL_CTX_use_certificate_chain_file(impl, filename.c_str()) != 1) - { - ec = asio::error::invalid_argument; - return ec; - } - - ec = asio::error_code(); - return ec; - } - - // Use a private key from a file. - asio::error_code use_private_key_file(impl_type& impl, - const std::string& filename, context_base::file_format format, - asio::error_code& ec) - { - int file_type; - switch (format) - { - case context_base::asn1: - file_type = SSL_FILETYPE_ASN1; - break; - case context_base::pem: - file_type = SSL_FILETYPE_PEM; - break; - default: - { - ec = asio::error::invalid_argument; - return ec; - } - } - - if (::SSL_CTX_use_PrivateKey_file(impl, filename.c_str(), file_type) != 1) - { - ec = asio::error::invalid_argument; - return ec; - } - - ec = asio::error_code(); - return ec; - } - - // Use an RSA private key from a file. - asio::error_code use_rsa_private_key_file(impl_type& impl, - const std::string& filename, context_base::file_format format, - asio::error_code& ec) - { - int file_type; - switch (format) - { - case context_base::asn1: - file_type = SSL_FILETYPE_ASN1; - break; - case context_base::pem: - file_type = SSL_FILETYPE_PEM; - break; - default: - { - ec = asio::error::invalid_argument; - return ec; - } - } - - if (::SSL_CTX_use_RSAPrivateKey_file( - impl, filename.c_str(), file_type) != 1) - { - ec = asio::error::invalid_argument; - return ec; - } - - ec = asio::error_code(); - return ec; - } - - // Use the specified file to obtain the temporary Diffie-Hellman parameters. - asio::error_code use_tmp_dh_file(impl_type& impl, - const std::string& filename, asio::error_code& ec) - { - ::BIO* bio = ::BIO_new_file(filename.c_str(), "r"); - if (!bio) - { - ec = asio::error::invalid_argument; - return ec; - } - - ::DH* dh = ::PEM_read_bio_DHparams(bio, 0, 0, 0); - if (!dh) - { - ::BIO_free(bio); - ec = asio::error::invalid_argument; - return ec; - } - - ::BIO_free(bio); - int result = ::SSL_CTX_set_tmp_dh(impl, dh); - if (result != 1) - { - ::DH_free(dh); - ec = asio::error::invalid_argument; - return ec; - } - - ec = asio::error_code(); - return ec; - } - - static int password_callback(char* buf, int size, int purpose, void* data) - { - using namespace std; // For strncat and strlen. - - if (data) - { - password_callback_type* callback = - static_cast(data); - std::string passwd = (*callback)(static_cast(size), - purpose ? context_base::for_writing : context_base::for_reading); - *buf = '\0'; - strncat(buf, passwd.c_str(), size); - return strlen(buf); - } - - return 0; - } - - // Set the password callback. - template - asio::error_code set_password_callback(impl_type& impl, - Password_Callback callback, asio::error_code& ec) - { - // Allocate callback function object if not already present. - if (impl->default_passwd_callback_userdata) - { - password_callback_type* callback_function = - static_cast( - impl->default_passwd_callback_userdata); - *callback_function = callback; - } - else - { - password_callback_type* callback_function = - new password_callback_type(callback); - impl->default_passwd_callback_userdata = callback_function; - } - - // Set the password callback. - SSL_CTX_set_default_passwd_cb(impl, - &openssl_context_service::password_callback); - - ec = asio::error_code(); - return ec; - } - -private: - // Ensure openssl is initialised. - openssl_init<> init_; -}; - -} // namespace detail -} // namespace ssl -} // namespace asio - -#include "asio/detail/pop_options.hpp" - -#endif // ASIO_SSL_DETAIL_OPENSSL_CONTEXT_SERVICE_HPP diff --git a/libtorrent/include/asio/ssl/detail/openssl_init.hpp b/libtorrent/include/asio/ssl/detail/openssl_init.hpp deleted file mode 100644 index 07d7e6674..000000000 --- a/libtorrent/include/asio/ssl/detail/openssl_init.hpp +++ /dev/null @@ -1,143 +0,0 @@ -// -// openssl_init.hpp -// ~~~~~~~~~~~~~~~~ -// -// Copyright (c) 2005 Voipster / Indrek dot Juhani at voipster dot com -// Copyright (c) 2005-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -#ifndef ASIO_SSL_DETAIL_OPENSSL_INIT_HPP -#define ASIO_SSL_DETAIL_OPENSSL_INIT_HPP - -#if defined(_MSC_VER) && (_MSC_VER >= 1200) -# pragma once -#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) - -#include "asio/detail/push_options.hpp" - -#include "asio/detail/push_options.hpp" -#include -#include -#include -#include "asio/detail/pop_options.hpp" - -#include "asio/detail/mutex.hpp" -#include "asio/detail/tss_ptr.hpp" -#include "asio/ssl/detail/openssl_types.hpp" - -namespace asio { -namespace ssl { -namespace detail { - -template -class openssl_init - : private boost::noncopyable -{ -private: - // Structure to perform the actual initialisation. - class do_init - { - public: - do_init() - { - if (Do_Init) - { - ::SSL_library_init(); - ::SSL_load_error_strings(); - ::OpenSSL_add_ssl_algorithms(); - - mutexes_.resize(::CRYPTO_num_locks()); - for (size_t i = 0; i < mutexes_.size(); ++i) - mutexes_[i].reset(new asio::detail::mutex); - ::CRYPTO_set_locking_callback(&do_init::openssl_locking_func); - ::CRYPTO_set_id_callback(&do_init::openssl_id_func); - } - } - - ~do_init() - { - if (Do_Init) - { - ::CRYPTO_set_id_callback(0); - ::CRYPTO_set_locking_callback(0); - ::ERR_free_strings(); - ::ERR_remove_state(0); - ::EVP_cleanup(); - ::CRYPTO_cleanup_all_ex_data(); - ::CONF_modules_unload(1); - ::ENGINE_cleanup(); - } - } - - // Helper function to manage a do_init singleton. The static instance of the - // openssl_init object ensures that this function is always called before - // main, and therefore before any other threads can get started. The do_init - // instance must be static in this function to ensure that it gets - // initialised before any other global objects try to use it. - static boost::shared_ptr instance() - { - static boost::shared_ptr init(new do_init); - return init; - } - - private: - static unsigned long openssl_id_func() - { - void* id = instance()->thread_id_; - if (id == 0) - instance()->thread_id_ = id = &id; // Ugh. - BOOST_ASSERT(sizeof(unsigned long) >= sizeof(void*)); - return reinterpret_cast(id); - } - - static void openssl_locking_func(int mode, int n, - const char *file, int line) - { - if (mode & CRYPTO_LOCK) - instance()->mutexes_[n]->lock(); - else - instance()->mutexes_[n]->unlock(); - } - - // Mutexes to be used in locking callbacks. - std::vector > mutexes_; - - // The thread identifiers to be used by openssl. - asio::detail::tss_ptr thread_id_; - }; - -public: - // Constructor. - openssl_init() - : ref_(do_init::instance()) - { - while (&instance_ == 0); // Ensure openssl_init::instance_ is linked in. - } - - // Destructor. - ~openssl_init() - { - } - -private: - // Instance to force initialisation of openssl at global scope. - static openssl_init instance_; - - // Reference to singleton do_init object to ensure that openssl does not get - // cleaned up until the last user has finished with it. - boost::shared_ptr ref_; -}; - -template -openssl_init openssl_init::instance_; - -} // namespace detail -} // namespace ssl -} // namespace asio - -#include "asio/detail/pop_options.hpp" - -#endif // ASIO_SSL_DETAIL_OPENSSL_INIT_HPP diff --git a/libtorrent/include/asio/ssl/detail/openssl_operation.hpp b/libtorrent/include/asio/ssl/detail/openssl_operation.hpp deleted file mode 100644 index c8603ac1e..000000000 --- a/libtorrent/include/asio/ssl/detail/openssl_operation.hpp +++ /dev/null @@ -1,516 +0,0 @@ -// -// openssl_operation.hpp -// ~~~~~~~~~~~~~~~~~~~~~ -// -// Copyright (c) 2005 Voipster / Indrek dot Juhani at voipster dot com -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -#ifndef ASIO_SSL_DETAIL_OPENSSL_OPERATION_HPP -#define ASIO_SSL_DETAIL_OPENSSL_OPERATION_HPP - -#if defined(_MSC_VER) && (_MSC_VER >= 1200) -# pragma once -#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) - -#include "asio/detail/push_options.hpp" - -#include "asio/detail/push_options.hpp" -#include -#include -#include -#include "asio/detail/pop_options.hpp" - -#include "asio/buffer.hpp" -#include "asio/placeholders.hpp" -#include "asio/write.hpp" -#include "asio/detail/socket_ops.hpp" -#include "asio/ssl/detail/openssl_types.hpp" - -namespace asio { -namespace ssl { -namespace detail { - -typedef boost::function ssl_primitive_func; -typedef boost::function - user_handler_func; - -// Network send_/recv buffer implementation -// -// -class net_buffer -{ - static const int NET_BUF_SIZE = 16*1024 + 256; // SSL record size + spare - - unsigned char buf_[NET_BUF_SIZE]; - unsigned char* data_start_; - unsigned char* data_end_; - -public: - net_buffer() - { - data_start_ = data_end_ = buf_; - } - unsigned char* get_unused_start() { return data_end_; } - unsigned char* get_data_start() { return data_start_; } - size_t get_unused_len() { return (NET_BUF_SIZE - (data_end_ - buf_)); } - size_t get_data_len() { return (data_end_ - data_start_); } - void data_added(size_t count) - { - data_end_ += count; - data_end_ = data_end_ > (buf_ + NET_BUF_SIZE)? - (buf_ + NET_BUF_SIZE): - data_end_; - } - void data_removed(size_t count) - { - data_start_ += count; - if (data_start_ >= data_end_) reset(); - } - void reset() { data_start_ = buf_; data_end_ = buf_; } - bool has_data() { return (data_start_ < data_end_); } -}; // class net_buffer - -// -// Operation class -// -// -template -class openssl_operation -{ -public: - - // Constructor for asynchronous operations - openssl_operation(ssl_primitive_func primitive, - Stream& socket, - net_buffer& recv_buf, - SSL* session, - BIO* ssl_bio, - user_handler_func handler, - asio::io_service::strand& strand - ) - : primitive_(primitive) - , user_handler_(handler) - , strand_(&strand) - , recv_buf_(recv_buf) - , socket_(socket) - , ssl_bio_(ssl_bio) - , session_(session) - { - write_ = boost::bind( - &openssl_operation::do_async_write, - this, boost::arg<1>(), boost::arg<2>() - ); - read_ = boost::bind( - &openssl_operation::do_async_read, - this - ); - handler_= boost::bind( - &openssl_operation::async_user_handler, - this, boost::arg<1>(), boost::arg<2>() - ); - } - - // Constructor for synchronous operations - openssl_operation(ssl_primitive_func primitive, - Stream& socket, - net_buffer& recv_buf, - SSL* session, - BIO* ssl_bio) - : primitive_(primitive) - , strand_(0) - , recv_buf_(recv_buf) - , socket_(socket) - , ssl_bio_(ssl_bio) - , session_(session) - { - write_ = boost::bind( - &openssl_operation::do_sync_write, - this, boost::arg<1>(), boost::arg<2>() - ); - read_ = boost::bind( - &openssl_operation::do_sync_read, - this - ); - handler_ = boost::bind( - &openssl_operation::sync_user_handler, - this, boost::arg<1>(), boost::arg<2>() - ); - } - - // Start operation - // In case of asynchronous it returns 0, in sync mode returns success code - // or throws an error... - int start() - { - int rc = primitive_( session_ ); - - bool is_operation_done = (rc > 0); - // For connect/accept/shutdown, the operation - // is done, when return code is 1 - // for write, it is done, when is retcode > 0 - // for read, is is done when retcode > 0 - - int error_code = !is_operation_done ? - ::SSL_get_error( session_, rc ) : - 0; - int sys_error_code = ERR_get_error(); - - bool is_read_needed = (error_code == SSL_ERROR_WANT_READ); - bool is_write_needed = (error_code == SSL_ERROR_WANT_WRITE || - ::BIO_ctrl_pending( ssl_bio_ )); - bool is_shut_down_received = - ((::SSL_get_shutdown( session_ ) & SSL_RECEIVED_SHUTDOWN) == - SSL_RECEIVED_SHUTDOWN); - bool is_shut_down_sent = - ((::SSL_get_shutdown( session_ ) & SSL_SENT_SHUTDOWN) == - SSL_SENT_SHUTDOWN); - - if (is_shut_down_sent && is_shut_down_received && is_operation_done && !is_write_needed) - // SSL connection is shut down cleanly - return handler_(asio::error_code(), 1); - - if (is_shut_down_received && !is_operation_done) - // Shutdown has been requested, while we were reading or writing... - // abort our action... - return handler_(asio::error::shut_down, 0); - - if (!is_operation_done && !is_read_needed && !is_write_needed - && !is_shut_down_sent) - { - // The operation has failed... It is not completed and does - // not want network communication nor does want to send shutdown out... - if (error_code == SSL_ERROR_SYSCALL) - { - return handler_(asio::error_code( - sys_error_code, asio::error::system_category), rc); - } - else - { - return handler_(asio::error_code( - error_code, asio::error::get_ssl_category()), rc); - } - } - - if (!is_operation_done && !is_write_needed) - { - // We may have left over data that we can pass to SSL immediately - if (recv_buf_.get_data_len() > 0) - { - // Pass the buffered data to SSL - int written = ::BIO_write - ( - ssl_bio_, - recv_buf_.get_data_start(), - recv_buf_.get_data_len() - ); - - if (written > 0) - { - recv_buf_.data_removed(written); - } - else if (written < 0) - { - if (!BIO_should_retry(ssl_bio_)) - { - // Some serios error with BIO.... - return handler_(asio::error::no_recovery, 0); - } - } - - return start(); - } - else if (is_read_needed || (is_shut_down_sent && !is_shut_down_received)) - { - return read_(); - } - } - - // Continue with operation, flush any SSL data out to network... - return write_(is_operation_done, rc); - } - -// Private implementation -private: - typedef boost::function - int_handler_func; - typedef boost::function write_func; - typedef boost::function read_func; - - ssl_primitive_func primitive_; - user_handler_func user_handler_; - asio::io_service::strand* strand_; - write_func write_; - read_func read_; - int_handler_func handler_; - - net_buffer send_buf_; // buffers for network IO - - // The recv buffer is owned by the stream, not the operation, since there can - // be left over bytes after passing the data up to the application, and these - // bytes need to be kept around for the next read operation issued by the - // application. - net_buffer& recv_buf_; - - Stream& socket_; - BIO* ssl_bio_; - SSL* session_; - - // - int sync_user_handler(const asio::error_code& error, int rc) - { - if (!error) - return rc; - - throw asio::system_error(error); - } - - int async_user_handler(asio::error_code error, int rc) - { - if (rc < 0) - { - if (!error) - error = asio::error::no_recovery; - rc = 0; - } - - user_handler_(error, rc); - return 0; - } - - // Writes bytes asynchronously from SSL to NET - int do_async_write(bool is_operation_done, int rc) - { - int len = ::BIO_ctrl_pending( ssl_bio_ ); - if ( len ) - { - // There is something to write into net, do it... - len = (int)send_buf_.get_unused_len() > len? - len: - send_buf_.get_unused_len(); - - if (len == 0) - { - // In case our send buffer is full, we have just to wait until - // previous send to complete... - return 0; - } - - // Read outgoing data from bio - len = ::BIO_read( ssl_bio_, send_buf_.get_unused_start(), len); - - if (len > 0) - { - unsigned char *data_start = send_buf_.get_unused_start(); - send_buf_.data_added(len); - - BOOST_ASSERT(strand_); - asio::async_write - ( - socket_, - asio::buffer(data_start, len), - strand_->wrap - ( - boost::bind - ( - &openssl_operation::async_write_handler, - this, - is_operation_done, - rc, - asio::placeholders::error, - asio::placeholders::bytes_transferred - ) - ) - ); - - return 0; - } - else if (!BIO_should_retry(ssl_bio_)) - { - // Seems like fatal error - // reading from SSL BIO has failed... - handler_(asio::error::no_recovery, 0); - return 0; - } - } - - if (is_operation_done) - { - // Finish the operation, with success - handler_(asio::error_code(), rc); - return 0; - } - - // OPeration is not done and writing to net has been made... - // start operation again - start(); - - return 0; - } - - void async_write_handler(bool is_operation_done, int rc, - const asio::error_code& error, size_t bytes_sent) - { - if (!error) - { - // Remove data from send buffer - send_buf_.data_removed(bytes_sent); - - if (is_operation_done) - handler_(asio::error_code(), rc); - else - // Since the operation was not completed, try it again... - start(); - } - else - handler_(error, rc); - } - - int do_async_read() - { - // Wait for new data - BOOST_ASSERT(strand_); - socket_.async_read_some - ( - asio::buffer(recv_buf_.get_unused_start(), - recv_buf_.get_unused_len()), - strand_->wrap - ( - boost::bind - ( - &openssl_operation::async_read_handler, - this, - asio::placeholders::error, - asio::placeholders::bytes_transferred - ) - ) - ); - return 0; - } - - void async_read_handler(const asio::error_code& error, - size_t bytes_recvd) - { - if (!error) - { - recv_buf_.data_added(bytes_recvd); - - // Pass the received data to SSL - int written = ::BIO_write - ( - ssl_bio_, - recv_buf_.get_data_start(), - recv_buf_.get_data_len() - ); - - if (written > 0) - { - recv_buf_.data_removed(written); - } - else if (written < 0) - { - if (!BIO_should_retry(ssl_bio_)) - { - // Some serios error with BIO.... - handler_(asio::error::no_recovery, 0); - return; - } - } - - // and try the SSL primitive again - start(); - } - else - { - // Error in network level... - // SSL can't continue either... - handler_(error, 0); - } - } - - // Syncronous functions... - int do_sync_write(bool is_operation_done, int rc) - { - int len = ::BIO_ctrl_pending( ssl_bio_ ); - if ( len ) - { - // There is something to write into net, do it... - len = (int)send_buf_.get_unused_len() > len? - len: - send_buf_.get_unused_len(); - - // Read outgoing data from bio - len = ::BIO_read( ssl_bio_, send_buf_.get_unused_start(), len); - - if (len > 0) - { - size_t sent_len = asio::write( - socket_, - asio::buffer(send_buf_.get_unused_start(), len) - ); - - send_buf_.data_added(len); - send_buf_.data_removed(sent_len); - } - else if (!BIO_should_retry(ssl_bio_)) - { - // Seems like fatal error - // reading from SSL BIO has failed... - throw asio::system_error(asio::error::no_recovery); - } - } - - if (is_operation_done) - // Finish the operation, with success - return rc; - - // Operation is not finished, start again. - return start(); - } - - int do_sync_read() - { - size_t len = socket_.read_some - ( - asio::buffer(recv_buf_.get_unused_start(), - recv_buf_.get_unused_len()) - ); - - // Write data to ssl - recv_buf_.data_added(len); - - // Pass the received data to SSL - int written = ::BIO_write - ( - ssl_bio_, - recv_buf_.get_data_start(), - recv_buf_.get_data_len() - ); - - if (written > 0) - { - recv_buf_.data_removed(written); - } - else if (written < 0) - { - if (!BIO_should_retry(ssl_bio_)) - { - // Some serios error with BIO.... - throw asio::system_error(asio::error::no_recovery); - } - } - - // Try the operation again - return start(); - } -}; // class openssl_operation - -} // namespace detail -} // namespace ssl -} // namespace asio - -#include "asio/detail/pop_options.hpp" - -#endif // ASIO_SSL_DETAIL_OPENSSL_OPERATION_HPP diff --git a/libtorrent/include/asio/ssl/detail/openssl_stream_service.hpp b/libtorrent/include/asio/ssl/detail/openssl_stream_service.hpp deleted file mode 100644 index 710c935cf..000000000 --- a/libtorrent/include/asio/ssl/detail/openssl_stream_service.hpp +++ /dev/null @@ -1,531 +0,0 @@ -// -// stream_service.hpp -// ~~~~~~~~~~~~~~~~~~ -// -// Copyright (c) 2005 Voipster / Indrek dot Juhani at voipster dot com -// Copyright (c) 2005-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -#ifndef ASIO_SSL_DETAIL_OPENSSL_STREAM_SERVICE_HPP -#define ASIO_SSL_DETAIL_OPENSSL_STREAM_SERVICE_HPP - -#if defined(_MSC_VER) && (_MSC_VER >= 1200) -# pragma once -#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) - -#include "asio/detail/push_options.hpp" - -#include "asio/detail/push_options.hpp" -#include -#include -#include -#include -#include -#include -#include "asio/detail/pop_options.hpp" - -#include "asio/error.hpp" -#include "asio/io_service.hpp" -#include "asio/strand.hpp" -#include "asio/detail/service_base.hpp" -#include "asio/ssl/basic_context.hpp" -#include "asio/ssl/stream_base.hpp" -#include "asio/ssl/detail/openssl_operation.hpp" -#include "asio/ssl/detail/openssl_types.hpp" - -namespace asio { -namespace ssl { -namespace detail { - -class openssl_stream_service - : public asio::detail::service_base -{ -private: - enum { max_buffer_size = INT_MAX }; - - //Base handler for asyncrhonous operations - template - class base_handler - { - public: - typedef boost::function< - void (const asio::error_code&, size_t)> func_t; - - base_handler(asio::io_service& io_service) - : op_(NULL) - , io_service_(io_service) - , work_(io_service) - {} - - void do_func(const asio::error_code& error, size_t size) - { - func_(error, size); - } - - void set_operation(openssl_operation* op) { op_ = op; } - void set_func(func_t func) { func_ = func; } - - ~base_handler() - { - delete op_; - } - - private: - func_t func_; - openssl_operation* op_; - asio::io_service& io_service_; - asio::io_service::work work_; - }; // class base_handler - - // Handler for asynchronous IO (write/read) operations - template - class io_handler - : public base_handler - { - public: - io_handler(Handler handler, asio::io_service& io_service) - : base_handler(io_service) - , handler_(handler) - { - set_func(boost::bind( - &io_handler::handler_impl, - this, boost::arg<1>(), boost::arg<2>() )); - } - - private: - Handler handler_; - void handler_impl(const asio::error_code& error, size_t size) - { - handler_(error, size); - delete this; - } - }; // class io_handler - - // Handler for asyncrhonous handshake (connect, accept) functions - template - class handshake_handler - : public base_handler - { - public: - handshake_handler(Handler handler, asio::io_service& io_service) - : base_handler(io_service) - , handler_(handler) - { - set_func(boost::bind( - &handshake_handler::handler_impl, - this, boost::arg<1>(), boost::arg<2>() )); - } - - private: - Handler handler_; - void handler_impl(const asio::error_code& error, size_t) - { - handler_(error); - delete this; - } - - }; // class handshake_handler - - // Handler for asyncrhonous shutdown - template - class shutdown_handler - : public base_handler - { - public: - shutdown_handler(Handler handler, asio::io_service& io_service) - : base_handler(io_service), - handler_(handler) - { - set_func(boost::bind( - &shutdown_handler::handler_impl, - this, boost::arg<1>(), boost::arg<2>() )); - } - - private: - Handler handler_; - void handler_impl(const asio::error_code& error, size_t) - { - handler_(error); - delete this; - } - }; // class shutdown_handler - -public: - // The implementation type. - typedef struct impl_struct - { - ::SSL* ssl; - ::BIO* ext_bio; - net_buffer recv_buf; - } * impl_type; - - // Construct a new stream socket service for the specified io_service. - explicit openssl_stream_service(asio::io_service& io_service) - : asio::detail::service_base(io_service), - strand_(io_service) - { - } - - // Destroy all user-defined handler objects owned by the service. - void shutdown_service() - { - } - - // Return a null stream implementation. - impl_type null() const - { - return 0; - } - - // Create a new stream implementation. - template - void create(impl_type& impl, Stream& next_layer, - basic_context& context) - { - impl = new impl_struct; - impl->ssl = ::SSL_new(context.impl()); - ::SSL_set_mode(impl->ssl, SSL_MODE_ENABLE_PARTIAL_WRITE); - ::SSL_set_mode(impl->ssl, SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER); - ::BIO* int_bio = 0; - impl->ext_bio = 0; - ::BIO_new_bio_pair(&int_bio, 8192, &impl->ext_bio, 8192); - ::SSL_set_bio(impl->ssl, int_bio, int_bio); - } - - // Destroy a stream implementation. - template - void destroy(impl_type& impl, Stream& next_layer) - { - if (impl != 0) - { - ::BIO_free(impl->ext_bio); - ::SSL_free(impl->ssl); - delete impl; - impl = 0; - } - } - - // Perform SSL handshaking. - template - asio::error_code handshake(impl_type& impl, Stream& next_layer, - stream_base::handshake_type type, asio::error_code& ec) - { - try - { - openssl_operation op( - type == stream_base::client ? - &ssl_wrap::SSL_connect: - &ssl_wrap::SSL_accept, - next_layer, - impl->recv_buf, - impl->ssl, - impl->ext_bio); - op.start(); - } - catch (asio::system_error& e) - { - ec = e.code(); - return ec; - } - - ec = asio::error_code(); - return ec; - } - - // Start an asynchronous SSL handshake. - template - void async_handshake(impl_type& impl, Stream& next_layer, - stream_base::handshake_type type, Handler handler) - { - typedef handshake_handler connect_handler; - - connect_handler* local_handler = - new connect_handler(handler, get_io_service()); - - openssl_operation* op = new openssl_operation - ( - type == stream_base::client ? - &ssl_wrap::SSL_connect: - &ssl_wrap::SSL_accept, - next_layer, - impl->recv_buf, - impl->ssl, - impl->ext_bio, - boost::bind - ( - &base_handler::do_func, - local_handler, - boost::arg<1>(), - boost::arg<2>() - ), - strand_ - ); - local_handler->set_operation(op); - - strand_.post(boost::bind(&openssl_operation::start, op)); - } - - // Shut down SSL on the stream. - template - asio::error_code shutdown(impl_type& impl, Stream& next_layer, - asio::error_code& ec) - { - try - { - openssl_operation op( - &ssl_wrap::SSL_shutdown, - next_layer, - impl->recv_buf, - impl->ssl, - impl->ext_bio); - op.start(); - } - catch (asio::system_error& e) - { - ec = e.code(); - return ec; - } - - ec = asio::error_code(); - return ec; - } - - // Asynchronously shut down SSL on the stream. - template - void async_shutdown(impl_type& impl, Stream& next_layer, Handler handler) - { - typedef shutdown_handler disconnect_handler; - - disconnect_handler* local_handler = - new disconnect_handler(handler, get_io_service()); - - openssl_operation* op = new openssl_operation - ( - &ssl_wrap::SSL_shutdown, - next_layer, - impl->recv_buf, - impl->ssl, - impl->ext_bio, - boost::bind - ( - &base_handler::do_func, - local_handler, - boost::arg<1>(), - boost::arg<2>() - ), - strand_ - ); - local_handler->set_operation(op); - - strand_.post(boost::bind(&openssl_operation::start, op)); - } - - // Write some data to the stream. - template - std::size_t write_some(impl_type& impl, Stream& next_layer, - const Const_Buffers& buffers, asio::error_code& ec) - { - size_t bytes_transferred = 0; - try - { - std::size_t buffer_size = asio::buffer_size(*buffers.begin()); - if (buffer_size > max_buffer_size) - buffer_size = max_buffer_size; - - boost::function send_func = - boost::bind(&::SSL_write, boost::arg<1>(), - asio::buffer_cast(*buffers.begin()), - static_cast(buffer_size)); - openssl_operation op( - send_func, - next_layer, - impl->recv_buf, - impl->ssl, - impl->ext_bio - ); - bytes_transferred = static_cast(op.start()); - } - catch (asio::system_error& e) - { - ec = e.code(); - return 0; - } - - ec = asio::error_code(); - return bytes_transferred; - } - - // Start an asynchronous write. - template - void async_write_some(impl_type& impl, Stream& next_layer, - const Const_Buffers& buffers, Handler handler) - { - typedef io_handler send_handler; - - send_handler* local_handler = new send_handler(handler, get_io_service()); - - std::size_t buffer_size = asio::buffer_size(*buffers.begin()); - if (buffer_size > max_buffer_size) - buffer_size = max_buffer_size; - - boost::function send_func = - boost::bind(&::SSL_write, boost::arg<1>(), - asio::buffer_cast(*buffers.begin()), - static_cast(buffer_size)); - - openssl_operation* op = new openssl_operation - ( - send_func, - next_layer, - impl->recv_buf, - impl->ssl, - impl->ext_bio, - boost::bind - ( - &base_handler::do_func, - local_handler, - boost::arg<1>(), - boost::arg<2>() - ), - strand_ - ); - local_handler->set_operation(op); - - strand_.post(boost::bind(&openssl_operation::start, op)); - } - - // Read some data from the stream. - template - std::size_t read_some(impl_type& impl, Stream& next_layer, - const Mutable_Buffers& buffers, asio::error_code& ec) - { - size_t bytes_transferred = 0; - try - { - std::size_t buffer_size = asio::buffer_size(*buffers.begin()); - if (buffer_size > max_buffer_size) - buffer_size = max_buffer_size; - - boost::function recv_func = - boost::bind(&::SSL_read, boost::arg<1>(), - asio::buffer_cast(*buffers.begin()), - static_cast(buffer_size)); - openssl_operation op(recv_func, - next_layer, - impl->recv_buf, - impl->ssl, - impl->ext_bio - ); - - bytes_transferred = static_cast(op.start()); - } - catch (asio::system_error& e) - { - ec = e.code(); - return 0; - } - - ec = asio::error_code(); - return bytes_transferred; - } - - // Start an asynchronous read. - template - void async_read_some(impl_type& impl, Stream& next_layer, - const Mutable_Buffers& buffers, Handler handler) - { - typedef io_handler recv_handler; - - recv_handler* local_handler = new recv_handler(handler, get_io_service()); - - std::size_t buffer_size = asio::buffer_size(*buffers.begin()); - if (buffer_size > max_buffer_size) - buffer_size = max_buffer_size; - - boost::function recv_func = - boost::bind(&::SSL_read, boost::arg<1>(), - asio::buffer_cast(*buffers.begin()), - static_cast(buffer_size)); - - openssl_operation* op = new openssl_operation - ( - recv_func, - next_layer, - impl->recv_buf, - impl->ssl, - impl->ext_bio, - boost::bind - ( - &base_handler::do_func, - local_handler, - boost::arg<1>(), - boost::arg<2>() - ), - strand_ - ); - local_handler->set_operation(op); - - strand_.post(boost::bind(&openssl_operation::start, op)); - } - - // Peek at the incoming data on the stream. - template - std::size_t peek(impl_type& impl, Stream& next_layer, - const Mutable_Buffers& buffers, asio::error_code& ec) - { - ec = asio::error_code(); - return 0; - } - - // Determine the amount of data that may be read without blocking. - template - std::size_t in_avail(impl_type& impl, Stream& next_layer, - asio::error_code& ec) - { - ec = asio::error_code(); - return 0; - } - -private: - asio::io_service::strand strand_; - - typedef asio::detail::mutex mutex_type; - - template - struct ssl_wrap - { - static Mutex ssl_mutex_; - - static int SSL_accept(SSL *ssl) - { - typename Mutex::scoped_lock lock(ssl_mutex_); - return ::SSL_accept(ssl); - } - - static int SSL_connect(SSL *ssl) - { - typename Mutex::scoped_lock lock(ssl_mutex_); - return ::SSL_connect(ssl); - } - - static int SSL_shutdown(SSL *ssl) - { - typename Mutex::scoped_lock lock(ssl_mutex_); - return ::SSL_shutdown(ssl); - } - }; -}; - -template -Mutex openssl_stream_service::ssl_wrap::ssl_mutex_; - -} // namespace detail -} // namespace ssl -} // namespace asio - -#include "asio/detail/pop_options.hpp" - -#endif // ASIO_SSL_DETAIL_OPENSSL_STREAM_SERVICE_HPP diff --git a/libtorrent/include/asio/ssl/detail/openssl_types.hpp b/libtorrent/include/asio/ssl/detail/openssl_types.hpp deleted file mode 100644 index 1111361e2..000000000 --- a/libtorrent/include/asio/ssl/detail/openssl_types.hpp +++ /dev/null @@ -1,31 +0,0 @@ -// -// openssl_types.hpp -// ~~~~~~~~~~~~~~~~~ -// -// Copyright (c) 2005-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -#ifndef ASIO_SSL_DETAIL_OPENSSL_TYPES_HPP -#define ASIO_SSL_DETAIL_OPENSSL_TYPES_HPP - -#if defined(_MSC_VER) && (_MSC_VER >= 1200) -# pragma once -#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) - -#include "asio/detail/push_options.hpp" - -#include "asio/detail/socket_types.hpp" - -#include "asio/detail/push_options.hpp" -#include -#include -#include -#include -#include "asio/detail/pop_options.hpp" - -#include "asio/detail/pop_options.hpp" - -#endif // ASIO_SSL_DETAIL_OPENSSL_TYPES_HPP diff --git a/libtorrent/include/asio/ssl/stream.hpp b/libtorrent/include/asio/ssl/stream.hpp deleted file mode 100644 index 77ced5bfe..000000000 --- a/libtorrent/include/asio/ssl/stream.hpp +++ /dev/null @@ -1,503 +0,0 @@ -// -// stream.hpp -// ~~~~~~~~~~ -// -// Copyright (c) 2005 Voipster / Indrek dot Juhani at voipster dot com -// Copyright (c) 2005-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -#ifndef ASIO_SSL_STREAM_HPP -#define ASIO_SSL_STREAM_HPP - -#if defined(_MSC_VER) && (_MSC_VER >= 1200) -# pragma once -#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) - -#include "asio/detail/push_options.hpp" - -#include "asio/detail/push_options.hpp" -#include -#include -#include -#include -#include "asio/detail/pop_options.hpp" - -#include "asio/error.hpp" -#include "asio/ssl/basic_context.hpp" -#include "asio/ssl/stream_base.hpp" -#include "asio/ssl/stream_service.hpp" -#include "asio/detail/throw_error.hpp" - -namespace asio { -namespace ssl { - -/// Provides stream-oriented functionality using SSL. -/** - * The stream class template provides asynchronous and blocking stream-oriented - * functionality using SSL. - * - * @par Thread Safety - * @e Distinct @e objects: Safe.@n - * @e Shared @e objects: Unsafe. - * - * @par Example - * To use the SSL stream template with an ip::tcp::socket, you would write: - * @code - * asio::io_service io_service; - * asio::ssl::context context(io_service, asio::ssl::context::sslv23); - * asio::ssl::stream sock(io_service, context); - * @endcode - * - * @par Concepts: - * AsyncReadStream, AsyncWriteStream, Stream, SyncRead_Stream, SyncWriteStream. - */ -template -class stream - : public stream_base, - private boost::noncopyable -{ -public: - /// The type of the next layer. - typedef typename boost::remove_reference::type next_layer_type; - - /// The type of the lowest layer. - typedef typename next_layer_type::lowest_layer_type lowest_layer_type; - - /// The type of the service that will be used to provide stream operations. - typedef Service service_type; - - /// The native implementation type of the stream. - typedef typename service_type::impl_type impl_type; - - /// Construct a stream. - /** - * This constructor creates a stream and initialises the underlying stream - * object. - * - * @param arg The argument to be passed to initialise the underlying stream. - * - * @param context The SSL context to be used for the stream. - */ - template - explicit stream(Arg& arg, basic_context& context) - : next_layer_(arg), - service_(asio::use_service(next_layer_.get_io_service())), - impl_(service_.null()) - { - service_.create(impl_, next_layer_, context); - } - - /// Destructor. - ~stream() - { - service_.destroy(impl_, next_layer_); - } - - /// (Deprecated: use get_io_service().) Get the io_service associated with - /// the object. - /** - * This function may be used to obtain the io_service object that the stream - * uses to dispatch handlers for asynchronous operations. - * - * @return A reference to the io_service object that stream will use to - * dispatch handlers. Ownership is not transferred to the caller. - */ - asio::io_service& io_service() - { - return next_layer_.get_io_service(); - } - - /// Get the io_service associated with the object. - /** - * This function may be used to obtain the io_service object that the stream - * uses to dispatch handlers for asynchronous operations. - * - * @return A reference to the io_service object that stream will use to - * dispatch handlers. Ownership is not transferred to the caller. - */ - asio::io_service& get_io_service() - { - return next_layer_.get_io_service(); - } - - /// Get a reference to the next layer. - /** - * This function returns a reference to the next layer in a stack of stream - * layers. - * - * @return A reference to the next layer in the stack of stream layers. - * Ownership is not transferred to the caller. - */ - next_layer_type& next_layer() - { - return next_layer_; - } - - /// Get a reference to the lowest layer. - /** - * This function returns a reference to the lowest layer in a stack of - * stream layers. - * - * @return A reference to the lowest layer in the stack of stream layers. - * Ownership is not transferred to the caller. - */ - lowest_layer_type& lowest_layer() - { - return next_layer_.lowest_layer(); - } - - /// Get the underlying implementation in the native type. - /** - * This function may be used to obtain the underlying implementation of the - * context. This is intended to allow access to stream functionality that is - * not otherwise provided. - */ - impl_type impl() - { - return impl_; - } - - /// Perform SSL handshaking. - /** - * This function is used to perform SSL handshaking on the stream. The - * function call will block until handshaking is complete or an error occurs. - * - * @param type The type of handshaking to be performed, i.e. as a client or as - * a server. - * - * @throws asio::system_error Thrown on failure. - */ - void handshake(handshake_type type) - { - asio::error_code ec; - service_.handshake(impl_, next_layer_, type, ec); - asio::detail::throw_error(ec); - } - - /// Perform SSL handshaking. - /** - * This function is used to perform SSL handshaking on the stream. The - * function call will block until handshaking is complete or an error occurs. - * - * @param type The type of handshaking to be performed, i.e. as a client or as - * a server. - * - * @param ec Set to indicate what error occurred, if any. - */ - asio::error_code handshake(handshake_type type, - asio::error_code& ec) - { - return service_.handshake(impl_, next_layer_, type, ec); - } - - /// Start an asynchronous SSL handshake. - /** - * This function is used to asynchronously perform an SSL handshake on the - * stream. This function call always returns immediately. - * - * @param type The type of handshaking to be performed, i.e. as a client or as - * a server. - * - * @param handler The handler to be called when the handshake operation - * completes. Copies will be made of the handler as required. The equivalent - * function signature of the handler must be: - * @code void handler( - * const asio::error_code& error // Result of operation. - * ); @endcode - */ - template - void async_handshake(handshake_type type, HandshakeHandler handler) - { - service_.async_handshake(impl_, next_layer_, type, handler); - } - - /// Shut down SSL on the stream. - /** - * This function is used to shut down SSL on the stream. The function call - * will block until SSL has been shut down or an error occurs. - * - * @throws asio::system_error Thrown on failure. - */ - void shutdown() - { - asio::error_code ec; - service_.shutdown(impl_, next_layer_, ec); - asio::detail::throw_error(ec); - } - - /// Shut down SSL on the stream. - /** - * This function is used to shut down SSL on the stream. The function call - * will block until SSL has been shut down or an error occurs. - * - * @param ec Set to indicate what error occurred, if any. - */ - asio::error_code shutdown(asio::error_code& ec) - { - return service_.shutdown(impl_, next_layer_, ec); - } - - /// Asynchronously shut down SSL on the stream. - /** - * This function is used to asynchronously shut down SSL on the stream. This - * function call always returns immediately. - * - * @param handler The handler to be called when the handshake operation - * completes. Copies will be made of the handler as required. The equivalent - * function signature of the handler must be: - * @code void handler( - * const asio::error_code& error // Result of operation. - * ); @endcode - */ - template - void async_shutdown(ShutdownHandler handler) - { - service_.async_shutdown(impl_, next_layer_, handler); - } - - /// Write some data to the stream. - /** - * This function is used to write data on the stream. The function call will - * block until one or more bytes of data has been written successfully, or - * until an error occurs. - * - * @param buffers The data to be written. - * - * @returns The number of bytes written. - * - * @throws asio::system_error Thrown on failure. - * - * @note The write_some operation may not transmit all of the data to the - * peer. Consider using the @ref write function if you need to ensure that all - * data is written before the blocking operation completes. - */ - template - std::size_t write_some(const ConstBufferSequence& buffers) - { - asio::error_code ec; - std::size_t s = service_.write_some(impl_, next_layer_, buffers, ec); - asio::detail::throw_error(ec); - return s; - } - - /// Write some data to the stream. - /** - * This function is used to write data on the stream. The function call will - * block until one or more bytes of data has been written successfully, or - * until an error occurs. - * - * @param buffers The data to be written to the stream. - * - * @param ec Set to indicate what error occurred, if any. - * - * @returns The number of bytes written. Returns 0 if an error occurred. - * - * @note The write_some operation may not transmit all of the data to the - * peer. Consider using the @ref write function if you need to ensure that all - * data is written before the blocking operation completes. - */ - template - std::size_t write_some(const ConstBufferSequence& buffers, - asio::error_code& ec) - { - return service_.write_some(impl_, next_layer_, buffers, ec); - } - - /// Start an asynchronous write. - /** - * This function is used to asynchronously write one or more bytes of data to - * the stream. The function call always returns immediately. - * - * @param buffers The data to be written to the stream. Although the buffers - * object may be copied as necessary, ownership of the underlying buffers is - * retained by the caller, which must guarantee that they remain valid until - * the handler is called. - * - * @param handler The handler to be called when the write operation completes. - * Copies will be made of the handler as required. The equivalent function - * signature of the handler must be: - * @code void handler( - * const asio::error_code& error, // Result of operation. - * std::size_t bytes_transferred // Number of bytes written. - * ); @endcode - * - * @note The async_write_some operation may not transmit all of the data to - * the peer. Consider using the @ref async_write function if you need to - * ensure that all data is written before the blocking operation completes. - */ - template - void async_write_some(const ConstBufferSequence& buffers, - WriteHandler handler) - { - service_.async_write_some(impl_, next_layer_, buffers, handler); - } - - /// Read some data from the stream. - /** - * This function is used to read data from the stream. The function call will - * block until one or more bytes of data has been read successfully, or until - * an error occurs. - * - * @param buffers The buffers into which the data will be read. - * - * @returns The number of bytes read. - * - * @throws asio::system_error Thrown on failure. - * - * @note The read_some operation may not read all of the requested number of - * bytes. Consider using the @ref read function if you need to ensure that the - * requested amount of data is read before the blocking operation completes. - */ - template - std::size_t read_some(const MutableBufferSequence& buffers) - { - asio::error_code ec; - std::size_t s = service_.read_some(impl_, next_layer_, buffers, ec); - asio::detail::throw_error(ec); - return s; - } - - /// Read some data from the stream. - /** - * This function is used to read data from the stream. The function call will - * block until one or more bytes of data has been read successfully, or until - * an error occurs. - * - * @param buffers The buffers into which the data will be read. - * - * @param ec Set to indicate what error occurred, if any. - * - * @returns The number of bytes read. Returns 0 if an error occurred. - * - * @note The read_some operation may not read all of the requested number of - * bytes. Consider using the @ref read function if you need to ensure that the - * requested amount of data is read before the blocking operation completes. - */ - template - std::size_t read_some(const MutableBufferSequence& buffers, - asio::error_code& ec) - { - return service_.read_some(impl_, next_layer_, buffers, ec); - } - - /// Start an asynchronous read. - /** - * This function is used to asynchronously read one or more bytes of data from - * the stream. The function call always returns immediately. - * - * @param buffers The buffers into which the data will be read. Although the - * buffers object may be copied as necessary, ownership of the underlying - * buffers is retained by the caller, which must guarantee that they remain - * valid until the handler is called. - * - * @param handler The handler to be called when the read operation completes. - * Copies will be made of the handler as required. The equivalent function - * signature of the handler must be: - * @code void handler( - * const asio::error_code& error, // Result of operation. - * std::size_t bytes_transferred // Number of bytes read. - * ); @endcode - * - * @note The async_read_some operation may not read all of the requested - * number of bytes. Consider using the @ref async_read function if you need to - * ensure that the requested amount of data is read before the asynchronous - * operation completes. - */ - template - void async_read_some(const MutableBufferSequence& buffers, - ReadHandler handler) - { - service_.async_read_some(impl_, next_layer_, buffers, handler); - } - - /// Peek at the incoming data on the stream. - /** - * This function is used to peek at the incoming data on the stream, without - * removing it from the input queue. The function call will block until data - * has been read successfully or an error occurs. - * - * @param buffers The buffers into which the data will be read. - * - * @returns The number of bytes read. - * - * @throws asio::system_error Thrown on failure. - */ - template - std::size_t peek(const MutableBufferSequence& buffers) - { - asio::error_code ec; - std::size_t s = service_.peek(impl_, next_layer_, buffers, ec); - asio::detail::throw_error(ec); - return s; - } - - /// Peek at the incoming data on the stream. - /** - * This function is used to peek at the incoming data on the stream, withoutxi - * removing it from the input queue. The function call will block until data - * has been read successfully or an error occurs. - * - * @param buffers The buffers into which the data will be read. - * - * @param ec Set to indicate what error occurred, if any. - * - * @returns The number of bytes read. Returns 0 if an error occurred. - */ - template - std::size_t peek(const MutableBufferSequence& buffers, - asio::error_code& ec) - { - return service_.peek(impl_, next_layer_, buffers, ec); - } - - /// Determine the amount of data that may be read without blocking. - /** - * This function is used to determine the amount of data, in bytes, that may - * be read from the stream without blocking. - * - * @returns The number of bytes of data that can be read without blocking. - * - * @throws asio::system_error Thrown on failure. - */ - std::size_t in_avail() - { - asio::error_code ec; - std::size_t s = service_.in_avail(impl_, next_layer_, ec); - asio::detail::throw_error(ec); - return s; - } - - /// Determine the amount of data that may be read without blocking. - /** - * This function is used to determine the amount of data, in bytes, that may - * be read from the stream without blocking. - * - * @param ec Set to indicate what error occurred, if any. - * - * @returns The number of bytes of data that can be read without blocking. - */ - std::size_t in_avail(asio::error_code& ec) - { - return service_.in_avail(impl_, next_layer_, ec); - } - -private: - /// The next layer. - Stream next_layer_; - - /// The backend service implementation. - service_type& service_; - - /// The underlying native implementation. - impl_type impl_; -}; - -} // namespace ssl -} // namespace asio - -#include "asio/detail/pop_options.hpp" - -#endif // ASIO_SSL_STREAM_HPP diff --git a/libtorrent/include/asio/ssl/stream_base.hpp b/libtorrent/include/asio/ssl/stream_base.hpp deleted file mode 100644 index 70ffbb269..000000000 --- a/libtorrent/include/asio/ssl/stream_base.hpp +++ /dev/null @@ -1,60 +0,0 @@ -// -// stream_base.hpp -// ~~~~~~~~~~~~~~~ -// -// Copyright (c) 2005-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -#ifndef ASIO_SSL_STREAM_BASE_HPP -#define ASIO_SSL_STREAM_BASE_HPP - -#if defined(_MSC_VER) && (_MSC_VER >= 1200) -# pragma once -#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) - -#include "asio/detail/push_options.hpp" - -#include "asio/detail/push_options.hpp" -#include -#include "asio/detail/pop_options.hpp" - -namespace asio { -namespace ssl { - -/// The stream_base class is used as a base for the asio::ssl::stream -/// class template so that we have a common place to define various enums. -class stream_base -{ -public: - /// Different handshake types. - enum handshake_type - { - /// Perform handshaking as a client. - client, - - /// Perform handshaking as a server. - server - }; - -protected: - /// Protected destructor to prevent deletion through this type. - ~stream_base() - { - } - -#if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564)) -private: - // Workaround to enable the empty base optimisation with Borland C++. - char dummy_; -#endif -}; - -} // namespace ssl -} // namespace asio - -#include "asio/detail/pop_options.hpp" - -#endif // ASIO_SSL_STREAM_BASE_HPP diff --git a/libtorrent/include/asio/ssl/stream_service.hpp b/libtorrent/include/asio/ssl/stream_service.hpp deleted file mode 100644 index 3465605f9..000000000 --- a/libtorrent/include/asio/ssl/stream_service.hpp +++ /dev/null @@ -1,186 +0,0 @@ -// -// stream_service.hpp -// ~~~~~~~~~~~~~~~~~~ -// -// Copyright (c) 2005 Voipster / Indrek dot Juhani at voipster dot com -// Copyright (c) 2005-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -#ifndef ASIO_SSL_STREAM_SERVICE_HPP -#define ASIO_SSL_STREAM_SERVICE_HPP - -#if defined(_MSC_VER) && (_MSC_VER >= 1200) -# pragma once -#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) - -#include "asio/detail/push_options.hpp" - -#include "asio/detail/push_options.hpp" -#include -#include -#include -#include "asio/detail/pop_options.hpp" - -#include "asio/io_service.hpp" -#include "asio/detail/service_base.hpp" -#include "asio/ssl/basic_context.hpp" -#include "asio/ssl/stream_base.hpp" -#include "asio/ssl/detail/openssl_stream_service.hpp" - -namespace asio { -namespace ssl { - -/// Default service implementation for an SSL stream. -class stream_service -#if defined(GENERATING_DOCUMENTATION) - : public asio::io_service::service -#else - : public asio::detail::service_base -#endif -{ -private: - // The type of the platform-specific implementation. - typedef detail::openssl_stream_service service_impl_type; - -public: -#if defined(GENERATING_DOCUMENTATION) - /// The unique service identifier. - static asio::io_service::id id; -#endif - - /// The type of a stream implementation. -#if defined(GENERATING_DOCUMENTATION) - typedef implementation_defined impl_type; -#else - typedef service_impl_type::impl_type impl_type; -#endif - - /// Construct a new stream service for the specified io_service. - explicit stream_service(asio::io_service& io_service) - : asio::detail::service_base(io_service), - service_impl_(asio::use_service(io_service)) - { - } - - /// Destroy all user-defined handler objects owned by the service. - void shutdown_service() - { - } - - /// Return a null stream implementation. - impl_type null() const - { - return service_impl_.null(); - } - - /// Create a new stream implementation. - template - void create(impl_type& impl, Stream& next_layer, - basic_context& context) - { - service_impl_.create(impl, next_layer, context); - } - - /// Destroy a stream implementation. - template - void destroy(impl_type& impl, Stream& next_layer) - { - service_impl_.destroy(impl, next_layer); - } - - /// Perform SSL handshaking. - template - asio::error_code handshake(impl_type& impl, Stream& next_layer, - stream_base::handshake_type type, asio::error_code& ec) - { - return service_impl_.handshake(impl, next_layer, type, ec); - } - - /// Start an asynchronous SSL handshake. - template - void async_handshake(impl_type& impl, Stream& next_layer, - stream_base::handshake_type type, HandshakeHandler handler) - { - service_impl_.async_handshake(impl, next_layer, type, handler); - } - - /// Shut down SSL on the stream. - template - asio::error_code shutdown(impl_type& impl, Stream& next_layer, - asio::error_code& ec) - { - return service_impl_.shutdown(impl, next_layer, ec); - } - - /// Asynchronously shut down SSL on the stream. - template - void async_shutdown(impl_type& impl, Stream& next_layer, - ShutdownHandler handler) - { - service_impl_.async_shutdown(impl, next_layer, handler); - } - - /// Write some data to the stream. - template - std::size_t write_some(impl_type& impl, Stream& next_layer, - const ConstBufferSequence& buffers, asio::error_code& ec) - { - return service_impl_.write_some(impl, next_layer, buffers, ec); - } - - /// Start an asynchronous write. - template - void async_write_some(impl_type& impl, Stream& next_layer, - const ConstBufferSequence& buffers, WriteHandler handler) - { - service_impl_.async_write_some(impl, next_layer, buffers, handler); - } - - /// Read some data from the stream. - template - std::size_t read_some(impl_type& impl, Stream& next_layer, - const MutableBufferSequence& buffers, asio::error_code& ec) - { - return service_impl_.read_some(impl, next_layer, buffers, ec); - } - - /// Start an asynchronous read. - template - void async_read_some(impl_type& impl, Stream& next_layer, - const MutableBufferSequence& buffers, ReadHandler handler) - { - service_impl_.async_read_some(impl, next_layer, buffers, handler); - } - - /// Peek at the incoming data on the stream. - template - std::size_t peek(impl_type& impl, Stream& next_layer, - const MutableBufferSequence& buffers, asio::error_code& ec) - { - return service_impl_.peek(impl, next_layer, buffers, ec); - } - - /// Determine the amount of data that may be read without blocking. - template - std::size_t in_avail(impl_type& impl, Stream& next_layer, - asio::error_code& ec) - { - return service_impl_.in_avail(impl, next_layer, ec); - } - -private: - // The service that provides the platform-specific implementation. - service_impl_type& service_impl_; -}; - -} // namespace ssl -} // namespace asio - -#include "asio/detail/pop_options.hpp" - -#endif // ASIO_SSL_STREAM_SERVICE_HPP diff --git a/libtorrent/include/asio/strand.hpp b/libtorrent/include/asio/strand.hpp deleted file mode 100644 index 065a9d9ad..000000000 --- a/libtorrent/include/asio/strand.hpp +++ /dev/null @@ -1,186 +0,0 @@ -// -// strand.hpp -// ~~~~~~~~~~ -// -// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -#ifndef ASIO_STRAND_HPP -#define ASIO_STRAND_HPP - -#if defined(_MSC_VER) && (_MSC_VER >= 1200) -# pragma once -#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) - -#include "asio/detail/push_options.hpp" - -#include "asio/io_service.hpp" -#include "asio/detail/strand_service.hpp" -#include "asio/detail/wrapped_handler.hpp" - -namespace asio { - -/// Provides serialised handler execution. -/** - * The io_service::strand class provides the ability to post and dispatch - * handlers with the guarantee that none of those handlers will execute - * concurrently. - * - * @par Thread Safety - * @e Distinct @e objects: Safe.@n - * @e Shared @e objects: Safe. - * - * @par Concepts: - * Dispatcher. - */ -class io_service::strand -{ -public: - /// Constructor. - /** - * Constructs the strand. - * - * @param io_service The io_service object that the strand will use to - * dispatch handlers that are ready to be run. - */ - explicit strand(asio::io_service& io_service) - : service_(asio::use_service< - asio::detail::strand_service>(io_service)) - { - service_.construct(impl_); - } - - /// Destructor. - /** - * Destroys a strand. - * - * Handlers posted through the strand that have not yet been invoked will - * still be dispatched in a way that meets the guarantee of non-concurrency. - */ - ~strand() - { - service_.destroy(impl_); - } - - /// (Deprecated: use get_io_service().) Get the io_service associated with - /// the strand. - /** - * This function may be used to obtain the io_service object that the strand - * uses to dispatch handlers for asynchronous operations. - * - * @return A reference to the io_service object that the strand will use to - * dispatch handlers. Ownership is not transferred to the caller. - */ - asio::io_service& io_service() - { - return service_.get_io_service(); - } - - /// Get the io_service associated with the strand. - /** - * This function may be used to obtain the io_service object that the strand - * uses to dispatch handlers for asynchronous operations. - * - * @return A reference to the io_service object that the strand will use to - * dispatch handlers. Ownership is not transferred to the caller. - */ - asio::io_service& get_io_service() - { - return service_.get_io_service(); - } - - /// Request the strand to invoke the given handler. - /** - * This function is used to ask the strand to execute the given handler. - * - * The strand object guarantees that handlers posted or dispatched through - * the strand will not be executed concurrently. The handler may be executed - * inside this function if the guarantee can be met. If this function is - * called from within a handler that was posted or dispatched through the same - * strand, then the new handler will be executed immediately. - * - * The strand's guarantee is in addition to the guarantee provided by the - * underlying io_service. The io_service guarantees that the handler will only - * be called in a thread in which the io_service's run member function is - * currently being invoked. - * - * @param handler The handler to be called. The strand will make a copy of the - * handler object as required. The function signature of the handler must be: - * @code void handler(); @endcode - */ - template - void dispatch(Handler handler) - { - service_.dispatch(impl_, handler); - } - - /// Request the strand to invoke the given handler and return - /// immediately. - /** - * This function is used to ask the strand to execute the given handler, but - * without allowing the strand to call the handler from inside this function. - * - * The strand object guarantees that handlers posted or dispatched through - * the strand will not be executed concurrently. The strand's guarantee is in - * addition to the guarantee provided by the underlying io_service. The - * io_service guarantees that the handler will only be called in a thread in - * which the io_service's run member function is currently being invoked. - * - * @param handler The handler to be called. The strand will make a copy of the - * handler object as required. The function signature of the handler must be: - * @code void handler(); @endcode - */ - template - void post(Handler handler) - { - service_.post(impl_, handler); - } - - /// Create a new handler that automatically dispatches the wrapped handler - /// on the strand. - /** - * This function is used to create a new handler function object that, when - * invoked, will automatically pass the wrapped handler to the strand's - * dispatch function. - * - * @param handler The handler to be wrapped. The strand will make a copy of - * the handler object as required. The function signature of the handler must - * be: @code void handler(A1 a1, ... An an); @endcode - * - * @return A function object that, when invoked, passes the wrapped handler to - * the strand's dispatch function. Given a function object with the signature: - * @code R f(A1 a1, ... An an); @endcode - * If this function object is passed to the wrap function like so: - * @code strand.wrap(f); @endcode - * then the return value is a function object with the signature - * @code void g(A1 a1, ... An an); @endcode - * that, when invoked, executes code equivalent to: - * @code strand.dispatch(boost::bind(f, a1, ... an)); @endcode - */ - template -#if defined(GENERATING_DOCUMENTATION) - unspecified -#else - detail::wrapped_handler -#endif - wrap(Handler handler) - { - return detail::wrapped_handler(*this, handler); - } - -private: - asio::detail::strand_service& service_; - asio::detail::strand_service::implementation_type impl_; -}; - -/// Typedef for backwards compatibility. -typedef asio::io_service::strand strand; - -} // namespace asio - -#include "asio/detail/pop_options.hpp" - -#endif // ASIO_STRAND_HPP diff --git a/libtorrent/include/asio/stream_socket_service.hpp b/libtorrent/include/asio/stream_socket_service.hpp deleted file mode 100644 index 510d8cf6d..000000000 --- a/libtorrent/include/asio/stream_socket_service.hpp +++ /dev/null @@ -1,286 +0,0 @@ -// -// stream_socket_service.hpp -// ~~~~~~~~~~~~~~~~~~~~~~~~~ -// -// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -#ifndef ASIO_STREAM_SOCKET_SERVICE_HPP -#define ASIO_STREAM_SOCKET_SERVICE_HPP - -#if defined(_MSC_VER) && (_MSC_VER >= 1200) -# pragma once -#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) - -#include "asio/detail/push_options.hpp" - -#include "asio/detail/push_options.hpp" -#include -#include -#include "asio/detail/pop_options.hpp" - -#include "asio/error.hpp" -#include "asio/io_service.hpp" -#include "asio/detail/epoll_reactor.hpp" -#include "asio/detail/kqueue_reactor.hpp" -#include "asio/detail/select_reactor.hpp" -#include "asio/detail/service_base.hpp" -#include "asio/detail/win_iocp_socket_service.hpp" -#include "asio/detail/reactive_socket_service.hpp" - -namespace asio { - -/// Default service implementation for a stream socket. -template -class stream_socket_service -#if defined(GENERATING_DOCUMENTATION) - : public asio::io_service::service -#else - : public asio::detail::service_base > -#endif -{ -public: -#if defined(GENERATING_DOCUMENTATION) - /// The unique service identifier. - static asio::io_service::id id; -#endif - - /// The protocol type. - typedef Protocol protocol_type; - - /// The endpoint type. - typedef typename Protocol::endpoint endpoint_type; - -private: - // The type of the platform-specific implementation. -#if defined(ASIO_HAS_IOCP) - typedef detail::win_iocp_socket_service service_impl_type; -#elif defined(ASIO_HAS_EPOLL) - typedef detail::reactive_socket_service< - Protocol, detail::epoll_reactor > service_impl_type; -#elif defined(ASIO_HAS_KQUEUE) - typedef detail::reactive_socket_service< - Protocol, detail::kqueue_reactor > service_impl_type; -#elif defined(ASIO_HAS_DEV_POLL) - typedef detail::reactive_socket_service< - Protocol, detail::dev_poll_reactor > service_impl_type; -#else - typedef detail::reactive_socket_service< - Protocol, detail::select_reactor > service_impl_type; -#endif - -public: - /// The type of a stream socket implementation. -#if defined(GENERATING_DOCUMENTATION) - typedef implementation_defined implementation_type; -#else - typedef typename service_impl_type::implementation_type implementation_type; -#endif - - /// The native socket type. -#if defined(GENERATING_DOCUMENTATION) - typedef implementation_defined native_type; -#else - typedef typename service_impl_type::native_type native_type; -#endif - - /// Construct a new stream socket service for the specified io_service. - explicit stream_socket_service(asio::io_service& io_service) - : asio::detail::service_base< - stream_socket_service >(io_service), - service_impl_(asio::use_service(io_service)) - { - } - - /// Destroy all user-defined handler objects owned by the service. - void shutdown_service() - { - } - - /// Construct a new stream socket implementation. - void construct(implementation_type& impl) - { - service_impl_.construct(impl); - } - - /// Destroy a stream socket implementation. - void destroy(implementation_type& impl) - { - service_impl_.destroy(impl); - } - - /// Open a stream socket. - asio::error_code open(implementation_type& impl, - const protocol_type& protocol, asio::error_code& ec) - { - if (protocol.type() == SOCK_STREAM) - service_impl_.open(impl, protocol, ec); - else - ec = asio::error::invalid_argument; - return ec; - } - - /// Assign an existing native socket to a stream socket. - asio::error_code assign(implementation_type& impl, - const protocol_type& protocol, const native_type& native_socket, - asio::error_code& ec) - { - return service_impl_.assign(impl, protocol, native_socket, ec); - } - - /// Determine whether the socket is open. - bool is_open(const implementation_type& impl) const - { - return service_impl_.is_open(impl); - } - - /// Close a stream socket implementation. - asio::error_code close(implementation_type& impl, - asio::error_code& ec) - { - return service_impl_.close(impl, ec); - } - - /// Get the native socket implementation. - native_type native(implementation_type& impl) - { - return service_impl_.native(impl); - } - - /// Cancel all asynchronous operations associated with the socket. - asio::error_code cancel(implementation_type& impl, - asio::error_code& ec) - { - return service_impl_.cancel(impl, ec); - } - - /// Determine whether the socket is at the out-of-band data mark. - bool at_mark(const implementation_type& impl, - asio::error_code& ec) const - { - return service_impl_.at_mark(impl, ec); - } - - /// Determine the number of bytes available for reading. - std::size_t available(const implementation_type& impl, - asio::error_code& ec) const - { - return service_impl_.available(impl, ec); - } - - /// Bind the stream socket to the specified local endpoint. - asio::error_code bind(implementation_type& impl, - const endpoint_type& endpoint, asio::error_code& ec) - { - return service_impl_.bind(impl, endpoint, ec); - } - - /// Connect the stream socket to the specified endpoint. - asio::error_code connect(implementation_type& impl, - const endpoint_type& peer_endpoint, asio::error_code& ec) - { - return service_impl_.connect(impl, peer_endpoint, ec); - } - - /// Start an asynchronous connect. - template - void async_connect(implementation_type& impl, - const endpoint_type& peer_endpoint, ConnectHandler handler) - { - service_impl_.async_connect(impl, peer_endpoint, handler); - } - - /// Set a socket option. - template - asio::error_code set_option(implementation_type& impl, - const SettableSocketOption& option, asio::error_code& ec) - { - return service_impl_.set_option(impl, option, ec); - } - - /// Get a socket option. - template - asio::error_code get_option(const implementation_type& impl, - GettableSocketOption& option, asio::error_code& ec) const - { - return service_impl_.get_option(impl, option, ec); - } - - /// Perform an IO control command on the socket. - template - asio::error_code io_control(implementation_type& impl, - IoControlCommand& command, asio::error_code& ec) - { - return service_impl_.io_control(impl, command, ec); - } - - /// Get the local endpoint. - endpoint_type local_endpoint(const implementation_type& impl, - asio::error_code& ec) const - { - return service_impl_.local_endpoint(impl, ec); - } - - /// Get the remote endpoint. - endpoint_type remote_endpoint(const implementation_type& impl, - asio::error_code& ec) const - { - return service_impl_.remote_endpoint(impl, ec); - } - - /// Disable sends or receives on the socket. - asio::error_code shutdown(implementation_type& impl, - socket_base::shutdown_type what, asio::error_code& ec) - { - return service_impl_.shutdown(impl, what, ec); - } - - /// Send the given data to the peer. - template - std::size_t send(implementation_type& impl, - const ConstBufferSequence& buffers, - socket_base::message_flags flags, asio::error_code& ec) - { - return service_impl_.send(impl, buffers, flags, ec); - } - - /// Start an asynchronous send. - template - void async_send(implementation_type& impl, - const ConstBufferSequence& buffers, - socket_base::message_flags flags, WriteHandler handler) - { - service_impl_.async_send(impl, buffers, flags, handler); - } - - /// Receive some data from the peer. - template - std::size_t receive(implementation_type& impl, - const MutableBufferSequence& buffers, - socket_base::message_flags flags, asio::error_code& ec) - { - return service_impl_.receive(impl, buffers, flags, ec); - } - - /// Start an asynchronous receive. - template - void async_receive(implementation_type& impl, - const MutableBufferSequence& buffers, - socket_base::message_flags flags, ReadHandler handler) - { - service_impl_.async_receive(impl, buffers, flags, handler); - } - -private: - // The service that provides the platform-specific implementation. - service_impl_type& service_impl_; -}; - -} // namespace asio - -#include "asio/detail/pop_options.hpp" - -#endif // ASIO_STREAM_SOCKET_SERVICE_HPP diff --git a/libtorrent/include/asio/streambuf.hpp b/libtorrent/include/asio/streambuf.hpp deleted file mode 100644 index e81986776..000000000 --- a/libtorrent/include/asio/streambuf.hpp +++ /dev/null @@ -1,31 +0,0 @@ -// -// streambuf.hpp -// ~~~~~~~~~~~~~ -// -// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -#ifndef ASIO_STREAMBUF_HPP -#define ASIO_STREAMBUF_HPP - -#if defined(_MSC_VER) && (_MSC_VER >= 1200) -# pragma once -#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) - -#include "asio/detail/push_options.hpp" - -#include "asio/basic_streambuf.hpp" - -namespace asio { - -/// Typedef for the typical usage of basic_streambuf. -typedef basic_streambuf<> streambuf; - -} // namespace asio - -#include "asio/detail/pop_options.hpp" - -#endif // ASIO_STREAMBUF_HPP diff --git a/libtorrent/include/asio/system_error.hpp b/libtorrent/include/asio/system_error.hpp deleted file mode 100644 index 397ffb2f2..000000000 --- a/libtorrent/include/asio/system_error.hpp +++ /dev/null @@ -1,117 +0,0 @@ -// -// system_error.hpp -// ~~~~~~~~~~~~~~~~ -// -// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -#ifndef ASIO_SYSTEM_ERROR_HPP -#define ASIO_SYSTEM_ERROR_HPP - -#if defined(_MSC_VER) && (_MSC_VER >= 1200) -# pragma once -#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) - -#include "asio/detail/push_options.hpp" - -#include "asio/detail/push_options.hpp" -#include -#include -#include -#include -#include -#include "asio/detail/pop_options.hpp" - -#include "asio/error_code.hpp" - -namespace asio { - -/// The system_error class is used to represent system conditions that -/// prevent the library from operating correctly. -class system_error - : public std::exception -{ -public: - /// Construct with an error code. - system_error(const error_code& code) - : code_(code), - context_() - { - } - - /// Construct with an error code and context. - system_error(const error_code& code, const std::string& context) - : code_(code), - context_(context) - { - } - - /// Copy constructor. - system_error(const system_error& other) - : std::exception(other), - code_(other.code_), - context_(other.context_), - what_() - { - } - - /// Destructor. - virtual ~system_error() throw () - { - } - - /// Assignment operator. - system_error& operator=(const system_error& e) - { - context_ = e.context_; - code_ = e.code_; - what_.reset(); - return *this; - } - - /// Get a string representation of the exception. - virtual const char* what() const throw () - { - try - { - if (!what_) - { - std::string tmp(context_); - if (tmp.length()) - tmp += ": "; - tmp += code_.message(); - what_.reset(new std::string(tmp)); - } - return what_->c_str(); - } - catch (std::exception&) - { - return "system_error"; - } - } - - /// Get the error code associated with the exception. - error_code code() const - { - return code_; - } - -private: - // The code associated with the error. - error_code code_; - - // The context associated with the error. - std::string context_; - - // The string representation of the error. - mutable boost::scoped_ptr what_; -}; - -} // namespace asio - -#include "asio/detail/pop_options.hpp" - -#endif // ASIO_SYSTEM_ERROR_HPP diff --git a/libtorrent/include/asio/thread.hpp b/libtorrent/include/asio/thread.hpp deleted file mode 100644 index b0f786c6b..000000000 --- a/libtorrent/include/asio/thread.hpp +++ /dev/null @@ -1,91 +0,0 @@ -// -// thread.hpp -// ~~~~~~~~~~ -// -// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -#ifndef ASIO_THREAD_HPP -#define ASIO_THREAD_HPP - -#if defined(_MSC_VER) && (_MSC_VER >= 1200) -# pragma once -#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) - -#include "asio/detail/push_options.hpp" - -#include "asio/detail/noncopyable.hpp" -#include "asio/detail/thread.hpp" - -namespace asio { - -/// A simple abstraction for starting threads. -/** - * The asio::thread class implements the smallest possible subset of the - * functionality of boost::thread. It is intended to be used only for starting - * a thread and waiting for it to exit. If more extensive threading - * capabilities are required, you are strongly advised to use something else. - * - * @par Thread Safety - * @e Distinct @e objects: Safe.@n - * @e Shared @e objects: Unsafe. - * - * @par Example - * A typical use of asio::thread would be to launch a thread to run an - * io_service's event processing loop: - * - * @par - * @code asio::io_service io_service; - * // ... - * asio::thread t(boost::bind(&asio::io_service::run, &io_service)); - * // ... - * t.join(); @endcode - */ -class thread - : private noncopyable -{ -public: - /// Start a new thread that executes the supplied function. - /** - * This constructor creates a new thread that will execute the given function - * or function object. - * - * @param f The function or function object to be run in the thread. The - * function signature must be: @code void f(); @endcode - */ - template - explicit thread(Function f) - : impl_(f, asio::detail::thread::external) - { - } - - /// Destructor. - ~thread() - { - } - - /// Wait for the thread to exit. - /** - * This function will block until the thread has exited. - * - * If this function is not called before the thread object is destroyed, the - * thread itself will continue to run until completion. You will, however, - * no longer have the ability to wait for it to exit. - */ - void join() - { - impl_.join(); - } - -private: - detail::thread impl_; -}; - -} // namespace asio - -#include "asio/detail/pop_options.hpp" - -#endif // ASIO_THREAD_HPP diff --git a/libtorrent/include/asio/time_traits.hpp b/libtorrent/include/asio/time_traits.hpp deleted file mode 100644 index 18a30f25b..000000000 --- a/libtorrent/include/asio/time_traits.hpp +++ /dev/null @@ -1,78 +0,0 @@ -// -// time_traits.hpp -// ~~~~~~~~~~~~~~~ -// -// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -#ifndef ASIO_TIME_TRAITS_HPP -#define ASIO_TIME_TRAITS_HPP - -#if defined(_MSC_VER) && (_MSC_VER >= 1200) -# pragma once -#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) - -#include "asio/detail/push_options.hpp" - -#include "asio/detail/socket_types.hpp" // Must come before posix_time. - -#include "asio/detail/push_options.hpp" -#include -#include "asio/detail/pop_options.hpp" - -namespace asio { - -/// Time traits suitable for use with the deadline timer. -template -struct time_traits; - -/// Time traits specialised for posix_time. -template <> -struct time_traits -{ - /// The time type. - typedef boost::posix_time::ptime time_type; - - /// The duration type. - typedef boost::posix_time::time_duration duration_type; - - /// Get the current time. - static time_type now() - { - return boost::posix_time::microsec_clock::universal_time(); - } - - /// Add a duration to a time. - static time_type add(const time_type& t, const duration_type& d) - { - return t + d; - } - - /// Subtract one time from another. - static duration_type subtract(const time_type& t1, const time_type& t2) - { - return t1 - t2; - } - - /// Test whether one time is less than another. - static bool less_than(const time_type& t1, const time_type& t2) - { - return t1 < t2; - } - - /// Convert to POSIX duration type. - static boost::posix_time::time_duration to_posix_duration( - const duration_type& d) - { - return d; - } -}; - -} // namespace asio - -#include "asio/detail/pop_options.hpp" - -#endif // ASIO_TIME_TRAITS_HPP diff --git a/libtorrent/include/asio/version.hpp b/libtorrent/include/asio/version.hpp deleted file mode 100644 index df2fa9f84..000000000 --- a/libtorrent/include/asio/version.hpp +++ /dev/null @@ -1,23 +0,0 @@ -// -// version.hpp -// ~~~~~~~~~~~ -// -// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -#ifndef ASIO_VERSION_HPP -#define ASIO_VERSION_HPP - -#if defined(_MSC_VER) && (_MSC_VER >= 1200) -# pragma once -#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) - -// ASIO_VERSION % 100 is the sub-minor version -// ASIO_VERSION / 100 % 1000 is the minor version -// ASIO_VERSION / 100000 is the major version -#define ASIO_VERSION 100100 // 1.1.0 - -#endif // ASIO_VERSION_HPP diff --git a/libtorrent/include/asio/windows/basic_handle.hpp b/libtorrent/include/asio/windows/basic_handle.hpp deleted file mode 100644 index f436436b7..000000000 --- a/libtorrent/include/asio/windows/basic_handle.hpp +++ /dev/null @@ -1,211 +0,0 @@ -// -// basic_handle.hpp -// ~~~~~~~~~~~~~~~~ -// -// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -#ifndef ASIO_WINDOWS_BASIC_HANDLE_HPP -#define ASIO_WINDOWS_BASIC_HANDLE_HPP - -#if defined(_MSC_VER) && (_MSC_VER >= 1200) -# pragma once -#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) - -#include "asio/detail/push_options.hpp" - -#include "asio/detail/push_options.hpp" -#include -#include "asio/detail/pop_options.hpp" - -#include "asio/basic_io_object.hpp" -#include "asio/error.hpp" -#include "asio/detail/throw_error.hpp" - -namespace asio { -namespace windows { - -/// Provides Windows handle functionality. -/** - * The windows::basic_handle class template provides the ability to wrap a - * Windows handle. - * - * @par Thread Safety - * @e Distinct @e objects: Safe.@n - * @e Shared @e objects: Unsafe. - */ -template -class basic_handle - : public basic_io_object -{ -public: - /// The native representation of a handle. - typedef typename HandleService::native_type native_type; - - /// A basic_handle is always the lowest layer. - typedef basic_handle lowest_layer_type; - - /// Construct a basic_handle without opening it. - /** - * This constructor creates a handle without opening it. - * - * @param io_service The io_service object that the handle will use to - * dispatch handlers for any asynchronous operations performed on the handle. - */ - explicit basic_handle(asio::io_service& io_service) - : basic_io_object(io_service) - { - } - - /// Construct a basic_handle on an existing native handle. - /** - * This constructor creates a handle object to hold an existing native handle. - * - * @param io_service The io_service object that the handle will use to - * dispatch handlers for any asynchronous operations performed on the handle. - * - * @param native_handle A native handle. - * - * @throws asio::system_error Thrown on failure. - */ - basic_handle(asio::io_service& io_service, - const native_type& native_handle) - : basic_io_object(io_service) - { - asio::error_code ec; - this->service.assign(this->implementation, native_handle, ec); - asio::detail::throw_error(ec); - } - - /// Get a reference to the lowest layer. - /** - * This function returns a reference to the lowest layer in a stack of - * layers. Since a basic_handle cannot contain any further layers, it simply - * returns a reference to itself. - * - * @return A reference to the lowest layer in the stack of layers. Ownership - * is not transferred to the caller. - */ - lowest_layer_type& lowest_layer() - { - return *this; - } - - /// Assign an existing native handle to the handle. - /* - * This function opens the handle to hold an existing native handle. - * - * @param native_handle A native handle. - * - * @throws asio::system_error Thrown on failure. - */ - void assign(const native_type& native_handle) - { - asio::error_code ec; - this->service.assign(this->implementation, native_handle, ec); - asio::detail::throw_error(ec); - } - - /// Assign an existing native handle to the handle. - /* - * This function opens the handle to hold an existing native handle. - * - * @param native_handle A native handle. - * - * @param ec Set to indicate what error occurred, if any. - */ - asio::error_code assign(const native_type& native_handle, - asio::error_code& ec) - { - return this->service.assign(this->implementation, native_handle, ec); - } - - /// Determine whether the handle is open. - bool is_open() const - { - return this->service.is_open(this->implementation); - } - - /// Close the handle. - /** - * This function is used to close the handle. Any asynchronous read or write - * operations will be cancelled immediately, and will complete with the - * asio::error::operation_aborted error. - * - * @throws asio::system_error Thrown on failure. - */ - void close() - { - asio::error_code ec; - this->service.close(this->implementation, ec); - asio::detail::throw_error(ec); - } - - /// Close the handle. - /** - * This function is used to close the handle. Any asynchronous read or write - * operations will be cancelled immediately, and will complete with the - * asio::error::operation_aborted error. - * - * @param ec Set to indicate what error occurred, if any. - */ - asio::error_code close(asio::error_code& ec) - { - return this->service.close(this->implementation, ec); - } - - /// Get the native handle representation. - /** - * This function may be used to obtain the underlying representation of the - * handle. This is intended to allow access to native handle functionality - * that is not otherwise provided. - */ - native_type native() - { - return this->service.native(this->implementation); - } - - /// Cancel all asynchronous operations associated with the handle. - /** - * This function causes all outstanding asynchronous read or write operations - * to finish immediately, and the handlers for cancelled operations will be - * passed the asio::error::operation_aborted error. - * - * @throws asio::system_error Thrown on failure. - */ - void cancel() - { - asio::error_code ec; - this->service.cancel(this->implementation, ec); - asio::detail::throw_error(ec); - } - - /// Cancel all asynchronous operations associated with the handle. - /** - * This function causes all outstanding asynchronous read or write operations - * to finish immediately, and the handlers for cancelled operations will be - * passed the asio::error::operation_aborted error. - * - * @param ec Set to indicate what error occurred, if any. - */ - asio::error_code cancel(asio::error_code& ec) - { - return this->service.cancel(this->implementation, ec); - } - -protected: - /// Protected destructor to prevent deletion through this type. - ~basic_handle() - { - } -}; - -} // namespace windows -} // namespace asio - -#include "asio/detail/pop_options.hpp" - -#endif // ASIO_WINDOWS_BASIC_HANDLE_HPP diff --git a/libtorrent/include/asio/windows/basic_random_access_handle.hpp b/libtorrent/include/asio/windows/basic_random_access_handle.hpp deleted file mode 100644 index 3f015619e..000000000 --- a/libtorrent/include/asio/windows/basic_random_access_handle.hpp +++ /dev/null @@ -1,320 +0,0 @@ -// -// basic_random_access_handle.hpp -// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -// -// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -#ifndef ASIO_WINDOWS_BASIC_RANDOM_ACCESS_HANDLE_HPP -#define ASIO_WINDOWS_BASIC_RANDOM_ACCESS_HANDLE_HPP - -#if defined(_MSC_VER) && (_MSC_VER >= 1200) -# pragma once -#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) - -#include "asio/detail/push_options.hpp" - -#include "asio/detail/push_options.hpp" -#include -#include -#include "asio/detail/pop_options.hpp" - -#include "asio/error.hpp" -#include "asio/windows/basic_handle.hpp" -#include "asio/windows/random_access_handle_service.hpp" -#include "asio/detail/throw_error.hpp" - -#if defined(ASIO_HAS_WINDOWS_RANDOM_ACCESS_HANDLE) \ - || defined(GENERATING_DOCUMENTATION) - -namespace asio { -namespace windows { - -/// Provides random-access handle functionality. -/** - * The windows::basic_random_access_handle class template provides asynchronous - * and blocking random-access handle functionality. - * - * @par Thread Safety - * @e Distinct @e objects: Safe.@n - * @e Shared @e objects: Unsafe. - */ -template -class basic_random_access_handle - : public basic_handle -{ -public: - /// The native representation of a handle. - typedef typename RandomAccessHandleService::native_type native_type; - - /// Construct a basic_random_access_handle without opening it. - /** - * This constructor creates a random-access handle without opening it. The - * handle needs to be opened before data can be written to or or read from it. - * - * @param io_service The io_service object that the random-access handle will - * use to dispatch handlers for any asynchronous operations performed on the - * handle. - */ - explicit basic_random_access_handle(asio::io_service& io_service) - : basic_handle(io_service) - { - } - - /// Construct a basic_random_access_handle on an existing native handle. - /** - * This constructor creates a random-access handle object to hold an existing - * native handle. - * - * @param io_service The io_service object that the random-access handle will - * use to dispatch handlers for any asynchronous operations performed on the - * handle. - * - * @param native_handle The new underlying handle implementation. - * - * @throws asio::system_error Thrown on failure. - */ - basic_random_access_handle(asio::io_service& io_service, - const native_type& native_handle) - : basic_handle(io_service, native_handle) - { - } - - /// Write some data to the handle at the specified offset. - /** - * This function is used to write data to the random-access handle. The - * function call will block until one or more bytes of the data has been - * written successfully, or until an error occurs. - * - * @param offset The offset at which the data will be written. - * - * @param buffers One or more data buffers to be written to the handle. - * - * @returns The number of bytes written. - * - * @throws asio::system_error Thrown on failure. An error code of - * asio::error::eof indicates that the connection was closed by the - * peer. - * - * @note The write_some_at operation may not write all of the data. Consider - * using the @ref write_at function if you need to ensure that all data is - * written before the blocking operation completes. - * - * @par Example - * To write a single data buffer use the @ref buffer function as follows: - * @code - * handle.write_some_at(42, asio::buffer(data, size)); - * @endcode - * See the @ref buffer documentation for information on writing multiple - * buffers in one go, and how to use it with arrays, boost::array or - * std::vector. - */ - template - std::size_t write_some_at(boost::uint64_t offset, - const ConstBufferSequence& buffers) - { - asio::error_code ec; - std::size_t s = this->service.write_some_at( - this->implementation, offset, buffers, ec); - asio::detail::throw_error(ec); - return s; - } - - /// Write some data to the handle at the specified offset. - /** - * This function is used to write data to the random-access handle. The - * function call will block until one or more bytes of the data has been - * written successfully, or until an error occurs. - * - * @param offset The offset at which the data will be written. - * - * @param buffers One or more data buffers to be written to the handle. - * - * @param ec Set to indicate what error occurred, if any. - * - * @returns The number of bytes written. Returns 0 if an error occurred. - * - * @note The write_some operation may not transmit all of the data to the - * peer. Consider using the @ref write_at function if you need to ensure that - * all data is written before the blocking operation completes. - */ - template - std::size_t write_some_at(boost::uint64_t offset, - const ConstBufferSequence& buffers, asio::error_code& ec) - { - return this->service.write_some_at( - this->implementation, offset, buffers, ec); - } - - /// Start an asynchronous write at the specified offset. - /** - * This function is used to asynchronously write data to the random-access - * handle. The function call always returns immediately. - * - * @param offset The offset at which the data will be written. - * - * @param buffers One or more data buffers to be written to the handle. - * Although the buffers object may be copied as necessary, ownership of the - * underlying memory blocks is retained by the caller, which must guarantee - * that they remain valid until the handler is called. - * - * @param handler The handler to be called when the write operation completes. - * Copies will be made of the handler as required. The function signature of - * the handler must be: - * @code void handler( - * const asio::error_code& error, // Result of operation. - * std::size_t bytes_transferred // Number of bytes written. - * ); @endcode - * Regardless of whether the asynchronous operation completes immediately or - * not, the handler will not be invoked from within this function. Invocation - * of the handler will be performed in a manner equivalent to using - * asio::io_service::post(). - * - * @note The write operation may not transmit all of the data to the peer. - * Consider using the @ref async_write_at function if you need to ensure that - * all data is written before the asynchronous operation completes. - * - * @par Example - * To write a single data buffer use the @ref buffer function as follows: - * @code - * handle.async_write_some_at(42, asio::buffer(data, size), handler); - * @endcode - * See the @ref buffer documentation for information on writing multiple - * buffers in one go, and how to use it with arrays, boost::array or - * std::vector. - */ - template - void async_write_some_at(boost::uint64_t offset, - const ConstBufferSequence& buffers, WriteHandler handler) - { - this->service.async_write_some_at( - this->implementation, offset, buffers, handler); - } - - /// Read some data from the handle at the specified offset. - /** - * This function is used to read data from the random-access handle. The - * function call will block until one or more bytes of data has been read - * successfully, or until an error occurs. - * - * @param offset The offset at which the data will be read. - * - * @param buffers One or more buffers into which the data will be read. - * - * @returns The number of bytes read. - * - * @throws asio::system_error Thrown on failure. An error code of - * asio::error::eof indicates that the connection was closed by the - * peer. - * - * @note The read_some operation may not read all of the requested number of - * bytes. Consider using the @ref read_at function if you need to ensure that - * the requested amount of data is read before the blocking operation - * completes. - * - * @par Example - * To read into a single data buffer use the @ref buffer function as follows: - * @code - * handle.read_some_at(42, asio::buffer(data, size)); - * @endcode - * See the @ref buffer documentation for information on reading into multiple - * buffers in one go, and how to use it with arrays, boost::array or - * std::vector. - */ - template - std::size_t read_some_at(boost::uint64_t offset, - const MutableBufferSequence& buffers) - { - asio::error_code ec; - std::size_t s = this->service.read_some_at( - this->implementation, offset, buffers, ec); - asio::detail::throw_error(ec); - return s; - } - - /// Read some data from the handle at the specified offset. - /** - * This function is used to read data from the random-access handle. The - * function call will block until one or more bytes of data has been read - * successfully, or until an error occurs. - * - * @param offset The offset at which the data will be read. - * - * @param buffers One or more buffers into which the data will be read. - * - * @param ec Set to indicate what error occurred, if any. - * - * @returns The number of bytes read. Returns 0 if an error occurred. - * - * @note The read_some operation may not read all of the requested number of - * bytes. Consider using the @ref read_at function if you need to ensure that - * the requested amount of data is read before the blocking operation - * completes. - */ - template - std::size_t read_some_at(boost::uint64_t offset, - const MutableBufferSequence& buffers, asio::error_code& ec) - { - return this->service.read_some_at( - this->implementation, offset, buffers, ec); - } - - /// Start an asynchronous read at the specified offset. - /** - * This function is used to asynchronously read data from the random-access - * handle. The function call always returns immediately. - * - * @param offset The offset at which the data will be read. - * - * @param buffers One or more buffers into which the data will be read. - * Although the buffers object may be copied as necessary, ownership of the - * underlying memory blocks is retained by the caller, which must guarantee - * that they remain valid until the handler is called. - * - * @param handler The handler to be called when the read operation completes. - * Copies will be made of the handler as required. The function signature of - * the handler must be: - * @code void handler( - * const asio::error_code& error, // Result of operation. - * std::size_t bytes_transferred // Number of bytes read. - * ); @endcode - * Regardless of whether the asynchronous operation completes immediately or - * not, the handler will not be invoked from within this function. Invocation - * of the handler will be performed in a manner equivalent to using - * asio::io_service::post(). - * - * @note The read operation may not read all of the requested number of bytes. - * Consider using the @ref async_read_at function if you need to ensure that - * the requested amount of data is read before the asynchronous operation - * completes. - * - * @par Example - * To read into a single data buffer use the @ref buffer function as follows: - * @code - * handle.async_read_some_at(42, asio::buffer(data, size), handler); - * @endcode - * See the @ref buffer documentation for information on reading into multiple - * buffers in one go, and how to use it with arrays, boost::array or - * std::vector. - */ - template - void async_read_some_at(boost::uint64_t offset, - const MutableBufferSequence& buffers, ReadHandler handler) - { - this->service.async_read_some_at( - this->implementation, offset, buffers, handler); - } -}; - -} // namespace windows -} // namespace asio - -#endif // defined(ASIO_HAS_WINDOWS_RANDOM_ACCESS_HANDLE) - // || defined(GENERATING_DOCUMENTATION) - -#include "asio/detail/pop_options.hpp" - -#endif // ASIO_WINDOWS_BASIC_RANDOM_ACCESS_HANDLE_HPP diff --git a/libtorrent/include/asio/windows/basic_stream_handle.hpp b/libtorrent/include/asio/windows/basic_stream_handle.hpp deleted file mode 100644 index aca40aff1..000000000 --- a/libtorrent/include/asio/windows/basic_stream_handle.hpp +++ /dev/null @@ -1,302 +0,0 @@ -// -// basic_stream_handle.hpp -// ~~~~~~~~~~~~~~~~~~~~~~~ -// -// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -#ifndef ASIO_WINDOWS_BASIC_STREAM_HANDLE_HPP -#define ASIO_WINDOWS_BASIC_STREAM_HANDLE_HPP - -#if defined(_MSC_VER) && (_MSC_VER >= 1200) -# pragma once -#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) - -#include "asio/detail/push_options.hpp" - -#include "asio/detail/push_options.hpp" -#include -#include -#include "asio/detail/pop_options.hpp" - -#include "asio/error.hpp" -#include "asio/windows/basic_handle.hpp" -#include "asio/windows/stream_handle_service.hpp" -#include "asio/detail/throw_error.hpp" - -#if defined(ASIO_HAS_WINDOWS_STREAM_HANDLE) \ - || defined(GENERATING_DOCUMENTATION) - -namespace asio { -namespace windows { - -/// Provides stream-oriented handle functionality. -/** - * The windows::basic_stream_handle class template provides asynchronous and - * blocking stream-oriented handle functionality. - * - * @par Thread Safety - * @e Distinct @e objects: Safe.@n - * @e Shared @e objects: Unsafe. - * - * @par Concepts: - * AsyncReadStream, AsyncWriteStream, Stream, SyncReadStream, SyncWriteStream. - */ -template -class basic_stream_handle - : public basic_handle -{ -public: - /// The native representation of a handle. - typedef typename StreamHandleService::native_type native_type; - - /// Construct a basic_stream_handle without opening it. - /** - * This constructor creates a stream handle without opening it. The handle - * needs to be opened and then connected or accepted before data can be sent - * or received on it. - * - * @param io_service The io_service object that the stream handle will use to - * dispatch handlers for any asynchronous operations performed on the handle. - */ - explicit basic_stream_handle(asio::io_service& io_service) - : basic_handle(io_service) - { - } - - /// Construct a basic_stream_handle on an existing native handle. - /** - * This constructor creates a stream handle object to hold an existing native - * handle. - * - * @param io_service The io_service object that the stream handle will use to - * dispatch handlers for any asynchronous operations performed on the handle. - * - * @param native_handle The new underlying handle implementation. - * - * @throws asio::system_error Thrown on failure. - */ - basic_stream_handle(asio::io_service& io_service, - const native_type& native_handle) - : basic_handle(io_service, native_handle) - { - } - - /// Write some data to the handle. - /** - * This function is used to write data to the stream handle. The function call - * will block until one or more bytes of the data has been written - * successfully, or until an error occurs. - * - * @param buffers One or more data buffers to be written to the handle. - * - * @returns The number of bytes written. - * - * @throws asio::system_error Thrown on failure. An error code of - * asio::error::eof indicates that the connection was closed by the - * peer. - * - * @note The write_some operation may not transmit all of the data to the - * peer. Consider using the @ref write function if you need to ensure that - * all data is written before the blocking operation completes. - * - * @par Example - * To write a single data buffer use the @ref buffer function as follows: - * @code - * handle.write_some(asio::buffer(data, size)); - * @endcode - * See the @ref buffer documentation for information on writing multiple - * buffers in one go, and how to use it with arrays, boost::array or - * std::vector. - */ - template - std::size_t write_some(const ConstBufferSequence& buffers) - { - asio::error_code ec; - std::size_t s = this->service.write_some(this->implementation, buffers, ec); - asio::detail::throw_error(ec); - return s; - } - - /// Write some data to the handle. - /** - * This function is used to write data to the stream handle. The function call - * will block until one or more bytes of the data has been written - * successfully, or until an error occurs. - * - * @param buffers One or more data buffers to be written to the handle. - * - * @param ec Set to indicate what error occurred, if any. - * - * @returns The number of bytes written. Returns 0 if an error occurred. - * - * @note The write_some operation may not transmit all of the data to the - * peer. Consider using the @ref write function if you need to ensure that - * all data is written before the blocking operation completes. - */ - template - std::size_t write_some(const ConstBufferSequence& buffers, - asio::error_code& ec) - { - return this->service.write_some(this->implementation, buffers, ec); - } - - /// Start an asynchronous write. - /** - * This function is used to asynchronously write data to the stream handle. - * The function call always returns immediately. - * - * @param buffers One or more data buffers to be written to the handle. - * Although the buffers object may be copied as necessary, ownership of the - * underlying memory blocks is retained by the caller, which must guarantee - * that they remain valid until the handler is called. - * - * @param handler The handler to be called when the write operation completes. - * Copies will be made of the handler as required. The function signature of - * the handler must be: - * @code void handler( - * const asio::error_code& error, // Result of operation. - * std::size_t bytes_transferred // Number of bytes written. - * ); @endcode - * Regardless of whether the asynchronous operation completes immediately or - * not, the handler will not be invoked from within this function. Invocation - * of the handler will be performed in a manner equivalent to using - * asio::io_service::post(). - * - * @note The write operation may not transmit all of the data to the peer. - * Consider using the @ref async_write function if you need to ensure that all - * data is written before the asynchronous operation completes. - * - * @par Example - * To write a single data buffer use the @ref buffer function as follows: - * @code - * handle.async_write_some(asio::buffer(data, size), handler); - * @endcode - * See the @ref buffer documentation for information on writing multiple - * buffers in one go, and how to use it with arrays, boost::array or - * std::vector. - */ - template - void async_write_some(const ConstBufferSequence& buffers, - WriteHandler handler) - { - this->service.async_write_some(this->implementation, buffers, handler); - } - - /// Read some data from the handle. - /** - * This function is used to read data from the stream handle. The function - * call will block until one or more bytes of data has been read successfully, - * or until an error occurs. - * - * @param buffers One or more buffers into which the data will be read. - * - * @returns The number of bytes read. - * - * @throws asio::system_error Thrown on failure. An error code of - * asio::error::eof indicates that the connection was closed by the - * peer. - * - * @note The read_some operation may not read all of the requested number of - * bytes. Consider using the @ref read function if you need to ensure that - * the requested amount of data is read before the blocking operation - * completes. - * - * @par Example - * To read into a single data buffer use the @ref buffer function as follows: - * @code - * handle.read_some(asio::buffer(data, size)); - * @endcode - * See the @ref buffer documentation for information on reading into multiple - * buffers in one go, and how to use it with arrays, boost::array or - * std::vector. - */ - template - std::size_t read_some(const MutableBufferSequence& buffers) - { - asio::error_code ec; - std::size_t s = this->service.read_some(this->implementation, buffers, ec); - asio::detail::throw_error(ec); - return s; - } - - /// Read some data from the handle. - /** - * This function is used to read data from the stream handle. The function - * call will block until one or more bytes of data has been read successfully, - * or until an error occurs. - * - * @param buffers One or more buffers into which the data will be read. - * - * @param ec Set to indicate what error occurred, if any. - * - * @returns The number of bytes read. Returns 0 if an error occurred. - * - * @note The read_some operation may not read all of the requested number of - * bytes. Consider using the @ref read function if you need to ensure that - * the requested amount of data is read before the blocking operation - * completes. - */ - template - std::size_t read_some(const MutableBufferSequence& buffers, - asio::error_code& ec) - { - return this->service.read_some(this->implementation, buffers, ec); - } - - /// Start an asynchronous read. - /** - * This function is used to asynchronously read data from the stream handle. - * The function call always returns immediately. - * - * @param buffers One or more buffers into which the data will be read. - * Although the buffers object may be copied as necessary, ownership of the - * underlying memory blocks is retained by the caller, which must guarantee - * that they remain valid until the handler is called. - * - * @param handler The handler to be called when the read operation completes. - * Copies will be made of the handler as required. The function signature of - * the handler must be: - * @code void handler( - * const asio::error_code& error, // Result of operation. - * std::size_t bytes_transferred // Number of bytes read. - * ); @endcode - * Regardless of whether the asynchronous operation completes immediately or - * not, the handler will not be invoked from within this function. Invocation - * of the handler will be performed in a manner equivalent to using - * asio::io_service::post(). - * - * @note The read operation may not read all of the requested number of bytes. - * Consider using the @ref async_read function if you need to ensure that the - * requested amount of data is read before the asynchronous operation - * completes. - * - * @par Example - * To read into a single data buffer use the @ref buffer function as follows: - * @code - * handle.async_read_some(asio::buffer(data, size), handler); - * @endcode - * See the @ref buffer documentation for information on reading into multiple - * buffers in one go, and how to use it with arrays, boost::array or - * std::vector. - */ - template - void async_read_some(const MutableBufferSequence& buffers, - ReadHandler handler) - { - this->service.async_read_some(this->implementation, buffers, handler); - } -}; - -} // namespace windows -} // namespace asio - -#endif // defined(ASIO_HAS_WINDOWS_STREAM_HANDLE) - // || defined(GENERATING_DOCUMENTATION) - -#include "asio/detail/pop_options.hpp" - -#endif // ASIO_WINDOWS_BASIC_STREAM_HANDLE_HPP diff --git a/libtorrent/include/asio/windows/random_access_handle.hpp b/libtorrent/include/asio/windows/random_access_handle.hpp deleted file mode 100644 index 7bc8db85a..000000000 --- a/libtorrent/include/asio/windows/random_access_handle.hpp +++ /dev/null @@ -1,39 +0,0 @@ -// -// random_access_handle.hpp -// ~~~~~~~~~~~~~~~~~~~~~~~~ -// -// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -#ifndef ASIO_WINDOWS_RANDOM_ACCESS_HANDLE_HPP -#define ASIO_WINDOWS_RANDOM_ACCESS_HANDLE_HPP - -#if defined(_MSC_VER) && (_MSC_VER >= 1200) -# pragma once -#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) - -#include "asio/detail/push_options.hpp" - -#include "asio/windows/basic_random_access_handle.hpp" - -#if defined(ASIO_HAS_WINDOWS_RANDOM_ACCESS_HANDLE) \ - || defined(GENERATING_DOCUMENTATION) - -namespace asio { -namespace windows { - -/// Typedef for the typical usage of a random-access handle. -typedef basic_random_access_handle<> random_access_handle; - -} // namespace windows -} // namespace asio - -#endif // defined(ASIO_HAS_WINDOWS_RANDOM_ACCESS_HANDLE) - // || defined(GENERATING_DOCUMENTATION) - -#include "asio/detail/pop_options.hpp" - -#endif // ASIO_WINDOWS_RANDOM_ACCESS_HANDLE_HPP diff --git a/libtorrent/include/asio/windows/random_access_handle_service.hpp b/libtorrent/include/asio/windows/random_access_handle_service.hpp deleted file mode 100644 index 3430deb32..000000000 --- a/libtorrent/include/asio/windows/random_access_handle_service.hpp +++ /dev/null @@ -1,179 +0,0 @@ -// -// random_access_handle_service.hpp -// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -// -// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -#ifndef ASIO_WINDOWS_RANDOM_ACCESS_HANDLE_SERVICE_HPP -#define ASIO_WINDOWS_RANDOM_ACCESS_HANDLE_SERVICE_HPP - -#if defined(_MSC_VER) && (_MSC_VER >= 1200) -# pragma once -#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) - -#include "asio/detail/push_options.hpp" - -#include "asio/detail/push_options.hpp" -#include -#include -#include -#include "asio/detail/pop_options.hpp" - -#include "asio/error.hpp" -#include "asio/io_service.hpp" -#include "asio/detail/service_base.hpp" -#include "asio/detail/win_iocp_handle_service.hpp" - -#if !defined(ASIO_DISABLE_WINDOWS_RANDOM_ACCESS_HANDLE) -# if defined(ASIO_HAS_IOCP) -# define ASIO_HAS_WINDOWS_RANDOM_ACCESS_HANDLE 1 -# endif // defined(ASIO_HAS_IOCP) -#endif // !defined(ASIO_DISABLE_WINDOWS_RANDOM_ACCESS_HANDLE) - -#if defined(ASIO_HAS_WINDOWS_RANDOM_ACCESS_HANDLE) \ - || defined(GENERATING_DOCUMENTATION) - -namespace asio { -namespace windows { - -/// Default service implementation for a random-access handle. -class random_access_handle_service -#if defined(GENERATING_DOCUMENTATION) - : public asio::io_service::service -#else - : public asio::detail::service_base -#endif -{ -public: -#if defined(GENERATING_DOCUMENTATION) - /// The unique service identifier. - static asio::io_service::id id; -#endif - -private: - // The type of the platform-specific implementation. - typedef detail::win_iocp_handle_service service_impl_type; - -public: - /// The type of a random-access handle implementation. -#if defined(GENERATING_DOCUMENTATION) - typedef implementation_defined implementation_type; -#else - typedef service_impl_type::implementation_type implementation_type; -#endif - - /// The native handle type. -#if defined(GENERATING_DOCUMENTATION) - typedef implementation_defined native_type; -#else - typedef service_impl_type::native_type native_type; -#endif - - /// Construct a new random-access handle service for the specified io_service. - explicit random_access_handle_service(asio::io_service& io_service) - : asio::detail::service_base< - random_access_handle_service>(io_service), - service_impl_(asio::use_service(io_service)) - { - } - - /// Destroy all user-defined handler objects owned by the service. - void shutdown_service() - { - } - - /// Construct a new random-access handle implementation. - void construct(implementation_type& impl) - { - service_impl_.construct(impl); - } - - /// Destroy a random-access handle implementation. - void destroy(implementation_type& impl) - { - service_impl_.destroy(impl); - } - - /// Assign an existing native handle to a random-access handle. - asio::error_code assign(implementation_type& impl, - const native_type& native_handle, asio::error_code& ec) - { - return service_impl_.assign(impl, native_handle, ec); - } - - /// Determine whether the handle is open. - bool is_open(const implementation_type& impl) const - { - return service_impl_.is_open(impl); - } - - /// Close a random-access handle implementation. - asio::error_code close(implementation_type& impl, - asio::error_code& ec) - { - return service_impl_.close(impl, ec); - } - - /// Get the native handle implementation. - native_type native(implementation_type& impl) - { - return service_impl_.native(impl); - } - - /// Cancel all asynchronous operations associated with the handle. - asio::error_code cancel(implementation_type& impl, - asio::error_code& ec) - { - return service_impl_.cancel(impl, ec); - } - - /// Write the given data at the specified offset. - template - std::size_t write_some_at(implementation_type& impl, boost::uint64_t offset, - const ConstBufferSequence& buffers, asio::error_code& ec) - { - return service_impl_.write_some_at(impl, offset, buffers, ec); - } - - /// Start an asynchronous write at the specified offset. - template - void async_write_some_at(implementation_type& impl, boost::uint64_t offset, - const ConstBufferSequence& buffers, WriteHandler handler) - { - service_impl_.async_write_some_at(impl, offset, buffers, handler); - } - - /// Read some data from the specified offset. - template - std::size_t read_some_at(implementation_type& impl, boost::uint64_t offset, - const MutableBufferSequence& buffers, asio::error_code& ec) - { - return service_impl_.read_some_at(impl, offset, buffers, ec); - } - - /// Start an asynchronous read at the specified offset. - template - void async_read_some_at(implementation_type& impl, boost::uint64_t offset, - const MutableBufferSequence& buffers, ReadHandler handler) - { - service_impl_.async_read_some_at(impl, offset, buffers, handler); - } - -private: - // The service that provides the platform-specific implementation. - service_impl_type& service_impl_; -}; - -} // namespace windows -} // namespace asio - -#endif // defined(ASIO_HAS_WINDOWS_RANDOM_ACCESS_HANDLE) - // || defined(GENERATING_DOCUMENTATION) - -#include "asio/detail/pop_options.hpp" - -#endif // ASIO_WINDOWS_RANDOM_ACCESS_HANDLE_SERVICE_HPP diff --git a/libtorrent/include/asio/windows/stream_handle.hpp b/libtorrent/include/asio/windows/stream_handle.hpp deleted file mode 100644 index 84b216d9f..000000000 --- a/libtorrent/include/asio/windows/stream_handle.hpp +++ /dev/null @@ -1,39 +0,0 @@ -// -// stream_handle.hpp -// ~~~~~~~~~~~~~~~~~~ -// -// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -#ifndef ASIO_WINDOWS_STREAM_HANDLE_HPP -#define ASIO_WINDOWS_STREAM_HANDLE_HPP - -#if defined(_MSC_VER) && (_MSC_VER >= 1200) -# pragma once -#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) - -#include "asio/detail/push_options.hpp" - -#include "asio/windows/basic_stream_handle.hpp" - -#if defined(ASIO_HAS_WINDOWS_STREAM_HANDLE) \ - || defined(GENERATING_DOCUMENTATION) - -namespace asio { -namespace windows { - -/// Typedef for the typical usage of a stream-oriented handle. -typedef basic_stream_handle<> stream_handle; - -} // namespace windows -} // namespace asio - -#endif // defined(ASIO_HAS_WINDOWS_STREAM_HANDLE) - // || defined(GENERATING_DOCUMENTATION) - -#include "asio/detail/pop_options.hpp" - -#endif // ASIO_WINDOWS_STREAM_HANDLE_HPP diff --git a/libtorrent/include/asio/windows/stream_handle_service.hpp b/libtorrent/include/asio/windows/stream_handle_service.hpp deleted file mode 100644 index 26bd529c4..000000000 --- a/libtorrent/include/asio/windows/stream_handle_service.hpp +++ /dev/null @@ -1,177 +0,0 @@ -// -// stream_handle_service.hpp -// ~~~~~~~~~~~~~~~~~~~~~~~~~ -// -// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -#ifndef ASIO_WINDOWS_STREAM_HANDLE_SERVICE_HPP -#define ASIO_WINDOWS_STREAM_HANDLE_SERVICE_HPP - -#if defined(_MSC_VER) && (_MSC_VER >= 1200) -# pragma once -#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) - -#include "asio/detail/push_options.hpp" - -#include "asio/detail/push_options.hpp" -#include -#include -#include "asio/detail/pop_options.hpp" - -#include "asio/error.hpp" -#include "asio/io_service.hpp" -#include "asio/detail/service_base.hpp" -#include "asio/detail/win_iocp_handle_service.hpp" - -#if !defined(ASIO_DISABLE_WINDOWS_STREAM_HANDLE) -# if defined(ASIO_HAS_IOCP) -# define ASIO_HAS_WINDOWS_STREAM_HANDLE 1 -# endif // defined(ASIO_HAS_IOCP) -#endif // !defined(ASIO_DISABLE_WINDOWS_STREAM_HANDLE) - -#if defined(ASIO_HAS_WINDOWS_STREAM_HANDLE) \ - || defined(GENERATING_DOCUMENTATION) - -namespace asio { -namespace windows { - -/// Default service implementation for a stream handle. -class stream_handle_service -#if defined(GENERATING_DOCUMENTATION) - : public asio::io_service::service -#else - : public asio::detail::service_base -#endif -{ -public: -#if defined(GENERATING_DOCUMENTATION) - /// The unique service identifier. - static asio::io_service::id id; -#endif - -private: - // The type of the platform-specific implementation. - typedef detail::win_iocp_handle_service service_impl_type; - -public: - /// The type of a stream handle implementation. -#if defined(GENERATING_DOCUMENTATION) - typedef implementation_defined implementation_type; -#else - typedef service_impl_type::implementation_type implementation_type; -#endif - - /// The native handle type. -#if defined(GENERATING_DOCUMENTATION) - typedef implementation_defined native_type; -#else - typedef service_impl_type::native_type native_type; -#endif - - /// Construct a new stream handle service for the specified io_service. - explicit stream_handle_service(asio::io_service& io_service) - : asio::detail::service_base(io_service), - service_impl_(asio::use_service(io_service)) - { - } - - /// Destroy all user-defined handler objects owned by the service. - void shutdown_service() - { - } - - /// Construct a new stream handle implementation. - void construct(implementation_type& impl) - { - service_impl_.construct(impl); - } - - /// Destroy a stream handle implementation. - void destroy(implementation_type& impl) - { - service_impl_.destroy(impl); - } - - /// Assign an existing native handle to a stream handle. - asio::error_code assign(implementation_type& impl, - const native_type& native_handle, asio::error_code& ec) - { - return service_impl_.assign(impl, native_handle, ec); - } - - /// Determine whether the handle is open. - bool is_open(const implementation_type& impl) const - { - return service_impl_.is_open(impl); - } - - /// Close a stream handle implementation. - asio::error_code close(implementation_type& impl, - asio::error_code& ec) - { - return service_impl_.close(impl, ec); - } - - /// Get the native handle implementation. - native_type native(implementation_type& impl) - { - return service_impl_.native(impl); - } - - /// Cancel all asynchronous operations associated with the handle. - asio::error_code cancel(implementation_type& impl, - asio::error_code& ec) - { - return service_impl_.cancel(impl, ec); - } - - /// Write the given data to the stream. - template - std::size_t write_some(implementation_type& impl, - const ConstBufferSequence& buffers, asio::error_code& ec) - { - return service_impl_.write_some(impl, buffers, ec); - } - - /// Start an asynchronous write. - template - void async_write_some(implementation_type& impl, - const ConstBufferSequence& buffers, WriteHandler handler) - { - service_impl_.async_write_some(impl, buffers, handler); - } - - /// Read some data from the stream. - template - std::size_t read_some(implementation_type& impl, - const MutableBufferSequence& buffers, asio::error_code& ec) - { - return service_impl_.read_some(impl, buffers, ec); - } - - /// Start an asynchronous read. - template - void async_read_some(implementation_type& impl, - const MutableBufferSequence& buffers, ReadHandler handler) - { - service_impl_.async_read_some(impl, buffers, handler); - } - -private: - // The service that provides the platform-specific implementation. - service_impl_type& service_impl_; -}; - -} // namespace windows -} // namespace asio - -#endif // defined(ASIO_HAS_WINDOWS_STREAM_HANDLE) - // || defined(GENERATING_DOCUMENTATION) - -#include "asio/detail/pop_options.hpp" - -#endif // ASIO_WINDOWS_STREAM_HANDLE_SERVICE_HPP diff --git a/libtorrent/include/asio/write.hpp b/libtorrent/include/asio/write.hpp deleted file mode 100644 index b1965880b..000000000 --- a/libtorrent/include/asio/write.hpp +++ /dev/null @@ -1,520 +0,0 @@ -// -// write.hpp -// ~~~~~~~~~ -// -// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -#ifndef ASIO_WRITE_HPP -#define ASIO_WRITE_HPP - -#if defined(_MSC_VER) && (_MSC_VER >= 1200) -# pragma once -#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) - -#include "asio/detail/push_options.hpp" - -#include "asio/detail/push_options.hpp" -#include -#include -#include "asio/detail/pop_options.hpp" - -#include "asio/basic_streambuf.hpp" -#include "asio/error.hpp" - -namespace asio { - -/** - * @defgroup write asio::write - * - * @brief Write a certain amount of data to a stream before returning. - */ -/*@{*/ - -/// Write all of the supplied data to a stream before returning. -/** - * This function is used to write a certain number of bytes of data to a stream. - * The call will block until one of the following conditions is true: - * - * @li All of the data in the supplied buffers has been written. That is, the - * bytes transferred is equal to the sum of the buffer sizes. - * - * @li An error occurred. - * - * This operation is implemented in terms of one or more calls to the stream's - * write_some function. - * - * @param s The stream to which the data is to be written. The type must support - * the SyncWriteStream concept. - * - * @param buffers One or more buffers containing the data to be written. The sum - * of the buffer sizes indicates the maximum number of bytes to write to the - * stream. - * - * @returns The number of bytes transferred. - * - * @throws asio::system_error Thrown on failure. - * - * @par Example - * To write a single data buffer use the @ref buffer function as follows: - * @code asio::write(s, asio::buffer(data, size)); @endcode - * See the @ref buffer documentation for information on writing multiple - * buffers in one go, and how to use it with arrays, boost::array or - * std::vector. - * - * @note This overload is equivalent to calling: - * @code asio::write( - * s, buffers, - * asio::transfer_all()); @endcode - */ -template -std::size_t write(SyncWriteStream& s, const ConstBufferSequence& buffers); - -/// Write a certain amount of data to a stream before returning. -/** - * This function is used to write a certain number of bytes of data to a stream. - * The call will block until one of the following conditions is true: - * - * @li All of the data in the supplied buffers has been written. That is, the - * bytes transferred is equal to the sum of the buffer sizes. - * - * @li The completion_condition function object returns true. - * - * This operation is implemented in terms of one or more calls to the stream's - * write_some function. - * - * @param s The stream to which the data is to be written. The type must support - * the SyncWriteStream concept. - * - * @param buffers One or more buffers containing the data to be written. The sum - * of the buffer sizes indicates the maximum number of bytes to write to the - * stream. - * - * @param completion_condition The function object to be called to determine - * whether the write operation is complete. The signature of the function object - * must be: - * @code bool completion_condition( - * const asio::error_code& error, // Result of latest write_some - * // operation. - * - * std::size_t bytes_transferred // Number of bytes transferred - * // so far. - * ); @endcode - * A return value of true indicates that the write operation is complete. False - * indicates that further calls to the stream's write_some function are - * required. - * - * @returns The number of bytes transferred. - * - * @throws asio::system_error Thrown on failure. - * - * @par Example - * To write a single data buffer use the @ref buffer function as follows: - * @code asio::write(s, asio::buffer(data, size), - * asio::transfer_at_least(32)); @endcode - * See the @ref buffer documentation for information on writing multiple - * buffers in one go, and how to use it with arrays, boost::array or - * std::vector. - */ -template -std::size_t write(SyncWriteStream& s, const ConstBufferSequence& buffers, - CompletionCondition completion_condition); - -/// Write a certain amount of data to a stream before returning. -/** - * This function is used to write a certain number of bytes of data to a stream. - * The call will block until one of the following conditions is true: - * - * @li All of the data in the supplied buffers has been written. That is, the - * bytes transferred is equal to the sum of the buffer sizes. - * - * @li The completion_condition function object returns true. - * - * This operation is implemented in terms of one or more calls to the stream's - * write_some function. - * - * @param s The stream to which the data is to be written. The type must support - * the SyncWriteStream concept. - * - * @param buffers One or more buffers containing the data to be written. The sum - * of the buffer sizes indicates the maximum number of bytes to write to the - * stream. - * - * @param completion_condition The function object to be called to determine - * whether the write operation is complete. The signature of the function object - * must be: - * @code bool completion_condition( - * const asio::error_code& error, // Result of latest write_some - * // operation. - * - * std::size_t bytes_transferred // Number of bytes transferred - * // so far. - * ); @endcode - * A return value of true indicates that the write operation is complete. False - * indicates that further calls to the stream's write_some function are - * required. - * - * @param ec Set to indicate what error occurred, if any. - * - * @returns The number of bytes written. If an error occurs, returns the total - * number of bytes successfully transferred prior to the error. - */ -template -std::size_t write(SyncWriteStream& s, const ConstBufferSequence& buffers, - CompletionCondition completion_condition, asio::error_code& ec); - -/// Write all of the supplied data to a stream before returning. -/** - * This function is used to write a certain number of bytes of data to a stream. - * The call will block until one of the following conditions is true: - * - * @li All of the data in the supplied basic_streambuf has been written. - * - * @li An error occurred. - * - * This operation is implemented in terms of one or more calls to the stream's - * write_some function. - * - * @param s The stream to which the data is to be written. The type must support - * the SyncWriteStream concept. - * - * @param b The basic_streambuf object from which data will be written. - * - * @returns The number of bytes transferred. - * - * @throws asio::system_error Thrown on failure. - * - * @note This overload is equivalent to calling: - * @code asio::write( - * s, b, - * asio::transfer_all()); @endcode - */ -template -std::size_t write(SyncWriteStream& s, basic_streambuf& b); - -/// Write a certain amount of data to a stream before returning. -/** - * This function is used to write a certain number of bytes of data to a stream. - * The call will block until one of the following conditions is true: - * - * @li All of the data in the supplied basic_streambuf has been written. - * - * @li The completion_condition function object returns true. - * - * This operation is implemented in terms of one or more calls to the stream's - * write_some function. - * - * @param s The stream to which the data is to be written. The type must support - * the SyncWriteStream concept. - * - * @param b The basic_streambuf object from which data will be written. - * - * @param completion_condition The function object to be called to determine - * whether the write operation is complete. The signature of the function object - * must be: - * @code bool completion_condition( - * const asio::error_code& error, // Result of latest write_some - * // operation. - * - * std::size_t bytes_transferred // Number of bytes transferred - * // so far. - * ); @endcode - * A return value of true indicates that the write operation is complete. False - * indicates that further calls to the stream's write_some function are - * required. - * - * @returns The number of bytes transferred. - * - * @throws asio::system_error Thrown on failure. - */ -template -std::size_t write(SyncWriteStream& s, basic_streambuf& b, - CompletionCondition completion_condition); - -/// Write a certain amount of data to a stream before returning. -/** - * This function is used to write a certain number of bytes of data to a stream. - * The call will block until one of the following conditions is true: - * - * @li All of the data in the supplied basic_streambuf has been written. - * - * @li The completion_condition function object returns true. - * - * This operation is implemented in terms of one or more calls to the stream's - * write_some function. - * - * @param s The stream to which the data is to be written. The type must support - * the SyncWriteStream concept. - * - * @param b The basic_streambuf object from which data will be written. - * - * @param completion_condition The function object to be called to determine - * whether the write operation is complete. The signature of the function object - * must be: - * @code bool completion_condition( - * const asio::error_code& error, // Result of latest write_some - * // operation. - * - * std::size_t bytes_transferred // Number of bytes transferred - * // so far. - * ); @endcode - * A return value of true indicates that the write operation is complete. False - * indicates that further calls to the stream's write_some function are - * required. - * - * @param ec Set to indicate what error occurred, if any. - * - * @returns The number of bytes written. If an error occurs, returns the total - * number of bytes successfully transferred prior to the error. - */ -template -std::size_t write(SyncWriteStream& s, basic_streambuf& b, - CompletionCondition completion_condition, asio::error_code& ec); - -/*@}*/ -/** - * @defgroup async_write asio::async_write - * - * @brief Start an asynchronous operation to write a certain amount of data to a - * stream. - */ -/*@{*/ - -/// Start an asynchronous operation to write all of the supplied data to a -/// stream. -/** - * This function is used to asynchronously write a certain number of bytes of - * data to a stream. The function call always returns immediately. The - * asynchronous operation will continue until one of the following conditions - * is true: - * - * @li All of the data in the supplied buffers has been written. That is, the - * bytes transferred is equal to the sum of the buffer sizes. - * - * @li An error occurred. - * - * This operation is implemented in terms of one or more calls to the stream's - * async_write_some function. - * - * @param s The stream to which the data is to be written. The type must support - * the AsyncWriteStream concept. - * - * @param buffers One or more buffers containing the data to be written. - * Although the buffers object may be copied as necessary, ownership of the - * underlying memory blocks is retained by the caller, which must guarantee - * that they remain valid until the handler is called. - * - * @param handler The handler to be called when the write operation completes. - * Copies will be made of the handler as required. The function signature of - * the handler must be: - * @code void handler( - * const asio::error_code& error, // Result of operation. - * - * std::size_t bytes_transferred // Number of bytes written from the - * // buffers. If an error occurred, - * // this will be less than the sum - * // of the buffer sizes. - * ); @endcode - * Regardless of whether the asynchronous operation completes immediately or - * not, the handler will not be invoked from within this function. Invocation of - * the handler will be performed in a manner equivalent to using - * asio::io_service::post(). - * - * @par Example - * To write a single data buffer use the @ref buffer function as follows: - * @code - * asio::async_write(s, asio::buffer(data, size), handler); - * @endcode - * See the @ref buffer documentation for information on writing multiple - * buffers in one go, and how to use it with arrays, boost::array or - * std::vector. - */ -template -void async_write(AsyncWriteStream& s, const ConstBufferSequence& buffers, - WriteHandler handler); - -/// Start an asynchronous operation to write a certain amount of data to a -/// stream. -/** - * This function is used to asynchronously write a certain number of bytes of - * data to a stream. The function call always returns immediately. The - * asynchronous operation will continue until one of the following conditions - * is true: - * - * @li All of the data in the supplied buffers has been written. That is, the - * bytes transferred is equal to the sum of the buffer sizes. - * - * @li The completion_condition function object returns true. - * - * This operation is implemented in terms of one or more calls to the stream's - * async_write_some function. - * - * @param s The stream to which the data is to be written. The type must support - * the AsyncWriteStream concept. - * - * @param buffers One or more buffers containing the data to be written. - * Although the buffers object may be copied as necessary, ownership of the - * underlying memory blocks is retained by the caller, which must guarantee - * that they remain valid until the handler is called. - * - * @param completion_condition The function object to be called to determine - * whether the write operation is complete. The signature of the function object - * must be: - * @code bool completion_condition( - * const asio::error_code& error, // Result of latest write_some - * // operation. - * - * std::size_t bytes_transferred // Number of bytes transferred - * // so far. - * ); @endcode - * A return value of true indicates that the write operation is complete. False - * indicates that further calls to the stream's async_write_some function are - * required. - * - * @param handler The handler to be called when the write operation completes. - * Copies will be made of the handler as required. The function signature of the - * handler must be: - * @code void handler( - * const asio::error_code& error, // Result of operation. - * - * std::size_t bytes_transferred // Number of bytes written from the - * // buffers. If an error occurred, - * // this will be less than the sum - * // of the buffer sizes. - * ); @endcode - * Regardless of whether the asynchronous operation completes immediately or - * not, the handler will not be invoked from within this function. Invocation of - * the handler will be performed in a manner equivalent to using - * asio::io_service::post(). - * - * @par Example - * To write a single data buffer use the @ref buffer function as follows: - * @code asio::async_write(s, - * asio::buffer(data, size), - * asio::transfer_at_least(32), - * handler); @endcode - * See the @ref buffer documentation for information on writing multiple - * buffers in one go, and how to use it with arrays, boost::array or - * std::vector. - */ -template -void async_write(AsyncWriteStream& s, const ConstBufferSequence& buffers, - CompletionCondition completion_condition, WriteHandler handler); - -/// Start an asynchronous operation to write all of the supplied data to a -/// stream. -/** - * This function is used to asynchronously write a certain number of bytes of - * data to a stream. The function call always returns immediately. The - * asynchronous operation will continue until one of the following conditions - * is true: - * - * @li All of the data in the supplied basic_streambuf has been written. - * - * @li An error occurred. - * - * This operation is implemented in terms of one or more calls to the stream's - * async_write_some function. - * - * @param s The stream to which the data is to be written. The type must support - * the AsyncWriteStream concept. - * - * @param b A basic_streambuf object from which data will be written. Ownership - * of the streambuf is retained by the caller, which must guarantee that it - * remains valid until the handler is called. - * - * @param handler The handler to be called when the write operation completes. - * Copies will be made of the handler as required. The function signature of the - * handler must be: - * @code void handler( - * const asio::error_code& error, // Result of operation. - * - * std::size_t bytes_transferred // Number of bytes written from the - * // buffers. If an error occurred, - * // this will be less than the sum - * // of the buffer sizes. - * ); @endcode - * Regardless of whether the asynchronous operation completes immediately or - * not, the handler will not be invoked from within this function. Invocation of - * the handler will be performed in a manner equivalent to using - * asio::io_service::post(). - */ -template -void async_write(AsyncWriteStream& s, basic_streambuf& b, - WriteHandler handler); - -/// Start an asynchronous operation to write a certain amount of data to a -/// stream. -/** - * This function is used to asynchronously write a certain number of bytes of - * data to a stream. The function call always returns immediately. The - * asynchronous operation will continue until one of the following conditions - * is true: - * - * @li All of the data in the supplied basic_streambuf has been written. - * - * @li The completion_condition function object returns true. - * - * This operation is implemented in terms of one or more calls to the stream's - * async_write_some function. - * - * @param s The stream to which the data is to be written. The type must support - * the AsyncWriteStream concept. - * - * @param b A basic_streambuf object from which data will be written. Ownership - * of the streambuf is retained by the caller, which must guarantee that it - * remains valid until the handler is called. - * - * @param completion_condition The function object to be called to determine - * whether the write operation is complete. The signature of the function object - * must be: - * @code bool completion_condition( - * const asio::error_code& error, // Result of latest write_some - * // operation. - * - * std::size_t bytes_transferred // Number of bytes transferred - * // so far. - * ); @endcode - * A return value of true indicates that the write operation is complete. False - * indicates that further calls to the stream's async_write_some function are - * required. - * - * @param handler The handler to be called when the write operation completes. - * Copies will be made of the handler as required. The function signature of the - * handler must be: - * @code void handler( - * const asio::error_code& error, // Result of operation. - * - * std::size_t bytes_transferred // Number of bytes written from the - * // buffers. If an error occurred, - * // this will be less than the sum - * // of the buffer sizes. - * ); @endcode - * Regardless of whether the asynchronous operation completes immediately or - * not, the handler will not be invoked from within this function. Invocation of - * the handler will be performed in a manner equivalent to using - * asio::io_service::post(). - */ -template -void async_write(AsyncWriteStream& s, basic_streambuf& b, - CompletionCondition completion_condition, WriteHandler handler); - -/*@}*/ - -} // namespace asio - -#include "asio/impl/write.ipp" - -#include "asio/detail/pop_options.hpp" - -#endif // ASIO_WRITE_HPP diff --git a/libtorrent/include/asio/write_at.hpp b/libtorrent/include/asio/write_at.hpp deleted file mode 100644 index a17733fff..000000000 --- a/libtorrent/include/asio/write_at.hpp +++ /dev/null @@ -1,555 +0,0 @@ -// -// write_at.hpp -// ~~~~~~~~~~~~ -// -// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -#ifndef ASIO_WRITE_AT_HPP -#define ASIO_WRITE_AT_HPP - -#if defined(_MSC_VER) && (_MSC_VER >= 1200) -# pragma once -#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) - -#include "asio/detail/push_options.hpp" - -#include "asio/detail/push_options.hpp" -#include -#include -#include -#include "asio/detail/pop_options.hpp" - -#include "asio/basic_streambuf.hpp" -#include "asio/error.hpp" - -namespace asio { - -/** - * @defgroup write_at asio::write_at - * - * @brief Write a certain amount of data at a specified offset before returning. - */ -/*@{*/ - -/// Write all of the supplied data at the specified offset before returning. -/** - * This function is used to write a certain number of bytes of data to a random - * access device at a specified offset. The call will block until one of the - * following conditions is true: - * - * @li All of the data in the supplied buffers has been written. That is, the - * bytes transferred is equal to the sum of the buffer sizes. - * - * @li An error occurred. - * - * This operation is implemented in terms of one or more calls to the device's - * write_some_at function. - * - * @param d The device to which the data is to be written. The type must support - * the SyncRandomAccessWriteDevice concept. - * - * @param offset The offset at which the data will be written. - * - * @param buffers One or more buffers containing the data to be written. The sum - * of the buffer sizes indicates the maximum number of bytes to write to the - * device. - * - * @returns The number of bytes transferred. - * - * @throws asio::system_error Thrown on failure. - * - * @par Example - * To write a single data buffer use the @ref buffer function as follows: - * @code asio::write_at(d, 42, asio::buffer(data, size)); @endcode - * See the @ref buffer documentation for information on writing multiple - * buffers in one go, and how to use it with arrays, boost::array or - * std::vector. - * - * @note This overload is equivalent to calling: - * @code asio::write_at( - * d, offset, buffers, - * asio::transfer_all()); @endcode - */ -template -std::size_t write_at(SyncRandomAccessWriteDevice& d, - boost::uint64_t offset, const ConstBufferSequence& buffers); - -/// Write a certain amount of data at a specified offset before returning. -/** - * This function is used to write a certain number of bytes of data to a random - * access device at a specified offset. The call will block until one of the - * following conditions is true: - * - * @li All of the data in the supplied buffers has been written. That is, the - * bytes transferred is equal to the sum of the buffer sizes. - * - * @li The completion_condition function object returns true. - * - * This operation is implemented in terms of one or more calls to the device's - * write_some_at function. - * - * @param d The device to which the data is to be written. The type must support - * the SyncRandomAccessWriteDevice concept. - * - * @param offset The offset at which the data will be written. - * - * @param buffers One or more buffers containing the data to be written. The sum - * of the buffer sizes indicates the maximum number of bytes to write to the - * device. - * - * @param completion_condition The function object to be called to determine - * whether the write operation is complete. The signature of the function object - * must be: - * @code bool completion_condition( - * // Result of latest write_some_at operation. - * const asio::error_code& error, - * - * // Number of bytes transferred so far. - * std::size_t bytes_transferred - * ); @endcode - * A return value of true indicates that the write operation is complete. False - * indicates that further calls to the device's write_some_at function are - * required. - * - * @returns The number of bytes transferred. - * - * @throws asio::system_error Thrown on failure. - * - * @par Example - * To write a single data buffer use the @ref buffer function as follows: - * @code asio::write_at(d, 42, asio::buffer(data, size), - * asio::transfer_at_least(32)); @endcode - * See the @ref buffer documentation for information on writing multiple - * buffers in one go, and how to use it with arrays, boost::array or - * std::vector. - */ -template -std::size_t write_at(SyncRandomAccessWriteDevice& d, - boost::uint64_t offset, const ConstBufferSequence& buffers, - CompletionCondition completion_condition); - -/// Write a certain amount of data at a specified offset before returning. -/** - * This function is used to write a certain number of bytes of data to a random - * access device at a specified offset. The call will block until one of the - * following conditions is true: - * - * @li All of the data in the supplied buffers has been written. That is, the - * bytes transferred is equal to the sum of the buffer sizes. - * - * @li The completion_condition function object returns true. - * - * This operation is implemented in terms of one or more calls to the device's - * write_some_at function. - * - * @param d The device to which the data is to be written. The type must support - * the SyncRandomAccessWriteDevice concept. - * - * @param offset The offset at which the data will be written. - * - * @param buffers One or more buffers containing the data to be written. The sum - * of the buffer sizes indicates the maximum number of bytes to write to the - * device. - * - * @param completion_condition The function object to be called to determine - * whether the write operation is complete. The signature of the function object - * must be: - * @code bool completion_condition( - * // Result of latest write_some_at operation. - * const asio::error_code& error, - * - * // Number of bytes transferred so far. - * std::size_t bytes_transferred - * ); @endcode - * A return value of true indicates that the write operation is complete. False - * indicates that further calls to the device's write_some_at function are - * required. - * - * @param ec Set to indicate what error occurred, if any. - * - * @returns The number of bytes written. If an error occurs, returns the total - * number of bytes successfully transferred prior to the error. - */ -template -std::size_t write_at(SyncRandomAccessWriteDevice& d, - boost::uint64_t offset, const ConstBufferSequence& buffers, - CompletionCondition completion_condition, asio::error_code& ec); - -/// Write all of the supplied data at the specified offset before returning. -/** - * This function is used to write a certain number of bytes of data to a random - * access device at a specified offset. The call will block until one of the - * following conditions is true: - * - * @li All of the data in the supplied basic_streambuf has been written. - * - * @li An error occurred. - * - * This operation is implemented in terms of one or more calls to the device's - * write_some_at function. - * - * @param d The device to which the data is to be written. The type must support - * the SyncRandomAccessWriteDevice concept. - * - * @param offset The offset at which the data will be written. - * - * @param b The basic_streambuf object from which data will be written. - * - * @returns The number of bytes transferred. - * - * @throws asio::system_error Thrown on failure. - * - * @note This overload is equivalent to calling: - * @code asio::write_at( - * d, 42, b, - * asio::transfer_all()); @endcode - */ -template -std::size_t write_at(SyncRandomAccessWriteDevice& d, - boost::uint64_t offset, basic_streambuf& b); - -/// Write a certain amount of data at a specified offset before returning. -/** - * This function is used to write a certain number of bytes of data to a random - * access device at a specified offset. The call will block until one of the - * following conditions is true: - * - * @li All of the data in the supplied basic_streambuf has been written. - * - * @li The completion_condition function object returns true. - * - * This operation is implemented in terms of one or more calls to the device's - * write_some_at function. - * - * @param d The device to which the data is to be written. The type must support - * the SyncRandomAccessWriteDevice concept. - * - * @param offset The offset at which the data will be written. - * - * @param b The basic_streambuf object from which data will be written. - * - * @param completion_condition The function object to be called to determine - * whether the write operation is complete. The signature of the function object - * must be: - * @code bool completion_condition( - * // Result of latest write_some_at operation. - * const asio::error_code& error, - * - * // Number of bytes transferred so far. - * std::size_t bytes_transferred - * ); @endcode - * A return value of true indicates that the write operation is complete. False - * indicates that further calls to the device's write_some_at function are - * required. - * - * @returns The number of bytes transferred. - * - * @throws asio::system_error Thrown on failure. - */ -template -std::size_t write_at(SyncRandomAccessWriteDevice& d, boost::uint64_t offset, - basic_streambuf& b, CompletionCondition completion_condition); - -/// Write a certain amount of data at a specified offset before returning. -/** - * This function is used to write a certain number of bytes of data to a random - * access device at a specified offset. The call will block until one of the - * following conditions is true: - * - * @li All of the data in the supplied basic_streambuf has been written. - * - * @li The completion_condition function object returns true. - * - * This operation is implemented in terms of one or more calls to the device's - * write_some_at function. - * - * @param d The device to which the data is to be written. The type must support - * the SyncRandomAccessWriteDevice concept. - * - * @param offset The offset at which the data will be written. - * - * @param b The basic_streambuf object from which data will be written. - * - * @param completion_condition The function object to be called to determine - * whether the write operation is complete. The signature of the function object - * must be: - * @code bool completion_condition( - * // Result of latest write_some_at operation. - * const asio::error_code& error, - * - * // Number of bytes transferred so far. - * std::size_t bytes_transferred - * ); @endcode - * A return value of true indicates that the write operation is complete. False - * indicates that further calls to the device's write_some_at function are - * required. - * - * @param ec Set to indicate what error occurred, if any. - * - * @returns The number of bytes written. If an error occurs, returns the total - * number of bytes successfully transferred prior to the error. - */ -template -std::size_t write_at(SyncRandomAccessWriteDevice& d, boost::uint64_t offset, - basic_streambuf& b, CompletionCondition completion_condition, - asio::error_code& ec); - -/*@}*/ -/** - * @defgroup async_write_at asio::async_write_at - * - * @brief Start an asynchronous operation to write a certain amount of data at - * the specified offset. - */ -/*@{*/ - -/// Start an asynchronous operation to write all of the supplied data at the -/// specified offset. -/** - * This function is used to asynchronously write a certain number of bytes of - * data to a random access device at a specified offset. The function call - * always returns immediately. The asynchronous operation will continue until - * one of the following conditions is true: - * - * @li All of the data in the supplied buffers has been written. That is, the - * bytes transferred is equal to the sum of the buffer sizes. - * - * @li An error occurred. - * - * This operation is implemented in terms of one or more calls to the device's - * async_write_some_at function. - * - * @param d The device to which the data is to be written. The type must support - * the AsyncRandomAccessWriteDevice concept. - * - * @param offset The offset at which the data will be written. - * - * @param buffers One or more buffers containing the data to be written. - * Although the buffers object may be copied as necessary, ownership of the - * underlying memory blocks is retained by the caller, which must guarantee - * that they remain valid until the handler is called. - * - * @param handler The handler to be called when the write operation completes. - * Copies will be made of the handler as required. The function signature of - * the handler must be: - * @code void handler( - * // Result of operation. - * const asio::error_code& error, - * - * // Number of bytes written from the buffers. If an error - * // occurred, this will be less than the sum of the buffer sizes. - * std::size_t bytes_transferred - * ); @endcode - * Regardless of whether the asynchronous operation completes immediately or - * not, the handler will not be invoked from within this function. Invocation of - * the handler will be performed in a manner equivalent to using - * asio::io_service::post(). - * - * @par Example - * To write a single data buffer use the @ref buffer function as follows: - * @code - * asio::async_write_at(d, 42, asio::buffer(data, size), handler); - * @endcode - * See the @ref buffer documentation for information on writing multiple - * buffers in one go, and how to use it with arrays, boost::array or - * std::vector. - */ -template -void async_write_at(AsyncRandomAccessWriteDevice& d, boost::uint64_t offset, - const ConstBufferSequence& buffers, WriteHandler handler); - -/// Start an asynchronous operation to write a certain amount of data at the -/// specified offset. -/** - * This function is used to asynchronously write a certain number of bytes of - * data to a random access device at a specified offset. The function call - * always returns immediately. The asynchronous operation will continue until - * one of the following conditions is true: - * - * @li All of the data in the supplied buffers has been written. That is, the - * bytes transferred is equal to the sum of the buffer sizes. - * - * @li The completion_condition function object returns true. - * - * This operation is implemented in terms of one or more calls to the device's - * async_write_some_at function. - * - * @param d The device to which the data is to be written. The type must support - * the AsyncRandomAccessWriteDevice concept. - * - * @param offset The offset at which the data will be written. - * - * @param buffers One or more buffers containing the data to be written. - * Although the buffers object may be copied as necessary, ownership of the - * underlying memory blocks is retained by the caller, which must guarantee - * that they remain valid until the handler is called. - * - * @param completion_condition The function object to be called to determine - * whether the write operation is complete. The signature of the function object - * must be: - * @code bool completion_condition( - * // Result of latest write_some_at operation. - * const asio::error_code& error, - * - * // Number of bytes transferred so far. - * std::size_t bytes_transferred - * ); @endcode - * A return value of true indicates that the write operation is complete. False - * indicates that further calls to the device's async_write_some_at function are - * required. - * - * @param handler The handler to be called when the write operation completes. - * Copies will be made of the handler as required. The function signature of the - * handler must be: - * @code void handler( - * // Result of operation. - * const asio::error_code& error, - * - * // Number of bytes written from the buffers. If an error - * // occurred, this will be less than the sum of the buffer sizes. - * std::size_t bytes_transferred - * ); @endcode - * Regardless of whether the asynchronous operation completes immediately or - * not, the handler will not be invoked from within this function. Invocation of - * the handler will be performed in a manner equivalent to using - * asio::io_service::post(). - * - * @par Example - * To write a single data buffer use the @ref buffer function as follows: - * @code asio::async_write_at(d, 42, - * asio::buffer(data, size), - * asio::transfer_at_least(32), - * handler); @endcode - * See the @ref buffer documentation for information on writing multiple - * buffers in one go, and how to use it with arrays, boost::array or - * std::vector. - */ -template -void async_write_at(AsyncRandomAccessWriteDevice& d, - boost::uint64_t offset, const ConstBufferSequence& buffers, - CompletionCondition completion_condition, WriteHandler handler); - -/// Start an asynchronous operation to write all of the supplied data at the -/// specified offset. -/** - * This function is used to asynchronously write a certain number of bytes of - * data to a random access device at a specified offset. The function call - * always returns immediately. The asynchronous operation will continue until - * one of the following conditions is true: - * - * @li All of the data in the supplied basic_streambuf has been written. - * - * @li An error occurred. - * - * This operation is implemented in terms of one or more calls to the device's - * async_write_some_at function. - * - * @param d The device to which the data is to be written. The type must support - * the AsyncRandomAccessWriteDevice concept. - * - * @param offset The offset at which the data will be written. - * - * @param b A basic_streambuf object from which data will be written. Ownership - * of the streambuf is retained by the caller, which must guarantee that it - * remains valid until the handler is called. - * - * @param handler The handler to be called when the write operation completes. - * Copies will be made of the handler as required. The function signature of the - * handler must be: - * @code void handler( - * // Result of operation. - * const asio::error_code& error, - * - * // Number of bytes written from the buffers. If an error - * // occurred, this will be less than the sum of the buffer sizes. - * std::size_t bytes_transferred - * ); @endcode - * Regardless of whether the asynchronous operation completes immediately or - * not, the handler will not be invoked from within this function. Invocation of - * the handler will be performed in a manner equivalent to using - * asio::io_service::post(). - */ -template -void async_write_at(AsyncRandomAccessWriteDevice& d, boost::uint64_t offset, - basic_streambuf& b, WriteHandler handler); - -/// Start an asynchronous operation to write a certain amount of data at the -/// specified offset. -/** - * This function is used to asynchronously write a certain number of bytes of - * data to a random access device at a specified offset. The function call - * always returns immediately. The asynchronous operation will continue until - * one of the following conditions is true: - * - * @li All of the data in the supplied basic_streambuf has been written. - * - * @li The completion_condition function object returns true. - * - * This operation is implemented in terms of one or more calls to the device's - * async_write_some_at function. - * - * @param d The device to which the data is to be written. The type must support - * the AsyncRandomAccessWriteDevice concept. - * - * @param offset The offset at which the data will be written. - * - * @param b A basic_streambuf object from which data will be written. Ownership - * of the streambuf is retained by the caller, which must guarantee that it - * remains valid until the handler is called. - * - * @param completion_condition The function object to be called to determine - * whether the write operation is complete. The signature of the function object - * must be: - * @code bool completion_condition( - * // Result of latest async_write_some_at operation. - * const asio::error_code& error, - * - * // Number of bytes transferred so far. - * std::size_t bytes_transferred - * ); @endcode - * A return value of true indicates that the write operation is complete. False - * indicates that further calls to the device's async_write_some_at function are - * required. - * - * @param handler The handler to be called when the write operation completes. - * Copies will be made of the handler as required. The function signature of the - * handler must be: - * @code void handler( - * // Result of operation. - * const asio::error_code& error, - * - * // Number of bytes written from the buffers. If an error - * // occurred, this will be less than the sum of the buffer sizes. - * std::size_t bytes_transferred - * ); @endcode - * Regardless of whether the asynchronous operation completes immediately or - * not, the handler will not be invoked from within this function. Invocation of - * the handler will be performed in a manner equivalent to using - * asio::io_service::post(). - */ -template -void async_write_at(AsyncRandomAccessWriteDevice& d, boost::uint64_t offset, - basic_streambuf& b, CompletionCondition completion_condition, - WriteHandler handler); - -/*@}*/ - -} // namespace asio - -#include "asio/impl/write_at.ipp" - -#include "asio/detail/pop_options.hpp" - -#endif // ASIO_WRITE_AT_HPP diff --git a/libtorrent/include/libtorrent/GeoIP.h b/libtorrent/include/libtorrent/GeoIP.h deleted file mode 100644 index 74d5c66c7..000000000 --- a/libtorrent/include/libtorrent/GeoIP.h +++ /dev/null @@ -1,180 +0,0 @@ -/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 2; tab-width: 2 -*- */ -/* GeoIP.h - * - * Copyright (C) 2006 MaxMind LLC - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#ifndef GEOIP_H -#define GEOIP_H - -#ifdef __cplusplus -extern "C" { -#endif - -#include -#include -#include -#include /* for fstat */ -#include /* for fstat */ - -#define SEGMENT_RECORD_LENGTH 3 -#define STANDARD_RECORD_LENGTH 3 -#define ORG_RECORD_LENGTH 4 -#define MAX_RECORD_LENGTH 4 -#define NUM_DB_TYPES 20 - -typedef struct GeoIPTag { - FILE *GeoIPDatabase; - char *file_path; - unsigned char *cache; - unsigned char *index_cache; - unsigned int *databaseSegments; - char databaseType; - time_t mtime; - int flags; - off_t size; - char record_length; - int charset; /* 0 iso-8859-1 1 utf8 */ - int record_iter; /* used in GeoIP_next_record */ - int netmask; /* netmask of last lookup - set using depth in _GeoIP_seek_record */ -} GeoIP; - - -typedef enum { - GEOIP_CHARSET_ISO_8859_1 = 0, - GEOIP_CHARSET_UTF8 = 1 -} GeoIPCharset; - -typedef struct GeoIPRegionTag { - char country_code[3]; - char region[3]; -} GeoIPRegion; - -typedef enum { - GEOIP_STANDARD = 0, - GEOIP_MEMORY_CACHE = 1, - GEOIP_CHECK_CACHE = 2, - GEOIP_INDEX_CACHE = 4, - GEOIP_MMAP_CACHE = 8 -} GeoIPOptions; - -typedef enum { - GEOIP_COUNTRY_EDITION = 1, - GEOIP_REGION_EDITION_REV0 = 7, - GEOIP_CITY_EDITION_REV0 = 6, - GEOIP_ORG_EDITION = 5, - GEOIP_ISP_EDITION = 4, - GEOIP_CITY_EDITION_REV1 = 2, - GEOIP_REGION_EDITION_REV1 = 3, - GEOIP_PROXY_EDITION = 8, - GEOIP_ASNUM_EDITION = 9, - GEOIP_NETSPEED_EDITION = 10, - GEOIP_DOMAIN_EDITION = 11 -} GeoIPDBTypes; - -typedef enum { - GEOIP_ANON_PROXY = 1, - GEOIP_HTTP_X_FORWARDED_FOR_PROXY = 2, - GEOIP_HTTP_CLIENT_IP_PROXY = 3 -} GeoIPProxyTypes; - -typedef enum { - GEOIP_UNKNOWN_SPEED = 0, - GEOIP_DIALUP_SPEED = 1, - GEOIP_CABLEDSL_SPEED = 2, - GEOIP_CORPORATE_SPEED = 3 -} GeoIPNetspeedValues; - -extern char **GeoIPDBFileName; -extern const char * GeoIPDBDescription[NUM_DB_TYPES]; -extern const char *GeoIPCountryDBFileName; -extern const char *GeoIPRegionDBFileName; -extern const char *GeoIPCityDBFileName; -extern const char *GeoIPOrgDBFileName; -extern const char *GeoIPISPDBFileName; - -extern const char GeoIP_country_code[253][3]; -extern const char GeoIP_country_code3[253][4]; -extern const char * GeoIP_country_name[253]; -extern const char GeoIP_country_continent[253][3]; - -#ifdef DLL -#define GEOIP_API __declspec(dllexport) -#else -#define GEOIP_API -#endif /* DLL */ - -GEOIP_API void GeoIP_setup_custom_directory(char *dir); -GEOIP_API GeoIP* GeoIP_open_type (int type, int flags); -GEOIP_API GeoIP* GeoIP_new(int flags); -GEOIP_API GeoIP* GeoIP_open(const char * filename, int flags); -GEOIP_API int GeoIP_db_avail(int type); -GEOIP_API void GeoIP_delete(GeoIP* gi); -GEOIP_API const char *GeoIP_country_code_by_addr (GeoIP* gi, const char *addr); -GEOIP_API const char *GeoIP_country_code_by_name (GeoIP* gi, const char *host); -GEOIP_API const char *GeoIP_country_code3_by_addr (GeoIP* gi, const char *addr); -GEOIP_API const char *GeoIP_country_code3_by_name (GeoIP* gi, const char *host); -GEOIP_API const char *GeoIP_country_name_by_addr (GeoIP* gi, const char *addr); -GEOIP_API const char *GeoIP_country_name_by_name (GeoIP* gi, const char *host); -GEOIP_API const char *GeoIP_country_name_by_ipnum (GeoIP* gi, unsigned long ipnum); -GEOIP_API const char *GeoIP_country_code_by_ipnum (GeoIP* gi, unsigned long ipnum); -GEOIP_API const char *GeoIP_country_code3_by_ipnum (GeoIP* gi, unsigned long ipnum); - -/* Deprecated - for backwards compatibility only */ -GEOIP_API int GeoIP_country_id_by_addr (GeoIP* gi, const char *addr); -GEOIP_API int GeoIP_country_id_by_name (GeoIP* gi, const char *host); -GEOIP_API char *GeoIP_org_by_addr (GeoIP* gi, const char *addr); -GEOIP_API char *GeoIP_org_by_name (GeoIP* gi, const char *host); -/* End deprecated */ - -GEOIP_API int GeoIP_id_by_addr (GeoIP* gi, const char *addr); -GEOIP_API int GeoIP_id_by_name (GeoIP* gi, const char *host); -GEOIP_API int GeoIP_id_by_ipnum (GeoIP* gi, unsigned long ipnum); - -GEOIP_API GeoIPRegion * GeoIP_region_by_addr (GeoIP* gi, const char *addr); -GEOIP_API GeoIPRegion * GeoIP_region_by_name (GeoIP* gi, const char *host); -GEOIP_API GeoIPRegion * GeoIP_region_by_ipnum (GeoIP *gi, unsigned long ipnum); - -/* Warning - don't call this after GeoIP_assign_region_by_inetaddr calls */ -GEOIP_API void GeoIPRegion_delete (GeoIPRegion *gir); - -GEOIP_API void GeoIP_assign_region_by_inetaddr(GeoIP* gi, unsigned long inetaddr, GeoIPRegion *gir); - -/* Used to query GeoIP Organization, ISP and AS Number databases */ -GEOIP_API char *GeoIP_name_by_ipnum (GeoIP* gi, unsigned long ipnum); -GEOIP_API char *GeoIP_name_by_addr (GeoIP* gi, const char *addr); -GEOIP_API char *GeoIP_name_by_name (GeoIP* gi, const char *host); - -GEOIP_API char *GeoIP_database_info (GeoIP* gi); -GEOIP_API unsigned char GeoIP_database_edition (GeoIP* gi); - -GEOIP_API int GeoIP_charset (GeoIP* gi); -GEOIP_API int GeoIP_set_charset (GeoIP* gi, int charset); - -GEOIP_API int GeoIP_last_netmask (GeoIP* gi); - -/* Convert region code to region name */ -GEOIP_API const char * GeoIP_region_name_by_code(const char *country_code, const char *region_code); - -/* Get timezone from country and region code */ -GEOIP_API const char * GeoIP_time_zone_by_country_and_region(const char *country_code, const char *region_code); - -#ifdef __cplusplus -} -#endif - -#endif /* GEOIP_H */ diff --git a/libtorrent/include/libtorrent/alert.hpp b/libtorrent/include/libtorrent/alert.hpp deleted file mode 100644 index 105dde3f5..000000000 --- a/libtorrent/include/libtorrent/alert.hpp +++ /dev/null @@ -1,196 +0,0 @@ -/* - -Copyright (c) 2003, Arvid Norberg, Daniel Wallin -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions -are met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in - the documentation and/or other materials provided with the distribution. - * Neither the name of the author nor the names of its - contributors may be used to endorse or promote products derived - from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -POSSIBILITY OF SUCH DAMAGE. - -*/ - -#ifndef TORRENT_ALERT_HPP_INCLUDED -#define TORRENT_ALERT_HPP_INCLUDED - -#include -#include -#include -#include - -#ifdef _MSC_VER -#pragma warning(push, 1) -#endif - -#include -#include - -#include -#include -#include -#include - -#ifdef _MSC_VER -#pragma warning(pop) -#endif - -#include "libtorrent/time.hpp" -#include "libtorrent/config.hpp" -#include "libtorrent/assert.hpp" - -#ifndef TORRENT_MAX_ALERT_TYPES -#define TORRENT_MAX_ALERT_TYPES 15 -#endif - -namespace libtorrent { - - class TORRENT_EXPORT alert - { - public: - - // only here for backwards compatibility - enum severity_t { debug, info, warning, critical, fatal, none }; - - enum category_t - { - error_notification = 0x1, - peer_notification = 0x2, - port_mapping_notification = 0x4, - storage_notification = 0x8, - tracker_notification = 0x10, - debug_notification = 0x20, - status_notification = 0x40, - progress_notification = 0x80, - ip_block_notification = 0x100, - performance_warning = 0x200, - - all_categories = 0xffffffff - }; - - alert(); - virtual ~alert(); - - // a timestamp is automatically created in the constructor - ptime timestamp() const; - - virtual char const* what() const = 0; - virtual std::string message() const = 0; - virtual int category() const = 0; - -#ifndef TORRENT_NO_DEPRECATE - severity_t severity() const TORRENT_DEPRECATED { return warning; } -#endif - - virtual std::auto_ptr clone() const = 0; - - private: - ptime m_timestamp; - }; - - class TORRENT_EXPORT alert_manager - { - public: - enum { queue_size_limit_default = 1000 }; - - alert_manager(); - ~alert_manager(); - - void post_alert(const alert& alert_); - bool pending() const; - std::auto_ptr get(); - - template - bool should_post() const { return (m_alert_mask & T::static_category) != 0; } - - alert const* wait_for_alert(time_duration max_wait); - - void set_alert_mask(int m) { m_alert_mask = m; } - - size_t alert_queue_size_limit() const { return m_queue_size_limit; } - size_t set_alert_queue_size_limit(size_t queue_size_limit_); - - private: - std::queue m_alerts; - mutable boost::mutex m_mutex; - boost::condition m_condition; - int m_alert_mask; - size_t m_queue_size_limit; - }; - - struct TORRENT_EXPORT unhandled_alert : std::exception - { - unhandled_alert() {} - }; - - namespace detail { - - struct void_; - - template - void handle_alert_dispatch( - const std::auto_ptr& alert_, const Handler& handler - , const std::type_info& typeid_ - , BOOST_PP_ENUM_BINARY_PARAMS(TORRENT_MAX_ALERT_TYPES, T, *p)) - { - if (typeid_ == typeid(T0)) - handler(*static_cast(alert_.get())); - else - handle_alert_dispatch(alert_, handler, typeid_ - , BOOST_PP_ENUM_SHIFTED_PARAMS( - TORRENT_MAX_ALERT_TYPES, p), (void_*)0); - } - - template - void handle_alert_dispatch( - const std::auto_ptr& alert_ - , const Handler& handler - , const std::type_info& typeid_ - , BOOST_PP_ENUM_PARAMS(TORRENT_MAX_ALERT_TYPES, void_* BOOST_PP_INTERCEPT)) - { - throw unhandled_alert(); - } - - } // namespace detail - - template - struct TORRENT_EXPORT handle_alert - { - template - handle_alert(const std::auto_ptr& alert_ - , const Handler& handler) - { - #define ALERT_POINTER_TYPE(z, n, text) (BOOST_PP_CAT(T, n)*)0 - - detail::handle_alert_dispatch(alert_, handler, typeid(*alert_) - , BOOST_PP_ENUM(TORRENT_MAX_ALERT_TYPES, ALERT_POINTER_TYPE, _)); - - #undef ALERT_POINTER_TYPE - } - }; - -} // namespace libtorrent - -#endif // TORRENT_ALERT_HPP_INCLUDED - diff --git a/libtorrent/include/libtorrent/alert_types.hpp b/libtorrent/include/libtorrent/alert_types.hpp deleted file mode 100644 index b98debf3f..000000000 --- a/libtorrent/include/libtorrent/alert_types.hpp +++ /dev/null @@ -1,1151 +0,0 @@ -/* - -Copyright (c) 2003, Arvid Norberg -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions -are met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in - the documentation and/or other materials provided with the distribution. - * Neither the name of the author nor the names of its - contributors may be used to endorse or promote products derived - from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -POSSIBILITY OF SUCH DAMAGE. - -*/ - -#ifndef TORRENT_ALERT_TYPES_HPP_INCLUDED -#define TORRENT_ALERT_TYPES_HPP_INCLUDED - -#include "libtorrent/alert.hpp" -#include "libtorrent/torrent_handle.hpp" -#include "libtorrent/socket.hpp" -#include "libtorrent/peer_connection.hpp" -#include "libtorrent/config.hpp" -#include "libtorrent/assert.hpp" -#include "libtorrent/identify_client.hpp" - -#include - -namespace libtorrent -{ - struct TORRENT_EXPORT torrent_alert: alert - { - torrent_alert(torrent_handle const& h) - : handle(h) - {} - - virtual std::string message() const - { return handle.is_valid()?handle.name():" - "; } - - torrent_handle handle; - }; - - struct TORRENT_EXPORT peer_alert: torrent_alert - { - peer_alert(torrent_handle const& h, tcp::endpoint const& ip_ - , peer_id const& pid_) - : torrent_alert(h) - , ip(ip_) - , pid(pid_) - {} - - const static int static_category = alert::peer_notification; - virtual int category() const { return static_category; } - virtual std::string message() const - { - error_code ec; - return torrent_alert::message() + " peer (" + ip.address().to_string(ec) - + ", " + identify_client(pid) + ")"; - } - - tcp::endpoint ip; - peer_id pid; - }; - - struct TORRENT_EXPORT tracker_alert: torrent_alert - { - tracker_alert(torrent_handle const& h - , std::string const& url_) - : torrent_alert(h) - , url(url_) - {} - - const static int static_category = alert::tracker_notification; - virtual int category() const { return static_category; } - virtual std::string message() const - { - return torrent_alert::message() + " (" + url + ")"; - } - - std::string url; - }; - - struct TORRENT_EXPORT file_renamed_alert: torrent_alert - { - file_renamed_alert(torrent_handle const& h - , std::string const& name_ - , int index_) - : torrent_alert(h) - , name(name_) - , index(index_) - {} - - virtual std::auto_ptr clone() const - { return std::auto_ptr(new file_renamed_alert(*this)); } - const static int static_category = alert::storage_notification; - virtual int category() const { return static_category; } - virtual char const* what() const { return "file renamed"; } - virtual std::string message() const - { - std::stringstream ret; - ret << torrent_alert::message() << ": file " - << index << " renamed to " << name; - return ret.str(); - } - - std::string name; - int index; - }; - - struct TORRENT_EXPORT file_rename_failed_alert: torrent_alert - { - file_rename_failed_alert(torrent_handle const& h - , std::string const& msg_ - , int index_) - : torrent_alert(h) - , msg(msg_) - , index(index_) - {} - - virtual std::auto_ptr clone() const - { return std::auto_ptr(new file_rename_failed_alert(*this)); } - - virtual char const* what() const { return "file rename failed"; } - virtual std::string message() const - { - std::stringstream ret; - ret << torrent_alert::message() << ": failed to rename file " - << index << ": " << msg; - return ret.str(); - } - - const static int static_category = alert::storage_notification; - virtual int category() const { return static_category; } - - std::string msg; - int index; - }; - - struct TORRENT_EXPORT performance_alert: torrent_alert - { - enum performance_warning_t - { - outstanding_disk_buffer_limit_reached, - outstanding_request_limit_reached - }; - - performance_alert(torrent_handle const& h - , performance_warning_t w) - : torrent_alert(h) - , warning_code(w) - {} - - virtual std::auto_ptr clone() const - { return std::auto_ptr(new performance_alert(*this)); } - - virtual char const* what() const { return "performance warning"; } - virtual std::string message() const - { - static char const* warning_str[] = - { - "max outstanding disk writes reached", - "max outstanding piece requests reached", - }; - - return torrent_alert::message() + ": performance warning: " - + warning_str[warning_code]; - } - - const static int static_category = alert::performance_warning; - virtual int category() const { return static_category; } - - performance_warning_t warning_code; - }; - - struct TORRENT_EXPORT state_changed_alert: torrent_alert - { - state_changed_alert(torrent_handle const& h - , torrent_status::state_t const& state_) - : torrent_alert(h) - , state(state_) - {} - - virtual std::auto_ptr clone() const - { return std::auto_ptr(new state_changed_alert(*this)); } - - virtual char const* what() const { return "torrent state changed"; } - virtual std::string message() const - { - static char const* state_str[] = - {"checking (q)", "checking", "dl metadata" - , "downloading", "finished", "seeding", "allocating" - , "checking (r)"}; - - return torrent_alert::message() + ": state changed to: " - + state_str[state]; - } - - - const static int static_category = alert::status_notification; - virtual int category() const { return static_category; } - - torrent_status::state_t state; - }; - - struct TORRENT_EXPORT tracker_error_alert: tracker_alert - { - tracker_error_alert(torrent_handle const& h - , int times - , int status - , std::string const& url_ - , std::string const& msg_) - : tracker_alert(h, url_) - , times_in_row(times) - , status_code(status) - , msg(msg_) - { TORRENT_ASSERT(!url.empty()); } - - virtual std::auto_ptr clone() const - { return std::auto_ptr(new tracker_error_alert(*this)); } - const static int static_category = alert::tracker_notification | alert::error_notification; - virtual int category() const { return static_category; } - virtual char const* what() const { return "tracker error"; } - virtual std::string message() const - { - std::stringstream ret; - ret << tracker_alert::message() << " (" << status_code << ") " - << msg << " (" << times_in_row << ")"; - return ret.str(); - } - - int times_in_row; - int status_code; - std::string msg; - }; - - struct TORRENT_EXPORT tracker_warning_alert: tracker_alert - { - tracker_warning_alert(torrent_handle const& h - , std::string const& url_ - , std::string const& msg_) - : tracker_alert(h, url_) - , msg(msg_) - { TORRENT_ASSERT(!url.empty()); } - - std::string msg; - - virtual std::auto_ptr clone() const - { return std::auto_ptr(new tracker_warning_alert(*this)); } - const static int static_category = alert::tracker_notification | alert::error_notification; - virtual int category() const { return static_category; } - virtual char const* what() const { return "tracker warning"; } - virtual std::string message() const - { - return tracker_alert::message() + " warning: " + msg; - } - }; - - struct TORRENT_EXPORT scrape_reply_alert: tracker_alert - { - scrape_reply_alert(torrent_handle const& h - , int incomplete_ - , int complete_ - , std::string const& url_) - : tracker_alert(h, url_) - , incomplete(incomplete_) - , complete(complete_) - { TORRENT_ASSERT(!url.empty()); } - - int incomplete; - int complete; - - virtual std::auto_ptr clone() const - { return std::auto_ptr(new scrape_reply_alert(*this)); } - virtual char const* what() const { return "tracker scrape reply"; } - virtual std::string message() const - { - std::stringstream ret; - ret << tracker_alert::message() << " scrape reply: " << incomplete - << " " << complete; - return ret.str(); - } - }; - - struct TORRENT_EXPORT scrape_failed_alert: tracker_alert - { - scrape_failed_alert(torrent_handle const& h - , std::string const& url_ - , std::string const& msg_) - : tracker_alert(h, url_) - , msg(msg_) - { TORRENT_ASSERT(!url.empty()); } - - std::string msg; - - virtual std::auto_ptr clone() const - { return std::auto_ptr(new scrape_failed_alert(*this)); } - const static int static_category = alert::tracker_notification | alert::error_notification; - virtual int category() const { return static_category; } - virtual char const* what() const { return "tracker scrape failed"; } - virtual std::string message() const - { - return tracker_alert::message() + " scrape failed: " + msg; - } - }; - - struct TORRENT_EXPORT tracker_reply_alert: tracker_alert - { - tracker_reply_alert(torrent_handle const& h - , int np - , std::string const& url_) - : tracker_alert(h, url_) - , num_peers(np) - { TORRENT_ASSERT(!url.empty()); } - - int num_peers; - - virtual std::auto_ptr clone() const - { return std::auto_ptr(new tracker_reply_alert(*this)); } - virtual char const* what() const { return "tracker reply"; } - virtual std::string message() const - { - std::stringstream ret; - ret << tracker_alert::message() << " received peers: " - << num_peers; - return ret.str(); - } - }; - - struct TORRENT_EXPORT dht_reply_alert: tracker_alert - { - dht_reply_alert(torrent_handle const& h - , int np) - : tracker_alert(h, "") - , num_peers(np) - {} - - int num_peers; - - virtual std::auto_ptr clone() const - { return std::auto_ptr(new dht_reply_alert(*this)); } - virtual char const* what() const { return "DHT reply"; } - virtual std::string message() const - { - std::stringstream ret; - ret << torrent_alert::message() << " received DHT peers: " - << num_peers; - return ret.str(); - } - }; - - struct TORRENT_EXPORT tracker_announce_alert: tracker_alert - { - tracker_announce_alert(torrent_handle const& h - , std::string const& url_, int event_) - : tracker_alert(h, url_) - , event(event_) - { TORRENT_ASSERT(!url.empty()); } - - int event; - - virtual std::auto_ptr clone() const - { return std::auto_ptr(new tracker_announce_alert(*this)); } - virtual char const* what() const { return "tracker announce sent"; } - virtual std::string message() const - { - const static char* event_str[] = {"none", "completed", "started", "stopped"}; - return tracker_alert::message() + " sending announce (" + event_str[event] + ")"; - } - }; - - struct TORRENT_EXPORT hash_failed_alert: torrent_alert - { - hash_failed_alert( - torrent_handle const& h - , int index) - : torrent_alert(h) - , piece_index(index) - { TORRENT_ASSERT(index >= 0);} - - virtual std::auto_ptr clone() const - { return std::auto_ptr(new hash_failed_alert(*this)); } - virtual char const* what() const { return "piece hash failed"; } - const static int static_category = alert::status_notification; - virtual int category() const { return static_category; } - virtual std::string message() const - { - std::stringstream ret; - ret << torrent_alert::message() << " hash for piece " - << piece_index << " failed"; - return ret.str(); - } - - int piece_index; - }; - - struct TORRENT_EXPORT peer_ban_alert: peer_alert - { - peer_ban_alert(torrent_handle h, tcp::endpoint const& ip - , peer_id const& pid) - : peer_alert(h, ip, pid) - {} - - virtual std::auto_ptr clone() const - { return std::auto_ptr(new peer_ban_alert(*this)); } - virtual char const* what() const { return "peer banned"; } - virtual std::string message() const - { - error_code ec; - return peer_alert::message() + " banned peer"; - } - }; - - struct TORRENT_EXPORT peer_unsnubbed_alert: peer_alert - { - peer_unsnubbed_alert(torrent_handle h, tcp::endpoint const& ip - , peer_id const& pid) - : peer_alert(h, ip, pid) - {} - - virtual std::auto_ptr clone() const - { return std::auto_ptr(new peer_unsnubbed_alert(*this)); } - virtual char const* what() const { return "peer unsnubbed"; } - virtual std::string message() const - { - return peer_alert::message() + " peer unsnubbed"; - } - }; - - struct TORRENT_EXPORT peer_snubbed_alert: peer_alert - { - peer_snubbed_alert(torrent_handle h, tcp::endpoint const& ip - , peer_id const& pid) - : peer_alert(h, ip, pid) - {} - - virtual std::auto_ptr clone() const - { return std::auto_ptr(new peer_snubbed_alert(*this)); } - virtual char const* what() const { return "peer snubbed"; } - virtual std::string message() const - { - return peer_alert::message() + " peer snubbed"; - } - }; - - struct TORRENT_EXPORT peer_error_alert: peer_alert - { - peer_error_alert(torrent_handle const& h, tcp::endpoint const& ip - , peer_id const& pid, std::string const& msg_) - : peer_alert(h, ip, pid) - , msg(msg_) - {} - - virtual std::auto_ptr clone() const - { return std::auto_ptr(new peer_error_alert(*this)); } - virtual char const* what() const { return "peer error"; } - const static int static_category = alert::peer_notification; - virtual int category() const { return static_category; } - virtual std::string message() const - { - error_code ec; - return peer_alert::message() + " peer error: " + msg; - } - - std::string msg; - }; - - struct TORRENT_EXPORT peer_connect_alert: peer_alert - { - peer_connect_alert(torrent_handle h, tcp::endpoint const& ip - , peer_id const& pid) - : peer_alert(h, ip, pid) - {} - - virtual std::auto_ptr clone() const - { return std::auto_ptr(new peer_connect_alert(*this)); } - virtual char const* what() const { return "connecting to peer"; } - const static int static_category = alert::debug_notification; - virtual int category() const { return static_category; } - virtual std::string message() const - { - return peer_alert::message() + " connecting to peer"; - } - }; - - struct TORRENT_EXPORT peer_disconnected_alert: peer_alert - { - peer_disconnected_alert(torrent_handle const& h, tcp::endpoint const& ip - , peer_id const& pid, std::string const& msg_) - : peer_alert(h, ip, pid) - , msg(msg_) - {} - - virtual std::auto_ptr clone() const - { return std::auto_ptr(new peer_disconnected_alert(*this)); } - virtual char const* what() const { return "peer disconnected"; } - const static int static_category = alert::debug_notification; - virtual int category() const { return static_category; } - virtual std::string message() const - { - return peer_alert::message() + " disconnecting: " + msg; - } - - std::string msg; - }; - - struct TORRENT_EXPORT invalid_request_alert: peer_alert - { - invalid_request_alert(torrent_handle const& h, tcp::endpoint const& ip - , peer_id const& pid, peer_request const& r) - : peer_alert(h, ip, pid) - , request(r) - {} - - virtual std::auto_ptr clone() const - { return std::auto_ptr(new invalid_request_alert(*this)); } - virtual char const* what() const { return "invalid piece request"; } - virtual std::string message() const - { - std::stringstream ret; - ret << peer_alert::message() << " peer sent an invalid piece request " - "( piece: " << request.piece << " start: " << request.start - << " len: " << request.length << ")"; - return ret.str(); - } - - peer_request request; - }; - - struct TORRENT_EXPORT torrent_finished_alert: torrent_alert - { - torrent_finished_alert( - const torrent_handle& h) - : torrent_alert(h) - {} - - virtual std::auto_ptr clone() const - { return std::auto_ptr(new torrent_finished_alert(*this)); } - virtual char const* what() const { return "torrent finished"; } - const static int static_category = alert::status_notification; - virtual int category() const { return static_category; } - virtual std::string message() const - { - return torrent_alert::message() + " torrent finished downloading"; - } - }; - - struct TORRENT_EXPORT piece_finished_alert: torrent_alert - { - piece_finished_alert( - const torrent_handle& h - , int piece_num) - : torrent_alert(h) - , piece_index(piece_num) - { TORRENT_ASSERT(piece_index >= 0);} - - int piece_index; - - virtual std::auto_ptr clone() const - { return std::auto_ptr(new piece_finished_alert(*this)); } - virtual char const* what() const { return "piece finished downloading"; } - const static int static_category = alert::progress_notification; - virtual int category() const { return static_category; } - virtual std::string message() const - { - std::stringstream ret; - ret << torrent_alert::message() << " piece " << piece_index - << " finished downloading"; - return ret.str(); - } - }; - - struct TORRENT_EXPORT request_dropped_alert: peer_alert - { - request_dropped_alert(const torrent_handle& h, tcp::endpoint const& ip - , peer_id const& pid, int block_num, int piece_num) - : peer_alert(h, ip, pid) - , block_index(block_num) - , piece_index(piece_num) - { TORRENT_ASSERT(block_index >= 0 && piece_index >= 0);} - - int block_index; - int piece_index; - - virtual std::auto_ptr clone() const - { return std::auto_ptr(new request_dropped_alert(*this)); } - virtual char const* what() const { return "block request dropped"; } - const static int static_category = alert::progress_notification - | alert::peer_notification; - virtual int category() const { return static_category; } - virtual std::string message() const - { - std::stringstream ret; - ret << peer_alert::message() << " peer dropped block ( piece: " - << piece_index << " block: " << block_index << ")"; - return ret.str(); - } - }; - - struct TORRENT_EXPORT block_timeout_alert: peer_alert - { - block_timeout_alert(const torrent_handle& h, tcp::endpoint const& ip - , peer_id const& pid, int block_num, int piece_num) - : peer_alert(h, ip, pid) - , block_index(block_num) - , piece_index(piece_num) - { TORRENT_ASSERT(block_index >= 0 && piece_index >= 0);} - - int block_index; - int piece_index; - - virtual std::auto_ptr clone() const - { return std::auto_ptr(new block_timeout_alert(*this)); } - virtual char const* what() const { return "block timed out"; } - const static int static_category = alert::progress_notification - | alert::peer_notification; - virtual int category() const { return static_category; } - virtual std::string message() const - { - std::stringstream ret; - ret << peer_alert::message() << " peer timed out request ( piece: " - << piece_index << " block: " << block_index << ")"; - return ret.str(); - } - }; - - struct TORRENT_EXPORT block_finished_alert: peer_alert - { - block_finished_alert(const torrent_handle& h, tcp::endpoint const& ip - , peer_id const& pid, int block_num, int piece_num) - : peer_alert(h, ip, pid) - , block_index(block_num) - , piece_index(piece_num) - { TORRENT_ASSERT(block_index >= 0 && piece_index >= 0);} - - int block_index; - int piece_index; - - virtual std::auto_ptr clone() const - { return std::auto_ptr(new block_finished_alert(*this)); } - virtual char const* what() const { return "block finished downloading"; } - const static int static_category = alert::progress_notification; - virtual int category() const { return static_category; } - virtual std::string message() const - { - std::stringstream ret; - ret << peer_alert::message() << " block finished downloading ( piece: " - << piece_index << " block: " << block_index << ")"; - return ret.str(); - } - }; - - struct TORRENT_EXPORT block_downloading_alert: peer_alert - { - block_downloading_alert(const torrent_handle& h, tcp::endpoint const& ip - , peer_id const& pid, char const* speedmsg, int block_num, int piece_num) - : peer_alert(h, ip, pid) - , peer_speedmsg(speedmsg) - , block_index(block_num) - , piece_index(piece_num) - { TORRENT_ASSERT(block_index >= 0 && piece_index >= 0);} - - char const* peer_speedmsg; - int block_index; - int piece_index; - - virtual std::auto_ptr clone() const - { return std::auto_ptr(new block_downloading_alert(*this)); } - virtual char const* what() const { return "block requested"; } - const static int static_category = alert::progress_notification; - virtual int category() const { return static_category; } - virtual std::string message() const - { - std::stringstream ret; - ret << peer_alert::message() << " requested block ( piece: " - << piece_index << " block: " << block_index << ") " << peer_speedmsg; - return ret.str(); - } - }; - - struct TORRENT_EXPORT unwanted_block_alert: peer_alert - { - unwanted_block_alert(const torrent_handle& h, tcp::endpoint const& ip - , peer_id const& pid, int block_num, int piece_num) - : peer_alert(h, ip, pid) - , block_index(block_num) - , piece_index(piece_num) - { TORRENT_ASSERT(block_index >= 0 && piece_index >= 0);} - - int block_index; - int piece_index; - - virtual std::auto_ptr clone() const - { return std::auto_ptr(new unwanted_block_alert(*this)); } - virtual char const* what() const { return "unwanted block received"; } - virtual std::string message() const - { - std::stringstream ret; - ret << peer_alert::message() << " received block not in download queue ( piece: " - << piece_index << " block: " << block_index << ")"; - return ret.str(); - } - }; - - struct TORRENT_EXPORT storage_moved_alert: torrent_alert - { - storage_moved_alert(torrent_handle const& h, std::string const& path_) - : torrent_alert(h) - , path(path_) - {} - - std::string path; - - virtual std::auto_ptr clone() const - { return std::auto_ptr(new storage_moved_alert(*this)); } - virtual char const* what() const { return "storage moved"; } - const static int static_category = alert::storage_notification; - virtual int category() const { return static_category; } - virtual std::string message() const - { - return torrent_alert::message() + " moved storage to: " - + path; - } - }; - - struct TORRENT_EXPORT torrent_deleted_alert: torrent_alert - { - torrent_deleted_alert(torrent_handle const& h) - : torrent_alert(h) - {} - - virtual std::auto_ptr clone() const - { return std::auto_ptr(new torrent_deleted_alert(*this)); } - virtual char const* what() const { return "torrent deleted"; } - const static int static_category = alert::storage_notification; - virtual int category() const { return static_category; } - virtual std::string message() const - { - return torrent_alert::message() + " deleted"; - } - }; - - struct TORRENT_EXPORT torrent_delete_failed_alert: torrent_alert - { - torrent_delete_failed_alert(torrent_handle const& h, std::string msg_) - : torrent_alert(h) - , msg(msg_) - {} - - std::string msg; - - virtual std::auto_ptr clone() const - { return std::auto_ptr(new torrent_delete_failed_alert(*this)); } - virtual char const* what() const { return "torrent delete failed"; } - const static int static_category = alert::storage_notification - | alert::error_notification; - virtual int category() const { return static_category; } - virtual std::string message() const - { - return torrent_alert::message() + " torrent deletion failed: " - + msg; - } - }; - - struct TORRENT_EXPORT save_resume_data_alert: torrent_alert - { - save_resume_data_alert(boost::shared_ptr const& rd - , torrent_handle const& h) - : torrent_alert(h) - , resume_data(rd) - {} - - boost::shared_ptr resume_data; - - virtual std::auto_ptr clone() const - { return std::auto_ptr(new save_resume_data_alert(*this)); } - virtual char const* what() const { return "save resume data complete"; } - const static int static_category = alert::storage_notification; - virtual int category() const { return static_category; } - virtual std::string message() const - { - return torrent_alert::message() + " resume data generated"; - } - }; - - struct TORRENT_EXPORT save_resume_data_failed_alert: torrent_alert - { - save_resume_data_failed_alert(torrent_handle const& h - , std::string const& msg_) - : torrent_alert(h) - , msg(msg_) - {} - - std::string msg; - - virtual std::auto_ptr clone() const - { return std::auto_ptr(new save_resume_data_failed_alert(*this)); } - virtual char const* what() const { return "save resume data failed"; } - const static int static_category = alert::storage_notification - | alert::error_notification; - virtual int category() const { return static_category; } - virtual std::string message() const - { - return torrent_alert::message() + " resume data was not generated: " - + msg; - } - }; - - struct TORRENT_EXPORT torrent_paused_alert: torrent_alert - { - torrent_paused_alert(torrent_handle const& h) - : torrent_alert(h) - {} - - virtual std::auto_ptr clone() const - { return std::auto_ptr(new torrent_paused_alert(*this)); } - virtual char const* what() const { return "torrent paused"; } - const static int static_category = alert::status_notification; - virtual int category() const { return static_category; } - virtual std::string message() const - { - return torrent_alert::message() + " paused"; - } - }; - - struct TORRENT_EXPORT torrent_resumed_alert: torrent_alert - { - torrent_resumed_alert(torrent_handle const& h) - : torrent_alert(h) {} - - virtual std::auto_ptr clone() const - { return std::auto_ptr(new torrent_resumed_alert(*this)); } - virtual char const* what() const { return "torrent resumed"; } - const static int static_category = alert::status_notification; - virtual int category() const { return static_category; } - virtual std::string message() const - { - return torrent_alert::message() + " resumed"; - } - }; - - struct TORRENT_EXPORT torrent_checked_alert: torrent_alert - { - torrent_checked_alert(torrent_handle const& h) - : torrent_alert(h) - {} - - virtual std::auto_ptr clone() const - { return std::auto_ptr(new torrent_checked_alert(*this)); } - virtual char const* what() const { return "torrent checked"; } - const static int static_category = alert::status_notification; - virtual int category() const { return static_category; } - virtual std::string message() const - { - return torrent_alert::message() + " checked"; - } - }; - - - struct TORRENT_EXPORT url_seed_alert: torrent_alert - { - url_seed_alert( - torrent_handle const& h - , const std::string& url_ - , const std::string& msg_) - : torrent_alert(h) - , url(url_) - , msg(msg_) - {} - - virtual std::auto_ptr clone() const - { return std::auto_ptr(new url_seed_alert(*this)); } - virtual char const* what() const { return "web seed error"; } - const static int static_category = alert::peer_notification | alert::error_notification; - virtual int category() const { return static_category; } - virtual std::string message() const - { - return torrent_alert::message() + " url seed (" - + url + ") failed: " + msg; - } - - std::string url; - std::string msg; - }; - - struct TORRENT_EXPORT file_error_alert: torrent_alert - { - file_error_alert( - std::string const& f - , const torrent_handle& h - , const std::string& msg_) - : torrent_alert(h) - , file(f) - , msg(msg_) - {} - - std::string file; - std::string msg; - - virtual std::auto_ptr clone() const - { return std::auto_ptr(new file_error_alert(*this)); } - virtual char const* what() const { return "file error"; } - const static int static_category = alert::status_notification - | alert::error_notification - | alert::storage_notification; - virtual int category() const { return static_category; } - virtual std::string message() const - { - return torrent_alert::message() + " file (" + file + ") error: " - + msg; - } - }; - - struct TORRENT_EXPORT metadata_failed_alert: torrent_alert - { - metadata_failed_alert(const torrent_handle& h) - : torrent_alert(h) - {} - - virtual std::auto_ptr clone() const - { return std::auto_ptr(new metadata_failed_alert(*this)); } - virtual char const* what() const { return "metadata failed"; } - const static int static_category = alert::error_notification; - virtual int category() const { return static_category; } - virtual std::string message() const - { - return torrent_alert::message() + " invalid metadata received"; - } - }; - - struct TORRENT_EXPORT metadata_received_alert: torrent_alert - { - metadata_received_alert( - const torrent_handle& h) - : torrent_alert(h) - {} - - virtual std::auto_ptr clone() const - { return std::auto_ptr(new metadata_received_alert(*this)); } - virtual char const* what() const { return "metadata received"; } - const static int static_category = alert::status_notification; - virtual int category() const { return static_category; } - virtual std::string message() const - { - return torrent_alert::message() + " metadata successfully received"; - } - }; - - struct TORRENT_EXPORT udp_error_alert: alert - { - udp_error_alert( - udp::endpoint const& ep - , error_code const& ec) - : endpoint(ep) - , error(ec) - {} - - udp::endpoint endpoint; - error_code error; - - virtual std::auto_ptr clone() const - { return std::auto_ptr(new udp_error_alert(*this)); } - virtual char const* what() const { return "udp error"; } - const static int static_category = alert::error_notification; - virtual int category() const { return static_category; } - virtual std::string message() const - { - error_code ec; - return "UDP error: " + error.message() + " from: " + endpoint.address().to_string(ec); - } - }; - - struct TORRENT_EXPORT external_ip_alert: alert - { - external_ip_alert(address const& ip) - : external_address(ip) - {} - - address external_address; - - virtual std::auto_ptr clone() const - { return std::auto_ptr(new external_ip_alert(*this)); } - virtual char const* what() const { return "external IP received"; } - const static int static_category = alert::status_notification; - virtual int category() const { return static_category; } - virtual std::string message() const - { - error_code ec; - return "external IP received: " + external_address.to_string(ec); - } - }; - - struct TORRENT_EXPORT listen_failed_alert: alert - { - listen_failed_alert( - tcp::endpoint const& ep - , error_code const& ec) - : endpoint(ep) - , error(ec) - {} - - tcp::endpoint endpoint; - error_code error; - - virtual std::auto_ptr clone() const - { return std::auto_ptr(new listen_failed_alert(*this)); } - virtual char const* what() const { return "listen failed"; } - const static int static_category = alert::status_notification | alert::error_notification; - virtual int category() const { return static_category; } - virtual std::string message() const - { - error_code ec; - std::stringstream ret; - ret << "listening on " << endpoint - << " failed: " << error.message(); - return ret.str(); - } - }; - - struct TORRENT_EXPORT listen_succeeded_alert: alert - { - listen_succeeded_alert(tcp::endpoint const& ep) - : endpoint(ep) - {} - - tcp::endpoint endpoint; - - virtual std::auto_ptr clone() const - { return std::auto_ptr(new listen_succeeded_alert(*this)); } - virtual char const* what() const { return "listen succeeded"; } - const static int static_category = alert::status_notification; - virtual int category() const { return static_category; } - virtual std::string message() const - { - error_code ec; - std::stringstream ret; - ret << "successfully listening on " << endpoint; - return ret.str(); - } - }; - - struct TORRENT_EXPORT portmap_error_alert: alert - { - portmap_error_alert(int i, int t, const std::string& msg_) - : mapping(i), type(t), msg(msg_) - {} - - int mapping; - int type; - std::string msg; - - virtual std::auto_ptr clone() const - { return std::auto_ptr(new portmap_error_alert(*this)); } - virtual char const* what() const { return "port map error"; } - const static int static_category = alert::port_mapping_notification - | alert::error_notification; - virtual int category() const { return static_category; } - virtual std::string message() const - { - static char const* type_str[] = {"NAT-PMP", "UPnP"}; - return std::string("could not map port using ") + type_str[type] - + ": " + msg; - } - }; - - struct TORRENT_EXPORT portmap_alert: alert - { - portmap_alert(int i, int port, int t) - : mapping(i), external_port(port), type(t) - {} - - int mapping; - int external_port; - int type; - - virtual std::auto_ptr clone() const - { return std::auto_ptr(new portmap_alert(*this)); } - virtual char const* what() const { return "port map succeeded"; } - const static int static_category = alert::port_mapping_notification; - virtual int category() const { return static_category; } - virtual std::string message() const - { - static char const* type_str[] = {"NAT-PMP", "UPnP"}; - std::stringstream ret; - ret << "successfully mapped port using " << type_str[type] - << ". external port: " << external_port; - return ret.str(); - } - }; - - struct TORRENT_EXPORT fastresume_rejected_alert: torrent_alert - { - fastresume_rejected_alert(torrent_handle const& h - , std::string const& msg_) - : torrent_alert(h) - , msg(msg_) - {} - - std::string msg; - - virtual std::auto_ptr clone() const - { return std::auto_ptr(new fastresume_rejected_alert(*this)); } - virtual char const* what() const { return "resume data rejected"; } - const static int static_category = alert::status_notification - | alert::error_notification; - virtual int category() const { return static_category; } - virtual std::string message() const - { - return torrent_alert::message() + " fast resume rejected: " + msg; - } - }; - - struct TORRENT_EXPORT peer_blocked_alert: alert - { - peer_blocked_alert(address const& ip_) - : ip(ip_) - {} - - address ip; - - virtual std::auto_ptr clone() const - { return std::auto_ptr(new peer_blocked_alert(*this)); } - virtual char const* what() const { return "peer blocked"; } - const static int static_category = alert::ip_block_notification; - virtual int category() const { return static_category; } - virtual std::string message() const - { - error_code ec; - return "blocked peer: " + ip.to_string(ec); - } - }; -} - - -#endif diff --git a/libtorrent/include/libtorrent/assert.hpp b/libtorrent/include/libtorrent/assert.hpp deleted file mode 100644 index 0000b6d53..000000000 --- a/libtorrent/include/libtorrent/assert.hpp +++ /dev/null @@ -1,60 +0,0 @@ -/* - -Copyright (c) 2007, Arvid Norberg -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions -are met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in - the documentation and/or other materials provided with the distribution. - * Neither the name of the author nor the names of its - contributors may be used to endorse or promote products derived - from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -POSSIBILITY OF SUCH DAMAGE. - -*/ - -#ifndef TORRENT_ASSERT - -#include "libtorrent/config.hpp" - -#if !defined TORRENT_DEBUG -#define TORRENT_ASSERT(a) do {} while(false) -#else - -#include - -#ifdef __GNUC__ -std::string demangle(char const* name); -#endif - -#if (defined __linux__ || defined __MACH__) && defined __GNUC__ && defined TORRENT_DEBUG - -TORRENT_EXPORT void assert_fail(const char* expr, int line, char const* file, char const* function); -#define TORRENT_ASSERT(x) do { if (x) {} else assert_fail(#x, __LINE__, __FILE__, __PRETTY_FUNCTION__); } while (false) - -#else -#include -#define TORRENT_ASSERT(x) assert(x) -#endif - -#endif - -#endif - diff --git a/libtorrent/include/libtorrent/aux_/session_impl.hpp b/libtorrent/include/libtorrent/aux_/session_impl.hpp deleted file mode 100644 index c787874f4..000000000 --- a/libtorrent/include/libtorrent/aux_/session_impl.hpp +++ /dev/null @@ -1,681 +0,0 @@ -/* - -Copyright (c) 2006, Arvid Norberg -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions -are met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in - the documentation and/or other materials provided with the distribution. - * Neither the name of the author nor the names of its - contributors may be used to endorse or promote products derived - from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -POSSIBILITY OF SUCH DAMAGE. - -*/ - -#ifndef TORRENT_SESSION_IMPL_HPP_INCLUDED -#define TORRENT_SESSION_IMPL_HPP_INCLUDED - -#include -#include -#include -#include -#include -#include - -#ifndef TORRENT_DISABLE_GEO_IP -#include "libtorrent/GeoIP.h" -#endif - -#ifdef _MSC_VER -#pragma warning(push, 1) -#endif - -#include -#include -#include -#include -#include -#include - -#ifdef _MSC_VER -#pragma warning(pop) -#endif - -#include "libtorrent/torrent_handle.hpp" -#include "libtorrent/entry.hpp" -#include "libtorrent/socket.hpp" -#include "libtorrent/peer_id.hpp" -#include "libtorrent/tracker_manager.hpp" -#include "libtorrent/alert.hpp" -#include "libtorrent/debug.hpp" -#include "libtorrent/piece_block_progress.hpp" -#include "libtorrent/ip_filter.hpp" -#include "libtorrent/config.hpp" -#include "libtorrent/session_settings.hpp" -#include "libtorrent/kademlia/dht_tracker.hpp" -#include "libtorrent/session_status.hpp" -#include "libtorrent/session.hpp" -#include "libtorrent/stat.hpp" -#include "libtorrent/file_pool.hpp" -#include "libtorrent/bandwidth_manager.hpp" -#include "libtorrent/socket_type.hpp" -#include "libtorrent/connection_queue.hpp" -#include "libtorrent/disk_io_thread.hpp" -#include "libtorrent/assert.hpp" - -namespace libtorrent -{ - - namespace fs = boost::filesystem; - class peer_connection; - class upnp; - class natpmp; - class lsd; - class fingerprint; - - namespace dht - { - class dht_tracker; - }; - - namespace aux - { - struct session_impl; - -#if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_LOGGING || defined TORRENT_ERROR_LOGGING - struct tracker_logger; -#endif - - // this is the link between the main thread and the - // thread started to run the main downloader loop - struct session_impl: boost::noncopyable - { - - // the size of each allocation that is chained in the send buffer - enum { send_buffer_size = 200 }; - -#ifdef TORRENT_DEBUG - friend class ::libtorrent::peer_connection; -#endif - friend struct checker_impl; - friend class invariant_access; - typedef std::set > connection_map; - typedef std::map > torrent_map; - - session_impl( - std::pair listen_port_range - , fingerprint const& cl_fprint - , char const* listen_interface -#if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_LOGGING || defined TORRENT_ERROR_LOGGING - , fs::path const& logpath -#endif - ); - ~session_impl(); - -#ifndef TORRENT_DISABLE_EXTENSIONS - void add_extension(boost::function( - torrent*, void*)> ext); -#endif -#ifdef TORRENT_DEBUG - bool has_peer(peer_connection const* p) const - { - return std::find_if(m_connections.begin(), m_connections.end() - , boost::bind(&boost::intrusive_ptr::get, _1) == p) - != m_connections.end(); - } -#endif - void operator()(); - - void open_listen_port(); - - // if we are listening on an IPv6 interface - // this will return one of the IPv6 addresses on this - // machine, otherwise just an empty endpoint - tcp::endpoint get_ipv6_interface() const; - - void async_accept(boost::shared_ptr const& listener); - void on_incoming_connection(boost::shared_ptr const& s - , boost::weak_ptr listener, error_code const& e); - - // must be locked to access the data - // in this struct - typedef boost::recursive_mutex mutex_t; - mutable mutex_t m_mutex; - - boost::weak_ptr find_torrent(const sha1_hash& info_hash); - peer_id const& get_peer_id() const { return m_peer_id; } - - void close_connection(peer_connection const* p - , char const* message); - - void set_settings(session_settings const& s); - session_settings const& settings() const { return m_settings; } - -#ifndef TORRENT_DISABLE_DHT - void add_dht_node(std::pair const& node); - void add_dht_node(udp::endpoint n); - void add_dht_router(std::pair const& node); - void set_dht_settings(dht_settings const& s); - dht_settings const& get_dht_settings() const { return m_dht_settings; } - void start_dht(entry const& startup_state); - void stop_dht(); - - entry dht_state() const; -#endif - -#ifndef TORRENT_DISABLE_ENCRYPTION - void set_pe_settings(pe_settings const& settings); - pe_settings const& get_pe_settings() const { return m_pe_settings; } -#endif - - // called when a port mapping is successful, or a router returns - // a failure to map a port - void on_port_mapping(int mapping, int port, std::string const& errmsg - , int nat_transport); - - bool is_aborted() const { return m_abort; } - bool is_paused() const { return m_paused; } - - void pause(); - void resume(); - - void set_ip_filter(ip_filter const& f); - void set_port_filter(port_filter const& f); - - bool listen_on( - std::pair const& port_range - , const char* net_interface = 0); - bool is_listening() const; - - torrent_handle add_torrent(add_torrent_params const&); - - void remove_torrent(torrent_handle const& h, int options); - - std::vector get_torrents(); - - void check_torrent(boost::shared_ptr const& t); - void done_checking(boost::shared_ptr const& t); - - void set_alert_mask(int m); - size_t set_alert_queue_size_limit(size_t queue_size_limit_); - std::auto_ptr pop_alert(); - - alert const* wait_for_alert(time_duration max_wait); - - int upload_rate_limit() const; - int download_rate_limit() const; - - void set_download_rate_limit(int bytes_per_second); - void set_upload_rate_limit(int bytes_per_second); - void set_max_half_open_connections(int limit); - void set_max_connections(int limit); - void set_max_uploads(int limit); - - int max_connections() const { return m_max_connections; } - int max_uploads() const { return m_max_uploads; } - int max_half_open_connections() const { return m_half_open.limit(); } - - int num_uploads() const { return m_num_unchoked; } - int num_connections() const - { return m_connections.size(); } - - void unchoke_peer(peer_connection& c); - - session_status status() const; - void set_peer_id(peer_id const& id); - void set_key(int key); - unsigned short listen_port() const; - - void abort(); - - torrent_handle find_torrent_handle(sha1_hash const& info_hash); - - void announce_lsd(sha1_hash const& ih); - - void set_peer_proxy(proxy_settings const& s) - { m_peer_proxy = s; } - void set_web_seed_proxy(proxy_settings const& s) - { m_web_seed_proxy = s; } - void set_tracker_proxy(proxy_settings const& s) - { m_tracker_proxy = s; } - - proxy_settings const& peer_proxy() const - { return m_peer_proxy; } - proxy_settings const& web_seed_proxy() const - { return m_web_seed_proxy; } - proxy_settings const& tracker_proxy() const - { return m_tracker_proxy; } - -#ifndef TORRENT_DISABLE_DHT - void set_dht_proxy(proxy_settings const& s) - { - m_dht_proxy = s; - m_dht_socket.set_proxy_settings(s); - } - proxy_settings const& dht_proxy() const - { return m_dht_proxy; } -#endif - -#ifndef TORRENT_DISABLE_GEO_IP - std::string as_name_for_ip(address const& a); - int as_for_ip(address const& a); - std::pair* lookup_as(int as); - bool load_asnum_db(char const* file); - bool has_asnum_db() const { return m_asnum_db; } - - bool load_country_db(char const* file); - bool has_country_db() const { return m_country_db; } - char const* country_for_ip(address const& a); -#endif - - void load_state(entry const& ses_state); - entry state() const; - - void start_lsd(); - natpmp* start_natpmp(); - upnp* start_upnp(); - - void stop_lsd(); - void stop_natpmp(); - void stop_upnp(); - - int next_port(); - - void add_redundant_bytes(size_type b) - { - TORRENT_ASSERT(b > 0); - m_total_redundant_bytes += b; - } - - void add_failed_bytes(size_type b) - { - TORRENT_ASSERT(b > 0); - m_total_failed_bytes += b; - } - - // handles delayed alerts - alert_manager m_alerts; - - std::pair allocate_buffer(int size); - void free_buffer(char* buf, int size); - - char* allocate_disk_buffer(); - void free_disk_buffer(char* buf); - - void set_external_address(address const& ip); - address const& external_address() const { return m_external_address; } - -// private: - - void dht_state_callback(boost::condition& c - , entry& e, bool& done) const; - void on_lsd_peer(tcp::endpoint peer, sha1_hash const& ih); - -#ifndef TORRENT_DISABLE_POOL_ALLOCATOR - // this pool is used to allocate and recycle send - // buffers from. - boost::pool<> m_send_buffers; -#endif - boost::mutex m_send_buffer_mutex; - - // the file pool that all storages in this session's - // torrents uses. It sets a limit on the number of - // open files by this session. - // file pool must be destructed after the torrents - // since they will still have references to it - // when they are destructed. - file_pool m_files; - - // this is where all active sockets are stored. - // the selector can sleep while there's no activity on - // them - mutable io_service m_io_service; - - // handles disk io requests asynchronously - // peers have pointers into the disk buffer - // pool, and must be destructed before this - // object. The disk thread relies on the file - // pool object, and must be destructed before - // m_files. The disk io thread posts completion - // events to the io service, and needs to be - // constructed after it. - disk_io_thread m_disk_thread; - - // this is a list of half-open tcp connections - // (only outgoing connections) - // this has to be one of the last - // members to be destructed - connection_queue m_half_open; - - // the bandwidth manager is responsible for - // handing out bandwidth to connections that - // asks for it, it can also throttle the - // rate. - bandwidth_manager m_download_channel; - bandwidth_manager m_upload_channel; - - bandwidth_manager* m_bandwidth_manager[2]; - - tracker_manager m_tracker_manager; - torrent_map m_torrents; - typedef std::list > check_queue_t; - check_queue_t m_queued_for_checking; - - // this maps sockets to their peer_connection - // object. It is the complete list of all connected - // peers. - connection_map m_connections; - - // filters incoming connections - ip_filter m_ip_filter; - - // filters outgoing connections - port_filter m_port_filter; - - // the peer id that is generated at the start of the session - peer_id m_peer_id; - - // the key is an id that is used to identify the - // client with the tracker only. It is randomized - // at startup - int m_key; - - // the number of retries we make when binding the - // listen socket. For each retry the port number - // is incremented by one - int m_listen_port_retries; - - // the ip-address of the interface - // we are supposed to listen on. - // if the ip is set to zero, it means - // that we should let the os decide which - // interface to listen on - tcp::endpoint m_listen_interface; - - // if we're listening on an IPv6 interface - // this is one of the non local IPv6 interfaces - // on this machine - tcp::endpoint m_ipv6_interface; - - struct listen_socket_t - { - listen_socket_t(): external_port(0) {} - // this is typically set to the same as the local - // listen port. In case a NAT port forward was - // successfully opened, this will be set to the - // port that is open on the external (NAT) interface - // on the NAT box itself. This is the port that has - // to be published to peers, since this is the port - // the client is reachable through. - int external_port; - - // the actual socket - boost::shared_ptr sock; - }; - // since we might be listening on multiple interfaces - // we might need more than one listen socket - std::list m_listen_sockets; - - listen_socket_t setup_listener(tcp::endpoint ep, int retries, bool v6_only = false); - - // the settings for the client - session_settings m_settings; - // the proxy settings for different - // kinds of connections - proxy_settings m_peer_proxy; - proxy_settings m_web_seed_proxy; - proxy_settings m_tracker_proxy; -#ifndef TORRENT_DISABLE_DHT - proxy_settings m_dht_proxy; -#endif - - // set to true when the session object - // is being destructed and the thread - // should exit - volatile bool m_abort; - - // is true if the session is paused - bool m_paused; - - // the max number of unchoked peers as set by the user - int m_max_uploads; - - // the number of unchoked peers as set by the auto-unchoker - // this should always be >= m_max_uploads - int m_allowed_upload_slots; - - // the max number of connections, as set by the user - int m_max_connections; - - // the number of unchoked peers - int m_num_unchoked; - - // this is initialized to the unchoke_interval - // session_setting and decreased every second. - // when it reaches zero, it is reset to the - // unchoke_interval and the unchoke set is - // recomputed. - int m_unchoke_time_scaler; - - // this is used to decide when to recalculate which - // torrents to keep queued and which to activate - int m_auto_manage_time_scaler; - - // works like unchoke_time_scaler but it - // is only decresed when the unchoke set - // is recomputed, and when it reaches zero, - // the optimistic unchoke is moved to another peer. - int m_optimistic_unchoke_time_scaler; - - // works like unchoke_time_scaler. Each time - // it reaches 0, and all the connections are - // used, the worst connection will be disconnected - // from the torrent with the most peers - int m_disconnect_time_scaler; - - // when this scaler reaches zero, it will - // scrape one of the auto managed, paused, - // torrents. - int m_auto_scrape_time_scaler; - - // statistics gathered from all torrents. - stat m_stat; - - // is false by default and set to true when - // the first incoming connection is established - // this is used to know if the client is behind - // NAT or not. - bool m_incoming_connection; - - void second_tick(error_code const& e); - void recalculate_auto_managed_torrents(); - void recalculate_unchoke_slots(int congested_torrents - , int uncongested_torrents); - - ptime m_last_tick; - - // when outgoing_ports is configured, this is the - // port we'll bind the next outgoing socket to - int m_next_port; - -#ifndef TORRENT_DISABLE_DHT - boost::intrusive_ptr m_dht; - dht_settings m_dht_settings; - // if this is set to true, the dht listen port - // will be set to the same as the tcp listen port - // and will be synchronlized with it as it changes - // it defaults to true - bool m_dht_same_port; - - // see m_external_listen_port. This is the same - // but for the udp port used by the DHT. - int m_external_udp_port; - - udp_socket m_dht_socket; - - // these are used when starting the DHT - // (and bootstrapping it), and then erased - std::list > m_dht_router_nodes; - - void on_receive_udp(error_code const& e - , udp::endpoint const& ep, char const* buf, int len); -#endif - -#ifndef TORRENT_DISABLE_ENCRYPTION - pe_settings m_pe_settings; -#endif - - boost::intrusive_ptr m_natpmp; - boost::intrusive_ptr m_upnp; - boost::intrusive_ptr m_lsd; - - // 0 is natpmp 1 is upnp - int m_tcp_mapping[2]; - int m_udp_mapping[2]; - - // the timer used to fire the second_tick - deadline_timer m_timer; - - // the index of the torrent that will be offered to - // connect to a peer next time second_tick is called. - // This implements a round robin. - int m_next_connect_torrent; -#ifdef TORRENT_DEBUG - void check_invariant() const; -#endif - -#ifdef TORRENT_STATS - void log_buffer_usage(); - - // logger used to write bandwidth usage statistics - std::ofstream m_stats_logger; - int m_second_counter; - // used to log send buffer usage statistics - std::ofstream m_buffer_usage_logger; - // the number of send buffers that are allocated - int m_buffer_allocations; -#endif -#if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_LOGGING || defined TORRENT_ERROR_LOGGING - boost::shared_ptr create_log(std::string const& name - , int instance, bool append = true); - - // this list of tracker loggers serves as tracker_callbacks when - // shutting down. This list is just here to keep them alive during - // whe shutting down process - std::list > m_tracker_loggers; - - fs::path m_logpath; - public: - boost::shared_ptr m_logger; - private: - -#endif - address m_external_address; - -#ifndef TORRENT_DISABLE_EXTENSIONS - typedef std::list(torrent*, void*)> > extension_list_t; - - extension_list_t m_extensions; -#endif - -#ifndef TORRENT_DISABLE_GEO_IP - GeoIP* m_asnum_db; - GeoIP* m_country_db; - - // maps AS number to the peak download rate - // we've seen from it. Entries are never removed - // from this map. Pointers to its elements - // are kept in the policy::peer structures. - std::map m_as_peak; -#endif - - // total redundant and failed bytes - size_type m_total_failed_bytes; - size_type m_total_redundant_bytes; - - // the main working thread - boost::scoped_ptr m_thread; - }; - -#if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_LOGGING || defined TORRENT_ERROR_LOGGING - struct tracker_logger : request_callback - { - tracker_logger(session_impl& ses): m_ses(ses) {} - void tracker_warning(tracker_request const& req - , std::string const& str) - { - debug_log("*** tracker warning: " + str); - } - - void tracker_response(tracker_request const& - , std::vector& peers - , int interval - , int complete - , int incomplete - , address const& external_ip) - { - std::stringstream s; - s << "TRACKER RESPONSE:\n" - "interval: " << interval << "\n" - "peers:\n"; - for (std::vector::const_iterator i = peers.begin(); - i != peers.end(); ++i) - { - s << " " << std::setfill(' ') << std::setw(16) << i->ip - << " " << std::setw(5) << std::dec << i->port << " "; - if (!i->pid.is_all_zeros()) s << " " << i->pid; - s << "\n"; - } - s << "external ip: " << external_ip << "\n"; - debug_log(s.str()); - } - - void tracker_request_timed_out( - tracker_request const&) - { - debug_log("*** tracker timed out"); - } - - void tracker_request_error( - tracker_request const& - , int response_code - , const std::string& str) - { - debug_log(std::string("*** tracker error: ") - + boost::lexical_cast(response_code) + ": " - + str); - } - - void debug_log(const std::string& line) - { - (*m_ses.m_logger) << time_now_string() << " " << line << "\n"; - } - session_impl& m_ses; - }; -#endif - - } -} - - -#endif - diff --git a/libtorrent/include/libtorrent/bandwidth_limit.hpp b/libtorrent/include/libtorrent/bandwidth_limit.hpp deleted file mode 100644 index e0675aa31..000000000 --- a/libtorrent/include/libtorrent/bandwidth_limit.hpp +++ /dev/null @@ -1,120 +0,0 @@ -/* - -Copyright (c) 2007, Arvid Norberg -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions -are met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in - the documentation and/or other materials provided with the distribution. - * Neither the name of the author nor the names of its - contributors may be used to endorse or promote products derived - from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -POSSIBILITY OF SUCH DAMAGE. - -*/ - -#ifndef TORRENT_BANDWIDTH_LIMIT_HPP_INCLUDED -#define TORRENT_BANDWIDTH_LIMIT_HPP_INCLUDED - -#include - -#include "libtorrent/assert.hpp" - -namespace libtorrent { - -// member of peer_connection -struct bandwidth_limit -{ - static const int inf = boost::integer_traits::const_max; - - bandwidth_limit() - : m_quota_left(0) - , m_local_limit(inf) - , m_current_rate(0) - {} - - void throttle(int limit) - { - TORRENT_ASSERT(limit > 0); - m_local_limit = limit; - } - - int throttle() const - { - return m_local_limit; - } - - void assign(int amount) - { - TORRENT_ASSERT(amount >= 0); - m_current_rate += amount; - m_quota_left += amount; - } - - void use_quota(int amount) - { - TORRENT_ASSERT(amount <= m_quota_left); - m_quota_left -= amount; - } - - int quota_left() const - { - return (std::max)(m_quota_left, 0); - } - - void expire(int amount) - { - TORRENT_ASSERT(amount >= 0); - m_current_rate -= amount; - } - - int max_assignable() const - { - if (m_local_limit == inf) return inf; - if (m_local_limit <= m_current_rate) return 0; - return m_local_limit - m_current_rate; - } - -private: - - // this is the amount of bandwidth we have - // been assigned without using yet. i.e. - // the bandwidth that we use up every time - // we receive or send a message. Once this - // hits zero, we need to request more - // bandwidth from the torrent which - // in turn will request bandwidth from - // the bandwidth manager - int m_quota_left; - - // the local limit is the number of bytes - // per window size we are allowed to use. - int m_local_limit; - - // the current rate is the number of - // bytes we have been assigned within - // the window size. - int m_current_rate; -}; - -} - -#endif - diff --git a/libtorrent/include/libtorrent/bandwidth_manager.hpp b/libtorrent/include/libtorrent/bandwidth_manager.hpp deleted file mode 100644 index ee37615b7..000000000 --- a/libtorrent/include/libtorrent/bandwidth_manager.hpp +++ /dev/null @@ -1,495 +0,0 @@ -/* - -Copyright (c) 2007, Arvid Norberg -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions -are met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in - the documentation and/or other materials provided with the distribution. - * Neither the name of the author nor the names of its - contributors may be used to endorse or promote products derived - from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -POSSIBILITY OF SUCH DAMAGE. - -*/ - -#ifndef TORRENT_BANDWIDTH_MANAGER_HPP_INCLUDED -#define TORRENT_BANDWIDTH_MANAGER_HPP_INCLUDED - -#include -#include -#include -#include -#include -#include -#include - -#ifdef TORRENT_VERBOSE_BANDWIDTH_LIMIT -#include -#endif - -#include "libtorrent/socket.hpp" -#include "libtorrent/invariant_check.hpp" -#include "libtorrent/assert.hpp" -#include "libtorrent/bandwidth_limit.hpp" -#include "libtorrent/bandwidth_queue_entry.hpp" - -using boost::weak_ptr; -using boost::shared_ptr; -using boost::intrusive_ptr; -using boost::bind; - - -namespace libtorrent { - -// the maximum block of bandwidth quota to -// hand out is 33kB. The block size may -// be smaller on lower limits -enum -{ - max_bandwidth_block_size = 33000, - min_bandwidth_block_size = 400 -}; - -const time_duration bw_window_size = seconds(1); - -template -struct history_entry -{ - history_entry(intrusive_ptr p, weak_ptr t - , int a, ptime exp) - : expires_at(exp), amount(a), peer(p), tor(t) {} - history_entry(int a, ptime exp) - : expires_at(exp), amount(a), peer(), tor() {} - ptime expires_at; - int amount; - intrusive_ptr peer; - weak_ptr tor; -}; - -template -T clamp(T val, T ceiling, T floor) -{ - TORRENT_ASSERT(ceiling >= floor); - if (val >= ceiling) return ceiling; - else if (val <= floor) return floor; - return val; -} - -template -struct assign_at_exit -{ - assign_at_exit(T& var, T val): var_(var), val_(val) {} - ~assign_at_exit() { var_ = val_; } - T& var_; - T val_; -}; - -template -struct bandwidth_manager -{ - bandwidth_manager(io_service& ios, int channel -#ifdef TORRENT_VERBOSE_BANDWIDTH_LIMIT - , bool log = false -#endif - ) - : m_ios(ios) - , m_history_timer(m_ios) - , m_limit(bandwidth_limit::inf) - , m_drain_quota(0) - , m_current_quota(0) - , m_channel(channel) - , m_in_hand_out_bandwidth(false) - , m_abort(false) - { -#ifdef TORRENT_VERBOSE_BANDWIDTH_LIMIT - if (log) - m_log.open("bandwidth_limiter.log", std::ios::trunc); - m_start = time_now(); -#endif - } - - void drain(int bytes) - { - mutex_t::scoped_lock l(m_mutex); - TORRENT_ASSERT(bytes >= 0); - m_drain_quota += bytes; - if (m_drain_quota > m_limit * 5) m_drain_quota = m_limit * 5; - } - - void throttle(int limit) - { - mutex_t::scoped_lock l(m_mutex); - TORRENT_ASSERT(limit >= 0); - m_limit = limit; - } - - int throttle() const - { - mutex_t::scoped_lock l(m_mutex); - return m_limit; - } - - void close() - { - m_abort = true; - m_queue.clear(); - m_history.clear(); - m_current_quota = 0; - error_code ec; - m_history_timer.cancel(ec); - } - -#ifdef TORRENT_DEBUG - bool is_queued(PeerConnection const* peer) const - { - mutex_t::scoped_lock l(m_mutex); - return is_queued(peer); - } - - bool is_queued(PeerConnection const* peer, boost::mutex::scoped_lock& l) const - { - for (typename queue_t::const_iterator i = m_queue.begin() - , end(m_queue.end()); i != end; ++i) - { - if (i->peer.get() == peer) return true; - } - return false; - } - - bool is_in_history(PeerConnection const* peer) const - { - mutex_t::scoped_lock l(m_mutex); - return is_in_history(peer, l); - } - - bool is_in_history(PeerConnection const* peer, boost::mutex::scoped_lock& l) const - { - for (typename history_t::const_iterator i - = m_history.begin(), end(m_history.end()); i != end; ++i) - { - if (i->peer.get() == peer) return true; - } - return false; - } -#endif - - int queue_size() const - { - mutex_t::scoped_lock l(m_mutex); - return m_queue.size(); - } - - // non prioritized means that, if there's a line for bandwidth, - // others will cut in front of the non-prioritized peers. - // this is used by web seeds - void request_bandwidth(intrusive_ptr const& peer - , int blk, int priority) - { - mutex_t::scoped_lock l(m_mutex); - INVARIANT_CHECK; - if (m_abort) return; - TORRENT_ASSERT(blk > 0); - TORRENT_ASSERT(!is_queued(peer.get(), l)); - - // make sure this peer isn't already in line - // waiting for bandwidth - TORRENT_ASSERT(peer->max_assignable_bandwidth(m_channel) > 0); - - typename queue_t::reverse_iterator i(m_queue.rbegin()); - while (i != m_queue.rend() && priority > i->priority) - { - ++i->priority; - ++i; - } - m_queue.insert(i.base(), bw_queue_entry(peer, blk, priority)); - if (!m_queue.empty()) hand_out_bandwidth(l); - } - -#ifdef TORRENT_DEBUG - void check_invariant() const - { - int current_quota = 0; - for (typename history_t::const_iterator i - = m_history.begin(), end(m_history.end()); i != end; ++i) - { - current_quota += i->amount; - } - TORRENT_ASSERT(current_quota == m_current_quota); - - typename queue_t::const_iterator j = m_queue.begin(); - if (j != m_queue.end()) - { - ++j; - for (typename queue_t::const_iterator i = m_queue.begin() - , end(m_queue.end()); i != end && j != end; ++i, ++j) - TORRENT_ASSERT(i->priority >= j->priority); - } - } -#endif - -private: - - void add_history_entry(history_entry const& e) - { - INVARIANT_CHECK; - - m_history.push_front(e); - m_current_quota += e.amount; - // in case the size > 1 there is already a timer - // active that will be invoked, no need to set one up - -#ifdef TORRENT_VERBOSE_BANDWIDTH_LIMIT - m_log << std::setw(7) << total_milliseconds(time_now() - m_start) << " + " - " queue: " << std::setw(3) << m_queue.size() - << " used: " << std::setw(7) << m_current_quota - << " limit: " << std::setw(7) << m_limit - << " history: " << std::setw(3) << m_history.size() - << std::endl; -#endif - if (m_history.size() > 1) return; - - if (m_abort) return; - - error_code ec; -// TORRENT_ASSERT(e.expires_at > time_now()); - m_history_timer.expires_at(e.expires_at, ec); - m_history_timer.async_wait(bind(&bandwidth_manager::on_history_expire, this, _1)); - } - - void on_history_expire(error_code const& e) - { - if (e) return; - - mutex_t::scoped_lock l(m_mutex); - INVARIANT_CHECK; - if (m_abort) return; - - TORRENT_ASSERT(!m_history.empty()); - - ptime now(time_now()); - while (!m_history.empty() && m_history.back().expires_at <= now) - { - history_entry e = m_history.back(); - m_history.pop_back(); - m_current_quota -= e.amount; - TORRENT_ASSERT(m_current_quota >= 0); - -#ifdef TORRENT_VERBOSE_BANDWIDTH_LIMIT - m_log << std::setw(7) << total_milliseconds(time_now() - m_start) << " - " - " queue: " << std::setw(3) << m_queue.size() - << " used: " << std::setw(7) << m_current_quota - << " limit: " << std::setw(7) << m_limit - << " history: " << std::setw(3) << m_history.size() - << std::endl; -#endif - intrusive_ptr c = e.peer; - if (!c) continue; - shared_ptr t = e.tor.lock(); - l.unlock(); - if (!c->is_disconnecting()) c->expire_bandwidth(m_channel, e.amount); - if (t) t->expire_bandwidth(m_channel, e.amount); - l.lock(); - } - - // now, wait for the next chunk to expire - if (!m_history.empty() && !m_abort) - { - error_code ec; - TORRENT_ASSERT(m_history.back().expires_at > now); - m_history_timer.expires_at(m_history.back().expires_at, ec); - m_history_timer.async_wait(bind(&bandwidth_manager::on_history_expire, this, _1)); - } - - // since some bandwidth just expired, it - // means we can hand out more (in case there - // are still consumers in line) - if (!m_queue.empty()) hand_out_bandwidth(l); - } - - void hand_out_bandwidth(boost::mutex::scoped_lock& l) - { - // if we're already handing out bandwidth, just return back - // to the loop further down on the callstack - if (m_in_hand_out_bandwidth) return; - m_in_hand_out_bandwidth = true; - // set it to false when exiting function - assign_at_exit sg(m_in_hand_out_bandwidth, false); - - INVARIANT_CHECK; - - ptime now(time_now()); - - int limit = m_limit; - - // available bandwidth to hand out - int amount = limit - m_current_quota; - - if (amount <= 0) return; - - if (m_drain_quota > 0) - { - int drain_amount = (std::min)(m_drain_quota, amount); - m_drain_quota -= drain_amount; - amount -= drain_amount; - add_history_entry(history_entry( - drain_amount, now + bw_window_size)); - } - - queue_t tmp; - while (!m_queue.empty() && amount > 0) - { - bw_queue_entry qe = m_queue.front(); - TORRENT_ASSERT(qe.max_block_size > 0); - m_queue.pop_front(); - - shared_ptr t = qe.torrent.lock(); - if (!t) continue; - if (qe.peer->is_disconnecting()) - { - l.unlock(); - t->expire_bandwidth(m_channel, qe.max_block_size); - l.lock(); - continue; - } - - // at this point, max_assignable may actually be zero. Since - // the rate limit of the peer might have changed while it - // was in the queue. - int max_assignable = qe.peer->max_assignable_bandwidth(m_channel); - if (max_assignable == 0) - { - TORRENT_ASSERT(is_in_history(qe.peer.get(), l)); - tmp.push_back(qe); - continue; - } - - // this is the limit of the block size. It depends on the throttle - // so that it can be closer to optimal. Larger block sizes will give lower - // granularity to the rate but will be more efficient. At high rates - // the block sizes are bigger and at low rates, the granularity - // is more important and block sizes are smaller - - // the minimum rate that can be given is the block size, so, the - // block size must be smaller for lower rates. This is because - // the history window is one second, and the block will be forgotten - // after one second. - int block_size = (std::min)(qe.peer->bandwidth_throttle(m_channel) - , limit / 10); - - if (block_size < min_bandwidth_block_size) - { - block_size = (std::min)(int(min_bandwidth_block_size), limit); - } - else if (block_size > max_bandwidth_block_size) - { - if (limit == bandwidth_limit::inf) - { - block_size = max_bandwidth_block_size; - } - else - { - // try to make the block_size a divisor of - // m_limit to make the distributions as fair - // as possible - // TODO: move this calculcation to where the limit - // is changed - block_size = limit - / (limit / max_bandwidth_block_size); - } - } - if (block_size > qe.max_block_size) block_size = qe.max_block_size; - - if (amount < block_size / 4) - { - tmp.push_back(qe); -// m_queue.push_front(qe); - break; - } - - // so, hand out max_assignable, but no more than - // the available bandwidth (amount) and no more - // than the max_bandwidth_block_size - int hand_out_amount = (std::min)((std::min)(block_size, max_assignable) - , amount); - TORRENT_ASSERT(hand_out_amount > 0); - amount -= hand_out_amount; - TORRENT_ASSERT(hand_out_amount <= qe.max_block_size); - l.unlock(); - t->assign_bandwidth(m_channel, hand_out_amount, qe.max_block_size); - qe.peer->assign_bandwidth(m_channel, hand_out_amount); - l.lock(); - add_history_entry(history_entry( - qe.peer, t, hand_out_amount, now + bw_window_size)); - } - if (!tmp.empty()) m_queue.insert(m_queue.begin(), tmp.begin(), tmp.end()); - } - - - typedef boost::mutex mutex_t; - mutable mutex_t m_mutex; - - // the io_service used for the timer - io_service& m_ios; - - // the timer that is waiting for the entries - // in the history queue to expire (slide out - // of the history window) - deadline_timer m_history_timer; - - // the rate limit (bytes per second) - int m_limit; - - // bytes to drain without handing out to a peer - // used to deduct the IP overhead - int m_drain_quota; - - // the sum of all recently handed out bandwidth blocks - int m_current_quota; - - // these are the consumers that want bandwidth - typedef std::deque > queue_t; - queue_t m_queue; - - // these are the consumers that have received bandwidth - // that will expire - typedef std::deque > history_t; - history_t m_history; - - // this is the channel within the consumers - // that bandwidth is assigned to (upload or download) - int m_channel; - - // this is true while we're in the hand_out_bandwidth loop - // to prevent recursive invocations to interfere - bool m_in_hand_out_bandwidth; - - bool m_abort; - -#ifdef TORRENT_VERBOSE_BANDWIDTH_LIMIT - std::ofstream m_log; - ptime m_start; -#endif -}; - -} - -#endif - diff --git a/libtorrent/include/libtorrent/bandwidth_queue_entry.hpp b/libtorrent/include/libtorrent/bandwidth_queue_entry.hpp deleted file mode 100644 index 54f669062..000000000 --- a/libtorrent/include/libtorrent/bandwidth_queue_entry.hpp +++ /dev/null @@ -1,56 +0,0 @@ -/* - -Copyright (c) 2007, Arvid Norberg -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions -are met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in - the documentation and/or other materials provided with the distribution. - * Neither the name of the author nor the names of its - contributors may be used to endorse or promote products derived - from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -POSSIBILITY OF SUCH DAMAGE. - -*/ - -#ifndef TORRENT_BANDWIDTH_QUEUE_ENTRY_HPP_INCLUDED -#define TORRENT_BANDWIDTH_QUEUE_ENTRY_HPP_INCLUDED - -#include - -namespace libtorrent { - -template -struct bw_queue_entry -{ - bw_queue_entry(boost::intrusive_ptr const& pe - , int blk, int prio) - : peer(pe), torrent(peer->associated_torrent()) - , max_block_size(blk), priority(prio) {} - boost::intrusive_ptr peer; - boost::weak_ptr torrent; - int max_block_size; - int priority; // 0 is low prio -}; - -} - -#endif - diff --git a/libtorrent/include/libtorrent/bencode.hpp b/libtorrent/include/libtorrent/bencode.hpp deleted file mode 100644 index cc4e5a220..000000000 --- a/libtorrent/include/libtorrent/bencode.hpp +++ /dev/null @@ -1,406 +0,0 @@ -/* - -Copyright (c) 2003, Arvid Norberg -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions -are met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in - the documentation and/or other materials provided with the distribution. - * Neither the name of the author nor the names of its - contributors may be used to endorse or promote products derived - from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -POSSIBILITY OF SUCH DAMAGE. - -*/ - - -#ifndef TORRENT_BENCODE_HPP_INCLUDED -#define TORRENT_BENCODE_HPP_INCLUDED - - - -/* - * This file declares the following functions: - * - *---------------------------------- - * template - * void libtorrent::bencode(OutIt out, const libtorrent::entry& e); - * - * Encodes a message entry with bencoding into the output - * iterator given. The bencoding is described in the BitTorrent - * protocol description document OutIt must be an OutputIterator - * of type char. This may throw libtorrent::invalid_encoding if - * the entry contains invalid nodes (undefined_t for example). - * - *---------------------------------- - * template - * libtorrent::entry libtorrent::bdecode(InIt start, InIt end); - * - * Decodes the buffer given by the start and end iterators - * and returns the decoded entry. InIt must be an InputIterator - * of type char. May throw libtorrent::invalid_encoding if - * the string is not correctly bencoded. - * - */ - - - - -#include - -#ifdef _MSC_VER -#pragma warning(push, 1) -#endif - -#include -#include - -#ifdef _MSC_VER -#pragma warning(pop) -#endif - -#include "libtorrent/entry.hpp" -#include "libtorrent/config.hpp" - -#include "libtorrent/assert.hpp" -#include "libtorrent/escape_string.hpp" - -namespace libtorrent -{ - - struct TORRENT_EXPORT invalid_encoding: std::exception - { - virtual const char* what() const throw() { return "invalid bencoding"; } - }; - - namespace detail - { - template - int write_string(OutIt& out, const std::string& val) - { - for (std::string::const_iterator i = val.begin() - , end(val.end()); i != end; ++i) - *out++ = *i; - return val.length(); - } - - TORRENT_EXPORT char const* integer_to_str(char* buf, int size, entry::integer_type val); - - template - int write_integer(OutIt& out, entry::integer_type val) - { - // the stack allocated buffer for keeping the - // decimal representation of the number can - // not hold number bigger than this: - BOOST_STATIC_ASSERT(sizeof(entry::integer_type) <= 8); - char buf[21]; - int ret = 0; - for (char const* str = integer_to_str(buf, 21, val); - *str != 0; ++str) - { - *out = *str; - ++out; - ++ret; - } - return ret; - } - - template - void write_char(OutIt& out, char c) - { - *out = c; - ++out; - } - - template - std::string read_until(InIt& in, InIt end, char end_token, bool& err) - { - std::string ret; - if (in == end) - { - err = true; - return ret; - } - while (*in != end_token) - { - ret += *in; - ++in; - if (in == end) - { - err = true; - return ret; - } - } - return ret; - } - - template - void read_string(InIt& in, InIt end, int len, std::string& str, bool& err) - { - TORRENT_ASSERT(len >= 0); - for (int i = 0; i < len; ++i) - { - if (in == end) - { - err = true; - return; - } - str += *in; - ++in; - } - } - - // returns the number of bytes written - template - int bencode_recursive(OutIt& out, const entry& e) - { - int ret = 0; - switch(e.type()) - { - case entry::int_t: - write_char(out, 'i'); - ret += write_integer(out, e.integer()); - write_char(out, 'e'); - ret += 2; - break; - case entry::string_t: - ret += write_integer(out, e.string().length()); - write_char(out, ':'); - ret += write_string(out, e.string()); - ret += 1; - break; - case entry::list_t: - write_char(out, 'l'); - for (entry::list_type::const_iterator i = e.list().begin(); i != e.list().end(); ++i) - ret += bencode_recursive(out, *i); - write_char(out, 'e'); - ret += 2; - break; - case entry::dictionary_t: - write_char(out, 'd'); - for (entry::dictionary_type::const_iterator i = e.dict().begin(); - i != e.dict().end(); ++i) - { - // write key - ret += write_integer(out, i->first.length()); - write_char(out, ':'); - ret += write_string(out, i->first); - // write value - ret += bencode_recursive(out, i->second); - ret += 1; - } - write_char(out, 'e'); - ret += 2; - break; - default: - // do nothing - break; - } - return ret; - } - - template - void bdecode_recursive(InIt& in, InIt end, entry& ret, bool& err, int depth) - { - if (depth >= 100) - { - err = true; - return; - } - - if (in == end) - { - err = true; -#ifdef TORRENT_DEBUG - ret.m_type_queried = false; -#endif - return; - } - switch (*in) - { - - // ---------------------------------------------- - // integer - case 'i': - { - ++in; // 'i' - std::string val = read_until(in, end, 'e', err); - if (err) return; - TORRENT_ASSERT(*in == 'e'); - ++in; // 'e' - ret = entry(entry::int_t); - ret.integer() = boost::lexical_cast(val); -#ifdef TORRENT_DEBUG - ret.m_type_queried = false; -#endif - } break; - - // ---------------------------------------------- - // list - case 'l': - { - ret = entry(entry::list_t); - ++in; // 'l' - while (*in != 'e') - { - ret.list().push_back(entry()); - entry& e = ret.list().back(); - bdecode_recursive(in, end, e, err, depth + 1); - if (err) - { -#ifdef TORRENT_DEBUG - ret.m_type_queried = false; -#endif - return; - } - if (in == end) - { - err = true; -#ifdef TORRENT_DEBUG - ret.m_type_queried = false; -#endif - return; - } - } -#ifdef TORRENT_DEBUG - ret.m_type_queried = false; -#endif - TORRENT_ASSERT(*in == 'e'); - ++in; // 'e' - } break; - - // ---------------------------------------------- - // dictionary - case 'd': - { - ret = entry(entry::dictionary_t); - ++in; // 'd' - while (*in != 'e') - { - entry key; - bdecode_recursive(in, end, key, err, depth + 1); - if (err || key.type() != entry::string_t) - { -#ifdef TORRENT_DEBUG - ret.m_type_queried = false; -#endif - return; - } - entry& e = ret[key.string()]; - bdecode_recursive(in, end, e, err, depth + 1); - if (err) - { -#ifdef TORRENT_DEBUG - ret.m_type_queried = false; -#endif - return; - } - if (in == end) - { - err = true; -#ifdef TORRENT_DEBUG - ret.m_type_queried = false; -#endif - return; - } - } -#ifdef TORRENT_DEBUG - ret.m_type_queried = false; -#endif - TORRENT_ASSERT(*in == 'e'); - ++in; // 'e' - } break; - - // ---------------------------------------------- - // string - default: - if (is_digit((unsigned char)*in)) - { - std::string len_s = read_until(in, end, ':', err); - if (err) - { -#ifdef TORRENT_DEBUG - ret.m_type_queried = false; -#endif - return; - } - TORRENT_ASSERT(*in == ':'); - ++in; // ':' - int len = std::atoi(len_s.c_str()); - ret = entry(entry::string_t); - read_string(in, end, len, ret.string(), err); - if (err) - { -#ifdef TORRENT_DEBUG - ret.m_type_queried = false; -#endif - return; - } - } - else - { - err = true; -#ifdef TORRENT_DEBUG - ret.m_type_queried = false; -#endif - return; - } -#ifdef TORRENT_DEBUG - ret.m_type_queried = false; -#endif - } - } - } - - template - int bencode(OutIt out, const entry& e) - { - return detail::bencode_recursive(out, e); - } - - template - entry bdecode(InIt start, InIt end) - { - entry e; - bool err = false; - detail::bdecode_recursive(start, end, e, err, 0); -#ifdef TORRENT_DEBUG - TORRENT_ASSERT(e.m_type_queried == false); -#endif - if (err) return entry(); - return e; - } - - template - entry bdecode(InIt start, InIt end, int& len) - { - entry e; - bool err = false; - InIt s = start; - detail::bdecode_recursive(start, end, e, err, 0); - len = std::distance(s, start); - TORRENT_ASSERT(len >= 0); - if (err) return entry(); - return e; - } -} - -#endif // TORRENT_BENCODE_HPP_INCLUDED - diff --git a/libtorrent/include/libtorrent/bitfield.hpp b/libtorrent/include/libtorrent/bitfield.hpp deleted file mode 100644 index edec78c7d..000000000 --- a/libtorrent/include/libtorrent/bitfield.hpp +++ /dev/null @@ -1,265 +0,0 @@ -/* - -Copyright (c) 2008, Arvid Norberg -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions -are met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in - the documentation and/or other materials provided with the distribution. - * Neither the name of the author nor the names of its - contributors may be used to endorse or promote products derived - from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -POSSIBILITY OF SUCH DAMAGE. - -*/ - -#ifndef TORRENT_BITFIELD_HPP_INCLUDED -#define TORRENT_BITFIELD_HPP_INCLUDED - -#include "libtorrent/assert.hpp" -#include "libtorrent/config.hpp" - -namespace libtorrent -{ - struct TORRENT_EXPORT bitfield - { - bitfield(): m_bytes(0), m_size(0), m_own(false) {} - bitfield(int bits): m_bytes(0), m_size(0) - { resize(bits); } - bitfield(int bits, bool val): m_bytes(0), m_size(0) - { resize(bits, val); } - bitfield(char const* bytes, int bits): m_bytes(0), m_size(0) - { assign(bytes, bits); } - bitfield(bitfield const& rhs): m_bytes(0), m_size(0), m_own(false) - { assign(rhs.bytes(), rhs.size()); } - - void borrow_bytes(char* bytes, int bits) - { - dealloc(); - m_bytes = (unsigned char*)bytes; - m_size = bits; - m_own = false; - } - ~bitfield() { dealloc(); } - - void assign(char const* bytes, int bits) - { resize(bits); std::memcpy(m_bytes, bytes, (bits + 7) / 8); clear_trailing_bits(); } - - bool operator[](int index) const - { return get_bit(index); } - - bool get_bit(int index) const - { - TORRENT_ASSERT(index >= 0); - TORRENT_ASSERT(index < m_size); - return m_bytes[index / 8] & (0x80 >> (index & 7)); - } - - void clear_bit(int index) - { - TORRENT_ASSERT(index >= 0); - TORRENT_ASSERT(index < m_size); - m_bytes[index / 8] &= ~(0x80 >> (index & 7)); - } - - void set_bit(int index) - { - TORRENT_ASSERT(index >= 0); - TORRENT_ASSERT(index < m_size); - m_bytes[index / 8] |= (0x80 >> (index & 7)); - } - - std::size_t size() const { return m_size; } - bool empty() const { return m_size == 0; } - - char const* bytes() const { return (char*)m_bytes; } - - bitfield& operator=(bitfield const& rhs) - { - assign(rhs.bytes(), rhs.size()); - return *this; - } - - int count() const - { - // 0000, 0001, 0010, 0011, 0100, 0101, 0110, 0111, - // 1000, 1001, 1010, 1011, 1100, 1101, 1110, 1111 - const static char num_bits[] = - { - 0, 1, 1, 2, 1, 2, 2, 3, - 1, 2, 2, 3, 2, 3, 3, 4 - }; - - int ret = 0; - const int num_bytes = m_size / 8; - for (int i = 0; i < num_bytes; ++i) - { - ret += num_bits[m_bytes[i] & 0xf] + num_bits[m_bytes[i] >> 4]; - } - - int rest = m_size - num_bytes * 8; - for (int i = 0; i < rest; ++i) - { - ret += (m_bytes[num_bytes] >> (7-i)) & 1; - } - TORRENT_ASSERT(ret <= m_size); - TORRENT_ASSERT(ret >= 0); - return ret; - } - - struct const_iterator - { - friend struct bitfield; - - typedef bool value_type; - typedef ptrdiff_t difference_type; - typedef bool const* pointer; - typedef bool& reference; - typedef std::forward_iterator_tag iterator_category; - - bool operator*() { return *byte & bit; } - const_iterator& operator++() { inc(); return *this; } - const_iterator operator++(int) - { const_iterator ret(*this); inc(); return ret; } - const_iterator& operator--() { dec(); return *this; } - const_iterator operator--(int) - { const_iterator ret(*this); dec(); return ret; } - - const_iterator(): byte(0), bit(0x80) {} - bool operator==(const_iterator const& rhs) const - { return byte == rhs.byte && bit == rhs.bit; } - - bool operator!=(const_iterator const& rhs) const - { return byte != rhs.byte || bit != rhs.bit; } - - private: - void inc() - { - TORRENT_ASSERT(byte); - if (bit == 0x01) - { - bit = 0x80; - ++byte; - } - else - { - bit >>= 1; - } - } - void dec() - { - TORRENT_ASSERT(byte); - if (bit == 0x80) - { - bit = 0x01; - --byte; - } - else - { - bit <<= 1; - } - } - const_iterator(unsigned char const* ptr, int offset) - : byte(ptr), bit(0x80 >> offset) {} - unsigned char const* byte; - int bit; - }; - - const_iterator begin() const { return const_iterator(m_bytes, 0); } - const_iterator end() const { return const_iterator(m_bytes + m_size / 8, m_size & 7); } - - void resize(int bits, bool val) - { - int s = m_size; - int b = m_size & 7; - resize(bits); - if (s >= m_size) return; - int old_size_bytes = (s + 7) / 8; - int new_size_bytes = (m_size + 7) / 8; - if (val) - { - if (old_size_bytes && b) m_bytes[old_size_bytes - 1] |= (0xff >> b); - if (old_size_bytes < new_size_bytes) - std::memset(m_bytes + old_size_bytes, 0xff, new_size_bytes - old_size_bytes); - clear_trailing_bits(); - } - else - { - if (old_size_bytes < new_size_bytes) - std::memset(m_bytes + old_size_bytes, 0x00, new_size_bytes - old_size_bytes); - } - } - - void set_all() - { - std::memset(m_bytes, 0xff, (m_size + 7) / 8); - clear_trailing_bits(); - } - - void clear_all() - { - std::memset(m_bytes, 0x00, (m_size + 7) / 8); - } - - void resize(int bits) - { - const int bytes = (bits + 7) / 8; - if (m_bytes) - { - if (m_own) - { - m_bytes = (unsigned char*)std::realloc(m_bytes, bytes); - m_own = true; - } - else if (bits > m_size) - { - unsigned char* tmp = (unsigned char*)std::malloc(bytes); - std::memcpy(tmp, m_bytes, (std::min)((m_size + 7)/ 8, bytes)); - m_bytes = tmp; - m_own = true; - } - } - else - { - m_bytes = (unsigned char*)std::malloc(bytes); - m_own = true; - } - m_size = bits; - clear_trailing_bits(); - } - - private: - - void clear_trailing_bits() - { - // clear the tail bits in the last byte - if (m_size & 7) m_bytes[(m_size + 7) / 8 - 1] &= 0xff << (8 - (m_size & 7)); - } - - void dealloc() { if (m_own) std::free(m_bytes); m_bytes = 0; } - unsigned char* m_bytes; - int m_size; // in bits - bool m_own; - }; - -} - -#endif // TORRENT_BITFIELD_HPP_INCLUDED - diff --git a/libtorrent/include/libtorrent/broadcast_socket.hpp b/libtorrent/include/libtorrent/broadcast_socket.hpp deleted file mode 100644 index 3a8d6a76e..000000000 --- a/libtorrent/include/libtorrent/broadcast_socket.hpp +++ /dev/null @@ -1,107 +0,0 @@ -/* - -Copyright (c) 2007, Arvid Norberg -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions -are met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in - the documentation and/or other materials provided with the distribution. - * Neither the name of the author nor the names of its - contributors may be used to endorse or promote products derived - from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -POSSIBILITY OF SUCH DAMAGE. - -*/ - -#ifndef TORRENT_BROADCAST_SOCKET_HPP_INCLUDED -#define TORRENT_BROADCAST_SOCKET_HPP_INCLUDED - -#include "libtorrent/config.hpp" -#include "libtorrent/socket.hpp" -#include -#include -#include - -namespace libtorrent -{ - - TORRENT_EXPORT bool is_local(address const& a); - TORRENT_EXPORT bool is_loopback(address const& addr); - TORRENT_EXPORT bool is_multicast(address const& addr); - TORRENT_EXPORT bool is_any(address const& addr); - TORRENT_EXPORT int cidr_distance(address const& a1, address const& a2); - - int common_bits(unsigned char const* b1 - , unsigned char const* b2, int n); - - TORRENT_EXPORT address guess_local_address(io_service&); - - typedef boost::function receive_handler_t; - - class TORRENT_EXPORT broadcast_socket - { - public: - broadcast_socket(io_service& ios, udp::endpoint const& multicast_endpoint - , receive_handler_t const& handler, bool loopback = true); - ~broadcast_socket() { close(); } - - void send(char const* buffer, int size, error_code& ec); - void close(); - - private: - - struct socket_entry - { - socket_entry(boost::shared_ptr const& s): socket(s) {} - boost::shared_ptr socket; - char buffer[1024]; - udp::endpoint remote; - void close() - { - if (!socket) return; - error_code ec; - socket->close(ec); - } - }; - - void on_receive(socket_entry* s, error_code const& ec - , std::size_t bytes_transferred); - void open_unicast_socket(io_service& ios, address const& addr); - void open_multicast_socket(io_service& ios, address const& addr - , bool loopback); - - // these sockets are used to - // join the multicast group (on each interface) - // and receive multicast messages - std::list m_sockets; - // these sockets are not bound to any - // specific port and are used to - // send messages to the multicast group - // and receive unicast responses - std::list m_unicast_sockets; - udp::endpoint m_multicast_endpoint; - receive_handler_t m_on_receive; - - }; -} - -#endif - diff --git a/libtorrent/include/libtorrent/bt_peer_connection.hpp b/libtorrent/include/libtorrent/bt_peer_connection.hpp deleted file mode 100644 index 6876d94aa..000000000 --- a/libtorrent/include/libtorrent/bt_peer_connection.hpp +++ /dev/null @@ -1,435 +0,0 @@ -/* - -Copyright (c) 2003 - 2006, Arvid Norberg -Copyright (c) 2007, Arvid Norberg, Un Shyam -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions -are met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in - the documentation and/or other materials provided with the distribution. - * Neither the name of the author nor the names of its - contributors may be used to endorse or promote products derived - from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -POSSIBILITY OF SUCH DAMAGE. - -*/ - -#ifndef TORRENT_BT_PEER_CONNECTION_HPP_INCLUDED -#define TORRENT_BT_PEER_CONNECTION_HPP_INCLUDED - -#include -#include -#include -#include -#include - -#include "libtorrent/debug.hpp" - -#ifdef _MSC_VER -#pragma warning(push, 1) -#endif - -#include -#include -#include -#include -#include - -#ifdef _MSC_VER -#pragma warning(pop) -#endif - -#include "libtorrent/buffer.hpp" -#include "libtorrent/peer_connection.hpp" -#include "libtorrent/socket.hpp" -#include "libtorrent/peer_id.hpp" -#include "libtorrent/storage.hpp" -#include "libtorrent/stat.hpp" -#include "libtorrent/alert.hpp" -#include "libtorrent/torrent_handle.hpp" -#include "libtorrent/torrent.hpp" -#include "libtorrent/peer_request.hpp" -#include "libtorrent/piece_block_progress.hpp" -#include "libtorrent/config.hpp" -#include "libtorrent/pe_crypto.hpp" - -namespace libtorrent -{ - class torrent; - - namespace detail - { - struct session_impl; - } - - class TORRENT_EXPORT bt_peer_connection - : public peer_connection - { - friend class invariant_access; - public: - - // this is the constructor where the we are the active part. - // The peer_conenction should handshake and verify that the - // other end has the correct id - bt_peer_connection( - aux::session_impl& ses - , boost::weak_ptr t - , boost::shared_ptr s - , tcp::endpoint const& remote - , policy::peer* peerinfo); - - // with this constructor we have been contacted and we still don't - // know which torrent the connection belongs to - bt_peer_connection( - aux::session_impl& ses - , boost::shared_ptr s - , tcp::endpoint const& remote - , policy::peer* peerinfo); - - void start(); - - ~bt_peer_connection(); - -#ifndef TORRENT_DISABLE_ENCRYPTION - bool supports_encryption() const - { return m_encrypted; } -#endif - - enum message_type - { - // standard messages - msg_choke = 0, - msg_unchoke, - msg_interested, - msg_not_interested, - msg_have, - msg_bitfield, - msg_request, - msg_piece, - msg_cancel, - // DHT extension - msg_dht_port, - // FAST extension - msg_suggest_piece = 0xd, - msg_have_all, - msg_have_none, - msg_reject_request, - msg_allowed_fast, - - // extension protocol message - msg_extended = 20, - - num_supported_messages - }; - - // called from the main loop when this connection has any - // work to do. - - void on_sent(error_code const& error - , std::size_t bytes_transferred); - void on_receive(error_code const& error - , std::size_t bytes_transferred); - - virtual void get_specific_peer_info(peer_info& p) const; - virtual bool in_handshake() const; - -#ifndef TORRENT_DISABLE_EXTENSIONS - bool support_extensions() const { return m_supports_extensions; } - - template - T* supports_extension() const - { - for (extension_list_t::const_iterator i = m_extensions.begin() - , end(m_extensions.end()); i != end; ++i) - { - T* ret = dynamic_cast(i->get()); - if (ret) return ret; - } - return 0; - } -#endif - - // the message handlers are called - // each time a recv() returns some new - // data, the last time it will be called - // is when the entire packet has been - // received, then it will no longer - // be called. i.e. most handlers need - // to check how much of the packet they - // have received before any processing - void on_keepalive(); - void on_choke(int received); - void on_unchoke(int received); - void on_interested(int received); - void on_not_interested(int received); - void on_have(int received); - void on_bitfield(int received); - void on_request(int received); - void on_piece(int received); - void on_cancel(int received); - - // DHT extension - void on_dht_port(int received); - - // FAST extension - void on_suggest_piece(int received); - void on_have_all(int received); - void on_have_none(int received); - void on_reject_request(int received); - void on_allowed_fast(int received); - - void on_extended(int received); - - void on_extended_handshake(); - - typedef void (bt_peer_connection::*message_handler)(int received); - - // the following functions appends messages - // to the send buffer - void write_choke(); - void write_unchoke(); - void write_interested(); - void write_not_interested(); - void write_request(peer_request const& r); - void write_cancel(peer_request const& r); - void write_bitfield(); - void write_have(int index); - void write_piece(peer_request const& r, disk_buffer_holder& buffer); - void write_handshake(); -#ifndef TORRENT_DISABLE_EXTENSIONS - void write_extensions(); -#endif - void write_chat_message(const std::string& msg); - void write_metadata(std::pair req); - void write_metadata_request(std::pair req); - void write_keepalive(); - - // DHT extension - void write_dht_port(int listen_port); - - // FAST extension - void write_have_all(); - void write_have_none(); - void write_reject_request(peer_request const&); - void write_allow_fast(int piece); - - void on_connected(); - void on_metadata(); - -#ifdef TORRENT_DEBUG - void check_invariant() const; - ptime m_last_choke; -#endif - - private: - - bool dispatch_message(int received); - // returns the block currently being - // downloaded. And the progress of that - // block. If the peer isn't downloading - // a piece for the moment, the boost::optional - // will be invalid. - boost::optional downloading_piece_progress() const; - -#ifndef TORRENT_DISABLE_ENCRYPTION - - // if (is_local()), we are 'a' otherwise 'b' - // - // 1. a -> b dhkey, pad - // 2. b -> a dhkey, pad - // 3. a -> b sync, payload - // 4. b -> a sync, payload - // 5. a -> b payload - - void write_pe1_2_dhkey(); - void write_pe3_sync(); - void write_pe4_sync(int crypto_select); - - void write_pe_vc_cryptofield(buffer::interval& write_buf - , int crypto_field, int pad_size); - - // stream key (info hash of attached torrent) - // secret is the DH shared secret - // initializes m_RC4_handler - void init_pe_RC4_handler(char const* secret, sha1_hash const& stream_key); - -public: - - // these functions encrypt the send buffer if m_rc4_encrypted - // is true, otherwise it passes the call to the - // peer_connection functions of the same names - void send_buffer(char const* buf, int size, int flags = 0); - buffer::interval allocate_send_buffer(int size); - template - void append_send_buffer(char* buffer, int size, Destructor const& destructor) - { -#ifndef TORRENT_DISABLE_ENCRYPTION - if (m_rc4_encrypted) - { - TORRENT_ASSERT(send_buffer_size() == m_encrypted_bytes); - m_RC4_handler->encrypt(buffer, size); -#ifdef TORRENT_DEBUG - m_encrypted_bytes += size; - TORRENT_ASSERT(m_encrypted_bytes == send_buffer_size() + size); -#endif - } -#endif - peer_connection::append_send_buffer(buffer, size, destructor); - } - void setup_send(); - -private: - - void encrypt_pending_buffer(); - - // Returns offset at which bytestream (src, src + src_size) - // matches bytestream(target, target + target_size). - // If no sync found, return -1 - int get_syncoffset(char const* src, int src_size - , char const* target, int target_size) const; -#endif - - enum state - { -#ifndef TORRENT_DISABLE_ENCRYPTION - read_pe_dhkey = 0, - read_pe_syncvc, - read_pe_synchash, - read_pe_skey_vc, - read_pe_cryptofield, - read_pe_pad, - read_pe_ia, - init_bt_handshake, - read_protocol_identifier, -#else - read_protocol_identifier = 0, -#endif - read_info_hash, - read_peer_id, - - // handshake complete - read_packet_size, - read_packet - }; - -#ifndef TORRENT_DISABLE_ENCRYPTION - enum - { - handshake_len = 68, - dh_key_len = 96 - }; -#endif - - std::string m_client_version; - - // state of on_receive - state m_state; - - static const message_handler m_message_handler[num_supported_messages]; - - // this is a queue of ranges that describes - // where in the send buffer actual payload - // data is located. This is currently - // only used to be able to gather statistics - // seperately on payload and protocol data. - struct range - { - range(int s, int l) - : start(s) - , length(l) - { - TORRENT_ASSERT(s >= 0); - TORRENT_ASSERT(l > 0); - } - int start; - int length; - }; - static bool range_below_zero(const range& r) - { return r.start < 0; } - std::deque m_payloads; - -#ifndef TORRENT_DISABLE_EXTENSIONS - // this is set to true if the handshake from - // the peer indicated that it supports the - // extension protocol - bool m_supports_extensions; - char m_reserved_bits[20]; -#endif - bool m_supports_dht_port; - bool m_supports_fast; - -#ifndef TORRENT_DISABLE_ENCRYPTION - // this is set to true after the encryption method has been - // succesfully negotiated (either plaintext or rc4), to signal - // automatic encryption/decryption. - bool m_encrypted; - - // true if rc4, false if plaintext - bool m_rc4_encrypted; - - // used to disconnect peer if sync points are not found within - // the maximum number of bytes - int m_sync_bytes_read; - - // hold information about latest allocated send buffer - // need to check for non zero (begin, end) for operations with this - buffer::interval m_enc_send_buffer; - - // initialized during write_pe1_2_dhkey, and destroyed on - // creation of m_RC4_handler. Cannot reinitialize once - // initialized. - boost::scoped_ptr m_dh_key_exchange; - - // if RC4 is negotiated, this is used for - // encryption/decryption during the entire session. Destroyed - // if plaintext is selected - boost::scoped_ptr m_RC4_handler; - - // (outgoing only) synchronize verification constant with - // remote peer, this will hold RC4_decrypt(vc). Destroyed - // after the sync step. - boost::scoped_array m_sync_vc; - - // (incoming only) synchronize hash with remote peer, holds - // the sync hash (hash("req1",secret)). Destroyed after the - // sync step. - boost::scoped_ptr m_sync_hash; -#endif // #ifndef TORRENT_DISABLE_ENCRYPTION - -#ifdef TORRENT_DEBUG - // this is set to true when the client's - // bitfield is sent to this peer - bool m_sent_bitfield; - - bool m_in_constructor; - - bool m_sent_handshake; - - // the number of bytes in the send buffer - // that have been encrypted (only used for - // encrypted connections) - int m_encrypted_bytes; -#endif - - }; -} - -#endif // TORRENT_BT_PEER_CONNECTION_HPP_INCLUDED - diff --git a/libtorrent/include/libtorrent/buffer.hpp b/libtorrent/include/libtorrent/buffer.hpp deleted file mode 100644 index 425a6a634..000000000 --- a/libtorrent/include/libtorrent/buffer.hpp +++ /dev/null @@ -1,205 +0,0 @@ -/* -Copyright (c) 2007, Arvid Norberg -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions -are met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in - the documentation and/or other materials provided with the distribution. - * Neither the name of Rasterbar Software nor the names of its - contributors may be used to endorse or promote products derived - from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -POSSIBILITY OF SUCH DAMAGE. - -*/ - -#ifndef LIBTORRENT_BUFFER_HPP -#define LIBTORRENT_BUFFER_HPP - -#include -#include -#include "libtorrent/invariant_check.hpp" -#include "libtorrent/assert.hpp" - -namespace libtorrent { - -class buffer -{ -public: - struct interval - { - interval() - : begin(0) - , end(0) - {} - - interval(char* begin, char* end) - : begin(begin) - , end(end) - {} - - char operator[](int index) const - { - TORRENT_ASSERT(begin + index < end); - return begin[index]; - } - - int left() const { TORRENT_ASSERT(end >= begin); return end - begin; } - - char* begin; - char* end; - }; - - struct const_interval - { - const_interval(char const* begin, char const* end) - : begin(begin) - , end(end) - {} - - char operator[](int index) const - { - TORRENT_ASSERT(begin + index < end); - return begin[index]; - } - - bool operator==(const const_interval& p_interval) - { - return (begin == p_interval.begin - && end == p_interval.end); - } - - int left() const { TORRENT_ASSERT(end >= begin); return end - begin; } - - char const* begin; - char const* end; - }; - - buffer(std::size_t n = 0) - : m_begin(0) - , m_end(0) - , m_last(0) - { - if (n) resize(n); - } - - buffer(buffer const& b) - : m_begin(0) - , m_end(0) - , m_last(0) - { - if (b.size() == 0) return; - resize(b.size()); - std::memcpy(m_begin, b.begin(), b.size()); - } - - buffer& operator=(buffer const& b) - { - resize(b.size()); - std::memcpy(m_begin, b.begin(), b.size()); - return *this; - } - - ~buffer() - { - ::operator delete (m_begin); - } - - buffer::interval data() { return interval(m_begin, m_end); } - buffer::const_interval data() const { return const_interval(m_begin, m_end); } - - void resize(std::size_t n) - { - reserve(n); - m_end = m_begin + n; - } - - void insert(char* point, char const* first, char const* last) - { - std::size_t p = point - m_begin; - if (point == m_end) - { - resize(size() + last - first); - std::memcpy(m_begin + p, first, last - first); - return; - } - - resize(size() + last - first); - std::memmove(m_begin + p + (last - first), m_begin + p, last - first); - std::memcpy(m_begin + p, first, last - first); - } - - void erase(char* begin, char* end) - { - TORRENT_ASSERT(end <= m_end); - TORRENT_ASSERT(begin >= m_begin); - TORRENT_ASSERT(begin <= end); - if (end == m_end) - { - resize(begin - m_begin); - return; - } - std::memmove(begin, end, m_end - end); - m_end = begin + (m_end - end); - } - - void clear() { m_end = m_begin; } - std::size_t size() const { return m_end - m_begin; } - std::size_t capacity() const { return m_last - m_begin; } - void reserve(std::size_t n) - { - if (n <= capacity()) return; - TORRENT_ASSERT(n > 0); - - char* buf = (char*)::operator new(n); - std::size_t s = size(); - std::memcpy(buf, m_begin, s); - ::operator delete (m_begin); - m_begin = buf; - m_end = buf + s; - m_last = m_begin + n; - } - - bool empty() const { return m_begin == m_end; } - char& operator[](std::size_t i) { TORRENT_ASSERT(i < size()); return m_begin[i]; } - char const& operator[](std::size_t i) const { TORRENT_ASSERT(i < size()); return m_begin[i]; } - - char* begin() { return m_begin; } - char const* begin() const { return m_begin; } - char* end() { return m_end; } - char const* end() const { return m_end; } - - void swap(buffer& b) - { - using std::swap; - swap(m_begin, b.m_begin); - swap(m_end, b.m_end); - swap(m_last, b.m_last); - } -private: - char* m_begin; // first - char* m_end; // one passed end of size - char* m_last; // one passed end of allocation -}; - - -} - -#endif // LIBTORRENT_BUFFER_HPP - diff --git a/libtorrent/include/libtorrent/chained_buffer.hpp b/libtorrent/include/libtorrent/chained_buffer.hpp deleted file mode 100644 index caf2e89be..000000000 --- a/libtorrent/include/libtorrent/chained_buffer.hpp +++ /dev/null @@ -1,200 +0,0 @@ -/* - -Copyright (c) 2007, Arvid Norberg -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions -are met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in - the documentation and/or other materials provided with the distribution. - * Neither the name of the author nor the names of its - contributors may be used to endorse or promote products derived - from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -POSSIBILITY OF SUCH DAMAGE. - -*/ - -#ifndef TORRENT_CHAINED_BUFFER_HPP_INCLUDED -#define TORRENT_CHAINED_BUFFER_HPP_INCLUDED - -#include -#include -#if BOOST_VERSION < 103500 -#include -#else -#include -#endif -#include -#include - -namespace libtorrent -{ -#if BOOST_VERSION >= 103500 - namespace asio = boost::asio; -#endif - struct chained_buffer - { - chained_buffer(): m_bytes(0), m_capacity(0) {} - - struct buffer_t - { - boost::function free; // destructs the buffer - char* buf; // the first byte of the buffer - int size; // the total size of the buffer - - char* start; // the first byte to send/receive in the buffer - int used_size; // this is the number of bytes to send/receive - }; - - bool empty() const { return m_bytes == 0; } - int size() const { return m_bytes; } - int capacity() const { return m_capacity; } - - void pop_front(int bytes_to_pop) - { - TORRENT_ASSERT(bytes_to_pop <= m_bytes); - while (bytes_to_pop > 0 && !m_vec.empty()) - { - buffer_t& b = m_vec.front(); - if (b.used_size > bytes_to_pop) - { - b.start += bytes_to_pop; - b.used_size -= bytes_to_pop; - m_bytes -= bytes_to_pop; - TORRENT_ASSERT(m_bytes <= m_capacity); - TORRENT_ASSERT(m_bytes >= 0); - TORRENT_ASSERT(m_capacity >= 0); - break; - } - - b.free(b.buf); - m_bytes -= b.used_size; - m_capacity -= b.size; - bytes_to_pop -= b.used_size; - TORRENT_ASSERT(m_bytes >= 0); - TORRENT_ASSERT(m_capacity >= 0); - TORRENT_ASSERT(m_bytes <= m_capacity); - m_vec.pop_front(); - } - } - - template - void append_buffer(char* buffer, int size, int used_size, D const& destructor) - { - TORRENT_ASSERT(size >= used_size); - buffer_t b; - b.buf = buffer; - b.size = size; - b.start = buffer; - b.used_size = used_size; - b.free = destructor; - m_vec.push_back(b); - - m_bytes += used_size; - m_capacity += size; - TORRENT_ASSERT(m_bytes <= m_capacity); - } - - // returns the number of bytes available at the - // end of the last chained buffer. - int space_in_last_buffer() - { - if (m_vec.empty()) return 0; - buffer_t& b = m_vec.back(); - return b.size - b.used_size - (b.start - b.buf); - } - - // tries to copy the given buffer to the end of the - // last chained buffer. If there's not enough room - // it returns false - bool append(char const* buf, int size) - { - char* insert = allocate_appendix(size); - if (insert == 0) return false; - std::memcpy(insert, buf, size); - return true; - } - - // tries to allocate memory from the end - // of the last buffer. If there isn't - // enough room, returns 0 - char* allocate_appendix(int size) - { - if (m_vec.empty()) return 0; - buffer_t& b = m_vec.back(); - char* insert = b.start + b.used_size; - if (insert + size > b.buf + b.size) return 0; - b.used_size += size; - m_bytes += size; - TORRENT_ASSERT(m_bytes <= m_capacity); - return insert; - } - - std::list const& build_iovec(int to_send) - { - m_tmp_vec.clear(); - - for (std::list::iterator i = m_vec.begin() - , end(m_vec.end()); to_send > 0 && i != end; ++i) - { - if (i->used_size > to_send) - { - TORRENT_ASSERT(to_send > 0); - m_tmp_vec.push_back(asio::const_buffer(i->start, to_send)); - break; - } - TORRENT_ASSERT(i->used_size > 0); - m_tmp_vec.push_back(asio::const_buffer(i->start, i->used_size)); - to_send -= i->used_size; - } - return m_tmp_vec; - } - - ~chained_buffer() - { - for (std::list::iterator i = m_vec.begin() - , end(m_vec.end()); i != end; ++i) - { - i->free(i->buf); - } - } - - private: - - // this is the list of all the buffers we want to - // send - std::list m_vec; - - // this is the number of bytes in the send buf. - // this will always be equal to the sum of the - // size of all buffers in vec - int m_bytes; - - // the total size of all buffers in the chain - // including unused space - int m_capacity; - - // this is the vector of buffers used when - // invoking the async write call - std::list m_tmp_vec; - }; -} - -#endif - diff --git a/libtorrent/include/libtorrent/config.hpp b/libtorrent/include/libtorrent/config.hpp deleted file mode 100644 index 529549977..000000000 --- a/libtorrent/include/libtorrent/config.hpp +++ /dev/null @@ -1,96 +0,0 @@ -/* - -Copyright (c) 2005, Arvid Norberg -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions -are met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in - the documentation and/or other materials provided with the distribution. - * Neither the name of the author nor the names of its - contributors may be used to endorse or promote products derived - from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -POSSIBILITY OF SUCH DAMAGE. - -*/ - -#ifndef TORRENT_CONFIG_HPP_INCLUDED -#define TORRENT_CONFIG_HPP_INCLUDED - -#include -#include - -#if defined(__GNUC__) && __GNUC__ >= 4 - -#define TORRENT_DEPRECATED __attribute__ ((deprecated)) - -# if defined(TORRENT_BUILDING_SHARED) || defined(TORRENT_LINKING_SHARED) -# define TORRENT_EXPORT __attribute__ ((visibility("default"))) -# else -# define TORRENT_EXPORT -# endif - -#elif defined(__GNUC__) - -# define TORRENT_EXPORT - -#elif defined(BOOST_MSVC) - -# if defined(TORRENT_BUILDING_SHARED) -# define TORRENT_EXPORT __declspec(dllexport) -# elif defined(TORRENT_LINKING_SHARED) -# define TORRENT_EXPORT __declspec(dllimport) -# else -# define TORRENT_EXPORT -# endif - -#else -# define TORRENT_EXPORT -#endif - -#ifndef TORRENT_DEPRECATED -#define TORRENT_DEPRECATED -#endif - -// set up defines for target environments -#if (defined __APPLE__ && __MACH__) || defined __FreeBSD__ || defined __NetBSD__ \ - || defined __OpenBSD__ || defined __bsdi__ || defined __DragonFly__ \ - || defined __FreeBSD_kernel__ -#define TORRENT_BSD -#elif defined __linux__ -#define TORRENT_LINUX -#elif defined WIN32 -#define TORRENT_WINDOWS -#elif defined sun || defined __sun -#define TORRENT_SOLARIS -#else -#warning unkown OS, assuming BSD -#define TORRENT_BSD -#endif - -// should wpath or path be used? -#if defined UNICODE && !defined BOOST_FILESYSTEM_NARROW_ONLY \ - && BOOST_VERSION >= 103400 && defined WIN32 -#define TORRENT_USE_WPATH 1 -#else -#define TORRENT_USE_WPATH 0 -#endif - -#endif // TORRENT_CONFIG_HPP_INCLUDED - diff --git a/libtorrent/include/libtorrent/connection_queue.hpp b/libtorrent/include/libtorrent/connection_queue.hpp deleted file mode 100644 index c41124e64..000000000 --- a/libtorrent/include/libtorrent/connection_queue.hpp +++ /dev/null @@ -1,115 +0,0 @@ -/* - -Copyright (c) 2007, Arvid Norberg -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions -are met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in - the documentation and/or other materials provided with the distribution. - * Neither the name of the author nor the names of its - contributors may be used to endorse or promote products derived - from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -POSSIBILITY OF SUCH DAMAGE. - -*/ - -#ifndef TORRENT_CONNECTION_QUEUE -#define TORRENT_CONNECTION_QUEUE - -#include -#include -#include -#include -#include "libtorrent/socket.hpp" -#include "libtorrent/time.hpp" - -#ifdef TORRENT_CONNECTION_LOGGING -#include -#endif - -namespace libtorrent -{ - -class connection_queue : public boost::noncopyable -{ -public: - connection_queue(io_service& ios); - - // if there are no free slots, returns the negative - // number of queued up connections - int free_slots() const; - - void enqueue(boost::function const& on_connect - , boost::function const& on_timeout - , time_duration timeout, int priority = 0); - void done(int ticket); - void limit(int limit); - int limit() const; - void close(); - int size() const { return m_queue.size(); } - -#ifdef TORRENT_DEBUG - void check_invariant() const; -#endif - -private: - - void try_connect(); - void on_timeout(error_code const& e); - - struct entry - { - entry(): connecting(false), ticket(0), expires(max_time()), priority(0) {} - // called when the connection is initiated - boost::function on_connect; - // called if done hasn't been called within the timeout - boost::function on_timeout; - bool connecting; - int ticket; - ptime expires; - time_duration timeout; - int priority; - }; - - std::list m_queue; - - // the next ticket id a connection will be given - int m_next_ticket; - int m_num_connecting; - int m_half_open_limit; - bool m_abort; - - deadline_timer m_timer; - - typedef boost::recursive_mutex mutex_t; - mutable mutex_t m_mutex; - -#ifdef TORRENT_DEBUG - bool m_in_timeout_function; -#endif -#ifdef TORRENT_CONNECTION_LOGGING - std::ofstream m_log; -#endif -}; - -} - -#endif - diff --git a/libtorrent/include/libtorrent/create_torrent.hpp b/libtorrent/include/libtorrent/create_torrent.hpp deleted file mode 100644 index a521a1b3e..000000000 --- a/libtorrent/include/libtorrent/create_torrent.hpp +++ /dev/null @@ -1,218 +0,0 @@ -/* - -Copyright (c) 2008, Arvid Norberg -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions -are met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in - the documentation and/or other materials provided with the distribution. - * Neither the name of the author nor the names of its - contributors may be used to endorse or promote products derived - from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -POSSIBILITY OF SUCH DAMAGE. - -*/ - -#ifndef TORRENT_CREATE_TORRENT_HPP_INCLUDED -#define TORRENT_CREATE_TORRENT_HPP_INCLUDED - -#include "libtorrent/bencode.hpp" -#include "libtorrent/peer_id.hpp" -#include "libtorrent/file_storage.hpp" -#include "libtorrent/file_pool.hpp" -#include "libtorrent/config.hpp" -#include "libtorrent/storage.hpp" -#include "libtorrent/hasher.hpp" - -#include -#include -#include - -#ifdef _MSC_VER -#pragma warning(push, 1) -#endif - -#include -#include -#include -#include -#include - -#ifdef _MSC_VER -#pragma warning(pop) -#endif - -namespace libtorrent -{ - namespace fs = boost::filesystem; - namespace pt = boost::posix_time; - - struct TORRENT_EXPORT create_torrent - { - create_torrent(file_storage& fs, int piece_size); - create_torrent(file_storage& fs); - entry generate() const; - - file_storage const& files() const { return m_files; } - - void set_comment(char const* str); - void set_creator(char const* str); - void set_hash(int index, sha1_hash const& h); - void add_url_seed(std::string const& url); - void add_node(std::pair const& node); - void add_tracker(std::string const& url, int tier = 0); - void set_priv(bool p) { m_private = p; } - - int num_pieces() const { return m_files.num_pieces(); } - int piece_length() const { return m_files.piece_length(); } - int piece_size(int i) const { return m_files.piece_size(i); } - bool priv() const { return m_private; } - - private: - - file_storage& m_files; - - // the urls to the trackers - typedef std::pair announce_entry; - std::vector m_urls; - - std::vector m_url_seeds; - - std::vector m_piece_hash; - - // dht nodes to add to the routing table/bootstrap from - typedef std::vector > nodes_t; - nodes_t m_nodes; - - // the hash that identifies this torrent - // is mutable because it's calculated - // lazily - mutable sha1_hash m_info_hash; - - // if a creation date is found in the torrent file - // this will be set to that, otherwise it'll be - // 1970, Jan 1 - pt::ptime m_creation_date; - - // if a comment is found in the torrent file - // this will be set to that comment - std::string m_comment; - - // an optional string naming the software used - // to create the torrent file - std::string m_created_by; - - // this is used when creating a torrent. If there's - // only one file there are cases where it's impossible - // to know if it should be written as a multifile torrent - // or not. e.g. test/test there's one file and one directory - // and they have the same name. - bool m_multifile; - - // this is true if the torrent is private. i.e., is should not - // be announced on the dht - bool m_private; - }; - - namespace detail - { - inline bool default_pred(boost::filesystem::path const&) { return true; } - - inline void nop(int i) {} - - template - void add_files_impl(file_storage& fs, boost::filesystem::path const& p - , boost::filesystem::path const& l, Pred pred) - { - using boost::filesystem::path; - using boost::filesystem::directory_iterator; -#if BOOST_VERSION < 103600 - std::string const& leaf = l.leaf(); -#else - std::string const& leaf = l.filename(); -#endif - if (leaf == ".." || leaf == ".") return; - if (!pred(l)) return; - path f(p / l); - if (is_directory(f)) - { - for (directory_iterator i(f), end; i != end; ++i) -#if BOOST_VERSION < 103600 - add_files_impl(fs, p, l / i->path().leaf(), pred); -#else - add_files_impl(fs, p, l / i->path().filename(), pred); -#endif - } - else - { - fs.add_file(l, file_size(f)); - } - } - } - - template - void add_files(file_storage& fs, boost::filesystem::path const& file, Pred p) - { -#if BOOST_VERSION < 103600 - detail::add_files_impl(fs, complete(file).branch_path(), file.leaf(), p); -#else - detail::add_files_impl(fs, complete(file).parent_path(), file.filename(), p); -#endif - } - - inline void add_files(file_storage& fs, boost::filesystem::path const& file) - { -#if BOOST_VERSION < 103600 - detail::add_files_impl(fs, complete(file).branch_path(), file.leaf(), detail::default_pred); -#else - detail::add_files_impl(fs, complete(file).parent_path(), file.filename(), detail::default_pred); -#endif - } - - template - void set_piece_hashes(create_torrent& t, boost::filesystem::path const& p, Fun f) - { - file_pool fp; - boost::scoped_ptr st( - default_storage_constructor(const_cast(t.files()), p, fp)); - - // calculate the hash for all pieces - int num = t.num_pieces(); - std::vector buf(t.piece_length()); - for (int i = 0; i < num; ++i) - { - // read hits the disk and will block. Progress should - // be updated in between reads - st->read(&buf[0], i, 0, t.piece_size(i)); - hasher h(&buf[0], t.piece_size(i)); - t.set_hash(i, h.final()); - f(i); - } - } - - inline void set_piece_hashes(create_torrent& t, boost::filesystem::path const& p) - { - set_piece_hashes(t, p, detail::nop); - } - -} - -#endif - diff --git a/libtorrent/include/libtorrent/debug.hpp b/libtorrent/include/libtorrent/debug.hpp deleted file mode 100644 index 0f2dad20b..000000000 --- a/libtorrent/include/libtorrent/debug.hpp +++ /dev/null @@ -1,94 +0,0 @@ -/* - -Copyright (c) 2003, Arvid Norberg -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions -are met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in - the documentation and/or other materials provided with the distribution. - * Neither the name of the author nor the names of its - contributors may be used to endorse or promote products derived - from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -POSSIBILITY OF SUCH DAMAGE. - -*/ - -#ifndef TORRENT_DEBUG_HPP_INCLUDED -#define TORRENT_DEBUG_HPP_INCLUDED - -#include -#include -#include - -#ifdef _MSC_VER -#pragma warning(push, 1) -#endif - -#include -#include -#include - -#ifdef _MSC_VER -#pragma warning(pop) -#endif - - -namespace libtorrent -{ - // DEBUG API - - namespace fs = boost::filesystem; - - struct logger - { - logger(fs::path const& logpath, fs::path const& filename, int instance, bool append = true) - { -#ifndef BOOST_NO_EXCEPTIONS - try - { -#endif - fs::path dir(fs::complete(logpath / ("libtorrent_logs" + boost::lexical_cast(instance)))); - if (!fs::exists(dir)) fs::create_directories(dir); - m_file.open((dir / filename).string().c_str(), std::ios_base::out | (append ? std::ios_base::app : std::ios_base::out)); - *this << "\n\n\n*** starting log ***\n"; -#ifndef BOOST_NO_EXCEPTIONS - } - catch (std::exception& e) - { - std::cerr << "failed to create log '" << filename.string() << "': " << e.what() << std::endl; - } -#endif - } - - template - logger& operator<<(T const& v) - { - m_file << v; - m_file.flush(); - return *this; - } - - std::ofstream m_file; - }; - -} - -#endif // TORRENT_DEBUG_HPP_INCLUDED - diff --git a/libtorrent/include/libtorrent/disk_buffer_holder.hpp b/libtorrent/include/libtorrent/disk_buffer_holder.hpp deleted file mode 100644 index 31be6b3c7..000000000 --- a/libtorrent/include/libtorrent/disk_buffer_holder.hpp +++ /dev/null @@ -1,65 +0,0 @@ -/* - -Copyright (c) 2008, Arvid Norberg -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions -are met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in - the documentation and/or other materials provided with the distribution. - * Neither the name of the author nor the names of its - contributors may be used to endorse or promote products derived - from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -POSSIBILITY OF SUCH DAMAGE. - -*/ - -#ifndef TORRENT_DISK_BUFFER_HOLDER_HPP_INCLUDED -#define TORRENT_DISK_BUFFER_HOLDER_HPP_INCLUDED - -#include "libtorrent/config.hpp" - -namespace libtorrent -{ - - namespace aux { class session_impl; } - class disk_io_thread; - - struct TORRENT_EXPORT disk_buffer_holder - { - disk_buffer_holder(aux::session_impl& ses, char* buf); - disk_buffer_holder(disk_io_thread& iothread, char* buf); - ~disk_buffer_holder(); - char* release(); - char* get() const { return m_buf; } - void reset(char* buf = 0); - - typedef char* (disk_buffer_holder::*unspecified_bool_type)(); - operator unspecified_bool_type() const - { return m_buf == 0? 0: &disk_buffer_holder::release; } - - private: - disk_io_thread& m_iothread; - char* m_buf; - }; - -} - -#endif - diff --git a/libtorrent/include/libtorrent/disk_io_thread.hpp b/libtorrent/include/libtorrent/disk_io_thread.hpp deleted file mode 100644 index bbed7618b..000000000 --- a/libtorrent/include/libtorrent/disk_io_thread.hpp +++ /dev/null @@ -1,318 +0,0 @@ -/* - -Copyright (c) 2007, Arvid Norberg -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions -are met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in - the documentation and/or other materials provided with the distribution. - * Neither the name of the author nor the names of its - contributors may be used to endorse or promote products derived - from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -POSSIBILITY OF SUCH DAMAGE. - -*/ - -#ifndef TORRENT_DISK_IO_THREAD -#define TORRENT_DISK_IO_THREAD - -#ifdef TORRENT_DISK_STATS -#include -#endif - -#include "libtorrent/storage.hpp" -#include -#include -#include -#include -#include -#include -#include -#include -#include "libtorrent/config.hpp" -#ifndef TORRENT_DISABLE_POOL_ALLOCATOR -#include -#endif - -namespace libtorrent -{ - - struct cached_piece_info - { - int piece; - std::vector blocks; - ptime last_use; - enum kind_t { read_cache = 0, write_cache = 1 }; - kind_t kind; - }; - - struct disk_io_job - { - disk_io_job() - : action(read) - , buffer(0) - , buffer_size(0) - , piece(0) - , offset(0) - , priority(0) - {} - - enum action_t - { - read - , write - , hash - , move_storage - , release_files - , delete_files - , check_fastresume - , check_files - , save_resume_data - , rename_file - , abort_thread - , clear_read_cache - , abort_torrent - }; - - action_t action; - - char* buffer; - int buffer_size; - boost::intrusive_ptr storage; - // arguments used for read and write - int piece, offset; - // used for move_storage and rename_file. On errors, this is set - // to the error message - std::string str; - - // on error, this is set to the path of the - // file the disk operation failed on - std::string error_file; - - // priority decides whether or not this - // job will skip entries in the queue or - // not. It always skips in front of entries - // with lower priority - int priority; - - boost::shared_ptr resume_data; - - // the error code from the file operation - error_code error; - - // this is called when operation completes - boost::function callback; - }; - - struct cache_status - { - cache_status() - : blocks_written(0) - , writes(0) - , blocks_read(0) - , blocks_read_hit(0) - , reads(0) - , cache_size(0) - , read_cache_size(0) - {} - - // the number of 16kB blocks written - size_type blocks_written; - // the number of write operations used - size_type writes; - // (blocks_written - writes) / blocks_written represents the - // "cache hit" ratio in the write cache - // the number of blocks read - - // the number of blocks passed back to the bittorrent engine - size_type blocks_read; - // the number of blocks that was just copied from the read cache - size_type blocks_read_hit; - // the number of read operations used - size_type reads; - - // the number of blocks in the cache (both read and write) - int cache_size; - - // the number of blocks in the cache used for read cache - int read_cache_size; - }; - - // this is a singleton consisting of the thread and a queue - // of disk io jobs - struct disk_io_thread : boost::noncopyable - { - disk_io_thread(io_service& ios, int block_size = 16 * 1024); - ~disk_io_thread(); - -#ifdef TORRENT_STATS - int disk_allocations() const - { return m_allocations; } -#endif - - void join(); - - // aborts read operations - void stop(boost::intrusive_ptr s); - void add_job(disk_io_job const& j - , boost::function const& f - = boost::function()); - - // keep track of the number of bytes in the job queue - // at any given time. i.e. the sum of all buffer_size. - // this is used to slow down the download global download - // speed when the queue buffer size is too big. - size_type queue_buffer_size() const - { return m_queue_buffer_size; } - - void get_cache_info(sha1_hash const& ih - , std::vector& ret) const; - - cache_status status() const; - void set_cache_size(int s); - void set_cache_expiry(int ex); - - void operator()(); - -#ifdef TORRENT_DEBUG - bool is_disk_buffer(char* buffer) const; -#endif - - char* allocate_buffer(); - void free_buffer(char* buf); - -#ifdef TORRENT_DEBUG - void check_invariant() const; -#endif - - private: - - struct cached_piece_entry - { - int piece; - // storage this piece belongs to - boost::intrusive_ptr storage; - // the last time a block was writting to this piece - ptime last_use; - // the number of blocks in the cache for this piece - int num_blocks; - // the pointers to the block data - boost::shared_array blocks; - }; - - typedef boost::recursive_mutex mutex_t; - typedef std::list cache_t; - - bool test_error(disk_io_job& j); - - // cache operations - cache_t::iterator find_cached_piece( - cache_t& cache, disk_io_job const& j - , mutex_t::scoped_lock& l); - - // write cache operations - void flush_oldest_piece(mutex_t::scoped_lock& l); - void flush_expired_pieces(); - void flush_and_remove(cache_t::iterator i, mutex_t::scoped_lock& l); - void flush(cache_t::iterator i, mutex_t::scoped_lock& l); - void cache_block(disk_io_job& j, mutex_t::scoped_lock& l); - - // read cache operations - bool clear_oldest_read_piece(cache_t::iterator ignore - , mutex_t::scoped_lock& l); - int read_into_piece(cached_piece_entry& p, int start_block, mutex_t::scoped_lock& l); - int cache_read_block(disk_io_job const& j, mutex_t::scoped_lock& l); - void free_piece(cached_piece_entry& p, mutex_t::scoped_lock& l); - bool make_room(int num_blocks - , cache_t::iterator ignore - , mutex_t::scoped_lock& l); - int try_read_from_cache(disk_io_job const& j); - - // this mutex only protects m_jobs, m_queue_buffer_size - // and m_abort - mutable mutex_t m_queue_mutex; - boost::condition m_signal; - bool m_abort; - std::list m_jobs; - size_type m_queue_buffer_size; - - // this protects the piece cache and related members - mutable mutex_t m_piece_mutex; - // write cache - cache_t m_pieces; - - // read cache - cache_t m_read_pieces; - - // total number of blocks in use by both the read - // and the write cache. This is not supposed to - // exceed m_cache_size - cache_status m_cache_stats; - - // in (16kB) blocks - int m_cache_size; - - // expiration time of cache entries in seconds - int m_cache_expiry; - - // if set to true, each piece flush will allocate - // one piece worth of temporary memory on the heap - // and copy the block data into it, and then perform - // a single write operation from that buffer. - // if memory is constrained, that temporary buffer - // might is avoided by setting this to false. - // in case the allocation fails, the piece flush - // falls back to writing each block separately. - bool m_coalesce_writes; - bool m_coalesce_reads; - bool m_use_read_cache; - - // this only protects the pool allocator - mutable mutex_t m_pool_mutex; -#ifndef TORRENT_DISABLE_POOL_ALLOCATOR - // memory pool for read and write operations - // and disk cache - boost::pool<> m_pool; -#endif - - // number of bytes per block. The BitTorrent - // protocol defines the block size to 16 KiB. - int m_block_size; - -#ifdef TORRENT_DISK_STATS - std::ofstream m_log; -#endif -#ifdef TORRENT_STATS - int m_allocations; -#endif - - size_type m_writes; - size_type m_blocks_written; - - io_service& m_ios; - - // thread for performing blocking disk io operations - boost::thread m_disk_io_thread; - }; - -} - -#endif - diff --git a/libtorrent/include/libtorrent/entry.hpp b/libtorrent/include/libtorrent/entry.hpp deleted file mode 100644 index a970bf81b..000000000 --- a/libtorrent/include/libtorrent/entry.hpp +++ /dev/null @@ -1,338 +0,0 @@ -/* - -Copyright (c) 2003, Arvid Norberg -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions -are met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in - the documentation and/or other materials provided with the distribution. - * Neither the name of the author nor the names of its - contributors may be used to endorse or promote products derived - from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -POSSIBILITY OF SUCH DAMAGE. - -*/ - -#ifndef TORRENT_ENTRY_HPP_INCLUDED -#define TORRENT_ENTRY_HPP_INCLUDED - -/* - * - * This file declares the entry class. It is a - * variant-type that can be an integer, list, - * dictionary (map) or a string. This type is - * used to hold bdecoded data (which is the - * encoding BitTorrent messages uses). - * - * it has 4 accessors to access the actual - * type of the object. They are: - * integer() - * string() - * list() - * dict() - * The actual type has to match the type you - * are asking for, otherwise you will get an - * assertion failure. - * When you default construct an entry, it is - * uninitialized. You can initialize it through the - * assignment operator, copy-constructor or - * the constructor that takes a data_type enum. - * - * - */ - - -#include -#include -#include -#include -#include - -#include "libtorrent/size_type.hpp" -#include "libtorrent/config.hpp" -#include "libtorrent/assert.hpp" - -namespace libtorrent -{ - - struct TORRENT_EXPORT type_error: std::runtime_error - { - type_error(const char* error): std::runtime_error(error) {} - }; - - namespace detail - { - template - struct max2 { enum { value = v1>v2?v1:v2 }; }; - - template - struct max3 - { - enum - { - temp = max2::value, - value = temp>v3?temp:v3 - }; - }; - - template - struct max4 - { - enum - { - temp = max3::value, - value = temp>v4?temp:v4 - }; - }; - } - - class entry; - - class TORRENT_EXPORT entry - { - public: - - // the key is always a string. If a generic entry would be allowed - // as a key, sorting would become a problem (e.g. to compare a string - // to a list). The definition doesn't mention such a limit though. - typedef std::map dictionary_type; - typedef std::string string_type; - typedef std::list list_type; - typedef size_type integer_type; - - enum data_type - { - int_t, - string_t, - list_t, - dictionary_t, - undefined_t - }; - - data_type type() const; - - entry(dictionary_type const&); - entry(string_type const&); - entry(list_type const&); - entry(integer_type const&); - - entry(); - entry(data_type t); - entry(entry const& e); - ~entry(); - - bool operator==(entry const& e) const; - - void operator=(entry const&); - void operator=(dictionary_type const&); - void operator=(string_type const&); - void operator=(list_type const&); - void operator=(integer_type const&); - - integer_type& integer(); - const integer_type& integer() const; - string_type& string(); - const string_type& string() const; - list_type& list(); - const list_type& list() const; - dictionary_type& dict(); - const dictionary_type& dict() const; - - void swap(entry& e); - - // these functions requires that the entry - // is a dictionary, otherwise they will throw - entry& operator[](char const* key); - entry& operator[](std::string const& key); -#ifndef BOOST_NO_EXCEPTIONS - const entry& operator[](char const* key) const; - const entry& operator[](std::string const& key) const; -#endif - entry* find_key(char const* key); - entry const* find_key(char const* key) const; - entry* find_key(std::string const& key); - entry const* find_key(std::string const& key) const; - - void print(std::ostream& os, int indent = 0) const; - - protected: - - void construct(data_type t); - void copy(const entry& e); - void destruct(); - - private: - - data_type m_type; - -#if defined(_MSC_VER) && _MSC_VER < 1310 - // workaround for msvc-bug. - // assumes sizeof(map) == sizeof(map) - // and sizeof(list) == sizeof(list) - union - { - char data[ - detail::max4) - , sizeof(std::map) - , sizeof(string_type) - , sizeof(integer_type)>::value]; - integer_type dummy_aligner; - }; -#else - union - { - char data[detail::max4::value]; - integer_type dummy_aligner; - }; -#endif - -#ifdef TORRENT_DEBUG - public: - // in debug mode this is set to false by bdecode - // to indicate that the program has not yet queried - // the type of this entry, and sould not assume - // that it has a certain type. This is asserted in - // the accessor functions. This does not apply if - // exceptions are used. - mutable bool m_type_queried; -#endif - }; - - inline std::ostream& operator<<(std::ostream& os, const entry& e) - { - e.print(os, 0); - return os; - } - - inline entry::data_type entry::type() const - { -#ifdef TORRENT_DEBUG - m_type_queried = true; -#endif - return m_type; - } - - inline entry::~entry() { destruct(); } - - inline void entry::operator=(const entry& e) - { - destruct(); - copy(e); - } - - inline entry::integer_type& entry::integer() - { - if (m_type == undefined_t) construct(int_t); -#ifndef BOOST_NO_EXCEPTIONS - if (m_type != int_t) throw type_error("invalid type requested from entry"); -#elif defined TORRENT_DEBUG - TORRENT_ASSERT(m_type_queried); -#endif - TORRENT_ASSERT(m_type == int_t); - return *reinterpret_cast(data); - } - - inline entry::integer_type const& entry::integer() const - { -#ifndef BOOST_NO_EXCEPTIONS - if (m_type != int_t) throw type_error("invalid type requested from entry"); -#elif defined TORRENT_DEBUG - TORRENT_ASSERT(m_type_queried); -#endif - TORRENT_ASSERT(m_type == int_t); - return *reinterpret_cast(data); - } - - inline entry::string_type& entry::string() - { - if (m_type == undefined_t) construct(string_t); -#ifndef BOOST_NO_EXCEPTIONS - if (m_type != string_t) throw type_error("invalid type requested from entry"); -#elif defined TORRENT_DEBUG - TORRENT_ASSERT(m_type_queried); -#endif - TORRENT_ASSERT(m_type == string_t); - return *reinterpret_cast(data); - } - - inline entry::string_type const& entry::string() const - { -#ifndef BOOST_NO_EXCEPTIONS - if (m_type != string_t) throw type_error("invalid type requested from entry"); -#elif defined TORRENT_DEBUG - TORRENT_ASSERT(m_type_queried); -#endif - TORRENT_ASSERT(m_type == string_t); - return *reinterpret_cast(data); - } - - inline entry::list_type& entry::list() - { - if (m_type == undefined_t) construct(list_t); -#ifndef BOOST_NO_EXCEPTIONS - if (m_type != list_t) throw type_error("invalid type requested from entry"); -#elif defined TORRENT_DEBUG - TORRENT_ASSERT(m_type_queried); -#endif - TORRENT_ASSERT(m_type == list_t); - return *reinterpret_cast(data); - } - - inline entry::list_type const& entry::list() const - { -#ifndef BOOST_NO_EXCEPTIONS - if (m_type != list_t) throw type_error("invalid type requested from entry"); -#elif defined TORRENT_DEBUG - TORRENT_ASSERT(m_type_queried); -#endif - TORRENT_ASSERT(m_type == list_t); - return *reinterpret_cast(data); - } - - inline entry::dictionary_type& entry::dict() - { - if (m_type == undefined_t) construct(dictionary_t); -#ifndef BOOST_NO_EXCEPTIONS - if (m_type != dictionary_t) throw type_error("invalid type requested from entry"); -#elif defined TORRENT_DEBUG - TORRENT_ASSERT(m_type_queried); -#endif - TORRENT_ASSERT(m_type == dictionary_t); - return *reinterpret_cast(data); - } - - inline entry::dictionary_type const& entry::dict() const - { -#ifndef BOOST_NO_EXCEPTIONS - if (m_type != dictionary_t) throw type_error("invalid type requested from entry"); -#elif defined TORRENT_DEBUG - TORRENT_ASSERT(m_type_queried); -#endif - TORRENT_ASSERT(m_type == dictionary_t); - return *reinterpret_cast(data); - } - -} - -#endif // TORRENT_ENTRY_HPP_INCLUDED - diff --git a/libtorrent/include/libtorrent/enum_net.hpp b/libtorrent/include/libtorrent/enum_net.hpp deleted file mode 100644 index 643c4c0c0..000000000 --- a/libtorrent/include/libtorrent/enum_net.hpp +++ /dev/null @@ -1,78 +0,0 @@ -/* - -Copyright (c) 2007, Arvid Norberg -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions -are met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in - the documentation and/or other materials provided with the distribution. - * Neither the name of the author nor the names of its - contributors may be used to endorse or promote products derived - from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -POSSIBILITY OF SUCH DAMAGE. - -*/ - -#ifndef TORRENT_ENUM_NET_HPP_INCLUDED -#define TORRENT_ENUM_NET_HPP_INCLUDED - -#include "libtorrent/config.hpp" -#include "libtorrent/socket.hpp" - -namespace libtorrent -{ - - struct ip_interface - { - address interface_address; - address netmask; - char name[64]; - }; - - struct ip_route - { - address destination; - address netmask; - address gateway; - char name[64]; - }; - - // returns a list of the configured IP interfaces - // on the machine - TORRENT_EXPORT std::vector enum_net_interfaces(io_service& ios - , error_code& ec); - - TORRENT_EXPORT std::vector enum_routes(io_service& ios, error_code& ec); - - // returns true if the specified address is on the same - // local network as the specified interface - TORRENT_EXPORT bool in_subnet(address const& addr, ip_interface const& iface); - - // returns true if the specified address is on the same - // local network as us - TORRENT_EXPORT bool in_local_network(io_service& ios, address const& addr - , error_code& ec); - - TORRENT_EXPORT address get_default_gateway(io_service& ios - , error_code& ec); -} - -#endif - diff --git a/libtorrent/include/libtorrent/error_code.hpp b/libtorrent/include/libtorrent/error_code.hpp deleted file mode 100644 index 36c8da342..000000000 --- a/libtorrent/include/libtorrent/error_code.hpp +++ /dev/null @@ -1,85 +0,0 @@ -/* - -Copyright (c) 2008, Arvid Norberg -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions -are met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in - the documentation and/or other materials provided with the distribution. - * Neither the name of the author nor the names of its - contributors may be used to endorse or promote products derived - from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -POSSIBILITY OF SUCH DAMAGE. - -*/ - -#ifndef TORRENT_ERROR_CODE_HPP_INCLUDED -#define TORRENT_ERROR_CODE_HPP_INCLUDED - -#include - -#if BOOST_VERSION < 103500 -#include -#else -#include -#endif - -namespace libtorrent -{ - - namespace errors - { - enum error_code_enum - { - no_error = 0, - file_collision - }; - } - -#if BOOST_VERSION < 103500 - typedef asio::error_code error_code; - inline asio::error::error_category get_posix_category() { return asio::error::system_category; } - inline asio::error::error_category get_system_category() { return asio::error::system_category; } -#else - - struct libtorrent_error_category : boost::system::error_category - { - virtual const char* name() const; - virtual std::string message(int ev) const; - virtual boost::system::error_condition default_error_condition(int ev) const - { return boost::system::error_condition(ev, *this); } - }; - - extern libtorrent_error_category libtorrent_category; - - using boost::system::error_code; - inline boost::system::error_category const& get_system_category() - { return boost::system::get_system_category(); } - inline boost::system::error_category const& get_posix_category() -#if BOOST_VERSION < 103600 - { return boost::system::get_posix_category(); } -#else - { return boost::system::get_generic_category(); } -#endif -#endif -} - -#endif - diff --git a/libtorrent/include/libtorrent/escape_string.hpp b/libtorrent/include/libtorrent/escape_string.hpp deleted file mode 100644 index f76939779..000000000 --- a/libtorrent/include/libtorrent/escape_string.hpp +++ /dev/null @@ -1,65 +0,0 @@ -/* - -Copyright (c) 2003, Arvid Norberg -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions -are met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in - the documentation and/or other materials provided with the distribution. - * Neither the name of the author nor the names of its - contributors may be used to endorse or promote products derived - from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -POSSIBILITY OF SUCH DAMAGE. - -*/ - -#ifndef TORRENT_ESCAPE_STRING_HPP_INCLUDED -#define TORRENT_ESCAPE_STRING_HPP_INCLUDED - -#include -#include -#include -#include -#include "libtorrent/config.hpp" -#include "libtorrent/size_type.hpp" - -namespace libtorrent -{ - boost::array::digits10> TORRENT_EXPORT to_string(size_type n); - bool TORRENT_EXPORT is_digit(char c); - bool TORRENT_EXPORT isprint(char c); - - std::string TORRENT_EXPORT unescape_string(std::string const& s); - std::string TORRENT_EXPORT escape_string(const char* str, int len); - std::string TORRENT_EXPORT escape_path(const char* str, int len); - - // encodes a string using the base64 scheme - TORRENT_EXPORT std::string base64encode(std::string const& s); - // encodes a string using the base32 scheme - TORRENT_EXPORT std::string base32encode(std::string const& s); - TORRENT_EXPORT std::string base32decode(std::string const& s); - - TORRENT_EXPORT boost::optional url_has_argument( - std::string const& url, std::string argument); - - TORRENT_EXPORT std::string to_hex(std::string const& s); -} - -#endif // TORRENT_ESCAPE_STRING_HPP_INCLUDED diff --git a/libtorrent/include/libtorrent/extensions.hpp b/libtorrent/include/libtorrent/extensions.hpp deleted file mode 100644 index b06a0fc74..000000000 --- a/libtorrent/include/libtorrent/extensions.hpp +++ /dev/null @@ -1,194 +0,0 @@ -/* - -Copyright (c) 2006, Arvid Norberg -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions -are met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in - the documentation and/or other materials provided with the distribution. - * Neither the name of the author nor the names of its - contributors may be used to endorse or promote products derived - from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -POSSIBILITY OF SUCH DAMAGE. - -*/ - -#ifndef TORRENT_EXTENSIONS_HPP_INCLUDED -#define TORRENT_EXTENSIONS_HPP_INCLUDED - -#ifndef TORRENT_DISABLE_EXTENSIONS - -#ifdef _MSC_VER -#pragma warning(push, 1) -#endif - -#include - -#ifdef _MSC_VER -#pragma warning(pop) -#endif - -#include -#include "libtorrent/config.hpp" -#include "libtorrent/buffer.hpp" - -namespace libtorrent -{ - struct peer_plugin; - class bt_peer_connection; - struct peer_request; - class peer_connection; - class entry; - struct lazy_entry; - struct disk_buffer_holder; - struct bitfield; - - struct TORRENT_EXPORT torrent_plugin - { - virtual ~torrent_plugin() {} - // throwing an exception closes the connection - // returning a 0 pointer is valid and will not add - // the peer_plugin to the peer_connection - virtual boost::shared_ptr new_connection(peer_connection*) - { return boost::shared_ptr(); } - - virtual void on_piece_pass(int index) {} - virtual void on_piece_failed(int index) {} - - // called aproximately once every second - virtual void tick() {} - - // if true is returned, it means the handler handled the event, - // and no other plugins will have their handlers called, and the - // default behavior will be skipped - virtual bool on_pause() { return false; } - virtual bool on_resume() { return false;} - - // this is called when the initial checking of - // files is completed. - virtual void on_files_checked() {} - }; - - struct TORRENT_EXPORT peer_plugin - { - virtual ~peer_plugin() {} - - // can add entries to the extension handshake - // this is not called for web seeds - virtual void add_handshake(entry&) {} - - // throwing an exception from any of the handlers (except add_handshake) - // closes the connection - - // this is called when the initial BT handshake is received. Returning false - // means that the other end doesn't support this extension and will remove - // it from the list of plugins. - // this is not called for web seeds - virtual bool on_handshake(char const* reserved_bits) { return true; } - - // called when the extension handshake from the other end is received - // if this returns false, it means that this extension isn't - // supported by this peer. It will result in this peer_plugin - // being removed from the peer_connection and destructed. - // this is not called for web seeds - virtual bool on_extension_handshake(lazy_entry const& h) { return true; } - - // returning true from any of the message handlers - // indicates that the plugin has handeled the message. - // it will break the plugin chain traversing and not let - // anyone else handle the message, including the default - // handler. - - virtual bool on_choke() - { return false; } - - virtual bool on_unchoke() - { return false; } - - virtual bool on_interested() - { return false; } - - virtual bool on_not_interested() - { return false; } - - virtual bool on_have(int index) - { return false; } - - virtual bool on_bitfield(bitfield const& bitfield) - { return false; } - - virtual bool on_have_all() - { return false; } - - virtual bool on_have_none() - { return false; } - - virtual bool on_allowed_fast(int index) - { return false; } - - virtual bool on_request(peer_request const& req) - { return false; } - - virtual bool on_piece(peer_request const& piece, disk_buffer_holder& data) - { return false; } - - virtual bool on_cancel(peer_request const& req) - { return false; } - - virtual bool on_reject(peer_request const& req) - { return false; } - - virtual bool on_suggest(int index) - { return false; } - - // called when an extended message is received. If returning true, - // the message is not processed by any other plugin and if false - // is returned the next plugin in the chain will receive it to - // be able to handle it - // this is not called for web seeds - virtual bool on_extended(int length - , int msg, buffer::const_interval body) - { return false; } - - // this is not called for web seeds - virtual bool on_unknown_message(int length, int msg - , buffer::const_interval body) - { return false; } - - // called when a piece that this peer participated in either - // fails or passes the hash_check - virtual void on_piece_pass(int index) {} - virtual void on_piece_failed(int index) {} - - // called aproximately once every second - virtual void tick() {} - - // called each time a request message is to be sent. If true - // is returned, the original request message won't be sent and - // no other plugin will have this function called. - virtual bool write_request(peer_request const& r) { return false; } - }; - -} - -#endif - -#endif // TORRENT_EXTENSIONS_HPP_INCLUDED - diff --git a/libtorrent/include/libtorrent/extensions/logger.hpp b/libtorrent/include/libtorrent/extensions/logger.hpp deleted file mode 100644 index 42e08fcf6..000000000 --- a/libtorrent/include/libtorrent/extensions/logger.hpp +++ /dev/null @@ -1,54 +0,0 @@ -/* - -Copyright (c) 2006, Arvid Norberg -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions -are met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in - the documentation and/or other materials provided with the distribution. - * Neither the name of the author nor the names of its - contributors may be used to endorse or promote products derived - from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -POSSIBILITY OF SUCH DAMAGE. - -*/ - -#ifndef TORRENT_LOGGER_HPP_INCLUDED -#define TORRENT_LOGGER_HPP_INCLUDED - -#ifdef _MSC_VER -#pragma warning(push, 1) -#endif - -#include - -#ifdef _MSC_VER -#pragma warning(pop) -#endif - -namespace libtorrent -{ - struct torrent_plugin; - class torrent; - boost::shared_ptr create_logger_plugin(torrent*); -} - -#endif // TORRENT_LOGGER_HPP_INCLUDED - diff --git a/libtorrent/include/libtorrent/extensions/metadata_transfer.hpp b/libtorrent/include/libtorrent/extensions/metadata_transfer.hpp deleted file mode 100644 index c42136d70..000000000 --- a/libtorrent/include/libtorrent/extensions/metadata_transfer.hpp +++ /dev/null @@ -1,55 +0,0 @@ -/* - -Copyright (c) 2006, Arvid Norberg -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions -are met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in - the documentation and/or other materials provided with the distribution. - * Neither the name of the author nor the names of its - contributors may be used to endorse or promote products derived - from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -POSSIBILITY OF SUCH DAMAGE. - -*/ - -#ifndef TORRENT_METADATA_TRANSFER_HPP_INCLUDED -#define TORRENT_METADATA_TRANSFER_HPP_INCLUDED - -#ifdef _MSC_VER -#pragma warning(push, 1) -#endif - -#include -#include "libtorrent/config.hpp" - -#ifdef _MSC_VER -#pragma warning(pop) -#endif - -namespace libtorrent -{ - struct torrent_plugin; - class torrent; - TORRENT_EXPORT boost::shared_ptr create_metadata_plugin(torrent*, void*); -} - -#endif // TORRENT_METADATA_TRANSFER_HPP_INCLUDED - diff --git a/libtorrent/include/libtorrent/extensions/smart_ban.hpp b/libtorrent/include/libtorrent/extensions/smart_ban.hpp deleted file mode 100644 index 5d7d30c82..000000000 --- a/libtorrent/include/libtorrent/extensions/smart_ban.hpp +++ /dev/null @@ -1,55 +0,0 @@ -/* - -Copyright (c) 2007, Arvid Norberg -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions -are met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in - the documentation and/or other materials provided with the distribution. - * Neither the name of the author nor the names of its - contributors may be used to endorse or promote products derived - from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -POSSIBILITY OF SUCH DAMAGE. - -*/ - -#ifndef TORRENT_SMART_BAN_HPP_INCLUDED -#define TORRENT_SMART_BAN_HPP_INCLUDED - -#ifdef _MSC_VER -#pragma warning(push, 1) -#endif - -#include -#include "libtorrent/config.hpp" - -#ifdef _MSC_VER -#pragma warning(pop) -#endif - -namespace libtorrent -{ - struct torrent_plugin; - class torrent; - TORRENT_EXPORT boost::shared_ptr create_smart_ban_plugin(torrent*, void*); -} - -#endif // TORRENT_SMART_BAN_HPP_INCLUDED - diff --git a/libtorrent/include/libtorrent/extensions/ut_metadata.hpp b/libtorrent/include/libtorrent/extensions/ut_metadata.hpp deleted file mode 100644 index 91437b17c..000000000 --- a/libtorrent/include/libtorrent/extensions/ut_metadata.hpp +++ /dev/null @@ -1,55 +0,0 @@ -/* - -Copyright (c) 2007, Arvid Norberg -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions -are met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in - the documentation and/or other materials provided with the distribution. - * Neither the name of the author nor the names of its - contributors may be used to endorse or promote products derived - from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -POSSIBILITY OF SUCH DAMAGE. - -*/ - -#ifndef TORRENT_UT_METADATA_HPP_INCLUDED -#define TORRENT_UT_METADATA_HPP_INCLUDED - -#ifdef _MSC_VER -#pragma warning(push, 1) -#endif - -#include -#include "libtorrent/config.hpp" - -#ifdef _MSC_VER -#pragma warning(pop) -#endif - -namespace libtorrent -{ - struct torrent_plugin; - class torrent; - TORRENT_EXPORT boost::shared_ptr create_ut_metadata_plugin(torrent*, void*); -} - -#endif // TORRENT_UT_METADATA_HPP_INCLUDED - diff --git a/libtorrent/include/libtorrent/extensions/ut_pex.hpp b/libtorrent/include/libtorrent/extensions/ut_pex.hpp deleted file mode 100644 index ebf6aa834..000000000 --- a/libtorrent/include/libtorrent/extensions/ut_pex.hpp +++ /dev/null @@ -1,54 +0,0 @@ -/* - -Copyright (c) 2006, MassaRoddel -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions -are met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in - the documentation and/or other materials provided with the distribution. - * Neither the name of the author nor the names of its - contributors may be used to endorse or promote products derived - from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -POSSIBILITY OF SUCH DAMAGE. - -*/ - -#ifndef TORRENT_UT_PEX_EXTENSION_HPP_INCLUDED -#define TORRENT_UT_PEX_EXTENSION_HPP_INCLUDED - -#ifdef _MSC_VER -#pragma warning(push, 1) -#endif - -#include -#include "libtorrent/config.hpp" - -#ifdef _MSC_VER -#pragma warning(pop) -#endif - -namespace libtorrent -{ - struct torrent_plugin; - class torrent; - TORRENT_EXPORT boost::shared_ptr create_ut_pex_plugin(torrent*, void*); -} - -#endif // TORRENT_UT_PEX_EXTENSION_HPP_INCLUDED diff --git a/libtorrent/include/libtorrent/file.hpp b/libtorrent/include/libtorrent/file.hpp deleted file mode 100644 index 568f7378c..000000000 --- a/libtorrent/include/libtorrent/file.hpp +++ /dev/null @@ -1,136 +0,0 @@ -/* - -Copyright (c) 2003, Arvid Norberg -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions -are met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in - the documentation and/or other materials provided with the distribution. - * Neither the name of the author nor the names of its - contributors may be used to endorse or promote products derived - from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -POSSIBILITY OF SUCH DAMAGE. - -*/ - -#ifndef TORRENT_FILE_HPP_INCLUDED -#define TORRENT_FILE_HPP_INCLUDED - -#include -#include -#include - -#ifdef _MSC_VER -#pragma warning(push, 1) -#endif - -#include -#include - -#ifdef _MSC_VER -#pragma warning(pop) -#endif - -#include "libtorrent/error_code.hpp" -#include "libtorrent/size_type.hpp" -#include "libtorrent/config.hpp" - -namespace libtorrent -{ - namespace fs = boost::filesystem; - - class TORRENT_EXPORT file: public boost::noncopyable - { - public: - - class seek_mode - { - friend class file; - private: - seek_mode(int v): m_val(v) {} - int m_val; - }; - - static const seek_mode begin; - static const seek_mode end; - - class open_mode - { - friend class file; - public: - - open_mode(): m_mask(0) {} - open_mode operator|(open_mode m) const - { return open_mode(m.m_mask | m_mask); } - - open_mode operator&(open_mode m) const - { return open_mode(m.m_mask & m_mask); } - - open_mode operator|=(open_mode m) - { - m_mask |= m.m_mask; - return *this; - } - - bool operator==(open_mode m) const { return m_mask == m.m_mask; } - bool operator!=(open_mode m) const { return m_mask != m.m_mask; } - operator bool() const { return m_mask != 0; } - - private: - - open_mode(int val): m_mask(val) {} - int m_mask; - }; - - static const open_mode in; - static const open_mode out; - - file(); - file(fs::path const& p, open_mode m, error_code& ec); - ~file(); - - bool open(fs::path const& p, open_mode m, error_code& ec); - bool is_open() const; - void close(); - bool set_size(size_type size, error_code& ec); - - size_type write(const char*, size_type num_bytes, error_code& ec); - size_type read(char*, size_type num_bytes, error_code& ec); - - size_type seek(size_type pos, seek_mode m, error_code& ec); - size_type tell(error_code& ec); - - private: - -#ifdef TORRENT_WINDOWS - HANDLE m_file_handle; -#else - int m_fd; -#endif -#ifdef TORRENT_DEBUG - open_mode m_open_mode; -#endif - - }; - -} - -#endif // TORRENT_FILE_HPP_INCLUDED - diff --git a/libtorrent/include/libtorrent/file_pool.hpp b/libtorrent/include/libtorrent/file_pool.hpp deleted file mode 100644 index cbabfe807..000000000 --- a/libtorrent/include/libtorrent/file_pool.hpp +++ /dev/null @@ -1,103 +0,0 @@ -/* - -Copyright (c) 2006, Arvid Norberg -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions -are met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in - the documentation and/or other materials provided with the distribution. - * Neither the name of the author nor the names of its - contributors may be used to endorse or promote products derived - from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -POSSIBILITY OF SUCH DAMAGE. - -*/ - -#ifndef TORRENT_FILE_POOL_HPP -#define TORRENT_FILE_POOL_HPP - -#ifdef _MSC_VER -#pragma warning(push, 1) -#endif - -#include -#include -#include -#include -#include -#include - -#ifdef _MSC_VER -#pragma warning(pop) -#endif - -#include "libtorrent/file.hpp" -#include "libtorrent/time.hpp" - -namespace libtorrent -{ - - using boost::multi_index::multi_index_container; - using boost::multi_index::ordered_non_unique; - using boost::multi_index::ordered_unique; - using boost::multi_index::indexed_by; - using boost::multi_index::member; - namespace fs = boost::filesystem; - - struct TORRENT_EXPORT file_pool : boost::noncopyable - { - file_pool(int size = 40): m_size(size) {} - - boost::shared_ptr open_file(void* st, fs::path const& p - , file::open_mode m, error_code& ec); - void release(void* st); - void release(fs::path const& p); - void resize(int size); - - private: - int m_size; - - struct lru_file_entry - { - lru_file_entry(): last_use(time_now()) {} - mutable boost::shared_ptr file_ptr; - fs::path file_path; - void* key; - ptime last_use; - file::open_mode mode; - }; - - typedef multi_index_container< - lru_file_entry, indexed_by< - ordered_unique > - , ordered_non_unique > - , ordered_non_unique > - > - > file_set; - - file_set m_files; - boost::mutex m_mutex; - }; -} - -#endif diff --git a/libtorrent/include/libtorrent/file_storage.hpp b/libtorrent/include/libtorrent/file_storage.hpp deleted file mode 100644 index 47fcb92eb..000000000 --- a/libtorrent/include/libtorrent/file_storage.hpp +++ /dev/null @@ -1,147 +0,0 @@ -/* - -Copyright (c) 2003-2008, Arvid Norberg -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions -are met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in - the documentation and/or other materials provided with the distribution. - * Neither the name of the author nor the names of its - contributors may be used to endorse or promote products derived - from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -POSSIBILITY OF SUCH DAMAGE. - -*/ - -#ifndef TORRENT_FILE_STORAGE_HPP_INCLUDED -#define TORRENT_FILE_STORAGE_HPP_INCLUDED - -#include -#include - -#ifdef _MSC_VER -#pragma warning(push, 1) -#endif - -#include - -#ifdef _MSC_VER -#pragma warning(pop) -#endif - -#include "libtorrent/size_type.hpp" -#include "libtorrent/assert.hpp" -#include "libtorrent/peer_request.hpp" - -namespace libtorrent -{ - namespace fs = boost::filesystem; - - struct TORRENT_EXPORT file_entry - { - file_entry(): offset(0), size(0), file_base(0) {} - - fs::path path; - size_type offset; // the offset of this file inside the torrent - size_type size; // the size of this file - // the offset in the file where the storage starts. - // This is always 0 unless parts of the torrent is - // compressed into a single file, such as a so-called part file. - size_type file_base; - }; - - struct TORRENT_EXPORT file_slice - { - int file_index; - size_type offset; - size_type size; - }; - - class TORRENT_EXPORT file_storage - { - friend class torrent_info; - public: - file_storage(); - ~file_storage() {} - - bool is_valid() const { return m_piece_length > 0; } - - void add_file(file_entry const& e); - void add_file(fs::path const& p, size_type size); - void rename_file(int index, std::string const& new_filename); - - std::vector map_block(int piece, size_type offset - , int size) const; - peer_request map_file(int file, size_type offset, int size) const; - - typedef std::vector::const_iterator iterator; - typedef std::vector::const_reverse_iterator reverse_iterator; - - iterator file_at_offset(size_type offset) const; - iterator begin() const { return m_files.begin(); } - iterator end() const { return m_files.end(); } - reverse_iterator rbegin() const { return m_files.rbegin(); } - reverse_iterator rend() const { return m_files.rend(); } - int num_files() const - { return int(m_files.size()); } - - file_entry const& at(int index) const - { - TORRENT_ASSERT(index >= 0 && index < int(m_files.size())); - return m_files[index]; - } - - size_type total_size() const { TORRENT_ASSERT(m_piece_length > 0); return m_total_size; } - void set_num_pieces(int n) { m_num_pieces = n; } - int num_pieces() const { TORRENT_ASSERT(m_piece_length > 0); return m_num_pieces; } - void set_piece_length(int l) { m_piece_length = l; } - int piece_length() const { TORRENT_ASSERT(m_piece_length > 0); return m_piece_length; } - int piece_size(int index) const; - - void set_name(std::string const& n) { m_name = n; } - const std::string& name() const { TORRENT_ASSERT(m_piece_length > 0); return m_name; } - - void swap(file_storage& ti) - { - using std::swap; - swap(ti.m_piece_length, m_piece_length); - swap(ti.m_files, m_files); - swap(ti.m_total_size, m_total_size); - swap(ti.m_num_pieces, m_num_pieces); - swap(ti.m_name, m_name); - } - - private: - int m_piece_length; - - // the list of files that this torrent consists of - std::vector m_files; - - // the sum of all filesizes - size_type m_total_size; - - // the number of pieces in the torrent - int m_num_pieces; - std::string m_name; - }; -} - -#endif // TORRENT_FILE_STORAGE_HPP_INCLUDED - diff --git a/libtorrent/include/libtorrent/fingerprint.hpp b/libtorrent/include/libtorrent/fingerprint.hpp deleted file mode 100644 index 237fef065..000000000 --- a/libtorrent/include/libtorrent/fingerprint.hpp +++ /dev/null @@ -1,95 +0,0 @@ -/* - -Copyright (c) 2003, Arvid Norberg -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions -are met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in - the documentation and/or other materials provided with the distribution. - * Neither the name of the author nor the names of its - contributors may be used to endorse or promote products derived - from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -POSSIBILITY OF SUCH DAMAGE. - -*/ - -#ifndef TORRENT_FINGERPRINT_HPP_INCLUDED -#define TORRENT_FINGERPRINT_HPP_INCLUDED - -#include -#include - -#include "libtorrent/peer_id.hpp" -#include "libtorrent/assert.hpp" - -namespace libtorrent -{ - - struct fingerprint - { - fingerprint(const char* id_string, int major, int minor, int revision, int tag) - : major_version(major) - , minor_version(minor) - , revision_version(revision) - , tag_version(tag) - { - TORRENT_ASSERT(id_string); - TORRENT_ASSERT(major >= 0); - TORRENT_ASSERT(minor >= 0); - TORRENT_ASSERT(revision >= 0); - TORRENT_ASSERT(tag >= 0); - TORRENT_ASSERT(std::strlen(id_string) == 2); - name[0] = id_string[0]; - name[1] = id_string[1]; - } - - std::string to_string() const - { - std::stringstream s; - s << "-" << name[0] << name[1] - << version_to_char(major_version) - << version_to_char(minor_version) - << version_to_char(revision_version) - << version_to_char(tag_version) << "-"; - return s.str(); - } - - char name[2]; - int major_version; - int minor_version; - int revision_version; - int tag_version; - - private: - - char version_to_char(int v) const - { - if (v >= 0 && v < 10) return '0' + v; - else if (v >= 10) return 'A' + (v - 10); - TORRENT_ASSERT(false); - return '0'; - } - - }; - -} - -#endif // TORRENT_FINGERPRINT_HPP_INCLUDED - diff --git a/libtorrent/include/libtorrent/gzip.hpp b/libtorrent/include/libtorrent/gzip.hpp deleted file mode 100644 index 0528b58f2..000000000 --- a/libtorrent/include/libtorrent/gzip.hpp +++ /dev/null @@ -1,43 +0,0 @@ -/* - -Copyright (c) 2007, Arvid Norberg -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions -are met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in - the documentation and/or other materials provided with the distribution. - * Neither the name of the author nor the names of its - contributors may be used to endorse or promote products derived - from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -POSSIBILITY OF SUCH DAMAGE. - -*/ - -namespace libtorrent -{ - - TORRENT_EXPORT bool inflate_gzip( - char const* in, int size - , std::vector& buffer - , int maximum_size - , std::string& error); - -} - diff --git a/libtorrent/include/libtorrent/hasher.hpp b/libtorrent/include/libtorrent/hasher.hpp deleted file mode 100644 index f1dba7d1a..000000000 --- a/libtorrent/include/libtorrent/hasher.hpp +++ /dev/null @@ -1,122 +0,0 @@ -/* - -Copyright (c) 2003, Arvid Norberg -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions -are met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in - the documentation and/or other materials provided with the distribution. - * Neither the name of the author nor the names of its - contributors may be used to endorse or promote products derived - from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -POSSIBILITY OF SUCH DAMAGE. - -*/ - -#ifndef TORRENT_HASHER_HPP_INCLUDED -#define TORRENT_HASHER_HPP_INCLUDED - -#include - -#include "libtorrent/peer_id.hpp" -#include "libtorrent/config.hpp" -#include "libtorrent/assert.hpp" -#include "zlib.h" - -#ifdef TORRENT_USE_OPENSSL -extern "C" -{ -#include -} -#else -// from sha1.cpp -struct TORRENT_EXPORT SHA_CTX -{ - boost::uint32_t state[5]; - boost::uint32_t count[2]; - boost::uint8_t buffer[64]; -}; - -TORRENT_EXPORT void SHA1_Init(SHA_CTX* context); -TORRENT_EXPORT void SHA1_Update(SHA_CTX* context, boost::uint8_t const* data, boost::uint32_t len); -TORRENT_EXPORT void SHA1_Final(boost::uint8_t* digest, SHA_CTX* context); - -#endif - -namespace libtorrent -{ - - class adler32_crc - { - public: - adler32_crc(): m_adler(adler32(0, 0, 0)) {} - - void update(const char* data, int len) - { - TORRENT_ASSERT(data != 0); - TORRENT_ASSERT(len > 0); - m_adler = adler32(m_adler, (const Bytef*)data, len); - } - unsigned long final() const { return m_adler; } - void reset() { m_adler = adler32(0, 0, 0); } - - private: - - unsigned long m_adler; - - }; - - class hasher - { - public: - - hasher() { SHA1_Init(&m_context); } - hasher(const char* data, int len) - { - SHA1_Init(&m_context); - TORRENT_ASSERT(data != 0); - TORRENT_ASSERT(len > 0); - SHA1_Update(&m_context, reinterpret_cast(data), len); - } - void update(const char* data, int len) - { - TORRENT_ASSERT(data != 0); - TORRENT_ASSERT(len > 0); - SHA1_Update(&m_context, reinterpret_cast(data), len); - } - - sha1_hash final() - { - sha1_hash digest; - SHA1_Final(digest.begin(), &m_context); - return digest; - } - - void reset() { SHA1_Init(&m_context); } - - private: - - SHA_CTX m_context; - - }; -} - -#endif // TORRENT_HASHER_HPP_INCLUDED - diff --git a/libtorrent/include/libtorrent/http_connection.hpp b/libtorrent/include/libtorrent/http_connection.hpp deleted file mode 100644 index b13b457fa..000000000 --- a/libtorrent/include/libtorrent/http_connection.hpp +++ /dev/null @@ -1,209 +0,0 @@ -/* - -Copyright (c) 2007, Arvid Norberg -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions -are met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in - the documentation and/or other materials provided with the distribution. - * Neither the name of the author nor the names of its - contributors may be used to endorse or promote products derived - from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -POSSIBILITY OF SUCH DAMAGE. - -*/ - -#ifndef TORRENT_HTTP_CONNECTION -#define TORRENT_HTTP_CONNECTION - -#include -#include -#include -#include -#include -#include -#include -#include - -#include "libtorrent/socket.hpp" -#include "libtorrent/http_parser.hpp" -#include "libtorrent/time.hpp" -#include "libtorrent/assert.hpp" -#include "libtorrent/socket_type.hpp" -#include "libtorrent/session_settings.hpp" - -#ifdef TORRENT_USE_OPENSSL -#include "libtorrent/ssl_stream.hpp" -#include "libtorrent/variant_stream.hpp" -#endif - -namespace libtorrent -{ - -struct http_connection; -class connection_queue; - -typedef boost::function http_handler; - -typedef boost::function http_connect_handler; - -// TODO: add bind interface - -// when bottled, the last two arguments to the handler -// will always be 0 -struct http_connection : boost::enable_shared_from_this, boost::noncopyable -{ - http_connection(io_service& ios, connection_queue& cc - , http_handler const& handler, bool bottled = true - , http_connect_handler const& ch = http_connect_handler()) - : m_sock(ios) - , m_read_pos(0) - , m_resolver(ios) - , m_handler(handler) - , m_connect_handler(ch) - , m_timer(ios) - , m_last_receive(time_now()) - , m_bottled(bottled) - , m_called(false) - , m_rate_limit(0) - , m_download_quota(0) - , m_limiter_timer_active(false) - , m_limiter_timer(ios) - , m_redirects(5) - , m_connection_ticket(-1) - , m_cc(cc) - , m_ssl(false) - , m_priority(0) - , m_abort(false) - { - TORRENT_ASSERT(!m_handler.empty()); - } - - void rate_limit(int limit); - - int rate_limit() const - { return m_rate_limit; } - - std::string sendbuffer; - - void get(std::string const& url, time_duration timeout = seconds(30) - , int prio = 0, proxy_settings const* ps = 0, int handle_redirects = 5 - , std::string const& user_agent = "", address const& bind_addr = address_v4::any()); - - void start(std::string const& hostname, std::string const& port - , time_duration timeout, int prio = 0, proxy_settings const* ps = 0 - , bool ssl = false, int handle_redirect = 5 - , address const& bind_addr = address_v4::any()); - - void close(); - -#ifdef TORRENT_USE_OPENSSL - variant_stream > const& socket() const { return m_sock; } -#else - socket_type const& socket() const { return m_sock; } -#endif - -private: - - void on_resolve(error_code const& e - , tcp::resolver::iterator i); - void queue_connect(); - void connect(int ticket, tcp::endpoint target_address); - void on_connect_timeout(); - void on_connect(error_code const& e); - void on_write(error_code const& e); - void on_read(error_code const& e, std::size_t bytes_transferred); - static void on_timeout(boost::weak_ptr p - , error_code const& e); - void on_assign_bandwidth(error_code const& e); - - void callback(error_code const& e, char const* data = 0, int size = 0); - - std::vector m_recvbuffer; -#ifdef TORRENT_USE_OPENSSL - variant_stream > m_sock; -#else - socket_type m_sock; -#endif - int m_read_pos; - tcp::resolver m_resolver; - http_parser m_parser; - http_handler m_handler; - http_connect_handler m_connect_handler; - deadline_timer m_timer; - time_duration m_timeout; - ptime m_last_receive; - // bottled means that the handler is called once, when - // everything is received (and buffered in memory). - // non bottled means that once the headers have been - // received, data is streamed to the handler - bool m_bottled; - // set to true the first time the handler is called - bool m_called; - std::string m_hostname; - std::string m_port; - std::string m_url; - - std::list m_endpoints; - - // the current download limit, in bytes per second - // 0 is unlimited. - int m_rate_limit; - - // the number of bytes we are allowed to receive - int m_download_quota; - - // only hand out new quota 4 times a second if the - // quota is 0. If it isn't 0 wait for it to reach - // 0 and continue to hand out quota at that time. - bool m_limiter_timer_active; - - // the timer fires every 250 millisecond as long - // as all the quota was used. - deadline_timer m_limiter_timer; - - // the number of redirects to follow (in sequence) - int m_redirects; - - int m_connection_ticket; - connection_queue& m_cc; - - // specifies whether or not the connection is - // configured to use a proxy - proxy_settings m_proxy; - - // true if the connection is using ssl - bool m_ssl; - - // the address to bind to. address_v4::any() - // means do not bind - address m_bind_addr; - - // the priority we have in the connection queue. - // 0 is normal, 1 is high - int m_priority; - - bool m_abort; -}; - -} - -#endif diff --git a/libtorrent/include/libtorrent/http_parser.hpp b/libtorrent/include/libtorrent/http_parser.hpp deleted file mode 100644 index 7d308ca36..000000000 --- a/libtorrent/include/libtorrent/http_parser.hpp +++ /dev/null @@ -1,111 +0,0 @@ -/* - -Copyright (c) 2008, Arvid Norberg -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions -are met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in - the documentation and/or other materials provided with the distribution. - * Neither the name of the author nor the names of its - contributors may be used to endorse or promote products derived - from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -POSSIBILITY OF SUCH DAMAGE. - -*/ - -#ifndef TORRENT_HTTP_PARSER_HPP_INCLUDED -#define TORRENT_HTTP_PARSER_HPP_INCLUDED - -#include -#include -#include - -#ifdef _MSC_VER -#pragma warning(push, 1) -#endif - -#include -#include -#include - -#ifdef _MSC_VER -#pragma warning(pop) -#endif - -#include "libtorrent/config.hpp" -#include "libtorrent/buffer.hpp" -#include "libtorrent/size_type.hpp" - -namespace libtorrent -{ - - class http_parser - { - public: - http_parser(); - std::string const& header(char const* key) const - { - static std::string empty; - std::map::const_iterator i - = m_header.find(key); - if (i == m_header.end()) return empty; - return i->second; - } - - std::string const& protocol() const { return m_protocol; } - int status_code() const { return m_status_code; } - std::string const& method() const { return m_method; } - std::string const& path() const { return m_path; } - std::string const& message() const { return m_server_message; } - buffer::const_interval get_body() const; - bool header_finished() const { return m_state == read_body; } - bool finished() const { return m_finished; } - boost::tuple incoming(buffer::const_interval recv_buffer - , bool& error); - int body_start() const { return m_body_start_pos; } - size_type content_length() const { return m_content_length; } - - void reset(); - - std::map const& headers() const { return m_header; } - - private: - int m_recv_pos; - int m_status_code; - std::string m_method; - std::string m_path; - std::string m_protocol; - std::string m_server_message; - - size_type m_content_length; - - enum { read_status, read_header, read_body, error_state } m_state; - - std::map m_header; - buffer::const_interval m_recv_buffer; - int m_body_start_pos; - - bool m_finished; - }; - -} - -#endif // TORRENT_HTTP_PARSER_HPP_INCLUDED - diff --git a/libtorrent/include/libtorrent/http_stream.hpp b/libtorrent/include/libtorrent/http_stream.hpp deleted file mode 100644 index db1602120..000000000 --- a/libtorrent/include/libtorrent/http_stream.hpp +++ /dev/null @@ -1,102 +0,0 @@ -/* - -Copyright (c) 2007, Arvid Norberg -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions -are met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in - the documentation and/or other materials provided with the distribution. - * Neither the name of the author nor the names of its - contributors may be used to endorse or promote products derived - from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -POSSIBILITY OF SUCH DAMAGE. - -*/ - -#ifndef TORRENT_HTTP_STREAM_HPP_INCLUDED -#define TORRENT_HTTP_STREAM_HPP_INCLUDED - -#include "libtorrent/proxy_base.hpp" - -namespace libtorrent { - -class http_stream : public proxy_base -{ -public: - - explicit http_stream(io_service& io_service) - : proxy_base(io_service) - , m_no_connect(false) - {} - - void set_no_connect(bool c) { m_no_connect = c; } - - void set_username(std::string const& user - , std::string const& password) - { - m_user = user; - m_password = password; - } - - typedef boost::function handler_type; - - template - void async_connect(endpoint_type const& endpoint, Handler const& handler) - { - m_remote_endpoint = endpoint; - - // the connect is split up in the following steps: - // 1. resolve name of proxy server - // 2. connect to proxy server - // 3. send HTTP CONNECT method and possibly username+password - // 4. read CONNECT response - - // to avoid unnecessary copying of the handler, - // store it in a shaed_ptr - boost::shared_ptr h(new handler_type(handler)); - - tcp::resolver::query q(m_hostname - , boost::lexical_cast(m_port)); - m_resolver.async_resolve(q, boost::bind( - &http_stream::name_lookup, this, _1, _2, h)); - } - -private: - - void name_lookup(error_code const& e, tcp::resolver::iterator i - , boost::shared_ptr h); - void connected(error_code const& e, boost::shared_ptr h); - void handshake1(error_code const& e, boost::shared_ptr h); - void handshake2(error_code const& e, boost::shared_ptr h); - - // send and receive buffer - std::vector m_buffer; - // proxy authentication - std::string m_user; - std::string m_password; - - // this is true if the connection is HTTP based and - // want to talk directly to the proxy - bool m_no_connect; -}; - -} - -#endif diff --git a/libtorrent/include/libtorrent/http_tracker_connection.hpp b/libtorrent/include/libtorrent/http_tracker_connection.hpp deleted file mode 100644 index ec34260b0..000000000 --- a/libtorrent/include/libtorrent/http_tracker_connection.hpp +++ /dev/null @@ -1,106 +0,0 @@ -/* - -Copyright (c) 2003, Arvid Norberg -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions -are met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in - the documentation and/or other materials provided with the distribution. - * Neither the name of the author nor the names of its - contributors may be used to endorse or promote products derived - from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -POSSIBILITY OF SUCH DAMAGE. - -*/ - -#ifndef TORRENT_HTTP_TRACKER_CONNECTION_HPP_INCLUDED -#define TORRENT_HTTP_TRACKER_CONNECTION_HPP_INCLUDED - -#include - -#ifdef _MSC_VER -#pragma warning(push, 1) -#endif - -#include - -#ifdef _MSC_VER -#pragma warning(pop) -#endif - -#include "libtorrent/peer_id.hpp" -#include "libtorrent/tracker_manager.hpp" -#include "libtorrent/config.hpp" - -namespace libtorrent -{ - - struct http_connection; - class entry; - class http_parser; - class connection_queue; - struct session_settings; - - class TORRENT_EXPORT http_tracker_connection - : public tracker_connection - { - friend class tracker_manager; - public: - - http_tracker_connection( - io_service& ios - , connection_queue& cc - , tracker_manager& man - , tracker_request const& req - , address bind_infc - , boost::weak_ptr c - , session_settings const& stn - , proxy_settings const& ps - , std::string const& password = ""); - - void start(); - void close(); - - private: - - boost::intrusive_ptr self() - { return boost::intrusive_ptr(this); } - - void on_response(error_code const& ec, http_parser const& parser - , char const* data, int size); - - virtual void on_timeout() {} - - void parse(int status_code, const entry& e); - bool extract_peer_info(const entry& e, peer_entry& ret); - - tracker_manager& m_man; - boost::shared_ptr m_tracker_connection; - session_settings const& m_settings; - address m_bind_iface; - proxy_settings const& m_ps; - connection_queue& m_cc; - io_service& m_ios; - }; - -} - -#endif // TORRENT_HTTP_TRACKER_CONNECTION_HPP_INCLUDED - diff --git a/libtorrent/include/libtorrent/identify_client.hpp b/libtorrent/include/libtorrent/identify_client.hpp deleted file mode 100644 index e8cb3b930..000000000 --- a/libtorrent/include/libtorrent/identify_client.hpp +++ /dev/null @@ -1,58 +0,0 @@ -/* - -Copyright (c) 2003, Arvid Norberg -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions -are met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in - the documentation and/or other materials provided with the distribution. - * Neither the name of the author nor the names of its - contributors may be used to endorse or promote products derived - from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -POSSIBILITY OF SUCH DAMAGE. - -*/ - -#ifndef TORRENT_IDENTIFY_CLIENT_HPP_INCLUDED -#define TORRENT_IDENTIFY_CLIENT_HPP_INCLUDED - -#ifdef _MSC_VER -#pragma warning(push, 1) -#endif - -#include - -#ifdef _MSC_VER -#pragma warning(pop) -#endif - -#include "libtorrent/peer_id.hpp" -#include "libtorrent/fingerprint.hpp" -#include "libtorrent/config.hpp" - -namespace libtorrent -{ - - TORRENT_EXPORT std::string identify_client(const peer_id& p); - TORRENT_EXPORT boost::optional client_fingerprint(peer_id const& p); - -} - -#endif // TORRENT_IDENTIFY_CLIENT_HPP_INCLUDED diff --git a/libtorrent/include/libtorrent/instantiate_connection.hpp b/libtorrent/include/libtorrent/instantiate_connection.hpp deleted file mode 100644 index 26efcd6cf..000000000 --- a/libtorrent/include/libtorrent/instantiate_connection.hpp +++ /dev/null @@ -1,48 +0,0 @@ -/* - -Copyright (c) 2007, Arvid Norberg -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions -are met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in - the documentation and/or other materials provided with the distribution. - * Neither the name of the author nor the names of its - contributors may be used to endorse or promote products derived - from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -POSSIBILITY OF SUCH DAMAGE. - -*/ - -#ifndef TORRENT_INSTANTIATE_CONNECTION -#define TORRENT_INSTANTIATE_CONNECTION - -#include "libtorrent/socket_type.hpp" -#include - -namespace libtorrent -{ - struct proxy_settings; - - bool instantiate_connection(io_service& ios - , proxy_settings const& ps, socket_type& s); -} - -#endif - diff --git a/libtorrent/include/libtorrent/intrusive_ptr_base.hpp b/libtorrent/include/libtorrent/intrusive_ptr_base.hpp deleted file mode 100644 index c2f4e5b60..000000000 --- a/libtorrent/include/libtorrent/intrusive_ptr_base.hpp +++ /dev/null @@ -1,85 +0,0 @@ -/* - -Copyright (c) 2007, Arvid Norberg -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions -are met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in - the documentation and/or other materials provided with the distribution. - * Neither the name of the author nor the names of its - contributors may be used to endorse or promote products derived - from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -POSSIBILITY OF SUCH DAMAGE. - -*/ - -#ifndef TORRENT_INTRUSIVE_PTR_BASE -#define TORRENT_INTRUSIVE_PTR_BASE - -#include -#include -#include -#include "libtorrent/config.hpp" -#include "libtorrent/assert.hpp" - -namespace libtorrent -{ - template - struct intrusive_ptr_base - { - intrusive_ptr_base(intrusive_ptr_base const&) - : m_refs(0) {} - - intrusive_ptr_base& operator=(intrusive_ptr_base const& rhs) - { return *this; } - - friend void intrusive_ptr_add_ref(intrusive_ptr_base const* s) - { - TORRENT_ASSERT(s->m_refs >= 0); - TORRENT_ASSERT(s != 0); - ++s->m_refs; - } - - friend void intrusive_ptr_release(intrusive_ptr_base const* s) - { - TORRENT_ASSERT(s->m_refs > 0); - TORRENT_ASSERT(s != 0); - if (--s->m_refs == 0) - boost::checked_delete(static_cast(s)); - } - - boost::intrusive_ptr self() - { return boost::intrusive_ptr((T*)this); } - - boost::intrusive_ptr self() const - { return boost::intrusive_ptr((T const*)this); } - - int refcount() const { return m_refs; } - - intrusive_ptr_base(): m_refs(0) {} - private: - // reference counter for intrusive_ptr - mutable boost::detail::atomic_count m_refs; - }; - -} - -#endif - diff --git a/libtorrent/include/libtorrent/invariant_check.hpp b/libtorrent/include/libtorrent/invariant_check.hpp deleted file mode 100644 index 175a9861b..000000000 --- a/libtorrent/include/libtorrent/invariant_check.hpp +++ /dev/null @@ -1,78 +0,0 @@ -// Copyright Daniel Wallin 2004. Use, modification and distribution is -// subject to the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) - -#ifndef TORRENT_INVARIANT_ACCESS_HPP_INCLUDED -#define TORRENT_INVARIANT_ACCESS_HPP_INCLUDED - -#include "libtorrent/assert.hpp" - -namespace libtorrent -{ - - class invariant_access - { - public: - template - static void check_invariant(T const& self) - { - self.check_invariant(); - } - }; - - template - void check_invariant(T const& x) - { - invariant_access::check_invariant(x); - } - - struct invariant_checker {}; - - template - struct invariant_checker_impl : invariant_checker - { - invariant_checker_impl(T const& self_) - : self(self_) - { - try - { - check_invariant(self); - } - catch (...) - { - TORRENT_ASSERT(false); - } - } - - ~invariant_checker_impl() - { - try - { - check_invariant(self); - } - catch (...) - { - TORRENT_ASSERT(false); - } - } - - T const& self; - }; - - template - invariant_checker_impl make_invariant_checker(T const& x) - { - return invariant_checker_impl(x); - } -} - -#if defined TORRENT_DEBUG && !defined TORRENT_DISABLE_INVARIANT_CHECKS -#define INVARIANT_CHECK \ - invariant_checker const& _invariant_check = make_invariant_checker(*this); \ - (void)_invariant_check; \ - do {} while (false) -#else -#define INVARIANT_CHECK do {} while (false) -#endif - -#endif // TORRENT_INVARIANT_ACCESS_HPP_INCLUDED diff --git a/libtorrent/include/libtorrent/io.hpp b/libtorrent/include/libtorrent/io.hpp deleted file mode 100644 index f73c3e290..000000000 --- a/libtorrent/include/libtorrent/io.hpp +++ /dev/null @@ -1,153 +0,0 @@ -/* - -Copyright (c) 2003, Arvid Norberg -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions -are met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in - the documentation and/or other materials provided with the distribution. - * Neither the name of the author nor the names of its - contributors may be used to endorse or promote products derived - from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -POSSIBILITY OF SUCH DAMAGE. - -*/ - -#ifndef TORRENT_IO_HPP_INCLUDED -#define TORRENT_IO_HPP_INCLUDED - -#include -#include - -namespace libtorrent -{ - namespace detail - { - template struct type {}; - - // reads an integer from a byte stream - // in big endian byte order and converts - // it to native endianess - template - inline T read_impl(InIt& start, type) - { - T ret = 0; - for (int i = 0; i < (int)sizeof(T); ++i) - { - ret <<= 8; - ret |= static_cast(*start); - ++start; - } - return ret; - } - - template - inline void write_impl(T val, OutIt& start) - { - for (int i = (int)sizeof(T)-1; i >= 0; --i) - { - *start = static_cast((val >> (i * 8)) & 0xff); - ++start; - } - } - - // -- adaptors - - template - boost::int64_t read_int64(InIt& start) - { return read_impl(start, type()); } - - template - boost::uint64_t read_uint64(InIt& start) - { return read_impl(start, type()); } - - template - boost::uint32_t read_uint32(InIt& start) - { return read_impl(start, type()); } - - template - boost::int32_t read_int32(InIt& start) - { return read_impl(start, type()); } - - template - boost::int16_t read_int16(InIt& start) - { return read_impl(start, type()); } - - template - boost::uint16_t read_uint16(InIt& start) - { return read_impl(start, type()); } - - template - boost::int8_t read_int8(InIt& start) - { return read_impl(start, type()); } - - template - boost::uint8_t read_uint8(InIt& start) - { return read_impl(start, type()); } - - - template - void write_uint64(boost::uint64_t val, OutIt& start) - { write_impl(val, start); } - - template - void write_int64(boost::int64_t val, OutIt& start) - { write_impl(val, start); } - - template - void write_uint32(boost::uint32_t val, OutIt& start) - { write_impl(val, start); } - - template - void write_int32(boost::int32_t val, OutIt& start) - { write_impl(val, start); } - - template - void write_uint16(boost::uint16_t val, OutIt& start) - { write_impl(val, start); } - - template - void write_int16(boost::int16_t val, OutIt& start) - { write_impl(val, start); } - - template - void write_uint8(boost::uint8_t val, OutIt& start) - { write_impl(val, start); } - - template - void write_int8(boost::int8_t val, OutIt& start) - { write_impl(val, start); } - - inline void write_string(std::string const& str, char*& start) - { - std::copy(str.begin(), str.end(), start); - start += str.size(); - } - - template - void write_string(std::string const& str, OutIt& start) - { - std::copy(str.begin(), str.end(), start); - } - - } -} - -#endif // TORRENT_IO_HPP_INCLUDED diff --git a/libtorrent/include/libtorrent/ip_filter.hpp b/libtorrent/include/libtorrent/ip_filter.hpp deleted file mode 100644 index 1adb14551..000000000 --- a/libtorrent/include/libtorrent/ip_filter.hpp +++ /dev/null @@ -1,317 +0,0 @@ -/* - -Copyright (c) 2005, Arvid Norberg -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions -are met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in - the documentation and/or other materials provided with the distribution. - * Neither the name of the author nor the names of its - contributors may be used to endorse or promote products derived - from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -POSSIBILITY OF SUCH DAMAGE. - -*/ - -#ifndef TORRENT_IP_FILTER_HPP -#define TORRENT_IP_FILTER_HPP - -#include -#include - -#ifdef _MSC_VER -#pragma warning(push, 1) -#endif - -#include -#include -#include - -#ifdef _MSC_VER -#pragma warning(pop) -#endif - - -#include "libtorrent/config.hpp" -#include "libtorrent/socket.hpp" -#include "libtorrent/assert.hpp" - -namespace libtorrent -{ - -inline bool operator<=(address const& lhs - , address const& rhs) -{ - return lhs < rhs || lhs == rhs; -} - -template -struct ip_range -{ - Addr first; - Addr last; - int flags; -}; - -namespace detail -{ - - template - Addr zero() - { - Addr zero; - std::fill(zero.begin(), zero.end(), 0); - return zero; - } - - template<> - inline boost::uint16_t zero() { return 0; } - - template - Addr plus_one(Addr const& a) - { - Addr tmp(a); - typedef typename Addr::reverse_iterator iter; - for (iter i = tmp.rbegin() - , end(tmp.rend()); i != end; ++i) - { - if (*i < (std::numeric_limits::max)()) - { - *i += 1; - break; - } - *i = 0; - } - return tmp; - } - - inline boost::uint16_t plus_one(boost::uint16_t val) { return val + 1; } - - template - Addr minus_one(Addr const& a) - { - Addr tmp(a); - typedef typename Addr::reverse_iterator iter; - for (iter i = tmp.rbegin() - , end(tmp.rend()); i != end; ++i) - { - if (*i > 0) - { - *i -= 1; - break; - } - *i = (std::numeric_limits::max)(); - } - return tmp; - } - - inline boost::uint16_t minus_one(boost::uint16_t val) { return val - 1; } - - template - Addr max_addr() - { - Addr tmp; - std::fill(tmp.begin(), tmp.end() - , (std::numeric_limits::max)()); - return Addr(tmp); - } - - template<> - inline boost::uint16_t max_addr() - { return (std::numeric_limits::max)(); } - - // this is the generic implementation of - // a filter for a specific address type. - // it works with IPv4 and IPv6 - template - class filter_impl - { - public: - - filter_impl() - { - // make the entire ip-range non-blocked - m_access_list.insert(range(zero(), 0)); - } - - void add_rule(Addr first, Addr last, int flags) - { - using boost::next; - using boost::prior; - - TORRENT_ASSERT(!m_access_list.empty()); - TORRENT_ASSERT(first < last || first == last); - - typename range_t::iterator i = m_access_list.upper_bound(first); - typename range_t::iterator j = m_access_list.upper_bound(last); - - if (i != m_access_list.begin()) --i; - - TORRENT_ASSERT(j != m_access_list.begin()); - TORRENT_ASSERT(j != i); - - int first_access = i->access; - int last_access = prior(j)->access; - - if (i->start != first && first_access != flags) - { - i = m_access_list.insert(i, range(first, flags)); - } - else if (i != m_access_list.begin() && prior(i)->access == flags) - { - --i; - first_access = i->access; - } - TORRENT_ASSERT(!m_access_list.empty()); - TORRENT_ASSERT(i != m_access_list.end()); - - if (i != j) m_access_list.erase(next(i), j); - if (i->start == first) - { - // we can do this const-cast because we know that the new - // start address will keep the set correctly ordered - const_cast(i->start) = first; - const_cast(i->access) = flags; - } - else if (first_access != flags) - { - m_access_list.insert(i, range(first, flags)); - } - - if ((j != m_access_list.end() - && minus_one(j->start) != last) - || (j == m_access_list.end() - && last != max_addr())) - { - TORRENT_ASSERT(j == m_access_list.end() || last < minus_one(j->start)); - if (last_access != flags) - j = m_access_list.insert(j, range(plus_one(last), last_access)); - } - - if (j != m_access_list.end() && j->access == flags) m_access_list.erase(j); - TORRENT_ASSERT(!m_access_list.empty()); - } - - int access(Addr const& addr) const - { - TORRENT_ASSERT(!m_access_list.empty()); - typename range_t::const_iterator i = m_access_list.upper_bound(addr); - if (i != m_access_list.begin()) --i; - TORRENT_ASSERT(i != m_access_list.end()); - TORRENT_ASSERT(i->start <= addr && (boost::next(i) == m_access_list.end() - || addr < boost::next(i)->start)); - return i->access; - } - - template - std::vector > export_filter() const - { - std::vector > ret; - ret.reserve(m_access_list.size()); - - for (typename range_t::const_iterator i = m_access_list.begin() - , end(m_access_list.end()); i != end;) - { - ip_range r; - r.first = ExternalAddressType(i->start); - r.flags = i->access; - - ++i; - if (i == end) - r.last = ExternalAddressType(max_addr()); - else - r.last = ExternalAddressType(minus_one(i->start)); - - ret.push_back(r); - } - return ret; - } - - private: - - struct range - { - range(Addr addr, int access = 0): start(addr), access(access) {} - bool operator<(range const& r) const - { return start < r.start; } - bool operator<(Addr const& a) const - { return start < a; } - Addr start; - // the end of the range is implicit - // and given by the next entry in the set - int access; - }; - - typedef std::set range_t; - range_t m_access_list; - - }; - -} - -class TORRENT_EXPORT ip_filter -{ -public: - - enum access_flags - { - blocked = 1 - }; - - // both addresses MUST be of the same type (i.e. both must - // be either IPv4 or both must be IPv6) - void add_rule(address first, address last, int flags); - int access(address const& addr) const; - - typedef boost::tuple > - , std::vector > > filter_tuple_t; - - filter_tuple_t export_filter() const; - -// void print() const; - -private: - - detail::filter_impl m_filter4; - detail::filter_impl m_filter6; -}; - -class TORRENT_EXPORT port_filter -{ -public: - - enum access_flags - { - blocked = 1 - }; - - void add_rule(boost::uint16_t first, boost::uint16_t last, int flags); - int access(boost::uint16_t port) const; - -private: - - detail::filter_impl m_filter; - -}; - -} - -#endif - diff --git a/libtorrent/include/libtorrent/kademlia/closest_nodes.hpp b/libtorrent/include/libtorrent/kademlia/closest_nodes.hpp deleted file mode 100644 index bd4771ea4..000000000 --- a/libtorrent/include/libtorrent/kademlia/closest_nodes.hpp +++ /dev/null @@ -1,117 +0,0 @@ -/* - -Copyright (c) 2006, Arvid Norberg & Daniel Wallin -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions -are met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in - the documentation and/or other materials provided with the distribution. - * Neither the name of the author nor the names of its - contributors may be used to endorse or promote products derived - from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -POSSIBILITY OF SUCH DAMAGE. - -*/ - -#ifndef CLOSEST_NODES_050323_HPP -#define CLOSEST_NODES_050323_HPP - -#include - -#include -#include -#include -#include -#include - -#include - -namespace libtorrent { namespace dht -{ - -class rpc_manager; - -// -------- closest nodes ----------- - -class closest_nodes : public traversal_algorithm -{ -public: - typedef boost::function< - void(std::vector const&) - > done_callback; - - static void initiate( - node_id target - , int branch_factor - , int max_results - , routing_table& table - , rpc_manager& rpc - , done_callback const& callback - ); - -private: - void done(); - void invoke(node_id const& id, udp::endpoint addr); - - closest_nodes( - node_id target - , int branch_factor - , int max_results - , routing_table& table - , rpc_manager& rpc - , done_callback const& callback - ); - - done_callback m_done_callback; -}; - -class closest_nodes_observer : public observer -{ -public: - closest_nodes_observer( - boost::intrusive_ptr const& algorithm - , node_id self - , node_id target) - : observer(algorithm->allocator()) - , m_algorithm(algorithm) - , m_target(target) - , m_self(self) - {} - ~closest_nodes_observer(); - - void send(msg& p) - { - p.info_hash = m_target; - } - - void timeout(); - void reply(msg const&); - void abort() { m_algorithm = 0; } - -private: - boost::intrusive_ptr m_algorithm; - node_id const m_target; - node_id const m_self; -}; - -} } // namespace libtorrent::dht - -#endif // CLOSEST_NODES_050323_HPP - diff --git a/libtorrent/include/libtorrent/kademlia/dht_tracker.hpp b/libtorrent/include/libtorrent/kademlia/dht_tracker.hpp deleted file mode 100644 index b5ecb21b3..000000000 --- a/libtorrent/include/libtorrent/kademlia/dht_tracker.hpp +++ /dev/null @@ -1,175 +0,0 @@ -/* - -Copyright (c) 2006, Arvid Norberg -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions -are met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in - the documentation and/or other materials provided with the distribution. - * Neither the name of the author nor the names of its - contributors may be used to endorse or promote products derived - from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -POSSIBILITY OF SUCH DAMAGE. - -*/ - -#ifndef TORRENT_DISABLE_DHT - -#ifndef TORRENT_DHT_TRACKER -#define TORRENT_DHT_TRACKER - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "libtorrent/kademlia/node.hpp" -#include "libtorrent/kademlia/node_id.hpp" -#include "libtorrent/kademlia/traversal_algorithm.hpp" -#include "libtorrent/session_settings.hpp" -#include "libtorrent/session_status.hpp" -#include "libtorrent/udp_socket.hpp" -#include "libtorrent/socket.hpp" - -namespace libtorrent { namespace dht -{ - -#ifdef TORRENT_DHT_VERBOSE_LOGGING - TORRENT_DECLARE_LOG(dht_tracker); -#endif - - struct dht_tracker; - - TORRENT_EXPORT void intrusive_ptr_add_ref(dht_tracker const*); - TORRENT_EXPORT void intrusive_ptr_release(dht_tracker const*); - - struct dht_tracker - { - friend void intrusive_ptr_add_ref(dht_tracker const*); - friend void intrusive_ptr_release(dht_tracker const*); - dht_tracker(udp_socket& sock, dht_settings const& settings - , entry const* state); - - void start(entry const& bootstrap); - void stop(); - - void add_node(udp::endpoint node); - void add_node(std::pair const& node); - void add_router_node(std::pair const& node); - - entry state() const; - - void announce(sha1_hash const& ih, int listen_port - , boost::function const& - , sha1_hash const&)> f); - - void dht_status(session_status& s); - - // translate bittorrent kademlia message into the generic kademlia message - // used by the library - void on_receive(udp::endpoint const& ep, char const* pkt, int size); - void on_unreachable(udp::endpoint const& ep); - - private: - - boost::intrusive_ptr self() - { return boost::intrusive_ptr(this); } - - void on_name_lookup(error_code const& e - , udp::resolver::iterator host); - void on_router_name_lookup(error_code const& e - , udp::resolver::iterator host); - void connection_timeout(error_code const& e); - void refresh_timeout(error_code const& e); - void tick(error_code const& e); - - void on_bootstrap(); - void send_packet(msg const& m); - - node_impl m_dht; - udp_socket& m_sock; - - std::vector m_send_buf; - - ptime m_last_new_key; - deadline_timer m_timer; - deadline_timer m_connection_timer; - deadline_timer m_refresh_timer; - dht_settings const& m_settings; - int m_refresh_bucket; - - // The mutex is used to abort the dht node - // it's only used to set m_abort to true - typedef boost::mutex mutex_t; - mutable mutex_t m_mutex; - bool m_abort; - - // used to resolve hostnames for nodes - udp::resolver m_host_resolver; - - // used to ignore abusive dht nodes - struct node_ban_entry - { - node_ban_entry(): count(0) {} - udp::endpoint src; - ptime limit; - int count; - }; - - enum { num_ban_nodes = 20 }; - - node_ban_entry m_ban_nodes[num_ban_nodes]; - - // reference counter for intrusive_ptr - mutable boost::detail::atomic_count m_refs; - -#ifdef TORRENT_DHT_VERBOSE_LOGGING - int m_replies_sent[5]; - int m_queries_received[5]; - int m_replies_bytes_sent[5]; - int m_queries_bytes_received[5]; - int m_counter; - int m_announces; - int m_failed_announces; - - int m_total_message_input; - int m_ut_message_input; - int m_lt_message_input; - int m_mp_message_input; - int m_gr_message_input; - int m_mo_message_input; - - int m_total_in_bytes; - int m_total_out_bytes; - - int m_queries_out_bytes; -#endif - }; -}} - -#endif -#endif diff --git a/libtorrent/include/libtorrent/kademlia/find_data.hpp b/libtorrent/include/libtorrent/kademlia/find_data.hpp deleted file mode 100644 index 7772ca7c3..000000000 --- a/libtorrent/include/libtorrent/kademlia/find_data.hpp +++ /dev/null @@ -1,125 +0,0 @@ -/* - -Copyright (c) 2006, Arvid Norberg & Daniel Wallin -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions -are met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in - the documentation and/or other materials provided with the distribution. - * Neither the name of the author nor the names of its - contributors may be used to endorse or promote products derived - from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -POSSIBILITY OF SUCH DAMAGE. - -*/ - -#ifndef FIND_DATA_050323_HPP -#define FIND_DATA_050323_HPP - -#include - -#include -#include -#include -#include -#include -#include - -#include -#include - -namespace libtorrent { namespace dht -{ - -typedef std::vector packet_t; - -class rpc_manager; - -// -------- find data ----------- - -class find_data : public traversal_algorithm -{ -public: - typedef boost::function done_callback; - - static void initiate( - node_id target - , int branch_factor - , int max_results - , routing_table& table - , rpc_manager& rpc - , done_callback const& callback - ); - - void got_data(msg const* m); - -private: - void done(); - void invoke(node_id const& id, udp::endpoint addr); - - find_data( - node_id target - , int branch_factor - , int max_results - , routing_table& table - , rpc_manager& rpc - , done_callback const& callback - ); - - done_callback m_done_callback; - boost::shared_ptr m_packet; - bool m_done; -}; - -class find_data_observer : public observer -{ -public: - find_data_observer( - boost::intrusive_ptr const& algorithm - , node_id self - , node_id target) - : observer(algorithm->allocator()) - , m_algorithm(algorithm) - , m_target(target) - , m_self(self) - {} - ~find_data_observer(); - - void send(msg& m) - { - m.reply = false; - m.message_id = messages::get_peers; - m.info_hash = m_target; - } - - void timeout(); - void reply(msg const&); - void abort() { m_algorithm = 0; } - -private: - boost::intrusive_ptr m_algorithm; - node_id const m_target; - node_id const m_self; -}; - -} } // namespace libtorrent::dht - -#endif // FIND_DATA_050323_HPP - diff --git a/libtorrent/include/libtorrent/kademlia/logging.hpp b/libtorrent/include/libtorrent/kademlia/logging.hpp deleted file mode 100644 index c0cbb31a4..000000000 --- a/libtorrent/include/libtorrent/kademlia/logging.hpp +++ /dev/null @@ -1,146 +0,0 @@ -/* - -Copyright (c) 2006, Arvid Norberg & Daniel Wallin -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions -are met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in - the documentation and/or other materials provided with the distribution. - * Neither the name of the author nor the names of its - contributors may be used to endorse or promote products derived - from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -POSSIBILITY OF SUCH DAMAGE. - -*/ - -#ifndef TORRENT_LOGGING_HPP -#define TORRENT_LOGGING_HPP - -#include -#include - -namespace libtorrent { namespace dht -{ - -class log -{ -public: - log(char const* id, std::ostream& stream) - : m_id(id) - , m_enabled(true) - , m_stream(stream) - { - } - - char const* id() const - { - return m_id; - } - - bool enabled() const - { - return m_enabled; - } - - void enable(bool e) - { - m_enabled = e; - } - - void flush() { m_stream.flush(); } - - template - log& operator<<(T const& x) - { - m_stream << x; - return *this; - } - -private: - char const* m_id; - bool m_enabled; - std::ostream& m_stream; -}; - -class log_event -{ -public: - log_event(log& log) - : log_(log) - { - if (log_.enabled()) - log_ << '[' << log.id() << "] "; - } - - ~log_event() - { - if (log_.enabled()) - { - log_ << "\n"; - log_.flush(); - } - } - - template - log_event& operator<<(T const& x) - { - log_ << x; - return *this; - } - - operator bool() const - { - return log_.enabled(); - } - -private: - log& log_; -}; - -class inverted_log_event : public log_event -{ -public: - inverted_log_event(log& log) : log_event(log) {} - - operator bool() const - { - return !log_event::operator bool(); - } -}; - -} } // namespace libtorrent::dht - -#define TORRENT_DECLARE_LOG(name) \ - libtorrent::dht::log& name ## _log() - -#define TORRENT_DEFINE_LOG(name) \ - libtorrent::dht::log& name ## _log() \ - { \ - static std::ofstream log_file("dht.log", std::ios::app); \ - static libtorrent::dht::log instance(#name, log_file); \ - return instance; \ - } - -#define TORRENT_LOG(name) \ - if (libtorrent::dht::inverted_log_event event_object__ = name ## _log()); \ - else static_cast(event_object__) - -#endif - diff --git a/libtorrent/include/libtorrent/kademlia/msg.hpp b/libtorrent/include/libtorrent/kademlia/msg.hpp deleted file mode 100644 index 00db7305c..000000000 --- a/libtorrent/include/libtorrent/kademlia/msg.hpp +++ /dev/null @@ -1,104 +0,0 @@ -/* - -Copyright (c) 2007, Arvid Norberg -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions -are met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in - the documentation and/or other materials provided with the distribution. - * Neither the name of the author nor the names of its - contributors may be used to endorse or promote products derived - from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -POSSIBILITY OF SUCH DAMAGE. - -*/ - -#ifndef MSG_HPP -#define MSG_HPP - -#include -#include -#include "libtorrent/entry.hpp" -#if BOOST_VERSION < 103500 -#include -#else -#include -#endif - -namespace libtorrent { -namespace dht { - -typedef std::vector packet_t; - -namespace messages -{ - enum { ping = 0, find_node = 1, get_peers = 2, announce_peer = 3, error = 4 }; - char const* const ids[] = { "ping", "find_node", "get_peers", "announce_peer", "error" }; -} // namespace messages - -struct msg -{ - msg() : reply(false), piggy_backed_ping(false) - , message_id(-1), port(0) {} - - // true if this message is a reply - bool reply; - // true if this is a reply with a piggy backed ping - bool piggy_backed_ping; - // the kind if message - int message_id; - // if this is a reply, a copy of the transaction id - // from the request. If it's a request, a transaction - // id that should be sent back in the reply - std::string transaction_id; - // if this packet has a piggy backed ping, this - // is the transaction id of that ping - std::string ping_transaction_id; - // the node id of the process sending the message - node_id id; - // the address of the process sending or receiving - // the message. - udp::endpoint addr; - // if this is a nodes response, these are the nodes - typedef std::vector nodes_t; - nodes_t nodes; - - typedef std::vector peers_t; - peers_t peers; - - // similar to transaction_id but for write operations. - entry write_token; - - // the info has for peer_requests, announce_peer - // and responses - node_id info_hash; - - // port for announce_peer messages - int port; - - // ERROR MESSAGES - int error_code; - std::string error_msg; -}; - - -} } - -#endif diff --git a/libtorrent/include/libtorrent/kademlia/node.hpp b/libtorrent/include/libtorrent/kademlia/node.hpp deleted file mode 100644 index a018ef040..000000000 --- a/libtorrent/include/libtorrent/kademlia/node.hpp +++ /dev/null @@ -1,262 +0,0 @@ -/* - -Copyright (c) 2006, Arvid Norberg -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions -are met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in - the documentation and/or other materials provided with the distribution. - * Neither the name of the author nor the names of its - contributors may be used to endorse or promote products derived - from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -POSSIBILITY OF SUCH DAMAGE. - -*/ - -#ifndef NODE_HPP -#define NODE_HPP - -#include -#include -#include - -#include -#include -#include -#include - -#include -#include -#include - -#include -#include -#include -#include - -#include "libtorrent/socket.hpp" - -namespace libtorrent { namespace dht -{ - -#ifdef TORRENT_DHT_VERBOSE_LOGGING -TORRENT_DECLARE_LOG(node); -#endif - -// this is the entry for every peer -// the timestamp is there to make it possible -// to remove stale peers -struct peer_entry -{ - tcp::endpoint addr; - ptime added; -}; - -// this is a group. It contains a set of group members -struct torrent_entry -{ - std::set peers; -}; - -inline bool operator<(peer_entry const& lhs, peer_entry const& rhs) -{ - return lhs.addr.address() == rhs.addr.address() - ? lhs.addr.port() < rhs.addr.port() - : lhs.addr.address() < rhs.addr.address(); -} - -struct null_type {}; - -class announce_observer : public observer -{ -public: - announce_observer(boost::pool<>& allocator - , sha1_hash const& info_hash - , int listen_port - , entry const& write_token) - : observer(allocator) - , m_info_hash(info_hash) - , m_listen_port(listen_port) - , m_token(write_token) - {} - - void send(msg& m) - { - m.port = m_listen_port; - m.info_hash = m_info_hash; - m.write_token = m_token; - } - - void timeout() {} - void reply(msg const&) {} - void abort() {} - -private: - sha1_hash m_info_hash; - int m_listen_port; - entry m_token; -}; - -class get_peers_observer : public observer -{ -public: - get_peers_observer(sha1_hash const& info_hash - , int listen_port - , rpc_manager& rpc - , boost::function const&, sha1_hash const&)> f) - : observer(rpc.allocator()) - , m_info_hash(info_hash) - , m_listen_port(listen_port) - , m_rpc(rpc) - , m_fun(f) - {} - - void send(msg& m) - { - m.port = m_listen_port; - m.info_hash = m_info_hash; - } - - void timeout() {} - void reply(msg const& r) - { - observer_ptr o(new (m_rpc.allocator().malloc()) announce_observer( - m_rpc.allocator(), m_info_hash, m_listen_port, r.write_token)); -#ifdef TORRENT_DEBUG - o->m_in_constructor = false; -#endif - m_rpc.invoke(messages::announce_peer, r.addr, o); - m_fun(r.peers, m_info_hash); - } - void abort() {} - -private: - sha1_hash m_info_hash; - int m_listen_port; - rpc_manager& m_rpc; - boost::function const&, sha1_hash const&)> m_fun; -}; - - - -class node_impl : boost::noncopyable -{ -typedef std::map table_t; -public: - node_impl(boost::function const& f - , dht_settings const& settings, boost::optional nid); - - virtual ~node_impl() {} - - void refresh(node_id const& id, boost::function0 f); - void bootstrap(std::vector const& nodes - , boost::function0 f); - void find_node(node_id const& id, boost::function< - void(std::vector const&)> f); - void add_router_node(udp::endpoint router); - - void unreachable(udp::endpoint const& ep); - void incoming(msg const& m); - - void refresh(); - void refresh_bucket(int bucket); - int bucket_size(int bucket); - - typedef routing_table::iterator iterator; - - iterator begin() const { return m_table.begin(); } - iterator end() const { return m_table.end(); } - - typedef table_t::iterator data_iterator; - - node_id const& nid() const { return m_id; } - - boost::tuple size() const{ return m_table.size(); } - size_type num_global_nodes() const - { return m_table.num_global_nodes(); } - - data_iterator begin_data() { return m_map.begin(); } - data_iterator end_data() { return m_map.end(); } - int data_size() const { return int(m_map.size()); } - -#ifdef TORRENT_DHT_VERBOSE_LOGGING - void print_state(std::ostream& os) const - { m_table.print_state(os); } -#endif - - void announce(sha1_hash const& info_hash, int listen_port - , boost::function const& - , sha1_hash const&)> f); - - bool verify_token(msg const& m); - entry generate_token(msg const& m); - - // the returned time is the delay until connection_timeout() - // should be called again the next time - time_duration connection_timeout(); - time_duration refresh_timeout(); - - // generates a new secret number used to generate write tokens - void new_write_key(); - - // pings the given node, and adds it to - // the routing table if it respons and if the - // bucket is not full. - void add_node(udp::endpoint node); - - void replacement_cache(bucket_t& nodes) const - { m_table.replacement_cache(nodes); } - -protected: - // is called when a find data request is received. Should - // return false if the data is not stored on this node. If - // the data is stored, it should be serialized into 'data'. - bool on_find(msg const& m, std::vector& peers) const; - - // this is called when a store request is received. The data - // is store-parameters and the data to be stored. - void on_announce(msg const& m, msg& reply); - - dht_settings const& m_settings; - - // the maximum number of peers to send in a get_peers - // reply. Ordinary trackers usually limit this to 50. - // 50 => 6 * 50 = 250 bytes + packet overhead - int m_max_peers_reply; - -private: - void incoming_request(msg const& h); - - node_id m_id; - routing_table m_table; - rpc_manager m_rpc; - table_t m_map; - - ptime m_last_tracker_tick; - - // secret random numbers used to create write tokens - int m_secret[2]; -}; - - -} } // namespace libtorrent::dht - -#endif // NODE_HPP - diff --git a/libtorrent/include/libtorrent/kademlia/node_entry.hpp b/libtorrent/include/libtorrent/kademlia/node_entry.hpp deleted file mode 100644 index e31a60e3f..000000000 --- a/libtorrent/include/libtorrent/kademlia/node_entry.hpp +++ /dev/null @@ -1,76 +0,0 @@ -/* - -Copyright (c) 2006, Arvid Norberg -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions -are met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in - the documentation and/or other materials provided with the distribution. - * Neither the name of the author nor the names of its - contributors may be used to endorse or promote products derived - from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -POSSIBILITY OF SUCH DAMAGE. - -*/ - -#ifndef KADEMLIA_NODE_ENTRY_HPP -#define KADEMLIA_NODE_ENTRY_HPP - -#include "libtorrent/kademlia/node_id.hpp" -#include "libtorrent/socket.hpp" - -namespace libtorrent { namespace dht -{ - -struct node_entry -{ - node_entry(node_id const& id_, udp::endpoint addr_) - : id(id_) - , addr(addr_) - , fail_count(0) - { -#ifdef TORRENT_DHT_VERBOSE_LOGGING - first_seen = time_now(); -#endif - } - node_entry(udp::endpoint addr_) - : id(0) - , addr(addr_) - , fail_count(0) - { -#ifdef TORRENT_DHT_VERBOSE_LOGGING - first_seen = time_now(); -#endif - } - - node_id id; - udp::endpoint addr; - // the number of times this node has failed to - // respond in a row - int fail_count; -#ifdef TORRENT_DHT_VERBOSE_LOGGING - ptime first_seen; -#endif -}; - -} } // namespace libtorrent::dht - -#endif - diff --git a/libtorrent/include/libtorrent/kademlia/node_id.hpp b/libtorrent/include/libtorrent/kademlia/node_id.hpp deleted file mode 100644 index 4173808c9..000000000 --- a/libtorrent/include/libtorrent/kademlia/node_id.hpp +++ /dev/null @@ -1,62 +0,0 @@ -/* - -Copyright (c) 2006, Arvid Norberg -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions -are met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in - the documentation and/or other materials provided with the distribution. - * Neither the name of the author nor the names of its - contributors may be used to endorse or promote products derived - from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -POSSIBILITY OF SUCH DAMAGE. - -*/ -#ifndef NODE_ID_HPP -#define NODE_ID_HPP - -#include - -#include -#include "libtorrent/peer_id.hpp" -#include "libtorrent/assert.hpp" - -namespace libtorrent { namespace dht -{ - -typedef libtorrent::big_number node_id; - -// returns the distance between the two nodes -// using the kademlia XOR-metric -node_id distance(node_id const& n1, node_id const& n2); - -// returns true if: distance(n1, ref) < distance(n2, ref) -bool compare_ref(node_id const& n1, node_id const& n2, node_id const& ref); - -// returns n in: 2^n <= distance(n1, n2) < 2^(n+1) -// usefult for finding out which bucket a node belongs to -int distance_exp(node_id const& n1, node_id const& n2); - -node_id generate_id(); - -} } // namespace libtorrent::dht - -#endif // NODE_ID_HPP - diff --git a/libtorrent/include/libtorrent/kademlia/observer.hpp b/libtorrent/include/libtorrent/kademlia/observer.hpp deleted file mode 100644 index 7e11a4c70..000000000 --- a/libtorrent/include/libtorrent/kademlia/observer.hpp +++ /dev/null @@ -1,102 +0,0 @@ -/* - -Copyright (c) 2007, Arvid Norberg -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions -are met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in - the documentation and/or other materials provided with the distribution. - * Neither the name of the author nor the names of its - contributors may be used to endorse or promote products derived - from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -POSSIBILITY OF SUCH DAMAGE. - -*/ - -#ifndef OBSERVER_HPP -#define OBSERVER_HPP - -#include -#include -#include - -namespace libtorrent { -namespace dht { - -struct observer; -struct msg; - -// defined in rpc_manager.cpp -TORRENT_EXPORT void intrusive_ptr_add_ref(observer const*); -TORRENT_EXPORT void intrusive_ptr_release(observer const*); - -struct observer : boost::noncopyable -{ - friend TORRENT_EXPORT void intrusive_ptr_add_ref(observer const*); - friend TORRENT_EXPORT void intrusive_ptr_release(observer const*); - - observer(boost::pool<>& p) - : sent(time_now()) - , pool_allocator(p) - , m_refs(0) - { -#ifdef TORRENT_DEBUG - m_in_constructor = true; -#endif - } - - virtual ~observer() - { - TORRENT_ASSERT(!m_in_constructor); - } - - // these two callbacks lets the observer add - // information to the message before it's sent - virtual void send(msg& m) = 0; - - // this is called when a reply is received - virtual void reply(msg const& m) = 0; - - // this is called when no reply has been received within - // some timeout - virtual void timeout() = 0; - - // if this is called the destructor should - // not invoke any new messages, and should - // only clean up. It means the rpc-manager - // is being destructed - virtual void abort() = 0; - - udp::endpoint target_addr; - ptime sent; -#ifdef TORRENT_DEBUG - bool m_in_constructor; -#endif -private: - boost::pool<>& pool_allocator; - // reference counter for intrusive_ptr - mutable boost::detail::atomic_count m_refs; -}; - -typedef boost::intrusive_ptr observer_ptr; - -} } - -#endif diff --git a/libtorrent/include/libtorrent/kademlia/refresh.hpp b/libtorrent/include/libtorrent/kademlia/refresh.hpp deleted file mode 100644 index 953c4d871..000000000 --- a/libtorrent/include/libtorrent/kademlia/refresh.hpp +++ /dev/null @@ -1,214 +0,0 @@ -/* - -Copyright (c) 2006, Arvid Norberg & Daniel Wallin -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions -are met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in - the documentation and/or other materials provided with the distribution. - * Neither the name of the author nor the names of its - contributors may be used to endorse or promote products derived - from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -POSSIBILITY OF SUCH DAMAGE. - -*/ - -#ifndef REFRESH_050324_HPP -#define REFRESH_050324_HPP - -#include - -#include -#include -#include -#include - -#include - -namespace libtorrent { namespace dht -{ - -#ifdef TORRENT_DHT_VERBOSE_LOGGING -TORRENT_DECLARE_LOG(refresh); -#endif - -class routing_table; -class rpc_manager; - -class refresh : public traversal_algorithm -{ -public: - typedef boost::function done_callback; - - template - static void initiate( - node_id target - , int branch_factor - , int max_active_pings - , int max_results - , routing_table& table - , InIt first - , InIt last - , rpc_manager& rpc - , done_callback const& callback - ); - - void ping_reply(node_id id); - void ping_timeout(node_id id, bool prevent_request = false); - -private: - template - refresh( - node_id target - , int branch_factor - , int max_active_pings - , int max_results - , routing_table& table - , InIt first - , InIt last - , rpc_manager& rpc - , done_callback const& callback - ); - - void done(); - void invoke(node_id const& id, udp::endpoint addr); - - void invoke_pings_or_finish(bool prevent_request = false); - - int m_max_active_pings; - int m_active_pings; - - done_callback m_done_callback; - - std::vector::iterator m_leftover_nodes_iterator; -}; - -class refresh_observer : public observer -{ -public: - refresh_observer( - boost::intrusive_ptr const& algorithm - , node_id self - , node_id target) - : observer(algorithm->allocator()) - , m_target(target) - , m_self(self) - , m_algorithm(algorithm) - {} - ~refresh_observer(); - - void send(msg& m) - { - m.info_hash = m_target; - } - - void timeout(); - void reply(msg const& m); - void abort() { m_algorithm = 0; } - - -private: - node_id const m_target; - node_id const m_self; - boost::intrusive_ptr m_algorithm; -}; - -class ping_observer : public observer -{ -public: - ping_observer( - boost::intrusive_ptr const& algorithm - , node_id self) - : observer(algorithm->allocator()) - , m_self(self) - , m_algorithm(algorithm) - {} - ~ping_observer(); - - void send(msg& p) {} - void timeout(); - void reply(msg const& m); - void abort() { m_algorithm = 0; } - - -private: - node_id const m_self; - boost::intrusive_ptr m_algorithm; -}; - -template -inline refresh::refresh( - node_id target - , int branch_factor - , int max_active_pings - , int max_results - , routing_table& table - , InIt first - , InIt last - , rpc_manager& rpc - , done_callback const& callback -) - : traversal_algorithm( - target - , branch_factor - , max_results - , table - , rpc - , first - , last - ) - , m_max_active_pings(max_active_pings) - , m_active_pings(0) - , m_done_callback(callback) -{ - boost::intrusive_ptr self(this); - add_requests(); -} - -template -inline void refresh::initiate( - node_id target - , int branch_factor - , int max_active_pings - , int max_results - , routing_table& table - , InIt first - , InIt last - , rpc_manager& rpc - , done_callback const& callback -) -{ - new refresh( - target - , branch_factor - , max_active_pings - , max_results - , table - , first - , last - , rpc - , callback - ); -} - -} } // namespace libtorrent::dht - -#endif // REFRESH_050324_HPP - diff --git a/libtorrent/include/libtorrent/kademlia/routing_table.hpp b/libtorrent/include/libtorrent/kademlia/routing_table.hpp deleted file mode 100644 index c037199c1..000000000 --- a/libtorrent/include/libtorrent/kademlia/routing_table.hpp +++ /dev/null @@ -1,254 +0,0 @@ -/* - -Copyright (c) 2006, Arvid Norberg -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions -are met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in - the documentation and/or other materials provided with the distribution. - * Neither the name of the author nor the names of its - contributors may be used to endorse or promote products derived - from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -POSSIBILITY OF SUCH DAMAGE. - -*/ - -#ifndef ROUTING_TABLE_HPP -#define ROUTING_TABLE_HPP - -#include -#include -#include - -#include -#include -#include -#include -#include -#include - -#include - -#include -#include -#include -#include -#include - -namespace libtorrent { namespace dht -{ - -#ifdef TORRENT_DHT_VERBOSE_LOGGING -TORRENT_DECLARE_LOG(table); -#endif - - -typedef std::vector bucket_t; - -// differences in the implementation from the description in -// the paper: -// -// * The routing table tree is not allocated dynamically, there -// are always 160 buckets. -// * Nodes are not marked as being stale, they keep a counter -// that tells how many times in a row they have failed. When -// a new node is to be inserted, the node that has failed -// the most times is replaced. If none of the nodes in the -// bucket has failed, then it is put in the replacement -// cache (just like in the paper). - -class routing_table; - -namespace aux -{ - - // Iterates over a flattened routing_table structure. - class routing_table_iterator - : public boost::iterator_facade< - routing_table_iterator - , node_entry const - , boost::forward_traversal_tag - > - { - public: - routing_table_iterator() - { - } - - private: - friend class libtorrent::dht::routing_table; - friend class boost::iterator_core_access; - - typedef boost::array, 160>::const_iterator - bucket_iterator_t; - - routing_table_iterator( - bucket_iterator_t begin - , bucket_iterator_t end) - : m_bucket_iterator(begin) - , m_bucket_end(end) - { - if (m_bucket_iterator == m_bucket_end) return; - m_iterator = begin->first.begin(); - while (m_iterator == m_bucket_iterator->first.end()) - { - if (++m_bucket_iterator == m_bucket_end) - break; - m_iterator = m_bucket_iterator->first.begin(); - } - } - - bool equal(routing_table_iterator const& other) const - { - return m_bucket_iterator == other.m_bucket_iterator - && (m_bucket_iterator == m_bucket_end - || *m_iterator == other.m_iterator); - } - - void increment() - { - TORRENT_ASSERT(m_bucket_iterator != m_bucket_end); - ++*m_iterator; - while (*m_iterator == m_bucket_iterator->first.end()) - { - if (++m_bucket_iterator == m_bucket_end) - break; - m_iterator = m_bucket_iterator->first.begin(); - } - } - - node_entry const& dereference() const - { - TORRENT_ASSERT(m_bucket_iterator != m_bucket_end); - return **m_iterator; - } - - bucket_iterator_t m_bucket_iterator; - bucket_iterator_t m_bucket_end; - // when debug iterators are enabled, default constructed - // iterators are not allowed to be copied. In the case - // where the routing table is empty, m_iterator would be - // default constructed and not copyable. - boost::optional m_iterator; - }; - -} // namespace aux - -class routing_table -{ -public: - typedef aux::routing_table_iterator iterator; - typedef iterator const_iterator; - - routing_table(node_id const& id, int bucket_size - , dht_settings const& settings); - - void node_failed(node_id const& id); - - // adds an endpoint that will never be added to - // the routing table - void add_router_node(udp::endpoint router); - - // iterates over the router nodes added - typedef std::set::const_iterator router_iterator; - router_iterator router_begin() const { return m_router_nodes.begin(); } - router_iterator router_end() const { return m_router_nodes.end(); } - - // this function is called every time the node sees - // a sign of a node being alive. This node will either - // be inserted in the k-buckets or be moved to the top - // of its bucket. - bool node_seen(node_id const& id, udp::endpoint addr); - - // returns time when the given bucket needs another refresh. - // if the given bucket is empty but there are nodes - // in a bucket closer to us, or if the bucket is non-empty and - // the time from the last activity is more than 15 minutes - ptime next_refresh(int bucket); - - // fills the vector with the count nodes from our buckets that - // are nearest to the given id. - void find_node(node_id const& id, std::vector& l - , bool include_self, int count = 0); - - // returns true if the given node would be placed in a bucket - // that is not full. If the node already exists in the table - // this function returns false - bool need_node(node_id const& id); - - // this will set the given bucket's latest activity - // to the current time - void touch_bucket(int bucket); - - int bucket_size(int bucket) - { - TORRENT_ASSERT(bucket >= 0 && bucket < 160); - return (int)m_buckets[bucket].first.size(); - } - int bucket_size() const { return m_bucket_size; } - - iterator begin() const; - iterator end() const; - - boost::tuple size() const; - size_type num_global_nodes() const; - - // returns true if there are no working nodes - // in the routing table - bool need_bootstrap() const; - int num_active_buckets() const - { return 160 - m_lowest_active_bucket + 1; } - - void replacement_cache(bucket_t& nodes) const; -#ifdef TORRENT_DHT_VERBOSE_LOGGING - // used for debug and monitoring purposes. This will print out - // the state of the routing table to the given stream - void print_state(std::ostream& os) const; -#endif - -private: - - // constant called k in paper - int m_bucket_size; - - dht_settings const& m_settings; - - // 160 (k-bucket, replacement cache) pairs - typedef boost::array, 160> table_t; - table_t m_buckets; - // timestamps of the last activity in each bucket - typedef boost::array table_activity_t; - table_activity_t m_bucket_activity; - node_id m_id; // our own node id - - // this is a set of all the endpoints that have - // been identified as router nodes. They will - // be used in searches, but they will never - // be added to the routing table. - std::set m_router_nodes; - - // this is the lowest bucket index with nodes in it - int m_lowest_active_bucket; -}; - -} } // namespace libtorrent::dht - -#endif // ROUTING_TABLE_HPP - diff --git a/libtorrent/include/libtorrent/kademlia/rpc_manager.hpp b/libtorrent/include/libtorrent/kademlia/rpc_manager.hpp deleted file mode 100644 index dcfa1b6eb..000000000 --- a/libtorrent/include/libtorrent/kademlia/rpc_manager.hpp +++ /dev/null @@ -1,141 +0,0 @@ -/* - -Copyright (c) 2006, Arvid Norberg -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions -are met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in - the documentation and/or other materials provided with the distribution. - * Neither the name of the author nor the names of its - contributors may be used to endorse or promote products derived - from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -POSSIBILITY OF SUCH DAMAGE. - -*/ - -#ifndef RPC_MANAGER_HPP -#define RPC_MANAGER_HPP - -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include - -#include "libtorrent/time.hpp" - -namespace libtorrent { namespace dht -{ - -struct observer; - -#ifdef TORRENT_DHT_VERBOSE_LOGGING -TORRENT_DECLARE_LOG(rpc); -#endif - -struct null_observer : public observer -{ - null_observer(boost::pool<>& allocator): observer(allocator) {} - virtual void reply(msg const&) {} - virtual void timeout() {} - virtual void send(msg&) {} - void abort() {} -}; - -class routing_table; - -class rpc_manager -{ -public: - typedef boost::function1 fun; - typedef boost::function1 send_fun; - - rpc_manager(fun const& incoming_fun, node_id const& our_id - , routing_table& table, send_fun const& sf); - ~rpc_manager(); - - void unreachable(udp::endpoint const& ep); - - // returns true if the node needs a refresh - bool incoming(msg const&); - time_duration tick(); - - void invoke(int message_id, udp::endpoint target - , observer_ptr o); - - void reply(msg& m); - void reply_with_ping(msg& m); - -#ifdef TORRENT_DEBUG - size_t allocation_size() const; - void check_invariant() const; -#endif - - boost::pool<>& allocator() const - { return m_pool_allocator; } - -private: - - enum { max_transactions = 2048 }; - - unsigned int new_transaction_id(observer_ptr o); - void update_oldest_transaction_id(); - - boost::uint32_t calc_connection_id(udp::endpoint addr); - - mutable boost::pool<> m_pool_allocator; - - typedef boost::array - transactions_t; - transactions_t m_transactions; - std::vector m_aborted_transactions; - - // this is the next transaction id to be used - int m_next_transaction_id; - // this is the oldest transaction id still - // (possibly) in use. This is the transaction - // that will time out first, the one we are - // waiting for to time out - int m_oldest_transaction_id; - - fun m_incoming; - send_fun m_send; - node_id m_our_id; - routing_table& m_table; - ptime m_timer; - node_id m_random_number; - bool m_destructing; -}; - -} } // namespace libtorrent::dht - -#endif - - diff --git a/libtorrent/include/libtorrent/kademlia/traversal_algorithm.hpp b/libtorrent/include/libtorrent/kademlia/traversal_algorithm.hpp deleted file mode 100644 index 74d79edc9..000000000 --- a/libtorrent/include/libtorrent/kademlia/traversal_algorithm.hpp +++ /dev/null @@ -1,161 +0,0 @@ -/* - -Copyright (c) 2006, Arvid Norberg & Daniel Wallin -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions -are met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in - the documentation and/or other materials provided with the distribution. - * Neither the name of the author nor the names of its - contributors may be used to endorse or promote products derived - from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -POSSIBILITY OF SUCH DAMAGE. - -*/ - -#ifndef TRAVERSAL_ALGORITHM_050324_HPP -#define TRAVERSAL_ALGORITHM_050324_HPP - -#include -#include - -#include -#include -#include - -#include -#include -#include -#include - -namespace libtorrent { namespace dht -{ -#ifdef TORRENT_DHT_VERBOSE_LOGGING -TORRENT_DECLARE_LOG(traversal); -#endif - -class rpc_manager; - -// this class may not be instantiated as a stack object -class traversal_algorithm : boost::noncopyable -{ -public: - void traverse(node_id const& id, udp::endpoint addr); - void finished(node_id const& id); - void failed(node_id const& id, bool prevent_request = false); - virtual ~traversal_algorithm() {} - boost::pool<>& allocator() const; - -protected: - template - traversal_algorithm( - node_id target - , int branch_factor - , int max_results - , routing_table& table - , rpc_manager& rpc - , InIt start - , InIt end - ); - - void add_requests(); - void add_entry(node_id const& id, udp::endpoint addr, unsigned char flags); - - virtual void done() = 0; - virtual void invoke(node_id const& id, udp::endpoint addr) = 0; - - struct result - { - result(node_id const& id, udp::endpoint addr, unsigned char f = 0) - : id(id), addr(addr), flags(f) {} - - node_id id; - udp::endpoint addr; - enum { queried = 1, initial = 2, no_id = 4 }; - unsigned char flags; - }; - - std::vector::iterator last_iterator(); - - friend void intrusive_ptr_add_ref(traversal_algorithm* p) - { - p->m_ref_count++; - } - - friend void intrusive_ptr_release(traversal_algorithm* p) - { - if (--p->m_ref_count == 0) - delete p; - } - - int m_ref_count; - - node_id m_target; - int m_branch_factor; - int m_max_results; - std::vector m_results; - std::set m_failed; - routing_table& m_table; - rpc_manager& m_rpc; - int m_invoke_count; -}; - -template -traversal_algorithm::traversal_algorithm( - node_id target - , int branch_factor - , int max_results - , routing_table& table - , rpc_manager& rpc - , InIt start // <- nodes to initiate traversal with - , InIt end -) - : m_ref_count(0) - , m_target(target) - , m_branch_factor(branch_factor) - , m_max_results(max_results) - , m_table(table) - , m_rpc(rpc) - , m_invoke_count(0) -{ - using boost::bind; - - for (InIt i = start; i != end; ++i) - { - add_entry(i->id, i->addr, result::initial); - } - - // in case the routing table is empty, use the - // router nodes in the table - if (start == end) - { - for (routing_table::router_iterator i = table.router_begin() - , end(table.router_end()); i != end; ++i) - { - add_entry(node_id(0), *i, result::initial); - } - } - -} - -} } // namespace libtorrent::dht - -#endif // TRAVERSAL_ALGORITHM_050324_HPP - diff --git a/libtorrent/include/libtorrent/lazy_entry.hpp b/libtorrent/include/libtorrent/lazy_entry.hpp deleted file mode 100644 index 3745535ef..000000000 --- a/libtorrent/include/libtorrent/lazy_entry.hpp +++ /dev/null @@ -1,236 +0,0 @@ -/* - -Copyright (c) 2003, Arvid Norberg -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions -are met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in - the documentation and/or other materials provided with the distribution. - * Neither the name of the author nor the names of its - contributors may be used to endorse or promote products derived - from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -POSSIBILITY OF SUCH DAMAGE. - -*/ - -#ifndef TORRENT_LAZY_ENTRY_HPP_INCLUDED -#define TORRENT_LAZY_ENTRY_HPP_INCLUDED - -#include -#include -#include -#include -#include "libtorrent/config.hpp" -#include "libtorrent/assert.hpp" -#include "libtorrent/size_type.hpp" - -namespace libtorrent -{ - struct lazy_entry; - - TORRENT_EXPORT char const* parse_int(char const* start, char const* end - , char delimiter, boost::int64_t& val); - // return 0 = success - TORRENT_EXPORT int lazy_bdecode(char const* start, char const* end, lazy_entry& ret, int depth_limit = 1000); - - struct TORRENT_EXPORT lazy_entry - { - enum entry_type_t - { - none_t, dict_t, list_t, string_t, int_t - }; - - lazy_entry() : m_type(none_t), m_begin(0), m_end(0) - { m_data.start = 0; } - - entry_type_t type() const { return m_type; } - - // start points to the first decimal digit - // length is the number of digits - void construct_int(char const* start, int length) - { - TORRENT_ASSERT(m_type == none_t); - m_type = int_t; - m_data.start = start; - m_size = length; - m_begin = start - 1; // include 'i' - m_end = start + length + 1; // include 'e' - } - - size_type int_value() const; - - // string functions - // ================ - - void construct_string(char const* start, int length); - - // the string is not null-terminated! - char const* string_ptr() const - { - TORRENT_ASSERT(m_type == string_t); - return m_data.start; - } - - // this will return a null terminated string - // it will write to the source buffer! - char const* string_cstr() const - { - TORRENT_ASSERT(m_type == string_t); - const_cast(m_data.start)[m_size] = 0; - return m_data.start; - } - - std::string string_value() const - { - TORRENT_ASSERT(m_type == string_t); - return std::string(m_data.start, m_size); - } - - int string_length() const - { return m_size; } - - // dictionary functions - // ==================== - - void construct_dict(char const* begin) - { - TORRENT_ASSERT(m_type == none_t); - m_type = dict_t; - m_size = 0; - m_capacity = 0; - m_begin = begin; - } - - lazy_entry* dict_append(char const* name); - lazy_entry* dict_find(char const* name); - lazy_entry const* dict_find(char const* name) const - { return const_cast(this)->dict_find(name); } - - std::string dict_find_string_value(char const* name) const; - size_type dict_find_int_value(char const* name, size_type default_val = 0) const; - lazy_entry const* dict_find_dict(char const* name) const; - lazy_entry const* dict_find_list(char const* name) const; - lazy_entry const* dict_find_string(char const* name) const; - - std::pair dict_at(int i) const - { - TORRENT_ASSERT(m_type == dict_t); - TORRENT_ASSERT(i < m_size); - std::pair const& e = m_data.dict[i]; - return std::make_pair(std::string(e.first, e.second.m_begin - e.first), &e.second); - } - - int dict_size() const - { - TORRENT_ASSERT(m_type == dict_t); - return m_size; - } - - // list functions - // ============== - - void construct_list(char const* begin) - { - TORRENT_ASSERT(m_type == none_t); - m_type = list_t; - m_size = 0; - m_capacity = 0; - m_begin = begin; - } - - lazy_entry* list_append(); - lazy_entry* list_at(int i) - { - TORRENT_ASSERT(m_type == list_t); - TORRENT_ASSERT(i < m_size); - return &m_data.list[i]; - } - lazy_entry const* list_at(int i) const - { return const_cast(this)->list_at(i); } - - std::string list_string_value_at(int i) const; - size_type list_int_value_at(int i, size_type default_val = 0) const; - - int list_size() const - { - TORRENT_ASSERT(m_type == list_t); - return m_size; - } - - // end points one byte passed last byte - void set_end(char const* end) - { - TORRENT_ASSERT(end > m_begin); - m_end = end; - } - - void clear(); - - // releases ownership of any memory allocated - void release() - { - m_data.start = 0; - m_size = 0; - m_capacity = 0; - m_type = none_t; - } - - ~lazy_entry() - { clear(); } - - // returns pointers into the source buffer where - // this entry has its bencoded data - std::pair data_section() const; - - void swap(lazy_entry& e) - { - using std::swap; - swap(m_type, e.m_type); - swap(m_data.start, e.m_data.start); - swap(m_size, e.m_size); - swap(m_capacity, e.m_capacity); - swap(m_begin, e.m_begin); - swap(m_end, e.m_end); - } - - private: - - entry_type_t m_type; - union data_t - { - std::pair* dict; - lazy_entry* list; - char const* start; - } m_data; - int m_size; // if list or dictionary, the number of items - int m_capacity; // if list or dictionary, allocated number of items - // used for dictionaries and lists to record the range - // in the original buffer they are based on - char const* m_begin; - char const* m_end; - }; - - TORRENT_EXPORT std::ostream& operator<<(std::ostream& os, lazy_entry const& e); - -} - - -#endif - diff --git a/libtorrent/include/libtorrent/lsd.hpp b/libtorrent/include/libtorrent/lsd.hpp deleted file mode 100644 index 6e3ddea7d..000000000 --- a/libtorrent/include/libtorrent/lsd.hpp +++ /dev/null @@ -1,98 +0,0 @@ -/* - -Copyright (c) 2007, Arvid Norberg -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions -are met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in - the documentation and/or other materials provided with the distribution. - * Neither the name of the author nor the names of its - contributors may be used to endorse or promote products derived - from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -POSSIBILITY OF SUCH DAMAGE. - -*/ - -#ifndef TORRENT_LSD_HPP -#define TORRENT_LSD_HPP - -#include "libtorrent/socket.hpp" -#include "libtorrent/peer_id.hpp" -#include "libtorrent/broadcast_socket.hpp" -#include "libtorrent/intrusive_ptr_base.hpp" - -#include -#include -#include -#include -#include - -#if defined(TORRENT_LOGGING) || defined(TORRENT_VERBOSE_LOGGING) -#include -#endif - -namespace libtorrent -{ - -typedef boost::function peer_callback_t; - -class lsd : public intrusive_ptr_base -{ -public: - lsd(io_service& ios, address const& listen_interface - , peer_callback_t const& cb); - ~lsd(); - -// void rebind(address const& listen_interface); - - void announce(sha1_hash const& ih, int listen_port); - void close(); - -private: - - void resend_announce(error_code const& e, std::string msg); - void on_announce(udp::endpoint const& from, char* buffer - , std::size_t bytes_transferred); -// void setup_receive(); - - peer_callback_t m_callback; - - // current retry count - int m_retry_count; - - // the udp socket used to send and receive - // multicast messages on - broadcast_socket m_socket; - - // used to resend udp packets in case - // they time out - deadline_timer m_broadcast_timer; - - bool m_disabled; -#if defined(TORRENT_LOGGING) || defined(TORRENT_VERBOSE_LOGGING) - std::ofstream m_log; -#endif -}; - -} - - -#endif - diff --git a/libtorrent/include/libtorrent/magnet_uri.hpp b/libtorrent/include/libtorrent/magnet_uri.hpp deleted file mode 100644 index 88675dfe8..000000000 --- a/libtorrent/include/libtorrent/magnet_uri.hpp +++ /dev/null @@ -1,66 +0,0 @@ -/* - -Copyright (c) 2007, Arvid Norberg -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions -are met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in - the documentation and/or other materials provided with the distribution. - * Neither the name of the author nor the names of its - contributors may be used to endorse or promote products derived - from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -POSSIBILITY OF SUCH DAMAGE. - -*/ - -#ifndef TORRENT_MAGNET_URI_HPP_INCLUDED -#define TORRENT_MAGNET_URI_HPP_INCLUDED - -#include -#include "libtorrent/config.hpp" -#include "libtorrent/torrent_handle.hpp" -#include "libtorrent/session.hpp" -#include - -namespace libtorrent -{ - namespace fs = boost::filesystem; - - struct torrent_handle; - - std::string TORRENT_EXPORT make_magnet_uri(torrent_handle const& handle); - std::string TORRENT_EXPORT make_magnet_uri(torrent_info const& info); - -#ifndef TORRENT_NO_DEPRECATE - // deprecated in 0.14 - torrent_handle TORRENT_EXPORT add_magnet_uri(session& ses, std::string const& uri - , fs::path const& save_path - , storage_mode_t storage_mode = storage_mode_sparse - , bool paused = false - , storage_constructor_type sc = default_storage_constructor - , void* userdata = 0) TORRENT_DEPRECATED; -#endif - - torrent_handle TORRENT_EXPORT add_magnet_uri(session& ses, std::string const& uri - , add_torrent_params p); -} - -#endif - diff --git a/libtorrent/include/libtorrent/natpmp.hpp b/libtorrent/include/libtorrent/natpmp.hpp deleted file mode 100644 index 8ce54132b..000000000 --- a/libtorrent/include/libtorrent/natpmp.hpp +++ /dev/null @@ -1,162 +0,0 @@ -/* - -Copyright (c) 2007, Arvid Norberg -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions -are met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in - the documentation and/or other materials provided with the distribution. - * Neither the name of the author nor the names of its - contributors may be used to endorse or promote products derived - from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -POSSIBILITY OF SUCH DAMAGE. - -*/ - -#ifndef TORRENT_NATPMP_HPP -#define TORRENT_NATPMP_HPP - -#include "libtorrent/socket.hpp" -#include "libtorrent/intrusive_ptr_base.hpp" - -#include -#include - -#if defined(TORRENT_LOGGING) || defined(TORRENT_VERBOSE_LOGGING) -#include -#endif - -namespace libtorrent -{ - -// int: port mapping index -// int: external port -// std::string: error message -typedef boost::function portmap_callback_t; - -class natpmp : public intrusive_ptr_base -{ -public: - natpmp(io_service& ios, address const& listen_interface, portmap_callback_t const& cb); - - void rebind(address const& listen_interface); - - // maps the ports, if a port is set to 0 - // it will not be mapped - enum protocol_type { none = 0, udp = 1, tcp = 2 }; - int add_mapping(protocol_type p, int external_port, int local_port); - void delete_mapping(int mapping_index); - - void close(); - -private: - - void update_mapping(int i); - void send_map_request(int i); - void resend_request(int i, error_code const& e); - void on_reply(error_code const& e - , std::size_t bytes_transferred); - void try_next_mapping(int i); - void update_expiration_timer(); - void mapping_expired(error_code const& e, int i); - - void disable(char const* message); - - struct mapping_t - { - enum action_t { action_none, action_add, action_delete }; - mapping_t() - : action(action_none) - , local_port(0) - , external_port(0) - , protocol(none) - {} - - // indicates that the mapping has changed - // and needs an update - int action; - - // the time the port mapping will expire - ptime expires; - - // the local port for this mapping. If this is set - // to 0, the mapping is not in use - int local_port; - - // the external (on the NAT router) port - // for the mapping. This is the port we - // should announce to others - int external_port; - - int protocol; - }; - - portmap_callback_t m_callback; - - std::vector m_mappings; - - // the endpoint to the nat router - udp::endpoint m_nat_endpoint; - - // this is the mapping that is currently - // being updated. It is -1 in case no - // mapping is being updated at the moment - int m_currently_mapping; - - // current retry count - int m_retry_count; - - // used to receive responses in - char m_response_buffer[16]; - - // the endpoint we received the message from - udp::endpoint m_remote; - - // the udp socket used to communicate - // with the NAT router - datagram_socket m_socket; - - // used to resend udp packets in case - // they time out - deadline_timer m_send_timer; - - // timer used to refresh mappings - deadline_timer m_refresh_timer; - - // the mapping index that will expire next - int m_next_refresh; - - bool m_disabled; - - bool m_abort; - - typedef boost::mutex mutex_t; - mutex_t m_mutex; - -#if defined(TORRENT_LOGGING) || defined(TORRENT_VERBOSE_LOGGING) - std::ofstream m_log; -#endif -}; - -} - - -#endif - diff --git a/libtorrent/include/libtorrent/parse_url.hpp b/libtorrent/include/libtorrent/parse_url.hpp deleted file mode 100644 index 18a6ddf90..000000000 --- a/libtorrent/include/libtorrent/parse_url.hpp +++ /dev/null @@ -1,59 +0,0 @@ -/* - -Copyright (c) 2008, Arvid Norberg -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions -are met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in - the documentation and/or other materials provided with the distribution. - * Neither the name of the author nor the names of its - contributors may be used to endorse or promote products derived - from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -POSSIBILITY OF SUCH DAMAGE. - -*/ - -#ifndef TORRENT_PARSE_URL_HPP_INCLUDED -#define TORRENT_PARSE_URL_HPP_INCLUDED - -#ifdef _MSC_VER -#pragma warning(push, 1) -#endif - -#include - -#ifdef _MSC_VER -#pragma warning(pop) -#endif - -#include -#include "libtorrent/config.hpp" - -namespace libtorrent -{ - - TORRENT_EXPORT boost::tuple - parse_url_components(std::string url); - -} - -#endif - diff --git a/libtorrent/include/libtorrent/pch.hpp b/libtorrent/include/libtorrent/pch.hpp deleted file mode 100644 index de937c596..000000000 --- a/libtorrent/include/libtorrent/pch.hpp +++ /dev/null @@ -1,127 +0,0 @@ -/* - -Copyright (c) 2008, Arvid Norberg -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions -are met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in - the documentation and/or other materials provided with the distribution. - * Neither the name of the author nor the names of its - contributors may be used to endorse or promote products derived - from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -POSSIBILITY OF SUCH DAMAGE. - -*/ - -#ifdef BOOST_BUILD_PCH_ENABLED - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#ifdef __OBJC__ -#define Protocol Protocol_ -#endif - -#include -#include -#include -#include -#include - -#ifdef __OBJC__ -#undef Protocol -#endif - -#endif - diff --git a/libtorrent/include/libtorrent/pe_crypto.hpp b/libtorrent/include/libtorrent/pe_crypto.hpp deleted file mode 100644 index c0c43e7fb..000000000 --- a/libtorrent/include/libtorrent/pe_crypto.hpp +++ /dev/null @@ -1,126 +0,0 @@ -/* - -Copyright (c) 2007, Un Shyam -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions -are met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in - the documentation and/or other materials provided with the distribution. - * Neither the name of the author nor the names of its - contributors may be used to endorse or promote products derived - from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -POSSIBILITY OF SUCH DAMAGE. - -*/ - -#ifndef TORRENT_DISABLE_ENCRYPTION - -#ifndef TORRENT_PE_CRYPTO_HPP_INCLUDED -#define TORRENT_PE_CRYPTO_HPP_INCLUDED - -#include -#include -#include - -#include "libtorrent/peer_id.hpp" // For sha1_hash -#include "libtorrent/assert.hpp" - -namespace libtorrent -{ - class dh_key_exchange - { - public: - dh_key_exchange(); - ~dh_key_exchange(); - bool good() const { return m_dh; } - - // Get local public key, always 96 bytes - char const* get_local_key() const; - - // read remote_pubkey, generate and store shared secret in - // m_dh_secret. - int compute_secret(const char* remote_pubkey); - - char const* get_secret() const { return m_dh_secret; } - - sha1_hash const& get_hash_xor_mask() const { return m_xor_mask; } - - private: - int get_local_key_size() const - { - TORRENT_ASSERT(m_dh); - return BN_num_bytes(m_dh->pub_key); - } - - DH* m_dh; - - char m_dh_local_key[96]; - char m_dh_secret[96]; - sha1_hash m_xor_mask; - }; - - class RC4_handler // Non copyable - { - public: - // Input longkeys must be 20 bytes - RC4_handler(const sha1_hash& rc4_local_longkey, - const sha1_hash& rc4_remote_longkey) - { - RC4_set_key(&m_local_key, 20, - reinterpret_cast(rc4_local_longkey.begin())); - RC4_set_key(&m_remote_key, 20, - reinterpret_cast(rc4_remote_longkey.begin())); - - // Discard first 1024 bytes - char buf[1024]; - encrypt(buf, 1024); - decrypt(buf, 1024); - }; - - ~RC4_handler() {}; - - void encrypt(char* pos, int len) - { - TORRENT_ASSERT(len >= 0); - TORRENT_ASSERT(pos); - - RC4(&m_local_key, len, reinterpret_cast(pos), - reinterpret_cast(pos)); - } - - void decrypt(char* pos, int len) - { - TORRENT_ASSERT(len >= 0); - TORRENT_ASSERT(pos); - - RC4(&m_remote_key, len, reinterpret_cast(pos), - reinterpret_cast(pos)); - } - - private: - RC4_KEY m_local_key; // Key to encrypt outgoing data - RC4_KEY m_remote_key; // Key to decrypt incoming data - }; - -} // namespace libtorrent - -#endif // TORRENT_PE_CRYPTO_HPP_INCLUDED -#endif // TORRENT_DISABLE_ENCRYPTION - diff --git a/libtorrent/include/libtorrent/peer.hpp b/libtorrent/include/libtorrent/peer.hpp deleted file mode 100644 index c404a611d..000000000 --- a/libtorrent/include/libtorrent/peer.hpp +++ /dev/null @@ -1,63 +0,0 @@ -/* - -Copyright (c) 2003, Arvid Norberg -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions -are met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in - the documentation and/or other materials provided with the distribution. - * Neither the name of the author nor the names of its - contributors may be used to endorse or promote products derived - from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -POSSIBILITY OF SUCH DAMAGE. - -*/ - -#ifndef TORRENT_PEER_HPP_INCLUDED -#define TORRENT_PEER_HPP_INCLUDED - -#include - -#include "libtorrent/peer_id.hpp" - -namespace libtorrent -{ - - struct TORRENT_EXPORT peer_entry - { - std::string ip; - int port; - peer_id pid; - - bool operator==(const peer_entry& p) const - { - return pid == p.pid; - } - - bool operator<(const peer_entry& p) const - { - return pid < p.pid; - } - }; - -} - -#endif // TORRENT_PEER_HPP_INCLUDED - diff --git a/libtorrent/include/libtorrent/peer_connection.hpp b/libtorrent/include/libtorrent/peer_connection.hpp deleted file mode 100644 index bc339f2ce..000000000 --- a/libtorrent/include/libtorrent/peer_connection.hpp +++ /dev/null @@ -1,887 +0,0 @@ -/* - -Copyright (c) 2003, Arvid Norberg -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions -are met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in - the documentation and/or other materials provided with the distribution. - * Neither the name of the author nor the names of its - contributors may be used to endorse or promote products derived - from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -POSSIBILITY OF SUCH DAMAGE. - -*/ - -#ifndef TORRENT_PEER_CONNECTION_HPP_INCLUDED -#define TORRENT_PEER_CONNECTION_HPP_INCLUDED - -#include -#include -#include -#include -#include - -#include "libtorrent/debug.hpp" - -#ifdef _MSC_VER -#pragma warning(push, 1) -#endif - -#include -#include -#include -#include -#include -#include -#include - -#ifdef _MSC_VER -#pragma warning(pop) -#endif - -#include "libtorrent/buffer.hpp" -#include "libtorrent/socket.hpp" -#include "libtorrent/peer_id.hpp" -#include "libtorrent/storage.hpp" -#include "libtorrent/stat.hpp" -#include "libtorrent/alert.hpp" -#include "libtorrent/torrent_handle.hpp" -#include "libtorrent/torrent.hpp" -#include "libtorrent/peer_request.hpp" -#include "libtorrent/piece_block_progress.hpp" -#include "libtorrent/config.hpp" -#include "libtorrent/session.hpp" -#include "libtorrent/bandwidth_limit.hpp" -#include "libtorrent/policy.hpp" -#include "libtorrent/socket_type.hpp" -#include "libtorrent/intrusive_ptr_base.hpp" -#include "libtorrent/assert.hpp" -#include "libtorrent/chained_buffer.hpp" -#include "libtorrent/disk_buffer_holder.hpp" -#include "libtorrent/bitfield.hpp" - -#ifdef TORRENT_STATS -#include "libtorrent/aux_/session_impl.hpp" -#endif - -namespace libtorrent -{ - class torrent; - struct peer_plugin; - - namespace detail - { - struct session_impl; - } - - struct pending_block - { - pending_block(piece_block const& b): skipped(0), block(b) {} - int skipped; - // the number of times the request - // has been skipped by out of order blocks - piece_block block; - }; - - struct has_block - { - has_block(piece_block const& b): block(b) {} - piece_block const& block; - bool operator()(pending_block const& pb) const - { return pb.block == block; } - }; - - class TORRENT_EXPORT peer_connection - : public intrusive_ptr_base - , public boost::noncopyable - { - friend class invariant_access; - public: - - enum channels - { - upload_channel, - download_channel, - num_channels - }; - - // this is the constructor where the we are the active part. - // The peer_conenction should handshake and verify that the - // other end has the correct id - peer_connection( - aux::session_impl& ses - , boost::weak_ptr t - , boost::shared_ptr s - , tcp::endpoint const& remote - , policy::peer* peerinfo); - - // with this constructor we have been contacted and we still don't - // know which torrent the connection belongs to - peer_connection( - aux::session_impl& ses - , boost::shared_ptr s - , tcp::endpoint const& remote - , policy::peer* peerinfo); - - // this function is called after it has been constructed and properly - // reference counted. It is safe to call self() in this function - // and schedule events with references to itself (that is not safe to - // do in the constructor). - virtual void start(); - - virtual ~peer_connection(); - - void set_peer_info(policy::peer* pi) - { m_peer_info = pi; } - - policy::peer* peer_info_struct() const - { return m_peer_info; } - - enum peer_speed_t { slow = 1, medium, fast }; - peer_speed_t peer_speed(); - - void send_allowed_set(); - -#ifndef TORRENT_DISABLE_EXTENSIONS - void add_extension(boost::shared_ptr); -#endif - - // this function is called once the torrent associated - // with this peer connection has retrieved the meta- - // data. If the torrent was spawned with metadata - // this is called from the constructor. - void init(); - - // this is called when the metadata is retrieved - // and the files has been checked - virtual void on_metadata() {}; - - void on_metadata_impl(); - - void set_upload_limit(int limit); - void set_download_limit(int limit); - - int upload_limit() const { return m_upload_limit; } - int download_limit() const { return m_download_limit; } - - int prefer_whole_pieces() const - { - if (on_parole()) return 1; - return m_prefer_whole_pieces; - } - - bool on_parole() const - { return peer_info_struct() && peer_info_struct()->on_parole; } - - int picker_options() const; - - void prefer_whole_pieces(int num) - { m_prefer_whole_pieces = num; } - - bool request_large_blocks() const - { return m_request_large_blocks; } - - void request_large_blocks(bool b) - { m_request_large_blocks = b; } - - void set_priority(int p) - { m_priority = p; } - - void fast_reconnect(bool r); - bool fast_reconnect() const { return m_fast_reconnect; } - - // this adds an announcement in the announcement queue - // it will let the peer know that we have the given piece - void announce_piece(int index); - - // tells if this connection has data it want to send - // and has enough upload bandwidth quota left to send it. - bool can_write() const; - bool can_read() const; - - bool is_seed() const; - - void set_upload_only(bool u) - { - m_upload_only = u; - disconnect_if_redundant(); - } - - bool upload_only() const { return m_upload_only; } - - // will send a keep-alive message to the peer - void keep_alive(); - - peer_id const& pid() const { return m_peer_id; } - void set_pid(const peer_id& pid) { m_peer_id = pid; } - bool has_piece(int i) const; - - std::deque const& download_queue() const; - std::deque const& request_queue() const; - std::deque const& upload_queue() const; - - bool is_interesting() const { return m_interesting; } - bool is_choked() const { return m_choked; } - - bool is_peer_interested() const { return m_peer_interested; } - bool has_peer_choked() const { return m_peer_choked; } - - void update_interest(); - - virtual void get_peer_info(peer_info& p) const; - - // returns the torrent this connection is a part of - // may be zero if the connection is an incoming connection - // and it hasn't received enough information to determine - // which torrent it should be associated with - boost::weak_ptr associated_torrent() const - { return m_torrent; } - - const stat& statistics() const { return m_statistics; } - void add_stat(size_type downloaded, size_type uploaded); - - void calc_ip_overhead(); - - // is called once every second by the main loop - void second_tick(float tick_interval); - - void timeout_requests(); - - boost::shared_ptr get_socket() const { return m_socket; } - tcp::endpoint const& remote() const { return m_remote; } - - bitfield const& get_bitfield() const; - std::vector const& allowed_fast(); - std::vector const& suggested_pieces() const { return m_suggested_pieces; } - - ptime connected_time() const { return m_connect; } - ptime last_received() const { return m_last_receive; } - - void timed_out(); - // this will cause this peer_connection to be disconnected. - void disconnect(char const* message, int error = 0); - bool is_disconnecting() const { return m_disconnecting; } - - // this is called when the connection attempt has succeeded - // and the peer_connection is supposed to set m_connecting - // to false, and stop monitor writability - void on_connection_complete(error_code const& e); - - // returns true if this connection is still waiting to - // finish the connection attempt - bool is_connecting() const { return m_connecting; } - - // returns true if the socket of this peer hasn't been - // attempted to connect yet (i.e. it's queued for - // connection attempt). - bool is_queued() const { return m_queued; } - - // called when it's time for this peer_conncetion to actually - // initiate the tcp connection. This may be postponed until - // the library isn't using up the limitation of half-open - // tcp connections. - void connect(int ticket); - - // This is called for every peer right after the upload - // bandwidth has been distributed among them - // It will reset the used bandwidth to 0. - void reset_upload_quota(); - - // free upload. - size_type total_free_upload() const; - void add_free_upload(size_type free_upload); - - // trust management. - void received_valid_data(int index); - void received_invalid_data(int index); - - size_type share_diff() const; - - // a connection is local if it was initiated by us. - // if it was an incoming connection, it is remote - bool is_local() const { return m_active; } - - bool on_local_network() const; - bool ignore_bandwidth_limits() const - { return m_ignore_bandwidth_limits; } - - bool failed() const { return m_failed; } - - int desired_queue_size() const { return m_desired_queue_size; } - - // compares this connection against the given connection - // for which one is more eligible for an unchoke. - // returns true if this is more eligible - bool unchoke_compare(boost::intrusive_ptr const& p) const; - - // resets the byte counters that are used to measure - // the number of bytes transferred within unchoke cycles - void reset_choke_counters(); - - // if this peer connection is useless (neither party is - // interested in the other), disconnect it - void disconnect_if_redundant(); - -#if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_ERROR_LOGGING - boost::shared_ptr m_logger; -#endif - - // the message handlers are called - // each time a recv() returns some new - // data, the last time it will be called - // is when the entire packet has been - // received, then it will no longer - // be called. i.e. most handlers need - // to check how much of the packet they - // have received before any processing - void incoming_keepalive(); - void incoming_choke(); - void incoming_unchoke(); - void incoming_interested(); - void incoming_not_interested(); - void incoming_have(int piece_index); - void incoming_bitfield(bitfield const& bits); - void incoming_request(peer_request const& r); - void incoming_piece(peer_request const& p, disk_buffer_holder& data); - void incoming_piece(peer_request const& p, char const* data); - void incoming_piece_fragment(); - void incoming_cancel(peer_request const& r); - - void incoming_dht_port(int listen_port); - - void incoming_reject_request(peer_request const& r); - void incoming_have_all(); - void incoming_have_none(); - void incoming_allowed_fast(int index); - void incoming_suggest(int index); - - // the following functions appends messages - // to the send buffer - void send_choke(); - bool send_unchoke(); - void send_interested(); - void send_not_interested(); - - void snub_peer(); - - // adds a block to the request queue - void add_request(piece_block const& b); - // removes a block from the request queue or download queue - // sends a cancel message if appropriate - // refills the request queue, and possibly ignoring pieces requested - // by peers in the ignore list (to avoid recursion) - void cancel_request(piece_block const& b); - void send_block_requests(); - - int max_assignable_bandwidth(int channel) const - { return m_bandwidth_limit[channel].max_assignable(); } - - int bandwidth_throttle(int channel) const - { return m_bandwidth_limit[channel].throttle(); } - - void assign_bandwidth(int channel, int amount); - void expire_bandwidth(int channel, int amount); - -#ifdef TORRENT_DEBUG - void check_invariant() const; - ptime m_last_choke; -#endif - - - // is true until we can be sure that the other end - // speaks our protocol (be it bittorrent or http). - virtual bool in_handshake() const = 0; - - // returns the block currently being - // downloaded. And the progress of that - // block. If the peer isn't downloading - // a piece for the moment, the boost::optional - // will be invalid. - virtual boost::optional - downloading_piece_progress() const - { -#ifdef TORRENT_VERBOSE_LOGGING - (*m_logger) << "downloading_piece_progress() dispatched to the base class!\n"; -#endif - return boost::optional(); - } - - // these functions are virtual to let bt_peer_connection hook into them - // and encrypt the content - enum message_type_flags { message_type_request = 1 }; - virtual void send_buffer(char const* begin, int size, int flags = 0); - virtual buffer::interval allocate_send_buffer(int size); - virtual void setup_send(); - - template - void append_send_buffer(char* buffer, int size, Destructor const& destructor) - { - m_send_buffer.append_buffer(buffer, size, size, destructor); -#ifdef TORRENT_STATS - m_ses.m_buffer_usage_logger << log_time() << " append_send_buffer: " << size << std::endl; - m_ses.log_buffer_usage(); -#endif - } - -#ifndef TORRENT_DISABLE_RESOLVE_COUNTRIES - void set_country(char const* c) - { - TORRENT_ASSERT(strlen(c) == 2); - m_country[0] = c[0]; - m_country[1] = c[1]; - } - bool has_country() const { return m_country[0] != 0; } -#endif - - int send_buffer_size() const - { return m_send_buffer.size(); } - - int send_buffer_capacity() const - { return m_send_buffer.capacity(); } - - int packet_size() const { return m_packet_size; } - - bool packet_finished() const - { return m_packet_size <= m_recv_pos; } - -#ifdef TORRENT_DEBUG - bool piece_failed; -#endif - - // upload and download channel state - // enum from peer_info::bw_state - char m_channel_state[2]; - - protected: - - virtual void get_specific_peer_info(peer_info& p) const = 0; - - virtual void write_choke() = 0; - virtual void write_unchoke() = 0; - virtual void write_interested() = 0; - virtual void write_not_interested() = 0; - virtual void write_request(peer_request const& r) = 0; - virtual void write_cancel(peer_request const& r) = 0; - virtual void write_have(int index) = 0; - virtual void write_keepalive() = 0; - virtual void write_piece(peer_request const& r, disk_buffer_holder& buffer) = 0; - - virtual void write_reject_request(peer_request const& r) = 0; - virtual void write_allow_fast(int piece) = 0; - - virtual void on_connected() = 0; - virtual void on_tick() {} - - virtual void on_receive(error_code const& error - , std::size_t bytes_transferred) = 0; - virtual void on_sent(error_code const& error - , std::size_t bytes_transferred) = 0; - -#ifndef TORRENT_DISABLE_ENCRYPTION - buffer::interval wr_recv_buffer() - { - TORRENT_ASSERT(!m_disk_recv_buffer); - TORRENT_ASSERT(m_disk_recv_buffer_size == 0); - if (m_recv_buffer.empty()) return buffer::interval(0,0); - return buffer::interval(&m_recv_buffer[0] - , &m_recv_buffer[0] + m_recv_pos); - } - - std::pair wr_recv_buffers(int bytes); -#endif - - buffer::const_interval receive_buffer() const - { - if (m_recv_buffer.empty()) return buffer::const_interval(0,0); - return buffer::const_interval(&m_recv_buffer[0] - , &m_recv_buffer[0] + m_recv_pos); - } - - bool allocate_disk_receive_buffer(int disk_buffer_size); - char* release_disk_receive_buffer(); - bool has_disk_receive_buffer() const { return m_disk_recv_buffer; } - void cut_receive_buffer(int size, int packet_size); - void reset_recv_buffer(int packet_size); - - void setup_receive(); - - void attach_to_torrent(sha1_hash const& ih); - - bool verify_piece(peer_request const& p) const; - - // the bandwidth channels, upload and download - // keeps track of the current quotas - bandwidth_limit m_bandwidth_limit[num_channels]; - - // statistics about upload and download speeds - // and total amount of uploads and downloads for - // this peer - stat m_statistics; - - // a back reference to the session - // the peer belongs to. - aux::session_impl& m_ses; - - // called from the main loop when this connection has any - // work to do. - void on_send_data(error_code const& error - , std::size_t bytes_transferred); - void on_receive_data(error_code const& error - , std::size_t bytes_transferred); - - // this is the limit on the number of outstanding requests - // we have to this peer. This is initialized to the settings - // in the session_settings structure. But it may be lowered - // if the peer is known to require a smaller limit (like BitComet). - // or if the extended handshake sets a limit. - // web seeds also has a limit on the queue size. - int m_max_out_request_queue; - - void set_timeout(int s) { m_timeout = s; } - -#ifndef TORRENT_DISABLE_EXTENSIONS - typedef std::list > extension_list_t; - extension_list_t m_extensions; -#endif - -#ifndef TORRENT_DISABLE_RESOLVE_COUNTRIES - // in case the session settings is set - // to resolve countries, this is set to - // the two character country code this - // peer resides in. - char m_country[2]; -#endif - -#ifdef TORRENT_DEBUG - boost::intrusive_ptr self() - { - TORRENT_ASSERT(!m_in_constructor); - return intrusive_ptr_base::self(); - } -#endif - - private: - - void fill_send_buffer(); - void on_disk_read_complete(int ret, disk_io_job const& j, peer_request r); - void on_disk_write_complete(int ret, disk_io_job const& j - , peer_request r, boost::shared_ptr t); - - // the time when we last got a part of a - // piece packet from this peer - ptime m_last_piece; - // the time we sent a request to - // this peer the last time - ptime m_last_request; - // the time we received the last - // piece request from the peer - ptime m_last_incoming_request; - // the time when we unchoked this peer - ptime m_last_unchoke; - - // timeouts - ptime m_last_receive; - ptime m_last_sent; - - // the time when the first entry in the - // request queue was requested, increased - // for each entry that is popped from the - // download queue. Used for request timeout - ptime m_requested; - - // if the timeout is extended for the outstanding - // requests, this is the number of seconds it was - // extended. - int m_timeout_extend; - - // a timestamp when the remote download rate - // was last updated - ptime m_remote_dl_update; - - // the time when async_connect was called - // or when the incoming connection was established - ptime m_connect; - - // the time when this peer sent us a not_interested message - // the last time. - ptime m_became_uninterested; - - // the time when we sent a not_interested message to - // this peer the last time. - ptime m_became_uninteresting; - - // the amount of data this peer has been given - // as free upload. This is distributed from - // peers from which we get free download - // this will be negative on a peer from which - // we get free download, and positive on peers - // that we give the free upload, to keep the balance. - size_type m_free_upload; - - // the total payload download bytes - // at the last unchoke cycle. This is used to - // measure the number of bytes transferred during - // an unchoke cycle, to unchoke peers the more bytes - // they sent us - size_type m_downloaded_at_last_unchoke; - -#ifndef TORRENT_DISABLE_GEO_IP - std::string m_inet_as_name; -#endif - - buffer m_recv_buffer; - - // if this peer is receiving a piece, this - // points to a disk buffer that the data is - // read into. This eliminates a memcopy from - // the receive buffer into the disk buffer - disk_buffer_holder m_disk_recv_buffer; - - chained_buffer m_send_buffer; - - boost::shared_ptr m_socket; - // this is the peer we're actually talking to - // it may not necessarily be the peer we're - // connected to, in case we use a proxy - tcp::endpoint m_remote; - - // this is the torrent this connection is - // associated with. If the connection is an - // incoming conncetion, this is set to zero - // until the info_hash is received. Then it's - // set to the torrent it belongs to. - boost::weak_ptr m_torrent; - - // remote peer's id - peer_id m_peer_id; - - // the pieces the other end have - bitfield m_have_piece; - - // the queue of requests we have got - // from this peer - std::deque m_requests; - - // the blocks we have reserved in the piece - // picker and will request from this peer. - std::deque m_request_queue; - - // the queue of blocks we have requested - // from this peer - std::deque m_download_queue; - - // the pieces we will send to the peer - // if requested (regardless of choke state) - std::set m_accept_fast; - - // the pieces the peer will send us if - // requested (regardless of choke state) - std::vector m_allowed_fast; - - // pieces that has been suggested to be - // downloaded from this peer - std::vector m_suggested_pieces; - - // a list of byte offsets inside the send buffer - // the piece requests - std::vector m_requests_in_buffer; - - // the number of pieces this peer - // has. Must be the same as - // std::count(m_have_piece.begin(), - // m_have_piece.end(), true) - int m_num_pieces; - - // the timeout in seconds - int m_timeout; - - // the size (in bytes) of the bittorrent message - // we're currently receiving - int m_packet_size; - - // the number of bytes of the bittorrent payload - // we've received so far - int m_recv_pos; - - int m_disk_recv_buffer_size; - - // the number of bytes we are currently reading - // from disk, that will be added to the send - // buffer as soon as they complete - int m_reading_bytes; - - // the number of invalid piece-requests - // we have got from this peer. If the request - // queue gets empty, and there have been - // invalid requests, we can assume the - // peer is waiting for those pieces. - // we can then clear its download queue - // by sending choke, unchoke. - int m_num_invalid_requests; - - // this is the priority with which this peer gets - // download bandwidth quota assigned to it. - int m_priority; - - int m_upload_limit; - int m_download_limit; - - // this peer's peer info struct. This may - // be 0, in case the connection is incoming - // and hasn't been added to a torrent yet. - policy::peer* m_peer_info; - - // this is a measurement of how fast the peer - // it allows some variance without changing - // back and forth between states - peer_speed_t m_speed; - - // the ticket id from the connection queue. - // This is used to identify the connection - // so that it can be removed from the queue - // once the connection completes - int m_connection_ticket; - - // bytes downloaded since last second - // timer timeout; used for determining - // approx download rate - int m_remote_bytes_dled; - - // approximate peer download rate - int m_remote_dl_rate; - - // the number of bytes send to the disk-io - // thread that hasn't yet been completely written. - int m_outstanding_writing_bytes; - - // max transfer rates seen on this peer - int m_download_rate_peak; - int m_upload_rate_peak; - - // estimated round trip time to this peer - // based on the time from when async_connect - // was called to when on_connection_complete - // was called. The rtt is specified in milliseconds - boost::uint16_t m_rtt; - - // if set to non-zero, this peer will always prefer - // to request entire n pieces, rather than blocks. - // where n is the value of this variable. - // if it is 0, the download rate limit setting - // will be used to determine if whole pieces - // are preferred. - boost::uint8_t m_prefer_whole_pieces; - - // the number of request we should queue up - // at the remote end. - boost::uint8_t m_desired_queue_size; - - // if this is true, the disconnection - // timestamp is not updated when the connection - // is closed. This means the time until we can - // reconnect to this peer is shorter, and likely - // immediate. - bool m_fast_reconnect:1; - - // is true if it was we that connected to the peer - // and false if we got an incoming connection - // could be considered: true = local, false = remote - bool m_active:1; - - // other side says that it's interested in downloading - // from us. - bool m_peer_interested:1; - - // the other side has told us that it won't send anymore - // data to us for a while - bool m_peer_choked:1; - - // the peer has pieces we are interested in - bool m_interesting:1; - - // we have choked the upload to the peer - bool m_choked:1; - - // this is set to true if the connection timed - // out or closed the connection. In that - // case we will not try to reconnect to - // this peer - bool m_failed:1; - - // if this is set to true, the peer will not - // request bandwidth from the limiter, but instead - // just send and receive as much as possible. - bool m_ignore_bandwidth_limits:1; - - // this is set to true when a have_all - // message is received. This information - // is used to fill the bitmask in init() - bool m_have_all:1; - - // this is true if this connection has been added - // to the list of connections that will be closed. - bool m_disconnecting:1; - - // this is true until this socket has become - // writable for the first time (i.e. the - // connection completed). While connecting - // the timeout will not be triggered. This is - // because windows XP SP2 may delay connection - // attempts, which means that the connection - // may not even have been attempted when the - // time out is reached. - bool m_connecting:1; - - // This is true until connect is called on the - // peer_connection's socket. It is false on incoming - // connections. - bool m_queued:1; - - // if this is true, the blocks picked by the piece - // picker will be merged before passed to the - // request function. i.e. subsequent blocks are - // merged into larger blocks. This is used by - // the http-downloader, to request whole pieces - // at a time. - bool m_request_large_blocks:1; - - // set to true when this peer is only uploading - bool m_upload_only:1; - - // set to true when a piece request times out. The - // result is that the desired pending queue size - // is set to 1 - bool m_snubbed:1; - - // this is set to true once the bitfield is received - bool m_bitfield_received:1; - -#ifdef TORRENT_DEBUG - public: - bool m_in_constructor:1; - bool m_disconnect_started:1; - bool m_initialized:1; -#endif - }; -} - -#endif // TORRENT_PEER_CONNECTION_HPP_INCLUDED - diff --git a/libtorrent/include/libtorrent/peer_id.hpp b/libtorrent/include/libtorrent/peer_id.hpp deleted file mode 100644 index d737fb4fb..000000000 --- a/libtorrent/include/libtorrent/peer_id.hpp +++ /dev/null @@ -1,196 +0,0 @@ -/* - -Copyright (c) 2003, Arvid Norberg -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions -are met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in - the documentation and/or other materials provided with the distribution. - * Neither the name of the author nor the names of its - contributors may be used to endorse or promote products derived - from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -POSSIBILITY OF SUCH DAMAGE. - -*/ - -#ifndef TORRENT_PEER_ID_HPP_INCLUDED -#define TORRENT_PEER_ID_HPP_INCLUDED - -#include -#include -#include -#include -#include -#include - -#include "libtorrent/config.hpp" -#include "libtorrent/assert.hpp" -#include "libtorrent/escape_string.hpp" - -namespace libtorrent -{ - - class TORRENT_EXPORT big_number - { - // the number of bytes of the number - enum { number_size = 20 }; - public: - enum { size = number_size }; - - big_number() {} - - explicit big_number(char const* s) - { - if (s == 0) clear(); - else std::memcpy(m_number, s, size); - } - - explicit big_number(std::string const& s) - { - TORRENT_ASSERT(s.size() >= 20); - int sl = int(s.size()) < size ? int(s.size()) : size; - std::memcpy(m_number, &s[0], sl); - } - - void clear() - { - std::fill(m_number,m_number+number_size,0); - } - - bool is_all_zeros() const - { - return std::count(m_number,m_number+number_size,0) == number_size; - } - - bool operator==(big_number const& n) const - { - return std::equal(n.m_number, n.m_number+number_size, m_number); - } - - bool operator!=(big_number const& n) const - { - return !std::equal(n.m_number, n.m_number+number_size, m_number); - } - - bool operator<(big_number const& n) const - { - for (int i = 0; i < number_size; ++i) - { - if (m_number[i] < n.m_number[i]) return true; - if (m_number[i] > n.m_number[i]) return false; - } - return false; - } - - big_number operator~() - { - big_number ret; - for (int i = 0; i< number_size; ++i) - ret.m_number[i] = ~m_number[i]; - return ret; - } - - big_number& operator &= (big_number const& n) - { - for (int i = 0; i< number_size; ++i) - m_number[i] &= n.m_number[i]; - return *this; - } - - big_number& operator |= (big_number const& n) - { - for (int i = 0; i< number_size; ++i) - m_number[i] |= n.m_number[i]; - return *this; - } - - big_number& operator ^= (big_number const& n) - { - for (int i = 0; i< number_size; ++i) - m_number[i] ^= n.m_number[i]; - return *this; - } - - unsigned char& operator[](int i) - { TORRENT_ASSERT(i >= 0 && i < number_size); return m_number[i]; } - - unsigned char const& operator[](int i) const - { TORRENT_ASSERT(i >= 0 && i < number_size); return m_number[i]; } - - typedef const unsigned char* const_iterator; - typedef unsigned char* iterator; - - const_iterator begin() const { return m_number; } - const_iterator end() const { return m_number+number_size; } - - iterator begin() { return m_number; } - iterator end() { return m_number+number_size; } - - std::string to_string() const - { return std::string((char const*)&m_number[0], number_size); } - - private: - - unsigned char m_number[number_size]; - - }; - - typedef big_number peer_id; - typedef big_number sha1_hash; - - inline std::ostream& operator<<(std::ostream& os, big_number const& peer) - { - for (big_number::const_iterator i = peer.begin(); - i != peer.end(); ++i) - { - os << std::hex << std::setw(2) << std::setfill('0') - << static_cast(*i); - } - os << std::dec << std::setfill(' '); - return os; - } - - inline std::istream& operator>>(std::istream& is, big_number& peer) - { - for (big_number::iterator i = peer.begin(); - i != peer.end(); ++i) - { - char c[2]; - is >> c[0] >> c[1]; - c[0] = tolower(c[0]); - c[1] = tolower(c[1]); - if ( - ((c[0] < '0' || c[0] > '9') && (c[0] < 'a' || c[0] > 'f')) - || ((c[1] < '0' || c[1] > '9') && (c[1] < 'a' || c[1] > 'f')) - || is.fail()) - { - is.setstate(std::ios_base::failbit); - return is; - } - *i = ((is_digit(c[0])?c[0]-'0':c[0]-'a'+10) << 4) - + (is_digit(c[1])?c[1]-'0':c[1]-'a'+10); - } - return is; - } - -} - -#endif // TORRENT_PEER_ID_HPP_INCLUDED - diff --git a/libtorrent/include/libtorrent/peer_info.hpp b/libtorrent/include/libtorrent/peer_info.hpp deleted file mode 100644 index a2bbc3056..000000000 --- a/libtorrent/include/libtorrent/peer_info.hpp +++ /dev/null @@ -1,218 +0,0 @@ -/* - -Copyright (c) 2003, Arvid Norberg -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions -are met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in - the documentation and/or other materials provided with the distribution. - * Neither the name of the author nor the names of its - contributors may be used to endorse or promote products derived - from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -POSSIBILITY OF SUCH DAMAGE. - -*/ - -#ifndef TORRENT_PEER_INFO_HPP_INCLUDED -#define TORRENT_PEER_INFO_HPP_INCLUDED - -#include "libtorrent/socket.hpp" -#include "libtorrent/peer_id.hpp" -#include "libtorrent/size_type.hpp" -#include "libtorrent/config.hpp" -#include "libtorrent/bitfield.hpp" - -namespace libtorrent -{ - struct TORRENT_EXPORT peer_info - { - enum - { - interesting = 0x1, - choked = 0x2, - remote_interested = 0x4, - remote_choked = 0x8, - supports_extensions = 0x10, - local_connection = 0x20, - handshake = 0x40, - connecting = 0x80, - queued = 0x100, - on_parole = 0x200, - seed = 0x400, - optimistic_unchoke = 0x800, - snubbed = 0x1000, - upload_only = 0x2000 -#ifndef TORRENT_DISABLE_ENCRYPTION - , rc4_encrypted = 0x100000, - plaintext_encrypted = 0x200000 -#endif - }; - - unsigned int flags; - - enum peer_source_flags - { - tracker = 0x1, - dht = 0x2, - pex = 0x4, - lsd = 0x8, - resume_data = 0x10, - incoming = 0x20 - }; - - int source; - - // bw_idle: the channel is not used - // bw_torrent: the channel is waiting for torrent quota - // bw_global: the channel is waiting for global quota - // bw_network: the channel is waiting for an async write - // for read operation to complete - enum bw_state { bw_idle, bw_torrent, bw_global, bw_network }; - - char read_state; - char write_state; - - tcp::endpoint ip; - float up_speed; - float down_speed; - float payload_up_speed; - float payload_down_speed; - size_type total_download; - size_type total_upload; - peer_id pid; - bitfield pieces; - int upload_limit; - int download_limit; - - // time since last request - time_duration last_request; - - // time since last download or upload - time_duration last_active; - - // the number of seconds until the current - // pending request times out - int request_timeout; - - // the size of the send buffer for this peer, in bytes - int send_buffer_size; - // the number bytes that's actually used of the send buffer - int used_send_buffer; - - int receive_buffer_size; - int used_receive_buffer; - - // the number of failed hashes for this peer - int num_hashfails; - -#ifndef TORRENT_DISABLE_RESOLVE_COUNTRIES - // in case the session settings is set - // to resolve countries, this is set to - // the two character country code this - // peer resides in. - char country[2]; -#endif - -#ifndef TORRENT_DISABLE_GEO_IP - // atonomous system this peer belongs to - std::string inet_as_name; - int inet_as; -#endif - - size_type load_balancing; - - // this is the number of requests - // we have sent to this peer - // that we haven't got a response - // for yet - int download_queue_length; - - // the number of request messages - // waiting to be sent inside the send buffer - int requests_in_buffer; - - // the number of requests that is - // tried to be maintained (this is - // typically a function of download speed) - int target_dl_queue_length; - - // this is the number of requests - // the peer has sent to us - // that we haven't sent yet - int upload_queue_length; - - // the number of times this IP - // has failed to connect - int failcount; - - // the currently downloading piece - // if piece index is -1 all associated - // members are just set to 0 - int downloading_piece_index; - int downloading_block_index; - int downloading_progress; - int downloading_total; - - std::string client; - - enum - { - standard_bittorrent = 0, - web_seed = 1 - }; - int connection_type; - - // approximate peer download rate - int remote_dl_rate; - - // number of bytes this peer has in - // the disk write queue - int pending_disk_bytes; - - // numbers used for bandwidth limiting - int send_quota; - int receive_quota; - - // estimated rtt to peer, in milliseconds - int rtt; - - // the highest transfer rates seen for this peer - int download_rate_peak; - int upload_rate_peak; - - // the peers progress - float progress; - }; - - struct TORRENT_EXPORT peer_list_entry - { - enum flags_t - { - banned = 1 - }; - - tcp::endpoint ip; - int flags; - boost::uint8_t failcount; - boost::uint8_t source; - }; -} - -#endif // TORRENT_PEER_INFO_HPP_INCLUDED diff --git a/libtorrent/include/libtorrent/peer_request.hpp b/libtorrent/include/libtorrent/peer_request.hpp deleted file mode 100644 index 445ff4d7e..000000000 --- a/libtorrent/include/libtorrent/peer_request.hpp +++ /dev/null @@ -1,49 +0,0 @@ -/* - -Copyright (c) 2006, Arvid Norberg -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions -are met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in - the documentation and/or other materials provided with the distribution. - * Neither the name of the author nor the names of its - contributors may be used to endorse or promote products derived - from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -POSSIBILITY OF SUCH DAMAGE. - -*/ - -#ifndef TORRENT_PEER_REQUEST_HPP_INCLUDED -#define TORRENT_PEER_REQUEST_HPP_INCLUDED - -namespace libtorrent -{ - struct TORRENT_EXPORT peer_request - { - int piece; - int start; - int length; - bool operator==(peer_request const& r) const - { return piece == r.piece && start == r.start && length == r.length; } - }; -} - -#endif // TORRENT_PEER_REQUEST_HPP_INCLUDED - diff --git a/libtorrent/include/libtorrent/piece_block_progress.hpp b/libtorrent/include/libtorrent/piece_block_progress.hpp deleted file mode 100644 index 481ffc971..000000000 --- a/libtorrent/include/libtorrent/piece_block_progress.hpp +++ /dev/null @@ -1,57 +0,0 @@ -/* - -Copyright (c) 2003, Arvid Norberg -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions -are met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in - the documentation and/or other materials provided with the distribution. - * Neither the name of the author nor the names of its - contributors may be used to endorse or promote products derived - from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -POSSIBILITY OF SUCH DAMAGE. - -*/ - -#ifndef TORRENT_PIECE_BLOCK_PROGRESS_HPP_INCLUDED -#define TORRENT_PIECE_BLOCK_PROGRESS_HPP_INCLUDED - -#include "libtorrent/config.hpp" - -namespace libtorrent -{ - struct TORRENT_EXPORT piece_block_progress - { - // the piece and block index - // determines exactly which - // part of the torrent that - // is currently being downloaded - int piece_index; - int block_index; - // the number of bytes we have received - // of this block - int bytes_downloaded; - // the number of bytes in the block - int full_block_bytes; - }; -} - -#endif // TORRENT_PIECE_BLOCK_PROGRESS_HPP_INCLUDED - diff --git a/libtorrent/include/libtorrent/piece_picker.hpp b/libtorrent/include/libtorrent/piece_picker.hpp deleted file mode 100644 index 1cdc84bec..000000000 --- a/libtorrent/include/libtorrent/piece_picker.hpp +++ /dev/null @@ -1,548 +0,0 @@ -/* - -Copyright (c) 2003, Arvid Norberg -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions -are met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in - the documentation and/or other materials provided with the distribution. - * Neither the name of the author nor the names of its - contributors may be used to endorse or promote products derived - from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -POSSIBILITY OF SUCH DAMAGE. - -*/ -#ifndef TORRENT_PIECE_PICKER_HPP_INCLUDED -#define TORRENT_PIECE_PICKER_HPP_INCLUDED - -#include -#include -#include -#include - -#ifdef _MSC_VER -#pragma warning(push, 1) -#endif - -#include - -#ifdef _MSC_VER -#pragma warning(pop) -#endif - -#include "libtorrent/peer_id.hpp" -#include "libtorrent/socket.hpp" -#include "libtorrent/session_settings.hpp" -#include "libtorrent/config.hpp" -#include "libtorrent/assert.hpp" - -namespace libtorrent -{ - - class torrent; - class peer_connection; - class bitfield; - - struct TORRENT_EXPORT piece_block - { - piece_block(int p_index, int b_index) - : piece_index(p_index) - , block_index(b_index) - {} - int piece_index; - int block_index; - - bool operator<(piece_block const& b) const - { - if (piece_index < b.piece_index) return true; - if (piece_index == b.piece_index) return block_index < b.block_index; - return false; - } - - bool operator==(piece_block const& b) const - { return piece_index == b.piece_index && block_index == b.block_index; } - - bool operator!=(piece_block const& b) const - { return piece_index != b.piece_index || block_index != b.block_index; } - - }; - - class TORRENT_EXPORT piece_picker - { - public: - - enum - { - // the number of priority levels - priority_levels = 8, - // priority factor - prio_factor = priority_levels - 4 - }; - - struct block_info - { - block_info(): peer(0), num_peers(0), state(state_none) {} - // the peer this block was requested or - // downloaded from. This is a pointer to - // a policy::peer object - void* peer; - // the number of peers that has this block in their - // download or request queues - unsigned num_peers:14; - // the state of this block - enum { state_none, state_requested, state_writing, state_finished }; - unsigned state:2; - }; - - // the peers that are downloading this piece - // are considered fast peers or slow peers. - // none is set if the blocks were downloaded - // in a previous session - enum piece_state_t - { none, slow, medium, fast }; - - enum options_t - { - // pick rarest first - rarest_first = 1, - // pick the most common first, or the last pieces if sequential - reverse = 2, - // only pick pieces exclusively requested from this peer - on_parole = 4, - // always pick partial pieces before any other piece - prioritize_partials = 8, - // pick pieces in sequential order - sequential = 16 - }; - - struct downloading_piece - { - downloading_piece(): finished(0), writing(0), requested(0) {} - piece_state_t state; - - // the index of the piece - int index; - // info about each block - // this is a pointer into the m_block_info - // vector owned by the piece_picker - block_info* info; - // the number of blocks in the finished state - boost::int16_t finished; - // the number of blocks in the writing state - boost::int16_t writing; - // the number of blocks in the requested state - boost::int16_t requested; - }; - - piece_picker(); - - void get_availability(std::vector& avail) const; - - // increases the peer count for the given piece - // (is used when a HAVE message is received) - void inc_refcount(int index); - void dec_refcount(int index); - - // increases the peer count for the given piece - // (is used when a BITFIELD message is received) - void inc_refcount(bitfield const& bitmask); - // decreases the peer count for the given piece - // (used when a peer disconnects) - void dec_refcount(bitfield const& bitmask); - - // these will increase and decrease the peer count - // of all pieces. They are used when seeds join - // or leave the swarm. - void inc_refcount_all(); - void dec_refcount_all(); - - // This indicates that we just received this piece - // it means that the refcounter will indicate that - // we are not interested in this piece anymore - // (i.e. we don't have to maintain a refcount) - void we_have(int index); - void we_dont_have(int index); - - int cursor() const { return m_cursor; } - int reverse_cursor() const { return m_reverse_cursor; } - - // sets all pieces to dont-have - void init(int blocks_per_piece, int total_num_blocks); - int num_pieces() const { return int(m_piece_map.size()); } - - bool have_piece(int index) const - { - TORRENT_ASSERT(index >= 0); - TORRENT_ASSERT(index < int(m_piece_map.size())); - return m_piece_map[index].index == piece_pos::we_have_index; - } - - // sets the priority of a piece. - // returns true if the priority was changed from 0 to non-0 - // or vice versa - bool set_piece_priority(int index, int prio); - - // returns the priority for the piece at 'index' - int piece_priority(int index) const; - - // returns the current piece priorities for all pieces - void piece_priorities(std::vector& pieces) const; - - // ========== start deprecation ============== - - // fills the bitmask with 1's for pieces that are filtered - void filtered_pieces(std::vector& mask) const; - - // ========== end deprecation ============== - - // pieces should be the vector that represents the pieces a - // client has. It returns a list of all pieces that this client - // has and that are interesting to download. It returns them in - // priority order. It doesn't care about the download flag. - // The user of this function must lookup if any piece is - // marked as being downloaded. If the user of this function - // decides to download a piece, it must mark it as being downloaded - // itself, by using the mark_as_downloading() member function. - // THIS IS DONE BY THE peer_connection::send_request() MEMBER FUNCTION! - // The last argument is the policy::peer pointer for the peer that - // we'll download from. - void pick_pieces(bitfield const& pieces - , std::vector& interesting_blocks, int num_blocks - , int prefer_whole_pieces, void* peer, piece_state_t speed - , int options, std::vector const& suggested_pieces) const; - - // picks blocks from each of the pieces in the piece_list - // vector that is also in the piece bitmask. The blocks - // are added to interesting_blocks, and busy blocks are - // added to backup_blocks. num blocks is the number of - // blocks to be picked. Blocks are not picked from pieces - // that are being downloaded - int add_blocks(int piece, bitfield const& pieces - , std::vector& interesting_blocks - , std::vector& backup_blocks - , std::vector& backup_blocks2 - , int num_blocks, int prefer_whole_pieces - , void* peer, std::vector const& ignore - , piece_state_t speed, int options) const; - - // picks blocks only from downloading pieces - int add_blocks_downloading(downloading_piece const& dp - , bitfield const& pieces - , std::vector& interesting_blocks - , std::vector& backup_blocks - , std::vector& backup_blocks2 - , int num_blocks, int prefer_whole_pieces - , void* peer, piece_state_t speed - , int options) const; - - // clears the peer pointer in all downloading pieces with this - // peer pointer - void clear_peer(void* peer); - - // returns true if any client is currently downloading this - // piece-block, or if it's queued for downloading by some client - // or if it already has been successfully downloaded - bool is_requested(piece_block block) const; - // returns true if the block has been downloaded - bool is_downloaded(piece_block block) const; - // returns true if the block has been downloaded and written to disk - bool is_finished(piece_block block) const; - - // marks this piece-block as queued for downloading - bool mark_as_downloading(piece_block block, void* peer - , piece_state_t s); - void mark_as_writing(piece_block block, void* peer); - void mark_as_finished(piece_block block, void* peer); - void write_failed(piece_block block); - int num_peers(piece_block block) const; - - // returns information about the given piece - void piece_info(int index, piece_picker::downloading_piece& st) const; - - // if a piece had a hash-failure, it must be restored and - // made available for redownloading - void restore_piece(int index); - - // clears the given piece's download flag - // this means that this piece-block can be picked again - void abort_download(piece_block block); - - bool is_piece_finished(int index) const; - - // returns the number of blocks there is in the given piece - int blocks_in_piece(int index) const; - - // the number of downloaded blocks that hasn't passed - // the hash-check yet - int unverified_blocks() const; - - void get_downloaders(std::vector& d, int index) const; - - std::vector const& get_download_queue() const - { return m_downloads; } - - void* get_downloader(piece_block block) const; - - // the number of filtered pieces we don't have - int num_filtered() const { return m_num_filtered; } - - // the number of filtered pieces we already have - int num_have_filtered() const { return m_num_have_filtered; } - - int num_have() const { return m_num_have; } - -#ifdef TORRENT_DEBUG - // used in debug mode - void verify_priority(int start, int end, int prio) const; - void check_invariant(const torrent* t = 0) const; - void verify_pick(std::vector const& picked - , bitfield const& bits) const; -#endif -#if defined TORRENT_PICKER_LOG || defined TORRENT_DEBUG - void print_pieces() const; -#endif - - // functor that compares indices on downloading_pieces - struct has_index - { - has_index(int i): index(i) { TORRENT_ASSERT(i >= 0); } - bool operator()(const downloading_piece& p) const - { return p.index == index; } - int index; - }; - - int blocks_in_last_piece() const - { return m_blocks_in_last_piece; } - - float distributed_copies() const; - - private: - - friend struct piece_pos; - - bool can_pick(int piece, bitfield const& bitmask) const; - bool is_piece_free(int piece, bitfield const& bitmask) const; - std::pair expand_piece(int piece, int whole_pieces - , bitfield const& have) const; - - struct piece_pos - { - piece_pos() {} - piece_pos(int peer_count_, int index_) - : peer_count(peer_count_) - , downloading(0) - , piece_priority(1) - , index(index_) - { - TORRENT_ASSERT(peer_count_ >= 0); - TORRENT_ASSERT(index_ >= 0); - } - - // the number of peers that has this piece - // (availability) - unsigned peer_count : 10; - // is 1 if the piece is marked as being downloaded - unsigned downloading : 1; - // is 0 if the piece is filtered (not to be downloaded) - // 1 is normal priority (default) - // 2 is higher priority than pieces at the same availability level - // 3 is same priority as partial pieces - // 4 is higher priority than partial pieces - // 5 and 6 same priority as availability 1 (ignores availability) - // 7 is maximum priority (ignores availability) - unsigned piece_priority : 3; - // index in to the piece_info vector - unsigned index : 18; - - enum - { - // index is set to this to indicate that we have the - // piece. There is no entry for the piece in the - // buckets if this is the case. - we_have_index = 0x3ffff, - // the priority value that means the piece is filtered - filter_priority = 0, - // the max number the peer count can hold - max_peer_count = 0x3ff - }; - - bool have() const { return index == we_have_index; } - void set_have() { index = we_have_index; TORRENT_ASSERT(have()); } - void set_not_have() { index = 0; TORRENT_ASSERT(!have()); } - - bool filtered() const { return piece_priority == filter_priority; } - void filtered(bool f) { piece_priority = f ? filter_priority : 0; } - - // prio 7 is always top priority - // prio 0 is always -1 (don't pick) - // downloading pieces are always on an even prio_factor priority - // - // availability x, downloading - // | availability x, prio 3; availability 2x, prio 6 - // | | availability x, prio 2; availability 2x, prio 5 - // | | | availability x, prio 1; availability 2x, prio 4 - // | | | | - // +---+---+---+---+ - // | 0 | 1 | 2 | 3 | - // +---+---+---+---+ - - int priority(piece_picker const* picker) const - { - // filtered pieces (prio = 0), pieces we have or pieces with - // availability = 0 should not be present in the piece list - // returning -1 indicates that they shouldn't. - if (filtered() || have() || peer_count + picker->m_seeds == 0) - return -1; - - // prio 7 disregards availability - if (piece_priority == priority_levels - 1) return 1 - downloading; - - // prio 4,5,6 halves the availability of a piece - int availability = peer_count; - int priority = piece_priority; - if (piece_priority >= priority_levels / 2) - { - availability /= 2; - priority -= (priority_levels - 2) / 2; - } - - if (downloading) return availability * prio_factor; - return availability * prio_factor + (priority_levels / 2) - priority; - } - - bool operator!=(piece_pos p) const - { return index != p.index || peer_count != p.peer_count; } - - bool operator==(piece_pos p) const - { return index == p.index && peer_count == p.peer_count; } - - }; - - BOOST_STATIC_ASSERT(sizeof(piece_pos) == sizeof(char) * 4); - - void update_pieces() const; - - // fills in the range [start, end) of pieces in - // m_pieces that have priority 'prio' - void priority_range(int prio, int* start, int* end); - - // adds the piece 'index' to m_pieces - void add(int index); - // removes the piece with the given priority and the - // elem_index in the m_pieces vector - void remove(int priority, int elem_index); - // updates the position of the piece with the given - // priority and the elem_index in the m_pieces vector - void update(int priority, int elem_index); - // shuffles the given piece inside it's priority range - void shuffle(int priority, int elem_index); - - void sort_piece(std::vector::iterator dp); - - downloading_piece& add_download_piece(); - void erase_download_piece(std::vector::iterator i); - - // the number of seeds. These are not added to - // the availability counters of the pieces - int m_seeds; - - // the following vectors are mutable because they sometimes may - // be updated lazily, triggered by const functions - - // this vector contains all piece indices that are pickable - // sorted by priority. Pieces are in random random order - // among pieces with the same priority - mutable std::vector m_pieces; - - // these are indices to the priority boundries inside - // the m_pieces vector. priority 0 always start at - // 0, priority 1 starts at m_priority_boundries[0] etc. - mutable std::vector m_priority_boundries; - - // this maps indices to number of peers that has this piece and - // index into the m_piece_info vectors. - // piece_pos::we_have_index means that we have the piece, so it - // doesn't exist in the piece_info buckets - // pieces with the filtered flag set doesn't have entries in - // the m_piece_info buckets either - mutable std::vector m_piece_map; - - // each piece that's currently being downloaded - // has an entry in this list with block allocations. - // i.e. it says wich parts of the piece that - // is being downloaded - std::vector m_downloads; - - // this holds the information of the - // blocks in partially downloaded pieces. - // the first m_blocks_per_piece entries - // in the vector belongs to the first - // entry in m_downloads, the second - // m_blocks_per_piece entries to the - // second entry in m_downloads and so on. - std::vector m_block_info; - - int m_blocks_per_piece; - int m_blocks_in_last_piece; - - // the number of filtered pieces that we don't already - // have. total_number_of_pieces - number_of_pieces_we_have - // - num_filtered is supposed to the number of pieces - // we still want to download - int m_num_filtered; - - // the number of pieces we have that also are filtered - int m_num_have_filtered; - - // the number of pieces we have - int m_num_have; - - // we have all pieces in the range [0, m_cursor) - // m_cursor is the first piece we don't have - int m_cursor; - - // we have all pieces in the range [m_reverse_cursor, end) - // m_reverse_cursor is the first piece where we also have - // all the subsequent pieces - int m_reverse_cursor; - - // if this is set to true, it means update_pieces() - // has to be called before accessing m_pieces. - mutable bool m_dirty; - public: - - enum { max_pieces = piece_pos::we_have_index - 1 }; - - }; - - inline int piece_picker::blocks_in_piece(int index) const - { - TORRENT_ASSERT(index >= 0); - TORRENT_ASSERT(index < (int)m_piece_map.size()); - if (index+1 == (int)m_piece_map.size()) - return m_blocks_in_last_piece; - else - return m_blocks_per_piece; - } - -} - -#endif // TORRENT_PIECE_PICKER_HPP_INCLUDED - diff --git a/libtorrent/include/libtorrent/policy.hpp b/libtorrent/include/libtorrent/policy.hpp deleted file mode 100644 index 62d165b77..000000000 --- a/libtorrent/include/libtorrent/policy.hpp +++ /dev/null @@ -1,300 +0,0 @@ -/* - -Copyright (c) 2003, Arvid Norberg -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions -are met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in - the documentation and/or other materials provided with the distribution. - * Neither the name of the author nor the names of its - contributors may be used to endorse or promote products derived - from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -POSSIBILITY OF SUCH DAMAGE. - -*/ - -#ifndef TORRENT_POLICY_HPP_INCLUDED -#define TORRENT_POLICY_HPP_INCLUDED - -#include -#include - -#ifdef _MSC_VER -#pragma warning(push, 1) -#endif - -#ifdef _MSC_VER -#pragma warning(pop) -#endif - -#include "libtorrent/peer.hpp" -#include "libtorrent/piece_picker.hpp" -#include "libtorrent/socket.hpp" -#include "libtorrent/size_type.hpp" -#include "libtorrent/invariant_check.hpp" -#include "libtorrent/config.hpp" -#include "libtorrent/time.hpp" - -namespace libtorrent -{ - - class torrent; - class peer_connection; - - enum - { - // the limits of the download queue size - min_request_queue = 2, - - // the amount of free upload allowed before - // the peer is choked - free_upload_amount = 4 * 16 * 1024 - }; - - void request_a_block(torrent& t, peer_connection& c); - - class TORRENT_EXPORT policy - { - public: - - policy(torrent* t); - - // this is called every 10 seconds to allow - // for peer choking management - void pulse(); - - struct peer; - // this is called once for every peer we get from - // the tracker, pex, lsd or dht. - policy::peer* peer_from_tracker(const tcp::endpoint& remote, const peer_id& pid - , int source, char flags); - - // false means duplicate connection - bool update_peer_port(int port, policy::peer* p, int src); - - // called when an incoming connection is accepted - // false means the connection was refused or failed - bool new_connection(peer_connection& c); - - // the given connection was just closed - void connection_closed(const peer_connection& c); - - // the peer has got at least one interesting piece - void peer_is_interesting(peer_connection& c); - - // the peer unchoked us - void unchoked(peer_connection& c); - - // the peer is interested in our pieces - void interested(peer_connection& c); - - // the peer is not interested in our pieces - void not_interested(peer_connection& c); - - void ip_filter_updated(); - -#ifdef TORRENT_DEBUG - bool has_connection(const peer_connection* p); - - void check_invariant() const; -#endif - - struct peer - { - enum connection_type { not_connectable, connectable }; - peer(tcp::endpoint const& ip, connection_type t, int src); - - size_type total_download() const; - size_type total_upload() const; - - tcp::endpoint ip() const { return tcp::endpoint(addr, port); } - void set_ip(tcp::endpoint const& endp) - { addr = endp.address(); port = endp.port(); } - - // this is the accumulated amount of - // uploaded and downloaded data to this - // peer. It only accounts for what was - // shared during the last connection to - // this peer. i.e. These are only updated - // when the connection is closed. For the - // total amount of upload and download - // we'll have to add thes figures with the - // statistics from the peer_connection. - size_type prev_amount_upload; - size_type prev_amount_download; - - // the ip address this peer is or was connected on - address addr; - - // the time when this peer was optimistically unchoked - // the last time. - libtorrent::ptime last_optimistically_unchoked; - - // the time when the peer connected to us - // or disconnected if it isn't connected right now - libtorrent::ptime connected; - - // if the peer is connected now, this - // will refer to a valid peer_connection - peer_connection* connection; - -#ifndef TORRENT_DISABLE_GEO_IP -#ifdef TORRENT_DEBUG - // only used in debug mode to assert that - // the first entry in the AS pair keeps the same - boost::uint16_t inet_as_num; -#endif - // The AS this peer belongs to - std::pair* inet_as; -#endif - - // the port this peer is or was connected on - boost::uint16_t port; - - // the number of failed connection attempts - // this peer has - boost::uint8_t failcount; - - // for every valid piece we receive where this - // peer was one of the participants, we increase - // this value. For every invalid piece we receive - // where this peer was a participant, we decrease - // this value. If it sinks below a threshold, its - // considered a bad peer and will be banned. - boost::int8_t trust_points; - - // a bitmap combining the peer_source flags - // from peer_info. - boost::uint8_t source; - - // the number of times this peer has been - // part of a piece that failed the hash check - boost::uint8_t hashfails; - - // type specifies if the connection was incoming - // or outgoing. If we ever saw this peer as connectable - // it will remain as connectable - unsigned type:4; - - // the number of times we have allowed a fast - // reconnect for this peer. - unsigned fast_reconnects:4; - -#ifndef TORRENT_DISABLE_ENCRYPTION - // Hints encryption support of peer. Only effective - // for and when the outgoing encryption policy - // allows both encrypted and non encrypted - // connections (pe_settings::out_enc_policy - // == enabled). The initial state of this flag - // determines the initial connection attempt - // type (true = encrypted, false = standard). - // This will be toggled everytime either an - // encrypted or non-encrypted handshake fails. - bool pe_support:1; -#endif - // true if this peer currently is unchoked - // because of an optimistic unchoke. - // when the optimistic unchoke is moved to - // another peer, this peer will be choked - // if this is true - bool optimistically_unchoked:1; - - // this is true if the peer is a seed - bool seed:1; - - // if this is true, the peer has previously - // participated in a piece that failed the piece - // hash check. This will put the peer on parole - // and only request entire pieces. If a piece pass - // that was partially requested from this peer it - // will leave parole mode and continue download - // pieces as normal peers. - bool on_parole:1; - - // is set to true if this peer has been banned - bool banned:1; - -#ifndef TORRENT_DISABLE_DHT - // this is set to true when this peer as been - // pinged by the DHT - bool added_to_dht:1; -#endif - }; - - int num_peers() const { return m_peers.size(); } - - typedef std::multimap::iterator iterator; - typedef std::multimap::const_iterator const_iterator; - iterator begin_peer() { return m_peers.begin(); } - iterator end_peer() { return m_peers.end(); } - const_iterator begin_peer() const { return m_peers.begin(); } - const_iterator end_peer() const { return m_peers.end(); } - - bool connect_one_peer(); - - bool has_peer(policy::peer const* p) const; - - int num_seeds() const { return m_num_seeds; } - int num_connect_candidates() const { return m_num_connect_candidates; } - void recalculate_connect_candidates() - { - if (m_num_connect_candidates == 0) - m_num_connect_candidates = 1; - } - - void erase_peer(iterator i); - - private: - - bool compare_peer(policy::peer const& lhs, policy::peer const& rhs - , address const& external_ip) const; - - iterator find_connect_candidate(); - - bool is_connect_candidate(peer const& p, bool finished); - - std::multimap m_peers; - - // since the peer list can grow too large - // to scan all of it, start at this iterator - iterator m_round_robin; - - torrent* m_torrent; - - // free download we have got that hasn't - // been distributed yet. - size_type m_available_free_upload; - - // The number of peers in our peer list - // that are connect candidates. i.e. they're - // not already connected and they have not - // yet reached their max try count and they - // have the connectable state (we have a listen - // port for them). - int m_num_connect_candidates; - - // the number of seeds in the peer list - int m_num_seeds; - }; - -} - -#endif // TORRENT_POLICY_HPP_INCLUDED - diff --git a/libtorrent/include/libtorrent/proxy_base.hpp b/libtorrent/include/libtorrent/proxy_base.hpp deleted file mode 100644 index 873e84190..000000000 --- a/libtorrent/include/libtorrent/proxy_base.hpp +++ /dev/null @@ -1,211 +0,0 @@ -/* - -Copyright (c) 2007, Arvid Norberg -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions -are met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in - the documentation and/or other materials provided with the distribution. - * Neither the name of the author nor the names of its - contributors may be used to endorse or promote products derived - from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -POSSIBILITY OF SUCH DAMAGE. - -*/ - -#ifndef TORRENT_PROXY_BASE_HPP_INCLUDED -#define TORRENT_PROXY_BASE_HPP_INCLUDED - -#include "libtorrent/io.hpp" -#include "libtorrent/socket.hpp" -#include -#include -#include -#if BOOST_VERSION < 103500 -#include -#include -#else -#include -#include -#endif - -namespace libtorrent { - -class proxy_base : boost::noncopyable -{ -public: - - typedef stream_socket::lowest_layer_type lowest_layer_type; - typedef stream_socket::endpoint_type endpoint_type; - typedef stream_socket::protocol_type protocol_type; - - explicit proxy_base(io_service& io_service) - : m_sock(io_service) - , m_resolver(io_service) - {} - - void set_proxy(std::string hostname, int port) - { - m_hostname = hostname; - m_port = port; - } - - template - void async_read_some(Mutable_Buffers const& buffers, Handler const& handler) - { - m_sock.async_read_some(buffers, handler); - } - - template - std::size_t read_some(Mutable_Buffers const& buffers, error_code& ec) - { - return m_sock.read_some(buffers, ec); - } - -#ifndef BOOST_NO_EXCEPTIONS - template - std::size_t read_some(Mutable_Buffers const& buffers) - { - return m_sock.read_some(buffers); - } - - template - void io_control(IO_Control_Command& ioc) - { - m_sock.io_control(ioc); - } -#endif - - template - void io_control(IO_Control_Command& ioc, error_code& ec) - { - m_sock.io_control(ioc, ec); - } - - template - void async_write_some(Const_Buffers const& buffers, Handler const& handler) - { - m_sock.async_write_some(buffers, handler); - } - -#ifndef BOOST_NO_EXCEPTIONS - template - void set_option(SettableSocketOption const& opt) - { - m_sock.set_option(opt); - } -#endif - - template - error_code set_option(SettableSocketOption const& opt, error_code& ec) - { - return m_sock.set_option(opt, ec); - } - -#ifndef BOOST_NO_EXCEPTIONS - void bind(endpoint_type const& endpoint) - { - m_sock.bind(endpoint); - } -#endif - - void bind(endpoint_type const& endpoint, error_code& ec) - { - m_sock.bind(endpoint, ec); - } - -#ifndef BOOST_NO_EXCEPTIONS - void open(protocol_type const& p) - { - m_sock.open(p); - } -#endif - - void open(protocol_type const& p, error_code& ec) - { - m_sock.open(p, ec); - } - -#ifndef BOOST_NO_EXCEPTIONS - void close() - { - m_remote_endpoint = endpoint_type(); - m_sock.close(); - m_resolver.cancel(); - } -#endif - - void close(error_code& ec) - { - m_sock.close(ec); - m_resolver.cancel(); - } - -#ifndef BOOST_NO_EXCEPTIONS - endpoint_type remote_endpoint() const - { - return m_remote_endpoint; - } -#endif - - endpoint_type remote_endpoint(error_code& ec) const - { - return m_remote_endpoint; - } - -#ifndef BOOST_NO_EXCEPTIONS - endpoint_type local_endpoint() const - { - return m_sock.local_endpoint(); - } -#endif - - endpoint_type local_endpoint(error_code& ec) const - { - return m_sock.local_endpoint(ec); - } - - io_service& get_io_service() - { - return m_sock.get_io_service(); - } - - lowest_layer_type& lowest_layer() - { - return m_sock.lowest_layer(); - } - - bool is_open() const { return m_sock.is_open(); } - -protected: - - stream_socket m_sock; - std::string m_hostname; - int m_port; - - endpoint_type m_remote_endpoint; - - tcp::resolver m_resolver; -}; - -} - -#endif - diff --git a/libtorrent/include/libtorrent/random_sample.hpp b/libtorrent/include/libtorrent/random_sample.hpp deleted file mode 100644 index 1eaaec1e3..000000000 --- a/libtorrent/include/libtorrent/random_sample.hpp +++ /dev/null @@ -1,74 +0,0 @@ -/* - -Copyright (c) 2006, Arvid Norberg & Daniel Wallin -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions -are met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in - the documentation and/or other materials provided with the distribution. - * Neither the name of the author nor the names of its - contributors may be used to endorse or promote products derived - from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -POSSIBILITY OF SUCH DAMAGE. - -*/ - -#ifndef TORRENT_RANDOM_SAMPLE_HPP -#define TORRENT_RANDOM_SAMPLE_HPP - -#include -#include - -#include "libtorrent/config.hpp" - -namespace libtorrent -{ - - template - inline void random_sample_n(InIter start, InIter end - , OutIter out, Distance n) - { - Distance t = 0; - Distance m = 0; - Distance N = std::distance(start, end); - - TORRENT_ASSERT(N >= n); - - while (m < n) - { - if ((std::rand() / (RAND_MAX + 1.f)) * (N - t) >= n - m) - { - ++start; - ++t; - } - else - { - *out = *start; - ++out; - ++start; - ++t; - ++m; - } - } - } - -} - -#endif diff --git a/libtorrent/include/libtorrent/session.hpp b/libtorrent/include/libtorrent/session.hpp deleted file mode 100644 index 1f837e317..000000000 --- a/libtorrent/include/libtorrent/session.hpp +++ /dev/null @@ -1,364 +0,0 @@ -/* - -Copyright (c) 2006, Arvid Norberg -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions -are met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in - the documentation and/or other materials provided with the distribution. - * Neither the name of the author nor the names of its - contributors may be used to endorse or promote products derived - from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -POSSIBILITY OF SUCH DAMAGE. - -*/ - -#ifndef TORRENT_SESSION_HPP_INCLUDED -#define TORRENT_SESSION_HPP_INCLUDED - -#include -#include -#include -#include -#include -#include - -#ifdef _MSC_VER -#pragma warning(push, 1) -#endif - -#include -#include -#include -#include - -#ifdef _MSC_VER -#pragma warning(pop) -#endif - -#include "libtorrent/config.hpp" -#include "libtorrent/torrent_handle.hpp" -#include "libtorrent/entry.hpp" -#include "libtorrent/alert.hpp" -#include "libtorrent/session_status.hpp" -#include "libtorrent/version.hpp" -#include "libtorrent/fingerprint.hpp" -#include "libtorrent/time.hpp" -#include "libtorrent/disk_io_thread.hpp" -#include "libtorrent/peer_id.hpp" - -#include "libtorrent/storage.hpp" - -#ifdef _MSC_VER -# include -#endif - -namespace libtorrent -{ - struct torrent_plugin; - class torrent; - class ip_filter; - class port_filter; - class connection_queue; - class natpmp; - class upnp; - - namespace fs = boost::filesystem; - - namespace aux - { - // workaround for microsofts - // hardware exceptions that makes - // it hard to debug stuff -#ifdef _MSC_VER - struct eh_initializer - { - eh_initializer() - { - ::_set_se_translator(straight_to_debugger); - } - - static void straight_to_debugger(unsigned int, _EXCEPTION_POINTERS*) - { throw; } - }; -#else - struct eh_initializer {}; -#endif - struct session_impl; - - struct filesystem_init - { - filesystem_init(); - }; - - } - - class TORRENT_EXPORT session_proxy - { - friend class session; - public: - session_proxy() {} - private: - session_proxy(boost::shared_ptr impl) - : m_impl(impl) {} - boost::shared_ptr m_impl; - }; - - struct add_torrent_params - { - add_torrent_params(storage_constructor_type sc = default_storage_constructor) - : tracker_url(0) - , name(0) - , resume_data(0) - , storage_mode(storage_mode_sparse) - , paused(true) - , auto_managed(true) - , duplicate_is_error(false) - , storage(sc) - , userdata(0) - {} - - boost::intrusive_ptr ti; - char const* tracker_url; - sha1_hash info_hash; - char const* name; - fs::path save_path; - std::vector* resume_data; - storage_mode_t storage_mode; - bool paused; - bool auto_managed; - bool duplicate_is_error; - storage_constructor_type storage; - void* userdata; - }; - - class TORRENT_EXPORT session: public boost::noncopyable, aux::eh_initializer - { - public: - - session(fingerprint const& print = fingerprint("LT" - , LIBTORRENT_VERSION_MAJOR, LIBTORRENT_VERSION_MINOR, 0, 0) - , int flags = start_default_features | add_default_plugins -#if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_LOGGING || defined TORRENT_ERROR_LOGGING - , fs::path logpath = "." -#endif - ); - session( - fingerprint const& print - , std::pair listen_port_range - , char const* listen_interface = "0.0.0.0" - , int flags = start_default_features | add_default_plugins -#if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_LOGGING || defined TORRENT_ERROR_LOGGING - , fs::path logpath = "." -#endif - ); - - ~session(); - - // returns a list of all torrents in this session - std::vector get_torrents() const; - - // returns an invalid handle in case the torrent doesn't exist - torrent_handle find_torrent(sha1_hash const& info_hash) const; - - // all torrent_handles must be destructed before the session is destructed! - torrent_handle add_torrent(add_torrent_params const& params); - -#ifndef TORRENT_NO_DEPRECATE - // deprecated in 0.14 - torrent_handle add_torrent( - torrent_info const& ti - , fs::path const& save_path - , entry const& resume_data = entry() - , storage_mode_t storage_mode = storage_mode_sparse - , bool paused = false - , storage_constructor_type sc = default_storage_constructor) TORRENT_DEPRECATED; - - // deprecated in 0.14 - torrent_handle add_torrent( - boost::intrusive_ptr ti - , fs::path const& save_path - , entry const& resume_data = entry() - , storage_mode_t storage_mode = storage_mode_sparse - , bool paused = false - , storage_constructor_type sc = default_storage_constructor - , void* userdata = 0) TORRENT_DEPRECATED; - - // deprecated in 0.14 - torrent_handle add_torrent( - char const* tracker_url - , sha1_hash const& info_hash - , char const* name - , fs::path const& save_path - , entry const& resume_data = entry() - , storage_mode_t storage_mode = storage_mode_sparse - , bool paused = false - , storage_constructor_type sc = default_storage_constructor - , void* userdata = 0) TORRENT_DEPRECATED; -#endif - - session_proxy abort() { return session_proxy(m_impl); } - - void pause(); - void resume(); - bool is_paused() const; - - session_status status() const; - cache_status get_cache_status() const; - - void get_cache_info(sha1_hash const& ih - , std::vector& ret) const; - -#ifndef TORRENT_DISABLE_DHT - void start_dht(entry const& startup_state = entry()); - void stop_dht(); - void set_dht_settings(dht_settings const& settings); - entry dht_state() const; - void add_dht_node(std::pair const& node); - void add_dht_router(std::pair const& node); -#endif - -#ifndef TORRENT_DISABLE_ENCRYPTION - void set_pe_settings(pe_settings const& settings); - pe_settings const& get_pe_settings() const; -#endif - -#ifndef TORRENT_DISABLE_EXTENSIONS - void add_extension(boost::function(torrent*, void*)> ext); -#endif - -#ifndef TORRENT_DISABLE_GEO_IP - int as_for_ip(address const& addr); - bool load_asnum_db(char const* file); - bool load_country_db(char const* file); -#endif - - void load_state(entry const& ses_state); - entry state() const; - - void set_ip_filter(ip_filter const& f); - void set_port_filter(port_filter const& f); - void set_peer_id(peer_id const& pid); - void set_key(int key); - peer_id id() const; - - bool is_listening() const; - - // if the listen port failed in some way - // you can retry to listen on another port- - // range with this function. If the listener - // succeeded and is currently listening, - // a call to this function will shut down the - // listen port and reopen it using these new - // properties (the given interface and port range). - // As usual, if the interface is left as 0 - // this function will return false on failure. - // If it fails, it will also generate alerts describing - // the error. It will return true on success. - bool listen_on( - std::pair const& port_range - , const char* net_interface = 0); - - // returns the port we ended up listening on - unsigned short listen_port() const; - - // Get the number of uploads. - int num_uploads() const; - - // Get the number of connections. This number also contains the - // number of half open connections. - int num_connections() const; - - enum options_t - { - none = 0, - delete_files = 1 - }; - - enum session_flags_t - { - add_default_plugins = 1, - start_default_features = 2 - }; - - void remove_torrent(const torrent_handle& h, int options = none); - - void set_settings(session_settings const& s); - session_settings const& settings(); - - void set_peer_proxy(proxy_settings const& s); - void set_web_seed_proxy(proxy_settings const& s); - void set_tracker_proxy(proxy_settings const& s); - - proxy_settings const& peer_proxy() const; - proxy_settings const& web_seed_proxy() const; - proxy_settings const& tracker_proxy() const; - -#ifndef TORRENT_DISABLE_DHT - void set_dht_proxy(proxy_settings const& s); - proxy_settings const& dht_proxy() const; -#endif - - int upload_rate_limit() const; - int download_rate_limit() const; - int max_half_open_connections() const; - - void set_upload_rate_limit(int bytes_per_second); - void set_download_rate_limit(int bytes_per_second); - void set_max_uploads(int limit); - void set_max_connections(int limit); - void set_max_half_open_connections(int limit); - - std::auto_ptr pop_alert(); -#ifndef TORRENT_NO_DEPRECATE - void set_severity_level(alert::severity_t s) TORRENT_DEPRECATED; -#endif - void set_alert_mask(int m); - size_t set_alert_queue_size_limit(size_t queue_size_limit_); - - alert const* wait_for_alert(time_duration max_wait); - - connection_queue& get_connection_queue(); - - // starts/stops UPnP, NATPMP or LSD port mappers - // they are stopped by default - void start_lsd(); - natpmp* start_natpmp(); - upnp* start_upnp(); - - void stop_lsd(); - void stop_natpmp(); - void stop_upnp(); - - private: - - // just a way to initialize boost.filesystem - // before the session_impl is created - aux::filesystem_init m_dummy; - - // data shared between the main thread - // and the working thread - boost::shared_ptr m_impl; - }; - -} - -#endif // TORRENT_SESSION_HPP_INCLUDED - diff --git a/libtorrent/include/libtorrent/session_settings.hpp b/libtorrent/include/libtorrent/session_settings.hpp deleted file mode 100644 index dbfa9be5c..000000000 --- a/libtorrent/include/libtorrent/session_settings.hpp +++ /dev/null @@ -1,527 +0,0 @@ -/* - -Copyright (c) 2003, Arvid Norberg -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions -are met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in - the documentation and/or other materials provided with the distribution. - * Neither the name of the author nor the names of its - contributors may be used to endorse or promote products derived - from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -POSSIBILITY OF SUCH DAMAGE. - -*/ - -#ifndef TORRENT_SESSION_SETTINGS_HPP_INCLUDED -#define TORRENT_SESSION_SETTINGS_HPP_INCLUDED - -#include "libtorrent/version.hpp" -#include "libtorrent/config.hpp" - -namespace libtorrent -{ - - struct TORRENT_EXPORT proxy_settings - { - proxy_settings() : port(0), type(none) {} - - std::string hostname; - int port; - - std::string username; - std::string password; - - enum proxy_type - { - // a plain tcp socket is used, and - // the other settings are ignored. - none, - // socks4 server, requires username. - socks4, - // the hostname and port settings are - // used to connect to the proxy. No - // username or password is sent. - socks5, - // the hostname and port are used to - // connect to the proxy. the username - // and password are used to authenticate - // with the proxy server. - socks5_pw, - // the http proxy is only available for - // tracker and web seed traffic - // assumes anonymous access to proxy - http, - // http proxy with basic authentication - // uses username and password - http_pw - }; - - proxy_type type; - - }; - - struct TORRENT_EXPORT session_settings - { - session_settings(std::string const& user_agent_ = "libtorrent/" - LIBTORRENT_VERSION) - : user_agent(user_agent_) - , tracker_completion_timeout(60) - , tracker_receive_timeout(40) - , stop_tracker_timeout(5) - , tracker_maximum_response_length(1024*1024) - , piece_timeout(20) - , request_timeout(50) - , request_queue_time(3.f) - , max_allowed_in_request_queue(250) - , max_out_request_queue(200) - , whole_pieces_threshold(20) - , peer_timeout(120) - , urlseed_timeout(20) - , urlseed_pipeline_size(5) - , urlseed_wait_retry(30) - , file_pool_size(40) - , allow_multiple_connections_per_ip(false) - , max_failcount(3) - , min_reconnect_time(60) - , peer_connect_timeout(7) - , ignore_limits_on_local_network(true) - , connection_speed(20) - , send_redundant_have(false) - , lazy_bitfields(true) - , inactivity_timeout(600) - , unchoke_interval(15) - , optimistic_unchoke_multiplier(4) - , num_want(200) - , initial_picker_threshold(4) - , allowed_fast_set_size(10) - , max_outstanding_disk_bytes_per_connection(64 * 1024) - , handshake_timeout(10) -#ifndef TORRENT_DISABLE_DHT - , use_dht_as_fallback(false) -#endif - , free_torrent_hashes(true) - , upnp_ignore_nonrouters(false) - , send_buffer_watermark(80 * 1024) - , auto_upload_slots(true) - , use_parole_mode(true) - , cache_size(512) - , cache_expiry(60) - , outgoing_ports(0,0) - , peer_tos(0) - , active_downloads(8) - , active_seeds(5) - , active_limit(15) - , dont_count_slow_torrents(true) - , auto_manage_interval(30) - , share_ratio_limit(2.f) - , seed_time_ratio_limit(7.f) - , seed_time_limit(24 * 60 * 60) // 24 hours - , peer_turnover(1 / 50.f) - , peer_turnover_cutoff(1.f) - , close_redundant_connections(true) - , auto_scrape_interval(1800) - , auto_scrape_min_interval(300) - , max_peerlist_size(8000) - , min_announce_interval(5 * 60) - , prioritize_partial_pieces(false) - , auto_manage_startup(120) - , rate_limit_ip_overhead(true) - {} - - // this is the user agent that will be sent to the tracker - // when doing requests. It is used to identify the client. - // It cannot contain \r or \n - std::string user_agent; - - // the number of seconds to wait until giving up on a - // tracker request if it hasn't finished - int tracker_completion_timeout; - - // the number of seconds where no data is received - // from the tracker until it should be considered - // as timed out - int tracker_receive_timeout; - - // the time to wait when sending a stopped message - // before considering a tracker to have timed out. - // this is usually shorter, to make the client quit - // faster - int stop_tracker_timeout; - - // if the content-length is greater than this value - // the tracker connection will be aborted - int tracker_maximum_response_length; - - // the number of seconds from a request is sent until - // it times out if no piece response is returned. - int piece_timeout; - - // the number of seconds one block (16kB) is expected - // to be received within. If it's not, the block is - // requested from a different peer - int request_timeout; - - // the length of the request queue given in the number - // of seconds it should take for the other end to send - // all the pieces. i.e. the actual number of requests - // depends on the download rate and this number. - float request_queue_time; - - // the number of outstanding block requests a peer is - // allowed to queue up in the client. If a peer sends - // more requests than this (before the first one has - // been sent) the last request will be dropped. - // the higher this is, the faster upload speeds the - // client can get to a single peer. - int max_allowed_in_request_queue; - - // the maximum number of outstanding requests to - // send to a peer. This limit takes precedence over - // request_queue_time. - int max_out_request_queue; - - // if a whole piece can be downloaded in this number - // of seconds, or less, the peer_connection will prefer - // to request whole pieces at a time from this peer. - // The benefit of this is to better utilize disk caches by - // doing localized accesses and also to make it easier - // to identify bad peers if a piece fails the hash check. - int whole_pieces_threshold; - - // the number of seconds to wait for any activity on - // the peer wire before closing the connectiong due - // to time out. - int peer_timeout; - - // same as peer_timeout, but only applies to url-seeds. - // this is usually set lower, because web servers are - // expected to be more reliable. - int urlseed_timeout; - - // controls the pipelining size of url-seeds - int urlseed_pipeline_size; - - // time to wait until a new retry takes place - int urlseed_wait_retry; - - // sets the upper limit on the total number of files this - // session will keep open. The reason why files are - // left open at all is that some anti virus software - // hooks on every file close, and scans the file for - // viruses. deferring the closing of the files will - // be the difference between a usable system and - // a completely hogged down system. Most operating - // systems also has a limit on the total number of - // file descriptors a process may have open. It is - // usually a good idea to find this limit and set the - // number of connections and the number of files - // limits so their sum is slightly below it. - int file_pool_size; - - // false to not allow multiple connections from the same - // IP address. true will allow it. - bool allow_multiple_connections_per_ip; - - // the number of times we can fail to connect to a peer - // before we stop retrying it. - int max_failcount; - - // the number of seconds to wait to reconnect to a peer. - // this time is multiplied with the failcount. - int min_reconnect_time; - - // this is the timeout for a connection attempt. If - // the connect does not succeed within this time, the - // connection is dropped. The time is specified in seconds. - int peer_connect_timeout; - - // if set to true, upload, download and unchoke limits - // are ignored for peers on the local network. - bool ignore_limits_on_local_network; - - // the number of connection attempts that - // are made per second. - int connection_speed; - - // if this is set to true, have messages will be sent - // to peers that already have the piece. This is - // typically not necessary, but it might be necessary - // for collecting statistics in some cases. Default is false. - bool send_redundant_have; - - // if this is true, outgoing bitfields will never be fuil. If the - // client is seed, a few bits will be set to 0, and later filled - // in with have messages. This is to prevent certain ISPs - // from stopping people from seeding. - bool lazy_bitfields; - - // if a peer is uninteresting and uninterested for longer - // than this number of seconds, it will be disconnected. - // default is 10 minutes - int inactivity_timeout; - - // the number of seconds between chokes/unchokes - int unchoke_interval; - - // the number of unchoke intervals between - // optimistic unchokes - int optimistic_unchoke_multiplier; - - // if this is set, this IP will be reported do the - // tracker in the ip= parameter. - address announce_ip; - - // the num want sent to trackers - int num_want; - - // while we have fewer pieces than this, pick - // random pieces instead of rarest first. - int initial_picker_threshold; - - // the number of allowed pieces to send to peers - // that supports the fast extensions - int allowed_fast_set_size; - - // the maximum number of bytes a connection may have - // pending in the disk write queue before its download - // rate is being throttled. This prevents fast downloads - // to slow medias to allocate more and more memory - // indefinitely. This should be set to at least 32 kB - // to not completely disrupt normal downloads. - int max_outstanding_disk_bytes_per_connection; - - // the number of seconds to wait for a handshake - // response from a peer. If no response is received - // within this time, the peer is disconnected. - int handshake_timeout; - -#ifndef TORRENT_DISABLE_DHT - // while this is true, the dht will note be used unless the - // tracker is online - bool use_dht_as_fallback; -#endif - - // if this is true, the piece hashes will be freed, in order - // to save memory, once the torrent is seeding. This will - // make the get_torrent_info() function to return an incomplete - // torrent object that cannot be passed back to add_torrent() - bool free_torrent_hashes; - - // when this is true, the upnp port mapper will ignore - // any upnp devices that don't have an address that matches - // our currently configured router. - bool upnp_ignore_nonrouters; - - // if the send buffer has fewer bytes than this, we'll - // read another 16kB block onto it. If set too small, - // upload rate capacity will suffer. If set too high, - // memory will be wasted. - // The actual watermark may be lower than this in case - // the upload rate is low, this is the upper limit. - int send_buffer_watermark; - - // if auto_upload_slots is true, and a global upload - // limit is set and the upload rate is less than 90% - // of the upload limit, on new slot is opened up. If - // the upload rate is >= upload limit for an extended - // period of time, one upload slot is closed. The - // upload slots are never automatically decreased below - // the manual settings, through max_uploads. - bool auto_upload_slots; - - // if set to true, peers that participate in a failing - // piece is put in parole mode. i.e. They will only - // download whole pieces until they either fail or pass. - // they are taken out of parole mode as soon as they - // participate in a piece that passes. - bool use_parole_mode; - - // the disk write cache, specified in 16 KiB blocks. - // default is 512 (= 8 MB) - int cache_size; - - // the number of seconds a write cache entry sits - // idle in the cache before it's forcefully flushed - // to disk. Default is 60 seconds. - int cache_expiry; - - // if != (0, 0), this is the range of ports that - // outgoing connections will be bound to. This - // is useful for users that have routers that - // allow QoS settings based on local port. - std::pair outgoing_ports; - - // the TOS byte of all peer traffic (including - // web seeds) is set to this value. The default - // is the QBSS scavenger service - // http://qbone.internet2.edu/qbss/ - // For unmarked packets, set to 0 - char peer_tos; - - // for auto managed torrents, these are the limits - // they are subject to. If there are too many torrents - // some of the auto managed ones will be paused until - // some slots free up. - int active_downloads; - int active_seeds; - int active_limit; - - // if this is true, torrents that don't have any significant - // transfers are not counted as active when determining which - // auto managed torrents to pause and resume - bool dont_count_slow_torrents; - - // the number of seconds in between recalculating which - // torrents to activate and which ones to queue - int auto_manage_interval; - - // when a seeding torrent reaches eaither the share ratio - // (bytes up / bytes down) or the seed time ratio - // (seconds as seed / seconds as downloader) or the seed - // time limit (seconds as seed) it is considered - // done, and it will leave room for other torrents - // the default value for share ratio is 2 - // the default seed time ratio is 7, because that's a common - // asymmetry ratio on connections - float share_ratio_limit; - float seed_time_ratio_limit; - int seed_time_limit; - - // the percentage of peers to disconnect every - // 90 seconds (if we're at the peer limit) - // defaults to 1/50:th - float peer_turnover; - - // when we are connected to more than - // limit * peer_turnover_enable peers - // disconnect peer_turnover fraction - // of the peers - float peer_turnover_cutoff; - - // if this is true (default) connections where both - // ends have no utility in keeping the connection open - // are closed. for instance if both ends have completed - // their downloads - bool close_redundant_connections; - - // the number of seconds between scrapes of - // queued torrents (auto managed and paused) - int auto_scrape_interval; - - // the minimum number of seconds between any - // automatic scrape (regardless of torrent) - int auto_scrape_min_interval; - - // the max number of peers in the peer list - // per torrent. This is the peers we know - // about, not necessarily connected to. - int max_peerlist_size; - - // any announce intervals reported from a tracker - // that is lower than this, will be clamped to this - // value. It's specified in seconds - int min_announce_interval; - - // if true, partial pieces are picked before pieces - // that are more rare - bool prioritize_partial_pieces; - - // the number of seconds a torrent is considered - // active after it was started, regardless of - // upload and download speed. This is so that - // newly started torrents are not considered - // inactive until they have a fair chance to - // start downloading. - int auto_manage_startup; - - // if set to true, the estimated TCP/IP overhead is - // drained from the rate limiters, to avoid exceeding - // the limits with the total traffic - bool rate_limit_ip_overhead; - }; - -#ifndef TORRENT_DISABLE_DHT - struct dht_settings - { - dht_settings() - : max_peers_reply(50) - , search_branching(5) - , service_port(0) - , max_fail_count(20) - {} - - // the maximum number of peers to send in a - // reply to get_peers - int max_peers_reply; - - // the number of simultanous "connections" when - // searching the DHT. - int search_branching; - - // the listen port for the dht. This is a UDP port. - // zero means use the same as the tcp interface - int service_port; - - // the maximum number of times a node can fail - // in a row before it is removed from the table. - int max_fail_count; - }; -#endif - -#ifndef TORRENT_DISABLE_ENCRYPTION - - struct pe_settings - { - pe_settings() - : out_enc_policy(enabled) - , in_enc_policy(enabled) - , allowed_enc_level(both) - , prefer_rc4(false) - {} - - enum enc_policy - { - forced, // disallow non encrypted connections - enabled, // allow encrypted and non encrypted connections - disabled // disallow encrypted connections - }; - - enum enc_level - { - plaintext, // use only plaintext encryption - rc4, // use only rc4 encryption - both // allow both - }; - - enc_policy out_enc_policy; - enc_policy in_enc_policy; - - enc_level allowed_enc_level; - // if the allowed encryption level is both, setting this to - // true will prefer rc4 if both methods are offered, plaintext - // otherwise - bool prefer_rc4; - }; -#endif - -} - -#endif diff --git a/libtorrent/include/libtorrent/session_status.hpp b/libtorrent/include/libtorrent/session_status.hpp deleted file mode 100644 index 6c3475a09..000000000 --- a/libtorrent/include/libtorrent/session_status.hpp +++ /dev/null @@ -1,79 +0,0 @@ -/* - -Copyright (c) 2006, Arvid Norberg -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions -are met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in - the documentation and/or other materials provided with the distribution. - * Neither the name of the author nor the names of its - contributors may be used to endorse or promote products derived - from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -POSSIBILITY OF SUCH DAMAGE. - -*/ - -#ifndef TORRENT_SESSION_STATUS_HPP_INCLUDED -#define TORRENT_SESSION_STATUS_HPP_INCLUDED - -#include "libtorrent/config.hpp" -#include "libtorrent/size_type.hpp" - -namespace libtorrent -{ - - struct TORRENT_EXPORT session_status - { - bool has_incoming_connections; - - float upload_rate; - float download_rate; - - float payload_upload_rate; - float payload_download_rate; - - size_type total_download; - size_type total_upload; - - size_type total_payload_download; - size_type total_payload_upload; - - size_type total_redundant_bytes; - size_type total_failed_bytes; - - int num_peers; - int num_unchoked; - int allowed_upload_slots; - - int up_bandwidth_queue; - int down_bandwidth_queue; - -#ifndef TORRENT_DISABLE_DHT - int dht_nodes; - int dht_node_cache; - int dht_torrents; - size_type dht_global_nodes; -#endif - }; - -} - -#endif // TORRENT_SESSION_STATUS_HPP_INCLUDED - diff --git a/libtorrent/include/libtorrent/size_type.hpp b/libtorrent/include/libtorrent/size_type.hpp deleted file mode 100644 index ce5e1e1f9..000000000 --- a/libtorrent/include/libtorrent/size_type.hpp +++ /dev/null @@ -1,53 +0,0 @@ -/* - -Copyright (c) 2003, Arvid Norberg -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions -are met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in - the documentation and/or other materials provided with the distribution. - * Neither the name of the author nor the names of its - contributors may be used to endorse or promote products derived - from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -POSSIBILITY OF SUCH DAMAGE. - -*/ - -#ifndef TORRENT_SIZE_TYPE_HPP_INCLUDED -#define TORRENT_SIZE_TYPE_HPP_INCLUDED - -#ifdef _MSC_VER -#pragma warning(push, 1) -#endif - -#include - -#ifdef _MSC_VER -#pragma warning(pop) -#endif - -namespace libtorrent -{ - typedef boost::int64_t size_type; - typedef boost::uint64_t unsigned_size_type; -} - - -#endif diff --git a/libtorrent/include/libtorrent/socket.hpp b/libtorrent/include/libtorrent/socket.hpp deleted file mode 100644 index 98f5d8151..000000000 --- a/libtorrent/include/libtorrent/socket.hpp +++ /dev/null @@ -1,248 +0,0 @@ -/* - -Copyright (c) 2003, Arvid Norberg -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions -are met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in - the documentation and/or other materials provided with the distribution. - * Neither the name of the author nor the names of its - contributors may be used to endorse or promote products derived - from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -POSSIBILITY OF SUCH DAMAGE. - -*/ - -#ifndef TORRENT_SOCKET_HPP_INCLUDED -#define TORRENT_SOCKET_HPP_INCLUDED - -#ifdef _MSC_VER -#pragma warning(push, 1) -#endif - -// if building as Objective C++, asio's template -// parameters Protocol has to be renamed to avoid -// colliding with keywords - -#ifdef __OBJC__ -#define Protocol Protocol_ -#endif - -#include - -#if BOOST_VERSION < 103500 -#include -#include -#include -#include -#include -#include -#include -#include -#else -#include -#include -#include -#include -#include -#include -#include -#include -#endif - -#ifdef __OBJC__ -#undef Protocol -#endif - -#include "libtorrent/io.hpp" -#include "libtorrent/time.hpp" -#include "libtorrent/error_code.hpp" - -#ifdef _MSC_VER -#pragma warning(pop) -#endif - -namespace libtorrent -{ - -#if BOOST_VERSION < 103500 - using asio::ip::tcp; - using asio::ip::udp; - using asio::async_write; - using asio::async_read; - - typedef asio::ip::tcp::socket stream_socket; - typedef asio::ip::address address; - typedef asio::ip::address_v4 address_v4; - typedef asio::ip::address_v6 address_v6; - typedef asio::ip::udp::socket datagram_socket; - typedef asio::ip::tcp::acceptor socket_acceptor; - typedef asio::io_service io_service; - - namespace asio = ::asio; - typedef asio::basic_deadline_timer deadline_timer; -#else - using boost::asio::ip::tcp; - using boost::asio::ip::udp; - using boost::asio::async_write; - using boost::asio::async_read; - - typedef boost::asio::ip::tcp::socket stream_socket; - typedef boost::asio::ip::address address; - typedef boost::asio::ip::address_v4 address_v4; - typedef boost::asio::ip::address_v6 address_v6; - typedef boost::asio::ip::udp::socket datagram_socket; - typedef boost::asio::ip::tcp::acceptor socket_acceptor; - typedef boost::asio::io_service io_service; - - namespace asio = boost::asio; - typedef boost::asio::basic_deadline_timer deadline_timer; -#endif - - inline std::ostream& print_address(std::ostream& os, address const& addr) - { - error_code ec; - std::string a = addr.to_string(ec); - if (ec) return os; - os << a; - return os; - } - - inline std::ostream& print_endpoint(std::ostream& os, tcp::endpoint const& ep) - { - address const& addr = ep.address(); - error_code ec; - std::string a = addr.to_string(ec); - if (ec) return os; - - if (addr.is_v6()) - os << "[" << a << "]:"; - else - os << a << ":"; - os << ep.port(); - return os; - } - - namespace detail - { - template - void write_address(address const& a, OutIt& out) - { - if (a.is_v4()) - { - write_uint32(a.to_v4().to_ulong(), out); - } - else if (a.is_v6()) - { - address_v6::bytes_type bytes - = a.to_v6().to_bytes(); - std::copy(bytes.begin(), bytes.end(), out); - } - } - - template - address read_v4_address(InIt& in) - { - unsigned long ip = read_uint32(in); - return address_v4(ip); - } - - template - address read_v6_address(InIt& in) - { - typedef address_v6::bytes_type bytes_t; - bytes_t bytes; - for (bytes_t::iterator i = bytes.begin() - , end(bytes.end()); i != end; ++i) - *i = read_uint8(in); - return address_v6(bytes); - } - - template - void write_endpoint(Endpoint const& e, OutIt& out) - { - write_address(e.address(), out); - write_uint16(e.port(), out); - } - - template - Endpoint read_v4_endpoint(InIt& in) - { - address addr = read_v4_address(in); - int port = read_uint16(in); - return Endpoint(addr, port); - } - - template - Endpoint read_v6_endpoint(InIt& in) - { - address addr = read_v6_address(in); - int port = read_uint16(in); - return Endpoint(addr, port); - } - } - - struct v6only - { - v6only(bool enable): m_value(enable) {} - template - int level(Protocol const&) const { return IPPROTO_IPV6; } - template - int name(Protocol const&) const { return IPV6_V6ONLY; } - template - int const* data(Protocol const&) const { return &m_value; } - template - size_t size(Protocol const&) const { return sizeof(m_value); } - int m_value; - }; - -#ifdef TORRENT_WINDOWS - struct v6_protection_level - { - v6_protection_level(int level): m_value(level) {} - template - int level(Protocol const&) const { return IPPROTO_IPV6; } - template - int name(Protocol const&) const { return IPV6_PROTECTION_LEVEL; } - template - int const* data(Protocol const&) const { return &m_value; } - template - size_t size(Protocol const&) const { return sizeof(m_value); } - int m_value; - }; -#endif - - struct type_of_service - { - type_of_service(char val): m_value(val) {} - template - int level(Protocol const&) const { return IPPROTO_IP; } - template - int name(Protocol const&) const { return IP_TOS; } - template - char const* data(Protocol const&) const { return &m_value; } - template - size_t size(Protocol const&) const { return sizeof(m_value); } - char m_value; - }; -} - -#endif // TORRENT_SOCKET_HPP_INCLUDED - diff --git a/libtorrent/include/libtorrent/socket_type.hpp b/libtorrent/include/libtorrent/socket_type.hpp deleted file mode 100644 index 9ed8f9a4b..000000000 --- a/libtorrent/include/libtorrent/socket_type.hpp +++ /dev/null @@ -1,51 +0,0 @@ -/* - -Copyright (c) 2007, Arvid Norberg -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions -are met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in - the documentation and/or other materials provided with the distribution. - * Neither the name of the author nor the names of its - contributors may be used to endorse or promote products derived - from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -POSSIBILITY OF SUCH DAMAGE. - -*/ - -#ifndef TORRENT_SOCKET_TYPE -#define TORRENT_SOCKET_TYPE - -#include "libtorrent/socks5_stream.hpp" -#include "libtorrent/socks4_stream.hpp" -#include "libtorrent/http_stream.hpp" -#include "libtorrent/variant_stream.hpp" - -namespace libtorrent -{ - typedef variant_stream< - stream_socket - , socks5_stream - , socks4_stream - , http_stream> socket_type; -} - -#endif - diff --git a/libtorrent/include/libtorrent/socks4_stream.hpp b/libtorrent/include/libtorrent/socks4_stream.hpp deleted file mode 100644 index e7054595e..000000000 --- a/libtorrent/include/libtorrent/socks4_stream.hpp +++ /dev/null @@ -1,92 +0,0 @@ -/* - -Copyright (c) 2007, Arvid Norberg -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions -are met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in - the documentation and/or other materials provided with the distribution. - * Neither the name of the author nor the names of its - contributors may be used to endorse or promote products derived - from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -POSSIBILITY OF SUCH DAMAGE. - -*/ - -#ifndef TORRENT_SOCKS4_STREAM_HPP_INCLUDED -#define TORRENT_SOCKS4_STREAM_HPP_INCLUDED - -#include "libtorrent/proxy_base.hpp" - -namespace libtorrent { - -class socks4_stream : public proxy_base -{ -public: - - explicit socks4_stream(io_service& io_service_) - : proxy_base(io_service_) - {} - - void set_username(std::string const& user) - { - m_user = user; - } - - typedef boost::function handler_type; - - template - void async_connect(endpoint_type const& endpoint, Handler const& handler) - { - m_remote_endpoint = endpoint; - - // the connect is split up in the following steps: - // 1. resolve name of proxy server - // 2. connect to proxy server - // 3. send SOCKS4 CONNECT message - - // to avoid unnecessary copying of the handler, - // store it in a shaed_ptr - boost::shared_ptr h(new handler_type(handler)); - - tcp::resolver::query q(m_hostname - , boost::lexical_cast(m_port)); - m_resolver.async_resolve(q, boost::bind( - &socks4_stream::name_lookup, this, _1, _2, h)); - } - -private: - - void name_lookup(error_code const& e, tcp::resolver::iterator i - , boost::shared_ptr h); - void connected(error_code const& e, boost::shared_ptr h); - void handshake1(error_code const& e, boost::shared_ptr h); - void handshake2(error_code const& e, boost::shared_ptr h); - - // send and receive buffer - std::vector m_buffer; - // proxy authentication - std::string m_user; -}; - -} - -#endif - diff --git a/libtorrent/include/libtorrent/socks5_stream.hpp b/libtorrent/include/libtorrent/socks5_stream.hpp deleted file mode 100644 index 24b27da85..000000000 --- a/libtorrent/include/libtorrent/socks5_stream.hpp +++ /dev/null @@ -1,104 +0,0 @@ -/* - -Copyright (c) 2007, Arvid Norberg -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions -are met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in - the documentation and/or other materials provided with the distribution. - * Neither the name of the author nor the names of its - contributors may be used to endorse or promote products derived - from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -POSSIBILITY OF SUCH DAMAGE. - -*/ - -#ifndef TORRENT_SOCKS5_STREAM_HPP_INCLUDED -#define TORRENT_SOCKS5_STREAM_HPP_INCLUDED - -#include "libtorrent/proxy_base.hpp" - -namespace libtorrent { - -class socks5_stream : public proxy_base -{ -public: - - explicit socks5_stream(io_service& io_service) - : proxy_base(io_service) - {} - - void set_username(std::string const& user - , std::string const& password) - { - m_user = user; - m_password = password; - } - - typedef boost::function handler_type; - - template - void async_connect(endpoint_type const& endpoint, Handler const& handler) - { - m_remote_endpoint = endpoint; - - // the connect is split up in the following steps: - // 1. resolve name of proxy server - // 2. connect to proxy server - // 3. send SOCKS5 authentication method message - // 4. read SOCKS5 authentication response - // 5. send username+password - // 6. send SOCKS5 CONNECT message - - // to avoid unnecessary copying of the handler, - // store it in a shaed_ptr - boost::shared_ptr h(new handler_type(handler)); - - tcp::resolver::query q(m_hostname - , boost::lexical_cast(m_port)); - m_resolver.async_resolve(q, boost::bind( - &socks5_stream::name_lookup, this, _1, _2, h)); - } - -private: - - void name_lookup(error_code const& e, tcp::resolver::iterator i - , boost::shared_ptr h); - void connected(error_code const& e, boost::shared_ptr h); - void handshake1(error_code const& e, boost::shared_ptr h); - void handshake2(error_code const& e, boost::shared_ptr h); - void handshake3(error_code const& e, boost::shared_ptr h); - void handshake4(error_code const& e, boost::shared_ptr h); - void socks_connect(boost::shared_ptr h); - void connect1(error_code const& e, boost::shared_ptr h); - void connect2(error_code const& e, boost::shared_ptr h); - void connect3(error_code const& e, boost::shared_ptr h); - - // send and receive buffer - std::vector m_buffer; - // proxy authentication - std::string m_user; - std::string m_password; -}; - -} - -#endif - diff --git a/libtorrent/include/libtorrent/ssl_stream.hpp b/libtorrent/include/libtorrent/ssl_stream.hpp deleted file mode 100644 index c4deb1352..000000000 --- a/libtorrent/include/libtorrent/ssl_stream.hpp +++ /dev/null @@ -1,228 +0,0 @@ -/* - -Copyright (c) 2008, Arvid Norberg -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions -are met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in - the documentation and/or other materials provided with the distribution. - * Neither the name of the author nor the names of its - contributors may be used to endorse or promote products derived - from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -POSSIBILITY OF SUCH DAMAGE. - -*/ - -#ifndef TORRENT_SSL_STREAM_HPP_INCLUDED -#define TORRENT_SSL_STREAM_HPP_INCLUDED - -#include "libtorrent/socket.hpp" -#if BOOST_VERSION < 103500 -#include -#else -#include -#endif -// openssl seems to believe it owns -// this name in every single scope -#undef set_key - -namespace libtorrent { - -template -class ssl_stream -{ -public: - - explicit ssl_stream(io_service& io_service) - : m_context(io_service, asio::ssl::context::sslv23_client) - , m_sock(io_service, m_context) - { - error_code ec; - m_context.set_verify_mode(asio::ssl::context::verify_none, ec); - } - - typedef Stream next_layer_type; - typedef typename Stream::lowest_layer_type lowest_layer_type; - typedef typename Stream::endpoint_type endpoint_type; - typedef typename Stream::protocol_type protocol_type; - typedef typename asio::ssl::stream sock_type; - - typedef boost::function handler_type; - - template - void async_connect(endpoint_type const& endpoint, Handler const& handler) - { - // the connect is split up in the following steps: - // 1. connect to peer - // 2. perform SSL client handshake - - // to avoid unnecessary copying of the handler, - // store it in a shared_ptr - boost::shared_ptr h(new handler_type(handler)); - - m_sock.next_layer().async_connect(endpoint - , boost::bind(&ssl_stream::connected, this, _1, h)); - } - - template - void async_read_some(Mutable_Buffers const& buffers, Handler const& handler) - { - m_sock.async_read_some(buffers, handler); - } - - template - std::size_t read_some(Mutable_Buffers const& buffers, error_code& ec) - { - return m_sock.read_some(buffers, ec); - } - -#ifndef BOOST_NO_EXCEPTIONS - template - std::size_t read_some(Mutable_Buffers const& buffers) - { - return m_sock.read_some(buffers); - } - - template - void io_control(IO_Control_Command& ioc) - { - m_sock.next_layer().io_control(ioc); - } -#endif - - template - void io_control(IO_Control_Command& ioc, error_code& ec) - { - m_sock.next_layer().io_control(ioc, ec); - } - - template - void async_write_some(Const_Buffers const& buffers, Handler const& handler) - { - m_sock.async_write_some(buffers, handler); - } - -#ifndef BOOST_NO_EXCEPTIONS - void bind(endpoint_type const& endpoint) - { - m_sock.next_layer().bind(endpoint); - } -#endif - - void bind(endpoint_type const& endpoint, error_code& ec) - { - m_sock.next_layer().bind(endpoint, ec); - } - -#ifndef BOOST_NO_EXCEPTIONS - void open(protocol_type const& p) - { - m_sock.next_layer().open(p); - } -#endif - - void open(protocol_type const& p, error_code& ec) - { - m_sock.next_layer().open(p, ec); - } - - bool is_open() const - { - return const_cast(m_sock).next_layer().is_open(); - } - -#ifndef BOOST_NO_EXCEPTIONS - void close() - { - m_sock.next_layer().close(); - } -#endif - - void close(error_code& ec) - { - m_sock.next_layer().close(ec); - } - -#ifndef BOOST_NO_EXCEPTIONS - endpoint_type remote_endpoint() const - { - return const_cast(m_sock).next_layer().remote_endpoint(); - } -#endif - - endpoint_type remote_endpoint(error_code& ec) const - { - return const_cast(m_sock).next_layer().remote_endpoint(ec); - } - -#ifndef BOOST_NO_EXCEPTIONS - endpoint_type local_endpoint() const - { - return const_cast(m_sock).next_layer().local_endpoint(); - } -#endif - - endpoint_type local_endpoint(error_code& ec) const - { - return const_cast(m_sock).next_layer().local_endpoint(ec); - } - - io_service& get_io_service() - { - return m_sock.get_io_service(); - } - - lowest_layer_type& lowest_layer() - { - return m_sock.lowest_layer(); - } - - next_layer_type& next_layer() - { - return m_sock.next_layer(); - } - -private: - - void connected(error_code const& e, boost::shared_ptr h) - { - if (e) - { - (*h)(e); - return; - } - - m_sock.async_handshake(asio::ssl::stream_base::client - , boost::bind(&ssl_stream::handshake, this, _1, h)); - } - - void handshake(error_code const& e, boost::shared_ptr h) - { - (*h)(e); - } - - asio::ssl::context m_context; - asio::ssl::stream m_sock; -}; - -} - -#endif - diff --git a/libtorrent/include/libtorrent/stat.hpp b/libtorrent/include/libtorrent/stat.hpp deleted file mode 100644 index d328fd0df..000000000 --- a/libtorrent/include/libtorrent/stat.hpp +++ /dev/null @@ -1,255 +0,0 @@ -/* - -Copyright (c) 2003, Arvid Norberg -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions -are met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in - the documentation and/or other materials provided with the distribution. - * Neither the name of the author nor the names of its - contributors may be used to endorse or promote products derived - from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -POSSIBILITY OF SUCH DAMAGE. - -*/ - -#ifndef TORRENT_STAT_HPP_INCLUDED -#define TORRENT_STAT_HPP_INCLUDED - -#include -#include -#include -#include - -#include "libtorrent/size_type.hpp" -#include "libtorrent/invariant_check.hpp" -#include "libtorrent/config.hpp" -#include "libtorrent/assert.hpp" - -namespace libtorrent -{ - class TORRENT_EXPORT stat_channel - { - friend class invariant_access; - public: - enum { history = 10 }; - - stat_channel() - : m_counter(0) - , m_total_counter(0) - , m_rate_sum(0) - { - std::memset(m_rate_history, 0, sizeof(m_rate_history)); - } - - void operator+=(stat_channel const& s) - { - m_counter += s.m_counter; - m_total_counter += s.m_counter; - } - - void add(int count) - { - TORRENT_ASSERT(count >= 0); - - m_counter += count; - m_total_counter += count; - } - - // should be called once every second - void second_tick(float tick_interval); - float rate() const { return m_rate_sum / float(history); } - size_type rate_sum() const { return m_rate_sum; } - size_type total() const { return m_total_counter; } - - void offset(size_type counter) - { - TORRENT_ASSERT(counter >= 0); - m_total_counter += counter; - } - - size_type counter() const { return m_counter; } - - void clear() - { - std::memset(m_rate_history, 0, sizeof(m_rate_history)); - m_counter = 0; - m_total_counter = 0; - m_rate_sum = 0; - } - - private: - -#ifdef TORRENT_DEBUG - void check_invariant() const - { - int sum = 0; - for (int i = 0; i < history; ++i) sum += m_rate_history[i]; - TORRENT_ASSERT(m_rate_sum == sum); - TORRENT_ASSERT(m_total_counter >= 0); - } -#endif - - // history of rates a few seconds back - int m_rate_history[history]; - - // the accumulator for this second. - int m_counter; - - // total counters - size_type m_total_counter; - - // sum of all elements in m_rate_history - size_type m_rate_sum; - }; - - class TORRENT_EXPORT stat - { - friend class invariant_access; - public: - void operator+=(const stat& s) - { - for (int i = 0; i < num_channels; ++i) - m_stat[i] += s.m_stat[i]; - } - - void received_bytes(int bytes_payload, int bytes_protocol) - { - TORRENT_ASSERT(bytes_payload >= 0); - TORRENT_ASSERT(bytes_protocol >= 0); - - m_stat[download_payload].add(bytes_payload); - m_stat[download_protocol].add(bytes_protocol); - } - - void sent_bytes(int bytes_payload, int bytes_protocol) - { - TORRENT_ASSERT(bytes_payload >= 0); - TORRENT_ASSERT(bytes_protocol >= 0); - - m_stat[upload_payload].add(bytes_payload); - m_stat[upload_protocol].add(bytes_protocol); - } - - // calculate ip protocol overhead - void calc_ip_overhead() - { - int uploaded = m_stat[upload_protocol].counter() - + m_stat[upload_payload].counter(); - int downloaded = m_stat[download_protocol].counter() - + m_stat[download_payload].counter(); - - // IP + TCP headers are 40 bytes per MTU (1460) - // bytes of payload, but at least 40 bytes - m_stat[upload_ip_protocol].add((std::max)(uploaded / 1460, uploaded>0?40:0)); - m_stat[download_ip_protocol].add((std::max)(downloaded / 1460, downloaded>0?40:0)); - - // also account for ACK traffic. That adds to the transfers - // in the opposite direction. Even on connections with symmetric - // transfer rates, it seems to add a penalty. - m_stat[upload_ip_protocol].add((std::max)(downloaded * 40 / 1460, downloaded>0?40:0)); - m_stat[download_ip_protocol].add((std::max)(uploaded * 40 / 1460, uploaded>0?40:0)); - } - - int upload_ip_overhead() const { return m_stat[upload_ip_protocol].counter(); } - int download_ip_overhead() const { return m_stat[download_ip_protocol].counter(); } - - // should be called once every second - void second_tick(float tick_interval) - { - for (int i = 0; i < num_channels; ++i) - m_stat[i].second_tick(tick_interval); - } - - float upload_rate() const - { - return (m_stat[upload_payload].rate_sum() - + m_stat[upload_protocol].rate_sum() - + m_stat[upload_ip_protocol].rate_sum()) - / float(stat_channel::history); - } - - float download_rate() const - { - return (m_stat[download_payload].rate_sum() - + m_stat[download_protocol].rate_sum() - + m_stat[download_ip_protocol].rate_sum()) - / float(stat_channel::history); - } - - float upload_payload_rate() const - { return m_stat[upload_payload].rate(); } - - float download_payload_rate() const - { return m_stat[download_payload].rate(); } - - size_type total_payload_upload() const - { return m_stat[upload_payload].total(); } - size_type total_payload_download() const - { return m_stat[download_payload].total(); } - - size_type total_protocol_upload() const - { return m_stat[upload_protocol].total(); } - size_type total_protocol_download() const - { return m_stat[download_protocol].total(); } - - // this is used to offset the statistics when a - // peer_connection is opened and have some previous - // transfers from earlier connections. - void add_stat(size_type downloaded, size_type uploaded) - { - TORRENT_ASSERT(downloaded >= 0); - TORRENT_ASSERT(uploaded >= 0); - m_stat[download_payload].offset(downloaded); - m_stat[upload_payload].offset(uploaded); - } - - size_type last_payload_downloaded() const - { return m_stat[download_payload].counter(); } - size_type last_payload_uploaded() const - { return m_stat[upload_payload].counter(); } - - void clear() - { - for (int i = 0; i < num_channels; ++i) - m_stat[i].clear(); - } - - private: - - // these are the channels we keep stats for - enum - { - upload_payload, - upload_protocol, - upload_ip_protocol, - download_payload, - download_protocol, - download_ip_protocol, - num_channels - }; - - stat_channel m_stat[num_channels]; - }; - -} - -#endif // TORRENT_STAT_HPP_INCLUDED - diff --git a/libtorrent/include/libtorrent/storage.hpp b/libtorrent/include/libtorrent/storage.hpp deleted file mode 100644 index 6bd1d4755..000000000 --- a/libtorrent/include/libtorrent/storage.hpp +++ /dev/null @@ -1,431 +0,0 @@ -/* - -Copyright (c) 2003, Arvid Norberg -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions -are met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in - the documentation and/or other materials provided with the distribution. - * Neither the name of the author nor the names of its - contributors may be used to endorse or promote products derived - from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -POSSIBILITY OF SUCH DAMAGE. - -*/ - -#ifndef TORRENT_STORAGE_HPP_INCLUDE -#define TORRENT_STORAGE_HPP_INCLUDE - -#include -#include - -#ifdef _MSC_VER -#pragma warning(push, 1) -#endif - -#include -#include -#include -#include -#include - -#ifdef _MSC_VER -#pragma warning(pop) -#endif - - -#include "libtorrent/torrent_info.hpp" -#include "libtorrent/piece_picker.hpp" -#include "libtorrent/intrusive_ptr_base.hpp" -#include "libtorrent/peer_request.hpp" -#include "libtorrent/hasher.hpp" -#include "libtorrent/config.hpp" -#include "libtorrent/buffer.hpp" - -namespace libtorrent -{ - namespace aux - { - struct piece_checker_data; - } - - namespace fs = boost::filesystem; - - class session; - struct file_pool; - struct disk_io_job; - struct disk_buffer_holder; - - enum storage_mode_t - { - storage_mode_allocate = 0, - storage_mode_sparse, - storage_mode_compact - }; - -#if TORRENT_USE_WPATH - - TORRENT_EXPORT std::wstring safe_convert(std::string const& s); - -#endif - - TORRENT_EXPORT std::vector > get_filesizes( - file_storage const& t - , fs::path p); - - TORRENT_EXPORT bool match_filesizes( - file_storage const& t - , fs::path p - , std::vector > const& sizes - , bool compact_mode - , std::string* error = 0); - - struct TORRENT_EXPORT file_allocation_failed: std::exception - { - file_allocation_failed(const char* error_msg): m_msg(error_msg) {} - virtual const char* what() const throw() { return m_msg.c_str(); } - virtual ~file_allocation_failed() throw() {} - std::string m_msg; - }; - - struct TORRENT_EXPORT partial_hash - { - partial_hash(): offset(0) {} - // the number of bytes in the piece that has been hashed - int offset; - // the sha-1 context - hasher h; - }; - - struct TORRENT_EXPORT storage_interface - { - // create directories and set file sizes - // if allocate_files is true. - // allocate_files is true if allocation mode - // is set to full and sparse files are supported - // false return value indicates an error - virtual bool initialize(bool allocate_files) = 0; - - // negative return value indicates an error - virtual int read(char* buf, int slot, int offset, int size) = 0; - - // negative return value indicates an error - virtual int write(const char* buf, int slot, int offset, int size) = 0; - - // non-zero return value indicates an error - virtual bool move_storage(fs::path save_path) = 0; - - // verify storage dependent fast resume entries - virtual bool verify_resume_data(lazy_entry const& rd, std::string& error) = 0; - - // write storage dependent fast resume entries - virtual bool write_resume_data(entry& rd) const = 0; - - // moves (or copies) the content in src_slot to dst_slot - virtual bool move_slot(int src_slot, int dst_slot) = 0; - - // swaps the data in slot1 and slot2 - virtual bool swap_slots(int slot1, int slot2) = 0; - - // swaps the puts the data in slot1 in slot2, the data in slot2 - // in slot3 and the data in slot3 in slot1 - virtual bool swap_slots3(int slot1, int slot2, int slot3) = 0; - - // returns the sha1-hash for the data at the given slot - virtual sha1_hash hash_for_slot(int slot, partial_hash& h, int piece_size) = 0; - - // this will close all open files that are opened for - // writing. This is called when a torrent has finished - // downloading. - // non-zero return value indicates an error - virtual bool release_files() = 0; - - // this will rename the file specified by index. - virtual bool rename_file(int index, std::string const& new_filename) = 0; - - // this will close all open files and delete them - // non-zero return value indicates an error - virtual bool delete_files() = 0; - - void set_error(boost::filesystem::path const& file, error_code const& ec) const - { - m_error_file = file.string(); - m_error = ec; - } - - error_code const& error() const { return m_error; } - std::string const& error_file() const { return m_error_file; } - void clear_error() { m_error = error_code(); m_error_file.clear(); } - - mutable error_code m_error; - mutable std::string m_error_file; - - virtual ~storage_interface() {} - }; - - typedef storage_interface* (&storage_constructor_type)( - file_storage const&, fs::path const&, file_pool&); - - TORRENT_EXPORT storage_interface* default_storage_constructor( - file_storage const&, fs::path const&, file_pool&); - TORRENT_EXPORT storage_interface* mapped_storage_constructor( - file_storage const&, fs::path const&, file_pool&); - - struct disk_io_thread; - - class TORRENT_EXPORT piece_manager - : public intrusive_ptr_base - , boost::noncopyable - { - friend class invariant_access; - friend struct disk_io_thread; - public: - - piece_manager( - boost::shared_ptr const& torrent - , boost::intrusive_ptr info - , fs::path const& path - , file_pool& fp - , disk_io_thread& io - , storage_constructor_type sc - , storage_mode_t sm); - - ~piece_manager(); - - boost::intrusive_ptr info() const { return m_info; } - void write_resume_data(entry& rd) const; - - void async_check_fastresume(lazy_entry const* resume_data - , boost::function const& handler); - - void async_check_files(boost::function const& handler); - - void async_rename_file(int index, std::string const& name - , boost::function const& handler); - - void async_read( - peer_request const& r - , boost::function const& handler - , int priority = 0); - - void async_write( - peer_request const& r - , disk_buffer_holder& buffer - , boost::function const& f); - - void async_hash(int piece, boost::function const& f); - - void async_release_files( - boost::function const& handler - = boost::function()); - - void abort_disk_io(); - - void async_clear_read_cache( - boost::function const& handler - = boost::function()); - - void async_delete_files( - boost::function const& handler - = boost::function()); - - void async_move_storage(fs::path const& p - , boost::function const& handler); - - void async_save_resume_data( - boost::function const& handler); - - enum return_t - { - // return values from check_fastresume and check_files - no_error = 0, - need_full_check = -1, - fatal_disk_error = -2, - disk_check_aborted = -3 - }; - - storage_interface* get_storage_impl() { return m_storage.get(); } - - private: - - fs::path save_path() const; - - bool verify_resume_data(lazy_entry const& rd, std::string& error) - { return m_storage->verify_resume_data(rd, error); } - - bool is_allocating() const - { return m_state == state_expand_pieces; } - - void mark_failed(int index); - - error_code const& error() const { return m_storage->error(); } - std::string const& error_file() const { return m_storage->error_file(); } - void clear_error() { m_storage->clear_error(); } - - int slot_for(int piece) const; - int piece_for(int slot) const; - - // helper functions for check_dastresume - int check_no_fastresume(std::string& error); - int check_init_storage(std::string& error); - - // if error is set and return value is 'no_error' or 'need_full_check' - // the error message indicates that the fast resume data was rejected - // if 'fatal_disk_error' is returned, the error message indicates what - // when wrong in the disk access - int check_fastresume(lazy_entry const& rd, std::string& error); - - // this function returns true if the checking is complete - int check_files(int& current_slot, int& have_piece, std::string& error); - - bool compact_allocation() const - { return m_storage_mode == storage_mode_compact; } - -#ifdef TORRENT_DEBUG - std::string name() const { return m_info->name(); } -#endif - - bool allocate_slots(int num_slots, bool abort_on_disk = false); - - int read_impl( - char* buf - , int piece_index - , int offset - , int size); - - int write_impl( - const char* buf - , int piece_index - , int offset - , int size); - - // -1=error 0=ok 1=skip - int check_one_piece(int& have_piece); - int identify_data( - const std::vector& piece_data - , int current_slot); - - void switch_to_full_mode(); - sha1_hash hash_for_piece_impl(int piece); - - int release_files_impl() { return m_storage->release_files(); } - int delete_files_impl() { return m_storage->delete_files(); } - int rename_file_impl(int index, std::string const& new_filename) - { return m_storage->rename_file(index, new_filename); } - - int move_storage_impl(fs::path const& save_path); - - int allocate_slot_for_piece(int piece_index); -#ifdef TORRENT_DEBUG - void check_invariant() const; -#ifdef TORRENT_STORAGE_DEBUG - void debug_log() const; -#endif -#endif - boost::intrusive_ptr m_info; - file_storage const& m_files; - - boost::scoped_ptr m_storage; - - storage_mode_t m_storage_mode; - - // slots that haven't had any file storage allocated - std::vector m_unallocated_slots; - // slots that have file storage, but isn't assigned to a piece - std::vector m_free_slots; - - enum - { - has_no_slot = -3 // the piece has no storage - }; - - // maps piece indices to slots. If a piece doesn't - // have any storage, it is set to 'has_no_slot' - std::vector m_piece_to_slot; - - enum - { - unallocated = -1, // the slot is unallocated - unassigned = -2 // the slot is allocated but not assigned to a piece - }; - - // maps slots to piece indices, if a slot doesn't have a piece - // it can either be 'unassigned' or 'unallocated' - std::vector m_slot_to_piece; - - fs::path m_save_path; - - mutable boost::recursive_mutex m_mutex; - - enum { - // the default initial state - state_none, - // the file checking is complete - state_finished, - // checking the files - state_full_check, - // move pieces to their final position - state_expand_pieces - } m_state; - int m_current_slot; - // used during check. If any piece is found - // that is not in its final position, this - // is set to true - bool m_out_of_place; - // used to move pieces while expanding - // the storage from compact allocation - // to full allocation - buffer m_scratch_buffer; - buffer m_scratch_buffer2; - // the piece that is in the scratch buffer - int m_scratch_piece; - - // this is saved in case we need to instantiate a new - // storage (osed when remapping files) - storage_constructor_type m_storage_constructor; - - // temporary buffer used while checking - std::vector m_piece_data; - - // this maps a piece hash to piece index. It will be - // build the first time it is used (to save time if it - // isn't needed) - std::multimap m_hash_to_piece; - - // this map contains partial hashes for downloading - // pieces. This is only accessed from within the - // disk-io thread. - std::map m_piece_hasher; - - disk_io_thread& m_io_thread; - - // the reason for this to be a void pointer - // is to avoid creating a dependency on the - // torrent. This shared_ptr is here only - // to keep the torrent object alive until - // the piece_manager destructs. This is because - // the torrent_info object is owned by the torrent. - boost::shared_ptr m_torrent; - }; - -} - -#endif // TORRENT_STORAGE_HPP_INCLUDED - diff --git a/libtorrent/include/libtorrent/time.hpp b/libtorrent/include/libtorrent/time.hpp deleted file mode 100644 index 93aa17a34..000000000 --- a/libtorrent/include/libtorrent/time.hpp +++ /dev/null @@ -1,412 +0,0 @@ -/* - -Copyright (c) 2007, Arvid Norberg -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions -are met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in - the documentation and/or other materials provided with the distribution. - * Neither the name of the author nor the names of its - contributors may be used to endorse or promote products derived - from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -POSSIBILITY OF SUCH DAMAGE. - -*/ - -#ifndef TORRENT_TIME_HPP_INCLUDED -#define TORRENT_TIME_HPP_INCLUDED - -#include -#include - -#ifndef _WIN32 -#include -#endif - -namespace libtorrent -{ - inline char const* time_now_string() - { - time_t t = std::time(0); - tm* timeinfo = std::localtime(&t); - static char str[200]; - std::strftime(str, 200, "%b %d %X", timeinfo); - return str; - } - - std::string log_time(); -} - -#if (!defined (__MACH__) && !defined (_WIN32) && (!defined(_POSIX_MONOTONIC_CLOCK) \ - || _POSIX_MONOTONIC_CLOCK < 0)) || defined (TORRENT_USE_BOOST_DATE_TIME) - -#include -#include "libtorrent/assert.hpp" - -namespace libtorrent -{ - typedef boost::posix_time::ptime ptime; - typedef boost::posix_time::time_duration time_duration; - inline ptime time_now() - { return boost::posix_time::microsec_clock::universal_time(); } - inline ptime min_time() - { return boost::posix_time::ptime(boost::posix_time::min_date_time); } - inline ptime max_time() - { return boost::posix_time::ptime(boost::posix_time::max_date_time); } - inline time_duration seconds(int s) { return boost::posix_time::seconds(s); } - inline time_duration milliseconds(int s) { return boost::posix_time::milliseconds(s); } - inline time_duration microsec(int s) { return boost::posix_time::microsec(s); } - inline time_duration minutes(int s) { return boost::posix_time::minutes(s); } - inline time_duration hours(int s) { return boost::posix_time::hours(s); } - - inline int total_seconds(time_duration td) - { return td.total_seconds(); } - inline int total_milliseconds(time_duration td) - { return td.total_milliseconds(); } - inline boost::int64_t total_microseconds(time_duration td) - { return td.total_microseconds(); } - -} - -#else - -#if BOOST_VERSION < 103500 -#include -#else -#include -#endif -#include -#include "libtorrent/assert.hpp" - -namespace libtorrent -{ - // libtorrent time_duration type - struct time_duration - { - time_duration() {} - time_duration operator/(int rhs) const { return time_duration(diff / rhs); } - explicit time_duration(boost::int64_t d) : diff(d) {} - time_duration& operator-=(time_duration const& c) { diff -= c.diff; return *this; } - time_duration& operator+=(time_duration const& c) { diff += c.diff; return *this; } - time_duration operator+(time_duration const& c) { return time_duration(diff + c.diff); } - boost::int64_t diff; - }; - - inline bool is_negative(time_duration dt) { return dt.diff < 0; } - inline bool operator<(time_duration lhs, time_duration rhs) - { return lhs.diff < rhs.diff; } - inline bool operator<=(time_duration lhs, time_duration rhs) - { return lhs.diff <= rhs.diff; } - inline bool operator>(time_duration lhs, time_duration rhs) - { return lhs.diff > rhs.diff; } - inline bool operator>=(time_duration lhs, time_duration rhs) - { return lhs.diff >= rhs.diff; } - - // libtorrent time type - struct ptime - { - ptime() {} - explicit ptime(boost::int64_t t): time(t) {} - ptime& operator+=(time_duration rhs) { time += rhs.diff; return *this; } - ptime& operator-=(time_duration rhs) { time -= rhs.diff; return *this; } - boost::int64_t time; - }; - - inline bool operator>(ptime lhs, ptime rhs) - { return lhs.time > rhs.time; } - inline bool operator>=(ptime lhs, ptime rhs) - { return lhs.time >= rhs.time; } - inline bool operator<=(ptime lhs, ptime rhs) - { return lhs.time <= rhs.time; } - inline bool operator<(ptime lhs, ptime rhs) - { return lhs.time < rhs.time; } - inline bool operator!=(ptime lhs, ptime rhs) - { return lhs.time != rhs.time;} - inline bool operator==(ptime lhs, ptime rhs) - { return lhs.time == rhs.time;} - inline time_duration operator-(ptime lhs, ptime rhs) - { return time_duration(lhs.time - rhs.time); } - inline ptime operator+(ptime lhs, time_duration rhs) - { return ptime(lhs.time + rhs.diff); } - inline ptime operator+(time_duration lhs, ptime rhs) - { return ptime(rhs.time + lhs.diff); } - inline ptime operator-(ptime lhs, time_duration rhs) - { return ptime(lhs.time - rhs.diff); } - - ptime time_now(); - inline ptime min_time() { return ptime(0); } - inline ptime max_time() { return ptime((std::numeric_limits::max)()); } - int total_seconds(time_duration td); - int total_milliseconds(time_duration td); - boost::int64_t total_microseconds(time_duration td); -} - -// asio time_traits -#if BOOST_VERSION >= 103500 -namespace boost { -#endif -namespace asio -{ - template<> - struct time_traits - { - typedef libtorrent::ptime time_type; - typedef libtorrent::time_duration duration_type; - static time_type now() - { return time_type(libtorrent::time_now()); } - static time_type add(time_type t, duration_type d) - { return time_type(t.time + d.diff);} - static duration_type subtract(time_type t1, time_type t2) - { return duration_type(t1 - t2); } - static bool less_than(time_type t1, time_type t2) - { return t1 < t2; } - static boost::posix_time::time_duration to_posix_duration( - duration_type d) - { return boost::posix_time::microseconds(libtorrent::total_microseconds(d)); } - }; -} -#if BOOST_VERSION >= 103500 -} -#endif - -#if defined(__MACH__) - -#include -#include -#include "libtorrent/assert.hpp" - -// high precision timer for darwin intel and ppc - -namespace libtorrent -{ - namespace aux - { - inline boost::int64_t absolutetime_to_microseconds(boost::int64_t at) - { - static mach_timebase_info_data_t timebase_info = {0,0}; - if (timebase_info.denom == 0) - mach_timebase_info(&timebase_info); - // make sure we don't overflow - TORRENT_ASSERT((at >= 0 && at >= at / 1000 * timebase_info.numer / timebase_info.denom) - || (at < 0 && at < at / 1000 * timebase_info.numer / timebase_info.denom)); - return at / 1000 * timebase_info.numer / timebase_info.denom; - } - - inline boost::int64_t microseconds_to_absolutetime(boost::int64_t ms) - { - static mach_timebase_info_data_t timebase_info = {0,0}; - if (timebase_info.denom == 0) - { - mach_timebase_info(&timebase_info); - TORRENT_ASSERT(timebase_info.numer > 0); - TORRENT_ASSERT(timebase_info.denom > 0); - } - // make sure we don't overflow - TORRENT_ASSERT((ms >= 0 && ms <= ms * timebase_info.denom / timebase_info.numer * 1000) - || (ms < 0 && ms > ms * timebase_info.denom / timebase_info.numer * 1000)); - return ms * timebase_info.denom / timebase_info.numer * 1000; - } - } - - inline int total_seconds(time_duration td) - { - return aux::absolutetime_to_microseconds(td.diff) - / 1000000; - } - inline int total_milliseconds(time_duration td) - { - return aux::absolutetime_to_microseconds(td.diff) - / 1000; - } - inline boost::int64_t total_microseconds(time_duration td) - { - return aux::absolutetime_to_microseconds(td.diff); - } - - inline ptime time_now() { return ptime(mach_absolute_time()); } - - inline time_duration microsec(boost::int64_t s) - { - return time_duration(aux::microseconds_to_absolutetime(s)); - } - inline time_duration milliseconds(boost::int64_t s) - { - return time_duration(aux::microseconds_to_absolutetime(s * 1000)); - } - inline time_duration seconds(boost::int64_t s) - { - return time_duration(aux::microseconds_to_absolutetime(s * 1000000)); - } - inline time_duration minutes(boost::int64_t s) - { - return time_duration(aux::microseconds_to_absolutetime(s * 1000000 * 60)); - } - inline time_duration hours(boost::int64_t s) - { - return time_duration(aux::microseconds_to_absolutetime(s * 1000000 * 60 * 60)); - } - -} -#elif defined(_WIN32) - -#ifndef WIN32_LEAN_AND_MEAN -#define WIN32_LEAN_AND_MEAN -#endif -#include -#include "libtorrent/assert.hpp" - -namespace libtorrent -{ - namespace aux - { - inline boost::int64_t performance_counter_to_microseconds(boost::int64_t pc) - { - static LARGE_INTEGER performace_counter_frequency = {0,0}; - if (performace_counter_frequency.QuadPart == 0) - QueryPerformanceFrequency(&performace_counter_frequency); - -#ifdef TORRENT_DEBUG - // make sure we don't overflow - boost::int64_t ret = (pc * 1000 / performace_counter_frequency.QuadPart) * 1000; - TORRENT_ASSERT((pc >= 0 && pc >= ret) || (pc < 0 && pc < ret)); -#endif - return (pc * 1000 / performace_counter_frequency.QuadPart) * 1000; - } - - inline boost::int64_t microseconds_to_performance_counter(boost::int64_t ms) - { - static LARGE_INTEGER performace_counter_frequency = {0,0}; - if (performace_counter_frequency.QuadPart == 0) - QueryPerformanceFrequency(&performace_counter_frequency); -#ifdef TORRENT_DEBUG - // make sure we don't overflow - boost::int64_t ret = (ms / 1000) * performace_counter_frequency.QuadPart / 1000; - TORRENT_ASSERT((ms >= 0 && ms <= ret) - || (ms < 0 && ms > ret)); -#endif - return (ms / 1000) * performace_counter_frequency.QuadPart / 1000; - } - } - - inline int total_seconds(time_duration td) - { - return int(aux::performance_counter_to_microseconds(td.diff) - / 1000000); - } - inline int total_milliseconds(time_duration td) - { - return int(aux::performance_counter_to_microseconds(td.diff) - / 1000); - } - inline boost::int64_t total_microseconds(time_duration td) - { - return aux::performance_counter_to_microseconds(td.diff); - } - - inline ptime time_now() - { - LARGE_INTEGER now; - QueryPerformanceCounter(&now); - return ptime(now.QuadPart); - } - - inline time_duration microsec(boost::int64_t s) - { - return time_duration(aux::microseconds_to_performance_counter(s)); - } - inline time_duration milliseconds(boost::int64_t s) - { - return time_duration(aux::microseconds_to_performance_counter( - s * 1000)); - } - inline time_duration seconds(boost::int64_t s) - { - return time_duration(aux::microseconds_to_performance_counter( - s * 1000000)); - } - inline time_duration minutes(boost::int64_t s) - { - return time_duration(aux::microseconds_to_performance_counter( - s * 1000000 * 60)); - } - inline time_duration hours(boost::int64_t s) - { - return time_duration(aux::microseconds_to_performance_counter( - s * 1000000 * 60 * 60)); - } - -} - -#elif defined(_POSIX_MONOTONIC_CLOCK) && _POSIX_MONOTONIC_CLOCK >= 0 - -#include -#include "libtorrent/assert.hpp" - -namespace libtorrent -{ - inline int total_seconds(time_duration td) - { - return td.diff / 1000000; - } - inline int total_milliseconds(time_duration td) - { - return td.diff / 1000; - } - inline boost::int64_t total_microseconds(time_duration td) - { - return td.diff; - } - - inline ptime time_now() - { - timespec ts; - clock_gettime(CLOCK_MONOTONIC, &ts); - return ptime(boost::int64_t(ts.tv_sec) * 1000000 + ts.tv_nsec / 1000); - } - - inline time_duration microsec(boost::int64_t s) - { - return time_duration(s); - } - inline time_duration milliseconds(boost::int64_t s) - { - return time_duration(s * 1000); - } - inline time_duration seconds(boost::int64_t s) - { - return time_duration(s * 1000000); - } - inline time_duration minutes(boost::int64_t s) - { - return time_duration(s * 1000000 * 60); - } - inline time_duration hours(boost::int64_t s) - { - return time_duration(s * 1000000 * 60 * 60); - } - -} - -#endif - -#endif - -#endif - diff --git a/libtorrent/include/libtorrent/torrent.hpp b/libtorrent/include/libtorrent/torrent.hpp deleted file mode 100644 index f5f210b38..000000000 --- a/libtorrent/include/libtorrent/torrent.hpp +++ /dev/null @@ -1,1022 +0,0 @@ -/* - -Copyright (c) 2003, Arvid Norberg -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions -are met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in - the documentation and/or other materials provided with the distribution. - * Neither the name of the author nor the names of its - contributors may be used to endorse or promote products derived - from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -POSSIBILITY OF SUCH DAMAGE. - -*/ - -#ifndef TORRENT_TORRENT_HPP_INCLUDE -#define TORRENT_TORRENT_HPP_INCLUDE - -#include -#include -#include -#include -#include - -#ifdef _MSC_VER -#pragma warning(push, 1) -#endif - -#include -#include -#include -#include -#include -#include - -#ifdef _MSC_VER -#pragma warning(pop) -#endif - -#include "libtorrent/torrent_handle.hpp" -#include "libtorrent/entry.hpp" -#include "libtorrent/torrent_info.hpp" -#include "libtorrent/socket.hpp" -#include "libtorrent/policy.hpp" -#include "libtorrent/tracker_manager.hpp" -#include "libtorrent/stat.hpp" -#include "libtorrent/alert.hpp" -#include "libtorrent/piece_picker.hpp" -#include "libtorrent/config.hpp" -#include "libtorrent/escape_string.hpp" -#include "libtorrent/bandwidth_limit.hpp" -#include "libtorrent/bandwidth_queue_entry.hpp" -#include "libtorrent/storage.hpp" -#include "libtorrent/hasher.hpp" -#include "libtorrent/assert.hpp" -#include "libtorrent/bitfield.hpp" - -namespace libtorrent -{ -#if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING) - struct logger; -#endif - - class piece_manager; - struct torrent_plugin; - struct bitfield; - - namespace aux - { - struct session_impl; - struct piece_checker_data; - } - - namespace fs = boost::filesystem; - - // a torrent is a class that holds information - // for a specific download. It updates itself against - // the tracker - class TORRENT_EXPORT torrent: public request_callback - , public boost::enable_shared_from_this - { - public: - - torrent( - aux::session_impl& ses - , boost::intrusive_ptr tf - , fs::path const& save_path - , tcp::endpoint const& net_interface - , storage_mode_t m_storage_mode - , int block_size - , storage_constructor_type sc - , bool paused - , std::vector* resume_data - , int seq - , bool auto_managed); - - // used with metadata-less torrents - // (the metadata is downloaded from the peers) - torrent( - aux::session_impl& ses - , char const* tracker_url - , sha1_hash const& info_hash - , char const* name - , fs::path const& save_path - , tcp::endpoint const& net_interface - , storage_mode_t m_storage_mode - , int block_size - , storage_constructor_type sc - , bool paused - , std::vector* resume_data - , int seq - , bool auto_managed); - - ~torrent(); - -#ifndef TORRENT_DISABLE_ENCRYPTION - sha1_hash const& obfuscated_hash() const - { return m_obfuscated_hash; } -#endif - - sha1_hash const& info_hash() const - { return m_torrent_file->info_hash(); } - - // starts the announce timer - void start(); - -#ifndef TORRENT_DISABLE_EXTENSIONS - void add_extension(boost::shared_ptr); - void add_extension(boost::function(torrent*, void*)> const& ext - , void* userdata); -#endif - -#ifdef TORRENT_DEBUG - bool has_peer(peer_connection* p) const - { return m_connections.find(p) != m_connections.end(); } -#endif - - // this is called when the torrent has metadata. - // it will initialize the storage and the piece-picker - void init(); - - void on_resume_data_checked(int ret, disk_io_job const& j); - void on_force_recheck(int ret, disk_io_job const& j); - void on_piece_checked(int ret, disk_io_job const& j); - void files_checked(); - void start_checking(); - - void start_announcing(); - void stop_announcing(); - - int seed_rank(session_settings const& s) const; - - storage_mode_t storage_mode() const { return m_storage_mode; } - storage_interface* get_storage() - { - if (!m_owning_storage) return 0; - return m_owning_storage->get_storage_impl(); - } - - // this will flag the torrent as aborted. The main - // loop in session_impl will check for this state - // on all torrents once every second, and take - // the necessary actions then. - void abort(); - bool is_aborted() const { return m_abort; } - - torrent_status::state_t state() const { return m_state; } - void set_state(torrent_status::state_t s); - - void clear_error(); - - session_settings const& settings() const; - - aux::session_impl& session() { return m_ses; } - - void set_sequential_download(bool sd); - bool is_sequential_download() const - { return m_sequential_download; } - - void set_queue_position(int p); - int queue_position() const { return m_sequence_number; } - - void second_tick(stat& accumulator, float tick_interval); - - // debug purpose only - void print(std::ostream& os) const; - - std::string name() const; - - stat statistics() const { return m_stat; } - void add_stats(stat const& s) { m_stat += s; } - size_type bytes_left() const; - boost::tuples::tuple bytes_done() const; - size_type quantized_bytes_done() const; - - void ip_filter_updated() { m_policy.ip_filter_updated(); } - - void set_error(std::string const& msg); - bool has_error() const { return !m_error.empty(); } - void pause(); - void resume(); - - ptime started() const { return m_started; } - void do_pause(); - void do_resume(); - - bool is_paused() const; - bool is_torrent_paused() const { return m_paused; } - void force_recheck(); - void save_resume_data(); - - bool is_auto_managed() const { return m_auto_managed; } - void auto_managed(bool a); - - bool should_check_files() const; - - void delete_files(); - - // ============ start deprecation ============= - void filter_piece(int index, bool filter); - void filter_pieces(std::vector const& bitmask); - bool is_piece_filtered(int index) const; - void filtered_pieces(std::vector& bitmask) const; - void filter_files(std::vector const& files); - void file_progress(std::vector& fp) const; - // ============ end deprecation ============= - - void piece_availability(std::vector& avail) const; - - void set_piece_priority(int index, int priority); - int piece_priority(int index) const; - - void prioritize_pieces(std::vector const& pieces); - void piece_priorities(std::vector&) const; - - void set_file_priority(int index, int priority); - int file_priority(int index) const; - - void prioritize_files(std::vector const& files); - void file_priorities(std::vector&) const; - - void update_piece_priorities(); - - torrent_status status() const; - - void file_progress(std::vector& fp) const; - - void use_interface(const char* net_interface); - tcp::endpoint const& get_interface() const { return m_net_interface; } - - void connect_to_url_seed(std::string const& url); - bool connect_to_peer(policy::peer* peerinfo); - - void set_ratio(float ratio) - { TORRENT_ASSERT(ratio >= 0.0f); m_ratio = ratio; } - - float ratio() const - { return m_ratio; } - -#ifndef TORRENT_DISABLE_RESOLVE_COUNTRIES - void resolve_countries(bool r) - { m_resolve_countries = r; } - - bool resolving_countries() const { return m_resolve_countries; } -#endif - -// -------------------------------------------- - // BANDWIDTH MANAGEMENT - - bandwidth_limit m_bandwidth_limit[2]; - - void request_bandwidth(int channel - , boost::intrusive_ptr const& p - , int max_block_size, int priority); - - void perform_bandwidth_request(int channel - , boost::intrusive_ptr const& p - , int block_size, int priority); - - void expire_bandwidth(int channel, int amount); - void assign_bandwidth(int channel, int amount, int blk); - - int bandwidth_throttle(int channel) const; - - int max_assignable_bandwidth(int channel) const - { return m_bandwidth_limit[channel].max_assignable(); } - - int bandwidth_queue_size(int channel) const; - -// -------------------------------------------- - // PEER MANAGEMENT - - // add or remove a url that will be attempted for - // finding the file(s) in this torrent. - void add_url_seed(std::string const& url) - { m_web_seeds.insert(url); } - - void remove_url_seed(std::string const& url) - { m_web_seeds.erase(url); } - - void retry_url_seed(std::string const& url); - - std::set url_seeds() const - { return m_web_seeds; } - - bool free_upload_slots() const - { return m_num_uploads < m_max_uploads; } - - void choke_peer(peer_connection& c); - bool unchoke_peer(peer_connection& c); - - // used by peer_connection to attach itself to a torrent - // since incoming connections don't know what torrent - // they're a part of until they have received an info_hash. - // false means attach failed - bool attach_peer(peer_connection* p); - - // this will remove the peer and make sure all - // the pieces it had have their reference counter - // decreased in the piece_picker - void remove_peer(peer_connection* p); - - void cancel_block(piece_block block); - - bool want_more_peers() const; - bool try_connect_peer(); - void give_connect_points(int points); - - // the number of peers that belong to this torrent - int num_peers() const { return (int)m_connections.size(); } - int num_seeds() const; - - typedef std::set::iterator peer_iterator; - typedef std::set::const_iterator const_peer_iterator; - - const_peer_iterator begin() const { return m_connections.begin(); } - const_peer_iterator end() const { return m_connections.end(); } - - peer_iterator begin() { return m_connections.begin(); } - peer_iterator end() { return m_connections.end(); } - - void resolve_peer_country(boost::intrusive_ptr const& p) const; - - void get_full_peer_list(std::vector& v) const; - void get_peer_info(std::vector& v); - void get_download_queue(std::vector& queue); - -// -------------------------------------------- - // TRACKER MANAGEMENT - - // these are callbacks called by the tracker_connection instance - // (either http_tracker_connection or udp_tracker_connection) - // when this torrent got a response from its tracker request - // or when a failure occured - virtual void tracker_response( - tracker_request const& r - , std::vector& e, int interval - , int complete, int incomplete, address const& external_ip); - virtual void tracker_request_timed_out( - tracker_request const& r); - virtual void tracker_request_error(tracker_request const& r - , int response_code, const std::string& str); - virtual void tracker_warning(tracker_request const& req - , std::string const& msg); - virtual void tracker_scrape_response(tracker_request const& req - , int complete, int incomplete, int downloaded); - - // if no password and username is set - // this will return an empty string, otherwise - // it will concatenate the login and password - // ready to be sent over http (but without - // base64 encoding). - std::string tracker_login() const; - - // returns the absolute time when the next tracker - // announce will take place. - ptime next_announce() const; - - // forcefully sets next_announce to the current time - void force_tracker_request(); - void force_tracker_request(ptime); - void scrape_tracker(); - void announce_with_tracker(tracker_request::event_t e - = tracker_request::none); - ptime const& last_scrape() const { return m_last_scrape; } - - // sets the username and password that will be sent to - // the tracker - void set_tracker_login(std::string const& name, std::string const& pw); - - // the tcp::endpoint of the tracker that we managed to - // announce ourself at the last time we tried to announce - const tcp::endpoint& current_tracker() const; - -// -------------------------------------------- - // PIECE MANAGEMENT - - // returns true if we have downloaded the given piece - bool have_piece(int index) const - { - return has_picker()?m_picker->have_piece(index):true; - } - - int num_have() const - { - return has_picker() - ?m_picker->num_have() - :m_torrent_file->num_pieces(); - } - - // when we get a have message, this is called for that piece - void peer_has(int index) - { - if (m_picker.get()) - { - TORRENT_ASSERT(!is_seed()); - m_picker->inc_refcount(index); - } -#ifdef TORRENT_DEBUG - else - { - TORRENT_ASSERT(is_seed()); - } -#endif - } - - // when we get a bitfield message, this is called for that piece - void peer_has(bitfield const& bits) - { - if (m_picker.get()) - { - TORRENT_ASSERT(!is_seed()); - m_picker->inc_refcount(bits); - } -#ifdef TORRENT_DEBUG - else - { - TORRENT_ASSERT(is_seed()); - } -#endif - } - - void peer_has_all() - { - if (m_picker.get()) - { - TORRENT_ASSERT(!is_seed()); - m_picker->inc_refcount_all(); - } -#ifdef TORRENT_DEBUG - else - { - TORRENT_ASSERT(is_seed()); - } -#endif - } - - void peer_lost(int index) - { - if (m_picker.get()) - { - TORRENT_ASSERT(!is_seed()); - m_picker->dec_refcount(index); - } -#ifdef TORRENT_DEBUG - else - { - TORRENT_ASSERT(is_seed()); - } -#endif - } - - int block_size() const { TORRENT_ASSERT(m_block_size > 0); return m_block_size; } - peer_request to_req(piece_block const& p); - - void disconnect_all(); - int disconnect_peers(int num); - - // this is called wheh the torrent has completed - // the download. It will post an event, disconnect - // all seeds and let the tracker know we're finished. - void completed(); - - // this is the asio callback that is called when a name - // lookup for a PEER is completed. - void on_peer_name_lookup(error_code const& e, tcp::resolver::iterator i - , peer_id pid); - - // this is the asio callback that is called when a name - // lookup for a WEB SEED is completed. - void on_name_lookup(error_code const& e, tcp::resolver::iterator i - , std::string url, tcp::endpoint proxy); - - // this is the asio callback that is called when a name - // lookup for a proxy for a web seed is completed. - void on_proxy_name_lookup(error_code const& e, tcp::resolver::iterator i - , std::string url); - - // this is called when the torrent has finished. i.e. - // all the pieces we have not filtered have been downloaded. - // If no pieces are filtered, this is called first and then - // completed() is called immediately after it. - void finished(); - - // This is the opposite of finished. It is called if we used - // to be finished but enabled some files for download so that - // we wasn't finished anymore. - void resume_download(); - - void async_verify_piece(int piece_index, boost::function const&); - - // this is called from the peer_connection - // each time a piece has failed the hash - // test - void piece_finished(int index, int passed_hash_check); - - // piece_passed is called when a piece passes the hash check - // this will tell all peers that we just got his piece - // and also let the piece picker know that we have this piece - // so it wont pick it for download - void piece_passed(int index); - - // piece_failed is called when a piece fails the hash check - void piece_failed(int index); - - // this will restore the piece picker state for a piece - // by re marking all the requests to blocks in this piece - // that are still outstanding in peers' download queues. - // this is done when a piece fails - void restore_piece_state(int index); - - void add_redundant_bytes(int b); - void add_failed_bytes(int b); - - // this is true if we have all the pieces - bool is_seed() const - { - return valid_metadata() - && (!m_picker - || m_state == torrent_status::seeding - || m_picker->num_have() == m_picker->num_pieces()); - } - - // this is true if we have all the pieces that we want - bool is_finished() const - { - if (is_seed()) return true; - return valid_metadata() && m_torrent_file->num_pieces() - - m_picker->num_have() - m_picker->num_filtered() == 0; - } - - fs::path save_path() const; - alert_manager& alerts() const; - piece_picker& picker() - { - TORRENT_ASSERT(m_picker.get()); - return *m_picker; - } - bool has_picker() const - { - return m_picker.get() != 0; - } - policy& get_policy() { return m_policy; } - piece_manager& filesystem(); - torrent_info const& torrent_file() const - { return *m_torrent_file; } - - std::vector const& trackers() const - { return m_trackers; } - - void replace_trackers(std::vector const& urls); - - torrent_handle get_handle(); - - void write_resume_data(entry& rd) const; - void read_resume_data(lazy_entry const& rd); - - // LOGGING -#if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_LOGGING || defined TORRENT_ERROR_LOGGING - virtual void debug_log(const std::string& line); -#endif - - // DEBUG -#ifdef TORRENT_DEBUG - void check_invariant() const; -#endif - -// -------------------------------------------- - // RESOURCE MANAGEMENT - - void set_peer_upload_limit(tcp::endpoint ip, int limit); - void set_peer_download_limit(tcp::endpoint ip, int limit); - - void set_upload_limit(int limit); - int upload_limit() const; - void set_download_limit(int limit); - int download_limit() const; - - void set_max_uploads(int limit); - int max_uploads() const { return m_max_uploads; } - void set_max_connections(int limit); - int max_connections() const { return m_max_connections; } - - void move_storage(fs::path const& save_path); - - // renames the file with the given index to the new name - // the name may include a directory path - // returns false on failure - bool rename_file(int index, std::string const& name); - - // unless this returns true, new connections must wait - // with their initialization. - bool ready_for_connections() const - { return m_connections_initialized; } - bool valid_metadata() const - { return m_torrent_file->is_valid(); } - bool are_files_checked() const - { return m_files_checked; } - - // parses the info section from the given - // bencoded tree and moves the torrent - // to the checker thread for initial checking - // of the storage. - // a return value of false indicates an error - bool set_metadata(lazy_entry const& metadata, std::string& error); - - int sequence_number() const { return m_sequence_number; } - - private: - - void on_files_deleted(int ret, disk_io_job const& j); - void on_files_released(int ret, disk_io_job const& j); - void on_torrent_paused(int ret, disk_io_job const& j); - void on_storage_moved(int ret, disk_io_job const& j); - void on_save_resume_data(int ret, disk_io_job const& j); - void on_file_renamed(int ret, disk_io_job const& j); - - void on_piece_verified(int ret, disk_io_job const& j - , boost::function f); - - void try_next_tracker(tracker_request const& req); - int prioritize_tracker(int tracker_index); - void on_country_lookup(error_code const& error, tcp::resolver::iterator i - , boost::intrusive_ptr p) const; - bool request_bandwidth_from_session(int channel) const; - - void update_peer_interest(bool was_finished); - - void queue_torrent_check(); - void dequeue_torrent_check(); - - policy m_policy; - - // total time we've been available on this torrent - // does not count when the torrent is stopped or paused - time_duration m_active_time; - - // total time we've been available as a seed on this torrent - // does not count when the torrent is stopped or paused - time_duration m_seeding_time; - - // all time totals of uploaded and downloaded payload - // stored in resume data - size_type m_total_uploaded; - size_type m_total_downloaded; - - // if this torrent is running, this was the time - // when it was started. This is used to have a - // bias towards keeping seeding torrents that - // recently was started, to avoid oscillation - ptime m_started; - - // the last time we initiated a scrape request to - // one of the trackers in this torrent - ptime m_last_scrape; - - boost::intrusive_ptr m_torrent_file; - - void parse_response(const entry& e, std::vector& peer_list); - - // if this pointer is 0, the torrent is in - // a state where the metadata hasn't been - // received yet. - // the piece_manager keeps the torrent object - // alive by holding a shared_ptr to it and - // the torrent keeps the piece manager alive - // with this intrusive_ptr. This cycle is - // broken when torrent::abort() is called - // Then the torrent releases the piece_manager - // and when the piece_manager is complete with all - // outstanding disk io jobs (that keeps - // the piece_manager alive) it will destruct - // and release the torrent file. The reason for - // this is that the torrent_info is used by - // the piece_manager, and stored in the - // torrent, so the torrent cannot destruct - // before the piece_manager. - boost::intrusive_ptr m_owning_storage; - - // this is a weak (non owninig) pointer to - // the piece_manager. This is used after the torrent - // has been aborted, and it can no longer own - // the object. - piece_manager* m_storage; - - // the time of next tracker announce - ptime m_next_tracker_announce; - -#ifdef TORRENT_DEBUG - public: -#endif - std::set m_connections; -#ifdef TORRENT_DEBUG - private: -#endif - - // The list of web seeds in this torrent. Seeds - // with fatal errors are removed from the set - std::set m_web_seeds; - - // a list of web seeds that have failed and are - // waiting to be retried - std::map m_web_seeds_next_retry; - - // urls of the web seeds that we are currently - // resolving the address for - std::set m_resolving_web_seeds; - -#ifndef TORRENT_DISABLE_EXTENSIONS - typedef std::list > extension_list_t; - extension_list_t m_extensions; -#endif - - // used to resolve the names of web seeds - mutable tcp::resolver m_host_resolver; - - // this announce timer is used both - // by Local service discovery and - // by the DHT. - deadline_timer m_lsd_announce_timer; - - // used for tracker announces - deadline_timer m_tracker_timer; - - void restart_tracker_timer(ptime announce_at); - - static void on_tracker_announce_disp(boost::weak_ptr p - , error_code const& e); - - void on_tracker_announce(); - - static void on_lsd_announce_disp(boost::weak_ptr p - , error_code const& e); - - // this is called once every 5 minutes for torrents - // that are not private - void on_lsd_announce(); - -#ifndef TORRENT_DISABLE_DHT - static void on_dht_announce_response_disp(boost::weak_ptr t - , std::vector const& peers); - void on_dht_announce_response(std::vector const& peers); - bool should_announce_dht() const; - - // the time when the DHT was last announced of our - // presence on this torrent - ptime m_last_dht_announce; -#endif - - // this is the upload and download statistics for the whole torrent. - // it's updated from all its peers once every second. - libtorrent::stat m_stat; - - // ----------------------------- - - // a back reference to the session - // this torrent belongs to. - aux::session_impl& m_ses; - - std::vector m_file_priority; - - boost::scoped_ptr m_picker; - - // the queue of peer_connections that want more bandwidth - typedef std::deque > queue_t; - queue_t m_bandwidth_queue[2]; - - std::vector m_trackers; - // this is an index into m_trackers - - // the number of bytes that has been - // downloaded that failed the hash-test - size_type m_total_failed_bytes; - size_type m_total_redundant_bytes; - - std::string m_username; - std::string m_password; - - // the network interface all outgoing connections - // are opened through - tcp::endpoint m_net_interface; - - fs::path m_save_path; - - // determines the storage state for this torrent. - storage_mode_t m_storage_mode; - - // the state of this torrent (queued, checking, downloading) - torrent_status::state_t m_state; - - // if there's an error on this torrent, this is the - // error message - std::string m_error; - - // used if there is any resume data - std::vector m_resume_data; - lazy_entry m_resume_entry; - - // if the torrent is started without metadata, it may - // still be given a name until the metadata is received - // once the metadata is received this field will no - // longer be used and will be reset - boost::scoped_ptr m_name; - -#ifndef TORRENT_DISABLE_ENCRYPTION - // this is SHA1("req2" + info-hash), used for - // encrypted hand shakes - sha1_hash m_obfuscated_hash; -#endif - session_settings const& m_settings; - - storage_constructor_type m_storage_constructor; - - float m_progress; - - // the upload/download ratio that each peer - // tries to maintain. - // 0 is infinite - float m_ratio; - - // the maximum number of uploads for this torrent - int m_max_uploads; - - // the number of unchoked peers in this torrent - int m_num_uploads; - - // the maximum number of connections for this torrent - int m_max_connections; - - // the size of a request block - // each piece is divided into these - // blocks when requested - int m_block_size; - - // ----------------------------- - // DATA FROM TRACKER RESPONSE - - // the scrape data from the tracker response, this - // is optional and may be -1. - int m_complete; - int m_incomplete; - -#ifdef TORRENT_DEBUG - // this is the amount downloaded when this torrent - // is started. i.e. - // total_done - m_initial_done <= total_payload_download - size_type m_initial_done; -#endif - // this is the deficit counter in the Deficit Round Robin - // used to determine which torrent gets the next - // connection attempt. See: - // http://www.ecs.umass.edu/ece/wolf/courses/ECE697J/papers/DRR.pdf - // The quanta assigned to each torrent depends on the torrents - // priority, whether it's seed and the number of connected - // peers it has. This has the effect that some torrents - // will have more connection attempts than other. Each - // connection attempt costs 100 points from the deficit - // counter. points are deducted in try_connect_peer and - // increased in give_connect_points. Outside of the - // torrent object, these points are called connect_points. - int m_deficit_counter; - - // the number number of seconds between requests - // from the tracker - boost::int16_t m_duration; - - // the sequence number for this torrent, this is a - // monotonically increasing number for each added torrent - boost::int16_t m_sequence_number; - - // the index to the last tracker that worked - boost::int8_t m_last_working_tracker; - - // the tracker that is currently (or was last) - // tried - boost::int8_t m_currently_trying_tracker; - - // the number of connection attempts that has - // failed in a row, this is currently used to - // determine the timeout until next try. - boost::int8_t m_failed_trackers; - - // this is a counter that is decreased every - // second, and when it reaches 0, the policy::pulse() - // is called and the time scaler is reset to 10. - boost::int8_t m_time_scaler; - - // is set to true when the torrent has - // been aborted. - bool m_abort:1; - - // is true if this torrent has been paused - bool m_paused:1; - - // if this is true, libtorrent may pause and resume - // this torrent depending on queuing rules. Torrents - // started with auto_managed flag set may be added in - // a paused state in case there are no available - // slots. - bool m_auto_managed:1; - -#ifndef TORRENT_DISABLE_RESOLVE_COUNTRIES - // this is true while there is a country - // resolution in progress. To avoid flodding - // the DNS request queue, only one ip is resolved - // at a time. - mutable bool m_resolving_country:1; - - // this is true if the user has enabled - // country resolution in this torrent - bool m_resolve_countries:1; -#endif - - // in case the piece picker hasn't been constructed - // when this settings is set, this variable will keep - // its value until the piece picker is created - bool m_sequential_download:1; - - // is false by default and set to - // true when the first tracker reponse - // is received - bool m_got_tracker_response:1; - - // this is set to false as long as the connections - // of this torrent hasn't been initialized. If we - // have metadata from the start, connections are - // initialized immediately, if we didn't have metadata, - // they are initialized right after files_checked(). - // valid_resume_data() will return false as long as - // the connections aren't initialized, to avoid - // them from altering the piece-picker before it - // has been initialized with files_checked(). - bool m_connections_initialized:1; - - // is set to true every time there is an incoming - // connection to this torrent - bool m_has_incoming:1; - - // this is set to true when the files are checked - // before the files are checked, we don't try to - // connect to peers - bool m_files_checked:1; - - // this is true if the torrent has been added to - // checking queue in the session - bool m_queued_for_checking:1; - - // this is true while tracker announcing is enabled - // is is disabled while paused and checking files - bool m_announcing:1; - - // this is true if event start has been sent to the tracker - bool m_start_sent:1; - - // this is true if event completed has been sent to the tracker - bool m_complete_sent:1; - }; - - inline ptime torrent::next_announce() const - { - return m_next_tracker_announce; - } - - inline void torrent::force_tracker_request() - { - if (!is_paused()) announce_with_tracker(); - } - - inline void torrent::force_tracker_request(ptime t) - { - if (!is_paused()) restart_tracker_timer(t); - } - - inline void torrent::set_tracker_login( - std::string const& name - , std::string const& pw) - { - m_username = name; - m_password = pw; - } - -} - -#endif // TORRENT_TORRENT_HPP_INCLUDED - diff --git a/libtorrent/include/libtorrent/torrent_handle.hpp b/libtorrent/include/libtorrent/torrent_handle.hpp deleted file mode 100644 index cad2d9965..000000000 --- a/libtorrent/include/libtorrent/torrent_handle.hpp +++ /dev/null @@ -1,503 +0,0 @@ -/* - -Copyright (c) 2003, Arvid Norberg -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions -are met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in - the documentation and/or other materials provided with the distribution. - * Neither the name of the author nor the names of its - contributors may be used to endorse or promote products derived - from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -POSSIBILITY OF SUCH DAMAGE. - -*/ - -#ifndef TORRENT_TORRENT_HANDLE_HPP_INCLUDED -#define TORRENT_TORRENT_HANDLE_HPP_INCLUDED - -#include -#include - -#ifdef _MSC_VER -#pragma warning(push, 1) -#endif - -#include - -#ifdef _MSC_VER -#pragma warning(pop) -#endif - -#include "libtorrent/peer_id.hpp" -#include "libtorrent/peer_info.hpp" -#include "libtorrent/piece_picker.hpp" -#include "libtorrent/torrent_info.hpp" -#include "libtorrent/time.hpp" -#include "libtorrent/config.hpp" -#include "libtorrent/storage.hpp" - -namespace libtorrent -{ - namespace fs = boost::filesystem; - - namespace aux - { - struct session_impl; - struct checker_impl; - } - - struct torrent_plugin; - - struct TORRENT_EXPORT duplicate_torrent: std::exception - { - virtual const char* what() const throw() - { return "torrent already exists in session"; } - }; - - struct TORRENT_EXPORT invalid_handle: std::exception - { - virtual const char* what() const throw() - { return "invalid torrent handle used"; } - }; - - struct TORRENT_EXPORT torrent_status - { - torrent_status() - : state(checking_resume_data) - , paused(false) - , progress(0.f) - , total_download(0) - , total_upload(0) - , total_payload_download(0) - , total_payload_upload(0) - , total_failed_bytes(0) - , total_redundant_bytes(0) - , download_rate(0) - , upload_rate(0) - , download_payload_rate(0) - , upload_payload_rate(0) - , num_seeds(0) - , num_peers(0) - , num_complete(-1) - , num_incomplete(-1) - , list_seeds(0) - , list_peers(0) - , num_pieces(0) - , total_done(0) - , total_wanted_done(0) - , total_wanted(0) - , distributed_copies(0.f) - , block_size(0) - , num_uploads(0) - , num_connections(0) - , uploads_limit(0) - , connections_limit(0) - , storage_mode(storage_mode_sparse) - , up_bandwidth_queue(0) - , down_bandwidth_queue(0) - , all_time_upload(0) - , all_time_download(0) - , active_time(0) - , seeding_time(0) - , seed_rank(0) - , last_scrape(0) - , has_incoming(false) - {} - - enum state_t - { - queued_for_checking, - checking_files, - downloading_metadata, - downloading, - finished, - seeding, - allocating, - checking_resume_data - }; - - state_t state; - bool paused; - float progress; - std::string error; - - boost::posix_time::time_duration next_announce; - boost::posix_time::time_duration announce_interval; - - std::string current_tracker; - - // transferred this session! - // total, payload plus protocol - size_type total_download; - size_type total_upload; - - // payload only - size_type total_payload_download; - size_type total_payload_upload; - - // the amount of payload bytes that - // has failed their hash test - size_type total_failed_bytes; - - // the number of payload bytes that - // has been received redundantly. - size_type total_redundant_bytes; - - // current transfer rate - // payload plus protocol - float download_rate; - float upload_rate; - - // the rate of payload that is - // sent and received - float download_payload_rate; - float upload_payload_rate; - - // the number of peers this torrent is connected to - // that are seeding. - int num_seeds; - - // the number of peers this torrent - // is connected to (including seeds). - int num_peers; - - // if the tracker sends scrape info in its - // announce reply, these fields will be - // set to the total number of peers that - // have the whole file and the total number - // of peers that are still downloading - int num_complete; - int num_incomplete; - - // this is the number of seeds whose IP we know - // but are not necessarily connected to - int list_seeds; - - // this is the number of peers whose IP we know - // (including seeds), but are not necessarily - // connected to - int list_peers; - - // the number of peers in our peerlist that - // we potentially could connect to - int connect_candidates; - - bitfield pieces; - - // this is the number of pieces the client has - // downloaded. it is equal to: - // std::accumulate(pieces->begin(), pieces->end()); - int num_pieces; - - // the number of bytes of the file we have - // including pieces that may have been filtered - // after we downloaded them - size_type total_done; - - // the number of bytes we have of those that we - // want. i.e. not counting bytes from pieces that - // are filtered as not wanted. - size_type total_wanted_done; - - // the total number of bytes we want to download - // this may be smaller than the total torrent size - // in case any pieces are filtered as not wanted - size_type total_wanted; - - // the number of distributed copies of the file. - // note that one copy may be spread out among many peers. - // - // the integer part tells how many copies - // there are of the rarest piece(s) - // - // the fractional part tells the fraction of pieces that - // have more copies than the rarest piece(s). - float distributed_copies; - - // the block size that is used in this torrent. i.e. - // the number of bytes each piece request asks for - // and each bit in the download queue bitfield represents - int block_size; - - int num_uploads; - int num_connections; - int uploads_limit; - int connections_limit; - - // true if the torrent is saved in compact mode - // false if it is saved in full allocation mode - storage_mode_t storage_mode; - - int up_bandwidth_queue; - int down_bandwidth_queue; - - // number of bytes downloaded since torrent was started - // saved and restored from resume data - size_type all_time_upload; - size_type all_time_download; - - // the number of seconds of being active - // and as being a seed, saved and restored - // from resume data - int active_time; - int seeding_time; - - // higher value means more important to seed - int seed_rank; - - // number of seconds since last scrape, or -1 if - // there hasn't been a scrape - int last_scrape; - - // true if there are incoming connections to this - // torrent - bool has_incoming; - }; - - struct TORRENT_EXPORT block_info - { - enum block_state_t - { none, requested, writing, finished }; - - tcp::endpoint peer; - // number of bytes downloaded in this block - unsigned bytes_progress:16; - // the total number of bytes in this block - unsigned block_size:16; - // the state this block is in (see block_state_t) - unsigned state:2; - // the number of peers that has requested this block - // typically 0 or 1. If > 1, this block is in - // end game mode - unsigned num_peers:14; - }; - - struct TORRENT_EXPORT partial_piece_info - { - enum { max_blocks_per_piece = 512 }; - int piece_index; - int blocks_in_piece; - // the number of blocks in the finished state - int finished; - // the number of blocks in the writing state - int writing; - // the number of blocks in the requested state - int requested; - block_info blocks[max_blocks_per_piece]; - enum state_t { none, slow, medium, fast }; - state_t piece_state; - }; - - struct TORRENT_EXPORT torrent_handle - { - friend class invariant_access; - friend struct aux::session_impl; - friend class torrent; - - torrent_handle() {} - - void get_full_peer_list(std::vector& v) const; - void get_peer_info(std::vector& v) const; - torrent_status status() const; - void get_download_queue(std::vector& queue) const; - -#ifndef TORRENT_NO_DEPRECATE - // fills the specified vector with the download progress [0, 1] - // of each file in the torrent. The files are ordered as in - // the torrent_info. - void file_progress(std::vector& progress) const TORRENT_DEPRECATED; -#endif - void file_progress(std::vector& progress) const; - - void clear_error() const; - - std::vector const& trackers() const; - void replace_trackers(std::vector const&) const; - - void add_url_seed(std::string const& url) const; - void remove_url_seed(std::string const& url) const; - std::set url_seeds() const; - -#ifndef TORRENT_DISABLE_EXTENSIONS - void add_extension(boost::function(torrent*, void*)> const& ext - , void* userdata = 0); -#endif - - bool has_metadata() const; - const torrent_info& get_torrent_info() const; - bool is_valid() const; - - bool is_seed() const; - bool is_finished() const; - bool is_paused() const; - void pause() const; - void resume() const; - void force_recheck() const; - void save_resume_data() const; - - bool is_auto_managed() const; - void auto_managed(bool m) const; - - int queue_position() const; - void queue_position_up() const; - void queue_position_down() const; - void queue_position_top() const; - void queue_position_bottom() const; - -#ifndef TORRENT_DISABLE_RESOLVE_COUNTRIES - void resolve_countries(bool r); - bool resolve_countries() const; -#endif - - storage_interface* get_storage_impl() const; - - // all these are deprecated, use piece - // priority functions instead - - // ================ start deprecation ============ - -#ifndef TORRENT_NO_DEPRECATE - // deprecated in 0.13 - // marks the piece with the given index as filtered - // it will not be downloaded - void filter_piece(int index, bool filter) const TORRENT_DEPRECATED; - void filter_pieces(std::vector const& pieces) const TORRENT_DEPRECATED; - bool is_piece_filtered(int index) const TORRENT_DEPRECATED; - std::vector filtered_pieces() const TORRENT_DEPRECATED; - // marks the file with the given index as filtered - // it will not be downloaded - void filter_files(std::vector const& files) const TORRENT_DEPRECATED; - - // ================ end deprecation ============ -#endif - - void piece_availability(std::vector& avail) const; - - // priority must be within the range [0, 7] - void piece_priority(int index, int priority) const; - int piece_priority(int index) const; - - void prioritize_pieces(std::vector const& pieces) const; - std::vector piece_priorities() const; - - // priority must be within the range [0, 7] - void file_priority(int index, int priority) const; - int file_priority(int index) const; - - void prioritize_files(std::vector const& files) const; - std::vector file_priorities() const; - - // set the interface to bind outgoing connections - // to. - void use_interface(const char* net_interface) const; - -#ifndef TORRENT_NO_DEPRECATE - // deprecated in 0.14 - // use save_resume_data() instead. It is async. and - // will return the resume data in an alert - entry write_resume_data() const TORRENT_DEPRECATED; -#endif - - // forces this torrent to reannounce - // (make a rerequest from the tracker) - void force_reannounce() const; - - // forces a reannounce in the specified amount of time. - // This overrides the default announce interval, and no - // announce will take place until the given time has - // timed out. - void force_reannounce(boost::posix_time::time_duration) const; - - // performs a scrape request - void scrape_tracker() const; - - // returns the name of this torrent, in case it doesn't - // have metadata it returns the name assigned to it - // when it was added. - std::string name() const; - - // TODO: add a feature where the user can tell the torrent - // to finish all pieces currently in the pipeline, and then - // abort the torrent. - - void set_upload_limit(int limit) const; - int upload_limit() const; - void set_download_limit(int limit) const; - int download_limit() const; - - void set_sequential_download(bool sd) const; - bool is_sequential_download() const; - - void set_peer_upload_limit(tcp::endpoint ip, int limit) const; - void set_peer_download_limit(tcp::endpoint ip, int limit) const; - - // manually connect a peer - void connect_peer(tcp::endpoint const& adr, int source = 0) const; - - // valid ratios are 0 (infinite ratio) or [ 1.0 , inf ) - // the ratio is uploaded / downloaded. less than 1 is not allowed - void set_ratio(float up_down_ratio) const; - - fs::path save_path() const; - - // -1 means unlimited unchokes - void set_max_uploads(int max_uploads) const; - - // -1 means unlimited connections - void set_max_connections(int max_connections) const; - - void set_tracker_login(std::string const& name - , std::string const& password) const; - - // post condition: save_path() == save_path if true is returned - void move_storage(fs::path const& save_path) const; - void rename_file(int index, fs::path const& new_name) const; - - sha1_hash info_hash() const; - - bool operator==(const torrent_handle& h) const - { return m_torrent.lock() == h.m_torrent.lock(); } - - bool operator!=(const torrent_handle& h) const - { return m_torrent.lock() != h.m_torrent.lock(); } - - bool operator<(const torrent_handle& h) const - { return m_torrent.lock() < h.m_torrent.lock(); } - - private: - - torrent_handle(boost::weak_ptr const& t) - : m_torrent(t) - {} - -#ifdef TORRENT_DEBUG - void check_invariant() const; -#endif - - boost::weak_ptr m_torrent; - - }; - - -} - -#endif // TORRENT_TORRENT_HANDLE_HPP_INCLUDED - diff --git a/libtorrent/include/libtorrent/torrent_info.hpp b/libtorrent/include/libtorrent/torrent_info.hpp deleted file mode 100644 index c71624ce8..000000000 --- a/libtorrent/include/libtorrent/torrent_info.hpp +++ /dev/null @@ -1,258 +0,0 @@ -/* - -Copyright (c) 2003-2008, Arvid Norberg -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions -are met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in - the documentation and/or other materials provided with the distribution. - * Neither the name of the author nor the names of its - contributors may be used to endorse or promote products derived - from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -POSSIBILITY OF SUCH DAMAGE. - -*/ - -#ifndef TORRENT_TORRENT_INFO_HPP_INCLUDED -#define TORRENT_TORRENT_INFO_HPP_INCLUDED - -#include -#include -#include - -#ifdef _MSC_VER -#pragma warning(push, 1) -#endif - -#include -#include -#include - -#ifdef _MSC_VER -#pragma warning(pop) -#endif - -#include "libtorrent/entry.hpp" -#include "libtorrent/lazy_entry.hpp" -#include "libtorrent/socket.hpp" -#include "libtorrent/peer_id.hpp" -#include "libtorrent/size_type.hpp" -#include "libtorrent/config.hpp" -#include "libtorrent/time.hpp" -#include "libtorrent/intrusive_ptr_base.hpp" -#include "libtorrent/assert.hpp" -#include "libtorrent/file_storage.hpp" - -namespace libtorrent -{ - namespace pt = boost::posix_time; - namespace gr = boost::gregorian; - namespace fs = boost::filesystem; - - struct TORRENT_EXPORT announce_entry - { - announce_entry(std::string const& u): url(u), tier(0) {} - std::string url; - int tier; - }; - -#ifndef BOOST_NO_EXCEPTIONS - struct TORRENT_EXPORT invalid_torrent_file: std::exception - { - virtual const char* what() const throw() { return "invalid torrent file"; } - }; -#endif - - int TORRENT_EXPORT load_file(fs::path const& filename, std::vector& v); - - class TORRENT_EXPORT torrent_info : public intrusive_ptr_base - { - public: - - torrent_info(sha1_hash const& info_hash); - torrent_info(lazy_entry const& torrent_file); - torrent_info(char const* buffer, int size); - torrent_info(fs::path const& filename); - ~torrent_info(); - - file_storage const& files() const { return m_files; } - file_storage const& orig_files() const { return m_orig_files ? *m_orig_files : m_files; } - - void rename_file(int index, std::string const& new_filename) - { - copy_on_write(); - m_files.rename_file(index, new_filename); - } - - void add_tracker(std::string const& url, int tier = 0); - std::vector const& trackers() const { return m_urls; } - - std::vector const& url_seeds() const - { return m_url_seeds; } - void add_url_seed(std::string const& url) - { m_url_seeds.push_back(url); } - - size_type total_size() const { return m_files.total_size(); } - int piece_length() const { return m_files.piece_length(); } - int num_pieces() const { return m_files.num_pieces(); } - const sha1_hash& info_hash() const { return m_info_hash; } - const std::string& name() const { return m_files.name(); } - - typedef file_storage::iterator file_iterator; - typedef file_storage::reverse_iterator reverse_file_iterator; - - file_iterator begin_files() const { return m_files.begin(); } - file_iterator end_files() const { return m_files.end(); } - reverse_file_iterator rbegin_files() const { return m_files.rbegin(); } - reverse_file_iterator rend_files() const { return m_files.rend(); } - int num_files() const { return m_files.num_files(); } - file_entry const& file_at(int index) const { return m_files.at(index); } - - file_iterator file_at_offset(size_type offset) const - { return m_files.file_at_offset(offset); } - std::vector map_block(int piece, size_type offset, int size) const - { return m_files.map_block(piece, offset, size); } - peer_request map_file(int file, size_type offset, int size) const - { return m_files.map_file(file, offset, size); } - -#ifndef TORRENT_NO_DEPRECATE -// ------- start deprecation ------- -// these functions will be removed in a future version - torrent_info(entry const& torrent_file) TORRENT_DEPRECATED; - void print(std::ostream& os) const TORRENT_DEPRECATED; - file_storage& files() TORRENT_DEPRECATED { return m_files; } -// ------- end deprecation ------- -#endif - - bool is_valid() const { return m_files.is_valid(); } - - bool priv() const { return m_private; } - - int piece_size(int index) const { return m_files.piece_size(index); } - - sha1_hash hash_for_piece(int index) const - { return sha1_hash(hash_for_piece_ptr(index)); } - - char const* hash_for_piece_ptr(int index) const - { - TORRENT_ASSERT(index >= 0); - TORRENT_ASSERT(index < m_files.num_pieces()); - TORRENT_ASSERT(m_piece_hashes); - TORRENT_ASSERT(m_piece_hashes >= m_info_section.get()); - TORRENT_ASSERT(m_piece_hashes < m_info_section.get() + m_info_section_size); - return &m_piece_hashes[index*20]; - } - - boost::optional creation_date() const; - - const std::string& creator() const - { return m_created_by; } - - const std::string& comment() const - { return m_comment; } - - // dht nodes to add to the routing table/bootstrap from - typedef std::vector > nodes_t; - - nodes_t const& nodes() const - { return m_nodes; } - void add_node(std::pair const& node) - { m_nodes.push_back(node); } - - bool parse_info_section(lazy_entry const& e, std::string& error); - - lazy_entry const* info(char const* key) const - { - if (m_info_dict.type() == lazy_entry::none_t) - lazy_bdecode(m_info_section.get(), m_info_section.get() - + m_info_section_size, m_info_dict); - return m_info_dict.dict_find(key); - } - - void swap(torrent_info& ti); - - boost::shared_array metadata() const - { return m_info_section; } - - int metadata_size() const { return m_info_section_size; } - - private: - - void copy_on_write(); - bool parse_torrent_file(lazy_entry const& libtorrent, std::string& error); - - file_storage m_files; - - // if m_files is modified, it is first copied into - // m_orig_files so that the original name and - // filenames are preserved. - boost::shared_ptr m_orig_files; - - // the urls to the trackers - std::vector m_urls; - std::vector m_url_seeds; - nodes_t m_nodes; - - // the hash that identifies this torrent - sha1_hash m_info_hash; - - // if a creation date is found in the torrent file - // this will be set to that, otherwise it'll be - // 1970, Jan 1 - pt::ptime m_creation_date; - - // if a comment is found in the torrent file - // this will be set to that comment - std::string m_comment; - - // an optional string naming the software used - // to create the torrent file - std::string m_created_by; - - // this is used when creating a torrent. If there's - // only one file there are cases where it's impossible - // to know if it should be written as a multifile torrent - // or not. e.g. test/test there's one file and one directory - // and they have the same name. - bool m_multifile; - - // this is true if the torrent is private. i.e., is should not - // be announced on the dht - bool m_private; - - // this is a copy of the info section from the torrent. - // it use maintained in this flat format in order to - // make it available through the metadata extension - boost::shared_array m_info_section; - int m_info_section_size; - - // this is a pointer into the m_info_section buffer - // pointing to the first byte of the first sha-1 hash - char const* m_piece_hashes; - - // the info section parsed. points into m_info_section - // parsed lazily - mutable lazy_entry m_info_dict; - }; - -} - -#endif // TORRENT_TORRENT_INFO_HPP_INCLUDED - diff --git a/libtorrent/include/libtorrent/tracker_manager.hpp b/libtorrent/include/libtorrent/tracker_manager.hpp deleted file mode 100644 index 8b3781bf8..000000000 --- a/libtorrent/include/libtorrent/tracker_manager.hpp +++ /dev/null @@ -1,247 +0,0 @@ -/* - -Copyright (c) 2003, Arvid Norberg -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions -are met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in - the documentation and/or other materials provided with the distribution. - * Neither the name of the author nor the names of its - contributors may be used to endorse or promote products derived - from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -POSSIBILITY OF SUCH DAMAGE. - -*/ - -#ifndef TORRENT_TRACKER_MANAGER_HPP_INCLUDED -#define TORRENT_TRACKER_MANAGER_HPP_INCLUDED - -#include -#include -#include -#include - -#ifdef _MSC_VER -#pragma warning(push, 1) -#endif - -#include -#include -#include -#include -#include -#include -#include - -#ifdef _MSC_VER -#pragma warning(pop) -#endif - -#include "libtorrent/socket.hpp" -#include "libtorrent/entry.hpp" -#include "libtorrent/session_settings.hpp" -#include "libtorrent/peer_id.hpp" -#include "libtorrent/peer.hpp" -#include "libtorrent/config.hpp" -#include "libtorrent/time.hpp" -#include "libtorrent/connection_queue.hpp" -#include "libtorrent/intrusive_ptr_base.hpp" - -namespace libtorrent -{ - struct request_callback; - class tracker_manager; - struct timeout_handler; - struct tracker_connection; - - // returns -1 if gzip header is invalid or the header size in bytes - TORRENT_EXPORT int gzip_header(const char* buf, int size); - - struct TORRENT_EXPORT tracker_request - { - tracker_request() - : kind(announce_request) - , event(none) - , key(0) - , num_want(0) - {} - - enum - { - announce_request, - scrape_request - } kind; - - enum event_t - { - none, - completed, - started, - stopped - }; - - sha1_hash info_hash; - peer_id pid; - size_type downloaded; - size_type uploaded; - size_type left; - unsigned short listen_port; - event_t event; - std::string url; - int key; - int num_want; - std::string ipv6; - }; - - struct TORRENT_EXPORT request_callback - { - friend class tracker_manager; - request_callback(): m_manager(0) {} - virtual ~request_callback() {} - virtual void tracker_warning(tracker_request const& req - , std::string const& msg) = 0; - virtual void tracker_scrape_response(tracker_request const& req - , int complete, int incomplete, int downloads) {} - virtual void tracker_response( - tracker_request const& req - , std::vector& peers - , int interval - , int complete - , int incomplete - , address const& external_ip) = 0; - virtual void tracker_request_timed_out( - tracker_request const& req) = 0; - virtual void tracker_request_error( - tracker_request const& req - , int response_code - , const std::string& description) = 0; - - tcp::endpoint m_tracker_address; - -#if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_LOGGING || defined TORRENT_ERROR_LOGGING - virtual void debug_log(const std::string& line) = 0; -#endif - private: - tracker_manager* m_manager; - }; - - struct TORRENT_EXPORT timeout_handler - : intrusive_ptr_base - , boost::noncopyable - { - timeout_handler(io_service& str); - - void set_timeout(int completion_timeout, int read_timeout); - void restart_read_timeout(); - void cancel(); - - virtual void on_timeout() = 0; - virtual ~timeout_handler() {} - - private: - - void timeout_callback(error_code const&); - - boost::intrusive_ptr self() - { return boost::intrusive_ptr(this); } - - // used for timeouts - // this is set when the request has been sent - ptime m_start_time; - // this is set every time something is received - ptime m_read_time; - // the asio async operation - deadline_timer m_timeout; - - int m_completion_timeout; - int m_read_timeout; - - typedef boost::mutex mutex_t; - mutable mutex_t m_mutex; - bool m_abort; - }; - - struct TORRENT_EXPORT tracker_connection - : timeout_handler - { - tracker_connection(tracker_manager& man - , tracker_request const& req - , io_service& ios - , address bind_interface - , boost::weak_ptr r); - - boost::shared_ptr requester(); - virtual ~tracker_connection() {} - - tracker_request const& tracker_req() const { return m_req; } - - void fail(int code, char const* msg); - void fail_timeout(); - virtual void start() = 0; - virtual void close(); - address const& bind_interface() const { return m_bind_interface; } - - protected: - boost::weak_ptr m_requester; - private: - address m_bind_interface; - tracker_manager& m_man; - const tracker_request m_req; - }; - - class TORRENT_EXPORT tracker_manager: boost::noncopyable - { - public: - - tracker_manager(session_settings const& s, proxy_settings const& ps) - : m_settings(s) - , m_proxy(ps) - , m_abort(false) {} - - void queue_request( - io_service& ios - , connection_queue& cc - , tracker_request r - , std::string const& auth - , address bind_infc - , boost::weak_ptr c - = boost::weak_ptr()); - void abort_all_requests(); - - void remove_request(tracker_connection const*); - bool empty() const; - int num_requests() const; - - private: - - typedef boost::recursive_mutex mutex_t; - mutable mutex_t m_mutex; - - typedef std::list > - tracker_connections_t; - tracker_connections_t m_connections; - session_settings const& m_settings; - proxy_settings const& m_proxy; - bool m_abort; - }; -} - -#endif // TORRENT_TRACKER_MANAGER_HPP_INCLUDED - diff --git a/libtorrent/include/libtorrent/udp_socket.hpp b/libtorrent/include/libtorrent/udp_socket.hpp deleted file mode 100644 index 8a982c9cb..000000000 --- a/libtorrent/include/libtorrent/udp_socket.hpp +++ /dev/null @@ -1,116 +0,0 @@ -/* - -Copyright (c) 2007, Arvid Norberg -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions -are met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in - the documentation and/or other materials provided with the distribution. - * Neither the name of the author nor the names of its - contributors may be used to endorse or promote products derived - from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -POSSIBILITY OF SUCH DAMAGE. - -*/ - -#ifndef TORRENT_UDP_SOCKET_HPP_INCLUDED -#define TORRENT_UDP_SOCKET_HPP_INCLUDED - -#include "libtorrent/socket.hpp" -#include "libtorrent/session_settings.hpp" - -#include -#include -#include - -namespace libtorrent -{ - class connection_queue; - - class udp_socket - { - public: - typedef boost::function callback_t; - - udp_socket(io_service& ios, callback_t const& c, connection_queue& cc); - ~udp_socket(); - - bool is_open() const { return m_ipv4_sock.is_open() || m_ipv6_sock.is_open(); } - io_service& get_io_service() { return m_ipv4_sock.get_io_service(); } - - void send(udp::endpoint const& ep, char const* p, int len, error_code& ec); - void bind(udp::endpoint const& ep, error_code& ec); - void bind(int port); - void close(); - int local_port() const { return m_bind_port; } - - void set_proxy_settings(proxy_settings const& ps); - proxy_settings const& get_proxy_settings() { return m_proxy_settings; } - - private: - - callback_t m_callback; - - void on_read(udp::socket* sock, error_code const& e, std::size_t bytes_transferred); - void on_name_lookup(error_code const& e, tcp::resolver::iterator i); - void on_timeout(); - void on_connect(int ticket); - void on_connected(error_code const& ec); - void handshake1(error_code const& e); - void handshake2(error_code const& e); - void handshake3(error_code const& e); - void handshake4(error_code const& e); - void socks_forward_udp(); - void connect1(error_code const& e); - void connect2(error_code const& e); - - void wrap(udp::endpoint const& ep, char const* p, int len, error_code& ec); - void unwrap(error_code const& e, char const* buf, int size); - - typedef boost::mutex mutex_t; - mutable mutex_t m_mutex; - - udp::socket m_ipv4_sock; - udp::socket m_ipv6_sock; - udp::endpoint m_v4_ep; - udp::endpoint m_v6_ep; - char m_v4_buf[1600]; - char m_v6_buf[1600]; - int m_bind_port; - char m_outstanding; - - tcp::socket m_socks5_sock; - int m_connection_ticket; - proxy_settings m_proxy_settings; - connection_queue& m_cc; - tcp::resolver m_resolver; - char m_tmp_buf[100]; - bool m_tunnel_packets; - bool m_abort; - udp::endpoint m_proxy_addr; -#ifdef TORRENT_DEBUG - int m_magic; -#endif - }; -} - -#endif - diff --git a/libtorrent/include/libtorrent/udp_tracker_connection.hpp b/libtorrent/include/libtorrent/udp_tracker_connection.hpp deleted file mode 100644 index fe51df1fb..000000000 --- a/libtorrent/include/libtorrent/udp_tracker_connection.hpp +++ /dev/null @@ -1,125 +0,0 @@ -/* - -Copyright (c) 2003, Arvid Norberg -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions -are met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in - the documentation and/or other materials provided with the distribution. - * Neither the name of the author nor the names of its - contributors may be used to endorse or promote products derived - from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -POSSIBILITY OF SUCH DAMAGE. - -*/ - -#ifndef TORRENT_UDP_TRACKER_CONNECTION_HPP_INCLUDED -#define TORRENT_UDP_TRACKER_CONNECTION_HPP_INCLUDED - -#include -#include -#include -#include - -#ifdef _MSC_VER -#pragma warning(push, 1) -#endif - -#include -#include - -#ifdef _MSC_VER -#pragma warning(pop) -#endif - -#include "libtorrent/udp_socket.hpp" -#include "libtorrent/entry.hpp" -#include "libtorrent/session_settings.hpp" -#include "libtorrent/peer_id.hpp" -#include "libtorrent/peer.hpp" -#include "libtorrent/tracker_manager.hpp" -#include "libtorrent/config.hpp" - -namespace libtorrent -{ - class TORRENT_EXPORT udp_tracker_connection: public tracker_connection - { - friend class tracker_manager; - public: - - udp_tracker_connection( - io_service& ios - , connection_queue& cc - , tracker_manager& man - , tracker_request const& req - , address bind_infc - , boost::weak_ptr c - , session_settings const& stn - , proxy_settings const& ps); - - void start(); - void close(); - - private: - - enum action_t - { - action_connect, - action_announce, - action_scrape, - action_error - }; - - boost::intrusive_ptr self() - { return boost::intrusive_ptr(this); } - - void name_lookup(error_code const& error, udp::resolver::iterator i); - void timeout(error_code const& error); - - void on_receive(error_code const& e, udp::endpoint const& ep - , char const* buf, int size); - void on_connect_response(char const* buf, int size); - void on_announce_response(char const* buf, int size); - void on_scrape_response(char const* buf, int size); - - void send_udp_connect(); - void send_udp_announce(); - void send_udp_scrape(); - - virtual void on_timeout(); - - tracker_manager& m_man; - - udp::resolver m_name_lookup; - udp_socket m_socket; - udp::endpoint m_target; - - int m_transaction_id; - boost::int64_t m_connection_id; - session_settings const& m_settings; - int m_attempts; - - action_t m_state; - }; - -} - -#endif // TORRENT_UDP_TRACKER_CONNECTION_HPP_INCLUDED - diff --git a/libtorrent/include/libtorrent/upnp.hpp b/libtorrent/include/libtorrent/upnp.hpp deleted file mode 100644 index 59baa915b..000000000 --- a/libtorrent/include/libtorrent/upnp.hpp +++ /dev/null @@ -1,285 +0,0 @@ -/* - -Copyright (c) 2007, Arvid Norberg -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions -are met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in - the documentation and/or other materials provided with the distribution. - * Neither the name of the author nor the names of its - contributors may be used to endorse or promote products derived - from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -POSSIBILITY OF SUCH DAMAGE. - -*/ - -#ifndef TORRENT_UPNP_HPP -#define TORRENT_UPNP_HPP - -#include "libtorrent/socket.hpp" -#include "libtorrent/broadcast_socket.hpp" -#include "libtorrent/http_connection.hpp" -#include "libtorrent/connection_queue.hpp" -#include "libtorrent/intrusive_ptr_base.hpp" - -#include -#include -#include -#include -#include -#include - - -#if (defined(TORRENT_LOGGING) || defined(TORRENT_VERBOSE_LOGGING)) && !defined (TORRENT_UPNP_LOGGING) -#define TORRENT_UPNP_LOGGING -#endif - -#if defined(TORRENT_UPNP_LOGGING) -#include -#endif - -namespace libtorrent -{ - -// int: port-mapping index -// int: external port -// std::string: error message -// an empty string as error means success -typedef boost::function portmap_callback_t; - -class upnp : public intrusive_ptr_base -{ -public: - upnp(io_service& ios, connection_queue& cc - , address const& listen_interface, std::string const& user_agent - , portmap_callback_t const& cb, bool ignore_nonrouters, void* state = 0); - ~upnp(); - - void* drain_state(); - - enum protocol_type { none = 0, udp = 1, tcp = 2 }; - int add_mapping(protocol_type p, int external_port, int local_port); - void delete_mapping(int mapping_index); - - void discover_device(); - void close(); - - std::string router_model() - { - mutex_t::scoped_lock l(m_mutex); - return m_model; - } - -private: - - void discover_device_impl(); - static address_v4 upnp_multicast_address; - static udp::endpoint upnp_multicast_endpoint; - - enum { default_lease_time = 3600 }; - - void resend_request(error_code const& e); - void on_reply(udp::endpoint const& from, char* buffer - , std::size_t bytes_transferred); - - struct rootdevice; - void next(rootdevice& d, int i); - void update_map(rootdevice& d, int i); - - - void on_upnp_xml(error_code const& e - , libtorrent::http_parser const& p, rootdevice& d - , http_connection& c); - void on_upnp_map_response(error_code const& e - , libtorrent::http_parser const& p, rootdevice& d - , int mapping, http_connection& c); - void on_upnp_unmap_response(error_code const& e - , libtorrent::http_parser const& p, rootdevice& d - , int mapping, http_connection& c); - void on_expire(error_code const& e); - - void disable(char const* msg); - void return_error(int mapping, int code); - - void delete_port_mapping(rootdevice& d, int i); - void create_port_mapping(http_connection& c, rootdevice& d, int i); - void post(upnp::rootdevice const& d, std::string const& soap - , std::string const& soap_action); - - int num_mappings() const { return int(m_mappings.size()); } - - struct global_mapping_t - { - global_mapping_t() - : protocol(none) - , external_port(0) - , local_port(0) - {} - int protocol; - int external_port; - int local_port; - }; - - struct mapping_t - { - enum action_t { action_none, action_add, action_delete }; - mapping_t() - : action(action_none) - , local_port(0) - , external_port(0) - , protocol(none) - , failcount(0) - {} - - // the time the port mapping will expire - ptime expires; - - int action; - - // the local port for this mapping. If this is set - // to 0, the mapping is not in use - int local_port; - - // the external (on the NAT router) port - // for the mapping. This is the port we - // should announce to others - int external_port; - - // 2 = udp, 1 = tcp - int protocol; - - // the number of times this mapping has failed - int failcount; - }; - - struct rootdevice - { - rootdevice(): service_namespace(0) - , lease_duration(default_lease_time) - , supports_specific_external(true) - , disabled(false) - { -#ifdef TORRENT_DEBUG - magic = 1337; -#endif - } - -#ifdef TORRENT_DEBUG - ~rootdevice() - { - TORRENT_ASSERT(magic == 1337); - magic = 0; - } -#endif - - // the interface url, through which the list of - // supported interfaces are fetched - std::string url; - - // the url to the WANIP or WANPPP interface - std::string control_url; - // either the WANIP namespace or the WANPPP namespace - char const* service_namespace; - - std::vector mapping; - - // this is the hostname, port and path - // component of the url or the control_url - // if it has been found - std::string hostname; - int port; - std::string path; - - int lease_duration; - // true if the device supports specifying a - // specific external port, false if it doesn't - bool supports_specific_external; - - bool disabled; - - mutable boost::shared_ptr upnp_connection; - -#ifdef TORRENT_DEBUG - int magic; -#endif - void close() const - { - TORRENT_ASSERT(magic == 1337); - if (!upnp_connection) return; - upnp_connection->close(); - upnp_connection.reset(); - } - - bool operator<(rootdevice const& rhs) const - { return url < rhs.url; } - }; - - struct upnp_state_t - { - std::vector mappings; - std::set devices; - }; - - std::vector m_mappings; - - std::string const& m_user_agent; - - // the set of devices we've found - std::set m_devices; - - portmap_callback_t m_callback; - - // current retry count - int m_retry_count; - - io_service& m_io_service; - - // the udp socket used to send and receive - // multicast messages on the network - broadcast_socket m_socket; - - // used to resend udp packets in case - // they time out - deadline_timer m_broadcast_timer; - - // timer used to refresh mappings - deadline_timer m_refresh_timer; - - bool m_disabled; - bool m_closing; - bool m_ignore_non_routers; - - connection_queue& m_cc; - - typedef boost::mutex mutex_t; - mutex_t m_mutex; - - std::string m_model; - -#ifdef TORRENT_UPNP_LOGGING - std::ofstream m_log; -#endif -}; - -} - - -#endif - diff --git a/libtorrent/include/libtorrent/utf8.hpp b/libtorrent/include/libtorrent/utf8.hpp deleted file mode 100644 index 157a7fdba..000000000 --- a/libtorrent/include/libtorrent/utf8.hpp +++ /dev/null @@ -1,161 +0,0 @@ -/* - Copyright (C) 2004-2005 Cory Nelson - - This software is provided 'as-is', without any express or implied - warranty. In no event will the authors be held liable for any damages - arising from the use of this software. - - Permission is granted to anyone to use this software for any purpose, - including commercial applications, and to alter it and redistribute it - freely, subject to the following restrictions: - - 1. The origin of this software must not be misrepresented; you must not - claim that you wrote the original software. If you use this software - in a product, an acknowledgment in the product documentation would be - appreciated but is not required. - 2. Altered source versions must be plainly marked as such, and must not be - misrepresented as being the original software. - 3. This notice may not be removed or altered from any source distribution. -*/ - -// namespaces added by Arvid Norberg - -#ifndef __UTF8_H__ -#define __UTF8_H__ - -#include -#include -#include -#include - -namespace libtorrent { -namespace detail { - -template -wchar_t decode_utf8_mb(InputIterator &iter, InputIterator last) -{ - if (iter == last) throw std::runtime_error("incomplete UTF-8 sequence"); - if (((*iter) & 0xc0) != 0x80) throw std::runtime_error("invalid UTF-8 sequence"); - - return (wchar_t)((*iter++) & 0x3f); -} - -template -wchar_t decode_utf8(InputIterator &iter, InputIterator last) -{ - wchar_t ret; - - if (((*iter) & 0x80) == 0) // one byte - { - ret = *iter++; - } - else if (((*iter) & 0xe0) == 0xc0) // two bytes - { - wchar_t byte1 = (*iter++) & 0x1f; - wchar_t byte2 = decode_utf8_mb(iter, last); - ret = (byte1 << 6) | byte2; - } - else if (((*iter) & 0xf0) == 0xe0) // three bytes - { - wchar_t byte1 = (*iter++) & 0x0f; - wchar_t byte2 = decode_utf8_mb(iter, last); - wchar_t byte3 = decode_utf8_mb(iter, last); - ret = (byte1 << 12) | (byte2 << 6) | byte3; - } - // TODO: support surrogate pairs - else throw std::runtime_error("UTF-8 not convertable to UTF-16"); - - return ret; -} - -template -OutputIterator utf8_wchar(InputIterator first, InputIterator last, OutputIterator dest) -{ - for(; first!=last; ++dest) - *dest = decode_utf8(first, last); - return dest; -} - -template -void encode_wchar(InputIterator iter, OutputIterator &dest) -{ - if(*iter <= 0x007F) - { - *dest=(char)*iter; - ++dest; - } - else if(*iter <= 0x07FF) - { - *dest = (char)( - 0xC0 | - ((*iter & 0x07C0) >> 6) - ); - ++dest; - - *dest = (char)( - 0x80 | - (*iter & 0x003F) - ); - ++dest; - } - else if(*iter <= 0xFFFF) - { - *dest = (char)( - 0xE0 | - ((*iter & 0xF000) >> 12) - ); - ++dest; - - *dest = (char)( - 0x80 | - ((*iter & 0x0FC0) >> 6) - ); - ++dest; - - *dest = (char)( - 0x80 | - (*iter & 0x003F) - ); - ++dest; - } -} - -template -OutputIterator wchar_utf8(InputIterator first, InputIterator last, OutputIterator dest) -{ - for(; first!=last; ++first) - encode_wchar(first, dest); - return dest; -} - -} - -inline void utf8_wchar(const std::string &utf8, std::wstring &wide) -{ - wide.clear(); - detail::utf8_wchar(utf8.begin(), utf8.end(), std::back_inserter(wide)); -} - -inline std::wstring utf8_wchar(const std::string &str) -{ - std::wstring ret; - utf8_wchar(str, ret); - return ret; -} - -inline void wchar_utf8(const std::wstring &wide, std::string &utf8) -{ - utf8.clear(); - detail::wchar_utf8(wide.begin(), wide.end(), std::back_inserter(utf8)); -} - -inline std::string wchar_utf8(const std::wstring &str) -{ - std::string ret; - wchar_utf8(str, ret); - return ret; -} - -} - -#endif diff --git a/libtorrent/include/libtorrent/variant_stream.hpp b/libtorrent/include/libtorrent/variant_stream.hpp deleted file mode 100644 index 3551f5c9e..000000000 --- a/libtorrent/include/libtorrent/variant_stream.hpp +++ /dev/null @@ -1,754 +0,0 @@ -// Copyright Daniel Wallin and Arvid Norberg 2007. -// Use, modification and distribution is -// subject to the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) - -#ifndef VARIANT_STREAM_070211_HPP -# define VARIANT_STREAM_070211_HPP - -# include - -# include -# include -# include -# include -# include - -# include -# include -# include - -# include -# include - -#if BOOST_VERSION < 103500 -#include -#else -#include -#endif - -# define NETWORK_VARIANT_STREAM_LIMIT 5 - -namespace libtorrent { - -namespace aux -{ - - struct delete_visitor - : boost::static_visitor<> - { - template - void operator()(T* p) const - { - delete p; - } - - void operator()(boost::blank) const - {} - }; - -// -------------- io_control ----------- - - template - struct io_control_visitor_ec: boost::static_visitor<> - { - io_control_visitor_ec(IO_Control_Command& ioc, error_code& ec_) - : ioc(ioc), ec(ec_) {} - - template - void operator()(T* p) const - { - p->io_control(ioc, ec); - } - - void operator()(boost::blank) const - {} - - IO_Control_Command& ioc; - error_code& ec; - }; - - template - struct io_control_visitor - : boost::static_visitor<> - { - io_control_visitor(IO_Control_Command& ioc) - : ioc(ioc) {} - - template - void operator()(T* p) const - { - p->io_control(ioc); - } - - void operator()(boost::blank) const - {} - - IO_Control_Command& ioc; - }; -// -------------- async_connect ----------- - - template - struct async_connect_visitor - : boost::static_visitor<> - { - async_connect_visitor(EndpointType const& endpoint, Handler const& handler) - : endpoint(endpoint) - , handler(handler) - {} - - template - void operator()(T* p) const - { - p->async_connect(endpoint, handler); - } - - void operator()(boost::blank) const - {} - - EndpointType const& endpoint; - Handler const& handler; - }; - -// -------------- bind ----------- - - template - struct bind_visitor_ec - : boost::static_visitor<> - { - bind_visitor_ec(EndpointType const& ep, error_code& ec_) - : endpoint(ep) - , ec(ec_) - {} - - template - void operator()(T* p) const - { p->bind(endpoint, ec); } - - void operator()(boost::blank) const {} - - EndpointType const& endpoint; - error_code& ec; - }; - - template - struct bind_visitor - : boost::static_visitor<> - { - bind_visitor(EndpointType const& ep) - : endpoint(ep) - {} - - template - void operator()(T* p) const - { p->bind(endpoint); } - - void operator()(boost::blank) const {} - - EndpointType const& endpoint; - }; - -// -------------- open ----------- - - template - struct open_visitor_ec - : boost::static_visitor<> - { - open_visitor_ec(Protocol const& p, error_code& ec_) - : proto(p) - , ec(ec_) - {} - - template - void operator()(T* p) const - { p->open(proto, ec); } - - void operator()(boost::blank) const {} - - Protocol const& proto; - error_code& ec; - }; - - template - struct open_visitor - : boost::static_visitor<> - { - open_visitor(Protocol const& p) - : proto(p) - {} - - template - void operator()(T* p) const - { p->open(proto); } - - void operator()(boost::blank) const {} - - Protocol const& proto; - }; - -// -------------- is_open ----------- - - struct is_open_visitor - : boost::static_visitor - { - is_open_visitor() {} - - template - bool operator()(T const* p) const - { return p->is_open(); } - - bool operator()(boost::blank) const { return false; } - }; - -// -------------- close ----------- - - struct close_visitor_ec - : boost::static_visitor<> - { - close_visitor_ec(error_code& ec_) - : ec(ec_) - {} - - template - void operator()(T* p) const - { p->close(ec); } - - void operator()(boost::blank) const {} - - error_code& ec; - }; - - struct close_visitor - : boost::static_visitor<> - { - template - void operator()(T* p) const - { p->close(); } - - void operator()(boost::blank) const {} - }; - -// -------------- remote_endpoint ----------- - - template - struct remote_endpoint_visitor_ec - : boost::static_visitor - { - remote_endpoint_visitor_ec(error_code& ec_) - : ec(ec_) - {} - - template - EndpointType operator()(T const* p) const - { return p->remote_endpoint(ec); } - - EndpointType operator()(boost::blank) const - { return EndpointType(); } - - error_code& ec; - }; - - template - struct remote_endpoint_visitor - : boost::static_visitor - { - template - EndpointType operator()(T const* p) const - { return p->remote_endpoint(); } - - EndpointType operator()(boost::blank) const - { return EndpointType(); } - }; - -// -------------- set_option ----------- - - template - struct set_option_visitor - : boost::static_visitor<> - { - set_option_visitor(SettableSocketOption const& opt) - : opt_(opt) - {} - - template - void operator()(T* p) const - { p->set_option(opt_); } - - void operator()(boost::blank) const {} - - SettableSocketOption const& opt_; - }; - - template - struct set_option_visitor_ec - : boost::static_visitor - { - set_option_visitor_ec(SettableSocketOption const& opt, error_code& ec) - : opt_(opt) - , ec_(ec) - {} - - template - error_code operator()(T* p) const - { return p->set_option(opt_, ec_); } - - error_code operator()(boost::blank) const - { return ec_; } - - SettableSocketOption const& opt_; - error_code& ec_; - }; - -// -------------- local_endpoint ----------- - - template - struct local_endpoint_visitor_ec - : boost::static_visitor - { - local_endpoint_visitor_ec(error_code& ec_) - : ec(ec_) - {} - - template - EndpointType operator()(T const* p) const - { - return p->local_endpoint(ec); - } - - EndpointType operator()(boost::blank) const - { - return EndpointType(); - } - - error_code& ec; - }; - - template - struct local_endpoint_visitor - : boost::static_visitor - { - template - EndpointType operator()(T const* p) const - { - return p->local_endpoint(); - } - - EndpointType operator()(boost::blank) const - { - return EndpointType(); - } - }; - -// -------------- async_read_some ----------- - - template - struct async_read_some_visitor - : boost::static_visitor<> - { - async_read_some_visitor(Mutable_Buffers const& buffers, Handler const& handler) - : buffers(buffers) - , handler(handler) - {} - - template - void operator()(T* p) const - { - p->async_read_some(buffers, handler); - } - void operator()(boost::blank) const - {} - - Mutable_Buffers const& buffers; - Handler const& handler; - }; - -// -------------- read_some ----------- - - template - struct read_some_visitor - : boost::static_visitor - { - read_some_visitor(Mutable_Buffers const& buffers) - : buffers(buffers) - {} - - template - std::size_t operator()(T* p) const - { return p->read_some(buffers); } - - std::size_t operator()(boost::blank) const - { return 0; } - - Mutable_Buffers const& buffers; - }; - - template - struct read_some_visitor_ec - : boost::static_visitor - { - read_some_visitor_ec(Mutable_Buffers const& buffers, error_code& ec_) - : buffers(buffers) - , ec(ec_) - {} - - template - std::size_t operator()(T* p) const - { return p->read_some(buffers, ec); } - - std::size_t operator()(boost::blank) const - { return 0; } - - Mutable_Buffers const& buffers; - error_code& ec; - }; - -// -------------- async_write_some ----------- - - template - struct async_write_some_visitor - : boost::static_visitor<> - { - async_write_some_visitor(Const_Buffers const& buffers, Handler const& handler) - : buffers(buffers) - , handler(handler) - {} - - template - void operator()(T* p) const - { - p->async_write_some(buffers, handler); - } - - void operator()(boost::blank) const - {} - - Const_Buffers const& buffers; - Handler const& handler; - }; - -// -------------- in_avail ----------- - - struct in_avail_visitor_ec - : boost::static_visitor - { - in_avail_visitor_ec(error_code& ec_) - : ec(ec_) - {} - - template - std::size_t operator()(T const* p) const - { - return p->in_avail(ec); - } - - std::size_t operator()(boost::blank) const - { - return 0; - } - - error_code& ec; - }; - - struct in_avail_visitor - : boost::static_visitor - { - template - std::size_t operator()(T const* p) const - { - return p->in_avail(); - } - - void operator()(boost::blank) const - {} - }; - -// -------------- io_service ----------- - - template - struct io_service_visitor - : boost::static_visitor - { - template - IOService& operator()(T* p) const - { - return p->get_io_service(); - } - - IOService& operator()(boost::blank) const - { - return *(IOService*)0; - } - }; - -// -------------- lowest_layer ----------- - - template - struct lowest_layer_visitor - : boost::static_visitor - { - template - LowestLayer& operator()(T* p) const - { - return p->lowest_layer(); - } - - LowestLayer& operator()(boost::blank) const - { - return *(LowestLayer*)0; - } - }; - -} // namespace aux - -template < - BOOST_PP_ENUM_BINARY_PARAMS( - NETWORK_VARIANT_STREAM_LIMIT, class S, = boost::mpl::void_ BOOST_PP_INTERCEPT - ) -> -class variant_stream : boost::noncopyable -{ -public: - typedef BOOST_PP_CAT(boost::mpl::vector, NETWORK_VARIANT_STREAM_LIMIT)< - BOOST_PP_ENUM_PARAMS(NETWORK_VARIANT_STREAM_LIMIT, S) - > types0; - - typedef typename boost::mpl::remove::type types; - - typedef typename boost::make_variant_over< - typename boost::mpl::push_back< - typename boost::mpl::transform< - types - , boost::add_pointer - >::type - , boost::blank - >::type - >::type variant_type; - - typedef typename S0::lowest_layer_type lowest_layer_type; - typedef typename S0::endpoint_type endpoint_type; - typedef typename S0::protocol_type protocol_type; - - explicit variant_stream(io_service& ios) - : m_io_service(ios), m_variant(boost::blank()) {} - - template - void instantiate(io_service& ios) - { - TORRENT_ASSERT(&ios == &m_io_service); - std::auto_ptr owned(new S(ios)); - boost::apply_visitor(aux::delete_visitor(), m_variant); - m_variant = owned.get(); - owned.release(); - } - - template - S& get() - { - return *boost::get(m_variant); - } - - bool instantiated() const - { - return m_variant.which() != boost::mpl::size::value; - } - - ~variant_stream() - { - boost::apply_visitor(aux::delete_visitor(), m_variant); - } - - template - std::size_t read_some(Mutable_Buffers const& buffers, error_code& ec) - { - TORRENT_ASSERT(instantiated()); - return boost::apply_visitor( - aux::read_some_visitor_ec(buffers, ec) - , m_variant - ); - } - - template - std::size_t read_some(Mutable_Buffers const& buffers) - { - TORRENT_ASSERT(instantiated()); - return boost::apply_visitor( - aux::read_some_visitor(buffers) - , m_variant - ); - } - - template - void async_read_some(Mutable_Buffers const& buffers, Handler const& handler) - { - TORRENT_ASSERT(instantiated()); - boost::apply_visitor( - aux::async_read_some_visitor(buffers, handler) - , m_variant - ); - } - - template - void async_write_some(Const_Buffers const& buffers, Handler const& handler) - { - TORRENT_ASSERT(instantiated()); - boost::apply_visitor( - aux::async_write_some_visitor(buffers, handler) - , m_variant - ); - } - - template - void async_connect(endpoint_type const& endpoint, Handler const& handler) - { - TORRENT_ASSERT(instantiated()); - boost::apply_visitor( - aux::async_connect_visitor(endpoint, handler), m_variant - ); - } - - template - void io_control(IO_Control_Command& ioc) - { - TORRENT_ASSERT(instantiated()); - boost::apply_visitor( - aux::io_control_visitor(ioc), m_variant - ); - } - - template - void io_control(IO_Control_Command& ioc, error_code& ec) - { - TORRENT_ASSERT(instantiated()); - boost::apply_visitor( - aux::io_control_visitor_ec(ioc, ec) - , m_variant - ); - } - - void bind(endpoint_type const& endpoint) - { - TORRENT_ASSERT(instantiated()); - boost::apply_visitor(aux::bind_visitor(endpoint), m_variant); - } - - void bind(endpoint_type const& endpoint, error_code& ec) - { - TORRENT_ASSERT(instantiated()); - boost::apply_visitor( - aux::bind_visitor_ec(endpoint, ec), m_variant - ); - } - - void open(protocol_type const& p) - { - TORRENT_ASSERT(instantiated()); - boost::apply_visitor(aux::open_visitor(p), m_variant); - } - - void open(protocol_type const& p, error_code& ec) - { - TORRENT_ASSERT(instantiated()); - boost::apply_visitor( - aux::open_visitor_ec(p, ec), m_variant - ); - } - - bool is_open() const - { - return boost::apply_visitor(aux::is_open_visitor(), m_variant); - } - - void close() - { - if (!instantiated()) return; - boost::apply_visitor(aux::close_visitor(), m_variant); - } - - void close(error_code& ec) - { - if (!instantiated()) return; - boost::apply_visitor( - aux::close_visitor_ec(ec), m_variant - ); - } - - std::size_t in_avail() const - { - TORRENT_ASSERT(instantiated()); - return boost::apply_visitor(aux::in_avail_visitor(), m_variant); - } - - std::size_t in_avail(error_code& ec) const - { - TORRENT_ASSERT(instantiated()); - return boost::apply_visitor( - aux::in_avail_visitor_ec(ec), m_variant - ); - } - - endpoint_type remote_endpoint() const - { - TORRENT_ASSERT(instantiated()); - return boost::apply_visitor(aux::remote_endpoint_visitor(), m_variant); - } - - endpoint_type remote_endpoint(error_code& ec) const - { - TORRENT_ASSERT(instantiated()); - return boost::apply_visitor( - aux::remote_endpoint_visitor_ec(ec), m_variant - ); - } - - template - void set_option(SettableSocketOption const& opt) - { - TORRENT_ASSERT(instantiated()); - boost::apply_visitor(aux::set_option_visitor(opt) - , m_variant); - } - - template - error_code set_option(SettableSocketOption const& opt, error_code& ec) - { - TORRENT_ASSERT(instantiated()); - return boost::apply_visitor(aux::set_option_visitor_ec(opt, ec) - , m_variant); - } - - endpoint_type local_endpoint() const - { - TORRENT_ASSERT(instantiated()); - return boost::apply_visitor(aux::local_endpoint_visitor(), m_variant); - } - - endpoint_type local_endpoint(error_code& ec) const - { - TORRENT_ASSERT(instantiated()); - return boost::apply_visitor( - aux::local_endpoint_visitor_ec(ec), m_variant - ); - } - - io_service& get_io_service() - { - return m_io_service; - } - - lowest_layer_type& lowest_layer() - { - TORRENT_ASSERT(instantiated()); - return boost::apply_visitor( - aux::lowest_layer_visitor(), m_variant - ); - } - -private: - io_service& m_io_service; - variant_type m_variant; -}; - -} // namespace libtorrent - -#endif // VARIANT_STREAM_070211_HPP - diff --git a/libtorrent/include/libtorrent/version.hpp b/libtorrent/include/libtorrent/version.hpp deleted file mode 100644 index ee376cc21..000000000 --- a/libtorrent/include/libtorrent/version.hpp +++ /dev/null @@ -1,42 +0,0 @@ -/* - -Copyright (c) 2003, Arvid Norberg -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions -are met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in - the documentation and/or other materials provided with the distribution. - * Neither the name of the author nor the names of its - contributors may be used to endorse or promote products derived - from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -POSSIBILITY OF SUCH DAMAGE. - -*/ - -#ifndef TORRENT_VERSION_HPP_INCLUDED -#define TORRENT_VERSION_HPP_INCLUDED - -#define LIBTORRENT_VERSION_MAJOR 0 -#define LIBTORRENT_VERSION_MINOR 14 - -#define LIBTORRENT_VERSION "0.14.2.0" -#define LIBTORRENT_REVISION "$Rev: 3169 $" - -#endif diff --git a/libtorrent/include/libtorrent/web_peer_connection.hpp b/libtorrent/include/libtorrent/web_peer_connection.hpp deleted file mode 100644 index 51e8de7b4..000000000 --- a/libtorrent/include/libtorrent/web_peer_connection.hpp +++ /dev/null @@ -1,183 +0,0 @@ -/* - -Copyright (c) 2003, Arvid Norberg -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions -are met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in - the documentation and/or other materials provided with the distribution. - * Neither the name of the author nor the names of its - contributors may be used to endorse or promote products derived - from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -POSSIBILITY OF SUCH DAMAGE. - -*/ - -#ifndef TORRENT_WEB_PEER_CONNECTION_HPP_INCLUDED -#define TORRENT_WEB_PEER_CONNECTION_HPP_INCLUDED - -#include -#include -#include -#include -#include - -#include "libtorrent/debug.hpp" - -#ifdef _MSC_VER -#pragma warning(push, 1) -#endif - -#include -#include -#include -#include -#include -#include - -#ifdef _MSC_VER -#pragma warning(pop) -#endif - -#include "libtorrent/buffer.hpp" -#include "libtorrent/peer_connection.hpp" -#include "libtorrent/socket.hpp" -#include "libtorrent/peer_id.hpp" -#include "libtorrent/storage.hpp" -#include "libtorrent/stat.hpp" -#include "libtorrent/alert.hpp" -#include "libtorrent/torrent_handle.hpp" -#include "libtorrent/torrent.hpp" -#include "libtorrent/peer_request.hpp" -#include "libtorrent/piece_block_progress.hpp" -#include "libtorrent/config.hpp" -// parse_url -#include "libtorrent/tracker_manager.hpp" -#include "libtorrent/http_parser.hpp" - -namespace libtorrent -{ - class torrent; - - namespace detail - { - struct session_impl; - } - - class TORRENT_EXPORT web_peer_connection - : public peer_connection - { - friend class invariant_access; - public: - - // this is the constructor where the we are the active part. - // The peer_conenction should handshake and verify that the - // other end has the correct id - web_peer_connection( - aux::session_impl& ses - , boost::weak_ptr t - , boost::shared_ptr s - , tcp::endpoint const& remote - , std::string const& url - , policy::peer* peerinfo); - - ~web_peer_connection(); - - // called from the main loop when this connection has any - // work to do. - void on_sent(error_code const& error - , std::size_t bytes_transferred); - void on_receive(error_code const& error - , std::size_t bytes_transferred); - - std::string const& url() const { return m_url; } - - virtual void get_specific_peer_info(peer_info& p) const; - virtual bool in_handshake() const; - - // the following functions appends messages - // to the send buffer - void write_choke() {} - void write_unchoke() {} - void write_interested() {} - void write_not_interested() {} - void write_request(peer_request const& r); - void write_cancel(peer_request const& r) - { incoming_reject_request(r); } - void write_have(int index) {} - void write_piece(peer_request const& r, disk_buffer_holder& buffer) { TORRENT_ASSERT(false); } - void write_keepalive() {} - void on_connected(); - void write_reject_request(peer_request const&) {} - void write_allow_fast(int) {} - -#ifdef TORRENT_DEBUG - void check_invariant() const; -#endif - - private: - - // returns the block currently being - // downloaded. And the progress of that - // block. If the peer isn't downloading - // a piece for the moment, the boost::optional - // will be invalid. - boost::optional downloading_piece_progress() const; - - // this has one entry per bittorrent request - std::deque m_requests; - // this has one entry per http-request - // (might be more than the bt requests) - std::deque m_file_requests; - - std::string m_server_string; - http_parser m_parser; - std::string m_auth; - std::string m_host; - int m_port; - std::string m_path; - std::string m_url; - - // the first request will contain a little bit more data - // than subsequent ones, things that aren't critical are left - // out to save bandwidth. - bool m_first_request; - - // this is used for intermediate storage of pieces - // that is received in more than on HTTP responses - std::vector m_piece; - // the mapping of the data in the m_piece buffer - peer_request m_intermediate_piece; - - // the number of bytes into the receive buffer where - // current read cursor is. - int m_body_start; - // the number of bytes received in the current HTTP - // response. used to know where in the buffer the - // next response starts - int m_received_body; - - // position in the current range response - int m_range_pos; - }; -} - -#endif // TORRENT_WEB_PEER_CONNECTION_HPP_INCLUDED - diff --git a/libtorrent/include/libtorrent/xml_parse.hpp b/libtorrent/include/libtorrent/xml_parse.hpp deleted file mode 100644 index b65b2c1df..000000000 --- a/libtorrent/include/libtorrent/xml_parse.hpp +++ /dev/null @@ -1,218 +0,0 @@ -/* - -Copyright (c) 2007, Arvid Norberg -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions -are met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in - the documentation and/or other materials provided with the distribution. - * Neither the name of the author nor the names of its - contributors may be used to endorse or promote products derived - from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -POSSIBILITY OF SUCH DAMAGE. - -*/ - -#ifndef TORRENT_XML_PARSE_HPP -#define TORRENT_XML_PARSE_HPP - -#include -#include - -namespace libtorrent -{ - enum - { - xml_start_tag, - xml_end_tag, - xml_empty_tag, - xml_declaration_tag, - xml_string, - xml_attribute, - xml_comment, - xml_parse_error - }; - - inline bool isspace(char c) - { - const static char* ws = " \t\n\r\f\v"; - return std::strchr(ws, c); - } - - // callback(int type, char const* name, char const* val) - // str2 is only used for attributes. name is element or attribute - // name and val is attribute value - - template - void xml_parse(char* p, char* end, CallbackType callback) - { - for(;p != end; ++p) - { - char const* start = p; - char const* val_start = 0; - int token; - // look for tag start - for(; *p != '<' && p != end; ++p); - - if (p != start) - { - if (p != end) - { - TORRENT_ASSERT(*p == '<'); - *p = 0; - } - token = xml_string; - callback(token, start, val_start); - if (p != end) *p = '<'; - } - - if (p == end) break; - - // skip '<' - ++p; - - // parse the name of the tag. - for (start = p; p != end && *p != '>' && !isspace(*p); ++p); - - char* tag_name_end = p; - - // skip the attributes for now - for (; p != end && *p != '>'; ++p); - - // parse error - if (p == end) - { - token = xml_parse_error; - start = "unexpected end of file"; - callback(token, start, val_start); - break; - } - - TORRENT_ASSERT(*p == '>'); - // save the character that terminated the tag name - // it could be both '>' and ' '. - char save = *tag_name_end; - *tag_name_end = 0; - - char* tag_end = p; - if (*start == '/') - { - ++start; - token = xml_end_tag; - callback(token, start, val_start); - } - else if (*(p-1) == '/') - { - *(p-1) = 0; - token = xml_empty_tag; - callback(token, start, val_start); - *(p-1) = '/'; - tag_end = p - 1; - } - else if (*start == '?' && *(p-1) == '?') - { - *(p-1) = 0; - ++start; - token = xml_declaration_tag; - callback(token, start, val_start); - *(p-1) = '?'; - tag_end = p - 1; - } - else if (start + 5 < p && std::memcmp(start, "!--", 3) == 0 && std::memcmp(p-2, "--", 2) == 0) - { - start += 3; - *(p-2) = 0; - token = xml_comment; - callback(token, start, val_start); - *(p-2) = '-'; - tag_end = p - 2; - } - else - { - token = xml_start_tag; - callback(token, start, val_start); - } - - *tag_name_end = save; - - // parse attributes - for (char* i = tag_name_end; i < tag_end; ++i) - { - // find start of attribute name - for (; i != tag_end && isspace(*i); ++i); - if (i == tag_end) break; - start = i; - // find end of attribute name - for (; i != tag_end && *i != '=' && !isspace(*i); ++i); - char* name_end = i; - - // look for equality sign - for (; i != tag_end && *i != '='; ++i); - - if (i == tag_end) - { - token = xml_parse_error; - val_start = 0; - start = "garbage inside element brackets"; - callback(token, start, val_start); - break; - } - - ++i; - for (; i != tag_end && isspace(*i); ++i); - // check for parse error (values must be quoted) - if (i == tag_end || (*i != '\'' && *i != '\"')) - { - token = xml_parse_error; - val_start = 0; - start = "unquoted attribute value"; - callback(token, start, val_start); - break; - } - char quote = *i; - ++i; - val_start = i; - for (; i != tag_end && *i != quote; ++i); - // parse error (missing end quote) - if (i == tag_end) - { - token = xml_parse_error; - val_start = 0; - start = "missing end quote on attribute"; - callback(token, start, val_start); - break; - } - save = *i; - *i = 0; - *name_end = 0; - token = xml_attribute; - callback(token, start, val_start); - *name_end = '='; - *i = save; - } - } - - } - -} - - -#endif - diff --git a/libtorrent/src/GeoIP.c b/libtorrent/src/GeoIP.c deleted file mode 100644 index 562cdc9a2..000000000 --- a/libtorrent/src/GeoIP.c +++ /dev/null @@ -1,1038 +0,0 @@ -/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 2; tab-width: 2 -*- */ -/* GeoIP.c - * - * Copyright (C) 2006 MaxMind LLC - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include "libtorrent/GeoIP.h" - -#ifndef WIN32 -#include -#include -#include /* For ntohl */ -#include - -#include - -#else -#include -#include -#define snprintf _snprintf -#endif -#include -#include -#include -#include -#include -#include /* for fstat */ -#include /* for fstat */ - -#ifdef HAVE_STDINT_H -#include /* For uint32_t */ -#endif - -#ifndef INADDR_NONE -#define INADDR_NONE -1 -#endif - -#define COUNTRY_BEGIN 16776960 -#define STATE_BEGIN_REV0 16700000 -#define STATE_BEGIN_REV1 16000000 -#define STRUCTURE_INFO_MAX_SIZE 20 -#define DATABASE_INFO_MAX_SIZE 100 -#define MAX_ORG_RECORD_LENGTH 300 -#define US_OFFSET 1 -#define CANADA_OFFSET 677 -#define WORLD_OFFSET 1353 -#define FIPS_RANGE 360 - -#define CHECK_ERR(err, msg) { \ - if (err != Z_OK) { \ - fprintf(stderr, "%s error: %d\n", msg, err); \ - exit(1); \ - } \ -} - -const char GeoIP_country_code[253][3] = { "--","AP","EU","AD","AE","AF","AG","AI","AL","AM","AN", - "AO","AQ","AR","AS","AT","AU","AW","AZ","BA","BB", - "BD","BE","BF","BG","BH","BI","BJ","BM","BN","BO", - "BR","BS","BT","BV","BW","BY","BZ","CA","CC","CD", - "CF","CG","CH","CI","CK","CL","CM","CN","CO","CR", - "CU","CV","CX","CY","CZ","DE","DJ","DK","DM","DO", - "DZ","EC","EE","EG","EH","ER","ES","ET","FI","FJ", - "FK","FM","FO","FR","FX","GA","GB","GD","GE","GF", - "GH","GI","GL","GM","GN","GP","GQ","GR","GS","GT", - "GU","GW","GY","HK","HM","HN","HR","HT","HU","ID", - "IE","IL","IN","IO","IQ","IR","IS","IT","JM","JO", - "JP","KE","KG","KH","KI","KM","KN","KP","KR","KW", - "KY","KZ","LA","LB","LC","LI","LK","LR","LS","LT", - "LU","LV","LY","MA","MC","MD","MG","MH","MK","ML", - "MM","MN","MO","MP","MQ","MR","MS","MT","MU","MV", - "MW","MX","MY","MZ","NA","NC","NE","NF","NG","NI", - "NL","NO","NP","NR","NU","NZ","OM","PA","PE","PF", - "PG","PH","PK","PL","PM","PN","PR","PS","PT","PW", - "PY","QA","RE","RO","RU","RW","SA","SB","SC","SD", - "SE","SG","SH","SI","SJ","SK","SL","SM","SN","SO", - "SR","ST","SV","SY","SZ","TC","TD","TF","TG","TH", - "TJ","TK","TM","TN","TO","TL","TR","TT","TV","TW", - "TZ","UA","UG","UM","US","UY","UZ","VA","VC","VE", - "VG","VI","VN","VU","WF","WS","YE","YT","RS","ZA", - "ZM","ME","ZW","A1","A2","O1","AX","GG","IM","JE", - "BL","MF"}; - -const char GeoIP_country_code3[253][4] = { "--","AP","EU","AND","ARE","AFG","ATG","AIA","ALB","ARM","ANT", - "AGO","AQ","ARG","ASM","AUT","AUS","ABW","AZE","BIH","BRB", - "BGD","BEL","BFA","BGR","BHR","BDI","BEN","BMU","BRN","BOL", - "BRA","BHS","BTN","BV","BWA","BLR","BLZ","CAN","CC","COD", - "CAF","COG","CHE","CIV","COK","CHL","CMR","CHN","COL","CRI", - "CUB","CPV","CX","CYP","CZE","DEU","DJI","DNK","DMA","DOM", - "DZA","ECU","EST","EGY","ESH","ERI","ESP","ETH","FIN","FJI", - "FLK","FSM","FRO","FRA","FX","GAB","GBR","GRD","GEO","GUF", - "GHA","GIB","GRL","GMB","GIN","GLP","GNQ","GRC","GS","GTM", - "GUM","GNB","GUY","HKG","HM","HND","HRV","HTI","HUN","IDN", - "IRL","ISR","IND","IO","IRQ","IRN","ISL","ITA","JAM","JOR", - "JPN","KEN","KGZ","KHM","KIR","COM","KNA","PRK","KOR","KWT", - "CYM","KAZ","LAO","LBN","LCA","LIE","LKA","LBR","LSO","LTU", - "LUX","LVA","LBY","MAR","MCO","MDA","MDG","MHL","MKD","MLI", - "MMR","MNG","MAC","MNP","MTQ","MRT","MSR","MLT","MUS","MDV", - "MWI","MEX","MYS","MOZ","NAM","NCL","NER","NFK","NGA","NIC", - "NLD","NOR","NPL","NRU","NIU","NZL","OMN","PAN","PER","PYF", - "PNG","PHL","PAK","POL","SPM","PCN","PRI","PSE","PRT","PLW", - "PRY","QAT","REU","ROU","RUS","RWA","SAU","SLB","SYC","SDN", - "SWE","SGP","SHN","SVN","SJM","SVK","SLE","SMR","SEN","SOM", - "SUR","STP","SLV","SYR","SWZ","TCA","TCD","TF","TGO","THA", - "TJK","TKL","TKM","TUN","TON","TLS","TUR","TTO","TUV","TWN", - "TZA","UKR","UGA","UM","USA","URY","UZB","VAT","VCT","VEN", - "VGB","VIR","VNM","VUT","WLF","WSM","YEM","YT","SRB","ZAF", - "ZMB","MNE","ZWE","A1","A2","O1","ALA","GGY","IMN","JEY", - "BLM","MAF"}; - -const char * GeoIP_country_name[253] = {"N/A","Asia/Pacific Region","Europe","Andorra","United Arab Emirates","Afghanistan","Antigua and Barbuda","Anguilla","Albania","Armenia","Netherlands Antilles", - "Angola","Antarctica","Argentina","American Samoa","Austria","Australia","Aruba","Azerbaijan","Bosnia and Herzegovina","Barbados", - "Bangladesh","Belgium","Burkina Faso","Bulgaria","Bahrain","Burundi","Benin","Bermuda","Brunei Darussalam","Bolivia", - "Brazil","Bahamas","Bhutan","Bouvet Island","Botswana","Belarus","Belize","Canada","Cocos (Keeling) Islands","Congo, The Democratic Republic of the", - "Central African Republic","Congo","Switzerland","Cote D'Ivoire","Cook Islands","Chile","Cameroon","China","Colombia","Costa Rica", - "Cuba","Cape Verde","Christmas Island","Cyprus","Czech Republic","Germany","Djibouti","Denmark","Dominica","Dominican Republic", - "Algeria","Ecuador","Estonia","Egypt","Western Sahara","Eritrea","Spain","Ethiopia","Finland","Fiji", - "Falkland Islands (Malvinas)","Micronesia, Federated States of","Faroe Islands","France","France, Metropolitan","Gabon","United Kingdom","Grenada","Georgia","French Guiana", - "Ghana","Gibraltar","Greenland","Gambia","Guinea","Guadeloupe","Equatorial Guinea","Greece","South Georgia and the South Sandwich Islands","Guatemala", - "Guam","Guinea-Bissau","Guyana","Hong Kong","Heard Island and McDonald Islands","Honduras","Croatia","Haiti","Hungary","Indonesia", - "Ireland","Israel","India","British Indian Ocean Territory","Iraq","Iran, Islamic Republic of","Iceland","Italy","Jamaica","Jordan", - "Japan","Kenya","Kyrgyzstan","Cambodia","Kiribati","Comoros","Saint Kitts and Nevis","Korea, Democratic People's Republic of","Korea, Republic of","Kuwait", - "Cayman Islands","Kazakhstan","Lao People's Democratic Republic","Lebanon","Saint Lucia","Liechtenstein","Sri Lanka","Liberia","Lesotho","Lithuania", - "Luxembourg","Latvia","Libyan Arab Jamahiriya","Morocco","Monaco","Moldova, Republic of","Madagascar","Marshall Islands","Macedonia","Mali", - "Myanmar","Mongolia","Macau","Northern Mariana Islands","Martinique","Mauritania","Montserrat","Malta","Mauritius","Maldives", - "Malawi","Mexico","Malaysia","Mozambique","Namibia","New Caledonia","Niger","Norfolk Island","Nigeria","Nicaragua", - "Netherlands","Norway","Nepal","Nauru","Niue","New Zealand","Oman","Panama","Peru","French Polynesia", - "Papua New Guinea","Philippines","Pakistan","Poland","Saint Pierre and Miquelon","Pitcairn Islands","Puerto Rico","Palestinian Territory","Portugal","Palau", - "Paraguay","Qatar","Reunion","Romania","Russian Federation","Rwanda","Saudi Arabia","Solomon Islands","Seychelles","Sudan", - "Sweden","Singapore","Saint Helena","Slovenia","Svalbard and Jan Mayen","Slovakia","Sierra Leone","San Marino","Senegal","Somalia","Suriname", - "Sao Tome and Principe","El Salvador","Syrian Arab Republic","Swaziland","Turks and Caicos Islands","Chad","French Southern Territories","Togo","Thailand", - "Tajikistan","Tokelau","Turkmenistan","Tunisia","Tonga","Timor-Leste","Turkey","Trinidad and Tobago","Tuvalu","Taiwan", - "Tanzania, United Republic of","Ukraine","Uganda","United States Minor Outlying Islands","United States","Uruguay","Uzbekistan","Holy See (Vatican City State)","Saint Vincent and the Grenadines","Venezuela", - "Virgin Islands, British","Virgin Islands, U.S.","Vietnam","Vanuatu","Wallis and Futuna","Samoa","Yemen","Mayotte","Serbia","South Africa", - "Zambia","Montenegro","Zimbabwe","Anonymous Proxy","Satellite Provider","Other","Aland Islands","Guernsey","Isle of Man","Jersey", - "Saint Barthelemy","Saint Martin"}; - -/* Possible continent codes are AF, AS, EU, NA, OC, SA for Africa, Asia, Europe, North America, Oceania -and South America. */ - -const char GeoIP_country_continent[253][3] = {"--","AS","EU","EU","AS","AS","SA","SA","EU","AS","SA", - "AF","AN","SA","OC","EU","OC","SA","AS","EU","SA", - "AS","EU","AF","EU","AS","AF","AF","SA","AS","SA", - "SA","SA","AS","AF","AF","EU","SA","NA","AS","AF", - "AF","AF","EU","AF","OC","SA","AF","AS","SA","SA", - "SA","AF","AS","AS","EU","EU","AF","EU","SA","SA", - "AF","SA","EU","AF","AF","AF","EU","AF","EU","OC", - "SA","OC","EU","EU","EU","AF","EU","SA","AS","SA", - "AF","EU","SA","AF","AF","SA","AF","EU","SA","SA", - "OC","AF","SA","AS","AF","SA","EU","SA","EU","AS", - "EU","AS","AS","AS","AS","AS","EU","EU","SA","AS", - "AS","AF","AS","AS","OC","AF","SA","AS","AS","AS", - "SA","AS","AS","AS","SA","EU","AS","AF","AF","EU", - "EU","EU","AF","AF","EU","EU","AF","OC","EU","AF", - "AS","AS","AS","OC","SA","AF","SA","EU","AF","AS", - "AF","NA","AS","AF","AF","OC","AF","OC","AF","SA", - "EU","EU","AS","OC","OC","OC","AS","SA","SA","OC", - "OC","AS","AS","EU","SA","OC","SA","AS","EU","OC", - "SA","AS","AF","EU","AS","AF","AS","OC","AF","AF", - "EU","AS","AF","EU","EU","EU","AF","EU","AF","AF", - "SA","AF","SA","AS","AF","SA","AF","AF","AF","AS", - "AS","OC","AS","AF","OC","AS","AS","SA","OC","AS", - "AF","EU","AF","OC","NA","SA","AS","EU","SA","SA", - "SA","SA","AS","OC","OC","OC","AS","AF","EU","AF", - "AF","EU","AF","--","--","--","EU","EU","EU","EU", - "SA","SA"}; - -const char * GeoIPDBDescription[NUM_DB_TYPES] = {NULL, "GeoIP Country Edition", "GeoIP City Edition, Rev 1", "GeoIP Region Edition, Rev 1", "GeoIP ISP Edition", "GeoIP Organization Edition", "GeoIP City Edition, Rev 0", "GeoIP Region Edition, Rev 0","GeoIP Proxy Edition","GeoIP ASNum Edition","GeoIP Netspeed Edition","GeoIP Domain Name Edition"}; - -char * custom_directory = NULL; - -void GeoIP_setup_custom_directory (char * dir) { - custom_directory = dir; -} -/* -char *_GeoIP_full_path_to(const char *file_name) { - int len; - char *path = malloc(sizeof(char) * 1024); - - if (custom_directory == NULL){ -#ifndef WIN32 - memset(path, 0, sizeof(char) * 1024); - snprintf(path, sizeof(char) * 1024 - 1, "%s/%s", GEOIPDATADIR, file_name); -#else - char buf[MAX_PATH], *p, *q = NULL; - memset(buf, 0, sizeof(buf)); - len = GetModuleFileName(GetModuleHandle(NULL), buf, sizeof(buf) - 1); - for (p = buf + len; p > buf; p--) - if (*p == '\\') - { - if (!q) - q = p; - else - *p = '/'; - } - *q = 0; - memset(path, 0, sizeof(char) * 1024); - snprintf(path, sizeof(char) * 1024 - 1, "%s/%s", buf, file_name); -#endif - } else { - len = strlen(custom_directory); - if (custom_directory[len-1] != '/') { - snprintf(path, sizeof(char) * 1024 - 1, "%s/%s",custom_directory, file_name); - } else { - snprintf(path, sizeof(char) * 1024 - 1, "%s%s", custom_directory, file_name); - } - } - return path; -} - -char ** GeoIPDBFileName = NULL; - -void _GeoIP_setup_dbfilename() { - if (NULL == GeoIPDBFileName) { - GeoIPDBFileName = malloc(sizeof(char *) * NUM_DB_TYPES); - memset(GeoIPDBFileName, 0, sizeof(char *) * NUM_DB_TYPES); - - GeoIPDBFileName[GEOIP_COUNTRY_EDITION] = _GeoIP_full_path_to("GeoIP.dat"); - GeoIPDBFileName[GEOIP_REGION_EDITION_REV0] = _GeoIP_full_path_to("GeoIPRegion.dat"); - GeoIPDBFileName[GEOIP_REGION_EDITION_REV1] = _GeoIP_full_path_to("GeoIPRegion.dat"); - GeoIPDBFileName[GEOIP_CITY_EDITION_REV0] = _GeoIP_full_path_to("GeoIPCity.dat"); - GeoIPDBFileName[GEOIP_CITY_EDITION_REV1] = _GeoIP_full_path_to("GeoIPCity.dat"); - GeoIPDBFileName[GEOIP_ISP_EDITION] = _GeoIP_full_path_to("GeoIPISP.dat"); - GeoIPDBFileName[GEOIP_ORG_EDITION] = _GeoIP_full_path_to("GeoIPOrg.dat"); - GeoIPDBFileName[GEOIP_PROXY_EDITION] = _GeoIP_full_path_to("GeoIPProxy.dat"); - GeoIPDBFileName[GEOIP_ASNUM_EDITION] = _GeoIP_full_path_to("GeoIPASNum.dat"); - GeoIPDBFileName[GEOIP_NETSPEED_EDITION] = _GeoIP_full_path_to("GeoIPNetSpeed.dat"); - GeoIPDBFileName[GEOIP_DOMAIN_EDITION] = _GeoIP_full_path_to("GeoIPDomain.dat"); - } -} -*/ - -static -int _file_exists(const char *file_name) { - struct stat file_stat; - return( (stat(file_name, &file_stat) == 0) ? 1:0); -} -/* -int GeoIP_db_avail(int type) { - const char * filePath; - if (type < 0 || type >= NUM_DB_TYPES) { - return 0; - } - _GeoIP_setup_dbfilename(); - filePath = GeoIPDBFileName[type]; - if (NULL == filePath) { - return 0; - } - return _file_exists(filePath); -} -*/ -static -void _setup_segments(GeoIP * gi) { - int i, j; - unsigned char delim[3]; - unsigned char buf[SEGMENT_RECORD_LENGTH]; - - gi->databaseSegments = NULL; - - /* default to GeoIP Country Edition */ - gi->databaseType = GEOIP_COUNTRY_EDITION; - gi->record_length = STANDARD_RECORD_LENGTH; - fseek(gi->GeoIPDatabase, -3l, SEEK_END); - for (i = 0; i < STRUCTURE_INFO_MAX_SIZE; i++) { - fread(delim, 1, 3, gi->GeoIPDatabase); - if (delim[0] == 255 && delim[1] == 255 && delim[2] == 255) { - fread(&gi->databaseType, 1, 1, gi->GeoIPDatabase); - if (gi->databaseType >= 106) { - /* backwards compatibility with databases from April 2003 and earlier */ - gi->databaseType -= 105; - } - - if (gi->databaseType == GEOIP_REGION_EDITION_REV0) { - /* Region Edition, pre June 2003 */ - gi->databaseSegments = (unsigned int*)malloc(sizeof(int)); - gi->databaseSegments[0] = STATE_BEGIN_REV0; - } else if (gi->databaseType == GEOIP_REGION_EDITION_REV1) { - /* Region Edition, post June 2003 */ - gi->databaseSegments = (unsigned int*)malloc(sizeof(int)); - gi->databaseSegments[0] = STATE_BEGIN_REV1; - } else if (gi->databaseType == GEOIP_CITY_EDITION_REV0 || - gi->databaseType == GEOIP_CITY_EDITION_REV1 || - gi->databaseType == GEOIP_ORG_EDITION || - gi->databaseType == GEOIP_ISP_EDITION || - gi->databaseType == GEOIP_ASNUM_EDITION) { - /* City/Org Editions have two segments, read offset of second segment */ - gi->databaseSegments = (unsigned int*)malloc(sizeof(int)); - gi->databaseSegments[0] = 0; - fread(buf, SEGMENT_RECORD_LENGTH, 1, gi->GeoIPDatabase); - for (j = 0; j < SEGMENT_RECORD_LENGTH; j++) { - gi->databaseSegments[0] += (buf[j] << (j * 8)); - } - if (gi->databaseType == GEOIP_ORG_EDITION || - gi->databaseType == GEOIP_ISP_EDITION) - gi->record_length = ORG_RECORD_LENGTH; - } - break; - } else { - fseek(gi->GeoIPDatabase, -4l, SEEK_CUR); - } - } - if (gi->databaseType == GEOIP_COUNTRY_EDITION || - gi->databaseType == GEOIP_PROXY_EDITION || - gi->databaseType == GEOIP_NETSPEED_EDITION) { - gi->databaseSegments = (unsigned int*)malloc(sizeof(int)); - gi->databaseSegments[0] = COUNTRY_BEGIN; - } -} - -static -int _check_mtime(GeoIP *gi) { - struct stat buf; - if (gi->flags & GEOIP_CHECK_CACHE) { - if (stat(gi->file_path, &buf) != -1) { - if (buf.st_mtime != gi->mtime) { - /* GeoIP Database file updated */ - if (gi->flags & (GEOIP_MEMORY_CACHE | GEOIP_MMAP_CACHE)) { -#ifndef WIN32 - if ( gi->flags & GEOIP_MMAP_CACHE) { - munmap(gi->cache, gi->size); - gi->cache = NULL; - } else -#endif - { - /* reload database into memory cache */ - if ((gi->cache = (unsigned char*) realloc(gi->cache, buf.st_size)) == NULL) { - fprintf(stderr,"Out of memory when reloading %s\n",gi->file_path); - return -1; - } - } - } - /* refresh filehandle */ - fclose(gi->GeoIPDatabase); - gi->GeoIPDatabase = fopen(gi->file_path,"rb"); - if (gi->GeoIPDatabase == NULL) { - fprintf(stderr,"Error Opening file %s when reloading\n",gi->file_path); - return -1; - } - gi->mtime = buf.st_mtime; - gi->size = buf.st_size; - -#ifndef WIN32 - if ( gi->flags & GEOIP_MMAP_CACHE) { - gi->cache = (unsigned char*)mmap(NULL, buf.st_size, PROT_READ, MAP_PRIVATE, fileno(gi->GeoIPDatabase), 0); - if ( gi->cache == MAP_FAILED ) { - - fprintf(stderr,"Error remapping file %s when reloading\n",gi->file_path); - gi->cache = 0; - return -1; - } - } else -#endif - if ( gi->flags & GEOIP_MEMORY_CACHE ) { - if (fread(gi->cache, sizeof(unsigned char), buf.st_size, gi->GeoIPDatabase) != (size_t) buf.st_size) { - fprintf(stderr,"Error reading file %s when reloading\n",gi->file_path); - return -1; - } - } - if (gi->databaseSegments != NULL) { - free(gi->databaseSegments); - gi->databaseSegments = NULL; - } - _setup_segments(gi); - if (gi->databaseSegments == NULL) { - fprintf(stderr, "Error reading file %s -- corrupt\n", gi->file_path); - return -1; - } - if (gi->flags & GEOIP_INDEX_CACHE) { - gi->index_cache = (unsigned char *) realloc(gi->index_cache, sizeof(unsigned char) * ((gi->databaseSegments[0] * (long)gi->record_length * 2))); - if (gi->index_cache != NULL) { - fseek(gi->GeoIPDatabase, 0, SEEK_SET); - if (fread(gi->index_cache, sizeof(unsigned char), gi->databaseSegments[0] * (long)gi->record_length * 2, gi->GeoIPDatabase) != (size_t) (gi->databaseSegments[0]*(long)gi->record_length * 2)) { - fprintf(stderr,"Error reading file %s where reloading\n",gi->file_path); - return -1; - } - } - } - } - } - } - return 0; -} - -unsigned int _GeoIP_seek_record (GeoIP *gi, unsigned long ipnum) { - int depth; - unsigned int x; - unsigned char stack_buffer[2 * MAX_RECORD_LENGTH]; - const unsigned char *buf = (gi->cache == NULL) ? stack_buffer : NULL; - unsigned int offset = 0; - - const unsigned char * p; - int j; - - _check_mtime(gi); - for (depth = 31; depth >= 0; depth--) { - if (gi->cache == NULL && gi->index_cache == NULL) { - /* read from disk */ - fseek(gi->GeoIPDatabase, (long)gi->record_length * 2 * offset, SEEK_SET); - fread(stack_buffer,gi->record_length,2,gi->GeoIPDatabase); - } else if (gi->index_cache == NULL) { - /* simply point to record in memory */ - buf = gi->cache + (long)gi->record_length * 2 *offset; - } else { - buf = gi->index_cache + (long)gi->record_length * 2 * offset; - } - - if (ipnum & (1 << depth)) { - /* Take the right-hand branch */ - if ( gi->record_length == 3 ) { - /* Most common case is completely unrolled and uses constants. */ - x = (buf[3*1 + 0] << (0*8)) - + (buf[3*1 + 1] << (1*8)) - + (buf[3*1 + 2] << (2*8)); - - } else { - /* General case */ - j = gi->record_length; - p = &buf[2*j]; - x = 0; - do { - x <<= 8; - x += *(--p); - } while ( --j ); - } - - } else { - /* Take the left-hand branch */ - if ( gi->record_length == 3 ) { - /* Most common case is completely unrolled and uses constants. */ - x = (buf[3*0 + 0] << (0*8)) - + (buf[3*0 + 1] << (1*8)) - + (buf[3*0 + 2] << (2*8)); - } else { - /* General case */ - j = gi->record_length; - p = &buf[1*j]; - x = 0; - do { - x <<= 8; - x += *(--p); - } while ( --j ); - } - } - - if (x >= gi->databaseSegments[0]) { - gi->netmask = 32 - depth; - return x; - } - offset = x; - } - - /* shouldn't reach here */ - fprintf(stderr,"Error Traversing Database for ipnum = %lu - Perhaps database is corrupt?\n",ipnum); - return 0; -} - -unsigned long -_GeoIP_addr_to_num(const char *addr) -{ - unsigned int c, octet, t; - unsigned long ipnum; - int i = 3; - - octet = ipnum = 0; - while ((c = *addr++)) { - if (c == '.') { - if (octet > 255) - return 0; - ipnum <<= 8; - ipnum += octet; - i--; - octet = 0; - } else { - t = octet; - octet <<= 3; - octet += t; - octet += t; - c -= '0'; - if (c > 9) - return 0; - octet += c; - } - } - if ((octet > 255) || (i != 0)) - return 0; - ipnum <<= 8; - return ipnum + octet; -} -/* -GeoIP* GeoIP_open_type (int type, int flags) { - GeoIP * gi; - const char * filePath; - if (type < 0 || type >= NUM_DB_TYPES) { - printf("Invalid database type %d\n", type); - return NULL; - } - _GeoIP_setup_dbfilename(); - filePath = GeoIPDBFileName[type]; - if (filePath == NULL) { - printf("Invalid database type %d\n", type); - return NULL; - } - gi = GeoIP_open (filePath, flags); - return gi; -} - -GeoIP* GeoIP_new (int flags) { - GeoIP * gi; - _GeoIP_setup_dbfilename(); - gi = GeoIP_open (GeoIPDBFileName[GEOIP_COUNTRY_EDITION], flags); - return gi; -} -*/ -GeoIP* GeoIP_open (const char * filename, int flags) { - struct stat buf; - GeoIP * gi; - size_t len; - - gi = (GeoIP *)malloc(sizeof(GeoIP)); - if (gi == NULL) - return NULL; - len = sizeof(char) * (strlen(filename)+1); - gi->file_path = (char*)malloc(len); - if (gi->file_path == NULL) { - free(gi); - return NULL; - } - strncpy(gi->file_path, filename, len); - gi->GeoIPDatabase = fopen(filename,"rb"); - if (gi->GeoIPDatabase == NULL) { - fprintf(stderr,"Error Opening file %s\n",filename); - free(gi->file_path); - free(gi); - return NULL; - } else { - if (flags & (GEOIP_MEMORY_CACHE | GEOIP_MMAP_CACHE) ) { - if (fstat(fileno(gi->GeoIPDatabase), &buf) == -1) { - fprintf(stderr,"Error stating file %s\n",filename); - free(gi->file_path); - free(gi); - return NULL; - } - gi->mtime = buf.st_mtime; - gi->size = buf.st_size; -#ifndef WIN32 - /* MMAP added my Peter Shipley */ - if ( flags & GEOIP_MMAP_CACHE) { - gi->cache = (unsigned char*)mmap(NULL, buf.st_size, PROT_READ, MAP_PRIVATE, fileno(gi->GeoIPDatabase), 0); - if ( gi->cache == MAP_FAILED ) { - fprintf(stderr,"Error mmaping file %s\n",filename); - free(gi->file_path); - free(gi); - return NULL; - } - } else -#endif - { - gi->cache = (unsigned char *) malloc(sizeof(unsigned char) * buf.st_size); - - if (gi->cache != NULL) { - if (fread(gi->cache, sizeof(unsigned char), buf.st_size, gi->GeoIPDatabase) != (size_t) buf.st_size) { - fprintf(stderr,"Error reading file %s\n",filename); - free(gi->cache); - free(gi->file_path); - free(gi); - return NULL; - } - } - } - } else { - if (flags & GEOIP_CHECK_CACHE) { - if (fstat(fileno(gi->GeoIPDatabase), &buf) == -1) { - fprintf(stderr,"Error stating file %s\n",filename); - free(gi->file_path); - free(gi); - return NULL; - } - gi->mtime = buf.st_mtime; - } - gi->cache = NULL; - } - gi->flags = flags; - gi->charset = GEOIP_CHARSET_ISO_8859_1; - - _setup_segments(gi); - if (flags & GEOIP_INDEX_CACHE) { - gi->index_cache = (unsigned char *) malloc(sizeof(unsigned char) * ((gi->databaseSegments[0] * (long)gi->record_length * 2))); - if (gi->index_cache != NULL) { - fseek(gi->GeoIPDatabase, 0, SEEK_SET); - if (fread(gi->index_cache, sizeof(unsigned char), gi->databaseSegments[0] * (long)gi->record_length * 2, gi->GeoIPDatabase) != (size_t) (gi->databaseSegments[0]*(long)gi->record_length * 2)) { - fprintf(stderr,"Error reading file %s\n",filename); - free(gi->databaseSegments); - free(gi->index_cache); - free(gi); - return NULL; - } - } - } else { - gi->index_cache = NULL; - } - return gi; - } -} - -void GeoIP_delete (GeoIP *gi) { - if (gi == NULL ) - return; - if (gi->GeoIPDatabase != NULL) - fclose(gi->GeoIPDatabase); - if (gi->cache != NULL) { -#ifndef WIN32 - if ( gi->flags & GEOIP_MMAP_CACHE) { - munmap(gi->cache, gi->size); - } else -#endif - { - free(gi->cache); - } - gi->cache = NULL; - } - if (gi->index_cache != NULL) - free(gi->index_cache); - if (gi->file_path != NULL) - free(gi->file_path); - if (gi->databaseSegments != NULL) - free(gi->databaseSegments); - free(gi); -} - -const char *GeoIP_country_code_by_name (GeoIP* gi, const char *name) { - int country_id; - country_id = GeoIP_id_by_name(gi, name); - return (country_id > 0) ? GeoIP_country_code[country_id] : NULL; -} - -const char *GeoIP_country_code3_by_name (GeoIP* gi, const char *name) { - int country_id; - country_id = GeoIP_id_by_name(gi, name); - return (country_id > 0) ? GeoIP_country_code3[country_id] : NULL; -} - -const char *GeoIP_country_name_by_name (GeoIP* gi, const char *name) { - int country_id; - country_id = GeoIP_id_by_name(gi, name); - return (country_id > 0) ? GeoIP_country_name[country_id] : NULL; -} - -unsigned long _GeoIP_lookupaddress (const char *host) { - unsigned long addr = inet_addr(host); - struct hostent phe2; - struct hostent * phe = &phe2; - char *buf = NULL; - int buflength = 16384; - int herr = 0; - int result = 0; -#ifdef HAVE_GETHOSTBYNAME_R - buf = malloc(buflength); -#endif - if (addr == INADDR_NONE) { -#ifdef HAVE_GETHOSTBYNAME_R - while (1) { - /* we use gethostbyname_r here because it is thread-safe and gethostbyname is not */ -#ifdef GETHOSTBYNAME_R_RETURNS_INT - result = gethostbyname_r(host,&phe2,buf,buflength,&phe,&herr); -#else - phe = gethostbyname_r(host,&phe2,buf,buflength,&herr); -#endif - if (herr != ERANGE) - break; - if (result == 0) - break; - /* double the buffer if the buffer is too small */ - buflength = buflength * 2; - buf = realloc(buf,buflength); - } -#endif -#ifndef HAVE_GETHOSTBYNAME_R - /* Some systems do not support gethostbyname_r, such as Mac OS X */ - phe = gethostbyname(host); -#endif - if (!phe || result != 0) { - free(buf); - return 0; - } - addr = *((unsigned long *) phe->h_addr_list[0]); - } -#ifdef HAVE_GETHOSTBYNAME_R - free(buf); -#endif - return ntohl(addr); -} - -int GeoIP_id_by_name (GeoIP* gi, const char *name) { - unsigned long ipnum; - int ret; - if (name == NULL) { - return 0; - } - if (gi->databaseType != GEOIP_COUNTRY_EDITION && gi->databaseType != GEOIP_PROXY_EDITION && gi->databaseType != GEOIP_NETSPEED_EDITION) { - printf("Invalid database type %s, expected %s\n", GeoIPDBDescription[(int)gi->databaseType], GeoIPDBDescription[GEOIP_COUNTRY_EDITION]); - return 0; - } - if (!(ipnum = _GeoIP_lookupaddress(name))) - return 0; - ret = _GeoIP_seek_record(gi, ipnum) - COUNTRY_BEGIN; - return ret; - -} - -const char *GeoIP_country_code_by_addr (GeoIP* gi, const char *addr) { - int country_id; - country_id = GeoIP_id_by_addr(gi, addr); - return (country_id > 0) ? GeoIP_country_code[country_id] : NULL; -} - -const char *GeoIP_country_code3_by_addr (GeoIP* gi, const char *addr) { - int country_id; - country_id = GeoIP_id_by_addr(gi, addr); - return (country_id > 0) ? GeoIP_country_code3[country_id] : NULL; - return GeoIP_country_code3[country_id]; -} - -const char *GeoIP_country_name_by_addr (GeoIP* gi, const char *addr) { - int country_id; - country_id = GeoIP_id_by_addr(gi, addr); - return (country_id > 0) ? GeoIP_country_name[country_id] : NULL; - return GeoIP_country_name[country_id]; -} - -const char *GeoIP_country_name_by_ipnum (GeoIP* gi, unsigned long ipnum) { - int country_id; - country_id = GeoIP_id_by_ipnum(gi, ipnum); - return (country_id > 0) ? GeoIP_country_name[country_id] : NULL; -} - -const char *GeoIP_country_code_by_ipnum (GeoIP* gi, unsigned long ipnum) { - int country_id; - country_id = GeoIP_id_by_ipnum(gi, ipnum); - return (country_id > 0) ? GeoIP_country_code[country_id] : NULL; -} - -const char *GeoIP_country_code3_by_ipnum (GeoIP* gi, unsigned long ipnum) { - int country_id; - country_id = GeoIP_id_by_ipnum(gi, ipnum); - return (country_id > 0) ? GeoIP_country_code3[country_id] : NULL; -} - -int GeoIP_country_id_by_addr (GeoIP* gi, const char *addr) { - return GeoIP_id_by_addr(gi, addr); -} - -int GeoIP_country_id_by_name (GeoIP* gi, const char *host) { - return GeoIP_id_by_name(gi, host); -} - -int GeoIP_id_by_addr (GeoIP* gi, const char *addr) { - unsigned long ipnum; - int ret; - if (addr == NULL) { - return 0; - } - if (gi->databaseType != GEOIP_COUNTRY_EDITION && - gi->databaseType != GEOIP_PROXY_EDITION && - gi->databaseType != GEOIP_NETSPEED_EDITION) { - printf("Invalid database type %s, expected %s\n", - GeoIPDBDescription[(int)gi->databaseType], - GeoIPDBDescription[GEOIP_COUNTRY_EDITION]); - return 0; - } - ipnum = _GeoIP_addr_to_num(addr); - ret = _GeoIP_seek_record(gi, ipnum) - COUNTRY_BEGIN; - return ret; -} - -int GeoIP_id_by_ipnum (GeoIP* gi, unsigned long ipnum) { - int ret; - if (ipnum == 0) { - return 0; - } - if (gi->databaseType != GEOIP_COUNTRY_EDITION && - gi->databaseType != GEOIP_PROXY_EDITION && - gi->databaseType != GEOIP_NETSPEED_EDITION) { - printf("Invalid database type %s, expected %s\n", - GeoIPDBDescription[(int)gi->databaseType], - GeoIPDBDescription[GEOIP_COUNTRY_EDITION]); - return 0; - } - ret = _GeoIP_seek_record(gi, ipnum) - COUNTRY_BEGIN; - return ret; -} - -char *GeoIP_database_info (GeoIP* gi) { - int i; - unsigned char buf[3]; - char *retval; - int hasStructureInfo = 0; - - if(gi == NULL) - return NULL; - - _check_mtime(gi); - fseek(gi->GeoIPDatabase, -3l, SEEK_END); - - /* first get past the database structure information */ - for (i = 0; i < STRUCTURE_INFO_MAX_SIZE; i++) { - fread(buf, 1, 3, gi->GeoIPDatabase); - if (buf[0] == 255 && buf[1] == 255 && buf[2] == 255) { - hasStructureInfo = 1; - break; - } - fseek(gi->GeoIPDatabase, -4l, SEEK_CUR); - } - if (hasStructureInfo == 1) { - fseek(gi->GeoIPDatabase, -6l, SEEK_CUR); - } else { - /* no structure info, must be pre Sep 2002 database, go back to end */ - fseek(gi->GeoIPDatabase, -3l, SEEK_END); - } - - for (i = 0; i < DATABASE_INFO_MAX_SIZE; i++) { - fread(buf, 1, 3, gi->GeoIPDatabase); - if (buf[0] == 0 && buf[1] == 0 && buf[2] == 0) { - retval = (char*)malloc(sizeof(char) * (i+1)); - if (retval == NULL) { - return NULL; - } - fread(retval, 1, i, gi->GeoIPDatabase); - retval[i] = '\0'; - return retval; - } - fseek(gi->GeoIPDatabase, -4l, SEEK_CUR); - } - return NULL; -} - -/* GeoIP Region Edition functions */ - -void GeoIP_assign_region_by_inetaddr(GeoIP* gi, unsigned long inetaddr, GeoIPRegion *region) { - unsigned int seek_region; - - /* This also writes in the terminating NULs (if you decide to - * keep them) and clear any fields that are not set. */ - memset(region, 0, sizeof(GeoIPRegion)); - - seek_region = _GeoIP_seek_record(gi, ntohl(inetaddr)); - - if (gi->databaseType == GEOIP_REGION_EDITION_REV0) { - /* Region Edition, pre June 2003 */ - seek_region -= STATE_BEGIN_REV0; - if (seek_region >= 1000) { - region->country_code[0] = 'U'; - region->country_code[1] = 'S'; - region->region[0] = (char) ((seek_region - 1000)/26 + 65); - region->region[1] = (char) ((seek_region - 1000)%26 + 65); - } else { - memcpy(region->country_code, GeoIP_country_code[seek_region], 2); - } - } else if (gi->databaseType == GEOIP_REGION_EDITION_REV1) { - /* Region Edition, post June 2003 */ - seek_region -= STATE_BEGIN_REV1; - if (seek_region < US_OFFSET) { - /* Unknown */ - /* we don't need to do anything here b/c we memset region to 0 */ - } else if (seek_region < CANADA_OFFSET) { - /* USA State */ - region->country_code[0] = 'U'; - region->country_code[1] = 'S'; - region->region[0] = (char) ((seek_region - US_OFFSET)/26 + 65); - region->region[1] = (char) ((seek_region - US_OFFSET)%26 + 65); - } else if (seek_region < WORLD_OFFSET) { - /* Canada Province */ - region->country_code[0] = 'C'; - region->country_code[1] = 'A'; - region->region[0] = (char) ((seek_region - CANADA_OFFSET)/26 + 65); - region->region[1] = (char) ((seek_region - CANADA_OFFSET)%26 + 65); - } else { - /* Not US or Canada */ - memcpy(region->country_code, GeoIP_country_code[(seek_region - WORLD_OFFSET) / FIPS_RANGE], 2); - } - } -} - -static -GeoIPRegion * _get_region(GeoIP* gi, unsigned long ipnum) { - GeoIPRegion * region; - - region = (GeoIPRegion*)malloc(sizeof(GeoIPRegion)); - if (region) { - GeoIP_assign_region_by_inetaddr(gi, htonl(ipnum), region); - } - return region; -} - -GeoIPRegion * GeoIP_region_by_addr (GeoIP* gi, const char *addr) { - unsigned long ipnum; - if (addr == NULL) { - return 0; - } - if (gi->databaseType != GEOIP_REGION_EDITION_REV0 && - gi->databaseType != GEOIP_REGION_EDITION_REV1) { - printf("Invalid database type %s, expected %s\n", GeoIPDBDescription[(int)gi->databaseType], GeoIPDBDescription[GEOIP_REGION_EDITION_REV1]); - return 0; - } - ipnum = _GeoIP_addr_to_num(addr); - return _get_region(gi, ipnum); -} - -GeoIPRegion * GeoIP_region_by_name (GeoIP* gi, const char *name) { - unsigned long ipnum; - if (name == NULL) { - return 0; - } - if (gi->databaseType != GEOIP_REGION_EDITION_REV0 && - gi->databaseType != GEOIP_REGION_EDITION_REV1) { - printf("Invalid database type %s, expected %s\n", GeoIPDBDescription[(int)gi->databaseType], GeoIPDBDescription[GEOIP_REGION_EDITION_REV1]); - return 0; - } - if (!(ipnum = _GeoIP_lookupaddress(name))) - return 0; - return _get_region(gi, ipnum); -} - -GeoIPRegion * GeoIP_region_by_ipnum (GeoIP* gi, unsigned long ipnum) { - if (gi->databaseType != GEOIP_REGION_EDITION_REV0 && - gi->databaseType != GEOIP_REGION_EDITION_REV1) { - printf("Invalid database type %s, expected %s\n", GeoIPDBDescription[(int)gi->databaseType], GeoIPDBDescription[GEOIP_REGION_EDITION_REV1]); - return 0; - } - return _get_region(gi, ipnum); -} - -void GeoIPRegion_delete (GeoIPRegion *gir) { - free(gir); -} - -/* GeoIP Organization, ISP and AS Number Edition private method */ -static -char *_get_name (GeoIP* gi, unsigned long ipnum) { - int seek_org; - char buf[MAX_ORG_RECORD_LENGTH]; - char * org_buf, * buf_pointer; - int record_pointer; - size_t len; - - if (gi->databaseType != GEOIP_ORG_EDITION && - gi->databaseType != GEOIP_ISP_EDITION && - gi->databaseType != GEOIP_ASNUM_EDITION) { - printf("Invalid database type %s, expected %s\n", GeoIPDBDescription[(int)gi->databaseType], GeoIPDBDescription[GEOIP_ORG_EDITION]); - return 0; - } - - seek_org = _GeoIP_seek_record(gi, ipnum); - if (seek_org == gi->databaseSegments[0]) - return NULL; - - record_pointer = seek_org + (2 * gi->record_length - 1) * gi->databaseSegments[0]; - - if (gi->cache == NULL) { - fseek(gi->GeoIPDatabase, record_pointer, SEEK_SET); - fread(buf, sizeof(char), MAX_ORG_RECORD_LENGTH, gi->GeoIPDatabase); - len = sizeof(char) * (strlen(buf)+1); - org_buf = (char*)malloc(len); - strncpy(org_buf, buf, len); - } else { - buf_pointer = (char*)(gi->cache + (long)record_pointer); - len = sizeof(char) * (strlen(buf_pointer)+1); - org_buf = (char*)malloc(len); - strncpy(org_buf, buf_pointer, len); - } - return org_buf; -} - -char *GeoIP_name_by_ipnum (GeoIP* gi, unsigned long ipnum) { - return _get_name(gi,ipnum); -} - -char *GeoIP_name_by_addr (GeoIP* gi, const char *addr) { - unsigned long ipnum; - if (addr == NULL) { - return 0; - } - ipnum = _GeoIP_addr_to_num(addr); - return _get_name(gi, ipnum); -} - -char *GeoIP_name_by_name (GeoIP* gi, const char *name) { - unsigned long ipnum; - if (name == NULL) { - return 0; - } - if (!(ipnum = _GeoIP_lookupaddress(name))) - return 0; - return _get_name(gi, ipnum); -} - -char *GeoIP_org_by_ipnum (GeoIP* gi, unsigned long ipnum) { - return GeoIP_name_by_ipnum(gi, ipnum); -} - -char *GeoIP_org_by_addr (GeoIP* gi, const char *addr) { - return GeoIP_name_by_addr(gi, addr); -} - -char *GeoIP_org_by_name (GeoIP* gi, const char *name) { - return GeoIP_name_by_name(gi, name); -} - -unsigned char GeoIP_database_edition (GeoIP* gi) { - return gi->databaseType; -} - -int GeoIP_charset( GeoIP* gi){ - return gi->charset; -} - -int GeoIP_set_charset( GeoIP* gi, int charset ){ - int old_charset = gi->charset; - gi->charset = charset; - return old_charset; -} - -int GeoIP_last_netmask (GeoIP* gi) { - return gi->netmask; -} - diff --git a/libtorrent/src/alert.cpp b/libtorrent/src/alert.cpp deleted file mode 100755 index 14c5c4e5c..000000000 --- a/libtorrent/src/alert.cpp +++ /dev/null @@ -1,119 +0,0 @@ -/* - -Copyright (c) 2003, Arvid Norberg, Daniel Wallin -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions -are met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in - the documentation and/or other materials provided with the distribution. - * Neither the name of the author nor the names of its - contributors may be used to endorse or promote products derived - from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -POSSIBILITY OF SUCH DAMAGE. - -*/ - -#include "libtorrent/pch.hpp" - -#include "libtorrent/alert.hpp" -#include - -namespace libtorrent { - - alert::alert() : m_timestamp(time_now()) {} - alert::~alert() {} - ptime alert::timestamp() const { return m_timestamp; } - - alert_manager::alert_manager() - : m_alert_mask(alert::error_notification) - , m_queue_size_limit(queue_size_limit_default) - {} - - alert_manager::~alert_manager() - { - while (!m_alerts.empty()) - { - delete m_alerts.front(); - m_alerts.pop(); - } - } - - alert const* alert_manager::wait_for_alert(time_duration max_wait) - { - boost::mutex::scoped_lock lock(m_mutex); - - if (!m_alerts.empty()) return m_alerts.front(); - - int secs = total_seconds(max_wait); - max_wait -= seconds(secs); - boost::xtime xt; - boost::xtime_get(&xt, boost::TIME_UTC); - xt.sec += secs; - boost::int64_t nsec = xt.nsec + total_microseconds(max_wait) * 1000; - if (nsec > 1000000000) - { - nsec -= 1000000000; - xt.sec += 1; - } - xt.nsec = boost::xtime::xtime_nsec_t(nsec); - // apparently this call can be interrupted - // prematurely if there are other signals - if (!m_condition.timed_wait(lock, xt)) return 0; - if (m_alerts.empty()) return 0; - return m_alerts.front(); - } - - void alert_manager::post_alert(const alert& alert_) - { - boost::mutex::scoped_lock lock(m_mutex); - - if (m_alerts.size() >= m_queue_size_limit) return; - m_alerts.push(alert_.clone().release()); - m_condition.notify_all(); - } - - std::auto_ptr alert_manager::get() - { - boost::mutex::scoped_lock lock(m_mutex); - - TORRENT_ASSERT(!m_alerts.empty()); - - alert* result = m_alerts.front(); - m_alerts.pop(); - return std::auto_ptr(result); - } - - bool alert_manager::pending() const - { - boost::mutex::scoped_lock lock(m_mutex); - - return !m_alerts.empty(); - } - - size_t alert_manager::set_alert_queue_size_limit(size_t queue_size_limit_) - { - boost::mutex::scoped_lock lock(m_mutex); - - std::swap(m_queue_size_limit, queue_size_limit_); - return queue_size_limit_; - } - -} // namespace libtorrent - diff --git a/libtorrent/src/assert.cpp b/libtorrent/src/assert.cpp deleted file mode 100644 index b98201d95..000000000 --- a/libtorrent/src/assert.cpp +++ /dev/null @@ -1,141 +0,0 @@ -/* - -Copyright (c) 2007, Arvid Norberg -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions -are met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in - the documentation and/or other materials provided with the distribution. - * Neither the name of the author nor the names of its - contributors may be used to endorse or promote products derived - from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -POSSIBILITY OF SUCH DAMAGE. - -*/ - -#ifdef TORRENT_DEBUG - -#ifdef __APPLE__ -#include -#endif - -#ifdef __GNUC__ - -#include -#include -#include -#include - -std::string demangle(char const* name) -{ -// in case this string comes - // this is needed on linux - char const* start = strchr(name, '('); - if (start != 0) - { - ++start; - } - else - { - // this is needed on macos x - start = strstr(name, "0x"); - if (start != 0) - { - start = strchr(start, ' '); - if (start != 0) ++start; - else start = name; - } - else start = name; - } - - char const* end = strchr(start, '+'); - if (end) while (*(end-1) == ' ') --end; - - std::string in; - if (end == 0) in.assign(start); - else in.assign(start, end); - - size_t len; - int status; - char* unmangled = ::abi::__cxa_demangle(in.c_str(), 0, &len, &status); - if (unmangled == 0) return in; - std::string ret(unmangled); - free(unmangled); - return ret; -} - -#endif - -#include -#include -#include -#include "libtorrent/version.hpp" - -// execinfo.h is available in the MacOS X 10.5 SDK. -#if (defined __linux__ || (defined __APPLE__ && MAC_OS_X_VERSION_MIN_REQUIRED >= 1050)) -#include - -void print_backtrace(char const* label) -{ - void* stack[50]; - int size = backtrace(stack, 50); - char** symbols = backtrace_symbols(stack, size); - - fprintf(stderr, "%s\n", label); - for (int i = 1; i < size; ++i) - { - fprintf(stderr, "%d: %s\n", i, demangle(symbols[i]).c_str()); - } - - free(symbols); -} -#else - -void print_backtrace(char const* label) {} - -#endif - -void assert_fail(char const* expr, int line, char const* file, char const* function) -{ - - fprintf(stderr, "assertion failed. Please file a bugreport at " - "http://code.rasterbar.com/libtorrent/newticket\n" - "Please include the following information:\n\n" - "version: " LIBTORRENT_VERSION "\n" - "%s\n" - "file: '%s'\n" - "line: %d\n" - "function: %s\n" - "expression: %s\n", LIBTORRENT_REVISION, file, line, function, expr); - - print_backtrace("stack:"); - - // send SIGINT to the current process - // to break into the debugger - raise(SIGINT); - abort(); -} - -#else - -void assert_fail(char const* expr, int line, char const* file, char const* function) {} - -#endif - diff --git a/libtorrent/src/broadcast_socket.cpp b/libtorrent/src/broadcast_socket.cpp deleted file mode 100644 index 5e3372ee5..000000000 --- a/libtorrent/src/broadcast_socket.cpp +++ /dev/null @@ -1,266 +0,0 @@ -/* - -Copyright (c) 2007, Arvid Norberg -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions -are met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in - the documentation and/or other materials provided with the distribution. - * Neither the name of the author nor the names of its - contributors may be used to endorse or promote products derived - from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -POSSIBILITY OF SUCH DAMAGE. - -*/ - -#include - -#if BOOST_VERSION < 103500 -#include -#include -#else -#include -#include -#endif - -#include - -#include "libtorrent/socket.hpp" -#include "libtorrent/enum_net.hpp" -#include "libtorrent/broadcast_socket.hpp" -#include "libtorrent/assert.hpp" - -namespace libtorrent -{ - bool is_local(address const& a) - { - if (a.is_v6()) return a.to_v6().is_link_local(); - address_v4 a4 = a.to_v4(); - unsigned long ip = a4.to_ulong(); - return ((ip & 0xff000000) == 0x0a000000 - || (ip & 0xfff00000) == 0xac100000 - || (ip & 0xffff0000) == 0xc0a80000); - } - - bool is_loopback(address const& addr) - { - if (addr.is_v4()) - return addr.to_v4() == address_v4::loopback(); - else - return addr.to_v6() == address_v6::loopback(); - } - - bool is_multicast(address const& addr) - { - if (addr.is_v4()) - return addr.to_v4().is_multicast(); - else - return addr.to_v6().is_multicast(); - } - - bool is_any(address const& addr) - { - if (addr.is_v4()) - return addr.to_v4() == address_v4::any(); - else if (addr.to_v6().is_v4_mapped()) - return (addr.to_v6().to_v4() == address_v4::any()); - else - return addr.to_v6() == address_v6::any(); - } - - address guess_local_address(io_service& ios) - { - // make a best guess of the interface we're using and its IP - error_code ec; - std::vector const& interfaces = enum_net_interfaces(ios, ec); - address ret = address_v4::any(); - for (std::vector::const_iterator i = interfaces.begin() - , end(interfaces.end()); i != end; ++i) - { - address const& a = i->interface_address; - if (is_loopback(a) - || is_multicast(a) - || is_any(a)) continue; - - // prefer a v4 address, but return a v6 if - // there are no v4 - if (a.is_v4()) return a; - - if (ret != address_v4::any()) - ret = a; - } - return ret; - } - - // count the length of the common bit prefix - int common_bits(unsigned char const* b1 - , unsigned char const* b2, int n) - { - for (int i = 0; i < n; ++i, ++b1, ++b2) - { - unsigned char a = *b1 ^ *b2; - if (a == 0) continue; - int ret = i * 8 + 8; - for (; a > 0; a >>= 1) --ret; - return ret; - } - return n * 8; - } - - // returns the number of bits in that differ from the right - // between the addresses. - int cidr_distance(address const& a1, address const& a2) - { - if (a1.is_v4() == a2.is_v4()) - { - // both are v4 - address_v4::bytes_type b1 = a1.to_v4().to_bytes(); - address_v4::bytes_type b2 = a2.to_v4().to_bytes(); - return address_v4::bytes_type::static_size * 8 - - common_bits(b1.c_array(), b2.c_array(), b1.size()); - } - - address_v6::bytes_type b1; - address_v6::bytes_type b2; - if (a1.is_v4()) b1 = address_v6::v4_mapped(a1.to_v4()).to_bytes(); - else b1 = a1.to_v6().to_bytes(); - if (a2.is_v4()) b2 = address_v6::v4_mapped(a2.to_v4()).to_bytes(); - else b2 = a2.to_v6().to_bytes(); - return address_v6::bytes_type::static_size * 8 - - common_bits(b1.c_array(), b2.c_array(), b1.size()); - } - - broadcast_socket::broadcast_socket(io_service& ios - , udp::endpoint const& multicast_endpoint - , receive_handler_t const& handler - , bool loopback) - : m_multicast_endpoint(multicast_endpoint) - , m_on_receive(handler) - { - TORRENT_ASSERT(is_multicast(m_multicast_endpoint.address())); - - using namespace asio::ip::multicast; - - error_code ec; - std::vector interfaces = enum_net_interfaces(ios, ec); - - if (multicast_endpoint.address().is_v4()) - open_multicast_socket(ios, address_v4::any(), loopback); - else - open_multicast_socket(ios, address_v6::any(), loopback); - - for (std::vector::const_iterator i = interfaces.begin() - , end(interfaces.end()); i != end; ++i) - { - // only multicast on compatible networks - if (i->interface_address.is_v4() != multicast_endpoint.address().is_v4()) continue; - // ignore any loopback interface - if (is_loopback(i->interface_address)) continue; - -#ifndef NDEBUG -// std::cerr << "broadcast socket [ if: " << i->interface_address.to_v4().to_string() -// << " group: " << multicast_endpoint.address() << " ]" << std::endl; -#endif - open_unicast_socket(ios, i->interface_address); - } - } - - void broadcast_socket::open_multicast_socket(io_service& ios - , address const& addr, bool loopback) - { - using namespace asio::ip::multicast; - - error_code ec; - boost::shared_ptr s(new datagram_socket(ios)); - if (addr.is_v4()) - s->open(udp::v4(), ec); - else - s->open(udp::v6(), ec); - if (ec) return; - s->set_option(datagram_socket::reuse_address(true), ec); - if (ec) return; - s->bind(udp::endpoint(addr, m_multicast_endpoint.port()), ec); - if (ec) return; - s->set_option(join_group(m_multicast_endpoint.address()), ec); - if (ec) return; - s->set_option(hops(255), ec); - if (ec) return; - s->set_option(enable_loopback(loopback), ec); - if (ec) return; - m_sockets.push_back(socket_entry(s)); - socket_entry& se = m_sockets.back(); - s->async_receive_from(asio::buffer(se.buffer, sizeof(se.buffer)) - , se.remote, bind(&broadcast_socket::on_receive, this, &se, _1, _2)); - } - - void broadcast_socket::open_unicast_socket(io_service& ios, address const& addr) - { - using namespace asio::ip::multicast; - error_code ec; - boost::shared_ptr s(new datagram_socket(ios)); - s->open(addr.is_v4() ? udp::v4() : udp::v6(), ec); - if (ec) return; - s->bind(udp::endpoint(addr, 0), ec); - if (ec) return; - m_unicast_sockets.push_back(socket_entry(s)); - socket_entry& se = m_unicast_sockets.back(); - s->async_receive_from(asio::buffer(se.buffer, sizeof(se.buffer)) - , se.remote, bind(&broadcast_socket::on_receive, this, &se, _1, _2)); - } - - void broadcast_socket::send(char const* buffer, int size, error_code& ec) - { - for (std::list::iterator i = m_unicast_sockets.begin() - , end(m_unicast_sockets.end()); i != end; ++i) - { - if (!i->socket) continue; - error_code e; - i->socket->send_to(asio::buffer(buffer, size), m_multicast_endpoint, 0, e); -#ifndef NDEBUG -// std::cerr << " sending on " << i->socket->local_endpoint().address().to_string() << " to: " << m_multicast_endpoint << std::endl; -#endif - if (e) - { - i->socket->close(e); - i->socket.reset(); - } - } - } - - void broadcast_socket::on_receive(socket_entry* s, error_code const& ec - , std::size_t bytes_transferred) - { - if (ec || bytes_transferred == 0 || !m_on_receive) return; - m_on_receive(s->remote, s->buffer, bytes_transferred); - if (!s->socket) return; - s->socket->async_receive_from(asio::buffer(s->buffer, sizeof(s->buffer)) - , s->remote, bind(&broadcast_socket::on_receive, this, s, _1, _2)); - } - - void broadcast_socket::close() - { - std::for_each(m_sockets.begin(), m_sockets.end(), bind(&socket_entry::close, _1)); - std::for_each(m_unicast_sockets.begin(), m_unicast_sockets.end(), bind(&socket_entry::close, _1)); - - m_on_receive.clear(); - } -} - - diff --git a/libtorrent/src/bt_peer_connection.cpp b/libtorrent/src/bt_peer_connection.cpp deleted file mode 100755 index 6e668fbf0..000000000 --- a/libtorrent/src/bt_peer_connection.cpp +++ /dev/null @@ -1,2735 +0,0 @@ -/* - -Copyright (c) 2003 - 2006, Arvid Norberg -Copyright (c) 2007, Arvid Norberg, Un Shyam -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions -are met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in - the documentation and/or other materials provided with the distribution. - * Neither the name of the author nor the names of its - contributors may be used to endorse or promote products derived - from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -POSSIBILITY OF SUCH DAMAGE. - -*/ - -#include "libtorrent/pch.hpp" - -#include -#include -#include -#include -#include - -#include "libtorrent/bt_peer_connection.hpp" -#include "libtorrent/session.hpp" -#include "libtorrent/identify_client.hpp" -#include "libtorrent/entry.hpp" -#include "libtorrent/bencode.hpp" -#include "libtorrent/alert_types.hpp" -#include "libtorrent/invariant_check.hpp" -#include "libtorrent/io.hpp" -#include "libtorrent/version.hpp" -#include "libtorrent/extensions.hpp" -#include "libtorrent/aux_/session_impl.hpp" -#include "libtorrent/broadcast_socket.hpp" - -#ifndef TORRENT_DISABLE_ENCRYPTION -#include "libtorrent/pe_crypto.hpp" -#include "libtorrent/hasher.hpp" -#endif - -using boost::bind; -using boost::shared_ptr; -using libtorrent::aux::session_impl; - -namespace libtorrent -{ - const bt_peer_connection::message_handler - bt_peer_connection::m_message_handler[] = - { - &bt_peer_connection::on_choke, - &bt_peer_connection::on_unchoke, - &bt_peer_connection::on_interested, - &bt_peer_connection::on_not_interested, - &bt_peer_connection::on_have, - &bt_peer_connection::on_bitfield, - &bt_peer_connection::on_request, - &bt_peer_connection::on_piece, - &bt_peer_connection::on_cancel, - &bt_peer_connection::on_dht_port, - 0, 0, 0, - // FAST extension messages - &bt_peer_connection::on_suggest_piece, - &bt_peer_connection::on_have_all, - &bt_peer_connection::on_have_none, - &bt_peer_connection::on_reject_request, - &bt_peer_connection::on_allowed_fast, - 0, 0, - &bt_peer_connection::on_extended - }; - - - bt_peer_connection::bt_peer_connection( - session_impl& ses - , boost::weak_ptr tor - , shared_ptr s - , tcp::endpoint const& remote - , policy::peer* peerinfo) - : peer_connection(ses, tor, s, remote - , peerinfo) - , m_state(read_protocol_identifier) -#ifndef TORRENT_DISABLE_EXTENSIONS - , m_supports_extensions(false) -#endif - , m_supports_dht_port(false) - , m_supports_fast(false) -#ifndef TORRENT_DISABLE_ENCRYPTION - , m_encrypted(false) - , m_rc4_encrypted(false) - , m_sync_bytes_read(0) - , m_enc_send_buffer(0, 0) -#endif -#ifdef TORRENT_DEBUG - , m_sent_bitfield(false) - , m_in_constructor(true) - , m_sent_handshake(false) -#endif - { -#ifdef TORRENT_VERBOSE_LOGGING - (*m_logger) << "*** bt_peer_connection\n"; -#endif - -#ifdef TORRENT_DEBUG - m_in_constructor = false; - m_encrypted_bytes = 0; -#endif - } - - bt_peer_connection::bt_peer_connection( - session_impl& ses - , boost::shared_ptr s - , tcp::endpoint const& remote - , policy::peer* peerinfo) - : peer_connection(ses, s, remote, peerinfo) - , m_state(read_protocol_identifier) -#ifndef TORRENT_DISABLE_EXTENSIONS - , m_supports_extensions(false) -#endif - , m_supports_dht_port(false) - , m_supports_fast(false) -#ifndef TORRENT_DISABLE_ENCRYPTION - , m_encrypted(false) - , m_rc4_encrypted(false) - , m_sync_bytes_read(0) - , m_enc_send_buffer(0, 0) -#endif -#ifdef TORRENT_DEBUG - , m_sent_bitfield(false) - , m_in_constructor(true) - , m_sent_handshake(false) -#endif - { - - // we are not attached to any torrent yet. - // we have to wait for the handshake to see - // which torrent the connector want's to connect to - - - // upload bandwidth will only be given to connections - // that are part of a torrent. Since this is an incoming - // connection, we have to give it some initial bandwidth - // to send the handshake. -#ifndef TORRENT_DISABLE_ENCRYPTION - m_bandwidth_limit[download_channel].assign(2048); - m_bandwidth_limit[upload_channel].assign(2048); -#else - m_bandwidth_limit[download_channel].assign(80); - m_bandwidth_limit[upload_channel].assign(80); -#endif - -#ifdef TORRENT_DEBUG - m_in_constructor = false; - m_encrypted_bytes = 0; -#endif - } - - void bt_peer_connection::start() - { - peer_connection::start(); - - // start in the state where we are trying to read the - // handshake from the other side - reset_recv_buffer(20); - setup_receive(); - } - - bt_peer_connection::~bt_peer_connection() - { - } - - void bt_peer_connection::on_connected() - { -#ifndef TORRENT_DISABLE_ENCRYPTION - - pe_settings::enc_policy const& out_enc_policy = m_ses.get_pe_settings().out_enc_policy; - - if (out_enc_policy == pe_settings::forced) - { - write_pe1_2_dhkey(); - if (is_disconnecting()) return; - - m_state = read_pe_dhkey; - reset_recv_buffer(dh_key_len); - setup_receive(); - } - else if (out_enc_policy == pe_settings::enabled) - { - TORRENT_ASSERT(peer_info_struct()); - - policy::peer* pi = peer_info_struct(); - if (pi->pe_support == true) - { - // toggle encryption support flag, toggled back to - // true if encrypted portion of the handshake - // completes correctly - pi->pe_support = false; - - // if this fails, we need to reconnect - // fast. - fast_reconnect(true); - - write_pe1_2_dhkey(); - if (is_disconnecting()) return; - m_state = read_pe_dhkey; - reset_recv_buffer(dh_key_len); - setup_receive(); - } - else // pi->pe_support == false - { - // toggled back to false if standard handshake - // completes correctly (without encryption) - pi->pe_support = true; - - write_handshake(); - reset_recv_buffer(20); - setup_receive(); - } - } - else if (out_enc_policy == pe_settings::disabled) -#endif - { - write_handshake(); - - // start in the state where we are trying to read the - // handshake from the other side - reset_recv_buffer(20); - setup_receive(); - } - } - - void bt_peer_connection::on_metadata() - { - // connections that are still in the handshake - // will send their bitfield when the handshake - // is done - if (m_state < read_packet_size) return; - boost::shared_ptr t = associated_torrent().lock(); - TORRENT_ASSERT(t); - write_bitfield(); -#ifndef TORRENT_DISABLE_DHT - if (m_supports_dht_port && m_ses.m_dht) - write_dht_port(m_ses.get_dht_settings().service_port); -#endif - } - - void bt_peer_connection::write_dht_port(int listen_port) - { - INVARIANT_CHECK; - - TORRENT_ASSERT(m_sent_handshake && m_sent_bitfield); - -#ifdef TORRENT_VERBOSE_LOGGING - (*m_logger) << time_now_string() - << " ==> DHT_PORT [ " << listen_port << " ]\n"; -#endif - char msg[] = {0,0,0,3, msg_dht_port, 0, 0}; - char* ptr = msg + 5; - detail::write_uint16(listen_port, ptr); - send_buffer(msg, sizeof(msg)); - } - - void bt_peer_connection::write_have_all() - { - INVARIANT_CHECK; - TORRENT_ASSERT(m_sent_handshake && !m_sent_bitfield); -#ifdef TORRENT_DEBUG - m_sent_bitfield = true; -#endif -#ifdef TORRENT_VERBOSE_LOGGING - (*m_logger) << time_now_string() - << " ==> HAVE_ALL\n"; -#endif - char msg[] = {0,0,0,1, msg_have_all}; - send_buffer(msg, sizeof(msg)); - } - - void bt_peer_connection::write_have_none() - { - INVARIANT_CHECK; - TORRENT_ASSERT(m_sent_handshake && !m_sent_bitfield); -#ifdef TORRENT_DEBUG - m_sent_bitfield = true; -#endif -#ifdef TORRENT_VERBOSE_LOGGING - (*m_logger) << time_now_string() - << " ==> HAVE_NONE\n"; -#endif - char msg[] = {0,0,0,1, msg_have_none}; - send_buffer(msg, sizeof(msg)); - } - - void bt_peer_connection::write_reject_request(peer_request const& r) - { - INVARIANT_CHECK; - - if (!m_supports_fast) return; - - TORRENT_ASSERT(m_sent_handshake && m_sent_bitfield); - TORRENT_ASSERT(associated_torrent().lock()->valid_metadata()); - - char msg[] = {0,0,0,13, msg_reject_request,0,0,0,0, 0,0,0,0, 0,0,0,0}; - char* ptr = msg + 5; - detail::write_int32(r.piece, ptr); // index - detail::write_int32(r.start, ptr); // begin - detail::write_int32(r.length, ptr); // length - send_buffer(msg, sizeof(msg)); - } - - void bt_peer_connection::write_allow_fast(int piece) - { - INVARIANT_CHECK; - - TORRENT_ASSERT(m_sent_handshake && m_sent_bitfield); - TORRENT_ASSERT(associated_torrent().lock()->valid_metadata()); - TORRENT_ASSERT(m_supports_fast); - - char msg[] = {0,0,0,5, msg_allowed_fast, 0, 0, 0, 0}; - char* ptr = msg + 5; - detail::write_int32(piece, ptr); - send_buffer(msg, sizeof(msg)); - } - - void bt_peer_connection::get_specific_peer_info(peer_info& p) const - { - TORRENT_ASSERT(!associated_torrent().expired()); - - if (is_interesting()) p.flags |= peer_info::interesting; - if (is_choked()) p.flags |= peer_info::choked; - if (is_peer_interested()) p.flags |= peer_info::remote_interested; - if (has_peer_choked()) p.flags |= peer_info::remote_choked; - if (support_extensions()) p.flags |= peer_info::supports_extensions; - if (is_local()) p.flags |= peer_info::local_connection; - -#ifndef TORRENT_DISABLE_ENCRYPTION - if (m_encrypted) - { - m_rc4_encrypted ? - p.flags |= peer_info::rc4_encrypted : - p.flags |= peer_info::plaintext_encrypted; - } -#endif - - if (!is_connecting() && in_handshake()) - p.flags |= peer_info::handshake; - if (is_connecting() && !is_queued()) p.flags |= peer_info::connecting; - if (is_queued()) p.flags |= peer_info::queued; - - p.client = m_client_version; - p.connection_type = peer_info::standard_bittorrent; - - } - - bool bt_peer_connection::in_handshake() const - { - return m_state < read_packet_size; - } - -#ifndef TORRENT_DISABLE_ENCRYPTION - - void bt_peer_connection::write_pe1_2_dhkey() - { - INVARIANT_CHECK; - - TORRENT_ASSERT(!m_encrypted); - TORRENT_ASSERT(!m_rc4_encrypted); - TORRENT_ASSERT(!m_dh_key_exchange.get()); - TORRENT_ASSERT(!m_sent_handshake); - -#ifdef TORRENT_VERBOSE_LOGGING - if (is_local()) - (*m_logger) << " initiating encrypted handshake\n"; -#endif - - m_dh_key_exchange.reset(new (std::nothrow) dh_key_exchange); - if (!m_dh_key_exchange || !m_dh_key_exchange->good()) - { - disconnect("out of memory"); - return; - } - - int pad_size = std::rand() % 512; - -#ifdef TORRENT_VERBOSE_LOGGING - (*m_logger) << " pad size: " << pad_size << "\n"; -#endif - - buffer::interval send_buf = allocate_send_buffer(dh_key_len + pad_size); - if (send_buf.begin == 0) - { - disconnect("out of memory"); - return; - } - - std::copy(m_dh_key_exchange->get_local_key(), - m_dh_key_exchange->get_local_key() + dh_key_len, - send_buf.begin); - - std::generate(send_buf.begin + dh_key_len, send_buf.end, std::rand); -#ifdef TORRENT_DEBUG - m_encrypted_bytes += send_buf.left(); - TORRENT_ASSERT(m_encrypted_bytes <= send_buffer_size()); -#endif - setup_send(); - -#ifdef TORRENT_VERBOSE_LOGGING - (*m_logger) << " sent DH key\n"; -#endif - } - - void bt_peer_connection::write_pe3_sync() - { - INVARIANT_CHECK; - - TORRENT_ASSERT(!m_encrypted); - TORRENT_ASSERT(!m_rc4_encrypted); - TORRENT_ASSERT(is_local()); - TORRENT_ASSERT(!m_sent_handshake); - - boost::shared_ptr t = associated_torrent().lock(); - TORRENT_ASSERT(t); - - hasher h; - sha1_hash const& info_hash = t->torrent_file().info_hash(); - char const* const secret = m_dh_key_exchange->get_secret(); - - int pad_size = rand() % 512; - - TORRENT_ASSERT(send_buffer_size() == m_encrypted_bytes); - - // synchash,skeyhash,vc,crypto_provide,len(pad),pad,len(ia) - buffer::interval send_buf = - allocate_send_buffer(20 + 20 + 8 + 4 + 2 + pad_size + 2); - if (send_buf.begin == 0) return; // out of memory - - // sync hash (hash('req1',S)) - h.reset(); - h.update("req1",4); - h.update(secret, dh_key_len); - sha1_hash sync_hash = h.final(); - - std::copy(sync_hash.begin(), sync_hash.end(), send_buf.begin); - send_buf.begin += 20; - - // stream key obfuscated hash [ hash('req2',SKEY) xor hash('req3',S) ] - h.reset(); - h.update("req2",4); - h.update((const char*)info_hash.begin(), 20); - sha1_hash streamkey_hash = h.final(); - - h.reset(); - h.update("req3",4); - h.update(secret, dh_key_len); - sha1_hash obfsc_hash = h.final(); - obfsc_hash ^= streamkey_hash; - - std::copy(obfsc_hash.begin(), obfsc_hash.end(), send_buf.begin); - send_buf.begin += 20; - - // Discard DH key exchange data, setup RC4 keys - init_pe_RC4_handler(secret, info_hash); - m_dh_key_exchange.reset(); // secret should be invalid at this point - - // write the verification constant and crypto field - TORRENT_ASSERT(send_buf.left() == 8 + 4 + 2 + pad_size + 2); - int encrypt_size = send_buf.left(); - - int crypto_provide = 0; - pe_settings::enc_level const& allowed_enc_level = m_ses.get_pe_settings().allowed_enc_level; - - if (allowed_enc_level == pe_settings::both) - crypto_provide = 0x03; - else if (allowed_enc_level == pe_settings::rc4) - crypto_provide = 0x02; - else if (allowed_enc_level == pe_settings::plaintext) - crypto_provide = 0x01; - -#ifdef TORRENT_VERBOSE_LOGGING - (*m_logger) << " crypto provide : [ "; - if (allowed_enc_level == pe_settings::both) - (*m_logger) << "plaintext rc4 ]\n"; - else if (allowed_enc_level == pe_settings::rc4) - (*m_logger) << "rc4 ]\n"; - else if (allowed_enc_level == pe_settings::plaintext) - (*m_logger) << "plaintext ]\n"; -#endif - - write_pe_vc_cryptofield(send_buf, crypto_provide, pad_size); - m_RC4_handler->encrypt(send_buf.end - encrypt_size, encrypt_size); -#ifdef TORRENT_DEBUG - const int packet_size = 20 + 20 + 8 + 4 + 2 + pad_size + 2; - TORRENT_ASSERT(send_buffer_size() - packet_size == m_encrypted_bytes); - m_encrypted_bytes += packet_size; - TORRENT_ASSERT(m_encrypted_bytes == send_buffer_size()); -#endif - - TORRENT_ASSERT(send_buf.begin == send_buf.end); - setup_send(); - } - - void bt_peer_connection::write_pe4_sync(int crypto_select) - { - INVARIANT_CHECK; - - TORRENT_ASSERT(!is_local()); - TORRENT_ASSERT(!m_encrypted); - TORRENT_ASSERT(!m_rc4_encrypted); - TORRENT_ASSERT(crypto_select == 0x02 || crypto_select == 0x01); - TORRENT_ASSERT(!m_sent_handshake); - - int pad_size =rand() % 512; - - TORRENT_ASSERT(send_buffer_size() == m_encrypted_bytes); - - const int buf_size = 8 + 4 + 2 + pad_size; - buffer::interval send_buf = allocate_send_buffer(buf_size); - if (send_buf.begin == 0) return; // out of memory - write_pe_vc_cryptofield(send_buf, crypto_select, pad_size); - - m_RC4_handler->encrypt(send_buf.end - buf_size, buf_size); - TORRENT_ASSERT(send_buffer_size() - buf_size == m_encrypted_bytes); -#ifdef TORRENT_DEBUG - m_encrypted_bytes += buf_size; - TORRENT_ASSERT(m_encrypted_bytes <= send_buffer_size()); -#endif - setup_send(); - - // encryption method has been negotiated - if (crypto_select == 0x02) - m_rc4_encrypted = true; - else // 0x01 - m_rc4_encrypted = false; - -#ifdef TORRENT_VERBOSE_LOGGING - (*m_logger) << " crypto select : [ "; - if (crypto_select == 0x01) - (*m_logger) << "plaintext ]\n"; - else - (*m_logger) << "rc4 ]\n"; -#endif - } - - void bt_peer_connection::write_pe_vc_cryptofield(buffer::interval& write_buf - , int crypto_field, int pad_size) - { - INVARIANT_CHECK; - - TORRENT_ASSERT(crypto_field <= 0x03 && crypto_field > 0); - // vc,crypto_field,len(pad),pad, (len(ia)) - TORRENT_ASSERT( (write_buf.left() == 8+4+2+pad_size+2 && is_local()) || - (write_buf.left() == 8+4+2+pad_size && !is_local()) ); - TORRENT_ASSERT(!m_sent_handshake); - - // encrypt(vc, crypto_provide/select, len(Pad), len(IA)) - // len(pad) is zero for now, len(IA) only for outgoing connections - - // vc - std::fill(write_buf.begin, write_buf.begin + 8, 0); - write_buf.begin += 8; - - detail::write_uint32(crypto_field, write_buf.begin); - detail::write_uint16(pad_size, write_buf.begin); // len (pad) - - // fill pad with zeroes - std::generate(write_buf.begin, write_buf.begin + pad_size, &std::rand); - write_buf.begin += pad_size; - - // append len(ia) if we are initiating - if (is_local()) - detail::write_uint16(handshake_len, write_buf.begin); // len(IA) - - TORRENT_ASSERT(write_buf.begin == write_buf.end); - } - - void bt_peer_connection::init_pe_RC4_handler(char const* secret, sha1_hash const& stream_key) - { - INVARIANT_CHECK; - - TORRENT_ASSERT(secret); - - hasher h; - static const char keyA[] = "keyA"; - static const char keyB[] = "keyB"; - - // encryption rc4 longkeys - // outgoing connection : hash ('keyA',S,SKEY) - // incoming connection : hash ('keyB',S,SKEY) - - is_local() ? h.update(keyA, 4) : h.update(keyB, 4); - h.update(secret, dh_key_len); - h.update((char const*)stream_key.begin(), 20); - const sha1_hash local_key = h.final(); - - h.reset(); - - // decryption rc4 longkeys - // outgoing connection : hash ('keyB',S,SKEY) - // incoming connection : hash ('keyA',S,SKEY) - - is_local() ? h.update(keyB, 4) : h.update(keyA, 4); - h.update(secret, dh_key_len); - h.update((char const*)stream_key.begin(), 20); - const sha1_hash remote_key = h.final(); - - TORRENT_ASSERT(!m_RC4_handler.get()); - m_RC4_handler.reset(new RC4_handler (local_key, remote_key)); - -#ifdef TORRENT_VERBOSE_LOGGING - (*m_logger) << " computed RC4 keys\n"; -#endif - } - - void bt_peer_connection::send_buffer(char const* buf, int size, int flags) - { - TORRENT_ASSERT(buf); - TORRENT_ASSERT(size > 0); - - encrypt_pending_buffer(); - -#ifndef TORRENT_DISABLE_ENCRYPTION - if (m_encrypted && m_rc4_encrypted) - { - TORRENT_ASSERT(send_buffer_size() == m_encrypted_bytes); - m_RC4_handler->encrypt(const_cast(buf), size); -#ifdef TORRENT_DEBUG - m_encrypted_bytes += size; -#endif - } -#endif - - peer_connection::send_buffer(buf, size, flags); - } - - buffer::interval bt_peer_connection::allocate_send_buffer(int size) - { -#ifndef TORRENT_DISABLE_ENCRYPTION - encrypt_pending_buffer(); - if (m_encrypted && m_rc4_encrypted) - { - TORRENT_ASSERT(m_enc_send_buffer.left() == 0); - m_enc_send_buffer = peer_connection::allocate_send_buffer(size); - return m_enc_send_buffer; - } - else -#endif - { - buffer::interval i = peer_connection::allocate_send_buffer(size); - return i; - } - } - -#ifndef TORRENT_DISABLE_ENCRYPTION - void bt_peer_connection::encrypt_pending_buffer() - { - if (m_encrypted && m_rc4_encrypted && m_enc_send_buffer.left()) - { - TORRENT_ASSERT(m_enc_send_buffer.begin); - TORRENT_ASSERT(m_enc_send_buffer.end); - TORRENT_ASSERT(m_RC4_handler); - TORRENT_ASSERT(send_buffer_size() - m_enc_send_buffer.left() == m_encrypted_bytes); -#ifdef TORRENT_DEBUG - m_encrypted_bytes += m_enc_send_buffer.left(); - TORRENT_ASSERT(m_encrypted_bytes <= send_buffer_size()); -#endif - - m_RC4_handler->encrypt(m_enc_send_buffer.begin, m_enc_send_buffer.left()); - m_enc_send_buffer.end = m_enc_send_buffer.begin; - } - } -#endif - - void bt_peer_connection::setup_send() - { -#ifndef TORRENT_DISABLE_ENCRYPTION - encrypt_pending_buffer(); - TORRENT_ASSERT(!m_encrypted || !m_rc4_encrypted || m_encrypted_bytes == send_buffer_size()); -#endif - peer_connection::setup_send(); - } - - int bt_peer_connection::get_syncoffset(char const* src, int src_size, - char const* target, int target_size) const - { - TORRENT_ASSERT(target_size >= src_size); - TORRENT_ASSERT(src_size > 0); - TORRENT_ASSERT(src); - TORRENT_ASSERT(target); - - int traverse_limit = target_size - src_size; - - // TODO: this could be optimized using knuth morris pratt - for (int i = 0; i < traverse_limit; ++i) - { - char const* target_ptr = target + i; - if (std::equal(src, src+src_size, target_ptr)) - return i; - } - -// // Partial sync -// for (int i = 0; i < target_size; ++i) -// { -// // first is iterator in src[] at which mismatch occurs -// // second is iterator in target[] at which mismatch occurs -// std::pair ret; -// int src_sync_size; -// if (i > traverse_limit) // partial sync test -// { -// ret = std::mismatch(src, src + src_size - (i - traverse_limit), &target[i]); -// src_sync_size = ret.first - src; -// if (src_sync_size == (src_size - (i - traverse_limit))) -// return i; -// } -// else // complete sync test -// { -// ret = std::mismatch(src, src + src_size, &target[i]); -// src_sync_size = ret.first - src; -// if (src_sync_size == src_size) -// return i; -// } -// } - - // no complete sync - return -1; - } -#endif // #ifndef TORRENT_DISABLE_ENCRYPTION - - void bt_peer_connection::write_handshake() - { - INVARIANT_CHECK; - - TORRENT_ASSERT(!m_sent_handshake); -#ifdef TORRENT_DEBUG - m_sent_handshake = true; -#endif - - boost::shared_ptr t = associated_torrent().lock(); - TORRENT_ASSERT(t); - - // add handshake to the send buffer - const char version_string[] = "BitTorrent protocol"; - const int string_len = sizeof(version_string)-1; - - buffer::interval i = allocate_send_buffer(1 + string_len + 8 + 20 + 20); - if (i.begin == 0) return; // out of memory - // length of version string - *i.begin = string_len; - ++i.begin; - - // version string itself - std::copy( - version_string - , version_string + string_len - , i.begin); - i.begin += string_len; - - // 8 zeroes - std::fill(i.begin, i.begin + 8, 0); - -#ifndef TORRENT_DISABLE_DHT - // indicate that we support the DHT messages - *(i.begin + 7) |= 0x01; -#endif - -#ifndef TORRENT_DISABLE_EXTENSIONS - // we support extensions - *(i.begin + 5) |= 0x10; -#endif - - // we support FAST extension - *(i.begin + 7) |= 0x04; - - i.begin += 8; - - // info hash - sha1_hash const& ih = t->torrent_file().info_hash(); - std::copy(ih.begin(), ih.end(), i.begin); - i.begin += 20; - - // peer id - std::copy( - m_ses.get_peer_id().begin() - , m_ses.get_peer_id().end() - , i.begin); - i.begin += 20; - TORRENT_ASSERT(i.begin == i.end); - -#ifdef TORRENT_VERBOSE_LOGGING - (*m_logger) << time_now_string() << " ==> HANDSHAKE\n"; -#endif - setup_send(); - } - - boost::optional bt_peer_connection::downloading_piece_progress() const - { - boost::shared_ptr t = associated_torrent().lock(); - TORRENT_ASSERT(t); - - buffer::const_interval recv_buffer = receive_buffer(); - // are we currently receiving a 'piece' message? - if (m_state != read_packet - || recv_buffer.left() < 9 - || recv_buffer[0] != msg_piece) - return boost::optional(); - - const char* ptr = recv_buffer.begin + 1; - peer_request r; - r.piece = detail::read_int32(ptr); - r.start = detail::read_int32(ptr); - r.length = packet_size() - 9; - - // is any of the piece message header data invalid? - if (!verify_piece(r)) - return boost::optional(); - - piece_block_progress p; - - p.piece_index = r.piece; - p.block_index = r.start / t->block_size(); - p.bytes_downloaded = recv_buffer.left() - 9; - p.full_block_bytes = r.length; - - return boost::optional(p); - } - - - // message handlers - - // ----------------------------- - // --------- KEEPALIVE --------- - // ----------------------------- - - void bt_peer_connection::on_keepalive() - { - INVARIANT_CHECK; - -#ifdef TORRENT_VERBOSE_LOGGING - (*m_logger) << time_now_string() << " <== KEEPALIVE\n"; -#endif - incoming_keepalive(); - } - - // ----------------------------- - // ----------- CHOKE ----------- - // ----------------------------- - - void bt_peer_connection::on_choke(int received) - { - INVARIANT_CHECK; - - TORRENT_ASSERT(received > 0); - if (packet_size() != 1) - { - disconnect("'choke' message size != 1", 2); - return; - } - m_statistics.received_bytes(0, received); - if (!packet_finished()) return; - - incoming_choke(); - if (is_disconnecting()) return; - if (!m_supports_fast) - { - boost::shared_ptr t = associated_torrent().lock(); - TORRENT_ASSERT(t); - while (!download_queue().empty()) - { - piece_block const& b = download_queue().front().block; - peer_request r; - r.piece = b.piece_index; - r.start = b.block_index * t->block_size(); - r.length = t->block_size(); - incoming_reject_request(r); - } - } - } - - // ----------------------------- - // ---------- UNCHOKE ---------- - // ----------------------------- - - void bt_peer_connection::on_unchoke(int received) - { - INVARIANT_CHECK; - - TORRENT_ASSERT(received > 0); - if (packet_size() != 1) - { - disconnect("'unchoke' message size != 1", 2); - return; - } - m_statistics.received_bytes(0, received); - if (!packet_finished()) return; - - incoming_unchoke(); - } - - // ----------------------------- - // -------- INTERESTED --------- - // ----------------------------- - - void bt_peer_connection::on_interested(int received) - { - INVARIANT_CHECK; - - TORRENT_ASSERT(received > 0); - if (packet_size() != 1) - { - disconnect("'interested' message size != 1", 2); - return; - } - m_statistics.received_bytes(0, received); - if (!packet_finished()) return; - - incoming_interested(); - } - - // ----------------------------- - // ------ NOT INTERESTED ------- - // ----------------------------- - - void bt_peer_connection::on_not_interested(int received) - { - INVARIANT_CHECK; - - TORRENT_ASSERT(received > 0); - if (packet_size() != 1) - { - disconnect("'not interested' message size != 1", 2); - return; - } - m_statistics.received_bytes(0, received); - if (!packet_finished()) return; - - incoming_not_interested(); - } - - // ----------------------------- - // ----------- HAVE ------------ - // ----------------------------- - - void bt_peer_connection::on_have(int received) - { - INVARIANT_CHECK; - - TORRENT_ASSERT(received > 0); - if (packet_size() != 5) - { - disconnect("'have' message size != 5", 2); - return; - } - m_statistics.received_bytes(0, received); - if (!packet_finished()) return; - - buffer::const_interval recv_buffer = receive_buffer(); - - const char* ptr = recv_buffer.begin + 1; - int index = detail::read_int32(ptr); - - incoming_have(index); - } - - // ----------------------------- - // --------- BITFIELD ---------- - // ----------------------------- - - void bt_peer_connection::on_bitfield(int received) - { - INVARIANT_CHECK; - - TORRENT_ASSERT(received > 0); - - boost::shared_ptr t = associated_torrent().lock(); - TORRENT_ASSERT(t); - - // if we don't have the metedata, we cannot - // verify the bitfield size - if (t->valid_metadata() - && packet_size() - 1 != (t->torrent_file().num_pieces() + 7) / 8) - { - std::stringstream msg; - msg << "got bitfield with invalid size: " << (packet_size() - 1) - << " bytes. expected: " << ((t->torrent_file().num_pieces() + 7) / 8) - << " bytes"; - disconnect(msg.str().c_str(), 2); - return; - } - - m_statistics.received_bytes(0, received); - if (!packet_finished()) return; - - buffer::const_interval recv_buffer = receive_buffer(); - - bitfield bits; - bits.borrow_bytes((char*)recv_buffer.begin + 1 - , t->valid_metadata()?get_bitfield().size():(packet_size()-1)*8); - - incoming_bitfield(bits); - } - - // ----------------------------- - // ---------- REQUEST ---------- - // ----------------------------- - - void bt_peer_connection::on_request(int received) - { - INVARIANT_CHECK; - - TORRENT_ASSERT(received > 0); - if (packet_size() != 13) - { - disconnect("'request' message size != 13", 2); - return; - } - m_statistics.received_bytes(0, received); - if (!packet_finished()) return; - - buffer::const_interval recv_buffer = receive_buffer(); - - peer_request r; - const char* ptr = recv_buffer.begin + 1; - r.piece = detail::read_int32(ptr); - r.start = detail::read_int32(ptr); - r.length = detail::read_int32(ptr); - - incoming_request(r); - } - - // ----------------------------- - // ----------- PIECE ----------- - // ----------------------------- - - void bt_peer_connection::on_piece(int received) - { - INVARIANT_CHECK; - - TORRENT_ASSERT(received > 0); - - buffer::const_interval recv_buffer = receive_buffer(); - int recv_pos = recv_buffer.end - recv_buffer.begin; - - if (recv_pos == 1) - { - TORRENT_ASSERT(!has_disk_receive_buffer()); - if (!allocate_disk_receive_buffer(packet_size() - 9)) - return; - } - TORRENT_ASSERT(has_disk_receive_buffer() || packet_size() == 9); - - // classify the received data as protocol chatter - // or data payload for the statistics - if (recv_pos <= 9) - // only received protocol data - m_statistics.received_bytes(0, received); - else if (recv_pos - received >= 9) - // only received payload data - m_statistics.received_bytes(received, 0); - else - { - // received a bit of both - TORRENT_ASSERT(recv_pos - received < 9); - TORRENT_ASSERT(recv_pos > 9); - TORRENT_ASSERT(9 - (recv_pos - received) <= 9); - m_statistics.received_bytes( - recv_pos - 9 - , 9 - (recv_pos - received)); - } - - incoming_piece_fragment(); - if (is_disconnecting()) return; - if (!packet_finished()) return; - - const char* ptr = recv_buffer.begin + 1; - peer_request p; - p.piece = detail::read_int32(ptr); - p.start = detail::read_int32(ptr); - p.length = packet_size() - 9; - - disk_buffer_holder holder(m_ses, release_disk_receive_buffer()); - incoming_piece(p, holder); - } - - // ----------------------------- - // ---------- CANCEL ----------- - // ----------------------------- - - void bt_peer_connection::on_cancel(int received) - { - INVARIANT_CHECK; - - TORRENT_ASSERT(received > 0); - if (packet_size() != 13) - { - disconnect("'cancel' message size != 13", 2); - return; - } - m_statistics.received_bytes(0, received); - if (!packet_finished()) return; - - buffer::const_interval recv_buffer = receive_buffer(); - - peer_request r; - const char* ptr = recv_buffer.begin + 1; - r.piece = detail::read_int32(ptr); - r.start = detail::read_int32(ptr); - r.length = detail::read_int32(ptr); - - incoming_cancel(r); - } - - // ----------------------------- - // --------- DHT PORT ---------- - // ----------------------------- - - void bt_peer_connection::on_dht_port(int received) - { - INVARIANT_CHECK; - - if (!m_supports_dht_port) - { - disconnect("got 'dht_port' message from peer that doesn't support it", 2); - return; - } - - TORRENT_ASSERT(received > 0); - if (packet_size() != 3) - { - disconnect("'dht_port' message size != 3", 2); - return; - } - m_statistics.received_bytes(0, received); - if (!packet_finished()) return; - - buffer::const_interval recv_buffer = receive_buffer(); - - const char* ptr = recv_buffer.begin + 1; - int listen_port = detail::read_uint16(ptr); - - incoming_dht_port(listen_port); - } - - void bt_peer_connection::on_suggest_piece(int received) - { - INVARIANT_CHECK; - - if (!m_supports_fast) - { - disconnect("got 'suggest_piece' without FAST excension support", 2); - return; - } - - m_statistics.received_bytes(0, received); - if (!packet_finished()) return; - - buffer::const_interval recv_buffer = receive_buffer(); - - const char* ptr = recv_buffer.begin + 1; - int piece = detail::read_uint32(ptr); - incoming_suggest(piece); - } - - void bt_peer_connection::on_have_all(int received) - { - INVARIANT_CHECK; - - if (!m_supports_fast) - { - disconnect("got 'have_all' without FAST extension support", 2); - return; - } - m_statistics.received_bytes(0, received); - incoming_have_all(); - } - - void bt_peer_connection::on_have_none(int received) - { - INVARIANT_CHECK; - - if (!m_supports_fast) - { - disconnect("got 'have_none' without FAST extension support", 2); - return; - } - m_statistics.received_bytes(0, received); - incoming_have_none(); - } - - void bt_peer_connection::on_reject_request(int received) - { - INVARIANT_CHECK; - - if (!m_supports_fast) - { - disconnect("got 'reject_request' without FAST extension support", 2); - return; - } - - m_statistics.received_bytes(0, received); - if (!packet_finished()) return; - - buffer::const_interval recv_buffer = receive_buffer(); - - peer_request r; - const char* ptr = recv_buffer.begin + 1; - r.piece = detail::read_int32(ptr); - r.start = detail::read_int32(ptr); - r.length = detail::read_int32(ptr); - - incoming_reject_request(r); - } - - void bt_peer_connection::on_allowed_fast(int received) - { - INVARIANT_CHECK; - - if (!m_supports_fast) - { - disconnect("got 'allowed_fast' without FAST extension support", 2); - return; - } - - m_statistics.received_bytes(0, received); - if (!packet_finished()) return; - buffer::const_interval recv_buffer = receive_buffer(); - const char* ptr = recv_buffer.begin + 1; - int index = detail::read_int32(ptr); - - incoming_allowed_fast(index); - } - - // ----------------------------- - // --------- EXTENDED ---------- - // ----------------------------- - - void bt_peer_connection::on_extended(int received) - { - INVARIANT_CHECK; - - TORRENT_ASSERT(received > 0); - m_statistics.received_bytes(0, received); - if (packet_size() < 2) - { - disconnect("'extended' message smaller than 2 bytes", 2); - return; - } - - if (associated_torrent().expired()) - { - disconnect("'extended' message sent before proper handshake", 2); - return; - } - - buffer::const_interval recv_buffer = receive_buffer(); - if (recv_buffer.left() < 2) return; - - TORRENT_ASSERT(*recv_buffer.begin == msg_extended); - ++recv_buffer.begin; - - int extended_id = detail::read_uint8(recv_buffer.begin); - - if (extended_id == 0) - { - on_extended_handshake(); - return; - } - -#ifndef TORRENT_DISABLE_EXTENSIONS - for (extension_list_t::iterator i = m_extensions.begin() - , end(m_extensions.end()); i != end; ++i) - { - if ((*i)->on_extended(packet_size() - 2, extended_id - , recv_buffer)) - return; - } -#endif - - std::stringstream msg; - msg << "unknown extended message id: " << extended_id; - disconnect(msg.str().c_str(), 2); - return; - } - - void bt_peer_connection::on_extended_handshake() - { - if (!packet_finished()) return; - - boost::shared_ptr t = associated_torrent().lock(); - TORRENT_ASSERT(t); - - buffer::const_interval recv_buffer = receive_buffer(); - - lazy_entry root; - lazy_bdecode(recv_buffer.begin + 2, recv_buffer.end, root); - if (root.type() != lazy_entry::dict_t) - { -#ifdef TORRENT_VERBOSE_LOGGING - (*m_logger) << "invalid extended handshake\n"; -#endif - return; - } - -#ifdef TORRENT_VERBOSE_LOGGING - (*m_logger) << "<== EXTENDED HANDSHAKE: \n" << root; -#endif - -#ifndef TORRENT_DISABLE_EXTENSIONS - for (extension_list_t::iterator i = m_extensions.begin(); - !m_extensions.empty() && i != m_extensions.end();) - { - // a false return value means that the extension - // isn't supported by the other end. So, it is removed. - if (!(*i)->on_extension_handshake(root)) - i = m_extensions.erase(i); - else - ++i; - } - if (is_disconnecting()) return; -#endif - - // there is supposed to be a remote listen port - int listen_port = root.dict_find_int_value("p"); - if (listen_port > 0 && peer_info_struct() != 0) - { - t->get_policy().update_peer_port(listen_port - , peer_info_struct(), peer_info::incoming); - if (is_disconnecting()) return; - } - // there should be a version too - // but where do we put that info? - - std::string client_info = root.dict_find_string_value("v"); - if (!client_info.empty()) m_client_version = client_info; - - int reqq = root.dict_find_int_value("reqq"); - if (reqq > 0) m_max_out_request_queue = reqq; - - if (root.dict_find_int_value("upload_only")) - set_upload_only(true); - - std::string myip = root.dict_find_string_value("yourip"); - if (!myip.empty()) - { - // TODO: don't trust this blindly - if (myip.size() == address_v4::bytes_type::static_size) - { - address_v4::bytes_type bytes; - std::copy(myip.begin(), myip.end(), bytes.begin()); - m_ses.set_external_address(address_v4(bytes)); - } - else if (myip.size() == address_v6::bytes_type::static_size) - { - address_v6::bytes_type bytes; - std::copy(myip.begin(), myip.end(), bytes.begin()); - address_v6 ipv6_address(bytes); - if (ipv6_address.is_v4_mapped()) - m_ses.set_external_address(ipv6_address.to_v4()); - else - m_ses.set_external_address(ipv6_address); - } - } - - // if we're finished and this peer is uploading only - // disconnect it - if (t->is_finished() && upload_only()) - disconnect("upload to upload connection, closing"); - } - - bool bt_peer_connection::dispatch_message(int received) - { - INVARIANT_CHECK; - - TORRENT_ASSERT(received > 0); - - // this means the connection has been closed already - if (associated_torrent().expired()) return false; - - buffer::const_interval recv_buffer = receive_buffer(); - - TORRENT_ASSERT(recv_buffer.left() >= 1); - int packet_type = recv_buffer[0]; - if (packet_type < 0 - || packet_type >= num_supported_messages - || m_message_handler[packet_type] == 0) - { -#ifndef TORRENT_DISABLE_EXTENSIONS - for (extension_list_t::iterator i = m_extensions.begin() - , end(m_extensions.end()); i != end; ++i) - { - if ((*i)->on_unknown_message(packet_size(), packet_type - , buffer::const_interval(recv_buffer.begin+1 - , recv_buffer.end))) - return packet_finished(); - } -#endif - - std::stringstream msg; - msg << "unkown message id: " << packet_type << " size: " << packet_size(); - disconnect(msg.str().c_str(), 2); - return packet_finished(); - } - - TORRENT_ASSERT(m_message_handler[packet_type] != 0); - - // call the correct handler for this packet type - (this->*m_message_handler[packet_type])(received); - - return packet_finished(); - } - - void bt_peer_connection::write_keepalive() - { - INVARIANT_CHECK; - - // Don't require the bitfield to have been sent at this point - // the case where m_sent_bitfield may not be true is if the - // torrent doesn't have any metadata, and a peer is timimg out. - // then the keep-alive message will be sent before the bitfield - // this is a violation to the original protocol, but necessary - // for the metadata extension. - TORRENT_ASSERT(m_sent_handshake); - - char msg[] = {0,0,0,0}; - send_buffer(msg, sizeof(msg)); - } - - void bt_peer_connection::write_cancel(peer_request const& r) - { - INVARIANT_CHECK; - - TORRENT_ASSERT(m_sent_handshake && m_sent_bitfield); - TORRENT_ASSERT(associated_torrent().lock()->valid_metadata()); - - char msg[17] = {0,0,0,13, msg_cancel}; - char* ptr = msg + 5; - detail::write_int32(r.piece, ptr); // index - detail::write_int32(r.start, ptr); // begin - detail::write_int32(r.length, ptr); // length - send_buffer(msg, sizeof(msg)); - - if (!m_supports_fast) - incoming_reject_request(r); - } - - void bt_peer_connection::write_request(peer_request const& r) - { - INVARIANT_CHECK; - - TORRENT_ASSERT(m_sent_handshake && m_sent_bitfield); - TORRENT_ASSERT(associated_torrent().lock()->valid_metadata()); - - char msg[17] = {0,0,0,13, msg_request}; - char* ptr = msg + 5; - - detail::write_int32(r.piece, ptr); // index - detail::write_int32(r.start, ptr); // begin - detail::write_int32(r.length, ptr); // length - send_buffer(msg, sizeof(msg), message_type_request); - } - - void bt_peer_connection::write_bitfield() - { - INVARIANT_CHECK; - - boost::shared_ptr t = associated_torrent().lock(); - TORRENT_ASSERT(t); - TORRENT_ASSERT(m_sent_handshake && !m_sent_bitfield); - TORRENT_ASSERT(t->valid_metadata()); - - // in this case, have_all or have_none should be sent instead - TORRENT_ASSERT(!m_supports_fast || !t->is_seed() || t->num_have() != 0); - - if (m_supports_fast && t->is_seed()) - { - write_have_all(); - send_allowed_set(); - return; - } - else if (m_supports_fast && t->num_have() == 0) - { - write_have_none(); - send_allowed_set(); - return; - } - else if (t->num_have() == 0) - { - // don't send a bitfield if we don't have any pieces -#ifdef TORRENT_VERBOSE_LOGGING - (*m_logger) << time_now_string() << " *** NOT SENDING BITFIELD\n"; -#endif -#ifdef TORRENT_DEBUG - m_sent_bitfield = true; -#endif - return; - } - - int num_pieces = t->torrent_file().num_pieces(); - int lazy_pieces[50]; - int num_lazy_pieces = 0; - int lazy_piece = 0; - - if (t->is_seed() && m_ses.settings().lazy_bitfields) - { - num_lazy_pieces = (std::min)(50, num_pieces / 10); - if (num_lazy_pieces < 1) num_lazy_pieces = 1; - for (int i = 0; i < num_pieces; ++i) - { - if (rand() % (num_pieces - i) >= num_lazy_pieces - lazy_piece) continue; - lazy_pieces[lazy_piece++] = i; - } - TORRENT_ASSERT(lazy_piece == num_lazy_pieces); - lazy_piece = 0; - } - - const int packet_size = (num_pieces + 7) / 8 + 5; - - buffer::interval i = allocate_send_buffer(packet_size); - if (i.begin == 0) return; // out of memory - - detail::write_int32(packet_size - 4, i.begin); - detail::write_uint8(msg_bitfield, i.begin); - - if (t->is_seed()) - { - memset(i.begin, 0xff, packet_size - 6); - - // Clear trailing bits - unsigned char *p = ((unsigned char *)i.begin) + packet_size - 6; - *p = (0xff << ((8 - (num_pieces & 7)) & 7)) & 0xff; - } - else - { - memset(i.begin, 0, packet_size - 5); - piece_picker const& p = t->picker(); - int mask = 0x80; - unsigned char* byte = (unsigned char*)i.begin; - for (int i = 0; i < num_pieces; ++i) - { - if (p.have_piece(i)) *byte |= mask; - mask >>= 1; - if (mask == 0) - { - mask = 0x80; - ++byte; - } - } - } - for (int c = 0; c < num_lazy_pieces; ++c) - i.begin[lazy_pieces[c] / 8] &= ~(0x80 >> (lazy_pieces[c] & 7)); - TORRENT_ASSERT(i.end - i.begin == (num_pieces + 7) / 8); - -#ifdef TORRENT_VERBOSE_LOGGING - (*m_logger) << time_now_string() << " ==> BITFIELD "; - - std::stringstream bitfield_string; - for (int k = 0; k < num_pieces; ++k) - { - if (i.begin[k / 8] & (0x80 >> (k % 8))) bitfield_string << "1"; - else bitfield_string << "0"; - } - bitfield_string << "\n"; - (*m_logger) << bitfield_string.str(); -#endif -#ifdef TORRENT_DEBUG - m_sent_bitfield = true; -#endif - - setup_send(); - - if (num_lazy_pieces > 0) - { - for (int i = 0; i < num_lazy_pieces; ++i) - { - write_have(lazy_pieces[i]); -#ifdef TORRENT_VERBOSE_LOGGING - (*m_logger) << time_now_string() - << " ==> HAVE [ piece: " << lazy_pieces[i] << "]\n"; -#endif - } - } - - if (m_supports_fast) - send_allowed_set(); - } - -#ifndef TORRENT_DISABLE_EXTENSIONS - void bt_peer_connection::write_extensions() - { - INVARIANT_CHECK; - -#ifdef TORRENT_VERBOSE_LOGGING - (*m_logger) << time_now_string() << " ==> EXTENSIONS\n"; -#endif - TORRENT_ASSERT(m_supports_extensions); - TORRENT_ASSERT(m_sent_handshake); - - entry handshake(entry::dictionary_t); - entry extension_list(entry::dictionary_t); - - handshake["m"] = extension_list; - - // only send the port in case we bade the connection - // on incoming connections the other end already knows - // our listen port - if (is_local()) handshake["p"] = m_ses.listen_port(); - handshake["v"] = m_ses.settings().user_agent; - std::string remote_address; - std::back_insert_iterator out(remote_address); - detail::write_address(remote().address(), out); - handshake["yourip"] = remote_address; - handshake["reqq"] = m_ses.settings().max_allowed_in_request_queue; - boost::shared_ptr t = associated_torrent().lock(); - TORRENT_ASSERT(t); - if (t->is_finished()) handshake["upload_only"] = 1; - - tcp::endpoint ep = m_ses.get_ipv6_interface(); - if (!is_any(ep.address())) - { - std::string ipv6_address; - std::back_insert_iterator out(ipv6_address); - detail::write_address(ep.address(), out); - handshake["ipv6"] = ipv6_address; - } - - // loop backwards, to make the first extension be the last - // to fill in the handshake (i.e. give the first extensions priority) - for (extension_list_t::reverse_iterator i = m_extensions.rbegin() - , end(m_extensions.rend()); i != end; ++i) - { - (*i)->add_handshake(handshake); - } - - std::vector msg; - bencode(std::back_inserter(msg), handshake); - - // make room for message - buffer::interval i = allocate_send_buffer(6 + msg.size()); - if (i.begin == 0) return; // out of memory - - // write the length of the message - detail::write_int32((int)msg.size() + 2, i.begin); - detail::write_uint8(msg_extended, i.begin); - // signal handshake message - detail::write_uint8(0, i.begin); - - std::copy(msg.begin(), msg.end(), i.begin); - i.begin += msg.size(); - TORRENT_ASSERT(i.begin == i.end); - -#ifdef TORRENT_VERBOSE_LOGGING - std::stringstream ext; - handshake.print(ext); - (*m_logger) << "==> EXTENDED HANDSHAKE: \n" << ext.str(); -#endif - - setup_send(); - } -#endif - - void bt_peer_connection::write_choke() - { - INVARIANT_CHECK; - - TORRENT_ASSERT(m_sent_handshake && m_sent_bitfield); - - if (is_choked()) return; - char msg[] = {0,0,0,1,msg_choke}; - send_buffer(msg, sizeof(msg)); - } - - void bt_peer_connection::write_unchoke() - { - INVARIANT_CHECK; - - TORRENT_ASSERT(m_sent_handshake && m_sent_bitfield); - - char msg[] = {0,0,0,1,msg_unchoke}; - send_buffer(msg, sizeof(msg)); - } - - void bt_peer_connection::write_interested() - { - INVARIANT_CHECK; - - TORRENT_ASSERT(m_sent_handshake && m_sent_bitfield); - - char msg[] = {0,0,0,1,msg_interested}; - send_buffer(msg, sizeof(msg)); - } - - void bt_peer_connection::write_not_interested() - { - INVARIANT_CHECK; - - TORRENT_ASSERT(m_sent_handshake && m_sent_bitfield); - - char msg[] = {0,0,0,1,msg_not_interested}; - send_buffer(msg, sizeof(msg)); - } - - void bt_peer_connection::write_have(int index) - { - INVARIANT_CHECK; - TORRENT_ASSERT(associated_torrent().lock()->valid_metadata()); - TORRENT_ASSERT(index >= 0); - TORRENT_ASSERT(index < associated_torrent().lock()->torrent_file().num_pieces()); - TORRENT_ASSERT(m_sent_handshake && m_sent_bitfield); - - char msg[] = {0,0,0,5,msg_have,0,0,0,0}; - char* ptr = msg + 5; - detail::write_int32(index, ptr); - send_buffer(msg, sizeof(msg)); - } - - void bt_peer_connection::write_piece(peer_request const& r, disk_buffer_holder& buffer) - { - INVARIANT_CHECK; - - TORRENT_ASSERT(m_sent_handshake && m_sent_bitfield); - - boost::shared_ptr t = associated_torrent().lock(); - TORRENT_ASSERT(t); - - char msg[4 + 1 + 4 + 4]; - char* ptr = msg; - TORRENT_ASSERT(r.length <= 16 * 1024); - detail::write_int32(r.length + 1 + 4 + 4, ptr); - detail::write_uint8(msg_piece, ptr); - detail::write_int32(r.piece, ptr); - detail::write_int32(r.start, ptr); - send_buffer(msg, sizeof(msg)); - - append_send_buffer(buffer.get(), r.length - , boost::bind(&session_impl::free_disk_buffer - , boost::ref(m_ses), _1)); - buffer.release(); - - m_payloads.push_back(range(send_buffer_size() - r.length, r.length)); - setup_send(); - } - - namespace - { - struct match_peer_id - { - match_peer_id(peer_id const& id, peer_connection const* pc) - : m_id(id), m_pc(pc) - { TORRENT_ASSERT(pc); } - - bool operator()(std::pair const& p) const - { - return p.second.connection != m_pc - && p.second.connection - && p.second.connection->pid() == m_id - && !p.second.connection->pid().is_all_zeros() - && p.second.addr == m_pc->remote().address(); - } - - peer_id const& m_id; - peer_connection const* m_pc; - }; - } - - // -------------------------- - // RECEIVE DATA - // -------------------------- - - // throws exception when the client should be disconnected - void bt_peer_connection::on_receive(error_code const& error - , std::size_t bytes_transferred) - { - INVARIANT_CHECK; - - if (error) return; - boost::shared_ptr t = associated_torrent().lock(); - - if (in_handshake()) - m_statistics.received_bytes(0, bytes_transferred); - -#ifndef TORRENT_DISABLE_ENCRYPTION - TORRENT_ASSERT(in_handshake() || !m_rc4_encrypted || m_encrypted); - if (m_rc4_encrypted && m_encrypted) - { - std::pair wr_buf = wr_recv_buffers(bytes_transferred); - m_RC4_handler->decrypt(wr_buf.first.begin, wr_buf.first.left()); - if (wr_buf.second.left()) m_RC4_handler->decrypt(wr_buf.second.begin, wr_buf.second.left()); - } -#endif - - buffer::const_interval recv_buffer = receive_buffer(); - -#ifndef TORRENT_DISABLE_ENCRYPTION - // m_state is set to read_pe_dhkey in initial state - // (read_protocol_identifier) for incoming, or in constructor - // for outgoing - if (m_state == read_pe_dhkey) - { - TORRENT_ASSERT(!m_encrypted); - TORRENT_ASSERT(!m_rc4_encrypted); - TORRENT_ASSERT(packet_size() == dh_key_len); - TORRENT_ASSERT(recv_buffer == receive_buffer()); - - if (!packet_finished()) return; - - // write our dh public key. m_dh_key_exchange is - // initialized in write_pe1_2_dhkey() - if (!is_local()) write_pe1_2_dhkey(); - if (is_disconnecting()) return; - - // read dh key, generate shared secret - if (m_dh_key_exchange->compute_secret(recv_buffer.begin) == -1) - { - disconnect("out of memory"); - return; - } - -#ifdef TORRENT_VERBOSE_LOGGING - (*m_logger) << " received DH key\n"; -#endif - - // PadA/B can be a max of 512 bytes, and 20 bytes more for - // the sync hash (if incoming), or 8 bytes more for the - // encrypted verification constant (if outgoing). Instead - // of requesting the maximum possible, request the maximum - // possible to ensure we do not overshoot the standard - // handshake. - - if (is_local()) - { - m_state = read_pe_syncvc; - write_pe3_sync(); - - // initial payload is the standard handshake, this is - // always rc4 if sent here. m_rc4_encrypted is flagged - // again according to peer selection. - m_rc4_encrypted = true; - m_encrypted = true; - write_handshake(); - m_rc4_encrypted = false; - m_encrypted = false; - - // vc,crypto_select,len(pad),pad, encrypt(handshake) - // 8+4+2+0+handshake_len - reset_recv_buffer(8+4+2+0+handshake_len); - } - else - { - // already written dh key - m_state = read_pe_synchash; - // synchash,skeyhash,vc,crypto_provide,len(pad),pad,encrypt(handshake) - reset_recv_buffer(20+20+8+4+2+0+handshake_len); - } - TORRENT_ASSERT(!packet_finished()); - return; - } - - // cannot fall through into - if (m_state == read_pe_synchash) - { - TORRENT_ASSERT(!m_encrypted); - TORRENT_ASSERT(!m_rc4_encrypted); - TORRENT_ASSERT(!is_local()); - TORRENT_ASSERT(recv_buffer == receive_buffer()); - - if (recv_buffer.left() < 20) - { - if (packet_finished()) - disconnect("sync hash not found", 2); - return; - } - - if (!m_sync_hash.get()) - { - TORRENT_ASSERT(m_sync_bytes_read == 0); - hasher h; - - // compute synchash (hash('req1',S)) - h.update("req1", 4); - h.update(m_dh_key_exchange->get_secret(), dh_key_len); - - m_sync_hash.reset(new sha1_hash(h.final())); - } - - int syncoffset = get_syncoffset((char*)m_sync_hash->begin(), 20 - , recv_buffer.begin, recv_buffer.left()); - - // No sync - if (syncoffset == -1) - { - std::size_t bytes_processed = recv_buffer.left() - 20; - m_sync_bytes_read += bytes_processed; - if (m_sync_bytes_read >= 512) - { - disconnect("sync hash not found within 532 bytes", 2); - return; - } - - cut_receive_buffer(bytes_processed, (std::min)(packet_size() - , (512+20) - m_sync_bytes_read)); - - TORRENT_ASSERT(!packet_finished()); - return; - } - // found complete sync - else - { - std::size_t bytes_processed = syncoffset + 20; -#ifdef TORRENT_VERBOSE_LOGGING - (*m_logger) << " sync point (hash) found at offset " - << m_sync_bytes_read + bytes_processed - 20 << "\n"; -#endif - m_state = read_pe_skey_vc; - // skey,vc - 28 bytes - m_sync_hash.reset(); - cut_receive_buffer(bytes_processed, 28); - } - } - - if (m_state == read_pe_skey_vc) - { - TORRENT_ASSERT(!m_encrypted); - TORRENT_ASSERT(!m_rc4_encrypted); - TORRENT_ASSERT(!is_local()); - TORRENT_ASSERT(packet_size() == 28); - - if (!packet_finished()) return; - - recv_buffer = receive_buffer(); - - aux::session_impl::torrent_map::const_iterator i; - - for (i = m_ses.m_torrents.begin(); i != m_ses.m_torrents.end(); ++i) - { - torrent const& ti = *i->second; - sha1_hash const& skey_hash = ti.obfuscated_hash(); - sha1_hash obfs_hash = m_dh_key_exchange->get_hash_xor_mask(); - obfs_hash ^= skey_hash; - - if (std::equal(recv_buffer.begin, recv_buffer.begin + 20, - (char*)&obfs_hash[0])) - { - if (!t) - { - attach_to_torrent(ti.info_hash()); - if (is_disconnecting()) return; - - t = associated_torrent().lock(); - TORRENT_ASSERT(t); - } - - init_pe_RC4_handler(m_dh_key_exchange->get_secret(), ti.info_hash()); -#ifdef TORRENT_VERBOSE_LOGGING - (*m_logger) << " stream key found, torrent located.\n"; -#endif - break; - } - } - - if (!m_RC4_handler.get()) - { - disconnect("invalid streamkey identifier (info hash) in encrypted handshake", 2); - return; - } - - // verify constant - buffer::interval wr_recv_buf = wr_recv_buffer(); - m_RC4_handler->decrypt(wr_recv_buf.begin + 20, 8); - wr_recv_buf.begin += 28; - - const char sh_vc[] = {0,0,0,0, 0,0,0,0}; - if (!std::equal(sh_vc, sh_vc+8, recv_buffer.begin + 20)) - { - disconnect("unable to verify constant", 2); - return; - } - -#ifdef TORRENT_VERBOSE_LOGGING - (*m_logger) << " verification constant found\n"; -#endif - m_state = read_pe_cryptofield; - reset_recv_buffer(4 + 2); - } - - // cannot fall through into - if (m_state == read_pe_syncvc) - { - TORRENT_ASSERT(is_local()); - TORRENT_ASSERT(!m_encrypted); - TORRENT_ASSERT(!m_rc4_encrypted); - TORRENT_ASSERT(recv_buffer == receive_buffer()); - - if (recv_buffer.left() < 8) - { - if (packet_finished()) - disconnect("sync verification constant not found", 2); - return; - } - - // generate the verification constant - if (!m_sync_vc.get()) - { - TORRENT_ASSERT(m_sync_bytes_read == 0); - - m_sync_vc.reset (new char[8]); - std::fill(m_sync_vc.get(), m_sync_vc.get() + 8, 0); - m_RC4_handler->decrypt(m_sync_vc.get(), 8); - } - - TORRENT_ASSERT(m_sync_vc.get()); - int syncoffset = get_syncoffset(m_sync_vc.get(), 8 - , recv_buffer.begin, recv_buffer.left()); - - // No sync - if (syncoffset == -1) - { - std::size_t bytes_processed = recv_buffer.left() - 8; - m_sync_bytes_read += bytes_processed; - if (m_sync_bytes_read >= 512) - { - disconnect("sync verification constant not found within 520 bytes", 2); - return; - } - - cut_receive_buffer(bytes_processed, (std::min)(packet_size(), (512+8) - m_sync_bytes_read)); - - TORRENT_ASSERT(!packet_finished()); - return; - } - // found complete sync - else - { - std::size_t bytes_processed = syncoffset + 8; -#ifdef TORRENT_VERBOSE_LOGGING - (*m_logger) << " sync point (verification constant) found at offset " - << m_sync_bytes_read + bytes_processed - 8 << "\n"; -#endif - cut_receive_buffer (bytes_processed, 4 + 2); - - // delete verification constant - m_sync_vc.reset(); - m_state = read_pe_cryptofield; - // fall through - } - } - - if (m_state == read_pe_cryptofield) // local/remote - { - TORRENT_ASSERT(!m_encrypted); - TORRENT_ASSERT(!m_rc4_encrypted); - TORRENT_ASSERT(packet_size() == 4+2); - - if (!packet_finished()) return; - - buffer::interval wr_buf = wr_recv_buffer(); - m_RC4_handler->decrypt(wr_buf.begin, packet_size()); - - recv_buffer = receive_buffer(); - - int crypto_field = detail::read_int32(recv_buffer.begin); - -#ifdef TORRENT_VERBOSE_LOGGING - if (!is_local()) - (*m_logger) << " crypto provide : [ "; - else - (*m_logger) << " crypto select : [ "; - - if (crypto_field & 0x01) - (*m_logger) << "plaintext "; - if (crypto_field & 0x02) - (*m_logger) << "rc4 "; - (*m_logger) << "]\n"; -#endif - - if (!is_local()) - { - int crypto_select = 0; - // select a crypto method - switch (m_ses.get_pe_settings().allowed_enc_level) - { - case pe_settings::plaintext: - if (!(crypto_field & 0x01)) - { - disconnect("plaintext not provided", 1); - return; - } - crypto_select = 0x01; - break; - case pe_settings::rc4: - if (!(crypto_field & 0x02)) - { - disconnect("rc4 not provided", 1); - return; - } - crypto_select = 0x02; - break; - case pe_settings::both: - if (m_ses.get_pe_settings().prefer_rc4) - { - if (crypto_field & 0x02) - crypto_select = 0x02; - else if (crypto_field & 0x01) - crypto_select = 0x01; - } - else - { - if (crypto_field & 0x01) - crypto_select = 0x01; - else if (crypto_field & 0x02) - crypto_select = 0x02; - } - if (!crypto_select) - { - disconnect("rc4/plaintext not provided", 1); - return; - } - break; - } // switch - - // write the pe4 step - write_pe4_sync(crypto_select); - } - else // is_local() - { - // check if crypto select is valid - pe_settings::enc_level const& allowed_enc_level = m_ses.get_pe_settings().allowed_enc_level; - - if (crypto_field == 0x02) - { - if (allowed_enc_level == pe_settings::plaintext) - { - disconnect("rc4 selected by peer when not provided", 2); - return; - } - m_rc4_encrypted = true; - } - else if (crypto_field == 0x01) - { - if (allowed_enc_level == pe_settings::rc4) - { - disconnect("plaintext selected by peer when not provided", 2); - return; - } - m_rc4_encrypted = false; - } - else - { - disconnect("unsupported crypto method selected by peer", 2); - return; - } - } - - int len_pad = detail::read_int16(recv_buffer.begin); - if (len_pad < 0 || len_pad > 512) - { - disconnect("invalid pad length", 2); - return; - } - - m_state = read_pe_pad; - if (!is_local()) - reset_recv_buffer(len_pad + 2); // len(IA) at the end of pad - else - { - if (len_pad == 0) - { - m_encrypted = true; - m_state = init_bt_handshake; - } - else - reset_recv_buffer(len_pad); - } - } - - if (m_state == read_pe_pad) - { - TORRENT_ASSERT(!m_encrypted); - if (!packet_finished()) return; - - int pad_size = is_local() ? packet_size() : packet_size() - 2; - - buffer::interval wr_buf = wr_recv_buffer(); - m_RC4_handler->decrypt(wr_buf.begin, packet_size()); - - recv_buffer = receive_buffer(); - - if (!is_local()) - { - recv_buffer.begin += pad_size; - int len_ia = detail::read_int16(recv_buffer.begin); - - if (len_ia < 0) - { - disconnect("invalid len_ia in handshake", 2); - return; - } - -#ifdef TORRENT_VERBOSE_LOGGING - (*m_logger) << " len(IA) : " << len_ia << "\n"; -#endif - if (len_ia == 0) - { - // everything after this is Encrypt2 - m_encrypted = true; - m_state = init_bt_handshake; - } - else - { - m_state = read_pe_ia; - reset_recv_buffer(len_ia); - } - } - else // is_local() - { - // everything that arrives after this is Encrypt2 - m_encrypted = true; - m_state = init_bt_handshake; - } - } - - if (m_state == read_pe_ia) - { - TORRENT_ASSERT(!is_local()); - TORRENT_ASSERT(!m_encrypted); - - if (!packet_finished()) return; - - // ia is always rc4, so decrypt it - buffer::interval wr_buf = wr_recv_buffer(); - m_RC4_handler->decrypt(wr_buf.begin, packet_size()); - -#ifdef TORRENT_VERBOSE_LOGGING - (*m_logger) << " decrypted ia : " << packet_size() << " bytes\n"; -#endif - - if (!m_rc4_encrypted) - { - m_RC4_handler.reset(); -#ifdef TORRENT_VERBOSE_LOGGING - (*m_logger) << " destroyed rc4 keys\n"; -#endif - } - - // everything that arrives after this is Encrypt2 - m_encrypted = true; - - m_state = read_protocol_identifier; - cut_receive_buffer(0, 20); - } - - if (m_state == init_bt_handshake) - { - TORRENT_ASSERT(m_encrypted); - - // decrypt remaining received bytes - if (m_rc4_encrypted) - { - buffer::interval wr_buf = wr_recv_buffer(); - wr_buf.begin += packet_size(); - m_RC4_handler->decrypt(wr_buf.begin, wr_buf.left()); -#ifdef TORRENT_VERBOSE_LOGGING - (*m_logger) << " decrypted remaining " << wr_buf.left() << " bytes\n"; -#endif - } - else // !m_rc4_encrypted - { - m_RC4_handler.reset(); -#ifdef TORRENT_VERBOSE_LOGGING - (*m_logger) << " destroyed rc4 keys\n"; -#endif - } - - // payload stream, start with 20 handshake bytes - m_state = read_protocol_identifier; - reset_recv_buffer(20); - - // encrypted portion of handshake completed, toggle - // peer_info pe_support flag back to true - if (is_local() && - m_ses.get_pe_settings().out_enc_policy == pe_settings::enabled) - { - policy::peer* pi = peer_info_struct(); - TORRENT_ASSERT(pi); - - pi->pe_support = true; - } - } - -#endif // #ifndef TORRENT_DISABLE_ENCRYPTION - - if (m_state == read_protocol_identifier) - { - TORRENT_ASSERT(packet_size() == 20); - - if (!packet_finished()) return; - recv_buffer = receive_buffer(); - - int packet_size = recv_buffer[0]; - const char protocol_string[] = "BitTorrent protocol"; - - if (packet_size != 19 || - !std::equal(recv_buffer.begin + 1, recv_buffer.begin + 19, protocol_string)) - { -#ifndef TORRENT_DISABLE_ENCRYPTION - if (!is_local() && m_ses.get_pe_settings().in_enc_policy == pe_settings::disabled) - { - disconnect("encrypted incoming connections disabled"); - return; - } - - // Don't attempt to perform an encrypted handshake - // within an encrypted connection - if (!m_encrypted && !is_local()) - { -#ifdef TORRENT_VERBOSE_LOGGING - (*m_logger) << " attempting encrypted connection\n"; -#endif - m_state = read_pe_dhkey; - cut_receive_buffer(0, dh_key_len); - TORRENT_ASSERT(!packet_finished()); - return; - } - - TORRENT_ASSERT((!is_local() && m_encrypted) || is_local()); -#endif // #ifndef TORRENT_DISABLE_ENCRYPTION - disconnect("incorrect protocol identifier", 2); - return; - } - -#ifndef TORRENT_DISABLE_ENCRYPTION - TORRENT_ASSERT(m_state != read_pe_dhkey); - - if (!is_local() && - (m_ses.get_pe_settings().in_enc_policy == pe_settings::forced) && - !m_encrypted) - { - disconnect("non encrypted incoming connections disabled"); - return; - } -#endif - -#ifdef TORRENT_VERBOSE_LOGGING - (*m_logger) << " BitTorrent protocol\n"; -#endif - - m_state = read_info_hash; - reset_recv_buffer(28); - } - - // fall through - if (m_state == read_info_hash) - { - TORRENT_ASSERT(packet_size() == 28); - - if (!packet_finished()) return; - recv_buffer = receive_buffer(); - - -#ifdef TORRENT_VERBOSE_LOGGING - for (int i=0; i < 8; ++i) - { - for (int j=0; j < 8; ++j) - { - if (recv_buffer[i] & (0x80 >> j)) (*m_logger) << "1"; - else (*m_logger) << "0"; - } - } - (*m_logger) << "\n"; - if (recv_buffer[7] & 0x01) - (*m_logger) << "supports DHT port message\n"; - if (recv_buffer[7] & 0x04) - (*m_logger) << "supports FAST extensions\n"; - if (recv_buffer[5] & 0x10) - (*m_logger) << "supports extensions protocol\n"; -#endif - -#ifndef DISABLE_EXTENSIONS - std::memcpy(m_reserved_bits, recv_buffer.begin, 20); - if ((recv_buffer[5] & 0x10)) - m_supports_extensions = true; -#endif - if (recv_buffer[7] & 0x01) - m_supports_dht_port = true; - - if (recv_buffer[7] & 0x04) - m_supports_fast = true; - - // ok, now we have got enough of the handshake. Is this connection - // attached to a torrent? - if (!t) - { - // now, we have to see if there's a torrent with the - // info_hash we got from the peer - sha1_hash info_hash; - std::copy(recv_buffer.begin + 8, recv_buffer.begin + 28 - , (char*)info_hash.begin()); - - attach_to_torrent(info_hash); - if (is_disconnecting()) return; - } - else - { - // verify info hash - if (!std::equal(recv_buffer.begin + 8, recv_buffer.begin + 28 - , (const char*)t->torrent_file().info_hash().begin())) - { -#ifdef TORRENT_VERBOSE_LOGGING - (*m_logger) << " received invalid info_hash\n"; -#endif - disconnect("invalid info-hash in handshake", 2); - return; - } - -#ifdef TORRENT_VERBOSE_LOGGING - (*m_logger) << " info_hash received\n"; -#endif - } - - t = associated_torrent().lock(); - TORRENT_ASSERT(t); - - // if this is a local connection, we have already - // sent the handshake - if (!is_local()) write_handshake(); -// if (t->valid_metadata()) -// write_bitfield(); - - if (is_disconnecting()) return; - - TORRENT_ASSERT(t->get_policy().has_connection(this)); - - m_state = read_peer_id; - reset_recv_buffer(20); - } - - // fall through - if (m_state == read_peer_id) - { - if (!t) - { - TORRENT_ASSERT(!packet_finished()); // TODO - return; - } - TORRENT_ASSERT(packet_size() == 20); - - if (!packet_finished()) return; - recv_buffer = receive_buffer(); - -#ifdef TORRENT_VERBOSE_LOGGING - { - peer_id tmp; - std::copy(recv_buffer.begin, recv_buffer.begin + 20, (char*)tmp.begin()); - std::stringstream s; - s << "received peer_id: " << tmp << " client: " << identify_client(tmp) << "\n"; - s << "as ascii: "; - for (peer_id::iterator i = tmp.begin(); i != tmp.end(); ++i) - { - if (std::isprint(*i)) s << *i; - else s << "."; - } - s << "\n"; - (*m_logger) << s.str(); - } -#endif - peer_id pid; - std::copy(recv_buffer.begin, recv_buffer.begin + 20, (char*)pid.begin()); - set_pid(pid); - - if (t->settings().allow_multiple_connections_per_ip) - { - // now, let's see if this connection should be closed - policy& p = t->get_policy(); - policy::iterator i = std::find_if(p.begin_peer(), p.end_peer() - , match_peer_id(pid, this)); - if (i != p.end_peer()) - { - TORRENT_ASSERT(i->second.connection->pid() == pid); - // we found another connection with the same peer-id - // which connection should be closed in order to be - // sure that the other end closes the same connection? - // the peer with greatest peer-id is the one allowed to - // initiate connections. So, if our peer-id is greater than - // the others, we should close the incoming connection, - // if not, we should close the outgoing one. - if (pid < m_ses.get_peer_id() && is_local()) - { - i->second.connection->disconnect("duplicate peer-id, connection closed"); - } - else - { - disconnect("duplicate peer-id, connection closed"); - return; - } - } - } - - if (pid == m_ses.get_peer_id()) - { - disconnect("closing connection to ourself", 1); - return; - } - - m_client_version = identify_client(pid); - boost::optional f = client_fingerprint(pid); - if (f && std::equal(f->name, f->name + 2, "BC")) - { - // if this is a bitcomet client, lower the request queue size limit - if (m_max_out_request_queue > 50) m_max_out_request_queue = 50; - } - - // disconnect if the peer has the same peer-id as ourself - // since it most likely is ourself then - if (pid == m_ses.get_peer_id()) - { - disconnect("closing connection to ourself", 1); - return; - } - -#ifndef TORRENT_DISABLE_EXTENSIONS - for (extension_list_t::iterator i = m_extensions.begin() - , end(m_extensions.end()); i != end;) - { - if (!(*i)->on_handshake(m_reserved_bits)) - { - i = m_extensions.erase(i); - } - else - { - ++i; - } - } - if (is_disconnecting()) return; - - if (m_supports_extensions) write_extensions(); -#endif - -#ifdef TORRENT_VERBOSE_LOGGING - (*m_logger) << time_now_string() << " <== HANDSHAKE\n"; -#endif - // consider this a successful connection, reset the failcount - if (peer_info_struct()) peer_info_struct()->failcount = 0; - -#ifndef TORRENT_DISABLE_ENCRYPTION - // Toggle pe_support back to false if this is a - // standard successful connection - if (is_local() && !m_encrypted && - m_ses.get_pe_settings().out_enc_policy == pe_settings::enabled) - { - policy::peer* pi = peer_info_struct(); - TORRENT_ASSERT(pi); - - pi->pe_support = false; - } -#endif - - m_state = read_packet_size; - reset_recv_buffer(5); - if (t->ready_for_connections()) - { - write_bitfield(); -#ifndef TORRENT_DISABLE_DHT - if (m_supports_dht_port && m_ses.m_dht) - write_dht_port(m_ses.get_dht_settings().service_port); -#endif - } - - TORRENT_ASSERT(!packet_finished()); - return; - } - - // cannot fall through into - if (m_state == read_packet_size) - { - // Make sure this is not fallen though into - TORRENT_ASSERT(recv_buffer == receive_buffer()); - - if (!t) return; - m_statistics.received_bytes(0, bytes_transferred); - - if (recv_buffer.left() < 4) return; - - const char* ptr = recv_buffer.begin; - int packet_size = detail::read_int32(ptr); - - // don't accept packets larger than 1 MB - if (packet_size > 1024*1024 || packet_size < 0) - { - // packet too large - std::stringstream msg; - msg << "packet > 1 MB (" << (unsigned int)packet_size << " bytes)"; - disconnect(msg.str().c_str(), 2); - return; - } - - if (packet_size == 0) - { - incoming_keepalive(); - if (is_disconnecting()) return; - // keepalive message - m_state = read_packet_size; - cut_receive_buffer(4, 4); - return; - } - else - { - if (recv_buffer.left() < 5) return; - - m_state = read_packet; - cut_receive_buffer(4, packet_size); - bytes_transferred = 1; - recv_buffer = receive_buffer(); - TORRENT_ASSERT(recv_buffer.left() == 1); - } - } - - if (m_state == read_packet) - { - TORRENT_ASSERT(recv_buffer == receive_buffer()); - if (!t) return; - if (dispatch_message(bytes_transferred)) - { - m_state = read_packet_size; - reset_recv_buffer(5); - } - TORRENT_ASSERT(!packet_finished()); - return; - } - - TORRENT_ASSERT(!packet_finished()); - } - - // -------------------------- - // SEND DATA - // -------------------------- - - void bt_peer_connection::on_sent(error_code const& error - , std::size_t bytes_transferred) - { - INVARIANT_CHECK; - - if (error) return; - - // manage the payload markers - int amount_payload = 0; - if (!m_payloads.empty()) - { - for (std::deque::iterator i = m_payloads.begin(); - i != m_payloads.end(); ++i) - { - i->start -= bytes_transferred; - if (i->start < 0) - { - if (i->start + i->length <= 0) - { - amount_payload += i->length; - } - else - { - amount_payload += -i->start; - i->length -= -i->start; - i->start = 0; - } - } - } - } - - // TODO: move the erasing into the loop above - // remove all payload ranges that has been sent - m_payloads.erase( - std::remove_if(m_payloads.begin(), m_payloads.end(), range_below_zero) - , m_payloads.end()); - -#if defined TORRENT_DEBUG && !defined TORRENT_DISABLE_ENCRYPTION - if (m_encrypted_bytes > 0) - { - if (m_rc4_encrypted) - { - m_encrypted_bytes -= bytes_transferred; - TORRENT_ASSERT(m_encrypted_bytes >= 0); - } - else - { - m_encrypted_bytes -= (std::min)(int(bytes_transferred), m_encrypted_bytes); - } - TORRENT_ASSERT(m_encrypted_bytes >= 0); - } -#endif - - TORRENT_ASSERT(amount_payload <= (int)bytes_transferred); - m_statistics.sent_bytes(amount_payload, bytes_transferred - amount_payload); - } - -#ifdef TORRENT_DEBUG - void bt_peer_connection::check_invariant() const - { -#ifndef TORRENT_DISABLE_ENCRYPTION - TORRENT_ASSERT( (bool(m_state != read_pe_dhkey) || m_dh_key_exchange.get()) - || !is_local()); - - TORRENT_ASSERT(!m_rc4_encrypted || m_RC4_handler.get()); -#endif - if (is_seed() && m_initialized) TORRENT_ASSERT(upload_only()); - - if (!in_handshake()) - { - TORRENT_ASSERT(m_sent_handshake); - } - - if (!m_payloads.empty()) - { - for (std::deque::const_iterator i = m_payloads.begin(); - i != m_payloads.end() - 1; ++i) - { - TORRENT_ASSERT(i->start + i->length <= (i+1)->start); - } - } - } -#endif - -} - diff --git a/libtorrent/src/connection_queue.cpp b/libtorrent/src/connection_queue.cpp deleted file mode 100644 index d7f730746..000000000 --- a/libtorrent/src/connection_queue.cpp +++ /dev/null @@ -1,279 +0,0 @@ - -/* - -Copyright (c) 2007, Arvid Norberg -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions -are met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in - the documentation and/or other materials provided with the distribution. - * Neither the name of the author nor the names of its - contributors may be used to endorse or promote products derived - from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -POSSIBILITY OF SUCH DAMAGE. - -*/ - -#include -#include "libtorrent/invariant_check.hpp" -#include "libtorrent/connection_queue.hpp" -#include "libtorrent/socket.hpp" - -namespace libtorrent -{ - - connection_queue::connection_queue(io_service& ios): m_next_ticket(0) - , m_num_connecting(0) - , m_half_open_limit(0) - , m_abort(false) - , m_timer(ios) -#ifdef TORRENT_DEBUG - , m_in_timeout_function(false) -#endif - { -#ifdef TORRENT_CONNECTION_LOGGING - m_log.open("connection_queue.log"); -#endif - } - - int connection_queue::free_slots() const - { - mutex_t::scoped_lock l(m_mutex); - return m_half_open_limit == 0 ? (std::numeric_limits::max)() - : m_half_open_limit - m_queue.size(); - } - - void connection_queue::enqueue(boost::function const& on_connect - , boost::function const& on_timeout - , time_duration timeout, int priority) - { - mutex_t::scoped_lock l(m_mutex); - - INVARIANT_CHECK; - - TORRENT_ASSERT(priority >= 0); - TORRENT_ASSERT(priority < 2); - - entry* e = 0; - - switch (priority) - { - case 0: - m_queue.push_back(entry()); - e = &m_queue.back(); - break; - case 1: - m_queue.push_front(entry()); - e = &m_queue.front(); - break; - } - - e->priority = priority; - e->on_connect = on_connect; - e->on_timeout = on_timeout; - e->ticket = m_next_ticket; - e->timeout = timeout; - ++m_next_ticket; - try_connect(); - } - - void connection_queue::done(int ticket) - { - mutex_t::scoped_lock l(m_mutex); - - INVARIANT_CHECK; - - std::list::iterator i = std::find_if(m_queue.begin() - , m_queue.end(), boost::bind(&entry::ticket, _1) == ticket); - if (i == m_queue.end()) - { - // this might not be here in case on_timeout calls remove - return; - } - if (i->connecting) --m_num_connecting; - m_queue.erase(i); - try_connect(); - } - - void connection_queue::close() - { - error_code ec; - mutex_t::scoped_lock l(m_mutex); - m_timer.cancel(ec); - m_abort = true; - - while (!m_queue.empty()) - { - // we don't want to call the timeout callback while we're locked - // since that is a recepie for dead-locks - entry e = m_queue.front(); - m_queue.pop_front(); - if (e.connecting) --m_num_connecting; - l.unlock(); - try { e.on_timeout(); } catch (std::exception&) {} - l.lock(); - } - } - - void connection_queue::limit(int limit) - { - TORRENT_ASSERT(limit >= 0); - m_half_open_limit = limit; - } - - int connection_queue::limit() const - { return m_half_open_limit; } - -#ifdef TORRENT_DEBUG - - void connection_queue::check_invariant() const - { - int num_connecting = 0; - for (std::list::const_iterator i = m_queue.begin(); - i != m_queue.end(); ++i) - { - if (i->connecting) ++num_connecting; - } - TORRENT_ASSERT(num_connecting == m_num_connecting); - } - -#endif - - void connection_queue::try_connect() - { - INVARIANT_CHECK; - -#ifdef TORRENT_CONNECTION_LOGGING - m_log << log_time() << " " << free_slots() << std::endl; -#endif - if (m_abort) return; - - if (m_num_connecting >= m_half_open_limit - && m_half_open_limit > 0) return; - - if (m_queue.empty()) - { - error_code ec; - m_timer.cancel(ec); - return; - } - - std::list::iterator i = std::find_if(m_queue.begin() - , m_queue.end(), boost::bind(&entry::connecting, _1) == false); - while (i != m_queue.end()) - { - TORRENT_ASSERT(i->connecting == false); - ptime expire = time_now() + i->timeout; - if (m_num_connecting == 0) - { - error_code ec; - m_timer.expires_at(expire, ec); - m_timer.async_wait(boost::bind(&connection_queue::on_timeout, this, _1)); - } - i->connecting = true; - ++m_num_connecting; - i->expires = expire; - - INVARIANT_CHECK; - - entry& ent = *i; - ++i; -#ifndef BOOST_NO_EXCEPTIONS - try { -#endif - ent.on_connect(ent.ticket); -#ifndef BOOST_NO_EXCEPTIONS - } catch (std::exception&) {} -#endif - -#ifdef TORRENT_CONNECTION_LOGGING - m_log << log_time() << " " << free_slots() << std::endl; -#endif - - if (m_num_connecting >= m_half_open_limit - && m_half_open_limit > 0) break; - i = std::find_if(i, m_queue.end(), boost::bind(&entry::connecting, _1) == false); - } - } - -#ifdef TORRENT_DEBUG - struct function_guard - { - function_guard(bool& v): val(v) { TORRENT_ASSERT(!val); val = true; } - ~function_guard() { val = false; } - - bool& val; - }; -#endif - - void connection_queue::on_timeout(error_code const& e) - { - mutex_t::scoped_lock l(m_mutex); - - INVARIANT_CHECK; -#ifdef TORRENT_DEBUG - function_guard guard_(m_in_timeout_function); -#endif - - TORRENT_ASSERT(!e || e == asio::error::operation_aborted); - if (e) return; - - ptime next_expire = max_time(); - ptime now = time_now(); - std::list timed_out; - for (std::list::iterator i = m_queue.begin(); - !m_queue.empty() && i != m_queue.end();) - { - if (i->connecting && i->expires < now) - { - std::list::iterator j = i; - ++i; - timed_out.splice(timed_out.end(), m_queue, j, i); - --m_num_connecting; - continue; - } - if (i->expires < next_expire) - next_expire = i->expires; - ++i; - } - - // we don't want to call the timeout callback while we're locked - // since that is a recepie for dead-locks - l.unlock(); - - for (std::list::iterator i = timed_out.begin() - , end(timed_out.end()); i != end; ++i) - { - try { i->on_timeout(); } catch (std::exception&) {} - } - - l.lock(); - - if (next_expire < max_time()) - { - error_code ec; - m_timer.expires_at(next_expire, ec); - m_timer.async_wait(boost::bind(&connection_queue::on_timeout, this, _1)); - } - try_connect(); - } - -} - diff --git a/libtorrent/src/create_torrent.cpp b/libtorrent/src/create_torrent.cpp deleted file mode 100644 index 67448bb7b..000000000 --- a/libtorrent/src/create_torrent.cpp +++ /dev/null @@ -1,273 +0,0 @@ -/* - -Copyright (c) 2008, Arvid Norberg -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions -are met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in - the documentation and/or other materials provided with the distribution. - * Neither the name of the author nor the names of its - contributors may be used to endorse or promote products derived - from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -POSSIBILITY OF SUCH DAMAGE. - -*/ - -#include "libtorrent/create_torrent.hpp" -#include "libtorrent/file_pool.hpp" -#include "libtorrent/storage.hpp" - -#include -#include -#include - -namespace gr = boost::gregorian; - -namespace libtorrent -{ - create_torrent::create_torrent(file_storage& fs, int size) - : m_files(fs) - , m_creation_date(pt::second_clock::universal_time()) - , m_multifile(fs.num_files() > 1) - , m_private(false) - { - TORRENT_ASSERT(fs.num_files() > 0); -#if BOOST_VERSION < 103600 - if (!m_multifile && m_files.at(0).path.has_branch_path()) m_multifile = true; -#else - if (!m_multifile && m_files.at(0).path.has_parent_path()) m_multifile = true; -#endif - - // make sure the size is an even power of 2 -#ifndef NDEBUG - for (int i = 0; i < 32; ++i) - { - if (size & (1 << i)) - { - TORRENT_ASSERT((size & ~(1 << i)) == 0); - break; - } - } -#endif - m_files.set_piece_length(size); - m_files.set_num_pieces(static_cast( - (m_files.total_size() + m_files.piece_length() - 1) / m_files.piece_length())); - m_piece_hash.resize(m_files.num_pieces()); - } - - create_torrent::create_torrent(file_storage& fs) - : m_files(fs) - , m_creation_date(pt::second_clock::universal_time()) - , m_multifile(fs.num_files() > 1) - , m_private(false) - { - TORRENT_ASSERT(fs.num_files() > 0); -#if BOOST_VERSION < 103600 - if (!m_multifile && m_files.at(0).path.has_branch_path()) m_multifile = true; -#else - if (!m_multifile && m_files.at(0).path.has_parent_path()) m_multifile = true; -#endif - - const int target_size = 40 * 1024; - int size = fs.total_size() / (target_size / 20); - - for (int i = 4*1024*1024; i > 16*1024; i /= 2) - { - if (size < i) continue; - size = i; - break; - } - - m_files.set_piece_length(size); - m_files.set_num_pieces(static_cast( - (m_files.total_size() + m_files.piece_length() - 1) / m_files.piece_length())); - m_piece_hash.resize(m_files.num_pieces()); - } - entry create_torrent::generate() const - { - TORRENT_ASSERT(m_files.piece_length() > 0); - - if (m_files.num_files() == 0) - { - // TODO: throw something here - // throw - return entry(); - } - - entry dict; - - if (!m_urls.empty()) dict["announce"] = m_urls.front().first; - - if (!m_nodes.empty()) - { - entry& nodes = dict["nodes"]; - entry::list_type& nodes_list = nodes.list(); - for (nodes_t::const_iterator i = m_nodes.begin() - , end(m_nodes.end()); i != end; ++i) - { - entry::list_type node; - node.push_back(entry(i->first)); - node.push_back(entry(i->second)); - nodes_list.push_back(entry(node)); - } - } - - if (m_urls.size() > 1) - { - entry trackers(entry::list_t); - entry tier(entry::list_t); - int current_tier = m_urls.front().second; - for (std::vector::const_iterator i = m_urls.begin(); - i != m_urls.end(); ++i) - { - if (i->second != current_tier) - { - current_tier = i->second; - trackers.list().push_back(tier); - tier.list().clear(); - } - tier.list().push_back(entry(i->first)); - } - trackers.list().push_back(tier); - dict["announce-list"] = trackers; - } - - if (!m_comment.empty()) - dict["comment"] = m_comment; - - dict["creation date"] = - (m_creation_date - pt::ptime(gr::date(1970, gr::Jan, 1))).total_seconds(); - - if (!m_created_by.empty()) - dict["created by"] = m_created_by; - - if (!m_url_seeds.empty()) - { - if (m_url_seeds.size() == 1) - { - dict["url-list"] = m_url_seeds.front(); - } - else - { - entry& list = dict["url-list"]; - for (std::vector::const_iterator i - = m_url_seeds.begin(); i != m_url_seeds.end(); ++i) - { - list.list().push_back(entry(*i)); - } - } - } - - entry& info = dict["info"]; - info["name"] = m_files.name(); - - if (m_private) info["private"] = 1; - - if (!m_multifile) - { - info["length"] = m_files.at(0).size; - } - else - { - if (!info.find_key("files")) - { - entry& files = info["files"]; - - for (file_storage::iterator i = m_files.begin(); - i != m_files.end(); ++i) - { - files.list().push_back(entry()); - entry& file_e = files.list().back(); - file_e["length"] = i->size; - entry& path_e = file_e["path"]; - -#if BOOST_VERSION < 103600 - TORRENT_ASSERT(i->path.has_branch_path()); -#else - TORRENT_ASSERT(i->path.has_parent_path()); -#endif - TORRENT_ASSERT(*i->path.begin() == m_files.name()); - - for (fs::path::iterator j = boost::next(i->path.begin()); - j != i->path.end(); ++j) - { - path_e.list().push_back(entry(*j)); - } - } - } - } - - info["piece length"] = m_files.piece_length(); - entry& pieces = info["pieces"]; - - std::string& p = pieces.string(); - - for (std::vector::const_iterator i = m_piece_hash.begin(); - i != m_piece_hash.end(); ++i) - { - p.append((char*)i->begin(), (char*)i->end()); - } - - std::vector buf; - bencode(std::back_inserter(buf), info); - m_info_hash = hasher(&buf[0], buf.size()).final(); - - return dict; - - } - - void create_torrent::add_tracker(std::string const& url, int tier) - { - m_urls.push_back(announce_entry(url, tier)); - - using boost::bind; - std::sort(m_urls.begin(), m_urls.end() - , bind(&announce_entry::second, _1) < bind(&announce_entry::second, _2)); - } - - void create_torrent::set_hash(int index, sha1_hash const& h) - { - TORRENT_ASSERT(index >= 0); - TORRENT_ASSERT(index < (int)m_piece_hash.size()); - m_piece_hash[index] = h; - } - - void create_torrent::add_node(std::pair const& node) - { - m_nodes.push_back(node); - } - - void create_torrent::add_url_seed(std::string const& url) - { - m_url_seeds.push_back(url); - } - - void create_torrent::set_comment(char const* str) - { - m_comment = str; - } - - void create_torrent::set_creator(char const* str) - { - m_created_by = str; - } - -} - diff --git a/libtorrent/src/disk_buffer_holder.cpp b/libtorrent/src/disk_buffer_holder.cpp deleted file mode 100644 index 1ee83e93e..000000000 --- a/libtorrent/src/disk_buffer_holder.cpp +++ /dev/null @@ -1,70 +0,0 @@ -/* - -Copyright (c) 2008, Arvid Norberg -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions -are met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in - the documentation and/or other materials provided with the distribution. - * Neither the name of the author nor the names of its - contributors may be used to endorse or promote products derived - from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -POSSIBILITY OF SUCH DAMAGE. - -*/ - -#include "libtorrent/disk_buffer_holder.hpp" -#include "libtorrent/aux_/session_impl.hpp" -#include "libtorrent/disk_io_thread.hpp" - -namespace libtorrent -{ - - disk_buffer_holder::disk_buffer_holder(aux::session_impl& ses, char* buf) - : m_iothread(ses.m_disk_thread), m_buf(buf) - { - TORRENT_ASSERT(buf == 0 || m_iothread.is_disk_buffer(buf)); - } - - disk_buffer_holder::disk_buffer_holder(disk_io_thread& iothread, char* buf) - : m_iothread(iothread), m_buf(buf) - { - TORRENT_ASSERT(buf == 0 || m_iothread.is_disk_buffer(buf)); - } - - void disk_buffer_holder::reset(char* buf) - { - if (m_buf) m_iothread.free_buffer(m_buf); - m_buf = buf; - } - - char* disk_buffer_holder::release() - { - char* ret = m_buf; - m_buf = 0; - return ret; - } - - disk_buffer_holder::~disk_buffer_holder() - { - if (m_buf) m_iothread.free_buffer(m_buf); - } -} - diff --git a/libtorrent/src/disk_io_thread.cpp b/libtorrent/src/disk_io_thread.cpp deleted file mode 100644 index e446964b0..000000000 --- a/libtorrent/src/disk_io_thread.cpp +++ /dev/null @@ -1,1192 +0,0 @@ -/* - -Copyright (c) 2007, Arvid Norberg -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions -are met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in - the documentation and/or other materials provided with the distribution. - * Neither the name of the author nor the names of its - contributors may be used to endorse or promote products derived - from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -POSSIBILITY OF SUCH DAMAGE. - -*/ - -#include "libtorrent/storage.hpp" -#include -#include "libtorrent/disk_io_thread.hpp" -#include "libtorrent/disk_buffer_holder.hpp" -#include - -#ifdef _WIN32 -#include -#ifndef alloca -#define alloca(s) _alloca(s) -#endif -#endif - -#ifdef TORRENT_DISK_STATS -#include "libtorrent/time.hpp" -#endif - -namespace libtorrent -{ - - disk_io_thread::disk_io_thread(asio::io_service& ios, int block_size) - : m_abort(false) - , m_queue_buffer_size(0) - , m_cache_size(512) // 512 * 16kB = 8MB - , m_cache_expiry(60) // 1 minute - , m_coalesce_writes(true) - , m_coalesce_reads(true) - , m_use_read_cache(true) -#ifndef TORRENT_DISABLE_POOL_ALLOCATOR - , m_pool(block_size) -#endif - , m_block_size(block_size) - , m_ios(ios) - , m_disk_io_thread(boost::ref(*this)) - { -#ifdef TORRENT_STATS - m_allocations = 0; -#endif -#ifdef TORRENT_DISK_STATS - m_log.open("disk_io_thread.log", std::ios::trunc); -#endif - } - - disk_io_thread::~disk_io_thread() - { - TORRENT_ASSERT(m_abort == true); - } - - void disk_io_thread::join() - { - mutex_t::scoped_lock l(m_queue_mutex); - disk_io_job j; - j.action = disk_io_job::abort_thread; - m_jobs.insert(m_jobs.begin(), j); - m_signal.notify_all(); - l.unlock(); - - m_disk_io_thread.join(); - l.lock(); - TORRENT_ASSERT(m_abort == true); - m_jobs.clear(); - } - - void disk_io_thread::get_cache_info(sha1_hash const& ih, std::vector& ret) const - { - mutex_t::scoped_lock l(m_piece_mutex); - ret.clear(); - ret.reserve(m_pieces.size()); - for (cache_t::const_iterator i = m_pieces.begin() - , end(m_pieces.end()); i != end; ++i) - { - torrent_info const& ti = *i->storage->info(); - if (ti.info_hash() != ih) continue; - cached_piece_info info; - info.piece = i->piece; - info.last_use = i->last_use; - info.kind = cached_piece_info::write_cache; - int blocks_in_piece = (ti.piece_size(i->piece) + (m_block_size) - 1) / m_block_size; - info.blocks.resize(blocks_in_piece); - for (int b = 0; b < blocks_in_piece; ++b) - if (i->blocks[b]) info.blocks[b] = true; - ret.push_back(info); - } - for (cache_t::const_iterator i = m_read_pieces.begin() - , end(m_read_pieces.end()); i != end; ++i) - { - torrent_info const& ti = *i->storage->info(); - if (ti.info_hash() != ih) continue; - cached_piece_info info; - info.piece = i->piece; - info.last_use = i->last_use; - info.kind = cached_piece_info::read_cache; - int blocks_in_piece = (ti.piece_size(i->piece) + (m_block_size) - 1) / m_block_size; - info.blocks.resize(blocks_in_piece); - for (int b = 0; b < blocks_in_piece; ++b) - if (i->blocks[b]) info.blocks[b] = true; - ret.push_back(info); - } - } - - cache_status disk_io_thread::status() const - { - mutex_t::scoped_lock l(m_piece_mutex); - return m_cache_stats; - } - - void disk_io_thread::set_cache_size(int s) - { - mutex_t::scoped_lock l(m_piece_mutex); - TORRENT_ASSERT(s >= 0); - m_cache_size = s; - } - - void disk_io_thread::set_cache_expiry(int ex) - { - mutex_t::scoped_lock l(m_piece_mutex); - TORRENT_ASSERT(ex > 0); - m_cache_expiry = ex; - } - - // aborts read operations - void disk_io_thread::stop(boost::intrusive_ptr s) - { - mutex_t::scoped_lock l(m_queue_mutex); - // read jobs are aborted, write and move jobs are syncronized - for (std::list::iterator i = m_jobs.begin(); - i != m_jobs.end();) - { - if (i->storage != s) - { - ++i; - continue; - } - if (i->action == disk_io_job::read) - { - if (i->callback) m_ios.post(bind(i->callback, -1, *i)); - m_jobs.erase(i++); - continue; - } - if (i->action == disk_io_job::check_files) - { - if (i->callback) m_ios.post(bind(i->callback - , piece_manager::disk_check_aborted, *i)); - m_jobs.erase(i++); - continue; - } - ++i; - } - disk_io_job j; - j.action = disk_io_job::abort_torrent; - j.storage = s; - add_job(j); - } - - bool range_overlap(int start1, int length1, int start2, int length2) - { - return (start1 <= start2 && start1 + length1 > start2) - || (start2 <= start1 && start2 + length2 > start1); - } - - namespace - { - // The semantic of this operator is: - // should lhs come before rhs in the job queue - bool operator<(disk_io_job const& lhs, disk_io_job const& rhs) - { - // NOTE: comparison inverted to make higher priority - // skip _in_front_of_ lower priority - if (lhs.priority > rhs.priority) return true; - if (lhs.priority < rhs.priority) return false; - - if (lhs.storage.get() < rhs.storage.get()) return true; - if (lhs.storage.get() > rhs.storage.get()) return false; - if (lhs.piece < rhs.piece) return true; - if (lhs.piece > rhs.piece) return false; - if (lhs.offset < rhs.offset) return true; -// if (lhs.offset > rhs.offset) return false; - return false; - } - } - - disk_io_thread::cache_t::iterator disk_io_thread::find_cached_piece( - disk_io_thread::cache_t& cache - , disk_io_job const& j, mutex_t::scoped_lock& l) - { - for (cache_t::iterator i = cache.begin() - , end(cache.end()); i != end; ++i) - { - if (i->storage != j.storage || i->piece != j.piece) continue; - return i; - } - return cache.end(); - } - - void disk_io_thread::flush_expired_pieces() - { - ptime now = time_now(); - - mutex_t::scoped_lock l(m_piece_mutex); - - INVARIANT_CHECK; - for (;;) - { - cache_t::iterator i = std::min_element( - m_pieces.begin(), m_pieces.end() - , bind(&cached_piece_entry::last_use, _1) - < bind(&cached_piece_entry::last_use, _2)); - if (i == m_pieces.end()) return; - int age = total_seconds(now - i->last_use); - if (age < m_cache_expiry) return; - flush_and_remove(i, l); - } - } - - void disk_io_thread::free_piece(cached_piece_entry& p, mutex_t::scoped_lock& l) - { - int piece_size = p.storage->info()->piece_size(p.piece); - int blocks_in_piece = (piece_size + m_block_size - 1) / m_block_size; - - for (int i = 0; i < blocks_in_piece; ++i) - { - if (p.blocks[i] == 0) continue; - free_buffer(p.blocks[i]); - p.blocks[i] = 0; - --p.num_blocks; - --m_cache_stats.cache_size; - --m_cache_stats.read_cache_size; - } - } - - bool disk_io_thread::clear_oldest_read_piece( - cache_t::iterator ignore - , mutex_t::scoped_lock& l) - { - INVARIANT_CHECK; - - cache_t::iterator i = std::min_element( - m_read_pieces.begin(), m_read_pieces.end() - , bind(&cached_piece_entry::last_use, _1) - < bind(&cached_piece_entry::last_use, _2)); - if (i != m_read_pieces.end() && i != ignore) - { - // don't replace an entry that is less than one second old - if (time_now() - i->last_use < seconds(1)) return false; - free_piece(*i, l); - m_read_pieces.erase(i); - return true; - } - return false; - } - - void disk_io_thread::flush_oldest_piece(mutex_t::scoped_lock& l) - { - INVARIANT_CHECK; - // first look if there are any read cache entries that can - // be cleared - if (clear_oldest_read_piece(m_read_pieces.end(), l)) return; - - cache_t::iterator i = std::min_element( - m_pieces.begin(), m_pieces.end() - , bind(&cached_piece_entry::last_use, _1) - < bind(&cached_piece_entry::last_use, _2)); - if (i == m_pieces.end()) return; - flush_and_remove(i, l); - } - - void disk_io_thread::flush_and_remove(disk_io_thread::cache_t::iterator e - , mutex_t::scoped_lock& l) - { - flush(e, l); - m_pieces.erase(e); - } - - void disk_io_thread::flush(disk_io_thread::cache_t::iterator e - , mutex_t::scoped_lock& l) - { - INVARIANT_CHECK; - cached_piece_entry& p = *e; - int piece_size = p.storage->info()->piece_size(p.piece); -#ifdef TORRENT_DISK_STATS - m_log << log_time() << " flushing " << piece_size << std::endl; -#endif - TORRENT_ASSERT(piece_size > 0); - boost::scoped_array buf; - if (m_coalesce_writes) buf.reset(new (std::nothrow) char[piece_size]); - - int blocks_in_piece = (piece_size + m_block_size - 1) / m_block_size; - int buffer_size = 0; - int offset = 0; - for (int i = 0; i <= blocks_in_piece; ++i) - { - if (i == blocks_in_piece || p.blocks[i] == 0) - { - if (buffer_size == 0) continue; - TORRENT_ASSERT(buf); - - TORRENT_ASSERT(buffer_size <= i * m_block_size); - l.unlock(); - p.storage->write_impl(buf.get(), p.piece, (std::min)( - i * m_block_size, piece_size) - buffer_size, buffer_size); - l.lock(); - ++m_cache_stats.writes; -// std::cerr << " flushing p: " << p.piece << " bytes: " << buffer_size << std::endl; - buffer_size = 0; - offset = 0; - continue; - } - int block_size = (std::min)(piece_size - i * m_block_size, m_block_size); - TORRENT_ASSERT(offset + block_size <= piece_size); - TORRENT_ASSERT(offset + block_size > 0); - if (!buf) - { - l.unlock(); - p.storage->write_impl(p.blocks[i], p.piece, i * m_block_size, block_size); - l.lock(); - ++m_cache_stats.writes; - } - else - { - std::memcpy(buf.get() + offset, p.blocks[i], block_size); - offset += m_block_size; - buffer_size += block_size; - } - free_buffer(p.blocks[i]); - p.blocks[i] = 0; - TORRENT_ASSERT(p.num_blocks > 0); - --p.num_blocks; - ++m_cache_stats.blocks_written; - --m_cache_stats.cache_size; - } - TORRENT_ASSERT(buffer_size == 0); -// std::cerr << " flushing p: " << p.piece << " cached_blocks: " << m_cache_stats.cache_size << std::endl; -#ifdef TORRENT_DEBUG - for (int i = 0; i < blocks_in_piece; ++i) - TORRENT_ASSERT(p.blocks[i] == 0); -#endif - } - - void disk_io_thread::cache_block(disk_io_job& j, mutex_t::scoped_lock& l) - { - INVARIANT_CHECK; - TORRENT_ASSERT(find_cached_piece(m_pieces, j, l) == m_pieces.end()); - cached_piece_entry p; - - int piece_size = j.storage->info()->piece_size(j.piece); - int blocks_in_piece = (piece_size + m_block_size - 1) / m_block_size; - - p.piece = j.piece; - p.storage = j.storage; - p.last_use = time_now(); - p.num_blocks = 1; - p.blocks.reset(new char*[blocks_in_piece]); - std::memset(&p.blocks[0], 0, blocks_in_piece * sizeof(char*)); - int block = j.offset / m_block_size; -// std::cerr << " adding cache entry for p: " << j.piece << " block: " << block << " cached_blocks: " << m_cache_stats.cache_size << std::endl; - p.blocks[block] = j.buffer; - ++m_cache_stats.cache_size; - m_pieces.push_back(p); - } - - // fills a piece with data from disk, returns the total number of bytes - // read or -1 if there was an error - int disk_io_thread::read_into_piece(cached_piece_entry& p, int start_block, mutex_t::scoped_lock& l) - { - int piece_size = p.storage->info()->piece_size(p.piece); - int blocks_in_piece = (piece_size + m_block_size - 1) / m_block_size; - - int end_block = start_block; - for (int i = start_block; i < blocks_in_piece - && m_cache_stats.cache_size < m_cache_size; ++i) - { - // this is a block that is already allocated - // stop allocating and don't read more than - // what we've allocated now - if (p.blocks[i]) break; - p.blocks[i] = allocate_buffer(); - - // the allocation failed, break - if (p.blocks[i] == 0) break; - ++p.num_blocks; - ++m_cache_stats.cache_size; - ++m_cache_stats.read_cache_size; - ++end_block; - } - - if (end_block == start_block) return -2; - - // the buffer_size is the size of the buffer we need to read - // all these blocks. - const int buffer_size = (std::min)((end_block - start_block) * m_block_size - , piece_size - start_block * m_block_size); - TORRENT_ASSERT(buffer_size <= piece_size); - TORRENT_ASSERT(buffer_size + start_block * m_block_size <= piece_size); - boost::scoped_array buf; - if (m_coalesce_reads) buf.reset(new (std::nothrow) char[buffer_size]); - int ret = 0; - if (buf) - { - l.unlock(); - ret += p.storage->read_impl(buf.get(), p.piece, start_block * m_block_size, buffer_size); - l.lock(); - if (p.storage->error()) { return -1; } - ++m_cache_stats.reads; - } - - int piece_offset = start_block * m_block_size; - int offset = 0; - for (int i = start_block; i < end_block; ++i) - { - int block_size = (std::min)(piece_size - piece_offset, m_block_size); - if (p.blocks[i] == 0) break; - TORRENT_ASSERT(offset <= buffer_size); - TORRENT_ASSERT(piece_offset <= piece_size); - TORRENT_ASSERT(offset + block_size <= buffer_size); - if (buf) - { - std::memcpy(p.blocks[i], buf.get() + offset, block_size); - } - else - { - l.unlock(); - ret += p.storage->read_impl(p.blocks[i], p.piece, piece_offset, block_size); - if (p.storage->error()) { return -1; } - l.lock(); - ++m_cache_stats.reads; - } - offset += m_block_size; - piece_offset += m_block_size; - } - TORRENT_ASSERT(ret <= buffer_size); - return (ret != buffer_size) ? -1 : ret; - } - - bool disk_io_thread::make_room(int num_blocks - , cache_t::iterator ignore - , mutex_t::scoped_lock& l) - { - if (m_cache_size - m_cache_stats.cache_size < num_blocks) - { - // there's not enough room in the cache, clear a piece - // from the read cache - if (!clear_oldest_read_piece(ignore, l)) return false; - } - - return m_cache_size - m_cache_stats.cache_size >= num_blocks; - } - - // returns -1 on read error, -2 if there isn't any space in the cache - // or the number of bytes read - int disk_io_thread::cache_read_block(disk_io_job const& j, mutex_t::scoped_lock& l) - { - INVARIANT_CHECK; - - int piece_size = j.storage->info()->piece_size(j.piece); - int blocks_in_piece = (piece_size + m_block_size - 1) / m_block_size; - - int start_block = j.offset / m_block_size; - - if (!make_room(blocks_in_piece - start_block - , m_read_pieces.end(), l)) return -2; - - cached_piece_entry p; - p.piece = j.piece; - p.storage = j.storage; - p.last_use = time_now(); - p.num_blocks = 0; - p.blocks.reset(new char*[blocks_in_piece]); - std::memset(&p.blocks[0], 0, blocks_in_piece * sizeof(char*)); - int ret = read_into_piece(p, start_block, l); - - if (ret == -1) - free_piece(p, l); - else - m_read_pieces.push_back(p); - - return ret; - } - -#ifdef TORRENT_DEBUG - void disk_io_thread::check_invariant() const - { - int cached_write_blocks = 0; - for (cache_t::const_iterator i = m_pieces.begin() - , end(m_pieces.end()); i != end; ++i) - { - cached_piece_entry const& p = *i; - TORRENT_ASSERT(p.blocks); - - if (!p.storage) continue; - int piece_size = p.storage->info()->piece_size(p.piece); - int blocks_in_piece = (piece_size + m_block_size - 1) / m_block_size; - int blocks = 0; - for (int k = 0; k < blocks_in_piece; ++k) - { - if (p.blocks[k]) - { -#ifndef TORRENT_DISABLE_POOL_ALLOCATOR - TORRENT_ASSERT(is_disk_buffer(p.blocks[k])); -#endif - ++blocks; - } - } -// TORRENT_ASSERT(blocks == p.num_blocks); - cached_write_blocks += blocks; - } - - int cached_read_blocks = 0; - for (cache_t::const_iterator i = m_read_pieces.begin() - , end(m_read_pieces.end()); i != end; ++i) - { - cached_piece_entry const& p = *i; - TORRENT_ASSERT(p.blocks); - - int piece_size = p.storage->info()->piece_size(p.piece); - int blocks_in_piece = (piece_size + m_block_size - 1) / m_block_size; - int blocks = 0; - for (int k = 0; k < blocks_in_piece; ++k) - { - if (p.blocks[k]) - { -#ifndef TORRENT_DISABLE_POOL_ALLOCATOR - TORRENT_ASSERT(is_disk_buffer(p.blocks[k])); -#endif - ++blocks; - } - } -// TORRENT_ASSERT(blocks == p.num_blocks); - cached_read_blocks += blocks; - } - - TORRENT_ASSERT(cached_read_blocks + cached_write_blocks == m_cache_stats.cache_size); - TORRENT_ASSERT(cached_read_blocks == m_cache_stats.read_cache_size); - - // when writing, there may be a one block difference, right before an old piece - // is flushed - TORRENT_ASSERT(m_cache_stats.cache_size <= m_cache_size + 1); - } -#endif - - int disk_io_thread::try_read_from_cache(disk_io_job const& j) - { - TORRENT_ASSERT(j.buffer); - - mutex_t::scoped_lock l(m_piece_mutex); - if (!m_use_read_cache) return -2; - - cache_t::iterator p - = find_cached_piece(m_read_pieces, j, l); - - bool hit = true; - int ret = 0; - - // if the piece cannot be found in the cache, - // read the whole piece starting at the block - // we got a request for. - if (p == m_read_pieces.end()) - { - ret = cache_read_block(j, l); - hit = false; - if (ret < 0) return ret; - p = m_read_pieces.end(); - --p; - TORRENT_ASSERT(!m_read_pieces.empty()); - TORRENT_ASSERT(p->piece == j.piece); - TORRENT_ASSERT(p->storage == j.storage); - } - - if (p != m_read_pieces.end()) - { - // copy from the cache and update the last use timestamp - int block = j.offset / m_block_size; - int block_offset = j.offset % m_block_size; - int buffer_offset = 0; - int size = j.buffer_size; - if (p->blocks[block] == 0) - { - int piece_size = j.storage->info()->piece_size(j.piece); - int blocks_in_piece = (piece_size + m_block_size - 1) / m_block_size; - int end_block = block; - while (end_block < blocks_in_piece && p->blocks[end_block] == 0) ++end_block; - if (!make_room(end_block - block, p, l)) return -2; - ret = read_into_piece(*p, block, l); - hit = false; - if (ret < 0) return ret; - TORRENT_ASSERT(p->blocks[block]); - } - - p->last_use = time_now(); - while (size > 0) - { - TORRENT_ASSERT(p->blocks[block]); - int to_copy = (std::min)(m_block_size - - block_offset, size); - std::memcpy(j.buffer + buffer_offset - , p->blocks[block] + block_offset - , to_copy); - size -= to_copy; - block_offset = 0; - buffer_offset += to_copy; - ++block; - } - ret = j.buffer_size; - ++m_cache_stats.blocks_read; - if (hit) ++m_cache_stats.blocks_read_hit; - } - return ret; - } - - void disk_io_thread::add_job(disk_io_job const& j - , boost::function const& f) - { - TORRENT_ASSERT(!j.callback); - TORRENT_ASSERT(j.storage); - TORRENT_ASSERT(j.buffer_size <= m_block_size); - mutex_t::scoped_lock l(m_queue_mutex); - - std::list::reverse_iterator i = m_jobs.rbegin(); - if (j.action == disk_io_job::read) - { - // when we're reading, we may not skip - // ahead of any write operation that overlaps - // the region we're reading - for (; i != m_jobs.rend(); i++) - { - // if *i should come before j, stop - // and insert j before i - if (*i < j) break; - // if we come across a write operation that - // overlaps the region we're reading, we need - // to stop - if (i->action == disk_io_job::write - && i->storage == j.storage - && i->piece == j.piece - && range_overlap(i->offset, i->buffer_size - , j.offset, j.buffer_size)) - break; - } - } - else if (j.action == disk_io_job::write) - { - for (; i != m_jobs.rend(); ++i) - { - if (*i < j) - { - if (i != m_jobs.rbegin() - && i.base()->storage.get() != j.storage.get()) - i = m_jobs.rbegin(); - break; - } - } - } - - // if we are placed in front of all other jobs, put it on the back of - // the queue, to sweep the disk in the same direction, and to avoid - // starvation. The exception is if the priority is higher than the - // job at the front of the queue - if (i == m_jobs.rend() && (m_jobs.empty() || j.priority <= m_jobs.back().priority)) - i = m_jobs.rbegin(); - - std::list::iterator k = m_jobs.insert(i.base(), j); - k->callback.swap(const_cast&>(f)); - if (j.action == disk_io_job::write) - m_queue_buffer_size += j.buffer_size; - TORRENT_ASSERT(j.storage.get()); - m_signal.notify_all(); - } - -#ifdef TORRENT_DEBUG - bool disk_io_thread::is_disk_buffer(char* buffer) const - { -#ifdef TORRENT_DISABLE_POOL_ALLOCATOR - return true; -#else - mutex_t::scoped_lock l(m_pool_mutex); - return m_pool.is_from(buffer); -#endif - } -#endif - - char* disk_io_thread::allocate_buffer() - { - mutex_t::scoped_lock l(m_pool_mutex); -#ifdef TORRENT_STATS - ++m_allocations; -#endif -#ifdef TORRENT_DISABLE_POOL_ALLOCATOR - return (char*)malloc(m_block_size); -#else - return (char*)m_pool.ordered_malloc(); -#endif - } - - void disk_io_thread::free_buffer(char* buf) - { - mutex_t::scoped_lock l(m_pool_mutex); -#ifdef TORRENT_STATS - --m_allocations; -#endif -#ifdef TORRENT_DISABLE_POOL_ALLOCATOR - free(buf); -#else - m_pool.ordered_free(buf); -#endif - } - - bool disk_io_thread::test_error(disk_io_job& j) - { - error_code const& ec = j.storage->error(); - if (ec) - { - j.str = ec.message(); - j.error = ec; - j.error_file = j.storage->error_file(); - j.storage->clear_error(); -#ifdef TORRENT_DEBUG - std::cout << "ERROR: '" << j.str << "' " << j.error_file << std::endl; -#endif - return true; - } - return false; - } - - void disk_io_thread::operator()() - { - for (;;) - { -#ifdef TORRENT_DISK_STATS - m_log << log_time() << " idle" << std::endl; -#endif - mutex_t::scoped_lock jl(m_queue_mutex); - - while (m_jobs.empty() && !m_abort) - m_signal.wait(jl); - if (m_abort && m_jobs.empty()) - { - jl.unlock(); - - mutex_t::scoped_lock l(m_piece_mutex); - // flush all disk caches - for (cache_t::iterator i = m_pieces.begin() - , end(m_pieces.end()); i != end; ++i) - flush(i, l); - for (cache_t::iterator i = m_read_pieces.begin() - , end(m_read_pieces.end()); i != end; ++i) - free_piece(*i, l); - m_pieces.clear(); - m_read_pieces.clear(); - return; - } - - // if there's a buffer in this job, it will be freed - // when this holder is destructed, unless it has been - // released. - disk_buffer_holder holder(*this - , m_jobs.front().action != disk_io_job::check_fastresume - ? m_jobs.front().buffer : 0); - - boost::function handler; - handler.swap(m_jobs.front().callback); - - disk_io_job j = m_jobs.front(); - m_jobs.pop_front(); - m_queue_buffer_size -= j.buffer_size; - jl.unlock(); - - flush_expired_pieces(); - - int ret = 0; - - TORRENT_ASSERT(j.storage || j.action == disk_io_job::abort_thread); -#ifdef TORRENT_DISK_STATS - ptime start = time_now(); -#endif -#ifndef BOOST_NO_EXCEPTIONS - try { -#endif - - switch (j.action) - { - case disk_io_job::abort_torrent: - { - mutex_t::scoped_lock jl(m_queue_mutex); - for (std::list::iterator i = m_jobs.begin(); - i != m_jobs.end();) - { - if (i->storage != j.storage) - { - ++i; - continue; - } - if (i->action == disk_io_job::check_files) - { - if (i->callback) m_ios.post(bind(i->callback - , piece_manager::disk_check_aborted, *i)); - m_jobs.erase(i++); - continue; - } - ++i; - } - break; - } - case disk_io_job::abort_thread: - { - mutex_t::scoped_lock jl(m_queue_mutex); - m_abort = true; - - for (std::list::iterator i = m_jobs.begin(); - i != m_jobs.end();) - { - if (i->action == disk_io_job::read) - { - if (i->callback) m_ios.post(bind(i->callback, -1, *i)); - m_jobs.erase(i++); - continue; - } - if (i->action == disk_io_job::check_files) - { - if (i->callback) m_ios.post(bind(i->callback - , piece_manager::disk_check_aborted, *i)); - m_jobs.erase(i++); - continue; - } - ++i; - } - break; - } - case disk_io_job::read: - { - if (test_error(j)) - { - ret = -1; - break; - } -#ifdef TORRENT_DISK_STATS - m_log << log_time() << " read " << j.buffer_size << std::endl; -#endif - INVARIANT_CHECK; - TORRENT_ASSERT(j.buffer == 0); - j.buffer = allocate_buffer(); - TORRENT_ASSERT(j.buffer_size <= m_block_size); - if (j.buffer == 0) - { - ret = -1; - j.error = error_code(ENOMEM, get_posix_category()); - j.str = j.error.message(); - break; - } - - disk_buffer_holder read_holder(*this, j.buffer); - ret = try_read_from_cache(j); - - // -2 means there's no space in the read cache - // or that the read cache is disabled - if (ret == -1) - { - j.buffer = 0; - test_error(j); - break; - } - else if (ret == -2) - { - ret = j.storage->read_impl(j.buffer, j.piece, j.offset - , j.buffer_size); - if (ret < 0) - { - test_error(j); - break; - } - ++m_cache_stats.blocks_read; - } - read_holder.release(); - break; - } - case disk_io_job::write: - { - if (test_error(j)) - { - ret = -1; - break; - } -#ifdef TORRENT_DISK_STATS - m_log << log_time() << " write " << j.buffer_size << std::endl; -#endif - mutex_t::scoped_lock l(m_piece_mutex); - INVARIANT_CHECK; - cache_t::iterator p - = find_cached_piece(m_pieces, j, l); - int block = j.offset / m_block_size; - TORRENT_ASSERT(j.buffer); - TORRENT_ASSERT(j.buffer_size <= m_block_size); - if (p != m_pieces.end()) - { - TORRENT_ASSERT(p->blocks[block] == 0); - if (p->blocks[block]) - { - free_buffer(p->blocks[block]); - --p->num_blocks; - } - p->blocks[block] = j.buffer; - ++m_cache_stats.cache_size; - ++p->num_blocks; - p->last_use = time_now(); - } - else - { - cache_block(j, l); - } - // we've now inserted the buffer - // in the cache, we should not - // free it at the end - holder.release(); - if (m_cache_stats.cache_size >= m_cache_size) - flush_oldest_piece(l); - break; - } - case disk_io_job::hash: - { -#ifdef TORRENT_DISK_STATS - m_log << log_time() << " hash" << std::endl; -#endif - mutex_t::scoped_lock l(m_piece_mutex); - INVARIANT_CHECK; - - cache_t::iterator i - = find_cached_piece(m_pieces, j, l); - if (i != m_pieces.end()) - { - flush_and_remove(i, l); - if (test_error(j)) - { - ret = -1; - j.storage->mark_failed(j.piece); - break; - } - } - l.unlock(); - sha1_hash h = j.storage->hash_for_piece_impl(j.piece); - if (test_error(j)) - { - ret = -1; - j.storage->mark_failed(j.piece); - break; - } - ret = (j.storage->info()->hash_for_piece(j.piece) == h)?0:-2; - if (ret == -2) j.storage->mark_failed(j.piece); - break; - } - case disk_io_job::move_storage: - { -#ifdef TORRENT_DISK_STATS - m_log << log_time() << " move" << std::endl; -#endif - TORRENT_ASSERT(j.buffer == 0); - ret = j.storage->move_storage_impl(j.str) ? 1 : 0; - if (ret != 0) - { - test_error(j); - break; - } - j.str = j.storage->save_path().string(); - break; - } - case disk_io_job::release_files: - { -#ifdef TORRENT_DISK_STATS - m_log << log_time() << " release" << std::endl; -#endif - TORRENT_ASSERT(j.buffer == 0); - - mutex_t::scoped_lock l(m_piece_mutex); - INVARIANT_CHECK; - - for (cache_t::iterator i = m_pieces.begin(); i != m_pieces.end();) - { - if (i->storage == j.storage) - { - flush(i, l); - i = m_pieces.erase(i); - } - else - { - ++i; - } - } - l.unlock(); -#ifndef TORRENT_DISABLE_POOL_ALLOCATOR - { - mutex_t::scoped_lock l(m_pool_mutex); - m_pool.release_memory(); - } -#endif - ret = j.storage->release_files_impl(); - if (ret != 0) test_error(j); - break; - } - case disk_io_job::clear_read_cache: - { -#ifdef TORRENT_DISK_STATS - m_log << log_time() << " clear-cache" << std::endl; -#endif - TORRENT_ASSERT(j.buffer == 0); - - mutex_t::scoped_lock l(m_piece_mutex); - INVARIANT_CHECK; - - for (cache_t::iterator i = m_read_pieces.begin(); - i != m_read_pieces.end();) - { - if (i->storage == j.storage) - { - free_piece(*i, l); - i = m_read_pieces.erase(i); - } - else - { - ++i; - } - } - l.unlock(); -#ifndef TORRENT_DISABLE_POOL_ALLOCATOR - { - mutex_t::scoped_lock l(m_pool_mutex); - m_pool.release_memory(); - } -#endif - ret = 0; - break; - } - case disk_io_job::delete_files: - { -#ifdef TORRENT_DISK_STATS - m_log << log_time() << " delete" << std::endl; -#endif - TORRENT_ASSERT(j.buffer == 0); - - mutex_t::scoped_lock l(m_piece_mutex); - INVARIANT_CHECK; - - cache_t::iterator i = std::remove_if( - m_pieces.begin(), m_pieces.end(), bind(&cached_piece_entry::storage, _1) == j.storage); - - for (cache_t::iterator k = i; k != m_pieces.end(); ++k) - { - torrent_info const& ti = *k->storage->info(); - int blocks_in_piece = (ti.piece_size(k->piece) + m_block_size - 1) / m_block_size; - for (int j = 0; j < blocks_in_piece; ++j) - { - if (k->blocks[j] == 0) continue; - free_buffer(k->blocks[j]); - k->blocks[j] = 0; - --m_cache_stats.cache_size; - } - } - m_pieces.erase(i, m_pieces.end()); - l.unlock(); -#ifndef TORRENT_DISABLE_POOL_ALLOCATOR - { - mutex_t::scoped_lock l(m_pool_mutex); - m_pool.release_memory(); - } -#endif - ret = j.storage->delete_files_impl(); - if (ret != 0) test_error(j); - break; - } - case disk_io_job::check_fastresume: - { -#ifdef TORRENT_DISK_STATS - m_log << log_time() << " check fastresume" << std::endl; -#endif - lazy_entry const* rd = (lazy_entry const*)j.buffer; - TORRENT_ASSERT(rd != 0); - ret = j.storage->check_fastresume(*rd, j.str); - break; - } - case disk_io_job::check_files: - { -#ifdef TORRENT_DISK_STATS - m_log << log_time() << " check files" << std::endl; -#endif - int piece_size = j.storage->info()->piece_length(); - for (int processed = 0; processed < 4 * 1024 * 1024; processed += piece_size) - { - ret = j.storage->check_files(j.piece, j.offset, j.str); - -#ifndef BOOST_NO_EXCEPTIONS - try { -#endif - TORRENT_ASSERT(handler); - if (handler && ret == piece_manager::need_full_check) - m_ios.post(bind(handler, ret, j)); -#ifndef BOOST_NO_EXCEPTIONS - } catch (std::exception&) {} -#endif - if (ret != piece_manager::need_full_check) break; - } - if (test_error(j)) - { - ret = piece_manager::fatal_disk_error; - break; - } - TORRENT_ASSERT(ret != -2 || !j.str.empty()); - - // if the check is not done, add it at the end of the job queue - if (ret == piece_manager::need_full_check) - { - add_job(j, handler); - continue; - } - break; - } - case disk_io_job::save_resume_data: - { -#ifdef TORRENT_DISK_STATS - m_log << log_time() << " save resume data" << std::endl; -#endif - j.resume_data.reset(new entry(entry::dictionary_t)); - j.storage->write_resume_data(*j.resume_data); - ret = 0; - break; - } - case disk_io_job::rename_file: - { -#ifdef TORRENT_DISK_STATS - m_log << log_time() << " rename file" << std::endl; -#endif - ret = j.storage->rename_file_impl(j.piece, j.str); - } - } -#ifndef BOOST_NO_EXCEPTIONS - } catch (std::exception& e) - { - ret = -1; - try - { - j.str = e.what(); - } - catch (std::exception&) {} - } -#endif - -// if (!handler) std::cerr << "DISK THREAD: no callback specified" << std::endl; -// else std::cerr << "DISK THREAD: invoking callback" << std::endl; -#ifndef BOOST_NO_EXCEPTIONS - try { -#endif - TORRENT_ASSERT(ret != -2 || !j.str.empty() - || j.action == disk_io_job::hash); - if (handler) m_ios.post(bind(handler, ret, j)); -#ifndef BOOST_NO_EXCEPTIONS - } catch (std::exception&) - { - TORRENT_ASSERT(false); - } -#endif - } - TORRENT_ASSERT(false); - } -} - diff --git a/libtorrent/src/entry.cpp b/libtorrent/src/entry.cpp deleted file mode 100755 index f6c9a8137..000000000 --- a/libtorrent/src/entry.cpp +++ /dev/null @@ -1,419 +0,0 @@ -/* - -Copyright (c) 2003, Arvid Norberg -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions -are met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in - the documentation and/or other materials provided with the distribution. - * Neither the name of the author nor the names of its - contributors may be used to endorse or promote products derived - from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -POSSIBILITY OF SUCH DAMAGE. - -*/ - -#include "libtorrent/pch.hpp" - -#include -#include -#include -#include -#include "libtorrent/entry.hpp" -#include "libtorrent/config.hpp" -#include "libtorrent/escape_string.hpp" - -#if defined(_MSC_VER) -namespace std -{ - using ::isprint; -} -#define for if (false) {} else for -#endif - -namespace -{ - template - void call_destructor(T* o) - { - TORRENT_ASSERT(o); - o->~T(); - } -} - -namespace libtorrent -{ - namespace detail - { - TORRENT_EXPORT char const* integer_to_str(char* buf, int size, entry::integer_type val) - { - int sign = 0; - if (val < 0) - { - sign = 1; - val = -val; - } - buf[--size] = '\0'; - if (val == 0) buf[--size] = '0'; - for (; size > sign && val != 0;) - { - buf[--size] = '0' + char(val % 10); - val /= 10; - } - if (sign) buf[--size] = '-'; - return buf + size; - } - } - - entry& entry::operator[](char const* key) - { - dictionary_type::iterator i = dict().find(key); - if (i != dict().end()) return i->second; - dictionary_type::iterator ret = dict().insert( - dict().begin() - , std::make_pair(key, entry())); - return ret->second; - } - - entry& entry::operator[](std::string const& key) - { - dictionary_type::iterator i = dict().find(key); - if (i != dict().end()) return i->second; - dictionary_type::iterator ret = dict().insert( - dict().begin() - , std::make_pair(std::string(key), entry())); - return ret->second; - } - - entry* entry::find_key(char const* key) - { - dictionary_type::iterator i = dict().find(key); - if (i == dict().end()) return 0; - return &i->second; - } - - entry const* entry::find_key(char const* key) const - { - dictionary_type::const_iterator i = dict().find(key); - if (i == dict().end()) return 0; - return &i->second; - } - - entry* entry::find_key(std::string const& key) - { - dictionary_type::iterator i = dict().find(key); - if (i == dict().end()) return 0; - return &i->second; - } - - entry const* entry::find_key(std::string const& key) const - { - dictionary_type::const_iterator i = dict().find(key); - if (i == dict().end()) return 0; - return &i->second; - } - -#ifndef BOOST_NO_EXCEPTIONS - const entry& entry::operator[](char const* key) const - { - dictionary_type::const_iterator i = dict().find(key); - if (i == dict().end()) throw type_error( - (std::string("key not found: ") + key).c_str()); - return i->second; - } - - const entry& entry::operator[](std::string const& key) const - { - return (*this)[key.c_str()]; - } -#endif - - entry::entry() - : m_type(undefined_t) - { -#ifdef TORRENT_DEBUG - m_type_queried = true; -#endif - } - - entry::entry(data_type t) - : m_type(undefined_t) - { - construct(t); -#ifdef TORRENT_DEBUG - m_type_queried = true; -#endif - } - - entry::entry(const entry& e) - : m_type(undefined_t) - { - copy(e); -#ifdef TORRENT_DEBUG - m_type_queried = e.m_type_queried; -#endif - } - - entry::entry(dictionary_type const& v) - : m_type(undefined_t) - { -#ifdef TORRENT_DEBUG - m_type_queried = true; -#endif - new(data) dictionary_type(v); - m_type = dictionary_t; - } - - entry::entry(string_type const& v) - : m_type(undefined_t) - { -#ifdef TORRENT_DEBUG - m_type_queried = true; -#endif - new(data) string_type(v); - m_type = string_t; - } - - entry::entry(list_type const& v) - : m_type(undefined_t) - { -#ifdef TORRENT_DEBUG - m_type_queried = true; -#endif - new(data) list_type(v); - m_type = list_t; - } - - entry::entry(integer_type const& v) - : m_type(undefined_t) - { -#ifdef TORRENT_DEBUG - m_type_queried = true; -#endif - new(data) integer_type(v); - m_type = int_t; - } - - void entry::operator=(dictionary_type const& v) - { - destruct(); - new(data) dictionary_type(v); - m_type = dictionary_t; -#ifdef TORRENT_DEBUG - m_type_queried = true; -#endif - } - - void entry::operator=(string_type const& v) - { - destruct(); - new(data) string_type(v); - m_type = string_t; -#ifdef TORRENT_DEBUG - m_type_queried = true; -#endif - } - - void entry::operator=(list_type const& v) - { - destruct(); - new(data) list_type(v); - m_type = list_t; -#ifdef TORRENT_DEBUG - m_type_queried = true; -#endif - } - - void entry::operator=(integer_type const& v) - { - destruct(); - new(data) integer_type(v); - m_type = int_t; -#ifdef TORRENT_DEBUG - m_type_queried = true; -#endif - } - - bool entry::operator==(entry const& e) const - { - if (m_type != e.m_type) return false; - - switch(m_type) - { - case int_t: - return integer() == e.integer(); - case string_t: - return string() == e.string(); - case list_t: - return list() == e.list(); - case dictionary_t: - return dict() == e.dict(); - default: - TORRENT_ASSERT(m_type == undefined_t); - return true; - } - } - - void entry::construct(data_type t) - { - switch(t) - { - case int_t: - new(data) integer_type; - break; - case string_t: - new(data) string_type; - break; - case list_t: - new(data) list_type; - break; - case dictionary_t: - new (data) dictionary_type; - break; - default: - TORRENT_ASSERT(t == undefined_t); - } - m_type = t; -#ifdef TORRENT_DEBUG - m_type_queried = true; -#endif - } - - void entry::copy(entry const& e) - { - switch (e.type()) - { - case int_t: - new(data) integer_type(e.integer()); - break; - case string_t: - new(data) string_type(e.string()); - break; - case list_t: - new(data) list_type(e.list()); - break; - case dictionary_t: - new (data) dictionary_type(e.dict()); - break; - default: - TORRENT_ASSERT(e.type() == undefined_t); - } - m_type = e.type(); -#ifdef TORRENT_DEBUG - m_type_queried = true; -#endif - } - - void entry::destruct() - { - switch(m_type) - { - case int_t: - call_destructor(reinterpret_cast(data)); - break; - case string_t: - call_destructor(reinterpret_cast(data)); - break; - case list_t: - call_destructor(reinterpret_cast(data)); - break; - case dictionary_t: - call_destructor(reinterpret_cast(data)); - break; - default: - TORRENT_ASSERT(m_type == undefined_t); - break; - } - m_type = undefined_t; -#ifdef TORRENT_DEBUG - m_type_queried = false; -#endif - } - - void entry::swap(entry& e) - { - // not implemented - TORRENT_ASSERT(false); - } - - void entry::print(std::ostream& os, int indent) const - { - TORRENT_ASSERT(indent >= 0); - for (int i = 0; i < indent; ++i) os << " "; - switch (m_type) - { - case int_t: - os << integer() << "\n"; - break; - case string_t: - { - bool binary_string = false; - for (std::string::const_iterator i = string().begin(); i != string().end(); ++i) - { - if (!std::isprint(static_cast(*i))) - { - binary_string = true; - break; - } - } - if (binary_string) os << to_hex(string()) << "\n"; - else os << string() << "\n"; - } break; - case list_t: - { - os << "list\n"; - for (list_type::const_iterator i = list().begin(); i != list().end(); ++i) - { - i->print(os, indent+1); - } - } break; - case dictionary_t: - { - os << "dictionary\n"; - for (dictionary_type::const_iterator i = dict().begin(); i != dict().end(); ++i) - { - bool binary_string = false; - for (std::string::const_iterator k = i->first.begin(); k != i->first.end(); ++k) - { - if (!std::isprint(static_cast(*k))) - { - binary_string = true; - break; - } - } - for (int j = 0; j < indent+1; ++j) os << " "; - os << "["; - if (binary_string) os << to_hex(i->first); - else os << i->first; - os << "]"; - - if (i->second.type() != entry::string_t - && i->second.type() != entry::int_t) - os << "\n"; - else os << " "; - i->second.print(os, indent+2); - } - } break; - default: - os << "\n"; - } - } -} - diff --git a/libtorrent/src/enum_net.cpp b/libtorrent/src/enum_net.cpp deleted file mode 100644 index babdd94b9..000000000 --- a/libtorrent/src/enum_net.cpp +++ /dev/null @@ -1,638 +0,0 @@ -/* - -Copyright (c) 2007, Arvid Norberg -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions -are met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in - the documentation and/or other materials provided with the distribution. - * Neither the name of the author nor the names of its - contributors may be used to endorse or promote products derived - from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -POSSIBILITY OF SUCH DAMAGE. - -*/ - -#include "libtorrent/config.hpp" -#include -#include -#include "libtorrent/enum_net.hpp" -#include "libtorrent/broadcast_socket.hpp" -#if BOOST_VERSION < 103500 -#include -#else -#include -#endif - -#if defined TORRENT_BSD || defined TORRENT_SOLARIS -#include -#include -#include -#include -#include -#include -#include -#endif - -#if defined TORRENT_BSD -#include -#endif - -#if defined TORRENT_WINDOWS -#ifndef WIN32_LEAN_AND_MEAN -#define WIN32_LEAN_AND_MEAN -#endif -#include -#include -#endif - -#if defined TORRENT_LINUX -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#endif - -namespace libtorrent { namespace -{ - - address inaddr_to_address(in_addr const* ina) - { - typedef asio::ip::address_v4::bytes_type bytes_t; - bytes_t b; - std::memcpy(&b[0], ina, b.size()); - return address_v4(b); - } - - address inaddr6_to_address(in6_addr const* ina6) - { - typedef asio::ip::address_v6::bytes_type bytes_t; - bytes_t b; - std::memcpy(&b[0], ina6, b.size()); - return address_v6(b); - } - - address sockaddr_to_address(sockaddr const* sin) - { - if (sin->sa_family == AF_INET) - return inaddr_to_address(&((sockaddr_in const*)sin)->sin_addr); - else if (sin->sa_family == AF_INET6) - return inaddr6_to_address(&((sockaddr_in6 const*)sin)->sin6_addr); - return address(); - } - -#if defined TORRENT_LINUX - - int read_nl_sock(int sock, char *buf, int bufsize, int seq, int pid) - { - nlmsghdr* nl_hdr; - - int msg_len = 0; - - do - { - int read_len = recv(sock, buf, bufsize - msg_len, 0); - if (read_len < 0) return -1; - - nl_hdr = (nlmsghdr*)buf; - - if ((NLMSG_OK(nl_hdr, read_len) == 0) || (nl_hdr->nlmsg_type == NLMSG_ERROR)) - return -1; - - if (nl_hdr->nlmsg_type == NLMSG_DONE) break; - - buf += read_len; - msg_len += read_len; - - if ((nl_hdr->nlmsg_flags & NLM_F_MULTI) == 0) break; - - } while((nl_hdr->nlmsg_seq != seq) || (nl_hdr->nlmsg_pid != pid)); - return msg_len; - } - - bool parse_route(nlmsghdr* nl_hdr, ip_route* rt_info) - { - rtmsg* rt_msg = (rtmsg*)NLMSG_DATA(nl_hdr); - - if((rt_msg->rtm_family != AF_INET) || (rt_msg->rtm_table != RT_TABLE_MAIN)) - return false; - - int rt_len = RTM_PAYLOAD(nl_hdr); - for (rtattr* rt_attr = (rtattr*)RTM_RTA(rt_msg); - RTA_OK(rt_attr,rt_len); rt_attr = RTA_NEXT(rt_attr,rt_len)) - { - switch(rt_attr->rta_type) - { - case RTA_OIF: - if_indextoname(*(int*)RTA_DATA(rt_attr), rt_info->name); - break; - case RTA_GATEWAY: - rt_info->gateway = address_v4(ntohl(*(u_int*)RTA_DATA(rt_attr))); - break; - case RTA_DST: - rt_info->destination = address_v4(ntohl(*(u_int*)RTA_DATA(rt_attr))); - break; - } - } - return true; - } -#endif - -#if defined TORRENT_BSD - - bool parse_route(rt_msghdr* rtm, ip_route* rt_info) - { - sockaddr* rti_info[RTAX_MAX]; - sockaddr* sa = (sockaddr*)(rtm + 1); - for (int i = 0; i < RTAX_MAX; ++i) - { - if ((rtm->rtm_addrs & (1 << i)) == 0) - { - rti_info[i] = 0; - continue; - } - rti_info[i] = sa; - -#define ROUNDUP(a) \ - ((a) > 0 ? (1 + (((a) - 1) | (sizeof(long) - 1))) : sizeof(long)) - - sa = (sockaddr*)((char*)(sa) + ROUNDUP(sa->sa_len)); - -#undef ROUNDUP - } - - sa = rti_info[RTAX_GATEWAY]; - if (sa == 0 - || rti_info[RTAX_DST] == 0 - || rti_info[RTAX_NETMASK] == 0 - || (sa->sa_family != AF_INET && sa->sa_family != AF_INET6)) - return false; - - rt_info->gateway = sockaddr_to_address(rti_info[RTAX_GATEWAY]); - rt_info->netmask = sockaddr_to_address(rti_info[RTAX_NETMASK]); - rt_info->destination = sockaddr_to_address(rti_info[RTAX_DST]); - if_indextoname(rtm->rtm_index, rt_info->name); - return true; - } -#endif - - -#ifdef TORRENT_BSD - bool verify_sockaddr(sockaddr_in* sin) - { - return (sin->sin_len == sizeof(sockaddr_in) - && sin->sin_family == AF_INET) - || (sin->sin_len == sizeof(sockaddr_in6) - && sin->sin_family == AF_INET6); - } -#endif - -}} // - -namespace libtorrent -{ - - bool in_subnet(address const& addr, ip_interface const& iface) - { - if (addr.is_v4() != iface.interface_address.is_v4()) return false; - // since netmasks seems unreliable for IPv6 interfaces - // (MacOS X returns AF_INET addresses as bitmasks) assume - // that any IPv6 address belongs to the subnet of any - // interface with an IPv6 address - if (addr.is_v6()) return true; - - return (addr.to_v4().to_ulong() & iface.netmask.to_v4().to_ulong()) - == (iface.interface_address.to_v4().to_ulong() & iface.netmask.to_v4().to_ulong()); - } - - bool in_local_network(io_service& ios, address const& addr, error_code& ec) - { - std::vector net = enum_net_interfaces(ios, ec); - if (ec) return false; - for (std::vector::iterator i = net.begin() - , end(net.end()); i != end; ++i) - { - if (in_subnet(addr, *i)) return true; - } - return false; - } - - std::vector enum_net_interfaces(io_service& ios, error_code& ec) - { - std::vector ret; -// covers linux, MacOS X and BSD distributions -#if defined TORRENT_LINUX || defined TORRENT_BSD || defined TORRENT_SOLARIS - int s = socket(AF_INET, SOCK_DGRAM, 0); - if (s < 0) - { - ec = error_code(errno, asio::error::system_category); - return ret; - } - ifconf ifc; - char buf[1024]; - ifc.ifc_len = sizeof(buf); - ifc.ifc_buf = buf; - if (ioctl(s, SIOCGIFCONF, &ifc) < 0) - { - ec = error_code(errno, asio::error::system_category); - close(s); - return ret; - } - - char *ifr = (char*)ifc.ifc_req; - int remaining = ifc.ifc_len; - - while (remaining) - { - ifreq const& item = *reinterpret_cast(ifr); - - if (item.ifr_addr.sa_family == AF_INET - || item.ifr_addr.sa_family == AF_INET6) - { - ip_interface iface; - iface.interface_address = sockaddr_to_address(&item.ifr_addr); - strcpy(iface.name, item.ifr_name); - - ifreq netmask = item; - if (ioctl(s, SIOCGIFNETMASK, &netmask) < 0) - { - if (iface.interface_address.is_v6()) - { - // this is expected to fail (at least on MacOS X) - iface.netmask = address_v6::any(); - } - else - { - ec = error_code(errno, asio::error::system_category); - close(s); - return ret; - } - } - else - { - iface.netmask = sockaddr_to_address(&netmask.ifr_addr); - } - ret.push_back(iface); - } - -#if defined TORRENT_BSD - int current_size = item.ifr_addr.sa_len + IFNAMSIZ; -#elif defined TORRENT_LINUX || defined TORRENT_SOLARIS - int current_size = sizeof(ifreq); -#endif - ifr += current_size; - remaining -= current_size; - } - close(s); - -#elif defined TORRENT_WINDOWS - - SOCKET s = socket(AF_INET, SOCK_DGRAM, 0); - if (s == SOCKET_ERROR) - { - ec = error_code(WSAGetLastError(), asio::error::system_category); - return ret; - } - - INTERFACE_INFO buffer[30]; - DWORD size; - - if (WSAIoctl(s, SIO_GET_INTERFACE_LIST, 0, 0, buffer, - sizeof(buffer), &size, 0, 0) != 0) - { - ec = error_code(WSAGetLastError(), asio::error::system_category); - closesocket(s); - return ret; - } - closesocket(s); - - int n = size / sizeof(INTERFACE_INFO); - - ip_interface iface; - for (int i = 0; i < n; ++i) - { - iface.interface_address = sockaddr_to_address(&buffer[i].iiAddress.Address); - iface.netmask = sockaddr_to_address(&buffer[i].iiNetmask.Address); - iface.name[0] = 0; - if (iface.interface_address == address_v4::any()) continue; - ret.push_back(iface); - } - -#else -#warning THIS OS IS NOT RECOGNIZED, enum_net_interfaces WILL PROBABLY NOT WORK - // make a best guess of the interface we're using and its IP - udp::resolver r(ios); - udp::resolver::iterator i = r.resolve(udp::resolver::query(asio::ip::host_name(ec), "0"), ec); - if (ec) return ret; - ip_interface iface; - for (;i != udp::resolver_iterator(); ++i) - { - iface.interface_address = i->endpoint().address(); - if (iface.interface_address.is_v4()) - iface.netmask = address_v4::netmask(iface.interface_address.to_v4()); - ret.push_back(iface); - } -#endif - return ret; - } - - address get_default_gateway(io_service& ios, error_code& ec) - { - std::vector ret = enum_routes(ios, ec); -#ifdef TORRENT_WINDOWS - std::vector::iterator i = std::find_if(ret.begin(), ret.end() - , boost::bind(&is_loopback, boost::bind(&ip_route::destination, _1))); -#else - std::vector::iterator i = std::find_if(ret.begin(), ret.end() - , boost::bind(&ip_route::destination, _1) == address()); -#endif - if (i == ret.end()) return address(); - return i->gateway; - } - - std::vector enum_routes(io_service& ios, error_code& ec) - { - std::vector ret; - -#if defined TORRENT_BSD -/* - struct rt_msg - { - rt_msghdr m_rtm; - char buf[512]; - }; - - rt_msg m; - int len = sizeof(rt_msg); - bzero(&m, len); - m.m_rtm.rtm_type = RTM_GET; - m.m_rtm.rtm_flags = RTF_UP | RTF_GATEWAY; - m.m_rtm.rtm_version = RTM_VERSION; - m.m_rtm.rtm_addrs = RTA_DST | RTA_GATEWAY | RTA_NETMASK; - m.m_rtm.rtm_seq = 0; - m.m_rtm.rtm_msglen = len; - - int s = socket(PF_ROUTE, SOCK_RAW, AF_UNSPEC); - if (s == -1) - { - ec = error_code(errno, asio::error::system_category); - return std::vector(); - } - - int n = write(s, &m, len); - if (n == -1) - { - ec = error_code(errno, asio::error::system_category); - close(s); - return std::vector(); - } - else if (n != len) - { - ec = asio::error::operation_not_supported; - close(s); - return std::vector(); - } - bzero(&m, len); - - n = read(s, &m, len); - if (n == -1) - { - ec = error_code(errno, asio::error::system_category); - close(s); - return std::vector(); - } - - for (rt_msghdr* ptr = &m.m_rtm; (char*)ptr < ((char*)&m.m_rtm) + n; ptr = (rt_msghdr*)(((char*)ptr) + ptr->rtm_msglen)) - { - std::cout << " rtm_msglen: " << ptr->rtm_msglen << std::endl; - std::cout << " rtm_type: " << ptr->rtm_type << std::endl; - if (ptr->rtm_errno) - { - ec = error_code(ptr->rtm_errno, asio::error::system_category); - return std::vector(); - } - if (m.m_rtm.rtm_flags & RTF_UP == 0 - || m.m_rtm.rtm_flags & RTF_GATEWAY == 0) - { - ec = asio::error::operation_not_supported; - return address_v4::any(); - } - if (ptr->rtm_addrs & RTA_DST == 0 - || ptr->rtm_addrs & RTA_GATEWAY == 0 - || ptr->rtm_addrs & RTA_NETMASK == 0) - { - ec = asio::error::operation_not_supported; - return std::vector(); - } - if (ptr->rtm_msglen > len - ((char*)ptr - ((char*)&m.m_rtm))) - { - ec = asio::error::operation_not_supported; - return std::vector(); - } - int min_len = sizeof(rt_msghdr) + 2 * sizeof(sockaddr_in); - if (m.m_rtm.rtm_msglen < min_len) - { - ec = asio::error::operation_not_supported; - return std::vector(); - } - - ip_route r; - // destination - char* p = m.buf; - sockaddr_in* sin = (sockaddr_in*)p; - r.destination = sockaddr_to_address((sockaddr*)p); - - // gateway - p += sin->sin_len; - sin = (sockaddr_in*)p; - r.gateway = sockaddr_to_address((sockaddr*)p); - - // netmask - p += sin->sin_len; - sin = (sockaddr_in*)p; - r.netmask = sockaddr_to_address((sockaddr*)p); - ret.push_back(r); - } - close(s); -*/ - int mib[6] = { CTL_NET, PF_ROUTE, 0, AF_UNSPEC, NET_RT_DUMP, 0}; - - size_t needed = 0; - if (sysctl(mib, 6, 0, &needed, 0, 0) < 0) - { - ec = error_code(errno, asio::error::system_category); - return std::vector(); - } - - if (needed <= 0) - { - return std::vector(); - } - - boost::scoped_array buf(new (std::nothrow) char[needed]); - if (buf.get() == 0) - { - ec = asio::error::no_memory; - return std::vector(); - } - - if (sysctl(mib, 6, buf.get(), &needed, 0, 0) < 0) - { - ec = error_code(errno, asio::error::system_category); - return std::vector(); - } - - char* end = buf.get() + needed; - - rt_msghdr* rtm; - for (char* next = buf.get(); next < end; next += rtm->rtm_msglen) - { - rtm = (rt_msghdr*)next; - if (rtm->rtm_version != RTM_VERSION) - continue; - - ip_route r; - if (parse_route(rtm, &r)) ret.push_back(r); - } - -#elif defined TORRENT_WINDOWS - - // Load Iphlpapi library - HMODULE iphlp = LoadLibraryA("Iphlpapi.dll"); - if (!iphlp) - { - ec = asio::error::operation_not_supported; - return std::vector(); - } - - // Get GetAdaptersInfo() pointer - typedef DWORD (WINAPI *GetAdaptersInfo_t)(PIP_ADAPTER_INFO, PULONG); - GetAdaptersInfo_t GetAdaptersInfo = (GetAdaptersInfo_t)GetProcAddress(iphlp, "GetAdaptersInfo"); - if (!GetAdaptersInfo) - { - FreeLibrary(iphlp); - ec = asio::error::operation_not_supported; - return std::vector(); - } - - PIP_ADAPTER_INFO adapter_info = 0; - ULONG out_buf_size = 0; - if (GetAdaptersInfo(adapter_info, &out_buf_size) != ERROR_BUFFER_OVERFLOW) - { - FreeLibrary(iphlp); - ec = asio::error::operation_not_supported; - return std::vector(); - } - - adapter_info = (IP_ADAPTER_INFO*)malloc(out_buf_size); - if (!adapter_info) - { - FreeLibrary(iphlp); - ec = asio::error::no_memory; - return std::vector(); - } - - if (GetAdaptersInfo(adapter_info, &out_buf_size) == NO_ERROR) - { - for (PIP_ADAPTER_INFO adapter = adapter_info; - adapter != 0; adapter = adapter->Next) - { - - ip_route r; - r.destination = address::from_string(adapter->IpAddressList.IpAddress.String, ec); - r.gateway = address::from_string(adapter->GatewayList.IpAddress.String, ec); - r.netmask = address::from_string(adapter->IpAddressList.IpMask.String, ec); - strncpy(r.name, adapter->AdapterName, sizeof(r.name)); - - if (ec) - { - ec = error_code(); - continue; - } - ret.push_back(r); - } - } - - // Free memory - free(adapter_info); - FreeLibrary(iphlp); - -#elif defined TORRENT_LINUX - - enum { BUFSIZE = 8192 }; - - int sock = socket(PF_ROUTE, SOCK_DGRAM, NETLINK_ROUTE); - if (sock < 0) - { - ec = error_code(errno, asio::error::system_category); - return std::vector(); - } - - int seq = 0; - - char msg[BUFSIZE]; - memset(msg, 0, BUFSIZE); - nlmsghdr* nl_msg = (nlmsghdr*)msg; - - nl_msg->nlmsg_len = NLMSG_LENGTH(sizeof(rtmsg)); - nl_msg->nlmsg_type = RTM_GETROUTE; - nl_msg->nlmsg_flags = NLM_F_DUMP | NLM_F_REQUEST; - nl_msg->nlmsg_seq = seq++; - nl_msg->nlmsg_pid = getpid(); - - if (send(sock, nl_msg, nl_msg->nlmsg_len, 0) < 0) - { - ec = error_code(errno, asio::error::system_category); - close(sock); - return std::vector(); - } - - int len = read_nl_sock(sock, msg, BUFSIZE, seq, getpid()); - if (len < 0) - { - ec = error_code(errno, asio::error::system_category); - close(sock); - return std::vector(); - } - - for (; NLMSG_OK(nl_msg, len); nl_msg = NLMSG_NEXT(nl_msg, len)) - { - ip_route r; - if (parse_route(nl_msg, &r)) ret.push_back(r); - } - close(sock); - -#endif - return ret; - } - -} - - diff --git a/libtorrent/src/error_code.cpp b/libtorrent/src/error_code.cpp deleted file mode 100644 index cdb33eeec..000000000 --- a/libtorrent/src/error_code.cpp +++ /dev/null @@ -1,60 +0,0 @@ -/* - -Copyright (c) 2008, Arvid Norberg -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions -are met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in - the documentation and/or other materials provided with the distribution. - * Neither the name of the author nor the names of its - contributors may be used to endorse or promote products derived - from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -POSSIBILITY OF SUCH DAMAGE. - -*/ - -#include - -#if BOOST_VERSION >= 103500 - -#include "libtorrent/error_code.hpp" - -namespace libtorrent -{ - const char* libtorrent_error_category::name() const - { - return "libtorrent error"; - } - - std::string libtorrent_error_category::message(int ev) const - { - static char const* msgs[] = - { "no error", "torrent file collides with file from another torrent" }; - if (ev < 0 || ev >= sizeof(msgs)/sizeof(msgs[0])) - return "Unknown error"; - return msgs[ev]; - } - - libtorrent_error_category libtorrent_category; - -} - -#endif - diff --git a/libtorrent/src/escape_string.cpp b/libtorrent/src/escape_string.cpp deleted file mode 100755 index 39c02a9a6..000000000 --- a/libtorrent/src/escape_string.cpp +++ /dev/null @@ -1,401 +0,0 @@ -/* - -Copyright (c) 2003, Arvid Norberg -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions -are met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in - the documentation and/or other materials provided with the distribution. - * Neither the name of the author nor the names of its - contributors may be used to endorse or promote products derived - from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -POSSIBILITY OF SUCH DAMAGE. - -*/ - -#include "libtorrent/pch.hpp" - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#include "libtorrent/assert.hpp" -#include "libtorrent/escape_string.hpp" - -namespace libtorrent -{ - - // lexical_cast's result depends on the locale. We need - // a well defined result - boost::array::digits10> to_string(size_type n) - { - boost::array::digits10> ret; - char *p = &ret.back();; - *p = '\0'; - unsigned_size_type un = n; - if (n < 0) un = -un; - do { - *--p = '0' + un % 10; - un /= 10; - } while (un); - if (n < 0) *--p = '-'; - std::memmove(&ret.front(), p, sizeof(ret.elems)); - return ret; - } - - bool is_digit(char c) - { - return c >= '0' && c <= '9'; - } - - bool isprint(char c) - { - return c >= 32 && c < 127; - } - - std::string unescape_string(std::string const& s) - { - std::string ret; - for (std::string::const_iterator i = s.begin(); i != s.end(); ++i) - { - if(*i == '+') - { - ret += ' '; - } - else if (*i != '%') - { - ret += *i; - } - else - { - ++i; - if (i == s.end()) -#ifdef BOOST_NO_EXCEPTIONS - return ret; -#else - throw std::runtime_error("invalid escaped string"); -#endif - - int high; - if(*i >= '0' && *i <= '9') high = *i - '0'; - else if(*i >= 'A' && *i <= 'F') high = *i + 10 - 'A'; - else if(*i >= 'a' && *i <= 'f') high = *i + 10 - 'a'; - else -#ifdef BOOST_NO_EXCEPTIONS - return ret; -#else - throw std::runtime_error("invalid escaped string"); -#endif - - ++i; - if (i == s.end()) -#ifdef BOOST_NO_EXCEPTIONS - return ret; -#else - throw std::runtime_error("invalid escaped string"); -#endif - - int low; - if(*i >= '0' && *i <= '9') low = *i - '0'; - else if(*i >= 'A' && *i <= 'F') low = *i + 10 - 'A'; - else if(*i >= 'a' && *i <= 'f') low = *i + 10 - 'a'; - else -#ifdef BOOST_NO_EXCEPTIONS - return ret; -#else - throw std::runtime_error("invalid escaped string"); -#endif - - ret += char(high * 16 + low); - } - } - return ret; - } - - std::string escape_string(const char* str, int len) - { - TORRENT_ASSERT(str != 0); - TORRENT_ASSERT(len >= 0); - // http://www.ietf.org/rfc/rfc2396.txt - // section 2.3 - // some trackers seems to require that ' is escaped -// static const char unreserved_chars[] = "-_.!~*'()"; - static const char unreserved_chars[] = "-_.!~*()" - "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz" - "0123456789"; - - std::stringstream ret; - ret << std::hex << std::setfill('0'); - for (int i = 0; i < len; ++i) - { - if (std::count( - unreserved_chars - , unreserved_chars+sizeof(unreserved_chars)-1 - , *str)) - { - ret << *str; - } - else - { - ret << '%' - << std::setw(2) - << (int)static_cast(*str); - } - ++str; - } - return ret.str(); - } - - std::string escape_path(const char* str, int len) - { - TORRENT_ASSERT(str != 0); - TORRENT_ASSERT(len >= 0); - static const char unreserved_chars[] = "/-_.!~*()" - "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz" - "0123456789"; - - std::stringstream ret; - ret << std::hex << std::setfill('0'); - for (int i = 0; i < len; ++i) - { - if (std::count( - unreserved_chars - , unreserved_chars+sizeof(unreserved_chars)-1 - , *str)) - { - ret << *str; - } - else - { - ret << '%' - << std::setw(2) - << (int)static_cast(*str); - } - ++str; - } - return ret.str(); - } - - std::string base64encode(const std::string& s) - { - static const char base64_table[] = - { - 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', - 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', - 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', - 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', - 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', - 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', - 'w', 'x', 'y', 'z', '0', '1', '2', '3', - '4', '5', '6', '7', '8', '9', '+', '/' - }; - - unsigned char inbuf[3]; - unsigned char outbuf[4]; - - std::string ret; - for (std::string::const_iterator i = s.begin(); i != s.end();) - { - // available input is 1,2 or 3 bytes - // since we read 3 bytes at a time at most - int available_input = (std::min)(3, (int)std::distance(i, s.end())); - - // clear input buffer - std::fill(inbuf, inbuf+3, 0); - - // read a chunk of input into inbuf - std::copy(i, i + available_input, inbuf); - i += available_input; - - // encode inbuf to outbuf - outbuf[0] = (inbuf[0] & 0xfc) >> 2; - outbuf[1] = ((inbuf[0] & 0x03) << 4) | ((inbuf [1] & 0xf0) >> 4); - outbuf[2] = ((inbuf[1] & 0x0f) << 2) | ((inbuf [2] & 0xc0) >> 6); - outbuf[3] = inbuf[2] & 0x3f; - - // write output - for (int j = 0; j < available_input+1; ++j) - { - ret += base64_table[outbuf[j]]; - } - - // write pad - for (int j = 0; j < 3 - available_input; ++j) - { - ret += '='; - } - } - return ret; - } - - std::string base32encode(std::string const& s) - { - static const char base32_table[] = - { - 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', - 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', - 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', - 'Y', 'Z', '2', '3', '4', '5', '6', '7' - }; - - int input_output_mapping[] = {0, 2, 4, 5, 7, 8}; - - unsigned char inbuf[5]; - unsigned char outbuf[8]; - - std::string ret; - for (std::string::const_iterator i = s.begin(); i != s.end();) - { - int available_input = (std::min)(5, (int)std::distance(i, s.end())); - - // clear input buffer - std::fill(inbuf, inbuf+5, 0); - - // read a chunk of input into inbuf - std::copy(i, i + available_input, inbuf); - i += available_input; - - // encode inbuf to outbuf - outbuf[0] = (inbuf[0] & 0xf8) >> 3; - outbuf[1] = ((inbuf[0] & 0x07) << 2) | ((inbuf[1] & 0xc0) >> 6); - outbuf[2] = ((inbuf[1] & 0x3e) >> 1); - outbuf[3] = ((inbuf[1] & 0x01) << 4) | ((inbuf[2] & 0xf0) >> 4); - outbuf[4] = ((inbuf[2] & 0x0f) << 1) | ((inbuf[3] & 0x80) >> 7); - outbuf[5] = ((inbuf[3] & 0x7c) >> 2); - outbuf[6] = ((inbuf[3] & 0x03) << 3) | ((inbuf[4] & 0xe0) >> 5); - outbuf[7] = inbuf[4] & 0x1f; - - // write output - int num_out = input_output_mapping[available_input]; - for (int j = 0; j < num_out; ++j) - { - ret += base32_table[outbuf[j]]; - } - - // write pad - for (int j = 0; j < 8 - num_out; ++j) - { - ret += '='; - } - } - return ret; - } - - std::string base32decode(std::string const& s) - { - unsigned char inbuf[8]; - unsigned char outbuf[5]; - - std::string ret; - for (std::string::const_iterator i = s.begin(); i != s.end();) - { - int available_input = (std::min)(8, (int)std::distance(i, s.end())); - - int pad_start = 0; - if (available_input < 8) pad_start = available_input; - - // clear input buffer - std::fill(inbuf, inbuf+8, 0); - for (int j = 0; j < available_input; ++j) - { - char in = std::toupper(*i++); - if (in >= 'A' && in <= 'Z') - inbuf[j] = in - 'A'; - else if (in >= '2' && in <= '7') - inbuf[j] = in - '2' + ('Z' - 'A') + 1; - else if (in == '=') - { - inbuf[j] = 0; - if (pad_start == 0) pad_start = j; - } - else if (in == '1') - inbuf[j] = 'I' - 'A'; - else - return std::string(); - TORRENT_ASSERT(inbuf[j] == (inbuf[j] & 0x1f)); - } - - // decode inbuf to outbuf - outbuf[0] = inbuf[0] << 3; - outbuf[0] |= inbuf[1] >> 2; - outbuf[1] = (inbuf[1] & 0x3) << 6; - outbuf[1] |= inbuf[2] << 1; - outbuf[1] |= (inbuf[3] & 0x10) >> 4; - outbuf[2] = (inbuf[3] & 0x0f) << 4; - outbuf[2] |= (inbuf[4] & 0x1e) >> 1; - outbuf[3] = (inbuf[4] & 0x01) << 7; - outbuf[3] |= (inbuf[5] & 0x1f) << 2; - outbuf[3] |= (inbuf[6] & 0x18) >> 3; - outbuf[4] = (inbuf[6] & 0x07) << 5; - outbuf[4] |= inbuf[7]; - - int input_output_mapping[] = {5, 1, 1, 2, 2, 3, 4, 4, 5}; - int num_out = input_output_mapping[pad_start]; - - // write output - std::copy(outbuf, outbuf + num_out, std::back_inserter(ret)); - } - return ret; - } - - boost::optional url_has_argument( - std::string const& url, std::string argument) - { - size_t i = url.find('?'); - if (i == std::string::npos) return boost::optional(); - ++i; - - argument += '='; - - if (url.compare(i, argument.size(), argument) == 0) - { - size_t pos = i + argument.size(); - return url.substr(pos, url.find('&', pos) - pos); - } - argument.insert(0, "&"); - i = url.find(argument, i); - if (i == std::string::npos) return boost::optional(); - size_t pos = i + argument.size(); - return url.substr(pos, url.find('&', pos) - pos); - } - - TORRENT_EXPORT std::string to_hex(std::string const& s) - { - std::string ret; - char const* digits = "0123456789abcdef"; - for (std::string::const_iterator i = s.begin(); i != s.end(); ++i) - { - ret += digits[((unsigned char)*i) >> 4]; - ret += digits[((unsigned char)*i) & 0xf]; - } - return ret; - } - -} - diff --git a/libtorrent/src/file.cpp b/libtorrent/src/file.cpp deleted file mode 100755 index 390baf341..000000000 --- a/libtorrent/src/file.cpp +++ /dev/null @@ -1,367 +0,0 @@ -/* - -Copyright (c) 2003, Arvid Norberg -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions -are met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in - the documentation and/or other materials provided with the distribution. - * Neither the name of the author nor the names of its - contributors may be used to endorse or promote products derived - from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -POSSIBILITY OF SUCH DAMAGE. - -*/ - -#include "libtorrent/pch.hpp" -#include "libtorrent/config.hpp" - -#include -#ifdef TORRENT_WINDOWS -// windows part -#include "libtorrent/utf8.hpp" - -#include -#include - -#else -// posix part -#define _FILE_OFFSET_BITS 64 -#include -#include -#include -#include -#include - -#include -// make sure the _FILE_OFFSET_BITS define worked -// on this platform -BOOST_STATIC_ASSERT(sizeof(lseek(0, 0, 0)) >= 8); - -#endif - -#include -#include "libtorrent/file.hpp" -#include -#include -#include - -#ifndef O_BINARY -#define O_BINARY 0 -#endif - -#ifndef O_RANDOM -#define O_RANDOM 0 -#endif - -#ifdef TORRENT_USE_WPATH -// for safe_convert -#include "libtorrent/storage.hpp" -#endif - -#include "libtorrent/assert.hpp" - -namespace -{ -#ifdef TORRENT_WINDOWS - std::string utf8_native(std::string const& s) - { - try - { - std::wstring ws; - libtorrent::utf8_wchar(s, ws); - std::size_t size = wcstombs(0, ws.c_str(), 0); - if (size == std::size_t(-1)) return s; - std::string ret; - ret.resize(size); - size = wcstombs(&ret[0], ws.c_str(), size + 1); - if (size == std::size_t(-1)) return s; - ret.resize(size); - return ret; - } - catch(std::exception) - { - return s; - } - } -#else - - enum { mode_in = 1, mode_out = 2 }; - - mode_t map_open_mode(int m) - { - if (m == (mode_in | mode_out)) return O_RDWR | O_CREAT | O_BINARY | O_RANDOM; - if (m == mode_out) return O_WRONLY | O_CREAT | O_BINARY | O_RANDOM; - if (m == mode_in) return O_RDONLY | O_BINARY | O_RANDOM; - TORRENT_ASSERT(false); - return 0; - } -#endif - -} - -namespace libtorrent -{ - namespace fs = boost::filesystem; - -#ifdef TORRENT_WINDOWS - const file::open_mode file::in(GENERIC_READ); - const file::open_mode file::out(GENERIC_WRITE); - const file::seek_mode file::begin(FILE_BEGIN); - const file::seek_mode file::end(FILE_END); -#else - const file::open_mode file::in(mode_in); - const file::open_mode file::out(mode_out); - const file::seek_mode file::begin(SEEK_SET); - const file::seek_mode file::end(SEEK_END); -#endif - - file::file() -#ifdef TORRENT_WINDOWS - : m_file_handle(INVALID_HANDLE_VALUE) -#else - : m_fd(-1) -#endif -#ifdef TORRENT_DEBUG - , m_open_mode(0) -#endif - {} - - file::file(fs::path const& path, open_mode mode, error_code& ec) -#ifdef TORRENT_WINDOWS - : m_file_handle(INVALID_HANDLE_VALUE) -#else - : m_fd(-1) -#endif -#ifdef TORRENT_DEBUG - , m_open_mode(0) -#endif - { - open(path, mode, ec); - } - - file::~file() - { - close(); - } - - bool file::open(fs::path const& path, open_mode mode, error_code& ec) - { - close(); -#ifdef TORRENT_WINDOWS - -#ifdef TORRENT_USE_WPATH - std::wstring file_path(safe_convert(path.external_file_string())); -#else - std::string file_path = utf8_native(path.external_file_string()); -#endif - - m_file_handle = CreateFile( - file_path.c_str() - , mode.m_mask - , FILE_SHARE_READ - , 0 - , (mode & out)?OPEN_ALWAYS:OPEN_EXISTING - , FILE_ATTRIBUTE_NORMAL - , 0); - - if (m_file_handle == INVALID_HANDLE_VALUE) - { - ec = error_code(GetLastError(), get_system_category()); - return false; - } - - // try to make the file sparse if supported - if (mode & out) - { - DWORD temp; - ::DeviceIoControl(m_file_handle, FSCTL_SET_SPARSE, 0, 0 - , 0, 0, &temp, 0); - } -#else - // rely on default umask to filter x and w permissions - // for group and others - int permissions = S_IRUSR | S_IWUSR - | S_IRGRP | S_IWGRP - | S_IROTH | S_IWOTH; - - m_fd = ::open(path.external_file_string().c_str() - , map_open_mode(mode.m_mask), permissions); - - if (m_fd == -1) - { - ec = error_code(errno, get_posix_category()); - return false; - } -#endif -#ifdef TORRENT_DEBUG - m_open_mode = mode; -#endif - TORRENT_ASSERT(is_open()); - return true; - } - - bool file::is_open() const - { -#ifdef TORRENT_WINDOWS - return m_file_handle != INVALID_HANDLE_VALUE; -#else - return m_fd != -1; -#endif - } - - void file::close() - { -#ifdef TORRENT_WINDOWS - if (m_file_handle == INVALID_HANDLE_VALUE) return; - CloseHandle(m_file_handle); - m_file_handle = INVALID_HANDLE_VALUE; -#else - if (m_fd == -1) return; - ::close(m_fd); - m_fd = -1; -#endif -#ifdef TORRENT_DEBUG - m_open_mode = 0; -#endif - } - - size_type file::read(char* buf, size_type num_bytes, error_code& ec) - { - TORRENT_ASSERT((m_open_mode & in) == in); - TORRENT_ASSERT(buf); - TORRENT_ASSERT(num_bytes >= 0); - TORRENT_ASSERT(is_open()); - -#ifdef TORRENT_WINDOWS - - TORRENT_ASSERT(DWORD(num_bytes) == num_bytes); - DWORD ret = 0; - if (num_bytes != 0) - { - if (ReadFile(m_file_handle, buf, (DWORD)num_bytes, &ret, 0) == FALSE) - { - ec = error_code(GetLastError(), get_system_category()); - return -1; - } - } -#else - size_type ret = ::read(m_fd, buf, num_bytes); - if (ret == -1) ec = error_code(errno, get_posix_category()); -#endif - return ret; - } - - size_type file::write(const char* buf, size_type num_bytes, error_code& ec) - { - TORRENT_ASSERT((m_open_mode & out) == out); - TORRENT_ASSERT(buf); - TORRENT_ASSERT(num_bytes >= 0); - TORRENT_ASSERT(is_open()); - -#ifdef TORRENT_WINDOWS - - DWORD ret = 0; - if (num_bytes != 0) - { - if (WriteFile(m_file_handle, buf, (DWORD)num_bytes, &ret, 0) == FALSE) - { - ec = error_code(GetLastError(), get_system_category()); - return -1; - } - } -#else - size_type ret = ::write(m_fd, buf, num_bytes); - if (ret == -1) ec = error_code(errno, get_posix_category()); -#endif - return ret; - } - - bool file::set_size(size_type s, error_code& ec) - { - TORRENT_ASSERT(is_open()); - TORRENT_ASSERT(s >= 0); - -#ifdef TORRENT_WINDOWS - size_type pos = tell(ec); - if (ec) return false; - seek(s, begin, ec); - if (ec) return false; - if (::SetEndOfFile(m_file_handle) == FALSE) - { - ec = error_code(GetLastError(), get_system_category()); - return false; - } -#else - if (ftruncate(m_fd, s) < 0) - { - ec = error_code(errno, get_posix_category()); - return false; - } -#endif - return true; - } - - size_type file::seek(size_type offset, seek_mode m, error_code& ec) - { - TORRENT_ASSERT(is_open()); - -#ifdef TORRENT_WINDOWS - LARGE_INTEGER offs; - offs.QuadPart = offset; - if (SetFilePointerEx(m_file_handle, offs, &offs, m.m_val) == FALSE) - { - ec = error_code(GetLastError(), get_system_category()); - return -1; - } - return offs.QuadPart; -#else - size_type ret = lseek(m_fd, offset, m.m_val); - if (ret < 0) ec = error_code(errno, get_posix_category()); - return ret; -#endif - } - - size_type file::tell(error_code& ec) - { - TORRENT_ASSERT(is_open()); - -#ifdef TORRENT_WINDOWS - LARGE_INTEGER offs; - offs.QuadPart = 0; - - // is there any other way to get offset? - if (SetFilePointerEx(m_file_handle, offs, &offs - , FILE_CURRENT) == FALSE) - { - ec = error_code(GetLastError(), get_system_category()); - return -1; - } - - return offs.QuadPart; -#else - size_type ret; - ret = lseek(m_fd, 0, SEEK_CUR); - if (ret < 0) ec = error_code(errno, get_posix_category()); - return ret; -#endif - } -} - diff --git a/libtorrent/src/file_pool.cpp b/libtorrent/src/file_pool.cpp deleted file mode 100644 index d31930cce..000000000 --- a/libtorrent/src/file_pool.cpp +++ /dev/null @@ -1,163 +0,0 @@ -/* - -Copyright (c) 2006, Arvid Norberg -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions -are met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in - the documentation and/or other materials provided with the distribution. - * Neither the name of the author nor the names of its - contributors may be used to endorse or promote products derived - from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -POSSIBILITY OF SUCH DAMAGE. - -*/ - -#include -#include "libtorrent/pch.hpp" -#include "libtorrent/file_pool.hpp" -#include "libtorrent/error_code.hpp" - -#include - -namespace libtorrent -{ - using boost::multi_index::nth_index; - using boost::multi_index::get; - - boost::shared_ptr file_pool::open_file(void* st, fs::path const& p - , file::open_mode m, error_code& ec) - { - TORRENT_ASSERT(st != 0); - TORRENT_ASSERT(p.is_complete()); - TORRENT_ASSERT(m == file::in || m == (file::in | file::out)); - boost::mutex::scoped_lock l(m_mutex); - typedef nth_index::type path_view; - path_view& pt = get<0>(m_files); - path_view::iterator i = pt.find(p); - if (i != pt.end()) - { - lru_file_entry e = *i; - e.last_use = time_now(); - - if (e.key != st && (e.mode != file::in - || m != file::in)) - { - // this means that another instance of the storage - // is using the exact same file. -#if BOOST_VERSION >= 103500 - ec = error_code(errors::file_collision, libtorrent_category); -#endif - return boost::shared_ptr(); - } - - e.key = st; - if ((e.mode & m) != m) - { - // close the file before we open it with - // the new read/write privilages - i->file_ptr.reset(); - TORRENT_ASSERT(e.file_ptr.unique()); - e.file_ptr->close(); - if (!e.file_ptr->open(p, m, ec)) - { - m_files.erase(i); - return boost::shared_ptr(); - } - TORRENT_ASSERT(e.file_ptr->is_open()); - e.mode = m; - } - pt.replace(i, e); - return e.file_ptr; - } - // the file is not in our cache - if ((int)m_files.size() >= m_size) - { - // the file cache is at its maximum size, close - // the least recently used (lru) file from it - typedef nth_index::type lru_view; - lru_view& lt = get<1>(m_files); - lru_view::iterator i = lt.begin(); - // the first entry in this view is the least recently used - TORRENT_ASSERT(lt.size() == 1 || (i->last_use <= boost::next(i)->last_use)); - lt.erase(i); - } - lru_file_entry e; - e.file_ptr.reset(new (std::nothrow)file); - if (!e.file_ptr) - { - ec = error_code(ENOMEM, get_posix_category()); - return e.file_ptr; - } - if (!e.file_ptr->open(p, m, ec)) - return boost::shared_ptr(); - e.mode = m; - e.key = st; - e.file_path = p; - pt.insert(e); - TORRENT_ASSERT(e.file_ptr->is_open()); - return e.file_ptr; - } - - void file_pool::release(fs::path const& p) - { - boost::mutex::scoped_lock l(m_mutex); - - typedef nth_index::type path_view; - path_view& pt = get<0>(m_files); - path_view::iterator i = pt.find(p); - if (i != pt.end()) pt.erase(i); - } - - void file_pool::release(void* st) - { - boost::mutex::scoped_lock l(m_mutex); - TORRENT_ASSERT(st != 0); - using boost::tie; - - typedef nth_index::type key_view; - key_view& kt = get<2>(m_files); - - key_view::iterator start, end; - tie(start, end) = kt.equal_range(st); - kt.erase(start, end); - } - - void file_pool::resize(int size) - { - TORRENT_ASSERT(size > 0); - if (size == m_size) return; - boost::mutex::scoped_lock l(m_mutex); - m_size = size; - if (int(m_files.size()) <= m_size) return; - - // close the least recently used files - typedef nth_index::type lru_view; - lru_view& lt = get<1>(m_files); - lru_view::iterator i = lt.begin(); - while (int(m_files.size()) > m_size) - { - // the first entry in this view is the least recently used - TORRENT_ASSERT(lt.size() == 1 || (i->last_use <= boost::next(i)->last_use)); - lt.erase(i++); - } - } - -} diff --git a/libtorrent/src/file_storage.cpp b/libtorrent/src/file_storage.cpp deleted file mode 100644 index dd732bef1..000000000 --- a/libtorrent/src/file_storage.cpp +++ /dev/null @@ -1,166 +0,0 @@ -/* - -Copyright (c) 2003-2008, Arvid Norberg -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions -are met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in - the documentation and/or other materials provided with the distribution. - * Neither the name of the author nor the names of its - contributors may be used to endorse or promote products derived - from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -POSSIBILITY OF SUCH DAMAGE. - -*/ - -#include "libtorrent/pch.hpp" - -#include "libtorrent/file_storage.hpp" - - -namespace libtorrent -{ - file_storage::file_storage() - : m_piece_length(0) - , m_total_size(0) - , m_num_pieces(0) - {} - - int file_storage::piece_size(int index) const - { - TORRENT_ASSERT(index >= 0 && index < num_pieces()); - if (index == num_pieces()-1) - { - int size = int(total_size() - - size_type(num_pieces() - 1) * piece_length()); - TORRENT_ASSERT(size > 0); - TORRENT_ASSERT(size <= piece_length()); - return int(size); - } - else - return piece_length(); - } - - void file_storage::rename_file(int index, std::string const& new_filename) - { - TORRENT_ASSERT(index >= 0 && index < int(m_files.size())); - m_files[index].path = new_filename; - } - - file_storage::iterator file_storage::file_at_offset(size_type offset) const - { - // TODO: do a binary search - std::vector::const_iterator i; - for (i = begin(); i != end(); ++i) - { - if (i->offset <= offset && i->offset + i->size > offset) - return i; - } - return i; - } - - std::vector file_storage::map_block(int piece, size_type offset - , int size_) const - { - TORRENT_ASSERT(num_files() > 0); - std::vector ret; - - size_type start = piece * (size_type)m_piece_length + offset; - size_type size = size_; - TORRENT_ASSERT(start + size <= m_total_size); - - // find the file iterator and file offset - // TODO: do a binary search on the file offsets - size_type file_offset = start; - std::vector::const_iterator file_iter; - - int counter = 0; - for (file_iter = begin();; ++counter, ++file_iter) - { - TORRENT_ASSERT(file_iter != end()); - if (file_offset < file_iter->size) - { - file_slice f; - f.file_index = counter; - f.offset = file_offset + file_iter->file_base; - f.size = (std::min)(file_iter->size - file_offset, (size_type)size); - size -= f.size; - file_offset += f.size; - ret.push_back(f); - } - - TORRENT_ASSERT(size >= 0); - if (size <= 0) break; - - file_offset -= file_iter->size; - } - return ret; - } - - peer_request file_storage::map_file(int file_index, size_type file_offset - , int size) const - { - TORRENT_ASSERT(file_index < num_files()); - TORRENT_ASSERT(file_index >= 0); - size_type offset = file_offset + at(file_index).offset; - - peer_request ret; - ret.piece = int(offset / piece_length()); - ret.start = int(offset - ret.piece * piece_length()); - ret.length = size; - return ret; - } - - void file_storage::add_file(fs::path const& file, size_type size) - { - TORRENT_ASSERT(size >= 0); -#if BOOST_VERSION < 103600 - if (!file.has_branch_path()) -#else - if (!file.has_parent_path()) -#endif - { - // you have already added at least one file with a - // path to the file (branch_path), which means that - // all the other files need to be in the same top - // directory as the first file. - TORRENT_ASSERT(m_files.empty()); - m_name = file.string(); - } - else - { - if (m_files.empty()) - m_name = *file.begin(); - } - TORRENT_ASSERT(m_name == *file.begin()); - file_entry e; - m_files.push_back(e); - m_files.back().size = size; - m_files.back().path = file; - m_files.back().offset = m_total_size; - m_total_size += size; - } - - void file_storage::add_file(file_entry const& e) - { - add_file(e.path, e.size); - } -} - diff --git a/libtorrent/src/gzip.cpp b/libtorrent/src/gzip.cpp deleted file mode 100644 index cf0c5b196..000000000 --- a/libtorrent/src/gzip.cpp +++ /dev/null @@ -1,213 +0,0 @@ -/* - -Copyright (c) 2007, Arvid Norberg -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions -are met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in - the documentation and/or other materials provided with the distribution. - * Neither the name of the author nor the names of its - contributors may be used to endorse or promote products derived - from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -POSSIBILITY OF SUCH DAMAGE. - -*/ - -#include "libtorrent/assert.hpp" - -#include "zlib.h" - -#include -#include - -namespace -{ - enum - { - FTEXT = 0x01, - FHCRC = 0x02, - FEXTRA = 0x04, - FNAME = 0x08, - FCOMMENT = 0x10, - FRESERVED = 0xe0, - - GZIP_MAGIC0 = 0x1f, - GZIP_MAGIC1 = 0x8b - }; - -} - -namespace libtorrent -{ - // returns -1 if gzip header is invalid or the header size in bytes - int gzip_header(const char* buf, int size) - { - TORRENT_ASSERT(buf != 0); - TORRENT_ASSERT(size > 0); - - const unsigned char* buffer = reinterpret_cast(buf); - const int total_size = size; - - // The zip header cannot be shorter than 10 bytes - if (size < 10) return -1; - - // check the magic header of gzip - if ((buffer[0] != GZIP_MAGIC0) || (buffer[1] != GZIP_MAGIC1)) return -1; - - int method = buffer[2]; - int flags = buffer[3]; - - // check for reserved flag and make sure it's compressed with the correct metod - if (method != Z_DEFLATED || (flags & FRESERVED) != 0) return -1; - - // skip time, xflags, OS code - size -= 10; - buffer += 10; - - if (flags & FEXTRA) - { - int extra_len; - - if (size < 2) return -1; - - extra_len = (buffer[1] << 8) | buffer[0]; - - if (size < (extra_len+2)) return -1; - size -= (extra_len + 2); - buffer += (extra_len + 2); - } - - if (flags & FNAME) - { - while (size && *buffer) - { - --size; - ++buffer; - } - if (!size || *buffer) return -1; - - --size; - ++buffer; - } - - if (flags & FCOMMENT) - { - while (size && *buffer) - { - --size; - ++buffer; - } - if (!size || *buffer) return -1; - - --size; - ++buffer; - } - - if (flags & FHCRC) - { - if (size < 2) return -1; - - size -= 2; - buffer += 2; - } - - return total_size - size; - } - - bool inflate_gzip( - char const* in - , int size - , std::vector& buffer - , int maximum_size - , std::string& error) - { - TORRENT_ASSERT(maximum_size > 0); - - int header_len = gzip_header(in, size); - if (header_len < 0) - { - error = "invalid gzip header in tracker response"; - return true; - } - - // start off with one kilobyte and grow - // if needed - buffer.resize(1024); - - // initialize the zlib-stream - z_stream str; - - // subtract 8 from the end of the buffer since that's CRC32 and input size - // and those belong to the gzip file - str.avail_in = (int)size - header_len - 8; - str.next_in = reinterpret_cast(const_cast(in + header_len)); - str.next_out = reinterpret_cast(&buffer[0]); - str.avail_out = (int)buffer.size(); - str.zalloc = Z_NULL; - str.zfree = Z_NULL; - str.opaque = 0; - // -15 is really important. It will make inflate() not look for a zlib header - // and just deflate the buffer - if (inflateInit2(&str, -15) != Z_OK) - { - error = "gzip out of memory"; - return true; - } - - // inflate and grow inflate_buffer as needed - int ret = inflate(&str, Z_SYNC_FLUSH); - while (ret == Z_OK) - { - if (str.avail_out == 0) - { - if (buffer.size() >= (unsigned)maximum_size) - { - inflateEnd(&str); - error = "response too large"; - return true; - } - int new_size = (int)buffer.size() * 2; - if (new_size > maximum_size) - new_size = maximum_size; - int old_size = (int)buffer.size(); - - buffer.resize(new_size); - str.next_out = reinterpret_cast(&buffer[old_size]); - str.avail_out = new_size - old_size; - } - - ret = inflate(&str, Z_SYNC_FLUSH); - } - - buffer.resize(buffer.size() - str.avail_out); - inflateEnd(&str); - - if (ret != Z_STREAM_END) - { - error = "gzip error"; - return true; - } - - // commit the resulting buffer - return false; - } - -} - diff --git a/libtorrent/src/http_connection.cpp b/libtorrent/src/http_connection.cpp deleted file mode 100644 index d750e92e5..000000000 --- a/libtorrent/src/http_connection.cpp +++ /dev/null @@ -1,595 +0,0 @@ -/* - -Copyright (c) 2007, Arvid Norberg -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions -are met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in - the documentation and/or other materials provided with the distribution. - * Neither the name of the author nor the names of its - contributors may be used to endorse or promote products derived - from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -POSSIBILITY OF SUCH DAMAGE. - -*/ - -#include "libtorrent/http_connection.hpp" -#include "libtorrent/escape_string.hpp" -#include "libtorrent/instantiate_connection.hpp" -#include "libtorrent/gzip.hpp" -#include "libtorrent/parse_url.hpp" -#include "libtorrent/socket.hpp" -#include "libtorrent/connection_queue.hpp" - -#include -#include -#include - -using boost::bind; - -namespace libtorrent { - -enum { max_bottled_buffer = 1024 * 1024 }; - - -void http_connection::get(std::string const& url, time_duration timeout, int prio - , proxy_settings const* ps, int handle_redirects, std::string const& user_agent - , address const& bind_addr) -{ - std::string protocol; - std::string auth; - std::string hostname; - std::string path; - char const* error; - int port; - - boost::tie(protocol, auth, hostname, port, path, error) - = parse_url_components(url); - - if (error) - { - callback(asio::error::socket_type_not_supported); - return; - } - - TORRENT_ASSERT(prio >= 0 && prio < 2); - - bool ssl = false; - if (protocol == "https") ssl = true; -#ifndef TORRENT_USE_OPENSSL - if (ssl) - { - callback(asio::error::socket_type_not_supported); - return; - } -#endif - - std::stringstream headers; - if (ps && (ps->type == proxy_settings::http - || ps->type == proxy_settings::http_pw) - && !ssl) - { - // if we're using an http proxy and not an ssl - // connection, just do a regular http proxy request - headers << "GET " << url << " HTTP/1.0\r\n"; - if (ps->type == proxy_settings::http_pw) - headers << "Proxy-Authorization: Basic " << base64encode( - ps->username + ":" + ps->password) << "\r\n"; - hostname = ps->hostname; - port = ps->port; - ps = 0; - } - else - { - headers << "GET " << path << " HTTP/1.0\r\n" - "Host:" << hostname << ":" << port << "\r\n"; - } - - if (!auth.empty()) - headers << "Authorization: Basic " << base64encode(auth) << "\r\n"; - - if (!user_agent.empty()) - headers << "User-Agent: " << user_agent << "\r\n"; - - headers << - "Connection: close\r\n" - "Accept-Encoding: gzip\r\n" - "\r\n"; - - sendbuffer = headers.str(); - m_url = url; - start(hostname, to_string(port).elems, timeout, prio - , ps, ssl, handle_redirects, bind_addr); -} - -void http_connection::start(std::string const& hostname, std::string const& port - , time_duration timeout, int prio, proxy_settings const* ps, bool ssl, int handle_redirects - , address const& bind_addr) -{ - TORRENT_ASSERT(prio >= 0 && prio < 2); - - m_redirects = handle_redirects; - if (ps) m_proxy = *ps; - - m_timeout = timeout; - error_code ec; - m_timer.expires_from_now(m_timeout, ec); - m_timer.async_wait(bind(&http_connection::on_timeout - , boost::weak_ptr(shared_from_this()), _1)); - m_called = false; - m_parser.reset(); - m_recvbuffer.clear(); - m_read_pos = 0; - m_priority = prio; - - if (ec) - { - callback(ec); - return; - } - - if (m_sock.is_open() && m_hostname == hostname && m_port == port - && m_ssl == ssl && m_bind_addr == bind_addr) - { - async_write(m_sock, asio::buffer(sendbuffer) - , bind(&http_connection::on_write, shared_from_this(), _1)); - } - else - { - m_ssl = ssl; - m_bind_addr = bind_addr; - error_code ec; - m_sock.close(ec); - -#ifdef TORRENT_USE_OPENSSL - if (m_ssl) - { - m_sock.instantiate >(m_resolver.get_io_service()); - ssl_stream& s = m_sock.get >(); - bool ret = instantiate_connection(m_resolver.get_io_service(), m_proxy, s.next_layer()); - TORRENT_ASSERT(ret); - } - else - { - m_sock.instantiate(m_resolver.get_io_service()); - bool ret = instantiate_connection(m_resolver.get_io_service() - , m_proxy, m_sock.get()); - TORRENT_ASSERT(ret); - } -#else - bool ret = instantiate_connection(m_resolver.get_io_service(), m_proxy, m_sock); - TORRENT_ASSERT(ret); -#endif - if (m_bind_addr != address_v4::any()) - { - error_code ec; - m_sock.open(m_bind_addr.is_v4()?tcp::v4():tcp::v6(), ec); - m_sock.bind(tcp::endpoint(m_bind_addr, 0), ec); - if (ec) - { - callback(ec); - return; - } - } - - tcp::resolver::query query(hostname, port); - m_resolver.async_resolve(query, bind(&http_connection::on_resolve - , shared_from_this(), _1, _2)); - m_hostname = hostname; - m_port = port; - } -} - -void http_connection::on_connect_timeout() -{ - if (m_connection_ticket > -1) m_cc.done(m_connection_ticket); - m_connection_ticket = -1; - - if (!m_endpoints.empty()) - { - error_code ec; - m_sock.close(ec); - } - else - { - callback(asio::error::timed_out); - close(); - } -} - -void http_connection::on_timeout(boost::weak_ptr p - , error_code const& e) -{ - boost::shared_ptr c = p.lock(); - if (!c) return; - - if (e == asio::error::operation_aborted) return; - - if (c->m_last_receive + c->m_timeout < time_now()) - { - if (c->m_connection_ticket > -1 && !c->m_endpoints.empty()) - { - error_code ec; - c->m_sock.close(ec); - c->m_timer.expires_at(c->m_last_receive + c->m_timeout, ec); - c->m_timer.async_wait(bind(&http_connection::on_timeout, p, _1)); - } - else - { - c->callback(asio::error::timed_out); - c->close(); - } - return; - } - - if (!c->m_sock.is_open()) return; - error_code ec; - c->m_timer.expires_at(c->m_last_receive + c->m_timeout, ec); - c->m_timer.async_wait(bind(&http_connection::on_timeout, p, _1)); -} - -void http_connection::close() -{ - error_code ec; - m_timer.cancel(ec); - m_resolver.cancel(); - m_limiter_timer.cancel(ec); - m_sock.close(ec); - m_hostname.clear(); - m_port.clear(); - m_handler.clear(); - m_abort = true; -} - -void http_connection::on_resolve(error_code const& e - , tcp::resolver::iterator i) -{ - if (e) - { - callback(e); - close(); - return; - } - TORRENT_ASSERT(i != tcp::resolver::iterator()); - - std::transform(i, tcp::resolver::iterator(), std::back_inserter(m_endpoints) - , boost::bind(&tcp::resolver::iterator::value_type::endpoint, _1)); - - // The following statement causes msvc to crash (ICE). Since it's not - // necessary in the vast majority of cases, just ignore the endpoint - // order for windows -#if !defined _MSC_VER || _MSC_VER > 1310 - // sort the endpoints so that the ones with the same IP version as our - // bound listen socket are first. So that when contacting a tracker, - // we'll talk to it from the same IP that we're listening on - std::partition(m_endpoints.begin(), m_endpoints.end() - , boost::bind(&address::is_v4, boost::bind(&tcp::endpoint::address, _1)) == m_bind_addr.is_v4()); -#endif - - queue_connect(); -} - -void http_connection::queue_connect() -{ - TORRENT_ASSERT(!m_endpoints.empty()); - tcp::endpoint target = m_endpoints.front(); - m_endpoints.pop_front(); - - m_cc.enqueue(bind(&http_connection::connect, shared_from_this(), _1, target) - , bind(&http_connection::on_connect_timeout, shared_from_this()) - , m_timeout, m_priority); -} - -void http_connection::connect(int ticket, tcp::endpoint target_address) -{ - m_connection_ticket = ticket; - m_sock.async_connect(target_address, boost::bind(&http_connection::on_connect - , shared_from_this(), _1)); -} - -void http_connection::on_connect(error_code const& e) -{ - if (m_connection_ticket >= 0) - { - m_cc.done(m_connection_ticket); - m_connection_ticket = -1; - } - - m_last_receive = time_now(); - if (!e) - { - if (m_connect_handler) m_connect_handler(*this); - async_write(m_sock, asio::buffer(sendbuffer) - , bind(&http_connection::on_write, shared_from_this(), _1)); - } - else if (!m_endpoints.empty() && !m_abort) - { - // The connection failed. Try the next endpoint in the list. - error_code ec; - m_sock.close(ec); - queue_connect(); - } - else - { - callback(e); - close(); - } -} - -void http_connection::callback(error_code const& e, char const* data, int size) -{ - if (!m_bottled || !m_called) - { - std::vector buf; - if (m_bottled && m_parser.header_finished()) - { - std::string const& encoding = m_parser.header("content-encoding"); - if (encoding == "gzip" || encoding == "x-gzip") - { - std::string error; - if (inflate_gzip(data, size, buf, max_bottled_buffer, error)) - { - if (m_handler) m_handler(asio::error::fault, m_parser, data, size, *this); - close(); - return; - } - data = &buf[0]; - size = int(buf.size()); - } - } - m_called = true; - error_code ec; - m_timer.cancel(ec); - if (m_handler) m_handler(e, m_parser, data, size, *this); - } -} - -void http_connection::on_write(error_code const& e) -{ - if (e) - { - callback(e); - close(); - return; - } - - std::string().swap(sendbuffer); - m_recvbuffer.resize(4096); - - int amount_to_read = m_recvbuffer.size() - m_read_pos; - if (m_rate_limit > 0 && amount_to_read > m_download_quota) - { - amount_to_read = m_download_quota; - if (m_download_quota == 0) - { - if (!m_limiter_timer_active) - on_assign_bandwidth(error_code()); - return; - } - } - m_sock.async_read_some(asio::buffer(&m_recvbuffer[0] + m_read_pos - , amount_to_read) - , bind(&http_connection::on_read - , shared_from_this(), _1, _2)); -} - -void http_connection::on_read(error_code const& e - , std::size_t bytes_transferred) -{ - if (m_rate_limit) - { - m_download_quota -= bytes_transferred; - TORRENT_ASSERT(m_download_quota >= 0); - } - - // when using the asio SSL wrapper, it seems like - // we get the shut_down error instead of EOF - if (e == asio::error::eof || e == asio::error::shut_down) - { - error_code ec = asio::error::eof; - TORRENT_ASSERT(bytes_transferred == 0); - char const* data = 0; - std::size_t size = 0; - if (m_bottled && m_parser.header_finished()) - { - data = m_parser.get_body().begin; - size = m_parser.get_body().left(); - } - callback(ec, data, size); - close(); - return; - } - - if (e) - { - TORRENT_ASSERT(bytes_transferred == 0); - callback(e); - close(); - return; - } - - m_read_pos += bytes_transferred; - TORRENT_ASSERT(m_read_pos <= int(m_recvbuffer.size())); - - if (m_bottled || !m_parser.header_finished()) - { - libtorrent::buffer::const_interval rcv_buf(&m_recvbuffer[0] - , &m_recvbuffer[0] + m_read_pos); - bool error = false; - m_parser.incoming(rcv_buf, error); - if (error) - { - // HTTP parse error - error_code ec = asio::error::fault; - callback(ec, 0, 0); - return; - } - - // having a nonempty path means we should handle redirects - if (m_redirects && m_parser.header_finished()) - { - int code = m_parser.status_code(); - - if (code >= 300 && code < 400) - { - // attempt a redirect - std::string const& location = m_parser.header("location"); - if (location.empty()) - { - // missing location header - callback(asio::error::fault); - close(); - return; - } - - error_code ec; - m_sock.close(ec); - using boost::tuples::ignore; - char const* error; - boost::tie(ignore, ignore, ignore, ignore, ignore, error) - = parse_url_components(location); - if (error == 0) - { - get(location, m_timeout, m_priority, &m_proxy, m_redirects - 1); - } - else - { - // some broken web servers send out relative paths - // in the location header. - std::string url = m_url; - // remove the leaf filename - std::size_t i = url.find_last_of('/'); - if (i == std::string::npos) - { - url += '/'; - } - else - { - url.resize(i + 1); - } - url += location; - - get(url, m_timeout, m_priority, &m_proxy, m_redirects - 1); - } - return; - } - - m_redirects = 0; - } - - if (!m_bottled && m_parser.header_finished()) - { - if (m_read_pos > m_parser.body_start()) - callback(e, &m_recvbuffer[0] + m_parser.body_start() - , m_read_pos - m_parser.body_start()); - m_read_pos = 0; - m_last_receive = time_now(); - } - else if (m_bottled && m_parser.finished()) - { - error_code ec; - m_timer.cancel(ec); - callback(e, m_parser.get_body().begin, m_parser.get_body().left()); - } - } - else - { - TORRENT_ASSERT(!m_bottled); - callback(e, &m_recvbuffer[0], m_read_pos); - m_read_pos = 0; - m_last_receive = time_now(); - } - - if (int(m_recvbuffer.size()) == m_read_pos) - m_recvbuffer.resize((std::min)(m_read_pos + 2048, int(max_bottled_buffer))); - if (m_read_pos == max_bottled_buffer) - { - callback(asio::error::eof); - close(); - return; - } - int amount_to_read = m_recvbuffer.size() - m_read_pos; - if (m_rate_limit > 0 && amount_to_read > m_download_quota) - { - amount_to_read = m_download_quota; - if (m_download_quota == 0) - { - if (!m_limiter_timer_active) - on_assign_bandwidth(error_code()); - return; - } - } - m_sock.async_read_some(asio::buffer(&m_recvbuffer[0] + m_read_pos - , amount_to_read) - , bind(&http_connection::on_read - , shared_from_this(), _1, _2)); -} - -void http_connection::on_assign_bandwidth(error_code const& e) -{ - if ((e == asio::error::operation_aborted - && m_limiter_timer_active) - || !m_sock.is_open()) - { - callback(asio::error::eof); - return; - } - m_limiter_timer_active = false; - if (e) return; - - if (m_download_quota > 0) return; - - m_download_quota = m_rate_limit / 4; - - int amount_to_read = m_recvbuffer.size() - m_read_pos; - if (amount_to_read > m_download_quota) - amount_to_read = m_download_quota; - - if (!m_sock.is_open()) return; - - m_sock.async_read_some(asio::buffer(&m_recvbuffer[0] + m_read_pos - , amount_to_read) - , bind(&http_connection::on_read - , shared_from_this(), _1, _2)); - - error_code ec; - m_limiter_timer_active = true; - m_limiter_timer.expires_from_now(milliseconds(250), ec); - m_limiter_timer.async_wait(bind(&http_connection::on_assign_bandwidth - , shared_from_this(), _1)); -} - -void http_connection::rate_limit(int limit) -{ - if (!m_sock.is_open()) return; - - if (!m_limiter_timer_active) - { - error_code ec; - m_limiter_timer_active = true; - m_limiter_timer.expires_from_now(milliseconds(250), ec); - m_limiter_timer.async_wait(bind(&http_connection::on_assign_bandwidth - , shared_from_this(), _1)); - } - m_rate_limit = limit; -} - -} - diff --git a/libtorrent/src/http_parser.cpp b/libtorrent/src/http_parser.cpp deleted file mode 100755 index 226cf6bdf..000000000 --- a/libtorrent/src/http_parser.cpp +++ /dev/null @@ -1,245 +0,0 @@ -/* - -Copyright (c) 2008, Arvid Norberg -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions -are met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in - the documentation and/or other materials provided with the distribution. - * Neither the name of the author nor the names of its - contributors may be used to endorse or promote products derived - from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -POSSIBILITY OF SUCH DAMAGE. - -*/ - -#include "libtorrent/pch.hpp" - -#include -#include -#include - -#include "libtorrent/config.hpp" -#include "libtorrent/http_parser.hpp" -#include "libtorrent/assert.hpp" - -using namespace libtorrent; - -namespace -{ - char to_lower(char c) { return std::tolower(c); } -} - -namespace libtorrent -{ - http_parser::http_parser() - : m_recv_pos(0) - , m_status_code(-1) - , m_content_length(-1) - , m_state(read_status) - , m_recv_buffer(0, 0) - , m_body_start_pos(0) - , m_finished(false) - {} - - boost::tuple http_parser::incoming( - buffer::const_interval recv_buffer, bool& error) - { - TORRENT_ASSERT(recv_buffer.left() >= m_recv_buffer.left()); - boost::tuple ret(0, 0); - int start_pos = m_recv_buffer.left(); - - // early exit if there's nothing new in the receive buffer - if (start_pos == recv_buffer.left()) return ret; - m_recv_buffer = recv_buffer; - - if (m_state == error_state) - { - error = true; - return ret; - } - - char const* pos = recv_buffer.begin + m_recv_pos; - if (m_state == read_status) - { - TORRENT_ASSERT(!m_finished); - char const* newline = std::find(pos, recv_buffer.end, '\n'); - // if we don't have a full line yet, wait. - if (newline == recv_buffer.end) - { - boost::get<1>(ret) += m_recv_buffer.left() - start_pos; - return ret; - } - - if (newline == pos) - { - m_state = error_state; - error = true; - return ret; - } - - char const* line_end = newline; - if (pos != line_end && *(line_end - 1) == '\r') --line_end; - - std::istringstream line(std::string(pos, line_end)); - ++newline; - int incoming = (int)std::distance(pos, newline); - m_recv_pos += incoming; - boost::get<1>(ret) += newline - (m_recv_buffer.begin + start_pos); - pos = newline; - - line >> m_protocol; - if (m_protocol.substr(0, 5) == "HTTP/") - { - line >> m_status_code; - std::getline(line, m_server_message); - } - else - { - m_method = m_protocol; - std::transform(m_method.begin(), m_method.end(), m_method.begin(), &to_lower); - m_protocol.clear(); - line >> m_path >> m_protocol; - m_status_code = 0; - } - m_state = read_header; - start_pos = pos - recv_buffer.begin; - } - - if (m_state == read_header) - { - TORRENT_ASSERT(!m_finished); - char const* newline = std::find(pos, recv_buffer.end, '\n'); - std::string line; - - while (newline != recv_buffer.end && m_state == read_header) - { - // if the LF character is preceeded by a CR - // charachter, don't copy it into the line string. - char const* line_end = newline; - if (pos != line_end && *(line_end - 1) == '\r') --line_end; - line.assign(pos, line_end); - ++newline; - m_recv_pos += newline - pos; - pos = newline; - - std::string::size_type separator = line.find(':'); - if (separator == std::string::npos) - { - // this means we got a blank line, - // the header is finished and the body - // starts. - m_state = read_body; - m_body_start_pos = m_recv_pos; - break; - } - - std::string name = line.substr(0, separator); - std::transform(name.begin(), name.end(), name.begin(), &to_lower); - ++separator; - // skip whitespace - while (separator < line.size() - && (line[separator] == ' ' || line[separator] == '\t')) - ++separator; - std::string value = line.substr(separator, std::string::npos); - m_header.insert(std::make_pair(name, value)); - - if (name == "content-length") - { -#ifdef TORRENT_WINDOWS - m_content_length = _atoi64(value.c_str()); -#else - m_content_length = atoll(value.c_str()); -#endif - } - else if (name == "content-range") - { - std::stringstream range_str(value); - char dummy; - std::string bytes; - size_type range_start, range_end; - // apparently some web servers do not send the "bytes" - // in their content-range - if (value.find(' ') != std::string::npos) - range_str >> bytes; - range_str >> range_start >> dummy >> range_end; - if (!range_str || range_end < range_start) - { - m_state = error_state; - error = true; - return ret; - } - // the http range is inclusive - m_content_length = range_end - range_start + 1; - } - - TORRENT_ASSERT(m_recv_pos <= (int)recv_buffer.left()); - newline = std::find(pos, recv_buffer.end, '\n'); - } - boost::get<1>(ret) += newline - (m_recv_buffer.begin + start_pos); - } - - if (m_state == read_body) - { - int incoming = recv_buffer.end - pos; - if (m_recv_pos - m_body_start_pos + incoming > m_content_length - && m_content_length >= 0) - incoming = m_content_length - m_recv_pos + m_body_start_pos; - - TORRENT_ASSERT(incoming >= 0); - m_recv_pos += incoming; - boost::get<0>(ret) += incoming; - - if (m_content_length >= 0 - && m_recv_pos - m_body_start_pos >= m_content_length) - { - m_finished = true; - } - } - return ret; - } - - buffer::const_interval http_parser::get_body() const - { - TORRENT_ASSERT(m_state == read_body); - if (m_content_length >= 0) - return buffer::const_interval(m_recv_buffer.begin + m_body_start_pos - , m_recv_buffer.begin + (std::min)(size_type(m_recv_pos) - , m_body_start_pos + m_content_length)); - else - return buffer::const_interval(m_recv_buffer.begin + m_body_start_pos - , m_recv_buffer.begin + m_recv_pos); - } - - void http_parser::reset() - { - m_recv_pos = 0; - m_body_start_pos = 0; - m_status_code = -1; - m_content_length = -1; - m_finished = false; - m_state = read_status; - m_recv_buffer.begin = 0; - m_recv_buffer.end = 0; - m_header.clear(); - } - -} - diff --git a/libtorrent/src/http_stream.cpp b/libtorrent/src/http_stream.cpp deleted file mode 100644 index 392935941..000000000 --- a/libtorrent/src/http_stream.cpp +++ /dev/null @@ -1,168 +0,0 @@ -/* - -Copyright (c) 2007, Arvid Norberg -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions -are met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in - the documentation and/or other materials provided with the distribution. - * Neither the name of the author nor the names of its - contributors may be used to endorse or promote products derived - from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -POSSIBILITY OF SUCH DAMAGE. - -*/ - -#include "libtorrent/pch.hpp" - -#include "libtorrent/http_stream.hpp" -#include "libtorrent/escape_string.hpp" // for base64encode - -namespace libtorrent -{ - - void http_stream::name_lookup(error_code const& e, tcp::resolver::iterator i - , boost::shared_ptr h) - { - if (e || i == tcp::resolver::iterator()) - { - (*h)(e); - error_code ec; - close(ec); - return; - } - - m_sock.async_connect(i->endpoint(), boost::bind( - &http_stream::connected, this, _1, h)); - } - - void http_stream::connected(error_code const& e, boost::shared_ptr h) - { - if (e) - { - (*h)(e); - error_code ec; - close(ec); - return; - } - - using namespace libtorrent::detail; - - if (m_no_connect) - { - std::vector().swap(m_buffer); - (*h)(e); - return; - } - - // send CONNECT - std::back_insert_iterator > p(m_buffer); - write_string("CONNECT " + boost::lexical_cast(m_remote_endpoint) - + " HTTP/1.0\r\n", p); - if (!m_user.empty()) - { - write_string("Proxy-Authorization: Basic " + base64encode( - m_user + ":" + m_password) + "\r\n", p); - } - write_string("\r\n", p); - async_write(m_sock, asio::buffer(m_buffer) - , boost::bind(&http_stream::handshake1, this, _1, h)); - } - - void http_stream::handshake1(error_code const& e, boost::shared_ptr h) - { - if (e) - { - (*h)(e); - error_code ec; - close(ec); - return; - } - - // read one byte from the socket - m_buffer.resize(1); - async_read(m_sock, asio::buffer(m_buffer) - , boost::bind(&http_stream::handshake2, this, _1, h)); - } - - void http_stream::handshake2(error_code const& e, boost::shared_ptr h) - { - if (e) - { - (*h)(e); - error_code ec; - close(ec); - return; - } - - int read_pos = m_buffer.size(); - // look for \n\n and \r\n\r\n - // both of which means end of http response header - bool found_end = false; - if (m_buffer[read_pos - 1] == '\n' && read_pos > 2) - { - if (m_buffer[read_pos - 2] == '\n') - { - found_end = true; - } - else if (read_pos > 4 - && m_buffer[read_pos - 2] == '\r' - && m_buffer[read_pos - 3] == '\n' - && m_buffer[read_pos - 4] == '\r') - { - found_end = true; - } - } - - if (found_end) - { - m_buffer.push_back(0); - char* status = std::strchr(&m_buffer[0], ' '); - if (status == 0) - { - (*h)(asio::error::operation_not_supported); - error_code ec; - close(ec); - return; - } - - status++; - int code = std::atoi(status); - if (code != 200) - { - (*h)(asio::error::operation_not_supported); - error_code ec; - close(ec); - return; - } - - (*h)(e); - std::vector().swap(m_buffer); - return; - } - - // read another byte from the socket - m_buffer.resize(read_pos + 1); - async_read(m_sock, asio::buffer(&m_buffer[0] + read_pos, 1) - , boost::bind(&http_stream::handshake2, this, _1, h)); - } - -} - diff --git a/libtorrent/src/http_tracker_connection.cpp b/libtorrent/src/http_tracker_connection.cpp deleted file mode 100755 index 4110a274f..000000000 --- a/libtorrent/src/http_tracker_connection.cpp +++ /dev/null @@ -1,451 +0,0 @@ -/* - -Copyright (c) 2003, Arvid Norberg -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions -are met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in - the documentation and/or other materials provided with the distribution. - * Neither the name of the author nor the names of its - contributors may be used to endorse or promote products derived - from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -POSSIBILITY OF SUCH DAMAGE. - -*/ - -#include "libtorrent/pch.hpp" - -#include -#include -#include -#include -#include -#include - -#include "libtorrent/config.hpp" -#include "libtorrent/gzip.hpp" - -#ifdef _MSC_VER -#pragma warning(push, 1) -#endif - -#include - -#ifdef _MSC_VER -#pragma warning(pop) -#endif - -#include "libtorrent/tracker_manager.hpp" -#include "libtorrent/http_tracker_connection.hpp" -#include "libtorrent/http_connection.hpp" -#include "libtorrent/entry.hpp" -#include "libtorrent/bencode.hpp" -#include "libtorrent/torrent.hpp" -#include "libtorrent/io.hpp" -#include "libtorrent/socket.hpp" - -using namespace libtorrent; -using boost::bind; - -namespace libtorrent -{ - - http_tracker_connection::http_tracker_connection( - io_service& ios - , connection_queue& cc - , tracker_manager& man - , tracker_request const& req - , address bind_infc - , boost::weak_ptr c - , session_settings const& stn - , proxy_settings const& ps - , std::string const& auth) - : tracker_connection(man, req, ios, bind_infc, c) - , m_man(man) - , m_settings(stn) - , m_bind_iface(bind_infc) - , m_ps(ps) - , m_cc(cc) - , m_ios(ios) - {} - - void http_tracker_connection::start() - { - // TODO: authentication - std::string url = tracker_req().url; - - if (tracker_req().kind == tracker_request::scrape_request) - { - // find and replace "announce" with "scrape" - // in request - - std::size_t pos = url.find("announce"); - if (pos == std::string::npos) - { - fail(-1, ("scrape is not available on url: '" - + tracker_req().url +"'").c_str()); - return; - } - url.replace(pos, 8, "scrape"); - } - - // if request-string already contains - // some parameters, append an ampersand instead - // of a question mark - size_t arguments_start = url.find('?'); - if (arguments_start != std::string::npos) - url += "&"; - else - url += "?"; - - url += "info_hash="; - url += escape_string( - reinterpret_cast(tracker_req().info_hash.begin()), 20); - - if (tracker_req().kind == tracker_request::announce_request) - { - url += "&peer_id="; - url += escape_string( - reinterpret_cast(tracker_req().pid.begin()), 20); - - url += "&port="; - url += to_string(tracker_req().listen_port).elems; - - url += "&uploaded="; - url += to_string(tracker_req().uploaded).elems; - - url += "&downloaded="; - url += to_string(tracker_req().downloaded).elems; - - url += "&left="; - url += to_string(tracker_req().left).elems; - - if (tracker_req().event != tracker_request::none) - { - const char* event_string[] = {"completed", "started", "stopped"}; - url += "&event="; - url += event_string[tracker_req().event - 1]; - } - - url += "&key="; - std::stringstream key_string; - key_string << std::hex << tracker_req().key; - url += key_string.str(); - - url += "&compact=1"; - - url += "&numwant="; - url += to_string((std::min)(tracker_req().num_want, 999)).elems; - - if (m_settings.announce_ip != address()) - { - error_code ec; - std::string ip = m_settings.announce_ip.to_string(ec); - if (!ec) url += "&ip=" + ip; - } - -#ifndef TORRENT_DISABLE_ENCRYPTION - url += "&supportcrypto=1"; -#endif - url += "&ipv6="; - url += tracker_req().ipv6; - - // extension that tells the tracker that - // we don't need any peer_id's in the response - url += "&no_peer_id=1"; - } - - m_tracker_connection.reset(new http_connection(m_ios, m_cc - , boost::bind(&http_tracker_connection::on_response, self(), _1, _2, _3, _4))); - - int timeout = tracker_req().event==tracker_request::stopped - ?m_settings.stop_tracker_timeout - :m_settings.tracker_completion_timeout; - - m_tracker_connection->get(url, seconds(timeout) - , 1, &m_ps, 5, m_settings.user_agent, m_bind_iface); - -#if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING) - - boost::shared_ptr cb = requester(); - if (cb) - { - cb->debug_log("==> TRACKER_REQUEST [ url: " + url + " ]"); - } -#endif - } - - void http_tracker_connection::close() - { - if (m_tracker_connection) - { - m_tracker_connection->close(); - m_tracker_connection.reset(); - } - tracker_connection::close(); - } - - void http_tracker_connection::on_response(error_code const& ec - , http_parser const& parser, char const* data, int size) - { - // keep this alive - boost::intrusive_ptr me(this); - - if (ec && ec != asio::error::eof) - { - fail(-1, ec.message().c_str()); - return; - } - - if (!parser.header_finished()) - { - fail(-1, "premature end of file"); - return; - } - - if (parser.status_code() != 200) - { - fail(parser.status_code(), parser.message().c_str()); - return; - } - - if (ec && ec != asio::error::eof) - { - fail(parser.status_code(), ec.message().c_str()); - return; - } - - // handle tracker response - entry e; - e = bdecode(data, data + size); - - if (e.type() == entry::dictionary_t) - { - parse(parser.status_code(), e); - } - else - { - std::string error_str("invalid bencoding of tracker response: \""); - for (char const* i = data, *end(data + size); i != end; ++i) - { - if (*i >= ' ' && *i <= '~') error_str += *i; - else error_str += "0x" + boost::lexical_cast((unsigned int)*i) + " "; - } - error_str += "\""; - fail(parser.status_code(), error_str.c_str()); - } - close(); - } - - bool http_tracker_connection::extract_peer_info(const entry& info, peer_entry& ret) - { - // extract peer id (if any) - if (info.type() != entry::dictionary_t) - { - fail(-1, "invalid response from tracker (invalid peer entry)"); - return false; - } - entry const* i = info.find_key("peer id"); - if (i != 0) - { - if (i->type() != entry::string_t || i->string().length() != 20) - { - fail(-1, "invalid response from tracker (invalid peer id)"); - return false; - } - std::copy(i->string().begin(), i->string().end(), ret.pid.begin()); - } - else - { - // if there's no peer_id, just initialize it to a bunch of zeroes - std::fill_n(ret.pid.begin(), 20, 0); - } - - // extract ip - i = info.find_key("ip"); - if (i == 0 || i->type() != entry::string_t) - { - fail(-1, "invalid response from tracker"); - return false; - } - ret.ip = i->string(); - - // extract port - i = info.find_key("port"); - if (i == 0 || i->type() != entry::int_t) - { - fail(-1, "invalid response from tracker"); - return false; - } - ret.port = (unsigned short)i->integer(); - - return true; - } - - void http_tracker_connection::parse(int status_code, entry const& e) - { - boost::shared_ptr cb = requester(); - if (!cb) return; - - // parse the response - entry const* failure = e.find_key("failure reason"); - if (failure && failure->type() == entry::string_t) - { - fail(status_code, failure->string().c_str()); - return; - } - - entry const* warning = e.find_key("warning message"); - if (warning && warning->type() == entry::string_t) - { - cb->tracker_warning(tracker_req(), warning->string()); - } - - std::vector peer_list; - - if (tracker_req().kind == tracker_request::scrape_request) - { - std::string ih = tracker_req().info_hash.to_string(); - - entry const* files = e.find_key("files"); - if (files == 0 || files->type() != entry::dictionary_t) - { - fail(-1, "invalid or missing 'files' entry in scrape response"); - return; - } - - entry const* scrape_data = files->find_key(ih); - if (scrape_data == 0 || scrape_data->type() != entry::dictionary_t) - { - fail(-1, "missing or invalid info-hash entry in scrape response"); - return; - } - entry const* complete = scrape_data->find_key("complete"); - entry const* incomplete = scrape_data->find_key("incomplete"); - entry const* downloaded = scrape_data->find_key("downloaded"); - if (complete == 0 || incomplete == 0 || downloaded == 0 - || complete->type() != entry::int_t - || incomplete->type() != entry::int_t - || downloaded->type() != entry::int_t) - { - fail(-1, "missing 'complete' or 'incomplete' entries in scrape response"); - return; - } - cb->tracker_scrape_response(tracker_req(), int(complete->integer()) - , int(incomplete->integer()), int(downloaded->integer())); - return; - } - - entry const* interval = e.find_key("interval"); - if (interval == 0 || interval->type() != entry::int_t) - { - fail(-1, "missing or invalid 'interval' entry in tracker response"); - return; - } - - entry const* peers_ent = e.find_key("peers"); - if (peers_ent == 0) - { - fail(-1, "missing 'peers' entry in tracker response"); - return; - } - - if (peers_ent->type() == entry::string_t) - { - std::string const& peers = peers_ent->string(); - for (std::string::const_iterator i = peers.begin(); - i != peers.end();) - { - if (std::distance(i, peers.end()) < 6) break; - - peer_entry p; - p.pid.clear(); - error_code ec; - p.ip = detail::read_v4_address(i).to_string(ec); - if (ec) continue; - p.port = detail::read_uint16(i); - peer_list.push_back(p); - } - } - else if (peers_ent->type() == entry::list_t) - { - entry::list_type const& l = peers_ent->list(); - for(entry::list_type::const_iterator i = l.begin(); i != l.end(); ++i) - { - peer_entry p; - if (!extract_peer_info(*i, p)) return; - peer_list.push_back(p); - } - } - else - { - fail(-1, "invalid 'peers' entry in tracker response"); - return; - } - - entry const* ipv6_peers = e.find_key("peers6"); - if (ipv6_peers && ipv6_peers->type() == entry::string_t) - { - std::string const& peers = ipv6_peers->string(); - for (std::string::const_iterator i = peers.begin(); - i != peers.end();) - { - if (std::distance(i, peers.end()) < 18) break; - - peer_entry p; - p.pid.clear(); - error_code ec; - p.ip = detail::read_v6_address(i).to_string(ec); - if (ec) continue; - p.port = detail::read_uint16(i); - peer_list.push_back(p); - } - } - - // look for optional scrape info - int complete = -1; - int incomplete = -1; - address external_ip; - - entry const* ip_ent = e.find_key("external ip"); - if (ip_ent && ip_ent->type() == entry::string_t) - { - std::string const& ip = ip_ent->string(); - char const* p = &ip[0]; - if (ip.size() == address_v4::bytes_type::static_size) - external_ip = detail::read_v4_address(p); - else if (ip.size() == address_v6::bytes_type::static_size) - external_ip = detail::read_v6_address(p); - } - - entry const* complete_ent = e.find_key("complete"); - if (complete_ent && complete_ent->type() == entry::int_t) - complete = int(complete_ent->integer()); - - entry const* incomplete_ent = e.find_key("incomplete"); - if (incomplete_ent && incomplete_ent->type() == entry::int_t) - incomplete = int(incomplete_ent->integer()); - - cb->tracker_response(tracker_req(), peer_list, interval->integer(), complete - , incomplete, external_ip); - } - -} - diff --git a/libtorrent/src/identify_client.cpp b/libtorrent/src/identify_client.cpp deleted file mode 100755 index 9ddfec612..000000000 --- a/libtorrent/src/identify_client.cpp +++ /dev/null @@ -1,384 +0,0 @@ -/* - -Copyright (c) 2003, Arvid Norberg -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions -are met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in - the documentation and/or other materials provided with the distribution. - * Neither the name of the author nor the names of its - contributors may be used to endorse or promote products derived - from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -POSSIBILITY OF SUCH DAMAGE. - -*/ - -#include "libtorrent/pch.hpp" - -#include -#include -#include - -#ifdef _MSC_VER -#pragma warning(push, 1) -#endif - -#include - -#ifdef _MSC_VER -#pragma warning(pop) -#endif - -#include "libtorrent/identify_client.hpp" -#include "libtorrent/fingerprint.hpp" -#include "libtorrent/escape_string.hpp" - -namespace -{ - - using namespace libtorrent; - - int decode_digit(char c) - { - if (is_digit(c)) return c - '0'; - return unsigned(c) - 'A' + 10; - } - - // takes a peer id and returns a valid boost::optional - // object if the peer id matched the azureus style encoding - // the returned fingerprint contains information about the - // client's id - boost::optional parse_az_style(const peer_id& id) - { - fingerprint ret("..", 0, 0, 0, 0); - - if (id[0] != '-' || !isprint(id[1]) || (id[2] < '0') - || (id[3] < '0') || (id[4] < '0') - || (id[5] < '0') || (id[6] < '0') - || id[7] != '-') - return boost::optional(); - - ret.name[0] = id[1]; - ret.name[1] = id[2]; - ret.major_version = decode_digit(id[3]); - ret.minor_version = decode_digit(id[4]); - ret.revision_version = decode_digit(id[5]); - ret.tag_version = decode_digit(id[6]); - - return boost::optional(ret); - } - - // checks if a peer id can possibly contain a shadow-style - // identification - boost::optional parse_shadow_style(const peer_id& id) - { - fingerprint ret("..", 0, 0, 0, 0); - - if (!std::isalnum(id[0])) - return boost::optional(); - - if (std::equal(id.begin()+4, id.begin()+6, "--")) - { - if ((id[1] < '0') || (id[2] < '0') - || (id[3] < '0')) - return boost::optional(); - ret.major_version = decode_digit(id[1]); - ret.minor_version = decode_digit(id[2]); - ret.revision_version = decode_digit(id[3]); - } - else - { - if (id[8] != 0 || id[1] > 127 || id[2] > 127 || id[3] > 127) - return boost::optional(); - ret.major_version = id[1]; - ret.minor_version = id[2]; - ret.revision_version = id[3]; - } - - ret.name[0] = id[0]; - ret.name[1] = 0; - - ret.tag_version = 0; - return boost::optional(ret); - } - - // checks if a peer id can possibly contain a mainline-style - // identification - boost::optional parse_mainline_style(const peer_id& id) - { - char ids[21]; - std::copy(id.begin(), id.end(), ids); - ids[20] = 0; - fingerprint ret("..", 0, 0, 0, 0); - ret.name[1] = 0; - ret.tag_version = 0; - if (sscanf(ids, "%c%d-%d-%d--", &ret.name[0], &ret.major_version, &ret.minor_version - , &ret.revision_version) != 4 - || !isprint(ret.name[0])) - return boost::optional(); - - return boost::optional(ret); - } - - struct map_entry - { - char const* id; - char const* name; - }; - - // only support BitTorrentSpecification - // must be ordered alphabetically - map_entry name_map[] = - { - {"A", "ABC"} - , {"AG", "Ares"} - , {"AR", "Arctic Torrent"} - , {"AV", "Avicora"} - , {"AX", "BitPump"} - , {"AZ", "Azureus"} - , {"A~", "Ares"} - , {"BB", "BitBuddy"} - , {"BC", "BitComet"} - , {"BF", "Bitflu"} - , {"BG", "BTG"} - , {"BR", "BitRocket"} - , {"BS", "BTSlave"} - , {"BX", "BittorrentX"} - , {"CD", "Enhanced CTorrent"} - , {"CT", "CTorrent"} - , {"DE", "Deluge Torrent"} - , {"EB", "EBit"} - , {"ES", "electric sheep"} - , {"HL", "Halite"} - , {"HN", "Hydranode"} - , {"KT", "KTorrent"} - , {"LC", "LeechCraft"} - , {"LK", "Linkage"} - , {"LP", "lphant"} - , {"LT", "libtorrent"} - , {"M", "Mainline"} - , {"ML", "MLDonkey"} - , {"MO", "Mono Torrent"} - , {"MP", "MooPolice"} - , {"MR", "Miro"} - , {"MT", "Moonlight Torrent"} - , {"O", "Osprey Permaseed"} - , {"PD", "Pando"} - , {"Q", "BTQueue"} - , {"QT", "Qt 4"} - , {"R", "Tribler"} - , {"S", "Shadow"} - , {"SB", "Swiftbit"} - , {"SN", "ShareNet"} - , {"SS", "SwarmScope"} - , {"ST", "SymTorrent"} - , {"SZ", "Shareaza"} - , {"S~", "Shareaza (beta)"} - , {"T", "BitTornado"} - , {"TN", "Torrent.NET"} - , {"TR", "Transmission"} - , {"TS", "TorrentStorm"} - , {"TT", "TuoTu"} - , {"U", "UPnP"} - , {"UL", "uLeecher"} - , {"UT", "uTorrent"} - , {"XL", "Xunlei"} - , {"XT", "XanTorrent"} - , {"XX", "Xtorrent"} - , {"ZT", "ZipTorrent"} - , {"lt", "rTorrent"} - , {"pX", "pHoeniX"} - , {"qB", "qBittorrent"} - , {"st", "SharkTorrent"} - }; - - struct generic_map_entry - { - int offset; - char const* id; - char const* name; - }; - // non-standard names - generic_map_entry generic_mappings[] = - { - {0, "Deadman Walking-", "Deadman"} - , {5, "Azureus", "Azureus 2.0.3.2"} - , {0, "DansClient", "XanTorrent"} - , {4, "btfans", "SimpleBT"} - , {0, "PRC.P---", "Bittorrent Plus! II"} - , {0, "P87.P---", "Bittorrent Plus!"} - , {0, "S587Plus", "Bittorrent Plus!"} - , {0, "martini", "Martini Man"} - , {0, "Plus---", "Bittorrent Plus"} - , {0, "turbobt", "TurboBT"} - , {0, "a00---0", "Swarmy"} - , {0, "a02---0", "Swarmy"} - , {0, "T00---0", "Teeweety"} - , {0, "BTDWV-", "Deadman Walking"} - , {2, "BS", "BitSpirit"} - , {0, "Pando-", "Pando"} - , {0, "LIME", "LimeWire"} - , {0, "btuga", "BTugaXP"} - , {0, "oernu", "BTugaXP"} - , {0, "Mbrst", "Burst!"} - , {0, "PEERAPP", "PeerApp"} - , {0, "Plus", "Plus!"} - , {0, "-Qt-", "Qt"} - , {0, "exbc", "BitComet"} - , {0, "DNA", "BitTorrent DNA"} - , {0, "-G3", "G3 Torrent"} - , {0, "-FG", "FlashGet"} - , {0, "-ML", "MLdonkey"} - , {0, "XBT", "XBT"} - , {0, "OP", "Opera"} - , {2, "RS", "Rufus"} - , {0, "AZ2500BT", "BitTyrant"} - }; - - bool compare_id(map_entry const& lhs, map_entry const& rhs) - { - return lhs.id[0] < rhs.id[0] - || ((lhs.id[0] == rhs.id[0]) && (lhs.id[1] < rhs.id[1])); - } - - std::string lookup(fingerprint const& f) - { - std::stringstream identity; - - const int size = sizeof(name_map)/sizeof(name_map[0]); - map_entry tmp = {f.name, ""}; - map_entry* i = - std::lower_bound(name_map, name_map + size - , tmp, &compare_id); - -#ifdef TORRENT_DEBUG - for (int i = 1; i < size; ++i) - { - TORRENT_ASSERT(compare_id(name_map[i-1] - , name_map[i])); - } -#endif - - if (i < name_map + size && std::equal(f.name, f.name + 2, i->id)) - identity << i->name; - else - { - identity << f.name[0]; - if (f.name[1] != 0) identity << f.name[1]; - } - - identity << " " << (int)f.major_version - << "." << (int)f.minor_version - << "." << (int)f.revision_version; - - if (f.name[1] != 0) - identity << "." << (int)f.tag_version; - - return identity.str(); - } - - bool find_string(unsigned char const* id, char const* search) - { - return std::equal(search, search + std::strlen(search), id); - } -} - -namespace libtorrent -{ - - boost::optional client_fingerprint(peer_id const& p) - { - // look for azureus style id - boost::optional f; - f = parse_az_style(p); - if (f) return f; - - // look for shadow style id - f = parse_shadow_style(p); - if (f) return f; - - // look for mainline style id - f = parse_mainline_style(p); - if (f) return f; - return f; - } - - std::string identify_client(peer_id const& p) - { - peer_id::const_iterator PID = p.begin(); - boost::optional f; - - if (p.is_all_zeros()) return "Unknown"; - - // ---------------------- - // non standard encodings - // ---------------------- - - int num_generic_mappings = sizeof(generic_mappings) / sizeof(generic_mappings[0]); - - for (int i = 0; i < num_generic_mappings; ++i) - { - generic_map_entry const& e = generic_mappings[i]; - if (find_string(PID + e.offset, e.id)) return e.name; - } - - if (find_string(PID, "-BOW") && PID[7] == '-') - return "Bits on Wheels " + std::string(PID + 4, PID + 7); - - - if (find_string(PID, "eX")) - { - std::string user(PID + 2, PID + 14); - return std::string("eXeem ('") + user.c_str() + "')"; - } - - if (std::equal(PID, PID + 13, "\0\0\0\0\0\0\0\0\0\0\0\0\x97")) - return "Experimental 3.2.1b2"; - - if (std::equal(PID, PID + 13, "\0\0\0\0\0\0\0\0\0\0\0\0\0")) - return "Experimental 3.1"; - - - // look for azureus style id - f = parse_az_style(p); - if (f) return lookup(*f); - - // look for shadow style id - f = parse_shadow_style(p); - if (f) return lookup(*f); - - // look for mainline style id - f = parse_mainline_style(p); - if (f) return lookup(*f); - - - if (std::equal(PID, PID + 12, "\0\0\0\0\0\0\0\0\0\0\0\0")) - return "Generic"; - - std::string unknown("Unknown ["); - for (peer_id::const_iterator i = p.begin(); i != p.end(); ++i) - { - unknown += isprint(char(*i))?*i:'.'; - } - unknown += "]"; - return unknown; - } - -} diff --git a/libtorrent/src/instantiate_connection.cpp b/libtorrent/src/instantiate_connection.cpp deleted file mode 100644 index 776ab6a12..000000000 --- a/libtorrent/src/instantiate_connection.cpp +++ /dev/null @@ -1,81 +0,0 @@ -/* - -Copyright (c) 2007, Arvid Norberg -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions -are met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in - the documentation and/or other materials provided with the distribution. - * Neither the name of the author nor the names of its - contributors may be used to endorse or promote products derived - from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -POSSIBILITY OF SUCH DAMAGE. - -*/ - -#include "libtorrent/pch.hpp" - -#include "libtorrent/socket.hpp" -#include "libtorrent/session_settings.hpp" -#include "libtorrent/socket_type.hpp" -#include -#include - -namespace libtorrent -{ - - bool instantiate_connection(io_service& ios - , proxy_settings const& ps, socket_type& s) - { - if (ps.type == proxy_settings::none) - { - s.instantiate(ios); - } - else if (ps.type == proxy_settings::http - || ps.type == proxy_settings::http_pw) - { - s.instantiate(ios); - s.get().set_proxy(ps.hostname, ps.port); - if (ps.type == proxy_settings::http_pw) - s.get().set_username(ps.username, ps.password); - } - else if (ps.type == proxy_settings::socks5 - || ps.type == proxy_settings::socks5_pw) - { - s.instantiate(ios); - s.get().set_proxy(ps.hostname, ps.port); - if (ps.type == proxy_settings::socks5_pw) - s.get().set_username(ps.username, ps.password); - } - else if (ps.type == proxy_settings::socks4) - { - s.instantiate(ios); - s.get().set_proxy(ps.hostname, ps.port); - s.get().set_username(ps.username); - } - else - { - return false; - } - return true; - } - -} - diff --git a/libtorrent/src/ip_filter.cpp b/libtorrent/src/ip_filter.cpp deleted file mode 100644 index eb91de0d0..000000000 --- a/libtorrent/src/ip_filter.cpp +++ /dev/null @@ -1,91 +0,0 @@ -/* - -Copyright (c) 2005, Arvid Norberg -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions -are met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in - the documentation and/or other materials provided with the distribution. - * Neither the name of the author nor the names of its - contributors may be used to endorse or promote products derived - from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -POSSIBILITY OF SUCH DAMAGE. - -*/ - -#include "libtorrent/pch.hpp" - -#include "libtorrent/ip_filter.hpp" -#include -//#include - - -namespace libtorrent -{ - void ip_filter::add_rule(address first, address last, int flags) - { - if (first.is_v4()) - { - TORRENT_ASSERT(last.is_v4()); - m_filter4.add_rule(first.to_v4().to_bytes(), last.to_v4().to_bytes(), flags); - } - else if (first.is_v6()) - { - TORRENT_ASSERT(last.is_v6()); - m_filter6.add_rule(first.to_v6().to_bytes(), last.to_v6().to_bytes(), flags); - } - else - TORRENT_ASSERT(false); - } - - int ip_filter::access(address const& addr) const - { - if (addr.is_v4()) - return m_filter4.access(addr.to_v4().to_bytes()); - TORRENT_ASSERT(addr.is_v6()); - return m_filter6.access(addr.to_v6().to_bytes()); - } - - ip_filter::filter_tuple_t ip_filter::export_filter() const - { - return boost::make_tuple(m_filter4.export_filter() - , m_filter6.export_filter()); - } - - void port_filter::add_rule(boost::uint16_t first, boost::uint16_t last, int flags) - { - m_filter.add_rule(first, last, flags); - } - - int port_filter::access(boost::uint16_t port) const - { - return m_filter.access(port); - } -/* - void ip_filter::print() const - { - for (range_t::iterator i = m_access_list.begin(); i != m_access_list.end(); ++i) - { - std::cout << i->start.as_string() << " " << i->access << "\n"; - } - } -*/ -} - diff --git a/libtorrent/src/kademlia/closest_nodes.cpp b/libtorrent/src/kademlia/closest_nodes.cpp deleted file mode 100644 index e9039642f..000000000 --- a/libtorrent/src/kademlia/closest_nodes.cpp +++ /dev/null @@ -1,137 +0,0 @@ -/* - -Copyright (c) 2006, Arvid Norberg & Daniel Wallin -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions -are met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in - the documentation and/or other materials provided with the distribution. - * Neither the name of the author nor the names of its - contributors may be used to endorse or promote products derived - from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -POSSIBILITY OF SUCH DAMAGE. - -*/ - -#include "libtorrent/pch.hpp" - -#include -#include -#include -#include "libtorrent/assert.hpp" - -namespace libtorrent { namespace dht -{ - -closest_nodes_observer::~closest_nodes_observer() -{ - if (m_algorithm) m_algorithm->failed(m_self, true); -} - -void closest_nodes_observer::reply(msg const& in) -{ - if (!m_algorithm) - { - TORRENT_ASSERT(false); - return; - } - - if (!in.nodes.empty()) - { - for (msg::nodes_t::const_iterator i = in.nodes.begin() - , end(in.nodes.end()); i != end; ++i) - { - m_algorithm->traverse(i->id, i->addr); - } - } - m_algorithm->finished(m_self); - m_algorithm = 0; -} - -void closest_nodes_observer::timeout() -{ - if (!m_algorithm) return; - m_algorithm->failed(m_self); - m_algorithm = 0; -} - - -closest_nodes::closest_nodes( - node_id target - , int branch_factor - , int max_results - , routing_table& table - , rpc_manager& rpc - , done_callback const& callback -) - : traversal_algorithm( - target - , branch_factor - , max_results - , table - , rpc - , table.begin() - , table.end() - ) - , m_done_callback(callback) -{ - boost::intrusive_ptr self(this); - add_requests(); -} - -void closest_nodes::invoke(node_id const& id, udp::endpoint addr) -{ - TORRENT_ASSERT(m_rpc.allocation_size() >= sizeof(closest_nodes_observer)); - observer_ptr o(new (m_rpc.allocator().malloc()) closest_nodes_observer(this, id, m_target)); -#ifdef TORRENT_DEBUG - o->m_in_constructor = false; -#endif - m_rpc.invoke(messages::find_node, addr, o); -} - -void closest_nodes::done() -{ - std::vector results; - int num_results = m_max_results; - for (std::vector::iterator i = m_results.begin() - , end(m_results.end()); i != end && num_results > 0; ++i) - { - if (i->flags & result::no_id) continue; - if ((i->flags & result::queried) == 0) continue; - results.push_back(node_entry(i->id, i->addr)); - --num_results; - } - m_done_callback(results); -} - -void closest_nodes::initiate( - node_id target - , int branch_factor - , int max_results - , routing_table& table - , rpc_manager& rpc - , done_callback const& callback -) -{ - new closest_nodes(target, branch_factor, max_results, table, rpc, callback); -} - -} } // namespace libtorrent::dht - diff --git a/libtorrent/src/kademlia/dht_tracker.cpp b/libtorrent/src/kademlia/dht_tracker.cpp deleted file mode 100644 index 88bc7738d..000000000 --- a/libtorrent/src/kademlia/dht_tracker.cpp +++ /dev/null @@ -1,1002 +0,0 @@ -/* - -Copyright (c) 2006, Arvid Norberg -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions -are met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in - the documentation and/or other materials provided with the distribution. - * Neither the name of the author nor the names of its - contributors may be used to endorse or promote products derived - from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -POSSIBILITY OF SUCH DAMAGE. - -*/ - -#include "libtorrent/pch.hpp" - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "libtorrent/kademlia/node.hpp" -#include "libtorrent/kademlia/node_id.hpp" -#include "libtorrent/kademlia/traversal_algorithm.hpp" -#include "libtorrent/kademlia/dht_tracker.hpp" - -#include "libtorrent/socket.hpp" -#include "libtorrent/bencode.hpp" -#include "libtorrent/io.hpp" -#include "libtorrent/version.hpp" -#include "libtorrent/escape_string.hpp" - -using boost::ref; -using boost::lexical_cast; -using libtorrent::dht::node_impl; -using libtorrent::dht::node_id; -using libtorrent::dht::packet_t; -using libtorrent::dht::msg; -namespace messages = libtorrent::dht::messages; -using namespace libtorrent::detail; - -enum -{ - key_refresh = 5 // generate a new write token key every 5 minutes -}; - -namespace -{ - const int tick_period = 1; // minutes - - struct count_peers - { - int& count; - count_peers(int& c): count(c) {} - void operator()(std::pair const& t) - { - count += std::distance(t.second.peers.begin() - , t.second.peers.end()); - } - }; - - template - void read_endpoint_list(libtorrent::entry const* n, std::vector& epl) - { - using namespace libtorrent; - if (n->type() != entry::list_t) return; - entry::list_type const& contacts = n->list(); - for (entry::list_type::const_iterator i = contacts.begin() - , end(contacts.end()); i != end; ++i) - { - if (i->type() != entry::string_t) return; - std::string const& p = i->string(); - if (p.size() < 6) continue; - std::string::const_iterator in = p.begin(); - if (p.size() == 6) - epl.push_back(read_v4_endpoint(in)); - else if (p.size() == 18) - epl.push_back(read_v6_endpoint(in)); - } - } - -} - -namespace libtorrent { namespace dht -{ - - void intrusive_ptr_add_ref(dht_tracker const* c) - { - TORRENT_ASSERT(c != 0); - TORRENT_ASSERT(c->m_refs >= 0); - ++c->m_refs; - } - - void intrusive_ptr_release(dht_tracker const* c) - { - TORRENT_ASSERT(c != 0); - TORRENT_ASSERT(c->m_refs > 0); - if (--c->m_refs == 0) - delete c; - } - -#ifdef TORRENT_DHT_VERBOSE_LOGGING - TORRENT_DEFINE_LOG(dht_tracker) -#endif - - boost::optional extract_node_id(entry const* e) - { - if (e == 0 || e->type() != entry::dictionary_t) return boost::optional(); - entry const* nid = e->find_key("node-id"); - if (nid == 0 || nid->type() != entry::string_t || nid->string().length() != 20) - return boost::optional(); - return boost::optional(node_id(nid->string().c_str())); - } - - // class that puts the networking and the kademlia node in a single - // unit and connecting them together. - dht_tracker::dht_tracker(udp_socket& sock, dht_settings const& settings - , entry const* state) - : m_dht(bind(&dht_tracker::send_packet, this, _1), settings, extract_node_id(state)) - , m_sock(sock) - , m_last_new_key(time_now() - minutes(key_refresh)) - , m_timer(sock.get_io_service()) - , m_connection_timer(sock.get_io_service()) - , m_refresh_timer(sock.get_io_service()) - , m_settings(settings) - , m_refresh_bucket(160) - , m_abort(false) - , m_host_resolver(sock.get_io_service()) - , m_refs(0) - { - using boost::bind; - -#ifdef TORRENT_DHT_VERBOSE_LOGGING - m_counter = 0; - std::fill_n(m_replies_bytes_sent, 5, 0); - std::fill_n(m_queries_bytes_received, 5, 0); - std::fill_n(m_replies_sent, 5, 0); - std::fill_n(m_queries_received, 5, 0); - m_announces = 0; - m_failed_announces = 0; - m_total_message_input = 0; - m_ut_message_input = 0; - m_lt_message_input = 0; - m_mp_message_input = 0; - m_gr_message_input = 0; - m_mo_message_input = 0; - m_total_in_bytes = 0; - m_total_out_bytes = 0; - m_queries_out_bytes = 0; - - // turns on and off individual components' logging - -// rpc_log().enable(false); -// node_log().enable(false); -// traversal_log().enable(false); -// dht_tracker_log.enable(false); - -#endif - } - - void dht_tracker::start(entry const& bootstrap) - { - std::vector initial_nodes; - - if (bootstrap.type() == entry::dictionary_t) - { - try - { - if (entry const* nodes = bootstrap.find_key("nodes")) - read_endpoint_list(nodes, initial_nodes); - } catch (std::exception&) {} - } - - error_code ec; - m_timer.expires_from_now(seconds(1), ec); - m_timer.async_wait(bind(&dht_tracker::tick, self(), _1)); - - m_connection_timer.expires_from_now(seconds(10), ec); - m_connection_timer.async_wait( - bind(&dht_tracker::connection_timeout, self(), _1)); - - m_refresh_timer.expires_from_now(seconds(5), ec); - m_refresh_timer.async_wait(bind(&dht_tracker::refresh_timeout, self(), _1)); - - m_dht.bootstrap(initial_nodes, bind(&dht_tracker::on_bootstrap, self())); - } - - void dht_tracker::stop() - { - mutex_t::scoped_lock l(m_mutex); - m_abort = true; - error_code ec; - m_timer.cancel(ec); - m_connection_timer.cancel(ec); - m_refresh_timer.cancel(ec); - m_host_resolver.cancel(); - } - - void dht_tracker::dht_status(session_status& s) - { - boost::tie(s.dht_nodes, s.dht_node_cache) = m_dht.size(); - s.dht_torrents = m_dht.data_size(); - s.dht_global_nodes = m_dht.num_global_nodes(); - } - - void dht_tracker::connection_timeout(error_code const& e) - try - { - mutex_t::scoped_lock l(m_mutex); - if (e || m_abort) return; - - time_duration d = m_dht.connection_timeout(); - m_connection_timer.expires_from_now(d); - m_connection_timer.async_wait(bind(&dht_tracker::connection_timeout, self(), _1)); - } - catch (std::exception& exc) - { -#ifdef TORRENT_DEBUG - std::cerr << "exception-type: " << typeid(exc).name() << std::endl; - std::cerr << "what: " << exc.what() << std::endl; - TORRENT_ASSERT(false); -#endif - }; - - void dht_tracker::refresh_timeout(error_code const& e) - try - { - mutex_t::scoped_lock l(m_mutex); - if (e || m_abort) return; - - time_duration d = m_dht.refresh_timeout(); - m_refresh_timer.expires_from_now(d); - m_refresh_timer.async_wait( - bind(&dht_tracker::refresh_timeout, self(), _1)); - } - catch (std::exception&) - { - TORRENT_ASSERT(false); - }; - - void dht_tracker::tick(error_code const& e) - try - { - mutex_t::scoped_lock l(m_mutex); - if (e || m_abort) return; - - m_timer.expires_from_now(minutes(tick_period)); - m_timer.async_wait(bind(&dht_tracker::tick, self(), _1)); - - ptime now = time_now(); - if (now - m_last_new_key > minutes(key_refresh)) - { - m_last_new_key = now; - m_dht.new_write_key(); -#ifdef TORRENT_DHT_VERBOSE_LOGGING - TORRENT_LOG(dht_tracker) << time_now_string() << " new write key"; -#endif - } - -#ifdef TORRENT_DHT_VERBOSE_LOGGING - static bool first = true; - if (first) - { - boost::filesystem::create_directory("libtorrent_logs"); - } - - std::ofstream st("libtorrent_logs/routing_table_state.txt", std::ios_base::trunc); - m_dht.print_state(st); - - // count torrents - int torrents = std::distance(m_dht.begin_data(), m_dht.end_data()); - - // count peers - int peers = 0; - std::for_each(m_dht.begin_data(), m_dht.end_data(), count_peers(peers)); - - std::ofstream pc("libtorrent_logs/dht_stats.log", first ? std::ios_base::trunc : std::ios_base::app); - if (first) - { - first = false; - pc << "\n\n ***** starting log at " << time_now_string() << " *****\n\n" - << "minute:active nodes:passive nodes" - ":ping replies sent:ping queries recvd" - ":ping replies bytes sent:ping queries bytes recvd" - ":find_node replies sent:find_node queries recv" - ":find_node replies bytes sent:find_node queries bytes recv" - ":get_peers replies sent:get_peers queries recvd" - ":get_peers replies bytes sent:get_peers queries bytes recv" - ":announce_peer replies sent:announce_peer queries recvd" - ":announce_peer replies bytes sent:announce_peer queries bytes recv" - ":error replies sent:error queries recvd" - ":error replies bytes sent:error queries bytes recv" - ":num torrents:num peers:announces per min" - ":failed announces per min:total msgs per min" - ":ut msgs per min:lt msgs per min:mp msgs per min" - ":gr msgs per min:mo msgs per min:bytes in per sec:bytes out per sec" - ":queries out bytes per sec\n\n"; - } - - int active; - int passive; - boost::tie(active, passive) = m_dht.size(); - pc << (m_counter * tick_period) - << "\t" << active - << "\t" << passive; - for (int i = 0; i < 5; ++i) - pc << "\t" << (m_replies_sent[i] / float(tick_period)) - << "\t" << (m_queries_received[i] / float(tick_period)) - << "\t" << (m_replies_bytes_sent[i] / float(tick_period*60)) - << "\t" << (m_queries_bytes_received[i] / float(tick_period*60)); - - pc << "\t" << torrents - << "\t" << peers - << "\t" << m_announces / float(tick_period) - << "\t" << m_failed_announces / float(tick_period) - << "\t" << (m_total_message_input / float(tick_period)) - << "\t" << (m_ut_message_input / float(tick_period)) - << "\t" << (m_lt_message_input / float(tick_period)) - << "\t" << (m_mp_message_input / float(tick_period)) - << "\t" << (m_gr_message_input / float(tick_period)) - << "\t" << (m_mo_message_input / float(tick_period)) - << "\t" << (m_total_in_bytes / float(tick_period*60)) - << "\t" << (m_total_out_bytes / float(tick_period*60)) - << "\t" << (m_queries_out_bytes / float(tick_period*60)) - << std::endl; - ++m_counter; - std::fill_n(m_replies_bytes_sent, 5, 0); - std::fill_n(m_queries_bytes_received, 5, 0); - std::fill_n(m_replies_sent, 5, 0); - std::fill_n(m_queries_received, 5, 0); - m_announces = 0; - m_failed_announces = 0; - m_total_message_input = 0; - m_ut_message_input = 0; - m_lt_message_input = 0; - m_total_in_bytes = 0; - m_total_out_bytes = 0; - m_queries_out_bytes = 0; -#endif - } - catch (std::exception&) - { - TORRENT_ASSERT(false); - }; - - void dht_tracker::announce(sha1_hash const& ih, int listen_port - , boost::function const& - , sha1_hash const&)> f) - { - m_dht.announce(ih, listen_port, f); - } - - - void dht_tracker::on_unreachable(udp::endpoint const& ep) - { - m_dht.unreachable(ep); - } - - // translate bittorrent kademlia message into the generice kademlia message - // used by the library - void dht_tracker::on_receive(udp::endpoint const& ep, char const* buf, int bytes_transferred) - try - { - node_ban_entry* match = 0; - node_ban_entry* min = m_ban_nodes; - ptime now = time_now(); - for (node_ban_entry* i = m_ban_nodes; i < m_ban_nodes + num_ban_nodes; ++i) - { - if (i->src == ep) - { - match = i; - break; - } - if (i->count < min->count) min = i; - } - - if (match) - { - ++match->count; - if (match->count >= 20) - { - if (now < match->limit) - { -#ifdef TORRENT_DHT_VERBOSE_LOGGING - if (match->count == 20) - { - TORRENT_LOG(dht_tracker) << time_now_string() << " BANNING PEER [ ip: " - << ep << " time: " << total_milliseconds((now - match->limit) + seconds(5)) / 1000.f - << " count: " << match->count << " ]"; - } -#endif - // we've received 20 messages in less than 5 seconds from - // this node. Ignore it until it's silent for 5 minutes - match->limit = now + minutes(5); - return; - } - - // we got 50 messages from this peer, but it was in - // more than 5 seconds. Reset the counter and the timer - match->count = 0; - match->limit = now + seconds(5); - } - } - else - { - min->count = 1; - min->limit = now + seconds(5); - min->src = ep; - } - -#ifdef TORRENT_DHT_VERBOSE_LOGGING - ++m_total_message_input; - m_total_in_bytes += bytes_transferred; -#endif - - try - { - using libtorrent::entry; - using libtorrent::bdecode; - - TORRENT_ASSERT(bytes_transferred > 0); - - entry e = bdecode(buf, buf + bytes_transferred); - if (e.type() == entry::undefined_t) - { -#ifdef TORRENT_DHT_VERBOSE_LOGGING - std::string msg(buf, buf + bytes_transferred); - TORRENT_LOG(dht_tracker) << "invalid incoming packet\n"; -#endif - return; - } - -#ifdef TORRENT_DHT_VERBOSE_LOGGING - std::stringstream log_line; - log_line << time_now_string() << " RECEIVED [" - " ip: " << ep; -#endif - - libtorrent::dht::msg m; - m.message_id = 0; - m.addr = ep; - m.transaction_id = e["t"].string(); - -#ifdef TORRENT_DHT_VERBOSE_LOGGING - log_line << " t: " << to_hex(m.transaction_id); - - try - { - entry const* ver = e.find_key("v"); - if (!ver) throw std::exception(); - - std::string const& client = ver->string(); - if (client.size() > 1 && std::equal(client.begin(), client.begin() + 2, "UT")) - { - ++m_ut_message_input; - log_line << " c: uTorrent"; - } - else if (client.size() > 1 && std::equal(client.begin(), client.begin() + 2, "LT")) - { - ++m_lt_message_input; - log_line << " c: libtorrent"; - } - else if (client.size() > 1 && std::equal(client.begin(), client.begin() + 2, "MP")) - { - ++m_mp_message_input; - log_line << " c: MooPolice"; - } - else if (client.size() > 1 && std::equal(client.begin(), client.begin() + 2, "GR")) - { - ++m_gr_message_input; - log_line << " c: GetRight"; - } - else if (client.size() > 1 && std::equal(client.begin(), client.begin() + 2, "MO")) - { - ++m_mo_message_input; - log_line << " c: Mono Torrent"; - } - else - { - log_line << " c: " << client; - } - } - catch (std::exception&) - { - log_line << " c: generic"; - }; -#endif - - std::string const& msg_type = e["y"].string(); - - if (msg_type == "r") - { -#ifdef TORRENT_DHT_VERBOSE_LOGGING - log_line << " r: " << messages::ids[m.message_id]; -#endif - - m.reply = true; - entry const& r = e["r"]; - std::string const& id = r["id"].string(); - if (id.size() != 20) throw std::runtime_error("invalid size of id"); - std::copy(id.begin(), id.end(), m.id.begin()); - - if (entry const* n = r.find_key("values")) - { - m.peers.clear(); - if (n->list().size() == 1) - { - // assume it's mainline format - std::string const& peers = n->list().front().string(); - std::string::const_iterator i = peers.begin(); - std::string::const_iterator end = peers.end(); - - while (std::distance(i, end) >= 6) - m.peers.push_back(read_v4_endpoint(i)); - } - else - { - // assume it's uTorrent/libtorrent format - read_endpoint_list(n, m.peers); - } -#ifdef TORRENT_DHT_VERBOSE_LOGGING - log_line << " p: " << m.peers.size(); -#endif - } - - m.nodes.clear(); - if (entry const* n = r.find_key("nodes")) - { - std::string const& nodes = n->string(); - std::string::const_iterator i = nodes.begin(); - std::string::const_iterator end = nodes.end(); - - while (std::distance(i, end) >= 26) - { - node_id id; - std::copy(i, i + 20, id.begin()); - i += 20; - m.nodes.push_back(libtorrent::dht::node_entry( - id, read_v4_endpoint(i))); - } -#ifdef TORRENT_DHT_VERBOSE_LOGGING - log_line << " n: " << m.nodes.size(); -#endif - } - - if (entry const* n = r.find_key("nodes2")) - { - entry::list_type const& contacts = n->list(); - for (entry::list_type::const_iterator i = contacts.begin() - , end(contacts.end()); i != end; ++i) - { - std::string const& p = i->string(); - if (p.size() < 6 + 20) continue; - std::string::const_iterator in = p.begin(); - - node_id id; - std::copy(in, in + 20, id.begin()); - in += 20; - if (p.size() == 6 + 20) - m.nodes.push_back(libtorrent::dht::node_entry( - id, read_v4_endpoint(in))); - else if (p.size() == 18 + 20) - m.nodes.push_back(libtorrent::dht::node_entry( - id, read_v6_endpoint(in))); - } -#ifdef TORRENT_DHT_VERBOSE_LOGGING - log_line << " n2: " << m.nodes.size(); -#endif - } - - entry const* token = r.find_key("token"); - if (token) m.write_token = *token; - } - else if (msg_type == "q") - { - m.reply = false; - entry const& a = e["a"]; - std::string const& id = a["id"].string(); - if (id.size() != 20) throw std::runtime_error("invalid size of id"); - std::copy(id.begin(), id.end(), m.id.begin()); - - std::string request_kind(e["q"].string()); -#ifdef TORRENT_DHT_VERBOSE_LOGGING - log_line << " q: " << request_kind; -#endif - - if (request_kind == "ping") - { - m.message_id = libtorrent::dht::messages::ping; - } - else if (request_kind == "find_node") - { - std::string const& target = a["target"].string(); - if (target.size() != 20) throw std::runtime_error("invalid size of target id"); - std::copy(target.begin(), target.end(), m.info_hash.begin()); -#ifdef TORRENT_DHT_VERBOSE_LOGGING - log_line << " target: " << boost::lexical_cast(m.info_hash); -#endif - - m.message_id = libtorrent::dht::messages::find_node; - } - else if (request_kind == "get_peers") - { - std::string const& info_hash = a["info_hash"].string(); - if (info_hash.size() != 20) throw std::runtime_error("invalid size of info-hash"); - std::copy(info_hash.begin(), info_hash.end(), m.info_hash.begin()); - m.message_id = libtorrent::dht::messages::get_peers; -#ifdef TORRENT_DHT_VERBOSE_LOGGING - log_line << " ih: " << boost::lexical_cast(m.info_hash); -#endif - } - else if (request_kind == "announce_peer") - { -#ifdef TORRENT_DHT_VERBOSE_LOGGING - ++m_announces; -#endif - std::string const& info_hash = a["info_hash"].string(); - if (info_hash.size() != 20) - throw std::runtime_error("invalid size of info-hash"); - std::copy(info_hash.begin(), info_hash.end(), m.info_hash.begin()); - m.port = a["port"].integer(); - m.write_token = a["token"]; - m.message_id = libtorrent::dht::messages::announce_peer; -#ifdef TORRENT_DHT_VERBOSE_LOGGING - log_line << " ih: " << boost::lexical_cast(m.info_hash); - log_line << " p: " << m.port; - - if (!m_dht.verify_token(m)) - ++m_failed_announces; -#endif - } - else - { -#ifdef TORRENT_DHT_VERBOSE_LOGGING - TORRENT_LOG(dht_tracker) << " *** UNSUPPORTED REQUEST *** : " - << request_kind; -#endif - throw std::runtime_error("unsupported request: " + request_kind); - } - } - else if (msg_type == "e") - { - entry::list_type const& list = e["e"].list(); - m.message_id = messages::error; - m.error_msg = list.back().string(); - m.error_code = list.front().integer(); -#ifdef TORRENT_DHT_VERBOSE_LOGGING - log_line << " incoming error: " << m.error_code - << " " << m.error_msg; -#endif - throw std::runtime_error("DHT error message"); - } - else - { -#ifdef TORRENT_DHT_VERBOSE_LOGGING - TORRENT_LOG(dht_tracker) << " *** UNSUPPORTED MESSAGE TYPE *** : " - << msg_type; -#endif - throw std::runtime_error("unsupported message type: " + msg_type); - } - -#ifdef TORRENT_DHT_VERBOSE_LOGGING - if (!m.reply) - { - ++m_queries_received[m.message_id]; - m_queries_bytes_received[m.message_id] += int(bytes_transferred); - } - TORRENT_LOG(dht_tracker) << log_line.str() << " ]"; -#endif - TORRENT_ASSERT(m.message_id != messages::error); - m_dht.incoming(m); - } - catch (std::exception& e) - { -#ifdef TORRENT_DHT_VERBOSE_LOGGING - std::string msg(buf, buf + bytes_transferred); - TORRENT_LOG(dht_tracker) << "invalid incoming packet: " - << e.what() << "\n" << msg << "\n"; -#endif - } - } - catch (std::exception& e) - { - TORRENT_ASSERT(false); - }; - - entry dht_tracker::state() const - { - entry ret(entry::dictionary_t); - { - entry nodes(entry::list_t); - for (node_impl::iterator i(m_dht.begin()) - , end(m_dht.end()); i != end; ++i) - { - std::string node; - std::back_insert_iterator out(node); - write_endpoint(i->addr, out); - nodes.list().push_back(entry(node)); - } - bucket_t cache; - m_dht.replacement_cache(cache); - for (bucket_t::iterator i(cache.begin()) - , end(cache.end()); i != end; ++i) - { - std::string node; - std::back_insert_iterator out(node); - write_endpoint(i->addr, out); - nodes.list().push_back(entry(node)); - } - if (!nodes.list().empty()) - ret["nodes"] = nodes; - } - - ret["node-id"] = boost::lexical_cast(m_dht.nid()); - return ret; - } - - void dht_tracker::add_node(udp::endpoint node) - { - m_dht.add_node(node); - } - - void dht_tracker::add_node(std::pair const& node) - { - udp::resolver::query q(node.first, lexical_cast(node.second)); - m_host_resolver.async_resolve(q, - bind(&dht_tracker::on_name_lookup, self(), _1, _2)); - } - - void dht_tracker::on_name_lookup(error_code const& e - , udp::resolver::iterator host) try - { - if (e || host == udp::resolver::iterator()) return; - add_node(host->endpoint()); - } - catch (std::exception&) - { - TORRENT_ASSERT(false); - }; - - void dht_tracker::add_router_node(std::pair const& node) - { - udp::resolver::query q(node.first, lexical_cast(node.second)); - m_host_resolver.async_resolve(q, - bind(&dht_tracker::on_router_name_lookup, self(), _1, _2)); - } - - void dht_tracker::on_router_name_lookup(error_code const& e - , udp::resolver::iterator host) try - { - if (e || host == udp::resolver::iterator()) return; - m_dht.add_router_node(host->endpoint()); - } - catch (std::exception&) - { - TORRENT_ASSERT(false); - }; - - void dht_tracker::on_bootstrap() - {} - - namespace - { - void write_nodes_entry(entry& r, libtorrent::dht::msg const& m) - { - bool ipv6_nodes = false; - entry& n = r["nodes"]; - std::back_insert_iterator out(n.string()); - for (msg::nodes_t::const_iterator i = m.nodes.begin() - , end(m.nodes.end()); i != end; ++i) - { - if (!i->addr.address().is_v4()) - { - ipv6_nodes = true; - continue; - } - std::copy(i->id.begin(), i->id.end(), out); - write_endpoint(i->addr, out); - } - - if (ipv6_nodes) - { - entry& p = r["nodes2"]; - std::string endpoint; - for (msg::nodes_t::const_iterator i = m.nodes.begin() - , end(m.nodes.end()); i != end; ++i) - { - if (!i->addr.address().is_v6()) continue; - endpoint.resize(18 + 20); - std::string::iterator out = endpoint.begin(); - std::copy(i->id.begin(), i->id.end(), out); - out += 20; - write_endpoint(i->addr, out); - endpoint.resize(out - endpoint.begin()); - p.list().push_back(entry(endpoint)); - } - } - } - } - - void dht_tracker::send_packet(msg const& m) - try - { - using libtorrent::bencode; - using libtorrent::entry; - entry e(entry::dictionary_t); - TORRENT_ASSERT(!m.transaction_id.empty() || m.message_id == messages::error); - e["t"] = m.transaction_id; - static char const version_str[] = {'L', 'T' - , LIBTORRENT_VERSION_MAJOR, LIBTORRENT_VERSION_MINOR}; - e["v"] = std::string(version_str, version_str + 4); - -#ifdef TORRENT_DHT_VERBOSE_LOGGING - std::stringstream log_line; - log_line << time_now_string() - << " SENDING [ ip: " << m.addr - << " t: " << to_hex(m.transaction_id); -#endif - - if (m.message_id == messages::error) - { - TORRENT_ASSERT(m.reply); - e["y"] = "e"; - entry error_list(entry::list_t); - TORRENT_ASSERT(m.error_code > 200 && m.error_code <= 204); - error_list.list().push_back(entry(m.error_code)); - error_list.list().push_back(entry(m.error_msg)); - e["e"] = error_list; -#ifdef TORRENT_DHT_VERBOSE_LOGGING - log_line << " err: " << m.error_code - << " msg: " << m.error_msg; -#endif - } - else if (m.reply) - { - e["y"] = "r"; - e["r"] = entry(entry::dictionary_t); - entry& r = e["r"]; - r["id"] = std::string(m.id.begin(), m.id.end()); - -#ifdef TORRENT_DHT_VERBOSE_LOGGING - log_line << " r: " << messages::ids[m.message_id]; -#endif - - if (m.write_token.type() != entry::undefined_t) - r["token"] = m.write_token; - - switch (m.message_id) - { - case messages::ping: - break; - case messages::find_node: - { - write_nodes_entry(r, m); - break; - } - case messages::get_peers: - { - if (m.peers.empty()) - { - write_nodes_entry(r, m); - } - else - { - r["values"] = entry(entry::list_t); - entry& p = r["values"]; - std::string endpoint; - for (msg::peers_t::const_iterator i = m.peers.begin() - , end(m.peers.end()); i != end; ++i) - { - endpoint.resize(18); - std::string::iterator out = endpoint.begin(); - write_endpoint(*i, out); - endpoint.resize(out - endpoint.begin()); - p.list().push_back(entry(endpoint)); - } -#ifdef TORRENT_DHT_VERBOSE_LOGGING - log_line << " p: " << m.peers.size(); -#endif - } - break; - } - - case messages::announce_peer: - break; - break; - } - } - else - { - e["y"] = "q"; - e["a"] = entry(entry::dictionary_t); - entry& a = e["a"]; - a["id"] = std::string(m.id.begin(), m.id.end()); - - if (m.write_token.type() != entry::undefined_t) - a["token"] = m.write_token; - TORRENT_ASSERT(m.message_id <= messages::error); - e["q"] = messages::ids[m.message_id]; - -#ifdef TORRENT_DHT_VERBOSE_LOGGING - log_line << " q: " << messages::ids[m.message_id]; -#endif - - switch (m.message_id) - { - case messages::find_node: - { - a["target"] = std::string(m.info_hash.begin(), m.info_hash.end()); -#ifdef TORRENT_DHT_VERBOSE_LOGGING - log_line << " target: " << boost::lexical_cast(m.info_hash); -#endif - break; - } - case messages::get_peers: - { - a["info_hash"] = std::string(m.info_hash.begin(), m.info_hash.end()); -#ifdef TORRENT_DHT_VERBOSE_LOGGING - log_line << " ih: " << boost::lexical_cast(m.info_hash); -#endif - break; - } - case messages::announce_peer: - a["port"] = m.port; - a["info_hash"] = std::string(m.info_hash.begin(), m.info_hash.end()); - a["token"] = m.write_token; -#ifdef TORRENT_DHT_VERBOSE_LOGGING - log_line << " p: " << m.port - << " ih: " << boost::lexical_cast(m.info_hash); -#endif - break; - default: break; - } - - } - - m_send_buf.clear(); - bencode(std::back_inserter(m_send_buf), e); - error_code ec; - m_sock.send(m.addr, &m_send_buf[0], (int)m_send_buf.size(), ec); - -#ifdef TORRENT_DHT_VERBOSE_LOGGING - m_total_out_bytes += m_send_buf.size(); - - if (m.reply) - { - ++m_replies_sent[m.message_id]; - m_replies_bytes_sent[m.message_id] += int(m_send_buf.size()); - } - else - { - m_queries_out_bytes += m_send_buf.size(); - } - TORRENT_LOG(dht_tracker) << log_line.str() << " ]"; -#endif - - if (!m.piggy_backed_ping) return; - - msg pm; - pm.reply = false; - pm.piggy_backed_ping = false; - pm.message_id = messages::ping; - pm.transaction_id = m.ping_transaction_id; - pm.id = m.id; - pm.addr = m.addr; - - send_packet(pm); - } - catch (std::exception&) - { - // m_send may fail with "no route to host" - // but it shouldn't throw since an error code - // is passed in instead - TORRENT_ASSERT(false); - } - -}} - diff --git a/libtorrent/src/kademlia/find_data.cpp b/libtorrent/src/kademlia/find_data.cpp deleted file mode 100644 index c33842a50..000000000 --- a/libtorrent/src/kademlia/find_data.cpp +++ /dev/null @@ -1,146 +0,0 @@ -/* - -Copyright (c) 2006, Arvid Norberg & Daniel Wallin -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions -are met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in - the documentation and/or other materials provided with the distribution. - * Neither the name of the author nor the names of its - contributors may be used to endorse or promote products derived - from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -POSSIBILITY OF SUCH DAMAGE. - -*/ - -#include "libtorrent/pch.hpp" - -#include -#include -#include -#include -#include - -namespace libtorrent { namespace dht -{ - -find_data_observer::~find_data_observer() -{ - if (m_algorithm) m_algorithm->failed(m_self); -} - -void find_data_observer::reply(msg const& m) -{ - if (!m_algorithm) - { - TORRENT_ASSERT(false); - return; - } - - if (!m.peers.empty()) - { - m_algorithm->got_data(&m); - } - else - { - for (msg::nodes_t::const_iterator i = m.nodes.begin() - , end(m.nodes.end()); i != end; ++i) - { - m_algorithm->traverse(i->id, i->addr); - } - } - m_algorithm->finished(m_self); - m_algorithm = 0; -} - -void find_data_observer::timeout() -{ - if (!m_algorithm) return; - m_algorithm->failed(m_self); - m_algorithm = 0; -} - - -find_data::find_data( - node_id target - , int branch_factor - , int max_results - , routing_table& table - , rpc_manager& rpc - , done_callback const& callback -) - : traversal_algorithm( - target - , branch_factor - , max_results - , table - , rpc - , table.begin() - , table.end() - ) - , m_done_callback(callback) - , m_done(false) -{ - boost::intrusive_ptr self(this); - add_requests(); -} - -void find_data::invoke(node_id const& id, udp::endpoint addr) -{ - if (m_done) - { - m_invoke_count = -1; - return; - } - - TORRENT_ASSERT(m_rpc.allocation_size() >= sizeof(find_data_observer)); - observer_ptr o(new (m_rpc.allocator().malloc()) find_data_observer(this, id, m_target)); -#ifdef TORRENT_DEBUG - o->m_in_constructor = false; -#endif - m_rpc.invoke(messages::get_peers, addr, o); -} - -void find_data::got_data(msg const* m) -{ - m_done = true; - m_done_callback(m); -} - -void find_data::done() -{ - if (m_invoke_count != 0) return; - if (!m_done) m_done_callback(0); -} - -void find_data::initiate( - node_id target - , int branch_factor - , int max_results - , routing_table& table - , rpc_manager& rpc - , done_callback const& callback -) -{ - new find_data(target, branch_factor, max_results, table, rpc, callback); -} - -} } // namespace libtorrent::dht - diff --git a/libtorrent/src/kademlia/node.cpp b/libtorrent/src/kademlia/node.cpp deleted file mode 100644 index 223cc3ce0..000000000 --- a/libtorrent/src/kademlia/node.cpp +++ /dev/null @@ -1,515 +0,0 @@ -/* - -Copyright (c) 2006, Arvid Norberg -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions -are met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in - the documentation and/or other materials provided with the distribution. - * Neither the name of the author nor the names of its - contributors may be used to endorse or promote products derived - from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -POSSIBILITY OF SUCH DAMAGE. - -*/ - -#include "libtorrent/pch.hpp" - -#include -#include -#include -#include -#include - -#include "libtorrent/io.hpp" -#include "libtorrent/hasher.hpp" -#include "libtorrent/random_sample.hpp" -#include "libtorrent/kademlia/node_id.hpp" -#include "libtorrent/kademlia/rpc_manager.hpp" -#include "libtorrent/kademlia/routing_table.hpp" -#include "libtorrent/kademlia/node.hpp" - -#include "libtorrent/kademlia/refresh.hpp" -#include "libtorrent/kademlia/closest_nodes.hpp" -#include "libtorrent/kademlia/find_data.hpp" - -using boost::bind; - -namespace libtorrent { namespace dht -{ - -#ifdef _MSC_VER -namespace -{ - char rand() { return (char)std::rand(); } -} -#endif - -// TODO: configurable? -enum { announce_interval = 30 }; - -#ifdef TORRENT_DHT_VERBOSE_LOGGING -TORRENT_DEFINE_LOG(node) -#endif - -// remove peers that have timed out -void purge_peers(std::set& peers) -{ - for (std::set::iterator i = peers.begin() - , end(peers.end()); i != end;) - { - // the peer has timed out - if (i->added + minutes(int(announce_interval * 1.5f)) < time_now()) - { -#ifdef TORRENT_DHT_VERBOSE_LOGGING - TORRENT_LOG(node) << "peer timed out at: " << i->addr.address(); -#endif - peers.erase(i++); - } - else - ++i; - } -} - -void nop() {} - -node_impl::node_impl(boost::function const& f - , dht_settings const& settings - , boost::optional nid) - : m_settings(settings) - , m_id(nid ? *nid : generate_id()) - , m_table(m_id, 8, settings) - , m_rpc(bind(&node_impl::incoming_request, this, _1) - , m_id, m_table, f) - , m_last_tracker_tick(time_now()) -{ - m_secret[0] = std::rand(); - m_secret[1] = std::rand(); -} - -bool node_impl::verify_token(msg const& m) -{ - if (m.write_token.type() != entry::string_t) - { -#ifdef TORRENT_DHT_VERBOSE_LOGGING - TORRENT_LOG(node) << "token of incorrect type " << m.write_token.type(); -#endif - return false; - } - std::string const& token = m.write_token.string(); - if (token.length() != 4) - { -#ifdef TORRENT_DHT_VERBOSE_LOGGING - TORRENT_LOG(node) << "token of incorrect length: " << token.length(); -#endif - return false; - } - - hasher h1; - error_code ec; - std::string address = m.addr.address().to_string(ec); - if (ec) return false; - h1.update(&address[0], address.length()); - h1.update((char*)&m_secret[0], sizeof(m_secret[0])); - h1.update((char*)&m.info_hash[0], sha1_hash::size); - - sha1_hash h = h1.final(); - if (std::equal(token.begin(), token.end(), (signed char*)&h[0])) - return true; - - hasher h2; - h2.update(&address[0], address.length()); - h2.update((char*)&m_secret[1], sizeof(m_secret[1])); - h2.update((char*)&m.info_hash[0], sha1_hash::size); - h = h2.final(); - if (std::equal(token.begin(), token.end(), (signed char*)&h[0])) - return true; - return false; -} - -entry node_impl::generate_token(msg const& m) -{ - std::string token; - token.resize(4); - hasher h; - error_code ec; - std::string address = m.addr.address().to_string(ec); - TORRENT_ASSERT(!ec); - h.update(&address[0], address.length()); - h.update((char*)&m_secret[0], sizeof(m_secret[0])); - h.update((char*)&m.info_hash[0], sha1_hash::size); - - sha1_hash hash = h.final(); - std::copy(hash.begin(), hash.begin() + 4, (signed char*)&token[0]); - return entry(token); -} - -void node_impl::refresh(node_id const& id - , boost::function0 f) -{ - // use the 'bucket size' closest nodes - // to start the refresh with - std::vector start; - start.reserve(m_table.bucket_size()); - m_table.find_node(id, start, false); - refresh::initiate(id, m_settings.search_branching, 10, m_table.bucket_size() - , m_table, start.begin(), start.end(), m_rpc, f); -} - -void node_impl::bootstrap(std::vector const& nodes - , boost::function0 f) -{ -#ifdef TORRENT_DHT_VERBOSE_LOGGING - TORRENT_LOG(node) << "bootrapping: " << nodes.size(); - for (std::vector::const_iterator i = nodes.begin() - , end(nodes.end()); i != end; ++i) - TORRENT_LOG(node) << " " << *i; -#endif - std::vector start; - start.reserve(nodes.size()); - std::copy(nodes.begin(), nodes.end(), std::back_inserter(start)); - refresh::initiate(m_id, m_settings.search_branching, 10, m_table.bucket_size() - , m_table, start.begin(), start.end(), m_rpc, f); -} - -void node_impl::refresh() -{ - std::vector start; - start.reserve(m_table.size().get<0>()); - std::copy(m_table.begin(), m_table.end(), std::back_inserter(start)); - - refresh::initiate(m_id, m_settings.search_branching, 10, m_table.bucket_size() - , m_table, start.begin(), start.end(), m_rpc, bind(&nop)); -} - -int node_impl::bucket_size(int bucket) -{ - return m_table.bucket_size(bucket); -} - -void node_impl::new_write_key() -{ - m_secret[1] = m_secret[0]; - m_secret[0] = std::rand(); -} - -void node_impl::refresh_bucket(int bucket) try -{ - TORRENT_ASSERT(bucket >= 0 && bucket < 160); - - // generate a random node_id within the given bucket - node_id target = generate_id(); - int num_bits = 160 - bucket; - node_id mask(0); - for (int i = 0; i < num_bits; ++i) - { - int byte = i / 8; - mask[byte] |= 0x80 >> (i % 8); - } - - node_id root = m_id; - root &= mask; - target &= ~mask; - target |= root; - - // make sure this is in another subtree than m_id - // clear the (num_bits - 1) bit and then set it to the - // inverse of m_id's corresponding bit. - target[(num_bits - 1) / 8] &= ~(0x80 >> ((num_bits - 1) % 8)); - target[(num_bits - 1) / 8] |= - (~(m_id[(num_bits - 1) / 8])) & (0x80 >> ((num_bits - 1) % 8)); - - TORRENT_ASSERT(distance_exp(m_id, target) == bucket); - - std::vector start; - start.reserve(m_table.bucket_size()); - m_table.find_node(target, start, false, m_table.bucket_size()); - - refresh::initiate(target, m_settings.search_branching, 10, m_table.bucket_size() - , m_table, start.begin(), start.end(), m_rpc, bind(&nop)); - m_table.touch_bucket(bucket); -} -catch (std::exception&) {} - -void node_impl::unreachable(udp::endpoint const& ep) -{ - m_rpc.unreachable(ep); -} - -void node_impl::incoming(msg const& m) -{ - if (m_rpc.incoming(m)) - { - refresh(); - } -} - -namespace -{ - void announce_fun(std::vector const& v, rpc_manager& rpc - , int listen_port, sha1_hash const& ih - , boost::function const&, sha1_hash const&)> f) - { -#ifdef TORRENT_DHT_VERBOSE_LOGGING - TORRENT_LOG(node) << "announce response [ ih: " << ih - << " p: " << listen_port - << " nodes: " << v.size() << " ]" ; -#endif - bool nodes = false; - // only store on the first k nodes - for (std::vector::const_iterator i = v.begin() - , end(v.end()); i != end; ++i) - { -#ifdef TORRENT_DHT_VERBOSE_LOGGING - TORRENT_LOG(node) << " distance: " << (160 - distance_exp(ih, i->id)); -#endif - observer_ptr o(new (rpc.allocator().malloc()) get_peers_observer(ih, listen_port, rpc, f)); -#ifdef TORRENT_DEBUG - o->m_in_constructor = false; -#endif - rpc.invoke(messages::get_peers, i->addr, o); - nodes = true; - } - } -} - -void node_impl::add_router_node(udp::endpoint router) -{ -#ifdef TORRENT_DHT_VERBOSE_LOGGING - TORRENT_LOG(node) << "adding router node: " << router; -#endif - m_table.add_router_node(router); -} - -void node_impl::add_node(udp::endpoint node) -{ - // ping the node, and if we get a reply, it - // will be added to the routing table - observer_ptr o(new (m_rpc.allocator().malloc()) null_observer(m_rpc.allocator())); -#ifdef TORRENT_DEBUG - o->m_in_constructor = false; -#endif - m_rpc.invoke(messages::ping, node, o); -} - -void node_impl::announce(sha1_hash const& info_hash, int listen_port - , boost::function const&, sha1_hash const&)> f) -{ -#ifdef TORRENT_DHT_VERBOSE_LOGGING - TORRENT_LOG(node) << "announcing [ ih: " << info_hash << " p: " << listen_port << " ]" ; -#endif - // search for nodes with ids close to id, and then invoke the - // get_peers and then announce_peer rpc on them. - closest_nodes::initiate(info_hash, m_settings.search_branching - , m_table.bucket_size(), m_table, m_rpc - , boost::bind(&announce_fun, _1, boost::ref(m_rpc), listen_port - , info_hash, f)); -} - -time_duration node_impl::refresh_timeout() -{ - int refresh = -1; - ptime now = time_now(); - ptime next = now + minutes(15); - try - { - for (int i = 0; i < 160; ++i) - { - ptime r = m_table.next_refresh(i); - if (r <= next) - { - refresh = i; - next = r; - } - } - if (next < now) - { - TORRENT_ASSERT(refresh > -1); -#ifdef TORRENT_DHT_VERBOSE_LOGGING - TORRENT_LOG(node) << "refreshing bucket: " << refresh; -#endif - refresh_bucket(refresh); - } - } - catch (std::exception&) {} - - time_duration next_refresh = next - now; - time_duration min_next_refresh - = minutes(15) / (m_table.num_active_buckets()); - if (min_next_refresh > seconds(40)) - min_next_refresh = seconds(40); - - if (next_refresh < min_next_refresh) - next_refresh = min_next_refresh; - -#ifdef TORRENT_DHT_VERBOSE_LOGGING - TORRENT_LOG(node) << "next refresh: " << total_seconds(next_refresh) << " seconds"; -#endif - - return next_refresh; -} - -time_duration node_impl::connection_timeout() -{ - time_duration d = m_rpc.tick(); - try - { - ptime now(time_now()); - if (now - m_last_tracker_tick < minutes(10)) return d; - m_last_tracker_tick = now; - - // look through all peers and see if any have timed out - for (data_iterator i = begin_data(), end(end_data()); i != end;) - { - torrent_entry& t = i->second; - node_id const& key = i->first; - ++i; - purge_peers(t.peers); - - // if there are no more peers, remove the entry altogether - if (t.peers.empty()) - { - table_t::iterator i = m_map.find(key); - if (i != m_map.end()) m_map.erase(i); - } - } - } - catch (std::exception&) {} - - return d; -} - -void node_impl::on_announce(msg const& m, msg& reply) -{ - if (!verify_token(m)) - { - reply.message_id = messages::error; - reply.error_code = 203; - reply.error_msg = "Incorrect token in announce_peer"; - return; - } - - // the token was correct. That means this - // node is not spoofing its address. So, let - // the table get a chance to add it. - m_table.node_seen(m.id, m.addr); - - torrent_entry& v = m_map[m.info_hash]; - peer_entry e; - e.addr = tcp::endpoint(m.addr.address(), m.port); - e.added = time_now(); - std::set::iterator i = v.peers.find(e); - if (i != v.peers.end()) v.peers.erase(i++); - v.peers.insert(i, e); -} - -namespace -{ - tcp::endpoint get_endpoint(peer_entry const& p) - { - return p.addr; - } -} - -bool node_impl::on_find(msg const& m, std::vector& peers) const -{ - table_t::const_iterator i = m_map.find(m.info_hash); - if (i == m_map.end()) return false; - - torrent_entry const& v = i->second; - - int num = (std::min)((int)v.peers.size(), m_settings.max_peers_reply); - peers.clear(); - peers.reserve(num); - random_sample_n(boost::make_transform_iterator(v.peers.begin(), &get_endpoint) - , boost::make_transform_iterator(v.peers.end(), &get_endpoint) - , std::back_inserter(peers), num); - -#ifdef TORRENT_DHT_VERBOSE_LOGGING - for (std::vector::iterator i = peers.begin() - , end(peers.end()); i != end; ++i) - { - TORRENT_LOG(node) << " " << *i; - } -#endif - return true; -} - -void node_impl::incoming_request(msg const& m) -{ - msg reply; - reply.message_id = m.message_id; - reply.addr = m.addr; - reply.reply = true; - reply.transaction_id = m.transaction_id; - - switch (m.message_id) - { - case messages::ping: - break; - case messages::get_peers: - { - reply.info_hash = m.info_hash; - reply.write_token = generate_token(m); - - if (!on_find(m, reply.peers)) - { - // we don't have any peers for this info_hash, - // return nodes instead - m_table.find_node(m.info_hash, reply.nodes, false); -#ifdef TORRENT_DHT_VERBOSE_LOGGING - for (std::vector::iterator i = reply.nodes.begin() - , end(reply.nodes.end()); i != end; ++i) - { - TORRENT_LOG(node) << " " << i->id << " " << i->addr; - } -#endif - } - } - break; - case messages::find_node: - { - reply.info_hash = m.info_hash; - - m_table.find_node(m.info_hash, reply.nodes, false); -#ifdef TORRENT_DHT_VERBOSE_LOGGING - for (std::vector::iterator i = reply.nodes.begin() - , end(reply.nodes.end()); i != end; ++i) - { - TORRENT_LOG(node) << " " << i->id << " " << i->addr; - } -#endif - } - break; - case messages::announce_peer: - on_announce(m, reply); - break; - default: - TORRENT_ASSERT(false); - }; - - if (m_table.need_node(m.id)) - m_rpc.reply_with_ping(reply); - else - m_rpc.reply(reply); -} - - -} } // namespace libtorrent::dht diff --git a/libtorrent/src/kademlia/node_id.cpp b/libtorrent/src/kademlia/node_id.cpp deleted file mode 100644 index 758af2f8d..000000000 --- a/libtorrent/src/kademlia/node_id.cpp +++ /dev/null @@ -1,117 +0,0 @@ -/* - -Copyright (c) 2006, Arvid Norberg -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions -are met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in - the documentation and/or other materials provided with the distribution. - * Neither the name of the author nor the names of its - contributors may be used to endorse or promote products derived - from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -POSSIBILITY OF SUCH DAMAGE. - -*/ - -#include "libtorrent/pch.hpp" - -#include -#include -#include -#include - -#include "libtorrent/kademlia/node_id.hpp" -#include "libtorrent/hasher.hpp" -#include "libtorrent/assert.hpp" - -using boost::bind; - -namespace libtorrent { namespace dht -{ - -// returns the distance between the two nodes -// using the kademlia XOR-metric -node_id distance(node_id const& n1, node_id const& n2) -{ - node_id ret; - node_id::iterator k = ret.begin(); - for (node_id::const_iterator i = n1.begin(), j = n2.begin() - , end(n1.end()); i != end; ++i, ++j, ++k) - { - *k = *i ^ *j; - } - return ret; -} - -// returns true if: distance(n1, ref) < distance(n2, ref) -bool compare_ref(node_id const& n1, node_id const& n2, node_id const& ref) -{ - for (node_id::const_iterator i = n1.begin(), j = n2.begin() - , k = ref.begin(), end(n1.end()); i != end; ++i, ++j, ++k) - { - boost::uint8_t lhs = (*i ^ *k); - boost::uint8_t rhs = (*j ^ *k); - if (lhs < rhs) return true; - if (lhs > rhs) return false; - } - return false; -} - -// returns n in: 2^n <= distance(n1, n2) < 2^(n+1) -// useful for finding out which bucket a node belongs to -int distance_exp(node_id const& n1, node_id const& n2) -{ - int byte = node_id::size - 1; - for (node_id::const_iterator i = n1.begin(), j = n2.begin() - , end(n1.end()); i != end; ++i, ++j, --byte) - { - TORRENT_ASSERT(byte >= 0); - boost::uint8_t t = *i ^ *j; - if (t == 0) continue; - // we have found the first non-zero byte - // return the bit-number of the first bit - // that differs - int bit = byte * 8; - for (int b = 7; b >= 0; --b) - if (t >= (1 << b)) return bit + b; - return bit; - } - - return 0; -} - -struct static_ { static_() { std::srand(std::time(0)); } } static__; - -node_id generate_id() -{ - char random[20]; -#ifdef _MSC_VER - std::generate(random, random + 20, &rand); -#else - std::generate(random, random + 20, &std::rand); -#endif - - hasher h; - h.update(random, 20); - return h.final(); -} - -} } // namespace libtorrent::dht - diff --git a/libtorrent/src/kademlia/refresh.cpp b/libtorrent/src/kademlia/refresh.cpp deleted file mode 100644 index 39b4272e0..000000000 --- a/libtorrent/src/kademlia/refresh.cpp +++ /dev/null @@ -1,180 +0,0 @@ -/* - -Copyright (c) 2006, Arvid Norberg & Daniel Wallin -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions -are met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in - the documentation and/or other materials provided with the distribution. - * Neither the name of the author nor the names of its - contributors may be used to endorse or promote products derived - from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -POSSIBILITY OF SUCH DAMAGE. - -*/ - -#include "libtorrent/pch.hpp" - -#include -#include -#include -#include -#include - -#include - -#include - -using boost::bind; - -namespace libtorrent { namespace dht -{ - -#ifdef TORRENT_DHT_VERBOSE_LOGGING -TORRENT_DEFINE_LOG(refresh) -#endif - -refresh_observer::~refresh_observer() -{ - if (m_algorithm) m_algorithm->failed(m_self, true); -} - -void refresh_observer::reply(msg const& in) -{ - if (!m_algorithm) return; - - if (!in.nodes.empty()) - { - for (msg::nodes_t::const_iterator i = in.nodes.begin() - , end(in.nodes.end()); i != end; ++i) - { - m_algorithm->traverse(i->id, i->addr); - } - } - m_algorithm->finished(m_self); - m_algorithm = 0; -} - -void refresh_observer::timeout() -{ - if (!m_algorithm) return; - m_algorithm->failed(m_self); - m_algorithm = 0; -} - -ping_observer::~ping_observer() -{ - if (m_algorithm) m_algorithm->ping_timeout(m_self, true); -} - -void ping_observer::reply(msg const& m) -{ - if (!m_algorithm) return; - - m_algorithm->ping_reply(m_self); - m_algorithm = 0; -} - -void ping_observer::timeout() -{ - if (!m_algorithm) return; - m_algorithm->ping_timeout(m_self); - m_algorithm = 0; -} - -void refresh::invoke(node_id const& nid, udp::endpoint addr) -{ - TORRENT_ASSERT(m_rpc.allocation_size() >= sizeof(refresh_observer)); - observer_ptr o(new (m_rpc.allocator().malloc()) refresh_observer( - this, nid, m_target)); -#ifdef TORRENT_DEBUG - o->m_in_constructor = false; -#endif - - m_rpc.invoke(messages::find_node, addr, o); -} - -void refresh::done() -{ - m_leftover_nodes_iterator = (int)m_results.size() > m_max_results ? - m_results.begin() + m_max_results : m_results.end(); - - invoke_pings_or_finish(); -} - -void refresh::ping_reply(node_id nid) -{ - m_active_pings--; - invoke_pings_or_finish(); -} - -void refresh::ping_timeout(node_id nid, bool prevent_request) -{ - m_active_pings--; - invoke_pings_or_finish(prevent_request); -} - -void refresh::invoke_pings_or_finish(bool prevent_request) -{ - if (prevent_request) - { - --m_max_active_pings; - if (m_max_active_pings <= 0) - m_max_active_pings = 1; - } - else - { - while (m_active_pings < m_max_active_pings) - { - if (m_leftover_nodes_iterator == m_results.end()) break; - - result const& node = *m_leftover_nodes_iterator; - - // Skip initial nodes - if (node.flags & result::initial) - { - ++m_leftover_nodes_iterator; - continue; - } - - try - { - TORRENT_ASSERT(m_rpc.allocation_size() >= sizeof(ping_observer)); - observer_ptr o(new (m_rpc.allocator().malloc()) ping_observer( - this, node.id)); -#ifdef TORRENT_DEBUG - o->m_in_constructor = false; -#endif - m_rpc.invoke(messages::ping, node.addr, o); - ++m_active_pings; - ++m_leftover_nodes_iterator; - } - catch (std::exception& e) {} - } - } - - if (m_active_pings == 0) - { - m_done_callback(); - } -} - -} } // namespace libtorrent::dht - diff --git a/libtorrent/src/kademlia/routing_table.cpp b/libtorrent/src/kademlia/routing_table.cpp deleted file mode 100644 index 6c4d93f2b..000000000 --- a/libtorrent/src/kademlia/routing_table.cpp +++ /dev/null @@ -1,475 +0,0 @@ -/* - -Copyright (c) 2006, Arvid Norberg -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions -are met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in - the documentation and/or other materials provided with the distribution. - * Neither the name of the author nor the names of its - contributors may be used to endorse or promote products derived - from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -POSSIBILITY OF SUCH DAMAGE. - -*/ - -#include "libtorrent/pch.hpp" - -#include -#include -#include -#include -#include -#include -#include - -#include "libtorrent/kademlia/routing_table.hpp" -#include "libtorrent/kademlia/node_id.hpp" -#include "libtorrent/session_settings.hpp" - -using boost::bind; -using boost::uint8_t; - -namespace libtorrent { namespace dht -{ - -#ifdef TORRENT_DHT_VERBOSE_LOGGING -TORRENT_DEFINE_LOG(table) -#endif - -routing_table::routing_table(node_id const& id, int bucket_size - , dht_settings const& settings) - : m_bucket_size(bucket_size) - , m_settings(settings) - , m_id(id) - , m_lowest_active_bucket(160) -{ - // distribute the refresh times for the buckets in an - // attempt do even out the network load - for (int i = 0; i < 160; ++i) - m_bucket_activity[i] = time_now() - milliseconds(i*5625); - m_bucket_activity[0] = time_now() - minutes(15); -} - -boost::tuple routing_table::size() const -{ - int nodes = 0; - int replacements = 0; - for (table_t::const_iterator i = m_buckets.begin() - , end(m_buckets.end()); i != end; ++i) - { - nodes += i->first.size(); - replacements += i->second.size(); - } - return boost::make_tuple(nodes, replacements); -} - -size_type routing_table::num_global_nodes() const -{ - int first_full = m_lowest_active_bucket; - int num_nodes = 1; // we are one of the nodes - for (; first_full < 160 - && int(m_buckets[first_full].first.size()) < m_bucket_size; - ++first_full) - { - num_nodes += m_buckets[first_full].first.size(); - } - - return (2 << (160 - first_full)) * num_nodes; -} - -#ifdef TORRENT_DHT_VERBOSE_LOGGING - -void routing_table::print_state(std::ostream& os) const -{ - os << "kademlia routing table state\n" - << "bucket_size: " << m_bucket_size << "\n" - << "global node count: " << num_global_nodes() << "\n" - << "node_id: " << m_id << "\n\n"; - - os << "number of nodes per bucket:\n-- live "; - for (int i = 8; i < 160; ++i) - os << "-"; - os << "\n"; - - for (int k = 0; k < 8; ++k) - { - for (table_t::const_iterator i = m_buckets.begin(), end(m_buckets.end()); - i != end; ++i) - { - os << (int(i->first.size()) > (7 - k) ? "|" : " "); - } - os << "\n"; - } - for (table_t::const_iterator i = m_buckets.begin(), end(m_buckets.end()); - i != end; ++i) - { - os << "+"; - } - os << "\n"; - for (int k = 0; k < 8; ++k) - { - for (table_t::const_iterator i = m_buckets.begin(), end(m_buckets.end()); - i != end; ++i) - { - os << (int(i->second.size()) > k ? "|" : " "); - } - os << "\n"; - } - os << "-- cached "; - for (int i = 10; i < 160; ++i) - os << "-"; - os << "\n\n"; - - os << "nodes:\n"; - for (table_t::const_iterator i = m_buckets.begin(), end(m_buckets.end()); - i != end; ++i) - { - int bucket_index = int(i - m_buckets.begin()); - os << "=== BUCKET = " << bucket_index - << " = " << (bucket_index >= m_lowest_active_bucket?"active":"inactive") - << " = " << total_seconds(time_now() - m_bucket_activity[bucket_index]) - << " s ago ===== \n"; - for (bucket_t::const_iterator j = i->first.begin() - , end(i->first.end()); j != end; ++j) - { - os << "ip: " << j->addr << " fails: " << j->fail_count - << " id: " << j->id << "\n"; - } - } -} - -#endif - -void routing_table::touch_bucket(int bucket) -{ - m_bucket_activity[bucket] = time_now(); -} - -ptime routing_table::next_refresh(int bucket) -{ - TORRENT_ASSERT(bucket < 160); - TORRENT_ASSERT(bucket >= 0); - // lower than or equal to since a refresh of bucket 0 will - // effectively refresh the lowest active bucket as well - if (bucket < m_lowest_active_bucket && bucket > 0) - return time_now() + minutes(15); - return m_bucket_activity[bucket] + minutes(15); -} - -void routing_table::replacement_cache(bucket_t& nodes) const -{ - for (table_t::const_iterator i = m_buckets.begin() - , end(m_buckets.end()); i != end; ++i) - { - std::copy(i->second.begin(), i->second.end() - , std::back_inserter(nodes)); - } -} - -bool routing_table::need_node(node_id const& id) -{ - int bucket_index = distance_exp(m_id, id); - TORRENT_ASSERT(bucket_index < (int)m_buckets.size()); - TORRENT_ASSERT(bucket_index >= 0); - bucket_t& b = m_buckets[bucket_index].first; - bucket_t& rb = m_buckets[bucket_index].second; - - // if the replacement cache is full, we don't - // need another node. The table is fine the - // way it is. - if ((int)rb.size() >= m_bucket_size) return false; - - // if the node already exists, we don't need it - if (std::find_if(b.begin(), b.end(), bind(&node_entry::id, _1) == id) - != b.end()) return false; - - if (std::find_if(rb.begin(), rb.end(), bind(&node_entry::id, _1) == id) - != rb.end()) return false; - - return true; -} - -void routing_table::node_failed(node_id const& id) -{ - int bucket_index = distance_exp(m_id, id); - TORRENT_ASSERT(bucket_index < (int)m_buckets.size()); - TORRENT_ASSERT(bucket_index >= 0); - bucket_t& b = m_buckets[bucket_index].first; - bucket_t& rb = m_buckets[bucket_index].second; - - bucket_t::iterator i = std::find_if(b.begin(), b.end() - , bind(&node_entry::id, _1) == id); - - if (i == b.end()) return; - - // if messages to ourself fails, ignore it - if (bucket_index == 0) return; - - if (rb.empty()) - { - ++i->fail_count; - -#ifdef TORRENT_DHT_VERBOSE_LOGGING - TORRENT_LOG(table) << " NODE FAILED" - " id: " << id << - " ip: " << i->addr << - " fails: " << i->fail_count << - " up-time: " << total_seconds(time_now() - i->first_seen); -#endif - - if (i->fail_count >= m_settings.max_fail_count) - { - b.erase(i); - TORRENT_ASSERT(m_lowest_active_bucket <= bucket_index); - while (m_lowest_active_bucket < 160 - && m_buckets[m_lowest_active_bucket].first.empty()) - { - ++m_lowest_active_bucket; - } - } - return; - } - - b.erase(i); - b.push_back(rb.back()); - rb.erase(rb.end() - 1); -} - -void routing_table::add_router_node(udp::endpoint router) -{ - m_router_nodes.insert(router); -} - -// this function is called every time the node sees -// a sign of a node being alive. This node will either -// be inserted in the k-buckets or be moved to the top -// of its bucket. -// the return value indicates if the table needs a refresh. -// if true, the node should refresh the table (i.e. do a find_node -// on its own id) -bool routing_table::node_seen(node_id const& id, udp::endpoint addr) -{ - if (m_router_nodes.find(addr) != m_router_nodes.end()) return false; - int bucket_index = distance_exp(m_id, id); - TORRENT_ASSERT(bucket_index < (int)m_buckets.size()); - TORRENT_ASSERT(bucket_index >= 0); - bucket_t& b = m_buckets[bucket_index].first; - - bucket_t::iterator i = std::find_if(b.begin(), b.end() - , bind(&node_entry::id, _1) == id); - - bool ret = need_bootstrap(); - - //m_bucket_activity[bucket_index] = time_now(); - - if (i != b.end()) - { - // TODO: what do we do if we see a node with - // the same id as a node at a different address? -// TORRENT_ASSERT(i->addr == addr); - - // we already have the node in our bucket - // just move it to the back since it was - // the last node we had any contact with - // in this bucket - b.erase(i); - b.push_back(node_entry(id, addr)); -// TORRENT_LOG(table) << "replacing node: " << id << " " << addr; - return ret; - } - - // if the node was not present in our list - // we will only insert it if there is room - // for it, or if some of our nodes have gone - // offline - if ((int)b.size() < m_bucket_size) - { - if (b.empty()) b.reserve(m_bucket_size); - b.push_back(node_entry(id, addr)); - // if bucket index is 0, the node is ourselves - // don't updated m_lowest_active_bucket - if (bucket_index < m_lowest_active_bucket - && bucket_index > 0) - m_lowest_active_bucket = bucket_index; -// TORRENT_LOG(table) << "inserting node: " << id << " " << addr; - return ret; - } - - // if there is no room, we look for nodes marked as stale - // in the k-bucket. If we find one, we can replace it. - // A node is considered stale if it has failed at least one - // time. Here we choose the node that has failed most times. - // If we don't find one, place this node in the replacement- - // cache and replace any nodes that will fail in the future - // with nodes from that cache. - - i = std::max_element(b.begin(), b.end() - , bind(&node_entry::fail_count, _1) - < bind(&node_entry::fail_count, _2)); - - if (i != b.end() && i->fail_count > 0) - { - // i points to a node that has been marked - // as stale. Replace it with this new one - b.erase(i); - b.push_back(node_entry(id, addr)); -// TORRENT_LOG(table) << "replacing stale node: " << id << " " << addr; - return ret; - } - - // if we don't have any identified stale nodes in - // the bucket, and the bucket is full, we have to - // cache this node and wait until some node fails - // and then replace it. - - bucket_t& rb = m_buckets[bucket_index].second; - - i = std::find_if(rb.begin(), rb.end() - , bind(&node_entry::id, _1) == id); - - // if the node is already in the replacement bucket - // just return. - if (i != rb.end()) return ret; - - if ((int)rb.size() > m_bucket_size) rb.erase(rb.begin()); - if (rb.empty()) rb.reserve(m_bucket_size); - rb.push_back(node_entry(id, addr)); -// TORRENT_LOG(table) << "inserting node in replacement cache: " << id << " " << addr; - return ret; -} - -bool routing_table::need_bootstrap() const -{ - for (const_iterator i = begin(); i != end(); ++i) - { - if (i->fail_count == 0) return false; - } - return true; -} - -template -DstIter copy_if_n(SrcIter begin, SrcIter end, DstIter target, size_t n, Pred p) -{ - for (; n > 0 && begin != end; ++begin) - { - if (!p(*begin)) continue; - *target = *begin; - --n; - ++target; - } - return target; -} - -// fills the vector with the k nodes from our buckets that -// are nearest to the given id. -void routing_table::find_node(node_id const& target - , std::vector& l, bool include_self, int count) -{ - l.clear(); - if (count == 0) count = m_bucket_size; - l.reserve(count); - - int bucket_index = distance_exp(m_id, target); - bucket_t& b = m_buckets[bucket_index].first; - - // copy all nodes that hasn't failed into the target - // vector. - copy_if_n(b.begin(), b.end(), std::back_inserter(l) - , (std::min)(size_t(count), b.size()), bind(&node_entry::fail_count, _1) == 0); - TORRENT_ASSERT((int)l.size() <= count); - - if ((int)l.size() == count) - { - TORRENT_ASSERT(std::count_if(l.begin(), l.end() - , boost::bind(&node_entry::fail_count, _1) != 0) == 0); - return; - } - - // if we didn't have enough nodes in that bucket - // we have to reply with nodes from buckets closer - // to us. i.e. all the buckets in the range - // [0, bucket_index) if we are to include ourself - // or [1, bucket_index) if not. - bucket_t tmpb; - for (int i = include_self?0:1; i < bucket_index; ++i) - { - bucket_t& b = m_buckets[i].first; - std::remove_copy_if(b.begin(), b.end(), std::back_inserter(tmpb) - , bind(&node_entry::fail_count, _1)); - } - - if (count - l.size() < tmpb.size()) - { - std::random_shuffle(tmpb.begin(), tmpb.end()); - size_t to_copy = count - l.size(); - std::copy(tmpb.begin(), tmpb.begin() + to_copy, std::back_inserter(l)); - } - else - { - std::copy(tmpb.begin(), tmpb.end(), std::back_inserter(l)); - } - - TORRENT_ASSERT((int)l.size() <= count); - - // return if we have enough nodes or if the bucket index - // is the biggest index available (there are no more buckets) - // to look in. - if ((int)l.size() == count) - { - TORRENT_ASSERT(std::count_if(l.begin(), l.end() - , boost::bind(&node_entry::fail_count, _1) != 0) == 0); - return; - } - - for (size_t i = bucket_index + 1; i < m_buckets.size(); ++i) - { - bucket_t& b = m_buckets[i].first; - - size_t to_copy = (std::min)(count - l.size(), b.size()); - copy_if_n(b.begin(), b.end(), std::back_inserter(l) - , to_copy, bind(&node_entry::fail_count, _1) == 0); - TORRENT_ASSERT((int)l.size() <= count); - if ((int)l.size() == count) - { - TORRENT_ASSERT(std::count_if(l.begin(), l.end() - , boost::bind(&node_entry::fail_count, _1) != 0) == 0); - return; - } - } - TORRENT_ASSERT((int)l.size() <= count); - - TORRENT_ASSERT(std::count_if(l.begin(), l.end() - , boost::bind(&node_entry::fail_count, _1) != 0) == 0); -} - -routing_table::iterator routing_table::begin() const -{ - // +1 to avoid ourself - return iterator(m_buckets.begin() + 1, m_buckets.end()); -} - -routing_table::iterator routing_table::end() const -{ - return iterator(m_buckets.end(), m_buckets.end()); -} - -} } // namespace libtorrent::dht - diff --git a/libtorrent/src/kademlia/rpc_manager.cpp b/libtorrent/src/kademlia/rpc_manager.cpp deleted file mode 100644 index 1e846831c..000000000 --- a/libtorrent/src/kademlia/rpc_manager.cpp +++ /dev/null @@ -1,498 +0,0 @@ -/* - -Copyright (c) 2006, Arvid Norberg -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions -are met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in - the documentation and/or other materials provided with the distribution. - * Neither the name of the author nor the names of its - contributors may be used to endorse or promote products derived - from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -POSSIBILITY OF SUCH DAMAGE. - -*/ - -#include "libtorrent/pch.hpp" -#include "libtorrent/socket.hpp" - -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -using boost::shared_ptr; -using boost::bind; - -namespace libtorrent { namespace dht -{ - -namespace io = libtorrent::detail; -namespace mpl = boost::mpl; - -#ifdef TORRENT_DHT_VERBOSE_LOGGING -TORRENT_DEFINE_LOG(rpc) -#endif - -void intrusive_ptr_add_ref(observer const* o) -{ - TORRENT_ASSERT(o->m_refs >= 0); - TORRENT_ASSERT(o != 0); - ++o->m_refs; -} - -void intrusive_ptr_release(observer const* o) -{ - TORRENT_ASSERT(o->m_refs > 0); - TORRENT_ASSERT(o != 0); - if (--o->m_refs == 0) - { - boost::pool<>& p = o->pool_allocator; - (const_cast(o))->~observer(); - p.free(const_cast(o)); - } -} - -node_id generate_id(); - -typedef mpl::vector< - closest_nodes_observer - , find_data_observer - , announce_observer - , get_peers_observer - , refresh_observer - , ping_observer - , null_observer - > observer_types; - -typedef mpl::max_element< - mpl::transform_view > - >::type max_observer_type_iter; - -rpc_manager::rpc_manager(fun const& f, node_id const& our_id - , routing_table& table, send_fun const& sf) - : m_pool_allocator(sizeof(mpl::deref::type)) - , m_next_transaction_id(std::rand() % max_transactions) - , m_oldest_transaction_id(m_next_transaction_id) - , m_incoming(f) - , m_send(sf) - , m_our_id(our_id) - , m_table(table) - , m_timer(time_now()) - , m_random_number(generate_id()) - , m_destructing(false) -{ - std::srand(time(0)); -} - -rpc_manager::~rpc_manager() -{ - TORRENT_ASSERT(!m_destructing); - m_destructing = true; -#ifdef TORRENT_DHT_VERBOSE_LOGGING - TORRENT_LOG(rpc) << "Destructing"; -#endif - std::for_each(m_aborted_transactions.begin(), m_aborted_transactions.end() - , bind(&observer::abort, _1)); - - for (transactions_t::iterator i = m_transactions.begin() - , end(m_transactions.end()); i != end; ++i) - { - if (*i) (*i)->abort(); - } -} - -#ifdef TORRENT_DEBUG -size_t rpc_manager::allocation_size() const -{ - size_t s = sizeof(mpl::deref::type); - return s; -} - -void rpc_manager::check_invariant() const -{ - TORRENT_ASSERT(m_oldest_transaction_id >= 0); - TORRENT_ASSERT(m_oldest_transaction_id < max_transactions); - TORRENT_ASSERT(m_next_transaction_id >= 0); - TORRENT_ASSERT(m_next_transaction_id < max_transactions); - TORRENT_ASSERT(!m_transactions[m_next_transaction_id]); - - for (int i = (m_next_transaction_id + 1) % max_transactions; - i != m_oldest_transaction_id; i = (i + 1) % max_transactions) - { - TORRENT_ASSERT(!m_transactions[i]); - } -} -#endif - -void rpc_manager::unreachable(udp::endpoint const& ep) -{ -#ifdef TORRENT_DHT_VERBOSE_LOGGING - TORRENT_LOG(rpc) << time_now_string() << " PORT_UNREACHABLE [ ip: " << ep << " ]"; -#endif - int num_active = m_oldest_transaction_id < m_next_transaction_id - ? m_next_transaction_id - m_oldest_transaction_id - : max_transactions - m_oldest_transaction_id + m_next_transaction_id; - TORRENT_ASSERT((m_oldest_transaction_id + num_active) % max_transactions - == m_next_transaction_id); - int tid = m_oldest_transaction_id; - for (int i = 0; i < num_active; ++i, ++tid) - { - if (tid >= max_transactions) tid = 0; - observer_ptr const& o = m_transactions[tid]; - if (!o) continue; - if (o->target_addr != ep) continue; - observer_ptr ptr = m_transactions[tid]; - m_transactions[tid] = 0; - if (tid == m_oldest_transaction_id) - { - ++m_oldest_transaction_id; - if (m_oldest_transaction_id >= max_transactions) - m_oldest_transaction_id = 0; - } -#ifdef TORRENT_DHT_VERBOSE_LOGGING - TORRENT_LOG(rpc) << " found transaction [ tid: " << tid << " ]"; -#endif - ptr->timeout(); - return; - } -} - -bool rpc_manager::incoming(msg const& m) -{ - INVARIANT_CHECK; - - if (m_destructing) return false; - - if (m.reply) - { - // if we don't have the transaction id in our - // request list, ignore the packet - - if (m.transaction_id.size() < 2) - { -#ifdef TORRENT_DHT_VERBOSE_LOGGING - TORRENT_LOG(rpc) << "Reply with invalid transaction id size: " - << m.transaction_id.size() << " from " << m.addr; -#endif - msg reply; - reply.reply = true; - reply.message_id = messages::error; - reply.error_code = 203; // Protocol error - reply.error_msg = "reply with invalid transaction id, size " - + boost::lexical_cast(m.transaction_id.size()); - reply.addr = m.addr; - reply.transaction_id = ""; - m_send(reply); - return false; - } - - std::string::const_iterator i = m.transaction_id.begin(); - int tid = io::read_uint16(i); - - if (tid >= (int)m_transactions.size() - || tid < 0) - { -#ifdef TORRENT_DHT_VERBOSE_LOGGING - TORRENT_LOG(rpc) << "Reply with invalid transaction id: " - << tid << " from " << m.addr; -#endif - msg reply; - reply.reply = true; - reply.message_id = messages::error; - reply.error_code = 203; // Protocol error - reply.error_msg = "reply with invalid transaction id"; - reply.addr = m.addr; - reply.transaction_id = ""; - m_send(reply); - return false; - } - - observer_ptr o = m_transactions[tid]; - - if (!o) - { -#ifdef TORRENT_DHT_VERBOSE_LOGGING - TORRENT_LOG(rpc) << "Reply with unknown transaction id: " - << tid << " from " << m.addr << " (possibly timed out)"; -#endif - return false; - } - - if (m.addr.address() != o->target_addr.address()) - { -#ifdef TORRENT_DHT_VERBOSE_LOGGING - TORRENT_LOG(rpc) << "Reply with incorrect address and valid transaction id: " - << tid << " from " << m.addr << " expected: " << o->target_addr; -#endif - return false; - } - -#ifdef TORRENT_DHT_VERBOSE_LOGGING - std::ofstream reply_stats("round_trip_ms.log", std::ios::app); - reply_stats << m.addr << "\t" << total_milliseconds(time_now() - o->sent) - << std::endl; -#endif -#ifdef TORRENT_DHT_VERBOSE_LOGGING - TORRENT_LOG(rpc) << "Reply with transaction id: " - << tid << " from " << m.addr; -#endif - o->reply(m); - m_transactions[tid] = 0; - - if (m.piggy_backed_ping) - { - // there is a ping request piggy - // backed in this reply - msg ph; - ph.message_id = messages::ping; - ph.transaction_id = m.ping_transaction_id; - ph.addr = m.addr; - ph.reply = true; - - reply(ph); - } - return m_table.node_seen(m.id, m.addr); - } - else - { - TORRENT_ASSERT(m.message_id != messages::error); - // this is an incoming request - m_incoming(m); - } - return false; -} - -time_duration rpc_manager::tick() -{ - INVARIANT_CHECK; - - const int timeout_ms = 10 * 1000; - - // look for observers that has timed out - - if (m_next_transaction_id == m_oldest_transaction_id) return milliseconds(timeout_ms); - - std::vector timeouts; - - time_duration ret = milliseconds(timeout_ms); - - for (;m_next_transaction_id != m_oldest_transaction_id; - m_oldest_transaction_id = (m_oldest_transaction_id + 1) % max_transactions) - { - TORRENT_ASSERT(m_oldest_transaction_id >= 0); - TORRENT_ASSERT(m_oldest_transaction_id < max_transactions); - - observer_ptr o = m_transactions[m_oldest_transaction_id]; - if (!o) continue; - - time_duration diff = o->sent + milliseconds(timeout_ms) - time_now(); - if (diff > seconds(0)) - { - if (diff < seconds(1)) - { - ret = seconds(1); - break; - } - else - { - ret = diff; - break; - } - } - - try - { - m_transactions[m_oldest_transaction_id] = 0; -#ifdef TORRENT_DHT_VERBOSE_LOGGING - TORRENT_LOG(rpc) << "Timing out transaction id: " - << m_oldest_transaction_id << " from " << o->target_addr; -#endif - timeouts.push_back(o); - } catch (std::exception) {} - } - - std::for_each(timeouts.begin(), timeouts.end(), bind(&observer::timeout, _1)); - timeouts.clear(); - - // clear the aborted transactions, will likely - // generate new requests. We need to swap, since the - // destrutors may add more observers to the m_aborted_transactions - std::vector().swap(m_aborted_transactions); - return ret; -} - -unsigned int rpc_manager::new_transaction_id(observer_ptr o) -{ - INVARIANT_CHECK; - - unsigned int tid = m_next_transaction_id; - m_next_transaction_id = (m_next_transaction_id + 1) % max_transactions; - if (m_transactions[m_next_transaction_id]) - { - // moving the observer into the set of aborted transactions - // it will prevent it from spawning new requests right now, - // since that would break the invariant - observer_ptr o = m_transactions[m_next_transaction_id]; - m_aborted_transactions.push_back(o); -#ifdef TORRENT_DHT_VERBOSE_LOGGING - TORRENT_LOG(rpc) << "[new_transaction_id] Aborting message with transaction id: " - << m_next_transaction_id << " sent to " << o->target_addr - << " " << total_seconds(time_now() - o->sent) << " seconds ago"; -#endif - m_transactions[m_next_transaction_id] = 0; - TORRENT_ASSERT(m_oldest_transaction_id == m_next_transaction_id); - } - TORRENT_ASSERT(!m_transactions[tid]); - m_transactions[tid] = o; - if (m_oldest_transaction_id == m_next_transaction_id) - { - m_oldest_transaction_id = (m_oldest_transaction_id + 1) % max_transactions; -#ifdef TORRENT_DHT_VERBOSE_LOGGING - TORRENT_LOG(rpc) << "WARNING: transaction limit reached! Too many concurrent" - " messages! limit: " << (int)max_transactions; -#endif - update_oldest_transaction_id(); - } - - return tid; -} - -void rpc_manager::update_oldest_transaction_id() -{ - INVARIANT_CHECK; - - TORRENT_ASSERT(m_oldest_transaction_id != m_next_transaction_id); - while (!m_transactions[m_oldest_transaction_id]) - { - m_oldest_transaction_id = (m_oldest_transaction_id + 1) - % max_transactions; - if (m_oldest_transaction_id == m_next_transaction_id) - break; - } -} - -void rpc_manager::invoke(int message_id, udp::endpoint target_addr - , observer_ptr o) -{ - INVARIANT_CHECK; - - if (m_destructing) - { - o->abort(); - return; - } - - msg m; - m.message_id = message_id; - m.reply = false; - m.id = m_our_id; - m.addr = target_addr; - TORRENT_ASSERT(!m_transactions[m_next_transaction_id]); -#ifdef TORRENT_DEBUG - int potential_new_id = m_next_transaction_id; -#endif - try - { - m.transaction_id.clear(); - std::back_insert_iterator out(m.transaction_id); - io::write_uint16(m_next_transaction_id, out); - - o->send(m); - - o->sent = time_now(); - o->target_addr = target_addr; - - #ifdef TORRENT_DHT_VERBOSE_LOGGING - TORRENT_LOG(rpc) << "Invoking " << messages::ids[message_id] - << " -> " << target_addr; - #endif - m_send(m); - new_transaction_id(o); - } - catch (std::exception& e) - { - // m_send may fail with "no route to host" - TORRENT_ASSERT(potential_new_id == m_next_transaction_id); - o->abort(); - } -} - -void rpc_manager::reply(msg& m) -{ - INVARIANT_CHECK; - - if (m_destructing) return; - - TORRENT_ASSERT(m.reply); - m.piggy_backed_ping = false; - m.id = m_our_id; - - m_send(m); -} - -void rpc_manager::reply_with_ping(msg& m) -{ - INVARIANT_CHECK; - - if (m_destructing) return; - TORRENT_ASSERT(m.reply); - - m.piggy_backed_ping = true; - m.id = m_our_id; - - m.ping_transaction_id.clear(); - std::back_insert_iterator out(m.ping_transaction_id); - io::write_uint16(m_next_transaction_id, out); - - TORRENT_ASSERT(allocation_size() >= sizeof(null_observer)); - observer_ptr o(new (allocator().malloc()) null_observer(allocator())); -#ifdef TORRENT_DEBUG - o->m_in_constructor = false; -#endif - TORRENT_ASSERT(!m_transactions[m_next_transaction_id]); - o->sent = time_now(); - o->target_addr = m.addr; - - m_send(m); - new_transaction_id(o); -} - - - -} } // namespace libtorrent::dht - diff --git a/libtorrent/src/kademlia/traversal_algorithm.cpp b/libtorrent/src/kademlia/traversal_algorithm.cpp deleted file mode 100644 index 138d42905..000000000 --- a/libtorrent/src/kademlia/traversal_algorithm.cpp +++ /dev/null @@ -1,193 +0,0 @@ -/* - -Copyright (c) 2006, Arvid Norberg & Daniel Wallin -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions -are met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in - the documentation and/or other materials provided with the distribution. - * Neither the name of the author nor the names of its - contributors may be used to endorse or promote products derived - from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -POSSIBILITY OF SUCH DAMAGE. - -*/ - -#include "libtorrent/pch.hpp" - -#include -#include -#include - -#include - -using boost::bind; - -namespace libtorrent { namespace dht -{ -#ifdef TORRENT_DHT_VERBOSE_LOGGING -TORRENT_DEFINE_LOG(traversal) -#endif - -void traversal_algorithm::add_entry(node_id const& id, udp::endpoint addr, unsigned char flags) -{ - if (m_failed.find(addr) != m_failed.end()) return; - - result entry(id, addr, flags); - if (entry.id.is_all_zeros()) - { - entry.id = generate_id(); - entry.flags |= result::no_id; - } - - std::vector::iterator i = std::lower_bound( - m_results.begin() - , m_results.end() - , entry - , bind( - compare_ref - , bind(&result::id, _1) - , bind(&result::id, _2) - , m_target - ) - ); - - if (i == m_results.end() || i->id != id) - { - TORRENT_ASSERT(std::find_if(m_results.begin(), m_results.end() - , bind(&result::id, _1) == id) == m_results.end()); -#ifdef TORRENT_DHT_VERBOSE_LOGGING - TORRENT_LOG(traversal) << "adding result: " << id << " " << addr; -#endif - m_results.insert(i, entry); - } -} - -boost::pool<>& traversal_algorithm::allocator() const -{ - return m_rpc.allocator(); -} - -void traversal_algorithm::traverse(node_id const& id, udp::endpoint addr) -{ -#ifdef TORRENT_DHT_VERBOSE_LOGGING - if (id.is_all_zeros()) - TORRENT_LOG(traversal) << time_now_string() << " WARNING: node returned a list which included a node with id 0"; -#endif - add_entry(id, addr, 0); -} - -void traversal_algorithm::finished(node_id const& id) -{ - --m_invoke_count; - add_requests(); - if (m_invoke_count == 0) done(); -} - -// prevent request means that the total number of requests has -// overflown. This query failed because it was the oldest one. -// So, if this is true, don't make another request -void traversal_algorithm::failed(node_id const& id, bool prevent_request) -{ - m_invoke_count--; - - TORRENT_ASSERT(!id.is_all_zeros()); - std::vector::iterator i = std::find_if( - m_results.begin() - , m_results.end() - , bind( - std::equal_to() - , bind(&result::id, _1) - , id - ) - ); - - TORRENT_ASSERT(i != m_results.end()); - - if (i != m_results.end()) - { - TORRENT_ASSERT(i->flags & result::queried); - m_failed.insert(i->addr); -#ifdef TORRENT_DHT_VERBOSE_LOGGING - TORRENT_LOG(traversal) << "failed: " << i->id << " " << i->addr; -#endif - // don't tell the routing table about - // node ids that we just generated ourself - if ((i->flags & result::no_id) == 0) - m_table.node_failed(id); - m_results.erase(i); - } - if (prevent_request) - { - --m_branch_factor; - if (m_branch_factor <= 0) m_branch_factor = 1; - } - add_requests(); - if (m_invoke_count == 0) done(); -} - -namespace -{ - bool bitwise_nand(unsigned char lhs, unsigned char rhs) - { - return (lhs & rhs) == 0; - } -} - -void traversal_algorithm::add_requests() -{ - while (m_invoke_count < m_branch_factor) - { - // Find the first node that hasn't already been queried. - // TODO: Better heuristic - std::vector::iterator i = std::find_if( - m_results.begin() - , last_iterator() - , bind( - &bitwise_nand - , bind(&result::flags, _1) - , (unsigned char)result::queried - ) - ); -#ifdef TORRENT_DHT_VERBOSE_LOGGING - TORRENT_LOG(traversal) << "nodes left (" << this << "): " << (last_iterator() - i); -#endif - - if (i == last_iterator()) break; - - try - { - invoke(i->id, i->addr); - ++m_invoke_count; - i->flags |= result::queried; - } - catch (std::exception& e) {} - } -} - -std::vector::iterator traversal_algorithm::last_iterator() -{ - return (int)m_results.size() >= m_max_results ? - m_results.begin() + m_max_results - : m_results.end(); -} - -} } // namespace libtorrent::dht - diff --git a/libtorrent/src/lazy_bdecode.cpp b/libtorrent/src/lazy_bdecode.cpp deleted file mode 100644 index 983b48a35..000000000 --- a/libtorrent/src/lazy_bdecode.cpp +++ /dev/null @@ -1,436 +0,0 @@ -/* - -Copyright (c) 2008, Arvid Norberg -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions -are met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in - the documentation and/or other materials provided with the distribution. - * Neither the name of the author nor the names of its - contributors may be used to endorse or promote products derived - from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -POSSIBILITY OF SUCH DAMAGE. - -*/ - -#include "libtorrent/lazy_entry.hpp" -#include "libtorrent/escape_string.hpp" -#include -#include -#include - -namespace -{ - const float lazy_entry_grow_factor = 1.5f; - const int lazy_entry_dict_init = 5; - const int lazy_entry_list_init = 5; -} - -namespace libtorrent -{ - int fail_bdecode(lazy_entry& ret) - { - ret = lazy_entry(); - return -1; - } - - // fills in 'val' with what the string between start and the - // first occurance of the delimiter is interpreted as an int. - // return the pointer to the delimiter, or 0 if there is a - // parse error. val should be initialized to zero - char const* parse_int(char const* start, char const* end, char delimiter, boost::int64_t& val) - { - while (start < end && *start != delimiter) - { - if (!is_digit(*start)) { return 0; } - val *= 10; - val += *start - '0'; - ++start; - } - return start; - } - - char const* find_char(char const* start, char const* end, char delimiter) - { - while (start < end && *start != delimiter) ++start; - return start; - } - - // return 0 = success - int lazy_bdecode(char const* start, char const* end, lazy_entry& ret, int depth_limit) - { - ret.clear(); - if (start == end) return 0; - - std::vector stack; - - stack.push_back(&ret); - while (start < end) - { - if (stack.empty()) break; // done! - - lazy_entry* top = stack.back(); - - if (int(stack.size()) > depth_limit) return fail_bdecode(ret); - if (start >= end) return fail_bdecode(ret); - char t = *start; - ++start; - if (start >= end && t != 'e') return fail_bdecode(ret); - - switch (top->type()) - { - case lazy_entry::dict_t: - { - if (t == 'e') - { - top->set_end(start); - stack.pop_back(); - continue; - } - boost::int64_t len = t - '0'; - start = parse_int(start, end, ':', len); - if (start == 0 || start + len + 3 > end || *start != ':') return fail_bdecode(ret); - ++start; - if (start == end) fail_bdecode(ret); - lazy_entry* ent = top->dict_append(start); - start += len; - if (start >= end) fail_bdecode(ret); - stack.push_back(ent); - t = *start; - ++start; - break; - } - case lazy_entry::list_t: - { - if (t == 'e') - { - top->set_end(start); - stack.pop_back(); - continue; - } - lazy_entry* ent = top->list_append(); - stack.push_back(ent); - break; - } - default: break; - } - - top = stack.back(); - switch (t) - { - case 'd': - top->construct_dict(start - 1); - continue; - case 'l': - top->construct_list(start - 1); - continue; - case 'i': - { - char const* int_start = start; - start = find_char(start, end, 'e'); - top->construct_int(int_start, start - int_start); - if (start == end) return fail_bdecode(ret); - TORRENT_ASSERT(*start == 'e'); - ++start; - stack.pop_back(); - continue; - } - default: - { - if (!is_digit(t)) return fail_bdecode(ret); - - boost::int64_t len = t - '0'; - start = parse_int(start, end, ':', len); - if (start == 0 || start + len + 1 > end || *start != ':') return fail_bdecode(ret); - ++start; - top->construct_string(start, int(len)); - stack.pop_back(); - start += len; - continue; - } - } - return 0; - } - return 0; - } - - size_type lazy_entry::int_value() const - { - TORRENT_ASSERT(m_type == int_t); - boost::int64_t val = 0; - bool negative = false; - if (*m_data.start == '-') negative = true; - parse_int(negative?m_data.start+1:m_data.start, m_data.start + m_size, 'e', val); - if (negative) val = -val; - return val; - } - - lazy_entry* lazy_entry::dict_append(char const* name) - { - TORRENT_ASSERT(m_type == dict_t); - TORRENT_ASSERT(m_size <= m_capacity); - if (m_capacity == 0) - { - int capacity = lazy_entry_dict_init; - m_data.dict = new (std::nothrow) std::pair[capacity]; - if (m_data.dict == 0) return 0; - m_capacity = capacity; - } - else if (m_size == m_capacity) - { - int capacity = m_capacity * lazy_entry_grow_factor; - std::pair* tmp = new (std::nothrow) std::pair[capacity]; - if (tmp == 0) return 0; - std::memcpy(tmp, m_data.dict, sizeof(std::pair) * m_size); - for (int i = 0; i < m_size; ++i) m_data.dict[i].second.release(); - delete[] m_data.dict; - m_data.dict = tmp; - m_capacity = capacity; - } - - TORRENT_ASSERT(m_size < m_capacity); - std::pair& ret = m_data.dict[m_size++]; - ret.first = name; - return &ret.second; - } - - namespace - { - // the number of decimal digits needed - // to represent the given value - int num_digits(int val) - { - int ret = 1; - while (val >= 10) - { - ++ret; - val /= 10; - } - return ret; - } - } - - void lazy_entry::construct_string(char const* start, int length) - { - TORRENT_ASSERT(m_type == none_t); - m_type = string_t; - m_data.start = start; - m_size = length; - m_begin = start - 1 - num_digits(length); - m_end = start + length; - } - - namespace - { - // str1 is null-terminated - // str2 is not, str2 is len2 chars - bool string_equal(char const* str1, char const* str2, int len2) - { - while (len2 > 0) - { - if (*str1 != *str2) return false; - if (*str1 == 0) return false; - ++str1; - ++str2; - --len2; - } - return *str1 == 0; - } - } - - std::string lazy_entry::dict_find_string_value(char const* name) const - { - lazy_entry const* e = dict_find(name); - if (e == 0 || e->type() != lazy_entry::string_t) return std::string(); - return e->string_value(); - } - - lazy_entry const* lazy_entry::dict_find_string(char const* name) const - { - lazy_entry const* e = dict_find(name); - if (e == 0 || e->type() != lazy_entry::string_t) return 0; - return e; - } - - size_type lazy_entry::dict_find_int_value(char const* name, size_type default_val) const - { - lazy_entry const* e = dict_find(name); - if (e == 0 || e->type() != lazy_entry::int_t) return default_val; - return e->int_value(); - } - - lazy_entry const* lazy_entry::dict_find_dict(char const* name) const - { - lazy_entry const* e = dict_find(name); - if (e == 0 || e->type() != lazy_entry::dict_t) return 0; - return e; - } - - lazy_entry const* lazy_entry::dict_find_list(char const* name) const - { - lazy_entry const* e = dict_find(name); - if (e == 0 || e->type() != lazy_entry::list_t) return 0; - return e; - } - - lazy_entry* lazy_entry::dict_find(char const* name) - { - TORRENT_ASSERT(m_type == dict_t); - for (int i = 0; i < m_size; ++i) - { - std::pair const& e = m_data.dict[i]; - if (string_equal(name, e.first, e.second.m_begin - e.first)) - return &m_data.dict[i].second; - } - return 0; - } - - lazy_entry* lazy_entry::list_append() - { - TORRENT_ASSERT(m_type == list_t); - TORRENT_ASSERT(m_size <= m_capacity); - if (m_capacity == 0) - { - int capacity = lazy_entry_list_init; - m_data.list = new (std::nothrow) lazy_entry[capacity]; - if (m_data.list == 0) return 0; - m_capacity = capacity; - } - else if (m_size == m_capacity) - { - int capacity = m_capacity * lazy_entry_grow_factor; - lazy_entry* tmp = new (std::nothrow) lazy_entry[capacity]; - if (tmp == 0) return 0; - std::memcpy(tmp, m_data.list, sizeof(lazy_entry) * m_size); - for (int i = 0; i < m_size; ++i) m_data.list[i].release(); - delete[] m_data.list; - m_data.list = tmp; - m_capacity = capacity; - } - - TORRENT_ASSERT(m_size < m_capacity); - return m_data.list + (m_size++); - } - - std::string lazy_entry::list_string_value_at(int i) const - { - lazy_entry const* e = list_at(i); - if (e == 0 || e->type() != lazy_entry::string_t) return std::string(); - return e->string_value(); - } - - size_type lazy_entry::list_int_value_at(int i, size_type default_val) const - { - lazy_entry const* e = list_at(i); - if (e == 0 || e->type() != lazy_entry::int_t) return default_val; - return e->int_value(); - } - - void lazy_entry::clear() - { - switch (m_type) - { - case list_t: delete[] m_data.list; break; - case dict_t: delete[] m_data.dict; break; - default: break; - } - m_data.start = 0; - m_size = 0; - m_capacity = 0; - m_type = none_t; - } - - std::pair lazy_entry::data_section() const - { - typedef std::pair return_t; - return return_t(m_begin, m_end - m_begin); - } - - std::ostream& operator<<(std::ostream& os, lazy_entry const& e) - { - switch (e.type()) - { - case lazy_entry::none_t: return os << "none"; - case lazy_entry::int_t: return os << std::dec << std::setw(0) << e.int_value(); - case lazy_entry::string_t: - { - bool printable = true; - char const* str = e.string_ptr(); - for (int i = 0; i < e.string_length(); ++i) - { - using namespace std; - if (isprint((unsigned char)str[i])) continue; - printable = false; - break; - } - os << "'"; - if (printable) return os << e.string_value() << "'"; - for (int i = 0; i < e.string_length(); ++i) - os << std::hex << std::setfill('0') << std::setw(2) - << int((unsigned char)(str[i])); - return os << "'"; - } - case lazy_entry::list_t: - { - os << "["; - bool one_liner = (e.list_size() == 0 - || (e.list_at(0)->type() == lazy_entry::int_t - && e.list_size() < 20) - || (e.list_at(0)->type() == lazy_entry::string_t - && (e.list_at(0)->string_length() < 10 - || e.list_size() < 2)) - && e.list_size() < 5); - if (!one_liner) os << "\n"; - for (int i = 0; i < e.list_size(); ++i) - { - if (i == 0 && one_liner) os << " "; - os << *e.list_at(i); - if (i < e.list_size() - 1) os << (one_liner?", ":",\n"); - else os << (one_liner?" ":"\n"); - } - return os << "]"; - } - case lazy_entry::dict_t: - { - os << "{"; - bool one_liner = (e.dict_size() == 0 - || e.dict_at(0).second->type() == lazy_entry::int_t - || (e.dict_at(0).second->type() == lazy_entry::string_t - && e.dict_at(0).second->string_length() < 30) - || e.dict_at(0).first.size() < 10) - && e.dict_size() < 5; - - if (!one_liner) os << "\n"; - for (int i = 0; i < e.dict_size(); ++i) - { - if (i == 0 && one_liner) os << " "; - std::pair ent = e.dict_at(i); - os << "'" << ent.first << "': " << *ent.second; - if (i < e.dict_size() - 1) os << (one_liner?", ":",\n"); - else os << (one_liner?" ":"\n"); - } - return os << "}"; - } - } - return os; - } - -}; - diff --git a/libtorrent/src/logger.cpp b/libtorrent/src/logger.cpp deleted file mode 100644 index 154415498..000000000 --- a/libtorrent/src/logger.cpp +++ /dev/null @@ -1,232 +0,0 @@ -/* - -Copyright (c) 2006, Arvid Norberg -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions -are met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in - the documentation and/or other materials provided with the distribution. - * Neither the name of the author nor the names of its - contributors may be used to endorse or promote products derived - from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -POSSIBILITY OF SUCH DAMAGE. - -*/ - -#include "libtorrent/pch.hpp" - -#ifdef _MSC_VER -#pragma warning(push, 1) -#endif - -#include -#include -#include - -#ifdef _MSC_VER -#pragma warning(pop) -#endif - -#include - -#include "libtorrent/extensions/logger.hpp" -#include "libtorrent/extensions.hpp" -#include "libtorrent/entry.hpp" -#include "libtorrent/peer_request.hpp" -#include "libtorrent/peer_connection.hpp" - -namespace libtorrent { - -namespace fs = boost::filesystem; - -namespace -{ - - struct logger_peer_plugin : peer_plugin - { - logger_peer_plugin(std::string const& filename) - { - fs::path dir(fs::complete("libtorrent_ext_logs")); - if (!fs::exists(dir)) fs::create_directories(dir); - m_file.open((dir / filename).string().c_str(), std::ios_base::out | std::ios_base::out); - m_file << "\n\n\n"; - log_timestamp(); - m_file << "*** starting log ***\n"; - } - - void log_timestamp() - { - m_file << time_now_string() << ": "; - } - - // can add entries to the extension handshake - virtual void add_handshake(entry&) {} - - // called when the extension handshake from the other end is received - virtual bool on_extension_handshake(lazy_entry const& h) - { - log_timestamp(); - m_file << "<== EXTENSION_HANDSHAKE\n" << h; - return true; - } - - // returning true from any of the message handlers - // indicates that the plugin has handeled the message. - // it will break the plugin chain traversing and not let - // anyone else handle the message, including the default - // handler. - - virtual bool on_choke() - { - log_timestamp(); - m_file << "<== CHOKE\n"; - m_file.flush(); - return false; - } - - virtual bool on_unchoke() - { - log_timestamp(); - m_file << "<== UNCHOKE\n"; - m_file.flush(); - return false; - } - - virtual bool on_interested() - { - log_timestamp(); - m_file << "<== INTERESTED\n"; - m_file.flush(); - return false; - } - - virtual bool on_not_interested() - { - log_timestamp(); - m_file << "<== NOT_INTERESTED\n"; - m_file.flush(); - return false; - } - - virtual bool on_have(int index) - { - log_timestamp(); - m_file << "<== HAVE [" << index << "]\n"; - m_file.flush(); - return false; - } - - virtual bool on_bitfield(std::vector const& bitfield) - { - log_timestamp(); - m_file << "<== BITFIELD\n"; - m_file.flush(); - return false; - } - - virtual bool on_request(peer_request const& r) - { - log_timestamp(); - m_file << "<== REQUEST [ piece: " << r.piece << " | s: " << r.start - << " | l: " << r.length << " ]\n"; - m_file.flush(); - return false; - } - - virtual bool on_piece(peer_request const& r, char const*) - { - log_timestamp(); - m_file << "<== PIECE [ piece: " << r.piece << " | s: " << r.start - << " | l: " << r.length << " ]\n"; - m_file.flush(); - return false; - } - - virtual bool on_cancel(peer_request const& r) - { - log_timestamp(); - m_file << "<== CANCEL [ piece: " << r.piece << " | s: " << r.start - << " | l: " << r.length << " ]\n"; - m_file.flush(); - return false; - } - - // called when an extended message is received. If returning true, - // the message is not processed by any other plugin and if false - // is returned the next plugin in the chain will receive it to - // be able to handle it - virtual bool on_extended(int length - , int msg, buffer::const_interval body) - { return false; } - - virtual bool on_unknown_message(int length, int msg - , buffer::const_interval body) - { - if (body.left() < length) return false; - log_timestamp(); - m_file << "<== UNKNOWN [ msg: " << msg - << " | l: " << length << " ]\n"; - m_file.flush(); - return false; - } - - virtual void on_piece_pass(int index) - { - log_timestamp(); - m_file << "*** HASH PASSED *** [ piece: " << index << " ]\n"; - m_file.flush(); - } - - virtual void on_piece_failed(int index) - { - log_timestamp(); - m_file << "*** HASH FAILED *** [ piece: " << index << " ]\n"; - m_file.flush(); - } - - private: - std::ofstream m_file; - }; - - struct logger_plugin : torrent_plugin - { - virtual boost::shared_ptr new_connection( - peer_connection* pc) - { - error_code ec; - return boost::shared_ptr(new logger_peer_plugin( - pc->remote().address().to_string(ec) + "_" - + to_string(pc->remote().port()).elems + ".log")); - } - }; - -} } - -namespace libtorrent -{ - - boost::shared_ptr create_logger_plugin(torrent*) - { - return boost::shared_ptr(new logger_plugin()); - } - -} - - diff --git a/libtorrent/src/lsd.cpp b/libtorrent/src/lsd.cpp deleted file mode 100644 index 5f5aa9e9e..000000000 --- a/libtorrent/src/lsd.cpp +++ /dev/null @@ -1,208 +0,0 @@ -/* - -Copyright (c) 2007, Arvid Norberg -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions -are met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in - the documentation and/or other materials provided with the distribution. - * Neither the name of the author nor the names of its - contributors may be used to endorse or promote products derived - from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -POSSIBILITY OF SUCH DAMAGE. - -*/ - -#include "libtorrent/pch.hpp" - -#include "libtorrent/lsd.hpp" -#include "libtorrent/io.hpp" -#include "libtorrent/http_tracker_connection.hpp" -#include "libtorrent/buffer.hpp" -#include "libtorrent/http_parser.hpp" -#include "libtorrent/escape_string.hpp" - -#include -#include -#if BOOST_VERSION < 103500 -#include -#include -#else -#include -#include -#endif -#include -#include -#include - -using boost::bind; -using namespace libtorrent; - -namespace libtorrent -{ - // defined in broadcast_socket.cpp - address guess_local_address(io_service&); -} - -static error_code ec; - -lsd::lsd(io_service& ios, address const& listen_interface - , peer_callback_t const& cb) - : m_callback(cb) - , m_retry_count(1) - , m_socket(ios, udp::endpoint(address_v4::from_string("239.192.152.143", ec), 6771) - , bind(&lsd::on_announce, self(), _1, _2, _3)) - , m_broadcast_timer(ios) - , m_disabled(false) -{ -#if defined(TORRENT_LOGGING) || defined(TORRENT_VERBOSE_LOGGING) - m_log.open("lsd.log", std::ios::in | std::ios::out | std::ios::trunc); -#endif -} - -lsd::~lsd() {} - -void lsd::announce(sha1_hash const& ih, int listen_port) -{ - if (m_disabled) return; - - std::stringstream btsearch; - btsearch << "BT-SEARCH * HTTP/1.1\r\n" - "Host: 239.192.152.143:6771\r\n" - "Port: " << to_string(listen_port).elems << "\r\n" - "Infohash: " << ih << "\r\n" - "\r\n\r\n"; - std::string const& msg = btsearch.str(); - - m_retry_count = 1; - error_code ec; - m_socket.send(msg.c_str(), int(msg.size()), ec); - if (ec) - { - m_disabled = true; - return; - } - -#if defined(TORRENT_LOGGING) || defined(TORRENT_VERBOSE_LOGGING) - m_log << time_now_string() - << " ==> announce: ih: " << ih << " port: " << to_string(listen_port).elems << std::endl; -#endif - - m_broadcast_timer.expires_from_now(milliseconds(250 * m_retry_count), ec); - m_broadcast_timer.async_wait(bind(&lsd::resend_announce, self(), _1, msg)); -} - -void lsd::resend_announce(error_code const& e, std::string msg) -{ - if (e) return; - - error_code ec; - m_socket.send(msg.c_str(), int(msg.size()), ec); - - ++m_retry_count; - if (m_retry_count >= 5) - return; - - m_broadcast_timer.expires_from_now(milliseconds(250 * m_retry_count), ec); - m_broadcast_timer.async_wait(bind(&lsd::resend_announce, self(), _1, msg)); -} - -void lsd::on_announce(udp::endpoint const& from, char* buffer - , std::size_t bytes_transferred) -{ - using namespace libtorrent::detail; - - http_parser p; - - bool error = false; - p.incoming(buffer::const_interval(buffer, buffer + bytes_transferred) - , error); - - if (!p.header_finished() || error) - { -#if defined(TORRENT_LOGGING) || defined(TORRENT_VERBOSE_LOGGING) - m_log << time_now_string() - << " <== announce: incomplete HTTP message\n"; -#endif - return; - } - - if (p.method() != "bt-search") - { -#if defined(TORRENT_LOGGING) || defined(TORRENT_VERBOSE_LOGGING) - m_log << time_now_string() - << " <== announce: invalid HTTP method: " << p.method() << std::endl; -#endif - return; - } - - std::string const& port_str = p.header("port"); - if (port_str.empty()) - { -#if defined(TORRENT_LOGGING) || defined(TORRENT_VERBOSE_LOGGING) - m_log << time_now_string() - << " <== announce: invalid BT-SEARCH, missing port" << std::endl; -#endif - return; - } - - std::string const& ih_str = p.header("infohash"); - if (ih_str.empty()) - { -#if defined(TORRENT_LOGGING) || defined(TORRENT_VERBOSE_LOGGING) - m_log << time_now_string() - << " <== announce: invalid BT-SEARCH, missing infohash" << std::endl; -#endif - return; - } - - sha1_hash ih(0); - std::istringstream ih_sstr(ih_str); - ih_sstr >> ih; - int port = std::atoi(port_str.c_str()); - - if (!ih.is_all_zeros() && port != 0) - { -#if defined(TORRENT_LOGGING) || defined(TORRENT_VERBOSE_LOGGING) - m_log << time_now_string() - << " *** incoming local announce " << from.address() - << ":" << to_string(port).elems << " ih: " << ih << std::endl; -#endif - // we got an announce, pass it on through the callback -#ifndef BOOST_NO_EXCEPTIONS - try { -#endif - m_callback(tcp::endpoint(from.address(), port), ih); -#ifndef BOOST_NO_EXCEPTIONS - } - catch (std::exception&) {} -#endif - } -} - -void lsd::close() -{ - m_socket.close(); - error_code ec; - m_broadcast_timer.cancel(ec); - m_disabled = true; - m_callback.clear(); -} - diff --git a/libtorrent/src/magnet_uri.cpp b/libtorrent/src/magnet_uri.cpp deleted file mode 100644 index 2570afc83..000000000 --- a/libtorrent/src/magnet_uri.cpp +++ /dev/null @@ -1,146 +0,0 @@ -/* - -Copyright (c) 2007, Arvid Norberg -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions -are met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in - the documentation and/or other materials provided with the distribution. - * Neither the name of the author nor the names of its - contributors may be used to endorse or promote products derived - from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -POSSIBILITY OF SUCH DAMAGE. - -*/ - -#include "libtorrent/magnet_uri.hpp" -#include "libtorrent/session.hpp" -#include "libtorrent/torrent_handle.hpp" -#include "libtorrent/escape_string.hpp" - -#include -#include - -namespace libtorrent -{ - std::string make_magnet_uri(torrent_handle const& handle) - { - std::stringstream ret; - if (!handle.is_valid()) return ret.str(); - - std::string name = handle.name(); - - ret << "magnet:?xt=urn:btih:" << base32encode( - std::string((char*)handle.info_hash().begin(), 20)); - if (!name.empty()) - ret << "&dn=" << escape_string(name.c_str(), name.length()); - torrent_status st = handle.status(); - if (!st.current_tracker.empty()) - { - ret << "&tr=" << escape_string(st.current_tracker.c_str() - , st.current_tracker.length()); - } - else - { - std::vector const& tr = handle.trackers(); - if (!tr.empty()) - { - ret << "&tr=" << escape_string(tr[0].url.c_str() - , tr[0].url.length()); - } - } - return ret.str(); - } - - std::string make_magnet_uri(torrent_info const& info) - { - std::stringstream ret; - if (!info.is_valid()) return ret.str(); - - std::string name = info.name(); - - ret << "magnet:?xt=urn:btih:" << base32encode( - std::string((char*)info.info_hash().begin(), 20)); - if (!name.empty()) - ret << "&dn=" << escape_string(name.c_str(), name.length()); - std::vector const& tr = info.trackers(); - if (!tr.empty()) - { - ret << "&tr=" << escape_string(tr[0].url.c_str() - , tr[0].url.length()); - } - return ret.str(); - } - -#ifndef TORRENT_NO_DEPRECATE - torrent_handle add_magnet_uri(session& ses, std::string const& uri - , fs::path const& save_path - , storage_mode_t storage_mode - , bool paused - , storage_constructor_type sc - , void* userdata) - { - std::string name; - std::string tracker; - - boost::optional display_name = url_has_argument(uri, "dn"); - if (display_name) name = unescape_string(display_name->c_str()); - boost::optional tracker_string = url_has_argument(uri, "tr"); - if (tracker_string) tracker = unescape_string(tracker_string->c_str()); - - boost::optional btih = url_has_argument(uri, "xt"); - if (!btih) return torrent_handle(); - - if (btih->compare(0, 9, "urn:btih:") != 0) return torrent_handle(); - - sha1_hash info_hash(base32decode(btih->substr(9))); - - return ses.add_torrent(tracker.empty() ? 0 : tracker.c_str(), info_hash - , name.empty() ? 0 : name.c_str(), save_path, entry() - , storage_mode, paused, sc, userdata); - } -#endif - - torrent_handle add_magnet_uri(session& ses, std::string const& uri - , add_torrent_params p) - { - std::string name; - std::string tracker; - - boost::optional display_name = url_has_argument(uri, "dn"); - if (display_name) name = unescape_string(display_name->c_str()); - boost::optional tracker_string = url_has_argument(uri, "tr"); - if (tracker_string) tracker = unescape_string(tracker_string->c_str()); - - boost::optional btih = url_has_argument(uri, "xt"); - if (!btih) return torrent_handle(); - - if (btih->compare(0, 9, "urn:btih:") != 0) return torrent_handle(); - - sha1_hash info_hash(base32decode(btih->substr(9))); - - if (!tracker.empty()) p.tracker_url = tracker.c_str(); - p.info_hash = info_hash; - if (!name.empty()) p.name = name.c_str(); - return ses.add_torrent(p); - } -} - - diff --git a/libtorrent/src/metadata_transfer.cpp b/libtorrent/src/metadata_transfer.cpp deleted file mode 100644 index 49267464e..000000000 --- a/libtorrent/src/metadata_transfer.cpp +++ /dev/null @@ -1,626 +0,0 @@ -/* - -Copyright (c) 2006, Arvid Norberg -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions -are met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in - the documentation and/or other materials provided with the distribution. - * Neither the name of the author nor the names of its - contributors may be used to endorse or promote products derived - from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -POSSIBILITY OF SUCH DAMAGE. - -*/ - -#include "libtorrent/pch.hpp" - -#ifdef _MSC_VER -#pragma warning(push, 1) -#endif - -#include - -#ifdef _MSC_VER -#pragma warning(pop) -#endif - -#include -#include -#include - -#include "libtorrent/peer_connection.hpp" -#include "libtorrent/bt_peer_connection.hpp" -#include "libtorrent/hasher.hpp" -#include "libtorrent/bencode.hpp" -#include "libtorrent/torrent.hpp" -#include "libtorrent/extensions.hpp" -#include "libtorrent/extensions/metadata_transfer.hpp" -#include "libtorrent/alert_types.hpp" -#include "libtorrent/buffer.hpp" - -namespace libtorrent { namespace -{ - int div_round_up(int numerator, int denominator) - { - return (numerator + denominator - 1) / denominator; - } - - std::pair req_to_offset(std::pair req, int total_size) - { - TORRENT_ASSERT(req.first >= 0); - TORRENT_ASSERT(req.second > 0); - TORRENT_ASSERT(req.second <= 256); - TORRENT_ASSERT(req.first + req.second <= 256); - - int start = div_round_up(req.first * total_size, 256); - int size = div_round_up((req.first + req.second) * total_size, 256) - start; - return std::make_pair(start, size); - } - - std::pair offset_to_req(std::pair offset, int total_size) - { - int start = offset.first * 256 / total_size; - int size = (offset.first + offset.second) * 256 / total_size - start; - - std::pair ret(start, size); - - TORRENT_ASSERT(start >= 0); - TORRENT_ASSERT(size > 0); - TORRENT_ASSERT(start <= 256); - TORRENT_ASSERT(start + size <= 256); - - // assert the identity of this function -#ifndef NDEBUG - std::pair identity = req_to_offset(ret, total_size); - TORRENT_ASSERT(offset == identity); -#endif - return ret; - } - - struct metadata_plugin : torrent_plugin - { - metadata_plugin(torrent& t) - : m_torrent(t) - , m_metadata_progress(0) - , m_metadata_size(0) - { - m_requested_metadata.resize(256, 0); - } - - virtual void on_files_checked() - { - // if the torrent is a seed, make a reference to - // the metadata from the torrent before it is deallocated - if (m_torrent.is_seed()) metadata(); - } - - virtual boost::shared_ptr new_connection( - peer_connection* pc); - - buffer::const_interval metadata() const - { - if (!m_metadata) - { - m_metadata = m_torrent.torrent_file().metadata(); - m_metadata_size = m_torrent.torrent_file().metadata_size(); - TORRENT_ASSERT(hasher(m_metadata.get(), m_metadata_size).final() - == m_torrent.torrent_file().info_hash()); - } - return buffer::const_interval(m_metadata.get(), m_metadata.get() - + m_metadata_size); - } - - bool received_metadata(char const* buf, int size, int offset, int total_size) - { - if (m_torrent.valid_metadata()) return false; - - if (!m_metadata || m_metadata_size < total_size) - { - m_metadata.reset(new char[total_size]); - m_metadata_size = total_size; - } - std::copy(buf, buf + size, &m_metadata[offset]); - - if (m_have_metadata.empty()) - m_have_metadata.resize(256, false); - - std::pair req = offset_to_req(std::make_pair(offset, size) - , total_size); - - TORRENT_ASSERT(req.first + req.second <= (int)m_have_metadata.size()); - - std::fill( - m_have_metadata.begin() + req.first - , m_have_metadata.begin() + req.first + req.second - , true); - - bool have_all = std::count( - m_have_metadata.begin() - , m_have_metadata.end() - , true) == 256; - - if (!have_all) return false; - - hasher h; - h.update(&m_metadata[0], m_metadata_size); - sha1_hash info_hash = h.final(); - - if (info_hash != m_torrent.torrent_file().info_hash()) - { - std::fill( - m_have_metadata.begin() - , m_have_metadata.begin() + req.first + req.second - , false); - m_metadata_progress = 0; - m_metadata_size = 0; - - if (m_torrent.alerts().should_post()) - { - m_torrent.alerts().post_alert(metadata_failed_alert( - m_torrent.get_handle())); - } - - return false; - } - - lazy_entry e; - lazy_bdecode(m_metadata.get(), m_metadata.get() + m_metadata_size, e); - std::string error; - if (!m_torrent.set_metadata(e, error)) - { - // this means the metadata is correct, since we - // verified it against the info-hash, but we - // failed to parse it. Pause the torrent - // TODO: Post an alert! - m_torrent.pause(); - return false; - } - - // clear the storage for the bitfield - std::vector().swap(m_have_metadata); - std::vector().swap(m_requested_metadata); - - return true; - } - - // returns a range of the metadata that - // we should request. - std::pair metadata_request(); - - void cancel_metadata_request(std::pair req) - { - for (int i = req.first; i < req.first + req.second; ++i) - { - TORRENT_ASSERT(m_requested_metadata[i] > 0); - if (m_requested_metadata[i] > 0) - --m_requested_metadata[i]; - } - } - - // this is called from the peer_connection for - // each piece of metadata it receives - void metadata_progress(int total_size, int received) - { - m_metadata_progress += received; - m_metadata_size = total_size; - } - - void on_piece_pass(int) - { - // if we became a seed, copy the metadata from - // the torrent before it is deallocated - if (m_torrent.is_seed()) - metadata(); - } - - private: - torrent& m_torrent; - - // this buffer is filled with the info-section of - // the metadata file while downloading it from - // peers, and while sending it. - // it is mutable because it's generated lazily - mutable boost::shared_array m_metadata; - - int m_metadata_progress; - mutable int m_metadata_size; - - // this is a bitfield of size 256, each bit represents - // a piece of the metadata. It is set to one if we - // have that piece. This vector may be empty - // (size 0) if we haven't received any metadata - // or if we already have all metadata - std::vector m_have_metadata; - // this vector keeps track of how many times each meatdata - // block has been requested - std::vector m_requested_metadata; - }; - - - struct metadata_peer_plugin : peer_plugin - { - metadata_peer_plugin(torrent& t, peer_connection& pc - , metadata_plugin& tp) - : m_waiting_metadata_request(false) - , m_message_index(0) - , m_metadata_progress(0) - , m_no_metadata(min_time()) - , m_metadata_request(min_time()) - , m_torrent(t) - , m_pc(pc) - , m_tp(tp) - {} - - // can add entries to the extension handshake - virtual void add_handshake(entry& h) - { - entry& messages = h["m"]; - messages["LT_metadata"] = 14; - } - - // called when the extension handshake from the other end is received - virtual bool on_extension_handshake(lazy_entry const& h) - { - m_message_index = 0; - if (h.type() != lazy_entry::dict_t) return false; - lazy_entry const* messages = h.dict_find("m"); - if (!messages || messages->type() != lazy_entry::dict_t) return false; - - int index = messages->dict_find_int_value("LT_metadata", -1); - if (index == -1) return false; - m_message_index = index; - return true; - } - - void write_metadata_request(std::pair req) - { - TORRENT_ASSERT(req.first >= 0); - TORRENT_ASSERT(req.second > 0); - TORRENT_ASSERT(req.first + req.second <= 256); - TORRENT_ASSERT(!m_pc.associated_torrent().expired()); - TORRENT_ASSERT(!m_pc.associated_torrent().lock()->valid_metadata()); - - int start = req.first; - int size = req.second; - - // abort if the peer doesn't support the metadata extension - if (m_message_index == 0) return; - -#ifdef TORRENT_VERBOSE_LOGGING - (*m_pc.m_logger) << time_now_string() - << " ==> METADATA_REQUEST [ start: " << start << " | size: " << size << " ]\n"; -#endif - - buffer::interval i = m_pc.allocate_send_buffer(9); - - detail::write_uint32(1 + 1 + 3, i.begin); - detail::write_uint8(bt_peer_connection::msg_extended, i.begin); - detail::write_uint8(m_message_index, i.begin); - // means 'request data' - detail::write_uint8(0, i.begin); - detail::write_uint8(start, i.begin); - detail::write_uint8(size - 1, i.begin); - TORRENT_ASSERT(i.begin == i.end); - m_pc.setup_send(); - } - - void write_metadata(std::pair req) - { - TORRENT_ASSERT(req.first >= 0); - TORRENT_ASSERT(req.second > 0); - TORRENT_ASSERT(req.second <= 256); - TORRENT_ASSERT(req.first + req.second <= 256); - TORRENT_ASSERT(!m_pc.associated_torrent().expired()); - - // abort if the peer doesn't support the metadata extension - if (m_message_index == 0) return; - - // only send metadata if the torrent is non-private - if (m_torrent.valid_metadata() && !m_torrent.torrent_file().priv()) - { - std::pair offset - = req_to_offset(req, (int)m_tp.metadata().left()); - - // TODO: don't allocate send buffer for the metadata part - // just tag it on as a separate buffer like ut_metadata - buffer::interval i = m_pc.allocate_send_buffer(15 + offset.second); - -#ifdef TORRENT_VERBOSE_LOGGING - (*m_pc.m_logger) << time_now_string() - << " ==> METADATA [ start: " << req.first - << " | size: " << req.second - << " | offset: " << offset.first - << " | byte_size: " << offset.second - << " ]\n"; -#endif - // yes, we have metadata, send it - detail::write_uint32(11 + offset.second, i.begin); - detail::write_uint8(bt_peer_connection::msg_extended, i.begin); - detail::write_uint8(m_message_index, i.begin); - // means 'data packet' - detail::write_uint8(1, i.begin); - detail::write_uint32((int)m_tp.metadata().left(), i.begin); - detail::write_uint32(offset.first, i.begin); - char const* metadata = m_tp.metadata().begin; - std::copy(metadata + offset.first - , metadata + offset.first + offset.second, i.begin); - i.begin += offset.second; - TORRENT_ASSERT(i.begin == i.end); - } - else - { -#ifdef TORRENT_VERBOSE_LOGGING - (*m_pc.m_logger) << time_now_string() - << " ==> DONT HAVE METADATA\n"; -#endif - buffer::interval i = m_pc.allocate_send_buffer(4 + 3); - // we don't have the metadata, reply with - // don't have-message - detail::write_uint32(1 + 2, i.begin); - detail::write_uint8(bt_peer_connection::msg_extended, i.begin); - detail::write_uint8(m_message_index, i.begin); - // means 'have no data' - detail::write_uint8(2, i.begin); - TORRENT_ASSERT(i.begin == i.end); - } - m_pc.setup_send(); - } - - virtual bool on_extended(int length - , int msg, buffer::const_interval body) - { - if (msg != 14) return false; - if (m_message_index == 0) return false; - - if (length > 500 * 1024) - { - m_pc.disconnect("LT_metadata message larger than 500 kB"); - return true; - } - - if (body.left() < 1) return true; - int type = detail::read_uint8(body.begin); - - switch (type) - { - case 0: // request - { - if (body.left() < 2) return true; - int start = detail::read_uint8(body.begin); - int size = detail::read_uint8(body.begin) + 1; - -#ifdef TORRENT_VERBOSE_LOGGING - (*m_pc.m_logger) << time_now_string() - << " <== METADATA_REQUEST [ start: " << start - << " | size: " << size - << " ]\n"; -#endif - - if (length != 3) - { - // invalid metadata request - m_pc.disconnect("invalid metadata request"); - return true; - } - - write_metadata(std::make_pair(start, size)); - } - break; - case 1: // data - { - if (body.left() < 8) return true; - - int total_size = detail::read_int32(body.begin); - int offset = detail::read_int32(body.begin); - int data_size = length - 9; - -#ifdef TORRENT_VERBOSE_LOGGING - (*m_pc.m_logger) << time_now_string() - << " <== METADATA [ total_size: " << total_size - << " | offset: " << offset - << " | data_size: " << data_size - << " ]\n"; -#endif - - if (total_size > 500 * 1024) - { - m_pc.disconnect("metadata size larger than 500 kB"); - return true; - } - if (total_size <= 0) - { - m_pc.disconnect("invalid metadata size"); - return true; - } - if (offset > total_size || offset < 0) - { - m_pc.disconnect("invalid metadata offset"); - return true; - } - if (offset + data_size > total_size) - { - m_pc.disconnect("invalid metadata message"); - return true; - } - - m_tp.metadata_progress(total_size - , body.left() - m_metadata_progress); - m_metadata_progress = body.left(); - - if (body.left() < data_size) return true; - - m_waiting_metadata_request = false; - m_tp.received_metadata(body.begin, data_size - , offset, total_size); - m_metadata_progress = 0; - } - break; - case 2: // have no data - m_no_metadata = time_now(); - if (m_waiting_metadata_request) - m_tp.cancel_metadata_request(m_last_metadata_request); - m_waiting_metadata_request = false; -#ifdef TORRENT_VERBOSE_LOGGING - (*m_pc.m_logger) << time_now_string() - << " <== DONT HAVE METADATA\n"; -#endif - break; - default: - { - std::stringstream msg; - msg << "unknown metadata extension message: " << type; - m_pc.disconnect(msg.str().c_str()); - } - } - return true; - } - - virtual void tick() - { - // if we don't have any metadata, and this peer - // supports the request metadata extension - // and we aren't currently waiting for a request - // reply. Then, send a request for some metadata. - if (!m_torrent.valid_metadata() - && m_message_index != 0 - && !m_waiting_metadata_request - && has_metadata()) - { - m_last_metadata_request = m_tp.metadata_request(); - write_metadata_request(m_last_metadata_request); - m_waiting_metadata_request = true; - m_metadata_request = time_now(); - } - } - - bool has_metadata() const - { - return time_now() - m_no_metadata > minutes(5); - } - - private: - - // this is set to true when we send a metadata - // request to this peer, and reset to false when - // we receive a reply to our request. - bool m_waiting_metadata_request; - - // this is the message index the remote peer uses - // for metadata extension messages. - int m_message_index; - - // the number of bytes of metadata we have received - // so far from this per, only counting the current - // request. Any previously finished requests - // that have been forwarded to the torrent object - // do not count. - int m_metadata_progress; - - // this is set to the current time each time we get a - // "I don't have metadata" message. - ptime m_no_metadata; - - // this is set to the time when we last sent - // a request for metadata to this peer - ptime m_metadata_request; - - // if we're waiting for a metadata request - // this was the request we sent - std::pair m_last_metadata_request; - - torrent& m_torrent; - peer_connection& m_pc; - metadata_plugin& m_tp; - }; - - boost::shared_ptr metadata_plugin::new_connection( - peer_connection* pc) - { - bt_peer_connection* c = dynamic_cast(pc); - if (!c) return boost::shared_ptr(); - return boost::shared_ptr(new metadata_peer_plugin(m_torrent, *pc, *this)); - } - - std::pair metadata_plugin::metadata_request() - { - // count the number of peers that supports the - // extension and that has metadata - int peers = 0; -#ifndef TORRENT_DISABLE_EXTENSIONS - for (torrent::peer_iterator i = m_torrent.begin() - , end(m_torrent.end()); i != end; ++i) - { - bt_peer_connection* c = dynamic_cast(*i); - if (c == 0) continue; - metadata_peer_plugin* p - = c->supports_extension(); - if (p == 0) continue; - if (!p->has_metadata()) continue; - ++peers; - } -#endif - - // the number of blocks to request - int num_blocks = 256 / (peers + 1); - if (num_blocks < 1) num_blocks = 1; - TORRENT_ASSERT(num_blocks <= 128); - - int min_element = (std::numeric_limits::max)(); - int best_index = 0; - for (int i = 0; i < 256 - num_blocks + 1; ++i) - { - int min = *std::min_element(m_requested_metadata.begin() + i - , m_requested_metadata.begin() + i + num_blocks); - min += std::accumulate(m_requested_metadata.begin() + i - , m_requested_metadata.begin() + i + num_blocks, (int)0); - - if (min_element > min) - { - best_index = i; - min_element = min; - } - } - - std::pair ret(best_index, num_blocks); - for (int i = ret.first; i < ret.first + ret.second; ++i) - m_requested_metadata[i]++; - - TORRENT_ASSERT(ret.first >= 0); - TORRENT_ASSERT(ret.second > 0); - TORRENT_ASSERT(ret.second <= 256); - TORRENT_ASSERT(ret.first + ret.second <= 256); - - return ret; - } - -} } - -namespace libtorrent -{ - - boost::shared_ptr create_metadata_plugin(torrent* t, void*) - { - return boost::shared_ptr(new metadata_plugin(*t)); - } - -} - - diff --git a/libtorrent/src/natpmp.cpp b/libtorrent/src/natpmp.cpp deleted file mode 100644 index 753d2c7df..000000000 --- a/libtorrent/src/natpmp.cpp +++ /dev/null @@ -1,552 +0,0 @@ -/* - -Copyright (c) 2007, Arvid Norberg -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions -are met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in - the documentation and/or other materials provided with the distribution. - * Neither the name of the author nor the names of its - contributors may be used to endorse or promote products derived - from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -POSSIBILITY OF SUCH DAMAGE. - -*/ - -#include "libtorrent/pch.hpp" - -#include -#include - -#if BOOST_VERSION < 103500 -#include -#else -#include -#endif - -#include "libtorrent/natpmp.hpp" -#include "libtorrent/io.hpp" -#include "libtorrent/assert.hpp" -#include "libtorrent/enum_net.hpp" - -using boost::bind; -using namespace libtorrent; - -natpmp::natpmp(io_service& ios, address const& listen_interface, portmap_callback_t const& cb) - : m_callback(cb) - , m_currently_mapping(-1) - , m_retry_count(0) - , m_socket(ios) - , m_send_timer(ios) - , m_refresh_timer(ios) - , m_next_refresh(-1) - , m_disabled(false) - , m_abort(false) -{ -#if defined(TORRENT_LOGGING) || defined(TORRENT_VERBOSE_LOGGING) - m_log.open("natpmp.log", std::ios::in | std::ios::out | std::ios::trunc); -#endif - rebind(listen_interface); -} - -void natpmp::rebind(address const& listen_interface) -{ - mutex_t::scoped_lock l(m_mutex); - - error_code ec; - address gateway = get_default_gateway(m_socket.get_io_service(), ec); - if (ec) - { -#if defined(TORRENT_LOGGING) || defined(TORRENT_VERBOSE_LOGGING) - m_log << time_now_string() << " failed to find default router: " - << ec.message() << std::endl; -#endif - disable("failed to find default router"); - return; - } - - m_disabled = false; - - udp::endpoint nat_endpoint(gateway, 5351); - if (nat_endpoint == m_nat_endpoint) return; - m_nat_endpoint = nat_endpoint; - -#if defined(TORRENT_LOGGING) || defined(TORRENT_VERBOSE_LOGGING) - m_log << time_now_string() << " found router at: " - << m_nat_endpoint.address() << std::endl; -#endif - - m_socket.open(udp::v4(), ec); - if (ec) - { - disable(ec.message().c_str()); - return; - } - m_socket.bind(udp::endpoint(address_v4::any(), 0), ec); - if (ec) - { - disable(ec.message().c_str()); - return; - } - - m_socket.async_receive_from(asio::buffer(&m_response_buffer, 16) - , m_remote, bind(&natpmp::on_reply, self(), _1, _2)); - - for (std::vector::iterator i = m_mappings.begin() - , end(m_mappings.end()); i != end; ++i) - { - if (i->protocol != none - || i->action != mapping_t::action_none) - continue; - i->action = mapping_t::action_add; - update_mapping(i - m_mappings.begin()); - } -} - -void natpmp::disable(char const* message) -{ - m_disabled = true; - - for (std::vector::iterator i = m_mappings.begin() - , end(m_mappings.end()); i != end; ++i) - { - if (i->protocol == none) continue; - i->protocol = none; - m_callback(i - m_mappings.begin(), 0, message); - } - -#if defined(TORRENT_LOGGING) || defined(TORRENT_VERBOSE_LOGGING) - m_log << time_now_string() << " NAT-PMP disabled: " << message << std::endl; -#endif - close(); -} -void natpmp::delete_mapping(int index) -{ - TORRENT_ASSERT(index < int(m_mappings.size()) && index >= 0); - if (index >= int(m_mappings.size()) || index < 0) return; - mapping_t& m = m_mappings[index]; - - if (m.protocol == none) return; - - m.action = mapping_t::action_delete; - update_mapping(index); -} - -int natpmp::add_mapping(protocol_type p, int external_port, int local_port) -{ - mutex_t::scoped_lock l(m_mutex); - - if (m_disabled) return -1; - - std::vector::iterator i = std::find_if(m_mappings.begin() - , m_mappings.end(), boost::bind(&mapping_t::protocol, _1) == int(none)); - if (i == m_mappings.end()) - { - m_mappings.push_back(mapping_t()); - i = m_mappings.end() - 1; - } - i->protocol = p; - i->external_port = external_port; - i->local_port = local_port; - i->action = mapping_t::action_add; - - int mapping_index = i - m_mappings.begin(); - - update_mapping(mapping_index); - return mapping_index; -} - -void natpmp::try_next_mapping(int i) -{ -#if defined(TORRENT_LOGGING) || defined(TORRENT_VERBOSE_LOGGING) - m_log << time_now_string() << " try_next_mapping [ " << i << " ]" << std::endl; -#endif - -#if defined(TORRENT_LOGGING) || defined(TORRENT_VERBOSE_LOGGING) - ptime now = time_now(); - for (std::vector::iterator m = m_mappings.begin() - , end(m_mappings.end()); m != end; ++m) - { - m_log << " " << (m - m_mappings.begin()) << " [ " - "proto: " << (m->protocol == none ? "none" : m->protocol == tcp ? "tcp" : "udp") - << " port: " << m->external_port - << " local-port: " << m->local_port - << " action: " << (m->action == mapping_t::action_none ? "none" : m->action == mapping_t::action_add ? "add" : "delete") - << " ttl: " << total_seconds(m->expires - now) - << " ]" << std::endl; - } -#endif - - if (i < int(m_mappings.size()) - 1) - { - update_mapping(i + 1); - return; - } - - std::vector::iterator m = std::find_if( - m_mappings.begin(), m_mappings.end() - , boost::bind(&mapping_t::action, _1) != int(mapping_t::action_none)); - - if (m == m_mappings.end()) - { - if (m_abort) - { - error_code ec; - m_send_timer.cancel(ec); - m_socket.close(ec); - } -#if defined(TORRENT_LOGGING) || defined(TORRENT_VERBOSE_LOGGING) - m_log << " done" << (m_abort?" shutting down":"") << std::endl; -#endif - return; - } - -#if defined(TORRENT_LOGGING) || defined(TORRENT_VERBOSE_LOGGING) - m_log << " updating " << (m - m_mappings.begin()) << std::endl; -#endif - - update_mapping(m - m_mappings.begin()); -} - -void natpmp::update_mapping(int i) -{ - if (i == m_mappings.size()) - { - if (m_abort) - { - error_code ec; - m_send_timer.cancel(ec); - m_socket.close(ec); - } -#if defined(TORRENT_LOGGING) || defined(TORRENT_VERBOSE_LOGGING) - m_log << " done" << (m_abort?" shutting down":"") << std::endl; -#endif - return; - } - - natpmp::mapping_t& m = m_mappings[i]; - if (m.action == mapping_t::action_none - || m.protocol == none) - { - try_next_mapping(i); - return; - } - - if (m_currently_mapping == -1) - { - // the socket is not currently in use - // send out a mapping request - m_retry_count = 0; - send_map_request(i); - } -} - -void natpmp::send_map_request(int i) -{ - using namespace libtorrent::detail; - - TORRENT_ASSERT(m_currently_mapping == -1 - || m_currently_mapping == i); - m_currently_mapping = i; - mapping_t& m = m_mappings[i]; - TORRENT_ASSERT(m.action != mapping_t::action_none); - char buf[12]; - char* out = buf; - write_uint8(0, out); // NAT-PMP version - write_uint8(m.protocol, out); // map "protocol" - write_uint16(0, out); // reserved - write_uint16(m.local_port, out); // private port - write_uint16(m.external_port, out); // requested public port - int ttl = m.action == mapping_t::action_add ? 3600 : 0; - write_uint32(ttl, out); // port mapping lifetime - -#if defined(TORRENT_LOGGING) || defined(TORRENT_VERBOSE_LOGGING) - m_log << time_now_string() - << " ==> port map [" - << " action: " << (m.action == mapping_t::action_add ? "add" : "delete") << " " - << " proto: " << (m.protocol == udp ? "udp" : "tcp") - << " local: " << m.local_port << " external: " << m.external_port - << " ttl: " << ttl << " ]" << std::endl; -#endif - - error_code ec; - m_socket.send_to(asio::buffer(buf, 12), m_nat_endpoint, 0, ec); - if (m_abort) - { - // when we're shutting down, ignore the - // responses and just remove all mappings - // immediately - m_currently_mapping = -1; - m.action = mapping_t::action_none; - try_next_mapping(i); - } - else - { - // linear back-off instead of exponential - ++m_retry_count; - m_send_timer.expires_from_now(milliseconds(250 * m_retry_count), ec); - m_send_timer.async_wait(bind(&natpmp::resend_request, self(), i, _1)); - } -} - -void natpmp::resend_request(int i, error_code const& e) -{ - if (e) return; - mutex_t::scoped_lock l(m_mutex); - if (m_currently_mapping != i) return; - - // if we're shutting down, don't retry, just move on - // to the next mapping - if (m_retry_count >= 9 || m_abort) - { - m_currently_mapping = -1; - m_mappings[i].action = mapping_t::action_none; - // try again in two hours - m_mappings[i].expires = time_now() + hours(2); - try_next_mapping(i); - return; - } - send_map_request(i); -} - -void natpmp::on_reply(error_code const& e - , std::size_t bytes_transferred) -{ - using namespace libtorrent::detail; - if (e) - { -#if defined(TORRENT_LOGGING) || defined(TORRENT_VERBOSE_LOGGING) - m_log << time_now_string() - << " <== on_receive [" - " error: " << e.message() << " ]" << std::endl; -#endif - return; - } - - m_socket.async_receive_from(asio::buffer(&m_response_buffer, 16) - , m_remote, bind(&natpmp::on_reply, self(), _1, _2)); - - // simulate packet loss -/* - if ((rand() % 2) == 0) - { - log(" simulating drop"); - return; - } -*/ - if (m_remote != m_nat_endpoint) - { -#if defined(TORRENT_LOGGING) || defined(TORRENT_VERBOSE_LOGGING) - m_log << time_now_string() - << " <== received packet from the wrong IP [" - " ip: " << m_remote << " ]" << std::endl; -#endif - return; - } - - mutex_t::scoped_lock l(m_mutex); - - error_code ec; - m_send_timer.cancel(ec); - - char* in = m_response_buffer; - int version = read_uint8(in); - int cmd = read_uint8(in); - int result = read_uint16(in); - int time = read_uint32(in); - int private_port = read_uint16(in); - int public_port = read_uint16(in); - int lifetime = read_uint32(in); - - (void)time; // to remove warning - - int protocol = (cmd - 128 == 1)?udp:tcp; - -#if defined(TORRENT_LOGGING) || defined(TORRENT_VERBOSE_LOGGING) - m_log << time_now_string() - << " <== port map [" - << " protocol: " << (cmd - 128 == 1 ? "udp" : "tcp") - << " local: " << private_port << " external: " << public_port - << " ttl: " << lifetime << " ]" << std::endl; -#endif - -#if defined(TORRENT_LOGGING) || defined(TORRENT_VERBOSE_LOGGING) - if (version != 0) - { - m_log << "*** unexpected version: " << version << std::endl; - } -#endif - - mapping_t* m = 0; - int index = -1; - for (std::vector::iterator i = m_mappings.begin() - , end(m_mappings.end()); i != end; ++i) - { - if (private_port != i->local_port) continue; - if (protocol != i->protocol) continue; - m = &*i; - index = i - m_mappings.begin(); - break; - } - - if (m == 0) - { -#if defined(TORRENT_LOGGING) || defined(TORRENT_VERBOSE_LOGGING) - m_log << "*** not found in map table" << std::endl; -#endif - return; - } - - if (public_port == 0 || lifetime == 0) - { - // this means the mapping was - // successfully closed - m->protocol = none; - } - else - { - m->expires = time_now() + seconds(int(lifetime * 0.7f)); - m->external_port = public_port; - } - - if (result != 0) - { -#if defined(TORRENT_LOGGING) || defined(TORRENT_VERBOSE_LOGGING) - m_log << "*** ERROR: " << result << std::endl; -#endif - std::stringstream errmsg; - errmsg << "NAT router reports error (" << result << ") "; - switch (result) - { - case 1: errmsg << "Unsupported protocol version"; break; - case 2: errmsg << "Not authorized to create port map (enable NAT-PMP on your router)"; break; - case 3: errmsg << "Network failure"; break; - case 4: errmsg << "Out of resources"; break; - case 5: errmsg << "Unsupported opcode"; break; - } - m->expires = time_now() + hours(2); - m_callback(index, 0, errmsg.str()); - } - else if (m->action == mapping_t::action_add) - { - m_callback(index, m->external_port, ""); - } - - m_currently_mapping = -1; - m->action = mapping_t::action_none; - m_send_timer.cancel(ec); - update_expiration_timer(); - try_next_mapping(index); -} - -void natpmp::update_expiration_timer() -{ - if (m_abort) return; - - ptime now = time_now(); -#if defined(TORRENT_LOGGING) || defined(TORRENT_VERBOSE_LOGGING) - m_log << time_now_string() << " update_expiration_timer " << std::endl; - for (std::vector::iterator i = m_mappings.begin() - , end(m_mappings.end()); i != end; ++i) - { - m_log << " " << (i - m_mappings.begin()) << " [ " - "proto: " << (i->protocol == none ? "none" : i->protocol == tcp ? "tcp" : "udp") - << " port: " << i->external_port - << " local-port: " << i->local_port - << " action: " << (i->action == mapping_t::action_none ? "none" : i->action == mapping_t::action_add ? "add" : "delete") - << " ttl: " << total_seconds(i->expires - now) - << " ]" << std::endl; - } -#endif - - ptime min_expire = now + seconds(3600); - int min_index = -1; - for (std::vector::iterator i = m_mappings.begin() - , end(m_mappings.end()); i != end; ++i) - { - if (i->protocol == none - || i->action != mapping_t::action_none) continue; - if (i->expires < min_expire) - { - min_expire = i->expires; - min_index = i - m_mappings.begin(); - } - } - - // this is already the mapping we're waiting for - if (m_next_refresh == min_index) return; - - if (min_index >= 0) - { -#if defined(TORRENT_LOGGING) || defined(TORRENT_VERBOSE_LOGGING) - m_log << time_now_string() << " next expiration [" - " i: " << min_index - << " ttl: " << total_seconds(min_expire - time_now()) - << " ]" << std::endl; -#endif - error_code ec; - if (m_next_refresh >= 0) m_refresh_timer.cancel(ec); - m_refresh_timer.expires_from_now(min_expire - now, ec); - m_refresh_timer.async_wait(bind(&natpmp::mapping_expired, self(), _1, min_index)); - m_next_refresh = min_index; - } -} - -void natpmp::mapping_expired(error_code const& e, int i) -{ - if (e) return; - mutex_t::scoped_lock l(m_mutex); -#if defined(TORRENT_LOGGING) || defined(TORRENT_VERBOSE_LOGGING) - m_log << time_now_string() << " mapping expired [ i: " << i << " ]" << std::endl; -#endif - m_mappings[i].action = mapping_t::action_add; - if (m_next_refresh == i) m_next_refresh = -1; - update_mapping(i); -} - -void natpmp::close() -{ - mutex_t::scoped_lock l(m_mutex); - m_abort = true; - error_code ec; -#if defined(TORRENT_LOGGING) || defined(TORRENT_VERBOSE_LOGGING) - m_log << time_now_string() << " close" << std::endl; -#endif - if (m_disabled) return; - ptime now = time_now(); - for (std::vector::iterator i = m_mappings.begin() - , end(m_mappings.end()); i != end; ++i) - { -#if defined(TORRENT_LOGGING) || defined(TORRENT_VERBOSE_LOGGING) - m_log << " " << (i - m_mappings.begin()) << " [ " - "proto: " << (i->protocol == none ? "none" : i->protocol == tcp ? "tcp" : "udp") - << " port: " << i->external_port - << " local-port: " << i->local_port - << " action: " << (i->action == mapping_t::action_none ? "none" : i->action == mapping_t::action_add ? "add" : "delete") - << " ttl: " << total_seconds(i->expires - now) - << " ]" << std::endl; -#endif - if (i->protocol == none) continue; - i->action = mapping_t::action_delete; - } - m_refresh_timer.cancel(ec); - update_mapping(0); -} - diff --git a/libtorrent/src/parse_url.cpp b/libtorrent/src/parse_url.cpp deleted file mode 100644 index c7e412c95..000000000 --- a/libtorrent/src/parse_url.cpp +++ /dev/null @@ -1,132 +0,0 @@ -/* - -Copyright (c) 2008, Arvid Norberg -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions -are met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in - the documentation and/or other materials provided with the distribution. - * Neither the name of the author nor the names of its - contributors may be used to endorse or promote products derived - from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -POSSIBILITY OF SUCH DAMAGE. - -*/ - -#include "libtorrent/parse_url.hpp" -#include - -namespace libtorrent -{ - - // returns protocol, auth, hostname, port, path, error - boost::tuple - parse_url_components(std::string url) - { - std::string hostname; // hostname only - std::string auth; // user:pass - std::string protocol; // http or https for instance - char const* error = 0; - int port = 80; - - std::string::iterator at; - std::string::iterator colon; - std::string::iterator port_pos; - - // PARSE URL - std::string::iterator start = url.begin(); - // remove white spaces in front of the url - while (start != url.end() && (*start == ' ' || *start == '\t')) - ++start; - std::string::iterator end - = std::find(url.begin(), url.end(), ':'); - protocol.assign(start, end); - - if (protocol == "https") port = 443; - - if (end == url.end()) - { - error = "no protocol in url"; - goto exit; - } - ++end; - if (end == url.end() || *end != '/') - { - error = "incomplete protocol"; - goto exit; - } - ++end; - if (end == url.end() || *end != '/') - { - error = "incomplete protocol"; - goto exit; - } - ++end; - start = end; - - at = std::find(start, url.end(), '@'); - colon = std::find(start, url.end(), ':'); - end = std::find(start, url.end(), '/'); - - if (at != url.end() - && colon != url.end() - && colon < at - && at < end) - { - auth.assign(start, at); - start = at; - ++start; - } - - // this is for IPv6 addresses - if (start != url.end() && *start == '[') - { - port_pos = std::find(start, url.end(), ']'); - if (port_pos == url.end()) - { - error = "expected closing ']' for address"; - goto exit; - } - port_pos = std::find(port_pos, url.end(), ':'); - } - else - { - port_pos = std::find(start, url.end(), ':'); - } - - if (port_pos < end) - { - hostname.assign(start, port_pos); - ++port_pos; - port = std::atoi(std::string(port_pos, end).c_str()); - } - else - { - hostname.assign(start, end); - } - - start = end; -exit: - return boost::make_tuple(protocol, auth, hostname, port - , std::string(start, url.end()), error); - } - -} - diff --git a/libtorrent/src/pe_crypto.cpp b/libtorrent/src/pe_crypto.cpp deleted file mode 100644 index fe6ab6c81..000000000 --- a/libtorrent/src/pe_crypto.cpp +++ /dev/null @@ -1,161 +0,0 @@ -/* - -Copyright (c) 2007, Un Shyam & Arvid Norberg -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions -are met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in - the documentation and/or other materials provided with the distribution. - * Neither the name of the author nor the names of its - contributors may be used to endorse or promote products derived - from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -POSSIBILITY OF SUCH DAMAGE. - -*/ - -#ifndef TORRENT_DISABLE_ENCRYPTION - -#include - -#include -#include - -#include "libtorrent/pe_crypto.hpp" -#include "libtorrent/hasher.hpp" -#include "libtorrent/assert.hpp" - -namespace libtorrent -{ - namespace - { - const unsigned char dh_prime[96] = { - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC9, 0x0F, 0xDA, 0xA2, - 0x21, 0x68, 0xC2, 0x34, 0xC4, 0xC6, 0x62, 0x8B, 0x80, 0xDC, 0x1C, 0xD1, - 0x29, 0x02, 0x4E, 0x08, 0x8A, 0x67, 0xCC, 0x74, 0x02, 0x0B, 0xBE, 0xA6, - 0x3B, 0x13, 0x9B, 0x22, 0x51, 0x4A, 0x08, 0x79, 0x8E, 0x34, 0x04, 0xDD, - 0xEF, 0x95, 0x19, 0xB3, 0xCD, 0x3A, 0x43, 0x1B, 0x30, 0x2B, 0x0A, 0x6D, - 0xF2, 0x5F, 0x14, 0x37, 0x4F, 0xE1, 0x35, 0x6D, 0x6D, 0x51, 0xC2, 0x45, - 0xE4, 0x85, 0xB5, 0x76, 0x62, 0x5E, 0x7E, 0xC6, 0xF4, 0x4C, 0x42, 0xE9, - 0xA6, 0x3A, 0x36, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x05, 0x63 - }; - - const unsigned char dh_generator[1] = { 2 }; - } - - // Set the prime P and the generator, generate local public key - dh_key_exchange::dh_key_exchange() - { - m_dh = DH_new(); - if (m_dh == 0) return; - - m_dh->p = BN_bin2bn(dh_prime, sizeof(dh_prime), 0); - m_dh->g = BN_bin2bn(dh_generator, sizeof(dh_generator), 0); - if (m_dh->p == 0 || m_dh->g == 0) - { - DH_free(m_dh); - m_dh = 0; - return; - } - - m_dh->length = 160l; - - TORRENT_ASSERT(sizeof(dh_prime) == DH_size(m_dh)); - - if (DH_generate_key(m_dh) == 0 || m_dh->pub_key == 0) - { - DH_free(m_dh); - m_dh = 0; - return; - } - - // DH can generate key sizes that are smaller than the size of - // P with exponentially decreasing probability, in which case - // the msb's of m_dh_local_key need to be zeroed - // appropriately. - int key_size = get_local_key_size(); - int len_dh = sizeof(dh_prime); // must equal DH_size(m_DH) - if (key_size != len_dh) - { - TORRENT_ASSERT(key_size > 0 && key_size < len_dh); - - int pad_zero_size = len_dh - key_size; - std::fill(m_dh_local_key, m_dh_local_key + pad_zero_size, 0); - if (BN_bn2bin(m_dh->pub_key, (unsigned char*)m_dh_local_key + pad_zero_size) == 0) - { - DH_free(m_dh); - m_dh = 0; - return; - } - } - else - { - if (BN_bn2bin(m_dh->pub_key, (unsigned char*)m_dh_local_key) == 0) - { - DH_free(m_dh); - m_dh = 0; - return; - } - } - } - - dh_key_exchange::~dh_key_exchange() - { - if (m_dh) DH_free(m_dh); - } - - char const* dh_key_exchange::get_local_key() const - { - return m_dh_local_key; - } - - - // compute shared secret given remote public key - int dh_key_exchange::compute_secret(char const* remote_pubkey) - { - TORRENT_ASSERT(remote_pubkey); - BIGNUM* bn_remote_pubkey = BN_bin2bn ((unsigned char*)remote_pubkey, 96, NULL); - if (bn_remote_pubkey == 0) return -1; - char dh_secret[96]; - - int secret_size = DH_compute_key((unsigned char*)dh_secret - , bn_remote_pubkey, m_dh); - if (secret_size < 0 || secret_size > 96) return -1; - - if (secret_size != 96) - { - TORRENT_ASSERT(secret_size < 96 && secret_size > 0); - std::fill(m_dh_secret, m_dh_secret + 96 - secret_size, 0); - } - std::copy(dh_secret, dh_secret + secret_size, m_dh_secret + 96 - secret_size); - BN_free(bn_remote_pubkey); - - // calculate the xor mask for the obfuscated hash - hasher h; - h.update("req3", 4); - h.update(m_dh_secret, 96); - m_xor_mask = h.final(); - - return 0; - } - -} // namespace libtorrent - -#endif // #ifndef TORRENT_DISABLE_ENCRYPTION - diff --git a/libtorrent/src/peer_connection.cpp b/libtorrent/src/peer_connection.cpp deleted file mode 100755 index 2384623cf..000000000 --- a/libtorrent/src/peer_connection.cpp +++ /dev/null @@ -1,4077 +0,0 @@ -/* - -Copyright (c) 2003, Arvid Norberg -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions -are met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in - the documentation and/or other materials provided with the distribution. - * Neither the name of the author nor the names of its - contributors may be used to endorse or promote products derived - from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -POSSIBILITY OF SUCH DAMAGE. - -*/ - -#include "libtorrent/pch.hpp" - -#include -#include -#include -#include -#include - -#include "libtorrent/peer_connection.hpp" -#include "libtorrent/identify_client.hpp" -#include "libtorrent/entry.hpp" -#include "libtorrent/bencode.hpp" -#include "libtorrent/alert_types.hpp" -#include "libtorrent/invariant_check.hpp" -#include "libtorrent/io.hpp" -#include "libtorrent/file.hpp" -#include "libtorrent/version.hpp" -#include "libtorrent/extensions.hpp" -#include "libtorrent/aux_/session_impl.hpp" -#include "libtorrent/policy.hpp" -#include "libtorrent/socket_type.hpp" -#include "libtorrent/assert.hpp" -#include "libtorrent/broadcast_socket.hpp" - -//#define TORRENT_CORRUPT_DATA - -using boost::bind; -using boost::shared_ptr; -using libtorrent::aux::session_impl; - -namespace libtorrent -{ - // outbound connection - peer_connection::peer_connection( - session_impl& ses - , boost::weak_ptr tor - , shared_ptr s - , tcp::endpoint const& endp - , policy::peer* peerinfo) - : -#ifdef TORRENT_DEBUG - m_last_choke(time_now() - hours(1)) - , -#endif - m_ses(ses) - , m_max_out_request_queue(m_ses.settings().max_out_request_queue) - , m_last_piece(time_now()) - , m_last_request(time_now()) - , m_last_incoming_request(min_time()) - , m_last_unchoke(min_time()) - , m_last_receive(time_now()) - , m_last_sent(time_now()) - , m_requested(min_time()) - , m_timeout_extend(0) - , m_remote_dl_update(time_now()) - , m_connect(time_now()) - , m_became_uninterested(time_now()) - , m_became_uninteresting(time_now()) - , m_free_upload(0) - , m_downloaded_at_last_unchoke(0) - , m_disk_recv_buffer(ses, 0) - , m_socket(s) - , m_remote(endp) - , m_torrent(tor) - , m_num_pieces(0) - , m_timeout(m_ses.settings().peer_timeout) - , m_packet_size(0) - , m_recv_pos(0) - , m_disk_recv_buffer_size(0) - , m_reading_bytes(0) - , m_num_invalid_requests(0) - , m_priority(1) - , m_upload_limit(bandwidth_limit::inf) - , m_download_limit(bandwidth_limit::inf) - , m_peer_info(peerinfo) - , m_speed(slow) - , m_connection_ticket(-1) - , m_remote_bytes_dled(0) - , m_remote_dl_rate(0) - , m_outstanding_writing_bytes(0) - , m_download_rate_peak(0) - , m_upload_rate_peak(0) - , m_rtt(0) - , m_prefer_whole_pieces(0) - , m_desired_queue_size(2) - , m_fast_reconnect(false) - , m_active(true) - , m_peer_interested(false) - , m_peer_choked(true) - , m_interesting(false) - , m_choked(true) - , m_failed(false) - , m_ignore_bandwidth_limits(false) - , m_have_all(false) - , m_disconnecting(false) - , m_connecting(true) - , m_queued(true) - , m_request_large_blocks(false) - , m_upload_only(false) - , m_snubbed(false) - , m_bitfield_received(false) -#ifdef TORRENT_DEBUG - , m_in_constructor(true) - , m_disconnect_started(false) - , m_initialized(false) -#endif - { - m_channel_state[upload_channel] = peer_info::bw_idle; - m_channel_state[download_channel] = peer_info::bw_idle; - - TORRENT_ASSERT(peerinfo == 0 || peerinfo->banned == false); -#ifndef TORRENT_DISABLE_RESOLVE_COUNTRIES - std::fill(m_country, m_country + 2, 0); -#ifndef TORRENT_DISABLE_GEO_IP - if (m_ses.has_country_db()) - { - char const *country = m_ses.country_for_ip(m_remote.address()); - if (country != 0) - { - m_country[0] = country[0]; - m_country[1] = country[1]; - } - } -#endif -#endif -#if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_ERROR_LOGGING - error_code ec; - m_logger = m_ses.create_log(m_remote.address().to_string(ec) + "_" - + to_string(m_remote.port()).elems, m_ses.listen_port()); - (*m_logger) << "*** OUTGOING CONNECTION\n"; -#endif -#ifdef TORRENT_DEBUG - piece_failed = false; -#endif -#ifndef TORRENT_DISABLE_GEO_IP - m_inet_as_name = m_ses.as_name_for_ip(m_remote.address()); -#endif - - std::fill(m_peer_id.begin(), m_peer_id.end(), 0); - } - - // incoming connection - peer_connection::peer_connection( - session_impl& ses - , shared_ptr s - , tcp::endpoint const& endp - , policy::peer* peerinfo) - : -#ifdef TORRENT_DEBUG - m_last_choke(time_now() - hours(1)) - , -#endif - m_ses(ses) - , m_max_out_request_queue(m_ses.settings().max_out_request_queue) - , m_last_piece(time_now()) - , m_last_request(time_now()) - , m_last_incoming_request(min_time()) - , m_last_unchoke(min_time()) - , m_last_receive(time_now()) - , m_last_sent(time_now()) - , m_requested(min_time()) - , m_timeout_extend(0) - , m_remote_dl_update(time_now()) - , m_connect(time_now()) - , m_became_uninterested(time_now()) - , m_became_uninteresting(time_now()) - , m_free_upload(0) - , m_downloaded_at_last_unchoke(0) - , m_disk_recv_buffer(ses, 0) - , m_socket(s) - , m_remote(endp) - , m_num_pieces(0) - , m_timeout(m_ses.settings().peer_timeout) - , m_packet_size(0) - , m_recv_pos(0) - , m_disk_recv_buffer_size(0) - , m_reading_bytes(0) - , m_num_invalid_requests(0) - , m_priority(1) - , m_upload_limit(bandwidth_limit::inf) - , m_download_limit(bandwidth_limit::inf) - , m_peer_info(peerinfo) - , m_speed(slow) - , m_connection_ticket(-1) - , m_remote_bytes_dled(0) - , m_remote_dl_rate(0) - , m_outstanding_writing_bytes(0) - , m_download_rate_peak(0) - , m_upload_rate_peak(0) - , m_rtt(0) - , m_prefer_whole_pieces(0) - , m_desired_queue_size(2) - , m_fast_reconnect(false) - , m_active(false) - , m_peer_interested(false) - , m_peer_choked(true) - , m_interesting(false) - , m_choked(true) - , m_failed(false) - , m_ignore_bandwidth_limits(false) - , m_have_all(false) - , m_disconnecting(false) - , m_connecting(false) - , m_queued(false) - , m_request_large_blocks(false) - , m_upload_only(false) - , m_snubbed(false) - , m_bitfield_received(false) -#ifdef TORRENT_DEBUG - , m_in_constructor(true) - , m_disconnect_started(false) - , m_initialized(false) -#endif - { - m_channel_state[upload_channel] = peer_info::bw_idle; - m_channel_state[download_channel] = peer_info::bw_idle; - -#ifndef TORRENT_DISABLE_RESOLVE_COUNTRIES - std::fill(m_country, m_country + 2, 0); -#ifndef TORRENT_DISABLE_GEO_IP - if (m_ses.has_country_db()) - { - char const *country = m_ses.country_for_ip(m_remote.address()); - if (country != 0) - { - m_country[0] = country[0]; - m_country[1] = country[1]; - } - } -#endif -#endif - -#if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_ERROR_LOGGING - error_code ec; - TORRENT_ASSERT(m_socket->remote_endpoint(ec) == m_remote || ec); - m_logger = m_ses.create_log(remote().address().to_string(ec) + "_" - + to_string(remote().port()).elems, m_ses.listen_port()); - (*m_logger) << "*** INCOMING CONNECTION\n"; -#endif - -#ifndef TORRENT_DISABLE_GEO_IP - m_inet_as_name = m_ses.as_name_for_ip(m_remote.address()); -#endif -#ifdef TORRENT_DEBUG - piece_failed = false; -#endif - std::fill(m_peer_id.begin(), m_peer_id.end(), 0); - } - - bool peer_connection::unchoke_compare(boost::intrusive_ptr const& p) const - { - TORRENT_ASSERT(p); - peer_connection const& rhs = *p; - - size_type c1; - size_type c2; - - // first compare how many bytes they've sent us - c1 = m_statistics.total_payload_download() - m_downloaded_at_last_unchoke; - c2 = rhs.m_statistics.total_payload_download() - rhs.m_downloaded_at_last_unchoke; - if (c1 > c2) return true; - if (c1 < c2) return false; - - // if they are equal, compare how much we have uploaded - if (m_peer_info) c1 = m_peer_info->total_upload(); - else c1 = m_statistics.total_payload_upload(); - if (rhs.m_peer_info) c2 = rhs.m_peer_info->total_upload(); - else c2 = rhs.m_statistics.total_payload_upload(); - - // in order to not switch back and forth too often, - // unchoked peers must be at least one piece ahead - // of a choked peer to be sorted at a lower unchoke-priority - boost::shared_ptr t1 = m_torrent.lock(); - TORRENT_ASSERT(t1); - boost::shared_ptr t2 = rhs.associated_torrent().lock(); - TORRENT_ASSERT(t2); - if (!is_choked()) c1 -= (std::max)(t1->torrent_file().piece_length(), 256 * 1024); - if (!rhs.is_choked()) c2 -= (std::max)(t2->torrent_file().piece_length(), 256 * 1024); - - return c1 < c2; - } - - void peer_connection::reset_choke_counters() - { - m_downloaded_at_last_unchoke = m_statistics.total_payload_download(); - } - - void peer_connection::start() - { - TORRENT_ASSERT(m_peer_info == 0 || m_peer_info->connection == this); - boost::shared_ptr t = m_torrent.lock(); - - if (!t) - { - tcp::socket::non_blocking_io ioc(true); - error_code ec; - m_socket->io_control(ioc, ec); - if (ec) - { - disconnect(ec.message().c_str()); - return; - } - m_remote = m_socket->remote_endpoint(ec); - if (ec) - { - disconnect(ec.message().c_str()); - return; - } - if (m_remote.address().is_v4()) - m_socket->set_option(type_of_service(m_ses.settings().peer_tos), ec); - } - else if (t->ready_for_connections()) - { - init(); - } - } - - void peer_connection::update_interest() - { - boost::shared_ptr t = m_torrent.lock(); - TORRENT_ASSERT(t); - - // if m_have_piece is 0, it means the connections - // have not been initialized yet. The interested - // flag will be updated once they are. - if (m_have_piece.size() == 0) return; - if (!t->ready_for_connections()) return; - - bool interested = false; - if (!t->is_finished()) - { - piece_picker const& p = t->picker(); - int num_pieces = p.num_pieces(); - for (int j = 0; j != num_pieces; ++j) - { - if (!p.have_piece(j) - && t->piece_priority(j) > 0 - && m_have_piece[j]) - { - interested = true; - break; - } - } - } - try - { - if (!interested) send_not_interested(); - else t->get_policy().peer_is_interesting(*this); - } - // may throw an asio error if socket has disconnected - catch (std::exception&) {} - - TORRENT_ASSERT(in_handshake() || is_interesting() == interested); - } - -#ifndef TORRENT_DISABLE_EXTENSIONS - void peer_connection::add_extension(boost::shared_ptr ext) - { - m_extensions.push_back(ext); - } -#endif - - void peer_connection::send_allowed_set() - { - INVARIANT_CHECK; - - boost::shared_ptr t = m_torrent.lock(); - TORRENT_ASSERT(t); - - int num_allowed_pieces = m_ses.settings().allowed_fast_set_size; - int num_pieces = t->torrent_file().num_pieces(); - - if (num_allowed_pieces >= num_pieces) - { - for (int i = 0; i < num_pieces; ++i) - { -#ifdef TORRENT_VERBOSE_LOGGING - (*m_logger) << time_now_string() - << " ==> ALLOWED_FAST [ " << i << " ]\n"; -#endif - write_allow_fast(i); - m_accept_fast.insert(i); - } - return; - } - - std::string x; - address const& addr = m_remote.address(); - if (addr.is_v4()) - { - address_v4::bytes_type bytes = addr.to_v4().to_bytes(); - x.assign((char*)&bytes[0], bytes.size()); - } - else - { - address_v6::bytes_type bytes = addr.to_v6().to_bytes(); - x.assign((char*)&bytes[0], bytes.size()); - } - x.append((char*)&t->torrent_file().info_hash()[0], 20); - - sha1_hash hash = hasher(&x[0], x.size()).final(); - for (;;) - { - char* p = (char*)&hash[0]; - for (int i = 0; i < 5; ++i) - { - int piece = detail::read_uint32(p) % num_pieces; - if (m_accept_fast.find(piece) == m_accept_fast.end()) - { -#ifdef TORRENT_VERBOSE_LOGGING - (*m_logger) << time_now_string() - << " ==> ALLOWED_FAST [ " << piece << " ]\n"; -#endif - write_allow_fast(piece); - m_accept_fast.insert(piece); - if (int(m_accept_fast.size()) >= num_allowed_pieces - || int(m_accept_fast.size()) == num_pieces) return; - } - } - hash = hasher((char*)&hash[0], 20).final(); - } - } - - void peer_connection::on_metadata_impl() - { - boost::shared_ptr t = associated_torrent().lock(); - m_have_piece.resize(t->torrent_file().num_pieces(), m_have_all); - m_num_pieces = m_have_piece.count(); - if (m_num_pieces == int(m_have_piece.size())) - { -#ifdef TORRENT_VERBOSE_LOGGING - (*m_logger) << time_now_string() - << " *** on_metadata(): THIS IS A SEED ***\n"; -#endif - // if this is a web seed. we don't have a peer_info struct - if (m_peer_info) m_peer_info->seed = true; - m_upload_only = true; - - t->peer_has_all(); - disconnect_if_redundant(); - if (m_disconnecting) return; - - on_metadata(); - if (m_disconnecting) return; - - if (!t->is_finished()) - t->get_policy().peer_is_interesting(*this); - - return; - } - TORRENT_ASSERT(!m_have_all); - - on_metadata(); - if (m_disconnecting) return; - - // let the torrent know which pieces the - // peer has - // if we're a seed, we don't keep track of piece availability - bool interesting = false; - if (!t->is_seed()) - { - t->peer_has(m_have_piece); - - for (int i = 0; i < (int)m_have_piece.size(); ++i) - { - if (m_have_piece[i]) - { - if (!t->have_piece(i) && t->picker().piece_priority(i) != 0) - interesting = true; - } - } - } - - if (interesting) t->get_policy().peer_is_interesting(*this); - else if (upload_only()) disconnect("upload to upload connections"); - } - - void peer_connection::init() - { - INVARIANT_CHECK; - - boost::shared_ptr t = m_torrent.lock(); - TORRENT_ASSERT(t); - TORRENT_ASSERT(t->valid_metadata()); - TORRENT_ASSERT(t->ready_for_connections()); - - m_have_piece.resize(t->torrent_file().num_pieces(), m_have_all); - - if (m_have_all) m_num_pieces = t->torrent_file().num_pieces(); -#ifdef TORRENT_DEBUG - m_initialized = true; -#endif - // now that we have a piece_picker, - // update it with this peer's pieces - - TORRENT_ASSERT(m_num_pieces == m_have_piece.count()); - - if (m_num_pieces == int(m_have_piece.size())) - { -#ifdef TORRENT_VERBOSE_LOGGING - (*m_logger) << " *** THIS IS A SEED ***\n"; -#endif - // if this is a web seed. we don't have a peer_info struct - if (m_peer_info) m_peer_info->seed = true; - m_upload_only = true; - - t->peer_has_all(); - if (t->is_finished()) send_not_interested(); - else t->get_policy().peer_is_interesting(*this); - return; - } - - // if we're a seed, we don't keep track of piece availability - if (!t->is_seed()) - { - t->peer_has(m_have_piece); - bool interesting = false; - for (int i = 0; i < int(m_have_piece.size()); ++i) - { - if (m_have_piece[i]) - { - // if the peer has a piece and we don't, the peer is interesting - if (!t->have_piece(i) - && t->picker().piece_priority(i) != 0) - interesting = true; - } - } - if (interesting) t->get_policy().peer_is_interesting(*this); - else send_not_interested(); - } - else - { - update_interest(); - } - } - - peer_connection::~peer_connection() - { -// INVARIANT_CHECK; - TORRENT_ASSERT(!m_in_constructor); - TORRENT_ASSERT(m_disconnecting); - TORRENT_ASSERT(m_disconnect_started); - - m_disk_recv_buffer_size = 0; - -#if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_ERROR_LOGGING - if (m_logger) - { - (*m_logger) << time_now_string() - << " *** CONNECTION CLOSED\n"; - } -#endif - TORRENT_ASSERT(!m_ses.has_peer(this)); -#ifdef TORRENT_DEBUG - for (aux::session_impl::torrent_map::const_iterator i = m_ses.m_torrents.begin() - , end(m_ses.m_torrents.end()); i != end; ++i) - TORRENT_ASSERT(!i->second->has_peer(this)); - if (m_peer_info) - TORRENT_ASSERT(m_peer_info->connection == 0); - - boost::shared_ptr t = m_torrent.lock(); -#endif - } - - int peer_connection::picker_options() const - { - int ret = 0; - boost::shared_ptr t = m_torrent.lock(); - TORRENT_ASSERT(t); - if (!t) return 0; - - if (t->is_sequential_download()) - { - ret |= piece_picker::sequential; - } - else if (t->num_have() < t->settings().initial_picker_threshold) - { - // if we have fewer pieces than a certain threshols - // don't pick rare pieces, just pick random ones, - // and prioritize finishing them - ret |= piece_picker::prioritize_partials; - } - else - { - ret |= piece_picker::rarest_first; - } - - if (m_snubbed) - { - // snubbed peers should request - // the common pieces first, just to make - // it more likely for all snubbed peers to - // request blocks from the same piece - ret |= piece_picker::reverse; - } - - if (t->settings().prioritize_partial_pieces) - ret |= piece_picker::prioritize_partials; - - if (on_parole()) ret |= piece_picker::on_parole - | piece_picker::prioritize_partials; - - // only one of rarest_first, common_first and sequential can be set. - TORRENT_ASSERT(bool(ret & piece_picker::rarest_first) - + bool(ret & piece_picker::sequential) <= 1); - return ret; - } - - void peer_connection::fast_reconnect(bool r) - { - if (!peer_info_struct() || peer_info_struct()->fast_reconnects > 1) - return; - m_fast_reconnect = r; - peer_info_struct()->connected = time_now() - - seconds(m_ses.settings().min_reconnect_time - * m_ses.settings().max_failcount); - ++peer_info_struct()->fast_reconnects; - } - - void peer_connection::announce_piece(int index) - { - // dont announce during handshake - if (in_handshake()) return; - - // remove suggested pieces that we have - std::vector::iterator i = std::find( - m_suggested_pieces.begin(), m_suggested_pieces.end(), index); - if (i != m_suggested_pieces.end()) m_suggested_pieces.erase(i); - - if (has_piece(index)) - { - // if we got a piece that this peer has - // it might have been the last interesting - // piece this peer had. We might not be - // interested anymore - update_interest(); - if (is_disconnecting()) return; - - // optimization, don't send have messages - // to peers that already have the piece - if (!m_ses.settings().send_redundant_have) - { -#ifdef TORRENT_VERBOSE_LOGGING - (*m_logger) << time_now_string() - << " ==> HAVE [ piece: " << index << " ] SUPRESSED\n"; -#endif - return; - } - } - -#ifdef TORRENT_VERBOSE_LOGGING - (*m_logger) << time_now_string() - << " ==> HAVE [ piece: " << index << "]\n"; -#endif - write_have(index); -#ifdef TORRENT_DEBUG - boost::shared_ptr t = m_torrent.lock(); - TORRENT_ASSERT(t); - TORRENT_ASSERT(t->have_piece(index)); -#endif - } - - bool peer_connection::has_piece(int i) const - { - boost::shared_ptr t = m_torrent.lock(); - TORRENT_ASSERT(t); - TORRENT_ASSERT(t->valid_metadata()); - TORRENT_ASSERT(i >= 0); - TORRENT_ASSERT(i < t->torrent_file().num_pieces()); - return m_have_piece[i]; - } - - std::deque const& peer_connection::request_queue() const - { - return m_request_queue; - } - - std::deque const& peer_connection::download_queue() const - { - return m_download_queue; - } - - std::deque const& peer_connection::upload_queue() const - { - return m_requests; - } - - void peer_connection::add_stat(size_type downloaded, size_type uploaded) - { - m_statistics.add_stat(downloaded, uploaded); - } - - bitfield const& peer_connection::get_bitfield() const - { - return m_have_piece; - } - - void peer_connection::received_valid_data(int index) - { - INVARIANT_CHECK; - -#ifndef TORRENT_DISABLE_EXTENSIONS - for (extension_list_t::iterator i = m_extensions.begin() - , end(m_extensions.end()); i != end; ++i) - { -#ifdef BOOST_NO_EXCEPTIONS - (*i)->on_piece_pass(index); -#else - try { (*i)->on_piece_pass(index); } catch (std::exception&) {} -#endif - } -#endif - } - - void peer_connection::received_invalid_data(int index) - { - INVARIANT_CHECK; - -#ifndef TORRENT_DISABLE_EXTENSIONS - for (extension_list_t::iterator i = m_extensions.begin() - , end(m_extensions.end()); i != end; ++i) - { -#ifdef BOOST_NO_EXCEPTIONS - (*i)->on_piece_failed(index); -#else - try { (*i)->on_piece_failed(index); } catch (std::exception&) {} -#endif - } -#endif - if (is_disconnecting()) return; - - if (peer_info_struct()) - { - if (m_ses.settings().use_parole_mode) - peer_info_struct()->on_parole = true; - - ++peer_info_struct()->hashfails; - boost::int8_t& trust_points = peer_info_struct()->trust_points; - - // we decrease more than we increase, to keep the - // allowed failed/passed ratio low. - // TODO: make this limit user settable - trust_points -= 2; - if (trust_points < -7) trust_points = -7; - } - } - - size_type peer_connection::total_free_upload() const - { - return m_free_upload; - } - - void peer_connection::add_free_upload(size_type free_upload) - { - INVARIANT_CHECK; - - m_free_upload += free_upload; - } - - // verifies a piece to see if it is valid (is within a valid range) - // and if it can correspond to a request generated by libtorrent. - bool peer_connection::verify_piece(const peer_request& p) const - { - boost::shared_ptr t = m_torrent.lock(); - TORRENT_ASSERT(t); - - TORRENT_ASSERT(t->valid_metadata()); - torrent_info const& ti = t->torrent_file(); - - return p.piece >= 0 - && p.piece < t->torrent_file().num_pieces() - && p.length > 0 - && p.start >= 0 - && (p.length == t->block_size() - || (p.length < t->block_size() - && p.piece == ti.num_pieces()-1 - && p.start + p.length == ti.piece_size(p.piece)) - || (m_request_large_blocks - && p.length <= ti.piece_length() * m_prefer_whole_pieces == 0 ? - 1 : m_prefer_whole_pieces)) - && p.piece * size_type(ti.piece_length()) + p.start + p.length - <= ti.total_size() - && (p.start % t->block_size() == 0); - } - - void peer_connection::attach_to_torrent(sha1_hash const& ih) - { - INVARIANT_CHECK; - - TORRENT_ASSERT(!m_disconnecting); - TORRENT_ASSERT(m_torrent.expired()); - boost::weak_ptr wpt = m_ses.find_torrent(ih); - boost::shared_ptr t = wpt.lock(); - - if (t && t->is_aborted()) - { -#if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_ERROR_LOGGING - (*m_logger) << " *** the torrent has been aborted\n"; -#endif - t.reset(); - } - - if (!t) - { - // we couldn't find the torrent! -#if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_ERROR_LOGGING - (*m_logger) << " *** couldn't find a torrent with the given info_hash: " << ih << "\n"; - (*m_logger) << " torrents:\n"; - session_impl::torrent_map const& torrents = m_ses.m_torrents; - for (session_impl::torrent_map::const_iterator i = torrents.begin() - , end(torrents.end()); i != end; ++i) - { - (*m_logger) << " " << i->second->torrent_file().info_hash() << "\n"; - } -#endif - disconnect("got invalid info-hash", 2); - return; - } - - if (t->is_paused()) - { - // paused torrents will not accept - // incoming connections -#if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_ERROR_LOGGING - (*m_logger) << " rejected connection to paused torrent\n"; -#endif - disconnect("connection rejected bacause torrent is paused"); - return; - } - - TORRENT_ASSERT(m_torrent.expired()); - // check to make sure we don't have another connection with the same - // info_hash and peer_id. If we do. close this connection. -#ifdef TORRENT_DEBUG - try - { -#endif - t->attach_peer(this); -#ifdef TORRENT_DEBUG - } - catch (std::exception& e) - { - std::cout << e.what() << std::endl; - TORRENT_ASSERT(false); - } -#endif - if (m_disconnecting) return; - m_torrent = wpt; - - TORRENT_ASSERT(!m_torrent.expired()); - - // if the torrent isn't ready to accept - // connections yet, we'll have to wait with - // our initialization - if (t->ready_for_connections()) init(); - - TORRENT_ASSERT(!m_torrent.expired()); - - // assume the other end has no pieces - // if we don't have valid metadata yet, - // leave the vector unallocated - TORRENT_ASSERT(m_num_pieces == 0); - m_have_piece.clear_all(); - TORRENT_ASSERT(!m_torrent.expired()); - } - - // message handlers - - // ----------------------------- - // --------- KEEPALIVE --------- - // ----------------------------- - - void peer_connection::incoming_keepalive() - { - INVARIANT_CHECK; - -#ifdef TORRENT_VERBOSE_LOGGING - (*m_logger) << time_now_string() << " <== KEEPALIVE\n"; -#endif - } - - // ----------------------------- - // ----------- CHOKE ----------- - // ----------------------------- - - void peer_connection::incoming_choke() - { - INVARIANT_CHECK; - - boost::shared_ptr t = m_torrent.lock(); - TORRENT_ASSERT(t); - -#ifndef TORRENT_DISABLE_EXTENSIONS - for (extension_list_t::iterator i = m_extensions.begin() - , end(m_extensions.end()); i != end; ++i) - { - if ((*i)->on_choke()) return; - } -#endif - if (is_disconnecting()) return; - -#ifdef TORRENT_VERBOSE_LOGGING - (*m_logger) << time_now_string() << " <== CHOKE\n"; -#endif - m_peer_choked = true; - - if (peer_info_struct() == 0 || !peer_info_struct()->on_parole) - { - // if the peer is not in parole mode, clear the queued - // up block requests - if (!t->is_seed()) - { - piece_picker& p = t->picker(); - for (std::deque::const_iterator i = m_request_queue.begin() - , end(m_request_queue.end()); i != end; ++i) - { - // since this piece was skipped, clear it and allow it to - // be requested from other peers - p.abort_download(*i); - } - } - m_request_queue.clear(); - } - } - - bool match_request(peer_request const& r, piece_block const& b, int block_size) - { - if (b.piece_index != r.piece) return false; - if (b.block_index != r.start / block_size) return false; - if (r.start % block_size != 0) return false; - return true; - } - - // ----------------------------- - // -------- REJECT PIECE ------- - // ----------------------------- - - void peer_connection::incoming_reject_request(peer_request const& r) - { - INVARIANT_CHECK; - - boost::shared_ptr t = m_torrent.lock(); - TORRENT_ASSERT(t); - -#ifndef TORRENT_DISABLE_EXTENSIONS - for (extension_list_t::iterator i = m_extensions.begin() - , end(m_extensions.end()); i != end; ++i) - { - if ((*i)->on_reject(r)) return; - } -#endif - - if (is_disconnecting()) return; - - std::deque::iterator i = std::find_if( - m_download_queue.begin(), m_download_queue.end() - , bind(match_request, boost::cref(r), bind(&pending_block::block, _1) - , t->block_size())); - -#ifdef TORRENT_VERBOSE_LOGGING - (*m_logger) << time_now_string() - << " <== REJECT_PIECE [ piece: " << r.piece << " | s: " << r.start << " | l: " << r.length << " ]\n"; -#endif - - piece_block b(-1, 0); - if (i != m_download_queue.end()) - { - b = i->block; - m_download_queue.erase(i); - - // if the peer is in parole mode, keep the request - if (peer_info_struct() && peer_info_struct()->on_parole) - { - m_request_queue.push_front(b); - } - else if (!t->is_seed()) - { - piece_picker& p = t->picker(); - p.abort_download(b); - } - } -#if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_ERROR_LOGGING - else - { - (*m_logger) << time_now_string() - << " *** PIECE NOT IN REQUEST QUEUE\n"; - } -#endif - if (has_peer_choked()) - { - // if we're choked and we got a rejection of - // a piece in the allowed fast set, remove it - // from the allow fast set. - std::vector::iterator i = std::find( - m_allowed_fast.begin(), m_allowed_fast.end(), r.piece); - if (i != m_allowed_fast.end()) m_allowed_fast.erase(i); - } - else - { - std::vector::iterator i = std::find(m_suggested_pieces.begin() - , m_suggested_pieces.end(), r.piece); - if (i != m_suggested_pieces.end()) - m_suggested_pieces.erase(i); - } - - if (m_request_queue.empty() && m_download_queue.size() < 2) - { - request_a_block(*t, *this); - send_block_requests(); - } - } - - // ----------------------------- - // ------- SUGGEST PIECE ------- - // ----------------------------- - - void peer_connection::incoming_suggest(int index) - { - INVARIANT_CHECK; - -#ifdef TORRENT_VERBOSE_LOGGING - (*m_logger) << time_now_string() - << " <== SUGGEST_PIECE [ piece: " << index << " ]\n"; -#endif - boost::shared_ptr t = m_torrent.lock(); - if (!t) return; - -#ifndef TORRENT_DISABLE_EXTENSIONS - for (extension_list_t::iterator i = m_extensions.begin() - , end(m_extensions.end()); i != end; ++i) - { - if ((*i)->on_suggest(index)) return; - } -#endif - - if (is_disconnecting()) return; - if (t->have_piece(index)) return; - - if (m_suggested_pieces.size() > 9) - m_suggested_pieces.erase(m_suggested_pieces.begin()); - m_suggested_pieces.push_back(index); - -#ifdef TORRENT_VERBOSE_LOGGING - (*m_logger) << time_now_string() - << " ** SUGGEST_PIECE [ piece: " << index << " added to set: " << m_suggested_pieces.size() << " ]\n"; -#endif - } - - // ----------------------------- - // ---------- UNCHOKE ---------- - // ----------------------------- - - void peer_connection::incoming_unchoke() - { - INVARIANT_CHECK; - - boost::shared_ptr t = m_torrent.lock(); - TORRENT_ASSERT(t); - -#ifndef TORRENT_DISABLE_EXTENSIONS - for (extension_list_t::iterator i = m_extensions.begin() - , end(m_extensions.end()); i != end; ++i) - { - if ((*i)->on_unchoke()) return; - } -#endif - -#ifdef TORRENT_VERBOSE_LOGGING - (*m_logger) << time_now_string() << " <== UNCHOKE\n"; -#endif - m_peer_choked = false; - if (is_disconnecting()) return; - - t->get_policy().unchoked(*this); - } - - // ----------------------------- - // -------- INTERESTED --------- - // ----------------------------- - - void peer_connection::incoming_interested() - { - INVARIANT_CHECK; - - boost::shared_ptr t = m_torrent.lock(); - TORRENT_ASSERT(t); - -#ifndef TORRENT_DISABLE_EXTENSIONS - for (extension_list_t::iterator i = m_extensions.begin() - , end(m_extensions.end()); i != end; ++i) - { - if ((*i)->on_interested()) return; - } -#endif - -#ifdef TORRENT_VERBOSE_LOGGING - (*m_logger) << time_now_string() << " <== INTERESTED\n"; -#endif - m_peer_interested = true; - if (is_disconnecting()) return; - t->get_policy().interested(*this); - } - - // ----------------------------- - // ------ NOT INTERESTED ------- - // ----------------------------- - - void peer_connection::incoming_not_interested() - { - INVARIANT_CHECK; - -#ifndef TORRENT_DISABLE_EXTENSIONS - for (extension_list_t::iterator i = m_extensions.begin() - , end(m_extensions.end()); i != end; ++i) - { - if ((*i)->on_not_interested()) return; - } -#endif - - m_became_uninterested = time_now(); - -#ifdef TORRENT_VERBOSE_LOGGING - (*m_logger) << time_now_string() << " <== NOT_INTERESTED\n"; -#endif - m_peer_interested = false; - if (is_disconnecting()) return; - - boost::shared_ptr t = m_torrent.lock(); - TORRENT_ASSERT(t); - - if (!is_choked()) - { - if (m_peer_info && m_peer_info->optimistically_unchoked) - { - m_peer_info->optimistically_unchoked = false; - m_ses.m_optimistic_unchoke_time_scaler = 0; - } - t->choke_peer(*this); - --m_ses.m_num_unchoked; - m_ses.m_unchoke_time_scaler = 0; - } - - t->get_policy().not_interested(*this); - } - - // ----------------------------- - // ----------- HAVE ------------ - // ----------------------------- - - void peer_connection::incoming_have(int index) - { - INVARIANT_CHECK; - - boost::shared_ptr t = m_torrent.lock(); - TORRENT_ASSERT(t); - -#ifndef TORRENT_DISABLE_EXTENSIONS - for (extension_list_t::iterator i = m_extensions.begin() - , end(m_extensions.end()); i != end; ++i) - { - if ((*i)->on_have(index)) return; - } -#endif - - if (is_disconnecting()) return; - - // if we haven't received a bitfield, it was - // probably omitted, which is the same as 'have_none' - if (!m_bitfield_received) incoming_have_none(); - -#ifdef TORRENT_VERBOSE_LOGGING - (*m_logger) << time_now_string() - << " <== HAVE [ piece: " << index << "]\n"; -#endif - - if (is_disconnecting()) return; - - if (!t->valid_metadata() && index > int(m_have_piece.size())) - { - if (index < 65536) - { - // if we don't have metadata - // and we might not have received a bitfield - // extend the bitmask to fit the new - // have message - m_have_piece.resize(index + 1, false); - } - else - { - // unless the index > 64k, in which case - // we just ignore it - return; - } - } - - // if we got an invalid message, abort - if (index >= int(m_have_piece.size()) || index < 0) - { - disconnect("got 'have'-message with higher index than the number of pieces", 2); - return; - } - - if (m_have_piece[index]) - { -#if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_ERROR_LOGGING - (*m_logger) << " got redundant HAVE message for index: " << index << "\n"; -#endif - } - else - { - m_have_piece.set_bit(index); - ++m_num_pieces; - - // only update the piece_picker if - // we have the metadata and if - // we're not a seed (in which case - // we won't have a piece picker) - if (t->valid_metadata()) - { - t->peer_has(index); - - if (!t->have_piece(index) - && !t->is_seed() - && !is_interesting() - && t->picker().piece_priority(index) != 0) - t->get_policy().peer_is_interesting(*this); - - // this will disregard all have messages we get within - // the first two seconds. Since some clients implements - // lazy bitfields, these will not be reliable to use - // for an estimated peer download rate. - if (!peer_info_struct() || time_now() - peer_info_struct()->connected > seconds(2)) - { - // update bytes downloaded since last timer - m_remote_bytes_dled += t->torrent_file().piece_size(index); - } - } - - if (is_seed()) - { - m_peer_info->seed = true; - m_upload_only = true; - disconnect_if_redundant(); - if (is_disconnecting()) return; - } - } - } - - // ----------------------------- - // --------- BITFIELD ---------- - // ----------------------------- - - void peer_connection::incoming_bitfield(bitfield const& bits) - { - INVARIANT_CHECK; - - boost::shared_ptr t = m_torrent.lock(); - TORRENT_ASSERT(t); - -#ifndef TORRENT_DISABLE_EXTENSIONS - for (extension_list_t::iterator i = m_extensions.begin() - , end(m_extensions.end()); i != end; ++i) - { - if ((*i)->on_bitfield(bits)) return; - } -#endif - - if (is_disconnecting()) return; - -#ifdef TORRENT_VERBOSE_LOGGING - (*m_logger) << time_now_string() << " <== BITFIELD "; - - for (int i = 0; i < int(bits.size()); ++i) - { - if (bits[i]) (*m_logger) << "1"; - else (*m_logger) << "0"; - } - (*m_logger) << "\n"; -#endif - - // if we don't have the metedata, we cannot - // verify the bitfield size - if (t->valid_metadata() - && (bits.size() + 7) / 8 != (m_have_piece.size() + 7) / 8) - { - std::stringstream msg; - msg << "got bitfield with invalid size: " << ((bits.size() + 7) / 8) - << "bytes. expected: " << ((m_have_piece.size() + 7) / 8) - << " bytes"; - disconnect(msg.str().c_str(), 2); - return; - } - - m_bitfield_received = true; - - // if we don't have metadata yet - // just remember the bitmask - // don't update the piecepicker - // (since it doesn't exist yet) - if (!t->ready_for_connections()) - { - m_have_piece = bits; - m_num_pieces = bits.count(); - if (m_peer_info) m_peer_info->seed = (m_num_pieces == int(bits.size())); - return; - } - - TORRENT_ASSERT(t->valid_metadata()); - - int num_pieces = bits.count(); - if (num_pieces == int(m_have_piece.size())) - { -#ifdef TORRENT_VERBOSE_LOGGING - (*m_logger) << " *** THIS IS A SEED ***\n"; -#endif - // if this is a web seed. we don't have a peer_info struct - if (m_peer_info) m_peer_info->seed = true; - m_upload_only = true; - - m_have_piece.set_all(); - m_num_pieces = num_pieces; - t->peer_has_all(); - if (!t->is_finished()) - t->get_policy().peer_is_interesting(*this); - - disconnect_if_redundant(); - - return; - } - - // let the torrent know which pieces the - // peer has - // if we're a seed, we don't keep track of piece availability - bool interesting = false; - if (!t->is_seed()) - { - t->peer_has(bits); - - for (int i = 0; i < (int)m_have_piece.size(); ++i) - { - bool have = bits[i]; - if (have && !m_have_piece[i]) - { - if (!t->have_piece(i) && t->picker().piece_priority(i) != 0) - interesting = true; - } - else if (!have && m_have_piece[i]) - { - // this should probably not be allowed - t->peer_lost(i); - } - } - } - - m_have_piece = bits; - m_num_pieces = num_pieces; - - if (interesting) t->get_policy().peer_is_interesting(*this); - else if (upload_only()) disconnect("upload to upload connections"); - } - - void peer_connection::disconnect_if_redundant() - { - if (!m_ses.settings().close_redundant_connections) return; - - boost::shared_ptr t = m_torrent.lock(); - TORRENT_ASSERT(t); - if (m_upload_only && t->is_finished()) - { - disconnect("seed to seed"); - return; - } - - if (m_upload_only - && !m_interesting - && m_bitfield_received - && t->are_files_checked()) - { - disconnect("uninteresting upload-only peer"); - return; - } - } - - // ----------------------------- - // ---------- REQUEST ---------- - // ----------------------------- - - void peer_connection::incoming_request(peer_request const& r) - { - INVARIANT_CHECK; - - boost::shared_ptr t = m_torrent.lock(); - TORRENT_ASSERT(t); - - // if we haven't received a bitfield, it was - // probably omitted, which is the same as 'have_none' - if (!m_bitfield_received) incoming_have_none(); - if (is_disconnecting()) return; - -#ifndef TORRENT_DISABLE_EXTENSIONS - for (extension_list_t::iterator i = m_extensions.begin() - , end(m_extensions.end()); i != end; ++i) - { - if ((*i)->on_request(r)) return; - } -#endif - if (is_disconnecting()) return; - - if (!t->valid_metadata()) - { - // if we don't have valid metadata yet, - // we shouldn't get a request -#if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_ERROR_LOGGING - (*m_logger) << time_now_string() - << " <== UNEXPECTED_REQUEST [ " - "piece: " << r.piece << " | " - "s: " << r.start << " | " - "l: " << r.length << " | " - "i: " << m_peer_interested << " | " - "t: " << t->torrent_file().piece_size(r.piece) << " | " - "n: " << t->torrent_file().num_pieces() << " ]\n"; - - (*m_logger) << time_now_string() - << " ==> REJECT_PIECE [ " - "piece: " << r.piece << " | " - "s: " << r.start << " | " - "l: " << r.length << " ]\n"; -#endif - write_reject_request(r); - return; - } - - if (int(m_requests.size()) > m_ses.settings().max_allowed_in_request_queue) - { - // don't allow clients to abuse our - // memory consumption. - // ignore requests if the client - // is making too many of them. -#if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_ERROR_LOGGING - (*m_logger) << time_now_string() - << " <== TOO MANY REQUESTS [ " - "piece: " << r.piece << " | " - "s: " << r.start << " | " - "l: " << r.length << " | " - "i: " << m_peer_interested << " | " - "t: " << t->torrent_file().piece_size(r.piece) << " | " - "n: " << t->torrent_file().num_pieces() << " ]\n"; - - (*m_logger) << time_now_string() - << " ==> REJECT_PIECE [ " - "piece: " << r.piece << " | " - "s: " << r.start << " | " - "l: " << r.length << " ]\n"; -#endif - write_reject_request(r); - return; - } - - // make sure this request - // is legal and that the peer - // is not choked - if (r.piece >= 0 - && r.piece < t->torrent_file().num_pieces() - && t->have_piece(r.piece) - && r.start >= 0 - && r.start < t->torrent_file().piece_size(r.piece) - && r.length > 0 - && r.length + r.start <= t->torrent_file().piece_size(r.piece) - && m_peer_interested - && r.length <= t->block_size()) - { -#ifdef TORRENT_VERBOSE_LOGGING - (*m_logger) << time_now_string() - << " <== REQUEST [ piece: " << r.piece << " | s: " << r.start << " | l: " << r.length << " ]\n"; -#endif - // if we have choked the client - // ignore the request - if (m_choked && m_accept_fast.find(r.piece) == m_accept_fast.end()) - { - write_reject_request(r); -#if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_ERROR_LOGGING - (*m_logger) << time_now_string() - << " *** REJECTING REQUEST [ peer choked and piece not in allowed fast set ]\n"; - (*m_logger) << time_now_string() - << " ==> REJECT_PIECE [ " - "piece: " << r.piece << " | " - "s: " << r.start << " | " - "l: " << r.length << " ]\n"; -#endif - } - else - { - m_requests.push_back(r); - m_last_incoming_request = time_now(); - fill_send_buffer(); - } - } - else - { -#if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_ERROR_LOGGING - (*m_logger) << time_now_string() - << " <== INVALID_REQUEST [ " - "piece: " << r.piece << " | " - "s: " << r.start << " | " - "l: " << r.length << " | " - "i: " << m_peer_interested << " | " - "t: " << t->torrent_file().piece_size(r.piece) << " | " - "n: " << t->torrent_file().num_pieces() << " | " - "h: " << t->have_piece(r.piece) << " | " - "block_limit: " << t->block_size() << " ]\n"; - - (*m_logger) << time_now_string() - << " ==> REJECT_PIECE [ " - "piece: " << r.piece << " | " - "s: " << r.start << " | " - "l: " << r.length << " ]\n"; -#endif - - write_reject_request(r); - ++m_num_invalid_requests; - - if (t->alerts().should_post()) - { - t->alerts().post_alert(invalid_request_alert( - t->get_handle(), m_remote, m_peer_id, r)); - } - } - } - - void peer_connection::incoming_piece_fragment() - { - m_last_piece = time_now(); - } - -#ifdef TORRENT_DEBUG - struct check_postcondition - { - check_postcondition(boost::shared_ptr const& t_ - , bool init_check = true): t(t_) { if (init_check) check(); } - - ~check_postcondition() { check(); } - - void check() - { - if (!t->is_seed()) - { - const int blocks_per_piece = static_cast( - t->torrent_file().piece_length() / t->block_size()); - - std::vector const& dl_queue - = t->picker().get_download_queue(); - - for (std::vector::const_iterator i = - dl_queue.begin(); i != dl_queue.end(); ++i) - { - TORRENT_ASSERT(i->finished <= blocks_per_piece); - } - } - } - - shared_ptr t; - }; -#endif - - - // ----------------------------- - // ----------- PIECE ----------- - // ----------------------------- - - void peer_connection::incoming_piece(peer_request const& p, char const* data) - { - char* buffer = m_ses.allocate_disk_buffer(); - if (buffer == 0) - { - disconnect("out of memory"); - return; - } - disk_buffer_holder holder(m_ses, buffer); - std::memcpy(buffer, data, p.length); - incoming_piece(p, holder); - } - - void peer_connection::incoming_piece(peer_request const& p, disk_buffer_holder& data) - { - INVARIANT_CHECK; - - boost::shared_ptr t = m_torrent.lock(); - TORRENT_ASSERT(t); - - TORRENT_ASSERT(!m_disk_recv_buffer); - TORRENT_ASSERT(m_disk_recv_buffer_size == 0); - -#ifdef TORRENT_CORRUPT_DATA - // corrupt all pieces from certain peers - if (m_remote.address().is_v4() - && (m_remote.address().to_v4().to_ulong() & 0xf) == 0) - { - data.get()[0] = ~data.get()[0]; - } -#endif - - // if we haven't received a bitfield, it was - // probably omitted, which is the same as 'have_none' - if (!m_bitfield_received) incoming_have_none(); - if (is_disconnecting()) return; - -#ifndef TORRENT_DISABLE_EXTENSIONS - for (extension_list_t::iterator i = m_extensions.begin() - , end(m_extensions.end()); i != end; ++i) - { - if ((*i)->on_piece(p, data)) return; - } -#endif - if (is_disconnecting()) return; - -#ifdef TORRENT_DEBUG - check_postcondition post_checker_(t); -#if !defined TORRENT_DISABLE_INVARIANT_CHECKS && defined TORRENT_EXPENSIVE_INVARIANT_CHECKS - t->check_invariant(); -#endif -#endif - -#ifdef TORRENT_VERBOSE_LOGGING - (*m_logger) << time_now_string() - << " <== PIECE [ piece: " << p.piece << " | " - "s: " << p.start << " | " - "l: " << p.length << " | " - "ds: " << statistics().download_rate() << " | " - "qs: " << int(m_desired_queue_size) << " ]\n"; -#endif - - if (p.length == 0) - { - if (t->alerts().should_post()) - { - t->alerts().post_alert(peer_error_alert(t->get_handle(), m_remote - , m_peer_id, "peer sent 0 length piece")); - } - return; - } - - if (!verify_piece(p)) - { -#if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_ERROR_LOGGING - (*m_logger) << time_now_string() - << " <== INVALID_PIECE [ piece: " << p.piece << " | " - "start: " << p.start << " | " - "length: " << p.length << " ]\n"; -#endif - disconnect("got invalid piece packet", 2); - return; - } - - // if we're already seeding, don't bother, - // just ignore it - if (t->is_seed()) - { - t->add_redundant_bytes(p.length); - return; - } - - ptime now = time_now(); - - piece_picker& picker = t->picker(); - piece_manager& fs = t->filesystem(); - - std::vector finished_blocks; - piece_block block_finished(p.piece, p.start / t->block_size()); - TORRENT_ASSERT(p.start % t->block_size() == 0); - TORRENT_ASSERT(p.length == t->block_size() - || p.length == t->torrent_file().total_size() % t->block_size()); - - std::deque::iterator b - = std::find_if( - m_download_queue.begin() - , m_download_queue.end() - , has_block(block_finished)); - - if (b == m_download_queue.end()) - { - if (t->alerts().should_post()) - { - t->alerts().post_alert(unwanted_block_alert(t->get_handle(), m_remote - , m_peer_id, block_finished.block_index, block_finished.piece_index)); - } -#if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_ERROR_LOGGING - (*m_logger) << " *** The block we just got was not in the " - "request queue ***\n"; -#endif - t->add_redundant_bytes(p.length); - request_a_block(*t, *this); - send_block_requests(); - return; - } -#ifdef TORRENT_DEBUG - pending_block pending_b = *b; -#endif - - int block_index = b - m_download_queue.begin() - 1; - for (int i = 0; i < block_index; ++i) - { - pending_block& qe = m_download_queue[i]; - -#if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_ERROR_LOGGING - (*m_logger) << time_now_string() - << " *** SKIPPED_PIECE [ piece: " << qe.block.piece_index << " | " - "b: " << qe.block.block_index << " ] ***\n"; -#endif - - ++qe.skipped; - // if the number of times a block is skipped by out of order - // blocks exceeds the size of the outstanding queue, assume that - // the other end dropped the request. - if (qe.skipped > m_desired_queue_size) - { - if (m_ses.m_alerts.should_post()) - m_ses.m_alerts.post_alert(request_dropped_alert(t->get_handle() - , remote(), pid(), qe.block.block_index, qe.block.piece_index)); - picker.abort_download(qe.block); - TORRENT_ASSERT(m_download_queue.begin() + i != b); - m_download_queue.erase(m_download_queue.begin() + i); - --i; - --block_index; - } - } - TORRENT_ASSERT(int(m_download_queue.size()) > block_index + 1); - b = m_download_queue.begin() + (block_index + 1); - TORRENT_ASSERT(b->block == pending_b.block); - - // if the block we got is already finished, then ignore it - if (picker.is_downloaded(block_finished)) - { - t->add_redundant_bytes(p.length); - - m_download_queue.erase(b); - m_timeout_extend = 0; - - if (!m_download_queue.empty()) - m_requested = now; - - request_a_block(*t, *this); - send_block_requests(); - return; - } - - if (total_seconds(now - m_requested) - < m_ses.settings().request_timeout - && m_snubbed) - { - m_snubbed = false; - if (m_ses.m_alerts.should_post()) - { - m_ses.m_alerts.post_alert(peer_unsnubbed_alert(t->get_handle() - , m_remote, m_peer_id)); - } - } - - fs.async_write(p, data, bind(&peer_connection::on_disk_write_complete - , self(), _1, _2, p, t)); - m_outstanding_writing_bytes += p.length; - TORRENT_ASSERT(m_channel_state[download_channel] == peer_info::bw_idle); - m_download_queue.erase(b); - - if (m_outstanding_writing_bytes >= m_ses.settings().max_outstanding_disk_bytes_per_connection - && t->alerts().should_post()) - { - t->alerts().post_alert(performance_alert(t->get_handle() - , performance_alert::outstanding_disk_buffer_limit_reached)); - } - - if (!m_download_queue.empty()) - { - m_timeout_extend = (std::max)(m_timeout_extend - - m_ses.settings().request_timeout, 0); - m_requested += seconds(m_ses.settings().request_timeout); - if (m_requested > now) m_requested = now; - } - else - { - m_timeout_extend = 0; - } - - // did we request this block from any other peers? - bool multi = picker.num_peers(block_finished) > 1; - picker.mark_as_writing(block_finished, peer_info_struct()); - - TORRENT_ASSERT(picker.num_peers(block_finished) == 0); - // if we requested this block from other peers, cancel it now - if (multi) t->cancel_block(block_finished); - - TORRENT_ASSERT(picker.num_peers(block_finished) == 0); - -#if defined TORRENT_DEBUG && !defined TORRENT_DISABLE_INVARIANT_CHECKS \ - && defined TORRENT_EXPENSIVE_INVARIANT_CHECKS - t->check_invariant(); -#endif - request_a_block(*t, *this); - send_block_requests(); - } - - void peer_connection::on_disk_write_complete(int ret, disk_io_job const& j - , peer_request p, boost::shared_ptr t) - { - session_impl::mutex_t::scoped_lock l(m_ses.m_mutex); - - INVARIANT_CHECK; - - m_outstanding_writing_bytes -= p.length; - TORRENT_ASSERT(m_outstanding_writing_bytes >= 0); - -#if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING) -// (*m_ses.m_logger) << time_now_string() << " *** DISK_WRITE_COMPLETE [ p: " -// << p.piece << " o: " << p.start << " ]\n"; -#endif - // in case the outstanding bytes just dropped down - // to allow to receive more data - setup_receive(); - - piece_block block_finished(p.piece, p.start / t->block_size()); - - if (ret == -1 || !t) - { - if (t->has_picker()) t->picker().write_failed(block_finished); - - if (!t) - { - disconnect(j.str.c_str()); - return; - } - - if (t->alerts().should_post()) - t->alerts().post_alert(file_error_alert(j.error_file, t->get_handle(), j.str)); - t->set_error(j.str); - t->pause(); - return; - } - - if (t->is_seed()) return; - - piece_picker& picker = t->picker(); - - TORRENT_ASSERT(p.piece == j.piece); - TORRENT_ASSERT(p.start == j.offset); - TORRENT_ASSERT(picker.num_peers(block_finished) == 0); - picker.mark_as_finished(block_finished, peer_info_struct()); - if (t->alerts().should_post()) - { - t->alerts().post_alert(block_finished_alert(t->get_handle(), - remote(), pid(), block_finished.block_index, block_finished.piece_index)); - } - - // did we just finish the piece? - if (picker.is_piece_finished(p.piece)) - { -#ifdef TORRENT_DEBUG - check_postcondition post_checker2_(t, false); -#endif - t->async_verify_piece(p.piece, bind(&torrent::piece_finished, t - , p.piece, _1)); - } - - if (!t->is_seed() && !m_torrent.expired()) - { - // this is a free function defined in policy.cpp - request_a_block(*t, *this); - send_block_requests(); - } - - } - - // ----------------------------- - // ---------- CANCEL ----------- - // ----------------------------- - - void peer_connection::incoming_cancel(peer_request const& r) - { - INVARIANT_CHECK; - -#ifndef TORRENT_DISABLE_EXTENSIONS - for (extension_list_t::iterator i = m_extensions.begin() - , end(m_extensions.end()); i != end; ++i) - { - if ((*i)->on_cancel(r)) return; - } -#endif - if (is_disconnecting()) return; - -#ifdef TORRENT_VERBOSE_LOGGING - (*m_logger) << time_now_string() - << " <== CANCEL [ piece: " << r.piece << " | s: " << r.start << " | l: " << r.length << " ]\n"; -#endif - - std::deque::iterator i - = std::find(m_requests.begin(), m_requests.end(), r); - - if (i != m_requests.end()) - { - m_requests.erase(i); -#ifdef TORRENT_VERBOSE_LOGGING - (*m_logger) << time_now_string() - << " ==> REJECT_PIECE [ " - "piece: " << r.piece << " | " - "s: " << r.start << " | " - "l: " << r.length << " ]\n"; -#endif - write_reject_request(r); - } - else - { -#if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_ERROR_LOGGING - (*m_logger) << time_now_string() << " *** GOT CANCEL NOT IN THE QUEUE\n"; -#endif - } - } - - // ----------------------------- - // --------- DHT PORT ---------- - // ----------------------------- - - void peer_connection::incoming_dht_port(int listen_port) - { - INVARIANT_CHECK; - -#ifdef TORRENT_VERBOSE_LOGGING - (*m_logger) << time_now_string() - << " <== DHT_PORT [ p: " << listen_port << " ]\n"; -#endif -#ifndef TORRENT_DISABLE_DHT - m_ses.add_dht_node(udp::endpoint( - m_remote.address(), listen_port)); -#endif - } - - // ----------------------------- - // --------- HAVE ALL ---------- - // ----------------------------- - - void peer_connection::incoming_have_all() - { - INVARIANT_CHECK; - - boost::shared_ptr t = m_torrent.lock(); - TORRENT_ASSERT(t); - -#ifdef TORRENT_VERBOSE_LOGGING - (*m_logger) << time_now_string() << " <== HAVE_ALL\n"; -#endif - -#ifndef TORRENT_DISABLE_EXTENSIONS - for (extension_list_t::iterator i = m_extensions.begin() - , end(m_extensions.end()); i != end; ++i) - { - if ((*i)->on_have_all()) return; - } -#endif - if (is_disconnecting()) return; - - m_have_all = true; - - if (m_peer_info) m_peer_info->seed = true; - m_upload_only = true; - m_bitfield_received = true; - -#ifdef TORRENT_VERBOSE_LOGGING - (*m_logger) << " *** THIS IS A SEED ***\n"; -#endif - - // if we don't have metadata yet - // just remember the bitmask - // don't update the piecepicker - // (since it doesn't exist yet) - if (!t->ready_for_connections()) - { - // assume seeds are interesting when we - // don't even have the metadata - t->get_policy().peer_is_interesting(*this); - - disconnect_if_redundant(); - // TODO: this might need something more - // so that once we have the metadata - // we can construct a full bitfield - return; - } - - TORRENT_ASSERT(!m_have_piece.empty()); - m_have_piece.set_all(); - m_num_pieces = m_have_piece.size(); - - t->peer_has_all(); - - // if we're finished, we're not interested - if (t->is_finished()) send_not_interested(); - else t->get_policy().peer_is_interesting(*this); - - disconnect_if_redundant(); - } - - // ----------------------------- - // --------- HAVE NONE --------- - // ----------------------------- - - void peer_connection::incoming_have_none() - { - INVARIANT_CHECK; - -#ifdef TORRENT_VERBOSE_LOGGING - (*m_logger) << time_now_string() << " <== HAVE_NONE\n"; -#endif - - boost::shared_ptr t = m_torrent.lock(); - TORRENT_ASSERT(t); - -#ifndef TORRENT_DISABLE_EXTENSIONS - for (extension_list_t::iterator i = m_extensions.begin() - , end(m_extensions.end()); i != end; ++i) - { - if ((*i)->on_have_none()) return; - } -#endif - if (is_disconnecting()) return; - if (m_peer_info) m_peer_info->seed = false; - m_bitfield_received = true; - - // we're never interested in a peer that doesn't have anything - send_not_interested(); - - TORRENT_ASSERT(!m_have_piece.empty() || !t->ready_for_connections()); - disconnect_if_redundant(); - } - - // ----------------------------- - // ------- ALLOWED FAST -------- - // ----------------------------- - - void peer_connection::incoming_allowed_fast(int index) - { - INVARIANT_CHECK; - - boost::shared_ptr t = m_torrent.lock(); - TORRENT_ASSERT(t); - -#ifdef TORRENT_VERBOSE_LOGGING - (*m_logger) << time_now_string() << " <== ALLOWED_FAST [ " << index << " ]\n"; -#endif - -#ifndef TORRENT_DISABLE_EXTENSIONS - for (extension_list_t::iterator i = m_extensions.begin() - , end(m_extensions.end()); i != end; ++i) - { - if ((*i)->on_allowed_fast(index)) return; - } -#endif - if (is_disconnecting()) return; - - if (t->valid_metadata()) - { - if (index < 0 || index >= int(m_have_piece.size())) - { -#if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_ERROR_LOGGING - (*m_logger) << time_now_string() << " <== INVALID_ALLOWED_FAST [ " << index << " | s: " - << int(m_have_piece.size()) << " ]\n"; -#endif - return; - } - - // if we already have the piece, we can - // ignore this message - if (t->have_piece(index)) - return; - } - - m_allowed_fast.push_back(index); - - // if the peer has the piece and we want - // to download it, request it - if (int(m_have_piece.size()) > index - && m_have_piece[index] - && t->valid_metadata() - && t->has_picker() - && t->picker().piece_priority(index) > 0) - { - t->get_policy().peer_is_interesting(*this); - } - } - - std::vector const& peer_connection::allowed_fast() - { - boost::shared_ptr t = m_torrent.lock(); - TORRENT_ASSERT(t); - - m_allowed_fast.erase(std::remove_if(m_allowed_fast.begin() - , m_allowed_fast.end(), bind(&torrent::have_piece, t, _1)) - , m_allowed_fast.end()); - - // TODO: sort the allowed fast set in priority order - return m_allowed_fast; - } - - void peer_connection::add_request(piece_block const& block) - { -// INVARIANT_CHECK; - - boost::shared_ptr t = m_torrent.lock(); - TORRENT_ASSERT(t); - - TORRENT_ASSERT(t->valid_metadata()); - TORRENT_ASSERT(block.piece_index >= 0); - TORRENT_ASSERT(block.piece_index < t->torrent_file().num_pieces()); - TORRENT_ASSERT(block.block_index >= 0); - TORRENT_ASSERT(block.block_index < t->torrent_file().piece_size(block.piece_index)); - TORRENT_ASSERT(!t->picker().is_requested(block) || (t->picker().num_peers(block) > 0)); - TORRENT_ASSERT(!t->have_piece(block.piece_index)); - TORRENT_ASSERT(std::find_if(m_download_queue.begin(), m_download_queue.end() - , has_block(block)) == m_download_queue.end()); - TORRENT_ASSERT(std::find(m_request_queue.begin(), m_request_queue.end() - , block) == m_request_queue.end()); - - piece_picker::piece_state_t state; - peer_speed_t speed = peer_speed(); - char const* speedmsg = 0; - if (speed == fast) - { - speedmsg = "fast"; - state = piece_picker::fast; - } - else if (speed == medium) - { - speedmsg = "medium"; - state = piece_picker::medium; - } - else - { - speedmsg = "slow"; - state = piece_picker::slow; - } - - if (!t->picker().mark_as_downloading(block, peer_info_struct(), state)) - return; - - if (t->alerts().should_post()) - { - t->alerts().post_alert(block_downloading_alert(t->get_handle(), - remote(), pid(), speedmsg, block.block_index, block.piece_index)); - } - - m_request_queue.push_back(block); - } - - void peer_connection::cancel_request(piece_block const& block) - { - INVARIANT_CHECK; - - boost::shared_ptr t = m_torrent.lock(); - // this peer might be disconnecting - if (!t) return; - - TORRENT_ASSERT(t->valid_metadata()); - - TORRENT_ASSERT(block.piece_index >= 0); - TORRENT_ASSERT(block.piece_index < t->torrent_file().num_pieces()); - TORRENT_ASSERT(block.block_index >= 0); - TORRENT_ASSERT(block.block_index < t->torrent_file().piece_size(block.piece_index)); - - // if all the peers that requested this block has been - // cancelled, then just ignore the cancel. - if (!t->picker().is_requested(block)) return; - - std::deque::iterator it - = std::find_if(m_download_queue.begin(), m_download_queue.end(), has_block(block)); - if (it == m_download_queue.end()) - { - std::deque::iterator rit = std::find(m_request_queue.begin() - , m_request_queue.end(), block); - - // when a multi block is received, it is cancelled - // from all peers, so if this one hasn't requested - // the block, just ignore to cancel it. - if (rit == m_request_queue.end()) return; - - t->picker().abort_download(block); - m_request_queue.erase(rit); - // since we found it in the request queue, it means it hasn't been - // sent yet, so we don't have to send a cancel. - return; - } - - int block_offset = block.block_index * t->block_size(); - int block_size - = (std::min)(t->torrent_file().piece_size(block.piece_index)-block_offset, - t->block_size()); - TORRENT_ASSERT(block_size > 0); - TORRENT_ASSERT(block_size <= t->block_size()); - - peer_request r; - r.piece = block.piece_index; - r.start = block_offset; - r.length = block_size; - -#ifdef TORRENT_VERBOSE_LOGGING - (*m_logger) << time_now_string() - << " ==> CANCEL [ piece: " << block.piece_index << " | s: " - << block_offset << " | l: " << block_size << " | " << block.block_index << " ]\n"; -#endif - write_cancel(r); - } - - void peer_connection::send_choke() - { - INVARIANT_CHECK; - - TORRENT_ASSERT(!m_peer_info || !m_peer_info->optimistically_unchoked); - - if (m_choked) return; - write_choke(); - m_choked = true; - -#ifdef TORRENT_VERBOSE_LOGGING - (*m_logger) << time_now_string() << " ==> CHOKE\n"; -#endif -#ifdef TORRENT_DEBUG - m_last_choke = time_now(); -#endif - m_num_invalid_requests = 0; - - // reject the requests we have in the queue - // except the allowed fast pieces - for (std::deque::iterator i = m_requests.begin(); - i != m_requests.end();) - { - if (m_accept_fast.count(i->piece)) - { - ++i; - continue; - } - - peer_request const& r = *i; - write_reject_request(r); - -#ifdef TORRENT_VERBOSE_LOGGING - (*m_logger) << time_now_string() - << " ==> REJECT_PIECE [ " - "piece: " << r.piece << " | " - "s: " << r.start << " | " - "l: " << r.length << " ]\n"; -#endif - i = m_requests.erase(i); - } - } - - bool peer_connection::send_unchoke() - { - INVARIANT_CHECK; - - if (!m_choked) return false; - boost::shared_ptr t = m_torrent.lock(); - if (!t->ready_for_connections()) return false; - m_last_unchoke = time_now(); - write_unchoke(); - m_choked = false; - -#ifdef TORRENT_VERBOSE_LOGGING - (*m_logger) << time_now_string() << " ==> UNCHOKE\n"; -#endif - return true; - } - - void peer_connection::send_interested() - { - if (m_interesting) return; - boost::shared_ptr t = m_torrent.lock(); - if (!t->ready_for_connections()) return; - m_interesting = true; - write_interested(); - -#ifdef TORRENT_VERBOSE_LOGGING - (*m_logger) << time_now_string() << " ==> INTERESTED\n"; -#endif - } - - void peer_connection::send_not_interested() - { - if (!m_interesting) return; - boost::shared_ptr t = m_torrent.lock(); - if (!t->ready_for_connections()) return; - m_interesting = false; - write_not_interested(); - - m_became_uninteresting = time_now(); - -#ifdef TORRENT_VERBOSE_LOGGING - (*m_logger) << time_now_string() << " ==> NOT_INTERESTED\n"; -#endif - disconnect_if_redundant(); - } - - void peer_connection::send_block_requests() - { - INVARIANT_CHECK; - - boost::shared_ptr t = m_torrent.lock(); - TORRENT_ASSERT(t); - - if ((int)m_download_queue.size() >= m_desired_queue_size) return; - - bool empty_download_queue = m_download_queue.empty(); - - while (!m_request_queue.empty() - && (int)m_download_queue.size() < m_desired_queue_size) - { - piece_block block = m_request_queue.front(); - - int block_offset = block.block_index * t->block_size(); - int block_size = (std::min)(t->torrent_file().piece_size( - block.piece_index) - block_offset, t->block_size()); - TORRENT_ASSERT(block_size > 0); - TORRENT_ASSERT(block_size <= t->block_size()); - - peer_request r; - r.piece = block.piece_index; - r.start = block_offset; - r.length = block_size; - - m_request_queue.pop_front(); - if (t->is_seed()) continue; - // this can happen if a block times out, is re-requested and - // then arrives "unexpectedly" - if (t->picker().is_finished(block) || t->picker().is_downloaded(block)) - continue; - - m_download_queue.push_back(block); -/* -#ifdef TORRENT_VERBOSE_LOGGING - (*m_logger) << time_now_string() - << " *** REQUEST-QUEUE** [ " - "piece: " << block.piece_index << " | " - "block: " << block.block_index << " ]\n"; -#endif -*/ - // if we are requesting large blocks, merge the smaller - // blocks that are in the same piece into larger requests - if (m_request_large_blocks) - { - int blocks_per_piece = t->torrent_file().piece_length() / t->block_size(); - - while (!m_request_queue.empty()) - { - // check to see if this block is connected to the previous one - // if it is, merge them, otherwise, break this merge loop - piece_block const& front = m_request_queue.front(); - if (front.piece_index * blocks_per_piece + front.block_index - != block.piece_index * blocks_per_piece + block.block_index + 1) - break; - block = m_request_queue.front(); - m_request_queue.pop_front(); - m_download_queue.push_back(block); - -#ifdef TORRENT_VERBOSE_LOGGING - (*m_logger) << time_now_string() - << " *** MERGING REQUEST ** [ " - "piece: " << block.piece_index << " | " - "block: " << block.block_index << " ]\n"; -#endif - - block_offset = block.block_index * t->block_size(); - block_size = (std::min)(t->torrent_file().piece_size( - block.piece_index) - block_offset, t->block_size()); - TORRENT_ASSERT(block_size > 0); - TORRENT_ASSERT(block_size <= t->block_size()); - - r.length += block_size; - } - } - - TORRENT_ASSERT(verify_piece(r)); - -#ifndef TORRENT_DISABLE_EXTENSIONS - bool handled = false; - for (extension_list_t::iterator i = m_extensions.begin() - , end(m_extensions.end()); i != end; ++i) - { - if (handled = (*i)->write_request(r)) break; - } - if (is_disconnecting()) return; - if (!handled) - { - write_request(r); - m_last_request = time_now(); - } -#else - write_request(r); - m_last_request = time_now(); -#endif - -#ifdef TORRENT_VERBOSE_LOGGING - (*m_logger) << time_now_string() - << " ==> REQUEST [ " - "piece: " << r.piece << " | " - "s: " << r.start << " | " - "l: " << r.length << " | " - "ds: " << statistics().download_rate() << " B/s | " - "qs: " << int(m_desired_queue_size) << " " - "blk: " << (m_request_large_blocks?"large":"single") << " ]\n"; -#endif - } - m_last_piece = time_now(); - - if (!m_download_queue.empty() - && empty_download_queue) - { - // This means we just added a request to this connection - m_requested = time_now(); - } - } - - void peer_connection::timed_out() - { - TORRENT_ASSERT(m_connecting); -#if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_LOGGING || defined TORRENT_ERROR_LOGGING - error_code ec; - (*m_ses.m_logger) << time_now_string() << " CONNECTION TIMED OUT: " << m_remote.address().to_string(ec) - << "\n"; -#endif - disconnect("timed out: connect", 1); - } - - // the error argument defaults to 0, which means deliberate disconnect - // 1 means unexpected disconnect/error - // 2 protocol error (client sent something invalid) - void peer_connection::disconnect(char const* message, int error) - { - session_impl::mutex_t::scoped_lock l(m_ses.m_mutex); - -#ifdef TORRENT_DEBUG - m_disconnect_started = true; -#endif - -#if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_ERROR_LOGGING - switch (error) - { - case 0: - (*m_logger) << "*** CONNECTION CLOSED " << message << "\n"; - break; - case 1: - (*m_logger) << "*** CONNECTION FAILED " << message << "\n"; - break; - case 2: - (*m_logger) << "*** PEER ERROR " << message << "\n"; - break; - } -#endif - // we cannot do this in a constructor - TORRENT_ASSERT(m_in_constructor == false); - if (error > 0) m_failed = true; - if (m_disconnecting) return; - boost::intrusive_ptr me(this); - - INVARIANT_CHECK; - - if (m_connecting && m_connection_ticket >= 0) - { - m_ses.m_half_open.done(m_connection_ticket); - m_connection_ticket = -1; - } - - boost::shared_ptr t = m_torrent.lock(); - torrent_handle handle; - if (t) handle = t->get_handle(); - - if (message) - { - if (error > 1 && m_ses.m_alerts.should_post()) - { - m_ses.m_alerts.post_alert( - peer_error_alert(handle, remote(), pid(), message)); - } - else if (error <= 1 && m_ses.m_alerts.should_post()) - { - m_ses.m_alerts.post_alert( - peer_disconnected_alert(handle, remote(), pid(), message)); - } - } - - if (t) - { - // make sure we keep all the stats! - calc_ip_overhead(); - t->add_stats(statistics()); - - if (t->has_picker()) - { - piece_picker& picker = t->picker(); - - while (!m_download_queue.empty()) - { - picker.abort_download(m_download_queue.back().block); - m_download_queue.pop_back(); - } - while (!m_request_queue.empty()) - { - picker.abort_download(m_request_queue.back()); - m_request_queue.pop_back(); - } - } - - t->remove_peer(this); - m_torrent.reset(); - } - -#if defined TORRENT_DEBUG && defined TORRENT_EXPENSIVE_INVARIANT_CHECKS - // since this connection doesn't have a torrent reference - // no torrent should have a reference to this connection either - for (aux::session_impl::torrent_map::const_iterator i = m_ses.m_torrents.begin() - , end(m_ses.m_torrents.end()); i != end; ++i) - TORRENT_ASSERT(!i->second->has_peer(this)); -#endif - - m_disconnecting = true; - error_code ec; - m_socket->close(ec); - m_ses.close_connection(this, message); - - // we should only disconnect while we still have - // at least one reference left to the connection - TORRENT_ASSERT(refcount() > 0); - } - - void peer_connection::set_upload_limit(int limit) - { - TORRENT_ASSERT(limit >= -1); - if (limit == -1) limit = (std::numeric_limits::max)(); - if (limit < 10) limit = 10; - m_upload_limit = limit; - m_bandwidth_limit[upload_channel].throttle(m_upload_limit); - } - - void peer_connection::set_download_limit(int limit) - { - TORRENT_ASSERT(limit >= -1); - if (limit == -1) limit = (std::numeric_limits::max)(); - if (limit < 10) limit = 10; - m_download_limit = limit; - m_bandwidth_limit[download_channel].throttle(m_download_limit); - } - - size_type peer_connection::share_diff() const - { - INVARIANT_CHECK; - - boost::shared_ptr t = m_torrent.lock(); - TORRENT_ASSERT(t); - - float ratio = t->ratio(); - - // if we have an infinite ratio, just say we have downloaded - // much more than we have uploaded. And we'll keep uploading. - if (ratio == 0.f) - return (std::numeric_limits::max)(); - - return m_free_upload - + static_cast(m_statistics.total_payload_download() * ratio) - - m_statistics.total_payload_upload(); - } - - // defined in upnp.cpp - bool is_local(address const& a); - - bool peer_connection::on_local_network() const - { - if (libtorrent::is_local(m_remote.address()) - || is_loopback(m_remote.address())) return true; - return false; - } - - void peer_connection::get_peer_info(peer_info& p) const - { - TORRENT_ASSERT(!associated_torrent().expired()); - - ptime now = time_now(); - - p.download_rate_peak = m_download_rate_peak; - p.upload_rate_peak = m_upload_rate_peak; - p.rtt = m_rtt; - p.down_speed = statistics().download_rate(); - p.up_speed = statistics().upload_rate(); - p.payload_down_speed = statistics().download_payload_rate(); - p.payload_up_speed = statistics().upload_payload_rate(); - p.pid = pid(); - p.ip = remote(); - p.pending_disk_bytes = m_outstanding_writing_bytes; - p.send_quota = m_bandwidth_limit[upload_channel].quota_left(); - p.receive_quota = m_bandwidth_limit[download_channel].quota_left(); - if (m_download_queue.empty()) p.request_timeout = -1; - else p.request_timeout = total_seconds(m_requested - now) + m_ses.settings().request_timeout - + m_timeout_extend; -#ifndef TORRENT_DISABLE_GEO_IP - p.inet_as_name = m_inet_as_name; -#endif - -#ifndef TORRENT_DISABLE_RESOLVE_COUNTRIES - p.country[0] = m_country[0]; - p.country[1] = m_country[1]; -#endif - - p.total_download = statistics().total_payload_download(); - p.total_upload = statistics().total_payload_upload(); - - if (m_bandwidth_limit[upload_channel].throttle() == bandwidth_limit::inf) - p.upload_limit = -1; - else - p.upload_limit = m_bandwidth_limit[upload_channel].throttle(); - - if (m_bandwidth_limit[download_channel].throttle() == bandwidth_limit::inf) - p.download_limit = -1; - else - p.download_limit = m_bandwidth_limit[download_channel].throttle(); - - p.load_balancing = total_free_upload(); - - p.download_queue_length = int(download_queue().size() + m_request_queue.size()); - p.requests_in_buffer = int(m_requests_in_buffer.size()); - p.target_dl_queue_length = int(desired_queue_size()); - p.upload_queue_length = int(upload_queue().size()); - - if (boost::optional ret = downloading_piece_progress()) - { - p.downloading_piece_index = ret->piece_index; - p.downloading_block_index = ret->block_index; - p.downloading_progress = ret->bytes_downloaded; - p.downloading_total = ret->full_block_bytes; - } - else - { - p.downloading_piece_index = -1; - p.downloading_block_index = -1; - p.downloading_progress = 0; - p.downloading_total = 0; - } - - p.pieces = get_bitfield(); - p.last_request = now - m_last_request; - p.last_active = now - (std::max)(m_last_sent, m_last_receive); - - // this will set the flags so that we can update them later - p.flags = 0; - get_specific_peer_info(p); - - p.flags |= is_seed() ? peer_info::seed : 0; - p.flags |= m_snubbed ? peer_info::snubbed : 0; - p.flags |= m_upload_only ? peer_info::upload_only : 0; - if (peer_info_struct()) - { - policy::peer* pi = peer_info_struct(); - p.source = pi->source; - p.failcount = pi->failcount; - p.num_hashfails = pi->hashfails; - p.flags |= pi->on_parole ? peer_info::on_parole : 0; - p.flags |= pi->optimistically_unchoked ? peer_info::optimistic_unchoke : 0; -#ifndef TORRENT_DISABLE_GEO_IP - p.inet_as = pi->inet_as->first; -#endif - } - else - { - p.source = 0; - p.failcount = 0; - p.num_hashfails = 0; - p.remote_dl_rate = 0; -#ifndef TORRENT_DISABLE_GEO_IP - p.inet_as = 0xffff; -#endif - } - - p.remote_dl_rate = m_remote_dl_rate; - p.send_buffer_size = m_send_buffer.capacity(); - p.used_send_buffer = m_send_buffer.size(); - p.receive_buffer_size = m_recv_buffer.capacity() + m_disk_recv_buffer_size; - p.used_receive_buffer = m_recv_pos; - p.write_state = m_channel_state[upload_channel]; - p.read_state = m_channel_state[download_channel]; - - p.progress = (float)p.pieces.count() / (float)p.pieces.size(); - } - - // allocates a disk buffer of size 'disk_buffer_size' and replaces the - // end of the current receive buffer with it. i.e. the receive pos - // must be <= packet_size - disk_buffer_size - // the disk buffer can be accessed through release_disk_receive_buffer() - // when it is queried, the responsibility to free it is transferred - // to the caller - bool peer_connection::allocate_disk_receive_buffer(int disk_buffer_size) - { - INVARIANT_CHECK; - - TORRENT_ASSERT(m_packet_size > 0); - TORRENT_ASSERT(m_recv_pos <= m_packet_size - disk_buffer_size); - TORRENT_ASSERT(!m_disk_recv_buffer); - TORRENT_ASSERT(disk_buffer_size <= 16 * 1024); - - if (disk_buffer_size == 0) return true; - - if (disk_buffer_size > 16 * 1024) - { - disconnect("invalid piece size", 2); - return false; - } - - m_disk_recv_buffer.reset(m_ses.allocate_disk_buffer()); - if (!m_disk_recv_buffer) - { - disconnect("out of memory"); - return false; - } - m_disk_recv_buffer_size = disk_buffer_size; - return true; - } - - char* peer_connection::release_disk_receive_buffer() - { - m_disk_recv_buffer_size = 0; - return m_disk_recv_buffer.release(); - } - - void peer_connection::cut_receive_buffer(int size, int packet_size) - { - INVARIANT_CHECK; - - TORRENT_ASSERT(packet_size > 0); - TORRENT_ASSERT(int(m_recv_buffer.size()) >= size); - TORRENT_ASSERT(int(m_recv_buffer.size()) >= m_recv_pos); - TORRENT_ASSERT(m_recv_pos >= size); - - if (size > 0) - std::memmove(&m_recv_buffer[0], &m_recv_buffer[0] + size, m_recv_pos - size); - - m_recv_pos -= size; - -#ifdef TORRENT_DEBUG - std::fill(m_recv_buffer.begin() + m_recv_pos, m_recv_buffer.end(), 0); -#endif - - m_packet_size = packet_size; - } - - void peer_connection::calc_ip_overhead() - { - m_statistics.calc_ip_overhead(); - } - - void peer_connection::second_tick(float tick_interval) - { - ptime now(time_now()); - boost::intrusive_ptr me(self()); - - // the invariant check must be run before me is destructed - // in case the peer got disconnected - INVARIANT_CHECK; - - boost::shared_ptr t = m_torrent.lock(); - if (!t || m_disconnecting) - { - m_ses.m_half_open.done(m_connection_ticket); - m_connecting = false; - disconnect("torrent aborted"); - return; - } - - on_tick(); - -#ifndef TORRENT_DISABLE_EXTENSIONS - for (extension_list_t::iterator i = m_extensions.begin() - , end(m_extensions.end()); i != end; ++i) - { - (*i)->tick(); - } - if (is_disconnecting()) return; -#endif - - // if the peer hasn't said a thing for a certain - // time, it is considered to have timed out - time_duration d; - d = now - m_last_receive; - if (d > seconds(m_timeout) && !m_connecting) - { -#if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_ERROR_LOGGING - (*m_logger) << time_now_string() << " *** LAST ACTIVITY [ " - << total_seconds(d) << " seconds ago ] ***\n"; -#endif - disconnect("timed out: inactivity"); - return; - } - - // do not stall waiting for a handshake - if (!m_connecting - && in_handshake() - && d > seconds(m_ses.settings().handshake_timeout)) - { -#if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_ERROR_LOGGING - (*m_logger) << time_now_string() << " *** NO HANDSHAKE [ waited " - << total_seconds(d) << " seconds ] ***\n"; -#endif - disconnect("timed out: no handshake"); - return; - } - - // disconnect peers that we unchoked, but - // they didn't send a request within 20 seconds. - // but only if we're a seed - d = now - (std::max)(m_last_unchoke, m_last_incoming_request); - if (!m_connecting - && m_requests.empty() - && !m_choked - && m_peer_interested - && t && t->is_finished() - && d > seconds(20)) - { -#if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_ERROR_LOGGING - (*m_logger) << time_now_string() << " *** NO REQUEST [ t: " - << total_seconds(d) << " ] ***\n"; -#endif - disconnect("timed out: no request when unchoked"); - return; - } - - // if the peer hasn't become interested and we haven't - // become interested in the peer for 10 minutes, it - // has also timed out. - time_duration d1; - time_duration d2; - d1 = now - m_became_uninterested; - d2 = now - m_became_uninteresting; - time_duration time_limit = seconds( - m_ses.settings().inactivity_timeout); - - // don't bother disconnect peers we haven't been interested - // in (and that hasn't been interested in us) for a while - // unless we have used up all our connection slots - if (!m_interesting - && !m_peer_interested - && d1 > time_limit - && d2 > time_limit - && (m_ses.num_connections() >= m_ses.max_connections() - || (t && t->num_peers() >= t->max_connections()))) - { -#if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_ERROR_LOGGING - (*m_logger) << time_now_string() << " *** MUTUAL NO INTEREST [ " - "t1: " << total_seconds(d1) << " | " - "t2: " << total_seconds(d2) << " ] ***\n"; -#endif - disconnect("timed out: no interest"); - return; - } - - if (!m_download_queue.empty() - && now > m_requested + seconds(m_ses.settings().request_timeout - + m_timeout_extend)) - { - snub_peer(); - } - - // if we haven't sent something in too long, send a keep-alive - keep_alive(); - - m_ignore_bandwidth_limits = m_ses.settings().ignore_limits_on_local_network - && on_local_network(); - - m_statistics.second_tick(tick_interval); - - if (m_statistics.upload_payload_rate() > m_upload_rate_peak) - { - m_upload_rate_peak = m_statistics.upload_payload_rate(); - } - if (m_statistics.download_payload_rate() > m_download_rate_peak) - { - m_download_rate_peak = m_statistics.download_payload_rate(); -#ifndef TORRENT_DISABLE_GEO_IP - if (peer_info_struct()) - { - std::pair* as_stats = peer_info_struct()->inet_as; - if (as_stats && as_stats->second < m_download_rate_peak) - as_stats->second = m_download_rate_peak; - } -#endif - } - if (is_disconnecting()) return; - - if (!t->ready_for_connections()) return; - - // calculate the desired download queue size - const float queue_time = m_ses.settings().request_queue_time; - // (if the latency is more than this, the download will stall) - // so, the queue size is queue_time * down_rate / 16 kiB - // (16 kB is the size of each request) - // the minimum number of requests is 2 and the maximum is 48 - // the block size doesn't have to be 16. So we first query the - // torrent for it - const int block_size = t->block_size(); - TORRENT_ASSERT(block_size > 0); - - if (m_snubbed) - { - m_desired_queue_size = 1; - } - else - { - m_desired_queue_size = static_cast(queue_time - * statistics().download_rate() / block_size); - if (m_desired_queue_size > m_max_out_request_queue) - m_desired_queue_size = m_max_out_request_queue; - if (m_desired_queue_size < min_request_queue) - m_desired_queue_size = min_request_queue; - - if (m_desired_queue_size == m_max_out_request_queue - && t->alerts().should_post()) - { - t->alerts().post_alert(performance_alert(t->get_handle() - , performance_alert::outstanding_request_limit_reached)); - } - } - - if (!m_download_queue.empty() - && now - m_last_piece > seconds(m_ses.settings().piece_timeout - + m_timeout_extend)) - { - // this peer isn't sending the pieces we've - // requested (this has been observed by BitComet) - // in this case we'll clear our download queue and - // re-request the blocks. -#if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_ERROR_LOGGING - (*m_logger) << time_now_string() - << " *** PIECE_REQUESTS TIMED OUT [ " << (int)m_download_queue.size() - << " " << total_seconds(now - m_last_piece) << "] ***\n"; -#endif - - snub_peer(); - } - - // If the client sends more data - // we send it data faster, otherwise, slower. - // It will also depend on how much data the - // client has sent us. This is the mean to - // maintain the share ratio given by m_ratio - // with all peers. - - if (t->is_finished() || is_choked() || t->ratio() == 0.0f) - { - // if we have downloaded more than one piece more - // than we have uploaded OR if we are a seed - // have an unlimited upload rate - m_bandwidth_limit[upload_channel].throttle(m_upload_limit); - } - else - { - size_type bias = 0x10000 + 2 * t->block_size() + m_free_upload; - - double break_even_time = 15; // seconds. - size_type have_uploaded = m_statistics.total_payload_upload(); - size_type have_downloaded = m_statistics.total_payload_download(); - double download_speed = m_statistics.download_rate(); - - size_type soon_downloaded = - have_downloaded + (size_type)(download_speed * break_even_time*1.5); - - if (t->ratio() != 1.f) - soon_downloaded = (size_type)(soon_downloaded*(double)t->ratio()); - - double upload_speed_limit = (std::min)((soon_downloaded - have_uploaded - + bias) / break_even_time, double(m_upload_limit)); - - upload_speed_limit = (std::min)(upload_speed_limit, - (double)(std::numeric_limits::max)()); - - m_bandwidth_limit[upload_channel].throttle( - (std::min)((std::max)((int)upload_speed_limit, 20) - , m_upload_limit)); - } - - // update once every minute - if (now - m_remote_dl_update >= seconds(60)) - { - float factor = 0.6666666666667f; - - if (m_remote_dl_rate == 0) factor = 0.0f; - - m_remote_dl_rate = int((m_remote_dl_rate * factor) + - ((m_remote_bytes_dled * (1.0f-factor)) / 60.f)); - - m_remote_bytes_dled = 0; - m_remote_dl_update = now; - } - - fill_send_buffer(); - } - - void peer_connection::snub_peer() - { - INVARIANT_CHECK; - - boost::shared_ptr t = m_torrent.lock(); - TORRENT_ASSERT(t); - - if (!m_snubbed) - { - m_snubbed = true; - if (m_ses.m_alerts.should_post()) - { - m_ses.m_alerts.post_alert(peer_snubbed_alert(t->get_handle() - , m_remote, m_peer_id)); - } - } - m_desired_queue_size = 1; - - if (on_parole()) - { - m_timeout_extend += m_ses.settings().request_timeout; - return; - } - if (!t->has_picker()) return; - piece_picker& picker = t->picker(); - - piece_block r(-1, -1); - // time out the last request in the queue - if (!m_request_queue.empty()) - { - r = m_request_queue.back(); - m_request_queue.pop_back(); - } - else - { - TORRENT_ASSERT(!m_download_queue.empty()); - r = m_download_queue.back().block; - - // only time out a request if it blocks the piece - // from being completed (i.e. no free blocks to - // request from it) - piece_picker::downloading_piece p; - picker.piece_info(r.piece_index, p); - int free_blocks = picker.blocks_in_piece(r.piece_index) - - p.finished - p.writing - p.requested; - if (free_blocks > 0) - { - m_timeout_extend += m_ses.settings().request_timeout; - return; - } - - if (m_ses.m_alerts.should_post()) - { - m_ses.m_alerts.post_alert(block_timeout_alert(t->get_handle() - , remote(), pid(), r.block_index, r.piece_index)); - } - m_download_queue.pop_back(); - } - if (!m_download_queue.empty() || !m_request_queue.empty()) - m_timeout_extend += m_ses.settings().request_timeout; - - m_desired_queue_size = 2; - request_a_block(*t, *this); - m_desired_queue_size = 1; - - // abort the block after the new one has - // been requested in order to prevent it from - // picking the same block again, stalling the - // same piece indefinitely. - if (r != piece_block(-1, -1)) - picker.abort_download(r); - - send_block_requests(); - } - - void peer_connection::fill_send_buffer() - { -#ifdef TORRENT_EXPENSIVE_INVARIANT_CHECKS - INVARIANT_CHECK; -#endif - - boost::shared_ptr t = m_torrent.lock(); - if (!t) return; - - // only add new piece-chunks if the send buffer is small enough - // otherwise there will be no end to how large it will be! - - int buffer_size_watermark = int(m_statistics.upload_rate()) / 2; - if (buffer_size_watermark < 512) buffer_size_watermark = 512; - else if (buffer_size_watermark > m_ses.settings().send_buffer_watermark) - buffer_size_watermark = m_ses.settings().send_buffer_watermark; - - while (!m_requests.empty() - && (send_buffer_size() + m_reading_bytes < buffer_size_watermark)) - { - TORRENT_ASSERT(t->ready_for_connections()); - peer_request& r = m_requests.front(); - - TORRENT_ASSERT(r.piece >= 0); - TORRENT_ASSERT(r.piece < (int)m_have_piece.size()); - TORRENT_ASSERT(t->have_piece(r.piece)); - TORRENT_ASSERT(r.start + r.length <= t->torrent_file().piece_size(r.piece)); - TORRENT_ASSERT(r.length > 0 && r.start >= 0); - - t->filesystem().async_read(r, bind(&peer_connection::on_disk_read_complete - , self(), _1, _2, r)); - m_reading_bytes += r.length; - - m_requests.erase(m_requests.begin()); - } - } - - void peer_connection::on_disk_read_complete(int ret, disk_io_job const& j, peer_request r) - { - session_impl::mutex_t::scoped_lock l(m_ses.m_mutex); - - m_reading_bytes -= r.length; - - disk_buffer_holder buffer(m_ses, j.buffer); - - if (ret != r.length || m_torrent.expired()) - { - boost::shared_ptr t = m_torrent.lock(); - if (!t) - { - disconnect(j.str.c_str()); - return; - } - - if (t->alerts().should_post()) - t->alerts().post_alert(file_error_alert(j.error_file, t->get_handle(), j.str)); - t->set_error(j.str); - t->pause(); - return; - } - -#ifdef TORRENT_VERBOSE_LOGGING - (*m_logger) << time_now_string() - << " ==> PIECE [ piece: " << r.piece << " | s: " << r.start - << " | l: " << r.length << " ]\n"; -#endif - - write_piece(r, buffer); - setup_send(); - } - - void peer_connection::assign_bandwidth(int channel, int amount) - { - session_impl::mutex_t::scoped_lock l(m_ses.m_mutex); - -#ifdef TORRENT_VERBOSE_LOGGING - (*m_logger) << "bandwidth [ " << channel << " ] + " << amount << "\n"; -#endif - - m_bandwidth_limit[channel].assign(amount); - TORRENT_ASSERT(m_channel_state[channel] == peer_info::bw_global); - m_channel_state[channel] = peer_info::bw_idle; - if (channel == upload_channel) - { - setup_send(); - } - else if (channel == download_channel) - { - setup_receive(); - } - } - - void peer_connection::expire_bandwidth(int channel, int amount) - { - session_impl::mutex_t::scoped_lock l(m_ses.m_mutex); - - m_bandwidth_limit[channel].expire(amount); - if (channel == upload_channel) - { - setup_send(); - } - else if (channel == download_channel) - { - setup_receive(); - } - } - - void peer_connection::setup_send() - { - session_impl::mutex_t::scoped_lock l(m_ses.m_mutex); - - if (m_channel_state[upload_channel] != peer_info::bw_idle) return; - - shared_ptr t = m_torrent.lock(); - - if (m_bandwidth_limit[upload_channel].quota_left() == 0 - && !m_send_buffer.empty() - && !m_connecting - && t - && !m_ignore_bandwidth_limits) - { - // in this case, we have data to send, but no - // bandwidth. So, we simply request bandwidth - // from the torrent - TORRENT_ASSERT(t); - if (m_bandwidth_limit[upload_channel].max_assignable() > 0) - { - int priority = is_interesting() * 2 + m_requests_in_buffer.size(); - // peers that we are not interested in are non-prioritized - m_channel_state[upload_channel] = peer_info::bw_torrent; - t->request_bandwidth(upload_channel, self() - , m_send_buffer.size(), priority); -#ifdef TORRENT_VERBOSE_LOGGING - (*m_logger) << time_now_string() << " *** REQUEST_BANDWIDTH [ upload prio: " - << priority << "]\n"; -#endif - - } - return; - } - - if (!can_write()) - { -#ifdef TORRENT_VERBOSE_LOGGING - (*m_logger) << time_now_string() << " *** CANNOT WRITE [" - " quota: " << m_bandwidth_limit[download_channel].quota_left() << - " ignore: " << (m_ignore_bandwidth_limits?"yes":"no") << - " buf: " << m_send_buffer.size() << - " connecting: " << (m_connecting?"yes":"no") << - " ]\n"; -#endif - return; - } - - // send the actual buffer - if (!m_send_buffer.empty()) - { - int amount_to_send = m_send_buffer.size(); - int quota_left = m_bandwidth_limit[upload_channel].quota_left(); - if (!m_ignore_bandwidth_limits && amount_to_send > quota_left) - amount_to_send = quota_left; - - TORRENT_ASSERT(amount_to_send > 0); - -#ifdef TORRENT_VERBOSE_LOGGING - (*m_logger) << time_now_string() << " *** ASYNC_WRITE [ bytes: " << amount_to_send << " ]\n"; -#endif - std::list const& vec = m_send_buffer.build_iovec(amount_to_send); - m_socket->async_write_some(vec, bind(&peer_connection::on_send_data, self(), _1, _2)); - - m_channel_state[upload_channel] = peer_info::bw_network; - } - } - - void peer_connection::setup_receive() - { - session_impl::mutex_t::scoped_lock l(m_ses.m_mutex); - - INVARIANT_CHECK; - - if (m_channel_state[download_channel] != peer_info::bw_idle) return; - - shared_ptr t = m_torrent.lock(); - - if (m_bandwidth_limit[download_channel].quota_left() == 0 - && !m_connecting - && t - && !m_ignore_bandwidth_limits) - { - if (m_bandwidth_limit[download_channel].max_assignable() > 0) - { -#ifdef TORRENT_VERBOSE_LOGGING - (*m_logger) << time_now_string() << " *** REQUEST_BANDWIDTH [ download ]\n"; -#endif - TORRENT_ASSERT(m_channel_state[download_channel] == peer_info::bw_idle); - m_channel_state[download_channel] = peer_info::bw_torrent; - t->request_bandwidth(download_channel, self() - , m_download_queue.size() * 16 * 1024 + 30, m_priority); - } - return; - } - - if (!can_read()) - { -#ifdef TORRENT_VERBOSE_LOGGING - (*m_logger) << time_now_string() << " *** CANNOT READ [" - " quota: " << m_bandwidth_limit[download_channel].quota_left() << - " ignore: " << (m_ignore_bandwidth_limits?"yes":"no") << - " outstanding: " << m_outstanding_writing_bytes << - " outstanding-limit: " << m_ses.settings().max_outstanding_disk_bytes_per_connection << - " ]\n"; -#endif - return; - } - - TORRENT_ASSERT(m_packet_size > 0); - int max_receive = m_packet_size - m_recv_pos; - int quota_left = m_bandwidth_limit[download_channel].quota_left(); - if (!m_ignore_bandwidth_limits && max_receive > quota_left) - max_receive = quota_left; - - if (max_receive == 0) return; - - TORRENT_ASSERT(m_recv_pos >= 0); - TORRENT_ASSERT(m_packet_size > 0); - TORRENT_ASSERT(can_read()); -#ifdef TORRENT_VERBOSE_LOGGING - (*m_logger) << time_now_string() << " *** ASYNC_READ [ max: " << max_receive << " bytes ]\n"; -#endif - - int regular_buffer_size = m_packet_size - m_disk_recv_buffer_size; - - if (int(m_recv_buffer.size()) < regular_buffer_size) - m_recv_buffer.resize(regular_buffer_size); - - if (!m_disk_recv_buffer || regular_buffer_size >= m_recv_pos + max_receive) - { - // only receive into regular buffer - TORRENT_ASSERT(m_recv_pos + max_receive <= int(m_recv_buffer.size())); - m_socket->async_read_some(asio::buffer(&m_recv_buffer[m_recv_pos] - , max_receive), bind(&peer_connection::on_receive_data, self(), _1, _2)); - } - else if (m_recv_pos >= regular_buffer_size) - { - // only receive into disk buffer - TORRENT_ASSERT(m_recv_pos - regular_buffer_size >= 0); - TORRENT_ASSERT(m_recv_pos - regular_buffer_size + max_receive <= m_disk_recv_buffer_size); - m_socket->async_read_some(asio::buffer(m_disk_recv_buffer.get() + m_recv_pos - regular_buffer_size - , max_receive) - , bind(&peer_connection::on_receive_data, self(), _1, _2)); - } - else - { - // receive into both regular and disk buffer - TORRENT_ASSERT(max_receive + m_recv_pos > regular_buffer_size); - TORRENT_ASSERT(m_recv_pos < regular_buffer_size); - TORRENT_ASSERT(max_receive - regular_buffer_size - + m_recv_pos <= m_disk_recv_buffer_size); - - boost::array vec; - vec[0] = asio::buffer(&m_recv_buffer[m_recv_pos] - , regular_buffer_size - m_recv_pos); - vec[1] = asio::buffer(m_disk_recv_buffer.get() - , max_receive - regular_buffer_size + m_recv_pos); - m_socket->async_read_some(vec, bind(&peer_connection::on_receive_data - , self(), _1, _2)); - } - m_channel_state[download_channel] = peer_info::bw_network; - } - -#ifndef TORRENT_DISABLE_ENCRYPTION - - // returns the last 'bytes' from the receive buffer - std::pair peer_connection::wr_recv_buffers(int bytes) - { - TORRENT_ASSERT(bytes <= m_recv_pos); - - std::pair vec; - int regular_buffer_size = m_packet_size - m_disk_recv_buffer_size; - TORRENT_ASSERT(regular_buffer_size >= 0); - if (!m_disk_recv_buffer || regular_buffer_size >= m_recv_pos) - { - vec.first = buffer::interval(&m_recv_buffer[0] - + m_recv_pos - bytes, &m_recv_buffer[0] + m_recv_pos); - vec.second = buffer::interval(0,0); - } - else if (m_recv_pos - bytes >= regular_buffer_size) - { - vec.first = buffer::interval(m_disk_recv_buffer.get() + m_recv_pos - - regular_buffer_size - bytes, m_disk_recv_buffer.get() + m_recv_pos - - regular_buffer_size); - vec.second = buffer::interval(0,0); - } - else - { - TORRENT_ASSERT(m_recv_pos - bytes < regular_buffer_size); - TORRENT_ASSERT(m_recv_pos > regular_buffer_size); - vec.first = buffer::interval(&m_recv_buffer[0] + m_recv_pos - bytes - , &m_recv_buffer[0] + regular_buffer_size); - vec.second = buffer::interval(m_disk_recv_buffer.get() - , m_disk_recv_buffer.get() + m_recv_pos - regular_buffer_size); - } - TORRENT_ASSERT(vec.first.left() + vec.second.left() == bytes); - return vec; - } -#endif - - void peer_connection::reset_recv_buffer(int packet_size) - { - TORRENT_ASSERT(packet_size > 0); - if (m_recv_pos > m_packet_size) - { - cut_receive_buffer(m_packet_size, packet_size); - return; - } - m_recv_pos = 0; - m_packet_size = packet_size; - } - - void peer_connection::send_buffer(char const* buf, int size, int flags) - { - if (flags == message_type_request) - m_requests_in_buffer.push_back(m_send_buffer.size() + size); - - int free_space = m_send_buffer.space_in_last_buffer(); - if (free_space > size) free_space = size; - if (free_space > 0) - { - m_send_buffer.append(buf, free_space); - size -= free_space; - buf += free_space; -#ifdef TORRENT_STATS - m_ses.m_buffer_usage_logger << log_time() << " send_buffer: " - << free_space << std::endl; - m_ses.log_buffer_usage(); -#endif - } - if (size <= 0) return; - - std::pair buffer = m_ses.allocate_buffer(size); - if (buffer.first == 0) - { - disconnect("out of memory"); - return; - } - TORRENT_ASSERT(buffer.second >= size); - std::memcpy(buffer.first, buf, size); - m_send_buffer.append_buffer(buffer.first, buffer.second, size - , bind(&session_impl::free_buffer, boost::ref(m_ses), _1, buffer.second)); -#ifdef TORRENT_STATS - m_ses.m_buffer_usage_logger << log_time() << " send_buffer_alloc: " << size << std::endl; - m_ses.log_buffer_usage(); -#endif - setup_send(); - } - -// TODO: change this interface to automatically call setup_send() when the -// return value is destructed - buffer::interval peer_connection::allocate_send_buffer(int size) - { - TORRENT_ASSERT(size > 0); - char* insert = m_send_buffer.allocate_appendix(size); - if (insert == 0) - { - std::pair buffer = m_ses.allocate_buffer(size); - if (buffer.first == 0) - { - disconnect("out of memory"); - return buffer::interval(0, 0); - } - TORRENT_ASSERT(buffer.second >= size); - m_send_buffer.append_buffer(buffer.first, buffer.second, size - , bind(&session_impl::free_buffer, boost::ref(m_ses), _1, buffer.second)); - buffer::interval ret(buffer.first, buffer.first + size); -#ifdef TORRENT_STATS - m_ses.m_buffer_usage_logger << log_time() << " allocate_buffer_alloc: " << size << std::endl; - m_ses.log_buffer_usage(); -#endif - return ret; - } - else - { -#ifdef TORRENT_STATS - m_ses.m_buffer_usage_logger << log_time() << " allocate_buffer: " << size << std::endl; - m_ses.log_buffer_usage(); -#endif - buffer::interval ret(insert, insert + size); - return ret; - } - } - - template - struct set_to_zero - { - set_to_zero(T& v, bool cond): m_val(v), m_cond(cond) {} - void fire() { if (!m_cond) return; m_cond = false; m_val = 0; } - ~set_to_zero() { if (m_cond) m_val = 0; } - private: - T& m_val; - bool m_cond; - }; - - // -------------------------- - // RECEIVE DATA - // -------------------------- - - // throws exception when the client should be disconnected - void peer_connection::on_receive_data(const error_code& error - , std::size_t bytes_transferred) - { - session_impl::mutex_t::scoped_lock l(m_ses.m_mutex); - - INVARIANT_CHECK; - - // keep ourselves alive in until this function exits in - // case we disconnect - boost::intrusive_ptr me(self()); - - TORRENT_ASSERT(m_channel_state[download_channel] == peer_info::bw_network); - m_channel_state[download_channel] = peer_info::bw_idle; - - if (error) - { -#if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_ERROR_LOGGING - (*m_logger) << time_now_string() << " **ERROR**: " - << error.message() << "[in peer_connection::on_receive_data]\n"; -#endif - on_receive(error, bytes_transferred); - disconnect(error.message().c_str()); - return; - } - - int max_receive = 0; - do - { -#ifdef TORRENT_VERBOSE_LOGGING - (*m_logger) << "read " << bytes_transferred << " bytes\n"; -#endif - // correct the dl quota usage, if not all of the buffer was actually read - if (!m_ignore_bandwidth_limits) - m_bandwidth_limit[download_channel].use_quota(bytes_transferred); - - if (m_disconnecting) return; - - TORRENT_ASSERT(m_packet_size > 0); - TORRENT_ASSERT(bytes_transferred > 0); - - m_last_receive = time_now(); - m_recv_pos += bytes_transferred; - TORRENT_ASSERT(m_recv_pos <= int(m_recv_buffer.size() - + m_disk_recv_buffer_size)); - - on_receive(error, bytes_transferred); - - TORRENT_ASSERT(m_packet_size > 0); - - if (m_peer_choked - && m_recv_pos == 0 - && (m_recv_buffer.capacity() - m_packet_size) > 128) - { - buffer(m_packet_size).swap(m_recv_buffer); - } - - max_receive = m_packet_size - m_recv_pos; - int quota_left = m_bandwidth_limit[download_channel].quota_left(); - if (!m_ignore_bandwidth_limits && max_receive > quota_left) - max_receive = quota_left; - - if (max_receive == 0) break; - - int regular_buffer_size = m_packet_size - m_disk_recv_buffer_size; - - if (int(m_recv_buffer.size()) < regular_buffer_size) - m_recv_buffer.resize(regular_buffer_size); - - error_code ec; - if (!m_disk_recv_buffer || regular_buffer_size >= m_recv_pos + max_receive) - { - // only receive into regular buffer - TORRENT_ASSERT(m_recv_pos + max_receive <= int(m_recv_buffer.size())); - bytes_transferred = m_socket->read_some(asio::buffer(&m_recv_buffer[m_recv_pos] - , max_receive), ec); - } - else if (m_recv_pos >= regular_buffer_size) - { - // only receive into disk buffer - TORRENT_ASSERT(m_recv_pos - regular_buffer_size >= 0); - TORRENT_ASSERT(m_recv_pos - regular_buffer_size + max_receive <= m_disk_recv_buffer_size); - bytes_transferred = m_socket->read_some(asio::buffer(m_disk_recv_buffer.get() - + m_recv_pos - regular_buffer_size, (std::min)(m_packet_size - - m_recv_pos, max_receive)), ec); - } - else - { - // receive into both regular and disk buffer - TORRENT_ASSERT(max_receive + m_recv_pos > regular_buffer_size); - TORRENT_ASSERT(m_recv_pos < regular_buffer_size); - TORRENT_ASSERT(max_receive - regular_buffer_size - + m_recv_pos <= m_disk_recv_buffer_size); - - boost::array vec; - vec[0] = asio::buffer(&m_recv_buffer[m_recv_pos] - , regular_buffer_size - m_recv_pos); - vec[1] = asio::buffer(m_disk_recv_buffer.get() - , (std::min)(m_disk_recv_buffer_size - , max_receive - regular_buffer_size + m_recv_pos)); - bytes_transferred = m_socket->read_some(vec, ec); - } - if (ec && ec != asio::error::would_block) - { - disconnect(ec.message().c_str()); - return; - } - if (ec == asio::error::would_block) break; - } - while (bytes_transferred > 0); - - setup_receive(); - } - - bool peer_connection::can_write() const - { - // if we have requests or pending data to be sent or announcements to be made - // we want to send data - return !m_send_buffer.empty() - && (m_bandwidth_limit[upload_channel].quota_left() > 0 - || m_ignore_bandwidth_limits) - && !m_connecting; - } - - bool peer_connection::can_read() const - { - bool ret = (m_bandwidth_limit[download_channel].quota_left() > 0 - || m_ignore_bandwidth_limits) - && !m_connecting - && m_outstanding_writing_bytes < - m_ses.settings().max_outstanding_disk_bytes_per_connection; - - return ret; - } - - void peer_connection::connect(int ticket) - { -#ifdef TORRENT_DEBUG - // in case we disconnect here, we need to - // keep the connection alive until the - // exit invariant check is run - boost::intrusive_ptr me(self()); -#endif - INVARIANT_CHECK; - - error_code ec; -#if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_LOGGING || defined TORRENT_ERROR_LOGGING - (*m_ses.m_logger) << time_now_string() << " CONNECTING: " << m_remote.address().to_string(ec) - << ":" << m_remote.port() << "\n"; -#endif - - m_connection_ticket = ticket; - boost::shared_ptr t = m_torrent.lock(); - - m_queued = false; - TORRENT_ASSERT(m_connecting); - - if (!t) - { - disconnect("torrent aborted"); - return; - } - - m_socket->open(t->get_interface().protocol(), ec); - if (ec) - { - disconnect(ec.message().c_str()); - return; - } - - // set the socket to non-blocking, so that we can - // read the entire buffer on each read event we get - tcp::socket::non_blocking_io ioc(true); - m_socket->io_control(ioc, ec); - if (ec) - { - disconnect(ec.message().c_str()); - return; - } - - tcp::endpoint bind_interface = t->get_interface(); - - std::pair const& out_ports = m_ses.settings().outgoing_ports; - if (out_ports.first > 0 && out_ports.second >= out_ports.first) - { - m_socket->set_option(socket_acceptor::reuse_address(true), ec); - if (ec) - { - disconnect(ec.message().c_str()); - return; - } - bind_interface.port(m_ses.next_port()); - } - - m_socket->bind(bind_interface, ec); - if (ec) - { - disconnect(ec.message().c_str()); - return; - } - m_socket->async_connect(m_remote - , bind(&peer_connection::on_connection_complete, self(), _1)); - m_connect = time_now(); - - if (t->alerts().should_post()) - { - t->alerts().post_alert(peer_connect_alert( - t->get_handle(), remote(), pid())); - } - } - - void peer_connection::on_connection_complete(error_code const& e) - { - ptime completed = time_now(); - - session_impl::mutex_t::scoped_lock l(m_ses.m_mutex); - - INVARIANT_CHECK; - - m_rtt = total_milliseconds(completed - m_connect); - - if (m_disconnecting) return; - - m_connecting = false; - m_ses.m_half_open.done(m_connection_ticket); - - error_code ec; - if (e) - { -#if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_LOGGING || defined TORRENT_ERROR_LOGGING - (*m_ses.m_logger) << time_now_string() << " CONNECTION FAILED: " << m_remote.address().to_string(ec) - << ": " << e.message() << "\n"; -#endif - disconnect(e.message().c_str(), 1); - return; - } - - if (m_disconnecting) return; - m_last_receive = time_now(); - - // this means the connection just succeeded - - TORRENT_ASSERT(m_socket); -#if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_LOGGING - (*m_ses.m_logger) << time_now_string() << " COMPLETED: " << m_remote.address().to_string(ec) - << " rtt = " << m_rtt << "\n"; -#endif - - if (m_remote == m_socket->local_endpoint(ec)) - { - // if the remote endpoint is the same as the local endpoint, we're connected - // to ourselves - disconnect("connected to ourselves", 1); - return; - } - - if (m_remote.address().is_v4()) - { - error_code ec; - m_socket->set_option(type_of_service(m_ses.settings().peer_tos), ec); - } - - on_connected(); - setup_send(); - setup_receive(); - } - - // -------------------------- - // SEND DATA - // -------------------------- - - // throws exception when the client should be disconnected - void peer_connection::on_send_data(error_code const& error - , std::size_t bytes_transferred) - { - session_impl::mutex_t::scoped_lock l(m_ses.m_mutex); - - INVARIANT_CHECK; - - // keep ourselves alive in until this function exits in - // case we disconnect - boost::intrusive_ptr me(self()); - - TORRENT_ASSERT(m_channel_state[upload_channel] == peer_info::bw_network); - - m_send_buffer.pop_front(bytes_transferred); - - for (std::vector::iterator i = m_requests_in_buffer.begin() - , end(m_requests_in_buffer.end()); i != end; ++i) - *i -= bytes_transferred; - - while (!m_requests_in_buffer.empty() - && m_requests_in_buffer.front() <= 0) - m_requests_in_buffer.erase(m_requests_in_buffer.begin()); - - m_channel_state[upload_channel] = peer_info::bw_idle; - - if (!m_ignore_bandwidth_limits) - m_bandwidth_limit[upload_channel].use_quota(bytes_transferred); - -#ifdef TORRENT_VERBOSE_LOGGING - (*m_logger) << "wrote " << bytes_transferred << " bytes\n"; -#endif - - if (error) - { -#if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_ERROR_LOGGING - (*m_logger) << "**ERROR**: " << error.message() << " [in peer_connection::on_send_data]\n"; -#endif - disconnect(error.message().c_str()); - return; - } - if (m_disconnecting) return; - - TORRENT_ASSERT(!m_connecting); - TORRENT_ASSERT(bytes_transferred > 0); - - m_last_sent = time_now(); - - on_sent(error, bytes_transferred); - fill_send_buffer(); - - setup_send(); - } - -#ifdef TORRENT_DEBUG - void peer_connection::check_invariant() const - { - TORRENT_ASSERT(bool(m_disk_recv_buffer) == (m_disk_recv_buffer_size > 0)); - - boost::shared_ptr t = m_torrent.lock(); - if (m_disconnecting) - { - TORRENT_ASSERT(!t); - TORRENT_ASSERT(m_disconnect_started); - } - else if (!m_in_constructor) - { - TORRENT_ASSERT(m_ses.has_peer((peer_connection*)this)); - } - -/* - // this assertion correct most of the time, but sometimes right when the - // limit is changed it might break - for (int i = 0; i < 2; ++i) - { - // this peer is in the bandwidth history iff max_assignable < limit - TORRENT_ASSERT((m_bandwidth_limit[i].max_assignable() < m_bandwidth_limit[i].throttle()) - == m_ses.m_bandwidth_manager[i]->is_in_history(this) - || m_bandwidth_limit[i].throttle() == bandwidth_limit::inf); - } -*/ - - if (m_channel_state[download_channel] == peer_info::bw_torrent - || m_channel_state[download_channel] == peer_info::bw_global) - TORRENT_ASSERT(m_bandwidth_limit[download_channel].quota_left() == 0); - if (m_channel_state[upload_channel] == peer_info::bw_torrent - || m_channel_state[upload_channel] == peer_info::bw_global) - TORRENT_ASSERT(m_bandwidth_limit[upload_channel].quota_left() == 0); - - std::set unique; - std::transform(m_download_queue.begin(), m_download_queue.end() - , std::inserter(unique, unique.begin()), boost::bind(&pending_block::block, _1)); - std::copy(m_request_queue.begin(), m_request_queue.end(), std::inserter(unique, unique.begin())); - TORRENT_ASSERT(unique.size() == m_download_queue.size() + m_request_queue.size()); - if (m_peer_info) - { - TORRENT_ASSERT(m_peer_info->prev_amount_upload == 0); - TORRENT_ASSERT(m_peer_info->prev_amount_download == 0); - TORRENT_ASSERT(m_peer_info->connection == this - || m_peer_info->connection == 0); - - if (m_peer_info->optimistically_unchoked) - TORRENT_ASSERT(!is_choked()); - } - - TORRENT_ASSERT(m_have_piece.count() == m_num_pieces); - - if (!t) - { -#ifdef TORRENT_EXPENSIVE_INVARIANT_CHECKS - // since this connection doesn't have a torrent reference - // no torrent should have a reference to this connection either - for (aux::session_impl::torrent_map::const_iterator i = m_ses.m_torrents.begin() - , end(m_ses.m_torrents.end()); i != end; ++i) - TORRENT_ASSERT(!i->second->has_peer((peer_connection*)this)); -#endif - return; - } - - if (t->ready_for_connections() && m_initialized) - TORRENT_ASSERT(t->torrent_file().num_pieces() == int(m_have_piece.size())); - - if (m_ses.settings().close_redundant_connections) - { - // make sure upload only peers are disconnected - if (t->is_finished() && m_upload_only) - TORRENT_ASSERT(m_disconnect_started); - if (m_upload_only - && !m_interesting - && m_bitfield_received - && t->are_files_checked()) - TORRENT_ASSERT(m_disconnect_started); - } - - if (!m_disconnect_started && m_initialized) - { - // none of this matters if we're disconnecting anyway - if (t->is_finished()) - TORRENT_ASSERT(!m_interesting); - if (is_seed()) - TORRENT_ASSERT(m_upload_only); - } - - if (t->has_picker()) - { - std::map num_requests; - for (torrent::const_peer_iterator i = t->begin(); i != t->end(); ++i) - { - // make sure this peer is not a dangling pointer -#ifdef TORRENT_EXPENSIVE_INVARIANT_CHECKS - TORRENT_ASSERT(m_ses.has_peer(*i)); -#endif - peer_connection const& p = *(*i); - for (std::deque::const_iterator i = p.request_queue().begin() - , end(p.request_queue().end()); i != end; ++i) - ++num_requests[*i]; - for (std::deque::const_iterator i = p.download_queue().begin() - , end(p.download_queue().end()); i != end; ++i) - ++num_requests[i->block]; - } - for (std::map::iterator i = num_requests.begin() - , end(num_requests.end()); i != end; ++i) - { - if (!t->picker().is_downloaded(i->first)) - TORRENT_ASSERT(t->picker().num_peers(i->first) == i->second); - } - } -#ifdef TORRENT_EXPENSIVE_INVARIANT_CHECKS - if (m_peer_info) - { - policy::const_iterator i = t->get_policy().begin_peer(); - policy::const_iterator end = t->get_policy().end_peer(); - for (; i != end; ++i) - { - if (&i->second == m_peer_info) break; - } - TORRENT_ASSERT(i != end); - } -#endif - if (t->has_picker() && !t->is_aborted()) - { - // make sure that pieces that have completed the download - // of all their blocks are in the disk io thread's queue - // to be checked. - const std::vector& dl_queue - = t->picker().get_download_queue(); - for (std::vector::const_iterator i = - dl_queue.begin(); i != dl_queue.end(); ++i) - { - const int blocks_per_piece = t->picker().blocks_in_piece(i->index); - - bool complete = true; - for (int j = 0; j < blocks_per_piece; ++j) - { - if (i->info[j].state == piece_picker::block_info::state_finished) - continue; - complete = false; - break; - } -/* -// this invariant is not valid anymore since the completion event -// might be queued in the io service - if (complete && !piece_failed) - { - disk_io_job ret = m_ses.m_disk_thread.find_job( - &t->filesystem(), -1, i->index); - TORRENT_ASSERT(ret.action == disk_io_job::hash || ret.action == disk_io_job::write); - TORRENT_ASSERT(ret.piece == i->index); - } -*/ - } - } - -// extremely expensive invariant check -/* - if (!t->is_seed()) - { - piece_picker& p = t->picker(); - const std::vector& dlq = p.get_download_queue(); - const int blocks_per_piece = static_cast( - t->torrent_file().piece_length() / t->block_size()); - - for (std::vector::const_iterator i = - dlq.begin(); i != dlq.end(); ++i) - { - for (int j = 0; j < blocks_per_piece; ++j) - { - if (std::find(m_request_queue.begin(), m_request_queue.end() - , piece_block(i->index, j)) != m_request_queue.end() - || - std::find(m_download_queue.begin(), m_download_queue.end() - , piece_block(i->index, j)) != m_download_queue.end()) - { - TORRENT_ASSERT(i->info[j].peer == m_remote); - } - else - { - TORRENT_ASSERT(i->info[j].peer != m_remote || i->info[j].finished); - } - } - } - } -*/ - } -#endif - - peer_connection::peer_speed_t peer_connection::peer_speed() - { - shared_ptr t = m_torrent.lock(); - TORRENT_ASSERT(t); - - int download_rate = int(statistics().download_payload_rate()); - int torrent_download_rate = int(t->statistics().download_payload_rate()); - - if (download_rate > 512 && download_rate > torrent_download_rate / 16) - m_speed = fast; - else if (download_rate > 4096 && download_rate > torrent_download_rate / 64) - m_speed = medium; - else if (download_rate < torrent_download_rate / 15 && m_speed == fast) - m_speed = medium; - else - m_speed = slow; - - return m_speed; - } - - void peer_connection::keep_alive() - { -#ifdef TORRENT_EXPENSIVE_INVARIANT_CHECKS - INVARIANT_CHECK; -#endif - - time_duration d; - d = time_now() - m_last_sent; - if (total_seconds(d) < m_timeout / 2) return; - - if (m_connecting) return; - if (in_handshake()) return; - - // if the last send has not completed yet, do not send a keep - // alive - if (m_channel_state[upload_channel] != peer_info::bw_idle) return; - -#ifdef TORRENT_VERBOSE_LOGGING - (*m_logger) << time_now_string() << " ==> KEEPALIVE\n"; -#endif - - m_last_sent = time_now(); - write_keepalive(); - } - - bool peer_connection::is_seed() const - { - // if m_num_pieces == 0, we probably don't have the - // metadata yet. - boost::shared_ptr t = m_torrent.lock(); - return m_num_pieces == (int)m_have_piece.size() && m_num_pieces > 0 && t && t->valid_metadata(); - } -} - diff --git a/libtorrent/src/piece_picker.cpp b/libtorrent/src/piece_picker.cpp deleted file mode 100755 index 68f1393a1..000000000 --- a/libtorrent/src/piece_picker.cpp +++ /dev/null @@ -1,2263 +0,0 @@ -/* - -Copyright (c) 2003, Arvid Norberg -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions -are met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in - the documentation and/or other materials provided with the distribution. - * Neither the name of the author nor the names of its - contributors may be used to endorse or promote products derived - from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -POSSIBILITY OF SUCH DAMAGE. - -*/ - -#include "libtorrent/pch.hpp" - -#include -#include -#include -#include - -#include "libtorrent/piece_picker.hpp" -#include "libtorrent/aux_/session_impl.hpp" -#include "libtorrent/bitfield.hpp" - -#ifdef TORRENT_DEBUG -#include "libtorrent/peer_connection.hpp" -#include "libtorrent/torrent.hpp" -#endif - -#define TORRENT_PIECE_PICKER_INVARIANT_CHECK INVARIANT_CHECK -//#define TORRENT_NO_EXPENSIVE_INVARIANT_CHECK -//#define TORRENT_PIECE_PICKER_INVARIANT_CHECK - -//#define TORRENT_PICKER_LOG - -namespace libtorrent -{ - - piece_picker::piece_picker() - : m_seeds(0) - , m_priority_boundries(1, int(m_pieces.size())) - , m_blocks_per_piece(0) - , m_blocks_in_last_piece(0) - , m_num_filtered(0) - , m_num_have_filtered(0) - , m_num_have(0) - , m_cursor(0) - , m_reverse_cursor(0) - , m_dirty(false) - { -#ifdef TORRENT_PICKER_LOG - std::cerr << "new piece_picker" << std::endl; -#endif -#ifdef TORRENT_DEBUG - check_invariant(); -#endif - } - - void piece_picker::init(int blocks_per_piece, int total_num_blocks) - { - TORRENT_ASSERT(blocks_per_piece > 0); - TORRENT_ASSERT(total_num_blocks >= 0); - -#ifdef TORRENT_PICKER_LOG - std::cerr << "piece_picker::init()" << std::endl; -#endif - // allocate the piece_map to cover all pieces - // and make them invalid (as if we don't have a single piece) - m_piece_map.resize((total_num_blocks + blocks_per_piece-1) / blocks_per_piece - , piece_pos(0, 0)); - m_reverse_cursor = int(m_piece_map.size()); - m_cursor = 0; - - m_num_filtered += m_num_have_filtered; - m_num_have_filtered = 0; - m_num_have = 0; - m_dirty = true; - for (std::vector::iterator i = m_piece_map.begin() - , end(m_piece_map.end()); i != end; ++i) - { - i->peer_count = 0; - i->downloading = 0; - i->index = 0; - } - - for (std::vector::const_iterator i = m_piece_map.begin() + m_cursor - , end(m_piece_map.end()); i != end && (i->have() || i->filtered()); - ++i, ++m_cursor); - for (std::vector::const_reverse_iterator i = m_piece_map.rend() - - m_reverse_cursor; m_reverse_cursor > 0 && (i->have() || i->filtered()); - ++i, --m_reverse_cursor); - - // the piece index is stored in 20 bits, which limits the allowed - // number of pieces somewhat - TORRENT_ASSERT(m_piece_map.size() < piece_pos::we_have_index); - - m_blocks_per_piece = blocks_per_piece; - m_blocks_in_last_piece = total_num_blocks % blocks_per_piece; - if (m_blocks_in_last_piece == 0) m_blocks_in_last_piece = blocks_per_piece; - - TORRENT_ASSERT(m_blocks_in_last_piece <= m_blocks_per_piece); - } - - void piece_picker::piece_info(int index, piece_picker::downloading_piece& st) const - { -#ifdef TORRENT_EXPENSIVE_INVARIANT_CHECKS - TORRENT_PIECE_PICKER_INVARIANT_CHECK; -#endif - - TORRENT_ASSERT(index >= 0); - TORRENT_ASSERT(index < int(m_piece_map.size())); - - if (m_piece_map[index].downloading) - { - std::vector::const_iterator piece = std::find_if( - m_downloads.begin(), m_downloads.end() - , bind(&downloading_piece::index, _1) == index); - TORRENT_ASSERT(piece != m_downloads.end()); - st = *piece; - st.info = 0; - return; - } - st.info = 0; - st.index = index; - st.writing = 0; - st.requested = 0; - if (m_piece_map[index].have()) - { - st.finished = blocks_in_piece(index); - return; - } - st.finished = 0; - } - - piece_picker::downloading_piece& piece_picker::add_download_piece() - { - int num_downloads = m_downloads.size(); - int block_index = num_downloads * m_blocks_per_piece; - if (int(m_block_info.size()) < block_index + m_blocks_per_piece) - { - block_info* base = 0; - if (!m_block_info.empty()) base = &m_block_info[0]; - m_block_info.resize(block_index + m_blocks_per_piece); - if (!m_downloads.empty() && &m_block_info[0] != base) - { - // this means the memory was reallocated, update the pointers - for (int i = 0; i < int(m_downloads.size()); ++i) - m_downloads[i].info = &m_block_info[m_downloads[i].info - base]; - } - } - m_downloads.push_back(downloading_piece()); - downloading_piece& ret = m_downloads.back(); - ret.info = &m_block_info[block_index]; - for (int i = 0; i < m_blocks_per_piece; ++i) - { - ret.info[i].num_peers = 0; - ret.info[i].state = block_info::state_none; - ret.info[i].peer = 0; - } - return ret; - } - - void piece_picker::erase_download_piece(std::vector::iterator i) - { - std::vector::iterator other = std::find_if( - m_downloads.begin(), m_downloads.end() - , bind(&downloading_piece::info, _1) - == &m_block_info[(m_downloads.size() - 1) * m_blocks_per_piece]); - TORRENT_ASSERT(other != m_downloads.end()); - - if (i != other) - { - std::copy(other->info, other->info + m_blocks_per_piece, i->info); - other->info = i->info; - } - m_downloads.erase(i); - } - -#ifdef TORRENT_DEBUG - - void piece_picker::verify_pick(std::vector const& picked - , bitfield const& bits) const - { - TORRENT_ASSERT(bits.size() == m_piece_map.size()); - for (std::vector::const_iterator i = picked.begin() - , end(picked.end()); i != end; ++i) - { - TORRENT_ASSERT(i->piece_index >= 0); - TORRENT_ASSERT(i->piece_index < int(bits.size())); - TORRENT_ASSERT(bits[i->piece_index]); - TORRENT_ASSERT(!m_piece_map[i->piece_index].have()); - } - } - - void piece_picker::verify_priority(int range_start, int range_end, int prio) const - { - TORRENT_ASSERT(range_start <= range_end); - TORRENT_ASSERT(range_end <= int(m_pieces.size())); - for (std::vector::const_iterator i = m_pieces.begin() + range_start - , end(m_pieces.begin() + range_end); i != end; ++i) - { - int index = *i; - TORRENT_ASSERT(index >= 0); - TORRENT_ASSERT(index < int(m_piece_map.size())); - int p = m_piece_map[index].priority(this); - TORRENT_ASSERT(p == prio); - } - } - -#if defined TORRENT_PICKER_LOG || defined TORRENT_DEBUG - void piece_picker::print_pieces() const - { - for (std::vector::const_iterator i = m_priority_boundries.begin() - , end(m_priority_boundries.end()); i != end; ++i) - { - std::cerr << *i << " "; - } - std::cout << std::endl; - int index = 0; - std::vector::const_iterator j = m_priority_boundries.begin(); - for (std::vector::const_iterator i = m_pieces.begin() - , end(m_pieces.end()); i != end; ++i, ++index) - { - if (*i == -1) break; - while (j != m_priority_boundries.end() && *j <= index) - { - std::cerr << "| "; - ++j; - } - std::cerr << *i << "(" << m_piece_map[*i].index << ") "; - } - std::cerr << std::endl; - } -#endif - - void piece_picker::check_invariant(const torrent* t) const - { - TORRENT_ASSERT(sizeof(piece_pos) == 4); - TORRENT_ASSERT(m_num_have >= 0); - TORRENT_ASSERT(m_num_have_filtered >= 0); - TORRENT_ASSERT(m_num_filtered >= 0); - TORRENT_ASSERT(m_seeds >= 0); - - if (!m_downloads.empty()) - { - for (std::vector::const_iterator i = m_downloads.begin(); - i != m_downloads.end() - 1; ++i) - { - downloading_piece const& dp = *i; - downloading_piece const& next = *(i + 1); - TORRENT_ASSERT(dp.finished + dp.writing >= next.finished + next.writing); - } - } - - if (t != 0) - TORRENT_ASSERT((int)m_piece_map.size() == t->torrent_file().num_pieces()); - - for (std::vector::const_iterator i = m_downloads.begin() - , end(m_downloads.end()); i != end; ++i) - { - bool blocks_requested = false; - int num_blocks = blocks_in_piece(i->index); - int num_requested = 0; - int num_finished = 0; - int num_writing = 0; - for (int k = 0; k < num_blocks; ++k) - { - if (i->info[k].state == block_info::state_finished) - { - ++num_finished; - TORRENT_ASSERT(i->info[k].num_peers == 0); - } - else if (i->info[k].state == block_info::state_requested) - { - ++num_requested; - blocks_requested = true; - TORRENT_ASSERT(i->info[k].num_peers > 0); - } - else if (i->info[k].state == block_info::state_writing) - { - ++num_writing; - TORRENT_ASSERT(i->info[k].num_peers == 0); - } - } - TORRENT_ASSERT(blocks_requested == (i->state != none)); - TORRENT_ASSERT(num_requested == i->requested); - TORRENT_ASSERT(num_writing == i->writing); - TORRENT_ASSERT(num_finished == i->finished); - } - int num_pieces = int(m_piece_map.size()); - TORRENT_ASSERT(m_cursor >= 0); - TORRENT_ASSERT(m_cursor <= num_pieces); - TORRENT_ASSERT(m_reverse_cursor <= num_pieces); - TORRENT_ASSERT(m_reverse_cursor >= 0); - TORRENT_ASSERT(m_reverse_cursor > m_cursor - || (m_cursor == num_pieces && m_reverse_cursor == 0)); - -#ifdef TORRENT_NO_EXPENSIVE_INVARIANT_CHECK - return; -#endif - - if (!m_dirty) - { - TORRENT_ASSERT(!m_priority_boundries.empty()); - int prio = 0; - int start = 0; - for (std::vector::const_iterator i = m_priority_boundries.begin() - , end(m_priority_boundries.end()); i != end; ++i) - { - verify_priority(start, *i, prio); - ++prio; - start = *i; - } - TORRENT_ASSERT(m_priority_boundries.back() == int(m_pieces.size())); - } - int index = 0; - for (std::vector::const_iterator i = m_piece_map.begin() - , end(m_piece_map.end()); i != end && (i->have() || i->filtered()); - ++i, ++index); - TORRENT_ASSERT(m_cursor == index); - index = num_pieces; - if (num_pieces > 0) - { - for (std::vector::const_reverse_iterator i = m_piece_map.rend() - - index; index > 0 && (i->have() || i->filtered()); ++i, --index); - TORRENT_ASSERT(index == num_pieces - || m_piece_map[index].have() - || m_piece_map[index].filtered()); - TORRENT_ASSERT(m_reverse_cursor == index); - } - else - { - TORRENT_ASSERT(m_reverse_cursor == 0); - } - - int num_filtered = 0; - int num_have_filtered = 0; - int num_have = 0; - for (std::vector::const_iterator i = m_piece_map.begin(); - i != m_piece_map.end(); ++i) - { - int index = static_cast(i - m_piece_map.begin()); - piece_pos const& p = *i; - - if (p.filtered()) - { - if (p.index != piece_pos::we_have_index) - ++num_filtered; - else - ++num_have_filtered; - } - if (p.index == piece_pos::we_have_index) - ++num_have; - -#if 0 - if (t != 0) - { - int actual_peer_count = 0; - for (torrent::const_peer_iterator peer = t->begin(); - peer != t->end(); ++peer) - { - if (peer->second->has_piece(index)) actual_peer_count++; - } - - TORRENT_ASSERT((int)i->peer_count == actual_peer_count); -/* - int num_downloaders = 0; - for (std::vector::const_iterator peer = t->begin(); - peer != t->end(); - ++peer) - { - const std::vector& queue = (*peer)->download_queue(); - if (std::find_if(queue.begin(), queue.end(), has_index(index)) == queue.end()) continue; - - ++num_downloaders; - } - - if (i->downloading) - { - TORRENT_ASSERT(num_downloaders == 1); - } - else - { - TORRENT_ASSERT(num_downloaders == 0); - } -*/ - } -#endif - - if (p.index == piece_pos::we_have_index) - { - TORRENT_ASSERT(t == 0 || t->have_piece(index)); - TORRENT_ASSERT(p.downloading == 0); - } - - if (t != 0) - TORRENT_ASSERT(!t->have_piece(index)); - - int prio = p.priority(this); - TORRENT_ASSERT(prio == -1 || p.downloading == (prio % piece_picker::prio_factor == 0)); - - if (!m_dirty) - { - TORRENT_ASSERT(prio < int(m_priority_boundries.size()) - || m_dirty); - if (prio >= 0) - { - TORRENT_ASSERT(p.index < m_pieces.size()); - TORRENT_ASSERT(m_pieces[p.index] == index); - } - else - { - TORRENT_ASSERT(prio == -1); - // make sure there's no entry - // with this index. (there shouldn't - // be since the priority is -1) - TORRENT_ASSERT(std::find(m_pieces.begin(), m_pieces.end(), index) - == m_pieces.end()); - } - } - - int count = std::count_if(m_downloads.begin(), m_downloads.end() - , has_index(index)); - if (i->downloading == 1) - { - TORRENT_ASSERT(count == 1); - } - else - { - TORRENT_ASSERT(count == 0); - } - } - TORRENT_ASSERT(num_have == m_num_have); - TORRENT_ASSERT(num_filtered == m_num_filtered); - TORRENT_ASSERT(num_have_filtered == m_num_have_filtered); - - if (!m_dirty) - { - for (std::vector::const_iterator i = m_pieces.begin() - , end(m_pieces.end()); i != end; ++i) - { - TORRENT_ASSERT(m_piece_map[*i].priority(this) >= 0); - } - } - } -#endif - - float piece_picker::distributed_copies() const - { - TORRENT_ASSERT(m_seeds >= 0); - const float num_pieces = static_cast(m_piece_map.size()); - - int min_availability = piece_pos::max_peer_count; - // find the lowest availability count - // count the number of pieces that have that availability - // and also the number of pieces that have more than that. - int integer_part = 0; - int fraction_part = 0; - for (std::vector::const_iterator i = m_piece_map.begin() - , end(m_piece_map.end()); i != end; ++i) - { - int peer_count = int(i->peer_count); - // take ourself into account - if (i->have()) ++peer_count; - if (min_availability > peer_count) - { - min_availability = peer_count; - fraction_part += integer_part; - integer_part = 1; - } - else if (peer_count == min_availability) - { - ++integer_part; - } - else - { - TORRENT_ASSERT(peer_count > min_availability); - ++fraction_part; - } - } - TORRENT_ASSERT(integer_part + fraction_part == num_pieces); - return float(min_availability + m_seeds) + (fraction_part / num_pieces); - } - - void piece_picker::priority_range(int prio, int* start, int* end) - { - TORRENT_ASSERT(prio >= 0); - TORRENT_ASSERT(prio < int(m_priority_boundries.size()) - || m_dirty); - if (prio == 0) *start = 0; - else *start = m_priority_boundries[prio - 1]; - *end = m_priority_boundries[prio]; - TORRENT_ASSERT(*start <= *end); - } - - void piece_picker::add(int index) - { - TORRENT_ASSERT(!m_dirty); - TORRENT_ASSERT(index >= 0); - TORRENT_ASSERT(index < int(m_piece_map.size())); - piece_pos& p = m_piece_map[index]; - TORRENT_ASSERT(!p.filtered()); - TORRENT_ASSERT(!p.have()); - - int priority = p.priority(this); - TORRENT_ASSERT(priority >= 0); - if (int(m_priority_boundries.size()) <= priority) - m_priority_boundries.resize(priority + 1, m_pieces.size()); - - TORRENT_ASSERT(int(m_priority_boundries.size()) >= priority); - - int range_start, range_end; - priority_range(priority, &range_start, &range_end); - int new_index; - if (range_end == range_start) new_index = range_start; - else new_index = rand() % (range_end - range_start + 1) + range_start; - -#ifdef TORRENT_PICKER_LOG - std::cerr << "add " << index << " (" << priority << ")" << std::endl; - print_pieces(); -#endif - m_pieces.push_back(-1); - - for (;;) - { - TORRENT_ASSERT(new_index < int(m_pieces.size())); - int temp = m_pieces[new_index]; - m_pieces[new_index] = index; - m_piece_map[index].index = new_index; - index = temp; - do - { - temp = m_priority_boundries[priority]++; - ++priority; - } while (temp == new_index && priority < int(m_priority_boundries.size())); - new_index = temp; -#ifdef TORRENT_PICKER_LOG - print_pieces(); - std::cerr << " index: " << index - << " prio: " << priority - << " new_index: " << new_index - << std::endl; -#endif - if (priority >= int(m_priority_boundries.size())) break; - TORRENT_ASSERT(temp >= 0); - } - if (index != -1) - { - TORRENT_ASSERT(new_index == int(m_pieces.size() - 1)); - m_pieces[new_index] = index; - m_piece_map[index].index = new_index; - -#ifdef TORRENT_PICKER_LOG - print_pieces(); -#endif -// shuffle(priority, new_index); -#ifdef TORRENT_PICKER_LOG -// print_pieces(); -#endif - } - } - - void piece_picker::remove(int priority, int elem_index) - { - TORRENT_ASSERT(!m_dirty); - TORRENT_ASSERT(priority >= 0); - -#ifdef TORRENT_PICKER_LOG - std::cerr << "remove " << m_pieces[elem_index] << " (" << priority << ")" << std::endl; -#endif - int next_index = elem_index; - TORRENT_ASSERT(m_piece_map[m_pieces[elem_index]].priority(this) == -1); - for (;;) - { -#ifdef TORRENT_PICKER_LOG - print_pieces(); -#endif - TORRENT_ASSERT(elem_index < int(m_pieces.size())); - int temp; - do - { - temp = --m_priority_boundries[priority]; - ++priority; - } while (next_index == temp && priority < int(m_priority_boundries.size())); - if (next_index == temp) break; - next_index = temp; - - int piece = m_pieces[next_index]; - m_pieces[elem_index] = piece; - m_piece_map[piece].index = elem_index; - TORRENT_ASSERT(m_piece_map[piece].priority(this) == priority - 1); - TORRENT_ASSERT(elem_index < int(m_pieces.size() - 1)); - elem_index = next_index; - - if (priority == int(m_priority_boundries.size())) - break; - } - m_pieces.pop_back(); - TORRENT_ASSERT(next_index == int(m_pieces.size())); -#ifdef TORRENT_PICKER_LOG - print_pieces(); -#endif - } - - // will update the piece with the given properties (priority, elem_index) - // to place it at the correct position - void piece_picker::update(int priority, int elem_index) - { - TORRENT_ASSERT(!m_dirty); - TORRENT_ASSERT(priority >= 0); - TORRENT_ASSERT(elem_index >= 0); - - TORRENT_ASSERT(int(m_priority_boundries.size()) > priority); - - int index = m_pieces[elem_index]; - // update the piece_map - piece_pos& p = m_piece_map[index]; - TORRENT_ASSERT(int(p.index) == elem_index || p.have()); - - int new_priority = p.priority(this); - - if (new_priority == priority) return; - - if (new_priority == -1) - { - remove(priority, elem_index); - return; - } - - if (int(m_priority_boundries.size()) <= new_priority) - m_priority_boundries.resize(new_priority + 1, m_pieces.size()); - -#ifdef TORRENT_PICKER_LOG - std::cerr << "update " << index << " (" << priority << "->" << new_priority << ")" << std::endl; -#endif - if (priority > new_priority) - { - int new_index; - int temp = index; - for (;;) - { -#ifdef TORRENT_PICKER_LOG - print_pieces(); -#endif - --priority; - new_index = m_priority_boundries[priority]++; - TORRENT_ASSERT(new_index < int(m_pieces.size())); - if (temp != m_pieces[new_index]) - { - temp = m_pieces[new_index]; - m_pieces[elem_index] = temp; - m_piece_map[temp].index = elem_index; - TORRENT_ASSERT(elem_index < int(m_pieces.size())); - } - elem_index = new_index; - if (priority == new_priority) break; - } -#ifdef TORRENT_PICKER_LOG - print_pieces(); -#endif - m_pieces[elem_index] = index; - m_piece_map[index].index = elem_index; - TORRENT_ASSERT(elem_index < int(m_pieces.size())); -#ifdef TORRENT_PICKER_LOG - print_pieces(); -#endif - shuffle(priority, elem_index); -#ifdef TORRENT_PICKER_LOG - print_pieces(); -#endif - TORRENT_ASSERT(m_piece_map[index].priority(this) == priority); - } - else - { - int new_index; - int temp = index; - for (;;) - { -#ifdef TORRENT_PICKER_LOG - print_pieces(); -#endif - new_index = --m_priority_boundries[priority]; - TORRENT_ASSERT(new_index < int(m_pieces.size())); - if (temp != m_pieces[new_index]) - { - temp = m_pieces[new_index]; - m_pieces[elem_index] = temp; - m_piece_map[temp].index = elem_index; - TORRENT_ASSERT(elem_index < int(m_pieces.size())); - } - elem_index = new_index; - ++priority; - if (priority == new_priority) break; - } -#ifdef TORRENT_PICKER_LOG - print_pieces(); -#endif - m_pieces[elem_index] = index; - m_piece_map[index].index = elem_index; - TORRENT_ASSERT(elem_index < int(m_pieces.size())); -#ifdef TORRENT_PICKER_LOG - print_pieces(); -#endif - shuffle(priority, elem_index); -#ifdef TORRENT_PICKER_LOG - print_pieces(); -#endif - TORRENT_ASSERT(m_piece_map[index].priority(this) == priority); - } - } - - void piece_picker::shuffle(int priority, int elem_index) - { -#ifdef TORRENT_PICKER_LOG - std::cerr << "shuffle()" << std::endl; -#endif - - TORRENT_ASSERT(!m_dirty); - TORRENT_ASSERT(priority >= 0); - TORRENT_ASSERT(elem_index >= 0); - TORRENT_ASSERT(elem_index < int(m_pieces.size())); - TORRENT_ASSERT(m_piece_map[m_pieces[elem_index]].priority(this) == priority); - - int range_start, range_end; - priority_range(priority, &range_start, &range_end); - TORRENT_ASSERT(range_start < range_end); - int other_index = rand() % (range_end - range_start) + range_start; - - if (other_index == elem_index) return; - - // swap other_index with elem_index - piece_pos& p1 = m_piece_map[m_pieces[other_index]]; - piece_pos& p2 = m_piece_map[m_pieces[elem_index]]; - - int temp = p1.index; - p1.index = p2.index; - p2.index = temp; - std::swap(m_pieces[other_index], m_pieces[elem_index]); - } - - void piece_picker::sort_piece(std::vector::iterator dp) - { - TORRENT_ASSERT(m_piece_map[dp->index].downloading); - if (dp == m_downloads.begin()) return; - int complete = dp->writing + dp->finished; - for (std::vector::iterator i = dp, j(dp-1); - i != m_downloads.begin(); --i, --j) - { - TORRENT_ASSERT(j >= m_downloads.begin()); - if (j->finished + j->writing >= complete) return; - using std::swap; - swap(*j, *i); - if (j == m_downloads.begin()) break; - } - } - - void piece_picker::restore_piece(int index) - { - TORRENT_PIECE_PICKER_INVARIANT_CHECK; - - TORRENT_ASSERT(index >= 0); - TORRENT_ASSERT(index < (int)m_piece_map.size()); - - TORRENT_ASSERT(m_piece_map[index].downloading == 1); - - std::vector::iterator i - = std::find_if(m_downloads.begin(), m_downloads.end() - , has_index(index)); - - TORRENT_ASSERT(i != m_downloads.end()); -#ifdef TORRENT_DEBUG - int num_blocks = blocks_in_piece(i->index); - for (int k = 0; k < num_blocks; ++k) - { - TORRENT_ASSERT(i->info[k].state == block_info::state_finished); - TORRENT_ASSERT(i->info[k].num_peers == 0); - } -#endif - erase_download_piece(i); - - piece_pos& p = m_piece_map[index]; - int prev_priority = p.priority(this); - p.downloading = 0; - int new_priority = p.priority(this); - - if (new_priority == prev_priority) return; - if (m_dirty) return; - if (prev_priority == -1) - { - add(index); - } - else - { - update(prev_priority, p.index); - } - } - - void piece_picker::inc_refcount_all() - { - TORRENT_PIECE_PICKER_INVARIANT_CHECK; - ++m_seeds; - if (m_seeds == 1) - { - // when m_seeds is increased from 0 to 1 - // we may have to add pieces that previously - // didn't have any peers - m_dirty = true; - } - } - - void piece_picker::dec_refcount_all() - { - TORRENT_PIECE_PICKER_INVARIANT_CHECK; - - if (m_seeds > 0) - { - --m_seeds; - if (m_seeds == 0) - { - // when m_seeds is decreased from 1 to 0 - // we may have to remove pieces that previously - // didn't have any peers - m_dirty = true; - } - return; - } - TORRENT_ASSERT(m_seeds == 0); - - for (std::vector::iterator i = m_piece_map.begin() - , end(m_piece_map.end()); i != end; ++i) - { - TORRENT_ASSERT(i->peer_count > 0); - --i->peer_count; - } - - m_dirty = true; - } - - void piece_picker::inc_refcount(int index) - { -#ifdef TORRENT_EXPENSIVE_INVARIANT_CHECKS - TORRENT_PIECE_PICKER_INVARIANT_CHECK; -#endif - - piece_pos& p = m_piece_map[index]; - - int prev_priority = p.priority(this); - ++p.peer_count; - if (m_dirty) return; - int new_priority = p.priority(this); - if (prev_priority == new_priority) return; - if (prev_priority == -1) - add(index); - else - update(prev_priority, p.index); - } - - void piece_picker::dec_refcount(int index) - { -#ifdef TORRENT_EXPENSIVE_INVARIANT_CHECKS - TORRENT_PIECE_PICKER_INVARIANT_CHECK; -#endif - - piece_pos& p = m_piece_map[index]; - int prev_priority = p.priority(this); - TORRENT_ASSERT(p.peer_count > 0); - --p.peer_count; - if (m_dirty) return; - if (prev_priority >= 0) update(prev_priority, p.index); - } - - void piece_picker::inc_refcount(bitfield const& bitmask) - { - TORRENT_PIECE_PICKER_INVARIANT_CHECK; - TORRENT_ASSERT(bitmask.size() == m_piece_map.size()); - - int index = 0; - bool updated = false; - for (bitfield::const_iterator i = bitmask.begin() - , end(bitmask.end()); i != end; ++i, ++index) - { - if (*i) - { - ++m_piece_map[index].peer_count; - updated = true; - } - } - - if (updated) m_dirty = true; - } - - void piece_picker::dec_refcount(bitfield const& bitmask) - { - TORRENT_PIECE_PICKER_INVARIANT_CHECK; - TORRENT_ASSERT(bitmask.size() == m_piece_map.size()); - - int index = 0; - bool updated = false; - for (bitfield::const_iterator i = bitmask.begin() - , end(bitmask.end()); i != end; ++i, ++index) - { - if (*i) - { - --m_piece_map[index].peer_count; - updated = true; - } - } - - if (updated) m_dirty = true; - } - - void piece_picker::update_pieces() const - { - TORRENT_ASSERT(m_dirty); - if (m_priority_boundries.empty()) m_priority_boundries.resize(1, 0); -#ifdef TORRENT_PICKER_LOG - std::cerr << "update_pieces" << std::endl; -#endif - std::fill(m_priority_boundries.begin(), m_priority_boundries.end(), 0); - for (std::vector::iterator i = m_piece_map.begin() - , end(m_piece_map.end()); i != end; ++i) - { - int prio = i->priority(this); - if (prio == -1) continue; - if (prio >= int(m_priority_boundries.size())) - m_priority_boundries.resize(prio + 1, 0); - i->index = m_priority_boundries[prio]; - ++m_priority_boundries[prio]; - } - -#ifdef TORRENT_PICKER_LOG - print_pieces(); -#endif - - int index = 0; - for (std::vector::iterator i = m_priority_boundries.begin() - , end(m_priority_boundries.end()); i != end; ++i) - { - *i += index; - index = *i; - } - m_pieces.resize(index, 0); - -#ifdef TORRENT_PICKER_LOG - print_pieces(); -#endif - - index = 0; - for (std::vector::iterator i = m_piece_map.begin() - , end(m_piece_map.end()); i != end; ++i, ++index) - { - piece_pos& p = *i; - int prio = p.priority(this); - if (prio == -1) continue; - int new_index = (prio == 0 ? 0 : m_priority_boundries[prio - 1]) + p.index; - m_pieces[new_index] = index; - } - - int start = 0; - for (std::vector::iterator i = m_priority_boundries.begin() - , end(m_priority_boundries.end()); i != end; ++i) - { - if (start == *i) continue; - std::random_shuffle(&m_pieces[0] + start, &m_pieces[0] + *i); - start = *i; - } - - index = 0; - for (std::vector::const_iterator i = m_pieces.begin() - , end(m_pieces.end()); i != end; ++i, ++index) - { - TORRENT_ASSERT(*i >= 0 && *i < int(m_piece_map.size())); - m_piece_map[*i].index = index; - } - - m_dirty = false; -#ifdef TORRENT_PICKER_LOG - print_pieces(); -#endif - } - - void piece_picker::we_dont_have(int index) - { - TORRENT_PIECE_PICKER_INVARIANT_CHECK; - TORRENT_ASSERT(index >= 0); - TORRENT_ASSERT(index < (int)m_piece_map.size()); - - piece_pos& p = m_piece_map[index]; - TORRENT_ASSERT(p.downloading == 0); - -#ifdef TORRENT_PICKER_LOG - std::cerr << "piece_picker::we_dont_have(" << index << ")" << std::endl; -#endif - if (!p.have()) return; - - if (p.filtered()) - { - ++m_num_filtered; - --m_num_have_filtered; - } - else - { - // update cursors - if (index < m_cursor) - m_cursor = index; - if (index >= m_reverse_cursor) - m_reverse_cursor = index + 1; - if (m_reverse_cursor == m_cursor) - { - m_reverse_cursor = 0; - m_cursor = num_pieces(); - } - } - - --m_num_have; - p.set_not_have(); - - if (m_dirty) return; - if (p.priority(this) >= 0) add(index); - } - - // this is used to indicate that we succesfully have - // downloaded a piece, and that no further attempts - // to pick that piece should be made. The piece will - // be removed from the available piece list. - void piece_picker::we_have(int index) - { -#ifdef TORRENT_EXPENSIVE_INVARIANT_CHECKS - TORRENT_PIECE_PICKER_INVARIANT_CHECK; -#endif - TORRENT_ASSERT(index >= 0); - TORRENT_ASSERT(index < (int)m_piece_map.size()); - -#ifdef TORRENT_PICKER_LOG - std::cerr << "piece_picker::we_have(" << index << ")" << std::endl; -#endif - piece_pos& p = m_piece_map[index]; - int info_index = p.index; - int priority = p.priority(this); - TORRENT_ASSERT(priority < int(m_priority_boundries.size()) || m_dirty); - - if (p.downloading) - { - std::vector::iterator i - = std::find_if(m_downloads.begin() - , m_downloads.end() - , has_index(index)); - TORRENT_ASSERT(i != m_downloads.end()); - erase_download_piece(i); - p.downloading = 0; - } - - TORRENT_ASSERT(std::find_if(m_downloads.begin(), m_downloads.end() - , has_index(index)) == m_downloads.end()); - - if (p.have()) return; - if (p.filtered()) - { - --m_num_filtered; - ++m_num_have_filtered; - } - ++m_num_have; - p.set_have(); - if (m_cursor == m_reverse_cursor - 1 && - m_cursor == index) - { - m_cursor = int(m_piece_map.size()); - m_reverse_cursor = 0; - TORRENT_ASSERT(num_pieces() > 0); - } - else if (m_cursor == index) - { - ++m_cursor; - for (std::vector::const_iterator i = m_piece_map.begin() + m_cursor - , end(m_piece_map.end()); i != end && (i->have() || i->filtered()); - ++i, ++m_cursor); - } - else if (m_reverse_cursor - 1 == index) - { - --m_reverse_cursor; - TORRENT_ASSERT(m_piece_map[m_reverse_cursor].have() - || m_piece_map[m_reverse_cursor].filtered()); - for (std::vector::const_iterator i = m_piece_map.begin() - + m_reverse_cursor - 1; m_reverse_cursor > 0 && (i->have() || i->filtered()); - --i, --m_reverse_cursor); - TORRENT_ASSERT(m_piece_map[m_reverse_cursor].have() - || m_piece_map[m_reverse_cursor].filtered()); - } - TORRENT_ASSERT(m_reverse_cursor > m_cursor - || (m_cursor == num_pieces() && m_reverse_cursor == 0)); - if (priority == -1) return; - if (m_dirty) return; - remove(priority, info_index); - TORRENT_ASSERT(p.priority(this) == -1); - } - - bool piece_picker::set_piece_priority(int index, int new_piece_priority) - { -#ifdef TORRENT_EXPENSIVE_INVARIANT_CHECKS - TORRENT_PIECE_PICKER_INVARIANT_CHECK; -#endif - TORRENT_ASSERT(new_piece_priority >= 0); - TORRENT_ASSERT(new_piece_priority <= 7); - TORRENT_ASSERT(index >= 0); - TORRENT_ASSERT(index < (int)m_piece_map.size()); - - piece_pos& p = m_piece_map[index]; - - // if the priority isn't changed, don't do anything - if (new_piece_priority == int(p.piece_priority)) return false; - - int prev_priority = p.priority(this); - TORRENT_ASSERT(m_dirty || prev_priority < int(m_priority_boundries.size())); - - bool ret = false; - if (new_piece_priority == piece_pos::filter_priority - && p.piece_priority != piece_pos::filter_priority) - { - // the piece just got filtered - if (p.have()) - { - ++m_num_have_filtered; - } - else - { - ++m_num_filtered; - - // update m_cursor - if (m_cursor == m_reverse_cursor - 1 && m_cursor == index) - { - m_cursor = int(m_piece_map.size()); - m_reverse_cursor = 0; - } - else if (m_cursor == index) - { - ++m_cursor; - while (m_cursor < int(m_piece_map.size()) - && (m_piece_map[m_cursor].have() - || m_piece_map[m_cursor].filtered())) - ++m_cursor; - } - else if (m_reverse_cursor == index + 1) - { - --m_reverse_cursor; - while (m_reverse_cursor > 0 - && (m_piece_map[m_reverse_cursor-1].have() - || m_piece_map[m_reverse_cursor-1].filtered())) - --m_reverse_cursor; - } - } - ret = true; - } - else if (new_piece_priority != piece_pos::filter_priority - && p.piece_priority == piece_pos::filter_priority) - { - // the piece just got unfiltered - if (p.have()) - { - --m_num_have_filtered; - } - else - { - --m_num_filtered; - // update cursors - if (index < m_cursor) - m_cursor = index; - if (index >= m_reverse_cursor) - m_reverse_cursor = index + 1; - if (m_reverse_cursor == m_cursor) - { - m_reverse_cursor = 0; - m_cursor = num_pieces(); - } - } - ret = true; - } - TORRENT_ASSERT(m_num_filtered >= 0); - TORRENT_ASSERT(m_num_have_filtered >= 0); - - p.piece_priority = new_piece_priority; - int new_priority = p.priority(this); - - if (prev_priority == new_priority) return ret; - - if (m_dirty) return ret; - if (prev_priority == -1) - { - add(index); - } - else - { - update(prev_priority, p.index); - } - return ret; - } - - int piece_picker::piece_priority(int index) const - { - TORRENT_ASSERT(index >= 0); - TORRENT_ASSERT(index < (int)m_piece_map.size()); - - return m_piece_map[index].piece_priority; - } - - void piece_picker::piece_priorities(std::vector& pieces) const - { - pieces.resize(m_piece_map.size()); - std::vector::iterator j = pieces.begin(); - for (std::vector::const_iterator i = m_piece_map.begin(), - end(m_piece_map.end()); i != end; ++i, ++j) - { - *j = i->piece_priority; - } - } - - // ============ start deprecation ============== - - void piece_picker::filtered_pieces(std::vector& mask) const - { - mask.resize(m_piece_map.size()); - std::vector::iterator j = mask.begin(); - for (std::vector::const_iterator i = m_piece_map.begin(), - end(m_piece_map.end()); i != end; ++i, ++j) - { - *j = i->filtered(); - } - } - - // ============ end deprecation ============== - - namespace - { - int append_blocks(std::vector& dst, std::vector& src - , int num_blocks) - { - if (src.empty()) return num_blocks; - int to_copy; -// if (prefer_whole_pieces == 0) - to_copy = (std::min)(int(src.size()), num_blocks); -// else -// to_copy = int(src.size()); - - dst.insert(dst.end() - , src.begin(), src.begin() + to_copy); - src.clear(); - return num_blocks - to_copy; - } - } - - // pieces describes which pieces the peer we're requesting from - // has. - // interesting_blocks is an out parameter, and will be filled - // with (up to) num_blocks of interesting blocks that the peer has. - // prefer_whole_pieces can be set if this peer should download - // whole pieces rather than trying to download blocks from the - // same piece as other peers. - // the void* is the pointer to the policy::peer of the peer we're - // picking pieces from. This is used when downloading whole pieces, - // to only pick from the same piece the same peer is downloading - // from. state is supposed to be set to fast if the peer is downloading - // relatively fast, by some notion. Slow peers will prefer not - // to pick blocks from the same pieces as fast peers, and vice - // versa. Downloading pieces are marked as being fast, medium - // or slow once they're started. - - // options are: - // * rarest_first - // pick the rarest pieces first - // * reverse - // reverse the piece picking. Pick the most common - // pieces first or the last pieces (if picking sequential) - // * sequential - // download pieces in-order - // * on_parole - // the peer is on parole, only pick whole pieces which - // has only been downloaded and requested from the same - // peer - // * prioritize_partials - // pick blocks from downloading pieces first - - // only one of rarest_first, sequential can be set - - void piece_picker::pick_pieces(bitfield const& pieces - , std::vector& interesting_blocks, int num_blocks - , int prefer_whole_pieces, void* peer, piece_state_t speed - , int options, std::vector const& suggested_pieces) const - { - // prevent the number of partial pieces to grow indefinitely - if (m_downloads.size() > 20) options |= prioritize_partials; - - // only one of rarest_first and sequential can be set. - TORRENT_ASSERT(bool(options & rarest_first) - + bool(options & sequential) <= 1); -#ifdef TORRENT_EXPENSIVE_INVARIANT_CHECKS - TORRENT_PIECE_PICKER_INVARIANT_CHECK; -#endif - TORRENT_ASSERT(num_blocks > 0); - TORRENT_ASSERT(pieces.size() == m_piece_map.size()); - - TORRENT_ASSERT(!m_priority_boundries.empty() - || m_dirty); - - // this will be filled with blocks that we should not request - // unless we can't find num_blocks among the other ones. - // blocks that belong to pieces with a mismatching speed - // category for instance, or if we prefer whole pieces, - // blocks belonging to a piece that others have - // downloaded to - std::vector backup_blocks; - std::vector backup_blocks2; - const std::vector empty_vector; - - // When prefer_whole_pieces is set (usually set when downloading from - // fast peers) the partial pieces will not be prioritized, but actually - // ignored as long as possible. All blocks found in downloading - // pieces are regarded as backup blocks - - if (options & prioritize_partials) - { - for (std::vector::const_iterator i = m_downloads.begin() - , end(m_downloads.end()); i != end; ++i) - { - if (!pieces[i->index]) continue; - num_blocks = add_blocks_downloading(*i, pieces - , interesting_blocks, backup_blocks, backup_blocks2 - , num_blocks, prefer_whole_pieces, peer, speed, options); - if (num_blocks <= 0) return; - } - - num_blocks = append_blocks(interesting_blocks, backup_blocks - , num_blocks); - if (num_blocks <= 0) return; - - num_blocks = append_blocks(interesting_blocks, backup_blocks2 - , num_blocks); - if (num_blocks <= 0) return; - } - - if (!suggested_pieces.empty()) - { - for (std::vector::const_iterator i = suggested_pieces.begin(); - i != suggested_pieces.end(); ++i) - { - if (!is_piece_free(*i, pieces)) continue; - num_blocks = add_blocks(*i, pieces - , interesting_blocks, backup_blocks - , backup_blocks2, num_blocks - , prefer_whole_pieces, peer, empty_vector - , speed, options); - if (num_blocks <= 0) return; - } - } - - if (options & sequential) - { - if (options & reverse) - { - for (int i = m_reverse_cursor - 1; i >= m_cursor; --i) - { - if (!is_piece_free(i, pieces)) continue; - num_blocks = add_blocks(i, pieces - , interesting_blocks, backup_blocks - , backup_blocks2, num_blocks - , prefer_whole_pieces, peer, suggested_pieces - , speed, options); - if (num_blocks <= 0) return; - } - } - else - { - for (int i = m_cursor; i < m_reverse_cursor; ++i) - { - if (!is_piece_free(i, pieces)) continue; - num_blocks = add_blocks(i, pieces - , interesting_blocks, backup_blocks - , backup_blocks2, num_blocks - , prefer_whole_pieces, peer, suggested_pieces - , speed, options); - if (num_blocks <= 0) return; - } - } - } - else if (options & rarest_first) - { - if (m_dirty) update_pieces(); - TORRENT_ASSERT(!m_dirty); - - if (options & reverse) - { - // it's a bit complicated in order to always prioritize - // partial pieces, and respect priorities. Every chunk - // of 4 priority levels are traversed in forward order, but otherwise - // they are traversed in reverse order - // round up to an even 4 priority boundry, to make it simpler - // to do the akward reverse traversing -#define div_round_up(n, d) (((n) + (d) - 1) / (d)) - m_priority_boundries.resize(div_round_up(m_priority_boundries.size() - , prio_factor) * prio_factor, m_priority_boundries.back()); - for (int i = m_priority_boundries.size() - 1; i >= 0; --i) - { - int prio = (i / prio_factor) * prio_factor - + prio_factor - 1 - (i % prio_factor); - - TORRENT_ASSERT(prio >= 0); - TORRENT_ASSERT(prio < int(m_priority_boundries.size())); - int start = prio == 0 ? 0 : m_priority_boundries[prio - 1]; - for (int p = start; p < m_priority_boundries[prio]; ++p) - { - if (!is_piece_free(m_pieces[p], pieces)) continue; - num_blocks = add_blocks(m_pieces[p], pieces - , interesting_blocks, backup_blocks - , backup_blocks2, num_blocks - , prefer_whole_pieces, peer, suggested_pieces - , speed, options); - if (num_blocks <= 0) return; - } - } -#undef div_round_up - } - else - { - for (std::vector::const_iterator i = m_pieces.begin(); - i != m_pieces.end(); ++i) - { - if (!is_piece_free(*i, pieces)) continue; - num_blocks = add_blocks(*i, pieces - , interesting_blocks, backup_blocks - , backup_blocks2, num_blocks - , prefer_whole_pieces, peer, suggested_pieces - , speed, options); - if (num_blocks <= 0) return; - } - } - } - else - { - // we're not using rarest first (only for the first - // bucket, since that's where the currently downloading - // pieces are) - int start_piece = std::rand() % m_piece_map.size(); - - int piece = start_piece; - while (num_blocks > 0) - { - bool done = false; - // skip pieces we can't pick, and suggested pieces - // since we've already picked those - while (!can_pick(piece, pieces) - && std::find(suggested_pieces.begin() - , suggested_pieces.end(), piece) - == suggested_pieces.end()) - { - ++piece; - if (piece == int(m_piece_map.size())) piece = 0; - // could not find any more pieces - if (piece == start_piece) { done = true; break; } - } - if (done) break; - - int start, end; - boost::tie(start, end) = expand_piece(piece, prefer_whole_pieces, pieces); - for (int k = start; k < end; ++k) - { - TORRENT_ASSERT(m_piece_map[piece].downloading == false); - TORRENT_ASSERT(m_piece_map[k].priority(this) >= 0); - int num_blocks_in_piece = blocks_in_piece(k); - if (prefer_whole_pieces == 0 && num_blocks_in_piece > num_blocks) - num_blocks_in_piece = num_blocks; - for (int j = 0; j < num_blocks_in_piece; ++j) - { - interesting_blocks.push_back(piece_block(k, j)); - --num_blocks; - } - } - piece = end; - if (piece == int(m_piece_map.size())) piece = 0; - // could not find any more pieces - if (piece == start_piece) break; - } - - } - - if (num_blocks <= 0) return; - -#ifdef TORRENT_DEBUG - verify_pick(interesting_blocks, pieces); - verify_pick(backup_blocks, pieces); - verify_pick(backup_blocks2, pieces); -#endif - - num_blocks = append_blocks(interesting_blocks, backup_blocks - , num_blocks); - if (num_blocks <= 0) return; - - num_blocks = append_blocks(interesting_blocks, backup_blocks2 - , num_blocks); - if (num_blocks <= 0) return; - - // don't double-pick anything if the peer is on parole - if (options & on_parole) return; - - for (std::vector::const_iterator i = m_downloads.begin() - , end(m_downloads.end()); i != end; ++i) - { - if (!pieces[i->index]) continue; - if (piece_priority(i->index) == 0) continue; - - int num_blocks_in_piece = blocks_in_piece(i->index); - - // fill in with blocks requested from other peers - // as backups - for (int j = 0; j < num_blocks_in_piece; ++j) - { - block_info const& info = i->info[j]; - if (info.state != block_info::state_requested - || info.peer == peer) - continue; - interesting_blocks.push_back(piece_block(i->index, j)); - } - } - -#ifdef TORRENT_DEBUG -// make sure that we at this point have added requests to all unrequested blocks -// in all downloading pieces - - for (std::vector::const_iterator i = m_downloads.begin() - , end(m_downloads.end()); i != end; ++i) - { - if (!pieces[i->index]) continue; - if (piece_priority(i->index) == 0) continue; - - int num_blocks_in_piece = blocks_in_piece(i->index); - for (int j = 0; j < num_blocks_in_piece; ++j) - { - block_info const& info = i->info[j]; - if (info.state != block_info::state_none) continue; - std::vector::iterator k = std::find( - interesting_blocks.begin(), interesting_blocks.end() - , piece_block(i->index, j)); - if (k != interesting_blocks.end()) continue; - - std::cerr << "interesting blocks:" << std::endl; - for (k = interesting_blocks.begin(); k != interesting_blocks.end(); ++k) - std::cerr << "(" << k->piece_index << ", " << k->block_index << ") "; - std::cerr << std::endl; - std::cerr << "num_blocks: " << num_blocks << std::endl; - - for (std::vector::const_iterator l = m_downloads.begin() - , end(m_downloads.end()); l != end; ++l) - { - std::cerr << l->index << " : "; - int num_blocks_in_piece = blocks_in_piece(l->index); - for (int m = 0; m < num_blocks_in_piece; ++m) - std::cerr << l->info[m].state; - std::cerr << std::endl; - } - - TORRENT_ASSERT(false); - } - } - - if (interesting_blocks.empty()) - { -// print_pieces(); - for (int i = 0; i < num_pieces(); ++i) - { - if (!pieces[i]) continue; - if (piece_priority(i) == 0) continue; - if (have_piece(i)) continue; - - std::vector::const_iterator k - = std::find_if(m_downloads.begin(), m_downloads.end(), has_index(i)); - - TORRENT_ASSERT(k != m_downloads.end()); - if (k == m_downloads.end()) continue; - - // this assert is not valid for web_seeds - /* - int num_blocks_in_piece = blocks_in_piece(k->index); - for (int j = 0; j < num_blocks_in_piece; ++j) - { - block_info const& info = k->info[j]; - if (info.state == block_info::state_finished) continue; - TORRENT_ASSERT(info.peer != 0); - } - */ - } - } -#endif - - } - - bool piece_picker::is_piece_free(int piece, bitfield const& bitmask) const - { - TORRENT_ASSERT(piece >= 0 && piece < int(m_piece_map.size())); - return bitmask[piece] - && !m_piece_map[piece].have() - && !m_piece_map[piece].filtered(); - } - - bool piece_picker::can_pick(int piece, bitfield const& bitmask) const - { - TORRENT_ASSERT(piece >= 0 && piece < int(m_piece_map.size())); - return bitmask[piece] - && !m_piece_map[piece].have() - && !m_piece_map[piece].downloading - && !m_piece_map[piece].filtered(); - } - - void piece_picker::clear_peer(void* peer) - { - for (std::vector::iterator i = m_block_info.begin() - , end(m_block_info.end()); i != end; ++i) - if (i->peer == peer) i->peer = 0; - } - - namespace - { - // the first bool is true if this is the only peer that has requested and downloaded - // blocks from this piece. - // the second bool is true if this is the only active peer that is requesting - // and downloading blocks from this piece. Active means having a connection. - boost::tuple requested_from(piece_picker::downloading_piece const& p - , int num_blocks_in_piece, void* peer) - { - bool exclusive = true; - bool exclusive_active = true; - for (int j = 0; j < num_blocks_in_piece; ++j) - { - piece_picker::block_info const& info = p.info[j]; - if (info.state != piece_picker::block_info::state_none - && info.peer != peer) - { - exclusive = false; - if (info.state == piece_picker::block_info::state_requested - && info.peer != 0) - { - exclusive_active = false; - return boost::make_tuple(exclusive, exclusive_active); - } - } - } - return boost::make_tuple(exclusive, exclusive_active); - } - } - - int piece_picker::add_blocks(int piece - , bitfield const& pieces - , std::vector& interesting_blocks - , std::vector& backup_blocks - , std::vector& backup_blocks2 - , int num_blocks, int prefer_whole_pieces - , void* peer, std::vector const& ignore - , piece_state_t speed, int options) const - { - TORRENT_ASSERT(piece >= 0); - TORRENT_ASSERT(piece < (int)m_piece_map.size()); - TORRENT_ASSERT(is_piece_free(piece, pieces)); - -// std::cout << "add_blocks(" << piece << ")" << std::endl; -// std::cout << " num_blocks " << num_blocks << std::endl; - - // ignore pieces found in the ignore list - if (std::find(ignore.begin(), ignore.end(), piece) != ignore.end()) return num_blocks; - - TORRENT_ASSERT(m_piece_map[piece].priority(this) >= 0); - if (m_piece_map[piece].downloading) - { - // if we're prioritizing partials, we've already - // looked through the downloading pieces - if (options & prioritize_partials) return num_blocks; - - std::vector::const_iterator i - = std::find_if(m_downloads.begin(), m_downloads.end(), has_index(piece)); - TORRENT_ASSERT(i != m_downloads.end()); - -// std::cout << "add_blocks_downloading(" << piece << ")" << std::endl; - - return add_blocks_downloading(*i, pieces - , interesting_blocks, backup_blocks, backup_blocks2 - , num_blocks, prefer_whole_pieces, peer, speed, options); - } - - int num_blocks_in_piece = blocks_in_piece(piece); - - // pick a new piece - if (prefer_whole_pieces == 0) - { - if (num_blocks_in_piece > num_blocks) - num_blocks_in_piece = num_blocks; - for (int j = 0; j < num_blocks_in_piece; ++j) - interesting_blocks.push_back(piece_block(piece, j)); - num_blocks -= num_blocks_in_piece; - } - else - { - int start, end; - boost::tie(start, end) = expand_piece(piece, prefer_whole_pieces, pieces); - for (int k = start; k < end; ++k) - { - TORRENT_ASSERT(m_piece_map[k].priority(this) > 0); - num_blocks_in_piece = blocks_in_piece(k); - for (int j = 0; j < num_blocks_in_piece; ++j) - { - interesting_blocks.push_back(piece_block(k, j)); - --num_blocks; - } - } - } -#ifdef TORRENT_DEBUG - verify_pick(interesting_blocks, pieces); -#endif - if (num_blocks <= 0) return 0; - return num_blocks; - } - - int piece_picker::add_blocks_downloading(downloading_piece const& dp - , bitfield const& pieces - , std::vector& interesting_blocks - , std::vector& backup_blocks - , std::vector& backup_blocks2 - , int num_blocks, int prefer_whole_pieces - , void* peer, piece_state_t speed, int options) const - { - if (!pieces[dp.index]) return num_blocks; - - int num_blocks_in_piece = blocks_in_piece(dp.index); - - // is true if all the other pieces that are currently - // requested from this piece are from the same - // peer as 'peer'. - bool exclusive; - bool exclusive_active; - boost::tie(exclusive, exclusive_active) - = requested_from(dp, num_blocks_in_piece, peer); - - // peers on parole are only allowed to pick blocks from - // pieces that only they have downloaded/requested from - if ((options & on_parole) && !exclusive) return num_blocks; - - // we prefer whole blocks, but there are other peers - // downloading from this piece, add it as backups - if (prefer_whole_pieces > 0 && !exclusive_active) - { - if (int(backup_blocks2.size()) >= num_blocks) - return num_blocks; - - for (int j = 0; j < num_blocks_in_piece; ++j) - { - // ignore completed blocks and already requested blocks - block_info const& info = dp.info[j]; - if (info.state != block_info::state_none) continue; - backup_blocks2.push_back(piece_block(dp.index, j)); - } - return num_blocks; - } - - for (int j = 0; j < num_blocks_in_piece; ++j) - { - // ignore completed blocks and already requested blocks - block_info const& info = dp.info[j]; - if (info.state != block_info::state_none) continue; - - TORRENT_ASSERT(dp.info[j].state == block_info::state_none); - - // if the piece is fast and the peer is slow, or vice versa, - // add the block as a backup. - // override this behavior if all the other blocks - // have been requested from the same peer or - // if the state of the piece is none (the - // piece will in that case change state). - if (dp.state != none && dp.state != speed - && !exclusive_active) - { - if (abs(dp.state - speed) == 1) - { - // don't pick too many back-up blocks - if (int(backup_blocks.size()) >= num_blocks) return num_blocks; - backup_blocks.push_back(piece_block(dp.index, j)); - } - else - { - // don't pick too many back-up blocks - if (int(backup_blocks2.size()) >= num_blocks) return num_blocks; - backup_blocks2.push_back(piece_block(dp.index, j)); - } - continue; - } - - // this block is interesting (we don't have it - // yet). - interesting_blocks.push_back(piece_block(dp.index, j)); - // we have found a block that's free to download - num_blocks--; - // if we prefer whole pieces, continue picking from this - // piece even though we have num_blocks - if (prefer_whole_pieces > 0) continue; - TORRENT_ASSERT(num_blocks >= 0); - if (num_blocks <= 0) return num_blocks; - } - - TORRENT_ASSERT(num_blocks >= 0 || prefer_whole_pieces > 0); - - if (num_blocks <= 0) return 0; - if (options & on_parole) return num_blocks; - - if (int(backup_blocks.size()) >= num_blocks) return num_blocks; - -#ifdef TORRENT_DEBUG - verify_pick(backup_blocks, pieces); -#endif - return num_blocks; - } - - std::pair piece_picker::expand_piece(int piece, int whole_pieces - , bitfield const& have) const - { - if (whole_pieces == 0) return std::make_pair(piece, piece + 1); - - int start = piece - 1; - int lower_limit = piece - whole_pieces; - if (lower_limit < -1) lower_limit = -1; - while (start > lower_limit - && can_pick(start, have)) - --start; - ++start; - TORRENT_ASSERT(start >= 0); - int end = piece + 1; - int upper_limit = start + whole_pieces; - if (upper_limit > int(m_piece_map.size())) upper_limit = int(m_piece_map.size()); - while (end < upper_limit - && can_pick(end, have)) - ++end; - return std::make_pair(start, end); - } - - bool piece_picker::is_piece_finished(int index) const - { - TORRENT_ASSERT(index < (int)m_piece_map.size()); - TORRENT_ASSERT(index >= 0); - - if (m_piece_map[index].downloading == 0) - { - TORRENT_ASSERT(std::find_if(m_downloads.begin(), m_downloads.end() - , has_index(index)) == m_downloads.end()); - return false; - } - std::vector::const_iterator i - = std::find_if(m_downloads.begin(), m_downloads.end(), has_index(index)); - TORRENT_ASSERT(i != m_downloads.end()); - TORRENT_ASSERT((int)i->finished <= m_blocks_per_piece); - int max_blocks = blocks_in_piece(index); - if ((int)i->finished < max_blocks) return false; - -#ifdef TORRENT_DEBUG - for (int k = 0; k < max_blocks; ++k) - { - TORRENT_ASSERT(i->info[k].state == block_info::state_finished); - } -#endif - - TORRENT_ASSERT((int)i->finished == max_blocks); - return true; - } - - bool piece_picker::is_requested(piece_block block) const - { - TORRENT_ASSERT(block.piece_index >= 0); - TORRENT_ASSERT(block.block_index >= 0); - TORRENT_ASSERT(block.piece_index < (int)m_piece_map.size()); - - if (m_piece_map[block.piece_index].downloading == 0) return false; - std::vector::const_iterator i - = std::find_if( - m_downloads.begin() - , m_downloads.end() - , has_index(block.piece_index)); - - TORRENT_ASSERT(i != m_downloads.end()); - return i->info[block.block_index].state == block_info::state_requested; - } - - bool piece_picker::is_downloaded(piece_block block) const - { - TORRENT_ASSERT(block.piece_index >= 0); - TORRENT_ASSERT(block.block_index >= 0); - TORRENT_ASSERT(block.piece_index < (int)m_piece_map.size()); - - if (m_piece_map[block.piece_index].index == piece_pos::we_have_index) return true; - if (m_piece_map[block.piece_index].downloading == 0) return false; - std::vector::const_iterator i - = std::find_if(m_downloads.begin(), m_downloads.end(), has_index(block.piece_index)); - TORRENT_ASSERT(i != m_downloads.end()); - return i->info[block.block_index].state == block_info::state_finished - || i->info[block.block_index].state == block_info::state_writing; - } - - bool piece_picker::is_finished(piece_block block) const - { - TORRENT_ASSERT(block.piece_index >= 0); - TORRENT_ASSERT(block.block_index >= 0); - TORRENT_ASSERT(block.piece_index < (int)m_piece_map.size()); - - if (m_piece_map[block.piece_index].index == piece_pos::we_have_index) return true; - if (m_piece_map[block.piece_index].downloading == 0) return false; - std::vector::const_iterator i - = std::find_if(m_downloads.begin(), m_downloads.end(), has_index(block.piece_index)); - TORRENT_ASSERT(i != m_downloads.end()); - return i->info[block.block_index].state == block_info::state_finished; - } - - bool piece_picker::mark_as_downloading(piece_block block - , void* peer, piece_state_t state) - { - TORRENT_ASSERT(state != piece_picker::none); - TORRENT_ASSERT(block.piece_index >= 0); - TORRENT_ASSERT(block.block_index >= 0); - TORRENT_ASSERT(block.piece_index < (int)m_piece_map.size()); - TORRENT_ASSERT(block.block_index < blocks_in_piece(block.piece_index)); - TORRENT_ASSERT(!m_piece_map[block.piece_index].have()); - - piece_pos& p = m_piece_map[block.piece_index]; - if (p.downloading == 0) - { -#ifdef TORRENT_EXPENSIVE_INVARIANT_CHECKS - TORRENT_PIECE_PICKER_INVARIANT_CHECK; -#endif - int prio = p.priority(this); - TORRENT_ASSERT(prio < int(m_priority_boundries.size()) - || m_dirty); - TORRENT_ASSERT(prio >= 0); - p.downloading = 1; - if (prio >= 0 && !m_dirty) update(prio, p.index); - - downloading_piece& dp = add_download_piece(); - dp.state = state; - dp.index = block.piece_index; - block_info& info = dp.info[block.block_index]; - info.state = block_info::state_requested; - info.peer = peer; - info.num_peers = 1; - ++dp.requested; - } - else - { -#ifdef TORRENT_EXPENSIVE_INVARIANT_CHECKS - TORRENT_PIECE_PICKER_INVARIANT_CHECK; -#endif - std::vector::iterator i - = std::find_if(m_downloads.begin(), m_downloads.end(), has_index(block.piece_index)); - TORRENT_ASSERT(i != m_downloads.end()); - block_info& info = i->info[block.block_index]; - if (info.state == block_info::state_writing - || info.state == block_info::state_finished) - return false; - TORRENT_ASSERT(info.state == block_info::state_none - || (info.state == block_info::state_requested - && (info.num_peers > 0))); - info.peer = peer; - if (info.state != block_info::state_requested) - { - info.state = block_info::state_requested; - ++i->requested; - } - ++info.num_peers; - if (i->state == none) i->state = state; - } - return true; - } - - int piece_picker::num_peers(piece_block block) const - { - TORRENT_ASSERT(block.piece_index >= 0); - TORRENT_ASSERT(block.block_index >= 0); - TORRENT_ASSERT(block.piece_index < (int)m_piece_map.size()); - TORRENT_ASSERT(block.block_index < blocks_in_piece(block.piece_index)); - - piece_pos const& p = m_piece_map[block.piece_index]; - if (!p.downloading) return 0; - - std::vector::const_iterator i - = std::find_if(m_downloads.begin(), m_downloads.end(), has_index(block.piece_index)); - TORRENT_ASSERT(i != m_downloads.end()); - - block_info const& info = i->info[block.block_index]; - return info.num_peers; - } - - void piece_picker::get_availability(std::vector& avail) const - { - TORRENT_ASSERT(m_seeds >= 0); - TORRENT_PIECE_PICKER_INVARIANT_CHECK; - - avail.resize(m_piece_map.size()); - std::vector::iterator j = avail.begin(); - for (std::vector::const_iterator i = m_piece_map.begin() - , end(m_piece_map.end()); i != end; ++i, ++j) - *j = i->peer_count + m_seeds; - } - - void piece_picker::mark_as_writing(piece_block block, void* peer) - { -#ifdef TORRENT_EXPENSIVE_INVARIANT_CHECKS - TORRENT_PIECE_PICKER_INVARIANT_CHECK; -#endif - - TORRENT_ASSERT(block.piece_index >= 0); - TORRENT_ASSERT(block.block_index >= 0); - TORRENT_ASSERT(block.piece_index < (int)m_piece_map.size()); - TORRENT_ASSERT(block.block_index < blocks_in_piece(block.piece_index)); - - TORRENT_ASSERT(m_piece_map[block.piece_index].downloading); - - std::vector::iterator i - = std::find_if(m_downloads.begin(), m_downloads.end(), has_index(block.piece_index)); - TORRENT_ASSERT(i != m_downloads.end()); - block_info& info = i->info[block.block_index]; - - info.peer = peer; - TORRENT_ASSERT(info.state == block_info::state_requested); - if (info.state == block_info::state_requested) --i->requested; - TORRENT_ASSERT(i->requested >= 0); - TORRENT_ASSERT(info.state != block_info::state_writing); - ++i->writing; - info.state = block_info::state_writing; - - // all other requests for this block should have been - // cancelled now - info.num_peers = 0; - - if (i->requested == 0) - { - // there are no blocks requested in this piece. - // remove the fast/slow state from it - i->state = none; - } - sort_piece(i); - } - - void piece_picker::write_failed(piece_block block) - { - TORRENT_PIECE_PICKER_INVARIANT_CHECK; - - std::vector::iterator i - = std::find_if(m_downloads.begin(), m_downloads.end(), has_index(block.piece_index)); - TORRENT_ASSERT(i != m_downloads.end()); - block_info& info = i->info[block.block_index]; - TORRENT_ASSERT(info.state == block_info::state_writing); - TORRENT_ASSERT(info.num_peers == 0); - - --i->writing; - info.state = block_info::state_none; - info.peer = 0; - } - - void piece_picker::mark_as_finished(piece_block block, void* peer) - { - TORRENT_ASSERT(block.piece_index >= 0); - TORRENT_ASSERT(block.block_index >= 0); - TORRENT_ASSERT(block.piece_index < (int)m_piece_map.size()); - TORRENT_ASSERT(block.block_index < blocks_in_piece(block.piece_index)); - - piece_pos& p = m_piece_map[block.piece_index]; - - if (p.downloading == 0) - { -#ifdef TORRENT_EXPENSIVE_INVARIANT_CHECKS - TORRENT_PIECE_PICKER_INVARIANT_CHECK; -#endif - - TORRENT_ASSERT(peer == 0); - int prio = p.priority(this); - TORRENT_ASSERT(prio < int(m_priority_boundries.size()) - || m_dirty); - p.downloading = 1; - if (prio >= 0 && !m_dirty) update(prio, p.index); - - downloading_piece& dp = add_download_piece(); - dp.state = none; - dp.index = block.piece_index; - block_info& info = dp.info[block.block_index]; - info.peer = peer; - TORRENT_ASSERT(info.state == block_info::state_none); - TORRENT_ASSERT(info.num_peers == 0); - if (info.state != block_info::state_finished) - { - ++dp.finished; - sort_piece(m_downloads.end() - 1); - } - info.state = block_info::state_finished; - } - else - { -#ifdef TORRENT_EXPENSIVE_INVARIANT_CHECKS - TORRENT_PIECE_PICKER_INVARIANT_CHECK; -#endif - - std::vector::iterator i - = std::find_if(m_downloads.begin(), m_downloads.end(), has_index(block.piece_index)); - TORRENT_ASSERT(i != m_downloads.end()); - block_info& info = i->info[block.block_index]; - TORRENT_ASSERT(info.num_peers == 0); - info.peer = peer; - TORRENT_ASSERT(info.state == block_info::state_writing - || peer == 0); - TORRENT_ASSERT(i->writing >= 0); - ++i->finished; - if (info.state == block_info::state_writing) - { - --i->writing; - info.state = block_info::state_finished; - } - else - { - TORRENT_ASSERT(info.state == block_info::state_none); - info.state = block_info::state_finished; - sort_piece(i); - } - } - } - - void piece_picker::get_downloaders(std::vector& d, int index) const - { - TORRENT_ASSERT(index >= 0 && index <= (int)m_piece_map.size()); - std::vector::const_iterator i - = std::find_if(m_downloads.begin(), m_downloads.end(), has_index(index)); - TORRENT_ASSERT(i != m_downloads.end()); - - d.clear(); - for (int j = 0; j < blocks_in_piece(index); ++j) - { - d.push_back(i->info[j].peer); - } - } - - void* piece_picker::get_downloader(piece_block block) const - { - std::vector::const_iterator i = std::find_if( - m_downloads.begin() - , m_downloads.end() - , has_index(block.piece_index)); - - if (i == m_downloads.end()) return 0; - - TORRENT_ASSERT(block.block_index >= 0); - - if (i->info[block.block_index].state == block_info::state_none) - return 0; - - return i->info[block.block_index].peer; - } - - // this is called when a request is rejected or when - // a peer disconnects. The piece might be in any state - void piece_picker::abort_download(piece_block block) - { -#ifdef TORRENT_EXPENSIVE_INVARIANT_CHECKS - TORRENT_PIECE_PICKER_INVARIANT_CHECK; -#endif - - TORRENT_ASSERT(block.piece_index >= 0); - TORRENT_ASSERT(block.block_index >= 0); - TORRENT_ASSERT(block.piece_index < (int)m_piece_map.size()); - TORRENT_ASSERT(block.block_index < blocks_in_piece(block.piece_index)); - - if (m_piece_map[block.piece_index].downloading == 0) - { - TORRENT_ASSERT(std::find_if(m_downloads.begin(), m_downloads.end() - , has_index(block.piece_index)) == m_downloads.end()); - return; - } - - std::vector::iterator i = std::find_if(m_downloads.begin() - , m_downloads.end(), has_index(block.piece_index)); - TORRENT_ASSERT(i != m_downloads.end()); - - block_info& info = i->info[block.block_index]; - - TORRENT_ASSERT(info.state != block_info::state_none); - - if (info.state == block_info::state_finished - || info.state == block_info::state_none - || info.state == block_info::state_writing) - return; - - if (info.state == block_info::state_requested) - { - TORRENT_ASSERT(info.num_peers > 0); - if (info.num_peers > 0) --info.num_peers; - - TORRENT_ASSERT(block.block_index < blocks_in_piece(block.piece_index)); - - // if there are other peers, leave the block requested - if (info.num_peers > 0) return; - - // clear the downloader of this block - info.peer = 0; - - // clear this block as being downloaded - info.state = block_info::state_none; - --i->requested; - } - - // if there are no other blocks in this piece - // that's being downloaded, remove it from the list - if (i->requested + i->finished + i->writing == 0) - { - erase_download_piece(i); - piece_pos& p = m_piece_map[block.piece_index]; - int prev_prio = p.priority(this); - TORRENT_ASSERT(prev_prio < int(m_priority_boundries.size()) - || m_dirty); - p.downloading = 0; - if (!m_dirty) - { - int prio = p.priority(this); - if (prev_prio == -1 && prio >= 0) add(block.piece_index); - else if (prev_prio >= 0) update(prev_prio, p.index); - } - - TORRENT_ASSERT(std::find_if(m_downloads.begin(), m_downloads.end() - , has_index(block.piece_index)) == m_downloads.end()); - } - else if (i->requested == 0) - { - // there are no blocks requested in this piece. - // remove the fast/slow state from it - i->state = none; - } - } - - int piece_picker::unverified_blocks() const - { - int counter = 0; - for (std::vector::const_iterator i = m_downloads.begin(); - i != m_downloads.end(); ++i) - { - counter += (int)i->finished; - } - return counter; - } - -} - diff --git a/libtorrent/src/policy.cpp b/libtorrent/src/policy.cpp deleted file mode 100755 index 8f6386009..000000000 --- a/libtorrent/src/policy.cpp +++ /dev/null @@ -1,1264 +0,0 @@ -/* - -Copyright (c) 2003, Arvid Norberg -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions -are met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in - the documentation and/or other materials provided with the distribution. - * Neither the name of the author nor the names of its - contributors may be used to endorse or promote products derived - from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -POSSIBILITY OF SUCH DAMAGE. - -*/ - -#include "libtorrent/pch.hpp" - -#include - -#ifdef _MSC_VER -#pragma warning(push, 1) -#endif - -#include -#include - -#ifdef _MSC_VER -#pragma warning(pop) -#endif - -#include "libtorrent/peer_connection.hpp" -#include "libtorrent/web_peer_connection.hpp" -#include "libtorrent/policy.hpp" -#include "libtorrent/torrent.hpp" -#include "libtorrent/socket.hpp" -#include "libtorrent/alert_types.hpp" -#include "libtorrent/invariant_check.hpp" -#include "libtorrent/time.hpp" -#include "libtorrent/aux_/session_impl.hpp" -#include "libtorrent/piece_picker.hpp" -#include "libtorrent/broadcast_socket.hpp" - -#ifdef TORRENT_DEBUG -#include "libtorrent/bt_peer_connection.hpp" -#endif - -namespace libtorrent -{ - class peer_connection; -} - -using boost::bind; - -namespace -{ - using namespace libtorrent; - - size_type collect_free_download( - torrent::peer_iterator start - , torrent::peer_iterator end) - { - size_type accumulator = 0; - for (torrent::peer_iterator i = start; i != end; ++i) - { - // if the peer is interested in us, it means it may - // want to trade it's surplus uploads for downloads itself - // (and we should not consider it free). If the share diff is - // negative, there's no free download to get from this peer. - size_type diff = (*i)->share_diff(); - TORRENT_ASSERT(diff < (std::numeric_limits::max)()); - if ((*i)->is_peer_interested() || diff <= 0) - continue; - - TORRENT_ASSERT(diff > 0); - (*i)->add_free_upload(-diff); - accumulator += diff; - TORRENT_ASSERT(accumulator > 0); - } - TORRENT_ASSERT(accumulator >= 0); - return accumulator; - } - - - // returns the amount of free upload left after - // it has been distributed to the peers - size_type distribute_free_upload( - torrent::peer_iterator start - , torrent::peer_iterator end - , size_type free_upload) - { - if (free_upload <= 0) return free_upload; - int num_peers = 0; - size_type total_diff = 0; - for (torrent::peer_iterator i = start; i != end; ++i) - { - size_type d = (*i)->share_diff(); - TORRENT_ASSERT(d < (std::numeric_limits::max)()); - total_diff += d; - if (!(*i)->is_peer_interested() || (*i)->share_diff() >= 0) continue; - ++num_peers; - } - - if (num_peers == 0) return free_upload; - size_type upload_share; - if (total_diff >= 0) - { - upload_share = (std::min)(free_upload, total_diff) / num_peers; - } - else - { - upload_share = (free_upload + total_diff) / num_peers; - } - if (upload_share < 0) return free_upload; - - for (torrent::peer_iterator i = start; i != end; ++i) - { - peer_connection* p = *i; - if (!p->is_peer_interested() || p->share_diff() >= 0) continue; - p->add_free_upload(upload_share); - free_upload -= upload_share; - } - return free_upload; - } - - struct match_peer_endpoint - { - match_peer_endpoint(tcp::endpoint const& ep) - : m_ep(ep) - {} - - bool operator()(std::pair const& p) const - { return p.second.addr == m_ep.address() && p.second.port == m_ep.port(); } - - tcp::endpoint const& m_ep; - }; - -#ifdef TORRENT_DEBUG - struct match_peer_connection - { - match_peer_connection(peer_connection const& c) - : m_conn(c) - {} - - bool operator()(std::pair const& p) const - { - return p.second.connection == &m_conn - || (p.second.ip() == m_conn.remote() - && p.second.type == policy::peer::connectable); - } - - peer_connection const& m_conn; - }; -#endif - -} - -namespace libtorrent -{ - // the case where ignore_peer is motivated is if two peers - // have only one piece that we don't have, and it's the - // same piece for both peers. Then they might get into an - // infinite loop, fighting to request the same blocks. - void request_a_block(torrent& t, peer_connection& c) - { - if (t.is_seed()) return; - - TORRENT_ASSERT(t.valid_metadata()); - TORRENT_ASSERT(c.peer_info_struct() != 0 || !dynamic_cast(&c)); - int num_requests = c.desired_queue_size() - - (int)c.download_queue().size() - - (int)c.request_queue().size(); - -#ifdef TORRENT_VERBOSE_LOGGING - (*c.m_logger) << time_now_string() << " PIECE_PICKER [ req: " << num_requests << " ]\n"; -#endif - TORRENT_ASSERT(c.desired_queue_size() > 0); - // if our request queue is already full, we - // don't have to make any new requests yet - if (num_requests <= 0) return; - - piece_picker& p = t.picker(); - std::vector interesting_pieces; - interesting_pieces.reserve(100); - - int prefer_whole_pieces = c.prefer_whole_pieces(); - - if (prefer_whole_pieces == 0) - { - prefer_whole_pieces = c.statistics().download_payload_rate() - * t.settings().whole_pieces_threshold - > t.torrent_file().piece_length() ? 1 : 0; - } - - // if we prefer whole pieces, the piece picker will pick at least - // the number of blocks we want, but it will try to make the picked - // blocks be from whole pieces, possibly by returning more blocks - // than we requested. -#ifdef TORRENT_DEBUG - error_code ec; - TORRENT_ASSERT(c.remote() == c.get_socket()->remote_endpoint(ec) || ec); -#endif - - piece_picker::piece_state_t state; - peer_connection::peer_speed_t speed = c.peer_speed(); - if (speed == peer_connection::fast) state = piece_picker::fast; - else if (speed == peer_connection::medium) state = piece_picker::medium; - else state = piece_picker::slow; - - // this vector is filled with the interesting pieces - // that some other peer is currently downloading - // we should then compare this peer's download speed - // with the other's, to see if we should abort another - // peer_connection in favour of this one - std::vector busy_pieces; - busy_pieces.reserve(num_requests); - - std::vector const& suggested = c.suggested_pieces(); - bitfield const& bits = c.get_bitfield(); - - if (c.has_peer_choked()) - { - // if we are choked we can only pick pieces from the - // allowed fast set. The allowed fast set is sorted - // in ascending priority order - std::vector const& allowed_fast = c.allowed_fast(); - - // build a bitmask with only the allowed pieces in it - bitfield mask(c.get_bitfield().size(), false); - for (std::vector::const_iterator i = allowed_fast.begin() - , end(allowed_fast.end()); i != end; ++i) - if (bits[*i]) mask.set_bit(*i); - - p.pick_pieces(mask, interesting_pieces - , num_requests, prefer_whole_pieces, c.peer_info_struct() - , state, c.picker_options(), suggested); - } - else - { - // picks the interesting pieces from this peer - // the integer is the number of pieces that - // should be guaranteed to be available for download - // (if num_requests is too big, too many pieces are - // picked and cpu-time is wasted) - // the last argument is if we should prefer whole pieces - // for this peer. If we're downloading one piece in 20 seconds - // then use this mode. - p.pick_pieces(bits, interesting_pieces - , num_requests, prefer_whole_pieces, c.peer_info_struct() - , state, c.picker_options(), suggested); - } - -#ifdef TORRENT_VERBOSE_LOGGING - (*c.m_logger) << time_now_string() << " PIECE_PICKER [ php: " << prefer_whole_pieces - << " picked: " << interesting_pieces.size() << " ]\n"; -#endif - std::deque const& dq = c.download_queue(); - std::deque const& rq = c.request_queue(); - for (std::vector::iterator i = interesting_pieces.begin(); - i != interesting_pieces.end(); ++i) - { - if (prefer_whole_pieces == 0 && num_requests <= 0) break; - - if (p.is_requested(*i)) - { - if (num_requests <= 0) break; - // don't request pieces we already have in our request queue - if (std::find_if(dq.begin(), dq.end(), has_block(*i)) != dq.end() - || std::find(rq.begin(), rq.end(), *i) != rq.end()) - continue; - - TORRENT_ASSERT(p.num_peers(*i) > 0); - busy_pieces.push_back(*i); - continue; - } - - TORRENT_ASSERT(p.num_peers(*i) == 0); - // ok, we found a piece that's not being downloaded - // by somebody else. request it from this peer - // and return - c.add_request(*i); - TORRENT_ASSERT(p.num_peers(*i) == 1); - TORRENT_ASSERT(p.is_requested(*i)); - num_requests--; - } - - if (busy_pieces.empty() || num_requests <= 0) - { - return; - } - - // if all blocks has the same number of peers on them - // we want to pick a random block - std::random_shuffle(busy_pieces.begin(), busy_pieces.end()); - - // find the block with the fewest requests to it - std::vector::iterator i = std::min_element( - busy_pieces.begin(), busy_pieces.end() - , bind(&piece_picker::num_peers, boost::cref(p), _1) < - bind(&piece_picker::num_peers, boost::cref(p), _2)); -#ifdef TORRENT_DEBUG - piece_picker::downloading_piece st; - p.piece_info(i->piece_index, st); - TORRENT_ASSERT(st.requested + st.finished + st.writing == p.blocks_in_piece(i->piece_index)); -#endif - TORRENT_ASSERT(p.is_requested(*i)); - TORRENT_ASSERT(p.num_peers(*i) > 0); - c.add_request(*i); - } - - policy::policy(torrent* t) - : m_round_robin(m_peers.end()) - , m_torrent(t) - , m_available_free_upload(0) - , m_num_connect_candidates(0) - , m_num_seeds(0) - { TORRENT_ASSERT(t); } - - // disconnects and removes all peers that are now filtered - void policy::ip_filter_updated() - { - aux::session_impl& ses = m_torrent->session(); - piece_picker* p = 0; - if (m_torrent->has_picker()) - p = &m_torrent->picker(); - for (iterator i = m_peers.begin(); i != m_peers.end();) - { - if ((ses.m_ip_filter.access(i->second.addr) & ip_filter::blocked) == 0) - { - ++i; - continue; - } - - if (i->second.connection) - { - i->second.connection->disconnect("peer banned by IP filter"); - if (ses.m_alerts.should_post()) - ses.m_alerts.post_alert(peer_blocked_alert(i->second.addr)); - TORRENT_ASSERT(i->second.connection == 0 - || i->second.connection->peer_info_struct() == 0); - } - else - { - if (ses.m_alerts.should_post()) - ses.m_alerts.post_alert(peer_blocked_alert(i->second.addr)); - } - erase_peer(i++); - } - } - - // any peer that is erased from m_peers will be - // erased through this function. This way we can make - // sure that any references to the peer are removed - // as well, such as in the piece picker. - void policy::erase_peer(iterator i) - { - if (m_torrent->has_picker()) - m_torrent->picker().clear_peer(&i->second); - if (i->second.seed) --m_num_seeds; - if (is_connect_candidate(i->second, m_torrent->is_finished())) - --m_num_connect_candidates; - if (m_round_robin == i) ++m_round_robin; - - m_peers.erase(i); - } - - bool policy::is_connect_candidate(peer const& p, bool finished) - { - if (p.connection - || p.banned - || p.type == peer::not_connectable - || (p.seed && finished) - || p.failcount >= m_torrent->settings().max_failcount) - return false; - - aux::session_impl& ses = m_torrent->session(); - if (ses.m_port_filter.access(p.port) & port_filter::blocked) - return false; - return true; - } - - policy::iterator policy::find_connect_candidate() - { -// too expensive -// INVARIANT_CHECK; - - ptime now = time_now(); - iterator candidate = m_peers.end(); - - int min_reconnect_time = m_torrent->settings().min_reconnect_time; - bool finished = m_torrent->is_finished(); - address external_ip = m_torrent->session().external_address(); - - // don't bias any particular peers when seeding - if (finished || external_ip == address()) - { - // set external_ip to a random value, to - // radomize which peers we prefer - address_v4::bytes_type bytes; - std::generate(bytes.begin(), bytes.end(), &std::rand); - external_ip = address_v4(bytes); - } - - if (m_round_robin == m_peers.end()) m_round_robin = m_peers.begin(); - -#ifndef TORRENT_DISABLE_DHT - bool pinged = false; -#endif - - for (int iterations = (std::min)(int(m_peers.size()), 300); - iterations > 0; --iterations) - { - if (m_round_robin == m_peers.end()) m_round_robin = m_peers.begin(); - - peer& pe = m_round_robin->second; - iterator current = m_round_robin; - -#ifndef TORRENT_DISABLE_DHT - // try to send a DHT ping to this peer - // as well, to figure out if it supports - // DHT (uTorrent and BitComet doesn't - // advertise support) - if (!pinged && !pe.added_to_dht) - { - udp::endpoint node(pe.addr, pe.port); - m_torrent->session().add_dht_node(node); - pe.added_to_dht = true; - pinged = true; - } -#endif - // if the number of peers is growing large - // we need to start weeding. - // don't remove peers we're connected to - // don't remove peers we've never even tried - // don't remove banned peers unless they're 2 - // hours old. They should remain banned for - // at least that long - // don't remove peers that we still can try again - if (pe.connection == 0 - && pe.connected != min_time() - && (!pe.banned || now - pe.connected > hours(2)) - && !is_connect_candidate(pe, finished) - && m_peers.size() >= m_torrent->settings().max_peerlist_size * 0.9) - { - erase_peer(m_round_robin++); - continue; - } - - ++m_round_robin; - - if (!is_connect_candidate(pe, finished)) continue; - - if (candidate != m_peers.end() - && !compare_peer(candidate->second, pe, external_ip)) continue; - - if (now - pe.connected < - seconds((pe.failcount + 1) * min_reconnect_time)) - continue; - - candidate = current; - } - -#if defined TORRENT_LOGGING || defined TORRENT_VERBOSE_LOGGING - if (candidate != m_peers.end()) - { - (*m_torrent->session().m_logger) << time_now_string() - << " *** FOUND CONNECTION CANDIDATE [" - " ip: " << candidate->second.ip() << - " d: " << cidr_distance(external_ip, candidate->second.addr) << - " external: " << external_ip << - " t: " << total_seconds(time_now() - candidate->second.connected) << - " ]\n"; - } -#endif - - return candidate; - } - - void policy::pulse() - { - INVARIANT_CHECK; - - // ------------------------ - // upload shift - // ------------------------ - - // this part will shift downloads - // from peers that are seeds and peers - // that don't want to download from us - // to peers that cannot upload anything - // to us. The shifting will make sure - // that the torrent's share ratio - // will be maintained - - // if the share ratio is 0 (infinite) - // m_available_free_upload isn't used - // because it isn't necessary - if (m_torrent->ratio() != 0.f) - { - // accumulate all the free download we get - // and add it to the available free upload - m_available_free_upload - += collect_free_download( - m_torrent->begin() - , m_torrent->end()); - - // distribute the free upload among the peers - m_available_free_upload = distribute_free_upload( - m_torrent->begin() - , m_torrent->end() - , m_available_free_upload); - } - } - - bool policy::new_connection(peer_connection& c) - { - TORRENT_ASSERT(!c.is_local()); - -// INVARIANT_CHECK; - - // if the connection comes from the tracker, - // it's probably just a NAT-check. Ignore the - // num connections constraint then. - - // TODO: only allow _one_ connection to use this - // override at a time - error_code ec; - TORRENT_ASSERT(c.remote() == c.get_socket()->remote_endpoint(ec) || ec); - - aux::session_impl& ses = m_torrent->session(); - - if (m_torrent->num_peers() >= m_torrent->max_connections() - && ses.num_connections() >= ses.max_connections() - && c.remote().address() != m_torrent->current_tracker().address()) - { - c.disconnect("too many connections, refusing incoming connection"); - return false; - } - -#if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_LOGGING - if (c.remote().address() == m_torrent->current_tracker().address()) - { - m_torrent->debug_log("overriding connection limit for tracker NAT-check"); - } -#endif - - iterator i; - - if (m_torrent->settings().allow_multiple_connections_per_ip) - { - tcp::endpoint remote = c.remote(); - std::pair range = m_peers.equal_range(remote.address()); - i = std::find_if(range.first, range.second, match_peer_endpoint(remote)); - - if (i == range.second) i = m_peers.end(); - } - else - { - i = m_peers.find(c.remote().address()); - } - - if (i != m_peers.end()) - { - if (i->second.banned) - { - c.disconnect("ip address banned, closing"); - return false; - } - - if (i->second.connection != 0) - { - boost::shared_ptr other_socket - = i->second.connection->get_socket(); - boost::shared_ptr this_socket - = c.get_socket(); - - error_code ec1; - error_code ec2; - bool self_connection = - other_socket->remote_endpoint(ec2) == this_socket->local_endpoint(ec1) - || other_socket->local_endpoint(ec2) == this_socket->remote_endpoint(ec1); - - if (ec1) - { - c.disconnect(ec1.message().c_str()); - return false; - } - - if (self_connection) - { - c.disconnect("connected to ourselves", 1); - i->second.connection->disconnect("connected to ourselves", 1); - return false; - } - - TORRENT_ASSERT(i->second.connection != &c); - // the new connection is a local (outgoing) connection - // or the current one is already connected - if (ec2) - { - i->second.connection->disconnect(ec2.message().c_str()); - } - else if (!i->second.connection->is_connecting() || c.is_local()) - { - c.disconnect("duplicate connection, closing"); - return false; - } - else - { -#if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_LOGGING - m_torrent->debug_log("duplicate connection. existing connection" - " is connecting and this connection is incoming. closing existing " - "connection in favour of this one"); -#endif - i->second.connection->disconnect("incoming duplicate connection " - "with higher priority, closing"); - } - } - - if (m_num_connect_candidates > 0) - --m_num_connect_candidates; - } - else - { - // we don't have any info about this peer. - // add a new entry - error_code ec; - TORRENT_ASSERT(c.remote() == c.get_socket()->remote_endpoint(ec) || ec); - - if (int(m_peers.size()) >= m_torrent->settings().max_peerlist_size) - { - c.disconnect("peer list size exceeded, refusing incoming connection"); - return false; - } - - peer p(c.remote(), peer::not_connectable, 0); - i = m_peers.insert(std::make_pair(c.remote().address(), p)); -#ifndef TORRENT_DISABLE_GEO_IP - int as = ses.as_for_ip(c.remote().address()); -#ifdef TORRENT_DEBUG - i->second.inet_as_num = as; -#endif - i->second.inet_as = ses.lookup_as(as); -#endif - } - - c.set_peer_info(&i->second); - TORRENT_ASSERT(i->second.connection == 0); - c.add_stat(i->second.prev_amount_download, i->second.prev_amount_upload); - i->second.prev_amount_download = 0; - i->second.prev_amount_upload = 0; - i->second.connection = &c; - TORRENT_ASSERT(i->second.connection); - if (!c.fast_reconnect()) - i->second.connected = time_now(); - return true; - } - - bool policy::update_peer_port(int port, policy::peer* p, int src) - { - TORRENT_ASSERT(p != 0); - TORRENT_ASSERT(p->connection); - - if (p->port == port) return true; - - if (m_torrent->settings().allow_multiple_connections_per_ip) - { - tcp::endpoint remote(p->addr, port); - std::pair range = m_peers.equal_range(remote.address()); - iterator i = std::find_if(range.first, range.second - , match_peer_endpoint(remote)); - if (i != m_peers.end()) - { - policy::peer& pp = i->second; - if (pp.connection) - { - p->connection->disconnect("duplicate connection"); - return false; - } - erase_peer(i); - } - } - else - { - TORRENT_ASSERT(m_peers.count(p->addr) == 1); - } - bool was_conn_cand = is_connect_candidate(*p, m_torrent->is_finished()); - p->port = port; - p->source |= src; - - if (was_conn_cand != is_connect_candidate(*p, m_torrent->is_finished())) - { - m_num_connect_candidates += was_conn_cand ? -1 : 1; - if (m_num_connect_candidates < 0) m_num_connect_candidates = 0; - } - return true; - } - - bool policy::has_peer(policy::peer const* p) const - { - // find p in m_peers - for (std::multimap::const_iterator i = m_peers.begin() - , end(m_peers.end()); i != end; ++i) - { - if (&i->second == p) return true; - } - return false; - } - - policy::peer* policy::peer_from_tracker(tcp::endpoint const& remote, peer_id const& pid - , int src, char flags) - { - // way too expensive - //INVARIANT_CHECK; - - // just ignore the obviously invalid entries - if (remote.address() == address() || remote.port() == 0) - return 0; - - aux::session_impl& ses = m_torrent->session(); - - port_filter const& pf = ses.m_port_filter; - if (pf.access(remote.port()) & port_filter::blocked) - { - if (ses.m_alerts.should_post()) - ses.m_alerts.post_alert(peer_blocked_alert(remote.address())); - return 0; - } - - iterator i; - - if (m_torrent->settings().allow_multiple_connections_per_ip) - { - std::pair range = m_peers.equal_range(remote.address()); - i = std::find_if(range.first, range.second, match_peer_endpoint(remote)); - if (i == range.second) i = m_peers.end(); - } - else - { - i = m_peers.find(remote.address()); - } - - if (i == m_peers.end()) - { - // if the IP is blocked, don't add it - if (ses.m_ip_filter.access(remote.address()) & ip_filter::blocked) - { - if (ses.m_alerts.should_post()) - { - ses.m_alerts.post_alert(peer_blocked_alert(remote.address())); - } - return 0; - } - - if (int(m_peers.size()) >= m_torrent->settings().max_peerlist_size) - return 0; - - // we don't have any info about this peer. - // add a new entry - i = m_peers.insert(std::make_pair(remote.address() - , peer(remote, peer::connectable, src))); -#ifndef TORRENT_DISABLE_ENCRYPTION - if (flags & 0x01) i->second.pe_support = true; -#endif - if (flags & 0x02) - { - i->second.seed = true; - ++m_num_seeds; - } - -#ifndef TORRENT_DISABLE_GEO_IP - int as = ses.as_for_ip(remote.address()); -#ifdef TORRENT_DEBUG - i->second.inet_as_num = as; -#endif - i->second.inet_as = ses.lookup_as(as); -#endif - if (is_connect_candidate(i->second, m_torrent->is_finished())) - ++m_num_connect_candidates; - } - else - { - bool was_conn_cand = is_connect_candidate(i->second, m_torrent->is_finished()); - - i->second.type = peer::connectable; - - i->second.set_ip(remote); - i->second.source |= src; - - // if this peer has failed before, decrease the - // counter to allow it another try, since somebody - // else is appearantly able to connect to it - // only trust this if it comes from the tracker - if (i->second.failcount > 0 && src == peer_info::tracker) - --i->second.failcount; - - // if we're connected to this peer - // we already know if it's a seed or not - // so we don't have to trust this source - if ((flags & 0x02) && !i->second.connection) - { - if (!i->second.seed) ++m_num_seeds; - i->second.seed = true; - } - -#if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_LOGGING - if (i->second.connection) - { - // this means we're already connected - // to this peer. don't connect to - // it again. - - error_code ec; - m_torrent->debug_log("already connected to peer: " + remote.address().to_string(ec) + ":" - + boost::lexical_cast(remote.port()) + " " - + boost::lexical_cast(i->second.connection->pid())); - - TORRENT_ASSERT(i->second.connection->associated_torrent().lock().get() == m_torrent); - } -#endif - - if (was_conn_cand != is_connect_candidate(i->second, m_torrent->is_finished())) - { - m_num_connect_candidates += was_conn_cand ? -1 : 1; - if (m_num_connect_candidates < 0) m_num_connect_candidates = 0; - } - } - - return &i->second; - } - - // this is called when we are unchoked by a peer - // i.e. a peer lets us know that we will receive - // data from now on - void policy::unchoked(peer_connection& c) - { -// INVARIANT_CHECK; - if (c.is_interesting()) - { - request_a_block(*m_torrent, c); - c.send_block_requests(); - } - } - - // called when a peer is interested in us - void policy::interested(peer_connection& c) - { -// INVARIANT_CHECK; - - TORRENT_ASSERT(std::find_if(m_peers.begin(), m_peers.end() - , boost::bind(std::equal_to(), bind(&peer::connection - , bind(&iterator::value_type::second, _1)), &c)) != m_peers.end()); - - aux::session_impl& ses = m_torrent->session(); - - // if the peer is choked and we have upload slots left, - // then unchoke it. Another condition that has to be met - // is that the torrent doesn't keep track of the individual - // up/down ratio for each peer (ratio == 0) or (if it does - // keep track) this particular connection isn't a leecher. - // If the peer was choked because it was leeching, don't - // unchoke it again. - // The exception to this last condition is if we're a seed. - // In that case we don't care if people are leeching, they - // can't pay for their downloads anyway. - if (c.is_choked() - && ses.num_uploads() < ses.max_uploads() - && (m_torrent->ratio() == 0 - || c.share_diff() >= -free_upload_amount - || m_torrent->is_finished())) - { - ses.unchoke_peer(c); - } -#if defined TORRENT_VERBOSE_LOGGING - else if (c.is_choked()) - { - std::string reason; - if (ses.num_uploads() >= ses.max_uploads()) - { - reason = "the number of uploads (" - + boost::lexical_cast(ses.num_uploads()) - + ") is more than or equal to the limit (" - + boost::lexical_cast(ses.max_uploads()) - + ")"; - } - else - { - reason = "the share ratio (" - + boost::lexical_cast(c.share_diff()) - + ") is <= free_upload_amount (" - + boost::lexical_cast(int(free_upload_amount)) - + ") and we are not seeding and the ratio (" - + boost::lexical_cast(m_torrent->ratio()) - + ")is non-zero"; - } - (*c.m_logger) << time_now_string() << " DID NOT UNCHOKE [ " << reason << " ]\n"; - } -#endif - } - - // called when a peer is no longer interested in us - void policy::not_interested(peer_connection& c) - { - INVARIANT_CHECK; - - if (m_torrent->ratio() != 0.f) - { - TORRENT_ASSERT(c.share_diff() < (std::numeric_limits::max)()); - size_type diff = c.share_diff(); - if (diff > 0 && c.is_seed()) - { - // the peer is a seed and has sent - // us more than we have sent it back. - // consider the download as free download - m_available_free_upload += diff; - c.add_free_upload(-diff); - } - } - } -/* - bool policy::unchoke_one_peer() - { - INVARIANT_CHECK; - - iterator p = find_unchoke_candidate(); - if (p == m_peers.end()) return false; - TORRENT_ASSERT(p->connection); - TORRENT_ASSERT(!p->connection->is_disconnecting()); - - TORRENT_ASSERT(p->connection->is_choked()); - p->connection->send_unchoke(); - p->last_optimistically_unchoked = time_now(); - ++m_num_unchoked; - return true; - } - - void policy::choke_one_peer() - { - INVARIANT_CHECK; - - iterator p = find_choke_candidate(); - if (p == m_peers.end()) return; - TORRENT_ASSERT(p->connection); - TORRENT_ASSERT(!p->connection->is_disconnecting()); - TORRENT_ASSERT(!p->connection->is_choked()); - p->connection->send_choke(); - --m_num_unchoked; - } -*/ - bool policy::connect_one_peer() - { -// INVARIANT_CHECK; - - TORRENT_ASSERT(m_torrent->want_more_peers()); - - iterator p = find_connect_candidate(); - if (p == m_peers.end()) return false; - - TORRENT_ASSERT(!p->second.banned); - TORRENT_ASSERT(!p->second.connection); - TORRENT_ASSERT(p->second.type == peer::connectable); - - TORRENT_ASSERT(is_connect_candidate(p->second, m_torrent->is_finished())); - if (!m_torrent->connect_to_peer(&p->second)) - { - ++p->second.failcount; - return false; - } - TORRENT_ASSERT(p->second.connection); - TORRENT_ASSERT(!is_connect_candidate(p->second, m_torrent->is_finished())); - --m_num_connect_candidates; - return true; - } - - // this is called whenever a peer connection is closed - void policy::connection_closed(const peer_connection& c) - { -// too expensive -// INVARIANT_CHECK; - - peer* p = c.peer_info_struct(); - - TORRENT_ASSERT((std::find_if( - m_peers.begin() - , m_peers.end() - , match_peer_connection(c)) - != m_peers.end()) == (p != 0)); - - // if we couldn't find the connection in our list, just ignore it. - if (p == 0) return; - - TORRENT_ASSERT(p->connection == &c); - - p->connection = 0; - p->optimistically_unchoked = false; - - // if fast reconnect is true, we won't - // update the timestamp, and it will remain - // the time when we initiated the connection. - if (!c.fast_reconnect()) - p->connected = time_now(); - - if (c.failed()) - { - ++p->failcount; -// p->connected = time_now(); - } - - if (is_connect_candidate(*p, m_torrent->is_finished())) - ++m_num_connect_candidates; - - // if the share ratio is 0 (infinite), the - // m_available_free_upload isn't used, - // because it isn't necessary. - if (m_torrent->ratio() != 0.f) - { - TORRENT_ASSERT(c.associated_torrent().lock().get() == m_torrent); - TORRENT_ASSERT(c.share_diff() < (std::numeric_limits::max)()); - m_available_free_upload += c.share_diff(); - } - TORRENT_ASSERT(p->prev_amount_upload == 0); - TORRENT_ASSERT(p->prev_amount_download == 0); - p->prev_amount_download += c.statistics().total_payload_download(); - p->prev_amount_upload += c.statistics().total_payload_upload(); - } - - void policy::peer_is_interesting(peer_connection& c) - { -// INVARIANT_CHECK; - - if (c.in_handshake()) return; - c.send_interested(); - if (c.has_peer_choked() - && c.allowed_fast().empty()) - return; - request_a_block(*m_torrent, c); - c.send_block_requests(); - } - -#ifdef TORRENT_DEBUG - bool policy::has_connection(const peer_connection* c) - { -// too expensive -// INVARIANT_CHECK; - - TORRENT_ASSERT(c); - error_code ec; - TORRENT_ASSERT(c->remote() == c->get_socket()->remote_endpoint(ec) || ec); - - return std::find_if( - m_peers.begin() - , m_peers.end() - , match_peer_connection(*c)) != m_peers.end(); - } - - void policy::check_invariant() const - { - TORRENT_ASSERT(m_num_connect_candidates >= 0); - if (m_torrent->is_aborted()) return; - - int connected_peers = 0; - - int total_connections = 0; - int nonempty_connections = 0; - - std::set unique_test; - for (const_iterator i = m_peers.begin(); - i != m_peers.end(); ++i) - { - peer const& p = i->second; -#ifndef TORRENT_DISABLE_GEO_IP - TORRENT_ASSERT(p.inet_as == 0 || p.inet_as->first == p.inet_as_num); -#endif - if (!m_torrent->settings().allow_multiple_connections_per_ip) - { - TORRENT_ASSERT(m_peers.count(p.addr) == 1); - } - else - { - TORRENT_ASSERT(unique_test.count(p.ip()) == 0); - unique_test.insert(p.ip()); - TORRENT_ASSERT(i->first == p.addr); -// TORRENT_ASSERT(p.connection == 0 || p.ip() == p.connection->remote()); - } - ++total_connections; - if (!p.connection) - { - continue; - } - TORRENT_ASSERT(p.prev_amount_upload == 0); - TORRENT_ASSERT(p.prev_amount_download == 0); - if (p.optimistically_unchoked) - { - TORRENT_ASSERT(p.connection); - TORRENT_ASSERT(!p.connection->is_choked()); - } - TORRENT_ASSERT(p.connection->peer_info_struct() == 0 - || p.connection->peer_info_struct() == &p); - ++nonempty_connections; - if (!p.connection->is_disconnecting()) - ++connected_peers; - } - - int num_torrent_peers = 0; - for (torrent::const_peer_iterator i = m_torrent->begin(); - i != m_torrent->end(); ++i) - { - if ((*i)->is_disconnecting()) continue; - // ignore web_peer_connections since they are not managed - // by the policy class - if (dynamic_cast(*i)) continue; - ++num_torrent_peers; - } - - if (m_torrent->has_picker()) - { - piece_picker& p = m_torrent->picker(); - std::vector downloaders = p.get_download_queue(); - - std::set peer_set; - std::vector peers; - for (std::vector::iterator i = downloaders.begin() - , end(downloaders.end()); i != end; ++i) - { - p.get_downloaders(peers, i->index); - std::copy(peers.begin(), peers.end() - , std::insert_iterator >(peer_set, peer_set.begin())); - } - - for (std::set::iterator i = peer_set.begin() - , end(peer_set.end()); i != end; ++i) - { - policy::peer* p = static_cast(*i); - if (p == 0) continue; - if (p->connection == 0) continue; - TORRENT_ASSERT(std::find_if(m_peers.begin(), m_peers.end() - , match_peer_connection(*p->connection)) != m_peers.end()); - } - } - - // this invariant is a bit complicated. - // the usual case should be that connected_peers - // == num_torrent_peers. But when there's an incoming - // connection, it will first be added to the policy - // and then be added to the torrent. - // When there's an outgoing connection, it will first - // be added to the torrent and then to the policy. - // that's why the two second cases are in there. -/* - TORRENT_ASSERT(connected_peers == num_torrent_peers - || (connected_peers == num_torrent_peers + 1 - && connected_peers > 0) - || (connected_peers + 1 == num_torrent_peers - && num_torrent_peers > 0)); -*/ - } -#endif - - policy::peer::peer(const tcp::endpoint& ip_, peer::connection_type t, int src) - : prev_amount_upload(0) - , prev_amount_download(0) - , addr(ip_.address()) - , last_optimistically_unchoked(min_time()) - , connected(min_time()) - , connection(0) -#ifndef TORRENT_DISABLE_GEO_IP - , inet_as(0) -#endif - , port(ip_.port()) - , failcount(0) - , trust_points(0) - , source(src) - , hashfails(0) - , type(t) - , fast_reconnects(0) -#ifndef TORRENT_DISABLE_ENCRYPTION - , pe_support(true) -#endif - , optimistically_unchoked(false) - , seed(false) - , on_parole(false) - , banned(false) -#ifndef TORRENT_DISABLE_DHT - , added_to_dht(false) -#endif - { - TORRENT_ASSERT((src & 0xff) == src); - TORRENT_ASSERT(connected < time_now()); - } - - size_type policy::peer::total_download() const - { - if (connection != 0) - { - TORRENT_ASSERT(prev_amount_download == 0); - return connection->statistics().total_payload_download(); - } - else - { - return prev_amount_download; - } - } - - size_type policy::peer::total_upload() const - { - if (connection != 0) - { - TORRENT_ASSERT(prev_amount_upload == 0); - return connection->statistics().total_payload_upload(); - } - else - { - return prev_amount_upload; - } - } - - // this returns true if lhs is a better connect candidate than rhs - bool policy::compare_peer(policy::peer const& lhs, policy::peer const& rhs - , address const& external_ip) const - { - // prefer peers with lower failcount - if (lhs.failcount != rhs.failcount) - return lhs.failcount < rhs.failcount; - - // Local peers should always be tried first - bool lhs_local = is_local(lhs.addr); - bool rhs_local = is_local(rhs.addr); - if (lhs_local != rhs_local) return lhs_local > rhs_local; - - if (lhs.connected != rhs.connected) - return lhs.connected < rhs.connected; - -#ifndef TORRENT_DISABLE_GEO_IP - // don't bias fast peers when seeding - if (!m_torrent->is_finished() && m_torrent->session().has_asnum_db()) - { - int lhs_as = lhs.inet_as ? lhs.inet_as->second : 0; - int rhs_as = rhs.inet_as ? rhs.inet_as->second : 0; - if (lhs_as != rhs_as) return lhs_as > rhs_as; - } -#endif - int lhs_distance = cidr_distance(external_ip, lhs.addr); - int rhs_distance = cidr_distance(external_ip, rhs.addr); - if (lhs_distance < rhs_distance) return true; - return false; - } -} - diff --git a/libtorrent/src/session.cpp b/libtorrent/src/session.cpp deleted file mode 100755 index 4ae88ee8c..000000000 --- a/libtorrent/src/session.cpp +++ /dev/null @@ -1,623 +0,0 @@ -/* - -Copyright (c) 2006, Arvid Norberg, Magnus Jonsson -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions -are met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in - the documentation and/or other materials provided with the distribution. - * Neither the name of the author nor the names of its - contributors may be used to endorse or promote products derived - from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -POSSIBILITY OF SUCH DAMAGE. - -*/ - -#include "libtorrent/pch.hpp" - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#ifdef _MSC_VER -#pragma warning(push, 1) -#endif - -#include -#include -#include -#include -#include - -#ifdef _MSC_VER -#pragma warning(pop) -#endif - -#include "libtorrent/extensions/ut_pex.hpp" -#include "libtorrent/extensions/ut_metadata.hpp" -#include "libtorrent/extensions/smart_ban.hpp" -#include "libtorrent/peer_id.hpp" -#include "libtorrent/torrent_info.hpp" -#include "libtorrent/tracker_manager.hpp" -#include "libtorrent/bencode.hpp" -#include "libtorrent/hasher.hpp" -#include "libtorrent/entry.hpp" -#include "libtorrent/session.hpp" -#include "libtorrent/fingerprint.hpp" -#include "libtorrent/entry.hpp" -#include "libtorrent/alert_types.hpp" -#include "libtorrent/invariant_check.hpp" -#include "libtorrent/file.hpp" -#include "libtorrent/bt_peer_connection.hpp" -#include "libtorrent/ip_filter.hpp" -#include "libtorrent/socket.hpp" -#include "libtorrent/aux_/session_impl.hpp" -#include "libtorrent/kademlia/dht_tracker.hpp" - -using boost::shared_ptr; -using boost::weak_ptr; -using boost::bind; -using libtorrent::aux::session_impl; - -#ifdef TORRENT_MEMDEBUG -void start_malloc_debug(); -void stop_malloc_debug(); -#endif - -namespace libtorrent -{ - - std::string log_time() - { - static const ptime start = time_now(); - char ret[200]; - std::sprintf(ret, "%d", total_milliseconds(time_now() - start)); - return ret; - } - - namespace aux - { - filesystem_init::filesystem_init() - { -#if BOOST_VERSION < 103400 - using namespace boost::filesystem; - if (path::default_name_check_writable()) - path::default_name_check(no_check); -#endif - } - } - - session::session( - fingerprint const& id - , std::pair listen_port_range - , char const* listen_interface - , int flags -#if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_LOGGING || defined TORRENT_ERROR_LOGGING - , fs::path logpath -#endif - ) - : m_impl(new session_impl(listen_port_range, id, listen_interface -#if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_LOGGING || defined TORRENT_ERROR_LOGGING - , logpath -#endif - )) - { -#ifdef TORRENT_MEMDEBUG - start_malloc_debug(); -#endif - // turn off the filename checking in boost.filesystem - TORRENT_ASSERT(listen_port_range.first > 0); - TORRENT_ASSERT(listen_port_range.first < listen_port_range.second); -#ifdef TORRENT_DEBUG - // this test was added after it came to my attention - // that devstudios managed c++ failed to generate - // correct code for boost.function - boost::function0 test = boost::ref(*m_impl); - TORRENT_ASSERT(!test.empty()); -#endif -#ifndef TORRENT_DISABLE_EXTENSIONS - if (flags & add_default_plugins) - { - add_extension(create_ut_pex_plugin); - add_extension(create_ut_metadata_plugin); - add_extension(create_smart_ban_plugin); - } -#endif - if (flags & start_default_features) - { - start_upnp(); - start_natpmp(); -#ifndef TORRENT_DISABLE_DHT - start_dht(); -#endif - start_lsd(); - } - } - - session::session(fingerprint const& id - , int flags -#if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_LOGGING || defined TORRENT_ERROR_LOGGING - , fs::path logpath -#endif - ) -#if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_LOGGING || defined TORRENT_ERROR_LOGGING - : m_impl(new session_impl(std::make_pair(0, 0), id, "0.0.0.0", logpath)) -#else - : m_impl(new session_impl(std::make_pair(0, 0), id, "0.0.0.0")) -#endif - { -#ifdef TORRENT_MEMDEBUG - start_malloc_debug(); -#endif -#ifdef TORRENT_DEBUG - boost::function0 test = boost::ref(*m_impl); - TORRENT_ASSERT(!test.empty()); -#endif -#ifndef TORRENT_DISABLE_EXTENSIONS - if (flags & add_default_plugins) - { - add_extension(create_ut_pex_plugin); - add_extension(create_ut_metadata_plugin); - add_extension(create_smart_ban_plugin); - } -#endif - if (flags & start_default_features) - { - start_upnp(); - start_natpmp(); -#ifndef TORRENT_DISABLE_DHT - start_dht(); -#endif - start_lsd(); - } - } - - session::~session() - { -#ifdef TORRENT_MEMDEBUG - stop_malloc_debug(); -#endif - TORRENT_ASSERT(m_impl); - // if there is at least one destruction-proxy - // abort the session and let the destructor - // of the proxy to syncronize - if (!m_impl.unique()) - m_impl->abort(); - } - -#ifndef TORRENT_DISABLE_EXTENSIONS - void session::add_extension(boost::function(torrent*, void*)> ext) - { - m_impl->add_extension(ext); - } -#endif - -#ifndef TORRENT_DISABLE_GEO_IP - bool session::load_asnum_db(char const* file) - { - return m_impl->load_asnum_db(file); - } - - bool session::load_country_db(char const* file) - { - return m_impl->load_country_db(file); - } - - int session::as_for_ip(address const& addr) - { - aux::session_impl::mutex_t::scoped_lock l(m_impl->m_mutex); - return m_impl->as_for_ip(addr); - } - -#endif - - void session::load_state(entry const& ses_state) - { - m_impl->load_state(ses_state); - } - - entry session::state() const - { - return m_impl->state(); - } - - void session::set_ip_filter(ip_filter const& f) - { - m_impl->set_ip_filter(f); - } - - void session::set_port_filter(port_filter const& f) - { - m_impl->set_port_filter(f); - } - - void session::set_peer_id(peer_id const& id) - { - m_impl->set_peer_id(id); - } - - peer_id session::id() const - { - return m_impl->get_peer_id(); - } - - void session::set_key(int key) - { - m_impl->set_key(key); - } - - std::vector session::get_torrents() const - { - return m_impl->get_torrents(); - } - - torrent_handle session::find_torrent(sha1_hash const& info_hash) const - { - return m_impl->find_torrent_handle(info_hash); - } - - torrent_handle session::add_torrent(add_torrent_params const& params) - { - return m_impl->add_torrent(params); - } - -#ifndef TORRENT_NO_DEPRECATE - // if the torrent already exists, this will throw duplicate_torrent - torrent_handle session::add_torrent( - torrent_info const& ti - , fs::path const& save_path - , entry const& resume_data - , storage_mode_t storage_mode - , bool paused - , storage_constructor_type sc) - { - boost::intrusive_ptr tip(new torrent_info(ti)); - add_torrent_params p(sc); - p.ti = tip; - p.save_path = save_path; - std::vector buf; - if (resume_data.type() != entry::undefined_t) - { - bencode(std::back_inserter(buf), resume_data); - p.resume_data = &buf; - } - p.storage_mode = storage_mode; - p.paused = paused; - return m_impl->add_torrent(p); - } - - torrent_handle session::add_torrent( - boost::intrusive_ptr ti - , fs::path const& save_path - , entry const& resume_data - , storage_mode_t storage_mode - , bool paused - , storage_constructor_type sc - , void* userdata) - { - add_torrent_params p(sc); - p.ti = ti; - p.save_path = save_path; - std::vector buf; - if (resume_data.type() != entry::undefined_t) - { - bencode(std::back_inserter(buf), resume_data); - p.resume_data = &buf; - } - p.storage_mode = storage_mode; - p.paused = paused; - p.userdata = userdata; - return m_impl->add_torrent(p); - } - - torrent_handle session::add_torrent( - char const* tracker_url - , sha1_hash const& info_hash - , char const* name - , fs::path const& save_path - , entry const& e - , storage_mode_t storage_mode - , bool paused - , storage_constructor_type sc - , void* userdata) - { - add_torrent_params p(sc); - p.tracker_url = tracker_url; - p.info_hash = info_hash; - p.save_path = save_path; - p.paused = paused; - p.userdata = userdata; - return m_impl->add_torrent(p); - } -#endif - - void session::remove_torrent(const torrent_handle& h, int options) - { - m_impl->remove_torrent(h, options); - } - - bool session::listen_on( - std::pair const& port_range - , const char* net_interface) - { - return m_impl->listen_on(port_range, net_interface); - } - - unsigned short session::listen_port() const - { - return m_impl->listen_port(); - } - - session_status session::status() const - { - return m_impl->status(); - } - - void session::pause() { m_impl->pause(); } - void session::resume() { m_impl->resume(); } - bool session::is_paused() const { return m_impl->is_paused(); } - - void session::get_cache_info(sha1_hash const& ih - , std::vector& ret) const - { - m_impl->m_disk_thread.get_cache_info(ih, ret); - } - - cache_status session::get_cache_status() const - { - return m_impl->m_disk_thread.status(); - } - -#ifndef TORRENT_DISABLE_DHT - - void session::start_dht(entry const& startup_state) - { - m_impl->start_dht(startup_state); - } - - void session::stop_dht() - { - m_impl->stop_dht(); - } - - void session::set_dht_settings(dht_settings const& settings) - { - m_impl->set_dht_settings(settings); - } - - entry session::dht_state() const - { - return m_impl->dht_state(); - } - - void session::add_dht_node(std::pair const& node) - { - m_impl->add_dht_node(node); - } - - void session::add_dht_router(std::pair const& node) - { - m_impl->add_dht_router(node); - } - -#endif - -#ifndef TORRENT_DISABLE_ENCRYPTION - void session::set_pe_settings(pe_settings const& settings) - { - m_impl->set_pe_settings(settings); - } - - pe_settings const& session::get_pe_settings() const - { - return m_impl->get_pe_settings(); - } -#endif - - bool session::is_listening() const - { - return m_impl->is_listening(); - } - - void session::set_settings(session_settings const& s) - { - m_impl->set_settings(s); - } - - session_settings const& session::settings() - { - return m_impl->settings(); - } - - void session::set_peer_proxy(proxy_settings const& s) - { - m_impl->set_peer_proxy(s); - } - - void session::set_web_seed_proxy(proxy_settings const& s) - { - m_impl->set_web_seed_proxy(s); - } - - void session::set_tracker_proxy(proxy_settings const& s) - { - m_impl->set_tracker_proxy(s); - } - - proxy_settings const& session::peer_proxy() const - { - return m_impl->peer_proxy(); - } - - proxy_settings const& session::web_seed_proxy() const - { - return m_impl->web_seed_proxy(); - } - - proxy_settings const& session::tracker_proxy() const - { - return m_impl->tracker_proxy(); - } - - -#ifndef TORRENT_DISABLE_DHT - void session::set_dht_proxy(proxy_settings const& s) - { - m_impl->set_dht_proxy(s); - } - - proxy_settings const& session::dht_proxy() const - { - return m_impl->dht_proxy(); - } -#endif - - void session::set_max_uploads(int limit) - { - m_impl->set_max_uploads(limit); - } - - void session::set_max_connections(int limit) - { - m_impl->set_max_connections(limit); - } - - int session::max_half_open_connections() const - { - return m_impl->max_half_open_connections(); - } - - void session::set_max_half_open_connections(int limit) - { - m_impl->set_max_half_open_connections(limit); - } - - int session::upload_rate_limit() const - { - return m_impl->upload_rate_limit(); - } - - int session::download_rate_limit() const - { - return m_impl->download_rate_limit(); - } - - void session::set_upload_rate_limit(int bytes_per_second) - { - m_impl->set_upload_rate_limit(bytes_per_second); - } - - void session::set_download_rate_limit(int bytes_per_second) - { - m_impl->set_download_rate_limit(bytes_per_second); - } - - int session::num_uploads() const - { - return m_impl->num_uploads(); - } - - int session::num_connections() const - { - return m_impl->num_connections(); - } - - std::auto_ptr session::pop_alert() - { - return m_impl->pop_alert(); - } - - alert const* session::wait_for_alert(time_duration max_wait) - { - return m_impl->wait_for_alert(max_wait); - } - - void session::set_alert_mask(int m) - { - m_impl->set_alert_mask(m); - } - - size_t session::set_alert_queue_size_limit(size_t queue_size_limit_) - { - return m_impl->set_alert_queue_size_limit(queue_size_limit_); - } - -#ifndef TORRENT_NO_DEPRECATE - void session::set_severity_level(alert::severity_t s) - { - int m = 0; - switch (s) - { - case alert::debug: m = alert::all_categories; break; - case alert::info: m = alert::all_categories & ~(alert::debug_notification - | alert::progress_notification); break; - case alert::warning: m = alert::all_categories & ~(alert::debug_notification - | alert::status_notification | alert::progress_notification); break; - case alert::critical: m = alert::error_notification | alert::storage_notification; break; - case alert::fatal: m = alert::error_notification; break; - default: break; - } - - m_impl->set_alert_mask(m); - } -#endif - - void session::start_lsd() - { - m_impl->start_lsd(); - } - - natpmp* session::start_natpmp() - { - return m_impl->start_natpmp(); - } - - upnp* session::start_upnp() - { - return m_impl->start_upnp(); - } - - void session::stop_lsd() - { - m_impl->stop_lsd(); - } - - void session::stop_natpmp() - { - m_impl->stop_natpmp(); - } - - void session::stop_upnp() - { - m_impl->stop_upnp(); - } - - connection_queue& session::get_connection_queue() - { - return m_impl->m_half_open; - } -} - diff --git a/libtorrent/src/session_impl.cpp b/libtorrent/src/session_impl.cpp deleted file mode 100755 index 4bb8caf00..000000000 --- a/libtorrent/src/session_impl.cpp +++ /dev/null @@ -1,2620 +0,0 @@ -/* - -Copyright (c) 2006, Arvid Norberg, Magnus Jonsson -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions -are met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in - the documentation and/or other materials provided with the distribution. - * Neither the name of the author nor the names of its - contributors may be used to endorse or promote products derived - from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -POSSIBILITY OF SUCH DAMAGE. - -*/ - -#include "libtorrent/pch.hpp" - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#ifdef _MSC_VER -#pragma warning(push, 1) -#endif - -#include -#include -#include -#include -#include -#include - -#ifdef _MSC_VER -#pragma warning(pop) -#endif - -#include "libtorrent/peer_id.hpp" -#include "libtorrent/torrent_info.hpp" -#include "libtorrent/tracker_manager.hpp" -#include "libtorrent/bencode.hpp" -#include "libtorrent/hasher.hpp" -#include "libtorrent/entry.hpp" -#include "libtorrent/session.hpp" -#include "libtorrent/fingerprint.hpp" -#include "libtorrent/entry.hpp" -#include "libtorrent/alert_types.hpp" -#include "libtorrent/invariant_check.hpp" -#include "libtorrent/file.hpp" -#include "libtorrent/bt_peer_connection.hpp" -#include "libtorrent/ip_filter.hpp" -#include "libtorrent/socket.hpp" -#include "libtorrent/aux_/session_impl.hpp" -#include "libtorrent/kademlia/dht_tracker.hpp" -#include "libtorrent/enum_net.hpp" -#include "libtorrent/config.hpp" -#include "libtorrent/upnp.hpp" -#include "libtorrent/natpmp.hpp" -#include "libtorrent/lsd.hpp" - -#ifndef TORRENT_WINDOWS -#include -#endif - -#ifndef TORRENT_DISABLE_ENCRYPTION - -#include - -namespace -{ - // openssl requires this to clean up internal - // structures it allocates - struct openssl_cleanup - { - ~openssl_cleanup() { CRYPTO_cleanup_all_ex_data(); } - } openssl_global_destructor; -} - -#endif -#ifdef _WIN32 -// for ERROR_SEM_TIMEOUT -#include -#endif - -using boost::shared_ptr; -using boost::weak_ptr; -using boost::bind; -using boost::mutex; -using libtorrent::aux::session_impl; - -namespace libtorrent { - -namespace fs = boost::filesystem; - -namespace detail -{ - - std::string generate_auth_string(std::string const& user - , std::string const& passwd) - { - if (user.empty()) return std::string(); - return user + ":" + passwd; - } - - -} -namespace aux { - - struct seed_random_generator - { - seed_random_generator() - { - std::srand(total_microseconds(time_now() - min_time())); - } - }; - - session_impl::session_impl( - std::pair listen_port_range - , fingerprint const& cl_fprint - , char const* listen_interface -#if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_LOGGING || defined TORRENT_ERROR_LOGGING - , fs::path const& logpath -#endif - ) - : -#ifndef TORRENT_DISABLE_POOL_ALLOCATOR - m_send_buffers(send_buffer_size), -#endif - m_files(40) - , m_io_service() - , m_disk_thread(m_io_service) - , m_half_open(m_io_service) - , m_download_channel(m_io_service, peer_connection::download_channel) -#ifdef TORRENT_VERBOSE_BANDWIDTH_LIMIT - , m_upload_channel(m_io_service, peer_connection::upload_channel, true) -#else - , m_upload_channel(m_io_service, peer_connection::upload_channel) -#endif - , m_tracker_manager(m_settings, m_tracker_proxy) - , m_listen_port_retries(listen_port_range.second - listen_port_range.first) - , m_abort(false) - , m_paused(false) - , m_max_uploads(8) - , m_allowed_upload_slots(8) - , m_max_connections(200) - , m_num_unchoked(0) - , m_unchoke_time_scaler(0) - , m_auto_manage_time_scaler(0) - , m_optimistic_unchoke_time_scaler(0) - , m_disconnect_time_scaler(90) - , m_auto_scrape_time_scaler(180) - , m_incoming_connection(false) - , m_last_tick(time_now()) -#ifndef TORRENT_DISABLE_DHT - , m_dht_same_port(true) - , m_external_udp_port(0) - , m_dht_socket(m_io_service, bind(&session_impl::on_receive_udp, this, _1, _2, _3, _4) - , m_half_open) -#endif - , m_timer(m_io_service) - , m_next_connect_torrent(0) -#if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_LOGGING || defined TORRENT_ERROR_LOGGING - , m_logpath(logpath) -#endif -#ifndef TORRENT_DISABLE_GEO_IP - , m_asnum_db(0) - , m_country_db(0) -#endif - , m_total_failed_bytes(0) - , m_total_redundant_bytes(0) - { - error_code ec; - m_listen_interface = tcp::endpoint(address::from_string(listen_interface, ec), listen_port_range.first); - TORRENT_ASSERT(!ec); - - m_tcp_mapping[0] = -1; - m_tcp_mapping[1] = -1; - m_udp_mapping[0] = -1; - m_udp_mapping[1] = -1; -#ifdef WIN32 - // windows XP has a limit on the number of - // simultaneous half-open TCP connections - DWORD windows_version = ::GetVersion(); - if ((windows_version & 0xff) >= 6) - { - // on vista the limit is 5 (in home edition) - m_half_open.limit(4); - } - else - { - // on XP SP2 it's 10 - m_half_open.limit(8); - } -#endif - - m_bandwidth_manager[peer_connection::download_channel] = &m_download_channel; - m_bandwidth_manager[peer_connection::upload_channel] = &m_upload_channel; - -#if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_LOGGING || defined TORRENT_ERROR_LOGGING - m_logger = create_log("main_session", listen_port(), false); - (*m_logger) << time_now_string() << "\n"; - - (*m_logger) << "sizeof(torrent): " << sizeof(torrent) << "\n"; - (*m_logger) << "sizeof(peer_connection): " << sizeof(peer_connection) << "\n"; - (*m_logger) << "sizeof(bt_peer_connection): " << sizeof(bt_peer_connection) << "\n"; - (*m_logger) << "sizeof(policy::peer): " << sizeof(policy::peer) << "\n"; - (*m_logger) << "sizeof(tcp::endpoint): " << sizeof(tcp::endpoint) << "\n"; - (*m_logger) << "sizeof(address): " << sizeof(address) << "\n"; - (*m_logger) << "sizeof(address_v4): " << sizeof(address_v4) << "\n"; - (*m_logger) << "sizeof(address_v6): " << sizeof(address_v6) << "\n"; - (*m_logger) << "sizeof(void*): " << sizeof(void*) << "\n"; -#endif - -#ifdef TORRENT_STATS - m_stats_logger.open("session_stats.log", std::ios::trunc); - m_stats_logger << - "1. second\n" - "2. upload rate\n" - "3. download rate\n" - "4. downloading torrents\n" - "5. seeding torrents\n" - "6. peers\n" - "7. connecting peers\n" - "8. disk block buffers\n" - "\n"; - m_buffer_usage_logger.open("buffer_stats.log", std::ios::trunc); - m_second_counter = 0; - m_buffer_allocations = 0; -#endif - - // ---- generate a peer id ---- - static seed_random_generator seeder; - - m_key = rand() + (rand() << 15) + (rand() << 30); - std::string print = cl_fprint.to_string(); - TORRENT_ASSERT(print.length() <= 20); - - // the client's fingerprint - std::copy( - print.begin() - , print.begin() + print.length() - , m_peer_id.begin()); - - // http-accepted characters: - static char const printable[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ" - "abcdefghijklmnopqrstuvwxyz-_.!~*'()"; - - // the random number - for (unsigned char* i = m_peer_id.begin() + print.length(); - i != m_peer_id.end(); ++i) - { - *i = printable[rand() % (sizeof(printable)-1)]; - } - - m_timer.expires_from_now(seconds(1), ec); - m_timer.async_wait( - bind(&session_impl::second_tick, this, _1)); - - m_thread.reset(new boost::thread(boost::ref(*this))); - } - -#ifndef TORRENT_DISABLE_GEO_IP - namespace - { - struct free_ptr - { - void* ptr_; - free_ptr(void* p): ptr_(p) {} - ~free_ptr() { free(ptr_); } - }; - } - - char const* session_impl::country_for_ip(address const& a) - { - if (!a.is_v4() || m_country_db == 0) return 0; - return GeoIP_country_code_by_ipnum(m_country_db, a.to_v4().to_ulong()); - } - - int session_impl::as_for_ip(address const& a) - { - if (!a.is_v4() || m_asnum_db == 0) return 0; - char* name = GeoIP_name_by_ipnum(m_asnum_db, a.to_v4().to_ulong()); - if (name == 0) return 0; - free_ptr p(name); - // GeoIP returns the name as AS??? where ? is the AS-number - return atoi(name + 2); - } - - std::string session_impl::as_name_for_ip(address const& a) - { - if (!a.is_v4() || m_asnum_db == 0) return std::string(); - char* name = GeoIP_name_by_ipnum(m_asnum_db, a.to_v4().to_ulong()); - if (name == 0) return std::string(); - free_ptr p(name); - char* tmp = std::strchr(name, ' '); - if (tmp == 0) return std::string(); - return tmp + 1; - } - - std::pair* session_impl::lookup_as(int as) - { - std::map::iterator i = m_as_peak.lower_bound(as); - - if (i == m_as_peak.end() || i->first != as) - { - // we don't have any data for this AS, insert a new entry - i = m_as_peak.insert(i, std::pair(as, 0)); - } - return &(*i); - } - - bool session_impl::load_asnum_db(char const* file) - { - mutex_t::scoped_lock l(m_mutex); - if (m_asnum_db) GeoIP_delete(m_asnum_db); - m_asnum_db = GeoIP_open(file, GEOIP_STANDARD); - return m_asnum_db; - } - - bool session_impl::load_country_db(char const* file) - { - mutex_t::scoped_lock l(m_mutex); - if (m_country_db) GeoIP_delete(m_country_db); - m_country_db = GeoIP_open(file, GEOIP_STANDARD); - return m_country_db; - } - -#endif - - void session_impl::load_state(entry const& ses_state) - { - if (ses_state.type() != entry::dictionary_t) return; - mutex_t::scoped_lock l(m_mutex); -#ifndef TORRENT_DISABLE_GEO_IP - entry const* as_map = ses_state.find_key("AS map"); - if (as_map && as_map->type() == entry::dictionary_t) - { - entry::dictionary_type const& as_peak = as_map->dict(); - for (entry::dictionary_type::const_iterator i = as_peak.begin() - , end(as_peak.end()); i != end; ++i) - { - int as_num = atoi(i->first.c_str()); - if (i->second.type() != entry::int_t || i->second.integer() == 0) continue; - int& peak = m_as_peak[as_num]; - if (peak < i->second.integer()) peak = i->second.integer(); - } - } -#endif - } - - entry session_impl::state() const - { - mutex_t::scoped_lock l(m_mutex); - entry ret; -#ifndef TORRENT_DISABLE_GEO_IP - entry::dictionary_type& as_map = ret["AS map"].dict(); - char buf[10]; - for (std::map::const_iterator i = m_as_peak.begin() - , end(m_as_peak.end()); i != end; ++i) - { - if (i->second == 0) continue; - sprintf(buf, "%05d", i->first); - as_map[buf] = i->second; - } -#endif - return ret; - } - -#ifndef TORRENT_DISABLE_EXTENSIONS - void session_impl::add_extension( - boost::function(torrent*, void*)> ext) - { - TORRENT_ASSERT(ext); - - typedef boost::shared_ptr(*function_t)(torrent*, void*); - function_t const* f = ext.target(); - - if (f) - { - for (extension_list_t::iterator i = m_extensions.begin(); i != m_extensions.end(); ++i) - if (function_equal(*i, *f)) return; - } - - m_extensions.push_back(ext); - } -#endif - -#ifndef TORRENT_DISABLE_DHT - void session_impl::add_dht_node(udp::endpoint n) - { - if (m_dht) m_dht->add_node(n); - } -#endif - - void session_impl::pause() - { - mutex_t::scoped_lock l(m_mutex); - if (m_paused) return; - m_paused = true; - for (torrent_map::iterator i = m_torrents.begin() - , end(m_torrents.end()); i != end; ++i) - { - torrent& t = *i->second; - if (!t.is_torrent_paused()) t.do_pause(); - } - } - - void session_impl::resume() - { - mutex_t::scoped_lock l(m_mutex); - if (!m_paused) return; - m_paused = false; - for (torrent_map::iterator i = m_torrents.begin() - , end(m_torrents.end()); i != end; ++i) - { - torrent& t = *i->second; - t.do_resume(); - } - } - - void session_impl::abort() - { - mutex_t::scoped_lock l(m_mutex); - if (m_abort) return; -#if defined(TORRENT_LOGGING) - (*m_logger) << time_now_string() << " *** ABORT CALLED ***\n"; -#endif - // abort the main thread - m_abort = true; - m_queued_for_checking.clear(); - if (m_lsd) m_lsd->close(); - if (m_upnp) m_upnp->close(); - if (m_natpmp) m_natpmp->close(); -#ifndef TORRENT_DISABLE_DHT - if (m_dht) m_dht->stop(); - m_dht_socket.close(); -#endif - error_code ec; - m_timer.cancel(ec); - - // close the listen sockets - for (std::list::iterator i = m_listen_sockets.begin() - , end(m_listen_sockets.end()); i != end; ++i) - { - i->sock->close(ec); - } - -#if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING) - (*m_logger) << time_now_string() << " aborting all torrents (" << m_torrents.size() << ")\n"; -#endif - // abort all torrents - for (torrent_map::iterator i = m_torrents.begin() - , end(m_torrents.end()); i != end; ++i) - { - i->second->abort(); - } - -#if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING) - (*m_logger) << time_now_string() << " aborting all tracker requests\n"; -#endif - m_tracker_manager.abort_all_requests(); - -#if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING) - (*m_logger) << time_now_string() << " sending event=stopped to trackers\n"; - int counter = 0; -#endif - for (torrent_map::iterator i = m_torrents.begin(); - i != m_torrents.end(); ++i) - { - torrent& t = *i->second; - t.abort(); - } - -#if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING) - (*m_logger) << time_now_string() << " sent " << counter << " tracker stop requests\n"; -#endif - -#if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING) - (*m_logger) << time_now_string() << " aborting all connections (" << m_connections.size() << ")\n"; -#endif - m_half_open.close(); - -#if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING) - (*m_logger) << time_now_string() << " connection queue: " << m_half_open.size() << "\n"; -#endif - - // abort all connections - while (!m_connections.empty()) - { -#ifdef TORRENT_DEBUG - int conn = m_connections.size(); -#endif - (*m_connections.begin())->disconnect("stopping torrent"); - TORRENT_ASSERT(conn == int(m_connections.size()) + 1); - } - -#if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING) - (*m_logger) << time_now_string() << " connection queue: " << m_half_open.size() << "\n"; -#endif - TORRENT_ASSERT(m_half_open.size() == 0); - -#if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING) - (*m_logger) << time_now_string() << " shutting down connection queue\n"; -#endif - - m_download_channel.close(); - m_upload_channel.close(); - } - - void session_impl::set_port_filter(port_filter const& f) - { - mutex_t::scoped_lock l(m_mutex); - m_port_filter = f; - } - - void session_impl::set_ip_filter(ip_filter const& f) - { - mutex_t::scoped_lock l(m_mutex); - - INVARIANT_CHECK; - - m_ip_filter = f; - - // Close connections whose endpoint is filtered - // by the new ip-filter - for (torrent_map::iterator i = m_torrents.begin() - , end(m_torrents.end()); i != end; ++i) - i->second->ip_filter_updated(); - } - - void session_impl::set_settings(session_settings const& s) - { - mutex_t::scoped_lock l(m_mutex); - - INVARIANT_CHECK; - - TORRENT_ASSERT(s.file_pool_size > 0); - - // less than 5 seconds unchoke interval is insane - TORRENT_ASSERT(s.unchoke_interval >= 5); - if (m_settings.cache_size != s.cache_size) - m_disk_thread.set_cache_size(s.cache_size); - if (m_settings.cache_expiry != s.cache_expiry) - m_disk_thread.set_cache_expiry(s.cache_expiry); - // if queuing settings were changed, recalculate - // queued torrents sooner - if ((m_settings.active_downloads != s.active_downloads - || m_settings.active_seeds != s.active_seeds - || m_settings.active_limit != s.active_limit) - && m_auto_manage_time_scaler > 2) - m_auto_manage_time_scaler = 2; - m_settings = s; - if (m_settings.connection_speed <= 0) m_settings.connection_speed = 200; - - m_files.resize(m_settings.file_pool_size); - if (!s.auto_upload_slots) m_allowed_upload_slots = m_max_uploads; - // replace all occurances of '\n' with ' '. - std::string::iterator i = m_settings.user_agent.begin(); - while ((i = std::find(i, m_settings.user_agent.end(), '\n')) - != m_settings.user_agent.end()) - *i = ' '; - } - - tcp::endpoint session_impl::get_ipv6_interface() const - { - return m_ipv6_interface; - } - - session_impl::listen_socket_t session_impl::setup_listener(tcp::endpoint ep - , int retries, bool v6_only) - { - error_code ec; - listen_socket_t s; - s.sock.reset(new socket_acceptor(m_io_service)); - s.sock->open(ep.protocol(), ec); - s.sock->set_option(socket_acceptor::reuse_address(true), ec); - if (ep.protocol() == tcp::v6()) - { - s.sock->set_option(v6only(v6_only), ec); -#ifdef TORRENT_WINDOWS - // enable Teredo on windows - s.sock->set_option(v6_protection_level(PROTECTION_LEVEL_UNRESTRICTED), ec); -#endif - } - s.sock->bind(ep, ec); - while (ec && retries > 0) - { - ec = error_code(); - TORRENT_ASSERT(!ec); - --retries; - ep.port(ep.port() + 1); - s.sock->bind(ep, ec); - } - if (ec) - { - // instead of giving up, try - // let the OS pick a port - ep.port(0); - ec = error_code(); - s.sock->bind(ep, ec); - } - if (ec) - { - // not even that worked, give up - if (m_alerts.should_post()) - m_alerts.post_alert(listen_failed_alert(ep, ec)); -#if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING) - std::stringstream msg; - msg << "cannot bind to interface '"; - print_endpoint(msg, ep) << "' " << ec.message(); - (*m_logger) << msg.str() << "\n"; -#endif - return listen_socket_t(); - } - s.external_port = s.sock->local_endpoint(ec).port(); - s.sock->listen(5, ec); - if (ec) - { - if (m_alerts.should_post()) - m_alerts.post_alert(listen_failed_alert(ep, ec)); -#if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING) - std::stringstream msg; - msg << "cannot listen on interface '"; - print_endpoint(msg, ep) << "' " << ec.message(); - (*m_logger) << msg.str() << "\n"; -#endif - return listen_socket_t(); - } - - if (m_alerts.should_post()) - m_alerts.post_alert(listen_succeeded_alert(ep)); - -#if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING) - (*m_logger) << "listening on: " << ep - << " external port: " << s.external_port << "\n"; -#endif - return s; - } - - void session_impl::open_listen_port() - { - // close the open listen sockets - m_listen_sockets.clear(); - m_incoming_connection = false; - - if (is_any(m_listen_interface.address())) - { - // this means we should open two listen sockets - // one for IPv4 and one for IPv6 - - listen_socket_t s = setup_listener( - tcp::endpoint(address_v4::any(), m_listen_interface.port()) - , m_listen_port_retries); - - if (s.sock) - { - m_listen_sockets.push_back(s); - async_accept(s.sock); - } - - s = setup_listener( - tcp::endpoint(address_v6::any(), m_listen_interface.port()) - , m_listen_port_retries, true); - - if (s.sock) - { - m_listen_sockets.push_back(s); - async_accept(s.sock); - } - } - else - { - // we should only open a single listen socket, that - // binds to the given interface - - listen_socket_t s = setup_listener( - m_listen_interface, m_listen_port_retries); - - if (s.sock) - { - m_listen_sockets.push_back(s); - async_accept(s.sock); - } - } - - m_ipv6_interface = tcp::endpoint(); - - for (std::list::const_iterator i = m_listen_sockets.begin() - , end(m_listen_sockets.end()); i != end; ++i) - { - error_code ec; - tcp::endpoint ep = i->sock->local_endpoint(ec); - if (ec || ep.address().is_v4()) continue; - - if (ep.address().to_v6() != address_v6::any()) - { - // if we're listening on a specific address - // pick it - m_ipv6_interface = ep; - } - else - { - // if we're listening on any IPv6 address, enumerate them and - // pick the first non-local address - std::vector const& ifs = enum_net_interfaces(m_io_service, ec); - for (std::vector::const_iterator i = ifs.begin() - , end(ifs.end()); i != end; ++i) - { - if (i->interface_address.is_v4() - || i->interface_address.to_v6().is_link_local() - || i->interface_address.to_v6().is_loopback()) continue; - m_ipv6_interface = tcp::endpoint(i->interface_address, ep.port()); - break; - } - break; - } - } - - if (!m_listen_sockets.empty()) - { - error_code ec; - tcp::endpoint local = m_listen_sockets.front().sock->local_endpoint(ec); - if (!ec) - { - if (m_natpmp.get()) - { - if (m_tcp_mapping[0] != -1) m_natpmp->delete_mapping(m_tcp_mapping[0]); - m_tcp_mapping[0] = m_natpmp->add_mapping(natpmp::tcp - , local.port(), local.port()); - } - if (m_upnp.get()) - { - if (m_tcp_mapping[1] != -1) m_upnp->delete_mapping(m_tcp_mapping[1]); - m_tcp_mapping[1] = m_upnp->add_mapping(upnp::tcp - , local.port(), local.port()); - } - } - } - -#if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_LOGGING || defined TORRENT_ERROR_LOGGING - m_logger = create_log("main_session", listen_port(), false); -#endif - } - -#ifndef TORRENT_DISABLE_DHT - - void session_impl::on_receive_udp(error_code const& e - , udp::endpoint const& ep, char const* buf, int len) - { - if (e) - { - if (e == asio::error::connection_refused - || e == asio::error::connection_reset - || e == asio::error::connection_aborted) - m_dht->on_unreachable(ep); - - if (m_alerts.should_post()) - m_alerts.post_alert(udp_error_alert(ep, e)); - return; - } - - if (len > 20 && *buf == 'd' && m_dht) - { - // this is probably a dht message - m_dht->on_receive(ep, buf, len); - } - } - -#endif - - void session_impl::async_accept(boost::shared_ptr const& listener) - { - shared_ptr c(new socket_type(m_io_service)); - c->instantiate(m_io_service); - listener->async_accept(c->get() - , bind(&session_impl::on_incoming_connection, this, c - , boost::weak_ptr(listener), _1)); - } - - void session_impl::on_incoming_connection(shared_ptr const& s - , weak_ptr listen_socket, error_code const& e) - { - boost::shared_ptr listener = listen_socket.lock(); - if (!listener) return; - - if (e == asio::error::operation_aborted) return; - - mutex_t::scoped_lock l(m_mutex); - if (m_abort) return; - - error_code ec; - if (e) - { - tcp::endpoint ep = listener->local_endpoint(ec); -#if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING) - std::string msg = "error accepting connection on '" - + boost::lexical_cast(ep) + "' " + e.message(); - (*m_logger) << msg << "\n"; -#endif -#ifdef TORRENT_WINDOWS - // Windows sometimes generates this error. It seems to be - // non-fatal and we have to do another async_accept. - if (e.value() == ERROR_SEM_TIMEOUT) - { - async_accept(listener); - return; - } -#endif -#ifdef TORRENT_BSD - // Leopard sometimes generates an "invalid argument" error. It seems to be - // non-fatal and we have to do another async_accept. - if (e.value() == EINVAL) - { - async_accept(listener); - return; - } -#endif - if (m_alerts.should_post()) - m_alerts.post_alert(listen_failed_alert(ep, e)); - return; - } - async_accept(listener); - - // we got a connection request! - tcp::endpoint endp = s->remote_endpoint(ec); - - if (ec) - { -#if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING) - (*m_logger) << endp << " <== INCOMING CONNECTION FAILED, could " - "not retrieve remote endpoint " << ec.message() << "\n"; -#endif - return; - } - -#if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING) - (*m_logger) << time_now_string() << " <== INCOMING CONNECTION " << endp << "\n"; -#endif - - // local addresses do not count, since it's likely - // coming from our own client through local service discovery - // and it does not reflect whether or not a router is open - // for incoming connections or not. - if (!is_local(endp.address())) - m_incoming_connection = true; - - if (m_ip_filter.access(endp.address()) & ip_filter::blocked) - { -#if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING) - (*m_logger) << "filtered blocked ip\n"; -#endif - if (m_alerts.should_post()) - m_alerts.post_alert(peer_blocked_alert(endp.address())); - return; - } - - // don't allow more connections than the max setting - if (num_connections() >= max_connections()) - { -#if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING) - (*m_logger) << "number of connections limit exceeded (conns: " - << num_connections() << ", limit: " << max_connections() - << "), connection rejected\n"; -#endif - return; - } - - // check if we have any active torrents - // if we don't reject the connection - if (m_torrents.empty()) - { -#if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING) - (*m_logger) << " There are no torrents, disconnect\n"; -#endif - return; - } - - bool has_active_torrent = false; - for (torrent_map::iterator i = m_torrents.begin() - , end(m_torrents.end()); i != end; ++i) - { - if (!i->second->is_paused()) - { - has_active_torrent = true; - break; - } - } - if (!has_active_torrent) - { -#if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING) - (*m_logger) << " There are no _active_ torrents, disconnect\n"; -#endif - return; - } - - boost::intrusive_ptr c( - new bt_peer_connection(*this, s, endp, 0)); -#ifdef TORRENT_DEBUG - c->m_in_constructor = false; -#endif - - if (!c->is_disconnecting()) - { - m_connections.insert(c); - c->start(); - } - } - void session_impl::close_connection(peer_connection const* p - , char const* message) - { - mutex_t::scoped_lock l(m_mutex); - -// too expensive -// INVARIANT_CHECK; - -#ifdef TORRENT_DEBUG -// for (aux::session_impl::torrent_map::const_iterator i = m_torrents.begin() -// , end(m_torrents.end()); i != end; ++i) -// TORRENT_ASSERT(!i->second->has_peer((peer_connection*)p)); -#endif - -#if defined(TORRENT_LOGGING) - (*m_logger) << time_now_string() << " CLOSING CONNECTION " - << p->remote() << " : " << message << "\n"; -#endif - - TORRENT_ASSERT(p->is_disconnecting()); - - if (!p->is_choked()) --m_num_unchoked; -// connection_map::iterator i = std::lower_bound(m_connections.begin(), m_connections.end() -// , p, bind(&boost::intrusive_ptr::get, _1) < p); -// if (i->get() != p) i == m_connections.end(); - connection_map::iterator i = std::find_if(m_connections.begin(), m_connections.end() - , bind(&boost::intrusive_ptr::get, _1) == p); - if (i != m_connections.end()) m_connections.erase(i); - } - - void session_impl::set_peer_id(peer_id const& id) - { - mutex_t::scoped_lock l(m_mutex); - m_peer_id = id; - } - - void session_impl::set_key(int key) - { - mutex_t::scoped_lock l(m_mutex); - m_key = key; - } - - void session_impl::unchoke_peer(peer_connection& c) - { - torrent* t = c.associated_torrent().lock().get(); - TORRENT_ASSERT(t); - if (t->unchoke_peer(c)) - ++m_num_unchoked; - } - - int session_impl::next_port() - { - std::pair const& out_ports = m_settings.outgoing_ports; - if (m_next_port < out_ports.first || m_next_port > out_ports.second) - m_next_port = out_ports.first; - - int port = m_next_port; - ++m_next_port; - if (m_next_port > out_ports.second) m_next_port = out_ports.first; -#if defined TORRENT_LOGGING - (*m_logger) << time_now_string() << " *** BINDING OUTGOING CONNECTION [ " - "port: " << port << " ]\n"; -#endif - return port; - } - - void session_impl::second_tick(error_code const& e) - { - session_impl::mutex_t::scoped_lock l(m_mutex); - -// too expensive -// INVARIANT_CHECK; - - if (m_abort) return; - - if (e) - { -#if defined TORRENT_LOGGING - (*m_logger) << "*** SECOND TIMER FAILED " << e.message() << "\n"; -#endif - ::abort(); - return; - } - - float tick_interval = total_microseconds(time_now() - m_last_tick) / 1000000.f; - m_last_tick = time_now(); - - error_code ec; - m_timer.expires_from_now(seconds(1), ec); - m_timer.async_wait( - bind(&session_impl::second_tick, this, _1)); - -#ifdef TORRENT_STATS - ++m_second_counter; - int downloading_torrents = 0; - int seeding_torrents = 0; - for (torrent_map::iterator i = m_torrents.begin() - , end(m_torrents.end()); i != end; ++i) - { - if (i->second->is_seed()) - ++seeding_torrents; - else - ++downloading_torrents; - } - int num_complete_connections = 0; - int num_half_open = 0; - for (connection_map::iterator i = m_connections.begin() - , end(m_connections.end()); i != end; ++i) - { - if ((*i)->is_connecting()) - ++num_half_open; - else - ++num_complete_connections; - } - - m_stats_logger - << m_second_counter << "\t" - << m_stat.upload_rate() << "\t" - << m_stat.download_rate() << "\t" - << downloading_torrents << "\t" - << seeding_torrents << "\t" - << num_complete_connections << "\t" - << num_half_open << "\t" - << m_disk_thread.disk_allocations() << "\t" - << std::endl; -#endif - - // -------------------------------------------------------------- - // check for incoming connections that might have timed out - // -------------------------------------------------------------- - - for (connection_map::iterator i = m_connections.begin(); - i != m_connections.end();) - { - peer_connection* p = (*i).get(); - ++i; - // ignore connections that already have a torrent, since they - // are ticked through the torrents' second_tick - if (!p->associated_torrent().expired()) continue; - if (m_last_tick - p->connected_time() > seconds(m_settings.handshake_timeout)) - p->disconnect("timeout: incoming connection"); - } - - // -------------------------------------------------------------- - // second_tick every torrent - // -------------------------------------------------------------- - - int congested_torrents = 0; - int uncongested_torrents = 0; - - // count the number of seeding torrents vs. downloading - // torrents we are running - int num_seeds = 0; - int num_downloads = 0; - - // count the number of peers of downloading torrents - int num_downloads_peers = 0; - - torrent_map::iterator least_recently_scraped = m_torrents.begin(); - int num_paused_auto_managed = 0; - - for (torrent_map::iterator i = m_torrents.begin(); - i != m_torrents.end();) - { - torrent& t = *i->second; - TORRENT_ASSERT(!t.is_aborted()); - if (t.bandwidth_queue_size(peer_connection::upload_channel)) - ++congested_torrents; - else - ++uncongested_torrents; - - if (t.is_auto_managed() && t.is_paused() && !t.has_error()) - { - ++num_paused_auto_managed; - if (!least_recently_scraped->second->is_auto_managed() - || !least_recently_scraped->second->is_paused() - || least_recently_scraped->second->last_scrape() > t.last_scrape()) - { - least_recently_scraped = i; - } - } - - if (t.is_finished()) - { - ++num_seeds; - } - else - { - ++num_downloads; - num_downloads_peers += t.num_peers(); - } - - t.second_tick(m_stat, tick_interval); - ++i; - } - - if (m_settings.rate_limit_ip_overhead) - { - // drain the IP overhead from the bandwidth limiters - m_download_channel.drain(m_stat.download_ip_overhead()); - m_upload_channel.drain(m_stat.upload_ip_overhead()); - } - - m_stat.second_tick(tick_interval); - - // -------------------------------------------------------------- - // scrape paused torrents that are auto managed - // -------------------------------------------------------------- - if (!is_paused()) - { - --m_auto_scrape_time_scaler; - if (m_auto_scrape_time_scaler <= 0) - { - m_auto_scrape_time_scaler = m_settings.auto_scrape_interval - / (std::max)(1, num_paused_auto_managed); - if (m_auto_scrape_time_scaler < m_settings.auto_scrape_min_interval) - m_auto_scrape_time_scaler = m_settings.auto_scrape_min_interval; - - if (least_recently_scraped != m_torrents.end()) - { - least_recently_scraped->second->scrape_tracker(); - } - } - } - - // -------------------------------------------------------------- - // connect new peers - // -------------------------------------------------------------- - - // let torrents connect to peers if they want to - // if there are any torrents and any free slots - - // this loop will "hand out" max(connection_speed - // , half_open.free_slots()) to the torrents, in a - // round robin fashion, so that every torrent is - // equallt likely to connect to a peer - - int free_slots = m_half_open.free_slots(); - if (!m_torrents.empty() - && free_slots > -m_half_open.limit() - && num_connections() < m_max_connections - && !m_abort) - { - // this is the maximum number of connections we will - // attempt this tick - int max_connections = m_settings.connection_speed; - int average_peers = 0; - if (num_downloads > 0) - average_peers = num_downloads_peers / num_downloads; - - torrent_map::iterator i = m_torrents.begin(); - if (m_next_connect_torrent < int(m_torrents.size())) - std::advance(i, m_next_connect_torrent); - else - m_next_connect_torrent = 0; - int steps_since_last_connect = 0; - int num_torrents = int(m_torrents.size()); - for (;;) - { - torrent& t = *i->second; - if (t.want_more_peers()) - { - int connect_points = 100; - // have a bias against torrents with more peers - // than average - if (!t.is_seed() && t.num_peers() > average_peers) - connect_points /= 2; - // if this is a seed and there is a torrent that - // is downloading, lower the rate at which this - // torrent gets connections. - // dividing by num_seeds will have the effect - // that all seed will get as many connections - // together, as a single downloading torrent. - if (t.is_seed() && num_downloads > 0) - connect_points /= num_seeds + 1; - if (connect_points <= 0) connect_points = 1; - t.give_connect_points(connect_points); - try - { - if (t.try_connect_peer()) - { - --max_connections; - --free_slots; - steps_since_last_connect = 0; - } - } - catch (std::bad_alloc&) - { - // we ran out of memory trying to connect to a peer - // lower the global limit to the number of peers - // we already have - m_max_connections = num_connections(); - if (m_max_connections < 2) m_max_connections = 2; - } - } - ++m_next_connect_torrent; - ++steps_since_last_connect; - ++i; - if (i == m_torrents.end()) - { - TORRENT_ASSERT(m_next_connect_torrent == num_torrents); - i = m_torrents.begin(); - m_next_connect_torrent = 0; - } - // if we have gone two whole loops without - // handing out a single connection, break - if (steps_since_last_connect > num_torrents * 2) break; - // if there are no more free connection slots, abort - if (free_slots <= -m_half_open.limit()) break; - // if we should not make any more connections - // attempts this tick, abort - if (max_connections == 0) break; - // maintain the global limit on number of connections - if (num_connections() >= m_max_connections) break; - } - } - - // -------------------------------------------------------------- - // auto managed torrent - // -------------------------------------------------------------- - m_auto_manage_time_scaler--; - if (m_auto_manage_time_scaler <= 0) - { - m_auto_manage_time_scaler = settings().auto_manage_interval; - recalculate_auto_managed_torrents(); - } - - // -------------------------------------------------------------- - // unchoke set and optimistic unchoke calculations - // -------------------------------------------------------------- - m_unchoke_time_scaler--; - if (m_unchoke_time_scaler <= 0 && !m_connections.empty()) - { - m_unchoke_time_scaler = settings().unchoke_interval; - recalculate_unchoke_slots(congested_torrents - , uncongested_torrents); - } - - // -------------------------------------------------------------- - // disconnect peers when we have too many - // -------------------------------------------------------------- - --m_disconnect_time_scaler; - if (m_disconnect_time_scaler <= 0) - { - m_disconnect_time_scaler = 90; - - // every 90 seconds, disconnect the worst peers - // if we have reached the connection limit - if (num_connections() >= max_connections() * m_settings.peer_turnover_cutoff - && !m_torrents.empty()) - { - torrent_map::iterator i = std::max_element(m_torrents.begin(), m_torrents.end() - , bind(&torrent::num_peers, bind(&torrent_map::value_type::second, _1)) - < bind(&torrent::num_peers, bind(&torrent_map::value_type::second, _2))); - - TORRENT_ASSERT(i != m_torrents.end()); - int peers_to_disconnect = (std::min)((std::max)(int(i->second->num_peers() - * m_settings.peer_turnover), 1) - , i->second->get_policy().num_connect_candidates()); - i->second->disconnect_peers(peers_to_disconnect); - } - else - { - // if we haven't reached the global max. see if any torrent - // has reached its local limit - for (torrent_map::iterator i = m_torrents.begin() - , end(m_torrents.end()); i != end; ++i) - { - boost::shared_ptr t = i->second; - if (t->num_peers() < t->max_connections() * m_settings.peer_turnover_cutoff) - continue; - - int peers_to_disconnect = (std::min)((std::max)(int(i->second->num_peers() - * m_settings.peer_turnover), 1) - , i->second->get_policy().num_connect_candidates()); - t->disconnect_peers(peers_to_disconnect); - } - } - } - } - - namespace - { - bool is_active(torrent* t, session_settings const& s) - { - return !(s.dont_count_slow_torrents - && t->statistics().upload_payload_rate() == 0.f - && t->statistics().download_payload_rate() == 0.f - && time_now() - t->started() > seconds(s.auto_manage_startup)); - } - } - - void session_impl::recalculate_auto_managed_torrents() - { - // these vectors are filled with auto managed torrents - std::vector downloaders; - downloaders.reserve(m_torrents.size()); - std::vector seeds; - seeds.reserve(m_torrents.size()); - - // these counters are set to the number of torrents - // of each kind we're allowed to have active - int num_downloaders = settings().active_downloads; - int num_seeds = settings().active_seeds; - int hard_limit = settings().active_limit; - - if (num_downloaders == -1) - num_downloaders = (std::numeric_limits::max)(); - if (num_seeds == -1) - num_seeds = (std::numeric_limits::max)(); - if (hard_limit == -1) - hard_limit = (std::numeric_limits::max)(); - - for (torrent_map::iterator i = m_torrents.begin() - , end(m_torrents.end()); i != end; ++i) - { - torrent* t = i->second.get(); - TORRENT_ASSERT(t); - if (t->is_auto_managed() && !t->has_error()) - { - // this torrent is auto managed, add it to - // the list (depending on if it's a seed or not) - if (t->is_finished()) - seeds.push_back(t); - else - downloaders.push_back(t); - } - else if (!t->is_paused()) - { - --hard_limit; - if (is_active(t, settings())) - { - // this is not an auto managed torrent, - // if it's running and active, decrease the - // counters. - --num_downloaders; - --num_seeds; - } - } - } - - bool handled_by_extension = false; - -#ifndef TORRENT_DISABLE_EXTENSIONS - // TODO: allow extensions to sort torrents for queuing -#endif - - if (!handled_by_extension) - { - std::sort(downloaders.begin(), downloaders.end() - , bind(&torrent::sequence_number, _1) < bind(&torrent::sequence_number, _2)); - - std::sort(seeds.begin(), seeds.end() - , bind(&torrent::seed_rank, _1, boost::ref(m_settings)) - > bind(&torrent::seed_rank, _2, boost::ref(m_settings))); - } - - int total_running = 0; - for (std::vector::iterator i = downloaders.begin() - , end(downloaders.end()); i != end; ++i) - { - torrent* t = *i; - if (!t->is_paused() && !is_active(t, settings()) - && hard_limit > 0) - { - --hard_limit; - ++total_running; - continue; - } - - if (num_downloaders > 0 && hard_limit > 0) - { - --hard_limit; - ++total_running; - --num_downloaders; - if (t->is_paused()) t->resume(); - } - else - { - if (!t->is_paused()) t->pause(); - } - } - - for (std::vector::iterator i = seeds.begin() - , end(seeds.end()); i != end; ++i) - { - torrent* t = *i; - if (!t->is_paused() && !is_active(t, settings()) - && hard_limit > 0) - { - --hard_limit; - ++total_running; - continue; - } - - if (num_seeds > 0 && hard_limit > 0) - { - --hard_limit; - --num_seeds; - ++total_running; - if (t->is_paused()) t->resume(); - } - else - { - if (!t->is_paused()) t->pause(); - } - } - } - - void session_impl::recalculate_unchoke_slots(int congested_torrents - , int uncongested_torrents) - { - std::vector peers; - for (connection_map::iterator i = m_connections.begin() - , end(m_connections.end()); i != end; ++i) - { - peer_connection* p = i->get(); - TORRENT_ASSERT(p); - torrent* t = p->associated_torrent().lock().get(); - if (!p->peer_info_struct() - || t == 0 - || !p->is_peer_interested() - || p->is_disconnecting() - || p->is_connecting() - || (p->share_diff() < -free_upload_amount - && !t->is_seed())) - { - if (!(*i)->is_choked() && t) - { - policy::peer* pi = p->peer_info_struct(); - if (pi && pi->optimistically_unchoked) - { - pi->optimistically_unchoked = false; - // force a new optimistic unchoke - m_optimistic_unchoke_time_scaler = 0; - } - t->choke_peer(*(*i)); - } - continue; - } - peers.push_back(i->get()); - } - - // sorts the peers that are eligible for unchoke by download rate and secondary - // by total upload. The reason for this is, if all torrents are being seeded, - // the download rate will be 0, and the peers we have sent the least to should - // be unchoked - std::sort(peers.begin(), peers.end() - , bind(&peer_connection::unchoke_compare, _1, _2)); - - std::for_each(m_connections.begin(), m_connections.end() - , bind(&peer_connection::reset_choke_counters, _1)); - - // auto unchoke - int upload_limit = m_bandwidth_manager[peer_connection::upload_channel]->throttle(); - if (m_settings.auto_upload_slots && upload_limit != bandwidth_limit::inf) - { - // if our current upload rate is less than 90% of our - // limit AND most torrents are not "congested", i.e. - // they are not holding back because of a per-torrent - // limit - if (m_stat.upload_rate() < upload_limit * 0.9f - && m_allowed_upload_slots <= m_num_unchoked + 1 - && congested_torrents < uncongested_torrents - && m_upload_channel.queue_size() < 2) - { - ++m_allowed_upload_slots; - } - else if (m_upload_channel.queue_size() > 1 - && m_allowed_upload_slots > m_max_uploads) - { - --m_allowed_upload_slots; - } - } - - // reserve one upload slot for optimistic unchokes - int unchoke_set_size = m_allowed_upload_slots - 1; - - m_num_unchoked = 0; - // go through all the peers and unchoke the first ones and choke - // all the other ones. - for (std::vector::iterator i = peers.begin() - , end(peers.end()); i != end; ++i) - { - peer_connection* p = *i; - TORRENT_ASSERT(p); - torrent* t = p->associated_torrent().lock().get(); - TORRENT_ASSERT(t); - if (unchoke_set_size > 0) - { - if (p->is_choked()) - { - if (!t->unchoke_peer(*p)) - continue; - } - - --unchoke_set_size; - ++m_num_unchoked; - - TORRENT_ASSERT(p->peer_info_struct()); - if (p->peer_info_struct()->optimistically_unchoked) - { - // force a new optimistic unchoke - // since this one just got promoted into the - // proper unchoke set - m_optimistic_unchoke_time_scaler = 0; - p->peer_info_struct()->optimistically_unchoked = false; - } - } - else - { - TORRENT_ASSERT(p->peer_info_struct()); - if (!p->is_choked() && !p->peer_info_struct()->optimistically_unchoked) - t->choke_peer(*p); - if (!p->is_choked()) - ++m_num_unchoked; - } - } - - if (m_allowed_upload_slots > 0) - { - m_optimistic_unchoke_time_scaler--; - if (m_optimistic_unchoke_time_scaler <= 0) - { - m_optimistic_unchoke_time_scaler - = settings().optimistic_unchoke_multiplier; - - // find the peer that has been waiting the longest to be optimistically - // unchoked - connection_map::iterator current_optimistic_unchoke = m_connections.end(); - connection_map::iterator optimistic_unchoke_candidate = m_connections.end(); - ptime last_unchoke = max_time(); - - for (connection_map::iterator i = m_connections.begin() - , end(m_connections.end()); i != end; ++i) - { - peer_connection* p = i->get(); - TORRENT_ASSERT(p); - policy::peer* pi = p->peer_info_struct(); - if (!pi) continue; - torrent* t = p->associated_torrent().lock().get(); - if (!t) continue; - - if (pi->optimistically_unchoked) - { - TORRENT_ASSERT(!p->is_choked()); - TORRENT_ASSERT(current_optimistic_unchoke == m_connections.end()); - current_optimistic_unchoke = i; - } - - if (pi->last_optimistically_unchoked < last_unchoke - && !p->is_connecting() - && !p->is_disconnecting() - && p->is_peer_interested() - && t->free_upload_slots() - && p->is_choked() - && t->valid_metadata()) - { - last_unchoke = pi->last_optimistically_unchoked; - optimistic_unchoke_candidate = i; - } - } - - if (optimistic_unchoke_candidate != m_connections.end() - && optimistic_unchoke_candidate != current_optimistic_unchoke) - { - if (current_optimistic_unchoke != m_connections.end()) - { - torrent* t = (*current_optimistic_unchoke)->associated_torrent().lock().get(); - TORRENT_ASSERT(t); - (*current_optimistic_unchoke)->peer_info_struct()->optimistically_unchoked = false; - t->choke_peer(*current_optimistic_unchoke->get()); - } - else - { - ++m_num_unchoked; - } - - torrent* t = (*optimistic_unchoke_candidate)->associated_torrent().lock().get(); - TORRENT_ASSERT(t); - bool ret = t->unchoke_peer(*optimistic_unchoke_candidate->get()); - TORRENT_ASSERT(ret); - (*optimistic_unchoke_candidate)->peer_info_struct()->optimistically_unchoked = true; - } - } - } - } - - void session_impl::operator()() - { - eh_initializer(); - - { - session_impl::mutex_t::scoped_lock l(m_mutex); - if (m_listen_interface.port() != 0) open_listen_port(); - } - - do - { - error_code ec; - m_io_service.run(ec); - TORRENT_ASSERT(m_abort == true); - if (ec) - { -#ifdef TORRENT_DEBUG - std::cerr << ec.message() << "\n"; - std::string err = ec.message(); -#endif - TORRENT_ASSERT(false); - } - } - while (!m_abort); - -#if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING) - (*m_logger) << time_now_string() << " locking mutex\n"; -#endif - - session_impl::mutex_t::scoped_lock l(m_mutex); -/* -#ifdef TORRENT_DEBUG - for (torrent_map::iterator i = m_torrents.begin(); - i != m_torrents.end(); ++i) - { - TORRENT_ASSERT(i->second->num_peers() == 0); - } -#endif -*/ -#if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING) - (*m_logger) << time_now_string() << " cleaning up torrents\n"; -#endif - m_torrents.clear(); - - TORRENT_ASSERT(m_torrents.empty()); - TORRENT_ASSERT(m_connections.empty()); - } - - - // the return value from this function is valid only as long as the - // session is locked! - boost::weak_ptr session_impl::find_torrent(sha1_hash const& info_hash) - { - std::map >::iterator i - = m_torrents.find(info_hash); -#ifdef TORRENT_DEBUG - for (std::map >::iterator j - = m_torrents.begin(); j != m_torrents.end(); ++j) - { - torrent* p = boost::get_pointer(j->second); - TORRENT_ASSERT(p); - } -#endif - if (i != m_torrents.end()) return i->second; - return boost::weak_ptr(); - } - -#if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_LOGGING || defined TORRENT_ERROR_LOGGING - boost::shared_ptr session_impl::create_log(std::string const& name - , int instance, bool append) - { - // current options are file_logger, cout_logger and null_logger - return boost::shared_ptr(new logger(m_logpath, name + ".log", instance, append)); - } -#endif - - std::vector session_impl::get_torrents() - { - mutex_t::scoped_lock l(m_mutex); - std::vector ret; - - for (session_impl::torrent_map::iterator i - = m_torrents.begin(), end(m_torrents.end()); - i != end; ++i) - { - if (i->second->is_aborted()) continue; - ret.push_back(torrent_handle(i->second)); - } - return ret; - } - - torrent_handle session_impl::find_torrent_handle(sha1_hash const& info_hash) - { - return torrent_handle(find_torrent(info_hash)); - } - - torrent_handle session_impl::add_torrent(add_torrent_params const& params) - { - TORRENT_ASSERT(!params.save_path.empty()); - - if (params.ti && params.ti->num_files() == 0) - { -#ifndef BOOST_NO_EXCEPTIONS - throw std::runtime_error("no files in torrent"); -#else - return torrent_handle(); -#endif - } - - // lock the session and the checker thread (the order is important!) - mutex_t::scoped_lock l(m_mutex); - -// INVARIANT_CHECK; - - if (is_aborted()) - { -#ifndef BOOST_NO_EXCEPTIONS - throw std::runtime_error("session is closing"); -#else - return torrent_handle(); -#endif - } - - // figure out the info hash of the torrent - sha1_hash const* ih = 0; - if (params.ti) ih = ¶ms.ti->info_hash(); - else ih = ¶ms.info_hash; - - // is the torrent already active? - boost::shared_ptr torrent_ptr = find_torrent(*ih).lock(); - if (torrent_ptr) - { - if (!params.duplicate_is_error) - return torrent_handle(torrent_ptr); - -#ifndef BOOST_NO_EXCEPTIONS - throw duplicate_torrent(); -#else - return torrent_handle(); -#endif - } - - int queue_pos = 0; - for (torrent_map::const_iterator i = m_torrents.begin() - , end(m_torrents.end()); i != end; ++i) - { - int pos = i->second->queue_position(); - if (pos >= queue_pos) queue_pos = pos + 1; - } - - // create the torrent and the data associated with - // the checker thread and store it before starting - // the thread - if (params.ti) - { - torrent_ptr.reset(new torrent(*this, params.ti, params.save_path - , m_listen_interface, params.storage_mode, 16 * 1024 - , params.storage, params.paused, params.resume_data - , queue_pos, params.auto_managed)); - } - else - { - torrent_ptr.reset(new torrent(*this, params.tracker_url, *ih, params.name - , params.save_path, m_listen_interface, params.storage_mode, 16 * 1024 - , params.storage, params.paused, params.resume_data - , queue_pos, params.auto_managed)); - } - torrent_ptr->start(); - -#ifndef TORRENT_DISABLE_EXTENSIONS - for (extension_list_t::iterator i = m_extensions.begin() - , end(m_extensions.end()); i != end; ++i) - { - boost::shared_ptr tp((*i)(torrent_ptr.get(), params.userdata)); - if (tp) torrent_ptr->add_extension(tp); - } -#endif - -#ifndef TORRENT_DISABLE_DHT - if (m_dht && params.ti) - { - torrent_info::nodes_t const& nodes = params.ti->nodes(); - std::for_each(nodes.begin(), nodes.end(), bind( - (void(dht::dht_tracker::*)(std::pair const&)) - &dht::dht_tracker::add_node - , boost::ref(m_dht), _1)); - } -#endif - - m_torrents.insert(std::make_pair(*ih, torrent_ptr)); - - // if this is an auto managed torrent, force a recalculation - // of which torrents to have active - if (params.auto_managed && m_auto_manage_time_scaler > 2) - m_auto_manage_time_scaler = 2; - - return torrent_handle(torrent_ptr); - } - - void session_impl::check_torrent(boost::shared_ptr const& t) - { - if (m_abort) return; - TORRENT_ASSERT(t->should_check_files()); - TORRENT_ASSERT(t->state() != torrent_status::checking_files); - if (m_queued_for_checking.empty()) t->start_checking(); - else t->set_state(torrent_status::queued_for_checking); - TORRENT_ASSERT(std::find(m_queued_for_checking.begin() - , m_queued_for_checking.end(), t) == m_queued_for_checking.end()); - m_queued_for_checking.push_back(t); - } - - void session_impl::done_checking(boost::shared_ptr const& t) - { - INVARIANT_CHECK; - - if (m_queued_for_checking.empty()) return; - boost::shared_ptr next_check = *m_queued_for_checking.begin(); - check_queue_t::iterator done = m_queued_for_checking.end(); - for (check_queue_t::iterator i = m_queued_for_checking.begin() - , end(m_queued_for_checking.end()); i != end; ++i) - { - TORRENT_ASSERT(*i == t || (*i)->should_check_files()); - if (*i == t) done = i; - if (next_check == t || next_check->queue_position() > (*i)->queue_position()) - next_check = *i; - } - // only start a new one if we removed the one that is checking - if (done == m_queued_for_checking.end()) return; - - if (next_check != t && t->state() == torrent_status::checking_files) - next_check->start_checking(); - m_queued_for_checking.erase(done); - } - - void session_impl::remove_torrent(const torrent_handle& h, int options) - { - boost::shared_ptr tptr = h.m_torrent.lock(); - if (!tptr) -#ifdef BOOST_NO_EXCEPTIONS - return; -#else - throw invalid_handle(); -#endif - - mutex_t::scoped_lock l(m_mutex); - - INVARIANT_CHECK; - - session_impl::torrent_map::iterator i = - m_torrents.find(tptr->torrent_file().info_hash()); - - if (i != m_torrents.end()) - { - torrent& t = *i->second; - if (options & session::delete_files) - t.delete_files(); - t.abort(); - -#ifdef TORRENT_DEBUG - sha1_hash i_hash = t.torrent_file().info_hash(); -#endif - t.set_queue_position(-1); - m_torrents.erase(i); - std::list >::iterator k - = std::find(m_queued_for_checking.begin(), m_queued_for_checking.end(), tptr); - if (k != m_queued_for_checking.end()) m_queued_for_checking.erase(k); - TORRENT_ASSERT(m_torrents.find(i_hash) == m_torrents.end()); - return; - } - } - - bool session_impl::listen_on( - std::pair const& port_range - , const char* net_interface) - { - session_impl::mutex_t::scoped_lock l(m_mutex); - - INVARIANT_CHECK; - - tcp::endpoint new_interface; - if (net_interface && std::strlen(net_interface) > 0) - { - error_code ec; - new_interface = tcp::endpoint(address::from_string(net_interface, ec), port_range.first); - if (ec) - { -#if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_LOGGING || defined TORRENT_ERROR_LOGGING - (*m_logger) << time_now_string() << "listen_on: " << net_interface - << " failed: " << ec.message() << "\n"; -#endif - return false; - } - } - else - new_interface = tcp::endpoint(address_v4::any(), port_range.first); - - m_listen_port_retries = port_range.second - port_range.first; - - // if the interface is the same and the socket is open - // don't do anything - if (new_interface == m_listen_interface - && !m_listen_sockets.empty()) return true; - - m_listen_interface = new_interface; - - open_listen_port(); - - bool new_listen_address = m_listen_interface.address() != new_interface.address(); - -#ifndef TORRENT_DISABLE_DHT - if ((new_listen_address || m_dht_same_port) && m_dht) - { - if (m_dht_same_port) - m_dht_settings.service_port = new_interface.port(); - // the listen interface changed, rebind the dht listen socket as well - m_dht_socket.bind(m_dht_settings.service_port); - if (m_natpmp.get()) - { - if (m_udp_mapping[0] != -1) m_natpmp->delete_mapping(m_udp_mapping[0]); - m_udp_mapping[0] = m_natpmp->add_mapping(natpmp::tcp - , m_dht_settings.service_port - , m_dht_settings.service_port); - } - if (m_upnp.get()) - { - if (m_udp_mapping[1] != -1) m_upnp->delete_mapping(m_udp_mapping[1]); - m_udp_mapping[1] = m_upnp->add_mapping(upnp::tcp - , m_dht_settings.service_port - , m_dht_settings.service_port); - } - } -#endif - -#if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_LOGGING || defined TORRENT_ERROR_LOGGING - m_logger = create_log("main_session", listen_port(), false); - (*m_logger) << time_now_string() << "\n"; -#endif - - return !m_listen_sockets.empty(); - } - - unsigned short session_impl::listen_port() const - { - mutex_t::scoped_lock l(m_mutex); - if (m_listen_sockets.empty()) return 0; - return m_listen_sockets.front().external_port;; - } - - void session_impl::announce_lsd(sha1_hash const& ih) - { - mutex_t::scoped_lock l(m_mutex); - // use internal listen port for local peers - if (m_lsd.get()) - m_lsd->announce(ih, m_listen_interface.port()); - } - - void session_impl::on_lsd_peer(tcp::endpoint peer, sha1_hash const& ih) - { - mutex_t::scoped_lock l(m_mutex); - - INVARIANT_CHECK; - - boost::shared_ptr t = find_torrent(ih).lock(); - if (!t) return; - // don't add peers from lsd to private torrents - if (t->torrent_file().priv()) return; - -#if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING) - (*m_logger) << time_now_string() - << ": added peer from local discovery: " << peer << "\n"; -#endif - t->get_policy().peer_from_tracker(peer, peer_id(0), peer_info::lsd, 0); - } - - void session_impl::on_port_mapping(int mapping, int port - , std::string const& errmsg, int map_transport) - { -#ifndef TORRENT_DISABLE_DHT - if (mapping == m_udp_mapping[map_transport] && port != 0) - { - m_external_udp_port = port; - m_dht_settings.service_port = port; - if (m_alerts.should_post()) - m_alerts.post_alert(portmap_alert(mapping, port - , map_transport)); - return; - } -#endif - - if (mapping == m_tcp_mapping[map_transport] && port != 0) - { - if (!m_listen_sockets.empty()) - m_listen_sockets.front().external_port = port; - if (m_alerts.should_post()) - m_alerts.post_alert(portmap_alert(mapping, port - , map_transport)); - return; - } - - if (!errmsg.empty()) - { - if (m_alerts.should_post()) - m_alerts.post_alert(portmap_error_alert(mapping - , map_transport, errmsg)); - } - else - { - if (m_alerts.should_post()) - m_alerts.post_alert(portmap_alert(mapping, port - , map_transport)); - } - } - - session_status session_impl::status() const - { - mutex_t::scoped_lock l(m_mutex); - -// INVARIANT_CHECK; - - session_status s; - - s.num_peers = (int)m_connections.size(); - s.num_unchoked = m_num_unchoked; - s.allowed_upload_slots = m_allowed_upload_slots; - - s.total_redundant_bytes = m_total_redundant_bytes; - s.total_failed_bytes = m_total_failed_bytes; - - s.up_bandwidth_queue = m_upload_channel.queue_size(); - s.down_bandwidth_queue = m_download_channel.queue_size(); - - s.has_incoming_connections = m_incoming_connection; - - s.download_rate = m_stat.download_rate(); - s.upload_rate = m_stat.upload_rate(); - - s.payload_download_rate = m_stat.download_payload_rate(); - s.payload_upload_rate = m_stat.upload_payload_rate(); - - s.total_download = m_stat.total_protocol_download() - + m_stat.total_payload_download(); - - s.total_upload = m_stat.total_protocol_upload() - + m_stat.total_payload_upload(); - - s.total_payload_download = m_stat.total_payload_download(); - s.total_payload_upload = m_stat.total_payload_upload(); - -#ifndef TORRENT_DISABLE_DHT - if (m_dht) - { - m_dht->dht_status(s); - } - else - { - s.dht_nodes = 0; - s.dht_node_cache = 0; - s.dht_torrents = 0; - s.dht_global_nodes = 0; - } -#endif - - return s; - } - -#ifndef TORRENT_DISABLE_DHT - - void session_impl::start_dht(entry const& startup_state) - { - mutex_t::scoped_lock l(m_mutex); - - INVARIANT_CHECK; - - if (m_dht) - { - m_dht->stop(); - m_dht = 0; - } - if (m_dht_settings.service_port == 0 - || m_dht_same_port) - { - m_dht_same_port = true; - if (m_listen_interface.port() > 0) - m_dht_settings.service_port = m_listen_interface.port(); - else - m_dht_settings.service_port = 45000 + (rand() % 10000); - } - m_external_udp_port = m_dht_settings.service_port; - if (m_natpmp.get() && m_udp_mapping[0] == -1) - { - m_udp_mapping[0] = m_natpmp->add_mapping(natpmp::udp - , m_dht_settings.service_port - , m_dht_settings.service_port); - } - if (m_upnp.get() && m_udp_mapping[1] == -1) - { - m_udp_mapping[1] = m_upnp->add_mapping(upnp::udp - , m_dht_settings.service_port - , m_dht_settings.service_port); - } - m_dht = new dht::dht_tracker(m_dht_socket, m_dht_settings, &startup_state); - if (!m_dht_socket.is_open() || m_dht_socket.local_port() != m_dht_settings.service_port) - { - m_dht_socket.bind(m_dht_settings.service_port); - } - - for (std::list >::iterator i = m_dht_router_nodes.begin() - , end(m_dht_router_nodes.end()); i != end; ++i) - { - m_dht->add_router_node(*i); - } - std::list >().swap(m_dht_router_nodes); - - m_dht->start(startup_state); - } - - void session_impl::stop_dht() - { - mutex_t::scoped_lock l(m_mutex); - if (!m_dht) return; - m_dht->stop(); - m_dht = 0; - } - - void session_impl::set_dht_settings(dht_settings const& settings) - { - mutex_t::scoped_lock l(m_mutex); - // only change the dht listen port in case the settings - // contains a vaiid port, and if it is different from - // the current setting - if (settings.service_port != 0) - m_dht_same_port = false; - else - m_dht_same_port = true; - if (!m_dht_same_port - && settings.service_port != m_dht_settings.service_port - && m_dht) - { - m_dht_socket.bind(settings.service_port); - - if (m_natpmp.get()) - { - if (m_udp_mapping[0] != -1) m_upnp->delete_mapping(m_udp_mapping[0]); - m_udp_mapping[0] = m_natpmp->add_mapping(natpmp::udp - , m_dht_settings.service_port - , m_dht_settings.service_port); - } - if (m_upnp.get()) - { - if (m_udp_mapping[1] != -1) m_upnp->delete_mapping(m_udp_mapping[1]); - m_udp_mapping[1] = m_upnp->add_mapping(upnp::udp - , m_dht_settings.service_port - , m_dht_settings.service_port); - } - m_external_udp_port = settings.service_port; - } - m_dht_settings = settings; - if (m_dht_same_port) - m_dht_settings.service_port = m_listen_interface.port(); - } - - void session_impl::dht_state_callback(boost::condition& c - , entry& e, bool& done) const - { - mutex_t::scoped_lock l(m_mutex); - if (m_dht) e = m_dht->state(); - done = true; - c.notify_all(); - } - - entry session_impl::dht_state() const - { - boost::condition cond; - mutex_t::scoped_lock l(m_mutex); - if (!m_dht) return entry(); - entry e; - bool done = false; - m_io_service.post(boost::bind(&session_impl::dht_state_callback - , this, boost::ref(cond), boost::ref(e), boost::ref(done))); - while (!done) cond.wait(l); - return e; - } - - void session_impl::add_dht_node(std::pair const& node) - { - TORRENT_ASSERT(m_dht); - mutex_t::scoped_lock l(m_mutex); - m_dht->add_node(node); - } - - void session_impl::add_dht_router(std::pair const& node) - { - // router nodes should be added before the DHT is started (and bootstrapped) - mutex_t::scoped_lock l(m_mutex); - if (m_dht) m_dht->add_router_node(node); - else m_dht_router_nodes.push_back(node); - } - -#endif - -#ifndef TORRENT_DISABLE_ENCRYPTION - void session_impl::set_pe_settings(pe_settings const& settings) - { - mutex_t::scoped_lock l(m_mutex); - m_pe_settings = settings; - } -#endif - - bool session_impl::is_listening() const - { - mutex_t::scoped_lock l(m_mutex); - return !m_listen_sockets.empty(); - } - - session_impl::~session_impl() - { -#if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING) - (*m_logger) << time_now_string() << "\n\n *** shutting down session *** \n\n"; -#endif - abort(); - TORRENT_ASSERT(m_connections.empty()); - -#ifndef TORRENT_DISABLE_GEO_IP - if (m_asnum_db) GeoIP_delete(m_asnum_db); - if (m_country_db) GeoIP_delete(m_country_db); -#endif -#if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING) - (*m_logger) << time_now_string() << " waiting for main thread\n"; -#endif - m_thread->join(); - - TORRENT_ASSERT(m_torrents.empty()); - -#if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING) - (*m_logger) << time_now_string() << " waiting for disk io thread\n"; -#endif - m_disk_thread.join(); - - TORRENT_ASSERT(m_torrents.empty()); - TORRENT_ASSERT(m_connections.empty()); -#if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING) - (*m_logger) << time_now_string() << " shutdown complete!\n"; -#endif - TORRENT_ASSERT(m_connections.empty()); - } - - void session_impl::set_max_uploads(int limit) - { - TORRENT_ASSERT(limit >= 0 || limit == -1); - mutex_t::scoped_lock l(m_mutex); - - INVARIANT_CHECK; - - if (limit <= 0) limit = (std::numeric_limits::max)(); - if (m_max_uploads == limit) return; - m_max_uploads = limit; - m_allowed_upload_slots = limit; - } - - void session_impl::set_max_connections(int limit) - { - TORRENT_ASSERT(limit > 0 || limit == -1); - mutex_t::scoped_lock l(m_mutex); - - INVARIANT_CHECK; - - if (limit <= 0) - { - limit = (std::numeric_limits::max)(); -#ifndef TORRENT_WINDOWS - rlimit l; - if (getrlimit(RLIMIT_NOFILE, &l) == 0 - && l.rlim_cur != RLIM_INFINITY) - { - limit = l.rlim_cur - m_settings.file_pool_size; - if (limit < 5) limit = 5; - } -#endif - } - m_max_connections = limit; - } - - void session_impl::set_max_half_open_connections(int limit) - { - TORRENT_ASSERT(limit > 0 || limit == -1); - mutex_t::scoped_lock l(m_mutex); - - INVARIANT_CHECK; - - if (limit <= 0) limit = (std::numeric_limits::max)(); - m_half_open.limit(limit); - } - - void session_impl::set_download_rate_limit(int bytes_per_second) - { - TORRENT_ASSERT(bytes_per_second > 0 || bytes_per_second == -1); - mutex_t::scoped_lock l(m_mutex); - - INVARIANT_CHECK; - - if (bytes_per_second <= 0) bytes_per_second = bandwidth_limit::inf; - m_bandwidth_manager[peer_connection::download_channel]->throttle(bytes_per_second); - } - - void session_impl::set_upload_rate_limit(int bytes_per_second) - { - TORRENT_ASSERT(bytes_per_second > 0 || bytes_per_second == -1); - mutex_t::scoped_lock l(m_mutex); - - INVARIANT_CHECK; - - if (bytes_per_second <= 0) bytes_per_second = bandwidth_limit::inf; - m_bandwidth_manager[peer_connection::upload_channel]->throttle(bytes_per_second); - } - - std::auto_ptr session_impl::pop_alert() - { - mutex_t::scoped_lock l(m_mutex); - -// too expensive -// INVARIANT_CHECK; - - if (m_alerts.pending()) - return m_alerts.get(); - return std::auto_ptr(0); - } - - alert const* session_impl::wait_for_alert(time_duration max_wait) - { - return m_alerts.wait_for_alert(max_wait); - } - - void session_impl::set_alert_mask(int m) - { - mutex_t::scoped_lock l(m_mutex); - m_alerts.set_alert_mask(m); - } - - size_t session_impl::set_alert_queue_size_limit(size_t queue_size_limit_) - { - mutex_t::scoped_lock l(m_mutex); - return m_alerts.set_alert_queue_size_limit(queue_size_limit_); - } - - int session_impl::upload_rate_limit() const - { - mutex_t::scoped_lock l(m_mutex); - - INVARIANT_CHECK; - - int ret = m_bandwidth_manager[peer_connection::upload_channel]->throttle(); - return ret == (std::numeric_limits::max)() ? -1 : ret; - } - - int session_impl::download_rate_limit() const - { - mutex_t::scoped_lock l(m_mutex); - int ret = m_bandwidth_manager[peer_connection::download_channel]->throttle(); - return ret == (std::numeric_limits::max)() ? -1 : ret; - } - - void session_impl::start_lsd() - { - mutex_t::scoped_lock l(m_mutex); - - INVARIANT_CHECK; - - if (m_lsd) return; - - m_lsd = new lsd(m_io_service - , m_listen_interface.address() - , bind(&session_impl::on_lsd_peer, this, _1, _2)); - } - - natpmp* session_impl::start_natpmp() - { - mutex_t::scoped_lock l(m_mutex); - - INVARIANT_CHECK; - - if (m_natpmp) return m_natpmp.get(); - - m_natpmp = new natpmp(m_io_service - , m_listen_interface.address() - , bind(&session_impl::on_port_mapping - , this, _1, _2, _3, 0)); - - if (m_listen_interface.port() > 0) - { - m_tcp_mapping[0] = m_natpmp->add_mapping(natpmp::tcp - , m_listen_interface.port(), m_listen_interface.port()); - } -#ifndef TORRENT_DISABLE_DHT - if (m_dht) - m_udp_mapping[0] = m_natpmp->add_mapping(natpmp::udp - , m_dht_settings.service_port - , m_dht_settings.service_port); -#endif - return m_natpmp.get(); - } - - upnp* session_impl::start_upnp() - { - mutex_t::scoped_lock l(m_mutex); - - INVARIANT_CHECK; - - if (m_upnp) return m_upnp.get(); - - m_upnp = new upnp(m_io_service, m_half_open - , m_listen_interface.address() - , m_settings.user_agent - , bind(&session_impl::on_port_mapping - , this, _1, _2, _3, 1) - , m_settings.upnp_ignore_nonrouters); - - m_upnp->discover_device(); - if (m_listen_interface.port() > 0) - { - m_tcp_mapping[1] = m_upnp->add_mapping(upnp::tcp - , m_listen_interface.port(), m_listen_interface.port()); - } -#ifndef TORRENT_DISABLE_DHT - if (m_dht) - m_udp_mapping[1] = m_upnp->add_mapping(upnp::udp - , m_dht_settings.service_port - , m_dht_settings.service_port); -#endif - return m_upnp.get(); - } - - void session_impl::stop_lsd() - { - mutex_t::scoped_lock l(m_mutex); - if (m_lsd.get()) - m_lsd->close(); - m_lsd = 0; - } - - void session_impl::stop_natpmp() - { - mutex_t::scoped_lock l(m_mutex); - if (m_natpmp.get()) - m_natpmp->close(); - m_natpmp = 0; - } - - void session_impl::stop_upnp() - { - mutex_t::scoped_lock l(m_mutex); - if (m_upnp.get()) - { - m_upnp->close(); - m_udp_mapping[1] = -1; - m_tcp_mapping[1] = -1; - } - m_upnp = 0; - } - - void session_impl::set_external_address(address const& ip) - { - TORRENT_ASSERT(ip != address()); - - if (is_local(ip)) return; - if (is_loopback(ip)) return; - if (m_external_address == ip) return; - - m_external_address = ip; - if (m_alerts.should_post()) - m_alerts.post_alert(external_ip_alert(ip)); - } - - void session_impl::free_disk_buffer(char* buf) - { - m_disk_thread.free_buffer(buf); - } - - char* session_impl::allocate_disk_buffer() - { - return m_disk_thread.allocate_buffer(); - } - - std::pair session_impl::allocate_buffer(int size) - { - TORRENT_ASSERT(size > 0); - int num_buffers = (size + send_buffer_size - 1) / send_buffer_size; - TORRENT_ASSERT(num_buffers > 0); - - boost::mutex::scoped_lock l(m_send_buffer_mutex); -#ifdef TORRENT_STATS - TORRENT_ASSERT(m_buffer_allocations >= 0); - m_buffer_allocations += num_buffers; - m_buffer_usage_logger << log_time() << " protocol_buffer: " - << (m_buffer_allocations * send_buffer_size) << std::endl; -#endif -#ifdef TORRENT_DISABLE_POOL_ALLOCATOR - int num_bytes = num_buffers * send_buffer_size; - return std::make_pair((char*)malloc(num_bytes), num_bytes); -#else - return std::make_pair((char*)m_send_buffers.ordered_malloc(num_buffers) - , num_buffers * send_buffer_size); -#endif - } - -#ifdef TORRENT_STATS - void session_impl::log_buffer_usage() - { - int send_buffer_capacity = 0; - int used_send_buffer = 0; - for (connection_map::const_iterator i = m_connections.begin() - , end(m_connections.end()); i != end; ++i) - { - send_buffer_capacity += (*i)->send_buffer_capacity(); - used_send_buffer += (*i)->send_buffer_size(); - } - TORRENT_ASSERT(send_buffer_capacity >= used_send_buffer); - m_buffer_usage_logger << log_time() << " send_buffer_size: " << send_buffer_capacity << std::endl; - m_buffer_usage_logger << log_time() << " used_send_buffer: " << used_send_buffer << std::endl; - m_buffer_usage_logger << log_time() << " send_buffer_utilization: " - << (used_send_buffer * 100.f / send_buffer_capacity) << std::endl; - } -#endif - - void session_impl::free_buffer(char* buf, int size) - { - TORRENT_ASSERT(size > 0); - TORRENT_ASSERT(size % send_buffer_size == 0); - int num_buffers = size / send_buffer_size; - TORRENT_ASSERT(num_buffers > 0); - - boost::mutex::scoped_lock l(m_send_buffer_mutex); -#ifdef TORRENT_STATS - m_buffer_allocations -= num_buffers; - TORRENT_ASSERT(m_buffer_allocations >= 0); - m_buffer_usage_logger << log_time() << " protocol_buffer: " - << (m_buffer_allocations * send_buffer_size) << std::endl; -#endif -#ifdef TORRENT_DISABLE_POOL_ALLOCATOR - free(buf); -#else - m_send_buffers.ordered_free(buf, num_buffers); -#endif - } - -#ifdef TORRENT_DEBUG - void session_impl::check_invariant() const - { - std::set unique; - int total_downloaders = 0; - for (torrent_map::const_iterator i = m_torrents.begin() - , end(m_torrents.end()); i != end; ++i) - { - int pos = i->second->queue_position(); - if (pos < 0) - { - TORRENT_ASSERT(pos == -1); - continue; - } - ++total_downloaders; - unique.insert(i->second->queue_position()); - } - TORRENT_ASSERT(int(unique.size()) == total_downloaders); - - TORRENT_ASSERT(m_max_connections > 0); - TORRENT_ASSERT(m_max_uploads > 0); - TORRENT_ASSERT(m_allowed_upload_slots >= m_max_uploads); - int unchokes = 0; - int num_optimistic = 0; - for (connection_map::const_iterator i = m_connections.begin(); - i != m_connections.end(); ++i) - { - TORRENT_ASSERT(*i); - boost::shared_ptr t = (*i)->associated_torrent().lock(); - - peer_connection* p = i->get(); - TORRENT_ASSERT(!p->is_disconnecting()); - if (!p->is_choked()) ++unchokes; - if (p->peer_info_struct() - && p->peer_info_struct()->optimistically_unchoked) - { - ++num_optimistic; - TORRENT_ASSERT(!p->is_choked()); - } - if (t && p->peer_info_struct()) - { - TORRENT_ASSERT(t->get_policy().has_connection(p)); - } - } - TORRENT_ASSERT(num_optimistic == 0 || num_optimistic == 1); - if (m_num_unchoked != unchokes) - { - TORRENT_ASSERT(false); - } - for (std::map >::const_iterator j - = m_torrents.begin(); j != m_torrents.end(); ++j) - { - TORRENT_ASSERT(boost::get_pointer(j->second)); - } - } -#endif - -}} - diff --git a/libtorrent/src/sha1.cpp b/libtorrent/src/sha1.cpp deleted file mode 100755 index a7ea67113..000000000 --- a/libtorrent/src/sha1.cpp +++ /dev/null @@ -1,317 +0,0 @@ -/* -SHA-1 C++ conversion - -original version: - -SHA-1 in C -By Steve Reid -100% Public Domain - -changelog at the end of the file. -*/ - -#include "libtorrent/pch.hpp" - -#include -#include - -// if you don't want boost -// replace with -// #include - -#include -using boost::uint32_t; -using boost::uint8_t; - -#include "libtorrent/config.hpp" - -struct TORRENT_EXPORT SHA_CTX -{ - uint32_t state[5]; - uint32_t count[2]; - uint8_t buffer[64]; -}; - -TORRENT_EXPORT void SHA1_Init(SHA_CTX* context); -TORRENT_EXPORT void SHA1_Update(SHA_CTX* context, uint8_t const* data, uint32_t len); -TORRENT_EXPORT void SHA1_Final(uint8_t* digest, SHA_CTX* context); - -namespace -{ - union CHAR64LONG16 - { - uint8_t c[64]; - uint32_t l[16]; - }; - -#define rol(value, bits) (((value) << (bits)) | ((value) >> (32 - (bits)))) - -// blk0() and blk() perform the initial expand. -// I got the idea of expanding during the round function from SSLeay - struct little_endian_blk0 - { - static uint32_t apply(CHAR64LONG16* block, int i) - { - return block->l[i] = (rol(block->l[i],24)&0xFF00FF00) - | (rol(block->l[i],8)&0x00FF00FF); - } - }; - - struct big_endian_blk0 - { - static uint32_t apply(CHAR64LONG16* block, int i) - { - return block->l[i]; - } - }; - - -#define blk(i) (block->l[i&15] = rol(block->l[(i+13)&15]^block->l[(i+8)&15] \ - ^block->l[(i+2)&15]^block->l[i&15],1)) - -// (R0+R1), R2, R3, R4 are the different operations used in SHA1 -#define R0(v,w,x,y,z,i) z+=((w&(x^y))^y)+BlkFun::apply(block, i)+0x5A827999+rol(v,5);w=rol(w,30); -#define R1(v,w,x,y,z,i) z+=((w&(x^y))^y)+blk(i)+0x5A827999+rol(v,5);w=rol(w,30); -#define R2(v,w,x,y,z,i) z+=(w^x^y)+blk(i)+0x6ED9EBA1+rol(v,5);w=rol(w,30); -#define R3(v,w,x,y,z,i) z+=(((w|x)&y)|(w&x))+blk(i)+0x8F1BBCDC+rol(v,5);w=rol(w,30); -#define R4(v,w,x,y,z,i) z+=(w^x^y)+blk(i)+0xCA62C1D6+rol(v,5);w=rol(w,30); - - // Hash a single 512-bit block. This is the core of the algorithm. - template - void SHA1Transform(uint32_t state[5], uint8_t const buffer[64]) - { - using namespace std; - uint32_t a, b, c, d, e; - - CHAR64LONG16* block; - uint8_t workspace[64]; - block = (CHAR64LONG16*)workspace; - memcpy(block, buffer, 64); - - // Copy context->state[] to working vars - a = state[0]; - b = state[1]; - c = state[2]; - d = state[3]; - e = state[4]; - // 4 rounds of 20 operations each. Loop unrolled. - R0(a,b,c,d,e, 0); R0(e,a,b,c,d, 1); R0(d,e,a,b,c, 2); R0(c,d,e,a,b, 3); - R0(b,c,d,e,a, 4); R0(a,b,c,d,e, 5); R0(e,a,b,c,d, 6); R0(d,e,a,b,c, 7); - R0(c,d,e,a,b, 8); R0(b,c,d,e,a, 9); R0(a,b,c,d,e,10); R0(e,a,b,c,d,11); - R0(d,e,a,b,c,12); R0(c,d,e,a,b,13); R0(b,c,d,e,a,14); R0(a,b,c,d,e,15); - R1(e,a,b,c,d,16); R1(d,e,a,b,c,17); R1(c,d,e,a,b,18); R1(b,c,d,e,a,19); - R2(a,b,c,d,e,20); R2(e,a,b,c,d,21); R2(d,e,a,b,c,22); R2(c,d,e,a,b,23); - R2(b,c,d,e,a,24); R2(a,b,c,d,e,25); R2(e,a,b,c,d,26); R2(d,e,a,b,c,27); - R2(c,d,e,a,b,28); R2(b,c,d,e,a,29); R2(a,b,c,d,e,30); R2(e,a,b,c,d,31); - R2(d,e,a,b,c,32); R2(c,d,e,a,b,33); R2(b,c,d,e,a,34); R2(a,b,c,d,e,35); - R2(e,a,b,c,d,36); R2(d,e,a,b,c,37); R2(c,d,e,a,b,38); R2(b,c,d,e,a,39); - R3(a,b,c,d,e,40); R3(e,a,b,c,d,41); R3(d,e,a,b,c,42); R3(c,d,e,a,b,43); - R3(b,c,d,e,a,44); R3(a,b,c,d,e,45); R3(e,a,b,c,d,46); R3(d,e,a,b,c,47); - R3(c,d,e,a,b,48); R3(b,c,d,e,a,49); R3(a,b,c,d,e,50); R3(e,a,b,c,d,51); - R3(d,e,a,b,c,52); R3(c,d,e,a,b,53); R3(b,c,d,e,a,54); R3(a,b,c,d,e,55); - R3(e,a,b,c,d,56); R3(d,e,a,b,c,57); R3(c,d,e,a,b,58); R3(b,c,d,e,a,59); - R4(a,b,c,d,e,60); R4(e,a,b,c,d,61); R4(d,e,a,b,c,62); R4(c,d,e,a,b,63); - R4(b,c,d,e,a,64); R4(a,b,c,d,e,65); R4(e,a,b,c,d,66); R4(d,e,a,b,c,67); - R4(c,d,e,a,b,68); R4(b,c,d,e,a,69); R4(a,b,c,d,e,70); R4(e,a,b,c,d,71); - R4(d,e,a,b,c,72); R4(c,d,e,a,b,73); R4(b,c,d,e,a,74); R4(a,b,c,d,e,75); - R4(e,a,b,c,d,76); R4(d,e,a,b,c,77); R4(c,d,e,a,b,78); R4(b,c,d,e,a,79); - // Add the working vars back into context.state[] - state[0] += a; - state[1] += b; - state[2] += c; - state[3] += d; - state[4] += e; - // Wipe variables - a = b = c = d = e = 0; - } - - void SHAPrintContext(SHA_CTX *context, char *msg) - { - using namespace std; - printf("%s (%d,%d) %x %x %x %x %x\n" - , msg, context->count[0], context->count[1] - , context->state[0], context->state[1] - , context->state[2], context->state[3] - , context->state[4]); - } - - template - void internal_update(SHA_CTX* context, uint8_t const* data, uint32_t len) - { - using namespace std; - uint32_t i, j; // JHB - -#ifdef VERBOSE - SHAPrintContext(context, "before"); -#endif - j = (context->count[0] >> 3) & 63; - if ((context->count[0] += len << 3) < (len << 3)) context->count[1]++; - context->count[1] += (len >> 29); - if ((j + len) > 63) - { - memcpy(&context->buffer[j], data, (i = 64-j)); - SHA1Transform(context->state, context->buffer); - for ( ; i + 63 < len; i += 64) - { - SHA1Transform(context->state, &data[i]); - } - j = 0; - } - else - { - i = 0; - } - memcpy(&context->buffer[j], &data[i], len - i); -#ifdef VERBOSE - SHAPrintContext(context, "after "); -#endif - } - - bool is_big_endian() - { - uint32_t test = 1; - return *reinterpret_cast(&test) == 0; - } -} - -// SHA1Init - Initialize new context - -void SHA1_Init(SHA_CTX* context) -{ - // SHA1 initialization constants - context->state[0] = 0x67452301; - context->state[1] = 0xEFCDAB89; - context->state[2] = 0x98BADCFE; - context->state[3] = 0x10325476; - context->state[4] = 0xC3D2E1F0; - context->count[0] = context->count[1] = 0; -} - - -// Run your data through this. - -void SHA1_Update(SHA_CTX* context, uint8_t const* data, uint32_t len) -{ -#if defined __BIG_ENDIAN__ - internal_update(context, data, len); -#elif defined LITTLE_ENDIAN - internal_update(context, data, len); -#else - // select different functions depending on endianess - // and figure out the endianess runtime - if (is_big_endian()) - internal_update(context, data, len); - else - internal_update(context, data, len); -#endif -} - - -// Add padding and return the message digest. - -void SHA1_Final(uint8_t* digest, SHA_CTX* context) -{ - uint8_t finalcount[8]; - - for (uint32_t i = 0; i < 8; ++i) - { - // Endian independent - finalcount[i] = static_cast( - (context->count[(i >= 4 ? 0 : 1)] - >> ((3-(i & 3)) * 8) ) & 255); - } - - SHA1_Update(context, (uint8_t const*)"\200", 1); - while ((context->count[0] & 504) != 448) - SHA1_Update(context, (uint8_t const*)"\0", 1); - SHA1_Update(context, finalcount, 8); // Should cause a SHA1Transform() - - for (uint32_t i = 0; i < 20; ++i) - { - digest[i] = static_cast( - (context->state[i>>2] >> ((3-(i & 3)) * 8) ) & 255); - } -} - -/************************************************************ - ------------------ -Modified 7/98 -By James H. Brown -Still 100% Public Domain - -Corrected a problem which generated improper hash values on 16 bit machines -Routine SHA1Update changed from - void SHA1Update(SHA1_CTX* context, unsigned char* data, unsigned int -len) -to - void SHA1Update(SHA1_CTX* context, unsigned char* data, unsigned -long len) - -The 'len' parameter was declared an int which works fine on 32 bit machines. -However, on 16 bit machines an int is too small for the shifts being done -against -it. This caused the hash function to generate incorrect values if len was -greater than 8191 (8K - 1) due to the 'len << 3' on line 3 of SHA1Update(). - -Since the file IO in main() reads 16K at a time, any file 8K or larger would -be guaranteed to generate the wrong hash (e.g. Test Vector #3, a million -"a"s). - -I also changed the declaration of variables i & j in SHA1Update to -unsigned long from unsigned int for the same reason. - -These changes should make no difference to any 32 bit implementations since -an -int and a long are the same size in those environments. - --- -I also corrected a few compiler warnings generated by Borland C. -1. Added #include for exit() prototype -2. Removed unused variable 'j' in SHA1Final -3. Changed exit(0) to return(0) at end of main. - -ALL changes I made can be located by searching for comments containing 'JHB' ------------------ -Modified 8/98 -By Steve Reid -Still 100% public domain - -1- Removed #include and used return() instead of exit() -2- Fixed overwriting of finalcount in SHA1Final() (discovered by Chris Hall) -3- Changed email address from steve@edmweb.com to sreid@sea-to-sky.net - ------------------ -Modified 4/01 -By Saul Kravitz -Still 100% PD -Modified to run on Compaq Alpha hardware. - ------------------ -Converted to C++ 6/04 -By Arvid Norberg -1- made the input buffer const, and made the - previous SHA1HANDSOFF implicit -2- uses C99 types with size guarantees - from boost -3- if none of __BIG_ENDIAN__ or LITTLE_ENDIAN - are defined, endianess is determined - at runtime. templates are used to duplicate - the transform function for each endianess -4- using anonymous namespace to avoid external - linkage on internal functions -5- using standard C++ includes -6- made API compatible with openssl - -still 100% PD -*/ - -/* -Test Vectors (from FIPS PUB 180-1) -"abc" - A9993E36 4706816A BA3E2571 7850C26C 9CD0D89D -"abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq" - 84983E44 1C3BD26E BAAE4AA1 F95129E5 E54670F1 -A million repetitions of "a" - 34AA973C D4C4DAA4 F61EEB2B DBAD2731 6534016F -*/ diff --git a/libtorrent/src/smart_ban.cpp b/libtorrent/src/smart_ban.cpp deleted file mode 100644 index 8e7bc90b4..000000000 --- a/libtorrent/src/smart_ban.cpp +++ /dev/null @@ -1,302 +0,0 @@ -/* - -Copyright (c) 2007, Arvid Norberg -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions -are met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in - the documentation and/or other materials provided with the distribution. - * Neither the name of the author nor the names of its - contributors may be used to endorse or promote products derived - from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -POSSIBILITY OF SUCH DAMAGE. - -*/ - -#include "libtorrent/pch.hpp" - -#ifdef _MSC_VER -#pragma warning(push, 1) -#endif - -#include -#include - -#ifdef _MSC_VER -#pragma warning(pop) -#endif - -#include -#include -#include -#include -#include - -#include "libtorrent/peer_connection.hpp" -#include "libtorrent/bt_peer_connection.hpp" -#include "libtorrent/hasher.hpp" -#include "libtorrent/bencode.hpp" -#include "libtorrent/torrent.hpp" -#include "libtorrent/extensions.hpp" -#include "libtorrent/extensions/smart_ban.hpp" -#include "libtorrent/alert_types.hpp" -#include "libtorrent/disk_io_thread.hpp" -#include "libtorrent/aux_/session_impl.hpp" - -namespace libtorrent { namespace -{ - - struct smart_ban_plugin : torrent_plugin, boost::enable_shared_from_this - { - smart_ban_plugin(torrent& t) - : m_torrent(t) - , m_salt(rand()) - { - } - - void on_piece_pass(int p) - { -#ifdef TORRENT_LOGGING - (*m_torrent.session().m_logger) << time_now_string() << " PIECE PASS [ p: " << p - << " | block_crc_size: " << m_block_crc.size() << " ]\n"; -#endif - // has this piece failed earlier? If it has, go through the - // CRCs from the time it failed and ban the peers that - // sent bad blocks - std::map::iterator i = m_block_crc.lower_bound(piece_block(p, 0)); - if (i == m_block_crc.end() || i->first.piece_index != p) return; - - int size = m_torrent.torrent_file().piece_size(p); - peer_request r = {p, 0, (std::min)(16*1024, size)}; - piece_block pb(p, 0); - while (size > 0) - { - if (i->first.block_index == pb.block_index) - { - m_torrent.filesystem().async_read(r, bind(&smart_ban_plugin::on_read_ok_block - , shared_from_this(), *i, _1, _2)); - m_block_crc.erase(i++); - } - else - { - TORRENT_ASSERT(i->first.block_index > pb.block_index); - } - - if (i == m_block_crc.end() || i->first.piece_index != p) - break; - - r.start += 16*1024; - size -= 16*1024; - r.length = (std::min)(16*1024, size); - ++pb.block_index; - } - -#ifndef NDEBUG - // make sure we actually removed all the entries for piece 'p' - i = m_block_crc.lower_bound(piece_block(p, 0)); - TORRENT_ASSERT(i == m_block_crc.end() || i->first.piece_index != p); -#endif - - if (m_torrent.is_seed()) - { - std::map().swap(m_block_crc); - return; - } - } - - void on_piece_failed(int p) - { - // The piece failed the hash check. Record - // the CRC and origin peer of every block - - // if the torrent is aborted, no point in starting - // a bunch of read operations on it - if (m_torrent.is_aborted()) return; - - std::vector downloaders; - m_torrent.picker().get_downloaders(downloaders, p); - - int size = m_torrent.torrent_file().piece_size(p); - peer_request r = {p, 0, (std::min)(16*1024, size)}; - piece_block pb(p, 0); - for (std::vector::iterator i = downloaders.begin() - , end(downloaders.end()); i != end; ++i) - { - if (*i != 0) - { - m_torrent.filesystem().async_read(r, bind(&smart_ban_plugin::on_read_failed_block - , shared_from_this(), pb, (policy::peer*)*i, _1, _2)); - } - - r.start += 16*1024; - size -= 16*1024; - r.length = (std::min)(16*1024, size); - ++pb.block_index; - } - TORRENT_ASSERT(size <= 0); - } - - private: - - // this entry ties a specific block CRC to - // a peer. - struct block_entry - { - policy::peer* peer; - unsigned long crc; - }; - - void on_read_failed_block(piece_block b, policy::peer* p, int ret, disk_io_job const& j) - { - TORRENT_ASSERT(p); - // ignore read errors - if (ret != j.buffer_size) return; - - adler32_crc crc; - crc.update(j.buffer, j.buffer_size); - crc.update((char const*)&m_salt, sizeof(m_salt)); - - block_entry e = {p, crc.final()}; - - // since this callback is called directory from the disk io - // thread, the session mutex is not locked when we get here - aux::session_impl::mutex_t::scoped_lock l(m_torrent.session().m_mutex); - - std::map::iterator i = m_block_crc.lower_bound(b); - if (i != m_block_crc.end() && i->first == b && i->second.peer == p) - { - // this peer has sent us this block before - if (i->second.crc != e.crc) - { - // this time the crc of the block is different - // from the first time it sent it - // at least one of them must be bad - - if (p == 0) return; - if (!m_torrent.get_policy().has_peer(p)) return; - -#ifdef TORRENT_LOGGING - char const* client = "-"; - peer_info info; - if (p->connection) - { - p->connection->get_peer_info(info); - client = info.client.c_str(); - } - (*m_torrent.session().m_logger) << time_now_string() << " BANNING PEER [ p: " << b.piece_index - << " | b: " << b.block_index - << " | c: " << client - << " | crc1: " << i->second.crc - << " | crc2: " << e.crc - << " | ip: " << p->ip() << " ]\n"; -#endif - p->banned = true; - if (p->connection) p->connection->disconnect("banning peer for sending bad data"); - } - // we already have this exact entry in the map - // we don't have to insert it - return; - } - - m_block_crc.insert(i, std::make_pair(b, e)); - -#ifdef TORRENT_LOGGING - char const* client = "-"; - peer_info info; - if (p->connection) - { - p->connection->get_peer_info(info); - client = info.client.c_str(); - } - (*m_torrent.session().m_logger) << time_now_string() << " STORE BLOCK CRC [ p: " << b.piece_index - << " | b: " << b.block_index - << " | c: " << client - << " | crc: " << e.crc - << " | ip: " << p->ip() << " ]\n"; -#endif - } - - void on_read_ok_block(std::pair b, int ret, disk_io_job const& j) - { - // since this callback is called directory from the disk io - // thread, the session mutex is not locked when we get here - aux::session_impl::mutex_t::scoped_lock l(m_torrent.session().m_mutex); - - // ignore read errors - if (ret != j.buffer_size) return; - - adler32_crc crc; - crc.update(j.buffer, j.buffer_size); - crc.update((char const*)&m_salt, sizeof(m_salt)); - unsigned long ok_crc = crc.final(); - - if (b.second.crc == ok_crc) return; - - policy::peer* p = b.second.peer; - - if (p == 0) return; - if (!m_torrent.get_policy().has_peer(p)) return; - -#ifdef TORRENT_LOGGING - char const* client = "-"; - peer_info info; - if (p->connection) - { - p->connection->get_peer_info(info); - client = info.client.c_str(); - } - (*m_torrent.session().m_logger) << time_now_string() << " BANNING PEER [ p: " << b.first.piece_index - << " | b: " << b.first.block_index - << " | c: " << client - << " | ok_crc: " << ok_crc - << " | bad_crc: " << b.second.crc - << " | ip: " << p->ip() << " ]\n"; -#endif - p->banned = true; - if (p->connection) p->connection->disconnect("banning peer for sending bad data"); - } - - torrent& m_torrent; - - // This table maps a piece_block (piece and block index - // pair) to a peer and the block CRC. The CRC is calculated - // from the data in the block + the salt - std::map m_block_crc; - - // This salt is a random value used to calculate the block CRCs - // Since the CRC function that is used is not a one way function - // the salt is required to avoid attacks where bad data is sent - // that is forged to match the CRC of the good data. - int m_salt; - }; - -} } - -namespace libtorrent -{ - - boost::shared_ptr create_smart_ban_plugin(torrent* t, void*) - { - return boost::shared_ptr(new smart_ban_plugin(*t)); - } - -} - - diff --git a/libtorrent/src/socks4_stream.cpp b/libtorrent/src/socks4_stream.cpp deleted file mode 100644 index e4add5d4f..000000000 --- a/libtorrent/src/socks4_stream.cpp +++ /dev/null @@ -1,152 +0,0 @@ -/* - -Copyright (c) 2007, Arvid Norberg -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions -are met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in - the documentation and/or other materials provided with the distribution. - * Neither the name of the author nor the names of its - contributors may be used to endorse or promote products derived - from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -POSSIBILITY OF SUCH DAMAGE. - -*/ - -#include "libtorrent/pch.hpp" - -#include "libtorrent/socks4_stream.hpp" - -namespace libtorrent -{ - - void socks4_stream::name_lookup(error_code const& e, tcp::resolver::iterator i - , boost::shared_ptr h) - { - if (e) - { - (*h)(e); - error_code ec; - close(ec); - return; - } - - // SOCKS4 doesn't support IPv6 addresses - while (i != tcp::resolver::iterator() && i->endpoint().address().is_v6()) - ++i; - - if (i == tcp::resolver::iterator()) - { - error_code ec = asio::error::operation_not_supported; - (*h)(ec); - close(ec); - return; - } - - m_sock.async_connect(i->endpoint(), boost::bind( - &socks4_stream::connected, this, _1, h)); - } - - void socks4_stream::connected(error_code const& e, boost::shared_ptr h) - { - if (e) - { - (*h)(e); - error_code ec; - close(ec); - return; - } - - using namespace libtorrent::detail; - - m_buffer.resize(m_user.size() + 9); - char* p = &m_buffer[0]; - write_uint8(4, p); // SOCKS VERSION 4 - write_uint8(1, p); // SOCKS CONNECT - write_uint16(m_remote_endpoint.port(), p); - write_uint32(m_remote_endpoint.address().to_v4().to_ulong(), p); - std::copy(m_user.begin(), m_user.end(), p); - p += m_user.size(); - write_uint8(0, p); // NULL terminator - - async_write(m_sock, asio::buffer(m_buffer) - , boost::bind(&socks4_stream::handshake1, this, _1, h)); - } - - void socks4_stream::handshake1(error_code const& e, boost::shared_ptr h) - { - if (e) - { - (*h)(e); - error_code ec; - close(ec); - return; - } - - m_buffer.resize(8); - async_read(m_sock, asio::buffer(m_buffer) - , boost::bind(&socks4_stream::handshake2, this, _1, h)); - } - - void socks4_stream::handshake2(error_code const& e, boost::shared_ptr h) - { - if (e) - { - (*h)(e); - error_code ec; - close(ec); - return; - } - - using namespace libtorrent::detail; - - char* p = &m_buffer[0]; - int reply_version = read_uint8(p); - int status_code = read_uint8(p); - - if (reply_version != 0) - { - error_code ec = asio::error::operation_not_supported; - (*h)(ec); - close(ec); - return; - } - - // access granted - if (status_code == 90) - { - std::vector().swap(m_buffer); - (*h)(e); - return; - } - - error_code ec = asio::error::fault; - switch (status_code) - { - case 91: ec = asio::error::connection_refused; break; - case 92: ec = asio::error::no_permission; break; - case 93: ec = asio::error::no_permission; break; - } - (*h)(ec); - close(ec); - } - -} - diff --git a/libtorrent/src/socks5_stream.cpp b/libtorrent/src/socks5_stream.cpp deleted file mode 100644 index 3fb9ec666..000000000 --- a/libtorrent/src/socks5_stream.cpp +++ /dev/null @@ -1,332 +0,0 @@ -/* - -Copyright (c) 2007, Arvid Norberg -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions -are met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in - the documentation and/or other materials provided with the distribution. - * Neither the name of the author nor the names of its - contributors may be used to endorse or promote products derived - from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -POSSIBILITY OF SUCH DAMAGE. - -*/ - -#include "libtorrent/pch.hpp" - -#include "libtorrent/socks5_stream.hpp" -#include "libtorrent/assert.hpp" - -namespace libtorrent -{ - - void socks5_stream::name_lookup(error_code const& e, tcp::resolver::iterator i - , boost::shared_ptr h) - { - if (e || i == tcp::resolver::iterator()) - { - (*h)(e); - error_code ec; - close(ec); - return; - } - - m_sock.async_connect(i->endpoint(), boost::bind( - &socks5_stream::connected, this, _1, h)); - } - - void socks5_stream::connected(error_code const& e, boost::shared_ptr h) - { - if (e) - { - (*h)(e); - error_code ec; - close(ec); - return; - } - - using namespace libtorrent::detail; - // send SOCKS5 authentication methods - m_buffer.resize(m_user.empty()?3:4); - char* p = &m_buffer[0]; - write_uint8(5, p); // SOCKS VERSION 5 - if (m_user.empty()) - { - write_uint8(1, p); // 1 authentication method (no auth) - write_uint8(0, p); // no authentication - } - else - { - write_uint8(2, p); // 2 authentication methods - write_uint8(0, p); // no authentication - write_uint8(2, p); // username/password - } - async_write(m_sock, asio::buffer(m_buffer) - , boost::bind(&socks5_stream::handshake1, this, _1, h)); - } - - void socks5_stream::handshake1(error_code const& e, boost::shared_ptr h) - { - if (e) - { - (*h)(e); - error_code ec; - close(ec); - return; - } - - m_buffer.resize(2); - async_read(m_sock, asio::buffer(m_buffer) - , boost::bind(&socks5_stream::handshake2, this, _1, h)); - } - - void socks5_stream::handshake2(error_code const& e, boost::shared_ptr h) - { - if (e) - { - (*h)(e); - error_code ec; - close(ec); - return; - } - - using namespace libtorrent::detail; - - char* p = &m_buffer[0]; - int version = read_uint8(p); - int method = read_uint8(p); - - if (version < 5) - { - (*h)(asio::error::operation_not_supported); - error_code ec; - close(ec); - return; - } - - if (method == 0) - { - socks_connect(h); - } - else if (method == 2) - { - if (m_user.empty()) - { - (*h)(asio::error::operation_not_supported); - error_code ec; - close(ec); - return; - } - - // start sub-negotiation - m_buffer.resize(m_user.size() + m_password.size() + 3); - char* p = &m_buffer[0]; - write_uint8(1, p); - write_uint8(m_user.size(), p); - write_string(m_user, p); - write_uint8(m_password.size(), p); - write_string(m_password, p); - async_write(m_sock, asio::buffer(m_buffer) - , boost::bind(&socks5_stream::handshake3, this, _1, h)); - } - else - { - (*h)(asio::error::operation_not_supported); - error_code ec; - close(ec); - return; - } - } - - void socks5_stream::handshake3(error_code const& e - , boost::shared_ptr h) - { - if (e) - { - (*h)(e); - error_code ec; - close(ec); - return; - } - - m_buffer.resize(2); - async_read(m_sock, asio::buffer(m_buffer) - , boost::bind(&socks5_stream::handshake4, this, _1, h)); - } - - void socks5_stream::handshake4(error_code const& e - , boost::shared_ptr h) - { - if (e) - { - (*h)(e); - error_code ec; - close(ec); - return; - } - - using namespace libtorrent::detail; - - char* p = &m_buffer[0]; - int version = read_uint8(p); - int status = read_uint8(p); - - if (version != 1) - { - (*h)(asio::error::operation_not_supported); - error_code ec; - close(ec); - return; - } - - if (status != 0) - { - (*h)(asio::error::operation_not_supported); - error_code ec; - close(ec); - return; - } - - std::vector().swap(m_buffer); - socks_connect(h); - } - - void socks5_stream::socks_connect(boost::shared_ptr h) - { - using namespace libtorrent::detail; - - // send SOCKS5 connect command - m_buffer.resize(6 + (m_remote_endpoint.address().is_v4()?4:16)); - char* p = &m_buffer[0]; - write_uint8(5, p); // SOCKS VERSION 5 - write_uint8(1, p); // CONNECT command - write_uint8(0, p); // reserved - write_uint8(m_remote_endpoint.address().is_v4()?1:4, p); // address type - write_endpoint(m_remote_endpoint, p); - TORRENT_ASSERT(p - &m_buffer[0] == int(m_buffer.size())); - - async_write(m_sock, asio::buffer(m_buffer) - , boost::bind(&socks5_stream::connect1, this, _1, h)); - } - - void socks5_stream::connect1(error_code const& e, boost::shared_ptr h) - { - if (e) - { - (*h)(e); - error_code ec; - close(ec); - return; - } - - m_buffer.resize(6 + 4); // assume an IPv4 address - async_read(m_sock, asio::buffer(m_buffer) - , boost::bind(&socks5_stream::connect2, this, _1, h)); - } - - void socks5_stream::connect2(error_code const& e, boost::shared_ptr h) - { - if (e) - { - (*h)(e); - error_code ec; - close(ec); - return; - } - - using namespace libtorrent::detail; - - // send SOCKS5 connect command - char* p = &m_buffer[0]; - int version = read_uint8(p); - if (version < 5) - { - (*h)(asio::error::operation_not_supported); - error_code ec; - close(ec); - return; - } - int response = read_uint8(p); - if (response != 0) - { - error_code e = asio::error::fault; - switch (response) - { - case 1: e = asio::error::fault; break; - case 2: e = asio::error::no_permission; break; - case 3: e = asio::error::network_unreachable; break; - case 4: e = asio::error::host_unreachable; break; - case 5: e = asio::error::connection_refused; break; - case 6: e = asio::error::timed_out; break; - case 7: e = asio::error::operation_not_supported; break; - case 8: e = asio::error::address_family_not_supported; break; - } - (*h)(e); - error_code ec; - close(ec); - return; - } - p += 1; // reserved - int atyp = read_uint8(p); - // we ignore the proxy IP it was bound to - if (atyp == 1) - { - std::vector().swap(m_buffer); - (*h)(e); - return; - } - int skip_bytes = 0; - if (atyp == 4) - { - skip_bytes = 12; - } - else if (atyp == 3) - { - skip_bytes = read_uint8(p) - 3; - } - else - { - (*h)(asio::error::operation_not_supported); - error_code ec; - close(ec); - return; - } - m_buffer.resize(skip_bytes); - - async_read(m_sock, asio::buffer(m_buffer) - , boost::bind(&socks5_stream::connect3, this, _1, h)); - } - - void socks5_stream::connect3(error_code const& e, boost::shared_ptr h) - { - if (e) - { - (*h)(e); - error_code ec; - close(ec); - return; - } - - std::vector().swap(m_buffer); - (*h)(e); - } -} - diff --git a/libtorrent/src/stat.cpp b/libtorrent/src/stat.cpp deleted file mode 100755 index 18a3285f8..000000000 --- a/libtorrent/src/stat.cpp +++ /dev/null @@ -1,69 +0,0 @@ -/* - -Copyright (c) 2003, Arvid Norberg -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions -are met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in - the documentation and/or other materials provided with the distribution. - * Neither the name of the author nor the names of its - contributors may be used to endorse or promote products derived - from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -POSSIBILITY OF SUCH DAMAGE. - -*/ - -// TODO: Use two algorithms to estimate transfer rate. -// one (simple) for transfer rates that are >= 1 packet -// per second and one (low pass-filter) for rates < 1 -// packet per second. - -#include "libtorrent/pch.hpp" - -#include -#include - -#include "libtorrent/stat.hpp" -#include "libtorrent/invariant_check.hpp" - -#if defined _MSC_VER && _MSC_VER <= 1200 -#define for if (false) {} else for -#endif - -namespace libtorrent -{ - -void stat_channel::second_tick(float tick_interval) -{ - INVARIANT_CHECK; - - m_rate_sum -= m_rate_history[history-1]; - - for (int i = history - 2; i >= 0; --i) - m_rate_history[i + 1] = m_rate_history[i]; - - m_rate_history[0] = m_counter / tick_interval; - m_rate_sum += m_rate_history[0]; - m_counter = 0; -} - - -} - diff --git a/libtorrent/src/storage.cpp b/libtorrent/src/storage.cpp deleted file mode 100755 index 64104d467..000000000 --- a/libtorrent/src/storage.cpp +++ /dev/null @@ -1,2752 +0,0 @@ -/* - -Copyright (c) 2003, Arvid Norberg, Daniel Wallin -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions -are met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in - the documentation and/or other materials provided with the distribution. - * Neither the name of the author nor the names of its - contributors may be used to endorse or promote products derived - from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -POSSIBILITY OF SUCH DAMAGE. - -*/ - -#include "libtorrent/pch.hpp" - -#include -#include -#include -#include -#include - -#ifdef _MSC_VER -#pragma warning(push, 1) -#endif - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#if BOOST_VERSION >= 103500 -#include -#endif - -#ifdef _MSC_VER -#pragma warning(pop) -#endif - -#include "libtorrent/config.hpp" -#include "libtorrent/storage.hpp" -#include "libtorrent/torrent.hpp" -#include "libtorrent/hasher.hpp" -#include "libtorrent/session.hpp" -#include "libtorrent/peer_id.hpp" -#include "libtorrent/file.hpp" -#include "libtorrent/invariant_check.hpp" -#include "libtorrent/file_pool.hpp" -#include "libtorrent/aux_/session_impl.hpp" -#include "libtorrent/disk_buffer_holder.hpp" - -//#define TORRENT_PARTIAL_HASH_LOG - -#ifdef TORRENT_DEBUG -#include -#include -#include -#include -#endif - -#if defined(__APPLE__) -// for getattrlist() -#include -#include -// for statfs() -#include -#include -#endif - -#if defined(__linux__) -#include -#endif - -#if defined(__FreeBSD__) -// for statfs() -#include -#include -#endif - -#if TORRENT_USE_WPATH - -#ifdef BOOST_WINDOWS -#include -#endif - -#include -#include "libtorrent/utf8.hpp" -#include "libtorrent/buffer.hpp" - -namespace libtorrent -{ - std::wstring safe_convert(std::string const& s) - { - try - { - return libtorrent::utf8_wchar(s); - } - catch (std::exception) - { - std::wstring ret; - const char* end = &s[0] + s.size(); - for (const char* i = &s[0]; i < end;) - { - wchar_t c = '.'; - int result = std::mbtowc(&c, i, end - i); - if (result > 0) i += result; - else ++i; - ret += c; - } - return ret; - } - } -} -#endif - -namespace fs = boost::filesystem; -using boost::bind; -using namespace ::boost::multi_index; -using boost::multi_index::multi_index_container; - -#if defined TORRENT_DEBUG && defined TORRENT_STORAGE_DEBUG -namespace -{ - using namespace libtorrent; - - void print_to_log(const std::string& s) - { - static std::ofstream log("log.txt"); - log << s; - log.flush(); - } -} -#endif - -namespace libtorrent -{ - template - void recursive_copy(Path const& old_path, Path const& new_path, error_code& ec) - { - using boost::filesystem::basic_directory_iterator; -#ifndef BOOST_NO_EXCEPTIONS - try { -#endif - TORRENT_ASSERT(!ec); - if (is_directory(old_path)) - { - create_directory(new_path); - for (basic_directory_iterator i(old_path), end; i != end; ++i) - { -#if BOOST_VERSION < 103600 - recursive_copy(i->path(), new_path / i->path().leaf(), ec); -#else - recursive_copy(i->path(), new_path / i->path().filename(), ec); -#endif - if (ec) return; - } - } - else - { - copy_file(old_path, new_path); - } -#ifndef BOOST_NO_EXCEPTIONS - } catch (std::exception& e) { ec = error_code(errno, get_posix_category()); } -#endif - } - - template - void recursive_remove(Path const& old_path) - { - using boost::filesystem::basic_directory_iterator; -#ifndef BOOST_NO_EXCEPTIONS - try { -#endif - if (is_directory(old_path)) - { - for (basic_directory_iterator i(old_path), end; i != end; ++i) - recursive_remove(i->path()); - remove(old_path); - } - else - { - remove(old_path); - } -#ifndef BOOST_NO_EXCEPTIONS - } catch (std::exception& e) {} -#endif - } - std::vector > get_filesizes( - file_storage const& s, fs::path p) - { - p = complete(p); - std::vector > sizes; - for (file_storage::iterator i = s.begin() - , end(s.end());i != end; ++i) - { - size_type size = 0; - std::time_t time = 0; -#if TORRENT_USE_WPATH - fs::wpath f = safe_convert((p / i->path).string()); -#else - fs::path f = p / i->path; -#endif -#ifndef BOOST_NO_EXCEPTIONS - try -#else - if (exists(f)) -#endif - { - size = file_size(f); - time = last_write_time(f); - } -#ifndef BOOST_NO_EXCEPTIONS - catch (std::exception&) {} -#endif - sizes.push_back(std::make_pair(size, time)); - } - return sizes; - } - - // matches the sizes and timestamps of the files passed in - // in non-compact mode, actual file sizes and timestamps - // are allowed to be bigger and more recent than the fast - // resume data. This is because full allocation will not move - // pieces, so any older version of the resume data will - // still be a correct subset of the actual data on disk. - bool match_filesizes( - file_storage const& fs - , fs::path p - , std::vector > const& sizes - , bool compact_mode - , std::string* error) - { - if ((int)sizes.size() != fs.num_files()) - { - if (error) *error = "mismatching number of files"; - return false; - } - p = complete(p); - - std::vector >::const_iterator s - = sizes.begin(); - for (file_storage::iterator i = fs.begin() - , end(fs.end());i != end; ++i, ++s) - { - size_type size = 0; - std::time_t time = 0; - -#if TORRENT_USE_WPATH - fs::wpath f = safe_convert((p / i->path).string()); -#else - fs::path f = p / i->path; -#endif -#ifndef BOOST_NO_EXCEPTIONS - try -#else - if (exists(f)) -#endif - { - size = file_size(f); - time = last_write_time(f); - } -#ifndef BOOST_NO_EXCEPTIONS - catch (std::exception&) {} -#endif - if ((compact_mode && size != s->first) - || (!compact_mode && size < s->first)) - { - if (error) *error = "filesize mismatch for file '" - + i->path.external_file_string() - + "', size: " + boost::lexical_cast(size) - + ", expected to be " + boost::lexical_cast(s->first) - + " bytes"; - return false; - } - // allow one second 'slack', because of FAT volumes - // in sparse mode, allow the files to be more recent - // than the resume data, but only by 5 minutes - if ((compact_mode && (time > s->second + 1 || time < s->second - 1)) || - (!compact_mode && (time > s->second + 5 * 60) || time < s->second - 1)) - { - if (error) *error = "timestamp mismatch for file '" - + i->path.external_file_string() - + "', modification date: " + boost::lexical_cast(time) - + ", expected to have modification date " - + boost::lexical_cast(s->second); - return false; - } - } - return true; - } - - class storage : public storage_interface, boost::noncopyable - { - public: - storage(file_storage const& fs, fs::path const& path, file_pool& fp) - : m_files(fs) - , m_pool(fp) - { - TORRENT_ASSERT(m_files.begin() != m_files.end()); - m_save_path = fs::complete(path); - TORRENT_ASSERT(m_save_path.is_complete()); - } - - bool rename_file(int index, std::string const& new_filename); - bool release_files(); - bool delete_files(); - bool initialize(bool allocate_files); - bool move_storage(fs::path save_path); - int read(char* buf, int slot, int offset, int size); - int write(const char* buf, int slot, int offset, int size); - bool move_slot(int src_slot, int dst_slot); - bool swap_slots(int slot1, int slot2); - bool swap_slots3(int slot1, int slot2, int slot3); - bool verify_resume_data(lazy_entry const& rd, std::string& error); - bool write_resume_data(entry& rd) const; - sha1_hash hash_for_slot(int slot, partial_hash& ph, int piece_size); - - int read_impl(char* buf, int slot, int offset, int size, bool fill_zero); - - ~storage() - { m_pool.release(this); } - - file_storage const& files() const { return m_mapped_files?*m_mapped_files:m_files; } - - boost::scoped_ptr m_mapped_files; - file_storage const& m_files; - - std::vector m_file_priority; - fs::path m_save_path; - // the file pool is typically stored in - // the session, to make all storage - // instances use the same pool - file_pool& m_pool; - - // temporary storage for moving pieces - buffer m_scratch_buffer; - }; - - sha1_hash storage::hash_for_slot(int slot, partial_hash& ph, int piece_size) - { - TORRENT_ASSERT(!error()); -#ifdef TORRENT_DEBUG - hasher partial; - hasher whole; - int slot_size1 = piece_size; - m_scratch_buffer.resize(slot_size1); - read_impl(&m_scratch_buffer[0], slot, 0, slot_size1, false); - if (error()) return sha1_hash(0); - if (ph.offset > 0) - partial.update(&m_scratch_buffer[0], ph.offset); - whole.update(&m_scratch_buffer[0], slot_size1); - hasher partial_copy = ph.h; - TORRENT_ASSERT(ph.offset == 0 || partial_copy.final() == partial.final()); -#endif - int slot_size = piece_size - ph.offset; - if (slot_size > 0) - { - m_scratch_buffer.resize(slot_size); - read_impl(&m_scratch_buffer[0], slot, ph.offset, slot_size, false); - if (error()) return sha1_hash(0); - ph.h.update(&m_scratch_buffer[0], slot_size); - } -#ifdef TORRENT_DEBUG - sha1_hash ret = ph.h.final(); - TORRENT_ASSERT(ret == whole.final()); - return ret; -#else - return ph.h.final(); -#endif - } - - bool storage::initialize(bool allocate_files) - { - error_code ec; - // first, create all missing directories - fs::path last_path; - for (file_storage::iterator file_iter = files().begin(), - end_iter = files().end(); file_iter != end_iter; ++file_iter) - { - fs::path dir = (m_save_path / file_iter->path).branch_path(); - - if (dir != last_path) - { - last_path = dir; - -#if TORRENT_USE_WPATH - fs::wpath wp = safe_convert(last_path.string()); - if (!exists(wp)) - create_directories(wp); -#else - if (!exists(last_path)) - create_directories(last_path); -#endif - } - -#ifndef BOOST_NO_EXCEPTIONS - try { -#endif - -#if TORRENT_USE_WPATH - fs::wpath file_path = safe_convert((m_save_path / file_iter->path).string()); -#else - fs::path file_path = m_save_path / file_iter->path; -#endif - // if the file is empty, just create it either way. - // if the file already exists, but is larger than what - // it's supposed to be, also truncate it - if (allocate_files - || file_iter->size == 0 - || (exists(file_path) && file_size(file_path) > file_iter->size)) - { - error_code ec; - boost::shared_ptr f = m_pool.open_file(this - , m_save_path / file_iter->path, file::in | file::out, ec); - if (ec) set_error(m_save_path / file_iter->path, ec); - else if (f) - { - f->set_size(file_iter->size, ec); - if (ec) set_error(m_save_path / file_iter->path, ec); - } - } -#ifndef BOOST_NO_EXCEPTIONS - } - catch (std::exception& e) - { - set_error(m_save_path / file_iter->path - , error_code(errno, get_posix_category())); - return true; - } -#endif - } - std::vector().swap(m_file_priority); - // close files that were opened in write mode - m_pool.release(this); - return false; - } - - bool storage::rename_file(int index, std::string const& new_filename) - { - if (index < 0 || index >= m_files.num_files()) return true; - fs::path old_name = m_save_path / files().at(index).path; - m_pool.release(old_name); - -#if TORRENT_USE_WPATH - fs::wpath old_path = safe_convert(old_name.string()); - fs::wpath new_path = safe_convert((m_save_path / new_filename).string()); -#else - fs::path const& old_path = old_name; - fs::path new_path = m_save_path / new_filename; -#endif - -#ifndef BOOST_NO_EXCEPTIONS - try - { -#endif - // if old path doesn't exist, just rename the file - // in our file_storage, so that when it is created - // it will get the new name - create_directories(new_path.branch_path()); - if (exists(old_path)) rename(old_path, new_path); -/* - error_code ec; - rename(old_path, new_path, ec); - if (ec) - { - set_error(old_path, ec); - return; - } -*/ - if (!m_mapped_files) - { m_mapped_files.reset(new file_storage(m_files)); } - m_mapped_files->rename_file(index, new_filename); -#ifndef BOOST_NO_EXCEPTIONS - } -#if BOOST_VERSION >= 103500 - catch (boost::system::system_error& e) - { - set_error(old_name, e.code()); - return true; - } -#endif - catch (std::exception& e) - { - set_error(old_name, error_code(errno, get_posix_category())); - return true; - } -#endif - return false; - } - - bool storage::release_files() - { - m_pool.release(this); - buffer().swap(m_scratch_buffer); - return false; - } - - bool storage::delete_files() - { - // make sure we don't have the files open - m_pool.release(this); - buffer().swap(m_scratch_buffer); - - int error = 0; - std::string error_file; - - // delete the files from disk - std::set directories; - typedef std::set::iterator iter_t; - for (file_storage::iterator i = files().begin() - , end(files().end()); i != end; ++i) - { - std::string p = (m_save_path / i->path).string(); - fs::path bp = i->path.branch_path(); - std::pair ret; - ret.second = true; - while (ret.second && !bp.empty()) - { - std::pair ret = directories.insert((m_save_path / bp).string()); - bp = bp.branch_path(); - } -#if TORRENT_USE_WPATH - try - { fs::remove(safe_convert(p)); } - catch (std::exception& e) - { - error = errno; - error_file = p; - } -#else - if (std::remove(p.c_str()) != 0 && errno != ENOENT) - { - error = errno; - error_file = p; - } -#endif - } - - // remove the directories. Reverse order to delete - // subdirectories first - - for (std::set::reverse_iterator i = directories.rbegin() - , end(directories.rend()); i != end; ++i) - { -#if TORRENT_USE_WPATH - try - { fs::remove(safe_convert(*i)); } - catch (std::exception& e) - { - error = errno; - error_file = *i; - } -#else - if (std::remove(i->c_str()) != 0 && errno != ENOENT) - { - error = errno; - error_file = *i; - } -#endif - } - - if (error) - { - m_error = error_code(error, get_posix_category()); - m_error_file.swap(error_file); - return true; - } - return false; - } - - bool storage::write_resume_data(entry& rd) const - { - TORRENT_ASSERT(rd.type() == entry::dictionary_t); - - std::vector > file_sizes - = get_filesizes(files(), m_save_path); - - entry::list_type& fl = rd["file sizes"].list(); - for (std::vector >::iterator i - = file_sizes.begin(), end(file_sizes.end()); i != end; ++i) - { - entry::list_type p; - p.push_back(entry(i->first)); - p.push_back(entry(i->second)); - fl.push_back(entry(p)); - } - - if (m_mapped_files) - { - entry::list_type& fl = rd["mapped_files"].list(); - for (file_storage::iterator i = m_mapped_files->begin() - , end(m_mapped_files->end()); i != end; ++i) - { - fl.push_back(i->path.string()); - } - } - - return false; - } - - bool storage::verify_resume_data(lazy_entry const& rd, std::string& error) - { - lazy_entry const* file_priority = rd.dict_find_list("file_priority"); - if (file_priority && file_priority->list_size() - == files().num_files()) - { - m_file_priority.resize(file_priority->list_size()); - for (int i = 0; i < file_priority->list_size(); ++i) - m_file_priority[i] = file_priority->list_int_value_at(i, 1); - } - - std::vector > file_sizes; - lazy_entry const* file_sizes_ent = rd.dict_find_list("file sizes"); - if (file_sizes_ent == 0) - { - error = "missing or invalid 'file sizes' entry in resume data"; - return false; - } - - for (int i = 0; i < file_sizes_ent->list_size(); ++i) - { - lazy_entry const* e = file_sizes_ent->list_at(i); - if (e->type() != lazy_entry::list_t - || e->list_size() != 2 - || e->list_at(0)->type() != lazy_entry::int_t - || e->list_at(1)->type() != lazy_entry::int_t) - continue; - file_sizes.push_back(std::pair( - e->list_int_value_at(0), std::time_t(e->list_int_value_at(1)))); - } - - if (file_sizes.empty()) - { - error = "the number of files in resume data is 0"; - return false; - } - - bool seed = false; - - lazy_entry const* slots = rd.dict_find_list("slots"); - if (slots) - { - if (int(slots->list_size()) == m_files.num_pieces()) - { - seed = true; - for (int i = 0; i < slots->list_size(); ++i) - { - if (slots->list_int_value_at(i, -1) >= 0) continue; - seed = false; - break; - } - } - } - else if (lazy_entry const* pieces = rd.dict_find_string("pieces")) - { - if (int(pieces->string_length()) == m_files.num_pieces()) - { - seed = true; - char const* p = pieces->string_ptr(); - for (int i = 0; i < pieces->string_length(); ++i) - { - if ((p[i] & 1) == 1) continue; - seed = false; - break; - } - } - } - else - { - error = "missing 'slots' and 'pieces' entry in resume data"; - return false; - } - - bool full_allocation_mode = false; - if (rd.dict_find_string_value("allocation") != "compact") - full_allocation_mode = true; - - if (seed) - { - if (files().num_files() != (int)file_sizes.size()) - { - error = "the number of files does not match the torrent (num: " - + boost::lexical_cast(file_sizes.size()) + " actual: " - + boost::lexical_cast(files().num_files()) + ")"; - return false; - } - - std::vector >::iterator - fs = file_sizes.begin(); - // the resume data says we have the entire torrent - // make sure the file sizes are the right ones - for (file_storage::iterator i = files().begin() - , end(files().end()); i != end; ++i, ++fs) - { - if (i->size != fs->first) - { - error = "file size for '" + i->path.external_file_string() - + "' was expected to be " - + boost::lexical_cast(i->size) + " bytes"; - return false; - } - } - } - - return match_filesizes(files(), m_save_path, file_sizes - , !full_allocation_mode, &error); - } - - // returns true on success - bool storage::move_storage(fs::path save_path) - { -#if TORRENT_USE_WPATH - fs::wpath old_path; - fs::wpath new_path; -#else - fs::path old_path; - fs::path new_path; -#endif - - save_path = complete(save_path); - -#if TORRENT_USE_WPATH - fs::wpath wp = safe_convert(save_path.string()); - if (!exists(wp)) - create_directory(wp); - else if (!is_directory(wp)) - return false; -#else - if (!exists(save_path)) - create_directory(save_path); - else if (!is_directory(save_path)) - return false; -#endif - - m_pool.release(this); - -#if TORRENT_USE_WPATH - old_path = safe_convert((m_save_path / files().name()).string()); - new_path = safe_convert((save_path / files().name()).string()); -#else - old_path = m_save_path / files().name(); - new_path = save_path / files().name(); -#endif - -#ifndef BOOST_NO_EXCEPTIONS - try - { -#endif - rename(old_path, new_path); - m_save_path = save_path; - return true; -#ifndef BOOST_NO_EXCEPTIONS - } - catch (std::exception& e) - { - error_code ec; - recursive_copy(old_path, new_path, ec); - if (ec) - { - set_error(m_save_path / files().name(), ec); - return true; - } - m_save_path = save_path; - recursive_remove(old_path); - } -#endif - return false; - } - -#ifdef TORRENT_DEBUG -/* - void storage::shuffle() - { - int num_pieces = files().num_pieces(); - - std::vector pieces(num_pieces); - for (std::vector::iterator i = pieces.begin(); - i != pieces.end(); ++i) - { - *i = static_cast(i - pieces.begin()); - } - std::srand((unsigned int)std::time(0)); - std::vector targets(pieces); - std::random_shuffle(pieces.begin(), pieces.end()); - std::random_shuffle(targets.begin(), targets.end()); - - for (int i = 0; i < (std::max)(num_pieces / 50, 1); ++i) - { - const int slot_index = targets[i]; - const int piece_index = pieces[i]; - const int slot_size =static_cast(m_files.piece_size(slot_index)); - std::vector buf(slot_size); - read(&buf[0], piece_index, 0, slot_size); - write(&buf[0], slot_index, 0, slot_size); - } - } -*/ -#endif - - bool storage::move_slot(int src_slot, int dst_slot) - { - int piece_size = m_files.piece_size(dst_slot); - m_scratch_buffer.resize(piece_size); - int ret1 = read_impl(&m_scratch_buffer[0], src_slot, 0, piece_size, true); - int ret2 = write(&m_scratch_buffer[0], dst_slot, 0, piece_size); - return ret1 != piece_size || ret2 != piece_size; - } - - bool storage::swap_slots(int slot1, int slot2) - { - // the size of the target slot is the size of the piece - int piece_size = m_files.piece_length(); - int piece1_size = m_files.piece_size(slot2); - int piece2_size = m_files.piece_size(slot1); - m_scratch_buffer.resize(piece_size * 2); - int ret1 = read_impl(&m_scratch_buffer[0], slot1, 0, piece1_size, true); - int ret2 = read_impl(&m_scratch_buffer[piece_size], slot2, 0, piece2_size, true); - int ret3 = write(&m_scratch_buffer[0], slot2, 0, piece1_size); - int ret4 = write(&m_scratch_buffer[piece_size], slot1, 0, piece2_size); - return ret1 != piece1_size || ret2 != piece2_size - || ret3 != piece1_size || ret4 != piece2_size; - } - - bool storage::swap_slots3(int slot1, int slot2, int slot3) - { - // the size of the target slot is the size of the piece - int piece_size = m_files.piece_length(); - int piece1_size = m_files.piece_size(slot2); - int piece2_size = m_files.piece_size(slot3); - int piece3_size = m_files.piece_size(slot1); - m_scratch_buffer.resize(piece_size * 2); - int ret1 = read_impl(&m_scratch_buffer[0], slot1, 0, piece1_size, true); - int ret2 = read_impl(&m_scratch_buffer[piece_size], slot2, 0, piece2_size, true); - int ret3 = write(&m_scratch_buffer[0], slot2, 0, piece1_size); - int ret4 = read_impl(&m_scratch_buffer[0], slot3, 0, piece3_size, true); - int ret5 = write(&m_scratch_buffer[piece_size], slot3, 0, piece2_size); - int ret6 = write(&m_scratch_buffer[0], slot1, 0, piece3_size); - return ret1 != piece1_size || ret2 != piece2_size - || ret3 != piece1_size || ret4 != piece3_size - || ret5 != piece2_size || ret6 != piece3_size; - } - - int storage::read( - char* buf - , int slot - , int offset - , int size) - { - return read_impl(buf, slot, offset, size, false); - } - - int storage::read_impl( - char* buf - , int slot - , int offset - , int size - , bool fill_zero) - { - TORRENT_ASSERT(buf != 0); - TORRENT_ASSERT(slot >= 0 && slot < m_files.num_pieces()); - TORRENT_ASSERT(offset >= 0); - TORRENT_ASSERT(offset < m_files.piece_size(slot)); - TORRENT_ASSERT(size > 0); - -#ifdef TORRENT_DEBUG - std::vector slices - = files().map_block(slot, offset, size); - TORRENT_ASSERT(!slices.empty()); -#endif - - size_type start = slot * (size_type)m_files.piece_length() + offset; - TORRENT_ASSERT(start + size <= m_files.total_size()); - - // find the file iterator and file offset - size_type file_offset = start; - std::vector::const_iterator file_iter; - - for (file_iter = files().begin();;) - { - if (file_offset < file_iter->size) - break; - - file_offset -= file_iter->size; - ++file_iter; - } - - int buf_pos = 0; - error_code ec; - boost::shared_ptr in(m_pool.open_file( - this, m_save_path / file_iter->path, file::in, ec)); - if (!in || ec) - { - set_error(m_save_path / file_iter->path, ec); - return -1; - } - TORRENT_ASSERT(file_offset < file_iter->size); - TORRENT_ASSERT(slices[0].offset == file_offset + file_iter->file_base); - - size_type new_pos = in->seek(file_offset + file_iter->file_base, file::begin, ec); - if (new_pos != file_offset + file_iter->file_base || ec) - { - // the file was not big enough - if (!fill_zero) - { - set_error(m_save_path / file_iter->path, ec); - return -1; - } - std::memset(buf + buf_pos, 0, size - buf_pos); - return size; - } - -#ifdef TORRENT_DEBUG - size_type in_tell = in->tell(ec); - TORRENT_ASSERT(in_tell == file_offset + file_iter->file_base && !ec); -#endif - - int left_to_read = size; - int slot_size = static_cast(m_files.piece_size(slot)); - - if (offset + left_to_read > slot_size) - left_to_read = slot_size - offset; - - TORRENT_ASSERT(left_to_read >= 0); - - size_type result = left_to_read; - -#ifdef TORRENT_DEBUG - int counter = 0; -#endif - - while (left_to_read > 0) - { - int read_bytes = left_to_read; - if (file_offset + read_bytes > file_iter->size) - read_bytes = static_cast(file_iter->size - file_offset); - - if (read_bytes > 0) - { -#ifdef TORRENT_DEBUG - TORRENT_ASSERT(int(slices.size()) > counter); - size_type slice_size = slices[counter].size; - TORRENT_ASSERT(slice_size == read_bytes); - TORRENT_ASSERT(files().at(slices[counter].file_index).path - == file_iter->path); -#endif - - int actual_read = int(in->read(buf + buf_pos, read_bytes, ec)); - - if (ec) - { - set_error(m_save_path / file_iter->path, ec); - return -1; - } - - if (read_bytes != actual_read) - { - // the file was not big enough - if (!fill_zero) - { -#ifdef TORRENT_WINDOWS - ec = error_code(ERROR_READ_FAULT, get_system_category()); -#else - ec = error_code(EIO, get_posix_category()); -#endif - set_error(m_save_path / file_iter->path, ec); - return actual_read; - } - if (actual_read > 0) buf_pos += actual_read; - std::memset(buf + buf_pos, 0, size - buf_pos); - return size; - } - - left_to_read -= read_bytes; - buf_pos += read_bytes; - TORRENT_ASSERT(buf_pos >= 0); - file_offset += read_bytes; - } - - if (left_to_read > 0) - { - ++file_iter; -#ifdef TORRENT_DEBUG - // empty files are not returned by map_block, so if - // this file was empty, don't increment the slice counter - if (read_bytes > 0) ++counter; -#endif - fs::path path = m_save_path / file_iter->path; - - file_offset = 0; - error_code ec; - in = m_pool.open_file( this, path, file::in, ec); - if (!in || ec) - { - set_error(path, ec); - return -1; - } - size_type pos = in->seek(file_iter->file_base, file::begin, ec); - if (pos != file_iter->file_base || ec) - { - if (!fill_zero) - { - set_error(m_save_path / file_iter->path, ec); - return -1; - } - std::memset(buf + buf_pos, 0, size - buf_pos); - return size; - } - } - } - return result; - } - - int storage::write( - const char* buf - , int slot - , int offset - , int size) - { - TORRENT_ASSERT(buf != 0); - TORRENT_ASSERT(slot >= 0); - TORRENT_ASSERT(slot < m_files.num_pieces()); - TORRENT_ASSERT(offset >= 0); - TORRENT_ASSERT(size > 0); - -#ifdef TORRENT_DEBUG - std::vector slices - = files().map_block(slot, offset, size); - TORRENT_ASSERT(!slices.empty()); -#endif - - size_type start = slot * (size_type)m_files.piece_length() + offset; - - // find the file iterator and file offset - size_type file_offset = start; - std::vector::const_iterator file_iter; - - for (file_iter = files().begin();;) - { - if (file_offset < file_iter->size) - break; - - file_offset -= file_iter->size; - ++file_iter; - TORRENT_ASSERT(file_iter != files().end()); - } - - fs::path p(m_save_path / file_iter->path); - error_code ec; - boost::shared_ptr out = m_pool.open_file( - this, p, file::out | file::in, ec); - - if (!out || ec) - { - set_error(p, ec); - return -1; - } - TORRENT_ASSERT(file_offset < file_iter->size); - TORRENT_ASSERT(slices[0].offset == file_offset + file_iter->file_base); - - size_type pos = out->seek(file_offset + file_iter->file_base, file::begin, ec); - - if (pos != file_offset + file_iter->file_base || ec) - { - set_error(p, ec); - return -1; - } - - int left_to_write = size; - int slot_size = static_cast(m_files.piece_size(slot)); - - if (offset + left_to_write > slot_size) - left_to_write = slot_size - offset; - - TORRENT_ASSERT(left_to_write >= 0); - - int buf_pos = 0; -#ifdef TORRENT_DEBUG - int counter = 0; -#endif - while (left_to_write > 0) - { - int write_bytes = left_to_write; - if (file_offset + write_bytes > file_iter->size) - { - TORRENT_ASSERT(file_iter->size >= file_offset); - write_bytes = static_cast(file_iter->size - file_offset); - } - - if (write_bytes > 0) - { - TORRENT_ASSERT(int(slices.size()) > counter); - TORRENT_ASSERT(slices[counter].size == write_bytes); - TORRENT_ASSERT(files().at(slices[counter].file_index).path - == file_iter->path); - - TORRENT_ASSERT(buf_pos >= 0); - TORRENT_ASSERT(write_bytes >= 0); - error_code ec; - size_type written = out->write(buf + buf_pos, write_bytes, ec); - - if (ec) - { - set_error(m_save_path / file_iter->path, ec); - return -1; - } - - if (write_bytes != written) - { - // the file was not big enough -#ifdef TORRENT_WINDOWS - ec = error_code(ERROR_READ_FAULT, get_system_category()); -#else - ec = error_code(EIO, get_posix_category()); -#endif - set_error(m_save_path / file_iter->path, ec); - return written; - } - - left_to_write -= write_bytes; - buf_pos += write_bytes; - TORRENT_ASSERT(buf_pos >= 0); - file_offset += write_bytes; - TORRENT_ASSERT(file_offset <= file_iter->size); - } - - if (left_to_write > 0) - { -#ifdef TORRENT_DEBUG - if (write_bytes > 0) ++counter; -#endif - ++file_iter; - - TORRENT_ASSERT(file_iter != files().end()); - fs::path p = m_save_path / file_iter->path; - file_offset = 0; - error_code ec; - out = m_pool.open_file( - this, p, file::out | file::in, ec); - - if (!out || ec) - { - set_error(p, ec); - return -1; - } - - size_type pos = out->seek(file_iter->file_base, file::begin, ec); - - if (pos != file_iter->file_base || ec) - { - set_error(p, ec); - return -1; - } - } - } - return size; - } - - storage_interface* default_storage_constructor(file_storage const& fs - , fs::path const& path, file_pool& fp) - { - return new storage(fs, path, fp); - } - - // -- piece_manager ----------------------------------------------------- - - piece_manager::piece_manager( - boost::shared_ptr const& torrent - , boost::intrusive_ptr info - , fs::path const& save_path - , file_pool& fp - , disk_io_thread& io - , storage_constructor_type sc - , storage_mode_t sm) - : m_info(info) - , m_files(m_info->files()) - , m_storage(sc(m_files, save_path, fp)) - , m_storage_mode(sm) - , m_save_path(complete(save_path)) - , m_state(state_none) - , m_current_slot(0) - , m_out_of_place(false) - , m_scratch_piece(-1) - , m_storage_constructor(sc) - , m_io_thread(io) - , m_torrent(torrent) - { - } - - piece_manager::~piece_manager() - { - } - - void piece_manager::async_save_resume_data( - boost::function const& handler) - { - disk_io_job j; - j.storage = this; - j.action = disk_io_job::save_resume_data; - m_io_thread.add_job(j, handler); - } - - void piece_manager::async_clear_read_cache( - boost::function const& handler) - { - disk_io_job j; - j.storage = this; - j.action = disk_io_job::clear_read_cache; - m_io_thread.add_job(j, handler); - } - - void piece_manager::async_release_files( - boost::function const& handler) - { - disk_io_job j; - j.storage = this; - j.action = disk_io_job::release_files; - m_io_thread.add_job(j, handler); - } - - void piece_manager::abort_disk_io() - { - m_io_thread.stop(this); - } - - void piece_manager::async_delete_files( - boost::function const& handler) - { - disk_io_job j; - j.storage = this; - j.action = disk_io_job::delete_files; - m_io_thread.add_job(j, handler); - } - - void piece_manager::async_move_storage(fs::path const& p - , boost::function const& handler) - { - disk_io_job j; - j.storage = this; - j.action = disk_io_job::move_storage; - j.str = p.string(); - m_io_thread.add_job(j, handler); - } - - void piece_manager::async_check_fastresume(lazy_entry const* resume_data - , boost::function const& handler) - { - TORRENT_ASSERT(resume_data != 0); - disk_io_job j; - j.storage = this; - j.action = disk_io_job::check_fastresume; - j.buffer = (char*)resume_data; - m_io_thread.add_job(j, handler); - } - - void piece_manager::async_rename_file(int index, std::string const& name - , boost::function const& handler) - { - disk_io_job j; - j.storage = this; - j.piece = index; - j.str = name; - j.action = disk_io_job::rename_file; - m_io_thread.add_job(j, handler); - } - - void piece_manager::async_check_files( - boost::function const& handler) - { - disk_io_job j; - j.storage = this; - j.action = disk_io_job::check_files; - m_io_thread.add_job(j, handler); - } - - void piece_manager::async_read( - peer_request const& r - , boost::function const& handler - , int priority) - { - disk_io_job j; - j.storage = this; - j.action = disk_io_job::read; - j.piece = r.piece; - j.offset = r.start; - j.buffer_size = r.length; - j.buffer = 0; - j.priority = priority; - // if a buffer is not specified, only one block can be read - // since that is the size of the pool allocator's buffers - TORRENT_ASSERT(r.length <= 16 * 1024); - m_io_thread.add_job(j, handler); -#ifdef TORRENT_DEBUG - boost::recursive_mutex::scoped_lock l(m_mutex); - // if this assert is hit, it suggests - // that check_files was not successful - TORRENT_ASSERT(slot_for(r.piece) >= 0); -#endif - } - - void piece_manager::async_write( - peer_request const& r - , disk_buffer_holder& buffer - , boost::function const& handler) - { - TORRENT_ASSERT(r.length <= 16 * 1024); - // the buffer needs to be allocated through the io_thread - TORRENT_ASSERT(m_io_thread.is_disk_buffer(buffer.get())); - - disk_io_job j; - j.storage = this; - j.action = disk_io_job::write; - j.piece = r.piece; - j.offset = r.start; - j.buffer_size = r.length; - j.buffer = buffer.get(); - m_io_thread.add_job(j, handler); - buffer.release(); - } - - void piece_manager::async_hash(int piece - , boost::function const& handler) - { - disk_io_job j; - j.storage = this; - j.action = disk_io_job::hash; - j.piece = piece; - - m_io_thread.add_job(j, handler); - } - - fs::path piece_manager::save_path() const - { - boost::recursive_mutex::scoped_lock l(m_mutex); - return m_save_path; - } - - sha1_hash piece_manager::hash_for_piece_impl(int piece) - { - partial_hash ph; - - std::map::iterator i = m_piece_hasher.find(piece); - if (i != m_piece_hasher.end()) - { - ph = i->second; - m_piece_hasher.erase(i); - } - - int slot = slot_for(piece); - TORRENT_ASSERT(slot != has_no_slot); - return m_storage->hash_for_slot(slot, ph, m_files.piece_size(piece)); - } - - int piece_manager::move_storage_impl(fs::path const& save_path) - { - if (m_storage->move_storage(save_path)) - { - m_save_path = fs::complete(save_path); - return 0; - } - return -1; - } - - void piece_manager::write_resume_data(entry& rd) const - { - boost::recursive_mutex::scoped_lock lock(m_mutex); - - INVARIANT_CHECK; - - m_storage->write_resume_data(rd); - - if (m_storage_mode == storage_mode_compact) - { - entry::list_type& slots = rd["slots"].list(); - slots.clear(); - std::vector::const_reverse_iterator last; - for (last = m_slot_to_piece.rbegin(); - last != m_slot_to_piece.rend(); ++last) - { - if (*last != unallocated) break; - } - - for (std::vector::const_iterator i = - m_slot_to_piece.begin(); - i != last.base(); ++i) - { - slots.push_back((*i >= 0) ? *i : unassigned); - } - } - - rd["allocation"] = m_storage_mode == storage_mode_sparse?"sparse" - :m_storage_mode == storage_mode_allocate?"full":"compact"; - } - - void piece_manager::mark_failed(int piece_index) - { - INVARIANT_CHECK; - - if (m_storage_mode != storage_mode_compact) return; - - TORRENT_ASSERT(piece_index >= 0 && piece_index < (int)m_piece_to_slot.size()); - int slot_index = m_piece_to_slot[piece_index]; - TORRENT_ASSERT(slot_index >= 0); - - m_slot_to_piece[slot_index] = unassigned; - m_piece_to_slot[piece_index] = has_no_slot; - m_free_slots.push_back(slot_index); - } - - int piece_manager::read_impl( - char* buf - , int piece_index - , int offset - , int size) - { - TORRENT_ASSERT(buf); - TORRENT_ASSERT(offset >= 0); - TORRENT_ASSERT(size > 0); - int slot = slot_for(piece_index); - return m_storage->read(buf, slot, offset, size); - } - - int piece_manager::write_impl( - const char* buf - , int piece_index - , int offset - , int size) - { - TORRENT_ASSERT(buf); - TORRENT_ASSERT(offset >= 0); - TORRENT_ASSERT(size > 0); - TORRENT_ASSERT(piece_index >= 0 && piece_index < m_files.num_pieces()); - - int slot = allocate_slot_for_piece(piece_index); - int ret = m_storage->write(buf, slot, offset, size); - // only save the partial hash if the write succeeds - if (ret != size) return ret; - -#ifdef TORRENT_PARTIAL_HASH_LOG - std::ofstream out("partial_hash.log", std::ios::app); -#endif - - if (offset == 0) - { - partial_hash& ph = m_piece_hasher[piece_index]; - TORRENT_ASSERT(ph.offset == 0); - ph.offset = size; - ph.h.update(buf, size); -#ifdef TORRENT_PARTIAL_HASH_LOG - out << time_now_string() << " NEW [" - " s: " << this - << " p: " << piece_index - << " off: " << offset - << " size: " << size - << " entries: " << m_piece_hasher.size() - << " ]" << std::endl; -#endif - } - else - { - std::map::iterator i = m_piece_hasher.find(piece_index); - if (i != m_piece_hasher.end()) - { -#ifdef TORRENT_DEBUG - TORRENT_ASSERT(i->second.offset > 0); - int hash_offset = i->second.offset; - TORRENT_ASSERT(offset >= hash_offset); -#endif - if (offset == i->second.offset) - { -#ifdef TORRENT_PARTIAL_HASH_LOG - out << time_now_string() << " UPDATING [" - " s: " << this - << " p: " << piece_index - << " off: " << offset - << " size: " << size - << " entries: " << m_piece_hasher.size() - << " ]" << std::endl; -#endif - i->second.offset += size; - i->second.h.update(buf, size); - } -#ifdef TORRENT_PARTIAL_HASH_LOG - else - { - out << time_now_string() << " SKIPPING (out of order) [" - " s: " << this - << " p: " << piece_index - << " off: " << offset - << " size: " << size - << " entries: " << m_piece_hasher.size() - << " ]" << std::endl; - } -#endif - } -#ifdef TORRENT_PARTIAL_HASH_LOG - else - { - out << time_now_string() << " SKIPPING (no entry) [" - " s: " << this - << " p: " << piece_index - << " off: " << offset - << " size: " << size - << " entries: " << m_piece_hasher.size() - << " ]" << std::endl; - } -#endif - } - - return ret; - } - - int piece_manager::identify_data( - const std::vector& piece_data - , int current_slot) - { -// INVARIANT_CHECK; - - const int piece_size = static_cast(m_files.piece_length()); - const int last_piece_size = static_cast(m_files.piece_size( - m_files.num_pieces() - 1)); - - TORRENT_ASSERT((int)piece_data.size() >= last_piece_size); - - // calculate a small digest, with the same - // size as the last piece. And a large digest - // which has the same size as a normal piece - hasher small_digest; - small_digest.update(&piece_data[0], last_piece_size); - hasher large_digest(small_digest); - TORRENT_ASSERT(piece_size - last_piece_size >= 0); - if (piece_size - last_piece_size > 0) - { - large_digest.update( - &piece_data[last_piece_size] - , piece_size - last_piece_size); - } - sha1_hash large_hash = large_digest.final(); - sha1_hash small_hash = small_digest.final(); - - typedef std::multimap::const_iterator map_iter; - map_iter begin1; - map_iter end1; - map_iter begin2; - map_iter end2; - - // makes the lookups for the small digest and the large digest - boost::tie(begin1, end1) = m_hash_to_piece.equal_range(small_hash); - boost::tie(begin2, end2) = m_hash_to_piece.equal_range(large_hash); - - // copy all potential piece indices into this vector - std::vector matching_pieces; - for (map_iter i = begin1; i != end1; ++i) - matching_pieces.push_back(i->second); - for (map_iter i = begin2; i != end2; ++i) - matching_pieces.push_back(i->second); - - // no piece matched the data in the slot - if (matching_pieces.empty()) - return unassigned; - - // ------------------------------------------ - // CHECK IF THE PIECE IS IN ITS CORRECT PLACE - // ------------------------------------------ - - if (std::find( - matching_pieces.begin() - , matching_pieces.end() - , current_slot) != matching_pieces.end()) - { - // the current slot is among the matching pieces, so - // we will assume that the piece is in the right place - const int piece_index = current_slot; - - int other_slot = m_piece_to_slot[piece_index]; - if (other_slot >= 0) - { - // we have already found a piece with - // this index. - - // take one of the other matching pieces - // that hasn't already been assigned - int other_piece = -1; - for (std::vector::iterator i = matching_pieces.begin(); - i != matching_pieces.end(); ++i) - { - if (m_piece_to_slot[*i] >= 0 || *i == piece_index) continue; - other_piece = *i; - break; - } - if (other_piece >= 0) - { - // replace the old slot with 'other_piece' - m_slot_to_piece[other_slot] = other_piece; - m_piece_to_slot[other_piece] = other_slot; - } - else - { - // this index is the only piece with this - // hash. The previous slot we found with - // this hash must be the same piece. Mark - // that piece as unassigned, since this slot - // is the correct place for the piece. - m_slot_to_piece[other_slot] = unassigned; - if (m_storage_mode == storage_mode_compact) - m_free_slots.push_back(other_slot); - } - TORRENT_ASSERT(m_piece_to_slot[piece_index] != current_slot); - TORRENT_ASSERT(m_piece_to_slot[piece_index] >= 0); - m_piece_to_slot[piece_index] = has_no_slot; - } - - TORRENT_ASSERT(m_piece_to_slot[piece_index] == has_no_slot); - - return piece_index; - } - - // find a matching piece that hasn't - // already been assigned - int free_piece = unassigned; - for (std::vector::iterator i = matching_pieces.begin(); - i != matching_pieces.end(); ++i) - { - if (m_piece_to_slot[*i] >= 0) continue; - free_piece = *i; - break; - } - - if (free_piece >= 0) - { - TORRENT_ASSERT(m_piece_to_slot[free_piece] == has_no_slot); - return free_piece; - } - else - { - TORRENT_ASSERT(free_piece == unassigned); - return unassigned; - } - } - - int piece_manager::check_no_fastresume(std::string& error) - { - file_storage::iterator i = m_files.begin(); - file_storage::iterator end = m_files.end(); - - for (; i != end; ++i) - { - bool file_exists = false; - fs::path f = m_save_path / i->path; -#ifndef BOOST_NO_EXCEPTIONS - try - { -#endif -#if TORRENT_USE_WPATH - fs::wpath wf = safe_convert(f.string()); - file_exists = exists(wf); -#else - file_exists = exists(f); -#endif -#ifndef BOOST_NO_EXCEPTIONS - } - catch (std::exception& e) - { - error = f.string(); - error += ": "; - error += e.what(); - TORRENT_ASSERT(!error.empty()); - return fatal_disk_error; - } -#endif - if (file_exists && i->size > 0) - { - m_state = state_full_check; - m_piece_to_slot.clear(); - m_piece_to_slot.resize(m_files.num_pieces(), has_no_slot); - m_slot_to_piece.clear(); - m_slot_to_piece.resize(m_files.num_pieces(), unallocated); - if (m_storage_mode == storage_mode_compact) - { - m_unallocated_slots.clear(); - m_free_slots.clear(); - } - TORRENT_ASSERT(int(m_piece_to_slot.size()) == m_files.num_pieces()); - return need_full_check; - } - } - - if (m_storage_mode == storage_mode_compact) - { - // in compact mode without checking, we need to - // populate the unallocated list - TORRENT_ASSERT(m_unallocated_slots.empty()); - for (int i = 0, end(m_files.num_pieces()); i < end; ++i) - m_unallocated_slots.push_back(i); - m_piece_to_slot.clear(); - m_piece_to_slot.resize(m_files.num_pieces(), has_no_slot); - m_slot_to_piece.clear(); - m_slot_to_piece.resize(m_files.num_pieces(), unallocated); - } - - return check_init_storage(error); - } - - int piece_manager::check_init_storage(std::string& error) - { - if (m_storage->initialize(m_storage_mode == storage_mode_allocate)) - { - error = m_storage->error().message(); - TORRENT_ASSERT(!error.empty()); - return fatal_disk_error; - } - m_state = state_finished; - buffer().swap(m_scratch_buffer); - buffer().swap(m_scratch_buffer2); - if (m_storage_mode != storage_mode_compact) - { - // if no piece is out of place - // since we're in full allocation mode, we can - // forget the piece allocation tables - std::vector().swap(m_piece_to_slot); - std::vector().swap(m_slot_to_piece); - std::vector().swap(m_free_slots); - std::vector().swap(m_unallocated_slots); - } - return no_error; - } - - // check if the fastresume data is up to date - // if it is, use it and return true. If it - // isn't return false and the full check - // will be run - int piece_manager::check_fastresume( - lazy_entry const& rd, std::string& error) - { - boost::recursive_mutex::scoped_lock lock(m_mutex); - - INVARIANT_CHECK; - - TORRENT_ASSERT(m_files.piece_length() > 0); - - // if we don't have any resume data, return - if (rd.type() == lazy_entry::none_t) return check_no_fastresume(error); - - if (rd.type() != lazy_entry::dict_t) - { - error = "invalid fastresume data (not a dictionary)"; - return check_no_fastresume(error); - } - - int block_size = (std::min)(16 * 1024, m_files.piece_length()); - int blocks_per_piece = rd.dict_find_int_value("blocks per piece", -1); - if (blocks_per_piece != -1 - && blocks_per_piece != m_files.piece_length() / block_size) - { - error = "invalid 'blocks per piece' entry"; - return check_no_fastresume(error); - } - - storage_mode_t storage_mode = storage_mode_compact; - if (rd.dict_find_string_value("allocation") != "compact") - storage_mode = storage_mode_sparse; - - if (!m_storage->verify_resume_data(rd, error)) - return check_no_fastresume(error); - - // assume no piece is out of place (i.e. in a slot - // other than the one it should be in) - bool out_of_place = false; - - // if we don't have a piece map, we need the slots - // if we're in compact mode, we also need the slots map - if (storage_mode == storage_mode_compact || rd.dict_find("pieces") == 0) - { - // read slots map - lazy_entry const* slots = rd.dict_find_list("slots"); - if (slots == 0) - { - error = "missing slot list"; - return check_no_fastresume(error); - } - - if ((int)slots->list_size() > m_files.num_pieces()) - { - error = "file has more slots than torrent (slots: " - + boost::lexical_cast(slots->list_size()) + " size: " - + boost::lexical_cast(m_files.num_pieces()) + " )"; - return check_no_fastresume(error); - } - - if (m_storage_mode == storage_mode_compact) - { - int num_pieces = int(m_files.num_pieces()); - m_slot_to_piece.resize(num_pieces, unallocated); - m_piece_to_slot.resize(num_pieces, has_no_slot); - for (int i = 0; i < slots->list_size(); ++i) - { - lazy_entry const* e = slots->list_at(i); - if (e->type() != lazy_entry::int_t) - { - error = "invalid entry type in slot list"; - return check_no_fastresume(error); - } - - int index = int(e->int_value()); - if (index >= num_pieces || index < -2) - { - error = "too high index number in slot map (index: " - + boost::lexical_cast(index) + " size: " - + boost::lexical_cast(num_pieces) + ")"; - return check_no_fastresume(error); - } - if (index >= 0) - { - m_slot_to_piece[i] = index; - m_piece_to_slot[index] = i; - if (i != index) out_of_place = true; - } - else if (index == unassigned) - { - if (m_storage_mode == storage_mode_compact) - m_free_slots.push_back(i); - } - else - { - TORRENT_ASSERT(index == unallocated); - if (m_storage_mode == storage_mode_compact) - m_unallocated_slots.push_back(i); - } - } - } - else - { - for (int i = 0; i < slots->list_size(); ++i) - { - lazy_entry const* e = slots->list_at(i); - if (e->type() != lazy_entry::int_t) - { - error = "invalid entry type in slot list"; - return check_no_fastresume(error); - } - - int index = int(e->int_value()); - if (index != i && index >= 0) - { - error = "invalid slot index"; - return check_no_fastresume(error); - } - } - } - - // This will corrupt the storage - // use while debugging to find - // states that cannot be scanned - // by check_pieces. - // m_storage->shuffle(); - - if (m_storage_mode == storage_mode_compact) - { - if (m_unallocated_slots.empty()) switch_to_full_mode(); - } - else - { - TORRENT_ASSERT(m_free_slots.empty()); - TORRENT_ASSERT(m_unallocated_slots.empty()); - - if (out_of_place) - { - // in this case we're in full allocation mode, but - // we're resuming a compact allocated storage - m_state = state_expand_pieces; - m_current_slot = 0; - error = "pieces needs to be reordered"; - TORRENT_ASSERT(int(m_piece_to_slot.size()) == m_files.num_pieces()); - return need_full_check; - } - } - - } - else if (m_storage_mode == storage_mode_compact) - { - // read piece map - lazy_entry const* pieces = rd.dict_find("pieces"); - if (pieces == 0 || pieces->type() != lazy_entry::string_t) - { - error = "missing pieces entry"; - return check_no_fastresume(error); - } - - if ((int)pieces->string_length() != m_files.num_pieces()) - { - error = "file has more slots than torrent (slots: " - + boost::lexical_cast(pieces->string_length()) + " size: " - + boost::lexical_cast(m_files.num_pieces()) + " )"; - return check_no_fastresume(error); - } - - int num_pieces = int(m_files.num_pieces()); - m_slot_to_piece.resize(num_pieces, unallocated); - m_piece_to_slot.resize(num_pieces, has_no_slot); - char const* have_pieces = pieces->string_ptr(); - for (int i = 0; i < num_pieces; ++i) - { - if (have_pieces[i] & 1) - { - m_slot_to_piece[i] = i; - m_piece_to_slot[i] = i; - } - else - { - m_free_slots.push_back(i); - } - } - if (m_unallocated_slots.empty()) switch_to_full_mode(); - } - - return check_init_storage(error); - } - -/* - state chart: - - check_fastresume() ----------+ - | - | | | - | v v - | +------------+ +---------------+ - | | full_check |-->| expand_pieses | - | +------------+ +---------------+ - | | | - | v | - | +--------------+ | - +->| finished | <------+ - +--------------+ -*/ - - - // performs the full check and full allocation - // (if necessary). returns true if finished and - // false if it should be called again - // the second return value is the progress the - // file check is at. 0 is nothing done, and 1 - // is finished - int piece_manager::check_files(int& current_slot, int& have_piece, std::string& error) - { - if (m_state == state_none) return check_no_fastresume(error); - - TORRENT_ASSERT(int(m_piece_to_slot.size()) == m_files.num_pieces()); - - current_slot = m_current_slot; - have_piece = -1; - if (m_state == state_expand_pieces) - { - INVARIANT_CHECK; - - if (m_scratch_piece >= 0) - { - int piece = m_scratch_piece; - int other_piece = m_slot_to_piece[piece]; - m_scratch_piece = -1; - - if (other_piece >= 0) - { - if (m_scratch_buffer2.empty()) - m_scratch_buffer2.resize(m_files.piece_length()); - - int piece_size = m_files.piece_size(other_piece); - if (m_storage->read(&m_scratch_buffer2[0], piece, 0, piece_size) - != piece_size) - { - error = m_storage->error().message(); - TORRENT_ASSERT(!error.empty()); - return fatal_disk_error; - } - m_scratch_piece = other_piece; - m_piece_to_slot[other_piece] = unassigned; - } - - // the slot where this piece belongs is - // free. Just move the piece there. - int piece_size = m_files.piece_size(piece); - if (m_storage->write(&m_scratch_buffer[0], piece, 0, piece_size) != piece_size) - { - error = m_storage->error().message(); - TORRENT_ASSERT(!error.empty()); - return fatal_disk_error; - } - m_piece_to_slot[piece] = piece; - m_slot_to_piece[piece] = piece; - - if (other_piece >= 0) - m_scratch_buffer.swap(m_scratch_buffer2); - - TORRENT_ASSERT(int(m_piece_to_slot.size()) == m_files.num_pieces()); - return need_full_check; - } - - while (m_current_slot < m_files.num_pieces() - && (m_slot_to_piece[m_current_slot] == m_current_slot - || m_slot_to_piece[m_current_slot] < 0)) - { - ++m_current_slot; - } - - if (m_current_slot == m_files.num_pieces()) - { - return check_init_storage(error); - } - - TORRENT_ASSERT(m_current_slot < m_files.num_pieces()); - - int piece = m_slot_to_piece[m_current_slot]; - TORRENT_ASSERT(piece >= 0); - int other_piece = m_slot_to_piece[piece]; - if (other_piece >= 0) - { - // there is another piece in the slot - // where this one goes. Store it in the scratch - // buffer until next iteration. - if (m_scratch_buffer.empty()) - m_scratch_buffer.resize(m_files.piece_length()); - - int piece_size = m_files.piece_size(other_piece); - if (m_storage->read(&m_scratch_buffer[0], piece, 0, piece_size) != piece_size) - { - error = m_storage->error().message(); - TORRENT_ASSERT(!error.empty()); - return fatal_disk_error; - } - m_scratch_piece = other_piece; - m_piece_to_slot[other_piece] = unassigned; - } - - // the slot where this piece belongs is - // free. Just move the piece there. - m_storage->move_slot(m_current_slot, piece); - m_piece_to_slot[piece] = piece; - m_slot_to_piece[m_current_slot] = unassigned; - m_slot_to_piece[piece] = piece; - - TORRENT_ASSERT(int(m_piece_to_slot.size()) == m_files.num_pieces()); - return need_full_check; - } - - TORRENT_ASSERT(m_state == state_full_check); - - int skip = check_one_piece(have_piece); - TORRENT_ASSERT(m_current_slot <= m_files.num_pieces()); - - if (skip == -1) - { - error = m_storage->error().message(); - TORRENT_ASSERT(!error.empty()); - return fatal_disk_error; - } - - if (skip) - { - clear_error(); - // skip means that the piece we checked failed to be read from disk - // completely. We should skip all pieces belonging to that file. - // find the file that failed, and skip all the pieces in that file - size_type file_offset = 0; - size_type current_offset = size_type(m_current_slot) * m_files.piece_length(); - for (file_storage::iterator i = m_files.begin() - , end(m_files.end()); i != end; ++i) - { - file_offset += i->size; - if (file_offset > current_offset) break; - } - - TORRENT_ASSERT(file_offset > current_offset); - int skip_blocks = static_cast( - (file_offset - current_offset + m_files.piece_length() - 1) - / m_files.piece_length()); - TORRENT_ASSERT(skip_blocks >= 1); - - if (m_storage_mode == storage_mode_compact) - { - for (int i = m_current_slot; i < m_current_slot + skip_blocks; ++i) - { - TORRENT_ASSERT(m_slot_to_piece[i] == unallocated); - m_unallocated_slots.push_back(i); - } - } - - // current slot will increase by one at the end of the for-loop too - m_current_slot += skip_blocks - 1; - TORRENT_ASSERT(m_current_slot <= m_files.num_pieces()); - } - - ++m_current_slot; - current_slot = m_current_slot; - - if (m_current_slot >= m_files.num_pieces()) - { - TORRENT_ASSERT(m_current_slot == m_files.num_pieces()); - - // clear the memory we've been using - std::vector().swap(m_piece_data); - std::multimap().swap(m_hash_to_piece); - - if (m_storage_mode != storage_mode_compact) - { - if (!m_out_of_place) - { - // if no piece is out of place - // since we're in full allocation mode, we can - // forget the piece allocation tables - - std::vector().swap(m_piece_to_slot); - std::vector().swap(m_slot_to_piece); - return check_init_storage(error); - } - else - { - // in this case we're in full allocation mode, but - // we're resuming a compact allocated storage - m_state = state_expand_pieces; - m_current_slot = 0; - current_slot = m_current_slot; - TORRENT_ASSERT(int(m_piece_to_slot.size()) == m_files.num_pieces()); - return need_full_check; - } - } - else if (m_unallocated_slots.empty()) - { - switch_to_full_mode(); - } - return check_init_storage(error); - } - - TORRENT_ASSERT(int(m_piece_to_slot.size()) == m_files.num_pieces()); - return need_full_check; - } - - // -1=error 0=ok 1=skip - int piece_manager::check_one_piece(int& have_piece) - { - // ------------------------ - // DO THE FULL CHECK - // ------------------------ - - TORRENT_ASSERT(int(m_piece_to_slot.size()) == m_files.num_pieces()); - TORRENT_ASSERT(int(m_slot_to_piece.size()) == m_files.num_pieces()); - TORRENT_ASSERT(have_piece == -1); - - // initialization for the full check - if (m_hash_to_piece.empty()) - { - for (int i = 0; i < m_files.num_pieces(); ++i) - m_hash_to_piece.insert(std::make_pair(m_info->hash_for_piece(i), i)); - } - - m_piece_data.resize(int(m_files.piece_length())); - int piece_size = m_files.piece_size(m_current_slot); - int num_read = m_storage->read(&m_piece_data[0] - , m_current_slot, 0, piece_size); - - if (num_read < 0) - { - if (m_storage->error() -#ifdef TORRENT_WINDOWS - && m_storage->error() != error_code(ERROR_FILE_NOT_FOUND, get_system_category())) -#else - && m_storage->error() != error_code(ENOENT, get_posix_category())) -#endif - return -1; - return 1; - } - - // if the file is incomplete, skip the rest of it - if (num_read != piece_size) - return 1; - - int piece_index = identify_data(m_piece_data, m_current_slot); - - if (piece_index >= 0) have_piece = piece_index; - - if (piece_index != m_current_slot - && piece_index >= 0) - m_out_of_place = true; - - TORRENT_ASSERT(piece_index == unassigned || piece_index >= 0); - - const bool this_should_move = piece_index >= 0 && m_slot_to_piece[piece_index] != unallocated; - const bool other_should_move = m_piece_to_slot[m_current_slot] != has_no_slot; - - // check if this piece should be swapped with any other slot - // this section will ensure that the storage is correctly sorted - // libtorrent will never leave the storage in a state that - // requires this sorting, but other clients may. - - // example of worst case: - // | m_current_slot = 5 - // V - // +---+- - - +---+- - - +---+- - - // | x | | 5 | | 3 | <- piece data in slots - // +---+- - - +---+- - - +---+- - - // 3 y 5 <- slot index - - // in this example, the data in the m_current_slot (5) - // is piece 3. It has to be moved into slot 3. The data - // in slot y (piece 5) should be moved into the m_current_slot. - // and the data in slot 3 (piece x) should be moved to slot y. - - // there are three possible cases. - // 1. There's another piece that should be placed into this slot - // 2. This piece should be placed into another slot. - // 3. There's another piece that should be placed into this slot - // and this piece should be placed into another slot - - // swap piece_index with this slot - - // case 1 - if (this_should_move && !other_should_move) - { - TORRENT_ASSERT(piece_index != m_current_slot); - - const int other_slot = piece_index; - TORRENT_ASSERT(other_slot >= 0); - int other_piece = m_slot_to_piece[other_slot]; - - m_slot_to_piece[other_slot] = piece_index; - m_slot_to_piece[m_current_slot] = other_piece; - m_piece_to_slot[piece_index] = piece_index; - if (other_piece >= 0) m_piece_to_slot[other_piece] = m_current_slot; - - if (other_piece == unassigned) - { - std::vector::iterator i = - std::find(m_free_slots.begin(), m_free_slots.end(), other_slot); - TORRENT_ASSERT(i != m_free_slots.end()); - if (m_storage_mode == storage_mode_compact) - { - m_free_slots.erase(i); - m_free_slots.push_back(m_current_slot); - } - } - - bool ret = false; - if (other_piece >= 0) - ret |= m_storage->swap_slots(other_slot, m_current_slot); - else - ret |= m_storage->move_slot(m_current_slot, other_slot); - - if (ret) return 1; - - TORRENT_ASSERT(m_slot_to_piece[m_current_slot] == unassigned - || m_piece_to_slot[m_slot_to_piece[m_current_slot]] == m_current_slot); - } - // case 2 - else if (!this_should_move && other_should_move) - { - TORRENT_ASSERT(piece_index != m_current_slot); - - const int other_piece = m_current_slot; - const int other_slot = m_piece_to_slot[other_piece]; - TORRENT_ASSERT(other_slot >= 0); - - m_slot_to_piece[m_current_slot] = other_piece; - m_slot_to_piece[other_slot] = piece_index; - m_piece_to_slot[other_piece] = m_current_slot; - - if (piece_index == unassigned - && m_storage_mode == storage_mode_compact) - m_free_slots.push_back(other_slot); - - bool ret = false; - if (piece_index >= 0) - { - m_piece_to_slot[piece_index] = other_slot; - ret |= m_storage->swap_slots(other_slot, m_current_slot); - } - else - { - ret |= m_storage->move_slot(other_slot, m_current_slot); - - } - if (ret) return 1; - - TORRENT_ASSERT(m_slot_to_piece[m_current_slot] == unassigned - || m_piece_to_slot[m_slot_to_piece[m_current_slot]] == m_current_slot); - } - else if (this_should_move && other_should_move) - { - TORRENT_ASSERT(piece_index != m_current_slot); - TORRENT_ASSERT(piece_index >= 0); - - const int piece1 = m_slot_to_piece[piece_index]; - const int piece2 = m_current_slot; - const int slot1 = piece_index; - const int slot2 = m_piece_to_slot[piece2]; - - TORRENT_ASSERT(slot1 >= 0); - TORRENT_ASSERT(slot2 >= 0); - TORRENT_ASSERT(piece2 >= 0); - - if (slot1 == slot2) - { - // this means there are only two pieces involved in the swap - TORRENT_ASSERT(piece1 >= 0); - - // movement diagram: - // +-------------------------------+ - // | | - // +--> slot1 --> m_current_slot --+ - - m_slot_to_piece[slot1] = piece_index; - m_slot_to_piece[m_current_slot] = piece1; - - m_piece_to_slot[piece_index] = slot1; - m_piece_to_slot[piece1] = m_current_slot; - - TORRENT_ASSERT(piece1 == m_current_slot); - TORRENT_ASSERT(piece_index == slot1); - - m_storage->swap_slots(m_current_slot, slot1); - - TORRENT_ASSERT(m_slot_to_piece[m_current_slot] == unassigned - || m_piece_to_slot[m_slot_to_piece[m_current_slot]] == m_current_slot); - } - else - { - TORRENT_ASSERT(slot1 != slot2); - TORRENT_ASSERT(piece1 != piece2); - - // movement diagram: - // +-----------------------------------------+ - // | | - // +--> slot1 --> slot2 --> m_current_slot --+ - - m_slot_to_piece[slot1] = piece_index; - m_slot_to_piece[slot2] = piece1; - m_slot_to_piece[m_current_slot] = piece2; - - m_piece_to_slot[piece_index] = slot1; - m_piece_to_slot[m_current_slot] = piece2; - - if (piece1 == unassigned) - { - std::vector::iterator i = - std::find(m_free_slots.begin(), m_free_slots.end(), slot1); - TORRENT_ASSERT(i != m_free_slots.end()); - if (m_storage_mode == storage_mode_compact) - { - m_free_slots.erase(i); - m_free_slots.push_back(slot2); - } - } - - bool ret = false; - if (piece1 >= 0) - { - m_piece_to_slot[piece1] = slot2; - ret |= m_storage->swap_slots3(m_current_slot, slot1, slot2); - } - else - { - ret |= m_storage->move_slot(m_current_slot, slot1); - ret |= m_storage->move_slot(slot2, m_current_slot); - } - - if (ret) return 1; - - TORRENT_ASSERT(m_slot_to_piece[m_current_slot] == unassigned - || m_piece_to_slot[m_slot_to_piece[m_current_slot]] == m_current_slot); - } - } - else - { - TORRENT_ASSERT(m_piece_to_slot[m_current_slot] == has_no_slot || piece_index != m_current_slot); - TORRENT_ASSERT(m_slot_to_piece[m_current_slot] == unallocated); - TORRENT_ASSERT(piece_index == unassigned || m_piece_to_slot[piece_index] == has_no_slot); - - // the slot was identified as piece 'piece_index' - if (piece_index != unassigned) - m_piece_to_slot[piece_index] = m_current_slot; - else if (m_storage_mode == storage_mode_compact) - m_free_slots.push_back(m_current_slot); - - m_slot_to_piece[m_current_slot] = piece_index; - - TORRENT_ASSERT(m_slot_to_piece[m_current_slot] == unassigned - || m_piece_to_slot[m_slot_to_piece[m_current_slot]] == m_current_slot); - } - return 0; - } - - void piece_manager::switch_to_full_mode() - { - TORRENT_ASSERT(m_storage_mode == storage_mode_compact); - TORRENT_ASSERT(m_unallocated_slots.empty()); - // we have allocated all slots, switch to - // full allocation mode in order to free - // some unnecessary memory. - m_storage_mode = storage_mode_sparse; - std::vector().swap(m_unallocated_slots); - std::vector().swap(m_free_slots); - std::vector().swap(m_piece_to_slot); - std::vector().swap(m_slot_to_piece); - } - - int piece_manager::allocate_slot_for_piece(int piece_index) - { - boost::recursive_mutex::scoped_lock lock(m_mutex); - - if (m_storage_mode != storage_mode_compact) return piece_index; - - INVARIANT_CHECK; - - TORRENT_ASSERT(piece_index >= 0); - TORRENT_ASSERT(piece_index < (int)m_piece_to_slot.size()); - TORRENT_ASSERT(m_piece_to_slot.size() == m_slot_to_piece.size()); - - int slot_index = m_piece_to_slot[piece_index]; - - if (slot_index != has_no_slot) - { - TORRENT_ASSERT(slot_index >= 0); - TORRENT_ASSERT(slot_index < (int)m_slot_to_piece.size()); - return slot_index; - } - - if (m_free_slots.empty()) - { - allocate_slots(1); - TORRENT_ASSERT(!m_free_slots.empty()); - } - - std::vector::iterator iter( - std::find( - m_free_slots.begin() - , m_free_slots.end() - , piece_index)); - - if (iter == m_free_slots.end()) - { - TORRENT_ASSERT(m_slot_to_piece[piece_index] != unassigned); - TORRENT_ASSERT(!m_free_slots.empty()); - iter = m_free_slots.end() - 1; - - // special case to make sure we don't use the last slot - // when we shouldn't, since it's smaller than ordinary slots - if (*iter == m_files.num_pieces() - 1 && piece_index != *iter) - { - if (m_free_slots.size() == 1) - allocate_slots(1); - TORRENT_ASSERT(m_free_slots.size() > 1); - // assumes that all allocated slots - // are put at the end of the free_slots vector - iter = m_free_slots.end() - 1; - } - } - - slot_index = *iter; - m_free_slots.erase(iter); - - TORRENT_ASSERT(m_slot_to_piece[slot_index] == unassigned); - - m_slot_to_piece[slot_index] = piece_index; - m_piece_to_slot[piece_index] = slot_index; - - // there is another piece already assigned to - // the slot we are interested in, swap positions - if (slot_index != piece_index - && m_slot_to_piece[piece_index] >= 0) - { - -#if defined TORRENT_DEBUG && defined TORRENT_STORAGE_DEBUG - std::stringstream s; - - s << "there is another piece at our slot, swapping.."; - - s << "\n piece_index: "; - s << piece_index; - s << "\n slot_index: "; - s << slot_index; - s << "\n piece at our slot: "; - s << m_slot_to_piece[piece_index]; - s << "\n"; - - print_to_log(s.str()); - debug_log(); -#endif - - int piece_at_our_slot = m_slot_to_piece[piece_index]; - TORRENT_ASSERT(m_piece_to_slot[piece_at_our_slot] == piece_index); - - std::swap( - m_slot_to_piece[piece_index] - , m_slot_to_piece[slot_index]); - - std::swap( - m_piece_to_slot[piece_index] - , m_piece_to_slot[piece_at_our_slot]); - - m_storage->move_slot(piece_index, slot_index); - - TORRENT_ASSERT(m_slot_to_piece[piece_index] == piece_index); - TORRENT_ASSERT(m_piece_to_slot[piece_index] == piece_index); - - slot_index = piece_index; - -#if defined TORRENT_DEBUG && defined TORRENT_STORAGE_DEBUG - debug_log(); -#endif - } - TORRENT_ASSERT(slot_index >= 0); - TORRENT_ASSERT(slot_index < (int)m_slot_to_piece.size()); - - if (m_free_slots.empty() && m_unallocated_slots.empty()) - switch_to_full_mode(); - - return slot_index; - } - - bool piece_manager::allocate_slots(int num_slots, bool abort_on_disk) - { - boost::recursive_mutex::scoped_lock lock(m_mutex); - TORRENT_ASSERT(num_slots > 0); - - INVARIANT_CHECK; - - TORRENT_ASSERT(!m_unallocated_slots.empty()); - TORRENT_ASSERT(m_storage_mode == storage_mode_compact); - - bool written = false; - - for (int i = 0; i < num_slots && !m_unallocated_slots.empty(); ++i) - { -// INVARIANT_CHECK; - - int pos = m_unallocated_slots.front(); - TORRENT_ASSERT(m_slot_to_piece[pos] == unallocated); - TORRENT_ASSERT(m_piece_to_slot[pos] != pos); - - int new_free_slot = pos; - if (m_piece_to_slot[pos] != has_no_slot) - { - new_free_slot = m_piece_to_slot[pos]; - m_storage->move_slot(new_free_slot, pos); - m_slot_to_piece[pos] = pos; - m_piece_to_slot[pos] = pos; - written = true; - } - m_unallocated_slots.erase(m_unallocated_slots.begin()); - m_slot_to_piece[new_free_slot] = unassigned; - m_free_slots.push_back(new_free_slot); - if (abort_on_disk && written) break; - } - - TORRENT_ASSERT(m_free_slots.size() > 0); - return written; - } - - int piece_manager::slot_for(int piece) const - { - if (m_storage_mode != storage_mode_compact) return piece; - TORRENT_ASSERT(piece < int(m_piece_to_slot.size())); - TORRENT_ASSERT(piece >= 0); - return m_piece_to_slot[piece]; - } - - int piece_manager::piece_for(int slot) const - { - if (m_storage_mode != storage_mode_compact) return slot; - TORRENT_ASSERT(slot < int(m_slot_to_piece.size())); - TORRENT_ASSERT(slot >= 0); - return m_slot_to_piece[slot]; - } - -#ifdef TORRENT_DEBUG - void piece_manager::check_invariant() const - { - boost::recursive_mutex::scoped_lock lock(m_mutex); - - TORRENT_ASSERT(m_current_slot <= m_files.num_pieces()); - - if (m_unallocated_slots.empty() - && m_free_slots.empty() - && m_state == state_finished) - { - TORRENT_ASSERT(m_storage_mode != storage_mode_compact - || m_files.num_pieces() == 0); - } - - if (m_storage_mode != storage_mode_compact) - { - TORRENT_ASSERT(m_unallocated_slots.empty()); - TORRENT_ASSERT(m_free_slots.empty()); - } - - if (m_storage_mode != storage_mode_compact - && m_state != state_expand_pieces - && m_state != state_full_check) - { - TORRENT_ASSERT(m_piece_to_slot.empty()); - TORRENT_ASSERT(m_slot_to_piece.empty()); - } - else - { - if (m_piece_to_slot.empty()) return; - - TORRENT_ASSERT((int)m_piece_to_slot.size() == m_files.num_pieces()); - TORRENT_ASSERT((int)m_slot_to_piece.size() == m_files.num_pieces()); - - for (std::vector::const_iterator i = m_free_slots.begin(); - i != m_free_slots.end(); ++i) - { - TORRENT_ASSERT(*i < (int)m_slot_to_piece.size()); - TORRENT_ASSERT(*i >= 0); - TORRENT_ASSERT(m_slot_to_piece[*i] == unassigned); - TORRENT_ASSERT(std::find(i+1, m_free_slots.end(), *i) - == m_free_slots.end()); - } - - for (std::vector::const_iterator i = m_unallocated_slots.begin(); - i != m_unallocated_slots.end(); ++i) - { - TORRENT_ASSERT(*i < (int)m_slot_to_piece.size()); - TORRENT_ASSERT(*i >= 0); - TORRENT_ASSERT(m_slot_to_piece[*i] == unallocated); - TORRENT_ASSERT(std::find(i+1, m_unallocated_slots.end(), *i) - == m_unallocated_slots.end()); - } - - for (int i = 0; i < m_files.num_pieces(); ++i) - { - // Check domain of piece_to_slot's elements - if (m_piece_to_slot[i] != has_no_slot) - { - TORRENT_ASSERT(m_piece_to_slot[i] >= 0); - TORRENT_ASSERT(m_piece_to_slot[i] < (int)m_slot_to_piece.size()); - } - - // Check domain of slot_to_piece's elements - if (m_slot_to_piece[i] != unallocated - && m_slot_to_piece[i] != unassigned) - { - TORRENT_ASSERT(m_slot_to_piece[i] >= 0); - TORRENT_ASSERT(m_slot_to_piece[i] < (int)m_piece_to_slot.size()); - } - - // do more detailed checks on piece_to_slot - if (m_piece_to_slot[i] >= 0) - { - TORRENT_ASSERT(m_slot_to_piece[m_piece_to_slot[i]] == i); - if (m_piece_to_slot[i] != i) - { - TORRENT_ASSERT(m_slot_to_piece[i] == unallocated); - } - } - else - { - TORRENT_ASSERT(m_piece_to_slot[i] == has_no_slot); - } - - // do more detailed checks on slot_to_piece - - if (m_slot_to_piece[i] >= 0) - { - TORRENT_ASSERT(m_slot_to_piece[i] < (int)m_piece_to_slot.size()); - TORRENT_ASSERT(m_piece_to_slot[m_slot_to_piece[i]] == i); -#ifdef TORRENT_STORAGE_DEBUG - TORRENT_ASSERT( - std::find( - m_unallocated_slots.begin() - , m_unallocated_slots.end() - , i) == m_unallocated_slots.end() - ); - TORRENT_ASSERT( - std::find( - m_free_slots.begin() - , m_free_slots.end() - , i) == m_free_slots.end() - ); -#endif - } - else if (m_slot_to_piece[i] == unallocated) - { -#ifdef TORRENT_STORAGE_DEBUG - TORRENT_ASSERT(m_unallocated_slots.empty() - || (std::find( - m_unallocated_slots.begin() - , m_unallocated_slots.end() - , i) != m_unallocated_slots.end()) - ); -#endif - } - else if (m_slot_to_piece[i] == unassigned) - { -#ifdef TORRENT_STORAGE_DEBUG - TORRENT_ASSERT( - std::find( - m_free_slots.begin() - , m_free_slots.end() - , i) != m_free_slots.end() - ); -#endif - } - else - { - TORRENT_ASSERT(false && "m_slot_to_piece[i] is invalid"); - } - } - } - } - -#ifdef TORRENT_STORAGE_DEBUG - void piece_manager::debug_log() const - { - std::stringstream s; - - s << "index\tslot\tpiece\n"; - - for (int i = 0; i < m_files.num_pieces(); ++i) - { - s << i << "\t" << m_slot_to_piece[i] << "\t"; - s << m_piece_to_slot[i] << "\n"; - } - - s << "---------------------------------\n"; - - print_to_log(s.str()); - } -#endif -#endif -} // namespace libtorrent - diff --git a/libtorrent/src/torrent.cpp b/libtorrent/src/torrent.cpp deleted file mode 100755 index 633e0ab90..000000000 --- a/libtorrent/src/torrent.cpp +++ /dev/null @@ -1,4789 +0,0 @@ -/* - -Copyright (c) 2003, Arvid Norberg -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions -are met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in - the documentation and/or other materials provided with the distribution. - * Neither the name of the author nor the names of its - contributors may be used to endorse or promote products derived - from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -POSSIBILITY OF SUCH DAMAGE. - -*/ - -#include "libtorrent/pch.hpp" - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#ifdef _MSC_VER -#pragma warning(push, 1) -#endif - -#include -#include -#include - -#ifdef _MSC_VER -#pragma warning(pop) -#endif - -#include "libtorrent/torrent_handle.hpp" -#include "libtorrent/session.hpp" -#include "libtorrent/torrent_info.hpp" -#include "libtorrent/tracker_manager.hpp" -#include "libtorrent/parse_url.hpp" -#include "libtorrent/bencode.hpp" -#include "libtorrent/hasher.hpp" -#include "libtorrent/entry.hpp" -#include "libtorrent/peer.hpp" -#include "libtorrent/bt_peer_connection.hpp" -#include "libtorrent/web_peer_connection.hpp" -#include "libtorrent/peer_id.hpp" -#include "libtorrent/alert.hpp" -#include "libtorrent/identify_client.hpp" -#include "libtorrent/alert_types.hpp" -#include "libtorrent/extensions.hpp" -#include "libtorrent/aux_/session_impl.hpp" -#include "libtorrent/instantiate_connection.hpp" -#include "libtorrent/assert.hpp" -#include "libtorrent/broadcast_socket.hpp" - -using namespace libtorrent; -using boost::tuples::tuple; -using boost::tuples::get; -using boost::tuples::make_tuple; -using boost::bind; -using libtorrent::aux::session_impl; - -namespace -{ - - enum - { - // wait 60 seconds before retrying a failed tracker - tracker_retry_delay_min = 60 - // when tracker_failed_max trackers - // has failed, wait 10 minutes instead - , tracker_retry_delay_max = 10 * 60 - , tracker_failed_max = 5 - }; - - struct find_peer_by_ip - { - find_peer_by_ip(tcp::endpoint const& a, const torrent* t) - : ip(a) - , tor(t) - { TORRENT_ASSERT(t != 0); } - - bool operator()(session_impl::connection_map::value_type const& c) const - { - tcp::endpoint const& sender = c->remote(); - if (sender.address() != ip.address()) return false; - if (tor != c->associated_torrent().lock().get()) return false; - return true; - } - - tcp::endpoint const& ip; - torrent const* tor; - }; - - struct peer_by_id - { - peer_by_id(const peer_id& i): pid(i) {} - - bool operator()(session_impl::connection_map::value_type const& p) const - { - if (p->pid() != pid) return false; - // have a special case for all zeros. We can have any number - // of peers with that pid, since it's used to indicate no pid. - if (std::count(pid.begin(), pid.end(), 0) == 20) return false; - return true; - } - - peer_id const& pid; - }; -} - -namespace libtorrent -{ - - torrent::torrent( - session_impl& ses - , boost::intrusive_ptr tf - , fs::path const& save_path - , tcp::endpoint const& net_interface - , storage_mode_t storage_mode - , int block_size - , storage_constructor_type sc - , bool paused - , std::vector* resume_data - , int seq - , bool auto_managed) - : m_policy(this) - , m_active_time(seconds(0)) - , m_seeding_time(seconds(0)) - , m_total_uploaded(0) - , m_total_downloaded(0) - , m_started(time_now()) - , m_last_scrape(min_time()) - , m_torrent_file(tf) - , m_storage(0) - , m_next_tracker_announce(time_now()) - , m_host_resolver(ses.m_io_service) - , m_lsd_announce_timer(ses.m_io_service) - , m_tracker_timer(ses.m_io_service) -#ifndef TORRENT_DISABLE_DHT - , m_last_dht_announce(time_now() - minutes(15)) -#endif - , m_ses(ses) - , m_picker(new piece_picker()) - , m_trackers(m_torrent_file->trackers()) - , m_total_failed_bytes(0) - , m_total_redundant_bytes(0) - , m_net_interface(net_interface.address(), 0) - , m_save_path(complete(save_path)) - , m_storage_mode(storage_mode) - , m_state(torrent_status::checking_resume_data) - , m_settings(ses.settings()) - , m_storage_constructor(sc) - , m_progress(0.f) - , m_ratio(0.f) - , m_max_uploads((std::numeric_limits::max)()) - , m_num_uploads(0) - , m_max_connections((std::numeric_limits::max)()) - , m_block_size((std::min)(block_size, tf->piece_length())) - , m_complete(-1) - , m_incomplete(-1) - , m_deficit_counter(0) - , m_duration(1800) - , m_sequence_number(seq) - , m_last_working_tracker(-1) - , m_currently_trying_tracker(0) - , m_failed_trackers(0) - , m_time_scaler(0) - , m_abort(false) - , m_paused(paused) - , m_auto_managed(auto_managed) -#ifndef TORRENT_DISABLE_RESOLVE_COUNTRIES - , m_resolving_country(false) - , m_resolve_countries(false) -#endif - , m_sequential_download(false) - , m_got_tracker_response(false) - , m_connections_initialized(true) - , m_has_incoming(false) - , m_files_checked(false) - , m_queued_for_checking(false) - , m_announcing(false) - , m_start_sent(false) - , m_complete_sent(false) - { - if (resume_data) m_resume_data.swap(*resume_data); - -#ifndef TORRENT_DISABLE_ENCRYPTION - hasher h; - h.update("req2", 4); - h.update((char*)&tf->info_hash()[0], 20); - m_obfuscated_hash = h.final(); -#endif - } - - torrent::torrent( - session_impl& ses - , char const* tracker_url - , sha1_hash const& info_hash - , char const* name - , fs::path const& save_path - , tcp::endpoint const& net_interface - , storage_mode_t storage_mode - , int block_size - , storage_constructor_type sc - , bool paused - , std::vector* resume_data - , int seq - , bool auto_managed) - : m_policy(this) - , m_active_time(seconds(0)) - , m_seeding_time(seconds(0)) - , m_total_uploaded(0) - , m_total_downloaded(0) - , m_started(time_now()) - , m_last_scrape(min_time()) - , m_torrent_file(new torrent_info(info_hash)) - , m_storage(0) - , m_next_tracker_announce(time_now()) - , m_host_resolver(ses.m_io_service) - , m_lsd_announce_timer(ses.m_io_service) - , m_tracker_timer(ses.m_io_service) -#ifndef TORRENT_DISABLE_DHT - , m_last_dht_announce(time_now() - minutes(15)) -#endif - , m_ses(ses) - , m_picker(new piece_picker()) - , m_total_failed_bytes(0) - , m_total_redundant_bytes(0) - , m_net_interface(net_interface.address(), 0) - , m_save_path(complete(save_path)) - , m_storage_mode(storage_mode) - , m_state(torrent_status::checking_resume_data) - , m_settings(ses.settings()) - , m_storage_constructor(sc) - , m_progress(0.f) - , m_ratio(0.f) - , m_max_uploads((std::numeric_limits::max)()) - , m_num_uploads(0) - , m_max_connections((std::numeric_limits::max)()) - , m_block_size(block_size) - , m_complete(-1) - , m_incomplete(-1) - , m_deficit_counter(0) - , m_duration(1800) - , m_sequence_number(seq) - , m_last_working_tracker(-1) - , m_currently_trying_tracker(0) - , m_failed_trackers(0) - , m_time_scaler(0) - , m_abort(false) - , m_paused(paused) - , m_auto_managed(auto_managed) -#ifndef TORRENT_DISABLE_RESOLVE_COUNTRIES - , m_resolving_country(false) - , m_resolve_countries(false) -#endif - , m_sequential_download(false) - , m_got_tracker_response(false) - , m_connections_initialized(false) - , m_has_incoming(false) - , m_files_checked(false) - , m_queued_for_checking(false) - , m_announcing(false) - , m_start_sent(false) - , m_complete_sent(false) - { - if (resume_data) m_resume_data.swap(*resume_data); - -#ifndef TORRENT_DISABLE_ENCRYPTION - hasher h; - h.update("req2", 4); - h.update((char*)&info_hash[0], 20); - m_obfuscated_hash = h.final(); -#endif - -#ifdef TORRENT_DEBUG - m_files_checked = false; -#endif - INVARIANT_CHECK; - - if (name) m_name.reset(new std::string(name)); - - if (tracker_url) - { - m_trackers.push_back(announce_entry(tracker_url)); - m_torrent_file->add_tracker(tracker_url); - } - } - - void torrent::start() - { - if (!m_resume_data.empty()) - { - if (lazy_bdecode(&m_resume_data[0], &m_resume_data[0] - + m_resume_data.size(), m_resume_entry) != 0) - { - std::vector().swap(m_resume_data); - if (m_ses.m_alerts.should_post()) - { - m_ses.m_alerts.post_alert(fastresume_rejected_alert(get_handle(), "parse failed")); -#if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_LOGGING || defined TORRENT_ERROR_LOGGING - (*m_ses.m_logger) << "fastresume data for " - << torrent_file().name() << " rejected: parse failed\n"; -#endif - } - } - } - - // we need to start announcing since we don't have any - // metadata. To receive peers to ask for it. - if (m_torrent_file->is_valid()) init(); - else - { - set_state(torrent_status::downloading_metadata); - if (!m_trackers.empty()) start_announcing(); - } - - if (m_abort) return; - } - -#ifndef TORRENT_DISABLE_DHT - bool torrent::should_announce_dht() const - { - if (m_ses.m_listen_sockets.empty()) return false; - - if (!m_ses.m_dht) return false; - if (m_torrent_file->is_valid() && !m_files_checked) return false; - - // don't announce private torrents - if (m_torrent_file->is_valid() && m_torrent_file->priv()) return false; - if (m_trackers.empty()) return true; - - return m_failed_trackers > 0 || !m_ses.settings().use_dht_as_fallback; - } -#endif - - 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. - - TORRENT_ASSERT(m_connections.empty()); - - INVARIANT_CHECK; - -#if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_ERROR_LOGGING - for (peer_iterator i = m_connections.begin(); - i != m_connections.end(); ++i) - { - (*(*i)->m_logger) << "*** DESTRUCTING TORRENT\n"; - } -#endif - - TORRENT_ASSERT(m_abort); - if (!m_connections.empty()) - disconnect_all(); - } - - peer_request torrent::to_req(piece_block const& p) - { - int block_offset = p.block_index * m_block_size; - int block_size = (std::min)(torrent_file().piece_size( - p.piece_index) - block_offset, m_block_size); - TORRENT_ASSERT(block_size > 0); - TORRENT_ASSERT(block_size <= m_block_size); - - peer_request r; - r.piece = p.piece_index; - r.start = block_offset; - r.length = block_size; - return r; - } - - std::string torrent::name() const - { - if (valid_metadata()) return m_torrent_file->name(); - if (m_name) return *m_name; - return ""; - } - -#ifndef TORRENT_DISABLE_EXTENSIONS - - void torrent::add_extension(boost::shared_ptr ext) - { - m_extensions.push_back(ext); - } - - void torrent::add_extension(boost::function(torrent*, void*)> const& ext - , void* userdata) - { - boost::shared_ptr tp(ext(this, userdata)); - if (!tp) return; - - add_extension(tp); - - for (peer_iterator i = m_connections.begin(); - i != m_connections.end(); ++i) - { - peer_connection* p = *i; - boost::shared_ptr pp(tp->new_connection(p)); - if (pp) p->add_extension(pp); - } - - // if files are checked for this torrent, call the extension - // to let it initialize itself - if (m_connections_initialized) - tp->on_files_checked(); - } - -#endif - - // this may not be called from a constructor because of the call to - // shared_from_this() - void torrent::init() - { - TORRENT_ASSERT(m_torrent_file->is_valid()); - TORRENT_ASSERT(m_torrent_file->num_files() > 0); - TORRENT_ASSERT(m_torrent_file->total_size() >= 0); - - m_file_priority.clear(); - m_file_priority.resize(m_torrent_file->num_files(), 1); - - m_block_size = (std::min)(m_block_size, m_torrent_file->piece_length()); - - if (m_torrent_file->num_pieces() - > piece_picker::max_pieces) - { - set_error("too many pieces in torrent"); - pause(); - } - - // the shared_from_this() will create an intentional - // cycle of ownership, se the hpp file for description. - m_owning_storage = new piece_manager(shared_from_this(), m_torrent_file - , m_save_path, m_ses.m_files, m_ses.m_disk_thread, m_storage_constructor - , m_storage_mode); - m_storage = m_owning_storage.get(); - m_picker->init((std::max)(m_torrent_file->piece_length() / m_block_size, 1) - , int((m_torrent_file->total_size()+m_block_size-1)/m_block_size)); - - std::vector const& url_seeds = m_torrent_file->url_seeds(); - std::copy(url_seeds.begin(), url_seeds.end(), std::inserter(m_web_seeds - , m_web_seeds.begin())); - - set_state(torrent_status::checking_resume_data); - - if (m_resume_entry.type() == lazy_entry::dict_t) - { - char const* error = 0; - if (m_resume_entry.dict_find_string_value("file-format") != "libtorrent resume file") - error = "invalid file format tag"; - - std::string info_hash = m_resume_entry.dict_find_string_value("info-hash"); - if (!error && info_hash.empty()) - error = "missing info-hash"; - - if (!error && sha1_hash(info_hash) != m_torrent_file->info_hash()) - error = "mismatching info-hash"; - - if (error && m_ses.m_alerts.should_post()) - { - m_ses.m_alerts.post_alert(fastresume_rejected_alert(get_handle(), error)); - } - - if (error) - { -#if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_LOGGING || defined TORRENT_ERROR_LOGGING - (*m_ses.m_logger) << "fastresume data for " - << torrent_file().name() << " rejected: " - << error << "\n"; -#endif - std::vector().swap(m_resume_data); - lazy_entry().swap(m_resume_entry); - } - else - { - read_resume_data(m_resume_entry); - } - } - - m_storage->async_check_fastresume(&m_resume_entry - , bind(&torrent::on_resume_data_checked - , shared_from_this(), _1, _2)); - } - - void torrent::on_resume_data_checked(int ret, disk_io_job const& j) - { - session_impl::mutex_t::scoped_lock l(m_ses.m_mutex); - - if (ret == piece_manager::fatal_disk_error) - { - if (m_ses.m_alerts.should_post()) - { - m_ses.m_alerts.post_alert(file_error_alert(j.error_file, get_handle(), j.str)); - } -#if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_LOGGING || defined TORRENT_ERROR_LOGGING - (*m_ses.m_logger) << time_now_string() << ": fatal disk error [" - " error: " << j.str << - " torrent: " << torrent_file().name() << - " ]\n"; -#endif - set_error(j.str); - pause(); - - std::vector().swap(m_resume_data); - lazy_entry().swap(m_resume_entry); - - return; - } - - if (m_resume_entry.type() == lazy_entry::dict_t) - { - // parse out "peers" from the resume data and add them to the peer list - if (lazy_entry const* peers_entry = m_resume_entry.dict_find_list("peers")) - { - peer_id id(0); - - for (int i = 0; i < peers_entry->list_size(); ++i) - { - lazy_entry const* e = peers_entry->list_at(i); - if (e->type() != lazy_entry::dict_t) continue; - std::string ip = e->dict_find_string_value("ip"); - int port = e->dict_find_int_value("port"); - if (ip.empty() || port == 0) continue; - error_code ec; - tcp::endpoint a(address::from_string(ip, ec), (unsigned short)port); - if (ec) continue; - m_policy.peer_from_tracker(a, id, peer_info::resume_data, 0); - } - } - - // parse out "banned_peers" and add them as banned - if (lazy_entry const* banned_peers_entry = m_resume_entry.dict_find_list("banned_peers")) - { - peer_id id(0); - - for (int i = 0; i < banned_peers_entry->list_size(); ++i) - { - lazy_entry const* e = banned_peers_entry->list_at(i); - if (e->type() != lazy_entry::dict_t) continue; - std::string ip = e->dict_find_string_value("ip"); - int port = e->dict_find_int_value("port"); - if (ip.empty() || port == 0) continue; - error_code ec; - tcp::endpoint a(address::from_string(ip, ec), (unsigned short)port); - if (ec) continue; - policy::peer* p = m_policy.peer_from_tracker(a, id, peer_info::resume_data, 0); - if (p) p->banned = true; - } - } - } - - bool fastresume_rejected = !j.str.empty(); - - if (fastresume_rejected && m_ses.m_alerts.should_post()) - { - m_ses.m_alerts.post_alert(fastresume_rejected_alert(get_handle(), j.str)); -#if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_LOGGING || defined TORRENT_ERROR_LOGGING - (*m_ses.m_logger) << "fastresume data for " - << torrent_file().name() << " rejected: " - << j.str << "\n"; -#endif - } - - if (ret == 0) - { - // there are either no files for this torrent - // or the resume_data was accepted - - if (!fastresume_rejected && m_resume_entry.type() == lazy_entry::dict_t) - { - // parse have bitmask - lazy_entry const* pieces = m_resume_entry.dict_find("pieces"); - if (pieces && pieces->type() == lazy_entry::string_t - && int(pieces->string_length()) == m_torrent_file->num_pieces()) - { - char const* pieces_str = pieces->string_ptr(); - for (int i = 0, end(pieces->string_length()); i < end; ++i) - { - if ((pieces_str[i] & 1) == 0) continue; - m_picker->we_have(i); - } - } - - // parse unfinished pieces - int num_blocks_per_piece = - static_cast(torrent_file().piece_length()) / block_size(); - - if (lazy_entry const* unfinished_ent = m_resume_entry.dict_find_list("unfinished")) - { - for (int i = 0; i < unfinished_ent->list_size(); ++i) - { - lazy_entry const* e = unfinished_ent->list_at(i); - if (e->type() != lazy_entry::dict_t) continue; - int piece = e->dict_find_int_value("piece", -1); - if (piece < 0 || piece > torrent_file().num_pieces()) continue; - - if (m_picker->have_piece(piece)) - m_picker->we_dont_have(piece); - - std::string bitmask = e->dict_find_string_value("bitmask"); - if (bitmask.empty()) continue; - - const int num_bitmask_bytes = (std::max)(num_blocks_per_piece / 8, 1); - if ((int)bitmask.size() != num_bitmask_bytes) continue; - for (int j = 0; j < num_bitmask_bytes; ++j) - { - unsigned char bits = bitmask[j]; - int num_bits = (std::min)(num_blocks_per_piece - j*8, 8); - for (int k = 0; k < num_bits; ++k) - { - const int bit = j * 8 + k; - if (bits & (1 << k)) - { - m_picker->mark_as_finished(piece_block(piece, bit), 0); - if (m_picker->is_piece_finished(piece)) - async_verify_piece(piece, bind(&torrent::piece_finished - , shared_from_this(), piece, _1)); - } - } - } - } - } - } - - files_checked(); - } - else - { - // either the fastresume data was rejected or there are - // some files - set_state(torrent_status::queued_for_checking); - if (should_check_files()) - queue_torrent_check(); - } - - std::vector().swap(m_resume_data); - lazy_entry().swap(m_resume_entry); - } - - void torrent::queue_torrent_check() - { - if (m_queued_for_checking) return; - m_queued_for_checking = true; - m_ses.check_torrent(shared_from_this()); - } - - void torrent::dequeue_torrent_check() - { - if (!m_queued_for_checking) return; - m_queued_for_checking = false; - m_ses.done_checking(shared_from_this()); - } - - void torrent::force_recheck() - { - // if the torrent is already queued to check its files - // don't do anything - if (should_check_files() - || m_state == torrent_status::checking_resume_data) - return; - - disconnect_all(); - - m_owning_storage->async_release_files(); - m_owning_storage = new piece_manager(shared_from_this(), m_torrent_file - , m_save_path, m_ses.m_files, m_ses.m_disk_thread, m_storage_constructor - , m_storage_mode); - m_storage = m_owning_storage.get(); - if (!m_picker) m_picker.reset(new piece_picker()); - m_picker->init(m_torrent_file->piece_length() / m_block_size - , int((m_torrent_file->total_size()+m_block_size-1)/m_block_size)); - // assume that we don't have anything - m_files_checked = false; - set_state(torrent_status::checking_resume_data); - - if (m_auto_managed) - set_queue_position((std::numeric_limits::max)()); - - std::vector().swap(m_resume_data); - lazy_entry().swap(m_resume_entry); - m_storage->async_check_fastresume(&m_resume_entry - , bind(&torrent::on_force_recheck - , shared_from_this(), _1, _2)); - } - - void torrent::on_force_recheck(int ret, disk_io_job const& j) - { - session_impl::mutex_t::scoped_lock l(m_ses.m_mutex); - - if (ret == piece_manager::fatal_disk_error) - { - if (m_ses.m_alerts.should_post()) - { - m_ses.m_alerts.post_alert(file_error_alert(j.error_file, get_handle(), j.str)); - } -#if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_LOGGING || defined TORRENT_ERROR_LOGGING - (*m_ses.m_logger) << time_now_string() << ": fatal disk error [" - " error: " << j.str << - " torrent: " << torrent_file().name() << - " ]\n"; -#endif - set_error(j.str); - pause(); - return; - } - set_state(torrent_status::queued_for_checking); - if (should_check_files()) - queue_torrent_check(); - } - - void torrent::start_checking() - { - TORRENT_ASSERT(should_check_files()); - set_state(torrent_status::checking_files); - - m_storage->async_check_files(bind( - &torrent::on_piece_checked - , shared_from_this(), _1, _2)); - } - - void torrent::on_piece_checked(int ret, disk_io_job const& j) - { - session_impl::mutex_t::scoped_lock l(m_ses.m_mutex); - INVARIANT_CHECK; - - if (ret == piece_manager::disk_check_aborted) - { - set_error("aborted"); - return; - } - if (ret == piece_manager::fatal_disk_error) - { - if (m_ses.m_alerts.should_post()) - { - m_ses.m_alerts.post_alert(file_error_alert(j.error_file, get_handle(), j.str)); - } -#if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_LOGGING || defined TORRENT_ERROR_LOGGING - (*m_ses.m_logger) << time_now_string() << ": fatal disk error [" - " error: " << j.str << - " torrent: " << torrent_file().name() << - " ]\n"; -#endif - set_error(j.str); - pause(); - return; - } - - m_progress = j.piece / float(torrent_file().num_pieces()); - - TORRENT_ASSERT(m_picker); - if (j.offset >= 0 && !m_picker->have_piece(j.offset)) - m_picker->we_have(j.offset); - - // we're not done checking yet - // this handler will be called repeatedly until - // we're done, or encounter a failure - if (ret == piece_manager::need_full_check) return; - - dequeue_torrent_check(); - files_checked(); - } - - void torrent::use_interface(const char* net_interface) - { - INVARIANT_CHECK; - - error_code ec; - address a(address::from_string(net_interface, ec)); - if (ec) return; - m_net_interface = tcp::endpoint(a, 0); - } - - void torrent::on_tracker_announce_disp(boost::weak_ptr p - , error_code const& e) - { - if (e) return; - boost::shared_ptr t = p.lock(); - if (!t) return; - t->on_tracker_announce(); - } - - void torrent::on_tracker_announce() - { - session_impl::mutex_t::scoped_lock l(m_ses.m_mutex); - - if (m_abort) return; - announce_with_tracker(); - } - - void torrent::on_lsd_announce_disp(boost::weak_ptr p - , error_code const& e) - { - if (e) return; - boost::shared_ptr t = p.lock(); - if (!t) return; - t->on_lsd_announce(); - } - - void torrent::on_lsd_announce() - { - session_impl::mutex_t::scoped_lock l(m_ses.m_mutex); - - if (m_abort) return; - - TORRENT_ASSERT(!m_torrent_file->priv()); - if (m_torrent_file->is_valid() && m_torrent_file->priv()) - return; - - if (is_paused()) return; - - boost::weak_ptr self(shared_from_this()); - - error_code ec; - - // announce on local network every 5 minutes - m_lsd_announce_timer.expires_from_now(minutes(5), ec); - m_lsd_announce_timer.async_wait( - bind(&torrent::on_lsd_announce_disp, self, _1)); - - // announce with the local discovery service - m_ses.announce_lsd(m_torrent_file->info_hash()); - -#ifndef TORRENT_DISABLE_DHT - if (!m_ses.m_dht) return; - ptime now = time_now(); - if (should_announce_dht() && now - m_last_dht_announce > minutes(14)) - { - m_last_dht_announce = now; - m_ses.m_dht->announce(m_torrent_file->info_hash() - , m_ses.m_listen_sockets.front().external_port - , bind(&torrent::on_dht_announce_response_disp, self, _1)); - } -#endif - } - -#ifndef TORRENT_DISABLE_DHT - - void torrent::on_dht_announce_response_disp(boost::weak_ptr t - , std::vector const& peers) - { - boost::shared_ptr tor = t.lock(); - if (!tor) return; - tor->on_dht_announce_response(peers); - } - - void torrent::on_dht_announce_response(std::vector const& peers) - { - if (peers.empty()) return; - - if (m_ses.m_alerts.should_post()) - { - m_ses.m_alerts.post_alert(dht_reply_alert( - get_handle(), peers.size())); - } - std::for_each(peers.begin(), peers.end(), bind( - &policy::peer_from_tracker, boost::ref(m_policy), _1, peer_id(0) - , peer_info::dht, 0)); - } - -#endif - - void torrent::announce_with_tracker(tracker_request::event_t e) - { - INVARIANT_CHECK; - - if (m_trackers.empty()) return; - - restart_tracker_timer(time_now() + seconds(tracker_retry_delay_max)); - - if (m_abort) e = tracker_request::stopped; - - if (e == tracker_request::none) - { - if (!m_start_sent) e = tracker_request::started; - if (!m_complete_sent && is_seed()) e = tracker_request::completed; - } - - tracker_request req; - req.info_hash = m_torrent_file->info_hash(); - req.pid = m_ses.get_peer_id(); - req.downloaded = m_stat.total_payload_download(); - req.uploaded = m_stat.total_payload_upload(); - req.left = bytes_left(); - if (req.left == -1) req.left = 16*1024; - req.event = e; - tcp::endpoint ep = m_ses.get_ipv6_interface(); - error_code ec; - if (ep != tcp::endpoint()) - req.ipv6 = ep.address().to_string(ec); - - req.url = m_trackers[m_currently_trying_tracker].url; - // if we are aborting. we don't want any new peers - req.num_want = (req.event == tracker_request::stopped) - ?0:m_settings.num_want; - - req.listen_port = m_ses.m_listen_sockets.empty() - ?0:m_ses.m_listen_sockets.front().external_port; - req.key = m_ses.m_key; - -#if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING) - if (m_abort) - { - boost::shared_ptr tl(new aux::tracker_logger(m_ses)); - m_ses.m_tracker_manager.queue_request(m_ses.m_io_service, m_ses.m_half_open, req - , tracker_login(), m_ses.m_listen_interface.address(), tl); - } - else -#endif - m_ses.m_tracker_manager.queue_request(m_ses.m_io_service, m_ses.m_half_open, req - , tracker_login(), m_ses.m_listen_interface.address() - , m_abort?boost::shared_ptr():shared_from_this()); - - if (m_ses.m_alerts.should_post()) - { - m_ses.m_alerts.post_alert( - tracker_announce_alert(get_handle(), req.url, req.event)); - } - } - - void torrent::scrape_tracker() - { - if (m_trackers.empty()) return; - - TORRENT_ASSERT(m_currently_trying_tracker >= 0); - TORRENT_ASSERT(m_currently_trying_tracker < int(m_trackers.size())); - - tracker_request req; - req.info_hash = m_torrent_file->info_hash(); - req.kind = tracker_request::scrape_request; - req.url = m_trackers[m_currently_trying_tracker].url; - m_ses.m_tracker_manager.queue_request(m_ses.m_io_service, m_ses.m_half_open, req - , tracker_login(), m_ses.m_listen_interface.address(), shared_from_this()); - - m_last_scrape = time_now(); - } - - void torrent::tracker_warning(tracker_request const& req, std::string const& msg) - { - session_impl::mutex_t::scoped_lock l(m_ses.m_mutex); - - INVARIANT_CHECK; - - if (m_ses.m_alerts.should_post()) - m_ses.m_alerts.post_alert(tracker_warning_alert(get_handle(), req.url, msg)); - } - - void torrent::tracker_scrape_response(tracker_request const& req - , int complete, int incomplete, int downloaded) - { - session_impl::mutex_t::scoped_lock l(m_ses.m_mutex); - - INVARIANT_CHECK; - TORRENT_ASSERT(req.kind == tracker_request::scrape_request); - - if (complete >= 0) m_complete = complete; - if (incomplete >= 0) m_incomplete = incomplete; - - if (m_ses.m_alerts.should_post()) - { - m_ses.m_alerts.post_alert(scrape_reply_alert( - get_handle(), m_incomplete, m_complete, req.url)); - } - } - - void torrent::tracker_response( - tracker_request const& r - , std::vector& peer_list - , int interval - , int complete - , int incomplete - , address const& external_ip) - { - session_impl::mutex_t::scoped_lock l(m_ses.m_mutex); - - INVARIANT_CHECK; - TORRENT_ASSERT(r.kind == tracker_request::announce_request); - - if (external_ip != address()) - m_ses.set_external_address(external_ip); - - if (!m_start_sent && r.event == tracker_request::started) - m_start_sent = true; - if (!m_complete_sent && r.event == tracker_request::completed) - m_complete_sent = true; - - m_failed_trackers = 0; - - if (interval < m_ses.settings().min_announce_interval) - interval = m_ses.settings().min_announce_interval; - - m_last_working_tracker - = prioritize_tracker(m_currently_trying_tracker); - m_currently_trying_tracker = 0; - - m_duration = interval; - restart_tracker_timer(time_now() + seconds(m_duration)); - - if (complete >= 0) m_complete = complete; - if (incomplete >= 0) m_incomplete = incomplete; - if (complete >= 0 && incomplete >= 0) - m_last_scrape = time_now(); - -#if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_LOGGING - std::stringstream s; - s << "TRACKER RESPONSE:\n" - "interval: " << m_duration << "\n" - "peers:\n"; - for (std::vector::const_iterator i = peer_list.begin(); - i != peer_list.end(); ++i) - { - s << " " << std::setfill(' ') << std::setw(16) << i->ip - << " " << std::setw(5) << std::dec << i->port << " "; - if (!i->pid.is_all_zeros()) s << " " << i->pid << " " << identify_client(i->pid); - s << "\n"; - } - s << "external ip: " << external_ip << "\n"; - debug_log(s.str()); -#endif - // for each of the peers we got from the tracker - for (std::vector::iterator i = peer_list.begin(); - i != peer_list.end(); ++i) - { - // don't make connections to ourself - if (i->pid == m_ses.get_peer_id()) - continue; - - error_code ec; - tcp::endpoint a(address::from_string(i->ip, ec), i->port); - - if (ec) - { - // assume this is because we got a hostname instead of - // an ip address from the tracker - - tcp::resolver::query q(i->ip, to_string(i->port).elems); - m_host_resolver.async_resolve(q, - bind(&torrent::on_peer_name_lookup, shared_from_this(), _1, _2, i->pid)); - } - else - { - m_policy.peer_from_tracker(a, i->pid, peer_info::tracker, 0); - } - } - - if (m_ses.m_alerts.should_post()) - { - m_ses.m_alerts.post_alert(tracker_reply_alert( - get_handle(), peer_list.size(), r.url)); - } - m_got_tracker_response = true; - } - - void torrent::on_peer_name_lookup(error_code const& e, tcp::resolver::iterator host - , peer_id pid) - { - session_impl::mutex_t::scoped_lock l(m_ses.m_mutex); - - INVARIANT_CHECK; - - if (e || host == tcp::resolver::iterator() || - m_ses.is_aborted()) return; - - if (m_ses.m_ip_filter.access(host->endpoint().address()) & ip_filter::blocked) - { -#if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_LOGGING || defined TORRENT_ERROR_LOGGING - error_code ec; - debug_log("blocked ip from tracker: " + host->endpoint().address().to_string(ec)); -#endif - if (m_ses.m_alerts.should_post()) - { - m_ses.m_alerts.post_alert(peer_blocked_alert(host->endpoint().address())); - } - - return; - } - - m_policy.peer_from_tracker(*host, pid, peer_info::tracker, 0); - } - - size_type torrent::bytes_left() const - { - // if we don't have the metadata yet, we - // cannot tell how big the torrent is. - if (!valid_metadata()) return -1; - return m_torrent_file->total_size() - - quantized_bytes_done(); - } - - size_type torrent::quantized_bytes_done() const - { -// INVARIANT_CHECK; - - if (!valid_metadata()) return 0; - - if (m_torrent_file->num_pieces() == 0) - return 0; - - if (is_seed()) return m_torrent_file->total_size(); - - const int last_piece = m_torrent_file->num_pieces() - 1; - - size_type total_done - = size_type(num_have()) * m_torrent_file->piece_length(); - - // if we have the last piece, we have to correct - // the amount we have, since the first calculation - // assumed all pieces were of equal size - if (m_picker->have_piece(last_piece)) - { - int corr = m_torrent_file->piece_size(last_piece) - - m_torrent_file->piece_length(); - total_done += corr; - } - return total_done; - } - - // the first value is the total number of bytes downloaded - // the second value is the number of bytes of those that haven't - // been filtered as not wanted we have downloaded - tuple torrent::bytes_done() const - { - INVARIANT_CHECK; - - if (!valid_metadata() || m_torrent_file->num_pieces() == 0) - return tuple(0,0); - - const int last_piece = m_torrent_file->num_pieces() - 1; - const int piece_size = m_torrent_file->piece_length(); - - if (is_seed()) - return make_tuple(m_torrent_file->total_size() - , m_torrent_file->total_size()); - - TORRENT_ASSERT(num_have() >= m_picker->num_have_filtered()); - size_type wanted_done = size_type(num_have() - m_picker->num_have_filtered()) - * piece_size; - TORRENT_ASSERT(wanted_done >= 0); - - size_type total_done - = size_type(num_have()) * piece_size; - TORRENT_ASSERT(num_have() < m_torrent_file->num_pieces()); - - // if we have the last piece, we have to correct - // the amount we have, since the first calculation - // assumed all pieces were of equal size - if (m_picker->have_piece(last_piece)) - { - TORRENT_ASSERT(total_done >= piece_size); - int corr = m_torrent_file->piece_size(last_piece) - - piece_size; - TORRENT_ASSERT(corr <= 0); - TORRENT_ASSERT(corr > -piece_size); - total_done += corr; - if (m_picker->piece_priority(last_piece) != 0) - { - TORRENT_ASSERT(wanted_done >= piece_size); - wanted_done += corr; - } - } - - TORRENT_ASSERT(total_done <= m_torrent_file->total_size()); - TORRENT_ASSERT(wanted_done <= m_torrent_file->total_size()); - TORRENT_ASSERT(total_done >= wanted_done); - - const std::vector& dl_queue - = m_picker->get_download_queue(); - - const int blocks_per_piece = (piece_size + m_block_size - 1) / m_block_size; - - for (std::vector::const_iterator i = - dl_queue.begin(); i != dl_queue.end(); ++i) - { - int corr = 0; - int index = i->index; - if (m_picker->have_piece(index)) continue; - TORRENT_ASSERT(i->finished <= m_picker->blocks_in_piece(index)); - -#ifdef TORRENT_DEBUG - for (std::vector::const_iterator j = boost::next(i); - j != dl_queue.end(); ++j) - { - TORRENT_ASSERT(j->index != index); - } -#endif - - for (int j = 0; j < blocks_per_piece; ++j) - { - TORRENT_ASSERT(m_picker->is_finished(piece_block(index, j)) == (i->info[j].state == piece_picker::block_info::state_finished)); - corr += (i->info[j].state == piece_picker::block_info::state_finished) * m_block_size; - TORRENT_ASSERT(corr >= 0); - TORRENT_ASSERT(index != last_piece || j < m_picker->blocks_in_last_piece() - || i->info[j].state != piece_picker::block_info::state_finished); - } - - // correction if this was the last piece - // and if we have the last block - if (i->index == last_piece - && i->info[m_picker->blocks_in_last_piece()-1].state - == piece_picker::block_info::state_finished) - { - corr -= m_block_size; - corr += m_torrent_file->piece_size(last_piece) % m_block_size; - } - total_done += corr; - if (m_picker->piece_priority(index) != 0) - wanted_done += corr; - } - - TORRENT_ASSERT(total_done <= m_torrent_file->total_size()); - TORRENT_ASSERT(wanted_done <= m_torrent_file->total_size()); - - std::map downloading_piece; - for (const_peer_iterator i = begin(); i != end(); ++i) - { - peer_connection* pc = *i; - boost::optional p - = pc->downloading_piece_progress(); - if (p) - { - if (m_picker->have_piece(p->piece_index)) - continue; - - piece_block block(p->piece_index, p->block_index); - if (m_picker->is_finished(block)) - continue; - - std::map::iterator dp - = downloading_piece.find(block); - if (dp != downloading_piece.end()) - { - if (dp->second < p->bytes_downloaded) - dp->second = p->bytes_downloaded; - } - else - { - downloading_piece[block] = p->bytes_downloaded; - } -#ifdef TORRENT_DEBUG - TORRENT_ASSERT(p->bytes_downloaded <= p->full_block_bytes); - int last_piece = m_torrent_file->num_pieces() - 1; - if (p->piece_index == last_piece - && p->block_index == m_torrent_file->piece_size(last_piece) / block_size()) - TORRENT_ASSERT(p->full_block_bytes == m_torrent_file->piece_size(last_piece) % block_size()); - else - TORRENT_ASSERT(p->full_block_bytes == block_size()); -#endif - } - } - for (std::map::iterator i = downloading_piece.begin(); - i != downloading_piece.end(); ++i) - { - total_done += i->second; - if (m_picker->piece_priority(i->first.piece_index) != 0) - wanted_done += i->second; - } - - TORRENT_ASSERT(total_done <= m_torrent_file->total_size()); - TORRENT_ASSERT(wanted_done <= m_torrent_file->total_size()); - -#ifdef TORRENT_DEBUG - - if (total_done >= m_torrent_file->total_size()) - { - // Thist happens when a piece has been downloaded completely - // but not yet verified against the hash - std::cerr << "num_have: " << num_have() << std::endl; - - std::cerr << "unfinished:" << std::endl; - - for (std::vector::const_iterator i = - dl_queue.begin(); i != dl_queue.end(); ++i) - { - std::cerr << " " << i->index << " "; - for (int j = 0; j < blocks_per_piece; ++j) - { - std::cerr << (i->info[j].state == piece_picker::block_info::state_finished ? "1" : "0"); - } - std::cerr << std::endl; - } - - std::cerr << "downloading pieces:" << std::endl; - - for (std::map::iterator i = downloading_piece.begin(); - i != downloading_piece.end(); ++i) - { - std::cerr << " " << i->first.piece_index << ":" << i->first.block_index - << " " << i->second << std::endl; - } - - } - - TORRENT_ASSERT(total_done <= m_torrent_file->total_size()); - TORRENT_ASSERT(wanted_done <= m_torrent_file->total_size()); - -#endif - - TORRENT_ASSERT(total_done >= wanted_done); - return make_tuple(total_done, wanted_done); - } - - // passed_hash_check - // 0: success, piece passed check - // -1: disk failure - // -2: piece failed check - void torrent::piece_finished(int index, int passed_hash_check) - { - session_impl::mutex_t::scoped_lock l(m_ses.m_mutex); - -#if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING) - (*m_ses.m_logger) << time_now_string() << " *** PIECE_FINISHED [ p: " - << index << " chk: " << ((passed_hash_check == 0) - ?"passed":passed_hash_check == -1 - ?"disk failed":"failed") << " ]\n"; -#endif - - TORRENT_ASSERT(valid_metadata()); - - if (passed_hash_check == 0) - { - // the following call may cause picker to become invalid - // in case we just became a seed - piece_passed(index); - } - else if (passed_hash_check == -2) - { - // piece_failed() will restore the piece - piece_failed(index); - } - else - { - TORRENT_ASSERT(passed_hash_check == -1); - m_picker->restore_piece(index); - restore_piece_state(index); - } - } - - void torrent::piece_passed(int index) - { -// INVARIANT_CHECK; - - TORRENT_ASSERT(index >= 0); - TORRENT_ASSERT(index < m_torrent_file->num_pieces()); - - if (m_ses.m_alerts.should_post()) - { - m_ses.m_alerts.post_alert(piece_finished_alert(get_handle() - , index)); - } - - bool was_finished = m_picker->num_filtered() + num_have() - == torrent_file().num_pieces(); - - std::vector downloaders; - m_picker->get_downloaders(downloaders, index); - - // increase the trust point of all peers that sent - // parts of this piece. - std::set peers; - std::copy(downloaders.begin(), downloaders.end(), std::inserter(peers, peers.begin())); - - m_picker->we_have(index); - for (peer_iterator i = m_connections.begin(); i != m_connections.end();) - { - peer_connection* p = *i; - ++i; - p->announce_piece(index); - } - - for (std::set::iterator i = peers.begin() - , end(peers.end()); i != end; ++i) - { - policy::peer* p = static_cast(*i); - if (p == 0) continue; - p->on_parole = false; - ++p->trust_points; - // TODO: make this limit user settable - if (p->trust_points > 20) p->trust_points = 20; - if (p->connection) p->connection->received_valid_data(index); - } - -#ifndef TORRENT_DISABLE_EXTENSIONS - for (extension_list_t::iterator i = m_extensions.begin() - , end(m_extensions.end()); i != end; ++i) - { -#ifndef BOOST_NO_EXCEPTIONS - try { -#endif - (*i)->on_piece_pass(index); -#ifndef BOOST_NO_EXCEPTIONS - } catch (std::exception&) {} -#endif - } -#endif - - // since this piece just passed, we might have - // become uninterested in some peers where this - // was the last piece we were interested in - for (peer_iterator i = m_connections.begin(); - i != m_connections.end();) - { - peer_connection* p = *i; - // update_interest may disconnect the peer and - // invalidate the iterator - ++i; - // if we're not interested already, no need to check - if (!p->is_interesting()) continue; - // if the peer doesn't have the piece we just got, it - // wouldn't affect our interest - if (!p->has_piece(index)) continue; - p->update_interest(); - } - - if (!was_finished && is_finished()) - { - // torrent finished - // i.e. all the pieces we're interested in have - // been downloaded. Release the files (they will open - // in read only mode if needed) - finished(); - // if we just became a seed, picker is now invalid, since it - // is deallocated by the torrent once it starts seeding - } - } - - void torrent::piece_failed(int index) - { - // if the last piece fails the peer connection will still - // think that it has received all of it until this function - // resets the download queue. So, we cannot do the - // invariant check here since it assumes: - // (total_done == m_torrent_file->total_size()) => is_seed() - INVARIANT_CHECK; - - TORRENT_ASSERT(m_storage); - TORRENT_ASSERT(m_storage->refcount() > 0); - TORRENT_ASSERT(m_picker.get()); - TORRENT_ASSERT(index >= 0); - TORRENT_ASSERT(index < m_torrent_file->num_pieces()); - - if (m_ses.m_alerts.should_post()) - m_ses.m_alerts.post_alert(hash_failed_alert(get_handle(), index)); - - // increase the total amount of failed bytes - add_failed_bytes(m_torrent_file->piece_size(index)); - - std::vector downloaders; - m_picker->get_downloaders(downloaders, index); - - // decrease the trust point of all peers that sent - // parts of this piece. - // first, build a set of all peers that participated - std::set peers; - std::copy(downloaders.begin(), downloaders.end(), std::inserter(peers, peers.begin())); - -#ifdef TORRENT_DEBUG - for (std::vector::iterator i = downloaders.begin() - , end(downloaders.end()); i != end; ++i) - { - policy::peer* p = (policy::peer*)*i; - if (p && p->connection) - { - p->connection->piece_failed = true; - } - } -#endif - -#ifndef TORRENT_DISABLE_EXTENSIONS - for (extension_list_t::iterator i = m_extensions.begin() - , end(m_extensions.end()); i != end; ++i) - { -#ifndef BOOST_NO_EXCEPTIONS - try { -#endif - (*i)->on_piece_failed(index); -#ifndef BOOST_NO_EXCEPTIONS - } catch (std::exception&) {} -#endif - } -#endif - - for (std::set::iterator i = peers.begin() - , end(peers.end()); i != end; ++i) - { - policy::peer* p = static_cast(*i); - if (p == 0) continue; - if (p->connection) p->connection->received_invalid_data(index); - - // either, we have received too many failed hashes - // or this was the only peer that sent us this piece. - // TODO: make this a changable setting - if (p->trust_points <= -7 - || peers.size() == 1) - { - // we don't trust this peer anymore - // ban it. - if (m_ses.m_alerts.should_post()) - { - peer_id pid(0); - if (p->connection) pid = p->connection->pid(); - m_ses.m_alerts.post_alert(peer_ban_alert( - get_handle(), p->ip(), pid)); - } - - // mark the peer as banned - p->banned = true; - - if (p->connection) - { -#ifdef TORRENT_LOGGING - (*m_ses.m_logger) << time_now_string() << " *** BANNING PEER [ " << p->ip() - << " ] 'too many corrupt pieces'\n"; -#endif -#if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_ERROR_LOGGING - (*p->connection->m_logger) << "*** BANNING PEER [ " << p->ip() - << " ] 'too many corrupt pieces'\n"; -#endif - p->connection->disconnect("too many corrupt pieces, banning peer"); - } - } - } - - // we have to let the piece_picker know that - // this piece failed the check as it can restore it - // and mark it as being interesting for download - // TODO: do this more intelligently! and keep track - // of how much crap (data that failed hash-check) and - // how much redundant data we have downloaded - // if some clients has sent more than one piece - // start with redownloading the pieces that the client - // that has sent the least number of pieces - m_picker->restore_piece(index); - restore_piece_state(index); - TORRENT_ASSERT(m_storage); - - TORRENT_ASSERT(m_picker->have_piece(index) == false); - -#ifdef TORRENT_DEBUG - for (std::vector::iterator i = downloaders.begin() - , end(downloaders.end()); i != end; ++i) - { - policy::peer* p = (policy::peer*)*i; - if (p && p->connection) - { - p->connection->piece_failed = false; - } - } -#endif - } - - void torrent::restore_piece_state(int index) - { - TORRENT_ASSERT(has_picker()); - for (peer_iterator i = m_connections.begin(); - i != m_connections.end(); ++i) - { - peer_connection* p = *i; - std::deque const& dq = p->download_queue(); - std::deque const& rq = p->request_queue(); - for (std::deque::const_iterator k = dq.begin() - , end(dq.end()); k != end; ++k) - { - if (k->block.piece_index != index) continue; - m_picker->mark_as_downloading(k->block, p->peer_info_struct() - , (piece_picker::piece_state_t)p->peer_speed()); - } - for (std::deque::const_iterator k = rq.begin() - , end(rq.end()); k != end; ++k) - { - if (k->piece_index != index) continue; - m_picker->mark_as_downloading(*k, p->peer_info_struct() - , (piece_picker::piece_state_t)p->peer_speed()); - } - } - } - - void torrent::abort() - { - INVARIANT_CHECK; - - if (m_abort) return; - - m_abort = true; - // if the torrent is paused, it doesn't need - // to announce with even=stopped again. - if (!is_paused()) - { - stop_announcing(); - } - -#if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_ERROR_LOGGING - for (peer_iterator i = m_connections.begin(); - i != m_connections.end(); ++i) - { - (*(*i)->m_logger) << "*** ABORTING TORRENT\n"; - } -#endif - - // disconnect all peers and close all - // files belonging to the torrents - disconnect_all(); - if (m_owning_storage.get()) - { - m_storage->async_release_files( - bind(&torrent::on_files_released, shared_from_this(), _1, _2)); - m_storage->abort_disk_io(); - } - - dequeue_torrent_check(); - - if (m_state == torrent_status::checking_files) - set_state(torrent_status::queued_for_checking); - - m_owning_storage = 0; - m_host_resolver.cancel(); - } - - void torrent::on_files_deleted(int ret, disk_io_job const& j) - { - session_impl::mutex_t::scoped_lock l(m_ses.m_mutex); - - if (ret != 0) - { - if (alerts().should_post()) - alerts().post_alert(torrent_delete_failed_alert(get_handle(), j.str)); - } - else - { - if (alerts().should_post()) - alerts().post_alert(torrent_deleted_alert(get_handle())); - } - } - - void torrent::on_files_released(int ret, disk_io_job const& j) - { -/* - session_impl::mutex_t::scoped_lock l(m_ses.m_mutex); - - if (alerts().should_post()) - { - alerts().post_alert(torrent_paused_alert(get_handle())); - } -*/ - } - - void torrent::on_save_resume_data(int ret, disk_io_job const& j) - { - session_impl::mutex_t::scoped_lock l(m_ses.m_mutex); - - if (!j.resume_data && alerts().should_post()) - { - alerts().post_alert(save_resume_data_failed_alert(get_handle(), j.str)); - return; - } - - if (j.resume_data && alerts().should_post()) - { - write_resume_data(*j.resume_data); - alerts().post_alert(save_resume_data_alert(j.resume_data - , get_handle())); - } - } - - void torrent::on_file_renamed(int ret, disk_io_job const& j) - { - session_impl::mutex_t::scoped_lock l(m_ses.m_mutex); - - { - if (ret == 0) - { - if (alerts().should_post()) - alerts().post_alert(file_renamed_alert(get_handle(), j.str, j.piece)); - m_torrent_file->rename_file(j.piece, j.str); - } - else - { - if (alerts().should_post()) - alerts().post_alert(file_rename_failed_alert(get_handle(), j.str, j.piece)); - } - } - } - - void torrent::on_torrent_paused(int ret, disk_io_job const& j) - { - session_impl::mutex_t::scoped_lock l(m_ses.m_mutex); - - if (alerts().should_post()) - alerts().post_alert(torrent_paused_alert(get_handle())); - } - - std::string torrent::tracker_login() const - { - if (m_username.empty() && m_password.empty()) return ""; - return m_username + ":" + m_password; - } - - void torrent::piece_availability(std::vector& avail) const - { - INVARIANT_CHECK; - - TORRENT_ASSERT(valid_metadata()); - if (is_seed()) - { - avail.clear(); - return; - } - - m_picker->get_availability(avail); - } - - void torrent::set_piece_priority(int index, int priority) - { -// INVARIANT_CHECK; - - TORRENT_ASSERT(valid_metadata()); - if (is_seed()) return; - - // this call is only valid on torrents with metadata - TORRENT_ASSERT(m_picker.get()); - TORRENT_ASSERT(index >= 0); - TORRENT_ASSERT(index < m_torrent_file->num_pieces()); - - bool was_finished = is_finished(); - bool filter_updated = m_picker->set_piece_priority(index, priority); - TORRENT_ASSERT(num_have() >= m_picker->num_have_filtered()); - if (filter_updated) update_peer_interest(was_finished); - } - - int torrent::piece_priority(int index) const - { -// INVARIANT_CHECK; - - TORRENT_ASSERT(valid_metadata()); - if (is_seed()) return 1; - - // this call is only valid on torrents with metadata - TORRENT_ASSERT(m_picker.get()); - TORRENT_ASSERT(index >= 0); - TORRENT_ASSERT(index < m_torrent_file->num_pieces()); - - return m_picker->piece_priority(index); - } - - void torrent::prioritize_pieces(std::vector const& pieces) - { - INVARIANT_CHECK; - - // this call is only valid on torrents with metadata - TORRENT_ASSERT(valid_metadata()); - if (is_seed()) return; - - TORRENT_ASSERT(m_picker.get()); - - int index = 0; - bool filter_updated = false; - bool was_finished = is_finished(); - for (std::vector::const_iterator i = pieces.begin() - , end(pieces.end()); i != end; ++i, ++index) - { - TORRENT_ASSERT(*i >= 0); - TORRENT_ASSERT(*i <= 7); - filter_updated |= m_picker->set_piece_priority(index, *i); - TORRENT_ASSERT(num_have() >= m_picker->num_have_filtered()); - } - if (filter_updated) update_peer_interest(was_finished); - } - - void torrent::piece_priorities(std::vector& pieces) const - { - INVARIANT_CHECK; - - // this call is only valid on torrents with metadata - TORRENT_ASSERT(valid_metadata()); - if (is_seed()) - { - pieces.clear(); - pieces.resize(m_torrent_file->num_pieces(), 1); - return; - } - - TORRENT_ASSERT(m_picker.get()); - m_picker->piece_priorities(pieces); - } - - namespace - { - void set_if_greater(int& piece_prio, int file_prio) - { - if (file_prio > piece_prio) piece_prio = file_prio; - } - } - - void torrent::prioritize_files(std::vector const& files) - { - INVARIANT_CHECK; - - // this call is only valid on torrents with metadata - if (!valid_metadata() || is_seed()) return; - - // the bitmask need to have exactly one bit for every file - // in the torrent - TORRENT_ASSERT(int(files.size()) == m_torrent_file->num_files()); - - if (m_torrent_file->num_pieces() == 0) return; - - std::copy(files.begin(), files.end(), m_file_priority.begin()); - update_piece_priorities(); - } - - void torrent::set_file_priority(int index, int prio) - { - INVARIANT_CHECK; - TORRENT_ASSERT(index < m_torrent_file->num_files()); - TORRENT_ASSERT(index >= 0); - if (m_file_priority[index] == prio) return; - m_file_priority[index] = prio; - update_piece_priorities(); - } - - int torrent::file_priority(int index) const - { - TORRENT_ASSERT(index < m_torrent_file->num_files()); - TORRENT_ASSERT(index >= 0); - return m_file_priority[index]; - } - - void torrent::file_priorities(std::vector& files) const - { - INVARIANT_CHECK; - files.resize(m_file_priority.size()); - std::copy(m_file_priority.begin(), m_file_priority.end(), files.begin()); - } - - void torrent::update_piece_priorities() - { - INVARIANT_CHECK; - - if (m_torrent_file->num_pieces() == 0) return; - - size_type position = 0; - int piece_length = m_torrent_file->piece_length(); - // initialize the piece priorities to 0, then only allow - // setting higher priorities - std::vector pieces(m_torrent_file->num_pieces(), 0); - for (int i = 0; i < int(m_file_priority.size()); ++i) - { - size_type start = position; - size_type size = m_torrent_file->files().at(i).size; - if (size == 0) continue; - position += size; - if (m_file_priority[i] == 0) continue; - - // mark all pieces of the file with this file's priority - // but only if the priority is higher than the pieces - // already set (to avoid problems with overlapping pieces) - int start_piece = int(start / piece_length); - int last_piece = int((position - 1) / piece_length); - TORRENT_ASSERT(last_piece < int(pieces.size())); - // if one piece spans several files, we might - // come here several times with the same start_piece, end_piece - std::for_each(pieces.begin() + start_piece - , pieces.begin() + last_piece + 1 - , bind(&set_if_greater, _1, m_file_priority[i])); - } - prioritize_pieces(pieces); - } - - // this is called when piece priorities have been updated - // updates the interested flag in peers - void torrent::update_peer_interest(bool was_finished) - { - for (peer_iterator i = begin(); i != end();) - { - peer_connection* p = *i; - // update_interest may disconnect the peer and - // invalidate the iterator - ++i; - p->update_interest(); - } - - // the torrent just became finished - if (is_finished() && !was_finished) - { - finished(); - } - else if (!is_finished() && was_finished) - { - // if we used to be finished, but we aren't anymore - // we may need to connect to peers again - resume_download(); - m_policy.recalculate_connect_candidates(); - } - } - - void torrent::filter_piece(int index, bool filter) - { - INVARIANT_CHECK; - - TORRENT_ASSERT(valid_metadata()); - if (is_seed()) return; - - // this call is only valid on torrents with metadata - TORRENT_ASSERT(m_picker.get()); - TORRENT_ASSERT(index >= 0); - TORRENT_ASSERT(index < m_torrent_file->num_pieces()); - - bool was_finished = is_finished(); - m_picker->set_piece_priority(index, filter ? 1 : 0); - update_peer_interest(was_finished); - } - - void torrent::filter_pieces(std::vector const& bitmask) - { - INVARIANT_CHECK; - - // this call is only valid on torrents with metadata - TORRENT_ASSERT(valid_metadata()); - if (is_seed()) return; - - TORRENT_ASSERT(m_picker.get()); - - bool was_finished = is_finished(); - int index = 0; - for (std::vector::const_iterator i = bitmask.begin() - , end(bitmask.end()); i != end; ++i, ++index) - { - if ((m_picker->piece_priority(index) == 0) == *i) continue; - if (*i) - m_picker->set_piece_priority(index, 0); - else - m_picker->set_piece_priority(index, 1); - } - update_peer_interest(was_finished); - } - - bool torrent::is_piece_filtered(int index) const - { - // this call is only valid on torrents with metadata - TORRENT_ASSERT(valid_metadata()); - if (is_seed()) return false; - - TORRENT_ASSERT(m_picker.get()); - TORRENT_ASSERT(index >= 0); - TORRENT_ASSERT(index < m_torrent_file->num_pieces()); - - return m_picker->piece_priority(index) == 0; - } - - void torrent::filtered_pieces(std::vector& bitmask) const - { - INVARIANT_CHECK; - - // this call is only valid on torrents with metadata - TORRENT_ASSERT(valid_metadata()); - if (is_seed()) - { - bitmask.clear(); - bitmask.resize(m_torrent_file->num_pieces(), false); - return; - } - - TORRENT_ASSERT(m_picker.get()); - m_picker->filtered_pieces(bitmask); - } - - void torrent::filter_files(std::vector const& bitmask) - { - INVARIANT_CHECK; - - // this call is only valid on torrents with metadata - if (!valid_metadata() || is_seed()) return; - - // the bitmask need to have exactly one bit for every file - // in the torrent - TORRENT_ASSERT((int)bitmask.size() == m_torrent_file->num_files()); - - size_type position = 0; - - if (m_torrent_file->num_pieces()) - { - int piece_length = m_torrent_file->piece_length(); - // mark all pieces as filtered, then clear the bits for files - // that should be downloaded - std::vector piece_filter(m_torrent_file->num_pieces(), true); - for (int i = 0; i < (int)bitmask.size(); ++i) - { - size_type start = position; - position += m_torrent_file->files().at(i).size; - // is the file selected for download? - if (!bitmask[i]) - { - // mark all pieces of the file as downloadable - int start_piece = int(start / piece_length); - int last_piece = int(position / piece_length); - // if one piece spans several files, we might - // come here several times with the same start_piece, end_piece - std::fill(piece_filter.begin() + start_piece, piece_filter.begin() - + last_piece + 1, false); - } - } - filter_pieces(piece_filter); - } - } - - void torrent::replace_trackers(std::vector const& urls) - { - m_trackers = urls; - if (m_currently_trying_tracker >= (int)m_trackers.size()) - m_currently_trying_tracker = (int)m_trackers.size()-1; - m_last_working_tracker = -1; - if (!m_trackers.empty()) start_announcing(); - else stop_announcing(); - } - - void torrent::choke_peer(peer_connection& c) - { - INVARIANT_CHECK; - - TORRENT_ASSERT(!c.is_choked()); - TORRENT_ASSERT(m_num_uploads > 0); - c.send_choke(); - --m_num_uploads; - } - - bool torrent::unchoke_peer(peer_connection& c) - { - INVARIANT_CHECK; - - TORRENT_ASSERT(c.is_choked()); - if (m_num_uploads >= m_max_uploads) return false; - if (!c.send_unchoke()) return false; - ++m_num_uploads; - return true; - } - - void torrent::cancel_block(piece_block block) - { - INVARIANT_CHECK; - - for (peer_iterator i = m_connections.begin() - , end(m_connections.end()); i != end; ++i) - { - (*i)->cancel_request(block); - } - } - - void torrent::remove_peer(peer_connection* p) - { -// INVARIANT_CHECK; - - TORRENT_ASSERT(p != 0); - - peer_iterator i = m_connections.find(p); - if (i == m_connections.end()) - { - TORRENT_ASSERT(false); - return; - } - - if (ready_for_connections()) - { - TORRENT_ASSERT(p->associated_torrent().lock().get() == this); - - if (p->is_seed()) - { - if (m_picker.get()) - { - m_picker->dec_refcount_all(); - } - } - else - { - if (m_picker.get()) - { - bitfield const& pieces = p->get_bitfield(); - TORRENT_ASSERT(pieces.count() < int(pieces.size())); - m_picker->dec_refcount(pieces); - } - } - } - - if (!p->is_choked()) - { - --m_num_uploads; - m_ses.m_unchoke_time_scaler = 0; - } - - if (p->peer_info_struct() && p->peer_info_struct()->optimistically_unchoked) - { - m_ses.m_optimistic_unchoke_time_scaler = 0; - } - - m_policy.connection_closed(*p); - p->set_peer_info(0); - TORRENT_ASSERT(i != m_connections.end()); - m_connections.erase(i); - - // remove from bandwidth request-queue - for (int c = 0; c < 2; ++c) - { - for (queue_t::iterator i = m_bandwidth_queue[c].begin() - , end(m_bandwidth_queue[c].end()); i != end; ++i) - { - if (i->peer != p) continue; - m_bandwidth_queue[c].erase(i); - break; - } - } - } - - void torrent::connect_to_url_seed(std::string const& url) - { - INVARIANT_CHECK; - -#if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_LOGGING - (*m_ses.m_logger) << time_now_string() << " resolving web seed: " << url << "\n"; -#endif - - std::string protocol; - std::string auth; - std::string hostname; - int port; - std::string path; - char const* error; - boost::tie(protocol, auth, hostname, port, path, error) - = parse_url_components(url); - - if (error) - { -#if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_LOGGING - (*m_ses.m_logger) << time_now_string() << " failed to parse web seed url: " << error << "\n"; -#endif - // never try it again - remove_url_seed(url); - return; - } - -#ifdef TORRENT_USE_OPENSSL - if (protocol != "http" && protocol != "https") -#else - if (protocol != "http") -#endif - { - if (m_ses.m_alerts.should_post()) - { - m_ses.m_alerts.post_alert( - url_seed_alert(get_handle(), url, "unknown protocol")); - } - // never try it again - remove_url_seed(url); - return; - } - - if (hostname.empty()) - { - if (m_ses.m_alerts.should_post()) - { - m_ses.m_alerts.post_alert( - url_seed_alert(get_handle(), url, "invalid hostname")); - } - // never try it again - remove_url_seed(url); - return; - } - - if (port == 0) - { - if (m_ses.m_alerts.should_post()) - { - m_ses.m_alerts.post_alert( - url_seed_alert(get_handle(), url, "invalid port")); - } - // never try it again - remove_url_seed(url); - return; - } - - m_resolving_web_seeds.insert(url); - proxy_settings const& ps = m_ses.web_seed_proxy(); - if (ps.type == proxy_settings::http - || ps.type == proxy_settings::http_pw) - { - // use proxy - tcp::resolver::query q(ps.hostname, to_string(ps.port).elems); - m_host_resolver.async_resolve(q, - bind(&torrent::on_proxy_name_lookup, shared_from_this(), _1, _2, url)); - } - else - { - if (m_ses.m_port_filter.access(port) & port_filter::blocked) - { - if (m_ses.m_alerts.should_post()) - { - m_ses.m_alerts.post_alert( - url_seed_alert(get_handle(), url, "port blocked by port-filter")); - } - // never try it again - remove_url_seed(url); - return; - } - - tcp::resolver::query q(hostname, to_string(port).elems); - m_host_resolver.async_resolve(q, - bind(&torrent::on_name_lookup, shared_from_this(), _1, _2, url - , tcp::endpoint())); - } - - } - - void torrent::on_proxy_name_lookup(error_code const& e, tcp::resolver::iterator host - , std::string url) - { - session_impl::mutex_t::scoped_lock l(m_ses.m_mutex); - - INVARIANT_CHECK; - -#if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_LOGGING - (*m_ses.m_logger) << time_now_string() << " completed resolve proxy hostname for: " << url << "\n"; -#endif - - if (m_abort) return; - - if (e || host == tcp::resolver::iterator()) - { - if (m_ses.m_alerts.should_post()) - { - m_ses.m_alerts.post_alert( - url_seed_alert(get_handle(), url, e.message())); - } - - // the name lookup failed for the http host. Don't try - // this host again - remove_url_seed(url); - return; - } - - if (m_ses.is_aborted()) return; - - tcp::endpoint a(host->endpoint()); - - using boost::tuples::ignore; - std::string hostname; - int port; - char const* error; - boost::tie(ignore, ignore, hostname, port, ignore, error) - = parse_url_components(url); - - if (error) - { - if (m_ses.m_alerts.should_post()) - { - m_ses.m_alerts.post_alert( - url_seed_alert(get_handle(), url, error)); - } - remove_url_seed(url); - return; - } - - if (m_ses.m_ip_filter.access(a.address()) & ip_filter::blocked) - { - if (m_ses.m_alerts.should_post()) - m_ses.m_alerts.post_alert(peer_blocked_alert(a.address())); - return; - } - - tcp::resolver::query q(hostname, to_string(port).elems); - m_host_resolver.async_resolve(q, - bind(&torrent::on_name_lookup, shared_from_this(), _1, _2, url, a)); - } - - void torrent::on_name_lookup(error_code const& e, tcp::resolver::iterator host - , std::string url, tcp::endpoint proxy) - { - session_impl::mutex_t::scoped_lock l(m_ses.m_mutex); - - INVARIANT_CHECK; - -#if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_LOGGING - (*m_ses.m_logger) << time_now_string() << " completed resolve: " << url << "\n"; -#endif - - if (m_abort) return; - - std::set::iterator i = m_resolving_web_seeds.find(url); - if (i != m_resolving_web_seeds.end()) m_resolving_web_seeds.erase(i); - - if (e || host == tcp::resolver::iterator()) - { - if (m_ses.m_alerts.should_post()) - { - std::stringstream msg; - msg << "HTTP seed hostname lookup failed: " << e.message(); - m_ses.m_alerts.post_alert( - url_seed_alert(get_handle(), url, msg.str())); - } -#if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_LOGGING || defined TORRENT_ERROR_LOGGING - (*m_ses.m_logger) << " ** HOSTNAME LOOKUP FAILED!**: " << url << "\n"; -#endif - - // the name lookup failed for the http host. Don't try - // this host again - remove_url_seed(url); - return; - } - - if (m_ses.is_aborted()) return; - - tcp::endpoint a(host->endpoint()); - - if (m_ses.m_ip_filter.access(a.address()) & ip_filter::blocked) - { - if (m_ses.m_alerts.should_post()) - m_ses.m_alerts.post_alert(peer_blocked_alert(a.address())); - return; - } - - boost::shared_ptr s(new (std::nothrow) socket_type(m_ses.m_io_service)); - if (!s) return; - - bool ret = instantiate_connection(m_ses.m_io_service, m_ses.web_seed_proxy(), *s); - (void)ret; - TORRENT_ASSERT(ret); - - if (m_ses.web_seed_proxy().type == proxy_settings::http - || m_ses.web_seed_proxy().type == proxy_settings::http_pw) - { - // the web seed connection will talk immediately to - // the proxy, without requiring CONNECT support - s->get().set_no_connect(true); - } - - boost::intrusive_ptr c(new (std::nothrow) web_peer_connection( - m_ses, shared_from_this(), s, a, url, 0)); - if (!c) return; - -#ifdef TORRENT_DEBUG - c->m_in_constructor = false; -#endif - -#ifndef TORRENT_DISABLE_EXTENSIONS - for (extension_list_t::iterator i = m_extensions.begin() - , end(m_extensions.end()); i != end; ++i) - { - boost::shared_ptr pp((*i)->new_connection(c.get())); - if (pp) c->add_extension(pp); - } -#endif - -#ifndef BOOST_NO_EXCEPTIONS - try - { -#endif - // add the newly connected peer to this torrent's peer list - m_connections.insert(boost::get_pointer(c)); - m_ses.m_connections.insert(c); - c->start(); - - m_ses.m_half_open.enqueue( - bind(&peer_connection::connect, c, _1) - , bind(&peer_connection::timed_out, c) - , seconds(settings().peer_connect_timeout)); -#ifndef BOOST_NO_EXCEPTIONS - } - catch (std::exception& e) - { -#if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_LOGGING || defined TORRENT_ERROR_LOGGING - (*m_ses.m_logger) << " ** HOSTNAME LOOKUP FAILED!**: " << e.what() << "\n"; -#endif - c->disconnect(e.what(), 1); - } -#endif - } - -#ifndef TORRENT_DISABLE_RESOLVE_COUNTRIES - namespace - { - unsigned long swap_bytes(unsigned long a) - { - return (a >> 24) | ((a & 0xff0000) >> 8) | ((a & 0xff00) << 8) | (a << 24); - } - } - - void torrent::resolve_peer_country(boost::intrusive_ptr const& p) const - { - if (m_resolving_country - || p->has_country() - || p->is_connecting() - || p->is_queued() - || p->in_handshake() - || p->remote().address().is_v6()) return; - - asio::ip::address_v4 reversed(swap_bytes(p->remote().address().to_v4().to_ulong())); - error_code ec; - tcp::resolver::query q(reversed.to_string(ec) + ".zz.countries.nerd.dk", "0"); - if (ec) - { - p->set_country("!!"); - return; - } - m_resolving_country = true; - m_host_resolver.async_resolve(q, - bind(&torrent::on_country_lookup, shared_from_this(), _1, _2, p)); - } - - namespace - { - struct country_entry - { - int code; - char const* name; - }; - } - - void torrent::on_country_lookup(error_code const& error, tcp::resolver::iterator i - , intrusive_ptr p) const - { - session_impl::mutex_t::scoped_lock l(m_ses.m_mutex); - - INVARIANT_CHECK; - - m_resolving_country = false; - - if (m_abort) return; - - // must be ordered in increasing order - static const country_entry country_map[] = - { - { 4, "AF"}, { 8, "AL"}, { 10, "AQ"}, { 12, "DZ"}, { 16, "AS"} - , { 20, "AD"}, { 24, "AO"}, { 28, "AG"}, { 31, "AZ"}, { 32, "AR"} - , { 36, "AU"}, { 40, "AT"}, { 44, "BS"}, { 48, "BH"}, { 50, "BD"} - , { 51, "AM"}, { 52, "BB"}, { 56, "BE"}, { 60, "BM"}, { 64, "BT"} - , { 68, "BO"}, { 70, "BA"}, { 72, "BW"}, { 74, "BV"}, { 76, "BR"} - , { 84, "BZ"}, { 86, "IO"}, { 90, "SB"}, { 92, "VG"}, { 96, "BN"} - , {100, "BG"}, {104, "MM"}, {108, "BI"}, {112, "BY"}, {116, "KH"} - , {120, "CM"}, {124, "CA"}, {132, "CV"}, {136, "KY"}, {140, "CF"} - , {144, "LK"}, {148, "TD"}, {152, "CL"}, {156, "CN"}, {158, "TW"} - , {162, "CX"}, {166, "CC"}, {170, "CO"}, {174, "KM"}, {175, "YT"} - , {178, "CG"}, {180, "CD"}, {184, "CK"}, {188, "CR"}, {191, "HR"} - , {192, "CU"}, {203, "CZ"}, {204, "BJ"}, {208, "DK"}, {212, "DM"} - , {214, "DO"}, {218, "EC"}, {222, "SV"}, {226, "GQ"}, {231, "ET"} - , {232, "ER"}, {233, "EE"}, {234, "FO"}, {238, "FK"}, {239, "GS"} - , {242, "FJ"}, {246, "FI"}, {248, "AX"}, {250, "FR"}, {254, "GF"} - , {258, "PF"}, {260, "TF"}, {262, "DJ"}, {266, "GA"}, {268, "GE"} - , {270, "GM"}, {275, "PS"}, {276, "DE"}, {288, "GH"}, {292, "GI"} - , {296, "KI"}, {300, "GR"}, {304, "GL"}, {308, "GD"}, {312, "GP"} - , {316, "GU"}, {320, "GT"}, {324, "GN"}, {328, "GY"}, {332, "HT"} - , {334, "HM"}, {336, "VA"}, {340, "HN"}, {344, "HK"}, {348, "HU"} - , {352, "IS"}, {356, "IN"}, {360, "ID"}, {364, "IR"}, {368, "IQ"} - , {372, "IE"}, {376, "IL"}, {380, "IT"}, {384, "CI"}, {388, "JM"} - , {392, "JP"}, {398, "KZ"}, {400, "JO"}, {404, "KE"}, {408, "KP"} - , {410, "KR"}, {414, "KW"}, {417, "KG"}, {418, "LA"}, {422, "LB"} - , {426, "LS"}, {428, "LV"}, {430, "LR"}, {434, "LY"}, {438, "LI"} - , {440, "LT"}, {442, "LU"}, {446, "MO"}, {450, "MG"}, {454, "MW"} - , {458, "MY"}, {462, "MV"}, {466, "ML"}, {470, "MT"}, {474, "MQ"} - , {478, "MR"}, {480, "MU"}, {484, "MX"}, {492, "MC"}, {496, "MN"} - , {498, "MD"}, {500, "MS"}, {504, "MA"}, {508, "MZ"}, {512, "OM"} - , {516, "NA"}, {520, "NR"}, {524, "NP"}, {528, "NL"}, {530, "AN"} - , {533, "AW"}, {540, "NC"}, {548, "VU"}, {554, "NZ"}, {558, "NI"} - , {562, "NE"}, {566, "NG"}, {570, "NU"}, {574, "NF"}, {578, "NO"} - , {580, "MP"}, {581, "UM"}, {583, "FM"}, {584, "MH"}, {585, "PW"} - , {586, "PK"}, {591, "PA"}, {598, "PG"}, {600, "PY"}, {604, "PE"} - , {608, "PH"}, {612, "PN"}, {616, "PL"}, {620, "PT"}, {624, "GW"} - , {626, "TL"}, {630, "PR"}, {634, "QA"}, {634, "QA"}, {638, "RE"} - , {642, "RO"}, {643, "RU"}, {646, "RW"}, {654, "SH"}, {659, "KN"} - , {660, "AI"}, {662, "LC"}, {666, "PM"}, {670, "VC"}, {674, "SM"} - , {678, "ST"}, {682, "SA"}, {686, "SN"}, {690, "SC"}, {694, "SL"} - , {702, "SG"}, {703, "SK"}, {704, "VN"}, {705, "SI"}, {706, "SO"} - , {710, "ZA"}, {716, "ZW"}, {724, "ES"}, {732, "EH"}, {736, "SD"} - , {740, "SR"}, {744, "SJ"}, {748, "SZ"}, {752, "SE"}, {756, "CH"} - , {760, "SY"}, {762, "TJ"}, {764, "TH"}, {768, "TG"}, {772, "TK"} - , {776, "TO"}, {780, "TT"}, {784, "AE"}, {788, "TN"}, {792, "TR"} - , {795, "TM"}, {796, "TC"}, {798, "TV"}, {800, "UG"}, {804, "UA"} - , {807, "MK"}, {818, "EG"}, {826, "GB"}, {834, "TZ"}, {840, "US"} - , {850, "VI"}, {854, "BF"}, {858, "UY"}, {860, "UZ"}, {862, "VE"} - , {876, "WF"}, {882, "WS"}, {887, "YE"}, {891, "CS"}, {894, "ZM"} - }; - - if (error || i == tcp::resolver::iterator()) - { - // this is used to indicate that we shouldn't - // try to resolve it again - p->set_country("--"); - return; - } - - while (i != tcp::resolver::iterator() - && !i->endpoint().address().is_v4()) ++i; - if (i != tcp::resolver::iterator()) - { - // country is an ISO 3166 country code - int country = i->endpoint().address().to_v4().to_ulong() & 0xffff; - - // look up the country code in the map - const int size = sizeof(country_map)/sizeof(country_map[0]); - country_entry tmp = {country, ""}; - country_entry const* i = - std::lower_bound(country_map, country_map + size, tmp - , bind(&country_entry::code, _1) < bind(&country_entry::code, _2)); - if (i == country_map + size - || i->code != country) - { - // unknown country! - p->set_country("!!"); -#if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_LOGGING || defined TORRENT_ERROR_LOGGING - (*m_ses.m_logger) << "IP " << p->remote().address() << " was mapped to unknown country: " << country << "\n"; -#endif - return; - } - - p->set_country(i->name); - } - } -#endif - - void torrent::read_resume_data(lazy_entry const& rd) - { - m_total_uploaded = rd.dict_find_int_value("total_uploaded"); - m_total_downloaded = rd.dict_find_int_value("total_downloaded"); - m_active_time = seconds(rd.dict_find_int_value("active_time")); - m_seeding_time = seconds(rd.dict_find_int_value("seeding_time")); - m_complete = rd.dict_find_int_value("num_seeds", -1); - m_incomplete = rd.dict_find_int_value("num_downloaders", -1); - set_upload_limit(rd.dict_find_int_value("upload_rate_limit", -1)); - set_download_limit(rd.dict_find_int_value("download_rate_limit", -1)); - set_max_connections(rd.dict_find_int_value("max_connections", -1)); - set_max_uploads(rd.dict_find_int_value("max_uploads", -1)); - - lazy_entry const* file_priority = rd.dict_find_list("file_priority"); - if (file_priority && file_priority->list_size() - == m_torrent_file->num_files()) - { - for (int i = 0; i < file_priority->list_size(); ++i) - m_file_priority[i] = file_priority->list_int_value_at(i, 1); - update_piece_priorities(); - } - lazy_entry const* piece_priority = rd.dict_find_string("piece_priority"); - if (piece_priority && piece_priority->string_length() - == m_torrent_file->num_pieces()) - { - char const* p = piece_priority->string_ptr(); - for (int i = 0; i < piece_priority->string_length(); ++i) - m_picker->set_piece_priority(i, p[i]); - } - - int auto_managed_ = rd.dict_find_int_value("auto_managed", -1); - if (auto_managed_ != -1) m_auto_managed = auto_managed_; - - int sequential_ = rd.dict_find_int_value("sequential_download", -1); - if (sequential_ != -1) set_sequential_download(sequential_); - - int paused_ = rd.dict_find_int_value("paused", -1); - if (paused_ != -1) m_paused = paused_; - - lazy_entry const* trackers = rd.dict_find_list("trackers"); - if (trackers) - { - int tier = 0; - for (int i = 0; i < trackers->list_size(); ++i) - { - lazy_entry const* tier_list = trackers->list_at(i); - if (tier_list == 0 || tier_list->type() != lazy_entry::list_t) - continue; - for (int j = 0; j < tier_list->list_size(); ++j) - { - announce_entry e(tier_list->list_string_value_at(j)); - if (std::find_if(m_trackers.begin(), m_trackers.end() - , boost::bind(&announce_entry::url, _1) == e.url) != m_trackers.end()) - continue; - e.tier = tier; - m_trackers.push_back(e); - } - ++tier; - } - std::sort(m_trackers.begin(), m_trackers.end(), boost::bind(&announce_entry::tier, _1) - < boost::bind(&announce_entry::tier, _2)); - } - - lazy_entry const* mapped_files = rd.dict_find_list("mapped_files"); - if (mapped_files && mapped_files->list_size() == m_torrent_file->num_files()) - { - for (int i = 0; i < m_torrent_file->num_files(); ++i) - { - std::string new_filename = mapped_files->list_string_value_at(i); - if (new_filename.empty()) continue; - rename_file(i, new_filename); - } - } - - lazy_entry const* url_list = rd.dict_find_list("url-list"); - if (url_list) - { - for (int i = 0; i < url_list->list_size(); ++i) - { - std::string url = url_list->list_string_value_at(i); - if (url.empty()) continue; - m_web_seeds.insert(url); - } - } - } - - void torrent::write_resume_data(entry& ret) const - { - ret["file-format"] = "libtorrent resume file"; - ret["file-version"] = 1; - - ret["total_uploaded"] = m_total_uploaded; - ret["total_downloaded"] = m_total_downloaded; - - ret["active_time"] = total_seconds(m_active_time); - ret["seeding_time"] = total_seconds(m_seeding_time); - - int seeds = 0; - int downloaders = 0; - if (m_complete >= 0) seeds = m_complete; - else seeds = m_policy.num_seeds(); - if (m_incomplete >= 0) downloaders = m_incomplete; - else downloaders = m_policy.num_peers() - m_policy.num_seeds(); - - ret["num_seeds"] = seeds; - ret["num_downloaders"] = downloaders; - - ret["sequential_download"] = m_sequential_download; - - const sha1_hash& info_hash = torrent_file().info_hash(); - ret["info-hash"] = std::string((char*)info_hash.begin(), (char*)info_hash.end()); - - // blocks per piece - int num_blocks_per_piece = - static_cast(torrent_file().piece_length()) / block_size(); - ret["blocks per piece"] = num_blocks_per_piece; - - // if this torrent is a seed, we won't have a piece picker - // and there will be no half-finished pieces. - if (!is_seed()) - { - const std::vector& q - = m_picker->get_download_queue(); - - // unfinished pieces - ret["unfinished"] = entry::list_type(); - entry::list_type& up = ret["unfinished"].list(); - - // info for each unfinished piece - for (std::vector::const_iterator i - = q.begin(); i != q.end(); ++i) - { - if (i->finished == 0) continue; - - entry piece_struct(entry::dictionary_t); - - // the unfinished piece's index - piece_struct["piece"] = i->index; - - std::string bitmask; - const int num_bitmask_bytes - = (std::max)(num_blocks_per_piece / 8, 1); - - for (int j = 0; j < num_bitmask_bytes; ++j) - { - unsigned char v = 0; - int bits = (std::min)(num_blocks_per_piece - j*8, 8); - for (int k = 0; k < bits; ++k) - v |= (i->info[j*8+k].state == piece_picker::block_info::state_finished) - ? (1 << k) : 0; - bitmask.insert(bitmask.end(), v); - TORRENT_ASSERT(bits == 8 || j == num_bitmask_bytes - 1); - } - piece_struct["bitmask"] = bitmask; - // push the struct onto the unfinished-piece list - up.push_back(piece_struct); - } - } - - // save trackers - if (!m_trackers.empty()) - { - entry::list_type& tr_list = ret["trackers"].list(); - tr_list.push_back(entry::list_type()); - int tier = 0; - for (std::vector::const_iterator i = m_trackers.begin() - , end(m_trackers.end()); i != end; ++i) - { - if (i->tier == tier) - { - tr_list.back().list().push_back(i->url); - } - else - { - tr_list.push_back(entry::list_t); - tr_list.back().list().push_back(i->url); - tier = i->tier; - } - } - } - - // save web seeds - if (!m_web_seeds.empty()) - { - entry::list_type& url_list = ret["url-list"].list(); - for (std::set::const_iterator i = m_web_seeds.begin() - , end(m_web_seeds.end()); i != end; ++i) - { - url_list.push_back(*i); - } - } - - // write have bitmask - entry::string_type& pieces = ret["pieces"].string(); - pieces.resize(m_torrent_file->num_pieces()); - if (is_seed()) - { - std::memset(&pieces[0], 1, pieces.size()); - } - else - { - for (int i = 0, end(pieces.size()); i < end; ++i) - pieces[i] = m_picker->have_piece(i) ? 1 : 0; - } - - // write local peers - - entry::list_type& peer_list = ret["peers"].list(); - entry::list_type& banned_peer_list = ret["banned_peers"].list(); - - int max_failcount = m_ses.m_settings.max_failcount; - - for (policy::const_iterator i = m_policy.begin_peer() - , end(m_policy.end_peer()); i != end; ++i) - { - error_code ec; - if (i->second.banned) - { - entry peer(entry::dictionary_t); - peer["ip"] = i->second.addr.to_string(ec); - if (ec) continue; - peer["port"] = i->second.port; - banned_peer_list.push_back(peer); - continue; - } - // we cannot save remote connection - // since we don't know their listen port - // unless they gave us their listen port - // through the extension handshake - // so, if the peer is not connectable (i.e. we - // don't know its listen port) or if it has - // been banned, don't save it. - if (i->second.type == policy::peer::not_connectable) continue; - - // don't save peers that doesn't work - if (i->second.failcount >= max_failcount) continue; - - entry peer(entry::dictionary_t); - peer["ip"] = i->second.addr.to_string(ec); - if (ec) continue; - peer["port"] = i->second.port; - peer_list.push_back(peer); - } - - ret["upload_rate_limit"] = upload_limit(); - ret["download_rate_limit"] = download_limit(); - ret["max_connections"] = max_connections(); - ret["max_uploads"] = max_uploads(); - ret["paused"] = m_paused; - ret["auto_managed"] = m_auto_managed; - - // write piece priorities - entry::string_type& piece_priority = ret["piece_priority"].string(); - piece_priority.resize(m_torrent_file->num_pieces()); - if (is_seed()) - { - std::memset(&piece_priority[0], 1, pieces.size()); - } - else - { - for (int i = 0, end(piece_priority.size()); i < end; ++i) - piece_priority[i] = m_picker->piece_priority(i); - } - - // write file priorities - entry::list_type& file_priority = ret["file_priority"].list(); - file_priority.clear(); - for (int i = 0, end(m_file_priority.size()); i < end; ++i) - file_priority.push_back(m_file_priority[i]); - - } - - void torrent::get_full_peer_list(std::vector& v) const - { - v.clear(); - v.reserve(m_policy.num_peers()); - for (policy::const_iterator i = m_policy.begin_peer(); - i != m_policy.end_peer(); ++i) - { - peer_list_entry e; - e.ip = i->second.ip(); - e.flags = i->second.banned ? peer_list_entry::banned : 0; - e.failcount = i->second.failcount; - e.source = i->second.source; - v.push_back(e); - } - } - - void torrent::get_peer_info(std::vector& v) - { - v.clear(); - for (peer_iterator i = begin(); - i != end(); ++i) - { - peer_connection* peer = *i; - - // incoming peers that haven't finished the handshake should - // not be included in this list - if (peer->associated_torrent().expired()) continue; - - v.push_back(peer_info()); - peer_info& p = v.back(); - - peer->get_peer_info(p); -#ifndef TORRENT_DISABLE_RESOLVE_COUNTRIES - if (resolving_countries()) - resolve_peer_country(intrusive_ptr(peer)); -#endif - } - } - - void torrent::get_download_queue(std::vector& queue) - { - queue.clear(); - if (!valid_metadata() || is_seed()) return; - piece_picker const& p = picker(); - std::vector const& q - = p.get_download_queue(); - - for (std::vector::const_iterator i - = q.begin(); i != q.end(); ++i) - { - partial_piece_info pi; - pi.piece_state = (partial_piece_info::state_t)i->state; - pi.blocks_in_piece = p.blocks_in_piece(i->index); - pi.finished = (int)i->finished; - pi.writing = (int)i->writing; - pi.requested = (int)i->requested; - int piece_size = int(torrent_file().piece_size(i->index)); - int num_blocks = (std::min)(pi.blocks_in_piece, int(partial_piece_info::max_blocks_per_piece)); - for (int j = 0; j < num_blocks; ++j) - { - block_info& bi = pi.blocks[j]; - bi.state = i->info[j].state; - bi.block_size = j < pi.blocks_in_piece - 1 ? m_block_size - : piece_size - (j * m_block_size); - bool complete = bi.state == block_info::writing - || bi.state == block_info::finished; - if (i->info[j].peer == 0) - { - bi.peer = tcp::endpoint(); - bi.bytes_progress = complete ? bi.block_size : 0; - } - else - { - policy::peer* p = static_cast(i->info[j].peer); - if (p->connection) - { - bi.peer = p->connection->remote(); - if (bi.state == block_info::requested) - { - boost::optional pbp - = p->connection->downloading_piece_progress(); - if (pbp && pbp->piece_index == i->index && pbp->block_index == j) - { - bi.bytes_progress = pbp->bytes_downloaded; - TORRENT_ASSERT(bi.bytes_progress <= bi.block_size); - } - else - { - bi.bytes_progress = 0; - } - } - else - { - bi.bytes_progress = complete ? bi.block_size : 0; - } - } - else - { - bi.peer = p->ip(); - bi.bytes_progress = complete ? bi.block_size : 0; - } - } - - pi.blocks[j].num_peers = i->info[j].num_peers; - } - pi.piece_index = i->index; - queue.push_back(pi); - } - - } - - bool torrent::connect_to_peer(policy::peer* peerinfo) - { - INVARIANT_CHECK; - - TORRENT_ASSERT(peerinfo); - TORRENT_ASSERT(peerinfo->connection == 0); - - peerinfo->connected = time_now(); -#ifdef TORRENT_DEBUG - // this asserts that we don't have duplicates in the policy's peer list - peer_iterator i_ = std::find_if(m_connections.begin(), m_connections.end() - , bind(&peer_connection::remote, _1) == peerinfo->ip()); - TORRENT_ASSERT(i_ == m_connections.end() - || dynamic_cast(*i_) == 0); -#endif - - TORRENT_ASSERT(want_more_peers()); - TORRENT_ASSERT(m_ses.num_connections() < m_ses.max_connections()); - - tcp::endpoint a(peerinfo->ip()); - TORRENT_ASSERT((m_ses.m_ip_filter.access(peerinfo->addr) & ip_filter::blocked) == 0); - - boost::shared_ptr s(new socket_type(m_ses.m_io_service)); - - bool ret = instantiate_connection(m_ses.m_io_service, m_ses.peer_proxy(), *s); - (void)ret; - TORRENT_ASSERT(ret); - - boost::intrusive_ptr c(new bt_peer_connection( - m_ses, shared_from_this(), s, a, peerinfo)); - -#ifdef TORRENT_DEBUG - c->m_in_constructor = false; -#endif - - c->add_stat(peerinfo->prev_amount_download, peerinfo->prev_amount_upload); - peerinfo->prev_amount_download = 0; - peerinfo->prev_amount_upload = 0; - -#ifndef TORRENT_DISABLE_EXTENSIONS - for (extension_list_t::iterator i = m_extensions.begin() - , end(m_extensions.end()); i != end; ++i) - { -#ifndef BOOST_NO_EXCEPTIONS - try { -#endif - boost::shared_ptr pp((*i)->new_connection(c.get())); - if (pp) c->add_extension(pp); -#ifndef BOOST_NO_EXCEPTIONS - } catch (std::exception&) {} -#endif - } -#endif - - // add the newly connected peer to this torrent's peer list - m_connections.insert(boost::get_pointer(c)); - m_ses.m_connections.insert(c); - peerinfo->connection = c.get(); - c->start(); - - int timeout = settings().peer_connect_timeout; - if (peerinfo) timeout += 3 * peerinfo->failcount; - -#ifndef BOOST_NO_EXCEPTIONS - try - { -#endif - m_ses.m_half_open.enqueue( - bind(&peer_connection::connect, c, _1) - , bind(&peer_connection::timed_out, c) - , seconds(timeout)); -#ifndef BOOST_NO_EXCEPTIONS - } - catch (std::exception& e) - { - std::set::iterator i - = m_connections.find(boost::get_pointer(c)); - if (i != m_connections.end()) m_connections.erase(i); - c->disconnect(e.what()); - return false; - } -#endif - - return peerinfo->connection; - } - - bool torrent::set_metadata(lazy_entry const& metadata, std::string& error) - { - INVARIANT_CHECK; - - TORRENT_ASSERT(!m_torrent_file->is_valid()); - if (!m_torrent_file->parse_info_section(metadata, error)) - { - // parse failed - return false; - } - - if (m_ses.m_alerts.should_post()) - { - m_ses.m_alerts.post_alert(metadata_received_alert( - get_handle())); - } - - init(); - - return true; - } - - bool torrent::attach_peer(peer_connection* p) - { -// INVARIANT_CHECK; - - TORRENT_ASSERT(p != 0); - TORRENT_ASSERT(!p->is_local()); - - m_has_incoming = true; - - if ((m_state == torrent_status::queued_for_checking - || m_state == torrent_status::checking_files - || m_state == torrent_status::checking_resume_data) - && valid_metadata()) - { - p->disconnect("torrent is not ready to accept peers"); - return false; - } - - if (m_ses.m_connections.find(p) == m_ses.m_connections.end()) - { - p->disconnect("peer is not properly constructed"); - return false; - } - - if (m_ses.is_aborted()) - { - p->disconnect("session is closing"); - return false; - } - - if (int(m_connections.size()) >= m_max_connections) - { - p->disconnect("reached connection limit"); - return false; - } - -#ifndef BOOST_NO_EXCEPTIONS - try - { -#endif -#ifndef TORRENT_DISABLE_EXTENSIONS - for (extension_list_t::iterator i = m_extensions.begin() - , end(m_extensions.end()); i != end; ++i) - { - boost::shared_ptr pp((*i)->new_connection(p)); - if (pp) p->add_extension(pp); - } -#endif - if (!m_policy.new_connection(*p)) - return false; -#ifndef BOOST_NO_EXCEPTIONS - } - catch (std::exception& e) - { -#if defined TORRENT_LOGGING - (*m_ses.m_logger) << time_now_string() << " CLOSING CONNECTION " - << p->remote() << " policy::new_connection threw: " << e.what() << "\n"; -#endif - p->disconnect(e.what()); - return false; - } -#endif - TORRENT_ASSERT(m_connections.find(p) == m_connections.end()); - peer_iterator ci = m_connections.insert(p).first; -#ifdef TORRENT_DEBUG - error_code ec; - TORRENT_ASSERT(p->remote() == p->get_socket()->remote_endpoint(ec) || ec); -#endif - -#if defined TORRENT_DEBUG && !defined TORRENT_DISABLE_INVARIANT_CHECKS - m_policy.check_invariant(); -#endif - return true; - } - - bool torrent::want_more_peers() const - { - return int(m_connections.size()) < m_max_connections - && !is_paused() - && m_state != torrent_status::checking_files - && m_state != torrent_status::checking_resume_data - && (m_state != torrent_status::queued_for_checking - || !valid_metadata()) - && m_policy.num_connect_candidates() > 0 - && !m_abort; - } - - void torrent::disconnect_all() - { - session_impl::mutex_t::scoped_lock l(m_ses.m_mutex); - -// doesn't work with the m_paused -> m_num_peers == 0 condition -// INVARIANT_CHECK; - - while (!m_connections.empty()) - { - peer_connection* p = *m_connections.begin(); - TORRENT_ASSERT(p->associated_torrent().lock().get() == this); - -#if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_ERROR_LOGGING - if (m_abort) - (*p->m_logger) << "*** CLOSING CONNECTION 'aborting'\n"; - else - (*p->m_logger) << "*** CLOSING CONNECTION 'pausing'\n"; -#endif -#ifdef TORRENT_DEBUG - std::size_t size = m_connections.size(); -#endif - if (p->is_disconnecting()) - m_connections.erase(m_connections.begin()); - else - p->disconnect(m_abort?"stopping torrent":"pausing torrent"); - TORRENT_ASSERT(m_connections.size() <= size); - } - } - - namespace - { - // this returns true if lhs is a better disconnect candidate than rhs - bool compare_disconnect_peer(peer_connection const* lhs, peer_connection const* rhs) - { - // prefer to disconnect peers we're not interested in - if (lhs->is_interesting() != rhs->is_interesting()) - return rhs->is_interesting(); - - // prefer to disconnect peers that are not seeds - if (lhs->is_seed() != rhs->is_seed()) - return rhs->is_seed(); - - // prefer to disconnect peers that are on parole - if (lhs->on_parole() != rhs->on_parole()) - return lhs->on_parole(); - - // prefer to disconnect peers that send data at a lower rate - size_type lhs_transferred = lhs->statistics().total_payload_download(); - size_type rhs_transferred = rhs->statistics().total_payload_download(); - - if (lhs_transferred != rhs_transferred - && lhs_transferred > 0 - && rhs_transferred > 0) - { - ptime now = time_now(); - size_type lhs_time_connected = total_seconds(now - lhs->connected_time()); - size_type rhs_time_connected = total_seconds(now - rhs->connected_time()); - - double lhs_rate = double(lhs_transferred) / (lhs_time_connected + 1); - double rhs_rate = double(rhs_transferred) / (rhs_time_connected + 1); - - return lhs_rate < rhs_rate; - } - - // prefer to disconnect peers that chokes us - if (lhs->is_choked() != rhs->is_choked()) - return lhs->is_choked(); - - return lhs->last_received() < rhs->last_received(); - } - } - - int torrent::disconnect_peers(int num) - { - INVARIANT_CHECK; - - int ret = 0; - // buils a list of all connected peers and sort it by 'disconnectability'. - std::vector peers(m_connections.size()); - std::copy(m_connections.begin(), m_connections.end(), peers.begin()); - std::sort(peers.begin(), peers.end(), boost::bind(&compare_disconnect_peer, _1, _2)); - - // never disconnect peers that connected less than 90 seconds ago - ptime cut_off = time_now() - seconds(90); - - for (std::vector::iterator i = peers.begin() - , end(peers.end()); i != end && ret < num; ++i) - { - peer_connection* p = *i; - if (p->connected_time() > cut_off) continue; - ++ret; - p->disconnect("optimistic disconnect"); - } - return ret; - } - - int torrent::bandwidth_throttle(int channel) const - { - return m_bandwidth_limit[channel].throttle(); - } - - int torrent::bandwidth_queue_size(int channel) const - { - return (int)m_bandwidth_queue[channel].size(); - } - - void torrent::request_bandwidth(int channel - , boost::intrusive_ptr const& p - , int max_block_size, int priority) - { - TORRENT_ASSERT(max_block_size > 0); - TORRENT_ASSERT(m_bandwidth_limit[channel].throttle() > 0); - TORRENT_ASSERT(p->max_assignable_bandwidth(channel) > 0); - TORRENT_ASSERT(p->m_channel_state[channel] == peer_info::bw_torrent); - int block_size = (std::min)(m_bandwidth_limit[channel].throttle() / 10 - , max_block_size); - if (block_size <= 0) block_size = 1; - - if (m_bandwidth_limit[channel].max_assignable() > 0) - { - perform_bandwidth_request(channel, p, block_size, priority); - } - else - { - // skip forward in the queue until we find a prioritized peer - // or hit the front of it. - queue_t::reverse_iterator i = m_bandwidth_queue[channel].rbegin(); - while (i != m_bandwidth_queue[channel].rend() && priority > i->priority) - { - ++i->priority; - ++i; - } - m_bandwidth_queue[channel].insert(i.base(), bw_queue_entry( - p, block_size, priority)); - } - } - - void torrent::expire_bandwidth(int channel, int amount) - { - session_impl::mutex_t::scoped_lock l(m_ses.m_mutex); - - INVARIANT_CHECK; - - TORRENT_ASSERT(amount > 0); - m_bandwidth_limit[channel].expire(amount); - queue_t tmp; - while (!m_bandwidth_queue[channel].empty()) - { - bw_queue_entry qe = m_bandwidth_queue[channel].front(); - if (m_bandwidth_limit[channel].max_assignable() == 0) - break; - m_bandwidth_queue[channel].pop_front(); - if (qe.peer->max_assignable_bandwidth(channel) <= 0) - { - TORRENT_ASSERT(m_ses.m_bandwidth_manager[channel]->is_in_history(qe.peer.get())); - if (!qe.peer->is_disconnecting()) tmp.push_back(qe); - continue; - } - perform_bandwidth_request(channel, qe.peer - , qe.max_block_size, qe.priority); - } - m_bandwidth_queue[channel].insert(m_bandwidth_queue[channel].begin(), tmp.begin(), tmp.end()); - } - - void torrent::perform_bandwidth_request(int channel - , boost::intrusive_ptr const& p - , int block_size - , int priority) - { - TORRENT_ASSERT(p->m_channel_state[channel] == peer_info::bw_torrent); - p->m_channel_state[channel] = peer_info::bw_global; - m_ses.m_bandwidth_manager[channel]->request_bandwidth(p - , block_size, priority); - m_bandwidth_limit[channel].assign(block_size); - } - - void torrent::assign_bandwidth(int channel, int amount, int blk) - { - session_impl::mutex_t::scoped_lock l(m_ses.m_mutex); - - TORRENT_ASSERT(amount > 0); - TORRENT_ASSERT(amount <= blk); - if (amount < blk) - expire_bandwidth(channel, blk - amount); - } - - // called when torrent is finished (all interesting - // pieces have been downloaded) - void torrent::finished() - { - INVARIANT_CHECK; - - TORRENT_ASSERT(is_finished()); - TORRENT_ASSERT(m_state != torrent_status::finished && m_state != torrent_status::seeding); - - if (alerts().should_post()) - { - alerts().post_alert(torrent_finished_alert( - get_handle())); - } - - set_state(torrent_status::finished); - set_queue_position(-1); - - // we have to call completed() before we start - // disconnecting peers, since there's an assert - // to make sure we're cleared the piece picker - if (is_seed()) completed(); - - // disconnect all seeds - // TODO: should disconnect all peers that have the pieces we have - // not just seeds - std::vector seeds; - for (peer_iterator i = m_connections.begin(); - i != m_connections.end(); ++i) - { - peer_connection* p = *i; - TORRENT_ASSERT(p->associated_torrent().lock().get() == this); - if (p->upload_only()) - { -#if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_ERROR_LOGGING - (*p->m_logger) << "*** SEED, CLOSING CONNECTION\n"; -#endif - seeds.push_back(p); - } - } - std::for_each(seeds.begin(), seeds.end() - , bind(&peer_connection::disconnect, _1, "torrent finished, disconnecting seed", 0)); - - TORRENT_ASSERT(m_storage); - // we need to keep the object alive during this operation - m_storage->async_release_files( - bind(&torrent::on_files_released, shared_from_this(), _1, _2)); - } - - // this is called when we were finished, but some files were - // marked for downloading, and we are no longer finished - void torrent::resume_download() - { - INVARIANT_CHECK; - - TORRENT_ASSERT(!is_finished()); - set_state(torrent_status::downloading); - set_queue_position((std::numeric_limits::max)()); - } - - // called when torrent is complete (all pieces downloaded) - void torrent::completed() - { - m_picker.reset(); - - set_state(torrent_status::seeding); - if (!m_complete_sent && m_announcing) announce_with_tracker(); - } - - // this will move the tracker with the given index - // to a prioritized position in the list (move it towards - // the begining) and return the new index to the tracker. - int torrent::prioritize_tracker(int index) - { - INVARIANT_CHECK; - - TORRENT_ASSERT(index >= 0); - if (index >= (int)m_trackers.size()) return (int)m_trackers.size()-1; - - while (index > 0 && m_trackers[index].tier == m_trackers[index-1].tier) - { - std::swap(m_trackers[index].url, m_trackers[index-1].url); - --index; - } - return index; - } - - void torrent::try_next_tracker(tracker_request const& req) - { - INVARIANT_CHECK; - - ++m_currently_trying_tracker; - - if ((unsigned)m_currently_trying_tracker < m_trackers.size()) - { - announce_with_tracker(req.event); - return; - } - - int delay = tracker_retry_delay_min - + (std::min)(int(m_failed_trackers), int(tracker_failed_max)) - * (tracker_retry_delay_max - tracker_retry_delay_min) - / tracker_failed_max; - - ++m_failed_trackers; - // if we've looped the tracker list, wait a bit before retrying - m_currently_trying_tracker = 0; - - // if we're stopping, just give up. Don't bother retrying - if (req.event == tracker_request::stopped) - return; - - restart_tracker_timer(time_now() + seconds(delay)); - -#ifndef TORRENT_DISABLE_DHT - if (m_abort) return; - - // only start the announce if we want to announce with the dht - ptime now = time_now(); - if (should_announce_dht() && now - m_last_dht_announce > minutes(14)) - { - // force the DHT to reannounce - m_last_dht_announce = now; - boost::weak_ptr self(shared_from_this()); - m_ses.m_dht->announce(m_torrent_file->info_hash() - , m_ses.m_listen_sockets.front().external_port - , bind(&torrent::on_dht_announce_response_disp, self, _1)); - } -#endif - - } - - void torrent::files_checked() - { - session_impl::mutex_t::scoped_lock l(m_ses.m_mutex); - - TORRENT_ASSERT(m_torrent_file->is_valid()); - - if (m_abort) return; - - // we might be finished already, in which case we should - // not switch to downloading mode. - if (m_state != torrent_status::finished) - set_state(torrent_status::downloading); - - INVARIANT_CHECK; - - if (m_ses.m_alerts.should_post()) - { - m_ses.m_alerts.post_alert(torrent_checked_alert( - get_handle())); - } - - if (!is_seed()) - { - // if we just finished checking and we're not a seed, we are - // likely to be unpaused - if (m_ses.m_auto_manage_time_scaler > 1) - m_ses.m_auto_manage_time_scaler = 1; - - if (is_finished() && m_state != torrent_status::finished) finished(); - } - else - { - m_complete_sent = true; - if (m_state != torrent_status::finished) finished(); - } - -#ifndef TORRENT_DISABLE_EXTENSIONS - for (extension_list_t::iterator i = m_extensions.begin() - , end(m_extensions.end()); i != end; ++i) - { -#ifndef BOOST_NO_EXCEPTIONS - try { -#endif - (*i)->on_files_checked(); -#ifndef BOOST_NO_EXCEPTIONS - } catch (std::exception&) {} -#endif - } -#endif - - if (!m_connections_initialized) - { - m_connections_initialized = true; - // all peer connections have to initialize themselves now that the metadata - // is available - for (torrent::peer_iterator i = m_connections.begin(); - i != m_connections.end();) - { - peer_connection* pc = *i; - ++i; - if (pc->is_disconnecting()) continue; - pc->on_metadata_impl(); - if (pc->is_disconnecting()) continue; - pc->init(); - } - } - - m_files_checked = true; - - start_announcing(); - } - - alert_manager& torrent::alerts() const - { - return m_ses.m_alerts; - } - - fs::path torrent::save_path() const - { - return m_save_path; - } - - bool torrent::rename_file(int index, std::string const& name) - { - INVARIANT_CHECK; - - TORRENT_ASSERT(index >= 0); - TORRENT_ASSERT(index < m_torrent_file->num_files()); - - if (!m_owning_storage.get()) return false; - - m_owning_storage->async_rename_file(index, name - , bind(&torrent::on_file_renamed, shared_from_this(), _1, _2)); - return true; - } - - void torrent::move_storage(fs::path const& save_path) - { - INVARIANT_CHECK; - - if (m_owning_storage.get()) - { - m_owning_storage->async_move_storage(save_path - , bind(&torrent::on_storage_moved, shared_from_this(), _1, _2)); - } - else - { - m_save_path = save_path; - } - } - - void torrent::on_storage_moved(int ret, disk_io_job const& j) - { - session_impl::mutex_t::scoped_lock l(m_ses.m_mutex); - - if (alerts().should_post()) - { - alerts().post_alert(storage_moved_alert(get_handle(), j.str)); - } - m_save_path = j.str; - } - - piece_manager& torrent::filesystem() - { - TORRENT_ASSERT(m_owning_storage.get()); - TORRENT_ASSERT(m_storage); - return *m_storage; - } - - - torrent_handle torrent::get_handle() - { - return torrent_handle(shared_from_this()); - } - - session_settings const& torrent::settings() const - { - return m_ses.settings(); - } - -#ifdef TORRENT_DEBUG - void torrent::check_invariant() const - { - session_impl::mutex_t::scoped_lock l(m_ses.m_mutex); - - if (is_paused()) TORRENT_ASSERT(num_peers() == 0); - - if (!should_check_files()) - TORRENT_ASSERT(m_state != torrent_status::checking_files); - else - TORRENT_ASSERT(m_queued_for_checking); - - if (!m_ses.m_queued_for_checking.empty()) - { - // if there are torrents waiting to be checked - // assert that there's a torrent that is being - // processed right now - int found = 0; - int found_active = 0; - for (aux::session_impl::torrent_map::iterator i = m_ses.m_torrents.begin() - , end(m_ses.m_torrents.end()); i != end; ++i) - if (i->second->m_state == torrent_status::checking_files) - { - ++found; - if (i->second->should_check_files()) ++found_active; - } - // the case of 2 is in the special case where one switches over from - // checking to complete - TORRENT_ASSERT(found_active >= 1); - TORRENT_ASSERT(found_active <= 2); - TORRENT_ASSERT(found >= 1); - } - - TORRENT_ASSERT(m_resume_entry.type() == lazy_entry::dict_t - || m_resume_entry.type() == lazy_entry::none_t); - - TORRENT_ASSERT(m_bandwidth_queue[0].size() <= m_connections.size()); - TORRENT_ASSERT(m_bandwidth_queue[1].size() <= m_connections.size()); - - for (int c = 0; c < 2; ++c) - { - queue_t::const_iterator j = m_bandwidth_queue[c].begin(); - if (j == m_bandwidth_queue[c].end()) continue; - ++j; - for (queue_t::const_iterator i = m_bandwidth_queue[c].begin() - , end(m_bandwidth_queue[c].end()); i != end && j != end; ++i, ++j) - TORRENT_ASSERT(i->priority >= j->priority); - } - - int num_uploads = 0; - std::map num_requests; - for (const_peer_iterator i = begin(); i != end(); ++i) - { -#ifdef TORRENT_EXPENSIVE_INVARIANT_CHECKS - // make sure this peer is not a dangling pointer - TORRENT_ASSERT(m_ses.has_peer(*i)); -#endif - peer_connection const& p = *(*i); - for (std::deque::const_iterator i = p.request_queue().begin() - , end(p.request_queue().end()); i != end; ++i) - ++num_requests[*i]; - for (std::deque::const_iterator i = p.download_queue().begin() - , end(p.download_queue().end()); i != end; ++i) - ++num_requests[i->block]; - if (!p.is_choked()) ++num_uploads; - torrent* associated_torrent = p.associated_torrent().lock().get(); - if (associated_torrent != this) - TORRENT_ASSERT(false); - } - TORRENT_ASSERT(num_uploads == m_num_uploads); - - if (has_picker()) - { - for (std::map::iterator i = num_requests.begin() - , end(num_requests.end()); i != end; ++i) - { - if (!m_picker->is_downloaded(i->first)) - TORRENT_ASSERT(m_picker->num_peers(i->first) == i->second); - } - TORRENT_ASSERT(num_have() >= m_picker->num_have_filtered()); - } - - if (valid_metadata()) - { - TORRENT_ASSERT(m_abort || !m_picker || m_picker->num_pieces() == m_torrent_file->num_pieces()); - } - else - { - TORRENT_ASSERT(m_abort || !m_picker || m_picker->num_pieces() == 0); - } - -#ifdef TORRENT_EXPENSIVE_INVARIANT_CHECKS - for (policy::const_iterator i = m_policy.begin_peer() - , end(m_policy.end_peer()); i != end; ++i) - { - TORRENT_ASSERT(i->second.addr == i->first); - } -#endif - - size_type total_done = quantized_bytes_done(); - if (m_torrent_file->is_valid()) - { - if (is_seed()) - TORRENT_ASSERT(total_done == m_torrent_file->total_size()); - else - TORRENT_ASSERT(total_done != m_torrent_file->total_size() || !m_files_checked); - - TORRENT_ASSERT(m_block_size <= m_torrent_file->piece_length()); - } - else - { - TORRENT_ASSERT(total_done == 0); - } - - if (m_picker && !m_abort) - { - // make sure that pieces that have completed the download - // of all their blocks are in the disk io thread's queue - // to be checked. - const std::vector& dl_queue - = m_picker->get_download_queue(); - for (std::vector::const_iterator i = - dl_queue.begin(); i != dl_queue.end(); ++i) - { - const int blocks_per_piece = m_picker->blocks_in_piece(i->index); - - bool complete = true; - for (int j = 0; j < blocks_per_piece; ++j) - { - if (i->info[j].state == piece_picker::block_info::state_finished) - continue; - complete = false; - break; - } - } - } - -// This check is very expensive. - TORRENT_ASSERT(!valid_metadata() || m_block_size > 0); - TORRENT_ASSERT(!valid_metadata() || (m_torrent_file->piece_length() % m_block_size) == 0); -// if (is_seed()) TORRENT_ASSERT(m_picker.get() == 0); - } -#endif - - void torrent::set_sequential_download(bool sd) - { m_sequential_download = sd; } - - void torrent::set_queue_position(int p) - { - TORRENT_ASSERT((p == -1) == is_finished() - || (!m_auto_managed && p == -1) - || (m_abort && p == -1)); - if (is_finished() && p != -1) return; - if (p == m_sequence_number) return; - - session_impl::torrent_map& torrents = m_ses.m_torrents; - if (p >= 0 && m_sequence_number == -1) - { - int max_seq = -1; - for (session_impl::torrent_map::iterator i = torrents.begin() - , end(torrents.end()); i != end; ++i) - { - torrent* t = i->second.get(); - if (t->m_sequence_number > max_seq) max_seq = t->m_sequence_number; - } - m_sequence_number = (std::min)(max_seq + 1, p); - } - else if (p < 0) - { - for (session_impl::torrent_map::iterator i = torrents.begin() - , end(torrents.end()); i != end; ++i) - { - torrent* t = i->second.get(); - if (t == this) continue; - if (t->m_sequence_number >= m_sequence_number - && t->m_sequence_number != -1) - --t->m_sequence_number; - } - m_sequence_number = p; - } - else if (p < m_sequence_number) - { - for (session_impl::torrent_map::iterator i = torrents.begin() - , end(torrents.end()); i != end; ++i) - { - torrent* t = i->second.get(); - if (t == this) continue; - if (t->m_sequence_number >= p - && t->m_sequence_number < m_sequence_number - && t->m_sequence_number != -1) - ++t->m_sequence_number; - } - m_sequence_number = p; - } - else if (p > m_sequence_number) - { - int max_seq = 0; - for (session_impl::torrent_map::iterator i = torrents.begin() - , end(torrents.end()); i != end; ++i) - { - torrent* t = i->second.get(); - int pos = t->m_sequence_number; - if (pos > max_seq) max_seq = pos; - if (t == this) continue; - - if (pos <= p - && pos > m_sequence_number - && pos != -1) - --t->m_sequence_number; - - } - m_sequence_number = (std::min)(max_seq, p); - } - - if (m_ses.m_auto_manage_time_scaler > 2) - m_ses.m_auto_manage_time_scaler = 2; - } - - void torrent::set_max_uploads(int limit) - { - TORRENT_ASSERT(limit >= -1); - if (limit <= 0) limit = (std::numeric_limits::max)(); - m_max_uploads = limit; - } - - void torrent::set_max_connections(int limit) - { - TORRENT_ASSERT(limit >= -1); - if (limit <= 0) limit = (std::numeric_limits::max)(); - m_max_connections = limit; - } - - void torrent::set_peer_upload_limit(tcp::endpoint ip, int limit) - { - TORRENT_ASSERT(limit >= -1); - peer_iterator i = std::find_if(m_connections.begin(), m_connections.end() - , bind(&peer_connection::remote, _1) == ip); - if (i == m_connections.end()) return; - (*i)->set_upload_limit(limit); - } - - void torrent::set_peer_download_limit(tcp::endpoint ip, int limit) - { - TORRENT_ASSERT(limit >= -1); - peer_iterator i = std::find_if(m_connections.begin(), m_connections.end() - , bind(&peer_connection::remote, _1) == ip); - if (i == m_connections.end()) return; - (*i)->set_download_limit(limit); - } - - void torrent::set_upload_limit(int limit) - { - TORRENT_ASSERT(limit >= -1); - if (limit <= 0) limit = (std::numeric_limits::max)(); - if (limit < num_peers() * 10) limit = num_peers() * 10; - m_bandwidth_limit[peer_connection::upload_channel].throttle(limit); - } - - int torrent::upload_limit() const - { - int limit = m_bandwidth_limit[peer_connection::upload_channel].throttle(); - if (limit == (std::numeric_limits::max)()) limit = -1; - return limit; - } - - void torrent::set_download_limit(int limit) - { - TORRENT_ASSERT(limit >= -1); - if (limit <= 0) limit = (std::numeric_limits::max)(); - if (limit < num_peers() * 10) limit = num_peers() * 10; - m_bandwidth_limit[peer_connection::download_channel].throttle(limit); - } - - int torrent::download_limit() const - { - int limit = m_bandwidth_limit[peer_connection::download_channel].throttle(); - if (limit == (std::numeric_limits::max)()) limit = -1; - return limit; - } - - void torrent::delete_files() - { -#if defined TORRENT_VERBOSE_LOGGING - for (peer_iterator i = m_connections.begin(); - i != m_connections.end(); ++i) - { - (*(*i)->m_logger) << "*** DELETING FILES IN TORRENT\n"; - } -#endif - - disconnect_all(); - stop_announcing(); - - if (m_owning_storage.get()) - { - TORRENT_ASSERT(m_storage); - m_storage->async_delete_files( - bind(&torrent::on_files_deleted, shared_from_this(), _1, _2)); - } - } - - void torrent::clear_error() - { - if (m_error.empty()) return; - bool checking_files = should_check_files(); - if (m_ses.m_auto_manage_time_scaler > 2) - m_ses.m_auto_manage_time_scaler = 2; - m_error.clear(); - if (!checking_files && should_check_files()) - queue_torrent_check(); - } - - void torrent::set_error(std::string const& msg) - { - bool checking_files = should_check_files(); - m_error = msg; - if (checking_files && !should_check_files()) - { - // stop checking - m_storage->abort_disk_io(); - dequeue_torrent_check(); - set_state(torrent_status::queued_for_checking); - } - } - - void torrent::auto_managed(bool a) - { - INVARIANT_CHECK; - - if (m_auto_managed == a) return; - bool checking_files = should_check_files(); - m_auto_managed = a; - // recalculate which torrents should be - // paused - m_ses.m_auto_manage_time_scaler = 0; - - if (!checking_files && should_check_files()) - { - queue_torrent_check(); - } - else if (checking_files && !should_check_files()) - { - // stop checking - m_storage->abort_disk_io(); - dequeue_torrent_check(); - set_state(torrent_status::queued_for_checking); - } - } - - // the higher seed rank, the more important to seed - int torrent::seed_rank(session_settings const& s) const - { - enum flags - { - seed_ratio_not_met = 0x400000, - recently_started = 0x200000, - no_seeds = 0x100000, - prio_mask = 0xfffff - }; - - if (!is_seed()) return 0; - - int ret = 0; - - ptime now(time_now()); - - int seed_time = total_seconds(m_seeding_time); - int download_time = total_seconds(m_active_time) - seed_time; - - // if we haven't yet met the seed limits, set the seed_ratio_not_met - // flag. That will make this seed prioritized - // downloaded may be 0 if the torrent is 0-sized - size_type downloaded = (std::max)(m_total_downloaded, m_torrent_file->total_size()); - if (seed_time < s.seed_time_limit - && (seed_time > 1 && download_time / float(seed_time) < s.seed_time_ratio_limit) - && downloaded > 0 - && m_total_uploaded / downloaded < s.share_ratio_limit) - ret |= seed_ratio_not_met; - - // if this torrent is running, and it was started less - // than 30 minutes ago, give it priority, to avoid oscillation - if (!is_paused() && now - m_started < minutes(30)) - ret |= recently_started; - - // if we have any scrape data, use it to calculate - // seed rank - int seeds = 0; - int downloaders = 0; - - if (m_complete >= 0) seeds = m_complete; - else seeds = m_policy.num_seeds(); - - if (m_incomplete >= 0) downloaders = m_incomplete; - else downloaders = m_policy.num_peers() - m_policy.num_seeds(); - - if (seeds == 0) - { - ret |= no_seeds; - ret |= downloaders & prio_mask; - } - else - { - ret |= (downloaders * 100 / seeds) & prio_mask; - } - - return ret; - } - - // this is an async operation triggered by the client - void torrent::save_resume_data() - { - INVARIANT_CHECK; - - if (m_owning_storage.get()) - { - TORRENT_ASSERT(m_storage); - if (m_state == torrent_status::queued_for_checking - || m_state == torrent_status::checking_files - || m_state == torrent_status::checking_resume_data) - { - if (alerts().should_post()) - { - alerts().post_alert(save_resume_data_failed_alert(get_handle() - , "won't save resume data, torrent does not have a complete resume state yet")); - } - } - else - { - m_storage->async_save_resume_data( - bind(&torrent::on_save_resume_data, shared_from_this(), _1, _2)); - } - } - else - { - if (alerts().should_post()) - { - alerts().post_alert(save_resume_data_failed_alert(get_handle() - , "save resume data failed, torrent is being destructed")); - } - } - } - - bool torrent::should_check_files() const - { - return (m_state == torrent_status::checking_files - || m_state == torrent_status::queued_for_checking) - && (!m_paused || m_auto_managed) - && m_error.empty() - && !m_abort; - } - - bool torrent::is_paused() const - { - return m_paused || m_ses.is_paused(); - } - - void torrent::pause() - { - INVARIANT_CHECK; - - if (m_paused) return; - bool checking_files = should_check_files(); - m_paused = true; - if (!m_ses.is_paused()) - do_pause(); - if (checking_files && !should_check_files()) - { - // stop checking - m_storage->abort_disk_io(); - dequeue_torrent_check(); - set_state(torrent_status::queued_for_checking); - } - } - - void torrent::do_pause() - { - if (!is_paused()) return; - -#ifndef TORRENT_DISABLE_EXTENSIONS - for (extension_list_t::iterator i = m_extensions.begin() - , end(m_extensions.end()); i != end; ++i) - { -#ifndef BOOST_NO_EXCEPTIONS - try { -#endif - if ((*i)->on_pause()) return; -#ifndef BOOST_NO_EXCEPTIONS - } catch (std::exception&) {} -#endif - } -#endif - -#if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_ERROR_LOGGING - for (peer_iterator i = m_connections.begin(); - i != m_connections.end(); ++i) - { - (*(*i)->m_logger) << "*** PAUSING TORRENT\n"; - } -#endif - - // this will make the storage close all - // files and flush all cached data - if (m_owning_storage.get()) - { - TORRENT_ASSERT(m_storage); - m_storage->async_release_files( - bind(&torrent::on_torrent_paused, shared_from_this(), _1, _2)); - m_storage->async_clear_read_cache(); - } - else - { - if (alerts().should_post()) - alerts().post_alert(torrent_paused_alert(get_handle())); - } - - disconnect_all(); - stop_announcing(); - } - - void torrent::resume() - { - INVARIANT_CHECK; - - if (!m_paused) return; - bool checking_files = should_check_files(); - m_paused = false; - do_resume(); - if (!checking_files && should_check_files()) - queue_torrent_check(); - } - - void torrent::do_resume() - { - if (is_paused()) return; - -#ifndef TORRENT_DISABLE_EXTENSIONS - for (extension_list_t::iterator i = m_extensions.begin() - , end(m_extensions.end()); i != end; ++i) - { -#ifndef BOOST_NO_EXCEPTIONS - try { -#endif - if ((*i)->on_resume()) return; -#ifndef BOOST_NO_EXCEPTIONS - } catch (std::exception&) {} -#endif - } -#endif - - if (alerts().should_post()) - alerts().post_alert(torrent_resumed_alert(get_handle())); - - m_started = time_now(); - m_error.clear(); - start_announcing(); - } - - void torrent::restart_tracker_timer(ptime announce_at) - { - if (!m_announcing) return; - - m_next_tracker_announce = announce_at; - error_code ec; - boost::weak_ptr self(shared_from_this()); - m_tracker_timer.expires_at(m_next_tracker_announce, ec); - m_tracker_timer.async_wait(bind(&torrent::on_tracker_announce_disp, self, _1)); - } - - void torrent::start_announcing() - { - if (is_paused()) return; - // if we don't have metadata, we need to announce - // before checking files, to get peers to - // request the metadata from - if (!m_files_checked && valid_metadata()) return; - if (m_announcing) return; - - m_announcing = true; - - if (!m_trackers.empty()) - { - // tell the tracker that we're back - m_start_sent = false; - m_stat.clear(); - announce_with_tracker(); - } - - // private torrents are never announced on LSD - // or on DHT, we don't need this timer. - if (!m_torrent_file->is_valid() || !m_torrent_file->priv()) - { - error_code ec; - boost::weak_ptr self(shared_from_this()); - m_lsd_announce_timer.expires_from_now(seconds(1), ec); - m_lsd_announce_timer.async_wait( - bind(&torrent::on_lsd_announce_disp, self, _1)); - } - } - - void torrent::stop_announcing() - { - if (!m_announcing) return; - - error_code ec; - m_lsd_announce_timer.cancel(ec); - m_tracker_timer.cancel(ec); - - m_announcing = false; - - if (!m_trackers.empty()) - announce_with_tracker(tracker_request::stopped); - } - - void torrent::second_tick(stat& accumulator, float tick_interval) - { - INVARIANT_CHECK; - -#ifndef TORRENT_DISABLE_EXTENSIONS - for (extension_list_t::iterator i = m_extensions.begin() - , end(m_extensions.end()); i != end; ++i) - { -#ifndef BOOST_NO_EXCEPTIONS - try { -#endif - (*i)->tick(); -#ifndef BOOST_NO_EXCEPTIONS - } catch (std::exception&) {} -#endif - } -#endif - - if (is_paused()) - { - // let the stats fade out to 0 - m_stat.second_tick(tick_interval); - return; - } - - time_duration since_last_tick = microsec(tick_interval * 1000000L); - if (is_seed()) m_seeding_time += since_last_tick; - m_active_time += since_last_tick; - - // ---- WEB SEEDS ---- - - // re-insert urls that are to be retrieds into the m_web_seeds - typedef std::map::iterator iter_t; - for (iter_t i = m_web_seeds_next_retry.begin(); i != m_web_seeds_next_retry.end();) - { - iter_t erase_element = i++; - if (erase_element->second <= time_now()) - { - m_web_seeds.insert(erase_element->first); - m_web_seeds_next_retry.erase(erase_element); - } - } - - // if we have everything we want we don't need to connect to any web-seed - if (!is_finished() && !m_web_seeds.empty()) - { - // keep trying web-seeds if there are any - // first find out which web seeds we are connected to - std::set web_seeds; - for (peer_iterator i = m_connections.begin(); - i != m_connections.end(); ++i) - { - web_peer_connection* p - = dynamic_cast(*i); - if (!p) continue; - web_seeds.insert(p->url()); - } - - for (std::set::iterator i = m_resolving_web_seeds.begin() - , end(m_resolving_web_seeds.end()); i != end; ++i) - web_seeds.insert(web_seeds.begin(), *i); - - // from the list of available web seeds, subtract the ones we are - // already connected to. - std::vector not_connected_web_seeds; - std::set_difference(m_web_seeds.begin(), m_web_seeds.end(), web_seeds.begin() - , web_seeds.end(), std::back_inserter(not_connected_web_seeds)); - - // connect to all of those that we aren't connected to - std::for_each(not_connected_web_seeds.begin(), not_connected_web_seeds.end() - , bind(&torrent::connect_to_url_seed, this, _1)); - } - - for (peer_iterator i = m_connections.begin(); - i != m_connections.end();) - { - peer_connection* p = *i; - ++i; - p->calc_ip_overhead(); - m_stat += p->statistics(); - // updates the peer connection's ul/dl bandwidth - // resource requests -#ifndef BOOST_NO_EXCEPTIONS - try - { -#endif - p->second_tick(tick_interval); -#ifndef BOOST_NO_EXCEPTIONS - } - catch (std::exception& e) - { -#if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_ERROR_LOGGING - (*p->m_logger) << "**ERROR**: " << e.what() << "\n"; -#endif - p->disconnect(e.what(), 1); - } -#endif - } - accumulator += m_stat; - m_total_uploaded += m_stat.last_payload_uploaded(); - m_total_downloaded += m_stat.last_payload_downloaded(); - m_stat.second_tick(tick_interval); - - m_time_scaler--; - if (m_time_scaler <= 0) - { - m_time_scaler = 10; - m_policy.pulse(); - } - } - - void torrent::retry_url_seed(std::string const& url) - { - m_web_seeds_next_retry[url] = time_now() - + seconds(m_ses.settings().urlseed_wait_retry); - } - - bool torrent::try_connect_peer() - { - TORRENT_ASSERT(want_more_peers()); - if (m_deficit_counter < 100) return false; - m_deficit_counter -= 100; - bool ret = m_policy.connect_one_peer(); - return ret; - } - - void torrent::give_connect_points(int points) - { - TORRENT_ASSERT(points <= 100); - TORRENT_ASSERT(points > 0); - TORRENT_ASSERT(want_more_peers()); - m_deficit_counter += points; - } - - void torrent::async_verify_piece(int piece_index, boost::function const& f) - { -// INVARIANT_CHECK; - - TORRENT_ASSERT(m_storage); - TORRENT_ASSERT(m_storage->refcount() > 0); - TORRENT_ASSERT(piece_index >= 0); - TORRENT_ASSERT(piece_index < m_torrent_file->num_pieces()); - TORRENT_ASSERT(piece_index < (int)m_picker->num_pieces()); -#ifdef TORRENT_DEBUG - if (m_picker) - { - int blocks_in_piece = m_picker->blocks_in_piece(piece_index); - for (int i = 0; i < blocks_in_piece; ++i) - { - TORRENT_ASSERT(m_picker->num_peers(piece_block(piece_index, i)) == 0); - } - } -#endif - - m_storage->async_hash(piece_index, bind(&torrent::on_piece_verified - , shared_from_this(), _1, _2, f)); -#if defined TORRENT_DEBUG && !defined TORRENT_DISABLE_INVARIANT_CHECKS - check_invariant(); -#endif - } - - void torrent::on_piece_verified(int ret, disk_io_job const& j - , boost::function f) - { - session_impl::mutex_t::scoped_lock l(m_ses.m_mutex); - - // return value: - // 0: success, piece passed hash check - // -1: disk failure - // -2: hash check failed - - if (ret == -1) - { - if (alerts().should_post()) - alerts().post_alert(file_error_alert(j.error_file, get_handle(), j.str)); - set_error(j.str); - pause(); - } - f(ret); - } - - const tcp::endpoint& torrent::current_tracker() const - { - return m_tracker_address; - } - - void torrent::file_progress(std::vector& fp) const - { - fp.clear(); - fp.resize(m_torrent_file->num_files(), 1.f); - if (is_seed()) return; - - std::vector progress; - file_progress(progress); - for (int i = 0; i < m_torrent_file->num_files(); ++i) - { - file_entry const& f = m_torrent_file->file_at(i); - if (f.size == 0) fp[i] = 1.f; - else fp[i] = float(progress[i]) / f.size; - } - } - - void torrent::file_progress(std::vector& fp) const - { - TORRENT_ASSERT(valid_metadata()); - - fp.resize(m_torrent_file->num_files(), 0); - - if (is_seed()) - { - for (int i = 0; i < m_torrent_file->num_files(); ++i) - fp[i] = m_torrent_file->files().at(i).size; - return; - } - - TORRENT_ASSERT(has_picker()); - - for (int i = 0; i < m_torrent_file->num_files(); ++i) - { - peer_request ret = m_torrent_file->files().map_file(i, 0, 0); - size_type size = m_torrent_file->files().at(i).size; - -// zero sized files are considered -// 100% done all the time - if (size == 0) - { - fp[i] = 0; - continue; - } - - size_type done = 0; - while (size > 0) - { - size_type bytes_step = (std::min)(size_type(m_torrent_file->piece_size(ret.piece) - - ret.start), size); - if (m_picker->have_piece(ret.piece)) done += bytes_step; - ++ret.piece; - ret.start = 0; - size -= bytes_step; - } - TORRENT_ASSERT(size == 0); - - fp[i] = done; - } - - const std::vector& q - = m_picker->get_download_queue(); - - for (std::vector::const_iterator - i = q.begin(), end(q.end()); i != end; ++i) - { - size_type offset = size_type(i->index) * m_torrent_file->piece_length(); - torrent_info::file_iterator file = m_torrent_file->file_at_offset(offset); - int file_index = file - m_torrent_file->begin_files(); - int num_blocks = m_picker->blocks_in_piece(i->index); - piece_picker::block_info const* info = i->info; - for (int k = 0; k < num_blocks; ++k) - { - TORRENT_ASSERT(file != m_torrent_file->end_files()); - TORRENT_ASSERT(offset == size_type(i->index) * m_torrent_file->piece_length() - + k * m_block_size); - TORRENT_ASSERT(offset < m_torrent_file->total_size()); - while (offset >= file->offset + file->size) - { - ++file; - ++file_index; - } - TORRENT_ASSERT(file != m_torrent_file->end_files()); - - size_type block_size = m_block_size; - - if (info[k].state == piece_picker::block_info::state_none) - { - offset += m_block_size; - continue; - } - - if (info[k].state == piece_picker::block_info::state_requested) - { - block_size = 0; - policy::peer* p = static_cast(info[k].peer); - if (p && p->connection) - { - boost::optional pbp - = p->connection->downloading_piece_progress(); - if (pbp && pbp->piece_index == i->index && pbp->block_index == k) - block_size = pbp->bytes_downloaded; - TORRENT_ASSERT(block_size <= m_block_size); - } - - if (block_size == 0) - { - offset += m_block_size; - continue; - } - } - - if (offset + block_size > file->offset + file->size) - { - int left_over = m_block_size - block_size; - // split the block on multiple files - while (block_size > 0) - { - TORRENT_ASSERT(offset <= file->offset + file->size); - size_type slice = (std::min)(file->offset + file->size - offset - , block_size); - fp[file_index] += slice; - offset += slice; - block_size -= slice; - TORRENT_ASSERT(offset <= file->offset + file->size); - if (offset == file->offset + file->size) - { - ++file; - ++file_index; - if (file == m_torrent_file->end_files()) - { - offset += block_size; - break; - } - } - } - offset += left_over; - TORRENT_ASSERT(offset == size_type(i->index) * m_torrent_file->piece_length() - + (k+1) * m_block_size); - } - else - { - fp[file_index] += block_size; - offset += m_block_size; - } - TORRENT_ASSERT(file_index <= m_torrent_file->num_files()); - } - } - } - - void torrent::set_state(torrent_status::state_t s) - { -#ifdef TORRENT_DEBUG - if (s != torrent_status::checking_files - && s != torrent_status::queued_for_checking) - TORRENT_ASSERT(!m_queued_for_checking); - if (s == torrent_status::seeding) - TORRENT_ASSERT(is_seed()); - if (s == torrent_status::finished) - TORRENT_ASSERT(is_finished()); - if (s == torrent_status::downloading && m_state == torrent_status::finished) - TORRENT_ASSERT(!is_finished()); -#endif - - if (m_state == s) return; - m_state = s; - if (m_ses.m_alerts.should_post()) - m_ses.m_alerts.post_alert(state_changed_alert(get_handle(), s)); - } - - torrent_status torrent::status() const - { - INVARIANT_CHECK; - - ptime now = time_now(); - - torrent_status st; - - st.has_incoming = m_has_incoming; - st.error = m_error; - - if (m_last_scrape == min_time()) - { - st.last_scrape = -1; - } - else - { - st.last_scrape = total_seconds(now - m_last_scrape); - } - st.up_bandwidth_queue = (int)m_bandwidth_queue[peer_connection::upload_channel].size(); - st.down_bandwidth_queue = (int)m_bandwidth_queue[peer_connection::download_channel].size(); - - st.num_peers = (int)std::count_if(m_connections.begin(), m_connections.end() - , !boost::bind(&peer_connection::is_connecting, _1)); - - st.list_peers = m_policy.num_peers(); - st.list_seeds = m_policy.num_seeds(); - st.connect_candidates = m_policy.num_connect_candidates(); - st.seed_rank = seed_rank(m_ses.m_settings); - - st.all_time_upload = m_total_uploaded; - st.all_time_download = m_total_downloaded; - - st.active_time = total_seconds(m_active_time); - st.seeding_time = total_seconds(m_seeding_time); - - st.storage_mode = m_storage_mode; - - st.num_complete = m_complete; - st.num_incomplete = m_incomplete; - st.paused = m_paused; - boost::tie(st.total_done, st.total_wanted_done) = bytes_done(); - TORRENT_ASSERT(st.total_wanted_done >= 0); - TORRENT_ASSERT(st.total_done >= st.total_wanted_done); - - // payload transfer - st.total_payload_download = m_stat.total_payload_download(); - st.total_payload_upload = m_stat.total_payload_upload(); - - // total transfer - st.total_download = m_stat.total_payload_download() - + m_stat.total_protocol_download(); - st.total_upload = m_stat.total_payload_upload() - + m_stat.total_protocol_upload(); - - // failed bytes - st.total_failed_bytes = m_total_failed_bytes; - st.total_redundant_bytes = m_total_redundant_bytes; - - // transfer rate - st.download_rate = m_stat.download_rate(); - st.upload_rate = m_stat.upload_rate(); - st.download_payload_rate = m_stat.download_payload_rate(); - st.upload_payload_rate = m_stat.upload_payload_rate(); - - st.next_announce = boost::posix_time::seconds( - total_seconds(next_announce() - now)); - if (st.next_announce.is_negative() || is_paused()) - st.next_announce = boost::posix_time::seconds(0); - - st.announce_interval = boost::posix_time::seconds(m_duration); - - if (m_last_working_tracker >= 0) - { - st.current_tracker - = m_trackers[m_last_working_tracker].url; - } - - st.num_uploads = m_num_uploads; - st.uploads_limit = m_max_uploads; - st.num_connections = int(m_connections.size()); - st.connections_limit = m_max_connections; - // if we don't have any metadata, stop here - - st.state = m_state; - // for backwards compatibility - if (st.state == torrent_status::checking_resume_data) - st.state = torrent_status::queued_for_checking; - - if (!valid_metadata()) - { - st.state = torrent_status::downloading_metadata; - st.progress = m_progress; - st.block_size = 0; - return st; - } - - st.block_size = block_size(); - - // fill in status that depends on metadata - - st.total_wanted = m_torrent_file->total_size(); - TORRENT_ASSERT(st.total_wanted >= 0); - TORRENT_ASSERT(st.total_wanted >= m_torrent_file->piece_length() - * (m_torrent_file->num_pieces() - 1)); - - if (m_picker.get() && (m_picker->num_filtered() > 0 - || m_picker->num_have_filtered() > 0)) - { - int num_filtered_pieces = m_picker->num_filtered() - + m_picker->num_have_filtered(); - int last_piece_index = m_torrent_file->num_pieces() - 1; - if (m_picker->piece_priority(last_piece_index) == 0) - { - st.total_wanted -= m_torrent_file->piece_size(last_piece_index); - --num_filtered_pieces; - } - - st.total_wanted -= size_type(num_filtered_pieces) * m_torrent_file->piece_length(); - } - - TORRENT_ASSERT(st.total_wanted >= st.total_wanted_done); - - if (m_state == torrent_status::checking_files) - st.progress = m_progress; - else if (st.total_wanted == 0) st.progress = 1.f; - else st.progress = st.total_wanted_done - / static_cast(st.total_wanted); - - if (has_picker()) - { - int num_pieces = m_picker->num_pieces(); - st.pieces.resize(num_pieces, false); - for (int i = 0; i < num_pieces; ++i) - if (m_picker->have_piece(i)) st.pieces.set_bit(i); - } - st.num_pieces = num_have(); - st.num_seeds = num_seeds(); - if (m_picker.get()) - st.distributed_copies = m_picker->distributed_copies(); - else - st.distributed_copies = -1; - return st; - } - - void torrent::add_redundant_bytes(int b) - { - TORRENT_ASSERT(b > 0); - m_total_redundant_bytes += b; - m_ses.add_redundant_bytes(b); - } - - void torrent::add_failed_bytes(int b) - { - TORRENT_ASSERT(b > 0); - m_total_failed_bytes += b; - m_ses.add_failed_bytes(b); - } - - int torrent::num_seeds() const - { - INVARIANT_CHECK; - - return (int)std::count_if(m_connections.begin(), m_connections.end() - , boost::bind(&peer_connection::is_seed, _1)); - } - - void torrent::tracker_request_timed_out( - tracker_request const& r) - { - session_impl::mutex_t::scoped_lock l(m_ses.m_mutex); - - INVARIANT_CHECK; - -#if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_LOGGING || defined TORRENT_ERROR_LOGGING - debug_log("*** tracker timed out"); -#endif - - if (r.kind == tracker_request::announce_request) - { - if (m_ses.m_alerts.should_post()) - { - m_ses.m_alerts.post_alert(tracker_error_alert(get_handle() - , m_failed_trackers + 1, 0, r.url, "tracker timed out")); - } - } - else if (r.kind == tracker_request::scrape_request) - { - if (m_ses.m_alerts.should_post()) - { - m_ses.m_alerts.post_alert(scrape_failed_alert(get_handle() - , r.url, "tracker timed out")); - } - } - - if (r.kind == tracker_request::announce_request) - try_next_tracker(r); - } - - // TODO: with some response codes, we should just consider - // the tracker as a failure and not retry - // it anymore - void torrent::tracker_request_error(tracker_request const& r - , int response_code, const std::string& str) - { - session_impl::mutex_t::scoped_lock l(m_ses.m_mutex); - - INVARIANT_CHECK; - -#if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_LOGGING || defined TORRENT_ERROR_LOGGING - debug_log(std::string("*** tracker error: ") + str); -#endif - if (r.kind == tracker_request::announce_request) - { - if (m_ses.m_alerts.should_post()) - { - m_ses.m_alerts.post_alert(tracker_error_alert(get_handle() - , m_failed_trackers + 1, response_code, r.url, str)); - } - } - else if (r.kind == tracker_request::scrape_request) - { - if (m_ses.m_alerts.should_post()) - { - m_ses.m_alerts.post_alert(scrape_failed_alert(get_handle(), r.url, str)); - } - } - - if (r.kind == tracker_request::announce_request) - try_next_tracker(r); - } - - -#if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_LOGGING || defined TORRENT_ERROR_LOGGING - void torrent::debug_log(const std::string& line) - { - (*m_ses.m_logger) << time_now_string() << " " << line << "\n"; - } -#endif - -} - diff --git a/libtorrent/src/torrent_handle.cpp b/libtorrent/src/torrent_handle.cpp deleted file mode 100755 index 81baf6763..000000000 --- a/libtorrent/src/torrent_handle.cpp +++ /dev/null @@ -1,635 +0,0 @@ -/* - -Copyright (c) 2003, Arvid Norberg -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions -are met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in - the documentation and/or other materials provided with the distribution. - * Neither the name of the author nor the names of its - contributors may be used to endorse or promote products derived - from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -POSSIBILITY OF SUCH DAMAGE. - -*/ - -#include "libtorrent/pch.hpp" - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#ifdef _MSC_VER -#pragma warning(push, 1) -#endif - -#include -#include -#include - -#ifdef _MSC_VER -#pragma warning(pop) -#endif - -#include "libtorrent/peer_id.hpp" -#include "libtorrent/bt_peer_connection.hpp" -#include "libtorrent/torrent_info.hpp" -#include "libtorrent/tracker_manager.hpp" -#include "libtorrent/bencode.hpp" -#include "libtorrent/hasher.hpp" -#include "libtorrent/entry.hpp" -#include "libtorrent/session.hpp" -#include "libtorrent/aux_/session_impl.hpp" -#include "libtorrent/invariant_check.hpp" - -#if defined(_MSC_VER) && _MSC_VER < 1300 -namespace std -{ - using ::srand; - using ::isalnum; -}; -#endif - -using boost::bind; -using libtorrent::aux::session_impl; - -#ifdef BOOST_NO_EXCEPTIONS - -#define TORRENT_FORWARD(call) \ - boost::shared_ptr t = m_torrent.lock(); \ - if (!t) return; \ - session_impl::mutex_t::scoped_lock l(t->session().m_mutex); \ - t->call - -#define TORRENT_FORWARD_RETURN(call, def) \ - boost::shared_ptr t = m_torrent.lock(); \ - if (!t) return def; \ - session_impl::mutex_t::scoped_lock l(t->session().m_mutex); \ - return t->call - -#define TORRENT_FORWARD_RETURN2(call, def) \ - boost::shared_ptr t = m_torrent.lock(); \ - if (!t) return def; \ - session_impl::mutex_t::scoped_lock l(t->session().m_mutex); \ - t->call - -#else - -#define TORRENT_FORWARD(call) \ - boost::shared_ptr t = m_torrent.lock(); \ - if (!t) throw_invalid_handle(); \ - session_impl::mutex_t::scoped_lock l(t->session().m_mutex); \ - t->call - -#define TORRENT_FORWARD_RETURN(call, def) \ - boost::shared_ptr t = m_torrent.lock(); \ - if (!t) throw_invalid_handle(); \ - session_impl::mutex_t::scoped_lock l(t->session().m_mutex); \ - return t->call - -#define TORRENT_FORWARD_RETURN2(call, def) \ - boost::shared_ptr t = m_torrent.lock(); \ - if (!t) throw_invalid_handle(); \ - session_impl::mutex_t::scoped_lock l(t->session().m_mutex); \ - t->call - -#endif - -namespace libtorrent -{ - namespace fs = boost::filesystem; - - namespace - { -#ifndef BOOST_NO_EXCEPTIONS - void throw_invalid_handle() - { - throw invalid_handle(); - } -#endif - } - -#ifdef TORRENT_DEBUG - - void torrent_handle::check_invariant() const - {} - -#endif - - sha1_hash torrent_handle::info_hash() const - { - INVARIANT_CHECK; - const static sha1_hash empty; - TORRENT_FORWARD_RETURN(torrent_file().info_hash(), empty); - } - - void torrent_handle::set_max_uploads(int max_uploads) const - { - INVARIANT_CHECK; - TORRENT_ASSERT(max_uploads >= 2 || max_uploads == -1); - TORRENT_FORWARD(set_max_uploads(max_uploads)); - } - - void torrent_handle::use_interface(const char* net_interface) const - { - INVARIANT_CHECK; - TORRENT_FORWARD(use_interface(net_interface)); - } - - void torrent_handle::set_max_connections(int max_connections) const - { - INVARIANT_CHECK; - TORRENT_ASSERT(max_connections >= 2 || max_connections == -1); - TORRENT_FORWARD(set_max_connections(max_connections)); - } - - void torrent_handle::set_peer_upload_limit(tcp::endpoint ip, int limit) const - { - INVARIANT_CHECK; - TORRENT_ASSERT(limit >= -1); - TORRENT_FORWARD(set_peer_upload_limit(ip, limit)); - } - - void torrent_handle::set_peer_download_limit(tcp::endpoint ip, int limit) const - { - INVARIANT_CHECK; - TORRENT_ASSERT(limit >= -1); - TORRENT_FORWARD(set_peer_download_limit(ip, limit)); - } - - void torrent_handle::set_upload_limit(int limit) const - { - INVARIANT_CHECK; - TORRENT_ASSERT(limit >= -1); - TORRENT_FORWARD(set_upload_limit(limit)); - } - - int torrent_handle::upload_limit() const - { - INVARIANT_CHECK; - TORRENT_FORWARD_RETURN(upload_limit(), 0); - } - - void torrent_handle::set_download_limit(int limit) const - { - INVARIANT_CHECK; - TORRENT_ASSERT(limit >= -1); - TORRENT_FORWARD(set_download_limit(limit)); - } - - int torrent_handle::download_limit() const - { - INVARIANT_CHECK; - TORRENT_FORWARD_RETURN(download_limit(), 0); - } - - void torrent_handle::move_storage( - fs::path const& save_path) const - { - INVARIANT_CHECK; - TORRENT_FORWARD(move_storage(save_path)); - } - - void torrent_handle::rename_file(int index, fs::path const& new_name) const - { - INVARIANT_CHECK; - TORRENT_FORWARD(rename_file(index, new_name.string())); - } - - void torrent_handle::add_extension( - boost::function(torrent*, void*)> const& ext - , void* userdata) - { - INVARIANT_CHECK; - TORRENT_FORWARD(add_extension(ext, userdata)); - } - - bool torrent_handle::has_metadata() const - { - INVARIANT_CHECK; - TORRENT_FORWARD_RETURN(valid_metadata(), false); - } - - bool torrent_handle::is_seed() const - { - INVARIANT_CHECK; - TORRENT_FORWARD_RETURN(is_seed(), false); - } - - bool torrent_handle::is_finished() const - { - INVARIANT_CHECK; - TORRENT_FORWARD_RETURN(is_finished(), false); - } - - bool torrent_handle::is_paused() const - { - INVARIANT_CHECK; - TORRENT_FORWARD_RETURN(is_torrent_paused(), false); - } - - void torrent_handle::pause() const - { - INVARIANT_CHECK; - TORRENT_FORWARD(pause()); - } - - void torrent_handle::save_resume_data() const - { - INVARIANT_CHECK; - TORRENT_FORWARD(save_resume_data()); - } - - void torrent_handle::force_recheck() const - { - INVARIANT_CHECK; - TORRENT_FORWARD(force_recheck()); - } - - void torrent_handle::resume() const - { - INVARIANT_CHECK; - TORRENT_FORWARD(resume()); - } - - bool torrent_handle::is_auto_managed() const - { - INVARIANT_CHECK; - TORRENT_FORWARD_RETURN(is_auto_managed(), true); - } - - void torrent_handle::auto_managed(bool m) const - { - INVARIANT_CHECK; - TORRENT_FORWARD(auto_managed(m)); - } - - int torrent_handle::queue_position() const - { - INVARIANT_CHECK; - TORRENT_FORWARD_RETURN(queue_position(), -1); - } - - void torrent_handle::queue_position_up() const - { - INVARIANT_CHECK; - TORRENT_FORWARD(set_queue_position(t->queue_position() == 0 - ? t->queue_position() : t->queue_position() - 1)); - } - - void torrent_handle::queue_position_down() const - { - INVARIANT_CHECK; - TORRENT_FORWARD(set_queue_position(t->queue_position() + 1)); - } - - void torrent_handle::queue_position_top() const - { - INVARIANT_CHECK; - TORRENT_FORWARD(set_queue_position(0)); - } - - void torrent_handle::queue_position_bottom() const - { - INVARIANT_CHECK; - TORRENT_FORWARD(set_queue_position((std::numeric_limits::max)())); - } - - void torrent_handle::clear_error() const - { - INVARIANT_CHECK; - TORRENT_FORWARD(clear_error()); - } - - void torrent_handle::set_tracker_login(std::string const& name - , std::string const& password) const - { - INVARIANT_CHECK; - TORRENT_FORWARD(set_tracker_login(name, password)); - } - -#ifndef TORRENT_NO_DEPRECATE - void torrent_handle::file_progress(std::vector& progress) const - { - INVARIANT_CHECK; - TORRENT_FORWARD(file_progress(progress)); - } -#endif - - void torrent_handle::file_progress(std::vector& progress) const - { - INVARIANT_CHECK; - TORRENT_FORWARD(file_progress(progress)); - } - - torrent_status torrent_handle::status() const - { - INVARIANT_CHECK; - TORRENT_FORWARD_RETURN(status(), torrent_status()); - } - - void torrent_handle::set_sequential_download(bool sd) const - { - INVARIANT_CHECK; - TORRENT_FORWARD(set_sequential_download(sd)); - } - - bool torrent_handle::is_sequential_download() const - { - INVARIANT_CHECK; - TORRENT_FORWARD_RETURN(is_sequential_download(), false); - } - - std::string torrent_handle::name() const - { - INVARIANT_CHECK; - TORRENT_FORWARD_RETURN(name(), ""); - } - - void torrent_handle::piece_availability(std::vector& avail) const - { - INVARIANT_CHECK; - TORRENT_FORWARD(piece_availability(avail)); - } - - void torrent_handle::piece_priority(int index, int priority) const - { - INVARIANT_CHECK; - TORRENT_FORWARD(set_piece_priority(index, priority)); - } - - int torrent_handle::piece_priority(int index) const - { - INVARIANT_CHECK; - TORRENT_FORWARD_RETURN(piece_priority(index), 0); - } - - void torrent_handle::prioritize_pieces(std::vector const& pieces) const - { - INVARIANT_CHECK; - TORRENT_FORWARD(prioritize_pieces(pieces)); - } - - std::vector torrent_handle::piece_priorities() const - { - INVARIANT_CHECK; - std::vector ret; - TORRENT_FORWARD_RETURN2(piece_priorities(ret), ret); - return ret; - } - - void torrent_handle::file_priority(int index, int priority) const - { - INVARIANT_CHECK; - TORRENT_FORWARD(set_file_priority(index, priority)); - } - - int torrent_handle::file_priority(int index) const - { - INVARIANT_CHECK; - TORRENT_FORWARD_RETURN(file_priority(index), 0); - } - - void torrent_handle::prioritize_files(std::vector const& files) const - { - INVARIANT_CHECK; - TORRENT_FORWARD(prioritize_files(files)); - } - - std::vector torrent_handle::file_priorities() const - { - INVARIANT_CHECK; - std::vector ret; - TORRENT_FORWARD_RETURN2(file_priorities(ret), ret); - return ret; - } - -#ifndef TORRENT_NO_DEPRECATE -// ============ start deprecation =============== - - void torrent_handle::filter_piece(int index, bool filter) const - { - INVARIANT_CHECK; - TORRENT_FORWARD(filter_piece(index, filter)); - } - - void torrent_handle::filter_pieces(std::vector const& pieces) const - { - INVARIANT_CHECK; - TORRENT_FORWARD(filter_pieces(pieces)); - } - - bool torrent_handle::is_piece_filtered(int index) const - { - INVARIANT_CHECK; - TORRENT_FORWARD_RETURN(is_piece_filtered(index), false); - } - - std::vector torrent_handle::filtered_pieces() const - { - INVARIANT_CHECK; - std::vector ret; - TORRENT_FORWARD_RETURN2(filtered_pieces(ret), ret); - return ret; - } - - void torrent_handle::filter_files(std::vector const& files) const - { - INVARIANT_CHECK; - TORRENT_FORWARD(filter_files(files)); - } - -// ============ end deprecation =============== -#endif - - std::vector const& torrent_handle::trackers() const - { - INVARIANT_CHECK; - const static std::vector empty; - TORRENT_FORWARD_RETURN(trackers(), empty); - } - - void torrent_handle::add_url_seed(std::string const& url) const - { - INVARIANT_CHECK; - TORRENT_FORWARD(add_url_seed(url)); - } - - void torrent_handle::remove_url_seed(std::string const& url) const - { - INVARIANT_CHECK; - TORRENT_FORWARD(remove_url_seed(url)); - } - - std::set torrent_handle::url_seeds() const - { - INVARIANT_CHECK; - const static std::set empty; - TORRENT_FORWARD_RETURN(url_seeds(), empty); - } - - void torrent_handle::replace_trackers( - std::vector const& urls) const - { - INVARIANT_CHECK; - TORRENT_FORWARD(replace_trackers(urls)); - } - - storage_interface* torrent_handle::get_storage_impl() const - { - INVARIANT_CHECK; - TORRENT_FORWARD_RETURN(get_storage(), 0); - } - - torrent_info const& torrent_handle::get_torrent_info() const - { - INVARIANT_CHECK; -#ifdef BOOST_NO_EXCEPTIONS - const static torrent_info empty(sha1_hash(0)); -#endif - boost::shared_ptr t = m_torrent.lock(); - if (!t) -#ifdef BOOST_NO_EXCEPTIONS - return empty; -#else - throw_invalid_handle(); -#endif - session_impl::mutex_t::scoped_lock l(t->session().m_mutex); - if (!t->valid_metadata()) -#ifdef BOOST_NO_EXCEPTIONS - return empty; -#else - throw_invalid_handle(); -#endif - return t->torrent_file(); - } - - bool torrent_handle::is_valid() const - { - INVARIANT_CHECK; - return !m_torrent.expired(); - } - -#ifndef TORRENT_NO_DEPRECATE - entry torrent_handle::write_resume_data() const - { - INVARIANT_CHECK; - - entry ret(entry::dictionary_t); - TORRENT_FORWARD_RETURN2(write_resume_data(ret), ret); - t->filesystem().write_resume_data(ret); - - return ret; - } -#endif - - fs::path torrent_handle::save_path() const - { - INVARIANT_CHECK; - TORRENT_FORWARD_RETURN(save_path(), fs::path()); - } - - void torrent_handle::connect_peer(tcp::endpoint const& adr, int source) const - { - INVARIANT_CHECK; - - boost::shared_ptr t = m_torrent.lock(); - if (!t) -#ifdef BOOST_NO_EXCEPTIONS - return; -#else - throw_invalid_handle(); -#endif - session_impl::mutex_t::scoped_lock l(t->session().m_mutex); - - peer_id id; - std::fill(id.begin(), id.end(), 0); - t->get_policy().peer_from_tracker(adr, id, source, 0); - } - - void torrent_handle::force_reannounce( - boost::posix_time::time_duration duration) const - { - INVARIANT_CHECK; - TORRENT_FORWARD(force_tracker_request(time_now() + seconds(duration.total_seconds()))); - } - - void torrent_handle::force_reannounce() const - { - INVARIANT_CHECK; - TORRENT_FORWARD(force_tracker_request()); - } - - void torrent_handle::scrape_tracker() const - { - INVARIANT_CHECK; - TORRENT_FORWARD(scrape_tracker()); - } - - void torrent_handle::set_ratio(float ratio) const - { - INVARIANT_CHECK; - - TORRENT_ASSERT(ratio >= 0.f); - if (ratio < 1.f && ratio > 0.f) - ratio = 1.f; - TORRENT_FORWARD(set_ratio(ratio)); - } - -#ifndef TORRENT_DISABLE_RESOLVE_COUNTRIES - void torrent_handle::resolve_countries(bool r) - { - INVARIANT_CHECK; - TORRENT_FORWARD(resolve_countries(r)); - } - - bool torrent_handle::resolve_countries() const - { - INVARIANT_CHECK; - TORRENT_FORWARD_RETURN(resolving_countries(), false); - } -#endif - - void torrent_handle::get_full_peer_list(std::vector& v) const - { - INVARIANT_CHECK; - TORRENT_FORWARD(get_full_peer_list(v)); - } - - void torrent_handle::get_peer_info(std::vector& v) const - { - INVARIANT_CHECK; - TORRENT_FORWARD(get_peer_info(v)); - } - - void torrent_handle::get_download_queue(std::vector& queue) const - { - INVARIANT_CHECK; - TORRENT_FORWARD(get_download_queue(queue)); - } - -} - diff --git a/libtorrent/src/torrent_info.cpp b/libtorrent/src/torrent_info.cpp deleted file mode 100755 index 172477974..000000000 --- a/libtorrent/src/torrent_info.cpp +++ /dev/null @@ -1,647 +0,0 @@ -/* - -Copyright (c) 2003-2008, Arvid Norberg -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions -are met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in - the documentation and/or other materials provided with the distribution. - * Neither the name of the author nor the names of its - contributors may be used to endorse or promote products derived - from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -POSSIBILITY OF SUCH DAMAGE. - -*/ - -#include "libtorrent/pch.hpp" - -#include -#include -#include -#include -#include -#include -#include - -#ifdef _MSC_VER -#pragma warning(push, 1) -#endif - -#include -#include -#include - -#ifdef _MSC_VER -#pragma warning(pop) -#endif - -#include "libtorrent/torrent_info.hpp" -#include "libtorrent/bencode.hpp" -#include "libtorrent/hasher.hpp" -#include "libtorrent/entry.hpp" -#include "libtorrent/file.hpp" - -namespace gr = boost::gregorian; - -using namespace libtorrent; - -namespace -{ - - namespace fs = boost::filesystem; - - void convert_to_utf8(std::string& str, unsigned char chr) - { - str += 0xc0 | ((chr & 0xff) >> 6); - str += 0x80 | (chr & 0x3f); - } - - bool verify_encoding(std::string& target) - { - std::string tmp_path; - bool valid_encoding = true; - for (std::string::iterator i = target.begin() - , end(target.end()); i != end; ++i) - { - // valid ascii-character - if ((*i & 0x80) == 0) - { - tmp_path += *i; - continue; - } - - if (std::distance(i, end) < 2) - { - convert_to_utf8(tmp_path, *i); - valid_encoding = false; - continue; - } - - // valid 2-byte utf-8 character - if ((i[0] & 0xe0) == 0xc0 - && (i[1] & 0xc0) == 0x80) - { - tmp_path += i[0]; - tmp_path += i[1]; - i += 1; - continue; - } - - if (std::distance(i, end) < 3) - { - convert_to_utf8(tmp_path, *i); - valid_encoding = false; - continue; - } - - // valid 3-byte utf-8 character - if ((i[0] & 0xf0) == 0xe0 - && (i[1] & 0xc0) == 0x80 - && (i[2] & 0xc0) == 0x80) - { - tmp_path += i[0]; - tmp_path += i[1]; - tmp_path += i[2]; - i += 2; - continue; - } - - if (std::distance(i, end) < 4) - { - convert_to_utf8(tmp_path, *i); - valid_encoding = false; - continue; - } - - // valid 4-byte utf-8 character - if ((i[0] & 0xf0) == 0xe0 - && (i[1] & 0xc0) == 0x80 - && (i[2] & 0xc0) == 0x80 - && (i[3] & 0xc0) == 0x80) - { - tmp_path += i[0]; - tmp_path += i[1]; - tmp_path += i[2]; - tmp_path += i[3]; - i += 3; - continue; - } - - convert_to_utf8(tmp_path, *i); - valid_encoding = false; - } - // the encoding was not valid utf-8 - // save the original encoding and replace the - // commonly used path with the correctly - // encoded string - if (!valid_encoding) target = tmp_path; - return valid_encoding; - } - - void verify_encoding(file_entry& target) - { - std::string p = target.path.string(); - if (!verify_encoding(p)) target.path = p; - } - - bool extract_single_file(lazy_entry const& dict, file_entry& target - , std::string const& root_dir) - { - lazy_entry const* length = dict.dict_find("length"); - if (length == 0 || length->type() != lazy_entry::int_t) - return false; - target.size = length->int_value(); - target.path = root_dir; - target.file_base = 0; - - // prefer the name.utf-8 - // because if it exists, it is more - // likely to be correctly encoded - - lazy_entry const* p = dict.dict_find("path.utf-8"); - if (p == 0 || p->type() != lazy_entry::list_t) - p = dict.dict_find("path"); - if (p == 0 || p->type() != lazy_entry::list_t) - return false; - - for (int i = 0, end(p->list_size()); i < end; ++i) - { - if (p->list_at(i)->type() != lazy_entry::string_t) - return false; - std::string path_element = p->list_at(i)->string_value(); - if (path_element != "..") - target.path /= path_element; - } - verify_encoding(target); - if (target.path.is_complete()) - return false; - return true; - } - - bool extract_files(lazy_entry const& list, file_storage& target - , std::string const& root_dir) - { - if (list.type() != lazy_entry::list_t) return false; - for (int i = 0, end(list.list_size()); i < end; ++i) - { - file_entry e; - if (!extract_single_file(*list.list_at(i), e, root_dir)) - return false; - target.add_file(e); - } - return true; - } -} - -namespace libtorrent -{ - - int load_file(fs::path const& filename, std::vector& v) - { - file f; - error_code ec; - if (!f.open(filename, file::in, ec)) return -1; - f.seek(0, file::end, ec); - if (ec) return -1; - size_type s = f.tell(ec); - if (ec) return -1; - if (s > 5000000) return -2; - v.resize(s); - if (s == 0) return 0; - f.seek(0, file::begin, ec); - if (ec) return -1; - size_type read = f.read(&v[0], s, ec); - if (read != s) return -3; - if (ec) return -3; - return 0; - } - -#ifndef TORRENT_NO_DEPRECATE - // standard constructor that parses a torrent file - torrent_info::torrent_info(entry const& torrent_file) - : m_creation_date(pt::ptime(pt::not_a_date_time)) - , m_multifile(false) - , m_private(false) - , m_info_section_size(0) - , m_piece_hashes(0) - { - std::vector tmp; - std::back_insert_iterator > out(tmp); - bencode(out, torrent_file); - - lazy_entry e; - lazy_bdecode(&tmp[0], &tmp[0] + tmp.size(), e); - std::string error; -#ifndef BOOST_NO_EXCEPTIONS - if (!parse_torrent_file(e, error)) - throw invalid_torrent_file(); -#else - parse_torrent_file(e, error); -#endif - } -#endif - - torrent_info::torrent_info(lazy_entry const& torrent_file) - : m_creation_date(pt::ptime(pt::not_a_date_time)) - , m_multifile(false) - , m_private(false) - , m_info_section_size(0) - , m_piece_hashes(0) - { - std::string error; -#ifndef BOOST_NO_EXCEPTIONS - if (!parse_torrent_file(torrent_file, error)) - throw invalid_torrent_file(); -#else - parse_torrent_file(torrent_file, error); -#endif - } - - torrent_info::torrent_info(char const* buffer, int size) - : m_creation_date(pt::ptime(pt::not_a_date_time)) - , m_multifile(false) - , m_private(false) - , m_info_section_size(0) - , m_piece_hashes(0) - { - std::string error; - lazy_entry e; - lazy_bdecode(buffer, buffer + size, e); -#ifndef BOOST_NO_EXCEPTIONS - if (!parse_torrent_file(e, error)) - throw invalid_torrent_file(); -#else - parse_torrent_file(e, error); -#endif - } - - // constructor used for creating new torrents - // will not contain any hashes, comments, creation date - // just the necessary to use it with piece manager - // used for torrents with no metadata - torrent_info::torrent_info(sha1_hash const& info_hash) - : m_info_hash(info_hash) - , m_creation_date(pt::second_clock::universal_time()) - , m_multifile(false) - , m_private(false) - , m_info_section_size(0) - , m_piece_hashes(0) - {} - - torrent_info::torrent_info(fs::path const& filename) - : m_creation_date(pt::ptime(pt::not_a_date_time)) - , m_multifile(false) - , m_private(false) - { - std::vector buf; - int ret = load_file(filename, buf); - if (ret < 0) return; - - if (buf.empty()) -#ifndef BOOST_NO_EXCEPTIONS - throw invalid_torrent_file(); -#else - return; -#endif - - lazy_entry e; - lazy_bdecode(&buf[0], &buf[0] + buf.size(), e); - std::string error; -#ifndef BOOST_NO_EXCEPTIONS - if (!parse_torrent_file(e, error)) - throw invalid_torrent_file(); -#else - parse_torrent_file(e, error); -#endif - } - - torrent_info::~torrent_info() - {} - - void torrent_info::copy_on_write() - { - if (m_orig_files) return; - m_orig_files.reset(new file_storage(m_files)); - } - - void torrent_info::swap(torrent_info& ti) - { - using std::swap; - m_urls.swap(ti.m_urls); - m_url_seeds.swap(ti.m_url_seeds); - m_files.swap(ti.m_files); - m_orig_files.swap(ti.m_orig_files); - m_nodes.swap(ti.m_nodes); - swap(m_info_hash, ti.m_info_hash); - swap(m_creation_date, ti.m_creation_date); - m_comment.swap(ti.m_comment); - m_created_by.swap(ti.m_created_by); - swap(m_multifile, ti.m_multifile); - swap(m_private, ti.m_private); - swap(m_info_section, ti.m_info_section); - swap(m_info_section_size, ti.m_info_section_size); - swap(m_piece_hashes, ti.m_piece_hashes); - swap(m_info_dict, ti.m_info_dict); - } - - bool torrent_info::parse_info_section(lazy_entry const& info, std::string& error) - { - if (info.type() != lazy_entry::dict_t) - { - error = "'info' entry is not a dictionary"; - return false; - } - - // hash the info-field to calculate info-hash - hasher h; - std::pair section = info.data_section(); - h.update(section.first, section.second); - m_info_hash = h.final(); - - // copy the info section - m_info_section_size = section.second; - m_info_section.reset(new char[m_info_section_size]); - std::memcpy(m_info_section.get(), section.first, m_info_section_size); - TORRENT_ASSERT(section.first[0] == 'd'); - TORRENT_ASSERT(section.first[m_info_section_size-1] == 'e'); - - // extract piece length - int piece_length = info.dict_find_int_value("piece length", -1); - if (piece_length <= 0) - { - error = "invalid or missing 'piece length' entry in torrent file"; - return false; - } - m_files.set_piece_length(piece_length); - - // extract file name (or the directory name if it's a multifile libtorrent) - std::string name = info.dict_find_string_value("name.utf-8"); - if (name.empty()) name = info.dict_find_string_value("name"); - if (name.empty()) - { - error = "missing name in torrent file"; - return false; - } - - fs::path tmp = name; - if (tmp.is_complete()) - { - name = tmp.leaf(); - } -#if BOOST_VERSION < 103600 - else if (tmp.has_branch_path()) -#else - else if (tmp.has_parent_path()) -#endif - { - fs::path p; - for (fs::path::iterator i = tmp.begin() - , end(tmp.end()); i != end; ++i) - { - if (*i == "." || *i == "..") continue; - p /= *i; - } - name = p.string(); - } - if (name == ".." || name == ".") - { - error = "invalid 'name' of torrent (possible exploit attempt)"; - return false; - } - - // correct utf-8 encoding errors - verify_encoding(name); - - // extract file list - lazy_entry const* i = info.dict_find_list("files"); - if (i == 0) - { - // if there's no list of files, there has to be a length - // field. - file_entry e; - e.path = name; - e.offset = 0; - e.size = info.dict_find_int_value("length", -1); - if (e.size < 0) - { - error = "invalid length of torrent"; - return false; - } - m_files.add_file(e); - m_multifile = false; - } - else - { - if (!extract_files(*i, m_files, name)) - { - error = "failed to parse files from torrent file"; - return false; - } - m_multifile = true; - } - m_files.set_name(name); - - // extract sha-1 hashes for all pieces - // we want this division to round upwards, that's why we have the - // extra addition - - m_files.set_num_pieces(int((m_files.total_size() + m_files.piece_length() - 1) - / m_files.piece_length())); - - lazy_entry const* pieces = info.dict_find("pieces"); - if (pieces == 0 || pieces->type() != lazy_entry::string_t) - { - error = "invalid or missing 'pieces' entry in torrent file"; - return false; - } - - if (pieces->string_length() != m_files.num_pieces() * 20) - { - error = "incorrect number of piece hashes in torrent file"; - return false; - } - - m_piece_hashes = m_info_section.get() + (pieces->string_ptr() - section.first); - TORRENT_ASSERT(m_piece_hashes >= m_info_section.get()); - TORRENT_ASSERT(m_piece_hashes < m_info_section.get() + m_info_section_size); - - m_private = info.dict_find_int_value("private", 0); - return true; - } - - bool torrent_info::parse_torrent_file(lazy_entry const& torrent_file, std::string& error) - { - if (torrent_file.type() != lazy_entry::dict_t) - { - error = "torrent file is not a dictionary"; - return false; - } - - // extract the url of the tracker - lazy_entry const* i = torrent_file.dict_find_list("announce-list"); - if (i) - { - m_urls.reserve(i->list_size()); - for (int j = 0, end(i->list_size()); j < end; ++j) - { - lazy_entry const* tier = i->list_at(j); - if (tier->type() != lazy_entry::list_t) continue; - for (int k = 0, end(tier->list_size()); k < end; ++k) - { - announce_entry e(tier->list_string_value_at(k)); - if (e.url.empty()) continue; - e.tier = j; - m_urls.push_back(e); - } - } - - if (!m_urls.empty()) - { - // shuffle each tier - std::vector::iterator start = m_urls.begin(); - std::vector::iterator stop; - int current_tier = m_urls.front().tier; - for (stop = m_urls.begin(); stop != m_urls.end(); ++stop) - { - if (stop->tier != current_tier) - { - std::random_shuffle(start, stop); - start = stop; - current_tier = stop->tier; - } - } - std::random_shuffle(start, stop); - } - } - - - if (m_urls.empty()) - { - announce_entry e(torrent_file.dict_find_string_value("announce")); - if (!e.url.empty()) m_urls.push_back(e); - } - - lazy_entry const* nodes = torrent_file.dict_find_list("nodes"); - if (nodes) - { - for (int i = 0, end(nodes->list_size()); i < end; ++i) - { - lazy_entry const* n = nodes->list_at(i); - if (n->type() != lazy_entry::list_t - || n->list_size() < 2 - || n->list_at(0)->type() != lazy_entry::string_t - || n->list_at(1)->type() != lazy_entry::int_t) - continue; - m_nodes.push_back(std::make_pair( - n->list_at(0)->string_value() - , int(n->list_at(1)->int_value()))); - } - } - - // extract creation date - size_type cd = torrent_file.dict_find_int_value("creation date", -1); - if (cd >= 0) - { - m_creation_date = pt::ptime(gr::date(1970, gr::Jan, 1)) - + pt::seconds(long(cd)); - } - - // if there are any url-seeds, extract them - lazy_entry const* url_seeds = torrent_file.dict_find("url-list"); - if (url_seeds && url_seeds->type() == lazy_entry::string_t) - { - m_url_seeds.push_back(url_seeds->string_value()); - } - else if (url_seeds && url_seeds->type() == lazy_entry::list_t) - { - for (int i = 0, end(url_seeds->list_size()); i < end; ++i) - { - lazy_entry const* url = url_seeds->list_at(i); - if (url->type() != lazy_entry::string_t) continue; - m_url_seeds.push_back(url->string_value()); - } - } - - m_comment = torrent_file.dict_find_string_value("comment.utf-8"); - if (m_comment.empty()) m_comment = torrent_file.dict_find_string_value("comment"); - verify_encoding(m_comment); - - m_created_by = torrent_file.dict_find_string_value("created by.utf-8"); - if (m_created_by.empty()) m_created_by = torrent_file.dict_find_string_value("created by"); - verify_encoding(m_created_by); - - lazy_entry const* info = torrent_file.dict_find_dict("info"); - if (info == 0) - { - error = "missing or invalid 'info' section in torrent file"; - return false; - } - return parse_info_section(*info, error); - } - - boost::optional - torrent_info::creation_date() const - { - if (m_creation_date != pt::ptime(gr::date(pt::not_a_date_time))) - { - return boost::optional(m_creation_date); - } - return boost::optional(); - } - - void torrent_info::add_tracker(std::string const& url, int tier) - { - announce_entry e(url); - e.tier = tier; - m_urls.push_back(e); - - using boost::bind; - std::sort(m_urls.begin(), m_urls.end(), boost::bind(std::less() - , bind(&announce_entry::tier, _1), bind(&announce_entry::tier, _2))); - } - -#ifndef TORRENT_NO_DEPRECATE -// ------- start deprecation ------- - - void torrent_info::print(std::ostream& os) const - { - os << "trackers:\n"; - for (std::vector::const_iterator i = trackers().begin(); - i != trackers().end(); ++i) - { - os << i->tier << ": " << i->url << "\n"; - } - if (!m_comment.empty()) - os << "comment: " << m_comment << "\n"; -// if (m_creation_date != pt::ptime(gr::date(pt::not_a_date_time))) -// os << "creation date: " << to_simple_string(m_creation_date) << "\n"; - os << "private: " << (m_private?"yes":"no") << "\n"; - os << "number of pieces: " << num_pieces() << "\n"; - os << "piece length: " << piece_length() << "\n"; - os << "files:\n"; - for (file_storage::iterator i = m_files.begin(); i != m_files.end(); ++i) - os << " " << std::setw(11) << i->size << " " << i->path.string() << "\n"; - } - -// ------- end deprecation ------- -#endif - -} - diff --git a/libtorrent/src/tracker_manager.cpp b/libtorrent/src/tracker_manager.cpp deleted file mode 100755 index 621c3b99c..000000000 --- a/libtorrent/src/tracker_manager.cpp +++ /dev/null @@ -1,284 +0,0 @@ -/* - -Copyright (c) 2003, Arvid Norberg -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions -are met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in - the documentation and/or other materials provided with the distribution. - * Neither the name of the author nor the names of its - contributors may be used to endorse or promote products derived - from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -POSSIBILITY OF SUCH DAMAGE. - -*/ - -#include "libtorrent/pch.hpp" - -#include -#include -#include -#include -#include - -#include - -#include "libtorrent/tracker_manager.hpp" -#include "libtorrent/http_tracker_connection.hpp" -#include "libtorrent/udp_tracker_connection.hpp" -#include "libtorrent/entry.hpp" -#include "libtorrent/bencode.hpp" -#include "libtorrent/torrent.hpp" -#include "libtorrent/peer_connection.hpp" - -using namespace libtorrent; -using boost::tuples::make_tuple; -using boost::tuples::tuple; -using boost::bind; - -namespace -{ - enum - { - minimum_tracker_response_length = 3, - http_buffer_size = 2048 - }; - -} - -namespace libtorrent -{ - timeout_handler::timeout_handler(io_service& ios) - : m_start_time(time_now()) - , m_read_time(time_now()) - , m_timeout(ios) - , m_completion_timeout(0) - , m_read_timeout(0) - , m_abort(false) - {} - - void timeout_handler::set_timeout(int completion_timeout, int read_timeout) - { - m_completion_timeout = completion_timeout; - m_read_timeout = read_timeout; - m_start_time = m_read_time = time_now(); - - if (m_abort) return; - - int timeout = (std::min)( - m_read_timeout, (std::min)(m_completion_timeout, m_read_timeout)); - error_code ec; - m_timeout.expires_at(m_read_time + seconds(timeout), ec); - m_timeout.async_wait(bind( - &timeout_handler::timeout_callback, self(), _1)); - } - - void timeout_handler::restart_read_timeout() - { - m_read_time = time_now(); - } - - void timeout_handler::cancel() - { - m_abort = true; - m_completion_timeout = 0; - error_code ec; - m_timeout.cancel(ec); - } - - void timeout_handler::timeout_callback(error_code const& error) - { - if (error) return; - if (m_completion_timeout == 0) return; - - ptime now(time_now()); - time_duration receive_timeout = now - m_read_time; - time_duration completion_timeout = now - m_start_time; - - if (m_read_timeout - < total_seconds(receive_timeout) - || m_completion_timeout - < total_seconds(completion_timeout)) - { - on_timeout(); - return; - } - - if (m_abort) return; - - int timeout = (std::min)( - m_read_timeout, (std::min)(m_completion_timeout, m_read_timeout)); - error_code ec; - m_timeout.expires_at(m_read_time + seconds(timeout), ec); - m_timeout.async_wait( - bind(&timeout_handler::timeout_callback, self(), _1)); - } - - tracker_connection::tracker_connection( - tracker_manager& man - , tracker_request const& req - , io_service& ios - , address bind_interface_ - , boost::weak_ptr r) - : timeout_handler(ios) - , m_requester(r) - , m_bind_interface(bind_interface_) - , m_man(man) - , m_req(req) - {} - - boost::shared_ptr tracker_connection::requester() - { - return m_requester.lock(); - } - - void tracker_connection::fail(int code, char const* msg) - { - boost::shared_ptr cb = requester(); - if (cb) cb->tracker_request_error(m_req, code, msg); - close(); - } - - void tracker_connection::fail_timeout() - { - boost::shared_ptr cb = requester(); - if (cb) cb->tracker_request_timed_out(m_req); - close(); - } - - void tracker_connection::close() - { - cancel(); - m_man.remove_request(this); - } - - void tracker_manager::remove_request(tracker_connection const* c) - { - mutex_t::scoped_lock l(m_mutex); - - tracker_connections_t::iterator i = std::find(m_connections.begin() - , m_connections.end(), boost::intrusive_ptr(c)); - if (i == m_connections.end()) return; - - m_connections.erase(i); - } - - void tracker_manager::queue_request( - io_service& ios - , connection_queue& cc - , tracker_request req - , std::string const& auth - , address bind_infc - , boost::weak_ptr c) - { - mutex_t::scoped_lock l(m_mutex); - TORRENT_ASSERT(req.num_want >= 0); - if (req.event == tracker_request::stopped) - req.num_want = 0; - - TORRENT_ASSERT(!m_abort || req.event == tracker_request::stopped); - if (m_abort && req.event != tracker_request::stopped) - return; - - std::string protocol = req.url.substr(0, req.url.find(':')); - - boost::intrusive_ptr con; - -#ifdef TORRENT_USE_OPENSSL - if (protocol == "http" || protocol == "https") -#else - if (protocol == "http") -#endif - { - con = new http_tracker_connection( - ios, cc, *this, req, bind_infc, c - , m_settings, m_proxy, auth); - } - else if (protocol == "udp") - { - con = new udp_tracker_connection( - ios, cc, *this, req, bind_infc - , c, m_settings, m_proxy); - } - else - { - if (boost::shared_ptr r = c.lock()) - r->tracker_request_error(req, -1, "unknown protocol in tracker url: " - + req.url); - return; - } - - m_connections.push_back(con); - - boost::shared_ptr cb = con->requester(); - if (cb) cb->m_manager = this; - con->start(); - } - - void tracker_manager::abort_all_requests() - { - // removes all connections from m_connections - // except those with a requester == 0 (since those are - // 'event=stopped'-requests) - mutex_t::scoped_lock l(m_mutex); - - m_abort = true; - tracker_connections_t keep_connections; - - while (!m_connections.empty()) - { - boost::intrusive_ptr& c = m_connections.back(); - if (!c) - { - m_connections.pop_back(); - continue; - } - tracker_request const& req = c->tracker_req(); - if (req.event == tracker_request::stopped) - { - keep_connections.push_back(c); - m_connections.pop_back(); - continue; - } - // close will remove the entry from m_connections - // so no need to pop - -#if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_LOGGING || defined TORRENT_ERROR_LOGGING - boost::shared_ptr rc = c->requester(); - if (rc) rc->debug_log("aborting: " + req.url); -#endif - c->close(); - } - - std::swap(m_connections, keep_connections); - } - - bool tracker_manager::empty() const - { - mutex_t::scoped_lock l(m_mutex); - return m_connections.empty(); - } - - int tracker_manager::num_requests() const - { - mutex_t::scoped_lock l(m_mutex); - return m_connections.size(); - } -} diff --git a/libtorrent/src/udp_socket.cpp b/libtorrent/src/udp_socket.cpp deleted file mode 100644 index d8d3fcc29..000000000 --- a/libtorrent/src/udp_socket.cpp +++ /dev/null @@ -1,618 +0,0 @@ -/* - -Copyright (c) 2007, Arvid Norberg -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions -are met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in - the documentation and/or other materials provided with the distribution. - * Neither the name of the author nor the names of its - contributors may be used to endorse or promote products derived - from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -POSSIBILITY OF SUCH DAMAGE. - -*/ - -#include "libtorrent/udp_socket.hpp" -#include "libtorrent/connection_queue.hpp" -#include "libtorrent/escape_string.hpp" -#include -#include -#include -#if BOOST_VERSION < 103500 -#include -#else -#include -#endif - -using namespace libtorrent; - -udp_socket::udp_socket(asio::io_service& ios, udp_socket::callback_t const& c - , connection_queue& cc) - : m_callback(c) - , m_ipv4_sock(ios) - , m_ipv6_sock(ios) - , m_bind_port(0) - , m_outstanding(0) - , m_socks5_sock(ios) - , m_connection_ticket(-1) - , m_cc(cc) - , m_resolver(ios) - , m_tunnel_packets(false) - , m_abort(false) -{ -#ifdef TORRENT_DEBUG - m_magic = 0x1337; -#endif -} - -udp_socket::~udp_socket() -{ -#ifdef TORRENT_DEBUG - TORRENT_ASSERT(m_magic == 0x1337); - TORRENT_ASSERT(!m_callback); - TORRENT_ASSERT(m_outstanding == 0); - m_magic = 0; -#endif -} - -#ifdef TORRENT_DEBUG - #define CHECK_MAGIC check_magic_ cm_(m_magic) - struct check_magic_ - { - check_magic_(int& m_): m(m_) { TORRENT_ASSERT(m == 0x1337); } - ~check_magic_() { TORRENT_ASSERT(m == 0x1337); } - int& m; - }; -#else - #define CHECK_MAGIC do {} while (false) -#endif - -void udp_socket::send(udp::endpoint const& ep, char const* p, int len, error_code& ec) -{ - CHECK_MAGIC; - // if the sockets are closed, the udp_socket is closing too - if (!m_ipv4_sock.is_open() && !m_ipv6_sock.is_open()) return; - - if (m_tunnel_packets) - { - // send udp packets through SOCKS5 server - wrap(ep, p, len, ec); - return; - } - - if (ep.address().is_v4() && m_ipv4_sock.is_open()) - m_ipv4_sock.send_to(asio::buffer(p, len), ep, 0, ec); - else - m_ipv6_sock.send_to(asio::buffer(p, len), ep, 0, ec); -} - -void udp_socket::on_read(udp::socket* s, error_code const& e, std::size_t bytes_transferred) -{ - TORRENT_ASSERT(m_magic == 0x1337); - mutex_t::scoped_lock l(m_mutex); - - TORRENT_ASSERT(m_outstanding > 0); - --m_outstanding; - - if (e == asio::error::operation_aborted) - { - if (m_outstanding == 0) - { - // "this" may be destructed in the callback - // that's why we need to unlock - callback_t tmp = m_callback; - m_callback.clear(); - l.unlock(); - } - return; - } - - CHECK_MAGIC; - if (!m_callback) return; - - if (e) - { - l.unlock(); -#ifndef BOOST_NO_EXCEPTIONS - try { -#endif - if (s == &m_ipv4_sock) - m_callback(e, m_v4_ep, 0, 0); - else - m_callback(e, m_v6_ep, 0, 0); -#ifndef BOOST_NO_EXCEPTIONS - } catch(std::exception&) {} -#endif - l.lock(); - - // don't stop listening on recoverable errors - if (e != asio::error::host_unreachable - && e != asio::error::fault - && e != asio::error::connection_reset - && e != asio::error::connection_refused - && e != asio::error::connection_aborted - && e != asio::error::message_size) - { - if (m_outstanding == 0) - { - // "this" may be destructed in the callback - // that's why we need to unlock - callback_t tmp = m_callback; - m_callback.clear(); - l.unlock(); - } - return; - } - - if (m_abort) return; - - if (s == &m_ipv4_sock) - s->async_receive_from(asio::buffer(m_v4_buf, sizeof(m_v4_buf)) - , m_v4_ep, boost::bind(&udp_socket::on_read, this, s, _1, _2)); - else - s->async_receive_from(asio::buffer(m_v6_buf, sizeof(m_v6_buf)) - , m_v6_ep, boost::bind(&udp_socket::on_read, this, s, _1, _2)); - - ++m_outstanding; - return; - } - - if (s == &m_ipv4_sock) - { -#ifndef BOOST_NO_EXCEPTIONS - try { -#endif - - if (m_tunnel_packets && m_v4_ep == m_proxy_addr) - { - l.unlock(); - unwrap(e, m_v4_buf, bytes_transferred); - } - else - { - l.unlock(); - m_callback(e, m_v4_ep, m_v4_buf, bytes_transferred); - } - l.lock(); - -#ifndef BOOST_NO_EXCEPTIONS - } catch(std::exception&) {} -#endif - - if (m_abort) return; - - s->async_receive_from(asio::buffer(m_v4_buf, sizeof(m_v4_buf)) - , m_v4_ep, boost::bind(&udp_socket::on_read, this, s, _1, _2)); - } - else - { -#ifndef BOOST_NO_EXCEPTIONS - try { -#endif - - if (m_tunnel_packets && m_v6_ep == m_proxy_addr) - { - l.unlock(); - unwrap(e, m_v6_buf, bytes_transferred); - } - else - { - l.unlock(); - m_callback(e, m_v6_ep, m_v6_buf, bytes_transferred); - } - -#ifndef BOOST_NO_EXCEPTIONS - } catch(std::exception&) {} -#endif - l.lock(); - - if (m_abort) return; - - s->async_receive_from(asio::buffer(m_v6_buf, sizeof(m_v6_buf)) - , m_v6_ep, boost::bind(&udp_socket::on_read, this, s, _1, _2)); - } - ++m_outstanding; -} - -void udp_socket::wrap(udp::endpoint const& ep, char const* p, int len, error_code& ec) -{ - CHECK_MAGIC; - using namespace libtorrent::detail; - - char header[20]; - char* h = header; - - write_uint16(0, h); // reserved - write_uint8(0, h); // fragment - write_uint8(ep.address().is_v4()?1:4, h); // atyp - write_address(ep.address(), h); - write_uint16(ep.port(), h); - - boost::array iovec; - iovec[0] = asio::const_buffer(header, h - header); - iovec[1] = asio::const_buffer(p, len); - - if (m_proxy_addr.address().is_v4() && m_ipv4_sock.is_open()) - m_ipv4_sock.send_to(iovec, m_proxy_addr, 0, ec); - else - m_ipv6_sock.send_to(iovec, m_proxy_addr, 0, ec); -} - -// unwrap the UDP packet from the SOCKS5 header -void udp_socket::unwrap(error_code const& e, char const* buf, int size) -{ - CHECK_MAGIC; - using namespace libtorrent::detail; - - // the minimum socks5 header size - if (size <= 10) return; - - char const* p = buf; - p += 2; // reserved - int frag = read_uint8(p); - // fragmentation is not supported - if (frag != 0) return; - - udp::endpoint sender; - - int atyp = read_uint8(p); - if (atyp == 1) - { - // IPv4 - sender = read_v4_endpoint(p); - } - else if (atyp == 4) - { - // IPv6 - sender = read_v6_endpoint(p); - } - else - { - // domain name not supported - return; - } - - m_callback(e, sender, p, size - (p - buf)); -} - -void udp_socket::close() -{ - mutex_t::scoped_lock l(m_mutex); - TORRENT_ASSERT(m_magic == 0x1337); - - error_code ec; - m_ipv4_sock.close(ec); - m_ipv6_sock.close(ec); - m_socks5_sock.close(ec); - m_resolver.cancel(); - m_abort = true; - if (m_connection_ticket >= 0) - { - m_cc.done(m_connection_ticket); - m_connection_ticket = -1; - } - - if (m_outstanding == 0) - { - // "this" may be destructed in the callback - callback_t tmp = m_callback; - m_callback.clear(); - l.unlock(); - } -} - -void udp_socket::bind(udp::endpoint const& ep, error_code& ec) -{ - CHECK_MAGIC; - mutex_t::scoped_lock l(m_mutex); - - if (m_ipv4_sock.is_open()) m_ipv4_sock.close(ec); - if (m_ipv6_sock.is_open()) m_ipv6_sock.close(ec); - - if (ep.address().is_v4()) - { - m_ipv4_sock.open(udp::v4(), ec); - if (ec) return; - m_ipv4_sock.bind(ep, ec); - if (ec) return; - m_ipv4_sock.async_receive_from(asio::buffer(m_v4_buf, sizeof(m_v4_buf)) - , m_v4_ep, boost::bind(&udp_socket::on_read, this, &m_ipv4_sock, _1, _2)); - } - else - { - m_ipv6_sock.set_option(v6only(true), ec); - if (ec) return; - m_ipv6_sock.bind(ep, ec); - if (ec) return; - m_ipv6_sock.async_receive_from(asio::buffer(m_v6_buf, sizeof(m_v6_buf)) - , m_v6_ep, boost::bind(&udp_socket::on_read, this, &m_ipv6_sock, _1, _2)); - } - ++m_outstanding; - m_bind_port = ep.port(); -} - -void udp_socket::bind(int port) -{ - CHECK_MAGIC; - mutex_t::scoped_lock l(m_mutex); - - error_code ec; - - if (m_ipv4_sock.is_open()) m_ipv4_sock.close(ec); - if (m_ipv6_sock.is_open()) m_ipv6_sock.close(ec); - - m_ipv4_sock.open(udp::v4(), ec); - if (!ec) - { - m_ipv4_sock.bind(udp::endpoint(address_v4::any(), port), ec); - m_ipv4_sock.async_receive_from(asio::buffer(m_v4_buf, sizeof(m_v4_buf)) - , m_v4_ep, boost::bind(&udp_socket::on_read, this, &m_ipv4_sock, _1, _2)); - ++m_outstanding; - } - m_ipv6_sock.open(udp::v6(), ec); - if (!ec) - { - m_ipv6_sock.set_option(v6only(true), ec); - m_ipv6_sock.bind(udp::endpoint(address_v6::any(), port), ec); - m_ipv6_sock.async_receive_from(asio::buffer(m_v6_buf, sizeof(m_v6_buf)) - , m_v6_ep, boost::bind(&udp_socket::on_read, this, &m_ipv6_sock, _1, _2)); - ++m_outstanding; - } - m_bind_port = port; -} - -void udp_socket::set_proxy_settings(proxy_settings const& ps) -{ - CHECK_MAGIC; - mutex_t::scoped_lock l(m_mutex); - - error_code ec; - m_socks5_sock.close(ec); - m_tunnel_packets = false; - - m_proxy_settings = ps; - - if (ps.type == proxy_settings::socks5 - || ps.type == proxy_settings::socks5_pw) - { - // connect to socks5 server and open up the UDP tunnel - tcp::resolver::query q(ps.hostname, to_string(ps.port).elems); - m_resolver.async_resolve(q, boost::bind( - &udp_socket::on_name_lookup, this, _1, _2)); - } -} - -void udp_socket::on_name_lookup(error_code const& e, tcp::resolver::iterator i) -{ - if (e) return; - CHECK_MAGIC; - - mutex_t::scoped_lock l(m_mutex); - - m_proxy_addr.address(i->endpoint().address()); - m_proxy_addr.port(i->endpoint().port()); - l.unlock(); // on_connect may be called from within this thread - m_cc.enqueue(boost::bind(&udp_socket::on_connect, this, _1) - , boost::bind(&udp_socket::on_timeout, this), seconds(10)); -} - -void udp_socket::on_timeout() -{ - CHECK_MAGIC; - mutex_t::scoped_lock l(m_mutex); - - error_code ec; - m_socks5_sock.close(ec); - m_connection_ticket = -1; -} - -void udp_socket::on_connect(int ticket) -{ - CHECK_MAGIC; - mutex_t::scoped_lock l(m_mutex); - - m_connection_ticket = ticket; - error_code ec; - m_socks5_sock.open(m_proxy_addr.address().is_v4()?tcp::v4():tcp::v6(), ec); - m_socks5_sock.async_connect(tcp::endpoint(m_proxy_addr.address(), m_proxy_addr.port()) - , boost::bind(&udp_socket::on_connected, this, _1)); -} - -void udp_socket::on_connected(error_code const& e) -{ - CHECK_MAGIC; - - mutex_t::scoped_lock l(m_mutex); - m_cc.done(m_connection_ticket); - m_connection_ticket = -1; - if (e) return; - - using namespace libtorrent::detail; - - // send SOCKS5 authentication methods - char* p = &m_tmp_buf[0]; - write_uint8(5, p); // SOCKS VERSION 5 - if (m_proxy_settings.username.empty() - || m_proxy_settings.type == proxy_settings::socks5) - { - write_uint8(1, p); // 1 authentication method (no auth) - write_uint8(0, p); // no authentication - } - else - { - write_uint8(2, p); // 2 authentication methods - write_uint8(0, p); // no authentication - write_uint8(2, p); // username/password - } - asio::async_write(m_socks5_sock, asio::buffer(m_tmp_buf, p - m_tmp_buf) - , boost::bind(&udp_socket::handshake1, this, _1)); -} - -void udp_socket::handshake1(error_code const& e) -{ - CHECK_MAGIC; - if (e) return; - - mutex_t::scoped_lock l(m_mutex); - - asio::async_read(m_socks5_sock, asio::buffer(m_tmp_buf, 2) - , boost::bind(&udp_socket::handshake2, this, _1)); -} - -void udp_socket::handshake2(error_code const& e) -{ - CHECK_MAGIC; - if (e) return; - - using namespace libtorrent::detail; - - mutex_t::scoped_lock l(m_mutex); - - char* p = &m_tmp_buf[0]; - int version = read_uint8(p); - int method = read_uint8(p); - - if (version < 5) return; - - if (method == 0) - { - socks_forward_udp(); - } - else if (method == 2) - { - if (m_proxy_settings.username.empty()) - { - error_code ec; - m_socks5_sock.close(ec); - return; - } - - // start sub-negotiation - char* p = &m_tmp_buf[0]; - write_uint8(1, p); - write_uint8(m_proxy_settings.username.size(), p); - write_string(m_proxy_settings.username, p); - write_uint8(m_proxy_settings.password.size(), p); - write_string(m_proxy_settings.password, p); - asio::async_write(m_socks5_sock, asio::buffer(m_tmp_buf, p - m_tmp_buf) - , boost::bind(&udp_socket::handshake3, this, _1)); - } - else - { - error_code ec; - m_socks5_sock.close(ec); - return; - } -} - -void udp_socket::handshake3(error_code const& e) -{ - CHECK_MAGIC; - if (e) return; - - mutex_t::scoped_lock l(m_mutex); - - asio::async_read(m_socks5_sock, asio::buffer(m_tmp_buf, 2) - , boost::bind(&udp_socket::handshake4, this, _1)); -} - -void udp_socket::handshake4(error_code const& e) -{ - CHECK_MAGIC; - if (e) return; - - mutex_t::scoped_lock l(m_mutex); - - using namespace libtorrent::detail; - - char* p = &m_tmp_buf[0]; - int version = read_uint8(p); - int status = read_uint8(p); - - if (version != 1) return; - if (status != 0) return; - - socks_forward_udp(); -} - -void udp_socket::socks_forward_udp() -{ - CHECK_MAGIC; - using namespace libtorrent::detail; - - mutex_t::scoped_lock l(m_mutex); - - // send SOCKS5 UDP command - char* p = &m_tmp_buf[0]; - write_uint8(5, p); // SOCKS VERSION 5 - write_uint8(3, p); // UDP ASSOCIATE command - write_uint8(0, p); // reserved - write_uint8(0, p); // ATYP IPv4 - write_uint32(0, p); // IP any - write_uint16(m_bind_port, p); - - asio::async_write(m_socks5_sock, asio::buffer(m_tmp_buf, p - m_tmp_buf) - , boost::bind(&udp_socket::connect1, this, _1)); -} - -void udp_socket::connect1(error_code const& e) -{ - CHECK_MAGIC; - if (e) return; - - mutex_t::scoped_lock l(m_mutex); - - asio::async_read(m_socks5_sock, asio::buffer(m_tmp_buf, 10) - , boost::bind(&udp_socket::connect2, this, _1)); -} - -void udp_socket::connect2(error_code const& e) -{ - CHECK_MAGIC; - if (e) return; - - mutex_t::scoped_lock l(m_mutex); - - using namespace libtorrent::detail; - - char* p = &m_tmp_buf[0]; - int version = read_uint8(p); // VERSION - int status = read_uint8(p); // STATUS - read_uint8(p); // RESERVED - int atyp = read_uint8(p); // address type - - if (version != 5) return; - if (status != 0) return; - - if (atyp == 1) - { - m_proxy_addr.address(address_v4(read_uint32(p))); - m_proxy_addr.port(read_uint16(p)); - } - else - { - // in this case we need to read more data from the socket - TORRENT_ASSERT(false && "not implemented yet!"); - } - - m_tunnel_packets = true; -} - diff --git a/libtorrent/src/udp_tracker_connection.cpp b/libtorrent/src/udp_tracker_connection.cpp deleted file mode 100755 index 01d4224c5..000000000 --- a/libtorrent/src/udp_tracker_connection.cpp +++ /dev/null @@ -1,525 +0,0 @@ -/* - -Copyright (c) 2003, Arvid Norberg -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions -are met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in - the documentation and/or other materials provided with the distribution. - * Neither the name of the author nor the names of its - contributors may be used to endorse or promote products derived - from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -POSSIBILITY OF SUCH DAMAGE. - -*/ - -#include "libtorrent/pch.hpp" - -#include -#include -#include -#include -#include - -#include "zlib.h" - -#ifdef _MSC_VER -#pragma warning(push, 1) -#endif - -#include - -#if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_LOGGING -#include -using boost::lexical_cast; -#endif - -#ifdef _MSC_VER -#pragma warning(pop) -#endif - -#include "libtorrent/tracker_manager.hpp" -#include "libtorrent/parse_url.hpp" -#include "libtorrent/udp_tracker_connection.hpp" -#include "libtorrent/io.hpp" -#include "libtorrent/escape_string.hpp" - -namespace -{ - enum - { - udp_connection_retries = 4, - udp_announce_retries = 15, - udp_connect_timeout = 15, - udp_announce_timeout = 10 - }; -} - -using boost::bind; - -namespace libtorrent -{ - - udp_tracker_connection::udp_tracker_connection( - io_service& ios - , connection_queue& cc - , tracker_manager& man - , tracker_request const& req - , address bind_infc - , boost::weak_ptr c - , session_settings const& stn - , proxy_settings const& proxy) - : tracker_connection(man, req, ios, bind_infc, c) - , m_man(man) - , m_name_lookup(ios) - , m_socket(ios, boost::bind(&udp_tracker_connection::on_receive, self(), _1, _2, _3, _4), cc) - , m_transaction_id(0) - , m_connection_id(0) - , m_settings(stn) - , m_attempts(0) - , m_state(action_error) - { - m_socket.set_proxy_settings(proxy); - } - - void udp_tracker_connection::start() - { - std::string hostname; - int port; - char const* error; - - using boost::tuples::ignore; - boost::tie(ignore, ignore, hostname, port, ignore, error) - = parse_url_components(tracker_req().url); - - if (error) - { - fail(-1, error); - return; - } - - udp::resolver::query q(hostname, to_string(port).elems); - m_name_lookup.async_resolve(q - , boost::bind( - &udp_tracker_connection::name_lookup, self(), _1, _2)); - set_timeout(tracker_req().event == tracker_request::stopped - ? m_settings.stop_tracker_timeout - : m_settings.tracker_completion_timeout - , m_settings.tracker_receive_timeout); -#if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_LOGGING - boost::shared_ptr cb = requester(); - if (cb) cb->debug_log(("*** UDP_TRACKER [ initiating name lookup: " + hostname + " ]").c_str()); -#endif - } - - void udp_tracker_connection::name_lookup(error_code const& error - , udp::resolver::iterator i) - { - if (error == asio::error::operation_aborted) return; - if (error || i == udp::resolver::iterator()) - { - fail(-1, error.message().c_str()); - return; - } - - boost::shared_ptr cb = requester(); -#if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_LOGGING - if (cb) cb->debug_log("*** UDP_TRACKER [ name lookup successful ]"); -#endif - restart_read_timeout(); - - // look for an address that has the same kind as the one - // we're listening on. To make sure the tracker get our - // correct listening address. - udp::resolver::iterator target = i; - udp::resolver::iterator end; - udp::endpoint target_address = *i; - for (; target != end && target->endpoint().address().is_v4() - != bind_interface().is_v4(); ++target); - if (target == end) - { - TORRENT_ASSERT(target_address.address().is_v4() != bind_interface().is_v4()); - if (cb) - { - std::string tracker_address_type = target_address.address().is_v4() ? "IPv4" : "IPv6"; - std::string bind_address_type = bind_interface().is_v4() ? "IPv4" : "IPv6"; - cb->tracker_warning(tracker_req(), "the tracker only resolves to an " - + tracker_address_type + " address, and you're listening on an " - + bind_address_type + " socket. This may prevent you from receiving incoming connections."); - } - } - else - { - target_address = *target; - } - - if (cb) cb->m_tracker_address = tcp::endpoint(target_address.address(), target_address.port()); - m_target = target_address; - error_code ec; - m_socket.bind(udp::endpoint(bind_interface(), 0), ec); - if (ec) - { - fail(-1, ec.message().c_str()); - return; - } - send_udp_connect(); - } - - void udp_tracker_connection::on_timeout() - { -#if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_LOGGING || defined TORRENT_ERROR_LOGGING - boost::shared_ptr cb = requester(); - if (cb) cb->debug_log("*** UDP_TRACKER [ timed out ]"); -#endif - m_socket.close(); - m_name_lookup.cancel(); - fail_timeout(); - } - - void udp_tracker_connection::close() - { - error_code ec; - m_socket.close(); - m_name_lookup.cancel(); - tracker_connection::close(); - } - - void udp_tracker_connection::on_receive(error_code const& e - , udp::endpoint const& ep, char const* buf, int size) - { - // ignore resposes before we've sent any requests - if (m_state == action_error) return; - - if (!m_socket.is_open()) return; // the operation was aborted - - // ignore packet not sent from the tracker - if (m_target != ep) return; - - if (e) fail(-1, e.message().c_str()); - -#if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_LOGGING - boost::shared_ptr cb = requester(); - if (cb) - { - std::stringstream msg; - msg << "<== UDP_TRACKER_PACKET [ size: " << size << " ]"; - cb->debug_log(msg.str()); - } -#endif - - // ignore packets smaller than 8 bytes - if (size < 8) return; - - restart_read_timeout(); - - const char* ptr = buf; - int action = detail::read_int32(ptr); - int transaction = detail::read_int32(ptr); - -#if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_LOGGING - if (cb) - { - std::stringstream msg; - msg << "*** UDP_TRACKER_PACKET [ acton: " << action << " ]"; - cb->debug_log(msg.str()); - } -#endif - - // ignore packets with incorrect transaction id - if (m_transaction_id != transaction) return; - - if (action == action_error) - { - fail(-1, std::string(ptr, size - 8).c_str()); - return; - } - - // ignore packets that's not a response to our message - if (action != m_state) return; - -#if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_LOGGING - if (cb) - { - std::stringstream msg; - msg << "*** UDP_TRACKER_RESPONSE [ cid: " << m_connection_id << " ]"; - cb->debug_log(msg.str()); - } -#endif - - switch (m_state) - { - case action_connect: - on_connect_response(buf, size); - break; - case action_announce: - on_announce_response(buf, size); - break; - case action_scrape: - on_scrape_response(buf, size); - break; - default: break; - } - } - - void udp_tracker_connection::on_connect_response(char const* buf, int size) - { - // ignore packets smaller than 16 bytes - if (size < 16) return; - - restart_read_timeout(); - buf += 8; // skip header - - // reset transaction - m_transaction_id = 0; - m_attempts = 0; - m_connection_id = detail::read_int64(buf); - - if (tracker_req().kind == tracker_request::announce_request) - send_udp_announce(); - else if (tracker_req().kind == tracker_request::scrape_request) - send_udp_scrape(); - } - - void udp_tracker_connection::send_udp_connect() - { -#if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_LOGGING - boost::shared_ptr cb = requester(); - if (cb) - { - cb->debug_log("==> UDP_TRACKER_CONNECT [" - + lexical_cast(tracker_req().info_hash) + "]"); - } -#endif - if (!m_socket.is_open()) return; // the operation was aborted - - char buf[16]; - char* ptr = buf; - - if (m_transaction_id == 0) - m_transaction_id = std::rand() ^ (std::rand() << 16); - - detail::write_uint32(0x417, ptr); - detail::write_uint32(0x27101980, ptr); // connection_id - detail::write_int32(action_connect, ptr); // action (connect) - detail::write_int32(m_transaction_id, ptr); // transaction_id - TORRENT_ASSERT(ptr - buf == sizeof(buf)); - - error_code ec; - m_socket.send(m_target, buf, 16, ec); - m_state = action_connect; - ++m_attempts; - if (ec) - { - fail(-1, ec.message().c_str()); - return; - } - } - - void udp_tracker_connection::send_udp_scrape() - { - if (m_transaction_id == 0) - m_transaction_id = std::rand() ^ (std::rand() << 16); - - if (!m_socket.is_open()) return; // the operation was aborted - - char buf[8 + 4 + 4 + 20]; - char* out = buf; - - detail::write_int64(m_connection_id, out); // connection_id - detail::write_int32(action_scrape, out); // action (scrape) - detail::write_int32(m_transaction_id, out); // transaction_id - // info_hash - std::copy(tracker_req().info_hash.begin(), tracker_req().info_hash.end(), out); - out += 20; - TORRENT_ASSERT(out - buf == sizeof(buf)); - - error_code ec; - m_socket.send(m_target, buf, sizeof(buf), ec); - m_state = action_scrape; - ++m_attempts; - if (ec) - { - fail(-1, ec.message().c_str()); - return; - } - } - - void udp_tracker_connection::on_announce_response(char const* buf, int size) - { - if (size < 20) return; - - restart_read_timeout(); - - buf += 8; // skip header - restart_read_timeout(); - int interval = detail::read_int32(buf); - int incomplete = detail::read_int32(buf); - int complete = detail::read_int32(buf); - int num_peers = (size - 20) / 6; - if ((size - 20) % 6 != 0) - { - fail(-1, "invalid udp tracker response length"); - return; - } - - boost::shared_ptr cb = requester(); -#if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_LOGGING - if (cb) - { - cb->debug_log("<== UDP_TRACKER_ANNOUNCE_RESPONSE"); - } -#endif - - if (!cb) - { - m_man.remove_request(this); - return; - } - - std::vector peer_list; - for (int i = 0; i < num_peers; ++i) - { - // TODO: don't use a string here - peer_entry e; - std::stringstream s; - s << (int)detail::read_uint8(buf) << "."; - s << (int)detail::read_uint8(buf) << "."; - s << (int)detail::read_uint8(buf) << "."; - s << (int)detail::read_uint8(buf); - e.ip = s.str(); - e.port = detail::read_uint16(buf); - e.pid.clear(); - peer_list.push_back(e); - } - - cb->tracker_response(tracker_req(), peer_list, interval - , complete, incomplete, address()); - - m_man.remove_request(this); - close(); - } - - void udp_tracker_connection::on_scrape_response(char const* buf, int size) - { - buf += 8; // skip header - - restart_read_timeout(); - int action = detail::read_int32(buf); - int transaction = detail::read_int32(buf); - - if (transaction != m_transaction_id) - { - fail(-1, "incorrect transaction id"); - return; - } - - if (action == action_error) - { - fail(-1, std::string(buf, size - 8).c_str()); - return; - } - - if (action != action_scrape) - { - fail(-1, "invalid action in announce response"); - return; - } - - if (size < 20) - { - fail(-1, "got a message with size < 20"); - return; - } - - int complete = detail::read_int32(buf); - int downloaded = detail::read_int32(buf); - int incomplete = detail::read_int32(buf); - - boost::shared_ptr cb = requester(); - if (!cb) - { - close(); - return; - } - - cb->tracker_scrape_response(tracker_req() - , complete, incomplete, downloaded); - - m_man.remove_request(this); - close(); - } - - void udp_tracker_connection::send_udp_announce() - { - if (m_transaction_id == 0) - m_transaction_id = std::rand() ^ (std::rand() << 16); - - if (!m_socket.is_open()) return; // the operation was aborted - - char buf[8 + 4 + 4 + 20 + 20 + 8 + 8 + 8 + 4 + 4 + 4 + 4 + 2 + 2]; - char* out = buf; - - tracker_request const& req = tracker_req(); - - detail::write_int64(m_connection_id, out); // connection_id - detail::write_int32(action_announce, out); // action (announce) - detail::write_int32(m_transaction_id, out); // transaction_id - std::copy(req.info_hash.begin(), req.info_hash.end(), out); // info_hash - out += 20; - std::copy(req.pid.begin(), req.pid.end(), out); // peer_id - out += 20; - detail::write_int64(req.downloaded, out); // downloaded - detail::write_int64(req.left, out); // left - detail::write_int64(req.uploaded, out); // uploaded - detail::write_int32(req.event, out); // event - // ip address - if (m_settings.announce_ip != address() && m_settings.announce_ip.is_v4()) - detail::write_uint32(m_settings.announce_ip.to_v4().to_ulong(), out); - else - detail::write_int32(0, out); - detail::write_int32(req.key, out); // key - detail::write_int32(req.num_want, out); // num_want - detail::write_uint16(req.listen_port, out); // port - detail::write_uint16(0, out); // extensions - - TORRENT_ASSERT(out - buf == sizeof(buf)); - -#if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_LOGGING - boost::shared_ptr cb = requester(); - if (cb) - { - cb->debug_log("==> UDP_TRACKER_ANNOUNCE [" - + lexical_cast(req.info_hash) + "]"); - } -#endif - - error_code ec; - m_socket.send(m_target, buf, sizeof(buf), ec); - m_state = action_announce; - ++m_attempts; - if (ec) - { - fail(-1, ec.message().c_str()); - return; - } - } - -} - diff --git a/libtorrent/src/upnp.cpp b/libtorrent/src/upnp.cpp deleted file mode 100644 index a91503b54..000000000 --- a/libtorrent/src/upnp.cpp +++ /dev/null @@ -1,1304 +0,0 @@ -/* - -Copyright (c) 2007, Arvid Norberg -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions -are met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in - the documentation and/or other materials provided with the distribution. - * Neither the name of the author nor the names of its - contributors may be used to endorse or promote products derived - from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -POSSIBILITY OF SUCH DAMAGE. - -*/ - -#include "libtorrent/pch.hpp" - -#include "libtorrent/socket.hpp" -#include "libtorrent/upnp.hpp" -#include "libtorrent/io.hpp" -#include "libtorrent/parse_url.hpp" -#include "libtorrent/xml_parse.hpp" -#include "libtorrent/connection_queue.hpp" -#include "libtorrent/enum_net.hpp" -#include "libtorrent/escape_string.hpp" - -#include -#include -#if BOOST_VERSION < 103500 -#include -#include -#else -#include -#include -#endif -#include -#include - -#if (defined(TORRENT_LOGGING) || defined(TORRENT_VERBOSE_LOGGING)) && !defined(TORRENT_UPNP_LOGGING) -#define TORRENT_UPNP_LOGGING -#endif - -using boost::bind; -using namespace libtorrent; - -static error_code ec; - -upnp::upnp(io_service& ios, connection_queue& cc - , address const& listen_interface, std::string const& user_agent - , portmap_callback_t const& cb, bool ignore_nonrouters, void* state) - : m_user_agent(user_agent) - , m_callback(cb) - , m_retry_count(0) - , m_io_service(ios) - , m_socket(ios, udp::endpoint(address_v4::from_string("239.255.255.250", ec), 1900) - , bind(&upnp::on_reply, self(), _1, _2, _3), false) - , m_broadcast_timer(ios) - , m_refresh_timer(ios) - , m_disabled(false) - , m_closing(false) - , m_ignore_non_routers(ignore_nonrouters) - , m_cc(cc) -{ -#ifdef TORRENT_UPNP_LOGGING - m_log.open("upnp.log", std::ios::in | std::ios::out | std::ios::trunc); -#endif - m_retry_count = 0; - - if (state) - { - upnp_state_t* s = (upnp_state_t*)state; - m_devices.swap(s->devices); - m_mappings.swap(s->mappings); - delete s; - } -} - -void* upnp::drain_state() -{ - upnp_state_t* s = new upnp_state_t; - s->mappings.swap(m_mappings); - - for (std::set::iterator i = m_devices.begin() - , end(m_devices.end()); i != end; ++i) - i->upnp_connection.reset(); - s->devices.swap(m_devices); - return s; -} - -upnp::~upnp() -{ -} - -void upnp::discover_device() -{ - mutex_t::scoped_lock l(m_mutex); - - discover_device_impl(); -} - -void upnp::discover_device_impl() -{ - const char msearch[] = - "M-SEARCH * HTTP/1.1\r\n" - "HOST: 239.255.255.250:1900\r\n" - "ST:upnp:rootdevice\r\n" - "MAN:\"ssdp:discover\"\r\n" - "MX:3\r\n" - "\r\n\r\n"; - - error_code ec; -#ifdef TORRENT_DEBUG_UPNP - // simulate packet loss - if (m_retry_count & 1) -#endif - m_socket.send(msearch, sizeof(msearch) - 1, ec); - - if (ec) - { -#ifdef TORRENT_UPNP_LOGGING - m_log << time_now_string() - << " ==> Broadcast FAILED: " << ec.message() << std::endl - << "aborting" << std::endl; -#endif - disable(ec.message().c_str()); - return; - } - - ++m_retry_count; - m_broadcast_timer.expires_from_now(seconds(2 * m_retry_count), ec); - m_broadcast_timer.async_wait(bind(&upnp::resend_request - , self(), _1)); - -#ifdef TORRENT_UPNP_LOGGING - m_log << time_now_string() - << " ==> Broadcasting search for rootdevice" << std::endl; -#endif -} - -// returns a reference to a mapping or -1 on failure -int upnp::add_mapping(upnp::protocol_type p, int external_port, int local_port) -{ - mutex_t::scoped_lock l(m_mutex); - -#ifdef TORRENT_UPNP_LOGGING - m_log << time_now_string() - << " *** add mapping [ proto: " << (p == tcp?"tcp":"udp") - << " ext_port: " << external_port - << " local_port :" << local_port << " ]"; - if (m_disabled) m_log << " DISABLED"; - m_log << std::endl; -#endif - if (m_disabled) return -1; - - std::vector::iterator i = std::find_if( - m_mappings.begin(), m_mappings.end() - , boost::bind(&global_mapping_t::protocol, _1) == int(none)); - - if (i == m_mappings.end()) - { - m_mappings.push_back(global_mapping_t()); - i = m_mappings.end() - 1; - } - - i->protocol = p; - i->external_port = external_port; - i->local_port = local_port; - - int mapping_index = i - m_mappings.begin(); - - for (std::set::iterator i = m_devices.begin() - , end(m_devices.end()); i != end; ++i) - { - rootdevice& d = const_cast(*i); - TORRENT_ASSERT(d.magic == 1337); - - if (int(d.mapping.size()) <= mapping_index) - d.mapping.resize(mapping_index + 1); - mapping_t& m = d.mapping[mapping_index]; - - m.action = mapping_t::action_add; - m.protocol = p; - m.external_port = external_port; - m.local_port = local_port; - - if (d.service_namespace) update_map(d, mapping_index); - } - - return mapping_index; -} - -void upnp::delete_mapping(int mapping) -{ - mutex_t::scoped_lock l(m_mutex); - - if (mapping <= int(m_mappings.size())) return; - - global_mapping_t& m = m_mappings[mapping]; - -#ifdef TORRENT_UPNP_LOGGING - m_log << time_now_string() - << " *** delete mapping [ proto: " << (m.protocol == tcp?"tcp":"udp") - << " ext_port:" << m.external_port - << " local_port:" << m.local_port << " ]"; - m_log << std::endl; -#endif - - if (m.protocol == none) return; - - for (std::set::iterator i = m_devices.begin() - , end(m_devices.end()); i != end; ++i) - { - rootdevice& d = const_cast(*i); - TORRENT_ASSERT(d.magic == 1337); - - TORRENT_ASSERT(mapping < int(d.mapping.size())); - d.mapping[mapping].action = mapping_t::action_delete; - - if (d.service_namespace) update_map(d, mapping); - } -} - -void upnp::resend_request(error_code const& e) -{ - if (e) return; - - mutex_t::scoped_lock l(m_mutex); - - if (m_closing) return; - - if (m_retry_count < 12 - && (m_devices.empty() || m_retry_count < 4)) - { - discover_device_impl(); - return; - } - - if (m_devices.empty()) - { -#ifdef TORRENT_UPNP_LOGGING - m_log << time_now_string() - << " *** Got no response in 12 retries. Giving up, " - "disabling UPnP." << std::endl; -#endif - disable("no UPnP router found"); - return; - } - - for (std::set::iterator i = m_devices.begin() - , end(m_devices.end()); i != end; ++i) - { - if (i->control_url.empty() && !i->upnp_connection && !i->disabled) - { - // we don't have a WANIP or WANPPP url for this device, - // ask for it - rootdevice& d = const_cast(*i); - TORRENT_ASSERT(d.magic == 1337); - try - { -#ifdef TORRENT_UPNP_LOGGING - m_log << time_now_string() - << " ==> connecting to " << d.url << std::endl; -#endif - if (d.upnp_connection) d.upnp_connection->close(); - d.upnp_connection.reset(new http_connection(m_io_service - , m_cc, bind(&upnp::on_upnp_xml, self(), _1, _2 - , boost::ref(d), _5))); - d.upnp_connection->get(d.url, seconds(30), 1); - } - catch (std::exception& e) - { - (void)e; -#ifdef TORRENT_UPNP_LOGGING - m_log << time_now_string() - << " *** Connection failed to: " << d.url - << " " << e.what() << std::endl; -#endif - d.disabled = true; - } - } - } -} - -void upnp::on_reply(udp::endpoint const& from, char* buffer - , std::size_t bytes_transferred) -{ - mutex_t::scoped_lock l(m_mutex); - - using namespace libtorrent::detail; - - // parse out the url for the device - -/* - the response looks like this: - - HTTP/1.1 200 OK - ST:upnp:rootdevice - USN:uuid:000f-66d6-7296000099dc::upnp:rootdevice - Location: http://192.168.1.1:5431/dyndev/uuid:000f-66d6-7296000099dc - Server: Custom/1.0 UPnP/1.0 Proc/Ver - EXT: - Cache-Control:max-age=180 - DATE: Fri, 02 Jan 1970 08:10:38 GMT - - a notification looks like this: - - NOTIFY * HTTP/1.1 - Host:239.255.255.250:1900 - NT:urn:schemas-upnp-org:device:MediaServer:1 - NTS:ssdp:alive - Location:http://10.0.3.169:2869/upnphost/udhisapi.dll?content=uuid:c17f0c32-d19b-4938-ae94-65f945c3a26e - USN:uuid:c17f0c32-d19b-4938-ae94-65f945c3a26e::urn:schemas-upnp-org:device:MediaServer:1 - Cache-Control:max-age=900 - Server:Microsoft-Windows-NT/5.1 UPnP/1.0 UPnP-Device-Host/1.0 - -*/ - error_code ec; - if (!in_local_network(m_io_service, from.address(), ec)) - { -#ifdef TORRENT_UPNP_LOGGING - if (ec) - { - m_log << time_now_string() << " <== (" << from << ") error: " - << ec.message() << std::endl; - } - else - { - m_log << time_now_string() << " <== (" << from << ") UPnP device " - "ignored because it's not on our local network "; - std::vector net = enum_net_interfaces(m_io_service, ec); - for (std::vector::const_iterator i = net.begin() - , end(net.end()); i != end; ++i) - { - m_log << "(" << i->interface_address << ", " << i->netmask << ") "; - } - m_log << std::endl; - } -#endif - return; - } - - if (m_ignore_non_routers) - { - std::vector routes = enum_routes(m_io_service, ec); - - if (std::find_if(routes.begin(), routes.end() - , bind(&ip_route::gateway, _1) == from.address()) == routes.end()) - { - // this upnp device is filtered because it's not in the - // list of configured routers -#ifdef TORRENT_UPNP_LOGGING - if (ec) - { - m_log << time_now_string() << " <== (" << from << ") error: " - << ec.message() << std::endl; - } - else - { - m_log << time_now_string() << " <== (" << from << ") UPnP device " - "ignored because it's not a router on our network "; - for (std::vector::const_iterator i = routes.begin() - , end(routes.end()); i != end; ++i) - { - m_log << "(" << i->gateway << ", " << i->netmask << ") "; - } - m_log << std::endl; - } -#endif - return; - } - } - - http_parser p; - bool error = false; - p.incoming(buffer::const_interval(buffer - , buffer + bytes_transferred), error); - if (error) - { -#ifdef TORRENT_UPNP_LOGGING - m_log << time_now_string() << " <== (" << from << ") Rootdevice " - "responded with incorrect HTTP packet. Ignoring device" << std::endl; -#endif - return; - } - - if (p.status_code() != 200 && p.method() != "notify") - { -#ifdef TORRENT_UPNP_LOGGING - if (p.method().empty()) - m_log << time_now_string() - << " <== (" << from << ") Device responded with HTTP status: " << p.status_code() - << ". Ignoring device" << std::endl; - else - m_log << time_now_string() - << " <== (" << from << ") Device with HTTP method: " << p.method() - << ". Ignoring device" << std::endl; -#endif - return; - } - - if (!p.header_finished()) - { -#ifdef TORRENT_UPNP_LOGGING - m_log << time_now_string() - << " <== (" << from << ") Rootdevice responded with incomplete HTTP " - "packet. Ignoring device" << std::endl; -#endif - return; - } - - std::string url = p.header("location"); - if (url.empty()) - { -#ifdef TORRENT_UPNP_LOGGING - m_log << time_now_string() - << " <== (" << from << ") Rootdevice response is missing a location header. " - "Ignoring device" << std::endl; -#endif - return; - } - - rootdevice d; - d.url = url; - - std::set::iterator i = m_devices.find(d); - - if (i == m_devices.end()) - { - - std::string protocol; - std::string auth; - char const* error; - // we don't have this device in our list. Add it - boost::tie(protocol, auth, d.hostname, d.port, d.path, error) - = parse_url_components(d.url); - - if (error) - { -#ifdef TORRENT_UPNP_LOGGING - m_log << time_now_string() - << " <== (" << from << ") Rootdevice advertized an invalid url: '" << d.url - << "'. " << error << ". Ignoring device" << std::endl; -#endif - return; - } - - // ignore the auth here. It will be re-parsed - // by the http connection later - - if (protocol != "http") - { -#ifdef TORRENT_UPNP_LOGGING - m_log << time_now_string() - << " <== (" << from << ") Rootdevice uses unsupported protocol: '" << protocol - << "'. Ignoring device" << std::endl; -#endif - return; - } - - if (d.port == 0) - { -#ifdef TORRENT_UPNP_LOGGING - m_log << time_now_string() - << " <== (" << from << ") Rootdevice responded with a url with port 0. " - "Ignoring device" << std::endl; -#endif - return; - } -#ifdef TORRENT_UPNP_LOGGING - m_log << time_now_string() - << " <== (" << from << ") Found rootdevice: " << d.url - << " total: " << m_devices.size() << std::endl; -#endif - - if (m_devices.size() >= 50) - { -#ifdef TORRENT_UPNP_LOGGING - m_log << time_now_string() - << " <== (" << from << ") Too many devices (" << m_devices.size() << "), " - "ignoring: " << d.url << std::endl; -#endif - return; - } - - TORRENT_ASSERT(d.mapping.empty()); - for (std::vector::iterator j = m_mappings.begin() - , end(m_mappings.end()); j != end; ++j) - { - mapping_t m; - m.action = mapping_t::action_add; - m.local_port = j->local_port; - m.external_port = j->external_port; - m.protocol = j->protocol; - d.mapping.push_back(m); - } - boost::tie(i, boost::tuples::ignore) = m_devices.insert(d); - } - - - // since we're using udp, send the query 4 times - // just to make sure we find all devices - if (m_retry_count >= 4 && !m_devices.empty()) - { - error_code ec; - m_broadcast_timer.cancel(ec); - - for (std::set::iterator i = m_devices.begin() - , end(m_devices.end()); i != end; ++i) - { - if (i->control_url.empty() && !i->upnp_connection && !i->disabled) - { - // we don't have a WANIP or WANPPP url for this device, - // ask for it - rootdevice& d = const_cast(*i); - TORRENT_ASSERT(d.magic == 1337); -#ifndef BOOST_NO_EXCEPTIONS - try - { -#endif -#ifdef TORRENT_UPNP_LOGGING - m_log << time_now_string() - << " ==> connecting to " << d.url << std::endl; -#endif - if (d.upnp_connection) d.upnp_connection->close(); - d.upnp_connection.reset(new http_connection(m_io_service - , m_cc, bind(&upnp::on_upnp_xml, self(), _1, _2 - , boost::ref(d), _5))); - d.upnp_connection->get(d.url, seconds(30), 1); -#ifndef BOOST_NO_EXCEPTIONS - } - catch (std::exception& e) - { - (void)e; -#ifdef TORRENT_UPNP_LOGGING - m_log << time_now_string() - << " *** Connection failed to: " << d.url - << " " << e.what() << std::endl; -#endif - d.disabled = true; - } -#endif - } - } - } -} - -void upnp::post(upnp::rootdevice const& d, std::string const& soap - , std::string const& soap_action) -{ - TORRENT_ASSERT(d.magic == 1337); - TORRENT_ASSERT(d.upnp_connection); - - std::stringstream header; - - header << "POST " << d.path << " HTTP/1.0\r\n" - "Host: " << d.hostname << ":" << d.port << "\r\n" - "Content-Type: text/xml; charset=\"utf-8\"\r\n" - "Content-Length: " << soap.size() << "\r\n" - "Soapaction: \"" << d.service_namespace << "#" << soap_action << "\"\r\n\r\n" << soap; - - d.upnp_connection->sendbuffer = header.str(); - -#ifdef TORRENT_UPNP_LOGGING - m_log << time_now_string() - << " ==> sending: " << header.str() << std::endl; -#endif - -} - -void upnp::create_port_mapping(http_connection& c, rootdevice& d, int i) -{ - mutex_t::scoped_lock l(m_mutex); - - TORRENT_ASSERT(d.magic == 1337); - - if (!d.upnp_connection) - { - TORRENT_ASSERT(d.disabled); -#ifdef TORRENT_UPNP_LOGGING - m_log << time_now_string() << " *** mapping (" << i - << ") aborted" << std::endl; -#endif - return; - } - - std::string soap_action = "AddPortMapping"; - - std::stringstream soap; - - soap << "\n" - "" - ""; - - error_code ec; - soap << "" - "" << d.mapping[i].external_port << "" - "" << (d.mapping[i].protocol == udp ? "UDP" : "TCP") << "" - "" << d.mapping[i].local_port << "" - "" << c.socket().local_endpoint(ec).address() << "" - "1" - "" << m_user_agent << "" - "" << d.lease_duration << ""; - soap << ""; - - post(d, soap.str(), soap_action); -} - -void upnp::next(rootdevice& d, int i) -{ - if (i < num_mappings() - 1) - { - update_map(d, i + 1); - } - else - { - std::vector::iterator i - = std::find_if(d.mapping.begin(), d.mapping.end() - , boost::bind(&mapping_t::action, _1) != int(mapping_t::action_none)); - if (i == d.mapping.end()) return; - - update_map(d, i - d.mapping.begin()); - } -} - -void upnp::update_map(rootdevice& d, int i) -{ - TORRENT_ASSERT(d.magic == 1337); - TORRENT_ASSERT(i < int(d.mapping.size())); - TORRENT_ASSERT(d.mapping.size() == m_mappings.size()); - - if (d.upnp_connection) return; - - mapping_t& m = d.mapping[i]; - - if (m.action == mapping_t::action_none - || m.protocol == none) - { -#ifdef TORRENT_UPNP_LOGGING - if (m.protocol != none) - m_log << time_now_string() << " *** mapping (" << i - << ") does not need update, skipping" << std::endl; -#endif - m.action = mapping_t::action_none; - next(d, i); - return; - } - - TORRENT_ASSERT(!d.upnp_connection); - TORRENT_ASSERT(d.service_namespace); - -#ifdef TORRENT_UPNP_LOGGING - m_log << time_now_string() - << " ==> connecting to " << d.hostname << std::endl; -#endif - if (m.action == mapping_t::action_add) - { - if (m.failcount > 5) - { - m.action = mapping_t::action_none; - // giving up - next(d, i); - return; - } - - if (d.upnp_connection) d.upnp_connection->close(); - d.upnp_connection.reset(new http_connection(m_io_service - , m_cc, bind(&upnp::on_upnp_map_response, self(), _1, _2 - , boost::ref(d), i, _5), true - , bind(&upnp::create_port_mapping, self(), _1, boost::ref(d), i))); - - d.upnp_connection->start(d.hostname, to_string(d.port).elems - , seconds(10), 1); - } - else if (m.action == mapping_t::action_delete) - { - if (d.upnp_connection) d.upnp_connection->close(); - d.upnp_connection.reset(new http_connection(m_io_service - , m_cc, bind(&upnp::on_upnp_unmap_response, self(), _1, _2 - , boost::ref(d), i, _5), true - , bind(&upnp::delete_port_mapping, self(), boost::ref(d), i))); - d.upnp_connection->start(d.hostname, to_string(d.port).elems - , seconds(10), 1); - } - - m.action = mapping_t::action_none; -} - -void upnp::delete_port_mapping(rootdevice& d, int i) -{ - mutex_t::scoped_lock l(m_mutex); - - TORRENT_ASSERT(d.magic == 1337); - - if (!d.upnp_connection) - { - TORRENT_ASSERT(d.disabled); -#ifdef TORRENT_UPNP_LOGGING - m_log << time_now_string() << " *** unmapping (" << i - << ") aborted" << std::endl; -#endif - return; - } - - std::stringstream soap; - - std::string soap_action = "DeletePortMapping"; - - soap << "\n" - "" - ""; - - soap << "" - "" << d.mapping[i].external_port << "" - "" << (d.mapping[i].protocol == udp ? "UDP" : "TCP") << ""; - soap << ""; - - post(d, soap.str(), soap_action); -} - -namespace -{ - char tolower(char c) - { - if (c >= 'A' && c <= 'Z') return c + ('a' - 'A'); - return c; - } - - void copy_tolower(std::string& dst, char const* src) - { - dst.clear(); - while (*src) dst.push_back(tolower(*src++)); - } - - bool string_equal_nocase(char const* lhs, char const* rhs) - { - while (tolower(*lhs) == tolower(*rhs)) - { - if (*lhs == 0) return true; - ++lhs; - ++rhs; - } - return false; - } -} - -struct parse_state -{ - parse_state(): in_service(false) {} - void reset(char const* st) - { - in_service = false; - service_type = st; - tag_stack.clear(); - control_url.clear(); - model.clear(); - url_base.clear(); - } - bool in_service; - std::list tag_stack; - std::string control_url; - char const* service_type; - std::string model; - std::string url_base; - bool top_tags(const char* str1, const char* str2) - { - std::list::reverse_iterator i = tag_stack.rbegin(); - if (i == tag_stack.rend()) return false; - if (!string_equal_nocase(i->c_str(), str2)) return false; - ++i; - if (i == tag_stack.rend()) return false; - if (!string_equal_nocase(i->c_str(), str1)) return false; - return true; - } -}; - -void find_control_url(int type, char const* string, parse_state& state) -{ - if (type == xml_start_tag) - { - std::string tag; - copy_tolower(tag, string); - state.tag_stack.push_back(tag); -// std::copy(state.tag_stack.begin(), state.tag_stack.end(), std::ostream_iterator(std::cout, " ")); -// std::cout << std::endl; - } - else if (type == xml_end_tag) - { - if (!state.tag_stack.empty()) - { - if (state.in_service && state.tag_stack.back() == "service") - state.in_service = false; - state.tag_stack.pop_back(); - } - } - else if (type == xml_string) - { - if (state.tag_stack.empty()) return; -// std::cout << " " << string << std::endl; - if (!state.in_service && state.top_tags("service", "servicetype")) - { - if (string_equal_nocase(string, state.service_type)) - state.in_service = true; - } - else if (state.in_service && state.top_tags("service", "controlurl")) - { - state.control_url = string; - } - else if (state.model.empty() && state.top_tags("device", "modelname")) - { - state.model = string; - } - else if (state.tag_stack.back() == "urlbase") - { - state.url_base = string; - } - } -} - -void upnp::on_upnp_xml(error_code const& e - , libtorrent::http_parser const& p, rootdevice& d - , http_connection& c) -{ - mutex_t::scoped_lock l(m_mutex); - - TORRENT_ASSERT(d.magic == 1337); - if (d.upnp_connection && d.upnp_connection.get() == &c) - { - d.upnp_connection->close(); - d.upnp_connection.reset(); - } - - if (e && e != asio::error::eof) - { -#ifdef TORRENT_UPNP_LOGGING - m_log << time_now_string() - << " <== (" << d.url << ") error while fetching control url: " - << e.message() << std::endl; -#endif - d.disabled = true; - return; - } - - if (!p.header_finished()) - { -#ifdef TORRENT_UPNP_LOGGING - m_log << time_now_string() - << " <== (" << d.url << ") error while fetching control url: incomplete http message" << std::endl; -#endif - d.disabled = true; - return; - } - - if (p.status_code() != 200) - { -#ifdef TORRENT_UPNP_LOGGING - m_log << time_now_string() - << " <== (" << d.url << ") error while fetching control url: " << p.message() << std::endl; -#endif - d.disabled = true; - return; - } - - parse_state s; - s.reset("urn:schemas-upnp-org:service:WANIPConnection:1"); - xml_parse((char*)p.get_body().begin, (char*)p.get_body().end - , bind(&find_control_url, _1, _2, boost::ref(s))); - if (!s.control_url.empty()) - { - d.service_namespace = s.service_type; - if (!s.model.empty()) m_model = s.model; - } - else - { - // we didn't find the WAN IP connection, look for - // a PPP connection - s.reset("urn:schemas-upnp-org:service:WANPPPConnection:1"); - xml_parse((char*)p.get_body().begin, (char*)p.get_body().end - , bind(&find_control_url, _1, _2, boost::ref(s))); - if (!s.control_url.empty()) - { - d.service_namespace = s.service_type; - if (!s.model.empty()) m_model = s.model; - } - else - { -#ifdef TORRENT_UPNP_LOGGING - m_log << time_now_string() - << " <== (" << d.url << ") Rootdevice response, did not find " - "a port mapping interface" << std::endl; -#endif - d.disabled = true; - return; - } - } - - if (!s.url_base.empty()) - { - // avoid double slashes in path - if (s.url_base[s.url_base.size()-1] == '/' - && !s.control_url.empty() - && s.control_url[0] == '/') - s.url_base.erase(s.url_base.end()-1); - d.control_url = s.url_base + s.control_url; - } - else d.control_url = s.control_url; - - std::string protocol; - std::string auth; - char const* error; - if (!d.control_url.empty() && d.control_url[0] == '/') - { - boost::tie(protocol, auth, d.hostname, d.port, d.path, error) - = parse_url_components(d.url); - d.control_url = protocol + "://" + d.hostname + ":" - + to_string(d.port).elems + s.control_url; - } - -#ifdef TORRENT_UPNP_LOGGING - m_log << time_now_string() - << " <== (" << d.url << ") Rootdevice response, found control URL: " << d.control_url - << " urlbase: " << s.url_base << " namespace: " << d.service_namespace << std::endl; -#endif - - boost::tie(protocol, auth, d.hostname, d.port, d.path, error) - = parse_url_components(d.control_url); - - if (error) - { -#ifdef TORRENT_UPNP_LOGGING - m_log << time_now_string() - << " *** Failed to parse URL '" << d.control_url << "': " << error << std::endl; -#endif - d.disabled = true; - return; - } - - if (num_mappings() > 0) update_map(d, 0); -} - -void upnp::disable(char const* msg) -{ - m_disabled = true; - - // kill all mappings - for (std::vector::iterator i = m_mappings.begin() - , end(m_mappings.end()); i != end; ++i) - { - if (i->protocol == none) continue; - i->protocol = none; - m_callback(i - m_mappings.begin(), 0, msg); - } - - m_devices.clear(); - error_code ec; - m_broadcast_timer.cancel(ec); - m_refresh_timer.cancel(ec); - m_socket.close(); -} - -namespace -{ - struct error_code_parse_state - { - error_code_parse_state(): in_error_code(false), exit(false), error_code(-1) {} - bool in_error_code; - bool exit; - int error_code; - }; - - void find_error_code(int type, char const* string, error_code_parse_state& state) - { - if (state.exit) return; - if (type == xml_start_tag && !std::strcmp("errorCode", string)) - { - state.in_error_code = true; - } - else if (type == xml_string && state.in_error_code) - { - state.error_code = std::atoi(string); - state.exit = true; - } - } -} - -namespace -{ - struct error_code_t - { - int code; - char const* msg; - }; - - error_code_t error_codes[] = - { - {402, "Invalid Arguments"} - , {501, "Action Failed"} - , {714, "The specified value does not exist in the array"} - , {715, "The source IP address cannot be wild-carded"} - , {716, "The external port cannot be wild-carded"} - , {718, "The port mapping entry specified conflicts with " - "a mapping assigned previously to another client"} - , {724, "Internal and External port values must be the same"} - , {725, "The NAT implementation only supports permanent " - "lease times on port mappings"} - , {726, "RemoteHost must be a wildcard and cannot be a " - "specific IP address or DNS name"} - , {727, "ExternalPort must be a wildcard and cannot be a specific port "} - }; - -} - -void upnp::on_upnp_map_response(error_code const& e - , libtorrent::http_parser const& p, rootdevice& d, int mapping - , http_connection& c) -{ - mutex_t::scoped_lock l(m_mutex); - - TORRENT_ASSERT(d.magic == 1337); - if (d.upnp_connection && d.upnp_connection.get() == &c) - { - d.upnp_connection->close(); - d.upnp_connection.reset(); - } - - if (e && e != asio::error::eof) - { -#ifdef TORRENT_UPNP_LOGGING - m_log << time_now_string() - << " <== error while adding portmap: " << e.message() << std::endl; -#endif - d.disabled = true; - return; - } - - if (m_closing) return; - -// error code response may look like this: -// -// -// -// s:Client -// UPnPError -// -// -// 402 -// Invalid Args -// -// -// -// -// - - if (!p.header_finished()) - { -#ifdef TORRENT_UPNP_LOGGING - m_log << time_now_string() - << " <== error while adding portmap: incomplete http message" << std::endl; -#endif - next(d, mapping); - return; - } - - // We don't want to ignore responses with return codes other than 200 - // since those might contain valid UPnP error codes - - error_code_parse_state s; - xml_parse((char*)p.get_body().begin, (char*)p.get_body().end - , bind(&find_error_code, _1, _2, boost::ref(s))); - -#ifdef TORRENT_UPNP_LOGGING - if (s.error_code != -1) - { - m_log << time_now_string() - << " <== got error message: " << s.error_code << std::endl; - } -#endif - - mapping_t& m = d.mapping[mapping]; - - if (s.error_code == 725) - { - // only permanent leases supported - d.lease_duration = 0; - m.action = mapping_t::action_add; - ++m.failcount; - update_map(d, mapping); - return; - } - else if (s.error_code == 718 || s.error_code == 727) - { - if (m.external_port != 0) - { - // conflict in mapping, set port to wildcard - // and let the router decide - m.external_port = 0; - m.action = mapping_t::action_add; - ++m.failcount; - update_map(d, mapping); - return; - } - return_error(mapping, s.error_code); - } - else if (s.error_code == 716) - { - // The external port cannot be wildcarder - // pick a random port - m.external_port = 40000 + (std::rand() % 10000); - m.action = mapping_t::action_add; - ++m.failcount; - update_map(d, mapping); - return; - } - else if (s.error_code != -1) - { - return_error(mapping, s.error_code); - } - -#ifdef TORRENT_UPNP_LOGGING - m_log << time_now_string() - << " <== map response: " << std::string(p.get_body().begin, p.get_body().end) - << std::endl; -#endif - - if (s.error_code == -1) - { - m_callback(mapping, m.external_port, ""); - if (d.lease_duration > 0) - { - m.expires = time_now() - + seconds(int(d.lease_duration * 0.75f)); - ptime next_expire = m_refresh_timer.expires_at(); - if (next_expire < time_now() - || next_expire > m.expires) - { - error_code ec; - m_refresh_timer.expires_at(m.expires, ec); - m_refresh_timer.async_wait(bind(&upnp::on_expire, self(), _1)); - } - } - else - { - m.expires = max_time(); - } - m.failcount = 0; - } - - next(d, mapping); -} - -void upnp::return_error(int mapping, int code) -{ - int num_errors = sizeof(error_codes) / sizeof(error_codes[0]); - error_code_t* end = error_codes + num_errors; - error_code_t tmp = {code, 0}; - error_code_t* e = std::lower_bound(error_codes, end, tmp - , bind(&error_code_t::code, _1) < bind(&error_code_t::code, _2)); - std::string error_string = "UPnP mapping error "; - error_string += to_string(code).elems; - if (e != end && e->code == code) - { - error_string += ": "; - error_string += e->msg; - } - m_callback(mapping, 0, error_string); -} - -void upnp::on_upnp_unmap_response(error_code const& e - , libtorrent::http_parser const& p, rootdevice& d, int mapping - , http_connection& c) -{ - mutex_t::scoped_lock l(m_mutex); - - TORRENT_ASSERT(d.magic == 1337); - if (d.upnp_connection && d.upnp_connection.get() == &c) - { - d.upnp_connection->close(); - d.upnp_connection.reset(); - } - - if (e && e != asio::error::eof) - { -#ifdef TORRENT_UPNP_LOGGING - m_log << time_now_string() - << " <== error while deleting portmap: " << e.message() << std::endl; -#endif - } else if (!p.header_finished()) - { -#ifdef TORRENT_UPNP_LOGGING - m_log << time_now_string() - << " <== error while deleting portmap: incomplete http message" << std::endl; -#endif - } - else if (p.status_code() != 200) - { -#ifdef TORRENT_UPNP_LOGGING - m_log << time_now_string() - << " <== error while deleting portmap: " << p.message() << std::endl; -#endif - } - else - { - -#ifdef TORRENT_UPNP_LOGGING - m_log << time_now_string() - << " <== unmap response: " << std::string(p.get_body().begin, p.get_body().end) - << std::endl; -#endif - } - - d.mapping[mapping].protocol = none; - - next(d, mapping); -} - -void upnp::on_expire(error_code const& e) -{ - if (e) return; - - ptime now = time_now(); - ptime next_expire = max_time(); - - mutex_t::scoped_lock l(m_mutex); - - for (std::set::iterator i = m_devices.begin() - , end(m_devices.end()); i != end; ++i) - { - rootdevice& d = const_cast(*i); - TORRENT_ASSERT(d.magic == 1337); - for (int m = 0; m < num_mappings(); ++m) - { - if (d.mapping[m].expires != max_time()) - continue; - - if (d.mapping[m].expires < now) - { - d.mapping[m].expires = max_time(); - update_map(d, m); - } - else if (d.mapping[m].expires < next_expire) - { - next_expire = d.mapping[m].expires; - } - } - } - if (next_expire != max_time()) - { - error_code ec; - m_refresh_timer.expires_at(next_expire, ec); - m_refresh_timer.async_wait(bind(&upnp::on_expire, self(), _1)); - } -} - -void upnp::close() -{ - mutex_t::scoped_lock l(m_mutex); - - error_code ec; - m_refresh_timer.cancel(ec); - m_broadcast_timer.cancel(ec); - m_closing = true; - m_socket.close(); - - for (std::set::iterator i = m_devices.begin() - , end(m_devices.end()); i != end; ++i) - { - rootdevice& d = const_cast(*i); - TORRENT_ASSERT(d.magic == 1337); - if (d.control_url.empty()) continue; - for (std::vector::iterator j = d.mapping.begin() - , end(d.mapping.end()); j != end; ++j) - { - if (j->protocol == none) continue; - if (j->action == mapping_t::action_add) - { - j->action = mapping_t::action_none; - continue; - } - j->action = mapping_t::action_delete; - m_mappings[j - d.mapping.begin()].protocol = none; - } - if (num_mappings() > 0) update_map(d, 0); - } -} - diff --git a/libtorrent/src/ut_metadata.cpp b/libtorrent/src/ut_metadata.cpp deleted file mode 100644 index aa1cfede1..000000000 --- a/libtorrent/src/ut_metadata.cpp +++ /dev/null @@ -1,460 +0,0 @@ -/* - -Copyright (c) 2007, Arvid Norberg -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions -are met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in - the documentation and/or other materials provided with the distribution. - * Neither the name of the author nor the names of its - contributors may be used to endorse or promote products derived - from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -POSSIBILITY OF SUCH DAMAGE. - -*/ - -#include "libtorrent/pch.hpp" - -#ifdef _MSC_VER -#pragma warning(push, 1) -#endif - -#include - -#ifdef _MSC_VER -#pragma warning(pop) -#endif - -#include -#include -#include -#include - -#include "libtorrent/peer_connection.hpp" -#include "libtorrent/bt_peer_connection.hpp" -#include "libtorrent/hasher.hpp" -#include "libtorrent/bencode.hpp" -#include "libtorrent/torrent.hpp" -#include "libtorrent/extensions.hpp" -#include "libtorrent/extensions/ut_metadata.hpp" -#include "libtorrent/alert_types.hpp" -#ifdef TORRENT_STATS -#include "libtorrent/aux_/session_impl.hpp" -#endif - -namespace libtorrent { namespace -{ - int div_round_up(int numerator, int denominator) - { - return (numerator + denominator - 1) / denominator; - } - - void nop(char*) {} - - struct ut_metadata_plugin : torrent_plugin - { - ut_metadata_plugin(torrent& t) - : m_torrent(t) - , m_metadata_progress(0) - , m_metadata_size(0) - { - } - - virtual void on_files_checked() - { - // if the torrent is a seed, copy the metadata from - // the torrent before it is deallocated - if (m_torrent.is_seed()) - metadata(); - } - - virtual boost::shared_ptr new_connection( - peer_connection* pc); - - buffer::const_interval metadata() const - { - TORRENT_ASSERT(m_torrent.valid_metadata()); - if (!m_metadata) - { - m_metadata = m_torrent.torrent_file().metadata(); - m_metadata_size = m_torrent.torrent_file().metadata_size(); - TORRENT_ASSERT(hasher(m_metadata.get(), m_metadata_size).final() - == m_torrent.torrent_file().info_hash()); - } - return buffer::const_interval(m_metadata.get(), m_metadata.get() - + m_metadata_size); - } - - bool received_metadata(char const* buf, int size, int piece, int total_size) - { - if (m_torrent.valid_metadata()) return false; - - if (!m_metadata) - { - // verify the total_size - if (total_size <= 0 || total_size > 500 * 1024) return false; - - m_metadata.reset(new char[total_size]); - m_requested_metadata.resize(div_round_up(total_size, 16 * 1024), 0); - m_metadata_size = total_size; - } - - if (piece < 0 || piece >= int(m_requested_metadata.size())) - return false; - - TORRENT_ASSERT(piece * 16 * 1024 + size <= m_metadata_size); - std::memcpy(&m_metadata[piece * 16 * 1024], buf, size); - // mark this piece has 'have' - m_requested_metadata[piece] = (std::numeric_limits::max)(); - - bool have_all = std::count(m_requested_metadata.begin() - , m_requested_metadata.end(), (std::numeric_limits::max)()) - == int(m_requested_metadata.size()); - - if (!have_all) return false; - - hasher h; - h.update(&m_metadata[0], m_metadata_size); - sha1_hash info_hash = h.final(); - - if (info_hash != m_torrent.torrent_file().info_hash()) - { - std::fill(m_requested_metadata.begin(), m_requested_metadata.end(), 0); - - if (m_torrent.alerts().should_post()) - { - m_torrent.alerts().post_alert(metadata_failed_alert( - m_torrent.get_handle())); - } - - return false; - } - - lazy_entry metadata; - int ret = lazy_bdecode(m_metadata.get(), m_metadata.get() + m_metadata_size, metadata); - std::string error; - if (!m_torrent.set_metadata(metadata, error)) - { - // this means the metadata is correct, since we - // verified it against the info-hash, but we - // failed to parse it. Pause the torrent - // TODO: Post an alert! - m_torrent.pause(); - return false; - } - - // clear the storage for the bitfield - std::vector().swap(m_requested_metadata); - - return true; - } - - // returns a piece of the metadata that - // we should request. - int metadata_request(); - - // this is called from the peer_connection for - // each piece of metadata it receives - void metadata_progress(int total_size, int received) - { - m_metadata_progress += received; - m_metadata_size = total_size; - } - - void on_piece_pass(int) - { - // if we became a seed, copy the metadata from - // the torrent before it is deallocated - if (m_torrent.is_seed()) - metadata(); - } - - void metadata_size(int size) - { - if (m_metadata_size > 0 || size <= 0 || size > 500 * 1024) return; - m_metadata_size = size; - m_metadata.reset(new char[size]); - m_requested_metadata.resize(div_round_up(size, 16 * 1024), 0); - } - - private: - torrent& m_torrent; - - // this buffer is filled with the info-section of - // the metadata file while downloading it from - // peers, and while sending it. - // it is mutable because it's generated lazily - mutable boost::shared_array m_metadata; - - int m_metadata_progress; - mutable int m_metadata_size; - - // this vector keeps track of how many times each meatdata - // block has been requested - // std::numeric_limits::max() means we have the piece - std::vector m_requested_metadata; - }; - - - struct ut_metadata_peer_plugin : peer_plugin - { - ut_metadata_peer_plugin(torrent& t, bt_peer_connection& pc - , ut_metadata_plugin& tp) - : m_message_index(0) - , m_no_metadata(min_time()) - , m_torrent(t) - , m_pc(pc) - , m_tp(tp) - {} - - // can add entries to the extension handshake - virtual void add_handshake(entry& h) - { - entry& messages = h["m"]; - messages["ut_metadata"] = 15; - if (m_torrent.valid_metadata()) - h["metadata_size"] = m_tp.metadata().left(); - } - - // called when the extension handshake from the other end is received - virtual bool on_extension_handshake(lazy_entry const& h) - { - m_message_index = 0; - if (h.type() != lazy_entry::dict_t) return false; - lazy_entry const* messages = h.dict_find("m"); - if (!messages || messages->type() != lazy_entry::dict_t) return false; - - int index = messages->dict_find_int_value("ut_metadata", -1); - if (index == -1) return false; - m_message_index = index; - - int metadata_size = h.dict_find_int_value("metadata_size"); - if (metadata_size > 0) - m_tp.metadata_size(metadata_size); - return true; - } - - void write_metadata_packet(int type, int piece) - { - TORRENT_ASSERT(type >= 0 && type <= 2); - TORRENT_ASSERT(piece >= 0); - TORRENT_ASSERT(!m_pc.associated_torrent().expired()); - -#ifdef TORRENT_VERBOSE_LOGGING - (*m_pc.m_logger) << time_now_string() << " ==> UT_METADATA [ " - "type: " << type << " | piece: " << piece << " ]\n"; -#endif - // abort if the peer doesn't support the metadata extension - if (m_message_index == 0) return; - - entry e; - e["msg_type"] = type; - e["piece"] = piece; - - char const* metadata = 0; - int metadata_piece_size = 0; - - if (type == 1) - { - TORRENT_ASSERT(m_pc.associated_torrent().lock()->valid_metadata()); - e["total_size"] = m_tp.metadata().left(); - int offset = piece * 16 * 1024; - metadata = m_tp.metadata().begin + offset; - metadata_piece_size = (std::min)( - int(m_tp.metadata().left() - offset), 16 * 1024); - TORRENT_ASSERT(metadata_piece_size > 0); - TORRENT_ASSERT(offset >= 0); - TORRENT_ASSERT(offset + metadata_piece_size <= int(m_tp.metadata().left())); - } - - char msg[200]; - char* header = msg; - char* p = &msg[6]; - int len = bencode(p, e); - int total_size = 2 + len + metadata_piece_size; - namespace io = detail; - io::write_uint32(total_size, header); - io::write_uint8(bt_peer_connection::msg_extended, header); - io::write_uint8(m_message_index, header); - - m_pc.send_buffer(msg, len + 6); - if (metadata_piece_size) m_pc.append_send_buffer( - (char*)metadata, metadata_piece_size, &nop); - } - - virtual bool on_extended(int length - , int extended_msg, buffer::const_interval body) - { - if (extended_msg != 15) return false; - if (m_message_index == 0) return false; - - if (length > 17 * 1024) - { - m_pc.disconnect("ut_metadata message larger than 17 kB", 2); - return true; - } - - if (!m_pc.packet_finished()) return true; - - int len; - entry msg = bdecode(body.begin, body.end, len); - if (msg.type() == entry::undefined_t) - { - m_pc.disconnect("invalid bencoding in ut_metadata message", 2); - return true; - } - - int type = msg["msg_type"].integer(); - int piece = msg["piece"].integer(); - -#ifdef TORRENT_VERBOSE_LOGGING - (*m_pc.m_logger) << time_now_string() << " <== UT_METADATA [ " - "type: " << type << " | piece: " << piece << " ]\n"; -#endif - - switch (type) - { - case 0: // request - { - if (!m_torrent.valid_metadata()) - { - write_metadata_packet(2, piece); - return true; - } - // TODO: put the request on the queue in some cases - write_metadata_packet(1, piece); - } - break; - case 1: // data - { - std::vector::iterator i = std::find(m_sent_requests.begin() - , m_sent_requests.end(), piece); - - // unwanted piece? - if (i == m_sent_requests.end()) return true; - - m_sent_requests.erase(i); - entry const* total_size = msg.find_key("total_size"); - m_tp.received_metadata(body.begin + len, body.left() - len, piece - , (total_size && total_size->type() == entry::int_t) ? total_size->integer() : 0); - } - break; - case 2: // have no data - { - m_no_metadata = time_now(); - std::vector::iterator i = std::find(m_sent_requests.begin() - , m_sent_requests.end(), piece); - // unwanted piece? - if (i == m_sent_requests.end()) return true; - m_sent_requests.erase(i); - } - break; - default: - { - std::stringstream msg; - msg << "unknown ut_metadata extension message: " << type; - m_pc.disconnect(msg.str().c_str(), 2); - } - } - return true; - } - - virtual void tick() - { - // if we don't have any metadata, and this peer - // supports the request metadata extension - // and we aren't currently waiting for a request - // reply. Then, send a request for some metadata. - if (!m_torrent.valid_metadata() - && m_message_index != 0 - && m_sent_requests.size() < 2 - && has_metadata()) - { - int piece = m_tp.metadata_request(); - m_sent_requests.push_back(piece); - write_metadata_packet(0, piece); - } - } - - bool has_metadata() const - { - return time_now() - m_no_metadata > minutes(1); - } - - private: - - // this is the message index the remote peer uses - // for metadata extension messages. - int m_message_index; - - // this is set to the current time each time we get a - // "I don't have metadata" message. - ptime m_no_metadata; - - // request queues - std::vector m_sent_requests; - std::vector m_incoming_requests; - - torrent& m_torrent; - bt_peer_connection& m_pc; - ut_metadata_plugin& m_tp; - }; - - boost::shared_ptr ut_metadata_plugin::new_connection( - peer_connection* pc) - { - bt_peer_connection* c = dynamic_cast(pc); - if (!c) return boost::shared_ptr(); - return boost::shared_ptr(new ut_metadata_peer_plugin(m_torrent, *c, *this)); - } - - int ut_metadata_plugin::metadata_request() - { - std::vector::iterator i = std::min_element( - m_requested_metadata.begin(), m_requested_metadata.end()); - - if (m_requested_metadata.empty()) - { - // if we don't know how many pieces there are - // just ask for piece 0 - m_requested_metadata.resize(1, 1); - return 0; - } - - int piece = i - m_requested_metadata.begin(); - m_requested_metadata[piece] = piece; - return piece; - } - -} } - -namespace libtorrent -{ - - boost::shared_ptr create_ut_metadata_plugin(torrent* t, void*) - { - // don't add this extension if the torrent is private - if (t->valid_metadata() && t->torrent_file().priv()) return boost::shared_ptr(); - return boost::shared_ptr(new ut_metadata_plugin(*t)); - } - -} - - diff --git a/libtorrent/src/ut_pex.cpp b/libtorrent/src/ut_pex.cpp deleted file mode 100644 index 723f119d2..000000000 --- a/libtorrent/src/ut_pex.cpp +++ /dev/null @@ -1,418 +0,0 @@ -/* - -Copyright (c) 2006, MassaRoddel, Arvid Norberg -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions -are met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in - the documentation and/or other materials provided with the distribution. - * Neither the name of the author nor the names of its - contributors may be used to endorse or promote products derived - from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -POSSIBILITY OF SUCH DAMAGE. - -*/ - -#include "libtorrent/pch.hpp" - -#ifdef _MSC_VER -#pragma warning(push, 1) -#endif - -#include - -#ifdef _MSC_VER -#pragma warning(pop) -#endif - -#include "libtorrent/peer_connection.hpp" -#include "libtorrent/bt_peer_connection.hpp" -#include "libtorrent/bencode.hpp" -#include "libtorrent/torrent.hpp" -#include "libtorrent/extensions.hpp" - -#include "libtorrent/extensions/ut_pex.hpp" - -namespace libtorrent { namespace -{ - const char extension_name[] = "ut_pex"; - - enum - { - extension_index = 1, - max_peer_entries = 100 - }; - - bool send_peer(peer_connection const& p) - { - // don't send out peers that we haven't connected to - // (that have connected to us) - if (!p.is_local()) return false; - // don't send out peers that we haven't successfully connected to - if (p.is_connecting()) return false; - return true; - } - - struct ut_pex_plugin: torrent_plugin - { - ut_pex_plugin(torrent& t): m_torrent(t), m_1_minute(55) {} - - virtual boost::shared_ptr new_connection(peer_connection* pc); - - std::vector& get_ut_pex_msg() - { - return m_ut_pex_msg; - } - - // the second tick of the torrent - // each minute the new lists of "added" + "added.f" and "dropped" - // are calculated here and the pex message is created - // each peer connection will use this message - // max_peer_entries limits the packet size - virtual void tick() - { - if (++m_1_minute < 60) return; - - m_1_minute = 0; - - entry pex; - std::string& pla = pex["added"].string(); - std::string& pld = pex["dropped"].string(); - std::string& plf = pex["added.f"].string(); - std::string& pla6 = pex["added6"].string(); - std::string& pld6 = pex["dropped6"].string(); - std::string& plf6 = pex["added6.f"].string(); - std::back_insert_iterator pla_out(pla); - std::back_insert_iterator pld_out(pld); - std::back_insert_iterator plf_out(plf); - std::back_insert_iterator pla6_out(pla6); - std::back_insert_iterator pld6_out(pld6); - std::back_insert_iterator plf6_out(plf6); - - std::set dropped; - m_old_peers.swap(dropped); - - int num_added = 0; - for (torrent::peer_iterator i = m_torrent.begin() - , end(m_torrent.end()); i != end; ++i) - { - peer_connection* peer = *i; - if (!send_peer(*peer)) continue; - - tcp::endpoint const& remote = peer->remote(); - m_old_peers.insert(remote); - - std::set::iterator di = dropped.find(remote); - if (di == dropped.end()) - { - // don't write too big of a package - if (num_added >= max_peer_entries) break; - - // only send proper bittorrent peers - bt_peer_connection* p = dynamic_cast(peer); - if (!p) continue; - - // no supported flags to set yet - // 0x01 - peer supports encryption - // 0x02 - peer is a seed - int flags = p->is_seed() ? 2 : 0; -#ifndef TORRENT_DISABLE_ENCRYPTION - flags |= p->supports_encryption() ? 1 : 0; -#endif - // i->first was added since the last time - if (remote.address().is_v4()) - { - detail::write_endpoint(remote, pla_out); - detail::write_uint8(flags, plf_out); - } - else - { - detail::write_endpoint(remote, pla6_out); - detail::write_uint8(flags, plf6_out); - } - ++num_added; - } - else - { - // this was in the previous message - // so, it wasn't dropped - dropped.erase(di); - } - } - - for (std::set::const_iterator i = dropped.begin() - , end(dropped.end()); i != end; ++i) - { - if (i->address().is_v4()) - detail::write_endpoint(*i, pld_out); - else - detail::write_endpoint(*i, pld6_out); - } - - m_ut_pex_msg.clear(); - bencode(std::back_inserter(m_ut_pex_msg), pex); - } - - private: - torrent& m_torrent; - - std::set m_old_peers; - int m_1_minute; - std::vector m_ut_pex_msg; - }; - - - struct ut_pex_peer_plugin : peer_plugin - { - ut_pex_peer_plugin(torrent& t, peer_connection& pc, ut_pex_plugin& tp) - : m_torrent(t) - , m_pc(pc) - , m_tp(tp) - , m_1_minute(55) - , m_message_index(0) - , m_first_time(true) - {} - - virtual void add_handshake(entry& h) - { - entry& messages = h["m"]; - messages[extension_name] = extension_index; - } - - virtual bool on_extension_handshake(lazy_entry const& h) - { - m_message_index = 0; - if (h.type() != lazy_entry::dict_t) return false; - lazy_entry const* messages = h.dict_find("m"); - if (!messages || messages->type() != lazy_entry::dict_t) return false; - - int index = messages->dict_find_int_value(extension_name, -1); - if (index == -1) return false; - m_message_index = index; - return true; - } - - virtual bool on_extended(int length, int msg, buffer::const_interval body) - { - if (msg != extension_index) return false; - if (m_message_index == 0) return false; - - if (length > 500 * 1024) - { - m_pc.disconnect("peer exchange message larger than 500 kB", 2); - return true; - } - - if (body.left() < length) return true; - - lazy_entry pex_msg; - int ret = lazy_bdecode(body.begin, body.end, pex_msg); - if (pex_msg.type() != lazy_entry::dict_t) - { - m_pc.disconnect("invalid bencoding in ut_metadata message", 2); - return true; - } - - lazy_entry const* p = pex_msg.dict_find("added"); - lazy_entry const* pf = pex_msg.dict_find("added.f"); - - if (p != 0 - && pf != 0 - && p->type() == lazy_entry::string_t - && pf->type() == lazy_entry::string_t - && pf->string_length() == p->string_length() / 6) - { - int num_peers = pf->string_length(); - char const* in = p->string_ptr(); - char const* fin = pf->string_ptr(); - - peer_id pid(0); - policy& p = m_torrent.get_policy(); - for (int i = 0; i < num_peers; ++i) - { - tcp::endpoint adr = detail::read_v4_endpoint(in); - char flags = *fin++; - p.peer_from_tracker(adr, pid, peer_info::pex, flags); - } - } - - lazy_entry const* p6 = pex_msg.dict_find("added6"); - lazy_entry const* p6f = pex_msg.dict_find("added6.f"); - if (p6 != 0 - && p6f != 0 - && p6->type() == lazy_entry::string_t - && p6f->type() == lazy_entry::string_t - && p6f->string_length() == p6->string_length() / 18) - { - int num_peers = p6f->string_length(); - char const* in = p6->string_ptr(); - char const* fin = p6f->string_ptr(); - - peer_id pid(0); - policy& p = m_torrent.get_policy(); - for (int i = 0; i < num_peers; ++i) - { - tcp::endpoint adr = detail::read_v6_endpoint(in); - char flags = *fin++; - p.peer_from_tracker(adr, pid, peer_info::pex, flags); - } - } - return true; - } - - // the peers second tick - // every minute we send a pex message - virtual void tick() - { - if (!m_message_index) return; // no handshake yet - if (++m_1_minute <= 60) return; - - if (m_first_time) - { - send_ut_peer_list(); - m_first_time = false; - } - else - { - send_ut_peer_diff(); - } - m_1_minute = 0; - } - - private: - - void send_ut_peer_diff() - { - std::vector const& pex_msg = m_tp.get_ut_pex_msg(); - - buffer::interval i = m_pc.allocate_send_buffer(6 + pex_msg.size()); - - detail::write_uint32(1 + 1 + pex_msg.size(), i.begin); - detail::write_uint8(bt_peer_connection::msg_extended, i.begin); - detail::write_uint8(m_message_index, i.begin); - std::copy(pex_msg.begin(), pex_msg.end(), i.begin); - i.begin += pex_msg.size(); - - TORRENT_ASSERT(i.begin == i.end); - m_pc.setup_send(); - } - - void send_ut_peer_list() - { - entry pex; - // leave the dropped string empty - pex["dropped"].string(); - std::string& pla = pex["added"].string(); - std::string& plf = pex["added.f"].string(); - pex["dropped6"].string(); - std::string& pla6 = pex["added6"].string(); - std::string& plf6 = pex["added6.f"].string(); - std::back_insert_iterator pla_out(pla); - std::back_insert_iterator plf_out(plf); - std::back_insert_iterator pla6_out(pla6); - std::back_insert_iterator plf6_out(plf6); - - int num_added = 0; - for (torrent::peer_iterator i = m_torrent.begin() - , end(m_torrent.end()); i != end; ++i) - { - peer_connection* peer = *i; - if (!send_peer(*peer)) continue; - - // don't write too big of a package - if (num_added >= max_peer_entries) break; - - // only send proper bittorrent peers - bt_peer_connection* p = dynamic_cast(peer); - if (!p) continue; - - // no supported flags to set yet - // 0x01 - peer supports encryption - // 0x02 - peer is a seed - int flags = p->is_seed() ? 2 : 0; -#ifndef TORRENT_DISABLE_ENCRYPTION - flags |= p->supports_encryption() ? 1 : 0; -#endif - tcp::endpoint const& remote = peer->remote(); - // i->first was added since the last time - if (remote.address().is_v4()) - { - detail::write_endpoint(remote, pla_out); - detail::write_uint8(flags, plf_out); - } - else - { - detail::write_endpoint(remote, pla6_out); - detail::write_uint8(flags, plf6_out); - } - ++num_added; - } - std::vector pex_msg; - bencode(std::back_inserter(pex_msg), pex); - - buffer::interval i = m_pc.allocate_send_buffer(6 + pex_msg.size()); - - detail::write_uint32(1 + 1 + pex_msg.size(), i.begin); - detail::write_uint8(bt_peer_connection::msg_extended, i.begin); - detail::write_uint8(m_message_index, i.begin); - std::copy(pex_msg.begin(), pex_msg.end(), i.begin); - i.begin += pex_msg.size(); - - TORRENT_ASSERT(i.begin == i.end); - m_pc.setup_send(); - } - - torrent& m_torrent; - peer_connection& m_pc; - ut_pex_plugin& m_tp; - int m_1_minute; - int m_message_index; - - // this is initialized to true, and set to - // false after the first pex message has been sent. - // it is used to know if a diff message or a full - // message should be sent. - bool m_first_time; - }; - - boost::shared_ptr ut_pex_plugin::new_connection(peer_connection* pc) - { - bt_peer_connection* c = dynamic_cast(pc); - if (!c) return boost::shared_ptr(); - return boost::shared_ptr(new ut_pex_peer_plugin(m_torrent - , *pc, *this)); - } -}} - -namespace libtorrent -{ - - boost::shared_ptr create_ut_pex_plugin(torrent* t, void*) - { - if (t->torrent_file().priv()) - { - return boost::shared_ptr(); - } - return boost::shared_ptr(new ut_pex_plugin(*t)); - } - -} - - diff --git a/libtorrent/src/web_peer_connection.cpp b/libtorrent/src/web_peer_connection.cpp deleted file mode 100755 index 277fa0035..000000000 --- a/libtorrent/src/web_peer_connection.cpp +++ /dev/null @@ -1,720 +0,0 @@ -/* - -Copyright (c) 2003, Arvid Norberg -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions -are met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in - the documentation and/or other materials provided with the distribution. - * Neither the name of the author nor the names of its - contributors may be used to endorse or promote products derived - from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -POSSIBILITY OF SUCH DAMAGE. - -*/ - -#include "libtorrent/pch.hpp" - -#include -#include -#include -#include -#include -#include -#include - -#include "libtorrent/web_peer_connection.hpp" -#include "libtorrent/session.hpp" -#include "libtorrent/identify_client.hpp" -#include "libtorrent/entry.hpp" -#include "libtorrent/bencode.hpp" -#include "libtorrent/alert_types.hpp" -#include "libtorrent/invariant_check.hpp" -#include "libtorrent/io.hpp" -#include "libtorrent/version.hpp" -#include "libtorrent/aux_/session_impl.hpp" -#include "libtorrent/parse_url.hpp" - -using boost::bind; -using boost::shared_ptr; -using libtorrent::aux::session_impl; - -namespace libtorrent -{ - web_peer_connection::web_peer_connection( - session_impl& ses - , boost::weak_ptr t - , boost::shared_ptr s - , tcp::endpoint const& remote - , std::string const& url - , policy::peer* peerinfo) - : peer_connection(ses, t, s, remote, peerinfo) - , m_url(url) - , m_first_request(true) - , m_range_pos(0) - { - INVARIANT_CHECK; - - // we want large blocks as well, so - // we can request more bytes at once - request_large_blocks(true); - set_upload_only(true); - - // we only want left-over bandwidth - set_priority(0); - shared_ptr tor = t.lock(); - TORRENT_ASSERT(tor); - int blocks_per_piece = tor->torrent_file().piece_length() / tor->block_size(); - - // we always prefer downloading 1 MB chunks - // from web seeds - prefer_whole_pieces((1024 * 1024) / tor->torrent_file().piece_length()); - - // multiply with the blocks per piece since that many requests are - // merged into one http request - m_max_out_request_queue = ses.settings().urlseed_pipeline_size - * blocks_per_piece; - - // since this is a web seed, change the timeout - // according to the settings. - set_timeout(ses.settings().urlseed_timeout); -#ifdef TORRENT_VERBOSE_LOGGING - (*m_logger) << "*** web_peer_connection\n"; -#endif - - std::string protocol; - char const* error; - boost::tie(protocol, m_auth, m_host, m_port, m_path, error) - = parse_url_components(url); - TORRENT_ASSERT(error == 0); - - if (!m_auth.empty()) - m_auth = base64encode(m_auth); - - m_server_string = "URL seed @ "; - m_server_string += m_host; - } - - web_peer_connection::~web_peer_connection() - {} - - boost::optional - web_peer_connection::downloading_piece_progress() const - { - if (m_requests.empty()) - return boost::optional(); - - boost::shared_ptr t = associated_torrent().lock(); - TORRENT_ASSERT(t); - - piece_block_progress ret; - - ret.piece_index = m_requests.front().piece; - if (!m_piece.empty()) - { - ret.bytes_downloaded = int(m_piece.size()); - } - else - { - if (!m_parser.header_finished()) - { - ret.bytes_downloaded = 0; - } - else - { - int receive_buffer_size = receive_buffer().left() - m_parser.body_start(); - ret.bytes_downloaded = receive_buffer_size % t->block_size(); - } - } - ret.block_index = (m_requests.front().start + ret.bytes_downloaded) / t->block_size(); - ret.full_block_bytes = t->block_size(); - const int last_piece = t->torrent_file().num_pieces() - 1; - if (ret.piece_index == last_piece && ret.block_index - == t->torrent_file().piece_size(last_piece) / t->block_size()) - ret.full_block_bytes = t->torrent_file().piece_size(last_piece) % t->block_size(); - return ret; - } - - void web_peer_connection::on_connected() - { - boost::shared_ptr t = associated_torrent().lock(); - TORRENT_ASSERT(t); - - // this is always a seed - incoming_have_all(); - - // it is always possible to request pieces - incoming_unchoke(); - - reset_recv_buffer(t->block_size() + 1024); - } - - void web_peer_connection::write_request(peer_request const& r) - { - INVARIANT_CHECK; - - boost::shared_ptr t = associated_torrent().lock(); - TORRENT_ASSERT(t); - - TORRENT_ASSERT(t->valid_metadata()); - - bool single_file_request = false; - if (!m_path.empty() && m_path[m_path.size() - 1] != '/') - single_file_request = true; - - torrent_info const& info = t->torrent_file(); - - std::string request; - request.reserve(400); - - int size = r.length; - const int block_size = t->block_size(); - const int piece_size = t->torrent_file().piece_length(); - peer_request pr; - while (size > 0) - { - int request_offset = r.start + r.length - size; - pr.start = request_offset % piece_size; - pr.length = (std::min)(block_size, size); - pr.piece = r.piece + request_offset / piece_size; - m_requests.push_back(pr); - size -= pr.length; - } - - proxy_settings const& ps = m_ses.web_seed_proxy(); - bool using_proxy = ps.type == proxy_settings::http - || ps.type == proxy_settings::http_pw; - - if (single_file_request) - { - request += "GET "; - // do not encode single file paths, they are - // assumed to be encoded in the torrent file - request += using_proxy ? m_url : m_path; - request += " HTTP/1.1\r\n"; - request += "Host: "; - request += m_host; - if (m_first_request) - { - request += "\r\nUser-Agent: "; - request += m_ses.settings().user_agent; - } - if (!m_auth.empty()) - { - request += "\r\nAuthorization: Basic "; - request += m_auth; - } - if (ps.type == proxy_settings::http_pw) - { - request += "\r\nProxy-Authorization: Basic "; - request += base64encode(ps.username + ":" + ps.password); - } - if (using_proxy) - { - request += "\r\nProxy-Connection: keep-alive"; - } - request += "\r\nRange: bytes="; - request += to_string(size_type(r.piece) * info.piece_length() + r.start).elems; - request += "-"; - request += to_string(r.piece * info.piece_length() + r.start + r.length - 1).elems; - if (m_first_request || using_proxy) - request += "\r\nConnection: keep-alive"; - request += "\r\n\r\n"; - m_first_request = false; - m_file_requests.push_back(0); - } - else - { - std::vector files = info.orig_files().map_block(r.piece, r.start - , r.length); - - for (std::vector::iterator i = files.begin(); - i != files.end(); ++i) - { - file_slice const& f = *i; - - request += "GET "; - if (using_proxy) - { - request += m_url; - std::string path = info.orig_files().at(f.file_index).path.string(); - request += escape_path(path.c_str(), path.length()); - } - else - { - std::string path = m_path; - path += info.orig_files().at(f.file_index).path.string(); - request += escape_path(path.c_str(), path.length()); - } - request += " HTTP/1.1\r\n"; - request += "Host: "; - request += m_host; - if (m_first_request) - { - request += "\r\nUser-Agent: "; - request += m_ses.settings().user_agent; - } - if (!m_auth.empty()) - { - request += "\r\nAuthorization: Basic "; - request += m_auth; - } - if (ps.type == proxy_settings::http_pw) - { - request += "\r\nProxy-Authorization: Basic "; - request += base64encode(ps.username + ":" + ps.password); - } - if (using_proxy) - { - request += "\r\nProxy-Connection: keep-alive"; - } - request += "\r\nRange: bytes="; - request += to_string(f.offset).elems; - request += "-"; - request += to_string(f.offset + f.size - 1).elems; - if (m_first_request || using_proxy) - request += "\r\nConnection: keep-alive"; - request += "\r\n\r\n"; - m_first_request = false; - TORRENT_ASSERT(f.file_index >= 0); - m_file_requests.push_back(f.file_index); - } - } - -#ifdef TORRENT_VERBOSE_LOGGING - (*m_logger) << request << "\n"; -#endif - - send_buffer(request.c_str(), request.size(), message_type_request); - } - - // -------------------------- - // RECEIVE DATA - // -------------------------- - - namespace - { - bool range_contains(peer_request const& range, peer_request const& req, int piece_size) - { - size_type range_start = size_type(range.piece) * piece_size + range.start; - size_type req_start = size_type(req.piece) * piece_size + req.start; - return range_start <= req_start - && range_start + range.length >= req_start + req.length; - } - } - - void web_peer_connection::on_receive(error_code const& error - , std::size_t bytes_transferred) - { - INVARIANT_CHECK; - - if (error) - { -#ifdef TORRENT_VERBOSE_LOGGING - (*m_logger) << "*** web_peer_connection error: " - << error.message() << "\n"; -#endif - return; - } - - boost::shared_ptr t = associated_torrent().lock(); - TORRENT_ASSERT(t); - - incoming_piece_fragment(); - - for (;;) - { - buffer::const_interval recv_buffer = receive_buffer(); - - int payload; - int protocol; - bool header_finished = m_parser.header_finished(); - if (!header_finished) - { - bool error = false; - boost::tie(payload, protocol) = m_parser.incoming(recv_buffer, error); - m_statistics.received_bytes(0, protocol); - bytes_transferred -= protocol; - - if (error) - { -#ifdef TORRENT_VERBOSE_LOGGING - (*m_logger) << "*** " << std::string(recv_buffer.begin, recv_buffer.end) << "\n"; -#endif - disconnect("failed to parse HTTP response", 2); - return; - } - - TORRENT_ASSERT(recv_buffer.left() == 0 || *recv_buffer.begin == 'H'); - - TORRENT_ASSERT(recv_buffer.left() <= packet_size()); - - // this means the entire status line hasn't been received yet - if (m_parser.status_code() == -1) - { - TORRENT_ASSERT(payload == 0); - TORRENT_ASSERT(bytes_transferred == 0); - break; - } - - // if the status code is not one of the accepted ones, abort - if (m_parser.status_code() != 206 // partial content - && m_parser.status_code() != 200 // OK - && !(m_parser.status_code() >= 300 // redirect - && m_parser.status_code() < 400)) - { - if (m_parser.status_code() == 503) - { - // temporarily unavailable, retry later - t->retry_url_seed(m_url); - } - t->remove_url_seed(m_url); - std::string error_msg = to_string(m_parser.status_code()).elems - + (" " + m_parser.message()); - if (m_ses.m_alerts.should_post()) - { - session_impl::mutex_t::scoped_lock l(m_ses.m_mutex); - m_ses.m_alerts.post_alert(url_seed_alert(t->get_handle(), url() - , error_msg)); - } - disconnect(error_msg.c_str(), 1); - return; - } - if (!m_parser.header_finished()) - { - TORRENT_ASSERT(payload == 0); - TORRENT_ASSERT(bytes_transferred == 0); - break; - } - - m_body_start = m_parser.body_start(); - m_received_body = 0; - } - - // we just completed reading the header - if (!header_finished) - { -#ifdef TORRENT_VERBOSE_LOGGING - (*m_logger) << "*** STATUS: " << m_parser.status_code() - << " " << m_parser.message() << "\n"; - std::map const& headers = m_parser.headers(); - for (std::map::const_iterator i = headers.begin() - , end(headers.end()); i != end; ++i) - (*m_logger) << " " << i->first << ": " << i->second << "\n"; -#endif - if (m_parser.status_code() >= 300 && m_parser.status_code() < 400) - { - // this means we got a redirection request - // look for the location header - std::string location = m_parser.header("location"); - - if (location.empty()) - { - // we should not try this server again. - t->remove_url_seed(m_url); - disconnect("got HTTP redirection status without location header", 2); - return; - } - - bool single_file_request = false; - if (!m_path.empty() && m_path[m_path.size() - 1] != '/') - single_file_request = true; - - // add the redirected url and remove the current one - if (!single_file_request) - { - TORRENT_ASSERT(!m_file_requests.empty()); - int file_index = m_file_requests.front(); - - torrent_info const& info = t->torrent_file(); - std::string path = info.orig_files().at(file_index).path.string(); - path = escape_path(path.c_str(), path.length()); - size_t i = location.rfind(path); - if (i == std::string::npos) - { - t->remove_url_seed(m_url); - std::stringstream msg; - msg << "got invalid HTTP redirection location (\"" << location << "\") " - "expected it to end with: " << path; - disconnect(msg.str().c_str(), 2); - return; - } - location.resize(i); - } - t->add_url_seed(location); - t->remove_url_seed(m_url); - std::stringstream msg; - msg << "redirecting to \"" << location << "\""; - disconnect(msg.str().c_str()); - return; - } - - std::string const& server_version = m_parser.header("server"); - if (!server_version.empty()) - { - m_server_string = "URL seed @ "; - m_server_string += m_host; - m_server_string += " ("; - m_server_string += server_version; - m_server_string += ")"; - } - - m_body_start = m_parser.body_start(); - m_received_body = 0; - m_range_pos = 0; - } - - recv_buffer.begin += m_body_start; - - // we only received the header, no data - if (recv_buffer.left() == 0) break; - - size_type range_start; - size_type range_end; - if (m_parser.status_code() == 206) - { - std::stringstream range_str(m_parser.header("content-range")); - char dummy; - std::string bytes; - range_str >> bytes >> range_start >> dummy >> range_end; - if (!range_str) - { - // we should not try this server again. - t->remove_url_seed(m_url); - std::stringstream msg; - msg << "invalid range in HTTP response: " << range_str.str(); - disconnect(msg.str().c_str(), 2); - return; - } - // the http range is inclusive - range_end++; - } - else - { - range_start = 0; - range_end = m_parser.content_length(); - if (range_end == -1) - { - // we should not try this server again. - t->remove_url_seed(m_url); - disconnect("no content-length in HTTP response", 2); - return; - } - } - - int left_in_response = range_end - range_start - m_range_pos; - int payload_transferred = (std::min)(left_in_response, int(bytes_transferred)); - m_statistics.received_bytes(payload_transferred, 0); - bytes_transferred -= payload_transferred; - m_range_pos += payload_transferred;; - if (m_range_pos > range_end - range_start) m_range_pos = range_end - range_start; - -// std::cerr << "REQUESTS: m_requests: " << m_requests.size() -// << " file_requests: " << m_file_requests.size() << std::endl; - - torrent_info const& info = t->torrent_file(); - - if (m_requests.empty() || m_file_requests.empty()) - { - disconnect("unexpected HTTP response", 2); - return; - } - - int file_index = m_file_requests.front(); - peer_request in_range = info.orig_files().map_file(file_index, range_start - , int(range_end - range_start)); - - peer_request front_request = m_requests.front(); - - size_type rs = size_type(in_range.piece) * info.piece_length() + in_range.start; - size_type re = rs + in_range.length; - size_type fs = size_type(front_request.piece) * info.piece_length() + front_request.start; -/* - size_type fe = fs + front_request.length; - - std::cerr << "RANGE: r = (" << rs << ", " << re << " ) " - "f = (" << fs << ", " << fe << ") " - "file_index = " << file_index << " received_body = " << m_received_body << std::endl; -*/ - - // the http response body consists of 3 parts - // 1. the middle of a block or the ending of a block - // 2. a number of whole blocks - // 3. the start of a block - // in that order, these parts are parsed. - - bool range_overlaps_request = re > fs + int(m_piece.size()); - - if (!range_overlaps_request) - { - // this means the end of the incoming request ends _before_ the - // first expected byte (fs + m_piece.size()) - disconnect("invalid range in HTTP response", 2); - return; - } - - // if the request is contained in the range (i.e. the entire request - // fits in the range) we should not start a partial piece, since we soon - // will receive enough to call incoming_piece() and pass the read buffer - // directly (in the next loop below). - if (range_overlaps_request && !range_contains(in_range, front_request, info.piece_length())) - { - // the start of the next block to receive is stored - // in m_piece. We need to append the rest of that - // block from the http receive buffer and then - // (if it completed) call incoming_piece() with - // m_piece as buffer. - - int piece_size = int(m_piece.size()); - int copy_size = (std::min)((std::min)(front_request.length - piece_size - , recv_buffer.left()), int(range_end - range_start - m_received_body)); - m_piece.resize(piece_size + copy_size); - TORRENT_ASSERT(copy_size > 0); - std::memcpy(&m_piece[0] + piece_size, recv_buffer.begin, copy_size); - TORRENT_ASSERT(int(m_piece.size()) <= front_request.length); - recv_buffer.begin += copy_size; - m_received_body += copy_size; - m_body_start += copy_size; - TORRENT_ASSERT(m_received_body <= range_end - range_start); - TORRENT_ASSERT(int(m_piece.size()) <= front_request.length); - if (int(m_piece.size()) == front_request.length) - { - // each call to incoming_piece() may result in us becoming - // a seed. If we become a seed, all seeds we're connected to - // will be disconnected, including this web seed. We need to - // check for the disconnect condition after the call. - - m_requests.pop_front(); - incoming_piece(front_request, &m_piece[0]); - if (associated_torrent().expired()) return; - cut_receive_buffer(m_body_start, t->block_size() + 1024); - m_body_start = 0; - recv_buffer = receive_buffer(); - TORRENT_ASSERT(m_received_body <= range_end - range_start); - m_piece.clear(); - TORRENT_ASSERT(m_piece.empty()); - } - } - - // report all received blocks to the bittorrent engine - while (!m_requests.empty() - && range_contains(in_range, m_requests.front(), info.piece_length()) - && recv_buffer.left() >= m_requests.front().length) - { - peer_request r = m_requests.front(); - m_requests.pop_front(); - TORRENT_ASSERT(recv_buffer.left() >= r.length); - - incoming_piece(r, recv_buffer.begin); - if (associated_torrent().expired()) return; - m_received_body += r.length; - TORRENT_ASSERT(receive_buffer().begin + m_body_start == recv_buffer.begin); - TORRENT_ASSERT(m_received_body <= range_end - range_start); - cut_receive_buffer(r.length + m_body_start, t->block_size() + 1024); - m_body_start = 0; - recv_buffer = receive_buffer(); - } - - if (!m_requests.empty()) - { - range_overlaps_request = in_range.start + in_range.length - > m_requests.front().start + int(m_piece.size()); - - if (in_range.start + in_range.length < m_requests.front().start + m_requests.front().length - && (m_received_body + recv_buffer.left() >= range_end - range_start)) - { - int piece_size = int(m_piece.size()); - int copy_size = (std::min)((std::min)(m_requests.front().length - piece_size - , recv_buffer.left()), int(range_end - range_start - m_received_body)); - TORRENT_ASSERT(copy_size >= 0); - if (copy_size > 0) - { - m_piece.resize(piece_size + copy_size); - std::memcpy(&m_piece[0] + piece_size, recv_buffer.begin, copy_size); - recv_buffer.begin += copy_size; - m_received_body += copy_size; - m_body_start += copy_size; - } - TORRENT_ASSERT(m_received_body == range_end - range_start); - } - } - - TORRENT_ASSERT(m_received_body <= range_end - range_start); - if (m_received_body == range_end - range_start) - { - cut_receive_buffer(recv_buffer.begin - receive_buffer().begin - , t->block_size() + 1024); - recv_buffer = receive_buffer(); - m_file_requests.pop_front(); - m_parser.reset(); - m_body_start = 0; - m_received_body = 0; - continue; - } - if (bytes_transferred == 0) break; - } - TORRENT_ASSERT(bytes_transferred == 0); - } - - void web_peer_connection::get_specific_peer_info(peer_info& p) const - { - if (is_interesting()) p.flags |= peer_info::interesting; - if (is_choked()) p.flags |= peer_info::choked; - if (is_peer_interested()) p.flags |= peer_info::remote_interested; - if (has_peer_choked()) p.flags |= peer_info::remote_choked; - if (is_local()) p.flags |= peer_info::local_connection; - if (!is_connecting() && m_server_string.empty()) - p.flags |= peer_info::handshake; - if (is_connecting() && !is_queued()) p.flags |= peer_info::connecting; - if (is_queued()) p.flags |= peer_info::queued; - - p.client = m_server_string; - p.connection_type = peer_info::web_seed; - } - - bool web_peer_connection::in_handshake() const - { - return m_server_string.empty(); - } - - // throws exception when the client should be disconnected - void web_peer_connection::on_sent(error_code const& error - , std::size_t bytes_transferred) - { - INVARIANT_CHECK; - - if (error) return; - m_statistics.sent_bytes(0, bytes_transferred); - } - - -#ifdef TORRENT_DEBUG - void web_peer_connection::check_invariant() const - { -/* - TORRENT_ASSERT(m_num_pieces == std::count( - m_have_piece.begin() - , m_have_piece.end() - , true)); -*/ } -#endif - -} -