diff --git a/docs/features.html b/docs/features.html index 1e1dd486c..646959a62 100644 --- a/docs/features.html +++ b/docs/features.html @@ -20,16 +20,16 @@
-

Table of contents

+

Table of contents

-
-

introduction

+
+

introduction

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 @@ -41,8 +41,8 @@ example client.

  • to be very easy to use
  • -
    -

    features

    +
    +

    features

    libtorrent is still being developed, however it is stable. It is an ongoing project (including this documentation). The current state includes the following features:

    @@ -67,7 +67,7 @@ as well as all local peers in a separate fast-resume file. This means it can download parts of the same piece from different peers. It will also prefer to download whole pieces from single peers if the download speed is high enough from that particular peer. -
  • supports the udp-tracker protocol by Olaf van der Spek.
  • +
  • supports the udp-tracker protocol by Olaf van der Spek.
  • queues torrents for file check, instead of checking all of them in parallel.
  • supports http proxies and basic proxy authentication
  • gzipped tracker-responses
  • @@ -76,7 +76,7 @@ unchoked peers
  • implements fair trade. User settable trade-ratio, must at least be 1:1, but one can choose to trade 1 for 2 or any other ratio that isn't unfair to the other party.
  • -
  • supports an extension protocol. See extensions.
  • +
  • supports an extension protocol. See extensions.
  • supports the no_peer_id=1 extension that will ease the load off trackers.
  • possibility to limit the number of connections.
  • delays have messages if there's no other outgoing traffic to the peer, and @@ -91,8 +91,8 @@ want to download.
  • being connected
    -
    -

    portability

    +
    +

    portability

    libtorrent is portable at least among Windows, MacOS X and other UNIX-systems. It uses Boost.Thread, Boost.Filesystem, Boost.Date_time and various other boost libraries as well as zlib (shipped) and asio (shipped). At least version @@ -114,8 +114,8 @@ epoll on linux and kqueue on MacOS X and BSD.

  • msvc6
  • -
    -

    license

    +
    +

    license

    libtorrent is released under the BSD-license.

    This means that you can use the library in your project without having to release its source code. The only requirement is that you give credit diff --git a/docs/manual.html b/docs/manual.html index d660f474c..f23744f2b 100644 --- a/docs/manual.html +++ b/docs/manual.html @@ -22,158 +22,158 @@

    -

    Table of contents

    +

    Table of contents

    -
    -

    overview

    +
    +

    overview

    The interface of libtorrent consists of a few classes. The main class is the session, it contains the main loop that serves all torrents.

    The basic usage is as follows:

    @@ -199,8 +199,8 @@ the session, it conta

    Each class and function is described in this manual.

    -
    -

    primitive network types

    +
    +

    primitive network types

    There are a few typedefs in the libtorrent namespace which pulls in network types from the asio namespace. These are:

    @@ -219,8 +219,8 @@ udp::endpoint
     

    Which are the endpoint types used in libtorrent. An endpoint is an address with an associated port.

    -
    -

    session

    +
    +

    session

    The session class has the following synopsis:

     class session: public boost::noncopyable
    @@ -308,8 +308,8 @@ class session: public boost::noncopyable
     

    Once it's created, the session object will spawn the main thread that will do all the work. The main thread will be idle as long it doesn't have any torrents to participate in.

    -
    -

    session()

    +
    +

    session()

     session(fingerprint const& print
    @@ -328,16 +328,16 @@ The other constructor, that takes a port range and an interface as well as the f
     will automatically try to listen on a port on the given interface. For more information about
     the parameters, see listen_on() function.

    -
    -

    ~session()

    +
    +

    ~session()

    The destructor of session will notify all trackers that our torrents have been shut down. If some trackers are down, they will time out. All this before the destructor of session returns. So, it's advised that any kind of interface (such as windows) are closed before destructing the session object. Because it can take a few second for it to finish. The timeout can be set with set_settings().

    -
    -

    abort()

    +
    +

    abort()

     session_proxy abort();
     
    @@ -359,8 +359,8 @@ public: };
    -
    -

    add_torrent()

    +
    +

    add_torrent()

     torrent_handle add_torrent(
    @@ -410,8 +410,8 @@ optional name argumen
     torrent. In case it's not 0, the name is used for the torrent as long as it doesn't
     have metadata. See torrent_handle::name.

    -
    -

    remove_torrent() find_torrent() get_torrents()

    +
    +

    remove_torrent() find_torrent() get_torrents()

     void remove_torrent(torrent_handle const& h);
    @@ -428,8 +428,8 @@ In case the torrent cannot be found, an invalid torrent_handle is returned.

    get_torrents() returns a vector of torrent_handles to all the torrents currently in the session.

    -
    -

    set_upload_rate_limit() set_download_rate_limit() upload_rate_limit() download_rate_limit()

    +
    +

    set_upload_rate_limit() set_download_rate_limit() upload_rate_limit() download_rate_limit()

     void set_upload_rate_limit(int bytes_per_second);
    @@ -446,8 +446,8 @@ of upload rate.
     download_rate_limit() and upload_rate_limit() returns the previously
     set limits.

    -
    -

    set_max_uploads() set_max_connections()

    +
    +

    set_max_uploads() set_max_connections()

     void set_max_uploads(int limit);
    @@ -460,8 +460,8 @@ minimum of at least two connections per torrent, so if you set a too low
     connections limit, and open too many torrents, the limit will not be met. The
     number of uploads is at least one per torrent.

    -
    -

    num_uploads() num_connections()

    +
    +

    num_uploads() num_connections()

     int num_uploads() const;
    @@ -471,8 +471,8 @@ int num_connections() const;
     

    Returns the number of currently unchoked peers and the number of connections (including half-open ones) respectively.

    -
    -

    set_max_half_open_connections()

    +
    +

    set_max_half_open_connections()

     void set_max_half_open_connections(int limit);
    @@ -488,8 +488,8 @@ and passing -1 as the limit, means to have no limit. When limiting the number
     of simultaneous connection attempts, peers will be put in a queue waiting for
     their turn to get connected.

    -
    -

    set_ip_filter()

    +
    +

    set_ip_filter()

     void set_ip_filter(ip_filter const& filter);
    @@ -502,8 +502,8 @@ accepted and not, see ip_filter.

    Each time a peer is blocked because of the IP filter, a peer_blocked_alert is generated.

    -
    -

    status()

    +
    +

    status()

     session_status status() const;
    @@ -533,6 +533,7 @@ struct session_status
             int dht_nodes;
             int dht_cache_nodes;
             int dht_torrents;
    +        int dht_global_nodes;
     };
     

    has_incoming_connections is false as long as no incoming connections have been @@ -553,9 +554,11 @@ table. This number only includes active nodes, not cache nodes. The are used to replace the regular nodes in the routing table in case any of them becomes unresponsive.

    dht_torrents are the number of torrents tracked by the DHT at the moment.

    +

    dht_global_nodes is an estimation of the total number of nodes in the DHT +network.

    -
    -

    is_listening() listen_port() listen_on()

    +
    +

    is_listening() listen_port() listen_on()

     bool is_listening() const;
    @@ -598,8 +601,8 @@ with a DHT ping packet, and connect to those that responds first. On windows one
     can only connect to a few peers at a time because of a built in limitation (in XP
     Service pack 2).

    -
    -

    pop_alert() set_severity_level()

    +
    +

    pop_alert() set_severity_level()

     std::auto_ptr<alert> pop_alert();
    @@ -610,8 +613,8 @@ void set_severity_level(alert::severity_t s);
     set_severity_level() you can filter how serious the event has to be for you to
     receive it through pop_alert(). For information, see alerts.

    -
    -

    add_extension()

    +
    +

    add_extension()

     void add_extension(boost::function<
    @@ -640,8 +643,8 @@ ses.add_extension(&libtorrent::create_metadata_plugin);
     ses.add_extension(&libtorrent::create_ut_pex_plugin);
     
    -
    -

    set_peer_proxy() set_web_seed_proxy() set_tracker_proxy() set_dht_proxy()

    +
    +

    set_peer_proxy() set_web_seed_proxy() set_tracker_proxy() set_dht_proxy()

     void set_peer_proxy(proxy_settings const& s);
    @@ -662,8 +665,8 @@ it only has any effect if the proxy supports UDP.

    For more information on what settings are available for proxies, see proxy_settings.

    -
    -

    peer_proxy() web_seed_proxy() tracker_proxy() dht_proxy()

    +
    +

    peer_proxy() web_seed_proxy() tracker_proxy() dht_proxy()

     proxy_settings const& peer_proxy() const;
    @@ -675,8 +678,8 @@ proxy_settings const& dht_proxy() const;
     

    These functions returns references to their respective current settings.

    The dht_proxy is not available when DHT is disabled.

    -
    -

    start_dht() stop_dht() set_dht_settings() dht_state()

    +
    +

    start_dht() stop_dht() set_dht_settings() dht_state()

     void start_dht(entry const& startup_state);
    @@ -736,8 +739,8 @@ that are ready to replace a failing node, it will be replaced immediately,
     this limit is only used to clear out nodes that don't have any node that can
     replace them.

    -
    -

    add_dht_node() add_dht_router()

    +
    +

    add_dht_node() add_dht_router()

     void add_dht_node(std::pair<std::string, int> const& node);
    @@ -756,8 +759,8 @@ for bootstrapping, to keep the load off them.

    router.bittorrent.com.

    -
    -

    entry

    +
    +

    entry

    The entry class represents one node in a bencoded hierarchy. It works as a variant type, it can be either a list, a dictionary (std::map), an integer or a string. This is its synopsis:

    @@ -820,8 +823,8 @@ public: };

    TODO: finish documentation of entry.

    -
    -

    integer() string() list() dict() type()

    +
    +

    integer() string() list() dict() type()

     integer_type& integer();
    @@ -873,8 +876,8 @@ if (entry* i = torrent_file.find_key("announce"))
     

    To make it easier to extract information from a torrent file, the class torrent_info exists.

    -
    -

    operator[]

    +
    +

    operator[]

     entry& operator[](char const* key);
    @@ -892,8 +895,8 @@ given key, a reference to a newly inserted element at that key.

    existing element at the given key. If the key is not found, it will throw libtorrent::type_error.

    -
    -

    find_key()

    +
    +

    find_key()

     entry* find_key(char const* key);
    @@ -907,8 +910,8 @@ element cannot be found, they will return 0. If an element with the given
     key is found, the return a pointer to it.

    -
    -

    torrent_info

    +
    +

    torrent_info

    The torrent_info has the following synopsis:

     class torrent_info
    @@ -972,8 +975,8 @@ public:
             sha1_hash const& hash_for_piece(unsigned int index) const;
     };
     
    -
    -

    torrent_info()

    +
    +

    torrent_info()

     torrent_info();
    @@ -996,8 +999,8 @@ object from the information found in the given torrent_file. The entry, use bdecode(),
     see bdecode() bencode().

    -
    -

    set_comment() set_piece_size() set_creator() set_hash() add_tracker() add_file()

    +
    +

    set_comment() set_piece_size() set_creator() set_hash() add_tracker() add_file()

     void set_comment(char const* str);
    @@ -1029,8 +1032,8 @@ of the torrent. The sizecreate_torrent().

    For a complete example of how to create a torrent from a file structure, see make_torrent.

    -
    -

    create_torrent()

    +
    +

    create_torrent()

     entry create_torrent();
    @@ -1044,8 +1047,8 @@ object.

    Note that a torrent file must include at least one file, and it must have at least one tracker url or at least one DHT node.

    -
    -

    begin_files() end_files() rbegin_files() rend_files()

    +
    +

    begin_files() end_files() rbegin_files() rend_files()

     file_iterator begin_files() const;
    @@ -1080,8 +1083,8 @@ struct file_entry
     };
     
    -
    -

    num_files() file_at()

    +
    +

    num_files() file_at()

     int num_files() const;
    @@ -1091,8 +1094,8 @@ file_entry const& file_at(int index) const;
     

    If you need index-access to files you can use the num_files() and file_at() to access files using indices.

    -
    -

    map_block()

    +
    +

    map_block()

     std::vector<file_slice> map_block(int piece, size_type offset
    @@ -1117,8 +1120,8 @@ as argument. The offsetsize is the number of bytes this range is. The size + offset
     will never be greater than the file size.

    -
    -

    map_file()

    +
    +

    map_file()

     peer_request map_file(int file_index, size_type file_offset
    @@ -1145,8 +1148,8 @@ struct peer_request
     + size is not allowed to be greater than the file size. file_index
     must refer to a valid file, i.e. it cannot be >= num_files().

    -
    -

    url_seeds()

    +
    +

    url_seeds()

     std::vector<std::string> const& url_seeds() const;
    @@ -1159,8 +1162,8 @@ adds one url to the list of url-seeds. Currently, the only transport protocol
     supported for the url is http.

    See HTTP seeding for more information.

    -
    -

    print()

    +
    +

    print()

     void print(std::ostream& os) const;
    @@ -1170,8 +1173,8 @@ void print(std::ostream& os) const;
     the torrent file to the given outstream. This function has been deprecated and will
     be removed from future releases.

    -
    -

    trackers()

    +
    +

    trackers()

     std::vector<announce_entry> const& trackers() const;
    @@ -1190,8 +1193,8 @@ struct announce_entry
     };
     
    -
    -

    total_size() piece_length() piece_size() num_pieces()

    +
    +

    total_size() piece_length() piece_size() num_pieces()

     size_type total_size() const;
    @@ -1208,8 +1211,8 @@ the piece index as argument and gives you the exact size of that piece. It will
     be the same as piece_length() except in the case of the last piece, which may
     be smaller.

    -
    -

    hash_for_piece() info_hash()

    +
    +

    hash_for_piece() info_hash()

     size_type piece_size(unsigned int index) const;
    @@ -1222,8 +1225,8 @@ torrent file. For more information on the info_hash() will only return a valid hash if the torrent_info was read from a
     .torrent file or if an entry was created from it (through create_torrent).

    -
    -

    name() comment() creation_date() creator()

    +
    +

    name() comment() creation_date() creator()

     std::string const& name() const;
    @@ -1240,8 +1243,8 @@ in the torrent file, this will return a date of January 1:st 1970.

    creator() returns the creator string in the torrent. If there is no creator string it will return an empty string.

    -
    -

    priv() set_priv()

    +
    +

    priv() set_priv()

     bool priv() const;
    @@ -1252,8 +1255,8 @@ void set_priv(bool v);
     distributed on the trackerless network (the kademlia DHT).

    set_priv() sets or clears the private flag on this torrent.

    -
    -

    nodes()

    +
    +

    nodes()

     std::vector<std::pair<std::string, int> > const& nodes() const;
    @@ -1262,8 +1265,8 @@ std::vector<std::pair<std::string, int> > const& nodes() const;
     

    If this torrent contains any DHT nodes, they are put in this vector in their original form (host name and port number).

    -
    -

    add_node()

    +
    +

    add_node()

     void add_node(std::pair<std::string, int> const& node);
    @@ -1273,8 +1276,8 @@ void add_node(std::pair<std::string, int> const& node);
     be used, by the client, to bootstrap into the DHT network.

    -
    -

    torrent_handle

    +
    +

    torrent_handle

    You will usually have to store your torrent handles somewhere, since it's the object through which you retrieve information about the torrent and aborts the torrent. Its declaration looks like this:

    @@ -1365,8 +1368,8 @@ two exceptions, info_hash()
    -
    -

    piece_priority() prioritize_pieces() piece_priorities() prioritize_files()

    +
    +

    piece_priority() prioritize_pieces() piece_priorities() prioritize_files()

     void piece_priority(int index, int priority) const;
    @@ -1410,8 +1413,8 @@ torrent. Each element is the current priority of that piece.

    files in the torrent. Each entry is the priority of that file. The function sets the priorities of all the pieces in the torrent based on the vector.

    -
    -

    file_progress()

    +
    +

    file_progress()

     void file_progress(std::vector<float>& fp);
    @@ -1422,8 +1425,8 @@ range [0, 1]) describing the download progress of each file in this torrent.
     The progress values are ordered the same as the files in the torrent_info.
     This operation is not very cheap.

    -
    -

    save_path()

    +
    +

    save_path()

     boost::filesystem::path save_path() const;
    @@ -1432,8 +1435,8 @@ boost::filesystem::path save_path() const;
     

    save_path() returns the path that was given to add_torrent() when this torrent was started.

    -
    -

    move_storage()

    +
    +

    move_storage()

     bool move_storage(boost::filesystem::path const& save_path) const;
    @@ -1445,8 +1448,8 @@ the same drive as the original save path. If the move operation fails, this func
     returns false, otherwise true. Post condition for successful operation is:
     save_path() == save_path.

    -
    -

    force_reannounce()

    +
    +

    force_reannounce()

     void force_reannounce() const;
    @@ -1456,8 +1459,8 @@ void force_reannounce() const;
     peers. If the torrent is invalid, queued or in checking mode, this functions will throw
     invalid_handle.

    -
    -

    connect_peer()

    +
    +

    connect_peer()

     void connect_peer(asio::ip::tcp::endpoint const& adr, int source = 0) const;
    @@ -1471,8 +1474,8 @@ will throw invalid_handle. The s
     the source mask of this peer. Typically this is one of the source flags in peer_info.
     i.e. tracker, pex, dht etc.

    -
    -

    name()

    +
    +

    name()

     std::string name() const;
    @@ -1482,8 +1485,8 @@ std::string name() const;
     case the torrent was started without metadata, and hasn't completely received it yet,
     it returns the name given to it when added to the session. See session::add_torrent.

    -
    -

    set_ratio()

    +
    +

    set_ratio()

     void set_ratio(float ratio) const;
    @@ -1497,8 +1500,8 @@ attempt to upload in return for each download. e.g. if set to 2, the client will
     2 bytes for every byte received. The default setting for this is 0, which will make it work
     as a standard client.

    -
    -

    set_upload_limit() set_download_limit() upload_limit() download_limit()

    +
    +

    set_upload_limit() set_download_limit() upload_limit() download_limit()

     void set_upload_limit(int limit) const;
    @@ -1516,8 +1519,8 @@ limit.

    upload_limit and download_limit will return the current limit setting, for upload and download, respectively.

    -
    -

    set_sequenced_download_threshold()

    +
    +

    set_sequenced_download_threshold()

     void set_sequenced_download_threshold(int threshold);
    @@ -1534,8 +1537,8 @@ in practice.

    negatively in the swarm. It should basically only be used in situations where the random seeks on the disk is the download bottleneck.

    -
    -

    set_peer_upload_limit() set_peer_download_limit()

    +
    +

    set_peer_upload_limit() set_peer_download_limit()

     void set_peer_upload_limit(asio::ip::tcp::endpoint ip, int limit) const;
    @@ -1545,8 +1548,8 @@ void set_peer_download_limit(asio::ip::tcp::endpoint ip, int limit) const;
     

    Works like set_upload_limit and set_download_limit respectively, but controls individual peer instead of the whole torrent.

    -
    -

    pause() resume() is_paused()

    +
    +

    pause() resume() is_paused()

     void pause() const;
    @@ -1560,8 +1563,8 @@ all potential (not connected) peers. You can use file_error_alert.

    -
    -

    resolve_countries()

    +
    +

    resolve_countries()

     void resolve_countries(bool r);
    @@ -1573,8 +1576,8 @@ torrent. It defaults to false. If it is set to true, the country member set. See peer_info for more information
     on how to interpret this field.

    -
    -

    is_seed()

    +
    +

    is_seed()

     bool is_seed() const;
    @@ -1582,8 +1585,8 @@ bool is_seed() const;
     

    Returns true if the torrent is in seed mode (i.e. if it has finished downloading).

    -
    -

    has_metadata()

    +
    +

    has_metadata()

     bool has_metadata() const;
    @@ -1594,8 +1597,8 @@ metadata has been downloaded). The only scenario where this can return false is
     was started torrent-less (i.e. with just an info-hash and tracker ip). Note that if the torrent
     doesn't have metadata, the member get_torrent_info() will throw.

    -
    -

    set_tracker_login()

    +
    +

    set_tracker_login()

     void set_tracker_login(std::string const& username
    @@ -1605,8 +1608,8 @@ void set_tracker_login(std::string const& username
     

    set_tracker_login() sets a username and password that will be sent along in the HTTP-request of the tracker announce. Set this if the tracker requires authorization.

    -
    -

    trackers() replace_trackers()

    +
    +

    trackers() replace_trackers()

     std::vector<announce_entry> const& trackers() const;
    @@ -1622,8 +1625,8 @@ a list of the same form as the one returned from force_reannounce().

    -
    -

    add_url_seed()

    +
    +

    add_url_seed()

     void add_url_seed(std::string const& url);
    @@ -1635,8 +1638,8 @@ will connect to the server and try to download pieces from it, unless it's
     paused, queued, checking or seeding.

    See HTTP seeding for more information.

    -
    -

    use_interface()

    +
    +

    use_interface()

     void use_interface(char const* net_interface) const;
    @@ -1647,8 +1650,8 @@ connections. By default, it uses the same interface as the 
     
    -
    -

    info_hash()

    +
    +

    info_hash()

     sha1_hash info_hash() const;
    @@ -1656,8 +1659,8 @@ sha1_hash info_hash() const;
     

    info_hash() returns the info-hash for the torrent.

    -
    -

    set_max_uploads() set_max_connections()

    +
    +

    set_max_uploads() set_max_connections()

     void set_max_uploads(int max_uploads) const;
    @@ -1671,8 +1674,8 @@ connections are used up, incoming connections may be refused or poor connections
     This must be at least 2. The default is unlimited number of connections. If -1 is given to the
     function, it means unlimited.

    -
    -

    write_resume_data()

    +
    +

    write_resume_data()

     entry write_resume_data() const;
    @@ -1697,8 +1700,8 @@ fast resume data, and then close it down.

    closing down. In full allocation mode the reume data is never invalidated by subsequent writes to the files, since pieces won't move around.

    -
    -

    status()

    +
    +

    status()

     torrent_status status() const;
    @@ -1708,8 +1711,8 @@ torrent_status status() const;
     torrent. If the torrent_handle is invalid, it will throw invalid_handle exception.
     See torrent_status.

    -
    -

    get_download_queue()

    +
    +

    get_download_queue()

     void get_download_queue(std::vector<partial_piece_info>& queue) const;
    @@ -1753,8 +1756,8 @@ the same category as themselves. The reason for this is to keep the number of pa
     downloaded pieces down. Pieces set to none can be converted into any of fast,
     medium or slow as soon as a peer want to download from it.

    -
    -

    get_peer_info()

    +
    +

    get_peer_info()

     void get_peer_info(std::vector<peer_info>&) const;
    @@ -1765,8 +1768,8 @@ with one entry for each peer connected to this torrent, given the handle is vali
     torrent_handle is invalid, it will throw invalid_handle exception. Each entry in
     the vector contains information about that particular peer. See peer_info.

    -
    -

    get_torrent_info()

    +
    +

    get_torrent_info()

     torrent_info const& get_torrent_info() const;
    @@ -1779,8 +1782,8 @@ exception will be thrown. The torrent may be in a state without metadata only if
     it was started without a .torrent file, i.e. by using the libtorrent extension of
     just supplying a tracker and info-hash.

    -
    -

    is_valid()

    +
    +

    is_valid()

     bool is_valid() const;
    @@ -1795,8 +1798,8 @@ that refers to that torrent will become invalid.

    TODO: document storage

    -
    -

    torrent_status

    +
    +

    torrent_status

    It contains the following fields:

     struct torrent_status
    @@ -1969,8 +1972,8 @@ bytes that each bit in the partia
     (see get_download_queue()). This is typically 16 kB, but it may be
     larger if the pieces are larger.

    -
    -

    peer_info

    +
    +

    peer_info

    It contains the following fields:

     struct peer_info
    @@ -2161,8 +2164,8 @@ string.

    connection_type can currently be one of standard_bittorrent or web_seed. These are currently the only implemented protocols.

    -
    -

    session_settings

    +
    +

    session_settings

    You have some control over tracker requests through the session_settings object. You create it and fill it with your settings and then use session::set_settings() to apply them. You have control over proxy and authorization settings and also the user-agent @@ -2188,6 +2191,7 @@ struct session_settings bool allow_multiple_connections_per_ip; int max_failcount; int min_reconnect_time; + int peer_connect_timeout; bool use_dht_as_fallback; }; @@ -2262,18 +2266,23 @@ a peer is retrieved from a peer source (other than DHT) the failcount is decremented by one, allowing another try.

    min_reconnect_time is the time to wait between connection attempts. If the peer fails, the time is multiplied by fail counter.

    +

    peer_connect_timeout the number of seconds to wait after a connection +attempt is initiated to a peer until it is considered as having timed out. +The default is 10 seconds. This setting is especially important in case +the number of half-open connections are limited, since stale half-open +connection may delay the connection of other peers considerably.

    use_dht_as_fallback determines how the DHT is used. If this is true (which it is by default), the DHT will only be used for torrents where all trackers in its tracker list has failed. Either by an explicit error message or a time out.

    -
    -

    proxy_settings

    +
    +

    proxy_settings

    The proxy_settings structs contains the information needed to direct certain traffic to a proxy.

    -struct TORRENT_EXPORT proxy_settings
    +struct proxy_settings
     {
             proxy_settings();
     
    @@ -2320,8 +2329,8 @@ user authorization. The username and password will be sent to the proxy.
     
     
    -
    -

    ip_filter

    +
    +

    ip_filter

    The ip_filter class is a set of rules that uniquely categorizes all ip addresses as allowed or disallowed. The default constructor creates a single rule that allows all addresses (0.0.0.0 - 255.255.255.255 for @@ -2353,8 +2362,8 @@ public: }; -

    -

    ip_filter()

    +
    +

    ip_filter()

     ip_filter()
    @@ -2364,8 +2373,8 @@ ip_filter()
     

    postcondition: access(x) == 0 for every x

    -
    -

    add_rule()

    +
    +

    add_rule()

     void add_rule(address first, address last, int flags);
    @@ -2382,8 +2391,8 @@ means disallowed.

    This means that in a case of overlapping ranges, the last one applied takes precedence.

    -
    -

    access()

    +
    +

    access()

     int access(address const& addr) const;
    @@ -2394,8 +2403,8 @@ can currently be 0 or ip_filter::
     is O(log n), where n is the minimum number of non-overlapping ranges to describe
     the current filter.

    -
    -

    export_filter()

    +
    +

    export_filter()

     boost::tuple<std::vector<ip_range<address_v4> >
    @@ -2410,8 +2419,8 @@ entry in the returned vector is a range with the access control specified in its
     and one for IPv6 addresses.

    -
    -

    big_number

    +
    +

    big_number

    Both the peer_id and sha1_hash types are typedefs of the class big_number. It represents 20 bytes of data. Its synopsis follows:

    @@ -2431,8 +2440,8 @@ public:
     

    The iterators gives you access to individual bytes.

    -
    -

    hasher

    +
    +

    hasher

    This class creates sha1-hashes. Its declaration looks like this:

     class hasher
    @@ -2458,8 +2467,8 @@ call reset() to reini
     

    The sha1-algorithm used was implemented by Steve Reid and released as public domain. For more info, see src/sha1.cpp.

    -
    -

    fingerprint

    +
    +

    fingerprint

    The fingerprint class represents information about a client and its version. It is used to encode this information into the client's peer id.

    This is the class declaration:

    @@ -2521,10 +2530,10 @@ sure not to clash with anybody else. Here are some taken id's:

    version of your client. All these numbers must be within the range [0, 9].

    to_string() will generate the actual string put in the peer-id, and return it.

    -
    -

    free functions

    -
    -

    identify_client()

    +
    +

    free functions

    +
    +

    identify_client()

     std::string identify_client(peer_id const& id);
    @@ -2534,8 +2543,8 @@ std::string identify_client(peer_id const& id);
     to extract a string describing a client version from its peer-id. It will recognize most clients
     that have this kind of identification in the peer-id.

    -
    -

    client_fingerprint()

    +
    +

    client_fingerprint()

     boost::optional<fingerprint> client_fingerprint(peer_id const& p);
    @@ -2546,8 +2555,8 @@ to automate the identification of clients. It will not be able to identify peers
     standard encodings. Only Azureus style, Shadow's style and Mainline style. This function is
     declared in the header <libtorrent/identify_client.hpp>.

    -
    -

    bdecode() bencode()

    +
    +

    bdecode() bencode()

     template<class InIt> entry bdecode(InIt start, InIt end);
    @@ -2586,8 +2595,8 @@ entry e = bdecode(buf, buf + data_size);
     

    If bdecode() encounters invalid encoded data in the range given to it it will throw invalid_encoding.

    -
    -

    supports_sparse_files()

    +
    +

    supports_sparse_files()

     bool supports_sparse_files(boost::filesystem::path const&);
    @@ -2601,8 +2610,8 @@ of sparse files, but rather the support for seeking passed end of file and
     write data there, with expected behavior.

    -
    -

    alerts

    +
    +

    alerts

    The pop_alert() function on session is the interface for retrieving alerts, warnings, messages and errors from libtorrent. If there hasn't occurred any errors (matching your severity level) pop_alert() will @@ -2693,8 +2702,8 @@ struct torrent_alert: alert };

    The specific alerts, that all derives from alert, are:

    -
    -

    listen_failed_alert

    +
    +

    listen_failed_alert

    This alert is generated when none of the ports, given in the port range, to session can be opened for listening. This alert is generated as severity level fatal.

    @@ -2706,8 +2715,8 @@ struct listen_failed_alert: alert };
    -
    -

    portmap_error_alert

    +
    +

    portmap_error_alert

    This alert is generated when a NAT router was successfully found but some part of the port mapping request failed. It contains a text message that may help the user figure out what is wrong. This alert is not generated in @@ -2724,8 +2733,8 @@ struct portmap_error_alert: alert };

    -
    -

    portmap_alert

    +
    +

    portmap_alert

    This alert is generated when a NAT router was successfully found and a port was successfully mapped on it. On a NAT:ed network with a NAT-PMP capable router, this is typically generated once when mapping the TCP @@ -2739,8 +2748,8 @@ struct portmap_alert: alert };

    -
    -

    file_error_alert

    +
    +

    file_error_alert

    If the storage fails to read or write files that it needs access to, this alert is generated and the torrent is paused. It is generated as severity level fatal.

    @@ -2754,8 +2763,8 @@ struct file_error_alert: torrent_alert
     };
     
    -
    -

    tracker_announce_alert

    +
    +

    tracker_announce_alert

    This alert is generated each time a tracker announce is sent (or attempted to be sent). It is generated at severity level info.

    @@ -2769,8 +2778,8 @@ struct tracker_announce_alert: torrent_alert
     };
     
    -
    -

    tracker_alert

    +
    +

    tracker_alert

    This alert is generated on tracker time outs, premature disconnects, invalid response or a HTTP response other than "200 OK". From the alert you can get the handle to the torrent the tracker belongs to. This alert is generated as severity level warning.

    @@ -2790,8 +2799,8 @@ struct tracker_alert: torrent_alert };
    -
    -

    tracker_reply_alert

    +
    +

    tracker_reply_alert

    This alert is only for informational purpose. It is generated when a tracker announce succeeds. It is generated regardless what kind of tracker was used, be it UDP, HTTP or the DHT. It is generated with severity level info.

    @@ -2810,8 +2819,8 @@ struct tracker_reply_alert: torrent_alert

    The num_peers tells how many peers were returned from the tracker. This is not necessarily all new peers, some of them may already be connected.

    -
    -

    tracker_warning_alert

    +
    +

    tracker_warning_alert

    This alert is triggered if the tracker reply contains a warning field. Usually this means that the tracker announce was successful, but the tracker has a message to the client. The message string in the alert will contain the warning message from @@ -2826,8 +2835,8 @@ struct tracker_warning_alert: torrent_alert };

    -
    -

    url_seed_alert

    +
    +

    url_seed_alert

    This alert is generated when a HTTP seed name lookup fails. This alert is generated as severity level warning.

    It contains url to the HTTP seed that failed along with an error message.

    @@ -2842,8 +2851,8 @@ struct url_seed_alert: torrent_alert };
    -
    -

    hash_failed_alert

    +
    +

    hash_failed_alert

    This alert is generated when a finished piece fails its hash check. You can get the handle to the torrent which got the failed piece and the index of the piece itself from the alert. This alert is generated as severity level info.

    @@ -2861,8 +2870,8 @@ struct hash_failed_alert: torrent_alert };
    -
    -

    peer_ban_alert

    +
    +

    peer_ban_alert

    This alert is generated when a peer is banned because it has sent too many corrupt pieces to us. It is generated at severity level info. The handle member is a torrent_handle to the torrent that this peer was a member of.

    @@ -2880,8 +2889,8 @@ struct peer_ban_alert: torrent_alert };
    -
    -

    peer_error_alert

    +
    +

    peer_error_alert

    This alert is generated when a peer sends invalid data over the peer-peer protocol. The peer will be disconnected, but you get its ip address from the alert, to identify it. This alert is generated as severity level debug.

    @@ -2899,8 +2908,8 @@ struct peer_error_alert: alert };
    -
    -

    invalid_request_alert

    +
    +

    invalid_request_alert

    This is a debug alert that is generated by an incoming invalid piece request. The handle is a handle to the torrent the peer is a member of. Ïp is the address of the peer and the request is the actual incoming request from the peer. The alert is generated as severity level @@ -2935,8 +2944,8 @@ struct peer_request the index of the piece it want data from, start is the offset within the piece where the data should be read, and length is the amount of data it wants.

    -
    -

    torrent_finished_alert

    +
    +

    torrent_finished_alert

    This alert is generated when a torrent switches from being a downloader to a seed. It will only be generated once per torrent. It contains a torrent_handle to the torrent in question. This alert is generated as severity level info.

    @@ -2951,8 +2960,8 @@ struct torrent_finished_alert: torrent_alert };
    -
    -

    metadata_failed_alert

    +
    +

    metadata_failed_alert

    This alert is generated when the metadata has been completely received and the info-hash failed to match it. i.e. the metadata that was received was corrupt. libtorrent will automatically retry to fetch it in this case. This is only relevant when running a @@ -2969,8 +2978,8 @@ struct metadata_failed_alert: torrent_alert };

    -
    -

    metadata_received_alert

    +
    +

    metadata_received_alert

    This alert is generated when the metadata has been completely received and the torrent can start downloading. It is not generated on torrents that are started with metadata, but only those that needs to download it from peers (when utilizing the libtorrent extension). @@ -2986,8 +2995,8 @@ struct metadata_received_alert: torrent_alert };

    -
    -

    fastresume_rejected_alert

    +
    +

    fastresume_rejected_alert

    This alert is generated when a fastresume file has been passed to add_torrent but the files on disk did not match the fastresume file. The string explains the reason why the resume file was rejected. It is generated at severity level warning.

    @@ -3001,8 +3010,8 @@ struct fastresume_rejected_alert: torrent_alert };
    -
    -

    peer_blocked_alert

    +
    +

    peer_blocked_alert

    This alert is generated when a peer is blocked by the IP filter. It has the severity leve info. The ip member is the address that was blocked.

    @@ -3017,8 +3026,8 @@ struct peer_blocked_alert: alert
     };
     
    -
    -

    dispatcher

    +
    +

    dispatcher

    The handle_alert class is defined in <libtorrent/alert.hpp>.

    Examples usage:

    @@ -3063,12 +3072,12 @@ parameters to select between more types. If the number of types are more than
     including <libtorrent/alert.hpp>.

    -
    -

    exceptions

    +
    +

    exceptions

    There are a number of exceptions that can be thrown from different places in libtorrent, here's a complete list with description.

    -
    -

    invalid_handle

    +
    +

    invalid_handle

    This exception is thrown when querying information from a torrent_handle that hasn't been initialized or that has become invalid.

    @@ -3078,8 +3087,8 @@ struct invalid_handle: std::exception
     };
     
    -
    -

    duplicate_torrent

    +
    +

    duplicate_torrent

    This is thrown by add_torrent() if the torrent already has been added to the session.

    @@ -3089,8 +3098,8 @@ struct duplicate_torrent: std::exception
     };
     
    -
    -

    invalid_encoding

    +
    +

    invalid_encoding

    This is thrown by bdecode() if the input data is not a valid bencoding.

     struct invalid_encoding: std::exception
    @@ -3099,8 +3108,8 @@ struct invalid_encoding: std::exception
     };
     
    -
    -

    type_error

    +
    +

    type_error

    This is thrown from the accessors of entry if the data type of the entry doesn't match the type you want to extract from it.

    @@ -3110,8 +3119,8 @@ struct type_error: std::runtime_error
     };
     
    -
    -

    invalid_torrent_file

    +
    +

    invalid_torrent_file

    This exception is thrown from the constructor of torrent_info if the given bencoded information doesn't meet the requirements on what information has to be present in a torrent file.

    @@ -3122,8 +3131,8 @@ struct invalid_torrent_file: std::exception
     
    -
    -

    fast resume

    +
    +

    fast resume

    The fast resume mechanism is a way to remember which pieces are downloaded and where they are put between sessions. You can generate fast resume data by calling torrent_handle::write_resume_data() on torrent_handle. You can @@ -3136,8 +3145,8 @@ start from scratch on the partially downloaded pieces.

    will skip the time consuming checks. It may have to do the checking anyway, if the fast-resume data is corrupt or doesn't fit the storage for that torrent, then it will not trust the fast-resume data and just do the checking.

    -
    -

    file format

    +
    +

    file format

    The file format is a bencoded dictionary containing the following fields:

    @@ -3242,8 +3251,8 @@ last resume data checkpoint.
    -
    -

    threads

    +
    +

    threads

    libtorrent starts 2 or 3 threads.

      @@ -3261,8 +3270,8 @@ non-blocking host name resolution to simulate non-blocking behavior.
    -
    -

    storage allocation

    +
    +

    storage allocation

    There are two modes in which storage (files on disk) are allocated in libtorrent.

      @@ -3282,8 +3291,8 @@ different drawbacks and benefits.

      any files are filtered and if the filesystem supports sparse files.

      To know if the filesystem supports sparse files (and to know if libtorrent believes the filesystem supports sparse files), see supports_sparse_files().

      -
      -

      full allocation

      +
      +

      full allocation

      When a torrent is started in full allocation mode, the checker thread (see threads) will make sure that the entire storage is allocated, and fill any gaps with zeros. This will be skipped if the filesystem supports sparse files or automatic zero filling. @@ -3314,8 +3323,8 @@ out of date data, since pieces won't move around.

    -
    -

    compact allocation

    +
    +

    compact allocation

    The compact allocation will only allocate as much storage as it needs to keep the pieces downloaded so far. This means that pieces will be moved around to be placed at their final position in the files while downloading (to make sure the completed @@ -3363,8 +3372,8 @@ contain any piece), return that slot index.

    -
    -

    extensions

    +
    +

    extensions

    These extensions all operates within the extension protocol. The name of the extension is the name used in the extension-list packets, and the payload is the data in the extended message (not counting the @@ -3373,8 +3382,8 @@ length-prefix, message-id nor extension-id).

    handshake, it may be incompatible with future versions of the mainline bittorrent client.

    These are the extensions that are currently implemented.

    -
    -

    metadata from peers

    +
    +

    metadata from peers

    Extension name: "LT_metadata"

    The point with this extension is that you don't have to distribute the metadata (.torrent-file) separately. The metadata can be distributed @@ -3492,8 +3501,8 @@ doesn't have any metadata.

    -
    -

    HTTP seeding

    +
    +

    HTTP seeding

    The HTTP seed extension implements this specification.

    The libtorrent implementation assumes that, if the URL ends with a slash ('/'), the filename should be appended to it in order to request pieces from @@ -3503,8 +3512,8 @@ torrent's name '/' the file name is appended. This is the same directory structure that libtorrent will download torrents into.

    -
    -

    filename checks

    +
    +

    filename checks

    Boost.Filesystem will by default check all its paths to make sure they conform to filename requirements on many platforms. If you don't want this check, you can set it to either only check for native filesystem requirements or turn it off @@ -3514,8 +3523,8 @@ boost::filesystem::path::default_name_check(boost::filesystem::native);

    for example. For more information, see the Boost.Filesystem docs.

    -
    -

    acknowledgments

    +
    +

    acknowledgments

    Written by Arvid Norberg. Copyright © 2003-2006

    Contributions by Magnus Jonsson, Daniel Wallin and Cory Nelson

    Lots of testing, suggestions and contributions by Massaroddel and Tianhao Qiu.

    diff --git a/docs/manual.rst b/docs/manual.rst index 6bce207b1..a72737998 100644 --- a/docs/manual.rst +++ b/docs/manual.rst @@ -388,6 +388,7 @@ struct has the following members:: int dht_nodes; int dht_cache_nodes; int dht_torrents; + int dht_global_nodes; }; ``has_incoming_connections`` is false as long as no incoming connections have been @@ -414,6 +415,8 @@ becomes unresponsive. ``dht_torrents`` are the number of torrents tracked by the DHT at the moment. +``dht_global_nodes`` is an estimation of the total number of nodes in the DHT +network. is_listening() listen_port() listen_on() ---------------------------------------- diff --git a/include/libtorrent/kademlia/node.hpp b/include/libtorrent/kademlia/node.hpp index 62791427a..78323c2f0 100644 --- a/include/libtorrent/kademlia/node.hpp +++ b/include/libtorrent/kademlia/node.hpp @@ -116,6 +116,8 @@ public: 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(); } diff --git a/include/libtorrent/kademlia/routing_table.hpp b/include/libtorrent/kademlia/routing_table.hpp index 2823344d7..45a7dd762 100644 --- a/include/libtorrent/kademlia/routing_table.hpp +++ b/include/libtorrent/kademlia/routing_table.hpp @@ -49,6 +49,7 @@ POSSIBILITY OF SUCH DAMAGE. #include #include #include +#include namespace libtorrent { namespace dht { @@ -201,17 +202,21 @@ public: 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 diff --git a/include/libtorrent/kademlia/rpc_manager.hpp b/include/libtorrent/kademlia/rpc_manager.hpp index 25eacebd6..c00b1b3fb 100644 --- a/include/libtorrent/kademlia/rpc_manager.hpp +++ b/include/libtorrent/kademlia/rpc_manager.hpp @@ -69,7 +69,7 @@ namespace messages struct msg { msg() : reply(false), piggy_backed_ping(false) - , port(0) {} + , message_id(-1), port(0) {} // true if this message is a reply bool reply; @@ -158,8 +158,8 @@ public: void invoke(int message_id, udp::endpoint target , boost::shared_ptr o); - void reply(msg& m, msg const& reply_to); - void reply_with_ping(msg& m, msg const& reply_to); + void reply(msg& m); + void reply_with_ping(msg& m); #ifndef NDEBUG void check_invariant() const; diff --git a/include/libtorrent/session_status.hpp b/include/libtorrent/session_status.hpp index 834044e36..adbb1b57d 100644 --- a/include/libtorrent/session_status.hpp +++ b/include/libtorrent/session_status.hpp @@ -59,6 +59,7 @@ namespace libtorrent int dht_nodes; int dht_node_cache; int dht_torrents; + size_type dht_global_nodes; #endif }; diff --git a/src/kademlia/dht_tracker.cpp b/src/kademlia/dht_tracker.cpp index 97f9064c5..8d2de8457 100644 --- a/src/kademlia/dht_tracker.cpp +++ b/src/kademlia/dht_tracker.cpp @@ -207,7 +207,7 @@ namespace libtorrent { namespace dht m_connection_timer.async_wait(m_strand.wrap( bind(&dht_tracker::connection_timeout, self(), _1))); - m_refresh_timer.expires_from_now(minutes(15)); + m_refresh_timer.expires_from_now(seconds(5)); m_refresh_timer.async_wait(m_strand.wrap(bind(&dht_tracker::refresh_timeout, self(), _1))); m_dht.bootstrap(initial_nodes, bind(&dht_tracker::on_bootstrap, self())); @@ -225,6 +225,7 @@ namespace libtorrent { namespace dht { 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(asio::error_code const& e) @@ -442,7 +443,7 @@ namespace libtorrent { namespace dht } else { - TORRENT_LOG(dht_tracker) << " client: generic"; + TORRENT_LOG(dht_tracker) << " client: " << client; } } catch (std::exception&) @@ -617,6 +618,7 @@ namespace libtorrent { namespace dht TORRENT_LOG(dht_tracker) << " error: " << m.error_code << " " << m.error_msg; #endif + throw std::runtime_error("DHT error message"); } else { @@ -635,7 +637,7 @@ namespace libtorrent { namespace dht } TORRENT_LOG(dht_tracker) << e; #endif - + assert(m.message_id != messages::error); m_dht.incoming(m); } catch (std::exception& e) @@ -774,16 +776,15 @@ namespace libtorrent { namespace dht } void dht_tracker::send_packet(msg const& m) + try { using libtorrent::bencode; using libtorrent::entry; entry e(entry::dictionary_t); e["t"] = m.transaction_id; - std::string version_str("LT "); - std::string::iterator i = version_str.begin() + 2; - detail::write_uint8(LIBTORRENT_VERSION_MAJOR, i); - detail::write_uint8(LIBTORRENT_VERSION_MINOR, i); - e["v"] = version_str; + 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 TORRENT_LOG(dht_tracker) << time_now_string() @@ -796,12 +797,13 @@ namespace libtorrent { namespace dht assert(m.reply); e["y"] = "e"; entry error_list(entry::list_t); + 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 - TORRENT_LOG(dht_tracker) << time_now_string() - << " error: " << m.error_code << " " << m.error_msg; + TORRENT_LOG(dht_tracker) << time_now_string() + << " error: " << m.error_code << " " << m.error_msg; #endif } else if (m.reply) @@ -914,8 +916,10 @@ namespace libtorrent { namespace dht m_send_buf.clear(); bencode(std::back_inserter(m_send_buf), e); + asio::error_code ec; m_socket.send_to(asio::buffer(&m_send_buf[0] - , (int)m_send_buf.size()), m.addr); + , (int)m_send_buf.size()), m.addr, 0, ec); + if (ec) return; #ifdef TORRENT_DHT_VERBOSE_LOGGING m_total_out_bytes += m_send_buf.size(); @@ -944,6 +948,13 @@ namespace libtorrent { namespace dht 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 + assert(false); + } }} diff --git a/src/kademlia/node.cpp b/src/kademlia/node.cpp index 124a7000e..999c88dbd 100644 --- a/src/kademlia/node.cpp +++ b/src/kademlia/node.cpp @@ -381,27 +381,35 @@ time_duration node_impl::refresh_timeout() for (int i = 0; i < 160; ++i) { ptime r = m_table.next_refresh(i); - if (r <= now) - { - if (refresh == -1) refresh = i; - } - else if (r < next) + if (r <= next) { + refresh = i; next = r; } } - if (refresh != -1) + if (next < now) { - #ifdef TORRENT_DHT_VERBOSE_LOGGING + assert(refresh > -1); +#ifdef TORRENT_DHT_VERBOSE_LOGGING TORRENT_LOG(node) << "refreshing bucket: " << refresh; - #endif +#endif refresh_bucket(refresh); } } catch (std::exception&) {} - if (next < now + seconds(5)) return seconds(5); - return next - now; + time_duration next_refresh = next - now; + time_duration min_next_refresh + = minutes(15) / (m_table.num_active_buckets()); + + 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() @@ -493,6 +501,11 @@ bool node_impl::on_find(msg const& m, std::vector& peers) const 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: @@ -532,16 +545,16 @@ void node_impl::incoming_request(msg const& m) } break; case messages::announce_peer: - { - on_announce(m, reply); - } + on_announce(m, reply); break; + default: + assert(false); }; if (m_table.need_node(m.id)) - m_rpc.reply_with_ping(reply, m); + m_rpc.reply_with_ping(reply); else - m_rpc.reply(reply, m); + m_rpc.reply(reply); } diff --git a/src/kademlia/routing_table.cpp b/src/kademlia/routing_table.cpp index 18d822859..f9b484bd0 100644 --- a/src/kademlia/routing_table.cpp +++ b/src/kademlia/routing_table.cpp @@ -63,7 +63,8 @@ routing_table::routing_table(node_id const& id, int bucket_size // 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() - seconds(15*60 - i*5); + m_bucket_activity[i] = time_now() - milliseconds(i*5625); + m_bucket_activity[0] = time_now() - minutes(15); } boost::tuple routing_table::size() const @@ -79,14 +80,33 @@ boost::tuple routing_table::size() const 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 && 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\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()); @@ -111,16 +131,20 @@ void routing_table::print_state(std::ostream& os) const } os << "\n"; } - os << "cached\n-----------\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") - << "\n"; + 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) { @@ -130,6 +154,8 @@ void routing_table::print_state(std::ostream& os) const } } +#endif + void routing_table::touch_bucket(int bucket) { m_bucket_activity[bucket] = time_now(); @@ -241,7 +267,7 @@ bool routing_table::node_seen(node_id const& id, udp::endpoint addr) bool ret = need_bootstrap(); - m_bucket_activity[bucket_index] = time_now(); + //m_bucket_activity[bucket_index] = time_now(); if (i != b.end()) { diff --git a/src/kademlia/rpc_manager.cpp b/src/kademlia/rpc_manager.cpp index 043981fcb..c73419672 100644 --- a/src/kademlia/rpc_manager.cpp +++ b/src/kademlia/rpc_manager.cpp @@ -133,7 +133,7 @@ bool rpc_manager::incoming(msg const& m) || tid < 0) { #ifdef TORRENT_DHT_VERBOSE_LOGGING - TORRENT_LOG(rpc) << "Reply with unknown transaction id: " + TORRENT_LOG(rpc) << "Reply with invalid transaction id: " << tid << " from " << m.addr; #endif return false; @@ -145,7 +145,7 @@ bool rpc_manager::incoming(msg const& m) { #ifdef TORRENT_DHT_VERBOSE_LOGGING TORRENT_LOG(rpc) << "Reply with unknown transaction id: " - << tid << " from " << m.addr; + << tid << " from " << m.addr << " (possibly timed out)"; #endif return false; } @@ -174,17 +174,16 @@ bool rpc_manager::incoming(msg const& m) msg ph; ph.message_id = messages::ping; ph.transaction_id = m.ping_transaction_id; - ph.id = m_our_id; ph.addr = m.addr; - - msg empty; + ph.reply = true; - reply(empty, ph); + reply(ph); } return m_table.node_seen(m.id, m.addr); } else { + assert(m.message_id != messages::error); // this is an incoming request m_incoming(m); } @@ -326,19 +325,15 @@ void rpc_manager::invoke(int message_id, udp::endpoint target_addr } } -void rpc_manager::reply(msg& m, msg const& reply_to) +void rpc_manager::reply(msg& m) { INVARIANT_CHECK; if (m_destructing) return; - if (m.message_id != messages::error) - m.message_id = reply_to.message_id; - m.addr = reply_to.addr; - m.reply = true; + assert(m.reply); m.piggy_backed_ping = false; m.id = m_our_id; - m.transaction_id = reply_to.transaction_id; m_send(m); } @@ -354,38 +349,27 @@ namespace }; } -void rpc_manager::reply_with_ping(msg& m, msg const& reply_to) +void rpc_manager::reply_with_ping(msg& m) { INVARIANT_CHECK; if (m_destructing) return; + assert(m.reply); - if (m.message_id != messages::error) - m.message_id = reply_to.message_id; - m.addr = reply_to.addr; - m.reply = true; m.piggy_backed_ping = true; m.id = m_our_id; - m.transaction_id = reply_to.transaction_id; - try - { - m.ping_transaction_id.clear(); - std::back_insert_iterator out(m.ping_transaction_id); - io::write_uint16(m_next_transaction_id, out); + m.ping_transaction_id.clear(); + std::back_insert_iterator out(m.ping_transaction_id); + io::write_uint16(m_next_transaction_id, out); - boost::shared_ptr o(new dummy_observer); - assert(!m_transactions[m_next_transaction_id]); - o->sent = time_now(); - o->target_addr = m.addr; + boost::shared_ptr o(new dummy_observer); + assert(!m_transactions[m_next_transaction_id]); + o->sent = time_now(); + o->target_addr = m.addr; - m_send(m); - new_transaction_id(o); - } - catch (std::exception& e) - { - // m_send may fail with "no route to host" - } + m_send(m); + new_transaction_id(o); } diff --git a/src/session_impl.cpp b/src/session_impl.cpp index 9aae25e12..9888dc137 100755 --- a/src/session_impl.cpp +++ b/src/session_impl.cpp @@ -1544,6 +1544,7 @@ namespace libtorrent { namespace detail s.dht_nodes = 0; s.dht_node_cache = 0; s.dht_torrents = 0; + s.dht_global_nodes = 0; } #endif