diff --git a/Jamfile b/Jamfile index 808c40c6a..4ca827e52 100755 --- a/Jamfile +++ b/Jamfile @@ -26,7 +26,6 @@ REQUIREMENTS = msvc-7:/Zc:wchar_t msvc-7.1:/Zc:wchar_t - msvc:WIN32 ; @@ -106,7 +105,6 @@ lib torrent multi static # debug:TORRENT_VERBOSE_LOGGING - TORRENT_ENABLE_EXTENSIONS : debug release ; diff --git a/docs/manual.html b/docs/manual.html index a6b364b78..05bf2c03b 100755 --- a/docs/manual.html +++ b/docs/manual.html @@ -1112,6 +1112,9 @@ struct torrent_status const std::vector<bool>* pieces; size_type total_done; + + int num_seeds; + float distributed_copies; };

progress is a value in the range [0, 1], that represents the progress of the @@ -1176,6 +1179,15 @@ be slightly smaller than the other rates, but if projected over a long time

total_done is the total number of bytes of the file(s) that we have. All this does not necessarily has to be downloaded during this session (that's total_download_payload).

+

num_seeds is the number of peers that are seeding that this client is +currently connected to.

+

distributed_copies is the number of distributed copies of the torrent. +Note that one copy may be spread out among many peers. The integer part +tells how many copies there are currently of the rarest piece(s) among the +peers this client is connected to. The fractional part tells the share of +pieces that have more copies than the rarest piece(s). For example: 2.5 would +mean that the rarest pieces have only 2 copies among the peers this torrent is +connected to, and that 50% of all the pieces have more than two copies.

peer_info

diff --git a/docs/manual.rst b/docs/manual.rst index 87d16485d..89a1be46d 100755 --- a/docs/manual.rst +++ b/docs/manual.rst @@ -155,29 +155,28 @@ want to disable such checks (you want to do that in a release build) you can see table below for which defines you can use to control the build. The ``Jamfile`` will define ``NDEBUG`` when it's building a release build. -+-------------------------------+-------------------------------------------------+ -| macro | description | -+===============================+=================================================+ -| ``NDEBUG`` | If you define this macro, all asserts, | -| | invariant checks and general debug code will be | -| | removed. This option takes precedence over | -| | other debug settings. | -+-------------------------------+-------------------------------------------------+ -| ``TORRENT_VERBOSE_LOGGING`` | If you define this macro, every peer connection | -| | will log its traffic to a log file. | -| | This setting requires a debug build, i.e. | -| | if you set ``NDEBUG`` aswell, no logs will be | -| | written. | -+-------------------------------+-------------------------------------------------+ -| ``TORRENT_STORAGE_DEBUG`` | This will enable extra expensive invariant | -| | checks in the storage, including logging of | -| | piece sorting. | -+-------------------------------+-------------------------------------------------+ -| ``TORRENT_ENABLE_EXTENSIONS`` | If you want extensions to be enabled, you must | -| | build with this define. For more information on | -| | which extensions are currently implemented, see | -| | extensions_. | -+-------------------------------+-------------------------------------------------+ ++--------------------------------+-------------------------------------------------+ +| macro | description | ++================================+=================================================+ +| ``NDEBUG`` | If you define this macro, all asserts, | +| | invariant checks and general debug code will be | +| | removed. This option takes precedence over | +| | other debug settings. | ++--------------------------------+-------------------------------------------------+ +| ``TORRENT_VERBOSE_LOGGING`` | If you define this macro, every peer connection | +| | will log its traffic to a log file. | +| | This setting requires a debug build, i.e. | +| | if you set ``NDEBUG`` aswell, no logs will be | +| | written. | ++--------------------------------+-------------------------------------------------+ +| ``TORRENT_STORAGE_DEBUG`` | This will enable extra expensive invariant | +| | checks in the storage, including logging of | +| | piece sorting. | ++--------------------------------+-------------------------------------------------+ +| ``TORRENT_DISABLE_EXTENSIONS`` | This will disble the support for extensions. | +| | For more information on which extensions are | +| | currently implemented, see extensions_. | ++--------------------------------+-------------------------------------------------+ If you experience that libtorrent uses unreasonable amounts of cpu, it will definately help to @@ -1154,18 +1153,16 @@ be slightly smaller than the other rates, but if projected over a long time this does not necessarily has to be downloaded during this session (that's ``total_download_payload``). -``num_seeds`` is the number of peers that are seeding that this torrent -currently is connected to. +``num_seeds`` is the number of peers that are seeding that this client is +currently connected to. ``distributed_copies`` is the number of distributed copies of the torrent. -Note that one copy may be spread out among many peers. The whole number part +Note that one copy may be spread out among many peers. The integer part tells how many copies there are currently of the rarest piece(s) among the -peers this torrent is connected to. The fractional part tells the share of +peers this client is connected to. The fractional part tells the share of pieces that have more copies than the rarest piece(s). For example: 2.5 would mean that the rarest pieces have only 2 copies among the peers this torrent is -connected to, and that there are as many pieces that have 2 copies as there are -pieces that have more than two copies. - +connected to, and that 50% of all the pieces have more than two copies. peer_info diff --git a/examples/client_test.cpp b/examples/client_test.cpp index 4b2fd92e9..82ba43565 100755 --- a/examples/client_test.cpp +++ b/examples/client_test.cpp @@ -218,7 +218,7 @@ void print_peer_info(std::ostream& out, std::vector const { using namespace libtorrent; - out << " down up q r flags block\n"; + out << " down up q r flags block\n"; for (std::vector::const_iterator i = peers.begin(); i != peers.end(); @@ -233,14 +233,15 @@ void print_peer_info(std::ostream& out, std::vector const // << "ul:" << add_suffix(i->upload_limit) << "/s " // << "uc:" << add_suffix(i->upload_ceiling) << "/s " // << "df:" << ratio(i->total_download, i->total_upload) << " " - << i->download_queue_length << " " - << i->upload_queue_length << " " + << to_string(i->download_queue_length, 2) << " " + << to_string(i->upload_queue_length, 2) << " " << static_cast((i->flags & peer_info::interesting)?"I":"_") << static_cast((i->flags & peer_info::choked)?"C":"_") << static_cast((i->flags & peer_info::remote_interested)?"i":"_") << static_cast((i->flags & peer_info::remote_choked)?"c":"_") << static_cast((i->flags & peer_info::supports_extensions)?"e":"_") - << static_cast((i->flags & peer_info::local_connection)?"l":"r"); + << static_cast((i->flags & peer_info::local_connection)?"l":"r") << " " + << identify_client(i->id); if (i->downloading_piece_index >= 0) { @@ -279,7 +280,7 @@ int main(int argc, char* argv[]) try { std::vector handles; - session ses(fingerprint("LT", 0, 1, 0, 0)); + session ses; ses.listen_on(std::make_pair(6881, 6889)); ses.set_upload_rate_limit(512 * 1024); diff --git a/include/libtorrent/http_tracker_connection.hpp b/include/libtorrent/http_tracker_connection.hpp index 6b57c2f71..b42c61891 100755 --- a/include/libtorrent/http_tracker_connection.hpp +++ b/include/libtorrent/http_tracker_connection.hpp @@ -109,6 +109,9 @@ namespace libtorrent tracker_request m_req; std::string m_password; int m_code; + + // server string in http-reply + std::string m_server; }; } diff --git a/include/libtorrent/peer_connection.hpp b/include/libtorrent/peer_connection.hpp index 4aa0e7276..800760ab0 100755 --- a/include/libtorrent/peer_connection.hpp +++ b/include/libtorrent/peer_connection.hpp @@ -90,16 +90,17 @@ namespace libtorrent friend class invariant_access; public: - // this is the constructor where the we are teh active part. The peer_conenction - // should handshake and verify that the other end has the correct id + // this is the constructor where the we are teh active part. + // The peer_conenction should handshake and verify that the + // other end has the correct id peer_connection( detail::session_impl& ses , selector& sel , torrent* t , boost::shared_ptr s); - // with this constructor we have been contacted and we still don't know which torrent the - // connection belongs to + // with this constructor we have been contacted and we still don't + // know which torrent the connection belongs to peer_connection( detail::session_impl& ses , selector& sel @@ -501,6 +502,15 @@ namespace libtorrent // this is set to the current time each time we get a // "I don't have metadata" message. boost::posix_time::ptime m_no_metadata; + + // this is set to the time when we last sent + // a request for metadata to this peer + boost::posix_time::ptime m_metadata_request; + + // 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; }; } diff --git a/include/libtorrent/resource_request.hpp b/include/libtorrent/resource_request.hpp index f831aa4db..fe8e26672 100755 --- a/include/libtorrent/resource_request.hpp +++ b/include/libtorrent/resource_request.hpp @@ -33,6 +33,14 @@ POSSIBILITY OF SUCH DAMAGE. #ifndef TORRENT_RESOURCE_REQUEST_HPP_INCLUDED #define TORRENT_RESOURCE_REQUEST_HPP_INCLUDED +#ifdef min +#undef min +#endif + +#ifdef max +#undef max +#endif + namespace libtorrent { struct resource_request diff --git a/include/libtorrent/torrent.hpp b/include/libtorrent/torrent.hpp index bc5c7dff6..4863273df 100755 --- a/include/libtorrent/torrent.hpp +++ b/include/libtorrent/torrent.hpp @@ -330,7 +330,15 @@ namespace libtorrent bool valid_metadata() const { return m_storage.get() != 0; } std::vector const& metadata() const { return m_metadata; } - bool received_metadata(char const* buf, int size, int offset, int total_size); + bool received_metadata( + char const* buf + , int size + , int offset + , int total_size); + + // returns a range of the metadata that + // we should request. + std::pair metadata_request(); private: diff --git a/src/http_tracker_connection.cpp b/src/http_tracker_connection.cpp index 0823bb5c1..4a91b9d97 100755 --- a/src/http_tracker_connection.cpp +++ b/src/http_tracker_connection.cpp @@ -336,7 +336,8 @@ namespace libtorrent { std::string error_msg = boost::lexical_cast(m_code) + " " + m_server_message; - if (requester()) requester()->tracker_request_error(m_code, error_msg.c_str()); + if (requester()) requester()->tracker_request_error( + m_code, error_msg.c_str()); return true; } } @@ -346,12 +347,14 @@ namespace libtorrent if (received <= 0) { if (requester()) - requester()->tracker_request_error(-1, "invalid tracker response, connection closed while reading header"); + requester()->tracker_request_error(-1, "invalid tracker " + "response, connection closed while reading header"); return true; } std::vector::iterator end = m_buffer.begin()+m_recv_pos; - std::vector::iterator newline = std::find(m_buffer.begin(), end, '\n'); + std::vector::iterator newline + = std::find(m_buffer.begin(), end, '\n'); std::string line; while (newline != end && m_state == read_header) @@ -366,7 +369,8 @@ namespace libtorrent { try { - m_content_length = boost::lexical_cast(line.substr(16)); + m_content_length = boost::lexical_cast( + line.substr(16)); } catch(boost::bad_lexical_cast&) { @@ -420,6 +424,10 @@ namespace libtorrent { m_location.assign(line.begin() + 10, line.end()); } + else if (line.substr(0, 7) == "Server: ") + { + m_server.assign(line.begin() + 7, line.end()); + } else if (line.size() < 3) { m_state = read_body; diff --git a/src/identify_client.cpp b/src/identify_client.cpp index 7f24c7f7c..745d133f9 100755 --- a/src/identify_client.cpp +++ b/src/identify_client.cpp @@ -71,35 +71,19 @@ namespace boost::optional parse_az_style(const peer_id& id) { fingerprint ret("..", 0, 0, 0, 0); - peer_id::const_iterator i = id.begin(); - if (*i != '-') return boost::optional(); - ++i; + if (id[0] != '-' || !std::isprint(id[1]) || !std::isprint(id[2]) + || !std::isalnum(id[3]) || !std::isalnum(id[4]) + || !std::isalnum(id[5]) || !std::isalnum(id[6]) + || id[7] != '-') + return boost::optional(); - for (int j = 0; j < 2; ++j) - { - if (!std::isprint(*i)) return boost::optional(); - ret.id[j] = *i; - ++i; - } - - if (!std::isalnum(*i)) return boost::optional(); - ret.major_version = decode_digit(*i); - ++i; - - if (!std::isalnum(*i)) return boost::optional(); - ret.minor_version = decode_digit(*i); - ++i; - - if (!std::isalnum(*i)) return boost::optional(); - ret.revision_version = decode_digit(*i); - ++i; - - if (!std::isalnum(*i)) return boost::optional(); - ret.tag_version = decode_digit(*i); - ++i; - - if (*i != '-') return boost::optional(); + ret.id[0] = id[1]; + ret.id[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); } @@ -109,41 +93,30 @@ namespace boost::optional parse_shadow_style(const peer_id& id) { fingerprint ret("..", 0, 0, 0, 0); - peer_id::const_iterator i = id.begin(); - if (!std::isalnum(*i)) return boost::optional(); - ret.id[0] = *i; - ret.id[1] = 0; - ++i; + if (!std::isalnum(id[0])) + return boost::optional(); if (std::equal(id.begin()+4, id.begin()+8, "----")) { - if (!std::isalnum(*i)) return boost::optional(); - ret.major_version = decode_digit(*i); - ++i; - - if (!std::isalnum(*i)) return boost::optional(); - ret.minor_version = decode_digit(*i); - ++i; - - if (!std::isalnum(*i)) return boost::optional(); - ret.revision_version = decode_digit(*i); - } - else if (id[8] == 0) - { - if (*i > 127) return boost::optional(); - ret.major_version = *i; - ++i; - - if (*i > 127) return boost::optional(); - ret.minor_version = *i; - ++i; - - if (*i > 127) return boost::optional(); - ret.revision_version = *i; + if (!std::isalnum(id[1]) || !std::isalnum(id[2]) + || !std::isalnum(id[3])) + 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 - return boost::optional(); + { + 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.id[0] = id[0]; + ret.id[1] = 0; ret.tag_version = 0; return boost::optional(ret); @@ -153,39 +126,79 @@ namespace // identification boost::optional parse_mainline_style(const peer_id& id) { + if (!std::isprint(id[0]) + || !std::isalnum(id[1]) + || id[2] != '-' + || !std::isalnum(id[3]) + || id[4] != '-' + || !std::isalnum(id[5]) + || !std::equal(id.begin() + 6, id.begin() + 8, "--")) + return boost::optional(); + fingerprint ret("..", 0, 0, 0, 0); - peer_id::const_iterator i = id.begin(); - if (!std::isprint(*i)) return boost::optional(); - ret.id[0] = *i; + ret.id[0] = id[0]; ret.id[1] = 0; - ++i; - - if (!std::isalnum(*i)) return boost::optional(); - ret.major_version = decode_digit(*i); - ++i; - - if (*i != '-') return boost::optional(); - ++i; - - if (!std::isalnum(*i)) return boost::optional(); - ret.minor_version = decode_digit(*i); - ++i; - - if (*i != '-') return boost::optional(); - ++i; - - if (!std::isalnum(*i)) return boost::optional(); - ret.revision_version = decode_digit(*i); - ++i; - - if (!std::equal(i, i+1, "--")) return boost::optional(); - + ret.major_version = decode_digit(id[1]); + ret.minor_version = decode_digit(id[3]); + ret.revision_version = decode_digit(id[5]); ret.tag_version = 0; return boost::optional(ret); } -} // namespace unnamed + typedef std::pair map_entry; + + // must be ordered alphabetically + map_entry name_map[] = + { + map_entry("A", "ABC") + , map_entry("AZ", "Azureus") + , map_entry("BX", "BittorrentX") + , map_entry("LT", "libtorrent") + , map_entry("M", "Mainline") + , map_entry("MT", "Moonlight Torrent") + , map_entry("S", "Shadow") + , map_entry("SS", "SwarmScope") + , map_entry("T", "BitTornado") + , map_entry("TN", "TorrentDonNet") + , map_entry("TS", "TorrentStorm") + , map_entry("U", "UPnP") + , map_entry("XT", "XanTorrent") + }; + + bool compare_first_string(map_entry const& e, char const* str) + { + return e.first[0] < str[0] + || ((e.first[0] == str[0]) && (e.first[1] < str[1])); + } + + std::string lookup(fingerprint const& f) + { + std::stringstream identity; + + const int size = sizeof(name_map)/sizeof(name_map[0]); + map_entry* i = + std::lower_bound(name_map, name_map + size + , f.id, &compare_first_string); + + if (i < name_map + size && std::equal(f.id, f.id + 2, i->first)) + identity << i->second; + else + identity << std::string(f.id, f.id + 2); + + identity << " " << (int)f.major_version + << "." << (int)f.minor_version + << "." << (int)f.revision_version + << "." << (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 { @@ -197,180 +210,50 @@ namespace libtorrent if (p.is_all_zeros()) return "Unknown"; - // look for azureus style id + // look for azureus style id f = parse_az_style(p); - if (f) - { - std::stringstream identity; + if (f) return lookup(*f); - // azureus - if (std::equal(f->id, f->id+2, "AZ")) - identity << "Azureus "; - - // BittorrentX - else if (std::equal(f->id, f->id+2, "BX")) - identity << "BittorrentX "; - - // libtorrent - else if (std::equal(f->id, f->id+2, "LT")) - identity << "libtorrent "; - - // Moonlight Torrent - else if (std::equal(f->id, f->id+2, "MT")) - identity << "Moonlight Torrent "; - - // Torrent Storm - else if (std::equal(f->id, f->id+2, "TS")) - identity << "TorrentStorm "; - - // SwarmScope - else if (std::equal(f->id, f->id+2, "SS")) - identity << "SwarmScope "; - - // XanTorrent - else if (std::equal(f->id, f->id+2, "XT")) - identity << "XanTorrent "; - - // TorrentDotNet - else if (std::equal(f->id, f->id+2, "TN")) - identity << "TorrentDotNET "; - - // unknown client - else - identity << std::string(f->id, f->id+2) << " "; - - identity << (int)f->major_version - << "." << (int)f->minor_version - << "." << (int)f->revision_version - << "." << (int)f->tag_version; - - return identity.str(); - } - - - // look for shadow style id + // look for shadow style id f = parse_shadow_style(p); - if (f) - { - std::stringstream identity; + if (f) return lookup(*f); - // Shadow - if (std::equal(f->id, f->id+1, "S")) - identity << "Shadow "; - - // ABC - else if (std::equal(f->id, f->id+1, "A")) - identity << "ABC "; - - // UPnP - else if (std::equal(f->id, f->id+1, "U")) - identity << "UPnP "; - - // BitTornado - else if (std::equal(f->id, f->id+1, "T")) - identity << "BitTornado "; - - // unknown client - else - identity << std::string(f->id, f->id+1) << " "; - - identity << (int)f->major_version - << "." << (int)f->minor_version - << "." << (int)f->revision_version; - - return identity.str(); - } - + // look for mainline style id f = parse_mainline_style(p); - if (f) - { - std::stringstream identity; - - // Mainline - if (std::equal(f->id, f->id+1, "M")) - identity << "Mainline "; - - // unknown client - else - identity << std::string(f->id, f->id+1) << " "; - - identity << (int)f->major_version - << "." << (int)f->minor_version - << "." << (int)f->revision_version; - - return identity.str(); - } + if (f) return lookup(*f); // ---------------------- // non standard encodings // ---------------------- - if (std::equal(PID, PID + 12, "-G3g3rmz ")) - { - return "G3 Torrent"; - } - - if (std::equal(PID, PID + 4, "exbc")) - { - std::stringstream s; - s << "BitComet " << (int)PID[4] << "." << (int)PID[5]/10 << (int)PID[5]%10; - return s.str(); - } - - if (std::equal(PID + 5, PID + 5 + 8, "Azureus")) - { - return "Azureus 2.0.3.2"; - } - - if (std::equal(PID, PID + 11, "DansClient")) - { - return "XanTorrent"; - } - - if (std::equal(PID, PID + 7, "Plus---")) - { - return "Bittorrent Plus"; - } - - if (std::equal(PID, PID + 16, "Deadman Walking-")) - { - return "Deadman"; - } - - if (std::equal(PID, PID + 7, "btuga")) - { - return "BTugaXP"; - } - - if (std::equal(PID, PID + 7, "btfans")) - { - return "SimpleBT"; - } - - if (std::equal(PID, PID + 7, "turbobt") - && std::isalnum(PID[8]) - && std::isalnum(PID[10]) - && std::isalnum(PID[12])) - { - std::stringstream s; - s << "TurboBT " << PID[8] << "." << PID[10] << "." << PID[12]; - return s.str(); - } + if (find_string(PID, "Deadman Walking-")) return "Deadman"; + if (find_string(PID + 5, "Azureus")) return "Azureus 2.0.3.2"; + if (find_string(PID, "DansClient")) return "XanTorrent"; + if (find_string(PID + 4, "btfans")) return "SimpleBT"; + if (find_string(PID, "PRC.P---")) return "Bittorrent Plus! II"; + if (find_string(PID, "P87.P---")) return "Bittorrent Plus!"; + if (find_string(PID, "S587Plus")) return "Bittorrent Plus!"; + if (find_string(PID, "martini")) return "Martini Man"; + if (find_string(PID, "Plus---")) return "Bittorrent Plus"; + if (find_string(PID, "turbobt")) return "TurboBT"; + if (find_string(PID, "BTDWV-")) return "Deadman Walking"; + if (find_string(PID + 2, "BS")) return "BitSpirit"; + if (find_string(PID, "btuga")) return "BTugaXP"; + if (find_string(PID, "oernu")) return "BTugaXP"; + if (find_string(PID, "Mbrst")) return "Burst!"; + if (find_string(PID, "Plus")) return "Plus!"; + if (find_string(PID, "exbc")) return "BitComet"; + if (find_string(PID, "-G3")) return "G3 Torrent"; + if (find_string(PID, "XBT")) return "XBT"; 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"; - } 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) diff --git a/src/peer_connection.cpp b/src/peer_connection.cpp index a4a260c37..470c8ac60 100755 --- a/src/peer_connection.cpp +++ b/src/peer_connection.cpp @@ -117,6 +117,10 @@ namespace libtorrent , m_no_metadata( boost::gregorian::date(1970, boost::date_time::Jan, 1) , boost::posix_time::seconds(0)) + , m_metadata_request( + boost::gregorian::date(1970, boost::date_time::Jan, 1) + , boost::posix_time::seconds(0)) + , m_waiting_metadata_request(false) { INVARIANT_CHECK; @@ -190,6 +194,10 @@ namespace libtorrent , m_no_metadata( boost::gregorian::date(1970, boost::date_time::Jan, 1) , boost::posix_time::seconds(0)) + , m_metadata_request( + boost::gregorian::date(1970, boost::date_time::Jan, 1) + , boost::posix_time::seconds(0)) + , m_waiting_metadata_request(false) { INVARIANT_CHECK; @@ -402,7 +410,7 @@ namespace libtorrent , m_send_buffer.begin() + pos + 8 , 0); // indicate that we support the extension protocol -#ifdef TORRENT_ENABLE_EXTENSIONS +#ifndef TORRENT_DISABLE_EXTENSIONS m_send_buffer[pos+7] = 0x01; #endif pos += 8; @@ -1059,6 +1067,9 @@ namespace libtorrent entry e = bdecode(m_recv_buffer.begin()+1, m_recv_buffer.end()); #ifndef NDEBUG entry::dictionary_type& extensions = e.dict(); + std::stringstream ext; + e.print(ext); + (*m_logger) << ext.str(); #endif for (int i = 0; i < num_supported_extensions; ++i) @@ -1078,13 +1089,6 @@ namespace libtorrent (*m_logger) << i->first << "\n"; } #endif - // TODO: move the requesting into second-tick - // of the torrent. - if (!m_torrent->valid_metadata() - && supports_extension(extended_metadata_message)) - { - send_metadata_request(0, 256); - } } catch(invalid_encoding&) { @@ -1216,11 +1220,13 @@ namespace libtorrent if (offset + data_size > total_size) throw protocol_error("invalid metadata message"); + m_waiting_metadata_request = false; m_torrent->received_metadata(&m_recv_buffer[5+9], data_size, offset, total_size); } break; case 2: // have no data m_no_metadata = boost::posix_time::second_clock::local_time(); + m_waiting_metadata_request = false; break; } @@ -1680,6 +1686,22 @@ namespace libtorrent { INVARIANT_CHECK; + // 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. + if (!m_torrent->valid_metadata() + && supports_extension(extended_metadata_message) + && !m_waiting_metadata_request) + { + assert(m_torrent); + std::pair req = m_torrent->metadata_request(); + send_metadata_request(req.first, req.second); + m_waiting_metadata_request = true; + m_metadata_request = boost::posix_time::second_clock::local_time(); + } + + m_statistics.second_tick(); m_ul_bandwidth_quota.used = std::min( (int)ceil(statistics().upload_rate()) @@ -1694,7 +1716,7 @@ namespace libtorrent // maintain the share ratio given by m_ratio // with all peers. - if (m_torrent->is_seed() || is_choked() || m_torrent->ratio()==0.0f) + if (m_torrent->is_seed() || is_choked() || m_torrent->ratio() == 0.0f) { // if we have downloaded more than one piece more // than we have uploaded OR if we are a seed @@ -1901,7 +1923,7 @@ namespace libtorrent // these 8 bytes would be used to describe the // extensions available on the other side // currently disabled -#ifdef TORRENT_ENABLE_EXTENSIONS +#ifndef TORRENT_DISABLE_EXTENSIONS if (m_recv_buffer[7] & 0x01) m_supports_extensions = true; #endif diff --git a/src/session.cpp b/src/session.cpp index f70e3cff9..1e87495e1 100755 --- a/src/session.cpp +++ b/src/session.cpp @@ -237,6 +237,7 @@ namespace libtorrent { namespace detail try { // create listener socket + m_selector.remove(m_listen_socket); m_listen_socket = boost::shared_ptr(new socket(socket::tcp, false)); for(;;) @@ -872,7 +873,7 @@ namespace libtorrent return torrent_handle(&m_impl, &m_checker_impl, ti.info_hash()); } -#ifdef TORRENT_ENABLE_EXTENSIONS +#ifndef TORRENT_DISABLE_EXTENSIONS torrent_handle session::add_torrent( char const* tracker_url , sha1_hash const& info_hash diff --git a/src/torrent.cpp b/src/torrent.cpp index b65c072ae..181b1be80 100755 --- a/src/torrent.cpp +++ b/src/torrent.cpp @@ -980,7 +980,11 @@ namespace libtorrent , m_have_metadata.begin() + start + block_size , true); - bool have_all = std::count(m_have_metadata.begin(), m_have_metadata.end(), true) == 255; + bool have_all = std::count( + m_have_metadata.begin() + , m_have_metadata.end() + , true) == 255; + if (!have_all) return false; hasher h; @@ -993,8 +997,6 @@ namespace libtorrent m_have_metadata.begin() , m_have_metadata.end() + start + block_size , false); - // TODO: rerequest - assert(false); return false; } @@ -1020,18 +1022,26 @@ namespace libtorrent m_picker->integrity_check(this); #endif - // clear the storage for the bitfield - { - std::vector t1; - m_have_metadata.swap(t1); - std::vector t2; - m_requested_metadata.swap(t2); - } + std::vector().swap(m_have_metadata); + std::vector().swap(m_requested_metadata); return true; } + std::pair torrent::metadata_request() + { + // TODO: count the peers that supports the + // metadata extension + // check to see if we know how big the metadata + // is (if m_metadata.size() > 0) + std::pair ret(0, 256); + + for (int i = ret.first; i < ret.first + ret.second; ++i) + m_requested_metadata[i]++; + return ret; + } + void torrent::tracker_request_timed_out() { #ifndef NDEBUG