From 4d330803996913e60b8291d0ab63c76d76a923f3 Mon Sep 17 00:00:00 2001 From: Arvid Norberg Date: Sat, 17 Jan 2004 20:04:19 +0000 Subject: [PATCH] *** empty log message *** --- docs/index.html | 25 ++++- docs/index.rst | 32 ++++-- docs/manual.html | 12 ++- docs/manual.rst | 12 ++- examples/client_test.cpp | 16 +-- include/libtorrent/storage.hpp | 12 +++ include/libtorrent/torrent_handle.hpp | 3 + src/peer_connection.cpp | 5 + src/policy.cpp | 15 ++- src/session.cpp | 41 ++++--- src/storage.cpp | 148 ++++++++++++++++---------- src/torrent.cpp | 10 +- src/torrent_handle.cpp | 9 ++ 13 files changed, 239 insertions(+), 101 deletions(-) diff --git a/docs/index.html b/docs/index.html index 7e9cc3720..9c4fd6128 100755 --- a/docs/index.html +++ b/docs/index.html @@ -12,14 +12,16 @@

libtorrent

--++++- - + + @@ -37,9 +39,22 @@ example client.

  • to be very easy to use
  • +

    Feedback

    -

    There's a mailing list.

    +

    There's a mailing list, general libtorrent discussion.

    You can usually find me as hydri in #btports @ irc.freenode.net.

    diff --git a/docs/index.rst b/docs/index.rst index 58ea4d88d..76949fe2d 100755 --- a/docs/index.rst +++ b/docs/index.rst @@ -3,12 +3,13 @@ libtorrent ========== -=================== ======= =========== =============== -`sourceforge page`_ manual_ screenshot_ `mailing list`_ -=================== ======= =========== =============== +=================== ============== ============== =========== =============== +`sourceforge page`_ documentation_ `report bugs`_ screenshot_ `mailing list`_ +=================== ============== ============== =========== =============== .. _sourceforge page: http://www.sourceforge.net/projects/libtorrent -.. _manual: manual.html +.. _documentation: manual.html +.. _`report bugs`: http://sourceforge.net/tracker/?group_id=79942&atid=558250 .. _screenshot: libtorrent_screen.png .. _mailing list: http://lists.sourceforge.net/lists/listinfo/libtorrent-discuss @@ -26,17 +27,36 @@ The main goals of libtorrent are: * to be very easy to use +Donate +====== + +Support the development of libtorrent + +.. raw:: html + +
    + + + + + + + + + + + Feedback ======== -There's a `mailing list`__. +There's a `mailing list`__, general libtorrent discussion. __ http://lists.sourceforge.net/lists/listinfo/libtorrent-discuss You can usually find me as hydri in ``#btports @ irc.freenode.net``. - Aknowledgements =============== diff --git a/docs/manual.html b/docs/manual.html index 1b2d30fdf..41f5d0fe5 100755 --- a/docs/manual.html +++ b/docs/manual.html @@ -101,7 +101,7 @@ party. of a resumed torrent. Saves the storage state, piece_picker state as well as all local peers in a separate fast-resume file.
  • Supports the extension protocol described by Nolar. See extensions.
  • -
  • SUpports files > 2 gigabytes (currently only on windows)
  • +
  • Supports files > 2 gigabytes (currently only on windows)
  • Functions that are yet to be implemented:

    @@ -133,6 +133,9 @@ boost.filesystem, boost.date_time and various other boost libraries as well as z

    building

    +

    Whwn building in release mode you need to define NDEBUG in order to avoid +all asserts and invariant checks within libtorrent. Developer studio does +this by default.

    To build libtorrent you need boost and bjam installed. Then you can use bjam to build libtorrent.

    To make bjam work, you need to set the environment variable BOOST_ROOT to the @@ -253,7 +256,7 @@ change in the future to give more control of the listen-port.

    parsing torrent files

    -

    The torrent files are bencoded. There are two functions in libtorrent that can encode and decode +

    The torrent files are bencoded. There are two functions in libtorrent that can encode and decode bencoded data. They are:

     template<class InIt> entry bdecode(InIt start, InIt end);
    @@ -537,6 +540,7 @@ struct torrent_status
             state_t state;
             float progress;
             boost::posix_time::time_duration next_announce;
    +        boost::posix_time::time_duration announce_interval;
     
             std::size_t total_download;
             std::size_t total_upload;
    @@ -587,7 +591,9 @@ is a pure seeder.
     
     
    sourceforge pagemanualdocumentationreport bugs screenshot mailing list
    -

    next_announce is the time until the torrent will announce itself to the tracker.

    +

    next_announce is the time until the torrent will announce itself to the tracker. And +announce_interval is the time the tracker want us to wait until we announce ourself +again the next time.

    total_download and total_upload is the number of bytes downloaded and uploaded to all peers, accumulated, this session only.

    total_payload_download and total_payload_upload counts the amount of bytes diff --git a/docs/manual.rst b/docs/manual.rst index 817772cda..50e251c57 100755 --- a/docs/manual.rst +++ b/docs/manual.rst @@ -73,6 +73,11 @@ libtorrent is released under the BSD-license_. building ======== +Whwn building in release mode you need to define NDEBUG in order to avoid +all asserts and invariant checks within libtorrent. Developer studio does +this by default. + + To build libtorrent you need boost_ and bjam installed. Then you can use ``bjam`` to build libtorrent. @@ -220,7 +225,7 @@ bencoded data. They are:: template entry bdecode(InIt start, InIt end); template void bencode(OutIt out, const entry& e); -__ http://bitconjurer.org/BitTorrent/protocol.html +__ http://wiki.theory.org/index.php/BitTorrentSpecification The entry_ class is the internal representation of the bencoded data @@ -548,6 +553,7 @@ It contains the following fields:: state_t state; float progress; boost::posix_time::time_duration next_announce; + boost::posix_time::time_duration announce_interval; std::size_t total_download; std::size_t total_upload; @@ -593,7 +599,9 @@ current task is in the ``state`` member, it will be one of the following: | | | +--------------------------+----------------------------------------------------------+ -``next_announce`` is the time until the torrent will announce itself to the tracker. +``next_announce`` is the time until the torrent will announce itself to the tracker. And +``announce_interval`` is the time the tracker want us to wait until we announce ourself +again the next time. ``total_download`` and ``total_upload`` is the number of bytes downloaded and uploaded to all peers, accumulated, *this session* only. diff --git a/examples/client_test.cpp b/examples/client_test.cpp index 2cd22d5f6..23c88242a 100755 --- a/examples/client_test.cpp +++ b/examples/client_test.cpp @@ -38,6 +38,7 @@ POSSIBILITY OF SUCH DAMAGE. #include #include #include +#include #include "libtorrent/entry.hpp" #include "libtorrent/bencode.hpp" @@ -56,7 +57,7 @@ POSSIBILITY OF SUCH DAMAGE. bool sleep_and_input(char* c) { - Sleep(200); + Sleep(500); if (kbhit()) { *c = getch(); @@ -116,7 +117,7 @@ bool sleep_and_input(char* c) fd_set set; FD_ZERO(&set); FD_SET(0, &set); - timeval tv = {0, 200000}; + timeval tv = {0, 500000}; if (select(1, &set, 0, 0, &tv) > 0) { *c = getc(stdin); @@ -220,7 +221,7 @@ int main(int argc, char* argv[]) // settings.proxy_port = 80; // settings.proxy_login = "hyd"; // settings.proxy_password = "foobar"; - settings.user_agent = "example"; + settings.user_agent = "client_test"; std::deque events; @@ -229,7 +230,6 @@ int main(int argc, char* argv[]) std::vector handles; session ses(6881); -// // limit global upload rate to 30 kB/s // ses.set_upload_rate_limit(30 * 1024); ses.set_http_settings(settings); ses.set_severity_level(alert::debug); @@ -293,9 +293,13 @@ int main(int argc, char* argv[]) break; } - if(c==' ') + if(c == 'r') { - events.pop_back(); + // force reannounce on all torrents + std::for_each( + handles.begin() + , handles.end() + , boost::bind(&torrent_handle::force_reannounce, _1)); } } diff --git a/include/libtorrent/storage.hpp b/include/libtorrent/storage.hpp index 60874b470..9a1569038 100755 --- a/include/libtorrent/storage.hpp +++ b/include/libtorrent/storage.hpp @@ -49,8 +49,20 @@ namespace libtorrent { struct piece_checker_data; } + class session; + typedef boost::int64_t size_type; + + std::vector get_filesizes( + const torrent_info& t + , const boost::filesystem::path& p); + + bool match_filesizes( + const torrent_info& t + , const boost::filesystem::path& p + , const std::vector& sizes); + struct file_allocation_failed: std::exception { file_allocation_failed(const char* error_msg): m_msg(error_msg) {} diff --git a/include/libtorrent/torrent_handle.hpp b/include/libtorrent/torrent_handle.hpp index 698b6ab60..f57b35204 100755 --- a/include/libtorrent/torrent_handle.hpp +++ b/include/libtorrent/torrent_handle.hpp @@ -92,6 +92,9 @@ namespace libtorrent state_t state; float progress; boost::posix_time::time_duration next_announce; + boost::posix_time::time_duration announce_interval; + + // TODO: add name of tracker that is currently used // transferred this session! // total, payload plus protocol diff --git a/src/peer_connection.cpp b/src/peer_connection.cpp index b051cd18a..342d2f015 100755 --- a/src/peer_connection.cpp +++ b/src/peer_connection.cpp @@ -1527,6 +1527,8 @@ namespace libtorrent assert(m_send_quota_left != 0); if (m_send_quota_left > 0) amount_to_send = std::min(m_send_quota_left, amount_to_send); + + // we have data that's scheduled for sending int sent = m_socket->send( &m_send_buffer[0] @@ -1540,6 +1542,7 @@ namespace libtorrent m_send_quota_left -= sent; } + // manage the payload markers int amount_payload = 0; if (!m_payloads.empty()) { @@ -1596,6 +1599,7 @@ namespace libtorrent assert(m_added_to_selector); send_buffer_updated(); +/* #ifndef NDEBUG if (has_data()) { @@ -1605,6 +1609,7 @@ namespace libtorrent } } #endif +*/ } diff --git a/src/policy.cpp b/src/policy.cpp index 5182be133..637f30714 100755 --- a/src/policy.cpp +++ b/src/policy.cpp @@ -719,8 +719,19 @@ namespace libtorrent // called when a peer is no longer interested in us void policy::not_interested(peer_connection& c) { - // TODO: return the diff() of this peer to the - // pool of undistributed free upload + if (m_torrent->ratio() != 0.f) + { + assert(c.share_diff() < std::numeric_limits::max()); + int 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() diff --git a/src/session.cpp b/src/session.cpp index 005918efa..103f36869 100755 --- a/src/session.cpp +++ b/src/session.cpp @@ -44,6 +44,7 @@ POSSIBILITY OF SUCH DAMAGE. #include #include #include +#include #include "libtorrent/peer_id.hpp" #include "libtorrent/torrent_info.hpp" @@ -935,6 +936,24 @@ namespace libtorrent if (hash != real_hash) return; + // the peers + + entry::list_type& peer_list = rd.dict()["peers"].list(); + + std::vector

    tmp_peers; + tmp_peers.reserve(peer_list.size()); + for (entry::list_type::iterator i = peer_list.begin(); + i != peer_list.end(); + ++i) + { + address a(i->dict()["ip"].string(), i->dict()["port"].integer()); + tmp_peers.push_back(a); + } + + peers.swap(tmp_peers); + + + // read piece map const entry::list_type& slots = rd.dict()["slots"].list(); if (slots.size() > info.num_pieces()) @@ -990,21 +1009,19 @@ namespace libtorrent tmp_unfinished.push_back(p); } - // the peers + // verify file sizes - entry::list_type& peer_list = rd.dict()["peers"].list(); + std::vector file_sizes; + entry::list_type& l = rd.dict()["file sizes"].list(); + std::transform( + l.begin() + , l.end() + , std::back_inserter(file_sizes) + , boost::bind(&entry::integer, _1)); - std::vector
    tmp_peers; - tmp_peers.reserve(peer_list.size()); - for (entry::list_type::iterator i = peer_list.begin(); - i != peer_list.end(); - ++i) - { - address a(i->dict()["ip"].string(), i->dict()["port"].integer()); - tmp_peers.push_back(a); - } + if (!match_filesizes(info, save_path, file_sizes)) + return; - peers.swap(tmp_peers); piece_map.swap(tmp_pieces); unfinished_pieces.swap(tmp_unfinished); } diff --git a/src/storage.cpp b/src/storage.cpp index d2b62c501..7401b7cae 100755 --- a/src/storage.cpp +++ b/src/storage.cpp @@ -81,14 +81,6 @@ namespace { } }; - void print_bitmask(const std::vector& x) - { - for (std::size_t i = 0; i < x.size(); ++i) - { - std::cout << x[i]; - } - } - } // namespace unnamed namespace fs = boost::filesystem; @@ -104,7 +96,43 @@ namespace { } -namespace libtorrent { +namespace libtorrent +{ + + std::vector get_filesizes( + const torrent_info& t + , const boost::filesystem::path& p) + { + std::vector sizes; + for (torrent_info::file_iterator i = t.begin_files(); + i != t.end_files(); + ++i) + { + file f(p / i->path / i->filename, file::in); + f.seek(0, file::end); + sizes.push_back(f.tell()); + } + return sizes; + } + + bool match_filesizes( + const torrent_info& t + , const boost::filesystem::path& p + , const std::vector& sizes) + { + if (sizes.size() != t.num_files()) return false; + + std::vector::const_iterator s = sizes.begin(); + for (torrent_info::file_iterator i = t.begin_files(); + i != t.end_files(); + ++i, ++s) + { + file f(p / i->path / i->filename, file::in); + f.seek(0, file::end); + if (f.tell() != *s) return false; + } + return true; + } struct thread_safe_storage { @@ -394,10 +422,10 @@ namespace libtorrent { // returns the slot currently associated with the given // piece or assigns the given piece_index to a free slot int slot_for_piece(int piece_index); - +#ifndef NDEBUG void check_invariant() const; void debug_log() const; - +#endif storage m_storage; // total number of bytes left to be downloaded @@ -464,9 +492,9 @@ namespace libtorrent { // synchronization ------------------------------------------------------ boost::recursive_mutex::scoped_lock lock(m_mutex); // ---------------------------------------------------------------------- - +#ifndef NDEBUG check_invariant(); - +#endif p.clear(); std::vector::const_reverse_iterator last; for (last = m_slot_to_piece.rbegin(); @@ -484,8 +512,9 @@ namespace libtorrent { p.push_back(*i); } +#ifndef NDEBUG check_invariant(); - +#endif } void piece_manager::export_piece_map( @@ -586,8 +615,10 @@ namespace libtorrent { const std::size_t last_piece_size = m_info.piece_size( m_info.num_pieces() - 1); + + // if we have fast-resume info - // use it instead of doingthe actual checking + // use it instead of doing the actual checking if (!data.piece_map.empty() && data.piece_map.size() <= m_slot_to_piece.size()) { @@ -630,6 +661,9 @@ namespace libtorrent { return; } + + // do the real check (we didn't have valid resume data) + bool changed_file = true; // fs::ifstream in; file in; @@ -675,26 +709,6 @@ namespace libtorrent { if (changed_file) { -/* - in.close(); - in.clear(); - in.open(path, std::ios_base::binary); - - changed_file = false; - - bytes_current_read = seek_into_next; - - if (!in) - { - filesize = 0; - } - else - { - in.seekg(0, std::ios_base::end); - filesize = in.tellg(); - in.seekg(seek_into_next, std::ios_base::beg); - } -*/ try { changed_file = false; @@ -709,7 +723,6 @@ namespace libtorrent { { filesize = 0; } - } // we are at the start of a new piece @@ -721,8 +734,6 @@ namespace libtorrent { if (filesize > 0) { -// in.read(&piece_data[piece_offset], bytes_to_read); -// bytes_read = in.gcount(); bytes_read = in.read(&piece_data[piece_offset], bytes_to_read); } @@ -832,16 +843,28 @@ namespace libtorrent { bytes_to_read = m_info.piece_size(current_slot); } - std::cout << " m_free_slots: " << m_free_slots.size() << "\n"; - std::cout << " m_unallocated_slots: " << m_unallocated_slots.size() << "\n"; - std::cout << " num pieces: " << m_info.num_pieces() << "\n"; +#ifndef NDEBUG + std::stringstream s; - std::cout << " have_pieces: "; - print_bitmask(pieces); - std::cout << "\n"; - std::cout << std::count(pieces.begin(), pieces.end(), true) << "\n"; + s << " m_free_slots: " << m_free_slots.size() << "\n" + " m_unallocated_slots: " << m_unallocated_slots.size() << "\n" + " num pieces: " << m_info.num_pieces() << "\n" + " have_pieces:\n"; + for (std::vector::iterator i = pieces.begin(); + i != pieces.end(); + ++i) + { + if (((i - pieces.begin()) % 60) == 0) s << "\n"; + if (*i) s << "1"; else s << "0"; + } + s << "\n"; + s << std::count(pieces.begin(), pieces.end(), true) << "\n"; + data.torrent_ptr->debug_log(s.str()); +#endif +#ifndef NDEBUG check_invariant(); +#endif } void piece_manager::check_pieces( @@ -858,7 +881,9 @@ namespace libtorrent { boost::recursive_mutex::scoped_lock lock(m_mutex); // ---------------------------------------------------------------------- +#ifndef NDEBUG check_invariant(); +#endif assert(piece_index >= 0 && piece_index < m_piece_to_slot.size()); assert(m_piece_to_slot.size() == m_slot_to_piece.size()); @@ -870,7 +895,9 @@ namespace libtorrent { assert(slot_index >= 0); assert(slot_index < m_slot_to_piece.size()); +#ifndef NDEBUG check_invariant(); +#endif return slot_index; } @@ -918,6 +945,7 @@ namespace libtorrent { if (slot_index != piece_index && m_slot_to_piece[piece_index] >= 0) { +#ifndef NDEBUG std::stringstream s; s << "there is another piece at our slot, swapping.."; @@ -929,18 +957,13 @@ namespace libtorrent { s << "\n piece at our slot: "; s << m_slot_to_piece[piece_index]; s << "\n"; - +#endif int piece_at_our_slot = m_slot_to_piece[piece_index]; assert(m_piece_to_slot[piece_at_our_slot] == piece_index); - +#ifndef NDEBUG print_to_log(s.str()); - debug_log(); - - std::vector buf(m_info.piece_length()); - m_storage.read(&buf[0], piece_index, 0, m_info.piece_length()); - m_storage.write(&buf[0], slot_index, 0, m_info.piece_length()); - +#endif std::swap( m_slot_to_piece[piece_index] , m_slot_to_piece[slot_index]); @@ -949,16 +972,22 @@ namespace libtorrent { m_piece_to_slot[piece_index] , m_piece_to_slot[piece_at_our_slot]); + std::vector buf(m_info.piece_length()); + m_storage.read(&buf[0], piece_index, 0, m_info.piece_length()); + m_storage.write(&buf[0], slot_index, 0, m_info.piece_length()); + assert(m_slot_to_piece[piece_index] == piece_index); assert(m_piece_to_slot[piece_index] == piece_index); slot_index = piece_index; - +#ifndef NDEBUG debug_log(); +#endif } +#ifndef NDEBUG check_invariant(); - +#endif return slot_index; } @@ -977,7 +1006,9 @@ namespace libtorrent { boost::recursive_mutex::scoped_lock lock(m_mutex); // ---------------------------------------------------------------------- +#ifndef NDEBUG check_invariant(); +#endif namespace fs = boost::filesystem; @@ -1019,7 +1050,9 @@ namespace libtorrent { m_allocating = false; +#ifndef NDEBUG check_invariant(); +#endif } void piece_manager::allocate_slots(int num_slots) @@ -1031,7 +1064,8 @@ namespace libtorrent { { return m_pimpl->save_path(); } - + +#ifndef NDEBUG void piece_manager::impl::check_invariant() const { // synchronization ------------------------------------------------------ @@ -1101,6 +1135,6 @@ namespace libtorrent { print_to_log(s.str()); } - +#endif } // namespace libtorrent diff --git a/src/torrent.cpp b/src/torrent.cpp index 991ca9366..8e13eaf69 100755 --- a/src/torrent.cpp +++ b/src/torrent.cpp @@ -426,11 +426,6 @@ namespace libtorrent std::vector
    downloaders; m_picker.get_downloaders(downloaders, index); -#ifndef NDEBUG -// std::cout << "hash-test failed. Some of these peers sent invalid data:\n"; -// std::copy(downloaders.begin(), downloaders.end(), std::ostream_iterator(std::cout, "\n")); -#endif - // decrease the trust point of all peers that sent // parts of this piece. for (std::vector
    ::iterator i = downloaders.begin(); @@ -587,8 +582,6 @@ namespace libtorrent peer_lost(*i); } -// std::cout << p->get_socket()->sender().as_string() << " *** DISCONNECT\n"; - m_policy->connection_closed(*p); m_connections.erase(i); @@ -623,7 +616,6 @@ namespace libtorrent m_ses.m_selector.monitor_readability(s); m_ses.m_selector.monitor_errors(s); -// std::cout << "connecting to: " << a.as_string() << ":" << a.port() << "\n"; return *c; } @@ -792,6 +784,8 @@ namespace libtorrent st.next_announce = next_announce() - boost::posix_time::second_clock::local_time(); + st.announce_interval = boost::posix_time::seconds(m_duration); + st.num_peers = m_connections.size(); diff --git a/src/torrent_handle.cpp b/src/torrent_handle.cpp index 013eba4c0..eb44743b4 100755 --- a/src/torrent_handle.cpp +++ b/src/torrent_handle.cpp @@ -252,6 +252,15 @@ namespace libtorrent peer_list.push_back(peer); } + std::vector file_sizes + = get_filesizes(t->torrent_file(), t->save_path()); + + ret.dict()["file sizes"] = entry::list_type(); + std::copy( + file_sizes.begin() + , file_sizes.end() + , std::back_inserter(ret.dict()["file sizes"].list())); + return ret; }